summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt99
-rw-r--r--src/core/core.cpp21
-rw-r--r--src/core/file_sys/control_metadata.h4
-rw-r--r--src/core/file_sys/system_archive/shared_font.cpp2
-rw-r--r--src/core/hle/kernel/k_thread.h4
-rw-r--r--src/core/hle/kernel/kernel.cpp57
-rw-r--r--src/core/hle/kernel/kernel.h4
-rw-r--r--src/core/hle/service/acc/profile_manager.cpp5
-rw-r--r--src/core/hle/service/am/am.cpp10
-rw-r--r--src/core/hle/service/am/am.h6
-rw-r--r--src/core/hle/service/am/applet.h6
-rw-r--r--src/core/hle/service/am/applet_manager.cpp18
-rw-r--r--src/core/hle/service/am/display_layer_manager.cpp151
-rw-r--r--src/core/hle/service/am/display_layer_manager.h62
-rw-r--r--src/core/hle/service/am/frontend/applet_web_browser.cpp2
-rw-r--r--src/core/hle/service/am/library_applet_storage.cpp4
-rw-r--r--src/core/hle/service/am/managed_layer_holder.cpp59
-rw-r--r--src/core/hle/service/am/managed_layer_holder.h32
-rw-r--r--src/core/hle/service/am/service/all_system_applet_proxies_service.cpp13
-rw-r--r--src/core/hle/service/am/service/all_system_applet_proxies_service.h8
-rw-r--r--src/core/hle/service/am/service/application_functions.cpp30
-rw-r--r--src/core/hle/service/am/service/application_functions.h1
-rw-r--r--src/core/hle/service/am/service/application_proxy.cpp9
-rw-r--r--src/core/hle/service/am/service/application_proxy.h3
-rw-r--r--src/core/hle/service/am/service/application_proxy_service.cpp7
-rw-r--r--src/core/hle/service/am/service/application_proxy_service.h7
-rw-r--r--src/core/hle/service/am/service/common_state_getter.cpp1
-rw-r--r--src/core/hle/service/am/service/display_controller.cpp6
-rw-r--r--src/core/hle/service/am/service/library_applet_creator.cpp2
-rw-r--r--src/core/hle/service/am/service/library_applet_proxy.cpp10
-rw-r--r--src/core/hle/service/am/service/library_applet_proxy.h3
-rw-r--r--src/core/hle/service/am/service/library_applet_self_accessor.cpp17
-rw-r--r--src/core/hle/service/am/service/library_applet_self_accessor.h2
-rw-r--r--src/core/hle/service/am/service/self_controller.cpp53
-rw-r--r--src/core/hle/service/am/service/self_controller.h3
-rw-r--r--src/core/hle/service/am/service/system_applet_proxy.cpp10
-rw-r--r--src/core/hle/service/am/service/system_applet_proxy.h3
-rw-r--r--src/core/hle/service/am/service/window_controller.cpp2
-rw-r--r--src/core/hle/service/am/system_buffer_manager.cpp80
-rw-r--r--src/core/hle/service/am/system_buffer_manager.h52
-rw-r--r--src/core/hle/service/audio/audctl.cpp201
-rw-r--r--src/core/hle/service/audio/audctl.h50
-rw-r--r--src/core/hle/service/audio/audio.cpp4
-rw-r--r--src/core/hle/service/audio/audio_controller.cpp174
-rw-r--r--src/core/hle/service/audio/audio_controller.h58
-rw-r--r--src/core/hle/service/caps/caps_a.cpp11
-rw-r--r--src/core/hle/service/caps/caps_a.h3
-rw-r--r--src/core/hle/service/erpt/erpt.cpp12
-rw-r--r--src/core/hle/service/filesystem/fsp/fsp_srv.cpp9
-rw-r--r--src/core/hle/service/filesystem/fsp/fsp_srv.h1
-rw-r--r--src/core/hle/service/glue/time/manager.cpp47
-rw-r--r--src/core/hle/service/glue/time/manager.h1
-rw-r--r--src/core/hle/service/glue/time/static.cpp17
-rw-r--r--src/core/hle/service/glue/time/worker.cpp2
-rw-r--r--src/core/hle/service/mii/mii.cpp9
-rw-r--r--src/core/hle/service/ns/account_proxy_interface.cpp21
-rw-r--r--src/core/hle/service/ns/account_proxy_interface.h16
-rw-r--r--src/core/hle/service/ns/application_manager_interface.cpp519
-rw-r--r--src/core/hle/service/ns/application_manager_interface.h62
-rw-r--r--src/core/hle/service/ns/application_version_interface.cpp33
-rw-r--r--src/core/hle/service/ns/application_version_interface.h16
-rw-r--r--src/core/hle/service/ns/content_management_interface.cpp72
-rw-r--r--src/core/hle/service/ns/content_management_interface.h25
-rw-r--r--src/core/hle/service/ns/develop_interface.cpp38
-rw-r--r--src/core/hle/service/ns/develop_interface.h16
-rw-r--r--src/core/hle/service/ns/document_interface.cpp38
-rw-r--r--src/core/hle/service/ns/document_interface.h22
-rw-r--r--src/core/hle/service/ns/download_task_interface.cpp39
-rw-r--r--src/core/hle/service/ns/download_task_interface.h20
-rw-r--r--src/core/hle/service/ns/dynamic_rights_interface.cpp62
-rw-r--r--src/core/hle/service/ns/dynamic_rights_interface.h22
-rw-r--r--src/core/hle/service/ns/ecommerce_interface.cpp27
-rw-r--r--src/core/hle/service/ns/ecommerce_interface.h16
-rw-r--r--src/core/hle/service/ns/factory_reset_interface.cpp27
-rw-r--r--src/core/hle/service/ns/factory_reset_interface.h16
-rw-r--r--src/core/hle/service/ns/ns.cpp903
-rw-r--r--src/core/hle/service/ns/ns.h133
-rw-r--r--src/core/hle/service/ns/ns_results.h (renamed from src/core/hle/service/ns/errors.h)0
-rw-r--r--src/core/hle/service/ns/ns_types.h111
-rw-r--r--src/core/hle/service/ns/pdm_qry.cpp67
-rw-r--r--src/core/hle/service/ns/platform_service_manager.cpp (renamed from src/core/hle/service/ns/iplatform_service_manager.cpp)130
-rw-r--r--src/core/hle/service/ns/platform_service_manager.h (renamed from src/core/hle/service/ns/iplatform_service_manager.h)33
-rw-r--r--src/core/hle/service/ns/query_service.cpp57
-rw-r--r--src/core/hle/service/ns/query_service.h (renamed from src/core/hle/service/ns/pdm_qry.h)12
-rw-r--r--src/core/hle/service/ns/read_only_application_control_data_interface.cpp122
-rw-r--r--src/core/hle/service/ns/read_only_application_control_data_interface.h30
-rw-r--r--src/core/hle/service/ns/read_only_application_record_interface.cpp38
-rw-r--r--src/core/hle/service/ns/read_only_application_record_interface.h22
-rw-r--r--src/core/hle/service/ns/service_getter_interface.cpp120
-rw-r--r--src/core/hle/service/ns/service_getter_interface.h47
-rw-r--r--src/core/hle/service/ns/system_update_control.cpp44
-rw-r--r--src/core/hle/service/ns/system_update_control.h16
-rw-r--r--src/core/hle/service/ns/system_update_interface.cpp61
-rw-r--r--src/core/hle/service/ns/system_update_interface.h38
-rw-r--r--src/core/hle/service/ns/vulnerability_manager_interface.cpp31
-rw-r--r--src/core/hle/service/ns/vulnerability_manager_interface.h21
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.cpp3
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.h9
-rw-r--r--src/core/hle/service/nvdrv/nvdrv_interface.cpp6
-rw-r--r--src/core/hle/service/nvdrv/nvdrv_interface.h4
-rw-r--r--src/core/hle/service/nvnflinger/binder.h24
-rw-r--r--src/core/hle/service/nvnflinger/buffer_item_consumer.cpp2
-rw-r--r--src/core/hle/service/nvnflinger/buffer_item_consumer.h2
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp76
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_consumer.h10
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_producer.cpp37
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_producer.h7
-rw-r--r--src/core/hle/service/nvnflinger/consumer_base.cpp2
-rw-r--r--src/core/hle/service/nvnflinger/consumer_base.h4
-rw-r--r--src/core/hle/service/nvnflinger/display.h55
-rw-r--r--src/core/hle/service/nvnflinger/hardware_composer.cpp65
-rw-r--r--src/core/hle/service/nvnflinger/hardware_composer.h20
-rw-r--r--src/core/hle/service/nvnflinger/hos_binder_driver.cpp66
-rw-r--r--src/core/hle/service/nvnflinger/hos_binder_driver.h46
-rw-r--r--src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp22
-rw-r--r--src/core/hle/service/nvnflinger/hos_binder_driver_server.h16
-rw-r--r--src/core/hle/service/nvnflinger/nvnflinger.cpp333
-rw-r--r--src/core/hle/service/nvnflinger/nvnflinger.h166
-rw-r--r--src/core/hle/service/nvnflinger/surface_flinger.cpp124
-rw-r--r--src/core/hle/service/nvnflinger/surface_flinger.h65
-rw-r--r--src/core/hle/service/service.cpp136
-rw-r--r--src/core/hle/service/service.h21
-rw-r--r--src/core/hle/service/services.cpp136
-rw-r--r--src/core/hle/service/services.h22
-rw-r--r--src/core/hle/service/set/setting_formats/system_settings.h4
-rw-r--r--src/core/hle/service/set/settings_types.h7
-rw-r--r--src/core/hle/service/set/system_settings_server.cpp1394
-rw-r--r--src/core/hle/service/set/system_settings_server.h208
-rw-r--r--src/core/hle/service/vi/application_display_service.cpp302
-rw-r--r--src/core/hle/service/vi/application_display_service.h81
-rw-r--r--src/core/hle/service/vi/application_root_service.cpp33
-rw-r--r--src/core/hle/service/vi/application_root_service.h33
-rw-r--r--src/core/hle/service/vi/conductor.cpp114
-rw-r--r--src/core/hle/service/vi/conductor.h57
-rw-r--r--src/core/hle/service/vi/container.cpp228
-rw-r--r--src/core/hle/service/vi/container.h92
-rw-r--r--src/core/hle/service/vi/display.h44
-rw-r--r--src/core/hle/service/vi/display/vi_display.cpp143
-rw-r--r--src/core/hle/service/vi/display/vi_display.h143
-rw-r--r--src/core/hle/service/vi/display_list.h83
-rw-r--r--src/core/hle/service/vi/layer.h79
-rw-r--r--src/core/hle/service/vi/layer/vi_layer.cpp18
-rw-r--r--src/core/hle/service/vi/layer/vi_layer.h118
-rw-r--r--src/core/hle/service/vi/layer_list.h69
-rw-r--r--src/core/hle/service/vi/manager_display_service.cpp140
-rw-r--r--src/core/hle/service/vi/manager_display_service.h37
-rw-r--r--src/core/hle/service/vi/manager_root_service.cpp38
-rw-r--r--src/core/hle/service/vi/manager_root_service.h32
-rw-r--r--src/core/hle/service/vi/service_creator.cpp38
-rw-r--r--src/core/hle/service/vi/service_creator.h28
-rw-r--r--src/core/hle/service/vi/shared_buffer_manager.cpp (renamed from src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp)136
-rw-r--r--src/core/hle/service/vi/shared_buffer_manager.h (renamed from src/core/hle/service/nvnflinger/fb_share_buffer_manager.h)46
-rw-r--r--src/core/hle/service/vi/system_display_service.cpp169
-rw-r--r--src/core/hle/service/vi/system_display_service.h47
-rw-r--r--src/core/hle/service/vi/system_root_service.cpp32
-rw-r--r--src/core/hle/service/vi/system_root_service.h32
-rw-r--r--src/core/hle/service/vi/vi.cpp974
-rw-r--r--src/core/hle/service/vi/vi.h42
-rw-r--r--src/core/hle/service/vi/vi_m.cpp34
-rw-r--r--src/core/hle/service/vi/vi_m.h32
-rw-r--r--src/core/hle/service/vi/vi_s.cpp30
-rw-r--r--src/core/hle/service/vi/vi_s.h32
-rw-r--r--src/core/hle/service/vi/vi_types.h92
-rw-r--r--src/core/hle/service/vi/vi_u.cpp30
-rw-r--r--src/core/hle/service/vi/vi_u.h32
-rw-r--r--src/core/hle/service/vi/vsync_manager.cpp26
-rw-r--r--src/core/hle/service/vi/vsync_manager.h29
-rw-r--r--src/core/memory/cheat_engine.cpp4
168 files changed, 6165 insertions, 5306 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index bc7f95fea..fa5c4de37 100644
--- 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,18 +990,36 @@ 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/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
+ hle/service/vi/system_root_service.h
+ hle/service/vi/vi_results.h
+ hle/service/vi/vi_types.h
hle/service/vi/vi.cpp
hle/service/vi/vi.h
- hle/service/vi/vi_m.cpp
- hle/service/vi/vi_m.h
- hle/service/vi/vi_s.cpp
- hle/service/vi/vi_s.h
- hle/service/vi/vi_u.cpp
- hle/service/vi/vi_u.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 435ef6793..9e8936728 100644
--- 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"
@@ -242,7 +243,7 @@ struct System::Impl {
void Run() {
std::unique_lock<std::mutex> lk(suspend_guard);
- kernel.SuspendApplication(false);
+ kernel.SuspendEmulation(false);
core_timing.SyncPause(false);
is_paused.store(false, std::memory_order_relaxed);
}
@@ -251,7 +252,7 @@ struct System::Impl {
std::unique_lock<std::mutex> lk(suspend_guard);
core_timing.SyncPause(true);
- kernel.SuspendApplication(true);
+ kernel.SuspendEmulation(true);
is_paused.store(true, std::memory_order_relaxed);
}
@@ -261,7 +262,7 @@ struct System::Impl {
std::unique_lock<std::mutex> StallApplication() {
std::unique_lock<std::mutex> lk(suspend_guard);
- kernel.SuspendApplication(true);
+ kernel.SuspendEmulation(true);
core_timing.SyncPause(true);
return lk;
}
@@ -269,7 +270,7 @@ struct System::Impl {
void UnstallApplication() {
if (!IsPaused()) {
core_timing.SyncPause(false);
- kernel.SuspendApplication(false);
+ kernel.SuspendEmulation(false);
}
}
@@ -310,7 +311,8 @@ struct System::Impl {
audio_core = std::make_unique<AudioCore::AudioCore>(system);
service_manager = std::make_shared<Service::SM::ServiceManager>(kernel);
- services = std::make_unique<Service::Services>(service_manager, system);
+ services =
+ std::make_unique<Service::Services>(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.SuspendApplication(true);
- if (services) {
- services->KillNVNFlinger();
- }
+ kernel.SuspendEmulation(true);
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<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{};
std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_cpu{};
diff --git a/src/core/file_sys/control_metadata.h b/src/core/file_sys/control_metadata.h
index 555b9d8f7..667efbbab 100644
--- a/src/core/file_sys/control_metadata.h
+++ b/src/core/file_sys/control_metadata.h
@@ -64,8 +64,8 @@ struct RawNACP {
u64_le cache_storage_size;
u64_le cache_storage_journal_size;
u64_le cache_storage_data_and_journal_max_size;
- u64_le cache_storage_max_index;
- INSERT_PADDING_BYTES(0xE70);
+ u16_le cache_storage_max_index;
+ INSERT_PADDING_BYTES(0xE76);
};
static_assert(sizeof(RawNACP) == 0x4000, "RawNACP has incorrect size.");
diff --git a/src/core/file_sys/system_archive/shared_font.cpp b/src/core/file_sys/system_archive/shared_font.cpp
index deb52069d..9ea16aa59 100644
--- 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/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index f13e232b2..e928cfebc 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -66,6 +66,7 @@ enum class SuspendType : u32 {
Debug = 2,
Backtrace = 3,
Init = 4,
+ System = 5,
Count,
};
@@ -84,8 +85,9 @@ enum class ThreadState : u16 {
DebugSuspended = (1 << (2 + SuspendShift)),
BacktraceSuspended = (1 << (3 + SuspendShift)),
InitSuspended = (1 << (4 + SuspendShift)),
+ SystemSuspended = (1 << (5 + SuspendShift)),
- SuspendFlagMask = ((1 << 5) - 1) << SuspendShift,
+ SuspendFlagMask = ((1 << 6) - 1) << SuspendShift,
};
DECLARE_ENUM_FLAG_OPERATORS(ThreadState);
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 34b25be66..4f4b02fac 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -1204,39 +1204,48 @@ const Kernel::KSharedMemory& KernelCore::GetHidBusSharedMem() const {
return *impl->hidbus_shared_mem;
}
-void KernelCore::SuspendApplication(bool suspended) {
+void KernelCore::SuspendEmulation(bool suspended) {
const bool should_suspend{exception_exited || suspended};
- const auto activity =
- should_suspend ? Svc::ProcessActivity::Paused : Svc::ProcessActivity::Runnable;
+ auto processes = GetProcessList();
- // Get the application process.
- KScopedAutoObject<KProcess> process = ApplicationProcess();
- if (process.IsNull()) {
- return;
+ for (auto& process : processes) {
+ KScopedLightLock ll{process->GetListLock()};
+
+ for (auto& thread : process->GetThreadList()) {
+ if (should_suspend) {
+ thread.RequestSuspend(SuspendType::System);
+ } else {
+ thread.Resume(SuspendType::System);
+ }
+ }
}
- // Set the new activity.
- process->SetActivity(activity);
+ if (!should_suspend) {
+ return;
+ }
// Wait for process execution to stop.
- bool must_wait{should_suspend};
-
- // KernelCore::SuspendApplication must be called from locked context,
- // or we could race another call to SetActivity, interfering with waiting.
- while (must_wait) {
+ // KernelCore::SuspendEmulation must be called from locked context,
+ // or we could race another call, interfering with waiting.
+ const auto TryWait = [&]() {
KScopedSchedulerLock sl{*this};
- // Assume that all threads have finished running.
- must_wait = false;
-
- for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) {
- if (Scheduler(i).GetSchedulerCurrentThread()->GetOwnerProcess() ==
- process.GetPointerUnsafe()) {
- // A thread has not finished running yet.
- // Continue waiting.
- must_wait = true;
+ for (auto& process : processes) {
+ for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) {
+ if (Scheduler(i).GetSchedulerCurrentThread()->GetOwnerProcess() ==
+ process.GetPointerUnsafe()) {
+ // A thread has not finished running yet.
+ // Continue waiting.
+ return false;
+ }
}
}
+
+ return true;
+ };
+
+ while (!TryWait()) {
+ // ...
}
}
@@ -1260,7 +1269,7 @@ bool KernelCore::IsShuttingDown() const {
void KernelCore::ExceptionalExitApplication() {
exception_exited = true;
- SuspendApplication(true);
+ SuspendEmulation(true);
}
void KernelCore::EnterSVCProfile() {
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 8ea5bed1c..57182c0c8 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -258,8 +258,8 @@ public:
/// Gets the shared memory object for HIDBus services.
const Kernel::KSharedMemory& GetHidBusSharedMem() const;
- /// Suspend/unsuspend application process.
- void SuspendApplication(bool suspend);
+ /// Suspend/unsuspend emulated processes.
+ void SuspendEmulation(bool suspend);
/// Exceptional exit application process.
void ExceptionalExitApplication();
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp
index 29a10ad13..ee9795532 100644
--- a/src/core/hle/service/acc/profile_manager.cpp
+++ b/src/core/hle/service/acc/profile_manager.cpp
@@ -329,9 +329,8 @@ bool ProfileManager::GetProfileBaseAndData(const ProfileInfo& user, ProfileBase&
/// Returns if the system is allowing user registrations or not
bool ProfileManager::CanSystemRegisterUser() const {
- return false; // TODO(ogniK): Games shouldn't have
- // access to user registration, when we
- // emulate qlaunch. Update this to dynamically change.
+ // TODO: Both games and applets can register users. Determine when this condition is not meet.
+ return true;
}
bool ProfileManager::RemoveUser(UUID uuid) {
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 9dc710ba9..8c4e14f08 100644
--- 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<ServerManager>(system);
- server_manager->RegisterNamedService(
- "appletAE", std::make_shared<IAllSystemAppletProxiesService>(system, nvnflinger));
- server_manager->RegisterNamedService(
- "appletOE", std::make_shared<IApplicationProxyService>(system, nvnflinger));
+ server_manager->RegisterNamedService("appletAE",
+ std::make_shared<IAllSystemAppletProxiesService>(system));
+ server_manager->RegisterNamedService("appletOE",
+ std::make_shared<IApplicationProxyService>(system));
ServerManager::RunServer(std::move(server_manager));
}
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 4a2d797bd..1afe253ae 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -7,12 +7,8 @@ namespace Core {
class System;
}
-namespace Service::Nvnflinger {
-class Nvnflinger;
-}
-
namespace Service::AM {
-void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system);
+void LoopProcess(Core::System& system);
} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet.h b/src/core/hle/service/am/applet.h
index 4f34d4811..ad602153e 100644
--- 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 100644
--- 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<u8> argument_data(sizeof(arguments));
+ std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
+ channel.Push(std::make_shared<IStorage>(system, std::move(argument_data)));
+}
+
void PushInShowAlbum(Core::System& system, AppletStorageChannel& channel) {
const CommonArguments arguments{
.arguments_version = CommonArgumentVersion::Version3,
@@ -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 100644
index 000000000..85ff6fb88
--- /dev/null
+++ b/src/core/hle/service/am/display_layer_manager.cpp
@@ -0,0 +1,151 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/core.h"
+#include "core/hle/service/am/display_layer_manager.h"
+#include "core/hle/service/sm/sm.h"
+#include "core/hle/service/vi/application_display_service.h"
+#include "core/hle/service/vi/container.h"
+#include "core/hle/service/vi/manager_display_service.h"
+#include "core/hle/service/vi/manager_root_service.h"
+#include "core/hle/service/vi/shared_buffer_manager.h"
+#include "core/hle/service/vi/vi_results.h"
+#include "core/hle/service/vi/vi_types.h"
+
+namespace Service::AM {
+
+DisplayLayerManager::DisplayLayerManager() = default;
+DisplayLayerManager::~DisplayLayerManager() {
+ this->Finalize();
+}
+
+void DisplayLayerManager::Initialize(Core::System& system, Kernel::KProcess* process,
+ AppletId applet_id, LibraryAppletMode mode) {
+ R_ASSERT(system.ServiceManager()
+ .GetService<VI::IManagerRootService>("vi:m", true)
+ ->GetDisplayService(&m_display_service, VI::Policy::Compositor));
+ R_ASSERT(m_display_service->GetManagerDisplayService(&m_manager_display_service));
+
+ m_process = process;
+ m_system_shared_buffer_id = 0;
+ m_system_shared_layer_id = 0;
+ m_applet_id = applet_id;
+ m_buffer_sharing_enabled = false;
+ m_blending_enabled = mode == LibraryAppletMode::PartialForeground ||
+ mode == LibraryAppletMode::PartialForegroundIndirectDisplay;
+}
+
+void DisplayLayerManager::Finalize() {
+ if (!m_manager_display_service) {
+ return;
+ }
+
+ // Clean up managed layers.
+ for (const auto& layer : m_managed_display_layers) {
+ m_manager_display_service->DestroyManagedLayer(layer);
+ }
+
+ for (const auto& layer : m_managed_display_recording_layers) {
+ m_manager_display_service->DestroyManagedLayer(layer);
+ }
+
+ // Clean up shared layers.
+ if (m_buffer_sharing_enabled) {
+ m_manager_display_service->DestroySharedLayerSession(m_process);
+ }
+
+ m_manager_display_service = nullptr;
+ m_display_service = nullptr;
+}
+
+Result DisplayLayerManager::CreateManagedDisplayLayer(u64* out_layer_id) {
+ R_UNLESS(m_manager_display_service != nullptr, VI::ResultOperationFailed);
+
+ // TODO(Subv): Find out how AM determines the display to use, for now just
+ // create the layer in the Default display.
+ u64 display_id;
+ R_TRY(m_display_service->OpenDisplay(&display_id, VI::DisplayName{"Default"}));
+ R_TRY(m_manager_display_service->CreateManagedLayer(
+ out_layer_id, 0, display_id, Service::AppletResourceUserId{m_process->GetProcessId()}));
+
+ m_manager_display_service->SetLayerVisibility(m_visible, *out_layer_id);
+ m_managed_display_layers.emplace(*out_layer_id);
+
+ R_SUCCEED();
+}
+
+Result DisplayLayerManager::CreateManagedDisplaySeparableLayer(u64* out_layer_id,
+ u64* out_recording_layer_id) {
+ R_UNLESS(m_manager_display_service != nullptr, VI::ResultOperationFailed);
+
+ // TODO(Subv): Find out how AM determines the display to use, for now just
+ // create the layer in the Default display.
+ // This calls nn::vi::CreateRecordingLayer() which creates another layer.
+ // Currently we do not support more than 1 layer per display, output 1 layer id for now.
+ // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse
+ // side effects.
+ *out_recording_layer_id = 0;
+ R_RETURN(this->CreateManagedDisplayLayer(out_layer_id));
+}
+
+Result DisplayLayerManager::IsSystemBufferSharingEnabled() {
+ // Succeed if already enabled.
+ R_SUCCEED_IF(m_buffer_sharing_enabled);
+
+ // Ensure we can access shared layers.
+ R_UNLESS(m_manager_display_service != nullptr, VI::ResultOperationFailed);
+ R_UNLESS(m_applet_id != AppletId::Application, VI::ResultPermissionDenied);
+
+ // Create the shared layer.
+ u64 display_id;
+ R_TRY(m_display_service->OpenDisplay(&display_id, VI::DisplayName{"Default"}));
+ R_TRY(m_manager_display_service->CreateSharedLayerSession(m_process, &m_system_shared_buffer_id,
+ &m_system_shared_layer_id, display_id,
+ m_blending_enabled));
+
+ // We succeeded, so set up remaining state.
+ m_buffer_sharing_enabled = true;
+ m_manager_display_service->SetLayerVisibility(m_visible, m_system_shared_layer_id);
+ R_SUCCEED();
+}
+
+Result DisplayLayerManager::GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id,
+ u64* out_system_shared_layer_id) {
+ R_TRY(this->IsSystemBufferSharingEnabled());
+
+ *out_system_shared_buffer_id = m_system_shared_buffer_id;
+ *out_system_shared_layer_id = m_system_shared_layer_id;
+
+ R_SUCCEED();
+}
+
+void DisplayLayerManager::SetWindowVisibility(bool visible) {
+ if (m_visible == visible) {
+ return;
+ }
+
+ m_visible = visible;
+
+ if (m_manager_display_service) {
+ if (m_system_shared_layer_id) {
+ m_manager_display_service->SetLayerVisibility(m_visible, m_system_shared_layer_id);
+ }
+
+ for (const auto layer_id : m_managed_display_layers) {
+ m_manager_display_service->SetLayerVisibility(m_visible, layer_id);
+ }
+ }
+}
+
+bool DisplayLayerManager::GetWindowVisibility() const {
+ return m_visible;
+}
+
+Result DisplayLayerManager::WriteAppletCaptureBuffer(bool* out_was_written,
+ s32* out_fbshare_layer_index) {
+ R_UNLESS(m_buffer_sharing_enabled, VI::ResultPermissionDenied);
+ R_RETURN(m_display_service->GetContainer()->GetSharedBufferManager()->WriteAppletCaptureBuffer(
+ out_was_written, out_fbshare_layer_index));
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/display_layer_manager.h b/src/core/hle/service/am/display_layer_manager.h
new file mode 100644
index 000000000..a66509c04
--- /dev/null
+++ b/src/core/hle/service/am/display_layer_manager.h
@@ -0,0 +1,62 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <set>
+
+#include "common/common_types.h"
+#include "core/hle/result.h"
+#include "core/hle/service/am/am_types.h"
+
+namespace Core {
+class System;
+}
+
+namespace Kernel {
+class KProcess;
+}
+
+namespace Service::VI {
+class IApplicationDisplayService;
+class IManagerDisplayService;
+} // namespace Service::VI
+
+namespace Service::AM {
+
+class DisplayLayerManager {
+public:
+ explicit DisplayLayerManager();
+ ~DisplayLayerManager();
+
+ void Initialize(Core::System& system, Kernel::KProcess* process, AppletId applet_id,
+ LibraryAppletMode mode);
+ void Finalize();
+
+ Result CreateManagedDisplayLayer(u64* out_layer_id);
+ Result CreateManagedDisplaySeparableLayer(u64* out_layer_id, u64* out_recording_layer_id);
+
+ Result IsSystemBufferSharingEnabled();
+ Result GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id,
+ u64* out_system_shared_layer_id);
+
+ void SetWindowVisibility(bool visible);
+ bool GetWindowVisibility() const;
+
+ Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_fbshare_layer_index);
+
+private:
+ Kernel::KProcess* m_process{};
+ std::shared_ptr<VI::IApplicationDisplayService> m_display_service{};
+ std::shared_ptr<VI::IManagerDisplayService> m_manager_display_service{};
+ std::set<u64> m_managed_display_layers{};
+ std::set<u64> m_managed_display_recording_layers{};
+ u64 m_system_shared_buffer_id{};
+ u64 m_system_shared_layer_id{};
+ AppletId m_applet_id{};
+ bool m_buffer_sharing_enabled{};
+ bool m_blending_enabled{};
+ bool m_visible{true};
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/frontend/applet_web_browser.cpp b/src/core/hle/service/am/frontend/applet_web_browser.cpp
index bb60260b4..835c20c4e 100644
--- 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/library_applet_storage.cpp b/src/core/hle/service/am/library_applet_storage.cpp
index 46e6c0111..0412c215d 100644
--- a/src/core/hle/service/am/library_applet_storage.cpp
+++ b/src/core/hle/service/am/library_applet_storage.cpp
@@ -70,7 +70,7 @@ public:
Result Read(s64 offset, void* buffer, size_t size) override {
R_TRY(ValidateOffset(offset, size, m_size));
- m_memory.ReadBlock(m_trmem->GetSourceAddress(), buffer, size);
+ m_memory.ReadBlock(m_trmem->GetSourceAddress() + offset, buffer, size);
R_SUCCEED();
}
@@ -79,7 +79,7 @@ public:
R_UNLESS(m_is_writable, ResultUnknown);
R_TRY(ValidateOffset(offset, size, m_size));
- m_memory.WriteBlock(m_trmem->GetSourceAddress(), buffer, size);
+ m_memory.WriteBlock(m_trmem->GetSourceAddress() + offset, buffer, size);
R_SUCCEED();
}
diff --git a/src/core/hle/service/am/managed_layer_holder.cpp b/src/core/hle/service/am/managed_layer_holder.cpp
deleted file mode 100644
index 61eb8641a..000000000
--- a/src/core/hle/service/am/managed_layer_holder.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/am/managed_layer_holder.h"
-#include "core/hle/service/nvnflinger/nvnflinger.h"
-
-namespace Service::AM {
-
-ManagedLayerHolder::ManagedLayerHolder() = default;
-ManagedLayerHolder::~ManagedLayerHolder() {
- if (!m_nvnflinger) {
- return;
- }
-
- for (const auto& layer : m_managed_display_layers) {
- m_nvnflinger->DestroyLayer(layer);
- }
-
- for (const auto& layer : m_managed_display_recording_layers) {
- m_nvnflinger->DestroyLayer(layer);
- }
-
- m_nvnflinger = nullptr;
-}
-
-void ManagedLayerHolder::Initialize(Nvnflinger::Nvnflinger* nvnflinger) {
- m_nvnflinger = nvnflinger;
-}
-
-void ManagedLayerHolder::CreateManagedDisplayLayer(u64* out_layer) {
- // TODO(Subv): Find out how AM determines the display to use, for now just
- // create the layer in the Default display.
- const auto display_id = m_nvnflinger->OpenDisplay("Default");
- const auto layer_id = m_nvnflinger->CreateLayer(*display_id);
-
- m_managed_display_layers.emplace(*layer_id);
-
- *out_layer = *layer_id;
-}
-
-void ManagedLayerHolder::CreateManagedDisplaySeparableLayer(u64* out_layer,
- u64* out_recording_layer) {
- // TODO(Subv): Find out how AM determines the display to use, for now just
- // create the layer in the Default display.
- // This calls nn::vi::CreateRecordingLayer() which creates another layer.
- // Currently we do not support more than 1 layer per display, output 1 layer id for now.
- // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse
- // side effects.
- // TODO: Support multiple layers
- const auto display_id = m_nvnflinger->OpenDisplay("Default");
- const auto layer_id = m_nvnflinger->CreateLayer(*display_id);
-
- m_managed_display_layers.emplace(*layer_id);
-
- *out_layer = *layer_id;
- *out_recording_layer = 0;
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/managed_layer_holder.h b/src/core/hle/service/am/managed_layer_holder.h
deleted file mode 100644
index f7fe03f24..000000000
--- a/src/core/hle/service/am/managed_layer_holder.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <set>
-
-#include "common/common_funcs.h"
-#include "common/common_types.h"
-
-namespace Service::Nvnflinger {
-class Nvnflinger;
-}
-
-namespace Service::AM {
-
-class ManagedLayerHolder {
-public:
- ManagedLayerHolder();
- ~ManagedLayerHolder();
-
- void Initialize(Nvnflinger::Nvnflinger* nvnflinger);
- void CreateManagedDisplayLayer(u64* out_layer);
- void CreateManagedDisplaySeparableLayer(u64* out_layer, u64* out_recording_layer);
-
-private:
- Nvnflinger::Nvnflinger* m_nvnflinger{};
- std::set<u64> m_managed_display_layers{};
- std::set<u64> m_managed_display_recording_layers{};
-};
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp b/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp
index eebd90ba2..21747783a 100644
--- 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<ISystemAppletProxy>(
- system, applet, process_handle.Get(), m_nvnflinger);
+ *out_system_applet_proxy =
+ std::make_shared<ISystemAppletProxy>(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<ILibraryAppletProxy>(
- system, applet, process_handle.Get(), m_nvnflinger);
+ *out_library_applet_proxy =
+ std::make_shared<ILibraryAppletProxy>(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 100644
--- 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<IAllSystemAppletProxiesService> {
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<Applet> 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..cb53b07e0 100644
--- a/src/core/hle/service/am/service/application_functions.cpp
+++ b/src/core/hle/service/am/service/application_functions.cpp
@@ -15,7 +15,9 @@
#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/glue/glue_manager.h"
+#include "core/hle/service/ns/application_manager_interface.h"
+#include "core/hle/service/ns/service_getter_interface.h"
#include "core/hle/service/sm/sm.h"
namespace Service::AM {
@@ -40,7 +42,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_
{26, D<&IApplicationFunctions::GetSaveDataSize>, "GetSaveDataSize"},
{27, D<&IApplicationFunctions::CreateCacheStorage>, "CreateCacheStorage"},
{28, D<&IApplicationFunctions::GetSaveDataSizeMax>, "GetSaveDataSizeMax"},
- {29, nullptr, "GetCacheStorageMax"},
+ {29, D<&IApplicationFunctions::GetCacheStorageMax>, "GetCacheStorageMax"},
{30, D<&IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed>, "BeginBlockingHomeButtonShortAndLongPressed"},
{31, D<&IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed>, "EndBlockingHomeButtonShortAndLongPressed"},
{32, D<&IApplicationFunctions::BeginBlockingHomeButton>, "BeginBlockingHomeButton"},
@@ -162,11 +164,13 @@ Result IApplicationFunctions::GetDesiredLanguage(Out<u64> out_language_code) {
// Call IApplicationManagerInterface implementation.
auto& service_manager = system.ServiceManager();
- auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2");
- auto app_man = ns_am2->GetApplicationManagerInterface();
+ auto ns_am2 = service_manager.GetService<NS::IServiceGetterInterface>("ns:am2");
+
+ std::shared_ptr<NS::IApplicationManagerInterface> app_man;
+ R_TRY(ns_am2->GetApplicationManagerInterface(&app_man));
// Get desired application language
- u8 desired_language{};
+ NS::ApplicationLanguage desired_language{};
R_TRY(app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages));
// Convert to settings language code.
@@ -267,6 +271,22 @@ Result IApplicationFunctions::GetSaveDataSizeMax(Out<u64> out_max_normal_size,
R_SUCCEED();
}
+Result IApplicationFunctions::GetCacheStorageMax(Out<u32> out_cache_storage_index_max,
+ Out<u64> out_max_journal_size) {
+ LOG_DEBUG(Service_AM, "called");
+
+ std::vector<u8> nacp;
+ R_TRY(system.GetARPManager().GetControlProperty(&nacp, m_applet->program_id));
+
+ auto raw_nacp = std::make_unique<FileSys::RawNACP>();
+ std::memcpy(raw_nacp.get(), nacp.data(), std::min(sizeof(*raw_nacp), nacp.size()));
+
+ *out_cache_storage_index_max = static_cast<u32>(raw_nacp->cache_storage_max_index);
+ *out_max_journal_size = static_cast<u64>(raw_nacp->cache_storage_data_and_journal_max_size);
+
+ R_SUCCEED();
+}
+
Result IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(s64 unused) {
LOG_WARNING(Service_AM, "(STUBBED) called");
diff --git a/src/core/hle/service/am/service/application_functions.h b/src/core/hle/service/am/service/application_functions.h
index 3548202f8..10025a152 100644
--- a/src/core/hle/service/am/service/application_functions.h
+++ b/src/core/hle/service/am/service/application_functions.h
@@ -40,6 +40,7 @@ private:
Result CreateCacheStorage(Out<u32> out_target_media, Out<u64> out_required_size, u16 index,
u64 normal_size, u64 journal_size);
Result GetSaveDataSizeMax(Out<u64> out_max_normal_size, Out<u64> out_max_journal_size);
+ Result GetCacheStorageMax(Out<u32> out_cache_storage_index_max, Out<u64> out_max_journal_size);
Result BeginBlockingHomeButtonShortAndLongPressed(s64 unused);
Result EndBlockingHomeButtonShortAndLongPressed();
Result BeginBlockingHomeButton(s64 timeout_ns);
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 100644
--- 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> 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<SharedPointer<ISelfController>> out_self_controller) {
LOG_DEBUG(Service_AM, "called");
- *out_self_controller =
- std::make_shared<ISelfController>(system, m_applet, m_process, m_nvnflinger);
+ *out_self_controller = std::make_shared<ISelfController>(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 100644
--- 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<IApplicationProxy> {
public:
explicit IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet,
- Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger);
+ Kernel::KProcess* process);
~IApplicationProxy();
private:
@@ -40,7 +40,6 @@ private:
Out<SharedPointer<IApplicationFunctions>> out_application_functions);
private:
- Nvnflinger::Nvnflinger& m_nvnflinger;
Kernel::KProcess* const m_process;
const std::shared_ptr<Applet> 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 100644
--- 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<IApplicationProxy>(system, applet, process_handle.Get(), m_nvnflinger);
+ std::make_shared<IApplicationProxy>(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 100644
--- 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<IApplicationProxyService> {
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<Applet> GetAppletFromProcessId(ProcessId pid);
- Nvnflinger::Nvnflinger& m_nvnflinger;
};
} // namespace AM
diff --git a/src/core/hle/service/am/service/common_state_getter.cpp b/src/core/hle/service/am/service/common_state_getter.cpp
index 12d7e8cb1..548498e83 100644
--- a/src/core/hle/service/am/service/common_state_getter.cpp
+++ b/src/core/hle/service/am/service/common_state_getter.cpp
@@ -11,6 +11,7 @@
#include "core/hle/service/pm/pm.h"
#include "core/hle/service/sm/sm.h"
#include "core/hle/service/vi/vi.h"
+#include "core/hle/service/vi/vi_types.h"
namespace Service::AM {
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 100644
--- 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<bool> out_was_written, Out<s32> 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<bool> out_was_written, Out<s32> 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<bool> out_was_written, Out<s32> 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 100644
--- 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<ILibraryAppletAccessor> 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 100644
--- 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> 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<SharedPointer<ISelfController>> out_self_controller) {
LOG_DEBUG(Service_AM, "called");
- *out_self_controller =
- std::make_shared<ISelfController>(system, m_applet, m_process, m_nvnflinger);
+ *out_self_controller = std::make_shared<ISelfController>(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 100644
--- 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<ILibraryAppletProxy> {
public:
explicit ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
- Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger);
+ Kernel::KProcess* process);
~ILibraryAppletProxy();
private:
@@ -47,7 +47,6 @@ private:
Result GetGlobalStateController(
Out<SharedPointer<IGlobalStateController>> out_global_state_controller);
- Nvnflinger::Nvnflinger& m_nvnflinger;
Kernel::KProcess* const m_process;
const std::shared_ptr<Applet> 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 100644
--- 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::NS>("ns:am2");
- auto app_man = ns_am2->GetApplicationManagerInterface();
+ auto ns_am2 = service_manager.GetService<NS::IServiceGetterInterface>("ns:am2");
+
+ std::shared_ptr<NS::IApplicationManagerInterface> app_man;
+ R_TRY(ns_am2->GetApplicationManagerInterface(&app_man));
// Get desired application language
- 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<u64> out_applicat
}
Result ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(
- Out<bool> out_no_users_available, Out<s32> out_users_count,
+ Out<bool> out_can_select_any_user, Out<s32> out_users_count,
OutArray<Common::UUID, BufferAttr_HipcMapAlias> out_users) {
const Service::Account::ProfileManager manager{};
- *out_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<s32>(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 100644
--- 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<ErrorContext, BufferAttr_HipcMapAlias> error_context);
Result GetMainAppletApplicationDesiredLanguage(Out<u64> out_desired_language);
Result GetCurrentApplicationId(Out<u64> out_application_id);
- Result GetMainAppletAvailableUsers(Out<bool> out_no_users_available, Out<s32> out_users_count,
+ Result GetMainAppletAvailableUsers(Out<bool> out_can_select_any_user, Out<s32> out_users_count,
OutArray<Common::UUID, BufferAttr_HipcMapAlias> out_users);
Result ShouldSetGpuTimeSliceManually(Out<bool> out_should_set_gpu_time_slice_manually);
Result Cmd160(Out<u64> out_unknown0);
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 100644
--- 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> 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<Applet>
// 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<u64> 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<u64> out_buffer_id, Out<u64> out_layer_id) {
- LOG_INFO(Service_AM, "(STUBBED) called");
-
- R_TRY(this->IsSystemBufferSharingEnabled());
+ LOG_INFO(Service_AM, "called");
- 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<u64> 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<u64> out_layer_id,
Out<u64> 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 100644
--- 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<ISelfController> {
public:
explicit ISelfController(Core::System& system_, std::shared_ptr<Applet> 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<Applet> 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 100644
--- 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> 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<SharedPointer<ISelfController>> out_self_controller) {
LOG_DEBUG(Service_AM, "called");
- *out_self_controller =
- std::make_shared<ISelfController>(system, m_applet, m_process, m_nvnflinger);
+ *out_self_controller = std::make_shared<ISelfController>(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 100644
--- 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<ISystemAppletProxy> {
public:
explicit ISystemAppletProxy(Core::System& system, std::shared_ptr<Applet> applet,
- Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger);
+ Kernel::KProcess* process);
~ISystemAppletProxy();
private:
@@ -46,7 +46,6 @@ private:
Result GetGlobalStateController(
Out<SharedPointer<IGlobalStateController>> out_global_state_controller);
- Nvnflinger::Nvnflinger& m_nvnflinger;
Kernel::KProcess* const m_process;
const std::shared_ptr<Applet> 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 100644
--- 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/am/system_buffer_manager.cpp b/src/core/hle/service/am/system_buffer_manager.cpp
deleted file mode 100644
index 48923fe41..000000000
--- a/src/core/hle/service/am/system_buffer_manager.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/am/system_buffer_manager.h"
-#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
-#include "core/hle/service/nvnflinger/nvnflinger.h"
-#include "core/hle/service/vi/vi_results.h"
-
-namespace Service::AM {
-
-SystemBufferManager::SystemBufferManager() = default;
-
-SystemBufferManager::~SystemBufferManager() {
- if (!m_nvnflinger) {
- return;
- }
-
- // Clean up shared layers.
- if (m_buffer_sharing_enabled) {
- m_nvnflinger->GetSystemBufferManager().Finalize(m_process);
- }
-}
-
-bool SystemBufferManager::Initialize(Nvnflinger::Nvnflinger* nvnflinger, Kernel::KProcess* process,
- AppletId applet_id, LibraryAppletMode mode) {
- if (m_nvnflinger) {
- return m_buffer_sharing_enabled;
- }
-
- m_process = process;
- m_nvnflinger = nvnflinger;
- m_buffer_sharing_enabled = false;
- m_system_shared_buffer_id = 0;
- m_system_shared_layer_id = 0;
-
- if (applet_id <= AppletId::Application) {
- return false;
- }
-
- Nvnflinger::LayerBlending blending = Nvnflinger::LayerBlending::None;
- if (mode == LibraryAppletMode::PartialForeground ||
- mode == LibraryAppletMode::PartialForegroundIndirectDisplay) {
- blending = Nvnflinger::LayerBlending::Coverage;
- }
-
- const auto display_id = m_nvnflinger->OpenDisplay("Default").value();
- const auto res = m_nvnflinger->GetSystemBufferManager().Initialize(
- m_process, &m_system_shared_buffer_id, &m_system_shared_layer_id, display_id, blending);
-
- if (res.IsSuccess()) {
- m_buffer_sharing_enabled = true;
- m_nvnflinger->SetLayerVisibility(m_system_shared_layer_id, m_visible);
- }
-
- return m_buffer_sharing_enabled;
-}
-
-void SystemBufferManager::SetWindowVisibility(bool visible) {
- if (m_visible == visible) {
- return;
- }
-
- m_visible = visible;
-
- if (m_nvnflinger) {
- m_nvnflinger->SetLayerVisibility(m_system_shared_layer_id, m_visible);
- }
-}
-
-Result SystemBufferManager::WriteAppletCaptureBuffer(bool* out_was_written,
- s32* out_fbshare_layer_index) {
- if (!m_buffer_sharing_enabled) {
- return VI::ResultPermissionDenied;
- }
-
- return m_nvnflinger->GetSystemBufferManager().WriteAppletCaptureBuffer(out_was_written,
- out_fbshare_layer_index);
-}
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/am/system_buffer_manager.h b/src/core/hle/service/am/system_buffer_manager.h
deleted file mode 100644
index 0690f68b6..000000000
--- a/src/core/hle/service/am/system_buffer_manager.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <set>
-
-#include "common/common_funcs.h"
-#include "common/common_types.h"
-
-#include "core/hle/service/am/am_types.h"
-
-namespace Kernel {
-class KProcess;
-}
-
-namespace Service::Nvnflinger {
-class Nvnflinger;
-}
-
-union Result;
-
-namespace Service::AM {
-
-class SystemBufferManager {
-public:
- SystemBufferManager();
- ~SystemBufferManager();
-
- bool Initialize(Nvnflinger::Nvnflinger* flinger, Kernel::KProcess* process, AppletId applet_id,
- LibraryAppletMode mode);
-
- void GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id,
- u64* out_system_shared_layer_id) {
- *out_system_shared_buffer_id = m_system_shared_buffer_id;
- *out_system_shared_layer_id = m_system_shared_layer_id;
- }
-
- void SetWindowVisibility(bool visible);
-
- Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_fbshare_layer_index);
-
-private:
- Kernel::KProcess* m_process{};
- Nvnflinger::Nvnflinger* m_nvnflinger{};
- bool m_buffer_sharing_enabled{};
- bool m_visible{true};
- u64 m_system_shared_buffer_id{};
- u64 m_system_shared_layer_id{};
-};
-
-} // namespace Service::AM
diff --git a/src/core/hle/service/audio/audctl.cpp b/src/core/hle/service/audio/audctl.cpp
deleted file mode 100644
index 3101cf447..000000000
--- a/src/core/hle/service/audio/audctl.cpp
+++ /dev/null
@@ -1,201 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "common/logging/log.h"
-#include "core/hle/service/audio/audctl.h"
-#include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/set/system_settings_server.h"
-#include "core/hle/service/sm/sm.h"
-
-namespace Service::Audio {
-
-AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "GetTargetVolume"},
- {1, nullptr, "SetTargetVolume"},
- {2, &AudCtl::GetTargetVolumeMin, "GetTargetVolumeMin"},
- {3, &AudCtl::GetTargetVolumeMax, "GetTargetVolumeMax"},
- {4, nullptr, "IsTargetMute"},
- {5, nullptr, "SetTargetMute"},
- {6, nullptr, "IsTargetConnected"},
- {7, nullptr, "SetDefaultTarget"},
- {8, nullptr, "GetDefaultTarget"},
- {9, &AudCtl::GetAudioOutputMode, "GetAudioOutputMode"},
- {10, &AudCtl::SetAudioOutputMode, "SetAudioOutputMode"},
- {11, nullptr, "SetForceMutePolicy"},
- {12, &AudCtl::GetForceMutePolicy, "GetForceMutePolicy"},
- {13, &AudCtl::GetOutputModeSetting, "GetOutputModeSetting"},
- {14, &AudCtl::SetOutputModeSetting, "SetOutputModeSetting"},
- {15, nullptr, "SetOutputTarget"},
- {16, nullptr, "SetInputTargetForceEnabled"},
- {17, &AudCtl::SetHeadphoneOutputLevelMode, "SetHeadphoneOutputLevelMode"},
- {18, &AudCtl::GetHeadphoneOutputLevelMode, "GetHeadphoneOutputLevelMode"},
- {19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"},
- {20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"},
- {21, nullptr, "GetAudioOutputTargetForPlayReport"},
- {22, nullptr, "NotifyHeadphoneVolumeWarningDisplayedEvent"},
- {23, nullptr, "SetSystemOutputMasterVolume"},
- {24, nullptr, "GetSystemOutputMasterVolume"},
- {25, nullptr, "GetAudioVolumeDataForPlayReport"},
- {26, nullptr, "UpdateHeadphoneSettings"},
- {27, nullptr, "SetVolumeMappingTableForDev"},
- {28, nullptr, "GetAudioOutputChannelCountForPlayReport"},
- {29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
- {30, &AudCtl::SetSpeakerAutoMuteEnabled, "SetSpeakerAutoMuteEnabled"},
- {31, &AudCtl::IsSpeakerAutoMuteEnabled, "IsSpeakerAutoMuteEnabled"},
- {32, nullptr, "GetActiveOutputTarget"},
- {33, nullptr, "GetTargetDeviceInfo"},
- {34, nullptr, "AcquireTargetNotification"},
- {35, nullptr, "SetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
- {36, nullptr, "GetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
- {37, nullptr, "SetHearingProtectionSafeguardEnabled"},
- {38, nullptr, "IsHearingProtectionSafeguardEnabled"},
- {39, nullptr, "IsHearingProtectionSafeguardMonitoringOutputForDebug"},
- {40, nullptr, "GetSystemInformationForDebug"},
- {41, nullptr, "SetVolumeButtonLongPressTime"},
- {42, nullptr, "SetNativeVolumeForDebug"},
- {10000, nullptr, "NotifyAudioOutputTargetForPlayReport"},
- {10001, nullptr, "NotifyAudioOutputChannelCountForPlayReport"},
- {10002, nullptr, "NotifyUnsupportedUsbOutputDeviceAttachedForPlayReport"},
- {10100, nullptr, "GetAudioVolumeDataForPlayReport"},
- {10101, nullptr, "BindAudioVolumeUpdateEventForPlayReport"},
- {10102, nullptr, "BindAudioOutputTargetUpdateEventForPlayReport"},
- {10103, nullptr, "GetAudioOutputTargetForPlayReport"},
- {10104, nullptr, "GetAudioOutputChannelCountForPlayReport"},
- {10105, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
- {10106, nullptr, "GetDefaultAudioOutputTargetForPlayReport"},
- {50000, nullptr, "SetAnalogInputBoostGainForPrototyping"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-
- m_set_sys =
- system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
-}
-
-AudCtl::~AudCtl() = default;
-
-void AudCtl::GetTargetVolumeMin(HLERequestContext& ctx) {
- LOG_DEBUG(Audio, "called.");
-
- // This service function is currently hardcoded on the
- // actual console to this value (as of 8.0.0).
- constexpr s32 target_min_volume = 0;
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(target_min_volume);
-}
-
-void AudCtl::GetTargetVolumeMax(HLERequestContext& ctx) {
- LOG_DEBUG(Audio, "called.");
-
- // This service function is currently hardcoded on the
- // actual console to this value (as of 8.0.0).
- constexpr s32 target_max_volume = 15;
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(target_max_volume);
-}
-
-void AudCtl::GetAudioOutputMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
-
- Set::AudioOutputMode output_mode{};
- const auto result = m_set_sys->GetAudioOutputMode(output_mode, target);
-
- LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(result);
- rb.PushEnum(output_mode);
-}
-
-void AudCtl::SetAudioOutputMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
- const auto output_mode{rp.PopEnum<Set::AudioOutputMode>()};
-
- const auto result = m_set_sys->SetAudioOutputMode(target, output_mode);
-
- LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void AudCtl::GetForceMutePolicy(HLERequestContext& ctx) {
- LOG_WARNING(Audio, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushEnum(ForceMutePolicy::Disable);
-}
-
-void AudCtl::GetOutputModeSetting(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
-
- LOG_WARNING(Audio, "(STUBBED) called, target={}", target);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushEnum(Set::AudioOutputMode::ch_7_1);
-}
-
-void AudCtl::SetOutputModeSetting(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()};
- const auto output_mode{rp.PopEnum<Set::AudioOutputMode>()};
-
- LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void AudCtl::SetHeadphoneOutputLevelMode(HLERequestContext& ctx) {
- LOG_WARNING(Audio, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void AudCtl::GetHeadphoneOutputLevelMode(HLERequestContext& ctx) {
- LOG_WARNING(Audio, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushEnum(HeadphoneOutputLevelMode::Normal);
-}
-
-void AudCtl::SetSpeakerAutoMuteEnabled(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto is_speaker_auto_mute_enabled{rp.Pop<bool>()};
-
- LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}",
- is_speaker_auto_mute_enabled);
-
- const auto result = m_set_sys->SetSpeakerAutoMuteFlag(is_speaker_auto_mute_enabled);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-void AudCtl::IsSpeakerAutoMuteEnabled(HLERequestContext& ctx) {
- bool is_speaker_auto_mute_enabled{};
- const auto result = m_set_sys->GetSpeakerAutoMuteFlag(is_speaker_auto_mute_enabled);
-
- LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}",
- is_speaker_auto_mute_enabled);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(result);
- rb.Push<u8>(is_speaker_auto_mute_enabled);
-}
-
-} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audctl.h b/src/core/hle/service/audio/audctl.h
deleted file mode 100644
index 4c90ead70..000000000
--- a/src/core/hle/service/audio/audctl.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "core/hle/service/service.h"
-
-namespace Core {
-class System;
-}
-
-namespace Service::Set {
-class ISystemSettingsServer;
-}
-
-namespace Service::Audio {
-
-class AudCtl final : public ServiceFramework<AudCtl> {
-public:
- explicit AudCtl(Core::System& system_);
- ~AudCtl() override;
-
-private:
- enum class ForceMutePolicy {
- Disable,
- SpeakerMuteOnHeadphoneUnplugged,
- };
-
- enum class HeadphoneOutputLevelMode {
- Normal,
- HighPower,
- };
-
- void GetTargetVolumeMin(HLERequestContext& ctx);
- void GetTargetVolumeMax(HLERequestContext& ctx);
- void GetAudioOutputMode(HLERequestContext& ctx);
- void SetAudioOutputMode(HLERequestContext& ctx);
- void GetForceMutePolicy(HLERequestContext& ctx);
- void GetOutputModeSetting(HLERequestContext& ctx);
- void SetOutputModeSetting(HLERequestContext& ctx);
- void SetHeadphoneOutputLevelMode(HLERequestContext& ctx);
- void GetHeadphoneOutputLevelMode(HLERequestContext& ctx);
- void SetSpeakerAutoMuteEnabled(HLERequestContext& ctx);
- void IsSpeakerAutoMuteEnabled(HLERequestContext& ctx);
- void AcquireTargetNotification(HLERequestContext& ctx);
-
- std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
-};
-
-} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio.cpp b/src/core/hle/service/audio/audio.cpp
index dccd16309..44af030eb 100644
--- a/src/core/hle/service/audio/audio.cpp
+++ b/src/core/hle/service/audio/audio.cpp
@@ -2,9 +2,9 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h"
-#include "core/hle/service/audio/audctl.h"
#include "core/hle/service/audio/audin_u.h"
#include "core/hle/service/audio/audio.h"
+#include "core/hle/service/audio/audio_controller.h"
#include "core/hle/service/audio/audout_u.h"
#include "core/hle/service/audio/audrec_a.h"
#include "core/hle/service/audio/audrec_u.h"
@@ -18,7 +18,7 @@ namespace Service::Audio {
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
- server_manager->RegisterNamedService("audctl", std::make_shared<AudCtl>(system));
+ server_manager->RegisterNamedService("audctl", std::make_shared<IAudioController>(system));
server_manager->RegisterNamedService("audout:u", std::make_shared<AudOutU>(system));
server_manager->RegisterNamedService("audin:u", std::make_shared<AudInU>(system));
server_manager->RegisterNamedService("audrec:a", std::make_shared<AudRecA>(system));
diff --git a/src/core/hle/service/audio/audio_controller.cpp b/src/core/hle/service/audio/audio_controller.cpp
new file mode 100644
index 000000000..a6da66d0f
--- /dev/null
+++ b/src/core/hle/service/audio/audio_controller.cpp
@@ -0,0 +1,174 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/logging/log.h"
+#include "core/hle/service/audio/audio_controller.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ipc_helpers.h"
+#include "core/hle/service/set/system_settings_server.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::Audio {
+
+IAudioController::IAudioController(Core::System& system_)
+ : ServiceFramework{system_, "audctl"}, service_context{system, "audctl"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetTargetVolume"},
+ {1, nullptr, "SetTargetVolume"},
+ {2, C<&IAudioController::GetTargetVolumeMin>, "GetTargetVolumeMin"},
+ {3, C<&IAudioController::GetTargetVolumeMax>, "GetTargetVolumeMax"},
+ {4, nullptr, "IsTargetMute"},
+ {5, nullptr, "SetTargetMute"},
+ {6, nullptr, "IsTargetConnected"},
+ {7, nullptr, "SetDefaultTarget"},
+ {8, nullptr, "GetDefaultTarget"},
+ {9, C<&IAudioController::GetAudioOutputMode>, "GetAudioOutputMode"},
+ {10, C<&IAudioController::SetAudioOutputMode>, "SetAudioOutputMode"},
+ {11, nullptr, "SetForceMutePolicy"},
+ {12, C<&IAudioController::GetForceMutePolicy>, "GetForceMutePolicy"},
+ {13, C<&IAudioController::GetOutputModeSetting>, "GetOutputModeSetting"},
+ {14, C<&IAudioController::SetOutputModeSetting>, "SetOutputModeSetting"},
+ {15, nullptr, "SetOutputTarget"},
+ {16, nullptr, "SetInputTargetForceEnabled"},
+ {17, C<&IAudioController::SetHeadphoneOutputLevelMode>, "SetHeadphoneOutputLevelMode"},
+ {18, C<&IAudioController::GetHeadphoneOutputLevelMode>, "GetHeadphoneOutputLevelMode"},
+ {19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"},
+ {20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"},
+ {21, nullptr, "GetAudioOutputTargetForPlayReport"},
+ {22, nullptr, "NotifyHeadphoneVolumeWarningDisplayedEvent"},
+ {23, nullptr, "SetSystemOutputMasterVolume"},
+ {24, nullptr, "GetSystemOutputMasterVolume"},
+ {25, nullptr, "GetAudioVolumeDataForPlayReport"},
+ {26, nullptr, "UpdateHeadphoneSettings"},
+ {27, nullptr, "SetVolumeMappingTableForDev"},
+ {28, nullptr, "GetAudioOutputChannelCountForPlayReport"},
+ {29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
+ {30, C<&IAudioController::SetSpeakerAutoMuteEnabled>, "SetSpeakerAutoMuteEnabled"},
+ {31, C<&IAudioController::IsSpeakerAutoMuteEnabled>, "IsSpeakerAutoMuteEnabled"},
+ {32, nullptr, "GetActiveOutputTarget"},
+ {33, nullptr, "GetTargetDeviceInfo"},
+ {34, C<&IAudioController::AcquireTargetNotification>, "AcquireTargetNotification"},
+ {35, nullptr, "SetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
+ {36, nullptr, "GetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
+ {37, nullptr, "SetHearingProtectionSafeguardEnabled"},
+ {38, nullptr, "IsHearingProtectionSafeguardEnabled"},
+ {39, nullptr, "IsHearingProtectionSafeguardMonitoringOutputForDebug"},
+ {40, nullptr, "GetSystemInformationForDebug"},
+ {41, nullptr, "SetVolumeButtonLongPressTime"},
+ {42, nullptr, "SetNativeVolumeForDebug"},
+ {10000, nullptr, "NotifyAudioOutputTargetForPlayReport"},
+ {10001, nullptr, "NotifyAudioOutputChannelCountForPlayReport"},
+ {10002, nullptr, "NotifyUnsupportedUsbOutputDeviceAttachedForPlayReport"},
+ {10100, nullptr, "GetAudioVolumeDataForPlayReport"},
+ {10101, nullptr, "BindAudioVolumeUpdateEventForPlayReport"},
+ {10102, nullptr, "BindAudioOutputTargetUpdateEventForPlayReport"},
+ {10103, nullptr, "GetAudioOutputTargetForPlayReport"},
+ {10104, nullptr, "GetAudioOutputChannelCountForPlayReport"},
+ {10105, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
+ {10106, nullptr, "GetDefaultAudioOutputTargetForPlayReport"},
+ {50000, nullptr, "SetAnalogInputBoostGainForPrototyping"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+
+ m_set_sys =
+ system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
+ notification_event = service_context.CreateEvent("IAudioController:NotificationEvent");
+}
+
+IAudioController::~IAudioController() {
+ service_context.CloseEvent(notification_event);
+};
+
+Result IAudioController::GetTargetVolumeMin(Out<s32> out_target_min_volume) {
+ LOG_DEBUG(Audio, "called.");
+
+ // This service function is currently hardcoded on the
+ // actual console to this value (as of 8.0.0).
+ *out_target_min_volume = 0;
+ R_SUCCEED();
+}
+
+Result IAudioController::GetTargetVolumeMax(Out<s32> out_target_max_volume) {
+ LOG_DEBUG(Audio, "called.");
+
+ // This service function is currently hardcoded on the
+ // actual console to this value (as of 8.0.0).
+ *out_target_max_volume = 15;
+ R_SUCCEED();
+}
+
+Result IAudioController::GetAudioOutputMode(Out<Set::AudioOutputMode> out_output_mode,
+ Set::AudioOutputModeTarget target) {
+ const auto result = m_set_sys->GetAudioOutputMode(out_output_mode, target);
+
+ LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, *out_output_mode);
+ R_RETURN(result);
+}
+
+Result IAudioController::SetAudioOutputMode(Set::AudioOutputModeTarget target,
+ Set::AudioOutputMode output_mode) {
+ LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
+
+ R_RETURN(m_set_sys->SetAudioOutputMode(target, output_mode));
+}
+
+Result IAudioController::GetForceMutePolicy(Out<ForceMutePolicy> out_mute_policy) {
+ LOG_WARNING(Audio, "(STUBBED) called");
+
+ // Removed on FW 13.2.1+
+ *out_mute_policy = ForceMutePolicy::Disable;
+ R_SUCCEED();
+}
+
+Result IAudioController::GetOutputModeSetting(Out<Set::AudioOutputMode> out_output_mode,
+ Set::AudioOutputModeTarget target) {
+ LOG_WARNING(Audio, "(STUBBED) called, target={}", target);
+
+ *out_output_mode = Set::AudioOutputMode::ch_7_1;
+ R_SUCCEED();
+}
+
+Result IAudioController::SetOutputModeSetting(Set::AudioOutputModeTarget target,
+ Set::AudioOutputMode output_mode) {
+ LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
+ R_SUCCEED();
+}
+
+Result IAudioController::SetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode output_level_mode) {
+ LOG_WARNING(Audio, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IAudioController::GetHeadphoneOutputLevelMode(
+ Out<HeadphoneOutputLevelMode> out_output_level_mode) {
+ LOG_INFO(Audio, "called");
+
+ *out_output_level_mode = HeadphoneOutputLevelMode::Normal;
+ R_SUCCEED();
+}
+
+Result IAudioController::SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled) {
+ LOG_INFO(Audio, "called, is_speaker_auto_mute_enabled={}", is_speaker_auto_mute_enabled);
+
+ R_RETURN(m_set_sys->SetSpeakerAutoMuteFlag(is_speaker_auto_mute_enabled));
+}
+
+Result IAudioController::IsSpeakerAutoMuteEnabled(Out<bool> out_is_speaker_auto_mute_enabled) {
+ const auto result = m_set_sys->GetSpeakerAutoMuteFlag(out_is_speaker_auto_mute_enabled);
+
+ LOG_INFO(Audio, "called, is_speaker_auto_mute_enabled={}", *out_is_speaker_auto_mute_enabled);
+ R_RETURN(result);
+}
+
+Result IAudioController::AcquireTargetNotification(
+ OutCopyHandle<Kernel::KReadableEvent> out_notification_event) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ *out_notification_event = &notification_event->GetReadableEvent();
+ R_SUCCEED();
+}
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio_controller.h b/src/core/hle/service/audio/audio_controller.h
new file mode 100644
index 000000000..9e8514373
--- /dev/null
+++ b/src/core/hle/service/audio/audio_controller.h
@@ -0,0 +1,58 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/set/settings_types.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::Set {
+class ISystemSettingsServer;
+}
+
+namespace Service::Audio {
+
+class IAudioController final : public ServiceFramework<IAudioController> {
+public:
+ explicit IAudioController(Core::System& system_);
+ ~IAudioController() override;
+
+private:
+ enum class ForceMutePolicy {
+ Disable,
+ SpeakerMuteOnHeadphoneUnplugged,
+ };
+
+ enum class HeadphoneOutputLevelMode {
+ Normal,
+ HighPower,
+ };
+
+ Result GetTargetVolumeMin(Out<s32> out_target_min_volume);
+ Result GetTargetVolumeMax(Out<s32> out_target_max_volume);
+ Result GetAudioOutputMode(Out<Set::AudioOutputMode> out_output_mode,
+ Set::AudioOutputModeTarget target);
+ Result SetAudioOutputMode(Set::AudioOutputModeTarget target, Set::AudioOutputMode output_mode);
+ Result GetForceMutePolicy(Out<ForceMutePolicy> out_mute_policy);
+ Result GetOutputModeSetting(Out<Set::AudioOutputMode> out_output_mode,
+ Set::AudioOutputModeTarget target);
+ Result SetOutputModeSetting(Set::AudioOutputModeTarget target,
+ Set::AudioOutputMode output_mode);
+ Result SetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode output_level_mode);
+ Result GetHeadphoneOutputLevelMode(Out<HeadphoneOutputLevelMode> out_output_level_mode);
+ Result SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled);
+ Result IsSpeakerAutoMuteEnabled(Out<bool> out_is_speaker_auto_mute_enabled);
+ Result AcquireTargetNotification(OutCopyHandle<Kernel::KReadableEvent> out_notification_event);
+
+ KernelHelpers::ServiceContext service_context;
+
+ Kernel::KEvent* notification_event;
+ std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
+};
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/caps/caps_a.cpp b/src/core/hle/service/caps/caps_a.cpp
index 47ff072c5..52228b830 100644
--- a/src/core/hle/service/caps/caps_a.cpp
+++ b/src/core/hle/service/caps/caps_a.cpp
@@ -16,7 +16,7 @@ IAlbumAccessorService::IAlbumAccessorService(Core::System& system_,
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetAlbumFileCount"},
- {1, nullptr, "GetAlbumFileList"},
+ {1, C<&IAlbumAccessorService::GetAlbumFileList>, "GetAlbumFileList"},
{2, nullptr, "LoadAlbumFile"},
{3, C<&IAlbumAccessorService::DeleteAlbumFile>, "DeleteAlbumFile"},
{4, nullptr, "StorageCopyAlbumFile"},
@@ -62,6 +62,15 @@ IAlbumAccessorService::IAlbumAccessorService(Core::System& system_,
IAlbumAccessorService::~IAlbumAccessorService() = default;
+Result IAlbumAccessorService::GetAlbumFileList(
+ Out<u64> out_count, AlbumStorage storage,
+ OutArray<AlbumEntry, BufferAttr_HipcMapAlias> out_entries) {
+ LOG_INFO(Service_Capture, "called, storage={}", storage);
+
+ const Result result = manager->GetAlbumFileList(out_entries, *out_count, storage, 0);
+ R_RETURN(TranslateResult(result));
+}
+
Result IAlbumAccessorService::DeleteAlbumFile(AlbumFileId file_id) {
LOG_INFO(Service_Capture, "called, application_id=0x{:0x}, storage={}, type={}",
file_id.application_id, file_id.storage, file_id.type);
diff --git a/src/core/hle/service/caps/caps_a.h b/src/core/hle/service/caps/caps_a.h
index 2cb9b4547..c7a5208e3 100644
--- a/src/core/hle/service/caps/caps_a.h
+++ b/src/core/hle/service/caps/caps_a.h
@@ -21,6 +21,9 @@ public:
~IAlbumAccessorService() override;
private:
+ Result GetAlbumFileList(Out<u64> out_count, AlbumStorage storage,
+ OutArray<AlbumEntry, BufferAttr_HipcMapAlias> out_entries);
+
Result DeleteAlbumFile(AlbumFileId file_id);
Result IsAlbumMounted(Out<bool> out_is_mounted, AlbumStorage storage);
diff --git a/src/core/hle/service/erpt/erpt.cpp b/src/core/hle/service/erpt/erpt.cpp
index 3ea862fad..39ae3a723 100644
--- a/src/core/hle/service/erpt/erpt.cpp
+++ b/src/core/hle/service/erpt/erpt.cpp
@@ -3,6 +3,8 @@
#include <memory>
+#include "common/logging/log.h"
+#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/erpt/erpt.h"
#include "core/hle/service/server_manager.h"
#include "core/hle/service/service.h"
@@ -15,7 +17,7 @@ public:
explicit ErrorReportContext(Core::System& system_) : ServiceFramework{system_, "erpt:c"} {
// clang-format off
static const FunctionInfo functions[] = {
- {0, nullptr, "SubmitContext"},
+ {0, C<&ErrorReportContext::SubmitContext>, "SubmitContext"},
{1, nullptr, "CreateReportV0"},
{2, nullptr, "SetInitialLaunchSettingsCompletionTime"},
{3, nullptr, "ClearInitialLaunchSettingsCompletionTime"},
@@ -36,6 +38,14 @@ public:
RegisterHandlers(functions);
}
+
+private:
+ Result SubmitContext(InBuffer<BufferAttr_HipcMapAlias> buffer_a,
+ InBuffer<BufferAttr_HipcMapAlias> buffer_b) {
+ LOG_WARNING(Service_SET, "(STUBBED) called, buffer_a_size={}, buffer_b_size={}",
+ buffer_a.size(), buffer_b.size());
+ R_SUCCEED();
+ }
};
class ErrorReportSession final : public ServiceFramework<ErrorReportSession> {
diff --git a/src/core/hle/service/filesystem/fsp/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp/fsp_srv.cpp
index 63c2d3a58..2d49f30c8 100644
--- a/src/core/hle/service/filesystem/fsp/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp/fsp_srv.cpp
@@ -336,7 +336,7 @@ FSP_SRV::FSP_SRV(Core::System& system_)
{1012, nullptr, "GetFsStackUsage"},
{1013, nullptr, "UnsetSaveDataRootPath"},
{1014, nullptr, "OutputMultiProgramTagAccessLog"},
- {1016, nullptr, "FlushAccessLogOnSdCard"},
+ {1016, &FSP_SRV::FlushAccessLogOnSdCard, "FlushAccessLogOnSdCard"},
{1017, nullptr, "OutputApplicationInfoAccessLog"},
{1018, nullptr, "SetDebugOption"},
{1019, nullptr, "UnsetDebugOption"},
@@ -706,6 +706,13 @@ void FSP_SRV::GetProgramIndexForAccessLog(HLERequestContext& ctx) {
rb.Push(access_log_program_index);
}
+void FSP_SRV::FlushAccessLogOnSdCard(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_FS, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
void FSP_SRV::GetCacheStorageSize(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto index{rp.Pop<s32>()};
diff --git a/src/core/hle/service/filesystem/fsp/fsp_srv.h b/src/core/hle/service/filesystem/fsp/fsp_srv.h
index 26980af99..59406e6f9 100644
--- a/src/core/hle/service/filesystem/fsp/fsp_srv.h
+++ b/src/core/hle/service/filesystem/fsp/fsp_srv.h
@@ -58,6 +58,7 @@ private:
void SetGlobalAccessLogMode(HLERequestContext& ctx);
void GetGlobalAccessLogMode(HLERequestContext& ctx);
void OutputAccessLogToSdCard(HLERequestContext& ctx);
+ void FlushAccessLogOnSdCard(HLERequestContext& ctx);
void GetProgramIndexForAccessLog(HLERequestContext& ctx);
void OpenMultiCommitManager(HLERequestContext& ctx);
void GetCacheStorageSize(HLERequestContext& ctx);
diff --git a/src/core/hle/service/glue/time/manager.cpp b/src/core/hle/service/glue/time/manager.cpp
index 0c27e8029..059ac3fc9 100644
--- a/src/core/hle/service/glue/time/manager.cpp
+++ b/src/core/hle/service/glue/time/manager.cpp
@@ -21,19 +21,6 @@
namespace Service::Glue::Time {
namespace {
-
-template <typename T>
-T GetSettingsItemValue(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys,
- const char* category, const char* name) {
- std::vector<u8> interval_buf;
- auto res = set_sys->GetSettingsItemValue(interval_buf, category, name);
- ASSERT(res == ResultSuccess);
-
- T v{};
- std::memcpy(&v, interval_buf.data(), sizeof(T));
- return v;
-}
-
s64 CalendarTimeToEpoch(Service::PSC::Time::CalendarTime calendar) {
constexpr auto is_leap = [](s32 year) -> bool {
return (((year) % 4) == 0 && (((year) % 100) != 0 || ((year) % 400) == 0));
@@ -65,13 +52,15 @@ s64 CalendarTimeToEpoch(Service::PSC::Time::CalendarTime calendar) {
s64 GetEpochTimeFromInitialYear(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys) {
Service::PSC::Time::CalendarTime calendar{
- .year = GetSettingsItemValue<s16>(set_sys, "time", "standard_user_clock_initial_year"),
+ .year = 2000,
.month = 1,
.day = 1,
.hour = 0,
.minute = 0,
.second = 0,
};
+ set_sys->GetSettingsItemValueImpl<s16>(calendar.year, "time",
+ "standard_user_clock_initial_year");
return CalendarTimeToEpoch(calendar);
}
@@ -124,7 +113,7 @@ TimeManager::TimeManager(Core::System& system)
ASSERT(res == ResultSuccess);
Service::PSC::Time::SystemClockContext user_clock_context{};
- res = m_set_sys->GetUserSystemClockContext(user_clock_context);
+ res = m_set_sys->GetUserSystemClockContext(&user_clock_context);
ASSERT(res == ResultSuccess);
// TODO the local clock should initialise with this epoch time, and be updated somewhere else on
@@ -140,11 +129,12 @@ TimeManager::TimeManager(Core::System& system)
ASSERT(res == ResultSuccess);
Service::PSC::Time::SystemClockContext network_clock_context{};
- res = m_set_sys->GetNetworkSystemClockContext(network_clock_context);
+ res = m_set_sys->GetNetworkSystemClockContext(&network_clock_context);
ASSERT(res == ResultSuccess);
- auto network_accuracy_m{GetSettingsItemValue<s32>(
- m_set_sys, "time", "standard_network_clock_sufficient_accuracy_minutes")};
+ s32 network_accuracy_m{};
+ m_set_sys->GetSettingsItemValueImpl<s32>(network_accuracy_m, "time",
+ "standard_network_clock_sufficient_accuracy_minutes");
auto one_minute_ns{
std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::minutes(1)).count()};
s64 network_accuracy_ns{network_accuracy_m * one_minute_ns};
@@ -153,12 +143,12 @@ TimeManager::TimeManager(Core::System& system)
ASSERT(res == ResultSuccess);
bool is_automatic_correction_enabled{};
- res = m_set_sys->IsUserSystemClockAutomaticCorrectionEnabled(is_automatic_correction_enabled);
+ res = m_set_sys->IsUserSystemClockAutomaticCorrectionEnabled(&is_automatic_correction_enabled);
ASSERT(res == ResultSuccess);
Service::PSC::Time::SteadyClockTimePoint automatic_correction_time_point{};
res = m_set_sys->GetUserSystemClockAutomaticCorrectionUpdatedTime(
- automatic_correction_time_point);
+ &automatic_correction_time_point);
ASSERT(res == ResultSuccess);
res = m_time_m->SetupStandardUserSystemClockCore(is_automatic_correction_enabled,
@@ -196,13 +186,17 @@ TimeManager::TimeManager(Core::System& system)
}
}
+TimeManager::~TimeManager() {
+ ResetTimeZoneBinary();
+}
+
Result TimeManager::SetupStandardSteadyClockCore() {
Common::UUID external_clock_source_id{};
- auto res = m_set_sys->GetExternalSteadyClockSourceId(external_clock_source_id);
+ auto res = m_set_sys->GetExternalSteadyClockSourceId(&external_clock_source_id);
ASSERT(res == ResultSuccess);
s64 external_steady_clock_internal_offset_s{};
- res = m_set_sys->GetExternalSteadyClockInternalOffset(external_steady_clock_internal_offset_s);
+ res = m_set_sys->GetExternalSteadyClockInternalOffset(&external_steady_clock_internal_offset_s);
ASSERT(res == ResultSuccess);
auto one_second_ns{
@@ -210,8 +204,9 @@ Result TimeManager::SetupStandardSteadyClockCore() {
s64 external_steady_clock_internal_offset_ns{external_steady_clock_internal_offset_s *
one_second_ns};
- s32 standard_steady_clock_test_offset_m{
- GetSettingsItemValue<s32>(m_set_sys, "time", "standard_steady_clock_test_offset_minutes")};
+ s32 standard_steady_clock_test_offset_m{};
+ m_set_sys->GetSettingsItemValueImpl<s32>(standard_steady_clock_test_offset_m, "time",
+ "standard_steady_clock_test_offset_minutes");
auto one_minute_ns{
std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::minutes(1)).count()};
s64 standard_steady_clock_test_offset_ns{standard_steady_clock_test_offset_m * one_minute_ns};
@@ -237,7 +232,7 @@ Result TimeManager::SetupStandardSteadyClockCore() {
Result TimeManager::SetupTimeZoneServiceCore() {
Service::PSC::Time::LocationName name{};
- auto res = m_set_sys->GetDeviceTimeZoneLocationName(name);
+ auto res = m_set_sys->GetDeviceTimeZoneLocationName(&name);
ASSERT(res == ResultSuccess);
auto configured_zone = GetTimeZoneString(name);
@@ -255,7 +250,7 @@ Result TimeManager::SetupTimeZoneServiceCore() {
}
Service::PSC::Time::SteadyClockTimePoint time_point{};
- res = m_set_sys->GetDeviceTimeZoneLocationUpdatedTime(time_point);
+ res = m_set_sys->GetDeviceTimeZoneLocationUpdatedTime(&time_point);
ASSERT(res == ResultSuccess);
auto location_count = GetTimeZoneCount();
diff --git a/src/core/hle/service/glue/time/manager.h b/src/core/hle/service/glue/time/manager.h
index 1de93f8f9..bb4b65049 100644
--- a/src/core/hle/service/glue/time/manager.h
+++ b/src/core/hle/service/glue/time/manager.h
@@ -26,6 +26,7 @@ namespace Service::Glue::Time {
class TimeManager {
public:
explicit TimeManager(Core::System& system);
+ ~TimeManager();
std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
diff --git a/src/core/hle/service/glue/time/static.cpp b/src/core/hle/service/glue/time/static.cpp
index f8c1218f3..ec9b0efb1 100644
--- a/src/core/hle/service/glue/time/static.cpp
+++ b/src/core/hle/service/glue/time/static.cpp
@@ -20,19 +20,6 @@
#include "core/hle/service/sm/sm.h"
namespace Service::Glue::Time {
-namespace {
-template <typename T>
-T GetSettingsItemValue(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys,
- const char* category, const char* name) {
- std::vector<u8> interval_buf;
- auto res = set_sys->GetSettingsItemValue(interval_buf, category, name);
- ASSERT(res == ResultSuccess);
-
- T v{};
- std::memcpy(&v, interval_buf.data(), sizeof(T));
- return v;
-}
-} // namespace
StaticService::StaticService(Core::System& system_,
Service::PSC::Time::StaticServiceSetupInfo setup_info,
@@ -181,8 +168,8 @@ Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled(
Result StaticService::GetStandardUserSystemClockInitialYear(Out<s32> out_year) {
SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_year={}", *out_year); });
- *out_year = GetSettingsItemValue<s32>(m_set_sys, "time", "standard_user_clock_initial_year");
- R_SUCCEED();
+ R_RETURN(m_set_sys->GetSettingsItemValueImpl<s32>(*out_year, "time",
+ "standard_user_clock_initial_year"));
}
Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient) {
diff --git a/src/core/hle/service/glue/time/worker.cpp b/src/core/hle/service/glue/time/worker.cpp
index 8787f2dcd..b28569b68 100644
--- a/src/core/hle/service/glue/time/worker.cpp
+++ b/src/core/hle/service/glue/time/worker.cpp
@@ -27,7 +27,7 @@ template <typename T>
T GetSettingsItemValue(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys,
const char* category, const char* name) {
std::vector<u8> interval_buf;
- auto res = set_sys->GetSettingsItemValue(interval_buf, category, name);
+ auto res = set_sys->GetSettingsItemValueImpl(interval_buf, category, name);
ASSERT(res == ResultSuccess);
T v{};
diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp
index 0086f82c5..adaaea571 100644
--- a/src/core/hle/service/mii/mii.cpp
+++ b/src/core/hle/service/mii/mii.cpp
@@ -207,7 +207,8 @@ private:
Result DestroyFile() {
bool is_db_test_mode_enabled{};
- m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled");
+ m_set_sys->GetSettingsItemValueImpl(is_db_test_mode_enabled, "mii",
+ "is_db_test_mode_enabled");
LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled);
R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly);
@@ -217,7 +218,8 @@ private:
Result DeleteFile() {
bool is_db_test_mode_enabled{};
- m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled");
+ m_set_sys->GetSettingsItemValueImpl(is_db_test_mode_enabled, "mii",
+ "is_db_test_mode_enabled");
LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled);
R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly);
@@ -227,7 +229,8 @@ private:
Result Format() {
bool is_db_test_mode_enabled{};
- m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled");
+ m_set_sys->GetSettingsItemValueImpl(is_db_test_mode_enabled, "mii",
+ "is_db_test_mode_enabled");
LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled);
R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly);
diff --git a/src/core/hle/service/ns/account_proxy_interface.cpp b/src/core/hle/service/ns/account_proxy_interface.cpp
new file mode 100644
index 000000000..e5041af66
--- /dev/null
+++ b/src/core/hle/service/ns/account_proxy_interface.cpp
@@ -0,0 +1,21 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/ns/account_proxy_interface.h"
+
+namespace Service::NS {
+
+IAccountProxyInterface::IAccountProxyInterface(Core::System& system_)
+ : ServiceFramework{system_, "IAccountProxyInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "CreateUserAccount"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IAccountProxyInterface::~IAccountProxyInterface() = default;
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/account_proxy_interface.h b/src/core/hle/service/ns/account_proxy_interface.h
new file mode 100644
index 000000000..e944d2a75
--- /dev/null
+++ b/src/core/hle/service/ns/account_proxy_interface.h
@@ -0,0 +1,16 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IAccountProxyInterface final : public ServiceFramework<IAccountProxyInterface> {
+public:
+ explicit IAccountProxyInterface(Core::System& system_);
+ ~IAccountProxyInterface() override;
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/application_manager_interface.cpp b/src/core/hle/service/ns/application_manager_interface.cpp
new file mode 100644
index 000000000..2e3a44c0d
--- /dev/null
+++ b/src/core/hle/service/ns/application_manager_interface.cpp
@@ -0,0 +1,519 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/file_sys/nca_metadata.h"
+#include "core/file_sys/registered_cache.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/filesystem/filesystem.h"
+#include "core/hle/service/ns/application_manager_interface.h"
+#include "core/hle/service/ns/content_management_interface.h"
+#include "core/hle/service/ns/read_only_application_control_data_interface.h"
+
+namespace Service::NS {
+
+IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_)
+ : ServiceFramework{system_, "IApplicationManagerInterface"},
+ service_context{system, "IApplicationManagerInterface"},
+ record_update_system_event{service_context}, sd_card_mount_status_event{service_context},
+ gamecard_update_detection_event{service_context},
+ gamecard_mount_status_event{service_context}, gamecard_mount_failure_event{service_context} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&IApplicationManagerInterface::ListApplicationRecord>, "ListApplicationRecord"},
+ {1, nullptr, "GenerateApplicationRecordCount"},
+ {2, D<&IApplicationManagerInterface::GetApplicationRecordUpdateSystemEvent>, "GetApplicationRecordUpdateSystemEvent"},
+ {3, nullptr, "GetApplicationViewDeprecated"},
+ {4, nullptr, "DeleteApplicationEntity"},
+ {5, nullptr, "DeleteApplicationCompletely"},
+ {6, nullptr, "IsAnyApplicationEntityRedundant"},
+ {7, nullptr, "DeleteRedundantApplicationEntity"},
+ {8, nullptr, "IsApplicationEntityMovable"},
+ {9, nullptr, "MoveApplicationEntity"},
+ {11, nullptr, "CalculateApplicationOccupiedSize"},
+ {16, nullptr, "PushApplicationRecord"},
+ {17, nullptr, "ListApplicationRecordContentMeta"},
+ {19, nullptr, "LaunchApplicationOld"},
+ {21, nullptr, "GetApplicationContentPath"},
+ {22, nullptr, "TerminateApplication"},
+ {23, nullptr, "ResolveApplicationContentPath"},
+ {26, nullptr, "BeginInstallApplication"},
+ {27, nullptr, "DeleteApplicationRecord"},
+ {30, nullptr, "RequestApplicationUpdateInfo"},
+ {31, nullptr, "Unknown31"},
+ {32, nullptr, "CancelApplicationDownload"},
+ {33, nullptr, "ResumeApplicationDownload"},
+ {35, nullptr, "UpdateVersionList"},
+ {36, nullptr, "PushLaunchVersion"},
+ {37, nullptr, "ListRequiredVersion"},
+ {38, D<&IApplicationManagerInterface::CheckApplicationLaunchVersion>, "CheckApplicationLaunchVersion"},
+ {39, nullptr, "CheckApplicationLaunchRights"},
+ {40, nullptr, "GetApplicationLogoData"},
+ {41, nullptr, "CalculateApplicationDownloadRequiredSize"},
+ {42, nullptr, "CleanupSdCard"},
+ {43, D<&IApplicationManagerInterface::CheckSdCardMountStatus>, "CheckSdCardMountStatus"},
+ {44, D<&IApplicationManagerInterface::GetSdCardMountStatusChangedEvent>, "GetSdCardMountStatusChangedEvent"},
+ {45, nullptr, "GetGameCardAttachmentEvent"},
+ {46, nullptr, "GetGameCardAttachmentInfo"},
+ {47, nullptr, "GetTotalSpaceSize"},
+ {48, D<&IApplicationManagerInterface::GetFreeSpaceSize>, "GetFreeSpaceSize"},
+ {49, nullptr, "GetSdCardRemovedEvent"},
+ {52, D<&IApplicationManagerInterface::GetGameCardUpdateDetectionEvent>, "GetGameCardUpdateDetectionEvent"},
+ {53, nullptr, "DisableApplicationAutoDelete"},
+ {54, nullptr, "EnableApplicationAutoDelete"},
+ {55, D<&IApplicationManagerInterface::GetApplicationDesiredLanguage>, "GetApplicationDesiredLanguage"},
+ {56, nullptr, "SetApplicationTerminateResult"},
+ {57, nullptr, "ClearApplicationTerminateResult"},
+ {58, nullptr, "GetLastSdCardMountUnexpectedResult"},
+ {59, D<&IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode>, "ConvertApplicationLanguageToLanguageCode"},
+ {60, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
+ {61, nullptr, "GetBackgroundDownloadStressTaskInfo"},
+ {62, nullptr, "GetGameCardStopper"},
+ {63, nullptr, "IsSystemProgramInstalled"},
+ {64, nullptr, "StartApplyDeltaTask"},
+ {65, nullptr, "GetRequestServerStopper"},
+ {66, nullptr, "GetBackgroundApplyDeltaStressTaskInfo"},
+ {67, nullptr, "CancelApplicationApplyDelta"},
+ {68, nullptr, "ResumeApplicationApplyDelta"},
+ {69, nullptr, "CalculateApplicationApplyDeltaRequiredSize"},
+ {70, D<&IApplicationManagerInterface::ResumeAll>, "ResumeAll"},
+ {71, D<&IApplicationManagerInterface::GetStorageSize>, "GetStorageSize"},
+ {80, nullptr, "RequestDownloadApplication"},
+ {81, nullptr, "RequestDownloadAddOnContent"},
+ {82, nullptr, "DownloadApplication"},
+ {83, nullptr, "CheckApplicationResumeRights"},
+ {84, nullptr, "GetDynamicCommitEvent"},
+ {85, nullptr, "RequestUpdateApplication2"},
+ {86, nullptr, "EnableApplicationCrashReport"},
+ {87, nullptr, "IsApplicationCrashReportEnabled"},
+ {90, nullptr, "BoostSystemMemoryResourceLimit"},
+ {91, nullptr, "DeprecatedLaunchApplication"},
+ {92, nullptr, "GetRunningApplicationProgramId"},
+ {93, nullptr, "GetMainApplicationProgramIndex"},
+ {94, nullptr, "LaunchApplication"},
+ {95, nullptr, "GetApplicationLaunchInfo"},
+ {96, nullptr, "AcquireApplicationLaunchInfo"},
+ {97, nullptr, "GetMainApplicationProgramIndexByApplicationLaunchInfo"},
+ {98, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
+ {99, nullptr, "LaunchDevMenu"},
+ {100, nullptr, "ResetToFactorySettings"},
+ {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"},
+ {102, nullptr, "ResetToFactorySettingsForRefurbishment"},
+ {103, nullptr, "ResetToFactorySettingsWithPlatformRegion"},
+ {104, nullptr, "ResetToFactorySettingsWithPlatformRegionAuthentication"},
+ {105, nullptr, "RequestResetToFactorySettingsSecurely"},
+ {106, nullptr, "RequestResetToFactorySettingsWithPlatformRegionAuthenticationSecurely"},
+ {200, nullptr, "CalculateUserSaveDataStatistics"},
+ {201, nullptr, "DeleteUserSaveDataAll"},
+ {210, nullptr, "DeleteUserSystemSaveData"},
+ {211, nullptr, "DeleteSaveData"},
+ {220, nullptr, "UnregisterNetworkServiceAccount"},
+ {221, nullptr, "UnregisterNetworkServiceAccountWithUserSaveDataDeletion"},
+ {300, nullptr, "GetApplicationShellEvent"},
+ {301, nullptr, "PopApplicationShellEventInfo"},
+ {302, nullptr, "LaunchLibraryApplet"},
+ {303, nullptr, "TerminateLibraryApplet"},
+ {304, nullptr, "LaunchSystemApplet"},
+ {305, nullptr, "TerminateSystemApplet"},
+ {306, nullptr, "LaunchOverlayApplet"},
+ {307, nullptr, "TerminateOverlayApplet"},
+ {400, D<&IApplicationManagerInterface::GetApplicationControlData>, "GetApplicationControlData"},
+ {401, nullptr, "InvalidateAllApplicationControlCache"},
+ {402, nullptr, "RequestDownloadApplicationControlData"},
+ {403, nullptr, "GetMaxApplicationControlCacheCount"},
+ {404, nullptr, "InvalidateApplicationControlCache"},
+ {405, nullptr, "ListApplicationControlCacheEntryInfo"},
+ {406, nullptr, "GetApplicationControlProperty"},
+ {407, nullptr, "ListApplicationTitle"},
+ {408, nullptr, "ListApplicationIcon"},
+ {502, nullptr, "RequestCheckGameCardRegistration"},
+ {503, nullptr, "RequestGameCardRegistrationGoldPoint"},
+ {504, nullptr, "RequestRegisterGameCard"},
+ {505, D<&IApplicationManagerInterface::GetGameCardMountFailureEvent>, "GetGameCardMountFailureEvent"},
+ {506, nullptr, "IsGameCardInserted"},
+ {507, nullptr, "EnsureGameCardAccess"},
+ {508, nullptr, "GetLastGameCardMountFailureResult"},
+ {509, nullptr, "ListApplicationIdOnGameCard"},
+ {510, nullptr, "GetGameCardPlatformRegion"},
+ {600, nullptr, "CountApplicationContentMeta"},
+ {601, nullptr, "ListApplicationContentMetaStatus"},
+ {602, nullptr, "ListAvailableAddOnContent"},
+ {603, nullptr, "GetOwnedApplicationContentMetaStatus"},
+ {604, nullptr, "RegisterContentsExternalKey"},
+ {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"},
+ {606, nullptr, "GetContentMetaStorage"},
+ {607, nullptr, "ListAvailableAddOnContent"},
+ {609, nullptr, "ListAvailabilityAssuredAddOnContent"},
+ {610, nullptr, "GetInstalledContentMetaStorage"},
+ {611, nullptr, "PrepareAddOnContent"},
+ {700, nullptr, "PushDownloadTaskList"},
+ {701, nullptr, "ClearTaskStatusList"},
+ {702, nullptr, "RequestDownloadTaskList"},
+ {703, nullptr, "RequestEnsureDownloadTask"},
+ {704, nullptr, "ListDownloadTaskStatus"},
+ {705, nullptr, "RequestDownloadTaskListData"},
+ {800, nullptr, "RequestVersionList"},
+ {801, nullptr, "ListVersionList"},
+ {802, nullptr, "RequestVersionListData"},
+ {900, nullptr, "GetApplicationRecord"},
+ {901, nullptr, "GetApplicationRecordProperty"},
+ {902, nullptr, "EnableApplicationAutoUpdate"},
+ {903, nullptr, "DisableApplicationAutoUpdate"},
+ {904, nullptr, "TouchApplication"},
+ {905, nullptr, "RequestApplicationUpdate"},
+ {906, D<&IApplicationManagerInterface::IsApplicationUpdateRequested>, "IsApplicationUpdateRequested"},
+ {907, nullptr, "WithdrawApplicationUpdateRequest"},
+ {908, nullptr, "ListApplicationRecordInstalledContentMeta"},
+ {909, nullptr, "WithdrawCleanupAddOnContentsWithNoRightsRecommendation"},
+ {910, nullptr, "HasApplicationRecord"},
+ {911, nullptr, "SetPreInstalledApplication"},
+ {912, nullptr, "ClearPreInstalledApplicationFlag"},
+ {913, nullptr, "ListAllApplicationRecord"},
+ {914, nullptr, "HideApplicationRecord"},
+ {915, nullptr, "ShowApplicationRecord"},
+ {916, nullptr, "IsApplicationAutoDeleteDisabled"},
+ {1000, nullptr, "RequestVerifyApplicationDeprecated"},
+ {1001, nullptr, "CorruptApplicationForDebug"},
+ {1002, nullptr, "RequestVerifyAddOnContentsRights"},
+ {1003, nullptr, "RequestVerifyApplication"},
+ {1004, nullptr, "CorruptContentForDebug"},
+ {1200, nullptr, "NeedsUpdateVulnerability"},
+ {1300, D<&IApplicationManagerInterface::IsAnyApplicationEntityInstalled>, "IsAnyApplicationEntityInstalled"},
+ {1301, nullptr, "DeleteApplicationContentEntities"},
+ {1302, nullptr, "CleanupUnrecordedApplicationEntity"},
+ {1303, nullptr, "CleanupAddOnContentsWithNoRights"},
+ {1304, nullptr, "DeleteApplicationContentEntity"},
+ {1305, nullptr, "TryDeleteRunningApplicationEntity"},
+ {1306, nullptr, "TryDeleteRunningApplicationCompletely"},
+ {1307, nullptr, "TryDeleteRunningApplicationContentEntities"},
+ {1308, nullptr, "DeleteApplicationCompletelyForDebug"},
+ {1309, nullptr, "CleanupUnavailableAddOnContents"},
+ {1310, nullptr, "RequestMoveApplicationEntity"},
+ {1311, nullptr, "EstimateSizeToMove"},
+ {1312, nullptr, "HasMovableEntity"},
+ {1313, nullptr, "CleanupOrphanContents"},
+ {1314, nullptr, "CheckPreconditionSatisfiedToMove"},
+ {1400, nullptr, "PrepareShutdown"},
+ {1500, nullptr, "FormatSdCard"},
+ {1501, nullptr, "NeedsSystemUpdateToFormatSdCard"},
+ {1502, nullptr, "GetLastSdCardFormatUnexpectedResult"},
+ {1504, nullptr, "InsertSdCard"},
+ {1505, nullptr, "RemoveSdCard"},
+ {1506, nullptr, "GetSdCardStartupStatus"},
+ {1600, nullptr, "GetSystemSeedForPseudoDeviceId"},
+ {1601, nullptr, "ResetSystemSeedForPseudoDeviceId"},
+ {1700, nullptr, "ListApplicationDownloadingContentMeta"},
+ {1701, D<&IApplicationManagerInterface::GetApplicationView>, "GetApplicationView"},
+ {1702, nullptr, "GetApplicationDownloadTaskStatus"},
+ {1703, nullptr, "GetApplicationViewDownloadErrorContext"},
+ {1704, D<&IApplicationManagerInterface::GetApplicationViewWithPromotionInfo>, "GetApplicationViewWithPromotionInfo"},
+ {1705, nullptr, "IsPatchAutoDeletableApplication"},
+ {1800, nullptr, "IsNotificationSetupCompleted"},
+ {1801, nullptr, "GetLastNotificationInfoCount"},
+ {1802, nullptr, "ListLastNotificationInfo"},
+ {1803, nullptr, "ListNotificationTask"},
+ {1900, nullptr, "IsActiveAccount"},
+ {1901, nullptr, "RequestDownloadApplicationPrepurchasedRights"},
+ {1902, nullptr, "GetApplicationTicketInfo"},
+ {1903, nullptr, "RequestDownloadApplicationPrepurchasedRightsForAccount"},
+ {2000, nullptr, "GetSystemDeliveryInfo"},
+ {2001, nullptr, "SelectLatestSystemDeliveryInfo"},
+ {2002, nullptr, "VerifyDeliveryProtocolVersion"},
+ {2003, nullptr, "GetApplicationDeliveryInfo"},
+ {2004, nullptr, "HasAllContentsToDeliver"},
+ {2005, nullptr, "CompareApplicationDeliveryInfo"},
+ {2006, nullptr, "CanDeliverApplication"},
+ {2007, nullptr, "ListContentMetaKeyToDeliverApplication"},
+ {2008, nullptr, "NeedsSystemUpdateToDeliverApplication"},
+ {2009, nullptr, "EstimateRequiredSize"},
+ {2010, nullptr, "RequestReceiveApplication"},
+ {2011, nullptr, "CommitReceiveApplication"},
+ {2012, nullptr, "GetReceiveApplicationProgress"},
+ {2013, nullptr, "RequestSendApplication"},
+ {2014, nullptr, "GetSendApplicationProgress"},
+ {2015, nullptr, "CompareSystemDeliveryInfo"},
+ {2016, nullptr, "ListNotCommittedContentMeta"},
+ {2017, nullptr, "CreateDownloadTask"},
+ {2018, nullptr, "GetApplicationDeliveryInfoHash"},
+ {2050, D<&IApplicationManagerInterface::GetApplicationRightsOnClient>, "GetApplicationRightsOnClient"},
+ {2051, nullptr, "InvalidateRightsIdCache"},
+ {2100, D<&IApplicationManagerInterface::GetApplicationTerminateResult>, "GetApplicationTerminateResult"},
+ {2101, nullptr, "GetRawApplicationTerminateResult"},
+ {2150, nullptr, "CreateRightsEnvironment"},
+ {2151, nullptr, "DestroyRightsEnvironment"},
+ {2152, nullptr, "ActivateRightsEnvironment"},
+ {2153, nullptr, "DeactivateRightsEnvironment"},
+ {2154, nullptr, "ForceActivateRightsContextForExit"},
+ {2155, nullptr, "UpdateRightsEnvironmentStatus"},
+ {2156, nullptr, "CreateRightsEnvironmentForMicroApplication"},
+ {2160, nullptr, "AddTargetApplicationToRightsEnvironment"},
+ {2161, nullptr, "SetUsersToRightsEnvironment"},
+ {2170, nullptr, "GetRightsEnvironmentStatus"},
+ {2171, nullptr, "GetRightsEnvironmentStatusChangedEvent"},
+ {2180, nullptr, "RequestExtendRightsInRightsEnvironment"},
+ {2181, nullptr, "GetResultOfExtendRightsInRightsEnvironment"},
+ {2182, nullptr, "SetActiveRightsContextUsingStateToRightsEnvironment"},
+ {2190, nullptr, "GetRightsEnvironmentHandleForApplication"},
+ {2199, nullptr, "GetRightsEnvironmentCountForDebug"},
+ {2200, nullptr, "GetGameCardApplicationCopyIdentifier"},
+ {2201, nullptr, "GetInstalledApplicationCopyIdentifier"},
+ {2250, nullptr, "RequestReportActiveELicence"},
+ {2300, nullptr, "ListEventLog"},
+ {2350, nullptr, "PerformAutoUpdateByApplicationId"},
+ {2351, nullptr, "RequestNoDownloadRightsErrorResolution"},
+ {2352, nullptr, "RequestResolveNoDownloadRightsError"},
+ {2353, nullptr, "GetApplicationDownloadTaskInfo"},
+ {2354, nullptr, "PrioritizeApplicationBackgroundTask"},
+ {2355, nullptr, "PreferStorageEfficientUpdate"},
+ {2356, nullptr, "RequestStorageEfficientUpdatePreferable"},
+ {2357, nullptr, "EnableMultiCoreDownload"},
+ {2358, nullptr, "DisableMultiCoreDownload"},
+ {2359, nullptr, "IsMultiCoreDownloadEnabled"},
+ {2400, nullptr, "GetPromotionInfo"},
+ {2401, nullptr, "CountPromotionInfo"},
+ {2402, nullptr, "ListPromotionInfo"},
+ {2403, nullptr, "ImportPromotionJsonForDebug"},
+ {2404, nullptr, "ClearPromotionInfoForDebug"},
+ {2500, nullptr, "ConfirmAvailableTime"},
+ {2510, nullptr, "CreateApplicationResource"},
+ {2511, nullptr, "GetApplicationResource"},
+ {2513, nullptr, "LaunchMicroApplication"},
+ {2514, nullptr, "ClearTaskOfAsyncTaskManager"},
+ {2515, nullptr, "CleanupAllPlaceHolderAndFragmentsIfNoTask"},
+ {2516, nullptr, "EnsureApplicationCertificate"},
+ {2517, nullptr, "CreateApplicationInstance"},
+ {2518, nullptr, "UpdateQualificationForDebug"},
+ {2519, nullptr, "IsQualificationTransitionSupported"},
+ {2520, nullptr, "IsQualificationTransitionSupportedByProcessId"},
+ {2521, nullptr, "GetRightsUserChangedEvent"},
+ {2522, nullptr, "IsRomRedirectionAvailable"},
+ {2800, nullptr, "GetApplicationIdOfPreomia"},
+ {3000, nullptr, "RegisterDeviceLockKey"},
+ {3001, nullptr, "UnregisterDeviceLockKey"},
+ {3002, nullptr, "VerifyDeviceLockKey"},
+ {3003, nullptr, "HideApplicationIcon"},
+ {3004, nullptr, "ShowApplicationIcon"},
+ {3005, nullptr, "HideApplicationTitle"},
+ {3006, nullptr, "ShowApplicationTitle"},
+ {3007, nullptr, "EnableGameCard"},
+ {3008, nullptr, "DisableGameCard"},
+ {3009, nullptr, "EnableLocalContentShare"},
+ {3010, nullptr, "DisableLocalContentShare"},
+ {3011, nullptr, "IsApplicationIconHidden"},
+ {3012, nullptr, "IsApplicationTitleHidden"},
+ {3013, nullptr, "IsGameCardEnabled"},
+ {3014, nullptr, "IsLocalContentShareEnabled"},
+ {3050, nullptr, "ListAssignELicenseTaskResult"},
+ {9999, nullptr, "GetApplicationCertificate"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IApplicationManagerInterface::~IApplicationManagerInterface() = default;
+
+Result IApplicationManagerInterface::GetApplicationControlData(
+ OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_actual_size,
+ ApplicationControlSource application_control_source, u64 application_id) {
+ LOG_DEBUG(Service_NS, "called");
+ R_RETURN(IReadOnlyApplicationControlDataInterface(system).GetApplicationControlData(
+ out_buffer, out_actual_size, application_control_source, application_id));
+}
+
+Result IApplicationManagerInterface::GetApplicationDesiredLanguage(
+ Out<ApplicationLanguage> out_desired_language, u32 supported_languages) {
+ LOG_DEBUG(Service_NS, "called");
+ R_RETURN(IReadOnlyApplicationControlDataInterface(system).GetApplicationDesiredLanguage(
+ out_desired_language, supported_languages));
+}
+
+Result IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
+ Out<u64> out_language_code, ApplicationLanguage application_language) {
+ LOG_DEBUG(Service_NS, "called");
+ R_RETURN(
+ IReadOnlyApplicationControlDataInterface(system).ConvertApplicationLanguageToLanguageCode(
+ out_language_code, application_language));
+}
+
+Result IApplicationManagerInterface::ListApplicationRecord(
+ OutArray<ApplicationRecord, BufferAttr_HipcMapAlias> out_records, Out<s32> out_count,
+ s32 offset) {
+ const auto limit = out_records.size();
+
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ const auto& cache = system.GetContentProviderUnion();
+ const auto installed_games = cache.ListEntriesFilterOrigin(
+ std::nullopt, FileSys::TitleType::Application, FileSys::ContentRecordType::Program);
+
+ size_t i = 0;
+ u8 ii = 24;
+
+ for (const auto& [slot, game] : installed_games) {
+ if (i >= limit) {
+ break;
+ }
+ if (game.title_id == 0 || game.title_id < 0x0100000000001FFFull) {
+ continue;
+ }
+ if (offset > 0) {
+ offset--;
+ continue;
+ }
+
+ ApplicationRecord record{};
+ record.application_id = game.title_id;
+ record.type = ApplicationRecordType::Installed;
+ record.unknown = 0; // 2 = needs update
+ record.unknown2 = ii++;
+
+ out_records[i++] = record;
+ }
+
+ *out_count = static_cast<s32>(i);
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::GetApplicationRecordUpdateSystemEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+
+ record_update_system_event.Signal();
+ *out_event = record_update_system_event.GetHandle();
+
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::GetGameCardMountFailureEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ *out_event = gamecard_mount_failure_event.GetHandle();
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::IsAnyApplicationEntityInstalled(
+ Out<bool> out_is_any_application_entity_installed) {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ *out_is_any_application_entity_installed = true;
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::GetApplicationView(
+ OutArray<ApplicationView, BufferAttr_HipcMapAlias> out_application_views,
+ InArray<u64, BufferAttr_HipcMapAlias> application_ids) {
+ const auto size = std::min(out_application_views.size(), application_ids.size());
+ LOG_WARNING(Service_NS, "(STUBBED) called, size={}", application_ids.size());
+
+ for (size_t i = 0; i < size; i++) {
+ ApplicationView view{};
+ view.application_id = application_ids[i];
+ view.unk = 0x70000;
+ view.flags = 0x401f17;
+
+ out_application_views[i] = view;
+ }
+
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::GetApplicationViewWithPromotionInfo(
+ OutArray<ApplicationViewWithPromotionInfo, BufferAttr_HipcMapAlias> out_application_views,
+ InArray<u64, BufferAttr_HipcMapAlias> application_ids) {
+ const auto size = std::min(out_application_views.size(), application_ids.size());
+ LOG_WARNING(Service_NS, "(STUBBED) called, size={}", application_ids.size());
+
+ for (size_t i = 0; i < size; i++) {
+ ApplicationViewWithPromotionInfo view{};
+ view.view.application_id = application_ids[i];
+ view.view.unk = 0x70000;
+ view.view.flags = 0x401f17;
+ view.promotion = {};
+
+ out_application_views[i] = view;
+ }
+
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::GetApplicationRightsOnClient(
+ OutArray<ApplicationRightsOnClient, BufferAttr_HipcMapAlias> out_rights, Out<u32> out_count,
+ 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()) {
+ ApplicationRightsOnClient rights{};
+ rights.application_id = application_id;
+ rights.uid = account_id;
+ rights.flags = 0;
+ rights.flags2 = 0;
+
+ out_rights[0] = rights;
+ *out_count = 1;
+ } else {
+ *out_count = 0;
+ }
+
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::CheckSdCardMountStatus() {
+ LOG_DEBUG(Service_NS, "called");
+ R_RETURN(IContentManagementInterface(system).CheckSdCardMountStatus());
+}
+
+Result IApplicationManagerInterface::GetSdCardMountStatusChangedEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ *out_event = sd_card_mount_status_event.GetHandle();
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::GetFreeSpaceSize(Out<s64> out_free_space_size,
+ FileSys::StorageId storage_id) {
+ LOG_DEBUG(Service_NS, "called");
+ R_RETURN(IContentManagementInterface(system).GetFreeSpaceSize(out_free_space_size, storage_id));
+}
+
+Result IApplicationManagerInterface::GetGameCardUpdateDetectionEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ *out_event = gamecard_update_detection_event.GetHandle();
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::ResumeAll() {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::GetStorageSize(Out<s64> out_total_space_size,
+ Out<s64> out_free_space_size,
+ FileSys::StorageId storage_id) {
+ LOG_INFO(Service_NS, "called, storage_id={}", storage_id);
+ *out_total_space_size = system.GetFileSystemController().GetTotalSpaceSize(storage_id);
+ *out_free_space_size = system.GetFileSystemController().GetFreeSpaceSize(storage_id);
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::IsApplicationUpdateRequested(Out<bool> out_update_required,
+ Out<u32> out_update_version,
+ u64 application_id) {
+ LOG_WARNING(Service_NS, "(STUBBED) called. application_id={:016X}", application_id);
+ *out_update_required = false;
+ *out_update_version = 0;
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::CheckApplicationLaunchVersion(u64 application_id) {
+ LOG_WARNING(Service_NS, "(STUBBED) called. application_id={:016X}", application_id);
+ R_SUCCEED();
+}
+
+Result IApplicationManagerInterface::GetApplicationTerminateResult(Out<Result> out_result,
+ u64 application_id) {
+ LOG_WARNING(Service_NS, "(STUBBED) called. application_id={:016X}", application_id);
+ *out_result = ResultSuccess;
+ R_SUCCEED();
+}
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/application_manager_interface.h b/src/core/hle/service/ns/application_manager_interface.h
new file mode 100644
index 000000000..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<IApplicationManagerInterface> {
+public:
+ explicit IApplicationManagerInterface(Core::System& system_);
+ ~IApplicationManagerInterface() override;
+
+ Result GetApplicationControlData(OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
+ Out<u32> out_actual_size,
+ ApplicationControlSource application_control_source,
+ u64 application_id);
+ Result GetApplicationDesiredLanguage(Out<ApplicationLanguage> out_desired_language,
+ u32 supported_languages);
+ Result ConvertApplicationLanguageToLanguageCode(Out<u64> out_language_code,
+ ApplicationLanguage application_language);
+ Result ListApplicationRecord(OutArray<ApplicationRecord, BufferAttr_HipcMapAlias> out_records,
+ Out<s32> out_count, s32 offset);
+ Result GetApplicationRecordUpdateSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result GetGameCardMountFailureEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result IsAnyApplicationEntityInstalled(Out<bool> out_is_any_application_entity_installed);
+ Result GetApplicationView(
+ OutArray<ApplicationView, BufferAttr_HipcMapAlias> out_application_views,
+ InArray<u64, BufferAttr_HipcMapAlias> application_ids);
+ Result GetApplicationViewWithPromotionInfo(
+ OutArray<ApplicationViewWithPromotionInfo, BufferAttr_HipcMapAlias> out_application_views,
+ InArray<u64, BufferAttr_HipcMapAlias> application_ids);
+ Result GetApplicationRightsOnClient(
+ OutArray<ApplicationRightsOnClient, BufferAttr_HipcMapAlias> out_rights, Out<u32> out_count,
+ Common::UUID account_id, u32 flags, u64 application_id);
+ Result CheckSdCardMountStatus();
+ Result GetSdCardMountStatusChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result GetFreeSpaceSize(Out<s64> out_free_space_size, FileSys::StorageId storage_id);
+ Result GetGameCardUpdateDetectionEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
+ Result ResumeAll();
+ Result GetStorageSize(Out<s64> out_total_space_size, Out<s64> out_free_space_size,
+ FileSys::StorageId storage_id);
+ Result IsApplicationUpdateRequested(Out<bool> out_update_required, Out<u32> out_update_version,
+ u64 application_id);
+ Result CheckApplicationLaunchVersion(u64 application_id);
+ Result GetApplicationTerminateResult(Out<Result> out_result, u64 application_id);
+
+private:
+ KernelHelpers::ServiceContext service_context;
+ Event record_update_system_event;
+ Event sd_card_mount_status_event;
+ Event gamecard_update_detection_event;
+ Event gamecard_mount_status_event;
+ Event gamecard_mount_failure_event;
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/application_version_interface.cpp b/src/core/hle/service/ns/application_version_interface.cpp
new file mode 100644
index 000000000..b89e127db
--- /dev/null
+++ b/src/core/hle/service/ns/application_version_interface.cpp
@@ -0,0 +1,33 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/ns/application_version_interface.h"
+
+namespace Service::NS {
+
+IApplicationVersionInterface::IApplicationVersionInterface(Core::System& system_)
+ : ServiceFramework{system_, "IApplicationVersionInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetLaunchRequiredVersion"},
+ {1, nullptr, "UpgradeLaunchRequiredVersion"},
+ {35, nullptr, "UpdateVersionList"},
+ {36, nullptr, "PushLaunchVersion"},
+ {37, nullptr, "ListRequiredVersion"},
+ {800, nullptr, "RequestVersionList"},
+ {801, nullptr, "ListVersionList"},
+ {802, nullptr, "RequestVersionListData"},
+ {900, nullptr, "ImportAutoUpdatePolicyJsonForDebug"},
+ {901, nullptr, "ListDefaultAutoUpdatePolicy"},
+ {902, nullptr, "ListAutoUpdatePolicyForSpecificApplication"},
+ {1000, nullptr, "PerformAutoUpdate"},
+ {1001, nullptr, "ListAutoUpdateSchedule"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IApplicationVersionInterface::~IApplicationVersionInterface() = default;
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/application_version_interface.h b/src/core/hle/service/ns/application_version_interface.h
new file mode 100644
index 000000000..b288cff1b
--- /dev/null
+++ b/src/core/hle/service/ns/application_version_interface.h
@@ -0,0 +1,16 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> {
+public:
+ explicit IApplicationVersionInterface(Core::System& system_);
+ ~IApplicationVersionInterface() override;
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/content_management_interface.cpp b/src/core/hle/service/ns/content_management_interface.cpp
new file mode 100644
index 000000000..69bb3f6e4
--- /dev/null
+++ b/src/core/hle/service/ns/content_management_interface.cpp
@@ -0,0 +1,72 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/common_funcs.h"
+#include "core/core.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/filesystem/filesystem.h"
+#include "core/hle/service/ns/content_management_interface.h"
+#include "core/hle/service/ns/ns_types.h"
+
+namespace Service::NS {
+
+IContentManagementInterface::IContentManagementInterface(Core::System& system_)
+ : ServiceFramework{system_, "IContentManagementInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {11, D<&IContentManagementInterface::CalculateApplicationOccupiedSize>, "CalculateApplicationOccupiedSize"},
+ {43, D<&IContentManagementInterface::CheckSdCardMountStatus>, "CheckSdCardMountStatus"},
+ {47, D<&IContentManagementInterface::GetTotalSpaceSize>, "GetTotalSpaceSize"},
+ {48, D<&IContentManagementInterface::GetFreeSpaceSize>, "GetFreeSpaceSize"},
+ {600, nullptr, "CountApplicationContentMeta"},
+ {601, nullptr, "ListApplicationContentMetaStatus"},
+ {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"},
+ {607, nullptr, "IsAnyApplicationRunning"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IContentManagementInterface::~IContentManagementInterface() = default;
+
+Result IContentManagementInterface::CalculateApplicationOccupiedSize(
+ Out<ApplicationOccupiedSize> out_size, u64 application_id) {
+ LOG_WARNING(Service_NS, "(STUBBED) called, application_id={:016X}", application_id);
+
+ using namespace Common::Literals;
+
+ constexpr ApplicationOccupiedSizeEntity stub_entity{
+ .storage_id = FileSys::StorageId::SdCard,
+ .app_size = 8_GiB,
+ .patch_size = 2_GiB,
+ .aoc_size = 12_MiB,
+ };
+
+ for (auto& entity : out_size->entities) {
+ entity = stub_entity;
+ }
+
+ R_SUCCEED();
+}
+
+Result IContentManagementInterface::CheckSdCardMountStatus() {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IContentManagementInterface::GetTotalSpaceSize(Out<s64> out_total_space_size,
+ FileSys::StorageId storage_id) {
+ LOG_INFO(Service_NS, "(STUBBED) called, storage_id={}", storage_id);
+ *out_total_space_size = system.GetFileSystemController().GetTotalSpaceSize(storage_id);
+ R_SUCCEED();
+}
+
+Result IContentManagementInterface::GetFreeSpaceSize(Out<s64> out_free_space_size,
+ FileSys::StorageId storage_id) {
+ LOG_INFO(Service_NS, "(STUBBED) called, storage_id={}", storage_id);
+ *out_free_space_size = system.GetFileSystemController().GetFreeSpaceSize(storage_id);
+ R_SUCCEED();
+}
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/content_management_interface.h b/src/core/hle/service/ns/content_management_interface.h
new file mode 100644
index 000000000..2894628e5
--- /dev/null
+++ b/src/core/hle/service/ns/content_management_interface.h
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/ns/ns_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IContentManagementInterface final : public ServiceFramework<IContentManagementInterface> {
+public:
+ explicit IContentManagementInterface(Core::System& system_);
+ ~IContentManagementInterface() override;
+
+public:
+ Result CalculateApplicationOccupiedSize(Out<ApplicationOccupiedSize> out_size,
+ u64 application_id);
+ Result CheckSdCardMountStatus();
+ Result GetTotalSpaceSize(Out<s64> out_total_space_size, FileSys::StorageId storage_id);
+ Result GetFreeSpaceSize(Out<s64> out_free_space_size, FileSys::StorageId storage_id);
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/develop_interface.cpp b/src/core/hle/service/ns/develop_interface.cpp
new file mode 100644
index 000000000..880bdbebb
--- /dev/null
+++ b/src/core/hle/service/ns/develop_interface.cpp
@@ -0,0 +1,38 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/ns/develop_interface.h"
+
+namespace Service::NS {
+
+IDevelopInterface::IDevelopInterface(Core::System& system_) : ServiceFramework{system_, "ns:dev"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "LaunchProgram"},
+ {1, nullptr, "TerminateProcess"},
+ {2, nullptr, "TerminateProgram"},
+ {4, nullptr, "GetShellEvent"},
+ {5, nullptr, "GetShellEventInfo"},
+ {6, nullptr, "TerminateApplication"},
+ {7, nullptr, "PrepareLaunchProgramFromHost"},
+ {8, nullptr, "LaunchApplicationFromHost"},
+ {9, nullptr, "LaunchApplicationWithStorageIdForDevelop"},
+ {10, nullptr, "IsSystemMemoryResourceLimitBoosted"},
+ {11, nullptr, "GetRunningApplicationProcessIdForDevelop"},
+ {12, nullptr, "SetCurrentApplicationRightsEnvironmentCanBeActiveForDevelop"},
+ {13, nullptr, "CreateApplicationResourceForDevelop"},
+ {14, nullptr, "IsPreomiaForDevelop"},
+ {15, nullptr, "GetApplicationProgramIdFromHost"},
+ {16, nullptr, "RefreshCachedDebugValues"},
+ {17, nullptr, "PrepareLaunchApplicationFromHost"},
+ {18, nullptr, "GetLaunchEvent"},
+ {19, nullptr, "GetLaunchResult"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IDevelopInterface::~IDevelopInterface() = default;
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/develop_interface.h b/src/core/hle/service/ns/develop_interface.h
new file mode 100644
index 000000000..a9f81ccd6
--- /dev/null
+++ b/src/core/hle/service/ns/develop_interface.h
@@ -0,0 +1,16 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IDevelopInterface final : public ServiceFramework<IDevelopInterface> {
+public:
+ explicit IDevelopInterface(Core::System& system_);
+ ~IDevelopInterface() override;
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/document_interface.cpp b/src/core/hle/service/ns/document_interface.cpp
new file mode 100644
index 000000000..51a1e46c0
--- /dev/null
+++ b/src/core/hle/service/ns/document_interface.cpp
@@ -0,0 +1,38 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/core.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ns/document_interface.h"
+
+namespace Service::NS {
+
+IDocumentInterface::IDocumentInterface(Core::System& system_)
+ : ServiceFramework{system_, "IDocumentInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {21, nullptr, "GetApplicationContentPath"},
+ {23, D<&IDocumentInterface::ResolveApplicationContentPath>, "ResolveApplicationContentPath"},
+ {92, D<&IDocumentInterface::GetRunningApplicationProgramId>, "GetRunningApplicationProgramId"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IDocumentInterface::~IDocumentInterface() = default;
+
+Result IDocumentInterface::ResolveApplicationContentPath(ContentPath content_path) {
+ LOG_WARNING(Service_NS, "(STUBBED) called, file_system_proxy_type={}, program_id={:016X}",
+ content_path.file_system_proxy_type, content_path.program_id);
+ R_SUCCEED();
+}
+
+Result IDocumentInterface::GetRunningApplicationProgramId(Out<u64> out_program_id,
+ u64 caller_program_id) {
+ LOG_WARNING(Service_NS, "(STUBBED) called, caller_program_id={:016X}", caller_program_id);
+ *out_program_id = system.GetApplicationProcessProgramID();
+ R_SUCCEED();
+}
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/document_interface.h b/src/core/hle/service/ns/document_interface.h
new file mode 100644
index 000000000..cd461652c
--- /dev/null
+++ b/src/core/hle/service/ns/document_interface.h
@@ -0,0 +1,22 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/ns/ns_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IDocumentInterface final : public ServiceFramework<IDocumentInterface> {
+public:
+ explicit IDocumentInterface(Core::System& system_);
+ ~IDocumentInterface() override;
+
+private:
+ Result ResolveApplicationContentPath(ContentPath content_path);
+ Result GetRunningApplicationProgramId(Out<u64> out_program_id, u64 caller_program_id);
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/download_task_interface.cpp b/src/core/hle/service/ns/download_task_interface.cpp
new file mode 100644
index 000000000..62dc7f187
--- /dev/null
+++ b/src/core/hle/service/ns/download_task_interface.cpp
@@ -0,0 +1,39 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ns/download_task_interface.h"
+
+namespace Service::NS {
+
+IDownloadTaskInterface::IDownloadTaskInterface(Core::System& system_)
+ : ServiceFramework{system_, "IDownloadTaskInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {701, nullptr, "ClearTaskStatusList"},
+ {702, nullptr, "RequestDownloadTaskList"},
+ {703, nullptr, "RequestEnsureDownloadTask"},
+ {704, nullptr, "ListDownloadTaskStatus"},
+ {705, nullptr, "RequestDownloadTaskListData"},
+ {706, nullptr, "TryCommitCurrentApplicationDownloadTask"},
+ {707, D<&IDownloadTaskInterface::EnableAutoCommit>, "EnableAutoCommit"},
+ {708, D<&IDownloadTaskInterface::DisableAutoCommit>, "DisableAutoCommit"},
+ {709, nullptr, "TriggerDynamicCommitEvent"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IDownloadTaskInterface::~IDownloadTaskInterface() = default;
+
+Result IDownloadTaskInterface::EnableAutoCommit() {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ R_SUCCEED();
+}
+Result IDownloadTaskInterface::DisableAutoCommit() {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/download_task_interface.h b/src/core/hle/service/ns/download_task_interface.h
new file mode 100644
index 000000000..b1cb69cb8
--- /dev/null
+++ b/src/core/hle/service/ns/download_task_interface.h
@@ -0,0 +1,20 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IDownloadTaskInterface final : public ServiceFramework<IDownloadTaskInterface> {
+public:
+ explicit IDownloadTaskInterface(Core::System& system_);
+ ~IDownloadTaskInterface() override;
+
+private:
+ Result EnableAutoCommit();
+ Result DisableAutoCommit();
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/dynamic_rights_interface.cpp b/src/core/hle/service/ns/dynamic_rights_interface.cpp
new file mode 100644
index 000000000..ce81e203f
--- /dev/null
+++ b/src/core/hle/service/ns/dynamic_rights_interface.cpp
@@ -0,0 +1,62 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ns/dynamic_rights_interface.h"
+
+namespace Service::NS {
+
+IDynamicRightsInterface::IDynamicRightsInterface(Core::System& system_)
+ : ServiceFramework{system_, "DynamicRightsInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "RequestApplicationRightsOnServer"},
+ {1, nullptr, "RequestAssignRights"},
+ {4, nullptr, "DeprecatedRequestAssignRightsToResume"},
+ {5, D<&IDynamicRightsInterface::VerifyActivatedRightsOwners>, "VerifyActivatedRightsOwners"},
+ {6, nullptr, "DeprecatedGetApplicationRightsStatus"},
+ {7, nullptr, "RequestPrefetchForDynamicRights"},
+ {8, nullptr, "GetDynamicRightsState"},
+ {9, nullptr, "RequestApplicationRightsOnServerToResume"},
+ {10, nullptr, "RequestAssignRightsToResume"},
+ {11, nullptr, "GetActivatedRightsUsers"},
+ {12, nullptr, "GetApplicationRightsStatus"},
+ {13, D<&IDynamicRightsInterface::GetRunningApplicationStatus>, "GetRunningApplicationStatus"},
+ {14, nullptr, "SelectApplicationLicense"},
+ {15, nullptr, "RequestContentsAuthorizationToken"},
+ {16, nullptr, "QualifyUser"},
+ {17, nullptr, "QualifyUserWithProcessId"},
+ {18, D<&IDynamicRightsInterface::NotifyApplicationRightsCheckStart>, "NotifyApplicationRightsCheckStart"},
+ {19, nullptr, "UpdateUserList"},
+ {20, nullptr, "IsRightsLostUser"},
+ {21, nullptr, "SetRequiredAddOnContentsOnContentsAvailabilityTransition"},
+ {22, nullptr, "GetLimitedApplicationLicense"},
+ {23, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"},
+ {24, nullptr, "NotifyLimitedApplicationLicenseUpgradableEventForDebug"},
+ {25, nullptr, "RequestProceedDynamicRightsState"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IDynamicRightsInterface::~IDynamicRightsInterface() = default;
+
+Result IDynamicRightsInterface::NotifyApplicationRightsCheckStart() {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ R_SUCCEED();
+}
+
+Result IDynamicRightsInterface::GetRunningApplicationStatus(Out<u32> out_status,
+ u64 rights_handle) {
+ LOG_WARNING(Service_NS, "(STUBBED) called, rights_handle={:#x}", rights_handle);
+ *out_status = 0;
+ R_SUCCEED();
+}
+
+Result IDynamicRightsInterface::VerifyActivatedRightsOwners(u64 rights_handle) {
+ LOG_WARNING(Service_NS, "(STUBBED) called, rights_handle={:#x}", rights_handle);
+ R_SUCCEED();
+}
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/dynamic_rights_interface.h b/src/core/hle/service/ns/dynamic_rights_interface.h
new file mode 100644
index 000000000..877e009b0
--- /dev/null
+++ b/src/core/hle/service/ns/dynamic_rights_interface.h
@@ -0,0 +1,22 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IDynamicRightsInterface final : public ServiceFramework<IDynamicRightsInterface> {
+public:
+ explicit IDynamicRightsInterface(Core::System& system_);
+ ~IDynamicRightsInterface() override;
+
+private:
+ Result NotifyApplicationRightsCheckStart();
+ Result GetRunningApplicationStatus(Out<u32> out_status, u64 rights_handle);
+ Result VerifyActivatedRightsOwners(u64 rights_handle);
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/ecommerce_interface.cpp b/src/core/hle/service/ns/ecommerce_interface.cpp
new file mode 100644
index 000000000..76fc425f0
--- /dev/null
+++ b/src/core/hle/service/ns/ecommerce_interface.cpp
@@ -0,0 +1,27 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/ns/ecommerce_interface.h"
+
+namespace Service::NS {
+
+IECommerceInterface::IECommerceInterface(Core::System& system_)
+ : ServiceFramework{system_, "IECommerceInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "RequestLinkDevice"},
+ {1, nullptr, "RequestCleanupAllPreInstalledApplications"},
+ {2, nullptr, "RequestCleanupPreInstalledApplication"},
+ {3, nullptr, "RequestSyncRights"},
+ {4, nullptr, "RequestUnlinkDevice"},
+ {5, nullptr, "RequestRevokeAllELicense"},
+ {6, nullptr, "RequestSyncRightsBasedOnAssignedELicenses"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IECommerceInterface::~IECommerceInterface() = default;
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/ecommerce_interface.h b/src/core/hle/service/ns/ecommerce_interface.h
new file mode 100644
index 000000000..4352101f4
--- /dev/null
+++ b/src/core/hle/service/ns/ecommerce_interface.h
@@ -0,0 +1,16 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IECommerceInterface final : public ServiceFramework<IECommerceInterface> {
+public:
+ explicit IECommerceInterface(Core::System& system_);
+ ~IECommerceInterface() override;
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/factory_reset_interface.cpp b/src/core/hle/service/ns/factory_reset_interface.cpp
new file mode 100644
index 000000000..fd5cf7e1f
--- /dev/null
+++ b/src/core/hle/service/ns/factory_reset_interface.cpp
@@ -0,0 +1,27 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/ns/factory_reset_interface.h"
+
+namespace Service::NS {
+
+IFactoryResetInterface::IFactoryResetInterface(Core::System& system_)
+ : ServiceFramework{system_, "IFactoryResetInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {100, nullptr, "ResetToFactorySettings"},
+ {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"},
+ {102, nullptr, "ResetToFactorySettingsForRefurbishment"},
+ {103, nullptr, "ResetToFactorySettingsWithPlatformRegion"},
+ {104, nullptr, "ResetToFactorySettingsWithPlatformRegionAuthentication"},
+ {105, nullptr, "RequestResetToFactorySettingsSecurely"},
+ {106, nullptr, "RequestResetToFactorySettingsWithPlatformRegionAuthenticationSecurely"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IFactoryResetInterface::~IFactoryResetInterface() = default;
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/factory_reset_interface.h b/src/core/hle/service/ns/factory_reset_interface.h
new file mode 100644
index 000000000..50d125123
--- /dev/null
+++ b/src/core/hle/service/ns/factory_reset_interface.h
@@ -0,0 +1,16 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IFactoryResetInterface final : public ServiceFramework<IFactoryResetInterface> {
+public:
+ explicit IFactoryResetInterface(Core::System& system_);
+ ~IFactoryResetInterface() override;
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp
index 19c3ff01b..8402e83cb 100644
--- a/src/core/hle/service/ns/ns.cpp
+++ b/src/core/hle/service/ns/ns.cpp
@@ -1,893 +1,38 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "common/logging/log.h"
-#include "common/settings.h"
-#include "core/arm/debug.h"
-#include "core/core.h"
-#include "core/file_sys/control_metadata.h"
-#include "core/file_sys/patch_manager.h"
-#include "core/file_sys/vfs/vfs.h"
-#include "core/hle/service/filesystem/filesystem.h"
-#include "core/hle/service/glue/glue_manager.h"
-#include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/ns/errors.h"
-#include "core/hle/service/ns/iplatform_service_manager.h"
-#include "core/hle/service/ns/language.h"
+#include "core/hle/service/ns/develop_interface.h"
#include "core/hle/service/ns/ns.h"
-#include "core/hle/service/ns/pdm_qry.h"
+#include "core/hle/service/ns/platform_service_manager.h"
+#include "core/hle/service/ns/query_service.h"
+#include "core/hle/service/ns/service_getter_interface.h"
+#include "core/hle/service/ns/system_update_interface.h"
+#include "core/hle/service/ns/vulnerability_manager_interface.h"
#include "core/hle/service/server_manager.h"
-#include "core/hle/service/set/settings_server.h"
namespace Service::NS {
-IAccountProxyInterface::IAccountProxyInterface(Core::System& system_)
- : ServiceFramework{system_, "IAccountProxyInterface"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "CreateUserAccount"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IAccountProxyInterface::~IAccountProxyInterface() = default;
-
-IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_)
- : ServiceFramework{system_, "IApplicationManagerInterface"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "ListApplicationRecord"},
- {1, nullptr, "GenerateApplicationRecordCount"},
- {2, nullptr, "GetApplicationRecordUpdateSystemEvent"},
- {3, nullptr, "GetApplicationViewDeprecated"},
- {4, nullptr, "DeleteApplicationEntity"},
- {5, nullptr, "DeleteApplicationCompletely"},
- {6, nullptr, "IsAnyApplicationEntityRedundant"},
- {7, nullptr, "DeleteRedundantApplicationEntity"},
- {8, nullptr, "IsApplicationEntityMovable"},
- {9, nullptr, "MoveApplicationEntity"},
- {11, nullptr, "CalculateApplicationOccupiedSize"},
- {16, nullptr, "PushApplicationRecord"},
- {17, nullptr, "ListApplicationRecordContentMeta"},
- {19, nullptr, "LaunchApplicationOld"},
- {21, nullptr, "GetApplicationContentPath"},
- {22, nullptr, "TerminateApplication"},
- {23, nullptr, "ResolveApplicationContentPath"},
- {26, nullptr, "BeginInstallApplication"},
- {27, nullptr, "DeleteApplicationRecord"},
- {30, nullptr, "RequestApplicationUpdateInfo"},
- {31, nullptr, "Unknown31"},
- {32, nullptr, "CancelApplicationDownload"},
- {33, nullptr, "ResumeApplicationDownload"},
- {35, nullptr, "UpdateVersionList"},
- {36, nullptr, "PushLaunchVersion"},
- {37, nullptr, "ListRequiredVersion"},
- {38, nullptr, "CheckApplicationLaunchVersion"},
- {39, nullptr, "CheckApplicationLaunchRights"},
- {40, nullptr, "GetApplicationLogoData"},
- {41, nullptr, "CalculateApplicationDownloadRequiredSize"},
- {42, nullptr, "CleanupSdCard"},
- {43, nullptr, "CheckSdCardMountStatus"},
- {44, nullptr, "GetSdCardMountStatusChangedEvent"},
- {45, nullptr, "GetGameCardAttachmentEvent"},
- {46, nullptr, "GetGameCardAttachmentInfo"},
- {47, nullptr, "GetTotalSpaceSize"},
- {48, nullptr, "GetFreeSpaceSize"},
- {49, nullptr, "GetSdCardRemovedEvent"},
- {52, nullptr, "GetGameCardUpdateDetectionEvent"},
- {53, nullptr, "DisableApplicationAutoDelete"},
- {54, nullptr, "EnableApplicationAutoDelete"},
- {55, &IApplicationManagerInterface::GetApplicationDesiredLanguage, "GetApplicationDesiredLanguage"},
- {56, nullptr, "SetApplicationTerminateResult"},
- {57, nullptr, "ClearApplicationTerminateResult"},
- {58, nullptr, "GetLastSdCardMountUnexpectedResult"},
- {59, &IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode, "ConvertApplicationLanguageToLanguageCode"},
- {60, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
- {61, nullptr, "GetBackgroundDownloadStressTaskInfo"},
- {62, nullptr, "GetGameCardStopper"},
- {63, nullptr, "IsSystemProgramInstalled"},
- {64, nullptr, "StartApplyDeltaTask"},
- {65, nullptr, "GetRequestServerStopper"},
- {66, nullptr, "GetBackgroundApplyDeltaStressTaskInfo"},
- {67, nullptr, "CancelApplicationApplyDelta"},
- {68, nullptr, "ResumeApplicationApplyDelta"},
- {69, nullptr, "CalculateApplicationApplyDeltaRequiredSize"},
- {70, nullptr, "ResumeAll"},
- {71, nullptr, "GetStorageSize"},
- {80, nullptr, "RequestDownloadApplication"},
- {81, nullptr, "RequestDownloadAddOnContent"},
- {82, nullptr, "DownloadApplication"},
- {83, nullptr, "CheckApplicationResumeRights"},
- {84, nullptr, "GetDynamicCommitEvent"},
- {85, nullptr, "RequestUpdateApplication2"},
- {86, nullptr, "EnableApplicationCrashReport"},
- {87, nullptr, "IsApplicationCrashReportEnabled"},
- {90, nullptr, "BoostSystemMemoryResourceLimit"},
- {91, nullptr, "DeprecatedLaunchApplication"},
- {92, nullptr, "GetRunningApplicationProgramId"},
- {93, nullptr, "GetMainApplicationProgramIndex"},
- {94, nullptr, "LaunchApplication"},
- {95, nullptr, "GetApplicationLaunchInfo"},
- {96, nullptr, "AcquireApplicationLaunchInfo"},
- {97, nullptr, "GetMainApplicationProgramIndexByApplicationLaunchInfo"},
- {98, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
- {99, nullptr, "LaunchDevMenu"},
- {100, nullptr, "ResetToFactorySettings"},
- {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"},
- {102, nullptr, "ResetToFactorySettingsForRefurbishment"},
- {103, nullptr, "ResetToFactorySettingsWithPlatformRegion"},
- {104, nullptr, "ResetToFactorySettingsWithPlatformRegionAuthentication"},
- {105, nullptr, "RequestResetToFactorySettingsSecurely"},
- {106, nullptr, "RequestResetToFactorySettingsWithPlatformRegionAuthenticationSecurely"},
- {200, nullptr, "CalculateUserSaveDataStatistics"},
- {201, nullptr, "DeleteUserSaveDataAll"},
- {210, nullptr, "DeleteUserSystemSaveData"},
- {211, nullptr, "DeleteSaveData"},
- {220, nullptr, "UnregisterNetworkServiceAccount"},
- {221, nullptr, "UnregisterNetworkServiceAccountWithUserSaveDataDeletion"},
- {300, nullptr, "GetApplicationShellEvent"},
- {301, nullptr, "PopApplicationShellEventInfo"},
- {302, nullptr, "LaunchLibraryApplet"},
- {303, nullptr, "TerminateLibraryApplet"},
- {304, nullptr, "LaunchSystemApplet"},
- {305, nullptr, "TerminateSystemApplet"},
- {306, nullptr, "LaunchOverlayApplet"},
- {307, nullptr, "TerminateOverlayApplet"},
- {400, &IApplicationManagerInterface::GetApplicationControlData, "GetApplicationControlData"},
- {401, nullptr, "InvalidateAllApplicationControlCache"},
- {402, nullptr, "RequestDownloadApplicationControlData"},
- {403, nullptr, "GetMaxApplicationControlCacheCount"},
- {404, nullptr, "InvalidateApplicationControlCache"},
- {405, nullptr, "ListApplicationControlCacheEntryInfo"},
- {406, nullptr, "GetApplicationControlProperty"},
- {407, nullptr, "ListApplicationTitle"},
- {408, nullptr, "ListApplicationIcon"},
- {502, nullptr, "RequestCheckGameCardRegistration"},
- {503, nullptr, "RequestGameCardRegistrationGoldPoint"},
- {504, nullptr, "RequestRegisterGameCard"},
- {505, nullptr, "GetGameCardMountFailureEvent"},
- {506, nullptr, "IsGameCardInserted"},
- {507, nullptr, "EnsureGameCardAccess"},
- {508, nullptr, "GetLastGameCardMountFailureResult"},
- {509, nullptr, "ListApplicationIdOnGameCard"},
- {510, nullptr, "GetGameCardPlatformRegion"},
- {600, nullptr, "CountApplicationContentMeta"},
- {601, nullptr, "ListApplicationContentMetaStatus"},
- {602, nullptr, "ListAvailableAddOnContent"},
- {603, nullptr, "GetOwnedApplicationContentMetaStatus"},
- {604, nullptr, "RegisterContentsExternalKey"},
- {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"},
- {606, nullptr, "GetContentMetaStorage"},
- {607, nullptr, "ListAvailableAddOnContent"},
- {609, nullptr, "ListAvailabilityAssuredAddOnContent"},
- {610, nullptr, "GetInstalledContentMetaStorage"},
- {611, nullptr, "PrepareAddOnContent"},
- {700, nullptr, "PushDownloadTaskList"},
- {701, nullptr, "ClearTaskStatusList"},
- {702, nullptr, "RequestDownloadTaskList"},
- {703, nullptr, "RequestEnsureDownloadTask"},
- {704, nullptr, "ListDownloadTaskStatus"},
- {705, nullptr, "RequestDownloadTaskListData"},
- {800, nullptr, "RequestVersionList"},
- {801, nullptr, "ListVersionList"},
- {802, nullptr, "RequestVersionListData"},
- {900, nullptr, "GetApplicationRecord"},
- {901, nullptr, "GetApplicationRecordProperty"},
- {902, nullptr, "EnableApplicationAutoUpdate"},
- {903, nullptr, "DisableApplicationAutoUpdate"},
- {904, nullptr, "TouchApplication"},
- {905, nullptr, "RequestApplicationUpdate"},
- {906, nullptr, "IsApplicationUpdateRequested"},
- {907, nullptr, "WithdrawApplicationUpdateRequest"},
- {908, nullptr, "ListApplicationRecordInstalledContentMeta"},
- {909, nullptr, "WithdrawCleanupAddOnContentsWithNoRightsRecommendation"},
- {910, nullptr, "HasApplicationRecord"},
- {911, nullptr, "SetPreInstalledApplication"},
- {912, nullptr, "ClearPreInstalledApplicationFlag"},
- {913, nullptr, "ListAllApplicationRecord"},
- {914, nullptr, "HideApplicationRecord"},
- {915, nullptr, "ShowApplicationRecord"},
- {916, nullptr, "IsApplicationAutoDeleteDisabled"},
- {1000, nullptr, "RequestVerifyApplicationDeprecated"},
- {1001, nullptr, "CorruptApplicationForDebug"},
- {1002, nullptr, "RequestVerifyAddOnContentsRights"},
- {1003, nullptr, "RequestVerifyApplication"},
- {1004, nullptr, "CorruptContentForDebug"},
- {1200, nullptr, "NeedsUpdateVulnerability"},
- {1300, nullptr, "IsAnyApplicationEntityInstalled"},
- {1301, nullptr, "DeleteApplicationContentEntities"},
- {1302, nullptr, "CleanupUnrecordedApplicationEntity"},
- {1303, nullptr, "CleanupAddOnContentsWithNoRights"},
- {1304, nullptr, "DeleteApplicationContentEntity"},
- {1305, nullptr, "TryDeleteRunningApplicationEntity"},
- {1306, nullptr, "TryDeleteRunningApplicationCompletely"},
- {1307, nullptr, "TryDeleteRunningApplicationContentEntities"},
- {1308, nullptr, "DeleteApplicationCompletelyForDebug"},
- {1309, nullptr, "CleanupUnavailableAddOnContents"},
- {1310, nullptr, "RequestMoveApplicationEntity"},
- {1311, nullptr, "EstimateSizeToMove"},
- {1312, nullptr, "HasMovableEntity"},
- {1313, nullptr, "CleanupOrphanContents"},
- {1314, nullptr, "CheckPreconditionSatisfiedToMove"},
- {1400, nullptr, "PrepareShutdown"},
- {1500, nullptr, "FormatSdCard"},
- {1501, nullptr, "NeedsSystemUpdateToFormatSdCard"},
- {1502, nullptr, "GetLastSdCardFormatUnexpectedResult"},
- {1504, nullptr, "InsertSdCard"},
- {1505, nullptr, "RemoveSdCard"},
- {1506, nullptr, "GetSdCardStartupStatus"},
- {1600, nullptr, "GetSystemSeedForPseudoDeviceId"},
- {1601, nullptr, "ResetSystemSeedForPseudoDeviceId"},
- {1700, nullptr, "ListApplicationDownloadingContentMeta"},
- {1701, nullptr, "GetApplicationView"},
- {1702, nullptr, "GetApplicationDownloadTaskStatus"},
- {1703, nullptr, "GetApplicationViewDownloadErrorContext"},
- {1704, nullptr, "GetApplicationViewWithPromotionInfo"},
- {1705, nullptr, "IsPatchAutoDeletableApplication"},
- {1800, nullptr, "IsNotificationSetupCompleted"},
- {1801, nullptr, "GetLastNotificationInfoCount"},
- {1802, nullptr, "ListLastNotificationInfo"},
- {1803, nullptr, "ListNotificationTask"},
- {1900, nullptr, "IsActiveAccount"},
- {1901, nullptr, "RequestDownloadApplicationPrepurchasedRights"},
- {1902, nullptr, "GetApplicationTicketInfo"},
- {1903, nullptr, "RequestDownloadApplicationPrepurchasedRightsForAccount"},
- {2000, nullptr, "GetSystemDeliveryInfo"},
- {2001, nullptr, "SelectLatestSystemDeliveryInfo"},
- {2002, nullptr, "VerifyDeliveryProtocolVersion"},
- {2003, nullptr, "GetApplicationDeliveryInfo"},
- {2004, nullptr, "HasAllContentsToDeliver"},
- {2005, nullptr, "CompareApplicationDeliveryInfo"},
- {2006, nullptr, "CanDeliverApplication"},
- {2007, nullptr, "ListContentMetaKeyToDeliverApplication"},
- {2008, nullptr, "NeedsSystemUpdateToDeliverApplication"},
- {2009, nullptr, "EstimateRequiredSize"},
- {2010, nullptr, "RequestReceiveApplication"},
- {2011, nullptr, "CommitReceiveApplication"},
- {2012, nullptr, "GetReceiveApplicationProgress"},
- {2013, nullptr, "RequestSendApplication"},
- {2014, nullptr, "GetSendApplicationProgress"},
- {2015, nullptr, "CompareSystemDeliveryInfo"},
- {2016, nullptr, "ListNotCommittedContentMeta"},
- {2017, nullptr, "CreateDownloadTask"},
- {2018, nullptr, "GetApplicationDeliveryInfoHash"},
- {2050, nullptr, "GetApplicationRightsOnClient"},
- {2051, nullptr, "InvalidateRightsIdCache"},
- {2100, nullptr, "GetApplicationTerminateResult"},
- {2101, nullptr, "GetRawApplicationTerminateResult"},
- {2150, nullptr, "CreateRightsEnvironment"},
- {2151, nullptr, "DestroyRightsEnvironment"},
- {2152, nullptr, "ActivateRightsEnvironment"},
- {2153, nullptr, "DeactivateRightsEnvironment"},
- {2154, nullptr, "ForceActivateRightsContextForExit"},
- {2155, nullptr, "UpdateRightsEnvironmentStatus"},
- {2156, nullptr, "CreateRightsEnvironmentForMicroApplication"},
- {2160, nullptr, "AddTargetApplicationToRightsEnvironment"},
- {2161, nullptr, "SetUsersToRightsEnvironment"},
- {2170, nullptr, "GetRightsEnvironmentStatus"},
- {2171, nullptr, "GetRightsEnvironmentStatusChangedEvent"},
- {2180, nullptr, "RequestExtendRightsInRightsEnvironment"},
- {2181, nullptr, "GetResultOfExtendRightsInRightsEnvironment"},
- {2182, nullptr, "SetActiveRightsContextUsingStateToRightsEnvironment"},
- {2190, nullptr, "GetRightsEnvironmentHandleForApplication"},
- {2199, nullptr, "GetRightsEnvironmentCountForDebug"},
- {2200, nullptr, "GetGameCardApplicationCopyIdentifier"},
- {2201, nullptr, "GetInstalledApplicationCopyIdentifier"},
- {2250, nullptr, "RequestReportActiveELicence"},
- {2300, nullptr, "ListEventLog"},
- {2350, nullptr, "PerformAutoUpdateByApplicationId"},
- {2351, nullptr, "RequestNoDownloadRightsErrorResolution"},
- {2352, nullptr, "RequestResolveNoDownloadRightsError"},
- {2353, nullptr, "GetApplicationDownloadTaskInfo"},
- {2354, nullptr, "PrioritizeApplicationBackgroundTask"},
- {2355, nullptr, "PreferStorageEfficientUpdate"},
- {2356, nullptr, "RequestStorageEfficientUpdatePreferable"},
- {2357, nullptr, "EnableMultiCoreDownload"},
- {2358, nullptr, "DisableMultiCoreDownload"},
- {2359, nullptr, "IsMultiCoreDownloadEnabled"},
- {2400, nullptr, "GetPromotionInfo"},
- {2401, nullptr, "CountPromotionInfo"},
- {2402, nullptr, "ListPromotionInfo"},
- {2403, nullptr, "ImportPromotionJsonForDebug"},
- {2404, nullptr, "ClearPromotionInfoForDebug"},
- {2500, nullptr, "ConfirmAvailableTime"},
- {2510, nullptr, "CreateApplicationResource"},
- {2511, nullptr, "GetApplicationResource"},
- {2513, nullptr, "LaunchMicroApplication"},
- {2514, nullptr, "ClearTaskOfAsyncTaskManager"},
- {2515, nullptr, "CleanupAllPlaceHolderAndFragmentsIfNoTask"},
- {2516, nullptr, "EnsureApplicationCertificate"},
- {2517, nullptr, "CreateApplicationInstance"},
- {2518, nullptr, "UpdateQualificationForDebug"},
- {2519, nullptr, "IsQualificationTransitionSupported"},
- {2520, nullptr, "IsQualificationTransitionSupportedByProcessId"},
- {2521, nullptr, "GetRightsUserChangedEvent"},
- {2522, nullptr, "IsRomRedirectionAvailable"},
- {2800, nullptr, "GetApplicationIdOfPreomia"},
- {3000, nullptr, "RegisterDeviceLockKey"},
- {3001, nullptr, "UnregisterDeviceLockKey"},
- {3002, nullptr, "VerifyDeviceLockKey"},
- {3003, nullptr, "HideApplicationIcon"},
- {3004, nullptr, "ShowApplicationIcon"},
- {3005, nullptr, "HideApplicationTitle"},
- {3006, nullptr, "ShowApplicationTitle"},
- {3007, nullptr, "EnableGameCard"},
- {3008, nullptr, "DisableGameCard"},
- {3009, nullptr, "EnableLocalContentShare"},
- {3010, nullptr, "DisableLocalContentShare"},
- {3011, nullptr, "IsApplicationIconHidden"},
- {3012, nullptr, "IsApplicationTitleHidden"},
- {3013, nullptr, "IsGameCardEnabled"},
- {3014, nullptr, "IsLocalContentShareEnabled"},
- {3050, nullptr, "ListAssignELicenseTaskResult"},
- {9999, nullptr, "GetApplicationCertificate"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IApplicationManagerInterface::~IApplicationManagerInterface() = default;
-
-void IApplicationManagerInterface::GetApplicationControlData(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto flag = rp.PopRaw<u64>();
- LOG_DEBUG(Service_NS, "called with flag={:016X}", flag);
-
- const auto title_id = rp.PopRaw<u64>();
-
- const auto size = ctx.GetWriteBufferSize();
-
- const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
- system.GetContentProvider()};
- const auto control = pm.GetControlMetadata();
-
- std::vector<u8> out;
-
- if (control.first != nullptr) {
- if (size < 0x4000) {
- LOG_ERROR(Service_NS,
- "output buffer is too small! (actual={:016X}, expected_min=0x4000)", size);
- IPC::ResponseBuilder rb{ctx, 2};
- // TODO(DarkLordZach): Find a better error code for this.
- rb.Push(ResultUnknown);
- return;
- }
-
- out.resize(0x4000);
- const auto bytes = control.first->GetRawBytes();
- std::memcpy(out.data(), bytes.data(), bytes.size());
- } else {
- LOG_WARNING(Service_NS, "missing NACP data for title_id={:016X}, defaulting to zeros.",
- title_id);
- out.resize(std::min<u64>(0x4000, size));
- }
-
- if (control.second != nullptr) {
- if (size < 0x4000 + control.second->GetSize()) {
- LOG_ERROR(Service_NS,
- "output buffer is too small! (actual={:016X}, expected_min={:016X})", size,
- 0x4000 + control.second->GetSize());
- IPC::ResponseBuilder rb{ctx, 2};
- // TODO(DarkLordZach): Find a better error code for this.
- rb.Push(ResultUnknown);
- return;
- }
-
- out.resize(0x4000 + control.second->GetSize());
- control.second->Read(out.data() + 0x4000, control.second->GetSize());
- } else {
- LOG_WARNING(Service_NS, "missing icon data for title_id={:016X}, defaulting to zeros.",
- title_id);
- }
-
- ctx.WriteBuffer(out);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u32>(static_cast<u32>(out.size()));
-}
-
-void IApplicationManagerInterface::GetApplicationDesiredLanguage(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto supported_languages = rp.Pop<u32>();
-
- u8 desired_language{};
- const auto res = GetApplicationDesiredLanguage(&desired_language, supported_languages);
- if (res == ResultSuccess) {
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u32>(desired_language);
- } else {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
- }
-}
-
-Result IApplicationManagerInterface::GetApplicationDesiredLanguage(u8* out_desired_language,
- const u32 supported_languages) {
- LOG_DEBUG(Service_NS, "called with supported_languages={:08X}", supported_languages);
-
- // Get language code from settings
- const auto language_code =
- Set::GetLanguageCodeFromIndex(static_cast<s32>(Settings::values.language_index.GetValue()));
-
- // Convert to application language, get priority list
- const auto application_language = ConvertToApplicationLanguage(language_code);
- if (application_language == std::nullopt) {
- LOG_ERROR(Service_NS, "Could not convert application language! language_code={}",
- language_code);
- return Service::NS::ResultApplicationLanguageNotFound;
- }
- const auto priority_list = GetApplicationLanguagePriorityList(*application_language);
- if (!priority_list) {
- LOG_ERROR(Service_NS,
- "Could not find application language priorities! application_language={}",
- *application_language);
- return Service::NS::ResultApplicationLanguageNotFound;
- }
-
- // Try to find a valid language.
- for (const auto lang : *priority_list) {
- const auto supported_flag = GetSupportedLanguageFlag(lang);
- if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) {
- *out_desired_language = static_cast<u8>(lang);
- return ResultSuccess;
- }
- }
-
- LOG_ERROR(Service_NS, "Could not find a valid language! supported_languages={:08X}",
- supported_languages);
- return Service::NS::ResultApplicationLanguageNotFound;
-}
-
-void IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
- HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto application_language = rp.Pop<u8>();
-
- u64 language_code{};
- const auto res = ConvertApplicationLanguageToLanguageCode(&language_code, application_language);
- if (res == ResultSuccess) {
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push(language_code);
- } else {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
- }
-}
-
-Result IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
- u64* out_language_code, u8 application_language) {
- const auto language_code =
- ConvertToLanguageCode(static_cast<ApplicationLanguage>(application_language));
- if (language_code == std::nullopt) {
- LOG_ERROR(Service_NS, "Language not found! application_language={}", application_language);
- return Service::NS::ResultApplicationLanguageNotFound;
- }
-
- *out_language_code = static_cast<u64>(*language_code);
- return ResultSuccess;
-}
-
-IApplicationVersionInterface::IApplicationVersionInterface(Core::System& system_)
- : ServiceFramework{system_, "IApplicationVersionInterface"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "GetLaunchRequiredVersion"},
- {1, nullptr, "UpgradeLaunchRequiredVersion"},
- {35, nullptr, "UpdateVersionList"},
- {36, nullptr, "PushLaunchVersion"},
- {37, nullptr, "ListRequiredVersion"},
- {800, nullptr, "RequestVersionList"},
- {801, nullptr, "ListVersionList"},
- {802, nullptr, "RequestVersionListData"},
- {900, nullptr, "ImportAutoUpdatePolicyJsonForDebug"},
- {901, nullptr, "ListDefaultAutoUpdatePolicy"},
- {902, nullptr, "ListAutoUpdatePolicyForSpecificApplication"},
- {1000, nullptr, "PerformAutoUpdate"},
- {1001, nullptr, "ListAutoUpdateSchedule"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IApplicationVersionInterface::~IApplicationVersionInterface() = default;
-
-IContentManagementInterface::IContentManagementInterface(Core::System& system_)
- : ServiceFramework{system_, "IContentManagementInterface"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {11, nullptr, "CalculateApplicationOccupiedSize"},
- {43, nullptr, "CheckSdCardMountStatus"},
- {47, &IContentManagementInterface::GetTotalSpaceSize, "GetTotalSpaceSize"},
- {48, &IContentManagementInterface::GetFreeSpaceSize, "GetFreeSpaceSize"},
- {600, nullptr, "CountApplicationContentMeta"},
- {601, nullptr, "ListApplicationContentMetaStatus"},
- {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"},
- {607, nullptr, "IsAnyApplicationRunning"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IContentManagementInterface::~IContentManagementInterface() = default;
-
-void IContentManagementInterface::GetTotalSpaceSize(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto storage{rp.PopEnum<FileSys::StorageId>()};
-
- LOG_INFO(Service_Capture, "called, storage={}", storage);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push<u64>(system.GetFileSystemController().GetTotalSpaceSize(storage));
-}
-
-void IContentManagementInterface::GetFreeSpaceSize(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto storage{rp.PopEnum<FileSys::StorageId>()};
-
- LOG_INFO(Service_Capture, "called, storage={}", storage);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push<u64>(system.GetFileSystemController().GetFreeSpaceSize(storage));
-}
-
-IDocumentInterface::IDocumentInterface(Core::System& system_)
- : ServiceFramework{system_, "IDocumentInterface"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {21, nullptr, "GetApplicationContentPath"},
- {23, &IDocumentInterface::ResolveApplicationContentPath, "ResolveApplicationContentPath"},
- {92, &IDocumentInterface::GetRunningApplicationProgramId, "GetRunningApplicationProgramId"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IDocumentInterface::~IDocumentInterface() = default;
-
-void IDocumentInterface::ResolveApplicationContentPath(HLERequestContext& ctx) {
- struct ContentPath {
- u8 file_system_proxy_type;
- u64 program_id;
- };
- static_assert(sizeof(ContentPath) == 0x10, "ContentPath has wrong size");
-
- IPC::RequestParser rp{ctx};
- auto content_path = rp.PopRaw<ContentPath>();
- LOG_WARNING(Service_NS, "(STUBBED) called, file_system_proxy_type={}, program_id={:016X}",
- content_path.file_system_proxy_type, content_path.program_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
-}
-
-void IDocumentInterface::GetRunningApplicationProgramId(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto caller_program_id = rp.PopRaw<u64>();
- LOG_WARNING(Service_NS, "(STUBBED) called, caller_program_id={:016X}", caller_program_id);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push<u64>(system.GetApplicationProcessProgramID());
-}
-
-IDownloadTaskInterface::IDownloadTaskInterface(Core::System& system_)
- : ServiceFramework{system_, "IDownloadTaskInterface"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {701, nullptr, "ClearTaskStatusList"},
- {702, nullptr, "RequestDownloadTaskList"},
- {703, nullptr, "RequestEnsureDownloadTask"},
- {704, nullptr, "ListDownloadTaskStatus"},
- {705, nullptr, "RequestDownloadTaskListData"},
- {706, nullptr, "TryCommitCurrentApplicationDownloadTask"},
- {707, nullptr, "EnableAutoCommit"},
- {708, nullptr, "DisableAutoCommit"},
- {709, nullptr, "TriggerDynamicCommitEvent"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IDownloadTaskInterface::~IDownloadTaskInterface() = default;
-
-IECommerceInterface::IECommerceInterface(Core::System& system_)
- : ServiceFramework{system_, "IECommerceInterface"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "RequestLinkDevice"},
- {1, nullptr, "RequestCleanupAllPreInstalledApplications"},
- {2, nullptr, "RequestCleanupPreInstalledApplication"},
- {3, nullptr, "RequestSyncRights"},
- {4, nullptr, "RequestUnlinkDevice"},
- {5, nullptr, "RequestRevokeAllELicense"},
- {6, nullptr, "RequestSyncRightsBasedOnAssignedELicenses"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IECommerceInterface::~IECommerceInterface() = default;
-
-IFactoryResetInterface::IFactoryResetInterface(Core::System& system_)
- : ServiceFramework{system_, "IFactoryResetInterface"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {100, nullptr, "ResetToFactorySettings"},
- {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"},
- {102, nullptr, "ResetToFactorySettingsForRefurbishment"},
- {103, nullptr, "ResetToFactorySettingsWithPlatformRegion"},
- {104, nullptr, "ResetToFactorySettingsWithPlatformRegionAuthentication"},
- {105, nullptr, "RequestResetToFactorySettingsSecurely"},
- {106, nullptr, "RequestResetToFactorySettingsWithPlatformRegionAuthenticationSecurely"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IFactoryResetInterface::~IFactoryResetInterface() = default;
-
-IReadOnlyApplicationRecordInterface::IReadOnlyApplicationRecordInterface(Core::System& system_)
- : ServiceFramework{system_, "IReadOnlyApplicationRecordInterface"} {
- static const FunctionInfo functions[] = {
- {0, &IReadOnlyApplicationRecordInterface::HasApplicationRecord, "HasApplicationRecord"},
- {1, nullptr, "NotifyApplicationFailure"},
- {2, &IReadOnlyApplicationRecordInterface::IsDataCorruptedResult, "IsDataCorruptedResult"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IReadOnlyApplicationRecordInterface::~IReadOnlyApplicationRecordInterface() = default;
-
-void IReadOnlyApplicationRecordInterface::HasApplicationRecord(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 program_id = rp.PopRaw<u64>();
- LOG_WARNING(Service_NS, "(STUBBED) called, program_id={:X}", program_id);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u8>(1);
-}
-
-void IReadOnlyApplicationRecordInterface::IsDataCorruptedResult(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto result = rp.PopRaw<Result>();
- LOG_WARNING(Service_NS, "(STUBBED) called, result={:#x}", result.GetInnerValue());
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u8>(0);
-}
-
-IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterface(
- Core::System& system_)
- : ServiceFramework{system_, "IReadOnlyApplicationControlDataInterface"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &IReadOnlyApplicationControlDataInterface::GetApplicationControlData, "GetApplicationControlData"},
- {1, nullptr, "GetApplicationDesiredLanguage"},
- {2, nullptr, "ConvertApplicationLanguageToLanguageCode"},
- {3, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
- {4, nullptr, "SelectApplicationDesiredLanguage"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-IReadOnlyApplicationControlDataInterface::~IReadOnlyApplicationControlDataInterface() = default;
-
-void IReadOnlyApplicationControlDataInterface::GetApplicationControlData(HLERequestContext& ctx) {
- enum class ApplicationControlSource : u8 {
- CacheOnly,
- Storage,
- StorageOnly,
- };
-
- struct RequestParameters {
- ApplicationControlSource source;
- u64 application_id;
- };
- static_assert(sizeof(RequestParameters) == 0x10, "RequestParameters has incorrect size.");
-
- IPC::RequestParser rp{ctx};
- std::vector<u8> nacp_data{};
- const auto parameters{rp.PopRaw<RequestParameters>()};
- const auto result =
- system.GetARPManager().GetControlProperty(&nacp_data, parameters.application_id);
-
- if (result == ResultSuccess) {
- ctx.WriteBuffer(nacp_data.data(), nacp_data.size());
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
-}
-
-NS::NS(const char* name, Core::System& system_) : ServiceFramework{system_, name} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {7988, nullptr, "GetDynamicRightsInterface"},
- {7989, &NS::PushInterface<IReadOnlyApplicationControlDataInterface>, "GetReadOnlyApplicationControlDataInterface"},
- {7991, &NS::PushInterface<IReadOnlyApplicationRecordInterface>, "GetReadOnlyApplicationRecordInterface"},
- {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"},
- {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"},
- {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"},
- {7995, &NS::PushInterface<IAccountProxyInterface>, "GetAccountProxyInterface"},
- {7996, &NS::PushIApplicationManagerInterface, "GetApplicationManagerInterface"},
- {7997, &NS::PushInterface<IDownloadTaskInterface>, "GetDownloadTaskInterface"},
- {7998, &NS::PushInterface<IContentManagementInterface>, "GetContentManagementInterface"},
- {7999, &NS::PushInterface<IDocumentInterface>, "GetDocumentInterface"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-NS::~NS() = default;
-
-std::shared_ptr<IApplicationManagerInterface> NS::GetApplicationManagerInterface() const {
- return GetInterface<IApplicationManagerInterface>(system);
-}
-
-class NS_DEV final : public ServiceFramework<NS_DEV> {
-public:
- explicit NS_DEV(Core::System& system_) : ServiceFramework{system_, "ns:dev"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "LaunchProgram"},
- {1, nullptr, "TerminateProcess"},
- {2, nullptr, "TerminateProgram"},
- {4, nullptr, "GetShellEvent"},
- {5, nullptr, "GetShellEventInfo"},
- {6, nullptr, "TerminateApplication"},
- {7, nullptr, "PrepareLaunchProgramFromHost"},
- {8, nullptr, "LaunchApplicationFromHost"},
- {9, nullptr, "LaunchApplicationWithStorageIdForDevelop"},
- {10, nullptr, "IsSystemMemoryResourceLimitBoosted"},
- {11, nullptr, "GetRunningApplicationProcessIdForDevelop"},
- {12, nullptr, "SetCurrentApplicationRightsEnvironmentCanBeActiveForDevelop"},
- {13, nullptr, "CreateApplicationResourceForDevelop"},
- {14, nullptr, "IsPreomiaForDevelop"},
- {15, nullptr, "GetApplicationProgramIdFromHost"},
- {16, nullptr, "RefreshCachedDebugValues"},
- {17, nullptr, "PrepareLaunchApplicationFromHost"},
- {18, nullptr, "GetLaunchEvent"},
- {19, nullptr, "GetLaunchResult"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-};
-
-class ISystemUpdateControl final : public ServiceFramework<ISystemUpdateControl> {
-public:
- explicit ISystemUpdateControl(Core::System& system_)
- : ServiceFramework{system_, "ISystemUpdateControl"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "HasDownloaded"},
- {1, nullptr, "RequestCheckLatestUpdate"},
- {2, nullptr, "RequestDownloadLatestUpdate"},
- {3, nullptr, "GetDownloadProgress"},
- {4, nullptr, "ApplyDownloadedUpdate"},
- {5, nullptr, "RequestPrepareCardUpdate"},
- {6, nullptr, "GetPrepareCardUpdateProgress"},
- {7, nullptr, "HasPreparedCardUpdate"},
- {8, nullptr, "ApplyCardUpdate"},
- {9, nullptr, "GetDownloadedEulaDataSize"},
- {10, nullptr, "GetDownloadedEulaData"},
- {11, nullptr, "SetupCardUpdate"},
- {12, nullptr, "GetPreparedCardUpdateEulaDataSize"},
- {13, nullptr, "GetPreparedCardUpdateEulaData"},
- {14, nullptr, "SetupCardUpdateViaSystemUpdater"},
- {15, nullptr, "HasReceived"},
- {16, nullptr, "RequestReceiveSystemUpdate"},
- {17, nullptr, "GetReceiveProgress"},
- {18, nullptr, "ApplyReceivedUpdate"},
- {19, nullptr, "GetReceivedEulaDataSize"},
- {20, nullptr, "GetReceivedEulaData"},
- {21, nullptr, "SetupToReceiveSystemUpdate"},
- {22, nullptr, "RequestCheckLatestUpdateIncludesRebootlessUpdate"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-};
-
-class NS_SU final : public ServiceFramework<NS_SU> {
-public:
- explicit NS_SU(Core::System& system_) : ServiceFramework{system_, "ns:su"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "GetBackgroundNetworkUpdateState"},
- {1, &NS_SU::OpenSystemUpdateControl, "OpenSystemUpdateControl"},
- {2, nullptr, "NotifyExFatDriverRequired"},
- {3, nullptr, "ClearExFatDriverStatusForDebug"},
- {4, nullptr, "RequestBackgroundNetworkUpdate"},
- {5, nullptr, "NotifyBackgroundNetworkUpdate"},
- {6, nullptr, "NotifyExFatDriverDownloadedForDebug"},
- {9, nullptr, "GetSystemUpdateNotificationEventForContentDelivery"},
- {10, nullptr, "NotifySystemUpdateForContentDelivery"},
- {11, nullptr, "PrepareShutdown"},
- {12, nullptr, "Unknown12"},
- {13, nullptr, "Unknown13"},
- {14, nullptr, "Unknown14"},
- {15, nullptr, "Unknown15"},
- {16, nullptr, "DestroySystemUpdateTask"},
- {17, nullptr, "RequestSendSystemUpdate"},
- {18, nullptr, "GetSendSystemUpdateProgress"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-
-private:
- void OpenSystemUpdateControl(HLERequestContext& ctx) {
- LOG_DEBUG(Service_NS, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<ISystemUpdateControl>(system);
- }
-};
-
-class NS_VM final : public ServiceFramework<NS_VM> {
-public:
- explicit NS_VM(Core::System& system_) : ServiceFramework{system_, "ns:vm"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {1200, &NS_VM::NeedsUpdateVulnerability, "NeedsUpdateVulnerability"},
- {1201, nullptr, "UpdateSafeSystemVersionForDebug"},
- {1202, nullptr, "GetSafeSystemVersion"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-
-private:
- void NeedsUpdateVulnerability(HLERequestContext& ctx) {
- LOG_WARNING(Service_NS, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(false);
- }
-};
-
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
- server_manager->RegisterNamedService("ns:am2", std::make_shared<NS>("ns:am2", system));
- server_manager->RegisterNamedService("ns:ec", std::make_shared<NS>("ns:ec", system));
- server_manager->RegisterNamedService("ns:rid", std::make_shared<NS>("ns:rid", system));
- server_manager->RegisterNamedService("ns:rt", std::make_shared<NS>("ns:rt", system));
- server_manager->RegisterNamedService("ns:web", std::make_shared<NS>("ns:web", system));
- server_manager->RegisterNamedService("ns:ro", std::make_shared<NS>("ns:ro", system));
-
- server_manager->RegisterNamedService("ns:dev", std::make_shared<NS_DEV>(system));
- server_manager->RegisterNamedService("ns:su", std::make_shared<NS_SU>(system));
- server_manager->RegisterNamedService("ns:vm", std::make_shared<NS_VM>(system));
- server_manager->RegisterNamedService("pdm:qry", std::make_shared<PDM_QRY>(system));
+ server_manager->RegisterNamedService(
+ "ns:am2", std::make_shared<IServiceGetterInterface>(system, "ns:am2"));
+ server_manager->RegisterNamedService(
+ "ns:ec", std::make_shared<IServiceGetterInterface>(system, "ns:ec"));
+ server_manager->RegisterNamedService(
+ "ns:rid", std::make_shared<IServiceGetterInterface>(system, "ns:rid"));
+ server_manager->RegisterNamedService(
+ "ns:rt", std::make_shared<IServiceGetterInterface>(system, "ns:rt"));
+ server_manager->RegisterNamedService(
+ "ns:web", std::make_shared<IServiceGetterInterface>(system, "ns:web"));
+ server_manager->RegisterNamedService(
+ "ns:ro", std::make_shared<IServiceGetterInterface>(system, "ns:ro"));
+
+ server_manager->RegisterNamedService("ns:dev", std::make_shared<IDevelopInterface>(system));
+ server_manager->RegisterNamedService("ns:su", std::make_shared<ISystemUpdateInterface>(system));
+ server_manager->RegisterNamedService("ns:vm",
+ std::make_shared<IVulnerabilityManagerInterface>(system));
+ server_manager->RegisterNamedService("pdm:qry", std::make_shared<IQueryService>(system));
server_manager->RegisterNamedService("pl:s",
std::make_shared<IPlatformServiceManager>(system, "pl:s"));
diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h
index 9ee306ef9..f79b4ae3d 100644
--- a/src/core/hle/service/ns/ns.h
+++ b/src/core/hle/service/ns/ns.h
@@ -3,141 +3,12 @@
#pragma once
-#include "core/hle/service/service.h"
-
namespace Core {
class System;
}
-namespace Service {
-
-namespace FileSystem {
-class FileSystemController;
-} // namespace FileSystem
-
-namespace NS {
-
-class IAccountProxyInterface final : public ServiceFramework<IAccountProxyInterface> {
-public:
- explicit IAccountProxyInterface(Core::System& system_);
- ~IAccountProxyInterface() override;
-};
-
-class IApplicationManagerInterface final : public ServiceFramework<IApplicationManagerInterface> {
-public:
- explicit IApplicationManagerInterface(Core::System& system_);
- ~IApplicationManagerInterface() override;
-
- Result GetApplicationDesiredLanguage(u8* out_desired_language, u32 supported_languages);
- Result ConvertApplicationLanguageToLanguageCode(u64* out_language_code,
- u8 application_language);
-
-private:
- void GetApplicationControlData(HLERequestContext& ctx);
- void GetApplicationDesiredLanguage(HLERequestContext& ctx);
- void ConvertApplicationLanguageToLanguageCode(HLERequestContext& ctx);
-};
-
-class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> {
-public:
- explicit IApplicationVersionInterface(Core::System& system_);
- ~IApplicationVersionInterface() override;
-};
-
-class IContentManagementInterface final : public ServiceFramework<IContentManagementInterface> {
-public:
- explicit IContentManagementInterface(Core::System& system_);
- ~IContentManagementInterface() override;
-
-private:
- void GetTotalSpaceSize(HLERequestContext& ctx);
- void GetFreeSpaceSize(HLERequestContext& ctx);
-};
-
-class IDocumentInterface final : public ServiceFramework<IDocumentInterface> {
-public:
- explicit IDocumentInterface(Core::System& system_);
- ~IDocumentInterface() override;
-
-private:
- void ResolveApplicationContentPath(HLERequestContext& ctx);
- void GetRunningApplicationProgramId(HLERequestContext& ctx);
-};
-
-class IDownloadTaskInterface final : public ServiceFramework<IDownloadTaskInterface> {
-public:
- explicit IDownloadTaskInterface(Core::System& system_);
- ~IDownloadTaskInterface() override;
-};
-
-class IECommerceInterface final : public ServiceFramework<IECommerceInterface> {
-public:
- explicit IECommerceInterface(Core::System& system_);
- ~IECommerceInterface() override;
-};
-
-class IFactoryResetInterface final : public ServiceFramework<IFactoryResetInterface> {
-public:
- explicit IFactoryResetInterface(Core::System& system_);
- ~IFactoryResetInterface() override;
-};
-
-class IReadOnlyApplicationRecordInterface final
- : public ServiceFramework<IReadOnlyApplicationRecordInterface> {
-public:
- explicit IReadOnlyApplicationRecordInterface(Core::System& system_);
- ~IReadOnlyApplicationRecordInterface() override;
-
-private:
- void HasApplicationRecord(HLERequestContext& ctx);
- void IsDataCorruptedResult(HLERequestContext& ctx);
-};
-
-class IReadOnlyApplicationControlDataInterface final
- : public ServiceFramework<IReadOnlyApplicationControlDataInterface> {
-public:
- explicit IReadOnlyApplicationControlDataInterface(Core::System& system_);
- ~IReadOnlyApplicationControlDataInterface() override;
-
-private:
- void GetApplicationControlData(HLERequestContext& ctx);
-};
-
-class NS final : public ServiceFramework<NS> {
-public:
- explicit NS(const char* name, Core::System& system_);
- ~NS() override;
-
- std::shared_ptr<IApplicationManagerInterface> GetApplicationManagerInterface() const;
-
-private:
- template <typename T, typename... Args>
- void PushInterface(HLERequestContext& ctx) {
- LOG_DEBUG(Service_NS, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<T>(system);
- }
-
- void PushIApplicationManagerInterface(HLERequestContext& ctx) {
- LOG_DEBUG(Service_NS, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IApplicationManagerInterface>(system);
- }
-
- template <typename T, typename... Args>
- std::shared_ptr<T> GetInterface(Args&&... args) const {
- static_assert(std::is_base_of_v<SessionRequestHandler, T>,
- "Not a base of ServiceFrameworkBase");
-
- return std::make_shared<T>(std::forward<Args>(args)...);
- }
-};
+namespace Service::NS {
void LoopProcess(Core::System& system);
-} // namespace NS
-} // namespace Service
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/errors.h b/src/core/hle/service/ns/ns_results.h
index 16d2ea6f7..16d2ea6f7 100644
--- a/src/core/hle/service/ns/errors.h
+++ b/src/core/hle/service/ns/ns_results.h
diff --git a/src/core/hle/service/ns/ns_types.h b/src/core/hle/service/ns/ns_types.h
new file mode 100644
index 000000000..38421b0f4
--- /dev/null
+++ b/src/core/hle/service/ns/ns_types.h
@@ -0,0 +1,111 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "common/common_funcs.h"
+#include "common/uuid.h"
+#include "core/file_sys/romfs_factory.h"
+
+namespace Service::NS {
+
+enum class ApplicationRecordType : u8 {
+ Installing = 2,
+ Installed = 3,
+ GameCardNotInserted = 5,
+ Archived = 11,
+ GameCard = 16,
+};
+
+enum class ApplicationControlSource : u8 {
+ CacheOnly = 0,
+ Storage = 1,
+ StorageOnly = 2,
+};
+
+enum class BackgroundNetworkUpdateState : u8 {
+ None,
+ InProgress,
+ Ready,
+};
+
+struct ApplicationRecord {
+ u64 application_id;
+ ApplicationRecordType type;
+ u8 unknown;
+ INSERT_PADDING_BYTES_NOINIT(0x6);
+ u8 unknown2;
+ INSERT_PADDING_BYTES_NOINIT(0x7);
+};
+static_assert(sizeof(ApplicationRecord) == 0x18, "ApplicationRecord has incorrect size.");
+
+/// ApplicationView
+struct ApplicationView {
+ u64 application_id; ///< ApplicationId.
+ u32 unk; ///< Unknown.
+ u32 flags; ///< Flags.
+ std::array<u8, 0x10> unk_x10; ///< Unknown.
+ u32 unk_x20; ///< Unknown.
+ u16 unk_x24; ///< Unknown.
+ std::array<u8, 0x2> unk_x26; ///< Unknown.
+ std::array<u8, 0x8> unk_x28; ///< Unknown.
+ std::array<u8, 0x10> unk_x30; ///< Unknown.
+ u32 unk_x40; ///< Unknown.
+ u8 unk_x44; ///< Unknown.
+ std::array<u8, 0xb> unk_x45; ///< Unknown.
+};
+static_assert(sizeof(ApplicationView) == 0x50, "ApplicationView has incorrect size.");
+
+struct ApplicationRightsOnClient {
+ u64 application_id;
+ Common::UUID uid;
+ u8 flags;
+ u8 flags2;
+ INSERT_PADDING_BYTES_NOINIT(0x6);
+};
+static_assert(sizeof(ApplicationRightsOnClient) == 0x20,
+ "ApplicationRightsOnClient has incorrect size.");
+
+/// NsPromotionInfo
+struct PromotionInfo {
+ u64 start_timestamp; ///< POSIX timestamp for the promotion start.
+ u64 end_timestamp; ///< POSIX timestamp for the promotion end.
+ s64 remaining_time; ///< Remaining time until the promotion ends, in nanoseconds
+ ///< ({end_timestamp - current_time} converted to nanoseconds).
+ INSERT_PADDING_BYTES_NOINIT(0x4);
+ u8 flags; ///< Flags. Bit0: whether the PromotionInfo is valid (including bit1). Bit1 clear:
+ ///< remaining_time is set.
+ INSERT_PADDING_BYTES_NOINIT(0x3);
+};
+static_assert(sizeof(PromotionInfo) == 0x20, "PromotionInfo has incorrect size.");
+
+/// NsApplicationViewWithPromotionInfo
+struct ApplicationViewWithPromotionInfo {
+ ApplicationView view; ///< \ref NsApplicationView
+ PromotionInfo promotion; ///< \ref NsPromotionInfo
+};
+static_assert(sizeof(ApplicationViewWithPromotionInfo) == 0x70,
+ "ApplicationViewWithPromotionInfo has incorrect size.");
+
+struct ApplicationOccupiedSizeEntity {
+ FileSys::StorageId storage_id;
+ u64 app_size;
+ u64 patch_size;
+ u64 aoc_size;
+};
+static_assert(sizeof(ApplicationOccupiedSizeEntity) == 0x20,
+ "ApplicationOccupiedSizeEntity has incorrect size.");
+
+struct ApplicationOccupiedSize {
+ std::array<ApplicationOccupiedSizeEntity, 4> entities;
+};
+static_assert(sizeof(ApplicationOccupiedSize) == 0x80,
+ "ApplicationOccupiedSize has incorrect size.");
+
+struct ContentPath {
+ u8 file_system_proxy_type;
+ u64 program_id;
+};
+static_assert(sizeof(ContentPath) == 0x10, "ContentPath has incorrect size.");
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/pdm_qry.cpp b/src/core/hle/service/ns/pdm_qry.cpp
deleted file mode 100644
index ce0ee30e0..000000000
--- a/src/core/hle/service/ns/pdm_qry.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include <memory>
-
-#include "common/logging/log.h"
-#include "common/uuid.h"
-#include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/ns/pdm_qry.h"
-#include "core/hle/service/service.h"
-
-namespace Service::NS {
-
-PDM_QRY::PDM_QRY(Core::System& system_) : ServiceFramework{system_, "pdm:qry"} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, nullptr, "QueryAppletEvent"},
- {1, nullptr, "QueryPlayStatistics"},
- {2, nullptr, "QueryPlayStatisticsByUserAccountId"},
- {3, nullptr, "QueryPlayStatisticsByNetworkServiceAccountId"},
- {4, nullptr, "QueryPlayStatisticsByApplicationId"},
- {5, &PDM_QRY::QueryPlayStatisticsByApplicationIdAndUserAccountId, "QueryPlayStatisticsByApplicationIdAndUserAccountId"},
- {6, nullptr, "QueryPlayStatisticsByApplicationIdAndNetworkServiceAccountId"},
- {7, nullptr, "QueryLastPlayTimeV0"},
- {8, nullptr, "QueryPlayEvent"},
- {9, nullptr, "GetAvailablePlayEventRange"},
- {10, nullptr, "QueryAccountEvent"},
- {11, nullptr, "QueryAccountPlayEvent"},
- {12, nullptr, "GetAvailableAccountPlayEventRange"},
- {13, nullptr, "QueryApplicationPlayStatisticsForSystemV0"},
- {14, nullptr, "QueryRecentlyPlayedApplication"},
- {15, nullptr, "GetRecentlyPlayedApplicationUpdateEvent"},
- {16, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystemV0"},
- {17, nullptr, "QueryLastPlayTime"},
- {18, nullptr, "QueryApplicationPlayStatisticsForSystem"},
- {19, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystem"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-PDM_QRY::~PDM_QRY() = default;
-
-void PDM_QRY::QueryPlayStatisticsByApplicationIdAndUserAccountId(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto unknown = rp.Pop<bool>();
- rp.Pop<u8>(); // Padding
- const auto application_id = rp.Pop<u64>();
- const auto user_account_uid = rp.PopRaw<Common::UUID>();
-
- // TODO(German77): Read statistics of the game
- PlayStatistics statistics{
- .application_id = application_id,
- .total_launches = 1,
- };
-
- LOG_WARNING(Service_NS,
- "(STUBBED) called. unknown={}. application_id=0x{:016X}, user_account_uid=0x{}",
- unknown, application_id, user_account_uid.RawString());
-
- IPC::ResponseBuilder rb{ctx, 12};
- rb.Push(ResultSuccess);
- rb.PushRaw(statistics);
-}
-
-} // namespace Service::NS
diff --git a/src/core/hle/service/ns/iplatform_service_manager.cpp b/src/core/hle/service/ns/platform_service_manager.cpp
index 46268be95..23cf05005 100644
--- a/src/core/hle/service/ns/iplatform_service_manager.cpp
+++ b/src/core/hle/service/ns/platform_service_manager.cpp
@@ -18,9 +18,9 @@
#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/ipc_helpers.h"
-#include "core/hle/service/ns/iplatform_service_manager.h"
+#include "core/hle/service/ns/platform_service_manager.h"
namespace Service::NS {
@@ -37,11 +37,6 @@ constexpr u32 EXPECTED_MAGIC{0x36f81a1e}; // What we expect the encrypted bfttf
constexpr u64 SHARED_FONT_MEM_SIZE{0x1100000};
constexpr FontRegion EMPTY_REGION{0, 0};
-enum class LoadState : u32 {
- Loading = 0,
- Done = 1,
-};
-
static void DecryptSharedFont(const std::vector<u32>& input, Kernel::PhysicalMemory& output,
std::size_t& offset) {
ASSERT_MSG(offset + (input.size() * sizeof(u32)) < SHARED_FONT_MEM_SIZE,
@@ -138,13 +133,13 @@ IPlatformServiceManager::IPlatformServiceManager(Core::System& system_, const ch
: ServiceFramework{system_, service_name_}, impl{std::make_unique<Impl>()} {
// clang-format off
static const FunctionInfo functions[] = {
- {0, &IPlatformServiceManager::RequestLoad, "RequestLoad"},
- {1, &IPlatformServiceManager::GetLoadState, "GetLoadState"},
- {2, &IPlatformServiceManager::GetSize, "GetSize"},
- {3, &IPlatformServiceManager::GetSharedMemoryAddressOffset, "GetSharedMemoryAddressOffset"},
- {4, &IPlatformServiceManager::GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"},
- {5, &IPlatformServiceManager::GetSharedFontInOrderOfPriority, "GetSharedFontInOrderOfPriority"},
- {6, &IPlatformServiceManager::GetSharedFontInOrderOfPriority, "GetSharedFontInOrderOfPriorityForSystem"},
+ {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"},
@@ -208,47 +203,33 @@ IPlatformServiceManager::IPlatformServiceManager(Core::System& system_, const ch
IPlatformServiceManager::~IPlatformServiceManager() = default;
-void IPlatformServiceManager::RequestLoad(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u32 shared_font_type{rp.Pop<u32>()};
+Result IPlatformServiceManager::RequestLoad(SharedFontType type) {
// Games don't call this so all fonts should be loaded
- LOG_DEBUG(Service_NS, "called, shared_font_type={}", shared_font_type);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ LOG_DEBUG(Service_NS, "called, shared_font_type={}", type);
+ R_SUCCEED();
}
-void IPlatformServiceManager::GetLoadState(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u32 font_id{rp.Pop<u32>()};
- LOG_DEBUG(Service_NS, "called, font_id={}", font_id);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u32>(static_cast<u32>(LoadState::Done));
+Result IPlatformServiceManager::GetLoadState(Out<LoadState> out_load_state, SharedFontType type) {
+ LOG_DEBUG(Service_NS, "called, shared_font_type={}", type);
+ *out_load_state = LoadState::Loaded;
+ R_SUCCEED();
}
-void IPlatformServiceManager::GetSize(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u32 font_id{rp.Pop<u32>()};
- LOG_DEBUG(Service_NS, "called, font_id={}", font_id);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u32>(impl->GetSharedFontRegion(font_id).size);
+Result IPlatformServiceManager::GetSize(Out<u32> out_size, SharedFontType type) {
+ LOG_DEBUG(Service_NS, "called, shared_font_type={}", type);
+ *out_size = impl->GetSharedFontRegion(static_cast<size_t>(type)).size;
+ R_SUCCEED();
}
-void IPlatformServiceManager::GetSharedMemoryAddressOffset(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u32 font_id{rp.Pop<u32>()};
- LOG_DEBUG(Service_NS, "called, font_id={}", font_id);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u32>(impl->GetSharedFontRegion(font_id).offset);
+Result IPlatformServiceManager::GetSharedMemoryAddressOffset(Out<u32> out_shared_memory_offset,
+ SharedFontType type) {
+ LOG_DEBUG(Service_NS, "called, shared_font_type={}", type);
+ *out_shared_memory_offset = impl->GetSharedFontRegion(static_cast<size_t>(type)).offset;
+ R_SUCCEED();
}
-void IPlatformServiceManager::GetSharedMemoryNativeHandle(HLERequestContext& ctx) {
+Result IPlatformServiceManager::GetSharedMemoryNativeHandle(
+ OutCopyHandle<Kernel::KSharedMemory> out_shared_memory_native_handle) {
// Map backing memory for the font data
LOG_DEBUG(Service_NS, "called");
@@ -256,50 +237,37 @@ void IPlatformServiceManager::GetSharedMemoryNativeHandle(HLERequestContext& ctx
std::memcpy(kernel.GetFontSharedMem().GetPointer(), impl->shared_font->data(),
impl->shared_font->size());
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(&kernel.GetFontSharedMem());
+ // FIXME: this shouldn't belong to the kernel
+ *out_shared_memory_native_handle = &kernel.GetFontSharedMem();
+ R_SUCCEED();
}
-void IPlatformServiceManager::GetSharedFontInOrderOfPriority(HLERequestContext& ctx) {
+Result IPlatformServiceManager::GetSharedFontInOrderOfPriority(
+ OutArray<u32, BufferAttr_HipcMapAlias> out_font_codes,
+ OutArray<u32, BufferAttr_HipcMapAlias> out_font_offsets,
+ OutArray<u32, BufferAttr_HipcMapAlias> out_font_sizes, Out<bool> out_fonts_are_loaded,
+ Out<u32> out_font_count, Set::LanguageCode language_code) {
+ LOG_DEBUG(Service_NS, "called, language_code={:#x}", language_code);
+
// The maximum number of elements that can be returned is 6. Regardless of the available fonts
// or buffer size.
- constexpr std::size_t MaxElementCount = 6;
- IPC::RequestParser rp{ctx};
- const u64 language_code{rp.Pop<u64>()}; // TODO(ogniK): Find out what this is used for
- const std::size_t font_codes_count =
- std::min(MaxElementCount, ctx.GetWriteBufferNumElements<u32>(0));
- const std::size_t font_offsets_count =
- std::min(MaxElementCount, ctx.GetWriteBufferNumElements<u32>(1));
- const std::size_t font_sizes_count =
- std::min(MaxElementCount, ctx.GetWriteBufferNumElements<u32>(2));
- LOG_DEBUG(Service_NS, "called, language_code={:X}", language_code);
-
- IPC::ResponseBuilder rb{ctx, 4};
- std::vector<u32> font_codes;
- std::vector<u32> font_offsets;
- std::vector<u32> font_sizes;
+ constexpr size_t MaxElementCount = 6;
// TODO(ogniK): Have actual priority order
- for (std::size_t i = 0; i < impl->shared_font_regions.size(); i++) {
- font_codes.push_back(static_cast<u32>(i));
- auto region = impl->GetSharedFontRegion(i);
- font_offsets.push_back(region.offset);
- font_sizes.push_back(region.size);
- }
+ const auto max_size = std::min({MaxElementCount, out_font_codes.size(), out_font_offsets.size(),
+ out_font_sizes.size(), impl->shared_font_regions.size()});
- // Resize buffers if game requests smaller size output
- font_codes.resize(std::min(font_codes.size(), font_codes_count));
- font_offsets.resize(std::min(font_offsets.size(), font_offsets_count));
- font_sizes.resize(std::min(font_sizes.size(), font_sizes_count));
+ for (size_t i = 0; i < max_size; i++) {
+ auto region = impl->GetSharedFontRegion(i);
- ctx.WriteBuffer(font_codes, 0);
- ctx.WriteBuffer(font_offsets, 1);
- ctx.WriteBuffer(font_sizes, 2);
+ out_font_codes[i] = static_cast<u32>(i);
+ out_font_offsets[i] = region.offset;
+ out_font_sizes[i] = region.size;
+ }
- rb.Push(ResultSuccess);
- rb.Push<u8>(static_cast<u8>(LoadState::Done)); // Fonts Loaded
- rb.Push<u32>(static_cast<u32>(font_codes.size()));
+ *out_fonts_are_loaded = true;
+ *out_font_count = static_cast<u32>(max_size);
+ R_SUCCEED();
}
} // namespace Service::NS
diff --git a/src/core/hle/service/ns/iplatform_service_manager.h b/src/core/hle/service/ns/platform_service_manager.h
index 03071e02b..b82c385a6 100644
--- a/src/core/hle/service/ns/iplatform_service_manager.h
+++ b/src/core/hle/service/ns/platform_service_manager.h
@@ -5,7 +5,9 @@
#include <memory>
#include <vector>
+#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
+#include "core/hle/service/set/settings_types.h"
namespace Service {
@@ -23,6 +25,20 @@ enum class FontArchives : u64 {
ChineseSimple = 0x0100000000000814,
};
+enum class SharedFontType : u32 {
+ JapanUSEuropeStandard = 0,
+ ChineseSimplified = 1,
+ ExtendedChineseSimplified = 2,
+ ChineseTraditional = 3,
+ KoreanHangul = 4,
+ NintendoExtended = 5,
+};
+
+enum class LoadState : u32 {
+ Loading = 0,
+ Loaded = 1,
+};
+
constexpr std::array<std::pair<FontArchives, const char*>, 7> SHARED_FONTS{
std::make_pair(FontArchives::Standard, "nintendo_udsg-r_std_003.bfttf"),
std::make_pair(FontArchives::ChineseSimple, "nintendo_udsg-r_org_zh-cn_003.bfttf"),
@@ -42,12 +58,17 @@ public:
~IPlatformServiceManager() override;
private:
- void RequestLoad(HLERequestContext& ctx);
- void GetLoadState(HLERequestContext& ctx);
- void GetSize(HLERequestContext& ctx);
- void GetSharedMemoryAddressOffset(HLERequestContext& ctx);
- void GetSharedMemoryNativeHandle(HLERequestContext& ctx);
- void GetSharedFontInOrderOfPriority(HLERequestContext& ctx);
+ Result RequestLoad(SharedFontType type);
+ Result GetLoadState(Out<LoadState> out_load_state, SharedFontType type);
+ Result GetSize(Out<u32> out_size, SharedFontType type);
+ Result GetSharedMemoryAddressOffset(Out<u32> out_shared_memory_offset, SharedFontType type);
+ Result GetSharedMemoryNativeHandle(
+ OutCopyHandle<Kernel::KSharedMemory> out_shared_memory_native_handle);
+ Result GetSharedFontInOrderOfPriority(OutArray<u32, BufferAttr_HipcMapAlias> out_font_codes,
+ OutArray<u32, BufferAttr_HipcMapAlias> out_font_offsets,
+ OutArray<u32, BufferAttr_HipcMapAlias> out_font_sizes,
+ Out<bool> out_fonts_are_loaded, Out<u32> out_font_count,
+ Set::LanguageCode language_code);
struct Impl;
std::unique_ptr<Impl> impl;
diff --git a/src/core/hle/service/ns/query_service.cpp b/src/core/hle/service/ns/query_service.cpp
new file mode 100644
index 000000000..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<PlayStatistics> 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/pdm_qry.h b/src/core/hle/service/ns/query_service.h
index c98e01660..6cdbfa277 100644
--- a/src/core/hle/service/ns/pdm_qry.h
+++ b/src/core/hle/service/ns/query_service.h
@@ -3,6 +3,8 @@
#pragma once
+#include "common/uuid.h"
+#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Service::NS {
@@ -20,13 +22,15 @@ struct PlayStatistics {
};
static_assert(sizeof(PlayStatistics) == 0x28, "PlayStatistics is an invalid size");
-class PDM_QRY final : public ServiceFramework<PDM_QRY> {
+class IQueryService final : public ServiceFramework<IQueryService> {
public:
- explicit PDM_QRY(Core::System& system_);
- ~PDM_QRY() override;
+ explicit IQueryService(Core::System& system_);
+ ~IQueryService() override;
private:
- void QueryPlayStatisticsByApplicationIdAndUserAccountId(HLERequestContext& ctx);
+ Result QueryPlayStatisticsByApplicationIdAndUserAccountId(
+ Out<PlayStatistics> 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 100644
index 000000000..9b2ca94a4
--- /dev/null
+++ b/src/core/hle/service/ns/read_only_application_control_data_interface.cpp
@@ -0,0 +1,122 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/settings.h"
+#include "core/file_sys/control_metadata.h"
+#include "core/file_sys/patch_manager.h"
+#include "core/file_sys/vfs/vfs.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ns/language.h"
+#include "core/hle/service/ns/ns_results.h"
+#include "core/hle/service/ns/read_only_application_control_data_interface.h"
+#include "core/hle/service/set/settings_server.h"
+
+namespace Service::NS {
+
+IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterface(
+ Core::System& system_)
+ : ServiceFramework{system_, "IReadOnlyApplicationControlDataInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlData>, "GetApplicationControlData"},
+ {1, D<&IReadOnlyApplicationControlDataInterface::GetApplicationDesiredLanguage>, "GetApplicationDesiredLanguage"},
+ {2, D<&IReadOnlyApplicationControlDataInterface::ConvertApplicationLanguageToLanguageCode>, "ConvertApplicationLanguageToLanguageCode"},
+ {3, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
+ {4, nullptr, "SelectApplicationDesiredLanguage"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IReadOnlyApplicationControlDataInterface::~IReadOnlyApplicationControlDataInterface() = default;
+
+Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData(
+ OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_actual_size,
+ ApplicationControlSource application_control_source, u64 application_id) {
+ LOG_INFO(Service_NS, "called with control_source={}, application_id={:016X}",
+ application_control_source, application_id);
+
+ const FileSys::PatchManager pm{application_id, system.GetFileSystemController(),
+ system.GetContentProvider()};
+ const auto control = pm.GetControlMetadata();
+ const auto size = out_buffer.size();
+
+ const auto icon_size = control.second ? control.second->GetSize() : 0;
+ const auto total_size = sizeof(FileSys::RawNACP) + icon_size;
+
+ if (size < total_size) {
+ LOG_ERROR(Service_NS, "output buffer is too small! (actual={:016X}, expected_min=0x4000)",
+ size);
+ R_THROW(ResultUnknown);
+ }
+
+ if (control.first != nullptr) {
+ const auto bytes = control.first->GetRawBytes();
+ std::memcpy(out_buffer.data(), bytes.data(), bytes.size());
+ } else {
+ LOG_WARNING(Service_NS, "missing NACP data for application_id={:016X}, defaulting to zero",
+ application_id);
+ std::memset(out_buffer.data(), 0, sizeof(FileSys::RawNACP));
+ }
+
+ if (control.second != nullptr) {
+ control.second->Read(out_buffer.data() + sizeof(FileSys::RawNACP), icon_size);
+ } else {
+ LOG_WARNING(Service_NS, "missing icon data for application_id={:016X}", application_id);
+ }
+
+ *out_actual_size = static_cast<u32>(total_size);
+ R_SUCCEED();
+}
+
+Result IReadOnlyApplicationControlDataInterface::GetApplicationDesiredLanguage(
+ Out<ApplicationLanguage> out_desired_language, u32 supported_languages) {
+ LOG_INFO(Service_NS, "called with supported_languages={:08X}", supported_languages);
+
+ // Get language code from settings
+ const auto language_code =
+ Set::GetLanguageCodeFromIndex(static_cast<s32>(Settings::values.language_index.GetValue()));
+
+ // Convert to application language, get priority list
+ const auto application_language = ConvertToApplicationLanguage(language_code);
+ if (application_language == std::nullopt) {
+ LOG_ERROR(Service_NS, "Could not convert application language! language_code={}",
+ language_code);
+ R_THROW(Service::NS::ResultApplicationLanguageNotFound);
+ }
+ const auto priority_list = GetApplicationLanguagePriorityList(*application_language);
+ if (!priority_list) {
+ LOG_ERROR(Service_NS,
+ "Could not find application language priorities! application_language={}",
+ *application_language);
+ R_THROW(Service::NS::ResultApplicationLanguageNotFound);
+ }
+
+ // Try to find a valid language.
+ for (const auto lang : *priority_list) {
+ const auto supported_flag = GetSupportedLanguageFlag(lang);
+ if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) {
+ *out_desired_language = lang;
+ R_SUCCEED();
+ }
+ }
+
+ LOG_ERROR(Service_NS, "Could not find a valid language! supported_languages={:08X}",
+ supported_languages);
+ R_THROW(Service::NS::ResultApplicationLanguageNotFound);
+}
+
+Result IReadOnlyApplicationControlDataInterface::ConvertApplicationLanguageToLanguageCode(
+ Out<u64> out_language_code, ApplicationLanguage application_language) {
+ const auto language_code = ConvertToLanguageCode(application_language);
+ if (language_code == std::nullopt) {
+ LOG_ERROR(Service_NS, "Language not found! application_language={}", application_language);
+ R_THROW(Service::NS::ResultApplicationLanguageNotFound);
+ }
+
+ *out_language_code = static_cast<u64>(*language_code);
+ R_SUCCEED();
+}
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/read_only_application_control_data_interface.h b/src/core/hle/service/ns/read_only_application_control_data_interface.h
new file mode 100644
index 000000000..ac099435a
--- /dev/null
+++ b/src/core/hle/service/ns/read_only_application_control_data_interface.h
@@ -0,0 +1,30 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/ns/language.h"
+#include "core/hle/service/ns/ns_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IReadOnlyApplicationControlDataInterface final
+ : public ServiceFramework<IReadOnlyApplicationControlDataInterface> {
+public:
+ explicit IReadOnlyApplicationControlDataInterface(Core::System& system_);
+ ~IReadOnlyApplicationControlDataInterface() override;
+
+public:
+ Result GetApplicationControlData(OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
+ Out<u32> out_actual_size,
+ ApplicationControlSource application_control_source,
+ u64 application_id);
+ Result GetApplicationDesiredLanguage(Out<ApplicationLanguage> out_desired_language,
+ u32 supported_languages);
+ Result ConvertApplicationLanguageToLanguageCode(Out<u64> out_language_code,
+ ApplicationLanguage application_language);
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/read_only_application_record_interface.cpp b/src/core/hle/service/ns/read_only_application_record_interface.cpp
new file mode 100644
index 000000000..816a1e1dc
--- /dev/null
+++ b/src/core/hle/service/ns/read_only_application_record_interface.cpp
@@ -0,0 +1,38 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ns/read_only_application_record_interface.h"
+
+namespace Service::NS {
+
+IReadOnlyApplicationRecordInterface::IReadOnlyApplicationRecordInterface(Core::System& system_)
+ : ServiceFramework{system_, "IReadOnlyApplicationRecordInterface"} {
+ static const FunctionInfo functions[] = {
+ {0, D<&IReadOnlyApplicationRecordInterface::HasApplicationRecord>, "HasApplicationRecord"},
+ {1, nullptr, "NotifyApplicationFailure"},
+ {2, D<&IReadOnlyApplicationRecordInterface::IsDataCorruptedResult>,
+ "IsDataCorruptedResult"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IReadOnlyApplicationRecordInterface::~IReadOnlyApplicationRecordInterface() = default;
+
+Result IReadOnlyApplicationRecordInterface::HasApplicationRecord(
+ Out<bool> out_has_application_record, u64 program_id) {
+ LOG_WARNING(Service_NS, "(STUBBED) called, program_id={:016X}", program_id);
+ *out_has_application_record = true;
+ R_SUCCEED();
+}
+
+Result IReadOnlyApplicationRecordInterface::IsDataCorruptedResult(
+ Out<bool> out_is_data_corrupted_result, Result result) {
+ LOG_WARNING(Service_NS, "(STUBBED) called, result={:#x}", result.GetInnerValue());
+ *out_is_data_corrupted_result = false;
+ R_SUCCEED();
+}
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/read_only_application_record_interface.h b/src/core/hle/service/ns/read_only_application_record_interface.h
new file mode 100644
index 000000000..d06e8f5e6
--- /dev/null
+++ b/src/core/hle/service/ns/read_only_application_record_interface.h
@@ -0,0 +1,22 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IReadOnlyApplicationRecordInterface final
+ : public ServiceFramework<IReadOnlyApplicationRecordInterface> {
+public:
+ explicit IReadOnlyApplicationRecordInterface(Core::System& system_);
+ ~IReadOnlyApplicationRecordInterface() override;
+
+private:
+ Result HasApplicationRecord(Out<bool> out_has_application_record, u64 program_id);
+ Result IsDataCorruptedResult(Out<bool> out_is_data_corrupted_result, Result result);
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/service_getter_interface.cpp b/src/core/hle/service/ns/service_getter_interface.cpp
new file mode 100644
index 000000000..1a3dd7166
--- /dev/null
+++ b/src/core/hle/service/ns/service_getter_interface.cpp
@@ -0,0 +1,120 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ns/account_proxy_interface.h"
+#include "core/hle/service/ns/application_manager_interface.h"
+#include "core/hle/service/ns/application_version_interface.h"
+#include "core/hle/service/ns/content_management_interface.h"
+#include "core/hle/service/ns/document_interface.h"
+#include "core/hle/service/ns/download_task_interface.h"
+#include "core/hle/service/ns/dynamic_rights_interface.h"
+#include "core/hle/service/ns/ecommerce_interface.h"
+#include "core/hle/service/ns/factory_reset_interface.h"
+#include "core/hle/service/ns/read_only_application_control_data_interface.h"
+#include "core/hle/service/ns/read_only_application_record_interface.h"
+#include "core/hle/service/ns/service_getter_interface.h"
+
+namespace Service::NS {
+
+IServiceGetterInterface::IServiceGetterInterface(Core::System& system_, const char* name)
+ : ServiceFramework{system_, name} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {7988, D<&IServiceGetterInterface::GetDynamicRightsInterface>, "GetDynamicRightsInterface"},
+ {7989, D<&IServiceGetterInterface::GetReadOnlyApplicationControlDataInterface>, "GetReadOnlyApplicationControlDataInterface"},
+ {7991, D<&IServiceGetterInterface::GetReadOnlyApplicationRecordInterface>, "GetReadOnlyApplicationRecordInterface"},
+ {7992, D<&IServiceGetterInterface::GetECommerceInterface>, "GetECommerceInterface"},
+ {7993, D<&IServiceGetterInterface::GetApplicationVersionInterface>, "GetApplicationVersionInterface"},
+ {7994, D<&IServiceGetterInterface::GetFactoryResetInterface>, "GetFactoryResetInterface"},
+ {7995, D<&IServiceGetterInterface::GetAccountProxyInterface>, "GetAccountProxyInterface"},
+ {7996, D<&IServiceGetterInterface::GetApplicationManagerInterface>, "GetApplicationManagerInterface"},
+ {7997, D<&IServiceGetterInterface::GetDownloadTaskInterface>, "GetDownloadTaskInterface"},
+ {7998, D<&IServiceGetterInterface::GetContentManagementInterface>, "GetContentManagementInterface"},
+ {7999, D<&IServiceGetterInterface::GetDocumentInterface>, "GetDocumentInterface"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IServiceGetterInterface::~IServiceGetterInterface() = default;
+
+Result IServiceGetterInterface::GetDynamicRightsInterface(
+ Out<SharedPointer<IDynamicRightsInterface>> out_interface) {
+ LOG_DEBUG(Service_NS, "called");
+ *out_interface = std::make_shared<IDynamicRightsInterface>(system);
+ R_SUCCEED();
+}
+
+Result IServiceGetterInterface::GetReadOnlyApplicationControlDataInterface(
+ Out<SharedPointer<IReadOnlyApplicationControlDataInterface>> out_interface) {
+ LOG_DEBUG(Service_NS, "called");
+ *out_interface = std::make_shared<IReadOnlyApplicationControlDataInterface>(system);
+ R_SUCCEED();
+}
+
+Result IServiceGetterInterface::GetReadOnlyApplicationRecordInterface(
+ Out<SharedPointer<IReadOnlyApplicationRecordInterface>> out_interface) {
+ LOG_DEBUG(Service_NS, "called");
+ *out_interface = std::make_shared<IReadOnlyApplicationRecordInterface>(system);
+ R_SUCCEED();
+}
+
+Result IServiceGetterInterface::GetECommerceInterface(
+ Out<SharedPointer<IECommerceInterface>> out_interface) {
+ LOG_DEBUG(Service_NS, "called");
+ *out_interface = std::make_shared<IECommerceInterface>(system);
+ R_SUCCEED();
+}
+
+Result IServiceGetterInterface::GetApplicationVersionInterface(
+ Out<SharedPointer<IApplicationVersionInterface>> out_interface) {
+ LOG_DEBUG(Service_NS, "called");
+ *out_interface = std::make_shared<IApplicationVersionInterface>(system);
+ R_SUCCEED();
+}
+
+Result IServiceGetterInterface::GetFactoryResetInterface(
+ Out<SharedPointer<IFactoryResetInterface>> out_interface) {
+ LOG_DEBUG(Service_NS, "called");
+ *out_interface = std::make_shared<IFactoryResetInterface>(system);
+ R_SUCCEED();
+}
+
+Result IServiceGetterInterface::GetAccountProxyInterface(
+ Out<SharedPointer<IAccountProxyInterface>> out_interface) {
+ LOG_DEBUG(Service_NS, "called");
+ *out_interface = std::make_shared<IAccountProxyInterface>(system);
+ R_SUCCEED();
+}
+
+Result IServiceGetterInterface::GetApplicationManagerInterface(
+ Out<SharedPointer<IApplicationManagerInterface>> out_interface) {
+ LOG_DEBUG(Service_NS, "called");
+ *out_interface = std::make_shared<IApplicationManagerInterface>(system);
+ R_SUCCEED();
+}
+
+Result IServiceGetterInterface::GetDownloadTaskInterface(
+ Out<SharedPointer<IDownloadTaskInterface>> out_interface) {
+ LOG_DEBUG(Service_NS, "called");
+ *out_interface = std::make_shared<IDownloadTaskInterface>(system);
+ R_SUCCEED();
+}
+
+Result IServiceGetterInterface::GetContentManagementInterface(
+ Out<SharedPointer<IContentManagementInterface>> out_interface) {
+ LOG_DEBUG(Service_NS, "called");
+ *out_interface = std::make_shared<IContentManagementInterface>(system);
+ R_SUCCEED();
+}
+
+Result IServiceGetterInterface::GetDocumentInterface(
+ Out<SharedPointer<IDocumentInterface>> out_interface) {
+ LOG_DEBUG(Service_NS, "called");
+ *out_interface = std::make_shared<IDocumentInterface>(system);
+ R_SUCCEED();
+}
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/service_getter_interface.h b/src/core/hle/service/ns/service_getter_interface.h
new file mode 100644
index 000000000..bbc18d444
--- /dev/null
+++ b/src/core/hle/service/ns/service_getter_interface.h
@@ -0,0 +1,47 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IDynamicRightsInterface;
+class IReadOnlyApplicationControlDataInterface;
+class IReadOnlyApplicationRecordInterface;
+class IECommerceInterface;
+class IApplicationVersionInterface;
+class IFactoryResetInterface;
+class IAccountProxyInterface;
+class IApplicationManagerInterface;
+class IDownloadTaskInterface;
+class IContentManagementInterface;
+class IDocumentInterface;
+
+class IServiceGetterInterface : public ServiceFramework<IServiceGetterInterface> {
+public:
+ explicit IServiceGetterInterface(Core::System& system_, const char* name);
+ ~IServiceGetterInterface() override;
+
+public:
+ Result GetDynamicRightsInterface(Out<SharedPointer<IDynamicRightsInterface>> out_interface);
+ Result GetReadOnlyApplicationControlDataInterface(
+ Out<SharedPointer<IReadOnlyApplicationControlDataInterface>> out_interface);
+ Result GetReadOnlyApplicationRecordInterface(
+ Out<SharedPointer<IReadOnlyApplicationRecordInterface>> out_interface);
+ Result GetECommerceInterface(Out<SharedPointer<IECommerceInterface>> out_interface);
+ Result GetApplicationVersionInterface(
+ Out<SharedPointer<IApplicationVersionInterface>> out_interface);
+ Result GetFactoryResetInterface(Out<SharedPointer<IFactoryResetInterface>> out_interface);
+ Result GetAccountProxyInterface(Out<SharedPointer<IAccountProxyInterface>> out_interface);
+ Result GetApplicationManagerInterface(
+ Out<SharedPointer<IApplicationManagerInterface>> out_interface);
+ Result GetDownloadTaskInterface(Out<SharedPointer<IDownloadTaskInterface>> out_interface);
+ Result GetContentManagementInterface(
+ Out<SharedPointer<IContentManagementInterface>> out_interface);
+ Result GetDocumentInterface(Out<SharedPointer<IDocumentInterface>> out_interface);
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/system_update_control.cpp b/src/core/hle/service/ns/system_update_control.cpp
new file mode 100644
index 000000000..f5f5cfd90
--- /dev/null
+++ b/src/core/hle/service/ns/system_update_control.cpp
@@ -0,0 +1,44 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ns/system_update_control.h"
+
+namespace Service::NS {
+
+ISystemUpdateControl::ISystemUpdateControl(Core::System& system_)
+ : ServiceFramework{system_, "ISystemUpdateControl"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "HasDownloaded"},
+ {1, nullptr, "RequestCheckLatestUpdate"},
+ {2, nullptr, "RequestDownloadLatestUpdate"},
+ {3, nullptr, "GetDownloadProgress"},
+ {4, nullptr, "ApplyDownloadedUpdate"},
+ {5, nullptr, "RequestPrepareCardUpdate"},
+ {6, nullptr, "GetPrepareCardUpdateProgress"},
+ {7, nullptr, "HasPreparedCardUpdate"},
+ {8, nullptr, "ApplyCardUpdate"},
+ {9, nullptr, "GetDownloadedEulaDataSize"},
+ {10, nullptr, "GetDownloadedEulaData"},
+ {11, nullptr, "SetupCardUpdate"},
+ {12, nullptr, "GetPreparedCardUpdateEulaDataSize"},
+ {13, nullptr, "GetPreparedCardUpdateEulaData"},
+ {14, nullptr, "SetupCardUpdateViaSystemUpdater"},
+ {15, nullptr, "HasReceived"},
+ {16, nullptr, "RequestReceiveSystemUpdate"},
+ {17, nullptr, "GetReceiveProgress"},
+ {18, nullptr, "ApplyReceivedUpdate"},
+ {19, nullptr, "GetReceivedEulaDataSize"},
+ {20, nullptr, "GetReceivedEulaData"},
+ {21, nullptr, "SetupToReceiveSystemUpdate"},
+ {22, nullptr, "RequestCheckLatestUpdateIncludesRebootlessUpdate"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+ISystemUpdateControl::~ISystemUpdateControl() = default;
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/system_update_control.h b/src/core/hle/service/ns/system_update_control.h
new file mode 100644
index 000000000..a30a09000
--- /dev/null
+++ b/src/core/hle/service/ns/system_update_control.h
@@ -0,0 +1,16 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class ISystemUpdateControl final : public ServiceFramework<ISystemUpdateControl> {
+public:
+ explicit ISystemUpdateControl(Core::System& system_);
+ ~ISystemUpdateControl() override;
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/system_update_interface.cpp b/src/core/hle/service/ns/system_update_interface.cpp
new file mode 100644
index 000000000..7e22ca3db
--- /dev/null
+++ b/src/core/hle/service/ns/system_update_interface.cpp
@@ -0,0 +1,61 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ns/system_update_control.h"
+#include "core/hle/service/ns/system_update_interface.h"
+
+namespace Service::NS {
+
+ISystemUpdateInterface::ISystemUpdateInterface(Core::System& system_)
+ : ServiceFramework{system_, "ns:su"}, service_context{system_, "ns:su"},
+ update_notification_event{service_context} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, D<&ISystemUpdateInterface::GetBackgroundNetworkUpdateState>, "GetBackgroundNetworkUpdateState"},
+ {1, D<&ISystemUpdateInterface::OpenSystemUpdateControl>, "OpenSystemUpdateControl"},
+ {2, nullptr, "NotifyExFatDriverRequired"},
+ {3, nullptr, "ClearExFatDriverStatusForDebug"},
+ {4, nullptr, "RequestBackgroundNetworkUpdate"},
+ {5, nullptr, "NotifyBackgroundNetworkUpdate"},
+ {6, nullptr, "NotifyExFatDriverDownloadedForDebug"},
+ {9, D<&ISystemUpdateInterface::GetSystemUpdateNotificationEventForContentDelivery>, "GetSystemUpdateNotificationEventForContentDelivery"},
+ {10, nullptr, "NotifySystemUpdateForContentDelivery"},
+ {11, nullptr, "PrepareShutdown"},
+ {12, nullptr, "Unknown12"},
+ {13, nullptr, "Unknown13"},
+ {14, nullptr, "Unknown14"},
+ {15, nullptr, "Unknown15"},
+ {16, nullptr, "DestroySystemUpdateTask"},
+ {17, nullptr, "RequestSendSystemUpdate"},
+ {18, nullptr, "GetSendSystemUpdateProgress"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+ISystemUpdateInterface::~ISystemUpdateInterface() = default;
+
+Result ISystemUpdateInterface::GetBackgroundNetworkUpdateState(
+ Out<BackgroundNetworkUpdateState> out_background_network_update_state) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+ *out_background_network_update_state = BackgroundNetworkUpdateState::None;
+ R_SUCCEED();
+}
+
+Result ISystemUpdateInterface::OpenSystemUpdateControl(
+ Out<SharedPointer<ISystemUpdateControl>> out_system_update_control) {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ *out_system_update_control = std::make_shared<ISystemUpdateControl>(system);
+ R_SUCCEED();
+}
+
+Result ISystemUpdateInterface::GetSystemUpdateNotificationEventForContentDelivery(
+ OutCopyHandle<Kernel::KReadableEvent> out_event) {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ *out_event = update_notification_event.GetHandle();
+ R_SUCCEED();
+}
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/system_update_interface.h b/src/core/hle/service/ns/system_update_interface.h
new file mode 100644
index 000000000..36a2880ec
--- /dev/null
+++ b/src/core/hle/service/ns/system_update_interface.h
@@ -0,0 +1,38 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/ns/ns_types.h"
+#include "core/hle/service/os/event.h"
+#include "core/hle/service/service.h"
+
+namespace Kernel {
+class KReadableEvent;
+}
+
+namespace Service::NS {
+
+class ISystemUpdateControl;
+
+class ISystemUpdateInterface final : public ServiceFramework<ISystemUpdateInterface> {
+public:
+ explicit ISystemUpdateInterface(Core::System& system_);
+ ~ISystemUpdateInterface() override;
+
+private:
+ Result GetBackgroundNetworkUpdateState(
+ Out<BackgroundNetworkUpdateState> out_background_network_update_state);
+ Result OpenSystemUpdateControl(
+ Out<SharedPointer<ISystemUpdateControl>> out_system_update_control);
+ Result GetSystemUpdateNotificationEventForContentDelivery(
+ OutCopyHandle<Kernel::KReadableEvent> out_event);
+
+private:
+ KernelHelpers::ServiceContext service_context;
+ Event update_notification_event;
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/vulnerability_manager_interface.cpp b/src/core/hle/service/ns/vulnerability_manager_interface.cpp
new file mode 100644
index 000000000..69c21fb89
--- /dev/null
+++ b/src/core/hle/service/ns/vulnerability_manager_interface.cpp
@@ -0,0 +1,31 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/ns/vulnerability_manager_interface.h"
+
+namespace Service::NS {
+
+IVulnerabilityManagerInterface::IVulnerabilityManagerInterface(Core::System& system_)
+ : ServiceFramework{system_, "ns:vm"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {1200, D<&IVulnerabilityManagerInterface::NeedsUpdateVulnerability>, "NeedsUpdateVulnerability"},
+ {1201, nullptr, "UpdateSafeSystemVersionForDebug"},
+ {1202, nullptr, "GetSafeSystemVersion"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IVulnerabilityManagerInterface::~IVulnerabilityManagerInterface() = default;
+
+Result IVulnerabilityManagerInterface::NeedsUpdateVulnerability(
+ Out<bool> out_needs_update_vulnerability) {
+ LOG_WARNING(Service_NS, "(STUBBED) called");
+ *out_needs_update_vulnerability = false;
+ R_SUCCEED();
+}
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/ns/vulnerability_manager_interface.h b/src/core/hle/service/ns/vulnerability_manager_interface.h
new file mode 100644
index 000000000..c689cf7ec
--- /dev/null
+++ b/src/core/hle/service/ns/vulnerability_manager_interface.h
@@ -0,0 +1,21 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Service::NS {
+
+class IVulnerabilityManagerInterface final
+ : public ServiceFramework<IVulnerabilityManagerInterface> {
+public:
+ explicit IVulnerabilityManagerInterface(Core::System& system_);
+ ~IVulnerabilityManagerInterface() override;
+
+private:
+ Result NeedsUpdateVulnerability(Out<bool> out_needs_update_vulnerability);
+};
+
+} // namespace Service::NS
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp
index cb256e5b4..03eb507b9 100644
--- a/src/core/hle/service/nvdrv/nvdrv.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv.cpp
@@ -42,7 +42,7 @@ void EventInterface::FreeEvent(Kernel::KEvent* event) {
module.service_context.CloseEvent(event);
}
-void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) {
+void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
auto module = std::make_shared<Module>(system);
const auto NvdrvInterfaceFactoryForApplication = [&, module] {
@@ -62,7 +62,6 @@ void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) {
server_manager->RegisterNamedService("nvdrv:s", NvdrvInterfaceFactoryForSysmodules);
server_manager->RegisterNamedService("nvdrv:t", NvdrvInterfaceFactoryForTesting);
server_manager->RegisterNamedService("nvmemp", std::make_shared<NVMEMP>(system));
- nvnflinger.SetNVDrvInstance(module);
ServerManager::RunServer(std::move(server_manager));
}
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h
index c594f0e5e..b76f81e59 100644
--- a/src/core/hle/service/nvdrv/nvdrv.h
+++ b/src/core/hle/service/nvdrv/nvdrv.h
@@ -10,13 +10,11 @@
#include <span>
#include <string>
#include <unordered_map>
-#include <vector>
#include "common/common_types.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/nvdrv/core/container.h"
#include "core/hle/service/nvdrv/nvdata.h"
-#include "core/hle/service/nvnflinger/ui/fence.h"
#include "core/hle/service/service.h"
namespace Core {
@@ -27,10 +25,6 @@ namespace Kernel {
class KEvent;
}
-namespace Service::Nvnflinger {
-class Nvnflinger;
-}
-
namespace Service::Nvidia {
namespace NvCore {
@@ -99,7 +93,6 @@ public:
private:
friend class EventInterface;
- friend class Service::Nvnflinger::Nvnflinger;
/// Manages syncpoints on the host
NvCore::Container container;
@@ -118,6 +111,6 @@ private:
std::unordered_map<std::string, std::function<FilesContainerType::iterator(DeviceFD)>> builders;
};
-void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system);
+void LoopProcess(Core::System& system);
} // namespace Service::Nvidia
diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.cpp b/src/core/hle/service/nvdrv/nvdrv_interface.cpp
index ffe72f281..241006cc8 100644
--- 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<Module> nvdrv_, const char*
}
NVDRV::~NVDRV() {
- auto& container = nvdrv->GetContainer();
- container.CloseSession(session_id);
+ if (is_initialized) {
+ auto& container = nvdrv->GetContainer();
+ container.CloseSession(session_id);
+ }
}
} // namespace Service::Nvidia
diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.h b/src/core/hle/service/nvdrv/nvdrv_interface.h
index f2195ae1e..c72f92597 100644
--- a/src/core/hle/service/nvdrv/nvdrv_interface.h
+++ b/src/core/hle/service/nvdrv/nvdrv_interface.h
@@ -16,6 +16,10 @@ public:
explicit NVDRV(Core::System& system_, std::shared_ptr<Module> nvdrv_, const char* name);
~NVDRV() override;
+ std::shared_ptr<Module> GetModule() const {
+ return nvdrv;
+ }
+
private:
void Open(HLERequestContext& ctx);
void Ioctl1(HLERequestContext& ctx);
diff --git a/src/core/hle/service/nvnflinger/binder.h b/src/core/hle/service/nvnflinger/binder.h
index aef1477e3..124accb94 100644
--- a/src/core/hle/service/nvnflinger/binder.h
+++ b/src/core/hle/service/nvnflinger/binder.h
@@ -6,6 +6,8 @@
#pragma once
+#include <span>
+
#include "common/common_types.h"
namespace Kernel {
@@ -18,28 +20,12 @@ class HLERequestContext;
namespace Service::android {
-enum class TransactionId {
- RequestBuffer = 1,
- SetBufferCount = 2,
- DequeueBuffer = 3,
- DetachBuffer = 4,
- DetachNextBuffer = 5,
- AttachBuffer = 6,
- QueueBuffer = 7,
- CancelBuffer = 8,
- Query = 9,
- Connect = 10,
- Disconnect = 11,
- AllocateBuffers = 13,
- SetPreallocatedBuffer = 14,
- GetBufferHistory = 17,
-};
-
class IBinder {
public:
virtual ~IBinder() = default;
- virtual void Transact(HLERequestContext& ctx, android::TransactionId code, u32 flags) = 0;
- virtual Kernel::KReadableEvent& GetNativeHandle() = 0;
+ virtual void Transact(u32 code, std::span<const u8> parcel_data, std::span<u8> parcel_reply,
+ u32 flags) = 0;
+ virtual Kernel::KReadableEvent* GetNativeHandle(u32 type_id) = 0;
};
} // namespace Service::android
diff --git a/src/core/hle/service/nvnflinger/buffer_item_consumer.cpp b/src/core/hle/service/nvnflinger/buffer_item_consumer.cpp
index cf151ea3a..123507123 100644
--- a/src/core/hle/service/nvnflinger/buffer_item_consumer.cpp
+++ b/src/core/hle/service/nvnflinger/buffer_item_consumer.cpp
@@ -12,7 +12,7 @@
namespace Service::android {
-BufferItemConsumer::BufferItemConsumer(std::unique_ptr<BufferQueueConsumer> consumer_)
+BufferItemConsumer::BufferItemConsumer(std::shared_ptr<BufferQueueConsumer> consumer_)
: ConsumerBase{std::move(consumer_)} {}
Status BufferItemConsumer::AcquireBuffer(BufferItem* item, std::chrono::nanoseconds present_when,
diff --git a/src/core/hle/service/nvnflinger/buffer_item_consumer.h b/src/core/hle/service/nvnflinger/buffer_item_consumer.h
index e0c6b3604..9f95c9280 100644
--- a/src/core/hle/service/nvnflinger/buffer_item_consumer.h
+++ b/src/core/hle/service/nvnflinger/buffer_item_consumer.h
@@ -19,7 +19,7 @@ class BufferItem;
class BufferItemConsumer final : public ConsumerBase {
public:
- explicit BufferItemConsumer(std::unique_ptr<BufferQueueConsumer> consumer);
+ explicit BufferItemConsumer(std::shared_ptr<BufferQueueConsumer> consumer);
Status AcquireBuffer(BufferItem* item, std::chrono::nanoseconds present_when,
bool wait_for_fence = true);
Status ReleaseBuffer(const BufferItem& item, const Fence& release_fence);
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp
index bbe8e06d4..3bc23aa97 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp
+++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp
@@ -4,12 +4,13 @@
// Parts of this implementation were based on:
// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp
+#include "common/assert.h"
#include "common/logging/log.h"
#include "core/hle/service/nvnflinger/buffer_item.h"
#include "core/hle/service/nvnflinger/buffer_queue_consumer.h"
#include "core/hle/service/nvnflinger/buffer_queue_core.h"
+#include "core/hle/service/nvnflinger/parcel.h"
#include "core/hle/service/nvnflinger/producer_listener.h"
-#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
namespace Service::android {
@@ -254,4 +255,77 @@ Status BufferQueueConsumer::GetReleasedBuffers(u64* out_slot_mask) {
return Status::NoError;
}
+void BufferQueueConsumer::Transact(u32 code, std::span<const u8> parcel_data,
+ std::span<u8> parcel_reply, u32 flags) {
+ // Values used by BnGraphicBufferConsumer onTransact
+ enum class TransactionId {
+ AcquireBuffer = 1,
+ DetachBuffer = 2,
+ AttachBuffer = 3,
+ ReleaseBuffer = 4,
+ ConsumerConnect = 5,
+ ConsumerDisconnect = 6,
+ GetReleasedBuffers = 7,
+ SetDefaultBufferSize = 8,
+ SetDefaultMaxBufferCount = 9,
+ DisableAsyncBuffer = 10,
+ SetMaxAcquiredBufferCount = 11,
+ SetConsumerName = 12,
+ SetDefaultBufferFormat = 13,
+ SetConsumerUsageBits = 14,
+ SetTransformHint = 15,
+ GetSidebandStream = 16,
+ Unknown18 = 18,
+ Unknown20 = 20,
+ };
+
+ Status status{Status::NoError};
+ InputParcel parcel_in{parcel_data};
+ OutputParcel parcel_out{};
+
+ switch (static_cast<TransactionId>(code)) {
+ case TransactionId::AcquireBuffer: {
+ BufferItem item;
+ const s64 present_when = parcel_in.Read<s64>();
+
+ status = AcquireBuffer(&item, std::chrono::nanoseconds{present_when});
+
+ // TODO: can't write this directly, needs a flattener for the sp<GraphicBuffer>
+ // parcel_out.WriteFlattened(item);
+ UNREACHABLE();
+ }
+ case TransactionId::ReleaseBuffer: {
+ const s32 slot = parcel_in.Read<s32>();
+ const u64 frame_number = parcel_in.Read<u64>();
+ const auto release_fence = parcel_in.ReadFlattened<Fence>();
+
+ status = ReleaseBuffer(slot, frame_number, release_fence);
+
+ break;
+ }
+ case TransactionId::GetReleasedBuffers: {
+ u64 slot_mask = 0;
+
+ status = GetReleasedBuffers(&slot_mask);
+
+ parcel_out.Write(slot_mask);
+ break;
+ }
+ default:
+ ASSERT_MSG(false, "called, code={} flags={}", code, flags);
+ break;
+ }
+
+ parcel_out.Write(status);
+
+ const auto serialized = parcel_out.Serialize();
+ std::memcpy(parcel_reply.data(), serialized.data(),
+ std::min(parcel_reply.size(), serialized.size()));
+}
+
+Kernel::KReadableEvent* BufferQueueConsumer::GetNativeHandle(u32 type_id) {
+ ASSERT_MSG(false, "called, type_id={}", type_id);
+ return nullptr;
+}
+
} // namespace Service::android
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_consumer.h b/src/core/hle/service/nvnflinger/buffer_queue_consumer.h
index 0a61e8dbd..a9226f1c3 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.h
+++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.h
@@ -10,6 +10,7 @@
#include <memory>
#include "common/common_types.h"
+#include "core/hle/service/nvnflinger/binder.h"
#include "core/hle/service/nvnflinger/buffer_queue_defs.h"
#include "core/hle/service/nvnflinger/status.h"
@@ -19,10 +20,10 @@ class BufferItem;
class BufferQueueCore;
class IConsumerListener;
-class BufferQueueConsumer final {
+class BufferQueueConsumer final : public IBinder {
public:
explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_);
- ~BufferQueueConsumer();
+ ~BufferQueueConsumer() override;
Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present);
Status ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence);
@@ -30,6 +31,11 @@ public:
Status Disconnect();
Status GetReleasedBuffers(u64* out_slot_mask);
+ void Transact(u32 code, std::span<const u8> parcel_data, std::span<u8> parcel_reply,
+ u32 flags) override;
+
+ Kernel::KReadableEvent* GetNativeHandle(u32 type_id) override;
+
private:
std::shared_ptr<BufferQueueCore> core;
BufferQueueDefs::SlotsType& slots;
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp
index 5d8762d25..9e5091eeb 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp
+++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp
@@ -6,12 +6,9 @@
#include "common/assert.h"
#include "common/logging/log.h"
-#include "common/settings.h"
-#include "core/core.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/kernel.h"
-#include "core/hle/service/hle_ipc.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/nvnflinger/buffer_queue_core.h"
#include "core/hle/service/nvnflinger/buffer_queue_producer.h"
@@ -19,7 +16,6 @@
#include "core/hle/service/nvnflinger/parcel.h"
#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
#include "core/hle/service/nvnflinger/window.h"
-#include "core/hle/service/vi/vi.h"
namespace Service::android {
@@ -807,12 +803,31 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot,
return Status::NoError;
}
-void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u32 flags) {
+void BufferQueueProducer::Transact(u32 code, std::span<const u8> parcel_data,
+ std::span<u8> parcel_reply, u32 flags) {
+ // Values used by BnGraphicBufferProducer onTransact
+ enum class TransactionId {
+ RequestBuffer = 1,
+ SetBufferCount = 2,
+ DequeueBuffer = 3,
+ DetachBuffer = 4,
+ DetachNextBuffer = 5,
+ AttachBuffer = 6,
+ QueueBuffer = 7,
+ CancelBuffer = 8,
+ Query = 9,
+ Connect = 10,
+ Disconnect = 11,
+ AllocateBuffers = 13,
+ SetPreallocatedBuffer = 14,
+ GetBufferHistory = 17,
+ };
+
Status status{Status::NoError};
- InputParcel parcel_in{ctx.ReadBuffer()};
+ InputParcel parcel_in{parcel_data};
OutputParcel parcel_out{};
- switch (code) {
+ switch (static_cast<TransactionId>(code)) {
case TransactionId::Connect: {
const auto enable_listener = parcel_in.Read<bool>();
const auto api = parcel_in.Read<NativeWindowApi>();
@@ -917,11 +932,13 @@ void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u
parcel_out.Write(status);
- ctx.WriteBuffer(parcel_out.Serialize());
+ const auto serialized = parcel_out.Serialize();
+ std::memcpy(parcel_reply.data(), serialized.data(),
+ std::min(parcel_reply.size(), serialized.size()));
}
-Kernel::KReadableEvent& BufferQueueProducer::GetNativeHandle() {
- return buffer_wait_event->GetReadableEvent();
+Kernel::KReadableEvent* BufferQueueProducer::GetNativeHandle(u32 type_id) {
+ return &buffer_wait_event->GetReadableEvent();
}
} // namespace Service::android
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.h b/src/core/hle/service/nvnflinger/buffer_queue_producer.h
index 64c17d56c..048523514 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_producer.h
+++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.h
@@ -45,11 +45,12 @@ public:
explicit BufferQueueProducer(Service::KernelHelpers::ServiceContext& service_context_,
std::shared_ptr<BufferQueueCore> buffer_queue_core_,
Service::Nvidia::NvCore::NvMap& nvmap_);
- ~BufferQueueProducer();
+ ~BufferQueueProducer() override;
- void Transact(HLERequestContext& ctx, android::TransactionId code, u32 flags) override;
+ void Transact(u32 code, std::span<const u8> parcel_data, std::span<u8> parcel_reply,
+ u32 flags) override;
- Kernel::KReadableEvent& GetNativeHandle() override;
+ Kernel::KReadableEvent* GetNativeHandle(u32 type_id) override;
public:
Status RequestBuffer(s32 slot, std::shared_ptr<GraphicBuffer>* buf);
diff --git a/src/core/hle/service/nvnflinger/consumer_base.cpp b/src/core/hle/service/nvnflinger/consumer_base.cpp
index 1059e72bf..e360ebfd8 100644
--- a/src/core/hle/service/nvnflinger/consumer_base.cpp
+++ b/src/core/hle/service/nvnflinger/consumer_base.cpp
@@ -14,7 +14,7 @@
namespace Service::android {
-ConsumerBase::ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_)
+ConsumerBase::ConsumerBase(std::shared_ptr<BufferQueueConsumer> consumer_)
: consumer{std::move(consumer_)} {}
ConsumerBase::~ConsumerBase() {
diff --git a/src/core/hle/service/nvnflinger/consumer_base.h b/src/core/hle/service/nvnflinger/consumer_base.h
index ea3e9e97a..b29c16f86 100644
--- a/src/core/hle/service/nvnflinger/consumer_base.h
+++ b/src/core/hle/service/nvnflinger/consumer_base.h
@@ -27,7 +27,7 @@ public:
void Abandon();
protected:
- explicit ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_);
+ explicit ConsumerBase(std::shared_ptr<BufferQueueConsumer> consumer_);
~ConsumerBase() override;
void OnFrameAvailable(const BufferItem& item) override;
@@ -54,7 +54,7 @@ protected:
bool is_abandoned{};
- std::unique_ptr<BufferQueueConsumer> consumer;
+ std::shared_ptr<BufferQueueConsumer> consumer;
mutable std::mutex mutex;
};
diff --git a/src/core/hle/service/nvnflinger/display.h b/src/core/hle/service/nvnflinger/display.h
new file mode 100644
index 000000000..f27cbf144
--- /dev/null
+++ b/src/core/hle/service/nvnflinger/display.h
@@ -0,0 +1,55 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <list>
+
+#include "core/hle/service/nvnflinger/buffer_item_consumer.h"
+#include "core/hle/service/nvnflinger/hwc_layer.h"
+
+namespace Service::Nvnflinger {
+
+struct Layer {
+ explicit Layer(std::shared_ptr<android::BufferItemConsumer> buffer_item_consumer_,
+ s32 consumer_id_)
+ : buffer_item_consumer(std::move(buffer_item_consumer_)), consumer_id(consumer_id_),
+ blending(LayerBlending::None), visible(true) {}
+ ~Layer() {
+ buffer_item_consumer->Abandon();
+ }
+
+ std::shared_ptr<android::BufferItemConsumer> buffer_item_consumer;
+ s32 consumer_id;
+ LayerBlending blending;
+ bool visible;
+};
+
+struct LayerStack {
+ std::list<Layer> 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;
+ }
+
+ bool HasLayers() {
+ return !stack.layers.empty();
+ }
+
+ 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 100644
--- a/src/core/hle/service/nvnflinger/hardware_composer.cpp
+++ b/src/core/hle/service/nvnflinger/hardware_composer.cpp
@@ -10,8 +10,6 @@
#include "core/hle/service/nvnflinger/hardware_composer.h"
#include "core/hle/service/nvnflinger/hwc_layer.h"
#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
-#include "core/hle/service/vi/display/vi_display.h"
-#include "core/hle/service/vi/layer/vi_layer.h"
namespace Service::Nvnflinger {
@@ -44,7 +42,7 @@ s32 NormalizeSwapInterval(f32* out_speed_scale, s32 swap_interval) {
HardwareComposer::HardwareComposer() = default;
HardwareComposer::~HardwareComposer() = default;
-u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display,
+u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, Display& display,
Nvidia::Devices::nvdisp_disp0& nvdisp) {
boost::container::small_vector<HwcLayer, 2> composition_stack;
@@ -56,12 +54,11 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display,
bool has_acquired_buffer{};
// Acquire all necessary framebuffers.
- for (size_t i = 0; i < display.GetNumLayers(); i++) {
- auto& layer = display.GetLayer(i);
- auto layer_id = layer.GetLayerId();
+ for (auto& layer : display.stack.layers) {
+ auto consumer_id = layer.consumer_id;
// Try to fetch the framebuffer (either new or stale).
- const auto result = this->CacheFramebufferLocked(layer, layer_id);
+ const auto result = this->CacheFramebufferLocked(layer, consumer_id);
// If we failed, skip this layer.
if (result == CacheStatus::NoBufferAvailable) {
@@ -73,24 +70,26 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display,
has_acquired_buffer = true;
}
- const auto& buffer = m_framebuffers[layer_id];
+ const auto& buffer = m_framebuffers[consumer_id];
const auto& item = buffer.item;
const auto& igbp_buffer = *item.graphic_buffer;
// TODO: get proper Z-index from layer
- composition_stack.emplace_back(HwcLayer{
- .buffer_handle = igbp_buffer.BufferId(),
- .offset = igbp_buffer.Offset(),
- .format = igbp_buffer.ExternalFormat(),
- .width = igbp_buffer.Width(),
- .height = igbp_buffer.Height(),
- .stride = igbp_buffer.Stride(),
- .z_index = 0,
- .blending = layer.GetBlending(),
- .transform = static_cast<android::BufferTransformFlags>(item.transform),
- .crop_rect = item.crop,
- .acquire_fence = item.fence,
- });
+ if (layer.visible) {
+ composition_stack.emplace_back(HwcLayer{
+ .buffer_handle = igbp_buffer.BufferId(),
+ .offset = igbp_buffer.Offset(),
+ .format = igbp_buffer.ExternalFormat(),
+ .width = igbp_buffer.Width(),
+ .height = igbp_buffer.Height(),
+ .stride = igbp_buffer.Stride(),
+ .z_index = 0,
+ .blending = layer.blending,
+ .transform = static_cast<android::BufferTransformFlags>(item.transform),
+ .crop_rect = item.crop,
+ .acquire_fence = item.fence,
+ });
+ }
// We need to compose again either before this frame is supposed to
// be released, or exactly on the vsync period it should be released.
@@ -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 100644
--- a/src/core/hle/service/nvnflinger/hardware_composer.h
+++ b/src/core/hle/service/nvnflinger/hardware_composer.h
@@ -3,35 +3,29 @@
#pragma once
-#include <memory>
#include <boost/container/flat_map.hpp>
#include "core/hle/service/nvnflinger/buffer_item.h"
+#include "core/hle/service/nvnflinger/display.h"
namespace Service::Nvidia::Devices {
class nvdisp_disp0;
}
-namespace Service::VI {
-class Display;
-class Layer;
-} // namespace Service::VI
-
namespace Service::Nvnflinger {
-using LayerId = u64;
+using ConsumerId = s32;
class HardwareComposer {
public:
explicit HardwareComposer();
~HardwareComposer();
- u32 ComposeLocked(f32* out_speed_scale, VI::Display& display,
+ u32 ComposeLocked(f32* out_speed_scale, Display& display,
Nvidia::Devices::nvdisp_disp0& nvdisp);
- void RemoveLayerLocked(VI::Display& display, LayerId layer_id);
+ void RemoveLayerLocked(Display& display, ConsumerId consumer_id);
private:
- // TODO: do we want to track frame number in vi instead?
u64 m_frame_number{0};
private:
@@ -49,11 +43,11 @@ private:
CachedBufferReused,
};
- boost::container::flat_map<LayerId, Framebuffer> m_framebuffers{};
+ boost::container::flat_map<ConsumerId, Framebuffer> m_framebuffers{};
private:
- bool TryAcquireFramebufferLocked(VI::Layer& layer, Framebuffer& framebuffer);
- CacheStatus CacheFramebufferLocked(VI::Layer& layer, LayerId layer_id);
+ bool TryAcquireFramebufferLocked(Layer& layer, Framebuffer& framebuffer);
+ CacheStatus CacheFramebufferLocked(Layer& layer, ConsumerId consumer_id);
};
} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/nvnflinger/hos_binder_driver.cpp b/src/core/hle/service/nvnflinger/hos_binder_driver.cpp
new file mode 100644
index 000000000..8629a2e89
--- /dev/null
+++ b/src/core/hle/service/nvnflinger/hos_binder_driver.cpp
@@ -0,0 +1,66 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/nvnflinger/binder.h"
+#include "core/hle/service/nvnflinger/hos_binder_driver.h"
+#include "core/hle/service/nvnflinger/hos_binder_driver_server.h"
+
+namespace Service::Nvnflinger {
+
+IHOSBinderDriver::IHOSBinderDriver(Core::System& system_,
+ std::shared_ptr<HosBinderDriverServer> server,
+ std::shared_ptr<SurfaceFlinger> surface_flinger)
+ : ServiceFramework{system_, "IHOSBinderDriver"}, m_server(server),
+ m_surface_flinger(surface_flinger) {
+ static const FunctionInfo functions[] = {
+ {0, C<&IHOSBinderDriver::TransactParcel>, "TransactParcel"},
+ {1, C<&IHOSBinderDriver::AdjustRefcount>, "AdjustRefcount"},
+ {2, C<&IHOSBinderDriver::GetNativeHandle>, "GetNativeHandle"},
+ {3, C<&IHOSBinderDriver::TransactParcelAuto>, "TransactParcelAuto"},
+ };
+ RegisterHandlers(functions);
+}
+
+IHOSBinderDriver::~IHOSBinderDriver() = default;
+
+Result IHOSBinderDriver::TransactParcel(s32 binder_id, u32 transaction_id,
+ InBuffer<BufferAttr_HipcMapAlias> parcel_data,
+ OutBuffer<BufferAttr_HipcMapAlias> parcel_reply,
+ u32 flags) {
+ LOG_DEBUG(Service_VI, "called. id={} transaction={}, flags={}", binder_id, transaction_id,
+ flags);
+
+ const auto binder = m_server->TryGetBinder(binder_id);
+ R_SUCCEED_IF(binder == nullptr);
+
+ binder->Transact(transaction_id, parcel_data, parcel_reply, flags);
+
+ R_SUCCEED();
+}
+
+Result IHOSBinderDriver::AdjustRefcount(s32 binder_id, s32 addval, s32 type) {
+ LOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={}, type={}", binder_id, addval, type);
+ R_SUCCEED();
+}
+
+Result IHOSBinderDriver::GetNativeHandle(s32 binder_id, u32 type_id,
+ OutCopyHandle<Kernel::KReadableEvent> out_handle) {
+ LOG_WARNING(Service_VI, "(STUBBED) called id={}, type_id={}", binder_id, type_id);
+
+ const auto binder = m_server->TryGetBinder(binder_id);
+ R_UNLESS(binder != nullptr, ResultUnknown);
+
+ *out_handle = binder->GetNativeHandle(type_id);
+
+ R_SUCCEED();
+}
+
+Result IHOSBinderDriver::TransactParcelAuto(s32 binder_id, u32 transaction_id,
+ InBuffer<BufferAttr_HipcAutoSelect> parcel_data,
+ OutBuffer<BufferAttr_HipcAutoSelect> parcel_reply,
+ u32 flags) {
+ R_RETURN(this->TransactParcel(binder_id, transaction_id, parcel_data, parcel_reply, flags));
+}
+
+} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/nvnflinger/hos_binder_driver.h b/src/core/hle/service/nvnflinger/hos_binder_driver.h
new file mode 100644
index 000000000..b7fb07bd2
--- /dev/null
+++ b/src/core/hle/service/nvnflinger/hos_binder_driver.h
@@ -0,0 +1,46 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Kernel {
+class KReadableEvent;
+}
+
+namespace Service::Nvnflinger {
+
+class HosBinderDriverServer;
+class SurfaceFlinger;
+
+class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> {
+public:
+ explicit IHOSBinderDriver(Core::System& system_, std::shared_ptr<HosBinderDriverServer> server,
+ std::shared_ptr<SurfaceFlinger> surface_flinger);
+ ~IHOSBinderDriver() override;
+
+ std::shared_ptr<SurfaceFlinger> GetSurfaceFlinger() {
+ return m_surface_flinger;
+ }
+
+ std::shared_ptr<HosBinderDriverServer> GetServer() {
+ return m_server;
+ }
+
+private:
+ Result TransactParcel(s32 binder_id, u32 transaction_id,
+ InBuffer<BufferAttr_HipcMapAlias> parcel_data,
+ OutBuffer<BufferAttr_HipcMapAlias> parcel_reply, u32 flags);
+ Result AdjustRefcount(s32 binder_id, s32 addval, s32 type);
+ Result GetNativeHandle(s32 binder_id, u32 type_id,
+ OutCopyHandle<Kernel::KReadableEvent> out_handle);
+ Result TransactParcelAuto(s32 binder_id, u32 transaction_id,
+ InBuffer<BufferAttr_HipcAutoSelect> parcel_data,
+ OutBuffer<BufferAttr_HipcAutoSelect> parcel_reply, u32 flags);
+
+private:
+ const std::shared_ptr<HosBinderDriverServer> m_server;
+ const std::shared_ptr<SurfaceFlinger> m_surface_flinger;
+};
+
+} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp b/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp
index b86a79ec9..29addda44 100644
--- a/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp
+++ b/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp
@@ -8,26 +8,30 @@
namespace Service::Nvnflinger {
-HosBinderDriverServer::HosBinderDriverServer(Core::System& system_)
- : service_context(system_, "HosBinderDriverServer") {}
+HosBinderDriverServer::HosBinderDriverServer() = default;
+HosBinderDriverServer::~HosBinderDriverServer() = default;
-HosBinderDriverServer::~HosBinderDriverServer() {}
-
-u64 HosBinderDriverServer::RegisterProducer(std::unique_ptr<android::IBinder>&& binder) {
+s32 HosBinderDriverServer::RegisterBinder(std::shared_ptr<android::IBinder>&& binder) {
std::scoped_lock lk{lock};
last_id++;
- producers[last_id] = std::move(binder);
+ binders[last_id] = std::move(binder);
return last_id;
}
-android::IBinder* HosBinderDriverServer::TryGetProducer(u64 id) {
+void HosBinderDriverServer::UnregisterBinder(s32 binder_id) {
+ std::scoped_lock lk{lock};
+
+ binders.erase(binder_id);
+}
+
+std::shared_ptr<android::IBinder> HosBinderDriverServer::TryGetBinder(s32 id) const {
std::scoped_lock lk{lock};
- if (auto search = producers.find(id); search != producers.end()) {
- return search->second.get();
+ if (auto search = binders.find(id); search != binders.end()) {
+ return search->second;
}
return {};
diff --git a/src/core/hle/service/nvnflinger/hos_binder_driver_server.h b/src/core/hle/service/nvnflinger/hos_binder_driver_server.h
index 58bb9469a..d72b50833 100644
--- a/src/core/hle/service/nvnflinger/hos_binder_driver_server.h
+++ b/src/core/hle/service/nvnflinger/hos_binder_driver_server.h
@@ -8,7 +8,6 @@
#include <unordered_map>
#include "common/common_types.h"
-#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/nvnflinger/binder.h"
namespace Core {
@@ -19,19 +18,18 @@ namespace Service::Nvnflinger {
class HosBinderDriverServer final {
public:
- explicit HosBinderDriverServer(Core::System& system_);
+ explicit HosBinderDriverServer();
~HosBinderDriverServer();
- u64 RegisterProducer(std::unique_ptr<android::IBinder>&& binder);
+ s32 RegisterBinder(std::shared_ptr<android::IBinder>&& binder);
+ void UnregisterBinder(s32 binder_id);
- android::IBinder* TryGetProducer(u64 id);
+ std::shared_ptr<android::IBinder> TryGetBinder(s32 id) const;
private:
- KernelHelpers::ServiceContext service_context;
-
- std::unordered_map<u64, std::unique_ptr<android::IBinder>> producers;
- std::mutex lock;
- u64 last_id{};
+ std::unordered_map<s32, std::shared_ptr<android::IBinder>> binders;
+ mutable std::mutex lock;
+ s32 last_id{};
};
} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp
index 687ccc9f9..9e3b68b8a 100644
--- a/src/core/hle/service/nvnflinger/nvnflinger.cpp
+++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp
@@ -1,335 +1,24 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
-#include <algorithm>
-#include <optional>
-
-#include "common/assert.h"
-#include "common/logging/log.h"
-#include "common/microprofile.h"
-#include "common/scope_exit.h"
-#include "common/settings.h"
-#include "common/thread.h"
#include "core/core.h"
-#include "core/core_timing.h"
-#include "core/hle/kernel/k_readable_event.h"
-#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
-#include "core/hle/service/nvdrv/nvdrv.h"
-#include "core/hle/service/nvnflinger/buffer_item_consumer.h"
-#include "core/hle/service/nvnflinger/buffer_queue_core.h"
-#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
-#include "core/hle/service/nvnflinger/hardware_composer.h"
+#include "core/hle/service/nvnflinger/hos_binder_driver.h"
#include "core/hle/service/nvnflinger/hos_binder_driver_server.h"
#include "core/hle/service/nvnflinger/nvnflinger.h"
-#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
-#include "core/hle/service/vi/display/vi_display.h"
-#include "core/hle/service/vi/layer/vi_layer.h"
-#include "core/hle/service/vi/vi_results.h"
-#include "video_core/gpu.h"
-#include "video_core/host1x/host1x.h"
-#include "video_core/host1x/syncpoint_manager.h"
+#include "core/hle/service/nvnflinger/surface_flinger.h"
+#include "core/hle/service/server_manager.h"
+#include "core/hle/service/sm/sm.h"
namespace Service::Nvnflinger {
-constexpr auto frame_ns = std::chrono::nanoseconds{1000000000 / 60};
-
-void Nvnflinger::SplitVSync(std::stop_token stop_token) {
- system.RegisterHostThread();
- std::string name = "VSyncThread";
- MicroProfileOnThreadCreate(name.c_str());
-
- // Cleanup
- SCOPE_EXIT({ MicroProfileOnThreadExit(); });
-
- Common::SetCurrentThreadName(name.c_str());
- Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
-
- while (!stop_token.stop_requested()) {
- vsync_signal.Wait();
-
- const auto lock_guard = Lock();
-
- if (!is_abandoned) {
- Compose();
- }
- }
-}
-
-Nvnflinger::Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_)
- : system(system_), service_context(system_, "nvnflinger"),
- hos_binder_driver_server(hos_binder_driver_server_) {
- displays.emplace_back(0, "Default", hos_binder_driver_server, service_context, system);
- displays.emplace_back(1, "External", hos_binder_driver_server, service_context, system);
- displays.emplace_back(2, "Edid", hos_binder_driver_server, service_context, system);
- displays.emplace_back(3, "Internal", hos_binder_driver_server, service_context, system);
- displays.emplace_back(4, "Null", hos_binder_driver_server, service_context, system);
- guard = std::make_shared<std::mutex>();
-
- // Schedule the screen composition events
- multi_composition_event = Core::Timing::CreateEvent(
- "ScreenComposition",
- [this](s64 time,
- std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
- vsync_signal.Set();
- return std::chrono::nanoseconds(GetNextTicks());
- });
-
- single_composition_event = Core::Timing::CreateEvent(
- "ScreenComposition",
- [this](s64 time,
- std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
- const auto lock_guard = Lock();
- Compose();
-
- return std::chrono::nanoseconds(GetNextTicks());
- });
-
- if (system.IsMulticore()) {
- system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, multi_composition_event);
- vsync_thread = std::jthread([this](std::stop_token token) { SplitVSync(token); });
- } else {
- system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, single_composition_event);
- }
-}
-
-Nvnflinger::~Nvnflinger() {
- if (system.IsMulticore()) {
- system.CoreTiming().UnscheduleEvent(multi_composition_event);
- vsync_thread.request_stop();
- vsync_signal.Set();
- } else {
- system.CoreTiming().UnscheduleEvent(single_composition_event);
- }
-
- ShutdownLayers();
-
- if (nvdrv) {
- nvdrv->Close(disp_fd);
- }
-}
-
-void Nvnflinger::ShutdownLayers() {
- // Abandon consumers.
- {
- const auto lock_guard = Lock();
- for (auto& display : displays) {
- display.Abandon();
- }
-
- is_abandoned = true;
- }
-
- // Join the vsync thread, if it exists.
- vsync_thread = {};
-}
-
-void Nvnflinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {
- nvdrv = std::move(instance);
- disp_fd = nvdrv->Open("/dev/nvdisp_disp0", {});
-}
-
-std::optional<u64> Nvnflinger::OpenDisplay(std::string_view name) {
- const auto lock_guard = Lock();
-
- LOG_DEBUG(Service_Nvnflinger, "Opening \"{}\" display", name);
-
- const auto itr =
- std::find_if(displays.begin(), displays.end(),
- [&](const VI::Display& display) { return display.GetName() == name; });
-
- if (itr == displays.end()) {
- return std::nullopt;
- }
-
- return itr->GetID();
-}
-
-bool Nvnflinger::CloseDisplay(u64 display_id) {
- const auto lock_guard = Lock();
- auto* const display = FindDisplay(display_id);
-
- if (display == nullptr) {
- return false;
- }
-
- display->Reset();
-
- return true;
-}
-
-std::optional<u64> Nvnflinger::CreateLayer(u64 display_id, LayerBlending blending) {
- const auto lock_guard = Lock();
- auto* const display = FindDisplay(display_id);
-
- if (display == nullptr) {
- return std::nullopt;
- }
-
- const u64 layer_id = next_layer_id++;
- CreateLayerAtId(*display, layer_id, blending);
- return layer_id;
-}
-
-void Nvnflinger::CreateLayerAtId(VI::Display& display, u64 layer_id, LayerBlending blending) {
- const auto buffer_id = next_buffer_queue_id++;
- display.CreateLayer(layer_id, buffer_id, nvdrv->container);
- display.FindLayer(layer_id)->SetBlending(blending);
-}
-
-bool Nvnflinger::OpenLayer(u64 layer_id) {
- const auto lock_guard = Lock();
-
- for (auto& display : displays) {
- if (auto* layer = display.FindLayer(layer_id); layer) {
- return layer->Open();
- }
- }
-
- return false;
-}
-
-bool Nvnflinger::CloseLayer(u64 layer_id) {
- const auto lock_guard = Lock();
-
- for (auto& display : displays) {
- if (auto* layer = display.FindLayer(layer_id); layer) {
- return layer->Close();
- }
- }
-
- return false;
-}
-
-void Nvnflinger::SetLayerVisibility(u64 layer_id, bool visible) {
- const auto lock_guard = Lock();
-
- for (auto& display : displays) {
- if (auto* layer = display.FindLayer(layer_id); layer) {
- layer->SetVisibility(visible);
- }
- }
-}
-
-void Nvnflinger::DestroyLayer(u64 layer_id) {
- const auto lock_guard = Lock();
-
- for (auto& display : displays) {
- display.DestroyLayer(layer_id);
- }
-}
-
-std::optional<u32> Nvnflinger::FindBufferQueueId(u64 display_id, u64 layer_id) {
- const auto lock_guard = Lock();
- const auto* const layer = FindLayer(display_id, layer_id);
-
- if (layer == nullptr) {
- return std::nullopt;
- }
-
- return layer->GetBinderId();
-}
-
-Result Nvnflinger::FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64 display_id) {
- const auto lock_guard = Lock();
- auto* const display = FindDisplay(display_id);
-
- if (display == nullptr) {
- return VI::ResultNotFound;
- }
-
- *out_vsync_event = display->GetVSyncEvent();
- return ResultSuccess;
-}
-
-VI::Display* Nvnflinger::FindDisplay(u64 display_id) {
- const auto itr =
- std::find_if(displays.begin(), displays.end(),
- [&](const VI::Display& display) { return display.GetID() == display_id; });
-
- if (itr == displays.end()) {
- return nullptr;
- }
-
- return &*itr;
-}
-
-const VI::Display* Nvnflinger::FindDisplay(u64 display_id) const {
- const auto itr =
- std::find_if(displays.begin(), displays.end(),
- [&](const VI::Display& display) { return display.GetID() == display_id; });
-
- if (itr == displays.end()) {
- return nullptr;
- }
-
- return &*itr;
-}
-
-VI::Layer* Nvnflinger::FindLayer(u64 display_id, u64 layer_id) {
- auto* const display = FindDisplay(display_id);
-
- if (display == nullptr) {
- return nullptr;
- }
-
- return display->FindLayer(layer_id);
-}
-
-void Nvnflinger::Compose() {
- for (auto& display : displays) {
- // Trigger vsync for this display at the end of drawing
- SCOPE_EXIT({ display.SignalVSyncEvent(); });
-
- // Don't do anything for displays without layers.
- if (!display.HasLayers()) {
- continue;
- }
-
- if (!system.IsPoweredOn()) {
- return; // We are likely shutting down
- }
-
- auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>(disp_fd);
- ASSERT(nvdisp);
-
- swap_interval = display.GetComposer().ComposeLocked(&compose_speed_scale, display, *nvdisp);
- }
-}
-
-s64 Nvnflinger::GetNextTicks() const {
- const auto& settings = Settings::values;
- auto speed_scale = 1.f;
- if (settings.use_multi_core.GetValue()) {
- if (settings.use_speed_limit.GetValue()) {
- // Scales the speed based on speed_limit setting on MC. SC is handled by
- // SpeedLimiter::DoSpeedLimiting.
- speed_scale = 100.f / settings.speed_limit.GetValue();
- } else {
- // Run at unlocked framerate.
- speed_scale = 0.01f;
- }
- }
-
- // Adjust by speed limit determined during composition.
- speed_scale /= compose_speed_scale;
-
- if (system.GetNVDECActive() && settings.use_video_framerate.GetValue()) {
- // Run at intended presentation rate during video playback.
- speed_scale = 1.f;
- }
-
- const f32 effective_fps = 60.f / static_cast<f32>(swap_interval);
- return static_cast<s64>(speed_scale * (1000000000.f / effective_fps));
-}
-
-FbShareBufferManager& Nvnflinger::GetSystemBufferManager() {
- const auto lock_guard = Lock();
-
- if (!system_buffer_manager) {
- system_buffer_manager = std::make_unique<FbShareBufferManager>(system, *this, nvdrv);
- }
+void LoopProcess(Core::System& system) {
+ const auto binder_server = std::make_shared<HosBinderDriverServer>();
+ const auto surface_flinger = std::make_shared<SurfaceFlinger>(system, *binder_server);
- return *system_buffer_manager;
+ auto server_manager = std::make_unique<ServerManager>(system);
+ server_manager->RegisterNamedService(
+ "dispdrv", std::make_shared<IHOSBinderDriver>(system, binder_server, surface_flinger));
+ ServerManager::RunServer(std::move(server_manager));
}
} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h
index 4cf4f069d..5c41f3013 100644
--- a/src/core/hle/service/nvnflinger/nvnflinger.h
+++ b/src/core/hle/service/nvnflinger/nvnflinger.h
@@ -3,170 +3,12 @@
#pragma once
-#include <list>
-#include <memory>
-#include <mutex>
-#include <optional>
-#include <thread>
-#include <vector>
-
-#include "common/common_types.h"
-#include "common/polyfill_thread.h"
-#include "common/thread.h"
-#include "core/hle/result.h"
-#include "core/hle/service/kernel_helpers.h"
-#include "core/hle/service/nvnflinger/hwc_layer.h"
-
-namespace Common {
-class Event;
-} // namespace Common
-
-namespace Core::Timing {
-class CoreTiming;
-struct EventType;
-} // namespace Core::Timing
-
-namespace Kernel {
-class KReadableEvent;
-} // namespace Kernel
-
-namespace Service::Nvidia {
-class Module;
-} // namespace Service::Nvidia
-
-namespace Service::VI {
-class Display;
-class Layer;
-} // namespace Service::VI
-
-namespace Service::android {
-class BufferQueueCore;
-class BufferQueueProducer;
-} // namespace Service::android
+namespace Core {
+class System;
+}
namespace Service::Nvnflinger {
-class FbShareBufferManager;
-class HardwareComposer;
-class HosBinderDriverServer;
-
-class Nvnflinger final {
-public:
- explicit Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_);
- ~Nvnflinger();
-
- void ShutdownLayers();
-
- /// Sets the NVDrv module instance to use to send buffers to the GPU.
- void SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance);
-
- /// Opens the specified display and returns the ID.
- ///
- /// If an invalid display name is provided, then an empty optional is returned.
- [[nodiscard]] std::optional<u64> OpenDisplay(std::string_view name);
-
- /// Closes the specified display by its ID.
- ///
- /// Returns false if an invalid display ID is provided.
- [[nodiscard]] bool CloseDisplay(u64 display_id);
-
- /// Creates a layer on the specified display and returns the layer ID.
- ///
- /// If an invalid display ID is specified, then an empty optional is returned.
- [[nodiscard]] std::optional<u64> CreateLayer(u64 display_id,
- LayerBlending blending = LayerBlending::None);
-
- /// Opens a layer on all displays for the given layer ID.
- bool OpenLayer(u64 layer_id);
-
- /// Closes a layer on all displays for the given layer ID.
- bool CloseLayer(u64 layer_id);
-
- /// Makes a layer visible on all displays for the given layer ID.
- void SetLayerVisibility(u64 layer_id, bool visible);
-
- /// Destroys the given layer ID.
- void DestroyLayer(u64 layer_id);
-
- /// Finds the buffer queue ID of the specified layer in the specified display.
- ///
- /// If an invalid display ID or layer ID is provided, then an empty optional is returned.
- [[nodiscard]] std::optional<u32> FindBufferQueueId(u64 display_id, u64 layer_id);
-
- /// Gets the vsync event for the specified display.
- ///
- /// If an invalid display ID is provided, then VI::ResultNotFound is returned.
- /// If the vsync event has already been retrieved, then VI::ResultPermissionDenied is returned.
- [[nodiscard]] Result FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64 display_id);
-
- /// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when
- /// finished.
- void Compose();
-
- [[nodiscard]] s64 GetNextTicks() const;
-
- FbShareBufferManager& GetSystemBufferManager();
-
-private:
- struct Layer {
- std::unique_ptr<android::BufferQueueCore> core;
- std::unique_ptr<android::BufferQueueProducer> producer;
- };
-
- friend class FbShareBufferManager;
-
-private:
- [[nodiscard]] std::unique_lock<std::mutex> Lock() const {
- return std::unique_lock{*guard};
- }
-
- /// Finds the display identified by the specified ID.
- [[nodiscard]] VI::Display* FindDisplay(u64 display_id);
-
- /// Finds the display identified by the specified ID.
- [[nodiscard]] const VI::Display* FindDisplay(u64 display_id) const;
-
- /// Finds the layer identified by the specified ID in the desired display.
- [[nodiscard]] VI::Layer* FindLayer(u64 display_id, u64 layer_id);
-
- /// Creates a layer with the specified layer ID in the desired display.
- void CreateLayerAtId(VI::Display& display, u64 layer_id, LayerBlending blending);
-
- void SplitVSync(std::stop_token stop_token);
-
- std::shared_ptr<Nvidia::Module> nvdrv;
- s32 disp_fd;
-
- std::list<VI::Display> displays;
-
- /// Id to use for the next layer that is created, this counter is shared among all displays.
- u64 next_layer_id = 1;
- /// Id to use for the next buffer queue that is created, this counter is shared among all
- /// layers.
- u32 next_buffer_queue_id = 1;
-
- s32 swap_interval = 1;
- f32 compose_speed_scale = 1.0f;
-
- bool is_abandoned = false;
-
- /// Event that handles screen composition.
- std::shared_ptr<Core::Timing::EventType> multi_composition_event;
- std::shared_ptr<Core::Timing::EventType> single_composition_event;
-
- std::unique_ptr<FbShareBufferManager> system_buffer_manager;
-
- std::shared_ptr<std::mutex> guard;
-
- Core::System& system;
-
- Common::Event vsync_signal;
-
- std::jthread vsync_thread;
-
- KernelHelpers::ServiceContext service_context;
-
- HosBinderDriverServer& hos_binder_driver_server;
-};
+void LoopProcess(Core::System& system);
} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/nvnflinger/surface_flinger.cpp b/src/core/hle/service/nvnflinger/surface_flinger.cpp
new file mode 100644
index 000000000..41a705717
--- /dev/null
+++ b/src/core/hle/service/nvnflinger/surface_flinger.cpp
@@ -0,0 +1,124 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/core.h"
+#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
+#include "core/hle/service/nvdrv/nvdrv_interface.h"
+#include "core/hle/service/nvnflinger/display.h"
+#include "core/hle/service/nvnflinger/hos_binder_driver_server.h"
+#include "core/hle/service/nvnflinger/surface_flinger.h"
+#include "core/hle/service/sm/sm.h"
+
+#include "core/hle/service/nvnflinger/buffer_queue_consumer.h"
+#include "core/hle/service/nvnflinger/buffer_queue_core.h"
+#include "core/hle/service/nvnflinger/buffer_queue_producer.h"
+
+namespace Service::Nvnflinger {
+
+SurfaceFlinger::SurfaceFlinger(Core::System& system, HosBinderDriverServer& server)
+ : m_system(system), m_server(server), m_context(m_system, "SurfaceFlinger") {
+ nvdrv = m_system.ServiceManager().GetService<Nvidia::NVDRV>("nvdrv:s", true)->GetModule();
+ disp_fd = nvdrv->Open("/dev/nvdisp_disp0", {});
+}
+
+SurfaceFlinger::~SurfaceFlinger() {
+ nvdrv->Close(disp_fd);
+}
+
+void SurfaceFlinger::AddDisplay(u64 display_id) {
+ m_displays.emplace_back(display_id);
+}
+
+void SurfaceFlinger::RemoveDisplay(u64 display_id) {
+ std::erase_if(m_displays, [&](auto& display) { return display.id == display_id; });
+}
+
+bool SurfaceFlinger::ComposeDisplay(s32* out_swap_interval, f32* out_compose_speed_scale,
+ u64 display_id) {
+ auto* const display = this->FindDisplay(display_id);
+ if (!display || !display->HasLayers()) {
+ return false;
+ }
+
+ *out_swap_interval =
+ m_composer.ComposeLocked(out_compose_speed_scale, *display,
+ *nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>(disp_fd));
+ return true;
+}
+
+void SurfaceFlinger::AddLayerToDisplayStack(u64 display_id, s32 consumer_binder_id) {
+ auto* const display = this->FindDisplay(display_id);
+ auto binder = std::static_pointer_cast<android::BufferQueueConsumer>(
+ m_server.TryGetBinder(consumer_binder_id));
+
+ if (!display || !binder) {
+ return;
+ }
+
+ auto buffer_item_consumer = std::make_shared<android::BufferItemConsumer>(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<android::BufferQueueCore>();
+ auto producer = std::make_shared<android::BufferQueueProducer>(m_context, core, nvmap);
+ auto consumer = std::make_shared<android::BufferQueueConsumer>(core);
+
+ *out_consumer_binder_id = m_server.RegisterBinder(std::move(consumer));
+ *out_producer_binder_id = m_server.RegisterBinder(std::move(producer));
+}
+
+void SurfaceFlinger::DestroyBufferQueue(s32 consumer_binder_id, s32 producer_binder_id) {
+ m_server.UnregisterBinder(producer_binder_id);
+ m_server.UnregisterBinder(consumer_binder_id);
+}
+
+} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/nvnflinger/surface_flinger.h b/src/core/hle/service/nvnflinger/surface_flinger.h
new file mode 100644
index 000000000..d8c53fbda
--- /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 <vector>
+
+#include "common/common_types.h"
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/nvnflinger/hardware_composer.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::Nvidia {
+class Module;
+}
+
+// TODO: ISurfaceComposer
+// TODO: ISurfaceComposerClient
+
+namespace Service::Nvnflinger {
+
+struct Display;
+class HosBinderDriverServer;
+enum class LayerBlending : u32;
+struct Layer;
+
+class SurfaceFlinger {
+public:
+ explicit SurfaceFlinger(Core::System& system, HosBinderDriverServer& server);
+ ~SurfaceFlinger();
+
+ void AddDisplay(u64 display_id);
+ void RemoveDisplay(u64 display_id);
+ bool ComposeDisplay(s32* out_swap_interval, f32* out_compose_speed_scale, u64 display_id);
+
+ void 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<Display> m_displays;
+ std::shared_ptr<Nvidia::Module> 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 fbdf217ba..ce5e3b5b4 100644
--- 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::ServiceManager>& sm, Core::System& system)
- : hos_binder_driver_server{std::make_unique<Nvnflinger::HosBinderDriverServer>(system)},
- nv_flinger{std::make_unique<Nvnflinger::Nvnflinger>(system, *hos_binder_driver_server)} {
-
- auto& kernel = system.Kernel();
-
- // Nvnflinger needs to be accessed by several services like Vi and AppletOE so we instantiate it
- // here and pass it into the respective InstallInterfaces functions.
- system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false);
-
- // clang-format off
- kernel.RunOnHostCoreProcess("audio", [&] { Audio::LoopProcess(system); }).detach();
- kernel.RunOnHostCoreProcess("FS", [&] { FileSystem::LoopProcess(system); }).detach();
- kernel.RunOnHostCoreProcess("jit", [&] { JIT::LoopProcess(system); }).detach();
- kernel.RunOnHostCoreProcess("ldn", [&] { LDN::LoopProcess(system); }).detach();
- kernel.RunOnHostCoreProcess("Loader", [&] { LDR::LoopProcess(system); }).detach();
- kernel.RunOnHostCoreProcess("nvservices", [&] { Nvidia::LoopProcess(*nv_flinger, system); }).detach();
- kernel.RunOnHostCoreProcess("bsdsocket", [&] { Sockets::LoopProcess(system); }).detach();
- kernel.RunOnHostCoreProcess("vi", [&] { VI::LoopProcess(system, *nv_flinger, *hos_binder_driver_server); }).detach();
-
- kernel.RunOnGuestCoreProcess("sm", [&] { SM::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("account", [&] { Account::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("am", [&] { AM::LoopProcess(*nv_flinger, system); });
- kernel.RunOnGuestCoreProcess("aoc", [&] { AOC::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("apm", [&] { APM::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("bcat", [&] { BCAT::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("bpc", [&] { BPC::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("btdrv", [&] { BtDrv::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("btm", [&] { BTM::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("capsrv", [&] { Capture::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("erpt", [&] { ERPT::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("es", [&] { ES::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("eupld", [&] { EUPLD::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("fatal", [&] { Fatal::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("fgm", [&] { FGM::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("friends", [&] { Friend::LoopProcess(system); });
- // glue depends on settings and psc, so they must come first
- kernel.RunOnGuestCoreProcess("settings", [&] { Set::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("psc", [&] { PSC::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("glue", [&] { Glue::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("grc", [&] { GRC::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("hid", [&] { HID::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("lbl", [&] { LBL::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("LogManager.Prod", [&] { LM::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("mig", [&] { Migration::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("mii", [&] { Mii::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("mm", [&] { MM::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("mnpp", [&] { MNPP::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("NCM", [&] { NCM::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("nfc", [&] { NFC::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("nfp", [&] { NFP::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("ngc", [&] { NGC::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("nifm", [&] { NIFM::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("nim", [&] { NIM::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("npns", [&] { NPNS::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("ns", [&] { NS::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("olsc", [&] { OLSC::LoopProcess(system); });
- kernel.RunOnGuestCoreProcess("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 22d1343d5..36aae1c79 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -28,11 +28,6 @@ namespace FileSystem {
class FileSystemController;
}
-namespace Nvnflinger {
-class HosBinderDriverServer;
-class Nvnflinger;
-} // namespace Nvnflinger
-
namespace SM {
class ServiceManager;
}
@@ -236,20 +231,4 @@ private:
}
};
-/**
- * The purpose of this class is to own any objects that need to be shared across the other service
- * implementations. Will be torn down when the global system instance is shutdown.
- */
-class Services final {
-public:
- explicit Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system);
- ~Services();
-
- void KillNVNFlinger();
-
-private:
- std::unique_ptr<Nvnflinger::HosBinderDriverServer> hos_binder_driver_server;
- std::unique_ptr<Nvnflinger::Nvnflinger> nv_flinger;
-};
-
} // namespace Service
diff --git a/src/core/hle/service/services.cpp b/src/core/hle/service/services.cpp
new file mode 100644
index 000000000..d6c6eff50
--- /dev/null
+++ b/src/core/hle/service/services.cpp
@@ -0,0 +1,136 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/services.h"
+
+#include "core/hle/service/acc/acc.h"
+#include "core/hle/service/am/am.h"
+#include "core/hle/service/aoc/aoc_u.h"
+#include "core/hle/service/apm/apm.h"
+#include "core/hle/service/audio/audio.h"
+#include "core/hle/service/bcat/bcat.h"
+#include "core/hle/service/bpc/bpc.h"
+#include "core/hle/service/btdrv/btdrv.h"
+#include "core/hle/service/btm/btm.h"
+#include "core/hle/service/caps/caps.h"
+#include "core/hle/service/erpt/erpt.h"
+#include "core/hle/service/es/es.h"
+#include "core/hle/service/eupld/eupld.h"
+#include "core/hle/service/fatal/fatal.h"
+#include "core/hle/service/fgm/fgm.h"
+#include "core/hle/service/filesystem/filesystem.h"
+#include "core/hle/service/friend/friend.h"
+#include "core/hle/service/glue/glue.h"
+#include "core/hle/service/grc/grc.h"
+#include "core/hle/service/hid/hid.h"
+#include "core/hle/service/ipc_helpers.h"
+#include "core/hle/service/jit/jit.h"
+#include "core/hle/service/lbl/lbl.h"
+#include "core/hle/service/ldn/ldn.h"
+#include "core/hle/service/ldr/ldr.h"
+#include "core/hle/service/lm/lm.h"
+#include "core/hle/service/mig/mig.h"
+#include "core/hle/service/mii/mii.h"
+#include "core/hle/service/mm/mm_u.h"
+#include "core/hle/service/mnpp/mnpp_app.h"
+#include "core/hle/service/ncm/ncm.h"
+#include "core/hle/service/nfc/nfc.h"
+#include "core/hle/service/nfp/nfp.h"
+#include "core/hle/service/ngc/ngc.h"
+#include "core/hle/service/nifm/nifm.h"
+#include "core/hle/service/nim/nim.h"
+#include "core/hle/service/npns/npns.h"
+#include "core/hle/service/ns/ns.h"
+#include "core/hle/service/nvdrv/nvdrv.h"
+#include "core/hle/service/nvnflinger/nvnflinger.h"
+#include "core/hle/service/olsc/olsc.h"
+#include "core/hle/service/omm/omm.h"
+#include "core/hle/service/pcie/pcie.h"
+#include "core/hle/service/pctl/pctl_module.h"
+#include "core/hle/service/pcv/pcv.h"
+#include "core/hle/service/pm/pm.h"
+#include "core/hle/service/prepo/prepo.h"
+#include "core/hle/service/psc/psc.h"
+#include "core/hle/service/ptm/ptm.h"
+#include "core/hle/service/ro/ro.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/set/settings.h"
+#include "core/hle/service/sm/sm.h"
+#include "core/hle/service/sockets/sockets.h"
+#include "core/hle/service/spl/spl_module.h"
+#include "core/hle/service/ssl/ssl.h"
+#include "core/hle/service/usb/usb.h"
+#include "core/hle/service/vi/vi.h"
+
+namespace Service {
+
+Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system,
+ std::stop_token token) {
+ auto& kernel = system.Kernel();
+
+ system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false);
+
+ // clang-format off
+ kernel.RunOnHostCoreProcess("audio", [&] { Audio::LoopProcess(system); }).detach();
+ kernel.RunOnHostCoreProcess("FS", [&] { FileSystem::LoopProcess(system); }).detach();
+ kernel.RunOnHostCoreProcess("jit", [&] { JIT::LoopProcess(system); }).detach();
+ kernel.RunOnHostCoreProcess("ldn", [&] { LDN::LoopProcess(system); }).detach();
+ kernel.RunOnHostCoreProcess("Loader", [&] { LDR::LoopProcess(system); }).detach();
+ kernel.RunOnHostCoreProcess("nvservices", [&] { Nvidia::LoopProcess(system); }).detach();
+ kernel.RunOnHostCoreProcess("bsdsocket", [&] { Sockets::LoopProcess(system); }).detach();
+ kernel.RunOnHostCoreProcess("vi", [&, token] { VI::LoopProcess(system, token); }).detach();
+
+ kernel.RunOnGuestCoreProcess("sm", [&] { SM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("account", [&] { Account::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("am", [&] { AM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("aoc", [&] { AOC::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("apm", [&] { APM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("bcat", [&] { BCAT::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("bpc", [&] { BPC::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("btdrv", [&] { BtDrv::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("btm", [&] { BTM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("capsrv", [&] { Capture::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("erpt", [&] { ERPT::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("es", [&] { ES::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("eupld", [&] { EUPLD::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("fatal", [&] { Fatal::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("fgm", [&] { FGM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("friends", [&] { Friend::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("settings", [&] { Set::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("psc", [&] { PSC::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("glue", [&] { Glue::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("grc", [&] { GRC::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("hid", [&] { HID::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("lbl", [&] { LBL::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("LogManager.Prod", [&] { LM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("mig", [&] { Migration::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("mii", [&] { Mii::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("mm", [&] { MM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("mnpp", [&] { MNPP::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("nvnflinger", [&] { Nvnflinger::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("NCM", [&] { NCM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("nfc", [&] { NFC::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("nfp", [&] { NFP::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("ngc", [&] { NGC::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("nifm", [&] { NIFM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("nim", [&] { NIM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("npns", [&] { NPNS::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("ns", [&] { NS::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("olsc", [&] { OLSC::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("omm", [&] { OMM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("pcie", [&] { PCIe::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("pctl", [&] { PCTL::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("pcv", [&] { PCV::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("prepo", [&] { PlayReport::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("ProcessManager", [&] { PM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("ptm", [&] { PTM::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("ro", [&] { RO::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("spl", [&] { SPL::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("ssl", [&] { SSL::LoopProcess(system); });
+ kernel.RunOnGuestCoreProcess("usb", [&] { USB::LoopProcess(system); });
+ // clang-format on
+}
+
+Services::~Services() = default;
+
+} // namespace Service
diff --git a/src/core/hle/service/services.h b/src/core/hle/service/services.h
new file mode 100644
index 000000000..a99fa1e53
--- /dev/null
+++ b/src/core/hle/service/services.h
@@ -0,0 +1,22 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "common/polyfill_thread.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service {
+
+/**
+ * The purpose of this class is to own any objects that need to be shared across the other service
+ * implementations. Will be torn down when the global system instance is shutdown.
+ */
+class Services final {
+public:
+ explicit Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system,
+ std::stop_token token);
+ ~Services();
+};
+
+} // namespace Service
diff --git a/src/core/hle/service/set/setting_formats/system_settings.h b/src/core/hle/service/set/setting_formats/system_settings.h
index 40230182a..a5b1552a5 100644
--- a/src/core/hle/service/set/setting_formats/system_settings.h
+++ b/src/core/hle/service/set/setting_formats/system_settings.h
@@ -244,7 +244,7 @@ struct SystemSettings {
INSERT_PADDING_BYTES(0x60); // Reserved
// nn::settings::system::AccountNotificationSettings
- u32 account_notification_settings_count;
+ s32 account_notification_settings_count;
INSERT_PADDING_BYTES(0xC); // Reserved
std::array<AccountNotificationSettings, 8> account_notification_settings;
INSERT_PADDING_BYTES(0x140); // Reserved
@@ -308,7 +308,7 @@ struct SystemSettings {
INSERT_PADDING_BYTES(0x34); // Reserved
// nn::settings::system::EulaVersion
- u32 eula_version_count;
+ s32 eula_version_count;
INSERT_PADDING_BYTES(0xC); // Reserved
std::array<EulaVersion, 32> eula_versions;
INSERT_PADDING_BYTES(0x200); // Reserved
diff --git a/src/core/hle/service/set/settings_types.h b/src/core/hle/service/set/settings_types.h
index 83ef6635b..29664e88c 100644
--- a/src/core/hle/service/set/settings_types.h
+++ b/src/core/hle/service/set/settings_types.h
@@ -12,6 +12,7 @@
#include "core/hle/service/psc/time/common.h"
namespace Service::Set {
+using SettingItemName = std::array<u8, 0x48>;
/// This is nn::settings::system::AudioOutputMode
enum class AudioOutputMode : u32 {
@@ -413,16 +414,18 @@ struct FirmwareVersionFormat {
u8 major;
u8 minor;
u8 micro;
- INSERT_PADDING_BYTES(1);
+ INSERT_PADDING_BYTES_NOINIT(1);
u8 revision_major;
u8 revision_minor;
- INSERT_PADDING_BYTES(2);
+ INSERT_PADDING_BYTES_NOINIT(2);
std::array<char, 0x20> platform;
std::array<u8, 0x40> version_hash;
std::array<char, 0x18> display_version;
std::array<char, 0x80> display_title;
};
static_assert(sizeof(FirmwareVersionFormat) == 0x100, "FirmwareVersionFormat is an invalid size");
+static_assert(std::is_trivial_v<FirmwareVersionFormat>,
+ "FirmwareVersionFormat type must be trivially copyable.");
/// This is nn::settings::system::HomeMenuScheme
struct HomeMenuScheme {
diff --git a/src/core/hle/service/set/system_settings_server.cpp b/src/core/hle/service/set/system_settings_server.cpp
index 7ef4a0ded..93925f783 100644
--- a/src/core/hle/service/set/system_settings_server.cpp
+++ b/src/core/hle/service/set/system_settings_server.cpp
@@ -17,6 +17,7 @@
#include "core/file_sys/registered_cache.h"
#include "core/file_sys/romfs.h"
#include "core/file_sys/system_archive/system_archive.h"
+#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/set/settings_server.h"
@@ -91,83 +92,83 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
: ServiceFramework{system_, "set:sys"}, m_system{system} {
// clang-format off
static const FunctionInfo functions[] = {
- {0, &ISystemSettingsServer::SetLanguageCode, "SetLanguageCode"},
+ {0, C<&ISystemSettingsServer::SetLanguageCode>, "SetLanguageCode"},
{1, nullptr, "SetNetworkSettings"},
{2, nullptr, "GetNetworkSettings"},
- {3, &ISystemSettingsServer::GetFirmwareVersion, "GetFirmwareVersion"},
- {4, &ISystemSettingsServer::GetFirmwareVersion2, "GetFirmwareVersion2"},
+ {3, C<&ISystemSettingsServer::GetFirmwareVersion>, "GetFirmwareVersion"},
+ {4, C<&ISystemSettingsServer::GetFirmwareVersion2>, "GetFirmwareVersion2"},
{5, nullptr, "GetFirmwareVersionDigest"},
- {7, &ISystemSettingsServer::GetLockScreenFlag, "GetLockScreenFlag"},
- {8, &ISystemSettingsServer::SetLockScreenFlag, "SetLockScreenFlag"},
+ {7, C<&ISystemSettingsServer::GetLockScreenFlag>, "GetLockScreenFlag"},
+ {8, C<&ISystemSettingsServer::SetLockScreenFlag>, "SetLockScreenFlag"},
{9, nullptr, "GetBacklightSettings"},
{10, nullptr, "SetBacklightSettings"},
{11, nullptr, "SetBluetoothDevicesSettings"},
{12, nullptr, "GetBluetoothDevicesSettings"},
- {13, &ISystemSettingsServer::GetExternalSteadyClockSourceId, "GetExternalSteadyClockSourceId"},
- {14, &ISystemSettingsServer::SetExternalSteadyClockSourceId, "SetExternalSteadyClockSourceId"},
- {15, &ISystemSettingsServer::GetUserSystemClockContext, "GetUserSystemClockContext"},
- {16, &ISystemSettingsServer::SetUserSystemClockContext, "SetUserSystemClockContext"},
- {17, &ISystemSettingsServer::GetAccountSettings, "GetAccountSettings"},
- {18, &ISystemSettingsServer::SetAccountSettings, "SetAccountSettings"},
+ {13, C<&ISystemSettingsServer::GetExternalSteadyClockSourceId>, "GetExternalSteadyClockSourceId"},
+ {14, C<&ISystemSettingsServer::SetExternalSteadyClockSourceId>, "SetExternalSteadyClockSourceId"},
+ {15, C<&ISystemSettingsServer::GetUserSystemClockContext>, "GetUserSystemClockContext"},
+ {16, C<&ISystemSettingsServer::SetUserSystemClockContext>, "SetUserSystemClockContext"},
+ {17, C<&ISystemSettingsServer::GetAccountSettings>, "GetAccountSettings"},
+ {18, C<&ISystemSettingsServer::SetAccountSettings>, "SetAccountSettings"},
{19, nullptr, "GetAudioVolume"},
{20, nullptr, "SetAudioVolume"},
- {21, &ISystemSettingsServer::GetEulaVersions, "GetEulaVersions"},
- {22, &ISystemSettingsServer::SetEulaVersions, "SetEulaVersions"},
- {23, &ISystemSettingsServer::GetColorSetId, "GetColorSetId"},
- {24, &ISystemSettingsServer::SetColorSetId, "SetColorSetId"},
+ {21, C<&ISystemSettingsServer::GetEulaVersions>, "GetEulaVersions"},
+ {22, C<&ISystemSettingsServer::SetEulaVersions>, "SetEulaVersions"},
+ {23, C<&ISystemSettingsServer::GetColorSetId>, "GetColorSetId"},
+ {24, C<&ISystemSettingsServer::SetColorSetId>, "SetColorSetId"},
{25, nullptr, "GetConsoleInformationUploadFlag"},
{26, nullptr, "SetConsoleInformationUploadFlag"},
{27, nullptr, "GetAutomaticApplicationDownloadFlag"},
{28, nullptr, "SetAutomaticApplicationDownloadFlag"},
- {29, &ISystemSettingsServer::GetNotificationSettings, "GetNotificationSettings"},
- {30, &ISystemSettingsServer::SetNotificationSettings, "SetNotificationSettings"},
- {31, &ISystemSettingsServer::GetAccountNotificationSettings, "GetAccountNotificationSettings"},
- {32, &ISystemSettingsServer::SetAccountNotificationSettings, "SetAccountNotificationSettings"},
- {35, &ISystemSettingsServer::GetVibrationMasterVolume, "GetVibrationMasterVolume"},
- {36, &ISystemSettingsServer::SetVibrationMasterVolume, "SetVibrationMasterVolume"},
- {37, &ISystemSettingsServer::GetSettingsItemValueSize, "GetSettingsItemValueSize"},
- {38, &ISystemSettingsServer::GetSettingsItemValue, "GetSettingsItemValue"},
- {39, &ISystemSettingsServer::GetTvSettings, "GetTvSettings"},
- {40, &ISystemSettingsServer::SetTvSettings, "SetTvSettings"},
+ {29, C<&ISystemSettingsServer::GetNotificationSettings>, "GetNotificationSettings"},
+ {30, C<&ISystemSettingsServer::SetNotificationSettings>, "SetNotificationSettings"},
+ {31, C<&ISystemSettingsServer::GetAccountNotificationSettings>, "GetAccountNotificationSettings"},
+ {32, C<&ISystemSettingsServer::SetAccountNotificationSettings>, "SetAccountNotificationSettings"},
+ {35, C<&ISystemSettingsServer::GetVibrationMasterVolume>, "GetVibrationMasterVolume"},
+ {36, C<&ISystemSettingsServer::SetVibrationMasterVolume>, "SetVibrationMasterVolume"},
+ {37, C<&ISystemSettingsServer::GetSettingsItemValueSize>, "GetSettingsItemValueSize"},
+ {38, C<&ISystemSettingsServer::GetSettingsItemValue>, "GetSettingsItemValue"},
+ {39, C<&ISystemSettingsServer::GetTvSettings>, "GetTvSettings"},
+ {40, C<&ISystemSettingsServer::SetTvSettings>, "SetTvSettings"},
{41, nullptr, "GetEdid"},
{42, nullptr, "SetEdid"},
- {43, &ISystemSettingsServer::GetAudioOutputMode, "GetAudioOutputMode"},
- {44, &ISystemSettingsServer::SetAudioOutputMode, "SetAudioOutputMode"},
- {45, &ISystemSettingsServer::GetSpeakerAutoMuteFlag , "GetSpeakerAutoMuteFlag"},
- {46, &ISystemSettingsServer::SetSpeakerAutoMuteFlag , "SetSpeakerAutoMuteFlag"},
- {47, &ISystemSettingsServer::GetQuestFlag, "GetQuestFlag"},
- {48, &ISystemSettingsServer::SetQuestFlag, "SetQuestFlag"},
+ {43, C<&ISystemSettingsServer::GetAudioOutputMode>, "GetAudioOutputMode"},
+ {44, C<&ISystemSettingsServer::SetAudioOutputMode>, "SetAudioOutputMode"},
+ {45, C<&ISystemSettingsServer::GetSpeakerAutoMuteFlag> , "GetSpeakerAutoMuteFlag"},
+ {46, C<&ISystemSettingsServer::SetSpeakerAutoMuteFlag> , "SetSpeakerAutoMuteFlag"},
+ {47, C<&ISystemSettingsServer::GetQuestFlag>, "GetQuestFlag"},
+ {48, C<&ISystemSettingsServer::SetQuestFlag>, "SetQuestFlag"},
{49, nullptr, "GetDataDeletionSettings"},
{50, nullptr, "SetDataDeletionSettings"},
{51, nullptr, "GetInitialSystemAppletProgramId"},
{52, nullptr, "GetOverlayDispProgramId"},
- {53, &ISystemSettingsServer::GetDeviceTimeZoneLocationName, "GetDeviceTimeZoneLocationName"},
- {54, &ISystemSettingsServer::SetDeviceTimeZoneLocationName, "SetDeviceTimeZoneLocationName"},
+ {53, C<&ISystemSettingsServer::GetDeviceTimeZoneLocationName>, "GetDeviceTimeZoneLocationName"},
+ {54, C<&ISystemSettingsServer::SetDeviceTimeZoneLocationName>, "SetDeviceTimeZoneLocationName"},
{55, nullptr, "GetWirelessCertificationFileSize"},
{56, nullptr, "GetWirelessCertificationFile"},
- {57, &ISystemSettingsServer::SetRegionCode, "SetRegionCode"},
- {58, &ISystemSettingsServer::GetNetworkSystemClockContext, "GetNetworkSystemClockContext"},
- {59, &ISystemSettingsServer::SetNetworkSystemClockContext, "SetNetworkSystemClockContext"},
- {60, &ISystemSettingsServer::IsUserSystemClockAutomaticCorrectionEnabled, "IsUserSystemClockAutomaticCorrectionEnabled"},
- {61, &ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionEnabled, "SetUserSystemClockAutomaticCorrectionEnabled"},
- {62, &ISystemSettingsServer::GetDebugModeFlag, "GetDebugModeFlag"},
- {63, &ISystemSettingsServer::GetPrimaryAlbumStorage, "GetPrimaryAlbumStorage"},
- {64, &ISystemSettingsServer::SetPrimaryAlbumStorage, "SetPrimaryAlbumStorage"},
+ {57, C<&ISystemSettingsServer::SetRegionCode>, "SetRegionCode"},
+ {58, C<&ISystemSettingsServer::GetNetworkSystemClockContext>, "GetNetworkSystemClockContext"},
+ {59, C<&ISystemSettingsServer::SetNetworkSystemClockContext>, "SetNetworkSystemClockContext"},
+ {60, C<&ISystemSettingsServer::IsUserSystemClockAutomaticCorrectionEnabled>, "IsUserSystemClockAutomaticCorrectionEnabled"},
+ {61, C<&ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionEnabled>, "SetUserSystemClockAutomaticCorrectionEnabled"},
+ {62, C<&ISystemSettingsServer::GetDebugModeFlag>, "GetDebugModeFlag"},
+ {63, C<&ISystemSettingsServer::GetPrimaryAlbumStorage>, "GetPrimaryAlbumStorage"},
+ {64, C<&ISystemSettingsServer::SetPrimaryAlbumStorage>, "SetPrimaryAlbumStorage"},
{65, nullptr, "GetUsb30EnableFlag"},
{66, nullptr, "SetUsb30EnableFlag"},
- {67, &ISystemSettingsServer::GetBatteryLot, "GetBatteryLot"},
- {68, &ISystemSettingsServer::GetSerialNumber, "GetSerialNumber"},
- {69, &ISystemSettingsServer::GetNfcEnableFlag, "GetNfcEnableFlag"},
- {70, &ISystemSettingsServer::SetNfcEnableFlag, "SetNfcEnableFlag"},
- {71, &ISystemSettingsServer::GetSleepSettings, "GetSleepSettings"},
- {72, &ISystemSettingsServer::SetSleepSettings, "SetSleepSettings"},
- {73, &ISystemSettingsServer::GetWirelessLanEnableFlag, "GetWirelessLanEnableFlag"},
- {74, &ISystemSettingsServer::SetWirelessLanEnableFlag, "SetWirelessLanEnableFlag"},
- {75, &ISystemSettingsServer::GetInitialLaunchSettings, "GetInitialLaunchSettings"},
- {76, &ISystemSettingsServer::SetInitialLaunchSettings, "SetInitialLaunchSettings"},
- {77, &ISystemSettingsServer::GetDeviceNickName, "GetDeviceNickName"},
- {78, &ISystemSettingsServer::SetDeviceNickName, "SetDeviceNickName"},
- {79, &ISystemSettingsServer::GetProductModel, "GetProductModel"},
+ {67, C<&ISystemSettingsServer::GetBatteryLot>, "GetBatteryLot"},
+ {68, C<&ISystemSettingsServer::GetSerialNumber>, "GetSerialNumber"},
+ {69, C<&ISystemSettingsServer::GetNfcEnableFlag>, "GetNfcEnableFlag"},
+ {70, C<&ISystemSettingsServer::SetNfcEnableFlag>, "SetNfcEnableFlag"},
+ {71, C<&ISystemSettingsServer::GetSleepSettings>, "GetSleepSettings"},
+ {72, C<&ISystemSettingsServer::SetSleepSettings>, "SetSleepSettings"},
+ {73, C<&ISystemSettingsServer::GetWirelessLanEnableFlag>, "GetWirelessLanEnableFlag"},
+ {74, C<&ISystemSettingsServer::SetWirelessLanEnableFlag>, "SetWirelessLanEnableFlag"},
+ {75, C<&ISystemSettingsServer::GetInitialLaunchSettings>, "GetInitialLaunchSettings"},
+ {76, C<&ISystemSettingsServer::SetInitialLaunchSettings>, "SetInitialLaunchSettings"},
+ {77, C<&ISystemSettingsServer::GetDeviceNickName>, "GetDeviceNickName"},
+ {78, C<&ISystemSettingsServer::SetDeviceNickName>, "SetDeviceNickName"},
+ {79, C<&ISystemSettingsServer::GetProductModel>, "GetProductModel"},
{80, nullptr, "GetLdnChannel"},
{81, nullptr, "SetLdnChannel"},
{82, nullptr, "AcquireTelemetryDirtyFlagEventHandle"},
@@ -176,25 +177,25 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{85, nullptr, "SetPtmBatteryLot"},
{86, nullptr, "GetPtmFuelGaugeParameter"},
{87, nullptr, "SetPtmFuelGaugeParameter"},
- {88, &ISystemSettingsServer::GetBluetoothEnableFlag, "GetBluetoothEnableFlag"},
- {89, &ISystemSettingsServer::SetBluetoothEnableFlag, "SetBluetoothEnableFlag"},
- {90, &ISystemSettingsServer::GetMiiAuthorId, "GetMiiAuthorId"},
+ {88, C<&ISystemSettingsServer::GetBluetoothEnableFlag>, "GetBluetoothEnableFlag"},
+ {89, C<&ISystemSettingsServer::SetBluetoothEnableFlag>, "SetBluetoothEnableFlag"},
+ {90, C<&ISystemSettingsServer::GetMiiAuthorId>, "GetMiiAuthorId"},
{91, nullptr, "SetShutdownRtcValue"},
{92, nullptr, "GetShutdownRtcValue"},
{93, nullptr, "AcquireFatalDirtyFlagEventHandle"},
{94, nullptr, "GetFatalDirtyFlags"},
- {95, &ISystemSettingsServer::GetAutoUpdateEnableFlag, "GetAutoUpdateEnableFlag"},
- {96, &ISystemSettingsServer::SetAutoUpdateEnableFlag, "SetAutoUpdateEnableFlag"},
+ {95, C<&ISystemSettingsServer::GetAutoUpdateEnableFlag>, "GetAutoUpdateEnableFlag"},
+ {96, C<&ISystemSettingsServer::SetAutoUpdateEnableFlag>, "SetAutoUpdateEnableFlag"},
{97, nullptr, "GetNxControllerSettings"},
{98, nullptr, "SetNxControllerSettings"},
- {99, &ISystemSettingsServer::GetBatteryPercentageFlag, "GetBatteryPercentageFlag"},
- {100, &ISystemSettingsServer::SetBatteryPercentageFlag, "SetBatteryPercentageFlag"},
+ {99, C<&ISystemSettingsServer::GetBatteryPercentageFlag>, "GetBatteryPercentageFlag"},
+ {100, C<&ISystemSettingsServer::SetBatteryPercentageFlag>, "SetBatteryPercentageFlag"},
{101, nullptr, "GetExternalRtcResetFlag"},
{102, nullptr, "SetExternalRtcResetFlag"},
{103, nullptr, "GetUsbFullKeyEnableFlag"},
{104, nullptr, "SetUsbFullKeyEnableFlag"},
- {105, &ISystemSettingsServer::SetExternalSteadyClockInternalOffset, "SetExternalSteadyClockInternalOffset"},
- {106, &ISystemSettingsServer::GetExternalSteadyClockInternalOffset, "GetExternalSteadyClockInternalOffset"},
+ {105, C<&ISystemSettingsServer::SetExternalSteadyClockInternalOffset>, "SetExternalSteadyClockInternalOffset"},
+ {106, C<&ISystemSettingsServer::GetExternalSteadyClockInternalOffset>, "GetExternalSteadyClockInternalOffset"},
{107, nullptr, "GetBacklightSettingsEx"},
{108, nullptr, "SetBacklightSettingsEx"},
{109, nullptr, "GetHeadphoneVolumeWarningCount"},
@@ -208,14 +209,14 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{117, nullptr, "GetHeadphoneVolumeUpdateFlag"},
{118, nullptr, "SetHeadphoneVolumeUpdateFlag"},
{119, nullptr, "NeedsToUpdateHeadphoneVolume"},
- {120, &ISystemSettingsServer::GetPushNotificationActivityModeOnSleep, "GetPushNotificationActivityModeOnSleep"},
- {121, &ISystemSettingsServer::SetPushNotificationActivityModeOnSleep, "SetPushNotificationActivityModeOnSleep"},
+ {120, C<&ISystemSettingsServer::GetPushNotificationActivityModeOnSleep>, "GetPushNotificationActivityModeOnSleep"},
+ {121, C<&ISystemSettingsServer::SetPushNotificationActivityModeOnSleep>, "SetPushNotificationActivityModeOnSleep"},
{122, nullptr, "GetServiceDiscoveryControlSettings"},
{123, nullptr, "SetServiceDiscoveryControlSettings"},
- {124, &ISystemSettingsServer::GetErrorReportSharePermission, "GetErrorReportSharePermission"},
- {125, &ISystemSettingsServer::SetErrorReportSharePermission, "SetErrorReportSharePermission"},
- {126, &ISystemSettingsServer::GetAppletLaunchFlags, "GetAppletLaunchFlags"},
- {127, &ISystemSettingsServer::SetAppletLaunchFlags, "SetAppletLaunchFlags"},
+ {124, C<&ISystemSettingsServer::GetErrorReportSharePermission>, "GetErrorReportSharePermission"},
+ {125, C<&ISystemSettingsServer::SetErrorReportSharePermission>, "SetErrorReportSharePermission"},
+ {126, C<&ISystemSettingsServer::GetAppletLaunchFlags>, "GetAppletLaunchFlags"},
+ {127, C<&ISystemSettingsServer::SetAppletLaunchFlags>, "SetAppletLaunchFlags"},
{128, nullptr, "GetConsoleSixAxisSensorAccelerationBias"},
{129, nullptr, "SetConsoleSixAxisSensorAccelerationBias"},
{130, nullptr, "GetConsoleSixAxisSensorAngularVelocityBias"},
@@ -224,8 +225,8 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{133, nullptr, "SetConsoleSixAxisSensorAccelerationGain"},
{134, nullptr, "GetConsoleSixAxisSensorAngularVelocityGain"},
{135, nullptr, "SetConsoleSixAxisSensorAngularVelocityGain"},
- {136, &ISystemSettingsServer::GetKeyboardLayout, "GetKeyboardLayout"},
- {137, &ISystemSettingsServer::SetKeyboardLayout, "SetKeyboardLayout"},
+ {136, C<&ISystemSettingsServer::GetKeyboardLayout>, "GetKeyboardLayout"},
+ {137, C<&ISystemSettingsServer::SetKeyboardLayout>, "SetKeyboardLayout"},
{138, nullptr, "GetWebInspectorFlag"},
{139, nullptr, "GetAllowedSslHosts"},
{140, nullptr, "GetHostFsMountPoint"},
@@ -238,10 +239,10 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{147, nullptr, "GetConsoleSixAxisSensorAngularAcceleration"},
{148, nullptr, "SetConsoleSixAxisSensorAngularAcceleration"},
{149, nullptr, "GetRebootlessSystemUpdateVersion"},
- {150, &ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime, "GetDeviceTimeZoneLocationUpdatedTime"},
- {151, &ISystemSettingsServer::SetDeviceTimeZoneLocationUpdatedTime, "SetDeviceTimeZoneLocationUpdatedTime"},
- {152, &ISystemSettingsServer::GetUserSystemClockAutomaticCorrectionUpdatedTime, "GetUserSystemClockAutomaticCorrectionUpdatedTime"},
- {153, &ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionUpdatedTime, "SetUserSystemClockAutomaticCorrectionUpdatedTime"},
+ {150, C<&ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime>, "GetDeviceTimeZoneLocationUpdatedTime"},
+ {151, C<&ISystemSettingsServer::SetDeviceTimeZoneLocationUpdatedTime>, "SetDeviceTimeZoneLocationUpdatedTime"},
+ {152, C<&ISystemSettingsServer::GetUserSystemClockAutomaticCorrectionUpdatedTime>, "GetUserSystemClockAutomaticCorrectionUpdatedTime"},
+ {153, C<&ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionUpdatedTime>, "SetUserSystemClockAutomaticCorrectionUpdatedTime"},
{154, nullptr, "GetAccountOnlineStorageSettings"},
{155, nullptr, "SetAccountOnlineStorageSettings"},
{156, nullptr, "GetPctlReadyFlag"},
@@ -258,11 +259,11 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{167, nullptr, "SetUsb30DeviceEnableFlag"},
{168, nullptr, "GetThemeId"},
{169, nullptr, "SetThemeId"},
- {170, &ISystemSettingsServer::GetChineseTraditionalInputMethod, "GetChineseTraditionalInputMethod"},
+ {170, C<&ISystemSettingsServer::GetChineseTraditionalInputMethod>, "GetChineseTraditionalInputMethod"},
{171, nullptr, "SetChineseTraditionalInputMethod"},
{172, nullptr, "GetPtmCycleCountReliability"},
{173, nullptr, "SetPtmCycleCountReliability"},
- {174, &ISystemSettingsServer::GetHomeMenuScheme, "GetHomeMenuScheme"},
+ {174, C<&ISystemSettingsServer::GetHomeMenuScheme>, "GetHomeMenuScheme"},
{175, nullptr, "GetThemeSettings"},
{176, nullptr, "SetThemeSettings"},
{177, nullptr, "GetThemeKey"},
@@ -273,10 +274,10 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{182, nullptr, "SetT"},
{183, nullptr, "GetPlatformRegion"},
{184, nullptr, "SetPlatformRegion"},
- {185, &ISystemSettingsServer::GetHomeMenuSchemeModel, "GetHomeMenuSchemeModel"},
+ {185, C<&ISystemSettingsServer::GetHomeMenuSchemeModel>, "GetHomeMenuSchemeModel"},
{186, nullptr, "GetMemoryUsageRateFlag"},
- {187, &ISystemSettingsServer::GetTouchScreenMode, "GetTouchScreenMode"},
- {188, &ISystemSettingsServer::SetTouchScreenMode, "SetTouchScreenMode"},
+ {187, C<&ISystemSettingsServer::GetTouchScreenMode>, "GetTouchScreenMode"},
+ {188, C<&ISystemSettingsServer::SetTouchScreenMode>, "SetTouchScreenMode"},
{189, nullptr, "GetButtonConfigSettingsFull"},
{190, nullptr, "SetButtonConfigSettingsFull"},
{191, nullptr, "GetButtonConfigSettingsEmbedded"},
@@ -289,10 +290,10 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{198, nullptr, "SetButtonConfigRegisteredSettingsEmbedded"},
{199, nullptr, "GetButtonConfigRegisteredSettings"},
{200, nullptr, "SetButtonConfigRegisteredSettings"},
- {201, &ISystemSettingsServer::GetFieldTestingFlag, "GetFieldTestingFlag"},
+ {201, C<&ISystemSettingsServer::GetFieldTestingFlag>, "GetFieldTestingFlag"},
{202, nullptr, "SetFieldTestingFlag"},
- {203, &ISystemSettingsServer::GetPanelCrcMode, "GetPanelCrcMode"},
- {204, &ISystemSettingsServer::SetPanelCrcMode, "SetPanelCrcMode"},
+ {203, C<&ISystemSettingsServer::GetPanelCrcMode>, "GetPanelCrcMode"},
+ {204, C<&ISystemSettingsServer::SetPanelCrcMode>, "SetPanelCrcMode"},
{205, nullptr, "GetNxControllerSettingsEx"},
{206, nullptr, "SetNxControllerSettingsEx"},
{207, nullptr, "GetHearingProtectionSafeguardFlag"},
@@ -422,178 +423,134 @@ bool ISystemSettingsServer::StoreSettingsFile(std::filesystem::path& path, auto&
return true;
}
-void ISystemSettingsServer::SetLanguageCode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.language_code = rp.PopEnum<LanguageCode>();
- SetSaveNeeded();
-
- LOG_INFO(Service_SET, "called, language_code={}", m_system_settings.language_code);
+Result ISystemSettingsServer::SetLanguageCode(LanguageCode language_code) {
+ LOG_INFO(Service_SET, "called, language_code={}", language_code);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.language_code = language_code;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetFirmwareVersion(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetFirmwareVersion(
+ OutLargeData<FirmwareVersionFormat, BufferAttr_HipcPointer> out_firmware_data) {
LOG_DEBUG(Service_SET, "called");
- FirmwareVersionFormat firmware_data{};
- const auto result =
- GetFirmwareVersionImpl(firmware_data, system, GetFirmwareVersionType::Version1);
-
- if (result.IsSuccess()) {
- ctx.WriteBuffer(firmware_data);
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
+ R_RETURN(GetFirmwareVersionImpl(*out_firmware_data, system, GetFirmwareVersionType::Version1));
}
-void ISystemSettingsServer::GetFirmwareVersion2(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetFirmwareVersion2(
+ OutLargeData<FirmwareVersionFormat, BufferAttr_HipcPointer> out_firmware_data) {
LOG_DEBUG(Service_SET, "called");
- FirmwareVersionFormat firmware_data{};
- const auto result =
- GetFirmwareVersionImpl(firmware_data, system, GetFirmwareVersionType::Version2);
-
- if (result.IsSuccess()) {
- ctx.WriteBuffer(firmware_data);
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
+ R_RETURN(GetFirmwareVersionImpl(*out_firmware_data, system, GetFirmwareVersionType::Version2));
}
-void ISystemSettingsServer::GetExternalSteadyClockSourceId(HLERequestContext& ctx) {
- LOG_INFO(Service_SET, "called");
-
- Common::UUID id{};
- const auto res = GetExternalSteadyClockSourceId(id);
+Result ISystemSettingsServer::GetLockScreenFlag(Out<bool> out_lock_screen_flag) {
+ LOG_INFO(Service_SET, "called, lock_screen_flag={}", m_system_settings.lock_screen_flag);
- IPC::ResponseBuilder rb{ctx, 2 + sizeof(Common::UUID) / sizeof(u32)};
- rb.Push(res);
- rb.PushRaw(id);
+ *out_lock_screen_flag = m_system_settings.lock_screen_flag;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetExternalSteadyClockSourceId(HLERequestContext& ctx) {
- LOG_INFO(Service_SET, "called");
+Result ISystemSettingsServer::SetLockScreenFlag(bool lock_screen_flag) {
+ LOG_INFO(Service_SET, "called, lock_screen_flag={}", lock_screen_flag);
- IPC::RequestParser rp{ctx};
- const auto id{rp.PopRaw<Common::UUID>()};
+ m_system_settings.lock_screen_flag = lock_screen_flag;
+ SetSaveNeeded();
+ R_SUCCEED();
+}
- const auto res = SetExternalSteadyClockSourceId(id);
+Result ISystemSettingsServer::GetExternalSteadyClockSourceId(
+ Out<Common::UUID> out_clock_source_id) {
+ LOG_INFO(Service_SET, "called, clock_source_id={}",
+ m_private_settings.external_clock_source_id.FormattedString());
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
+ *out_clock_source_id = m_private_settings.external_clock_source_id;
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetUserSystemClockContext(HLERequestContext& ctx) {
- LOG_INFO(Service_SET, "called");
-
- Service::PSC::Time::SystemClockContext context{};
- const auto res = GetUserSystemClockContext(context);
+Result ISystemSettingsServer::SetExternalSteadyClockSourceId(const Common::UUID& clock_source_id) {
+ LOG_INFO(Service_SET, "called, clock_source_id={}", clock_source_id.FormattedString());
- IPC::ResponseBuilder rb{ctx, 2 + sizeof(Service::PSC::Time::SystemClockContext) / sizeof(u32)};
- rb.Push(res);
- rb.PushRaw(context);
+ m_private_settings.external_clock_source_id = clock_source_id;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetUserSystemClockContext(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetUserSystemClockContext(
+ Out<Service::PSC::Time::SystemClockContext> out_clock_context) {
LOG_INFO(Service_SET, "called");
- IPC::RequestParser rp{ctx};
- const auto context{rp.PopRaw<Service::PSC::Time::SystemClockContext>()};
-
- const auto res = SetUserSystemClockContext(context);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
+ *out_clock_context = m_system_settings.user_system_clock_context;
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetLockScreenFlag(HLERequestContext& ctx) {
- LOG_INFO(Service_SET, "called, lock_screen_flag={}", m_system_settings.lock_screen_flag);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(m_system_settings.lock_screen_flag);
-}
+Result ISystemSettingsServer::SetUserSystemClockContext(
+ const Service::PSC::Time::SystemClockContext& clock_context) {
+ LOG_INFO(Service_SET, "called");
-void ISystemSettingsServer::SetLockScreenFlag(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.lock_screen_flag = rp.Pop<bool>();
+ m_system_settings.user_system_clock_context = clock_context;
SetSaveNeeded();
-
- LOG_INFO(Service_SET, "called, lock_screen_flag={}", m_system_settings.lock_screen_flag);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetAccountSettings(HLERequestContext& ctx) {
- LOG_INFO(Service_SET, "called");
+Result ISystemSettingsServer::GetAccountSettings(Out<AccountSettings> out_account_settings) {
+ LOG_INFO(Service_SET, "called, account_settings_flags={}",
+ m_system_settings.account_settings.flags);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushRaw(m_system_settings.account_settings);
+ *out_account_settings = m_system_settings.account_settings;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetAccountSettings(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.account_settings = rp.PopRaw<AccountSettings>();
- SetSaveNeeded();
-
- LOG_INFO(Service_SET, "called, account_settings_flags={}",
- m_system_settings.account_settings.flags);
+Result ISystemSettingsServer::SetAccountSettings(AccountSettings account_settings) {
+ LOG_INFO(Service_SET, "called, account_settings_flags={}", account_settings.flags);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.account_settings = account_settings;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetEulaVersions(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetEulaVersions(
+ Out<s32> out_count, OutArray<EulaVersion, BufferAttr_HipcMapAlias> out_eula_versions) {
LOG_INFO(Service_SET, "called, elements={}", m_system_settings.eula_version_count);
- ctx.WriteBuffer(m_system_settings.eula_versions);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(m_system_settings.eula_version_count);
+ *out_count =
+ std::min(m_system_settings.eula_version_count, static_cast<s32>(out_eula_versions.size()));
+ memcpy(out_eula_versions.data(), m_system_settings.eula_versions.data(),
+ static_cast<std::size_t>(*out_count) * sizeof(EulaVersion));
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetEulaVersions(HLERequestContext& ctx) {
- const auto elements = ctx.GetReadBufferNumElements<EulaVersion>();
- const auto buffer_data = ctx.ReadBuffer();
+Result ISystemSettingsServer::SetEulaVersions(
+ InArray<EulaVersion, BufferAttr_HipcMapAlias> eula_versions) {
+ LOG_INFO(Service_SET, "called, elements={}", eula_versions.size());
- LOG_INFO(Service_SET, "called, elements={}", elements);
- ASSERT(elements <= m_system_settings.eula_versions.size());
+ ASSERT(eula_versions.size() <= m_system_settings.eula_versions.size());
- m_system_settings.eula_version_count = static_cast<u32>(elements);
- std::memcpy(&m_system_settings.eula_versions, buffer_data.data(),
- sizeof(EulaVersion) * elements);
+ m_system_settings.eula_version_count = static_cast<s32>(eula_versions.size());
+ std::memcpy(m_system_settings.eula_versions.data(), eula_versions.data(),
+ eula_versions.size() * sizeof(EulaVersion));
SetSaveNeeded();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetColorSetId(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetColorSetId(Out<ColorSet> out_color_set_id) {
LOG_DEBUG(Service_SET, "called, color_set=", m_system_settings.color_set_id);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushEnum(m_system_settings.color_set_id);
+ *out_color_set_id = m_system_settings.color_set_id;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetColorSetId(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.color_set_id = rp.PopEnum<ColorSet>();
- SetSaveNeeded();
-
- LOG_DEBUG(Service_SET, "called, color_set={}", m_system_settings.color_set_id);
+Result ISystemSettingsServer::SetColorSetId(ColorSet color_set_id) {
+ LOG_DEBUG(Service_SET, "called, color_set={}", color_set_id);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.color_set_id = color_set_id;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetNotificationSettings(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetNotificationSettings(
+ Out<NotificationSettings> out_notification_settings) {
LOG_INFO(Service_SET, "called, flags={}, volume={}, head_time={}:{}, tailt_time={}:{}",
m_system_settings.notification_settings.flags.raw,
m_system_settings.notification_settings.volume,
@@ -602,77 +559,67 @@ void ISystemSettingsServer::GetNotificationSettings(HLERequestContext& ctx) {
m_system_settings.notification_settings.stop_time.hour,
m_system_settings.notification_settings.stop_time.minute);
- IPC::ResponseBuilder rb{ctx, 8};
- rb.Push(ResultSuccess);
- rb.PushRaw(m_system_settings.notification_settings);
+ *out_notification_settings = m_system_settings.notification_settings;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetNotificationSettings(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.notification_settings = rp.PopRaw<NotificationSettings>();
- SetSaveNeeded();
-
+Result ISystemSettingsServer::SetNotificationSettings(
+ const NotificationSettings& notification_settings) {
LOG_INFO(Service_SET, "called, flags={}, volume={}, head_time={}:{}, tailt_time={}:{}",
- m_system_settings.notification_settings.flags.raw,
- m_system_settings.notification_settings.volume,
- m_system_settings.notification_settings.start_time.hour,
- m_system_settings.notification_settings.start_time.minute,
- m_system_settings.notification_settings.stop_time.hour,
- m_system_settings.notification_settings.stop_time.minute);
+ notification_settings.flags.raw, notification_settings.volume,
+ notification_settings.start_time.hour, notification_settings.start_time.minute,
+ notification_settings.stop_time.hour, notification_settings.stop_time.minute);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.notification_settings = notification_settings;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetAccountNotificationSettings(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetAccountNotificationSettings(
+ Out<s32> out_count, OutArray<AccountNotificationSettings, BufferAttr_HipcMapAlias>
+ out_account_notification_settings) {
LOG_INFO(Service_SET, "called, elements={}",
m_system_settings.account_notification_settings_count);
- ctx.WriteBuffer(m_system_settings.account_notification_settings);
+ *out_count = std::min(m_system_settings.account_notification_settings_count,
+ static_cast<s32>(out_account_notification_settings.size()));
+ memcpy(out_account_notification_settings.data(),
+ m_system_settings.account_notification_settings.data(),
+ static_cast<std::size_t>(*out_count) * sizeof(AccountNotificationSettings));
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(m_system_settings.account_notification_settings_count);
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetAccountNotificationSettings(HLERequestContext& ctx) {
- const auto elements = ctx.GetReadBufferNumElements<AccountNotificationSettings>();
- const auto buffer_data = ctx.ReadBuffer();
-
- LOG_INFO(Service_SET, "called, elements={}", elements);
+Result ISystemSettingsServer::SetAccountNotificationSettings(
+ InArray<AccountNotificationSettings, BufferAttr_HipcMapAlias> account_notification_settings) {
+ LOG_INFO(Service_SET, "called, elements={}", account_notification_settings.size());
- ASSERT(elements <= m_system_settings.account_notification_settings.size());
+ ASSERT(account_notification_settings.size() <=
+ m_system_settings.account_notification_settings.size());
- m_system_settings.account_notification_settings_count = static_cast<u32>(elements);
- std::memcpy(&m_system_settings.account_notification_settings, buffer_data.data(),
- elements * sizeof(AccountNotificationSettings));
+ m_system_settings.account_notification_settings_count =
+ static_cast<s32>(account_notification_settings.size());
+ std::memcpy(m_system_settings.account_notification_settings.data(),
+ account_notification_settings.data(),
+ account_notification_settings.size() * sizeof(AccountNotificationSettings));
SetSaveNeeded();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetVibrationMasterVolume(HLERequestContext& ctx) {
- f32 vibration_master_volume = {};
- const auto result = GetVibrationMasterVolume(vibration_master_volume);
+Result ISystemSettingsServer::GetVibrationMasterVolume(Out<f32> vibration_master_volume) {
+ LOG_INFO(Service_SET, "called, vibration_master_volume={}",
+ m_system_settings.vibration_master_volume);
- LOG_INFO(Service_SET, "called, master_volume={}", vibration_master_volume);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(result);
- rb.Push(vibration_master_volume);
+ *vibration_master_volume = m_system_settings.vibration_master_volume;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetVibrationMasterVolume(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto vibration_master_volume = rp.PopRaw<f32>();
-
- LOG_INFO(Service_SET, "called, elements={}", m_system_settings.vibration_master_volume);
+Result ISystemSettingsServer::SetVibrationMasterVolume(f32 vibration_master_volume) {
+ LOG_INFO(Service_SET, "called, vibration_master_volume={}", vibration_master_volume);
- const auto result = SetVibrationMasterVolume(vibration_master_volume);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
+ m_system_settings.vibration_master_volume = vibration_master_volume;
+ SetSaveNeeded();
+ R_SUCCEED();
}
// FIXME: implement support for the real system_settings.ini
@@ -734,55 +681,38 @@ static Settings GetSettings() {
return ret;
}
-void ISystemSettingsServer::GetSettingsItemValueSize(HLERequestContext& ctx) {
- LOG_DEBUG(Service_SET, "called");
+Result ISystemSettingsServer::GetSettingsItemValueSize(
+ Out<u64> out_size, InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_category_buffer,
+ InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_name_buffer) {
+ const std::string setting_category{Common::StringFromBuffer(*setting_category_buffer)};
+ const std::string setting_name{Common::StringFromBuffer(*setting_name_buffer)};
- // The category of the setting. This corresponds to the top-level keys of
- // system_settings.ini.
- const auto setting_category_buf{ctx.ReadBuffer(0)};
- const std::string setting_category{Common::StringFromBuffer(setting_category_buf)};
+ LOG_DEBUG(Service_SET, "called, category={}, name={}", setting_category, setting_name);
- // The name of the setting. This corresponds to the second-level keys of
- // system_settings.ini.
- const auto setting_name_buf{ctx.ReadBuffer(1)};
- const std::string setting_name{Common::StringFromBuffer(setting_name_buf)};
+ *out_size = 0;
auto settings{GetSettings()};
- u64 response_size{0};
-
if (settings.contains(setting_category) && settings[setting_category].contains(setting_name)) {
- response_size = settings[setting_category][setting_name].size();
+ *out_size = settings[setting_category][setting_name].size();
}
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(response_size == 0 ? ResultUnknown : ResultSuccess);
- rb.Push(response_size);
+ R_UNLESS(*out_size != 0, ResultUnknown);
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetSettingsItemValue(HLERequestContext& ctx) {
- // The category of the setting. This corresponds to the top-level keys of
- // system_settings.ini.
- const auto setting_category_buf{ctx.ReadBuffer(0)};
- const std::string setting_category{Common::StringFromBuffer(setting_category_buf)};
-
- // The name of the setting. This corresponds to the second-level keys of
- // system_settings.ini.
- const auto setting_name_buf{ctx.ReadBuffer(1)};
- const std::string setting_name{Common::StringFromBuffer(setting_name_buf)};
+Result ISystemSettingsServer::GetSettingsItemValue(
+ OutBuffer<BufferAttr_HipcMapAlias> out_data,
+ InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_category_buffer,
+ InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_name_buffer) {
+ const std::string setting_category{Common::StringFromBuffer(*setting_category_buffer)};
+ const std::string setting_name{Common::StringFromBuffer(*setting_name_buffer)};
- std::vector<u8> value;
- auto response = GetSettingsItemValue(value, setting_category, setting_name);
+ LOG_INFO(Service_SET, "called, category={}, name={}", setting_category, setting_name);
- LOG_INFO(Service_SET, "called. category={}, name={} -- res=0x{:X}", setting_category,
- setting_name, response.raw);
-
- ctx.WriteBuffer(value.data(), value.size());
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(response);
+ R_RETURN(GetSettingsItemValueImpl(out_data, setting_category, setting_name));
}
-void ISystemSettingsServer::GetTvSettings(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetTvSettings(Out<TvSettings> out_tv_settings) {
LOG_INFO(Service_SET,
"called, flags={}, cmu_mode={}, contrast_ratio={}, hdmi_content_type={}, "
"rgb_range={}, tv_gama={}, tv_resolution={}, tv_underscan={}",
@@ -793,371 +723,335 @@ void ISystemSettingsServer::GetTvSettings(HLERequestContext& ctx) {
m_system_settings.tv_settings.tv_resolution,
m_system_settings.tv_settings.tv_underscan);
- IPC::ResponseBuilder rb{ctx, 10};
- rb.Push(ResultSuccess);
- rb.PushRaw(m_system_settings.tv_settings);
+ *out_tv_settings = m_system_settings.tv_settings;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetTvSettings(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.tv_settings = rp.PopRaw<TvSettings>();
- SetSaveNeeded();
+Result ISystemSettingsServer::SetTvSettings(TvSettings tv_settings) {
LOG_INFO(Service_SET,
"called, flags={}, cmu_mode={}, contrast_ratio={}, hdmi_content_type={}, "
"rgb_range={}, tv_gama={}, tv_resolution={}, tv_underscan={}",
- m_system_settings.tv_settings.flags.raw, m_system_settings.tv_settings.cmu_mode,
- m_system_settings.tv_settings.contrast_ratio,
- m_system_settings.tv_settings.hdmi_content_type,
- m_system_settings.tv_settings.rgb_range, m_system_settings.tv_settings.tv_gama,
- m_system_settings.tv_settings.tv_resolution,
- m_system_settings.tv_settings.tv_underscan);
+ tv_settings.flags.raw, tv_settings.cmu_mode, tv_settings.contrast_ratio,
+ tv_settings.hdmi_content_type, tv_settings.rgb_range, tv_settings.tv_gama,
+ tv_settings.tv_resolution, tv_settings.tv_underscan);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.tv_settings = tv_settings;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetAudioOutputMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto target{rp.PopEnum<AudioOutputModeTarget>()};
-
- AudioOutputMode output_mode{};
- const auto result = GetAudioOutputMode(output_mode, target);
-
- LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
+Result ISystemSettingsServer::GetAudioOutputMode(Out<AudioOutputMode> out_output_mode,
+ AudioOutputModeTarget target) {
+ switch (target) {
+ case AudioOutputModeTarget::Hdmi:
+ *out_output_mode = m_system_settings.audio_output_mode_hdmi;
+ break;
+ case AudioOutputModeTarget::Speaker:
+ *out_output_mode = m_system_settings.audio_output_mode_speaker;
+ break;
+ case AudioOutputModeTarget::Headphone:
+ *out_output_mode = m_system_settings.audio_output_mode_headphone;
+ break;
+ case AudioOutputModeTarget::Type3:
+ *out_output_mode = m_system_settings.audio_output_mode_type3;
+ break;
+ case AudioOutputModeTarget::Type4:
+ *out_output_mode = m_system_settings.audio_output_mode_type4;
+ break;
+ default:
+ LOG_ERROR(Service_SET, "Invalid audio output mode target {}", target);
+ }
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(result);
- rb.PushEnum(output_mode);
+ LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, *out_output_mode);
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetAudioOutputMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto target{rp.PopEnum<AudioOutputModeTarget>()};
- const auto output_mode{rp.PopEnum<AudioOutputMode>()};
-
- const auto result = SetAudioOutputMode(target, output_mode);
-
+Result ISystemSettingsServer::SetAudioOutputMode(AudioOutputModeTarget target,
+ AudioOutputMode output_mode) {
LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
+ switch (target) {
+ case AudioOutputModeTarget::Hdmi:
+ m_system_settings.audio_output_mode_hdmi = output_mode;
+ break;
+ case AudioOutputModeTarget::Speaker:
+ m_system_settings.audio_output_mode_speaker = output_mode;
+ break;
+ case AudioOutputModeTarget::Headphone:
+ m_system_settings.audio_output_mode_headphone = output_mode;
+ break;
+ case AudioOutputModeTarget::Type3:
+ m_system_settings.audio_output_mode_type3 = output_mode;
+ break;
+ case AudioOutputModeTarget::Type4:
+ m_system_settings.audio_output_mode_type4 = output_mode;
+ break;
+ default:
+ LOG_ERROR(Service_SET, "Invalid audio output mode target {}", target);
+ }
+
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetSpeakerAutoMuteFlag(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetSpeakerAutoMuteFlag(
+ Out<bool> out_force_mute_on_headphone_removed) {
LOG_INFO(Service_SET, "called, force_mute_on_headphone_removed={}",
m_system_settings.force_mute_on_headphone_removed);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushRaw(m_system_settings.force_mute_on_headphone_removed);
+ *out_force_mute_on_headphone_removed = m_system_settings.force_mute_on_headphone_removed;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetSpeakerAutoMuteFlag(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.force_mute_on_headphone_removed = rp.PopRaw<bool>();
- SetSaveNeeded();
-
+Result ISystemSettingsServer::SetSpeakerAutoMuteFlag(bool force_mute_on_headphone_removed) {
LOG_INFO(Service_SET, "called, force_mute_on_headphone_removed={}",
- m_system_settings.force_mute_on_headphone_removed);
+ force_mute_on_headphone_removed);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.force_mute_on_headphone_removed = force_mute_on_headphone_removed;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetQuestFlag(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetQuestFlag(Out<QuestFlag> out_quest_flag) {
LOG_INFO(Service_SET, "called, quest_flag={}", m_system_settings.quest_flag);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushEnum(m_system_settings.quest_flag);
+ *out_quest_flag = m_system_settings.quest_flag;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetQuestFlag(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.quest_flag = rp.PopEnum<QuestFlag>();
- SetSaveNeeded();
+Result ISystemSettingsServer::SetQuestFlag(QuestFlag quest_flag) {
+ LOG_INFO(Service_SET, "called, quest_flag={}", quest_flag);
- LOG_INFO(Service_SET, "called, quest_flag={}", m_system_settings.quest_flag);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.quest_flag = quest_flag;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetDeviceTimeZoneLocationName(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetDeviceTimeZoneLocationName(
+ Out<Service::PSC::Time::LocationName> out_name) {
LOG_INFO(Service_SET, "called");
- Service::PSC::Time::LocationName name{};
- const auto res = GetDeviceTimeZoneLocationName(name);
-
- IPC::ResponseBuilder rb{ctx, 2 + sizeof(Service::PSC::Time::LocationName) / sizeof(u32)};
- rb.Push(res);
- rb.PushRaw<Service::PSC::Time::LocationName>(name);
+ *out_name = m_system_settings.device_time_zone_location_name;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetDeviceTimeZoneLocationName(HLERequestContext& ctx) {
+Result ISystemSettingsServer::SetDeviceTimeZoneLocationName(
+ const Service::PSC::Time::LocationName& name) {
LOG_INFO(Service_SET, "called");
- IPC::RequestParser rp{ctx};
- auto name{rp.PopRaw<Service::PSC::Time::LocationName>()};
-
- const auto res = SetDeviceTimeZoneLocationName(name);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
-}
-
-void ISystemSettingsServer::SetRegionCode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.region_code = rp.PopEnum<SystemRegionCode>();
+ m_system_settings.device_time_zone_location_name = name;
SetSaveNeeded();
-
- LOG_INFO(Service_SET, "called, region_code={}", m_system_settings.region_code);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetNetworkSystemClockContext(HLERequestContext& ctx) {
- LOG_INFO(Service_SET, "called");
+Result ISystemSettingsServer::SetRegionCode(SystemRegionCode region_code) {
+ LOG_INFO(Service_SET, "called, region_code={}", region_code);
- Service::PSC::Time::SystemClockContext context{};
- const auto res = GetNetworkSystemClockContext(context);
-
- IPC::ResponseBuilder rb{ctx, 2 + sizeof(Service::PSC::Time::SystemClockContext) / sizeof(u32)};
- rb.Push(res);
- rb.PushRaw(context);
+ m_system_settings.region_code = region_code;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetNetworkSystemClockContext(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetNetworkSystemClockContext(
+ Out<Service::PSC::Time::SystemClockContext> out_context) {
LOG_INFO(Service_SET, "called");
- IPC::RequestParser rp{ctx};
- const auto context{rp.PopRaw<Service::PSC::Time::SystemClockContext>()};
-
- const auto res = SetNetworkSystemClockContext(context);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
+ *out_context = m_system_settings.network_system_clock_context;
+ R_SUCCEED();
}
-void ISystemSettingsServer::IsUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx) {
+Result ISystemSettingsServer::SetNetworkSystemClockContext(
+ const Service::PSC::Time::SystemClockContext& context) {
LOG_INFO(Service_SET, "called");
- bool enabled{};
- const auto res = IsUserSystemClockAutomaticCorrectionEnabled(enabled);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(res);
- rb.PushRaw(enabled);
+ m_system_settings.network_system_clock_context = context;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx) {
- LOG_INFO(Service_SET, "called");
+Result ISystemSettingsServer::IsUserSystemClockAutomaticCorrectionEnabled(
+ Out<bool> out_automatic_correction_enabled) {
+ LOG_INFO(Service_SET, "called, out_automatic_correction_enabled={}",
+ m_system_settings.user_system_clock_automatic_correction_enabled);
- IPC::RequestParser rp{ctx};
- auto enabled{rp.Pop<bool>()};
+ *out_automatic_correction_enabled =
+ m_system_settings.user_system_clock_automatic_correction_enabled;
+ R_SUCCEED();
+}
- const auto res = SetUserSystemClockAutomaticCorrectionEnabled(enabled);
+Result ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionEnabled(
+ bool automatic_correction_enabled) {
+ LOG_INFO(Service_SET, "called, out_automatic_correction_enabled={}",
+ automatic_correction_enabled);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
+ m_system_settings.user_system_clock_automatic_correction_enabled = automatic_correction_enabled;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetDebugModeFlag(HLERequestContext& ctx) {
- bool is_debug_mode_enabled = false;
- GetSettingsItemValue<bool>(is_debug_mode_enabled, "settings_debug", "is_debug_mode_enabled");
+Result ISystemSettingsServer::GetDebugModeFlag(Out<bool> is_debug_mode_enabled) {
+ const auto result = GetSettingsItemValueImpl<bool>(*is_debug_mode_enabled, "settings_debug",
+ "is_debug_mode_enabled");
- LOG_DEBUG(Service_SET, "called, is_debug_mode_enabled={}", is_debug_mode_enabled);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(is_debug_mode_enabled);
+ LOG_DEBUG(Service_SET, "called, is_debug_mode_enabled={}", *is_debug_mode_enabled);
+ R_RETURN(result);
}
-void ISystemSettingsServer::GetPrimaryAlbumStorage(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetPrimaryAlbumStorage(
+ Out<PrimaryAlbumStorage> out_primary_album_storage) {
LOG_INFO(Service_SET, "called, primary_album_storage={}",
m_system_settings.primary_album_storage);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushEnum(m_system_settings.primary_album_storage);
+ *out_primary_album_storage = m_system_settings.primary_album_storage;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetPrimaryAlbumStorage(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.primary_album_storage = rp.PopEnum<PrimaryAlbumStorage>();
- SetSaveNeeded();
+Result ISystemSettingsServer::SetPrimaryAlbumStorage(PrimaryAlbumStorage primary_album_storage) {
+ LOG_INFO(Service_SET, "called, primary_album_storage={}", primary_album_storage);
- LOG_INFO(Service_SET, "called, primary_album_storage={}",
- m_system_settings.primary_album_storage);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.primary_album_storage = primary_album_storage;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetBatteryLot(HLERequestContext& ctx) {
- BatteryLot battery_lot = {"YUZUEMULATOR123456789"};
-
+Result ISystemSettingsServer::GetBatteryLot(Out<BatteryLot> out_battery_lot) {
LOG_INFO(Service_SET, "called");
- IPC::ResponseBuilder rb{ctx, 8};
- rb.Push(ResultSuccess);
- rb.PushRaw(battery_lot);
+ *out_battery_lot = {"YUZU0EMULATOR14022024"};
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetSerialNumber(HLERequestContext& ctx) {
- SerialNumber console_serial = {"YUZ10012345678"};
-
+Result ISystemSettingsServer::GetSerialNumber(Out<SerialNumber> out_console_serial) {
LOG_INFO(Service_SET, "called");
- IPC::ResponseBuilder rb{ctx, 8};
- rb.Push(ResultSuccess);
- rb.PushRaw(console_serial);
+ *out_console_serial = {"YUZ10000000001"};
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetNfcEnableFlag(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetNfcEnableFlag(Out<bool> out_nfc_enable_flag) {
LOG_INFO(Service_SET, "called, nfc_enable_flag={}", m_system_settings.nfc_enable_flag);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u8>(m_system_settings.nfc_enable_flag);
+ *out_nfc_enable_flag = m_system_settings.nfc_enable_flag;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetNfcEnableFlag(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.nfc_enable_flag = rp.Pop<bool>();
- SetSaveNeeded();
-
- LOG_INFO(Service_SET, "called, nfc_enable_flag={}", m_system_settings.nfc_enable_flag);
+Result ISystemSettingsServer::SetNfcEnableFlag(bool nfc_enable_flag) {
+ LOG_INFO(Service_SET, "called, nfc_enable_flag={}", nfc_enable_flag);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.nfc_enable_flag = nfc_enable_flag;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetSleepSettings(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetSleepSettings(Out<SleepSettings> out_sleep_settings) {
LOG_INFO(Service_SET, "called, flags={}, handheld_sleep_plan={}, console_sleep_plan={}",
m_system_settings.sleep_settings.flags.raw,
m_system_settings.sleep_settings.handheld_sleep_plan,
m_system_settings.sleep_settings.console_sleep_plan);
- IPC::ResponseBuilder rb{ctx, 5};
- rb.Push(ResultSuccess);
- rb.PushRaw(m_system_settings.sleep_settings);
+ *out_sleep_settings = m_system_settings.sleep_settings;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetSleepSettings(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.sleep_settings = rp.PopRaw<SleepSettings>();
- SetSaveNeeded();
-
+Result ISystemSettingsServer::SetSleepSettings(SleepSettings sleep_settings) {
LOG_INFO(Service_SET, "called, flags={}, handheld_sleep_plan={}, console_sleep_plan={}",
- m_system_settings.sleep_settings.flags.raw,
- m_system_settings.sleep_settings.handheld_sleep_plan,
- m_system_settings.sleep_settings.console_sleep_plan);
+ sleep_settings.flags.raw, sleep_settings.handheld_sleep_plan,
+ sleep_settings.console_sleep_plan);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.sleep_settings = sleep_settings;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetWirelessLanEnableFlag(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetWirelessLanEnableFlag(Out<bool> out_wireless_lan_enable_flag) {
LOG_INFO(Service_SET, "called, wireless_lan_enable_flag={}",
m_system_settings.wireless_lan_enable_flag);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(m_system_settings.wireless_lan_enable_flag);
+ *out_wireless_lan_enable_flag = m_system_settings.wireless_lan_enable_flag;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetWirelessLanEnableFlag(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.wireless_lan_enable_flag = rp.Pop<bool>();
- SetSaveNeeded();
-
- LOG_INFO(Service_SET, "called, wireless_lan_enable_flag={}",
- m_system_settings.wireless_lan_enable_flag);
+Result ISystemSettingsServer::SetWirelessLanEnableFlag(bool wireless_lan_enable_flag) {
+ LOG_INFO(Service_SET, "called, wireless_lan_enable_flag={}", wireless_lan_enable_flag);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.wireless_lan_enable_flag = wireless_lan_enable_flag;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetInitialLaunchSettings(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetInitialLaunchSettings(
+ Out<InitialLaunchSettings> out_initial_launch_settings) {
LOG_INFO(Service_SET, "called, flags={}, timestamp={}",
m_system_settings.initial_launch_settings_packed.flags.raw,
m_system_settings.initial_launch_settings_packed.timestamp.time_point);
- IPC::ResponseBuilder rb{ctx, 10};
- rb.Push(ResultSuccess);
- rb.PushRaw(m_system_settings.initial_launch_settings_packed);
+ *out_initial_launch_settings = {
+ .flags = m_system_settings.initial_launch_settings_packed.flags,
+ .timestamp = m_system_settings.initial_launch_settings_packed.timestamp,
+ };
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetInitialLaunchSettings(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- auto initial_launch_settings = rp.PopRaw<InitialLaunchSettings>();
+Result ISystemSettingsServer::SetInitialLaunchSettings(
+ InitialLaunchSettings initial_launch_settings) {
+ LOG_INFO(Service_SET, "called, flags={}, timestamp={}", initial_launch_settings.flags.raw,
+ initial_launch_settings.timestamp.time_point);
m_system_settings.initial_launch_settings_packed.flags = initial_launch_settings.flags;
m_system_settings.initial_launch_settings_packed.timestamp = initial_launch_settings.timestamp;
SetSaveNeeded();
-
- LOG_INFO(Service_SET, "called, flags={}, timestamp={}",
- m_system_settings.initial_launch_settings_packed.flags.raw,
- m_system_settings.initial_launch_settings_packed.timestamp.time_point);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetDeviceNickName(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetDeviceNickName(
+ OutLargeData<std::array<u8, 0x80>, BufferAttr_HipcMapAlias> out_device_name) {
LOG_DEBUG(Service_SET, "called");
- ctx.WriteBuffer(::Settings::values.device_name.GetValue());
+ *out_device_name = {};
+ const auto device_name_buffer = ::Settings::values.device_name.GetValue().c_str();
+ memcpy(out_device_name->data(), device_name_buffer,
+ ::Settings::values.device_name.GetValue().size());
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetDeviceNickName(HLERequestContext& ctx) {
- const std::string device_name = Common::StringFromBuffer(ctx.ReadBuffer());
+Result ISystemSettingsServer::SetDeviceNickName(
+ InLargeData<std::array<u8, 0x80>, BufferAttr_HipcMapAlias> device_name_buffer) {
+ const std::string device_name = Common::StringFromBuffer(*device_name_buffer);
LOG_INFO(Service_SET, "called, device_name={}", device_name);
::Settings::values.device_name = device_name;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetProductModel(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetProductModel(Out<u32> out_product_model) {
const u32 product_model = 1;
LOG_WARNING(Service_SET, "(STUBBED) called, product_model={}", product_model);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(product_model);
+
+ *out_product_model = product_model;
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetBluetoothEnableFlag(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetBluetoothEnableFlag(Out<bool> out_bluetooth_enable_flag) {
LOG_INFO(Service_SET, "called, bluetooth_enable_flag={}",
m_system_settings.bluetooth_enable_flag);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push<u8>(m_system_settings.bluetooth_enable_flag);
+ *out_bluetooth_enable_flag = m_system_settings.bluetooth_enable_flag;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetBluetoothEnableFlag(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.bluetooth_enable_flag = rp.Pop<bool>();
- SetSaveNeeded();
+Result ISystemSettingsServer::SetBluetoothEnableFlag(bool bluetooth_enable_flag) {
+ LOG_INFO(Service_SET, "called, bluetooth_enable_flag={}", bluetooth_enable_flag);
- LOG_INFO(Service_SET, "called, bluetooth_enable_flag={}",
- m_system_settings.bluetooth_enable_flag);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.bluetooth_enable_flag = bluetooth_enable_flag;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetMiiAuthorId(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetMiiAuthorId(Out<Common::UUID> out_mii_author_id) {
if (m_system_settings.mii_author_id.IsInvalid()) {
m_system_settings.mii_author_id = Common::UUID::MakeDefault();
SetSaveNeeded();
@@ -1166,282 +1060,224 @@ void ISystemSettingsServer::GetMiiAuthorId(HLERequestContext& ctx) {
LOG_INFO(Service_SET, "called, author_id={}",
m_system_settings.mii_author_id.FormattedString());
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(ResultSuccess);
- rb.PushRaw(m_system_settings.mii_author_id);
+ *out_mii_author_id = m_system_settings.mii_author_id;
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetAutoUpdateEnableFlag(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetAutoUpdateEnableFlag(Out<bool> out_auto_update_enable_flag) {
LOG_INFO(Service_SET, "called, auto_update_flag={}", m_system_settings.auto_update_enable_flag);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(m_system_settings.auto_update_enable_flag);
+ *out_auto_update_enable_flag = m_system_settings.auto_update_enable_flag;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetAutoUpdateEnableFlag(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.auto_update_enable_flag = rp.Pop<bool>();
- SetSaveNeeded();
+Result ISystemSettingsServer::SetAutoUpdateEnableFlag(bool auto_update_enable_flag) {
+ LOG_INFO(Service_SET, "called, auto_update_flag={}", auto_update_enable_flag);
- LOG_INFO(Service_SET, "called, auto_update_flag={}", m_system_settings.auto_update_enable_flag);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.auto_update_enable_flag = auto_update_enable_flag;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetBatteryPercentageFlag(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetBatteryPercentageFlag(Out<bool> out_battery_percentage_flag) {
LOG_DEBUG(Service_SET, "called, battery_percentage_flag={}",
m_system_settings.battery_percentage_flag);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(m_system_settings.battery_percentage_flag);
+ *out_battery_percentage_flag = m_system_settings.battery_percentage_flag;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetBatteryPercentageFlag(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.battery_percentage_flag = rp.Pop<bool>();
- SetSaveNeeded();
-
- LOG_INFO(Service_SET, "called, battery_percentage_flag={}",
- m_system_settings.battery_percentage_flag);
+Result ISystemSettingsServer::SetBatteryPercentageFlag(bool battery_percentage_flag) {
+ LOG_INFO(Service_SET, "called, battery_percentage_flag={}", battery_percentage_flag);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.battery_percentage_flag = battery_percentage_flag;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetExternalSteadyClockInternalOffset(HLERequestContext& ctx) {
- LOG_DEBUG(Service_SET, "called.");
-
- IPC::RequestParser rp{ctx};
- auto offset{rp.Pop<s64>()};
-
- const auto res = SetExternalSteadyClockInternalOffset(offset);
+Result ISystemSettingsServer::SetExternalSteadyClockInternalOffset(s64 offset) {
+ LOG_DEBUG(Service_SET, "called, external_steady_clock_internal_offset={}", offset);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
+ m_private_settings.external_steady_clock_internal_offset = offset;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetExternalSteadyClockInternalOffset(HLERequestContext& ctx) {
- LOG_DEBUG(Service_SET, "called.");
+Result ISystemSettingsServer::GetExternalSteadyClockInternalOffset(Out<s64> out_offset) {
+ LOG_DEBUG(Service_SET, "called, external_steady_clock_internal_offset={}",
+ m_private_settings.external_steady_clock_internal_offset);
- s64 offset{};
- const auto res = GetExternalSteadyClockInternalOffset(offset);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(res);
- rb.Push(offset);
+ *out_offset = m_private_settings.external_steady_clock_internal_offset;
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetPushNotificationActivityModeOnSleep(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetPushNotificationActivityModeOnSleep(
+ Out<s32> out_push_notification_activity_mode_on_sleep) {
LOG_INFO(Service_SET, "called, push_notification_activity_mode_on_sleep={}",
m_system_settings.push_notification_activity_mode_on_sleep);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(m_system_settings.push_notification_activity_mode_on_sleep);
+ *out_push_notification_activity_mode_on_sleep =
+ m_system_settings.push_notification_activity_mode_on_sleep;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetPushNotificationActivityModeOnSleep(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.push_notification_activity_mode_on_sleep = rp.Pop<s32>();
- SetSaveNeeded();
-
+Result ISystemSettingsServer::SetPushNotificationActivityModeOnSleep(
+ s32 push_notification_activity_mode_on_sleep) {
LOG_INFO(Service_SET, "called, push_notification_activity_mode_on_sleep={}",
- m_system_settings.push_notification_activity_mode_on_sleep);
+ push_notification_activity_mode_on_sleep);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.push_notification_activity_mode_on_sleep =
+ push_notification_activity_mode_on_sleep;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetErrorReportSharePermission(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetErrorReportSharePermission(
+ Out<ErrorReportSharePermission> out_error_report_share_permission) {
LOG_INFO(Service_SET, "called, error_report_share_permission={}",
m_system_settings.error_report_share_permission);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushEnum(m_system_settings.error_report_share_permission);
+ *out_error_report_share_permission = m_system_settings.error_report_share_permission;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetErrorReportSharePermission(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.error_report_share_permission = rp.PopEnum<ErrorReportSharePermission>();
- SetSaveNeeded();
-
+Result ISystemSettingsServer::SetErrorReportSharePermission(
+ ErrorReportSharePermission error_report_share_permission) {
LOG_INFO(Service_SET, "called, error_report_share_permission={}",
- m_system_settings.error_report_share_permission);
+ error_report_share_permission);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.error_report_share_permission = error_report_share_permission;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetAppletLaunchFlags(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetAppletLaunchFlags(Out<u32> out_applet_launch_flag) {
LOG_INFO(Service_SET, "called, applet_launch_flag={}", m_system_settings.applet_launch_flag);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(m_system_settings.applet_launch_flag);
+ *out_applet_launch_flag = m_system_settings.applet_launch_flag;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetAppletLaunchFlags(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.applet_launch_flag = rp.Pop<u32>();
- SetSaveNeeded();
-
- LOG_INFO(Service_SET, "called, applet_launch_flag={}", m_system_settings.applet_launch_flag);
+Result ISystemSettingsServer::SetAppletLaunchFlags(u32 applet_launch_flag) {
+ LOG_INFO(Service_SET, "called, applet_launch_flag={}", applet_launch_flag);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.applet_launch_flag = applet_launch_flag;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetKeyboardLayout(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetKeyboardLayout(Out<KeyboardLayout> out_keyboard_layout) {
LOG_INFO(Service_SET, "called, keyboard_layout={}", m_system_settings.keyboard_layout);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(static_cast<u32>(m_system_settings.keyboard_layout));
+ *out_keyboard_layout = m_system_settings.keyboard_layout;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetKeyboardLayout(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.keyboard_layout = rp.PopRaw<KeyboardLayout>();
- SetSaveNeeded();
-
- LOG_INFO(Service_SET, "called, keyboard_layout={}", m_system_settings.keyboard_layout);
+Result ISystemSettingsServer::SetKeyboardLayout(KeyboardLayout keyboard_layout) {
+ LOG_INFO(Service_SET, "called, keyboard_layout={}", keyboard_layout);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.keyboard_layout = keyboard_layout;
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime(
+ Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) {
LOG_INFO(Service_SET, "called");
- Service::PSC::Time::SteadyClockTimePoint time_point{};
- const auto res = GetDeviceTimeZoneLocationUpdatedTime(time_point);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(res);
- rb.PushRaw<Service::PSC::Time::SteadyClockTimePoint>(time_point);
+ *out_time_point = m_system_settings.device_time_zone_location_updated_time;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx) {
+Result ISystemSettingsServer::SetDeviceTimeZoneLocationUpdatedTime(
+ const Service::PSC::Time::SteadyClockTimePoint& time_point) {
LOG_INFO(Service_SET, "called");
- IPC::RequestParser rp{ctx};
- auto time_point{rp.PopRaw<Service::PSC::Time::SteadyClockTimePoint>()};
-
- const auto res = SetDeviceTimeZoneLocationUpdatedTime(time_point);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
+ m_system_settings.device_time_zone_location_updated_time = time_point;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetUserSystemClockAutomaticCorrectionUpdatedTime(
- HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetUserSystemClockAutomaticCorrectionUpdatedTime(
+ Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) {
LOG_INFO(Service_SET, "called");
- Service::PSC::Time::SteadyClockTimePoint time_point{};
- const auto res = GetUserSystemClockAutomaticCorrectionUpdatedTime(time_point);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(res);
- rb.PushRaw<Service::PSC::Time::SteadyClockTimePoint>(time_point);
+ *out_time_point = m_system_settings.user_system_clock_automatic_correction_updated_time_point;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionUpdatedTime(
- HLERequestContext& ctx) {
+Result ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionUpdatedTime(
+ const Service::PSC::Time::SteadyClockTimePoint& out_time_point) {
LOG_INFO(Service_SET, "called");
- IPC::RequestParser rp{ctx};
- const auto time_point{rp.PopRaw<Service::PSC::Time::SteadyClockTimePoint>()};
-
- const auto res = SetUserSystemClockAutomaticCorrectionUpdatedTime(time_point);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
+ m_system_settings.user_system_clock_automatic_correction_updated_time_point = out_time_point;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetChineseTraditionalInputMethod(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetChineseTraditionalInputMethod(
+ Out<ChineseTraditionalInputMethod> out_chinese_traditional_input_method) {
LOG_INFO(Service_SET, "called, chinese_traditional_input_method={}",
m_system_settings.chinese_traditional_input_method);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.PushEnum(m_system_settings.chinese_traditional_input_method);
+ *out_chinese_traditional_input_method = m_system_settings.chinese_traditional_input_method;
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetHomeMenuScheme(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetHomeMenuScheme(Out<HomeMenuScheme> out_home_menu_scheme) {
LOG_DEBUG(Service_SET, "(STUBBED) called");
- const HomeMenuScheme default_color = {
+ *out_home_menu_scheme = {
.main = 0xFF323232,
.back = 0xFF323232,
.sub = 0xFFFFFFFF,
.bezel = 0xFFFFFFFF,
.extra = 0xFF000000,
};
-
- IPC::ResponseBuilder rb{ctx, 2 + sizeof(HomeMenuScheme) / sizeof(u32)};
- rb.Push(ResultSuccess);
- rb.PushRaw(default_color);
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetHomeMenuSchemeModel(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetHomeMenuSchemeModel(Out<u32> out_home_menu_scheme_model) {
LOG_WARNING(Service_SET, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(0);
+ *out_home_menu_scheme_model = 0;
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetTouchScreenMode(HLERequestContext& ctx) {
- TouchScreenMode touch_screen_mode{};
- auto res = GetTouchScreenMode(touch_screen_mode);
+Result ISystemSettingsServer::GetTouchScreenMode(Out<TouchScreenMode> out_touch_screen_mode) {
+ LOG_INFO(Service_SET, "called, touch_screen_mode={}", m_system_settings.touch_screen_mode);
- LOG_INFO(Service_SET, "called, touch_screen_mode={}", touch_screen_mode);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(res);
- rb.PushEnum(touch_screen_mode);
+ *out_touch_screen_mode = m_system_settings.touch_screen_mode;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetTouchScreenMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto touch_screen_mode = rp.PopEnum<TouchScreenMode>();
- auto res = SetTouchScreenMode(touch_screen_mode);
-
+Result ISystemSettingsServer::SetTouchScreenMode(TouchScreenMode touch_screen_mode) {
LOG_INFO(Service_SET, "called, touch_screen_mode={}", touch_screen_mode);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(res);
+ m_system_settings.touch_screen_mode = touch_screen_mode;
+ SetSaveNeeded();
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetFieldTestingFlag(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetFieldTestingFlag(Out<bool> out_field_testing_flag) {
LOG_INFO(Service_SET, "called, field_testing_flag={}", m_system_settings.field_testing_flag);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(m_system_settings.field_testing_flag);
+ *out_field_testing_flag = m_system_settings.field_testing_flag;
+ R_SUCCEED();
}
-void ISystemSettingsServer::GetPanelCrcMode(HLERequestContext& ctx) {
+Result ISystemSettingsServer::GetPanelCrcMode(Out<s32> out_panel_crc_mode) {
LOG_INFO(Service_SET, "called, panel_crc_mode={}", m_system_settings.panel_crc_mode);
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(m_system_settings.panel_crc_mode);
+ *out_panel_crc_mode = m_system_settings.panel_crc_mode;
+ R_SUCCEED();
}
-void ISystemSettingsServer::SetPanelCrcMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- m_system_settings.panel_crc_mode = rp.PopRaw<s32>();
- SetSaveNeeded();
+Result ISystemSettingsServer::SetPanelCrcMode(s32 panel_crc_mode) {
+ LOG_INFO(Service_SET, "called, panel_crc_mode={}", panel_crc_mode);
- LOG_INFO(Service_SET, "called, panel_crc_mode={}", m_system_settings.panel_crc_mode);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ m_system_settings.panel_crc_mode = panel_crc_mode;
+ SetSaveNeeded();
+ R_SUCCEED();
}
void ISystemSettingsServer::SetupSettings() {
@@ -1513,9 +1349,9 @@ void ISystemSettingsServer::SetSaveNeeded() {
m_save_needed = true;
}
-Result ISystemSettingsServer::GetSettingsItemValue(std::vector<u8>& out_value,
- const std::string& category,
- const std::string& name) {
+Result ISystemSettingsServer::GetSettingsItemValueImpl(std::vector<u8>& out_value,
+ const std::string& category,
+ const std::string& name) {
auto settings{GetSettings()};
R_UNLESS(settings.contains(category) && settings[category].contains(name), ResultUnknown);
@@ -1523,184 +1359,4 @@ Result ISystemSettingsServer::GetSettingsItemValue(std::vector<u8>& out_value,
R_SUCCEED();
}
-Result ISystemSettingsServer::GetVibrationMasterVolume(f32& out_volume) const {
- out_volume = m_system_settings.vibration_master_volume;
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetVibrationMasterVolume(f32 volume) {
- m_system_settings.vibration_master_volume = volume;
- SetSaveNeeded();
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::GetAudioOutputMode(AudioOutputMode& out_output_mode,
- AudioOutputModeTarget target) const {
- switch (target) {
- case AudioOutputModeTarget::Hdmi:
- out_output_mode = m_system_settings.audio_output_mode_hdmi;
- break;
- case AudioOutputModeTarget::Speaker:
- out_output_mode = m_system_settings.audio_output_mode_speaker;
- break;
- case AudioOutputModeTarget::Headphone:
- out_output_mode = m_system_settings.audio_output_mode_headphone;
- break;
- case AudioOutputModeTarget::Type3:
- out_output_mode = m_system_settings.audio_output_mode_type3;
- break;
- case AudioOutputModeTarget::Type4:
- out_output_mode = m_system_settings.audio_output_mode_type4;
- break;
- default:
- LOG_ERROR(Service_SET, "Invalid audio output mode target {}", target);
- }
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetAudioOutputMode(AudioOutputModeTarget target,
- AudioOutputMode output_mode) {
- switch (target) {
- case AudioOutputModeTarget::Hdmi:
- m_system_settings.audio_output_mode_hdmi = output_mode;
- break;
- case AudioOutputModeTarget::Speaker:
- m_system_settings.audio_output_mode_speaker = output_mode;
- break;
- case AudioOutputModeTarget::Headphone:
- m_system_settings.audio_output_mode_headphone = output_mode;
- break;
- case AudioOutputModeTarget::Type3:
- m_system_settings.audio_output_mode_type3 = output_mode;
- break;
- case AudioOutputModeTarget::Type4:
- m_system_settings.audio_output_mode_type4 = output_mode;
- break;
- default:
- LOG_ERROR(Service_SET, "Invalid audio output mode target {}", target);
- }
- SetSaveNeeded();
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::GetSpeakerAutoMuteFlag(bool& is_auto_mute) const {
- is_auto_mute = m_system_settings.force_mute_on_headphone_removed;
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetSpeakerAutoMuteFlag(bool is_auto_mute) {
- m_system_settings.force_mute_on_headphone_removed = is_auto_mute;
- SetSaveNeeded();
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::GetExternalSteadyClockSourceId(Common::UUID& out_id) const {
- out_id = m_private_settings.external_clock_source_id;
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetExternalSteadyClockSourceId(const Common::UUID& id) {
- m_private_settings.external_clock_source_id = id;
- SetSaveNeeded();
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::GetUserSystemClockContext(
- Service::PSC::Time::SystemClockContext& out_context) const {
- out_context = m_system_settings.user_system_clock_context;
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetUserSystemClockContext(
- const Service::PSC::Time::SystemClockContext& context) {
- m_system_settings.user_system_clock_context = context;
- SetSaveNeeded();
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::GetDeviceTimeZoneLocationName(
- Service::PSC::Time::LocationName& out_name) const {
- out_name = m_system_settings.device_time_zone_location_name;
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetDeviceTimeZoneLocationName(
- const Service::PSC::Time::LocationName& name) {
- m_system_settings.device_time_zone_location_name = name;
- SetSaveNeeded();
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::GetNetworkSystemClockContext(
- Service::PSC::Time::SystemClockContext& out_context) const {
- out_context = m_system_settings.network_system_clock_context;
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetNetworkSystemClockContext(
- const Service::PSC::Time::SystemClockContext& context) {
- m_system_settings.network_system_clock_context = context;
- SetSaveNeeded();
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::IsUserSystemClockAutomaticCorrectionEnabled(bool& out_enabled) const {
- out_enabled = m_system_settings.user_system_clock_automatic_correction_enabled;
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionEnabled(bool enabled) {
- m_system_settings.user_system_clock_automatic_correction_enabled = enabled;
- SetSaveNeeded();
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetExternalSteadyClockInternalOffset(s64 offset) {
- m_private_settings.external_steady_clock_internal_offset = offset;
- SetSaveNeeded();
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::GetExternalSteadyClockInternalOffset(s64& out_offset) const {
- out_offset = m_private_settings.external_steady_clock_internal_offset;
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime(
- Service::PSC::Time::SteadyClockTimePoint& out_time_point) const {
- out_time_point = m_system_settings.device_time_zone_location_updated_time;
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetDeviceTimeZoneLocationUpdatedTime(
- const Service::PSC::Time::SteadyClockTimePoint& time_point) {
- m_system_settings.device_time_zone_location_updated_time = time_point;
- SetSaveNeeded();
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::GetUserSystemClockAutomaticCorrectionUpdatedTime(
- Service::PSC::Time::SteadyClockTimePoint& out_time_point) const {
- out_time_point = m_system_settings.user_system_clock_automatic_correction_updated_time_point;
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetUserSystemClockAutomaticCorrectionUpdatedTime(
- const Service::PSC::Time::SteadyClockTimePoint& out_time_point) {
- m_system_settings.user_system_clock_automatic_correction_updated_time_point = out_time_point;
- SetSaveNeeded();
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::GetTouchScreenMode(TouchScreenMode& touch_screen_mode) const {
- touch_screen_mode = m_system_settings.touch_screen_mode;
- R_SUCCEED();
-}
-
-Result ISystemSettingsServer::SetTouchScreenMode(TouchScreenMode touch_screen_mode) {
- m_system_settings.touch_screen_mode = touch_screen_mode;
- SetSaveNeeded();
- R_SUCCEED();
-}
-
} // namespace Service::Set
diff --git a/src/core/hle/service/set/system_settings_server.h b/src/core/hle/service/set/system_settings_server.h
index 9a3b36f0c..46e06c8ea 100644
--- a/src/core/hle/service/set/system_settings_server.h
+++ b/src/core/hle/service/set/system_settings_server.h
@@ -11,6 +11,7 @@
#include "common/polyfill_thread.h"
#include "common/uuid.h"
#include "core/hle/result.h"
+#include "core/hle/service/cmif_types.h"
#include "core/hle/service/psc/time/common.h"
#include "core/hle/service/service.h"
#include "core/hle/service/set/setting_formats/appln_settings.h"
@@ -33,13 +34,14 @@ public:
explicit ISystemSettingsServer(Core::System& system_);
~ISystemSettingsServer() override;
- Result GetSettingsItemValue(std::vector<u8>& out_value, const std::string& category,
- const std::string& name);
+ Result GetSettingsItemValueImpl(std::vector<u8>& out_value, const std::string& category,
+ const std::string& name);
template <typename T>
- Result GetSettingsItemValue(T& value, const std::string& category, const std::string& name) {
+ Result GetSettingsItemValueImpl(T& value, const std::string& category,
+ const std::string& name) {
std::vector<u8> data;
- const auto result = GetSettingsItemValue(data, category, name);
+ const auto result = GetSettingsItemValueImpl(data, category, name);
if (result.IsError()) {
return result;
}
@@ -48,120 +50,114 @@ public:
return result;
}
- Result GetVibrationMasterVolume(f32& out_volume) const;
- Result SetVibrationMasterVolume(f32 volume);
- Result GetAudioOutputMode(AudioOutputMode& out_output_mode, AudioOutputModeTarget target) const;
+public:
+ Result SetLanguageCode(LanguageCode language_code);
+ Result GetFirmwareVersion(
+ OutLargeData<FirmwareVersionFormat, BufferAttr_HipcPointer> out_firmware_data);
+ Result GetFirmwareVersion2(
+ OutLargeData<FirmwareVersionFormat, BufferAttr_HipcPointer> out_firmware_data);
+ Result GetLockScreenFlag(Out<bool> out_lock_screen_flag);
+ Result SetLockScreenFlag(bool lock_screen_flag);
+ Result GetExternalSteadyClockSourceId(Out<Common::UUID> out_clock_source_id);
+ Result SetExternalSteadyClockSourceId(const Common::UUID& clock_source_id);
+ Result GetUserSystemClockContext(Out<Service::PSC::Time::SystemClockContext> out_clock_context);
+ Result SetUserSystemClockContext(const Service::PSC::Time::SystemClockContext& clock_context);
+ Result GetAccountSettings(Out<AccountSettings> out_account_settings);
+ Result SetAccountSettings(AccountSettings account_settings);
+ Result GetEulaVersions(Out<s32> out_count,
+ OutArray<EulaVersion, BufferAttr_HipcMapAlias> out_eula_versions);
+ Result SetEulaVersions(InArray<EulaVersion, BufferAttr_HipcMapAlias> eula_versions);
+ Result GetColorSetId(Out<ColorSet> out_color_set_id);
+ Result SetColorSetId(ColorSet color_set_id);
+ Result GetNotificationSettings(Out<NotificationSettings> out_notification_settings);
+ Result SetNotificationSettings(const NotificationSettings& notification_settings);
+ Result GetAccountNotificationSettings(
+ Out<s32> out_count, OutArray<AccountNotificationSettings, BufferAttr_HipcMapAlias>
+ out_account_notification_settings);
+ Result SetAccountNotificationSettings(
+ InArray<AccountNotificationSettings, BufferAttr_HipcMapAlias>
+ account_notification_settings);
+ Result GetVibrationMasterVolume(Out<f32> vibration_master_volume);
+ Result SetVibrationMasterVolume(f32 vibration_master_volume);
+ Result GetSettingsItemValueSize(
+ Out<u64> out_size,
+ InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_category_buffer,
+ InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_name_buf);
+ Result GetSettingsItemValue(
+ OutBuffer<BufferAttr_HipcMapAlias> out_data,
+ InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_category_buffer,
+ InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_name_buffer);
+ Result GetTvSettings(Out<TvSettings> out_tv_settings);
+ Result SetTvSettings(TvSettings tv_settings);
+ Result GetAudioOutputMode(Out<AudioOutputMode> out_output_mode, AudioOutputModeTarget target);
Result SetAudioOutputMode(AudioOutputModeTarget target, AudioOutputMode output_mode);
- Result GetSpeakerAutoMuteFlag(bool& is_auto_mute) const;
- Result SetSpeakerAutoMuteFlag(bool auto_mute);
- Result GetExternalSteadyClockSourceId(Common::UUID& out_id) const;
- Result SetExternalSteadyClockSourceId(const Common::UUID& id);
- Result GetUserSystemClockContext(Service::PSC::Time::SystemClockContext& out_context) const;
- Result SetUserSystemClockContext(const Service::PSC::Time::SystemClockContext& context);
- Result GetDeviceTimeZoneLocationName(Service::PSC::Time::LocationName& out_name) const;
+ Result GetSpeakerAutoMuteFlag(Out<bool> out_force_mute_on_headphone_removed);
+ Result SetSpeakerAutoMuteFlag(bool force_mute_on_headphone_removed);
+ Result GetQuestFlag(Out<QuestFlag> out_quest_flag);
+ Result SetQuestFlag(QuestFlag quest_flag);
+ Result GetDeviceTimeZoneLocationName(Out<Service::PSC::Time::LocationName> out_name);
Result SetDeviceTimeZoneLocationName(const Service::PSC::Time::LocationName& name);
- Result GetNetworkSystemClockContext(Service::PSC::Time::SystemClockContext& out_context) const;
+ Result SetRegionCode(SystemRegionCode region_code);
+ Result GetNetworkSystemClockContext(Out<Service::PSC::Time::SystemClockContext> out_context);
Result SetNetworkSystemClockContext(const Service::PSC::Time::SystemClockContext& context);
- Result IsUserSystemClockAutomaticCorrectionEnabled(bool& out_enabled) const;
- Result SetUserSystemClockAutomaticCorrectionEnabled(bool enabled);
+ Result IsUserSystemClockAutomaticCorrectionEnabled(Out<bool> out_automatic_correction_enabled);
+ Result SetUserSystemClockAutomaticCorrectionEnabled(bool automatic_correction_enabled);
+ Result GetDebugModeFlag(Out<bool> is_debug_mode_enabled);
+ Result GetPrimaryAlbumStorage(Out<PrimaryAlbumStorage> out_primary_album_storage);
+ Result SetPrimaryAlbumStorage(PrimaryAlbumStorage primary_album_storage);
+ Result GetBatteryLot(Out<BatteryLot> out_battery_lot);
+ Result GetSerialNumber(Out<SerialNumber> out_console_serial);
+ Result GetNfcEnableFlag(Out<bool> out_nfc_enable_flag);
+ Result SetNfcEnableFlag(bool nfc_enable_flag);
+ Result GetSleepSettings(Out<SleepSettings> out_sleep_settings);
+ Result SetSleepSettings(SleepSettings sleep_settings);
+ Result GetWirelessLanEnableFlag(Out<bool> out_wireless_lan_enable_flag);
+ Result SetWirelessLanEnableFlag(bool wireless_lan_enable_flag);
+ Result GetInitialLaunchSettings(Out<InitialLaunchSettings> out_initial_launch_settings);
+ Result SetInitialLaunchSettings(InitialLaunchSettings initial_launch_settings);
+ Result GetDeviceNickName(
+ OutLargeData<std::array<u8, 0x80>, BufferAttr_HipcMapAlias> out_device_name);
+ Result SetDeviceNickName(
+ InLargeData<std::array<u8, 0x80>, BufferAttr_HipcMapAlias> device_name_buffer);
+ Result GetProductModel(Out<u32> out_product_model);
+ Result GetBluetoothEnableFlag(Out<bool> out_bluetooth_enable_flag);
+ Result SetBluetoothEnableFlag(bool bluetooth_enable_flag);
+ Result GetMiiAuthorId(Out<Common::UUID> out_mii_author_id);
+ Result GetAutoUpdateEnableFlag(Out<bool> out_auto_update_enable_flag);
+ Result SetAutoUpdateEnableFlag(bool auto_update_enable_flag);
+ Result GetBatteryPercentageFlag(Out<bool> out_battery_percentage_flag);
+ Result SetBatteryPercentageFlag(bool battery_percentage_flag);
Result SetExternalSteadyClockInternalOffset(s64 offset);
- Result GetExternalSteadyClockInternalOffset(s64& out_offset) const;
+ Result GetExternalSteadyClockInternalOffset(Out<s64> out_offset);
+ Result GetPushNotificationActivityModeOnSleep(
+ Out<s32> out_push_notification_activity_mode_on_sleep);
+ Result SetPushNotificationActivityModeOnSleep(s32 push_notification_activity_mode_on_sleep);
+ Result GetErrorReportSharePermission(
+ Out<ErrorReportSharePermission> out_error_report_share_permission);
+ Result SetErrorReportSharePermission(ErrorReportSharePermission error_report_share_permission);
+ Result GetAppletLaunchFlags(Out<u32> out_applet_launch_flag);
+ Result SetAppletLaunchFlags(u32 applet_launch_flag);
+ Result GetKeyboardLayout(Out<KeyboardLayout> out_keyboard_layout);
+ Result SetKeyboardLayout(KeyboardLayout keyboard_layout);
Result GetDeviceTimeZoneLocationUpdatedTime(
- Service::PSC::Time::SteadyClockTimePoint& out_time_point) const;
+ Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point);
Result SetDeviceTimeZoneLocationUpdatedTime(
const Service::PSC::Time::SteadyClockTimePoint& time_point);
Result GetUserSystemClockAutomaticCorrectionUpdatedTime(
- Service::PSC::Time::SteadyClockTimePoint& out_time_point) const;
+ Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point);
Result SetUserSystemClockAutomaticCorrectionUpdatedTime(
- const Service::PSC::Time::SteadyClockTimePoint& time_point);
- Result GetTouchScreenMode(TouchScreenMode& touch_screen_mode) const;
+ const Service::PSC::Time::SteadyClockTimePoint& out_time_point);
+ Result GetChineseTraditionalInputMethod(
+ Out<ChineseTraditionalInputMethod> out_chinese_traditional_input_method);
+ Result GetHomeMenuScheme(Out<HomeMenuScheme> out_home_menu_scheme);
+ Result GetHomeMenuSchemeModel(Out<u32> out_home_menu_scheme_model);
+ Result GetTouchScreenMode(Out<TouchScreenMode> out_touch_screen_mode);
Result SetTouchScreenMode(TouchScreenMode touch_screen_mode);
+ Result GetFieldTestingFlag(Out<bool> out_field_testing_flag);
+ Result GetPanelCrcMode(Out<s32> out_panel_crc_mode);
+ Result SetPanelCrcMode(s32 panel_crc_mode);
private:
- void SetLanguageCode(HLERequestContext& ctx);
- void GetFirmwareVersion(HLERequestContext& ctx);
- void GetFirmwareVersion2(HLERequestContext& ctx);
- void GetLockScreenFlag(HLERequestContext& ctx);
- void SetLockScreenFlag(HLERequestContext& ctx);
- void GetExternalSteadyClockSourceId(HLERequestContext& ctx);
- void SetExternalSteadyClockSourceId(HLERequestContext& ctx);
- void GetUserSystemClockContext(HLERequestContext& ctx);
- void SetUserSystemClockContext(HLERequestContext& ctx);
- void GetAccountSettings(HLERequestContext& ctx);
- void SetAccountSettings(HLERequestContext& ctx);
- void GetEulaVersions(HLERequestContext& ctx);
- void SetEulaVersions(HLERequestContext& ctx);
- void GetColorSetId(HLERequestContext& ctx);
- void SetColorSetId(HLERequestContext& ctx);
- void GetNotificationSettings(HLERequestContext& ctx);
- void SetNotificationSettings(HLERequestContext& ctx);
- void GetAccountNotificationSettings(HLERequestContext& ctx);
- void SetAccountNotificationSettings(HLERequestContext& ctx);
- void GetVibrationMasterVolume(HLERequestContext& ctx);
- void SetVibrationMasterVolume(HLERequestContext& ctx);
- void GetSettingsItemValueSize(HLERequestContext& ctx);
- void GetSettingsItemValue(HLERequestContext& ctx);
- void GetTvSettings(HLERequestContext& ctx);
- void SetTvSettings(HLERequestContext& ctx);
- void GetAudioOutputMode(HLERequestContext& ctx);
- void SetAudioOutputMode(HLERequestContext& ctx);
- void GetSpeakerAutoMuteFlag(HLERequestContext& ctx);
- void SetSpeakerAutoMuteFlag(HLERequestContext& ctx);
- void GetDebugModeFlag(HLERequestContext& ctx);
- void GetQuestFlag(HLERequestContext& ctx);
- void SetQuestFlag(HLERequestContext& ctx);
- void GetDeviceTimeZoneLocationName(HLERequestContext& ctx);
- void SetDeviceTimeZoneLocationName(HLERequestContext& ctx);
- void SetRegionCode(HLERequestContext& ctx);
- void GetNetworkSystemClockContext(HLERequestContext& ctx);
- void SetNetworkSystemClockContext(HLERequestContext& ctx);
- void IsUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx);
- void SetUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx);
- void GetPrimaryAlbumStorage(HLERequestContext& ctx);
- void SetPrimaryAlbumStorage(HLERequestContext& ctx);
- void GetBatteryLot(HLERequestContext& ctx);
- void GetSerialNumber(HLERequestContext& ctx);
- void GetNfcEnableFlag(HLERequestContext& ctx);
- void SetNfcEnableFlag(HLERequestContext& ctx);
- void GetSleepSettings(HLERequestContext& ctx);
- void SetSleepSettings(HLERequestContext& ctx);
- void GetWirelessLanEnableFlag(HLERequestContext& ctx);
- void SetWirelessLanEnableFlag(HLERequestContext& ctx);
- void GetInitialLaunchSettings(HLERequestContext& ctx);
- void SetInitialLaunchSettings(HLERequestContext& ctx);
- void GetDeviceNickName(HLERequestContext& ctx);
- void SetDeviceNickName(HLERequestContext& ctx);
- void GetProductModel(HLERequestContext& ctx);
- void GetBluetoothEnableFlag(HLERequestContext& ctx);
- void SetBluetoothEnableFlag(HLERequestContext& ctx);
- void GetMiiAuthorId(HLERequestContext& ctx);
- void GetAutoUpdateEnableFlag(HLERequestContext& ctx);
- void SetAutoUpdateEnableFlag(HLERequestContext& ctx);
- void GetBatteryPercentageFlag(HLERequestContext& ctx);
- void SetBatteryPercentageFlag(HLERequestContext& ctx);
- void SetExternalSteadyClockInternalOffset(HLERequestContext& ctx);
- void GetExternalSteadyClockInternalOffset(HLERequestContext& ctx);
- void GetPushNotificationActivityModeOnSleep(HLERequestContext& ctx);
- void SetPushNotificationActivityModeOnSleep(HLERequestContext& ctx);
- void GetErrorReportSharePermission(HLERequestContext& ctx);
- void SetErrorReportSharePermission(HLERequestContext& ctx);
- void GetAppletLaunchFlags(HLERequestContext& ctx);
- void SetAppletLaunchFlags(HLERequestContext& ctx);
- void GetKeyboardLayout(HLERequestContext& ctx);
- void SetKeyboardLayout(HLERequestContext& ctx);
- void GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx);
- void SetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx);
- void GetUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx);
- void SetUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx);
- void GetChineseTraditionalInputMethod(HLERequestContext& ctx);
- void GetHomeMenuScheme(HLERequestContext& ctx);
- void GetHomeMenuSchemeModel(HLERequestContext& ctx);
- void GetTouchScreenMode(HLERequestContext& ctx);
- void SetTouchScreenMode(HLERequestContext& ctx);
- void GetFieldTestingFlag(HLERequestContext& ctx);
- void GetPanelCrcMode(HLERequestContext& ctx);
- void SetPanelCrcMode(HLERequestContext& ctx);
-
bool LoadSettingsFile(std::filesystem::path& path, auto&& default_func);
bool StoreSettingsFile(std::filesystem::path& path, auto& settings);
void SetupSettings();
diff --git a/src/core/hle/service/vi/application_display_service.cpp b/src/core/hle/service/vi/application_display_service.cpp
new file mode 100644
index 000000000..6b0bcb536
--- /dev/null
+++ b/src/core/hle/service/vi/application_display_service.cpp
@@ -0,0 +1,302 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/nvnflinger/hos_binder_driver.h"
+#include "core/hle/service/nvnflinger/parcel.h"
+#include "core/hle/service/os/event.h"
+#include "core/hle/service/vi/application_display_service.h"
+#include "core/hle/service/vi/container.h"
+#include "core/hle/service/vi/manager_display_service.h"
+#include "core/hle/service/vi/system_display_service.h"
+#include "core/hle/service/vi/vi_results.h"
+
+namespace Service::VI {
+
+IApplicationDisplayService::IApplicationDisplayService(Core::System& system_,
+ std::shared_ptr<Container> container)
+ : ServiceFramework{system_, "IApplicationDisplayService"},
+ m_container{std::move(container)}, m_context{system, "IApplicationDisplayService"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {100, C<&IApplicationDisplayService::GetRelayService>, "GetRelayService"},
+ {101, C<&IApplicationDisplayService::GetSystemDisplayService>, "GetSystemDisplayService"},
+ {102, C<&IApplicationDisplayService::GetManagerDisplayService>, "GetManagerDisplayService"},
+ {103, C<&IApplicationDisplayService::GetIndirectDisplayTransactionService>, "GetIndirectDisplayTransactionService"},
+ {1000, C<&IApplicationDisplayService::ListDisplays>, "ListDisplays"},
+ {1010, C<&IApplicationDisplayService::OpenDisplay>, "OpenDisplay"},
+ {1011, C<&IApplicationDisplayService::OpenDefaultDisplay>, "OpenDefaultDisplay"},
+ {1020, C<&IApplicationDisplayService::CloseDisplay>, "CloseDisplay"},
+ {1101, C<&IApplicationDisplayService::SetDisplayEnabled>, "SetDisplayEnabled"},
+ {1102, C<&IApplicationDisplayService::GetDisplayResolution>, "GetDisplayResolution"},
+ {2020, C<&IApplicationDisplayService::OpenLayer>, "OpenLayer"},
+ {2021, C<&IApplicationDisplayService::CloseLayer>, "CloseLayer"},
+ {2030, C<&IApplicationDisplayService::CreateStrayLayer>, "CreateStrayLayer"},
+ {2031, C<&IApplicationDisplayService::DestroyStrayLayer>, "DestroyStrayLayer"},
+ {2101, C<&IApplicationDisplayService::SetLayerScalingMode>, "SetLayerScalingMode"},
+ {2102, C<&IApplicationDisplayService::ConvertScalingMode>, "ConvertScalingMode"},
+ {2450, C<&IApplicationDisplayService::GetIndirectLayerImageMap>, "GetIndirectLayerImageMap"},
+ {2451, nullptr, "GetIndirectLayerImageCropMap"},
+ {2460, C<&IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo>, "GetIndirectLayerImageRequiredMemoryInfo"},
+ {5202, C<&IApplicationDisplayService::GetDisplayVsyncEvent>, "GetDisplayVsyncEvent"},
+ {5203, nullptr, "GetDisplayVsyncEventForDebug"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IApplicationDisplayService::~IApplicationDisplayService() {
+ for (auto& [display_id, event] : m_display_vsync_events) {
+ m_container->UnlinkVsyncEvent(display_id, &event);
+ }
+ for (const auto layer_id : m_open_layer_ids) {
+ m_container->CloseLayer(layer_id);
+ }
+ for (const auto layer_id : m_stray_layer_ids) {
+ m_container->DestroyStrayLayer(layer_id);
+ }
+}
+
+Result IApplicationDisplayService::GetRelayService(
+ Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_relay_service) {
+ LOG_WARNING(Service_VI, "(STUBBED) called");
+ R_RETURN(m_container->GetBinderDriver(out_relay_service));
+}
+
+Result IApplicationDisplayService::GetSystemDisplayService(
+ Out<SharedPointer<ISystemDisplayService>> out_system_display_service) {
+ LOG_WARNING(Service_VI, "(STUBBED) called");
+ *out_system_display_service = std::make_shared<ISystemDisplayService>(system, m_container);
+ R_SUCCEED();
+}
+
+Result IApplicationDisplayService::GetManagerDisplayService(
+ Out<SharedPointer<IManagerDisplayService>> out_manager_display_service) {
+ LOG_WARNING(Service_VI, "(STUBBED) called");
+ *out_manager_display_service = std::make_shared<IManagerDisplayService>(system, m_container);
+ R_SUCCEED();
+}
+
+Result IApplicationDisplayService::GetIndirectDisplayTransactionService(
+ Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_indirect_display_transaction_service) {
+ LOG_WARNING(Service_VI, "(STUBBED) called");
+ R_RETURN(m_container->GetBinderDriver(out_indirect_display_transaction_service));
+}
+
+Result IApplicationDisplayService::OpenDisplay(Out<u64> out_display_id, DisplayName display_name) {
+ LOG_WARNING(Service_VI, "(STUBBED) called");
+
+ display_name[display_name.size() - 1] = '\0';
+ ASSERT_MSG(strcmp(display_name.data(), "Default") == 0,
+ "Non-default displays aren't supported yet");
+
+ R_RETURN(m_container->OpenDisplay(out_display_id, display_name));
+}
+
+Result IApplicationDisplayService::OpenDefaultDisplay(Out<u64> out_display_id) {
+ LOG_DEBUG(Service_VI, "called");
+ R_RETURN(this->OpenDisplay(out_display_id, DisplayName{"Default"}));
+}
+
+Result IApplicationDisplayService::CloseDisplay(u64 display_id) {
+ LOG_DEBUG(Service_VI, "called");
+ R_RETURN(m_container->CloseDisplay(display_id));
+}
+
+Result IApplicationDisplayService::SetDisplayEnabled(u32 state, u64 display_id) {
+ LOG_DEBUG(Service_VI, "called");
+
+ // This literally does nothing internally in the actual service itself,
+ // and just returns a successful result code regardless of the input.
+ R_SUCCEED();
+}
+
+Result IApplicationDisplayService::GetDisplayResolution(Out<s64> out_width, Out<s64> out_height,
+ u64 display_id) {
+ LOG_DEBUG(Service_VI, "called. display_id={}", display_id);
+
+ // This only returns the fixed values of 1280x720 and makes no distinguishing
+ // between docked and undocked dimensions.
+ *out_width = static_cast<s64>(DisplayResolution::UndockedWidth);
+ *out_height = static_cast<s64>(DisplayResolution::UndockedHeight);
+ R_SUCCEED();
+}
+
+Result IApplicationDisplayService::SetLayerScalingMode(NintendoScaleMode scale_mode, u64 layer_id) {
+ LOG_DEBUG(Service_VI, "called. scale_mode={}, unknown=0x{:016X}", scale_mode, layer_id);
+
+ if (scale_mode > NintendoScaleMode::PreserveAspectRatio) {
+ LOG_ERROR(Service_VI, "Invalid scaling mode provided.");
+ R_THROW(VI::ResultOperationFailed);
+ }
+
+ if (scale_mode != NintendoScaleMode::ScaleToWindow &&
+ scale_mode != NintendoScaleMode::PreserveAspectRatio) {
+ LOG_ERROR(Service_VI, "Unsupported scaling mode supplied.");
+ R_THROW(VI::ResultNotSupported);
+ }
+
+ R_SUCCEED();
+}
+
+Result IApplicationDisplayService::ListDisplays(
+ Out<u64> out_count, OutArray<DisplayInfo, BufferAttr_HipcMapAlias> out_displays) {
+ LOG_WARNING(Service_VI, "(STUBBED) called");
+
+ if (out_displays.size() > 0) {
+ out_displays[0] = DisplayInfo{};
+ *out_count = 1;
+ } else {
+ *out_count = 0;
+ }
+
+ R_SUCCEED();
+}
+
+Result IApplicationDisplayService::OpenLayer(Out<u64> out_size,
+ OutBuffer<BufferAttr_HipcMapAlias> out_native_window,
+ DisplayName display_name, u64 layer_id,
+ ClientAppletResourceUserId aruid) {
+ display_name[display_name.size() - 1] = '\0';
+
+ LOG_DEBUG(Service_VI, "called. layer_id={}, aruid={:#x}", layer_id, aruid.pid);
+
+ u64 display_id;
+ R_TRY(m_container->OpenDisplay(&display_id, display_name));
+
+ s32 producer_binder_id;
+ R_TRY(m_container->OpenLayer(&producer_binder_id, layer_id, aruid.pid));
+
+ {
+ std::scoped_lock lk{m_lock};
+ m_open_layer_ids.insert(layer_id);
+ }
+
+ android::OutputParcel parcel;
+ parcel.WriteInterface(NativeWindow{producer_binder_id});
+
+ const auto buffer = parcel.Serialize();
+ std::memcpy(out_native_window.data(), buffer.data(),
+ std::min(out_native_window.size(), buffer.size()));
+ *out_size = buffer.size();
+
+ R_SUCCEED();
+}
+
+Result IApplicationDisplayService::CloseLayer(u64 layer_id) {
+ LOG_DEBUG(Service_VI, "called. layer_id={}", layer_id);
+
+ {
+ std::scoped_lock lk{m_lock};
+ R_UNLESS(m_open_layer_ids.contains(layer_id), VI::ResultNotFound);
+ m_open_layer_ids.erase(layer_id);
+ }
+
+ R_RETURN(m_container->CloseLayer(layer_id));
+}
+
+Result IApplicationDisplayService::CreateStrayLayer(
+ Out<u64> out_layer_id, Out<u64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_native_window,
+ u32 flags, u64 display_id) {
+ LOG_DEBUG(Service_VI, "called. flags={}, display_id={}", flags, display_id);
+
+ s32 producer_binder_id;
+ R_TRY(m_container->CreateStrayLayer(&producer_binder_id, out_layer_id, display_id));
+
+ std::scoped_lock lk{m_lock};
+ m_stray_layer_ids.insert(*out_layer_id);
+
+ android::OutputParcel parcel;
+ parcel.WriteInterface(NativeWindow{producer_binder_id});
+
+ const auto buffer = parcel.Serialize();
+ std::memcpy(out_native_window.data(), buffer.data(),
+ std::min(out_native_window.size(), buffer.size()));
+
+ *out_size = buffer.size();
+
+ R_SUCCEED();
+}
+
+Result IApplicationDisplayService::DestroyStrayLayer(u64 layer_id) {
+ LOG_WARNING(Service_VI, "(STUBBED) called. layer_id={}", layer_id);
+
+ {
+ std::scoped_lock lk{m_lock};
+ R_UNLESS(m_stray_layer_ids.contains(layer_id), VI::ResultNotFound);
+ m_stray_layer_ids.erase(layer_id);
+ }
+
+ R_RETURN(m_container->DestroyStrayLayer(layer_id));
+}
+
+Result IApplicationDisplayService::GetDisplayVsyncEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_vsync_event, u64 display_id) {
+ LOG_DEBUG(Service_VI, "called. display_id={}", display_id);
+
+ std::scoped_lock lk{m_lock};
+
+ auto [it, created] = m_display_vsync_events.emplace(display_id, m_context);
+ R_UNLESS(created, VI::ResultPermissionDenied);
+
+ m_container->LinkVsyncEvent(display_id, &it->second);
+ *out_vsync_event = it->second.GetHandle();
+
+ R_SUCCEED();
+}
+
+Result IApplicationDisplayService::ConvertScalingMode(Out<ConvertedScaleMode> out_scaling_mode,
+ NintendoScaleMode mode) {
+ LOG_DEBUG(Service_VI, "called mode={}", mode);
+
+ switch (mode) {
+ case NintendoScaleMode::None:
+ *out_scaling_mode = ConvertedScaleMode::None;
+ R_SUCCEED();
+ case NintendoScaleMode::Freeze:
+ *out_scaling_mode = ConvertedScaleMode::Freeze;
+ R_SUCCEED();
+ case NintendoScaleMode::ScaleToWindow:
+ *out_scaling_mode = ConvertedScaleMode::ScaleToWindow;
+ R_SUCCEED();
+ case NintendoScaleMode::ScaleAndCrop:
+ *out_scaling_mode = ConvertedScaleMode::ScaleAndCrop;
+ R_SUCCEED();
+ case NintendoScaleMode::PreserveAspectRatio:
+ *out_scaling_mode = ConvertedScaleMode::PreserveAspectRatio;
+ R_SUCCEED();
+ default:
+ LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode);
+ R_THROW(VI::ResultOperationFailed);
+ }
+}
+
+Result IApplicationDisplayService::GetIndirectLayerImageMap(
+ Out<u64> out_size, Out<u64> out_stride,
+ OutBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> out_buffer,
+ s64 width, s64 height, u64 indirect_layer_consumer_handle, ClientAppletResourceUserId aruid) {
+ LOG_WARNING(
+ Service_VI,
+ "(STUBBED) called, width={}, height={}, indirect_layer_consumer_handle={}, aruid={:#x}",
+ width, height, indirect_layer_consumer_handle, aruid.pid);
+ *out_size = 0;
+ *out_stride = 0;
+ R_SUCCEED();
+}
+
+Result IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo(Out<s64> out_size,
+ Out<s64> out_alignment,
+ s64 width, s64 height) {
+ LOG_DEBUG(Service_VI, "called width={}, height={}", width, height);
+
+ constexpr u64 base_size = 0x20000;
+ const auto texture_size = width * height * 4;
+
+ *out_alignment = 0x1000;
+ *out_size = (texture_size + base_size - 1) / base_size * base_size;
+
+ R_SUCCEED();
+}
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/application_display_service.h b/src/core/hle/service/vi/application_display_service.h
new file mode 100644
index 000000000..1bdeb8f84
--- /dev/null
+++ b/src/core/hle/service/vi/application_display_service.h
@@ -0,0 +1,81 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <map>
+#include <set>
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/os/event.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/vi/vi_types.h"
+
+namespace Kernel {
+class KReadableEvent;
+}
+
+namespace Service::Nvnflinger {
+class IHOSBinderDriver;
+}
+
+namespace Service::VI {
+
+class Container;
+class IManagerDisplayService;
+class ISystemDisplayService;
+
+class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> {
+public:
+ IApplicationDisplayService(Core::System& system_, std::shared_ptr<Container> container);
+ ~IApplicationDisplayService() override;
+
+ std::shared_ptr<Container> GetContainer() const {
+ return m_container;
+ }
+
+public:
+ Result GetRelayService(Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_relay_service);
+ Result GetSystemDisplayService(
+ Out<SharedPointer<ISystemDisplayService>> out_system_display_service);
+ Result GetManagerDisplayService(
+ Out<SharedPointer<IManagerDisplayService>> out_manager_display_service);
+ Result GetIndirectDisplayTransactionService(
+ Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_indirect_display_transaction_service);
+ Result OpenDisplay(Out<u64> out_display_id, DisplayName display_name);
+ Result OpenDefaultDisplay(Out<u64> out_display_id);
+ Result CloseDisplay(u64 display_id);
+ Result SetDisplayEnabled(u32 state, u64 display_id);
+ Result GetDisplayResolution(Out<s64> out_width, Out<s64> out_height, u64 display_id);
+ Result SetLayerScalingMode(NintendoScaleMode scale_mode, u64 layer_id);
+ Result ListDisplays(Out<u64> out_count,
+ OutArray<DisplayInfo, BufferAttr_HipcMapAlias> out_displays);
+ Result OpenLayer(Out<u64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_native_window,
+ DisplayName display_name, u64 layer_id, ClientAppletResourceUserId aruid);
+ Result CloseLayer(u64 layer_id);
+ Result CreateStrayLayer(Out<u64> out_layer_id, Out<u64> out_size,
+ OutBuffer<BufferAttr_HipcMapAlias> out_native_window, u32 flags,
+ u64 display_id);
+ Result DestroyStrayLayer(u64 layer_id);
+ Result GetDisplayVsyncEvent(OutCopyHandle<Kernel::KReadableEvent> out_vsync_event,
+ u64 display_id);
+ Result ConvertScalingMode(Out<ConvertedScaleMode> out_scaling_mode, NintendoScaleMode mode);
+ Result GetIndirectLayerImageMap(
+ Out<u64> out_size, Out<u64> out_stride,
+ OutBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> out_buffer,
+ s64 width, s64 height, u64 indirect_layer_consumer_handle,
+ ClientAppletResourceUserId aruid);
+ Result GetIndirectLayerImageRequiredMemoryInfo(Out<s64> out_size, Out<s64> out_alignment,
+ s64 width, s64 height);
+
+private:
+ const std::shared_ptr<Container> m_container;
+
+ KernelHelpers::ServiceContext m_context;
+ std::mutex m_lock{};
+ std::set<u64> m_open_layer_ids{};
+ std::set<u64> m_stray_layer_ids{};
+ std::map<u64, Event> m_display_vsync_events{};
+ bool m_vsync_event_fetched{false};
+};
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/application_root_service.cpp b/src/core/hle/service/vi/application_root_service.cpp
new file mode 100644
index 000000000..7f35a048d
--- /dev/null
+++ b/src/core/hle/service/vi/application_root_service.cpp
@@ -0,0 +1,33 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/vi/application_display_service.h"
+#include "core/hle/service/vi/application_root_service.h"
+#include "core/hle/service/vi/container.h"
+#include "core/hle/service/vi/service_creator.h"
+#include "core/hle/service/vi/vi.h"
+#include "core/hle/service/vi/vi_types.h"
+
+namespace Service::VI {
+
+IApplicationRootService::IApplicationRootService(Core::System& system_,
+ std::shared_ptr<Container> container)
+ : ServiceFramework{system_, "vi:u"}, m_container{std::move(container)} {
+ static const FunctionInfo functions[] = {
+ {0, C<&IApplicationRootService::GetDisplayService>, "GetDisplayService"},
+ {1, nullptr, "GetDisplayServiceWithProxyNameExchange"},
+ };
+ RegisterHandlers(functions);
+}
+
+IApplicationRootService::~IApplicationRootService() = default;
+
+Result IApplicationRootService::GetDisplayService(
+ Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) {
+ LOG_DEBUG(Service_VI, "called");
+ R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_container,
+ Permission::User, policy));
+}
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/application_root_service.h b/src/core/hle/service/vi/application_root_service.h
new file mode 100644
index 000000000..15aa4483d
--- /dev/null
+++ b/src/core/hle/service/vi/application_root_service.h
@@ -0,0 +1,33 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::VI {
+
+class Container;
+class IApplicationDisplayService;
+enum class Policy : u32;
+
+class IApplicationRootService final : public ServiceFramework<IApplicationRootService> {
+public:
+ explicit IApplicationRootService(Core::System& system_, std::shared_ptr<Container> container);
+ ~IApplicationRootService() override;
+
+private:
+ Result GetDisplayService(
+ Out<SharedPointer<IApplicationDisplayService>> out_application_display_service,
+ Policy policy);
+
+private:
+ const std::shared_ptr<Container> m_container;
+};
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/conductor.cpp b/src/core/hle/service/vi/conductor.cpp
new file mode 100644
index 000000000..c8ce4fca0
--- /dev/null
+++ b/src/core/hle/service/vi/conductor.cpp
@@ -0,0 +1,114 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/settings.h"
+#include "core/core.h"
+#include "core/core_timing.h"
+#include "core/hle/service/vi/conductor.h"
+#include "core/hle/service/vi/container.h"
+#include "core/hle/service/vi/display_list.h"
+#include "core/hle/service/vi/vsync_manager.h"
+
+constexpr auto FrameNs = std::chrono::nanoseconds{1000000000 / 60};
+
+namespace Service::VI {
+
+Conductor::Conductor(Core::System& system, Container& container, DisplayList& displays)
+ : m_system(system), m_container(container) {
+ displays.ForEachDisplay([&](Display& display) {
+ m_vsync_managers.insert({display.GetId(), VsyncManager{}});
+ });
+
+ if (system.IsMulticore()) {
+ m_event = Core::Timing::CreateEvent(
+ "ScreenComposition",
+ [this](s64 time,
+ std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
+ m_signal.Set();
+ return std::chrono::nanoseconds(this->GetNextTicks());
+ });
+
+ system.CoreTiming().ScheduleLoopingEvent(FrameNs, FrameNs, m_event);
+ m_thread = std::jthread([this](std::stop_token token) { this->VsyncThread(token); });
+ } else {
+ m_event = Core::Timing::CreateEvent(
+ "ScreenComposition",
+ [this](s64 time,
+ std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
+ this->ProcessVsync();
+ return std::chrono::nanoseconds(this->GetNextTicks());
+ });
+
+ system.CoreTiming().ScheduleLoopingEvent(FrameNs, FrameNs, m_event);
+ }
+}
+
+Conductor::~Conductor() {
+ m_system.CoreTiming().UnscheduleEvent(m_event);
+
+ if (m_system.IsMulticore()) {
+ m_thread.request_stop();
+ m_signal.Set();
+ }
+}
+
+void Conductor::LinkVsyncEvent(u64 display_id, Event* event) {
+ if (auto it = m_vsync_managers.find(display_id); it != m_vsync_managers.end()) {
+ it->second.LinkVsyncEvent(event);
+ }
+}
+
+void Conductor::UnlinkVsyncEvent(u64 display_id, Event* event) {
+ if (auto it = m_vsync_managers.find(display_id); it != m_vsync_managers.end()) {
+ it->second.UnlinkVsyncEvent(event);
+ }
+}
+
+void Conductor::ProcessVsync() {
+ for (auto& [display_id, manager] : m_vsync_managers) {
+ m_container.ComposeOnDisplay(&m_swap_interval, &m_compose_speed_scale, display_id);
+ manager.SignalVsync();
+ }
+}
+
+void Conductor::VsyncThread(std::stop_token token) {
+ Common::SetCurrentThreadName("VSyncThread");
+
+ while (!token.stop_requested()) {
+ m_signal.Wait();
+
+ if (m_system.IsShuttingDown()) {
+ return;
+ }
+
+ this->ProcessVsync();
+ }
+}
+
+s64 Conductor::GetNextTicks() const {
+ const auto& settings = Settings::values;
+ auto speed_scale = 1.f;
+ if (settings.use_multi_core.GetValue()) {
+ if (settings.use_speed_limit.GetValue()) {
+ // Scales the speed based on speed_limit setting on MC. SC is handled by
+ // SpeedLimiter::DoSpeedLimiting.
+ speed_scale = 100.f / settings.speed_limit.GetValue();
+ } else {
+ // Run at unlocked framerate.
+ speed_scale = 0.01f;
+ }
+ }
+
+ // Adjust by speed limit determined during composition.
+ speed_scale /= m_compose_speed_scale;
+
+ if (m_system.GetNVDECActive() && settings.use_video_framerate.GetValue()) {
+ // Run at intended presentation rate during video playback.
+ speed_scale = 1.f;
+ }
+
+ const f32 effective_fps = 60.f / static_cast<f32>(m_swap_interval);
+ return static_cast<s64>(speed_scale * (1000000000.f / effective_fps));
+}
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/conductor.h b/src/core/hle/service/vi/conductor.h
new file mode 100644
index 000000000..52e3595d2
--- /dev/null
+++ b/src/core/hle/service/vi/conductor.h
@@ -0,0 +1,57 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <memory>
+#include <unordered_map>
+
+#include "common/common_types.h"
+#include "common/polyfill_thread.h"
+#include "common/thread.h"
+
+namespace Core {
+class System;
+}
+
+namespace Core::Timing {
+struct EventType;
+}
+
+namespace Service {
+class Event;
+}
+
+namespace Service::VI {
+
+class Container;
+class DisplayList;
+class VsyncManager;
+
+class Conductor {
+public:
+ explicit Conductor(Core::System& system, Container& container, DisplayList& displays);
+ ~Conductor();
+
+ void LinkVsyncEvent(u64 display_id, Event* event);
+ void UnlinkVsyncEvent(u64 display_id, Event* event);
+
+private:
+ void ProcessVsync();
+ void VsyncThread(std::stop_token token);
+ s64 GetNextTicks() const;
+
+private:
+ Core::System& m_system;
+ Container& m_container;
+ std::unordered_map<u64, VsyncManager> m_vsync_managers;
+ std::shared_ptr<Core::Timing::EventType> m_event;
+ Common::Event m_signal;
+ std::jthread m_thread;
+
+private:
+ s32 m_swap_interval = 1;
+ f32 m_compose_speed_scale = 1.0f;
+};
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/container.cpp b/src/core/hle/service/vi/container.cpp
new file mode 100644
index 000000000..310a207f1
--- /dev/null
+++ b/src/core/hle/service/vi/container.cpp
@@ -0,0 +1,228 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/core.h"
+#include "core/hle/service/nvdrv/nvdrv_interface.h"
+#include "core/hle/service/nvnflinger/buffer_queue_producer.h"
+#include "core/hle/service/nvnflinger/hos_binder_driver.h"
+#include "core/hle/service/nvnflinger/hos_binder_driver_server.h"
+#include "core/hle/service/nvnflinger/surface_flinger.h"
+#include "core/hle/service/sm/sm.h"
+#include "core/hle/service/vi/container.h"
+#include "core/hle/service/vi/vi_results.h"
+
+namespace Service::VI {
+
+Container::Container(Core::System& system) {
+ m_displays.CreateDisplay(DisplayName{"Default"});
+ m_displays.CreateDisplay(DisplayName{"External"});
+ m_displays.CreateDisplay(DisplayName{"Edid"});
+ m_displays.CreateDisplay(DisplayName{"Internal"});
+ m_displays.CreateDisplay(DisplayName{"Null"});
+
+ m_binder_driver =
+ system.ServiceManager().GetService<Nvnflinger::IHOSBinderDriver>("dispdrv", true);
+ m_surface_flinger = m_binder_driver->GetSurfaceFlinger();
+
+ const auto nvdrv =
+ system.ServiceManager().GetService<Nvidia::NVDRV>("nvdrv:s", true)->GetModule();
+ m_shared_buffer_manager.emplace(system, *this, nvdrv);
+
+ m_displays.ForEachDisplay(
+ [&](auto& display) { m_surface_flinger->AddDisplay(display.GetId()); });
+
+ m_conductor.emplace(system, *this, m_displays);
+}
+
+Container::~Container() {
+ this->OnTerminate();
+}
+
+void Container::OnTerminate() {
+ std::scoped_lock lk{m_lock};
+
+ m_is_shut_down = true;
+
+ m_layers.ForEachLayer([&](auto& layer) {
+ 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<Nvnflinger::IHOSBinderDriver>* out_binder_driver) {
+ *out_binder_driver = m_binder_driver;
+ R_SUCCEED();
+}
+
+Result Container::GetLayerProducerHandle(
+ std::shared_ptr<android::BufferQueueProducer>* out_producer, u64 layer_id) {
+ std::scoped_lock lk{m_lock};
+
+ auto* const layer = m_layers.GetLayerById(layer_id);
+ R_UNLESS(layer != nullptr, VI::ResultNotFound);
+
+ const auto binder = m_binder_driver->GetServer()->TryGetBinder(layer->GetProducerBinderId());
+ R_UNLESS(binder != nullptr, VI::ResultNotFound);
+
+ *out_producer = std::static_pointer_cast<android::BufferQueueProducer>(binder);
+ R_SUCCEED();
+}
+
+Result Container::OpenDisplay(u64* out_display_id, const DisplayName& display_name) {
+ auto* const display = m_displays.GetDisplayByName(display_name);
+ R_UNLESS(display != nullptr, VI::ResultNotFound);
+
+ *out_display_id = display->GetId();
+ R_SUCCEED();
+}
+
+Result Container::CloseDisplay(u64 display_id) {
+ R_SUCCEED();
+}
+
+Result Container::CreateManagedLayer(u64* out_layer_id, u64 display_id, u64 owner_aruid) {
+ std::scoped_lock lk{m_lock};
+ R_RETURN(this->CreateLayerLocked(out_layer_id, display_id, owner_aruid));
+}
+
+Result Container::DestroyManagedLayer(u64 layer_id) {
+ std::scoped_lock lk{m_lock};
+
+ // Try to close, if open, but don't fail if not.
+ this->CloseLayerLocked(layer_id);
+
+ R_RETURN(this->DestroyLayerLocked(layer_id));
+}
+
+Result Container::OpenLayer(s32* out_producer_binder_id, u64 layer_id, u64 aruid) {
+ std::scoped_lock lk{m_lock};
+ R_RETURN(this->OpenLayerLocked(out_producer_binder_id, layer_id, aruid));
+}
+
+Result Container::CloseLayer(u64 layer_id) {
+ std::scoped_lock lk{m_lock};
+ R_RETURN(this->CloseLayerLocked(layer_id));
+}
+
+Result Container::SetLayerVisibility(u64 layer_id, bool visible) {
+ std::scoped_lock lk{m_lock};
+
+ auto* const layer = m_layers.GetLayerById(layer_id);
+ R_UNLESS(layer != nullptr, VI::ResultNotFound);
+
+ m_surface_flinger->SetLayerVisibility(layer->GetConsumerBinderId(), visible);
+ R_SUCCEED();
+}
+
+Result Container::SetLayerBlending(u64 layer_id, bool enabled) {
+ std::scoped_lock lk{m_lock};
+
+ auto* const layer = m_layers.GetLayerById(layer_id);
+ R_UNLESS(layer != nullptr, VI::ResultNotFound);
+
+ m_surface_flinger->SetLayerBlending(layer->GetConsumerBinderId(),
+ enabled ? Nvnflinger::LayerBlending::Coverage
+ : Nvnflinger::LayerBlending::None);
+ R_SUCCEED();
+}
+
+void Container::LinkVsyncEvent(u64 display_id, Event* event) {
+ std::scoped_lock lk{m_lock};
+ m_conductor->LinkVsyncEvent(display_id, event);
+}
+
+void Container::UnlinkVsyncEvent(u64 display_id, Event* event) {
+ std::scoped_lock lk{m_lock};
+ m_conductor->UnlinkVsyncEvent(display_id, event);
+}
+
+Result Container::CreateStrayLayer(s32* out_producer_binder_id, u64* out_layer_id, u64 display_id) {
+ std::scoped_lock lk{m_lock};
+ R_TRY(this->CreateLayerLocked(out_layer_id, display_id, {}));
+ R_RETURN(this->OpenLayerLocked(out_producer_binder_id, *out_layer_id, {}));
+}
+
+Result Container::DestroyStrayLayer(u64 layer_id) {
+ std::scoped_lock lk{m_lock};
+ R_TRY(this->CloseLayerLocked(layer_id));
+ R_RETURN(this->DestroyLayerLocked(layer_id));
+}
+
+Result Container::CreateLayerLocked(u64* out_layer_id, u64 display_id, u64 owner_aruid) {
+ auto* const display = m_displays.GetDisplayById(display_id);
+ R_UNLESS(display != nullptr, VI::ResultNotFound);
+
+ 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());
+}
+
+bool Container::ComposeOnDisplay(s32* out_swap_interval, f32* out_compose_speed_scale,
+ u64 display_id) {
+ std::scoped_lock lk{m_lock};
+ return m_surface_flinger->ComposeDisplay(out_swap_interval, out_compose_speed_scale,
+ display_id);
+}
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/container.h b/src/core/hle/service/vi/container.h
new file mode 100644
index 000000000..cd0d2ca86
--- /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 <memory>
+#include <mutex>
+#include <optional>
+
+#include "core/hle/service/vi/conductor.h"
+#include "core/hle/service/vi/display_list.h"
+#include "core/hle/service/vi/layer_list.h"
+#include "core/hle/service/vi/shared_buffer_manager.h"
+
+union Result;
+
+namespace Service::android {
+class BufferQueueProducer;
+}
+
+namespace Service::Nvnflinger {
+class IHOSBinderDriver;
+class SurfaceFlinger;
+} // namespace Service::Nvnflinger
+
+namespace Service {
+class Event;
+}
+
+namespace Service::VI {
+
+class SharedBufferManager;
+
+class Container {
+public:
+ explicit Container(Core::System& system);
+ ~Container();
+
+ void OnTerminate();
+
+ SharedBufferManager* GetSharedBufferManager();
+
+ Result GetBinderDriver(std::shared_ptr<Nvnflinger::IHOSBinderDriver>* out_binder_driver);
+ Result GetLayerProducerHandle(std::shared_ptr<android::BufferQueueProducer>* out_producer,
+ u64 layer_id);
+
+ Result OpenDisplay(u64* out_display_id, const DisplayName& display_name);
+ Result CloseDisplay(u64 display_id);
+
+ // Managed layers are created by the interaction between am and ommdisp
+ // on behalf of an applet. Their lifetime ends with the lifetime of the
+ // applet's ISelfController.
+ Result CreateManagedLayer(u64* out_layer_id, u64 display_id, u64 owner_aruid);
+ Result DestroyManagedLayer(u64 layer_id);
+ Result OpenLayer(s32* out_producer_binder_id, u64 layer_id, u64 aruid);
+ Result CloseLayer(u64 layer_id);
+
+ // Stray layers are created by non-applet sysmodules. Their lifetime ends
+ // with the lifetime of the IApplicationDisplayService which created them.
+ Result CreateStrayLayer(s32* out_producer_binder_id, u64* out_layer_id, u64 display_id);
+ Result DestroyStrayLayer(u64 layer_id);
+
+ Result SetLayerVisibility(u64 layer_id, bool visible);
+ Result SetLayerBlending(u64 layer_id, bool enabled);
+
+ void LinkVsyncEvent(u64 display_id, Event* event);
+ void UnlinkVsyncEvent(u64 display_id, Event* event);
+
+private:
+ Result CreateLayerLocked(u64* out_layer_id, u64 display_id, u64 owner_aruid);
+ Result DestroyLayerLocked(u64 layer_id);
+ Result OpenLayerLocked(s32* out_producer_binder_id, u64 layer_id, u64 aruid);
+ Result CloseLayerLocked(u64 layer_id);
+
+ void CreateBufferQueueLocked(Layer* layer);
+ void DestroyBufferQueueLocked(Layer* layer);
+
+public:
+ bool ComposeOnDisplay(s32* out_swap_interval, f32* out_compose_speed_scale, u64 display_id);
+
+private:
+ std::mutex m_lock{};
+ DisplayList m_displays{};
+ LayerList m_layers{};
+ std::shared_ptr<Nvnflinger::IHOSBinderDriver> m_binder_driver{};
+ std::shared_ptr<Nvnflinger::SurfaceFlinger> m_surface_flinger{};
+ std::optional<SharedBufferManager> m_shared_buffer_manager{};
+ std::optional<Conductor> m_conductor{};
+ bool m_is_shut_down{};
+};
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/display.h b/src/core/hle/service/vi/display.h
new file mode 100644
index 000000000..fceda75e3
--- /dev/null
+++ b/src/core/hle/service/vi/display.h
@@ -0,0 +1,44 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/vi/vi_types.h"
+
+namespace Service::VI {
+
+class Display {
+public:
+ constexpr Display() = default;
+
+ void Initialize(u64 id, const DisplayName& display_name) {
+ m_id = id;
+ m_display_name = display_name;
+ m_is_initialized = true;
+ }
+
+ void Finalize() {
+ m_id = {};
+ m_display_name = {};
+ m_is_initialized = {};
+ }
+
+ u64 GetId() const {
+ return m_id;
+ }
+
+ const DisplayName& GetDisplayName() const {
+ return m_display_name;
+ }
+
+ bool IsInitialized() const {
+ return m_is_initialized;
+ }
+
+private:
+ u64 m_id{};
+ DisplayName m_display_name{};
+ bool m_is_initialized{};
+};
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp
deleted file mode 100644
index 7f2af9acc..000000000
--- a/src/core/hle/service/vi/display/vi_display.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include <algorithm>
-#include <utility>
-
-#include <fmt/format.h>
-
-#include "common/assert.h"
-#include "core/core.h"
-#include "core/hle/kernel/k_event.h"
-#include "core/hle/kernel/k_readable_event.h"
-#include "core/hle/service/kernel_helpers.h"
-#include "core/hle/service/nvdrv/core/container.h"
-#include "core/hle/service/nvnflinger/buffer_item_consumer.h"
-#include "core/hle/service/nvnflinger/buffer_queue_consumer.h"
-#include "core/hle/service/nvnflinger/buffer_queue_core.h"
-#include "core/hle/service/nvnflinger/buffer_queue_producer.h"
-#include "core/hle/service/nvnflinger/hardware_composer.h"
-#include "core/hle/service/nvnflinger/hos_binder_driver_server.h"
-#include "core/hle/service/vi/display/vi_display.h"
-#include "core/hle/service/vi/layer/vi_layer.h"
-#include "core/hle/service/vi/vi_results.h"
-
-namespace Service::VI {
-
-struct BufferQueue {
- std::shared_ptr<android::BufferQueueCore> core;
- std::unique_ptr<android::BufferQueueProducer> producer;
- std::unique_ptr<android::BufferQueueConsumer> consumer;
-};
-
-static BufferQueue CreateBufferQueue(KernelHelpers::ServiceContext& service_context,
- Service::Nvidia::NvCore::NvMap& nvmap) {
- auto buffer_queue_core = std::make_shared<android::BufferQueueCore>();
- return {
- buffer_queue_core,
- std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core, nvmap),
- std::make_unique<android::BufferQueueConsumer>(buffer_queue_core)};
-}
-
-Display::Display(u64 id, std::string name_,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_,
- KernelHelpers::ServiceContext& service_context_, Core::System& system_)
- : display_id{id}, name{std::move(name_)}, hos_binder_driver_server{hos_binder_driver_server_},
- service_context{service_context_} {
- hardware_composer = std::make_unique<Nvnflinger::HardwareComposer>();
- vsync_event = service_context.CreateEvent(fmt::format("Display VSync Event {}", id));
-}
-
-Display::~Display() {
- service_context.CloseEvent(vsync_event);
-}
-
-Layer& Display::GetLayer(std::size_t index) {
- size_t i = 0;
- for (auto& layer : layers) {
- if (!layer->IsOpen() || !layer->IsVisible()) {
- continue;
- }
-
- if (i == index) {
- return *layer;
- }
-
- i++;
- }
-
- UNREACHABLE();
-}
-
-size_t Display::GetNumLayers() const {
- return std::ranges::count_if(layers, [](auto& l) { return l->IsOpen() && l->IsVisible(); });
-}
-
-Kernel::KReadableEvent* Display::GetVSyncEvent() {
- return &vsync_event->GetReadableEvent();
-}
-
-void Display::SignalVSyncEvent() {
- vsync_event->Signal();
-}
-
-void Display::CreateLayer(u64 layer_id, u32 binder_id,
- Service::Nvidia::NvCore::Container& nv_core) {
- auto [core, producer, consumer] = CreateBufferQueue(service_context, nv_core.GetNvMapFile());
-
- auto buffer_item_consumer = std::make_shared<android::BufferItemConsumer>(std::move(consumer));
- buffer_item_consumer->Connect(false);
-
- layers.emplace_back(std::make_unique<Layer>(layer_id, binder_id, *core, *producer,
- std::move(buffer_item_consumer)));
-
- if (is_abandoned) {
- this->FindLayer(layer_id)->GetConsumer().Abandon();
- }
-
- hos_binder_driver_server.RegisterProducer(std::move(producer));
-}
-
-void Display::DestroyLayer(u64 layer_id) {
- if (auto* layer = this->FindLayer(layer_id); layer != nullptr) {
- layer->GetConsumer().Abandon();
- }
-
- std::erase_if(layers,
- [layer_id](const auto& layer) { return layer->GetLayerId() == layer_id; });
-}
-
-void Display::Abandon() {
- for (auto& layer : layers) {
- layer->GetConsumer().Abandon();
- }
- is_abandoned = true;
-}
-
-Layer* Display::FindLayer(u64 layer_id) {
- const auto itr =
- std::find_if(layers.begin(), layers.end(), [layer_id](const std::unique_ptr<Layer>& layer) {
- return layer->GetLayerId() == layer_id;
- });
-
- if (itr == layers.end()) {
- return nullptr;
- }
-
- return itr->get();
-}
-
-const Layer* Display::FindLayer(u64 layer_id) const {
- const auto itr =
- std::find_if(layers.begin(), layers.end(), [layer_id](const std::unique_ptr<Layer>& layer) {
- return layer->GetLayerId() == layer_id;
- });
-
- if (itr == layers.end()) {
- return nullptr;
- }
-
- return itr->get();
-}
-
-} // namespace Service::VI
diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h
deleted file mode 100644
index 220292cff..000000000
--- a/src/core/hle/service/vi/display/vi_display.h
+++ /dev/null
@@ -1,143 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "common/common_funcs.h"
-#include "common/common_types.h"
-#include "core/hle/result.h"
-
-namespace Core {
-class System;
-}
-
-namespace Kernel {
-class KEvent;
-class KReadableEvent;
-} // namespace Kernel
-
-namespace Service::android {
-class BufferQueueProducer;
-}
-
-namespace Service::KernelHelpers {
-class ServiceContext;
-}
-
-namespace Service::Nvnflinger {
-class HardwareComposer;
-class HosBinderDriverServer;
-} // namespace Service::Nvnflinger
-
-namespace Service::Nvidia::NvCore {
-class Container;
-class NvMap;
-} // namespace Service::Nvidia::NvCore
-
-namespace Service::VI {
-
-class Layer;
-
-/// Represents a single display type
-class Display {
-public:
- YUZU_NON_COPYABLE(Display);
- YUZU_NON_MOVEABLE(Display);
-
- /// Constructs a display with a given unique ID and name.
- ///
- /// @param id The unique ID for this display.
- /// @param hos_binder_driver_server_ Nvnflinger HOSBinderDriver server instance.
- /// @param service_context_ The ServiceContext for the owning service.
- /// @param name_ The name for this display.
- /// @param system_ The global system instance.
- ///
- Display(u64 id, std::string name_, Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_,
- KernelHelpers::ServiceContext& service_context_, Core::System& system_);
- ~Display();
-
- /// Gets the unique ID assigned to this display.
- u64 GetID() const {
- return display_id;
- }
-
- /// Gets the name of this display
- const std::string& GetName() const {
- return name;
- }
-
- /// Whether or not this display has any layers added to it.
- bool HasLayers() const {
- return GetNumLayers() > 0;
- }
-
- /// Gets a layer for this display based off an index.
- Layer& GetLayer(std::size_t index);
-
- std::size_t GetNumLayers() const;
-
- /// Gets the internal vsync event.
- Kernel::KReadableEvent* GetVSyncEvent();
-
- /// Signals the internal vsync event.
- void SignalVSyncEvent();
-
- /// Creates and adds a layer to this display with the given ID.
- ///
- /// @param layer_id The ID to assign to the created layer.
- /// @param binder_id The ID assigned to the buffer queue.
- ///
- void CreateLayer(u64 layer_id, u32 binder_id, Service::Nvidia::NvCore::Container& core);
-
- /// Removes a layer from this display with the given ID.
- ///
- /// @param layer_id The ID assigned to the layer to destroy.
- ///
- void DestroyLayer(u64 layer_id);
-
- /// Resets the display for a new connection.
- void Reset() {
- layers.clear();
- }
-
- void Abandon();
-
- /// Attempts to find a layer with the given ID.
- ///
- /// @param layer_id The layer ID.
- ///
- /// @returns If found, the Layer instance with the given ID.
- /// If not found, then nullptr is returned.
- ///
- Layer* FindLayer(u64 layer_id);
-
- /// Attempts to find a layer with the given ID.
- ///
- /// @param layer_id The layer ID.
- ///
- /// @returns If found, the Layer instance with the given ID.
- /// If not found, then nullptr is returned.
- ///
- const Layer* FindLayer(u64 layer_id) const;
-
- Nvnflinger::HardwareComposer& GetComposer() const {
- return *hardware_composer;
- }
-
-private:
- u64 display_id;
- std::string name;
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server;
- KernelHelpers::ServiceContext& service_context;
-
- std::vector<std::unique_ptr<Layer>> layers;
- std::unique_ptr<Nvnflinger::HardwareComposer> hardware_composer;
- Kernel::KEvent* vsync_event{};
- bool is_abandoned{};
-};
-
-} // namespace Service::VI
diff --git a/src/core/hle/service/vi/display_list.h b/src/core/hle/service/vi/display_list.h
new file mode 100644
index 000000000..f710ac472
--- /dev/null
+++ b/src/core/hle/service/vi/display_list.h
@@ -0,0 +1,83 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <cstring>
+
+#include "core/hle/service/vi/display.h"
+
+namespace Service::VI {
+
+class DisplayList {
+public:
+ constexpr DisplayList() = default;
+
+ bool CreateDisplay(const DisplayName& name) {
+ Display* const display = this->GetFreeDisplay();
+ if (!display) {
+ return false;
+ }
+
+ display->Initialize(m_next_id++, name);
+ return true;
+ }
+
+ bool DestroyDisplay(u64 display_id) {
+ Display* display = this->GetDisplayById(display_id);
+ if (!display) {
+ return false;
+ }
+
+ display->Finalize();
+ return true;
+ }
+
+ Display* GetDisplayByName(const DisplayName& name) {
+ for (auto& display : m_displays) {
+ if (display.IsInitialized() &&
+ std::strncmp(name.data(), display.GetDisplayName().data(), sizeof(DisplayName)) ==
+ 0) {
+ return &display;
+ }
+ }
+
+ return nullptr;
+ }
+
+ Display* GetDisplayById(u64 display_id) {
+ for (auto& display : m_displays) {
+ if (display.IsInitialized() && display.GetId() == display_id) {
+ return &display;
+ }
+ }
+
+ return nullptr;
+ }
+
+ template <typename F>
+ void ForEachDisplay(F&& cb) {
+ for (auto& display : m_displays) {
+ if (display.IsInitialized()) {
+ cb(display);
+ }
+ }
+ }
+
+private:
+ Display* GetFreeDisplay() {
+ for (auto& display : m_displays) {
+ if (!display.IsInitialized()) {
+ return &display;
+ }
+ }
+
+ return nullptr;
+ }
+
+private:
+ std::array<Display, 8> m_displays{};
+ u64 m_next_id{};
+};
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/layer.h b/src/core/hle/service/vi/layer.h
new file mode 100644
index 000000000..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/vi_layer.cpp b/src/core/hle/service/vi/layer/vi_layer.cpp
deleted file mode 100644
index eca35d82a..000000000
--- a/src/core/hle/service/vi/layer/vi_layer.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "core/hle/service/nvnflinger/hwc_layer.h"
-#include "core/hle/service/vi/layer/vi_layer.h"
-
-namespace Service::VI {
-
-Layer::Layer(u64 layer_id_, u32 binder_id_, android::BufferQueueCore& core_,
- android::BufferQueueProducer& binder_,
- std::shared_ptr<android::BufferItemConsumer>&& consumer_)
- : layer_id{layer_id_}, binder_id{binder_id_}, core{core_}, binder{binder_}, consumer{std::move(
- consumer_)},
- blending{Nvnflinger::LayerBlending::None}, open{false}, visible{true} {}
-
-Layer::~Layer() = default;
-
-} // namespace Service::VI
diff --git a/src/core/hle/service/vi/layer/vi_layer.h b/src/core/hle/service/vi/layer/vi_layer.h
deleted file mode 100644
index 14e229903..000000000
--- a/src/core/hle/service/vi/layer/vi_layer.h
+++ /dev/null
@@ -1,118 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <memory>
-#include <utility>
-
-#include "common/common_types.h"
-
-namespace Service::android {
-class BufferItemConsumer;
-class BufferQueueCore;
-class BufferQueueProducer;
-} // namespace Service::android
-
-namespace Service::Nvnflinger {
-enum class LayerBlending : u32;
-}
-
-namespace Service::VI {
-
-/// Represents a single display layer.
-class Layer {
-public:
- /// Constructs a layer with a given ID and buffer queue.
- ///
- /// @param layer_id_ The ID to assign to this layer.
- /// @param binder_id_ The binder ID to assign to this layer.
- /// @param binder_ The buffer producer queue for this layer to use.
- ///
- Layer(u64 layer_id_, u32 binder_id_, android::BufferQueueCore& core_,
- android::BufferQueueProducer& binder_,
- std::shared_ptr<android::BufferItemConsumer>&& consumer_);
- ~Layer();
-
- Layer(const Layer&) = delete;
- Layer& operator=(const Layer&) = delete;
-
- Layer(Layer&&) = default;
- Layer& operator=(Layer&&) = delete;
-
- /// Gets the ID for this layer.
- u64 GetLayerId() const {
- return layer_id;
- }
-
- /// Gets the binder ID for this layer.
- u32 GetBinderId() const {
- return binder_id;
- }
-
- /// Gets a reference to the buffer queue this layer is using.
- android::BufferQueueProducer& GetBufferQueue() {
- return binder;
- }
-
- /// Gets a const reference to the buffer queue this layer is using.
- const android::BufferQueueProducer& GetBufferQueue() const {
- return binder;
- }
-
- android::BufferItemConsumer& GetConsumer() {
- return *consumer;
- }
-
- const android::BufferItemConsumer& GetConsumer() const {
- return *consumer;
- }
-
- android::BufferQueueCore& Core() {
- return core;
- }
-
- const android::BufferQueueCore& Core() const {
- return core;
- }
-
- bool IsVisible() const {
- return visible;
- }
-
- void SetVisibility(bool v) {
- visible = v;
- }
-
- bool IsOpen() const {
- return open;
- }
-
- bool Close() {
- return std::exchange(open, false);
- }
-
- bool Open() {
- return !std::exchange(open, true);
- }
-
- Nvnflinger::LayerBlending GetBlending() {
- return blending;
- }
-
- void SetBlending(Nvnflinger::LayerBlending b) {
- blending = b;
- }
-
-private:
- const u64 layer_id;
- const u32 binder_id;
- android::BufferQueueCore& core;
- android::BufferQueueProducer& binder;
- std::shared_ptr<android::BufferItemConsumer> consumer;
- Service::Nvnflinger::LayerBlending blending;
- bool open;
- bool visible;
-};
-
-} // namespace Service::VI
diff --git a/src/core/hle/service/vi/layer_list.h b/src/core/hle/service/vi/layer_list.h
new file mode 100644
index 000000000..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 <typename F>
+ void ForEachLayer(F&& cb) {
+ for (auto& layer : m_layers) {
+ if (layer.IsInitialized()) {
+ cb(layer);
+ }
+ }
+ }
+
+private:
+ Layer* GetFreeLayer() {
+ for (auto& layer : m_layers) {
+ if (!layer.IsInitialized()) {
+ return &layer;
+ }
+ }
+
+ return nullptr;
+ }
+
+private:
+ std::array<Layer, 8> m_layers{};
+ u64 m_next_id{};
+};
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/manager_display_service.cpp b/src/core/hle/service/vi/manager_display_service.cpp
new file mode 100644
index 000000000..9f856282e
--- /dev/null
+++ b/src/core/hle/service/vi/manager_display_service.cpp
@@ -0,0 +1,140 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/vi/container.h"
+#include "core/hle/service/vi/manager_display_service.h"
+
+namespace Service::VI {
+
+IManagerDisplayService::IManagerDisplayService(Core::System& system_,
+ std::shared_ptr<Container> container)
+ : ServiceFramework{system_, "IManagerDisplayService"}, m_container{std::move(container)} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {200, nullptr, "AllocateProcessHeapBlock"},
+ {201, nullptr, "FreeProcessHeapBlock"},
+ {1102, nullptr, "GetDisplayResolution"},
+ {2010, C<&IManagerDisplayService::CreateManagedLayer>, "CreateManagedLayer"},
+ {2011, C<&IManagerDisplayService::DestroyManagedLayer>, "DestroyManagedLayer"},
+ {2012, nullptr, "CreateStrayLayer"},
+ {2050, nullptr, "CreateIndirectLayer"},
+ {2051, nullptr, "DestroyIndirectLayer"},
+ {2052, nullptr, "CreateIndirectProducerEndPoint"},
+ {2053, nullptr, "DestroyIndirectProducerEndPoint"},
+ {2054, nullptr, "CreateIndirectConsumerEndPoint"},
+ {2055, nullptr, "DestroyIndirectConsumerEndPoint"},
+ {2060, nullptr, "CreateWatermarkCompositor"},
+ {2062, nullptr, "SetWatermarkText"},
+ {2063, nullptr, "SetWatermarkLayerStacks"},
+ {2300, nullptr, "AcquireLayerTexturePresentingEvent"},
+ {2301, nullptr, "ReleaseLayerTexturePresentingEvent"},
+ {2302, nullptr, "GetDisplayHotplugEvent"},
+ {2303, nullptr, "GetDisplayModeChangedEvent"},
+ {2402, nullptr, "GetDisplayHotplugState"},
+ {2501, nullptr, "GetCompositorErrorInfo"},
+ {2601, nullptr, "GetDisplayErrorEvent"},
+ {2701, nullptr, "GetDisplayFatalErrorEvent"},
+ {4201, nullptr, "SetDisplayAlpha"},
+ {4203, nullptr, "SetDisplayLayerStack"},
+ {4205, nullptr, "SetDisplayPowerState"},
+ {4206, nullptr, "SetDefaultDisplay"},
+ {4207, nullptr, "ResetDisplayPanel"},
+ {4208, nullptr, "SetDisplayFatalErrorEnabled"},
+ {4209, nullptr, "IsDisplayPanelOn"},
+ {4300, nullptr, "GetInternalPanelId"},
+ {6000, C<&IManagerDisplayService::AddToLayerStack>, "AddToLayerStack"},
+ {6001, nullptr, "RemoveFromLayerStack"},
+ {6002, C<&IManagerDisplayService::SetLayerVisibility>, "SetLayerVisibility"},
+ {6003, nullptr, "SetLayerConfig"},
+ {6004, nullptr, "AttachLayerPresentationTracer"},
+ {6005, nullptr, "DetachLayerPresentationTracer"},
+ {6006, nullptr, "StartLayerPresentationRecording"},
+ {6007, nullptr, "StopLayerPresentationRecording"},
+ {6008, nullptr, "StartLayerPresentationFenceWait"},
+ {6009, nullptr, "StopLayerPresentationFenceWait"},
+ {6010, nullptr, "GetLayerPresentationAllFencesExpiredEvent"},
+ {6011, nullptr, "EnableLayerAutoClearTransitionBuffer"},
+ {6012, nullptr, "DisableLayerAutoClearTransitionBuffer"},
+ {6013, nullptr, "SetLayerOpacity"},
+ {6014, nullptr, "AttachLayerWatermarkCompositor"},
+ {6015, nullptr, "DetachLayerWatermarkCompositor"},
+ {7000, nullptr, "SetContentVisibility"},
+ {8000, nullptr, "SetConductorLayer"},
+ {8001, nullptr, "SetTimestampTracking"},
+ {8100, nullptr, "SetIndirectProducerFlipOffset"},
+ {8200, nullptr, "CreateSharedBufferStaticStorage"},
+ {8201, nullptr, "CreateSharedBufferTransferMemory"},
+ {8202, nullptr, "DestroySharedBuffer"},
+ {8203, nullptr, "BindSharedLowLevelLayerToManagedLayer"},
+ {8204, nullptr, "BindSharedLowLevelLayerToIndirectLayer"},
+ {8207, nullptr, "UnbindSharedLowLevelLayer"},
+ {8208, nullptr, "ConnectSharedLowLevelLayerToSharedBuffer"},
+ {8209, nullptr, "DisconnectSharedLowLevelLayerFromSharedBuffer"},
+ {8210, nullptr, "CreateSharedLayer"},
+ {8211, nullptr, "DestroySharedLayer"},
+ {8216, nullptr, "AttachSharedLayerToLowLevelLayer"},
+ {8217, nullptr, "ForceDetachSharedLayerFromLowLevelLayer"},
+ {8218, nullptr, "StartDetachSharedLayerFromLowLevelLayer"},
+ {8219, nullptr, "FinishDetachSharedLayerFromLowLevelLayer"},
+ {8220, nullptr, "GetSharedLayerDetachReadyEvent"},
+ {8221, nullptr, "GetSharedLowLevelLayerSynchronizedEvent"},
+ {8222, nullptr, "CheckSharedLowLevelLayerSynchronized"},
+ {8223, nullptr, "RegisterSharedBufferImporterAruid"},
+ {8224, nullptr, "UnregisterSharedBufferImporterAruid"},
+ {8227, nullptr, "CreateSharedBufferProcessHeap"},
+ {8228, nullptr, "GetSharedLayerLayerStacks"},
+ {8229, nullptr, "SetSharedLayerLayerStacks"},
+ {8291, nullptr, "PresentDetachedSharedFrameBufferToLowLevelLayer"},
+ {8292, nullptr, "FillDetachedSharedFrameBufferColor"},
+ {8293, nullptr, "GetDetachedSharedFrameBufferImage"},
+ {8294, nullptr, "SetDetachedSharedFrameBufferImage"},
+ {8295, nullptr, "CopyDetachedSharedFrameBufferImage"},
+ {8296, nullptr, "SetDetachedSharedFrameBufferSubImage"},
+ {8297, nullptr, "GetSharedFrameBufferContentParameter"},
+ {8298, nullptr, "ExpandStartupLogoOnSharedFrameBuffer"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IManagerDisplayService::~IManagerDisplayService() = default;
+
+Result IManagerDisplayService::CreateSharedLayerSession(Kernel::KProcess* owner_process,
+ u64* out_buffer_id, u64* out_layer_handle,
+ u64 display_id, bool enable_blending) {
+ R_RETURN(m_container->GetSharedBufferManager()->CreateSession(
+ owner_process, out_buffer_id, out_layer_handle, display_id, enable_blending));
+}
+
+void IManagerDisplayService::DestroySharedLayerSession(Kernel::KProcess* owner_process) {
+ m_container->GetSharedBufferManager()->DestroySession(owner_process);
+}
+
+Result IManagerDisplayService::SetLayerBlending(bool enabled, u64 layer_id) {
+ R_RETURN(m_container->SetLayerBlending(layer_id, enabled));
+}
+
+Result IManagerDisplayService::CreateManagedLayer(Out<u64> out_layer_id, u32 flags, u64 display_id,
+ AppletResourceUserId aruid) {
+ LOG_DEBUG(Service_VI, "called. flags={}, display={}, aruid={}", flags, display_id, aruid.pid);
+ R_RETURN(m_container->CreateManagedLayer(out_layer_id, display_id, aruid.pid));
+}
+
+Result IManagerDisplayService::DestroyManagedLayer(u64 layer_id) {
+ LOG_DEBUG(Service_VI, "called. layer_id={}", layer_id);
+ R_RETURN(m_container->DestroyManagedLayer(layer_id));
+}
+
+Result IManagerDisplayService::AddToLayerStack(u32 stack_id, u64 layer_id) {
+ LOG_WARNING(Service_VI, "(STUBBED) called. stack_id={}, layer_id={}", stack_id, layer_id);
+ R_SUCCEED();
+}
+
+Result IManagerDisplayService::SetLayerVisibility(bool visible, u64 layer_id) {
+ LOG_DEBUG(Service_VI, "called, layer_id={}, visible={}", layer_id, visible);
+ R_RETURN(m_container->SetLayerVisibility(layer_id, visible));
+}
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/manager_display_service.h b/src/core/hle/service/vi/manager_display_service.h
new file mode 100644
index 000000000..b1bdf7f41
--- /dev/null
+++ b/src/core/hle/service/vi/manager_display_service.h
@@ -0,0 +1,37 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Kernel {
+class KProcess;
+}
+
+namespace Service::VI {
+
+class Container;
+
+class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> {
+public:
+ explicit IManagerDisplayService(Core::System& system_, std::shared_ptr<Container> container);
+ ~IManagerDisplayService() override;
+
+ Result CreateSharedLayerSession(Kernel::KProcess* owner_process, u64* out_buffer_id,
+ u64* out_layer_handle, u64 display_id, bool enable_blending);
+ void DestroySharedLayerSession(Kernel::KProcess* owner_process);
+
+ Result SetLayerBlending(bool enabled, u64 layer_id);
+
+public:
+ Result CreateManagedLayer(Out<u64> out_layer_id, u32 flags, u64 display_id,
+ AppletResourceUserId aruid);
+ Result DestroyManagedLayer(u64 layer_id);
+ Result AddToLayerStack(u32 stack_id, u64 layer_id);
+ Result SetLayerVisibility(bool visible, u64 layer_id);
+
+private:
+ const std::shared_ptr<Container> m_container;
+};
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/manager_root_service.cpp b/src/core/hle/service/vi/manager_root_service.cpp
new file mode 100644
index 000000000..0f16a15b4
--- /dev/null
+++ b/src/core/hle/service/vi/manager_root_service.cpp
@@ -0,0 +1,38 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/nvnflinger/hos_binder_driver.h"
+#include "core/hle/service/vi/application_display_service.h"
+#include "core/hle/service/vi/container.h"
+#include "core/hle/service/vi/manager_root_service.h"
+#include "core/hle/service/vi/service_creator.h"
+#include "core/hle/service/vi/vi.h"
+#include "core/hle/service/vi/vi_types.h"
+
+namespace Service::VI {
+
+IManagerRootService::IManagerRootService(Core::System& system_,
+ std::shared_ptr<Container> container)
+ : ServiceFramework{system_, "vi:m"}, m_container{std::move(container)} {
+ static const FunctionInfo functions[] = {
+ {2, C<&IManagerRootService::GetDisplayService>, "GetDisplayService"},
+ {3, nullptr, "GetDisplayServiceWithProxyNameExchange"},
+ {100, nullptr, "PrepareFatal"},
+ {101, nullptr, "ShowFatal"},
+ {102, nullptr, "DrawFatalRectangle"},
+ {103, nullptr, "DrawFatalText32"},
+ };
+ RegisterHandlers(functions);
+}
+
+IManagerRootService::~IManagerRootService() = default;
+
+Result IManagerRootService::GetDisplayService(
+ Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) {
+ LOG_DEBUG(Service_VI, "called");
+ R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_container,
+ Permission::Manager, policy));
+}
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/manager_root_service.h b/src/core/hle/service/vi/manager_root_service.h
new file mode 100644
index 000000000..77cd32869
--- /dev/null
+++ b/src/core/hle/service/vi/manager_root_service.h
@@ -0,0 +1,32 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::VI {
+
+class Container;
+class IApplicationDisplayService;
+enum class Policy : u32;
+
+class IManagerRootService final : public ServiceFramework<IManagerRootService> {
+public:
+ explicit IManagerRootService(Core::System& system_, std::shared_ptr<Container> container);
+ ~IManagerRootService() override;
+
+ Result GetDisplayService(
+ Out<SharedPointer<IApplicationDisplayService>> out_application_display_service,
+ Policy policy);
+
+private:
+ const std::shared_ptr<Container> m_container;
+};
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/service_creator.cpp b/src/core/hle/service/vi/service_creator.cpp
new file mode 100644
index 000000000..2b8e5f957
--- /dev/null
+++ b/src/core/hle/service/vi/service_creator.cpp
@@ -0,0 +1,38 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/vi/application_display_service.h"
+#include "core/hle/service/vi/service_creator.h"
+#include "core/hle/service/vi/vi_results.h"
+#include "core/hle/service/vi/vi_types.h"
+
+namespace Service::VI {
+
+static bool IsValidServiceAccess(Permission permission, Policy policy) {
+ if (permission == Permission::User) {
+ return policy == Policy::User;
+ }
+
+ if (permission == Permission::System || permission == Permission::Manager) {
+ return policy == Policy::User || policy == Policy::Compositor;
+ }
+
+ return false;
+}
+
+Result GetApplicationDisplayService(
+ std::shared_ptr<IApplicationDisplayService>* out_application_display_service,
+ Core::System& system, std::shared_ptr<Container> container, Permission permission,
+ Policy policy) {
+
+ if (!IsValidServiceAccess(permission, policy)) {
+ LOG_ERROR(Service_VI, "Permission denied for policy {}", policy);
+ R_THROW(ResultPermissionDenied);
+ }
+
+ *out_application_display_service =
+ std::make_shared<IApplicationDisplayService>(system, std::move(container));
+ R_SUCCEED();
+}
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/service_creator.h b/src/core/hle/service/vi/service_creator.h
new file mode 100644
index 000000000..c6ba1797d
--- /dev/null
+++ b/src/core/hle/service/vi/service_creator.h
@@ -0,0 +1,28 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <memory>
+
+#include "common/common_types.h"
+
+namespace Core {
+class System;
+}
+
+union Result;
+
+namespace Service::VI {
+
+class Container;
+class IApplicationDisplayService;
+enum class Permission;
+enum class Policy : u32;
+
+Result GetApplicationDisplayService(
+ std::shared_ptr<IApplicationDisplayService>* out_application_display_service,
+ Core::System& system, std::shared_ptr<Container> container, Permission permission,
+ Policy policy);
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp b/src/core/hle/service/vi/shared_buffer_manager.cpp
index 90f7248a0..869b18961 100644
--- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
+++ b/src/core/hle/service/vi/shared_buffer_manager.cpp
@@ -9,15 +9,15 @@
#include "core/hle/service/nvdrv/devices/nvmap.h"
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/nvnflinger/buffer_queue_producer.h"
-#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
#include "core/hle/service/nvnflinger/pixel_format.h"
#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
-#include "core/hle/service/vi/layer/vi_layer.h"
+#include "core/hle/service/vi/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::Nvnflinger {
+namespace Service::VI {
namespace {
@@ -26,7 +26,6 @@ Result AllocateSharedBufferMemory(std::unique_ptr<Kernel::KPageGroup>* out_page_
using Core::Memory::YUZU_PAGESIZE;
// Allocate memory for the system shared buffer.
- // FIXME: This memory belongs to vi's .data section.
auto& kernel = system.Kernel();
// Hold a temporary page group reference while we try to map it.
@@ -204,15 +203,15 @@ void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 han
} // namespace
-FbShareBufferManager::FbShareBufferManager(Core::System& system, Nvnflinger& flinger,
- std::shared_ptr<Nvidia::Module> nvdrv)
- : m_system(system), m_flinger(flinger), m_nvdrv(std::move(nvdrv)) {}
+SharedBufferManager::SharedBufferManager(Core::System& system, Container& container,
+ std::shared_ptr<Nvidia::Module> nvdrv)
+ : m_system(system), m_container(container), m_nvdrv(std::move(nvdrv)) {}
-FbShareBufferManager::~FbShareBufferManager() = default;
+SharedBufferManager::~SharedBufferManager() = default;
-Result FbShareBufferManager::Initialize(Kernel::KProcess* owner_process, u64* out_buffer_id,
- u64* out_layer_handle, u64 display_id,
- LayerBlending blending) {
+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.
@@ -237,7 +236,7 @@ Result FbShareBufferManager::Initialize(Kernel::KProcess* owner_process, u64* ou
owner_process, m_system));
// Create new session.
- auto [it, was_emplaced] = m_sessions.emplace(aruid, FbShareSession{});
+ auto [it, was_emplaced] = m_sessions.emplace(aruid, SharedBufferSession{});
auto& session = it->second;
auto& container = m_nvdrv->GetContainer();
@@ -249,17 +248,18 @@ Result FbShareBufferManager::Initialize(Kernel::KProcess* owner_process, u64* ou
session.nvmap_fd, map_address, SharedBufferSize));
// Create and open a layer for the display.
- session.layer_id = m_flinger.CreateLayer(m_display_id, blending).value();
- m_flinger.OpenLayer(session.layer_id);
+ s32 producer_binder_id;
+ R_TRY(m_container.CreateStrayLayer(std::addressof(producer_binder_id),
+ std::addressof(session.layer_id), display_id));
- // Get the layer.
- VI::Layer* layer = m_flinger.FindLayer(m_display_id, session.layer_id);
- ASSERT(layer != nullptr);
+ // Configure blending.
+ R_ASSERT(m_container.SetLayerBlending(session.layer_id, enable_blending));
// Get the producer and set preallocated buffers.
- auto& producer = layer->GetBufferQueue();
- MakeGraphicBuffer(producer, 0, session.buffer_nvmap_handle);
- MakeGraphicBuffer(producer, 1, session.buffer_nvmap_handle);
+ std::shared_ptr<android::BufferQueueProducer> producer;
+ R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), session.layer_id));
+ MakeGraphicBuffer(*producer, 0, session.buffer_nvmap_handle);
+ MakeGraphicBuffer(*producer, 1, session.buffer_nvmap_handle);
// Assign outputs.
*out_buffer_id = m_buffer_id;
@@ -269,7 +269,7 @@ Result FbShareBufferManager::Initialize(Kernel::KProcess* owner_process, u64* ou
R_SUCCEED();
}
-void FbShareBufferManager::Finalize(Kernel::KProcess* owner_process) {
+void SharedBufferManager::DestroySession(Kernel::KProcess* owner_process) {
std::scoped_lock lk{m_guard};
if (m_buffer_id == 0) {
@@ -285,7 +285,7 @@ void FbShareBufferManager::Finalize(Kernel::KProcess* owner_process) {
auto& session = it->second;
// Destroy the layer.
- m_flinger.DestroyLayer(session.layer_id);
+ R_ASSERT(m_container.DestroyStrayLayer(session.layer_id));
// Close nvmap handle.
FreeHandle(session.buffer_nvmap_handle, *m_nvdrv, session.nvmap_fd);
@@ -301,11 +301,11 @@ void FbShareBufferManager::Finalize(Kernel::KProcess* owner_process) {
m_sessions.erase(it);
}
-Result FbShareBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size,
- s32* out_nvmap_handle,
- SharedMemoryPoolLayout* out_pool_layout,
- u64 buffer_id,
- u64 applet_resource_user_id) {
+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);
@@ -319,36 +319,20 @@ Result FbShareBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size,
R_SUCCEED();
}
-Result FbShareBufferManager::GetLayerFromId(VI::Layer** out_layer, u64 layer_id) {
- // Ensure the layer id is valid.
- R_UNLESS(layer_id > 0, VI::ResultNotFound);
-
- // Get the layer.
- VI::Layer* layer = m_flinger.FindLayer(m_display_id, layer_id);
- R_UNLESS(layer != nullptr, VI::ResultNotFound);
-
- // We succeeded.
- *out_layer = layer;
- R_SUCCEED();
-}
-
-Result FbShareBufferManager::AcquireSharedFrameBuffer(android::Fence* out_fence,
- std::array<s32, 4>& out_slot_indexes,
- s64* out_target_slot, u64 layer_id) {
+Result SharedBufferManager::AcquireSharedFrameBuffer(android::Fence* out_fence,
+ std::array<s32, 4>& out_slot_indexes,
+ s64* out_target_slot, u64 layer_id) {
std::scoped_lock lk{m_guard};
- // Get the layer.
- VI::Layer* layer;
- R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id));
-
// Get the producer.
- auto& producer = layer->GetBufferQueue();
+ std::shared_ptr<android::BufferQueueProducer> producer;
+ R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id));
// Get the next buffer from the producer.
s32 slot;
- R_UNLESS(producer.DequeueBuffer(std::addressof(slot), out_fence, SharedBufferAsync != 0,
- SharedBufferWidth, SharedBufferHeight,
- SharedBufferBlockLinearFormat, 0) == android::Status::NoError,
+ R_UNLESS(producer->DequeueBuffer(std::addressof(slot), out_fence, SharedBufferAsync != 0,
+ SharedBufferWidth, SharedBufferHeight,
+ SharedBufferBlockLinearFormat, 0) == android::Status::NoError,
VI::ResultOperationFailed);
// Assign remaining outputs.
@@ -359,27 +343,24 @@ Result FbShareBufferManager::AcquireSharedFrameBuffer(android::Fence* out_fence,
R_SUCCEED();
}
-Result FbShareBufferManager::PresentSharedFrameBuffer(android::Fence fence,
- Common::Rectangle<s32> crop_region,
- u32 transform, s32 swap_interval,
- u64 layer_id, s64 slot) {
+Result SharedBufferManager::PresentSharedFrameBuffer(android::Fence fence,
+ Common::Rectangle<s32> crop_region,
+ u32 transform, s32 swap_interval, u64 layer_id,
+ s64 slot) {
std::scoped_lock lk{m_guard};
- // Get the layer.
- VI::Layer* layer;
- R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id));
-
// Get the producer.
- auto& producer = layer->GetBufferQueue();
+ std::shared_ptr<android::BufferQueueProducer> producer;
+ R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id));
// Request to queue the buffer.
std::shared_ptr<android::GraphicBuffer> buffer;
- R_UNLESS(producer.RequestBuffer(static_cast<s32>(slot), std::addressof(buffer)) ==
+ R_UNLESS(producer->RequestBuffer(static_cast<s32>(slot), std::addressof(buffer)) ==
android::Status::NoError,
VI::ResultOperationFailed);
ON_RESULT_FAILURE {
- producer.CancelBuffer(static_cast<s32>(slot), fence);
+ producer->CancelBuffer(static_cast<s32>(slot), fence);
};
// Queue the buffer to the producer.
@@ -389,7 +370,7 @@ Result FbShareBufferManager::PresentSharedFrameBuffer(android::Fence fence,
input.fence = fence;
input.transform = static_cast<android::NativeWindowTransform>(transform);
input.swap_interval = swap_interval;
- R_UNLESS(producer.QueueBuffer(static_cast<s32>(slot), input, std::addressof(output)) ==
+ R_UNLESS(producer->QueueBuffer(static_cast<s32>(slot), input, std::addressof(output)) ==
android::Status::NoError,
VI::ResultOperationFailed);
@@ -397,25 +378,36 @@ Result FbShareBufferManager::PresentSharedFrameBuffer(android::Fence fence,
R_SUCCEED();
}
-Result FbShareBufferManager::GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event,
- u64 layer_id) {
+Result SharedBufferManager::CancelSharedFrameBuffer(u64 layer_id, s64 slot) {
std::scoped_lock lk{m_guard};
- // Get the layer.
- VI::Layer* layer;
- R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id));
+ // Get the producer.
+ std::shared_ptr<android::BufferQueueProducer> producer;
+ R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id));
+
+ // Cancel.
+ producer->CancelBuffer(static_cast<s32>(slot), android::Fence::NoFence());
+
+ // We succeeded.
+ R_SUCCEED();
+}
+
+Result SharedBufferManager::GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event,
+ u64 layer_id) {
+ std::scoped_lock lk{m_guard};
// Get the producer.
- auto& producer = layer->GetBufferQueue();
+ std::shared_ptr<android::BufferQueueProducer> producer;
+ R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id));
// Set the event.
- *out_event = std::addressof(producer.GetNativeHandle());
+ *out_event = producer->GetNativeHandle({});
// We succeeded.
R_SUCCEED();
}
-Result FbShareBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index) {
+Result SharedBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index) {
std::vector<u8> capture_buffer(m_system.GPU().GetAppletCaptureBuffer());
Common::ScratchBuffer<u32> scratch;
@@ -444,4 +436,4 @@ Result FbShareBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32
R_SUCCEED();
}
-} // namespace Service::Nvnflinger
+} // namespace Service::VI
diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h b/src/core/hle/service/vi/shared_buffer_manager.h
index b79a7d23a..7c9bb7199 100644
--- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h
+++ b/src/core/hle/service/vi/shared_buffer_manager.h
@@ -8,15 +8,27 @@
#include "common/math_util.h"
#include "core/hle/service/nvdrv/core/container.h"
#include "core/hle/service/nvdrv/nvdata.h"
-#include "core/hle/service/nvnflinger/hwc_layer.h"
#include "core/hle/service/nvnflinger/nvnflinger.h"
#include "core/hle/service/nvnflinger/ui/fence.h"
namespace Kernel {
class KPageGroup;
+class KReadableEvent;
+} // namespace Kernel
+
+namespace Service::android {
+class BufferQueueProducer;
+}
+
+namespace Service::Nvidia {
+class Module;
}
-namespace Service::Nvnflinger {
+union Result;
+
+namespace Service::VI {
+
+class Container;
struct SharedMemorySlot {
u64 buffer_offset;
@@ -32,17 +44,17 @@ struct SharedMemoryPoolLayout {
};
static_assert(sizeof(SharedMemoryPoolLayout) == 0x188, "SharedMemoryPoolLayout has wrong size");
-struct FbShareSession;
+struct SharedBufferSession;
-class FbShareBufferManager final {
+class SharedBufferManager final {
public:
- explicit FbShareBufferManager(Core::System& system, Nvnflinger& flinger,
- std::shared_ptr<Nvidia::Module> nvdrv);
- ~FbShareBufferManager();
+ explicit SharedBufferManager(Core::System& system, Container& container,
+ std::shared_ptr<Nvidia::Module> nvdrv);
+ ~SharedBufferManager();
- Result Initialize(Kernel::KProcess* owner_process, u64* out_buffer_id, u64* out_layer_handle,
- u64 display_id, LayerBlending blending);
- void Finalize(Kernel::KProcess* owner_process);
+ Result 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,
@@ -51,32 +63,30 @@ public:
s64* out_target_slot, u64 layer_id);
Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle<s32> crop_region,
u32 transform, s32 swap_interval, u64 layer_id, s64 slot);
+ Result CancelSharedFrameBuffer(u64 layer_id, s64 slot);
Result GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, u64 layer_id);
Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index);
private:
- Result GetLayerFromId(VI::Layer** out_layer, u64 layer_id);
-
-private:
u64 m_next_buffer_id = 1;
u64 m_display_id = 0;
u64 m_buffer_id = 0;
SharedMemoryPoolLayout m_pool_layout = {};
- std::map<u64, FbShareSession> m_sessions;
+ std::map<u64, SharedBufferSession> m_sessions;
std::unique_ptr<Kernel::KPageGroup> m_buffer_page_group;
std::mutex m_guard;
Core::System& m_system;
- Nvnflinger& m_flinger;
- std::shared_ptr<Nvidia::Module> m_nvdrv;
+ Container& m_container;
+ const std::shared_ptr<Nvidia::Module> m_nvdrv;
};
-struct FbShareSession {
+struct SharedBufferSession {
Nvidia::DeviceFD nvmap_fd = {};
Nvidia::NvCore::SessionId session_id = {};
u64 layer_id = {};
u32 buffer_nvmap_handle = 0;
};
-} // namespace Service::Nvnflinger
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/system_display_service.cpp b/src/core/hle/service/vi/system_display_service.cpp
new file mode 100644
index 000000000..c3c50b07b
--- /dev/null
+++ b/src/core/hle/service/vi/system_display_service.cpp
@@ -0,0 +1,169 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/settings.h"
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/vi/container.h"
+#include "core/hle/service/vi/system_display_service.h"
+#include "core/hle/service/vi/vi_types.h"
+
+namespace Service::VI {
+
+ISystemDisplayService::ISystemDisplayService(Core::System& system_,
+ std::shared_ptr<Container> container)
+ : ServiceFramework{system_, "ISystemDisplayService"}, m_container{std::move(container)} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {1200, nullptr, "GetZOrderCountMin"},
+ {1202, nullptr, "GetZOrderCountMax"},
+ {1203, nullptr, "GetDisplayLogicalResolution"},
+ {1204, nullptr, "SetDisplayMagnification"},
+ {2201, nullptr, "SetLayerPosition"},
+ {2203, nullptr, "SetLayerSize"},
+ {2204, nullptr, "GetLayerZ"},
+ {2205, C<&ISystemDisplayService::SetLayerZ>, "SetLayerZ"},
+ {2207, C<&ISystemDisplayService::SetLayerVisibility>, "SetLayerVisibility"},
+ {2209, nullptr, "SetLayerAlpha"},
+ {2210, nullptr, "SetLayerPositionAndSize"},
+ {2312, nullptr, "CreateStrayLayer"},
+ {2400, nullptr, "OpenIndirectLayer"},
+ {2401, nullptr, "CloseIndirectLayer"},
+ {2402, nullptr, "FlipIndirectLayer"},
+ {3000, C<&ISystemDisplayService::ListDisplayModes>, "ListDisplayModes"},
+ {3001, nullptr, "ListDisplayRgbRanges"},
+ {3002, nullptr, "ListDisplayContentTypes"},
+ {3200, C<&ISystemDisplayService::GetDisplayMode>, "GetDisplayMode"},
+ {3201, nullptr, "SetDisplayMode"},
+ {3202, nullptr, "GetDisplayUnderscan"},
+ {3203, nullptr, "SetDisplayUnderscan"},
+ {3204, nullptr, "GetDisplayContentType"},
+ {3205, nullptr, "SetDisplayContentType"},
+ {3206, nullptr, "GetDisplayRgbRange"},
+ {3207, nullptr, "SetDisplayRgbRange"},
+ {3208, nullptr, "GetDisplayCmuMode"},
+ {3209, nullptr, "SetDisplayCmuMode"},
+ {3210, nullptr, "GetDisplayContrastRatio"},
+ {3211, nullptr, "SetDisplayContrastRatio"},
+ {3214, nullptr, "GetDisplayGamma"},
+ {3215, nullptr, "SetDisplayGamma"},
+ {3216, nullptr, "GetDisplayCmuLuma"},
+ {3217, nullptr, "SetDisplayCmuLuma"},
+ {3218, nullptr, "SetDisplayCrcMode"},
+ {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"},
+ {8225, C<&ISystemDisplayService::GetSharedBufferMemoryHandleId>, "GetSharedBufferMemoryHandleId"},
+ {8250, C<&ISystemDisplayService::OpenSharedLayer>, "OpenSharedLayer"},
+ {8251, nullptr, "CloseSharedLayer"},
+ {8252, C<&ISystemDisplayService::ConnectSharedLayer>, "ConnectSharedLayer"},
+ {8253, nullptr, "DisconnectSharedLayer"},
+ {8254, C<&ISystemDisplayService::AcquireSharedFrameBuffer>, "AcquireSharedFrameBuffer"},
+ {8255, C<&ISystemDisplayService::PresentSharedFrameBuffer>, "PresentSharedFrameBuffer"},
+ {8256, C<&ISystemDisplayService::GetSharedFrameBufferAcquirableEvent>, "GetSharedFrameBufferAcquirableEvent"},
+ {8257, nullptr, "FillSharedFrameBufferColor"},
+ {8258, C<&ISystemDisplayService::CancelSharedFrameBuffer>, "CancelSharedFrameBuffer"},
+ {9000, nullptr, "GetDp2hdmiController"},
+ };
+ // clang-format on
+ RegisterHandlers(functions);
+}
+
+ISystemDisplayService::~ISystemDisplayService() = default;
+
+Result ISystemDisplayService::SetLayerZ(u32 z_value, u64 layer_id) {
+ LOG_WARNING(Service_VI, "(STUBBED) called. layer_id={}, z_value={}", layer_id, z_value);
+ R_SUCCEED();
+}
+
+// This function currently does nothing but return a success error code in
+// the vi library itself, so do the same thing, but log out the passed in values.
+Result ISystemDisplayService::SetLayerVisibility(bool visible, u64 layer_id) {
+ LOG_DEBUG(Service_VI, "called, layer_id={}, visible={}", layer_id, visible);
+ R_SUCCEED();
+}
+
+Result ISystemDisplayService::ListDisplayModes(
+ Out<u64> out_count, u64 display_id,
+ OutArray<DisplayMode, BufferAttr_HipcMapAlias> out_display_modes) {
+ LOG_WARNING(Service_VI, "(STUBBED) called, display_id={}", display_id);
+
+ if (!out_display_modes.empty()) {
+ out_display_modes[0] = {
+ .width = 1920,
+ .height = 1080,
+ .refresh_rate = 60.f,
+ .unknown = {},
+ };
+ *out_count = 1;
+ } else {
+ *out_count = 0;
+ }
+
+ R_SUCCEED();
+}
+
+Result ISystemDisplayService::GetDisplayMode(Out<DisplayMode> out_display_mode, u64 display_id) {
+ LOG_WARNING(Service_VI, "(STUBBED) called, display_id={}", display_id);
+
+ if (Settings::IsDockedMode()) {
+ out_display_mode->width = static_cast<u32>(DisplayResolution::DockedWidth);
+ out_display_mode->height = static_cast<u32>(DisplayResolution::DockedHeight);
+ } else {
+ out_display_mode->width = static_cast<u32>(DisplayResolution::UndockedWidth);
+ out_display_mode->height = static_cast<u32>(DisplayResolution::UndockedHeight);
+ }
+
+ out_display_mode->refresh_rate = 60.f; // This wouldn't seem to be correct for 30 fps games.
+ out_display_mode->unknown = 0;
+
+ R_SUCCEED();
+}
+
+Result ISystemDisplayService::GetSharedBufferMemoryHandleId(
+ Out<s32> out_nvmap_handle, Out<u64> out_size,
+ OutLargeData<SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout, u64 buffer_id,
+ ClientAppletResourceUserId aruid) {
+ LOG_INFO(Service_VI, "called. buffer_id={}, aruid={:#x}", buffer_id, aruid.pid);
+
+ R_RETURN(m_container->GetSharedBufferManager()->GetSharedBufferMemoryHandleId(
+ out_size, out_nvmap_handle, out_pool_layout, buffer_id, aruid.pid));
+}
+
+Result ISystemDisplayService::OpenSharedLayer(u64 layer_id) {
+ LOG_INFO(Service_VI, "(STUBBED) called. layer_id={}", layer_id);
+ R_SUCCEED();
+}
+
+Result ISystemDisplayService::ConnectSharedLayer(u64 layer_id) {
+ LOG_INFO(Service_VI, "(STUBBED) called. layer_id={}", layer_id);
+ R_SUCCEED();
+}
+
+Result ISystemDisplayService::AcquireSharedFrameBuffer(Out<android::Fence> out_fence,
+ Out<std::array<s32, 4>> out_slots,
+ Out<s64> out_target_slot, u64 layer_id) {
+ LOG_DEBUG(Service_VI, "called");
+ R_RETURN(m_container->GetSharedBufferManager()->AcquireSharedFrameBuffer(
+ out_fence, *out_slots, out_target_slot, layer_id));
+}
+
+Result ISystemDisplayService::PresentSharedFrameBuffer(android::Fence fence,
+ Common::Rectangle<s32> crop_region,
+ u32 window_transform, s32 swap_interval,
+ u64 layer_id, s64 surface_id) {
+ LOG_DEBUG(Service_VI, "called");
+ R_RETURN(m_container->GetSharedBufferManager()->PresentSharedFrameBuffer(
+ fence, crop_region, window_transform, swap_interval, layer_id, surface_id));
+}
+
+Result ISystemDisplayService::GetSharedFrameBufferAcquirableEvent(
+ OutCopyHandle<Kernel::KReadableEvent> out_event, u64 layer_id) {
+ LOG_DEBUG(Service_VI, "called");
+ R_RETURN(m_container->GetSharedBufferManager()->GetSharedFrameBufferAcquirableEvent(out_event,
+ layer_id));
+}
+
+Result ISystemDisplayService::CancelSharedFrameBuffer(u64 layer_id, s64 slot) {
+ LOG_DEBUG(Service_VI, "called");
+ R_RETURN(m_container->GetSharedBufferManager()->CancelSharedFrameBuffer(layer_id, slot));
+}
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/system_display_service.h b/src/core/hle/service/vi/system_display_service.h
new file mode 100644
index 000000000..7228d826e
--- /dev/null
+++ b/src/core/hle/service/vi/system_display_service.h
@@ -0,0 +1,47 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/math_util.h"
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/nvnflinger/ui/fence.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/vi/shared_buffer_manager.h"
+
+namespace Service::VI {
+struct DisplayMode;
+
+class Container;
+
+class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> {
+public:
+ explicit ISystemDisplayService(Core::System& system_, std::shared_ptr<Container> container);
+ ~ISystemDisplayService() override;
+
+private:
+ Result SetLayerZ(u32 z_value, u64 layer_id);
+ Result SetLayerVisibility(bool visible, u64 layer_id);
+ Result ListDisplayModes(Out<u64> out_count, u64 display_id,
+ OutArray<DisplayMode, BufferAttr_HipcMapAlias> out_display_modes);
+ Result GetDisplayMode(Out<DisplayMode> out_display_mode, u64 display_id);
+
+ Result GetSharedBufferMemoryHandleId(
+ Out<s32> out_nvmap_handle, Out<u64> out_size,
+ OutLargeData<SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout,
+ u64 buffer_id, ClientAppletResourceUserId aruid);
+ Result OpenSharedLayer(u64 layer_id);
+ Result ConnectSharedLayer(u64 layer_id);
+ Result GetSharedFrameBufferAcquirableEvent(OutCopyHandle<Kernel::KReadableEvent> out_event,
+ u64 layer_id);
+ Result AcquireSharedFrameBuffer(Out<android::Fence> out_fence,
+ Out<std::array<s32, 4>> out_slots, Out<s64> out_target_slot,
+ u64 layer_id);
+ Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle<s32> crop_region,
+ u32 window_transform, s32 swap_interval, u64 layer_id,
+ s64 surface_id);
+ Result CancelSharedFrameBuffer(u64 layer_id, s64 slot);
+
+private:
+ const std::shared_ptr<Container> m_container;
+};
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/system_root_service.cpp b/src/core/hle/service/vi/system_root_service.cpp
new file mode 100644
index 000000000..3489727d8
--- /dev/null
+++ b/src/core/hle/service/vi/system_root_service.cpp
@@ -0,0 +1,32 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/cmif_serialization.h"
+#include "core/hle/service/vi/application_display_service.h"
+#include "core/hle/service/vi/container.h"
+#include "core/hle/service/vi/service_creator.h"
+#include "core/hle/service/vi/system_root_service.h"
+#include "core/hle/service/vi/vi.h"
+#include "core/hle/service/vi/vi_types.h"
+
+namespace Service::VI {
+
+ISystemRootService::ISystemRootService(Core::System& system_, std::shared_ptr<Container> container)
+ : ServiceFramework{system_, "vi:s"}, m_container{std::move(container)} {
+ static const FunctionInfo functions[] = {
+ {1, C<&ISystemRootService::GetDisplayService>, "GetDisplayService"},
+ {3, nullptr, "GetDisplayServiceWithProxyNameExchange"},
+ };
+ RegisterHandlers(functions);
+}
+
+ISystemRootService::~ISystemRootService() = default;
+
+Result ISystemRootService::GetDisplayService(
+ Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) {
+ LOG_DEBUG(Service_VI, "called");
+ R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_container,
+ Permission::System, policy));
+}
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/system_root_service.h b/src/core/hle/service/vi/system_root_service.h
new file mode 100644
index 000000000..9d5aa53d3
--- /dev/null
+++ b/src/core/hle/service/vi/system_root_service.h
@@ -0,0 +1,32 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/cmif_types.h"
+#include "core/hle/service/service.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::VI {
+
+class Container;
+class IApplicationDisplayService;
+enum class Policy : u32;
+
+class ISystemRootService final : public ServiceFramework<ISystemRootService> {
+public:
+ explicit ISystemRootService(Core::System& system_, std::shared_ptr<Container> container);
+ ~ISystemRootService() override;
+
+private:
+ Result GetDisplayService(
+ Out<SharedPointer<IApplicationDisplayService>> out_application_display_service,
+ Policy policy);
+
+ const std::shared_ptr<Container> m_container;
+};
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index d508ed28c..b388efaf6 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -1,974 +1,30 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include <algorithm>
-#include <array>
-#include <cstring>
-#include <memory>
-#include <optional>
-#include <type_traits>
-#include <utility>
-
-#include "common/alignment.h"
-#include "common/assert.h"
-#include "common/common_funcs.h"
-#include "common/logging/log.h"
-#include "common/math_util.h"
-#include "common/settings.h"
-#include "common/string_util.h"
-#include "common/swap.h"
-#include "core/core_timing.h"
-#include "core/hle/kernel/k_readable_event.h"
-#include "core/hle/kernel/k_thread.h"
-#include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/nvdrv/devices/nvmap.h"
-#include "core/hle/service/nvdrv/nvdata.h"
-#include "core/hle/service/nvdrv/nvdrv.h"
-#include "core/hle/service/nvnflinger/binder.h"
-#include "core/hle/service/nvnflinger/buffer_queue_producer.h"
-#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
-#include "core/hle/service/nvnflinger/hos_binder_driver_server.h"
-#include "core/hle/service/nvnflinger/nvnflinger.h"
-#include "core/hle/service/nvnflinger/parcel.h"
+#include "core/core.h"
#include "core/hle/service/server_manager.h"
-#include "core/hle/service/service.h"
+#include "core/hle/service/vi/application_root_service.h"
+#include "core/hle/service/vi/container.h"
+#include "core/hle/service/vi/manager_root_service.h"
+#include "core/hle/service/vi/system_root_service.h"
#include "core/hle/service/vi/vi.h"
-#include "core/hle/service/vi/vi_m.h"
-#include "core/hle/service/vi/vi_results.h"
-#include "core/hle/service/vi/vi_s.h"
-#include "core/hle/service/vi/vi_u.h"
namespace Service::VI {
-struct DisplayInfo {
- /// The name of this particular display.
- char display_name[0x40]{"Default"};
-
- /// Whether or not the display has a limited number of layers.
- u8 has_limited_layers{1};
- INSERT_PADDING_BYTES(7);
-
- /// Indicates the total amount of layers supported by the display.
- /// @note This is only valid if has_limited_layers is set.
- u64 max_layers{1};
-
- /// Maximum width in pixels.
- u64 width{1920};
-
- /// Maximum height in pixels.
- u64 height{1080};
-};
-static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo has wrong size");
-
-class NativeWindow final {
-public:
- constexpr explicit NativeWindow(u32 id_) : id{id_} {}
- constexpr explicit NativeWindow(const NativeWindow& other) = default;
-
-private:
- const u32 magic = 2;
- const u32 process_id = 1;
- const u64 id;
- INSERT_PADDING_WORDS(2);
- std::array<u8, 8> dispdrv = {'d', 'i', 's', 'p', 'd', 'r', 'v', '\0'};
- INSERT_PADDING_WORDS(2);
-};
-static_assert(sizeof(NativeWindow) == 0x28, "NativeWindow has wrong size");
-
-class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> {
-public:
- explicit IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderDriverServer& server_)
- : ServiceFramework{system_, "IHOSBinderDriver"}, server(server_) {
- static const FunctionInfo functions[] = {
- {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"},
- {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"},
- {2, &IHOSBinderDriver::GetNativeHandle, "GetNativeHandle"},
- {3, &IHOSBinderDriver::TransactParcel, "TransactParcelAuto"},
- };
- RegisterHandlers(functions);
- }
-
-private:
- void TransactParcel(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u32 id = rp.Pop<u32>();
- const auto transaction = static_cast<android::TransactionId>(rp.Pop<u32>());
- const u32 flags = rp.Pop<u32>();
-
- LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id,
- transaction, flags);
-
- server.TryGetProducer(id)->Transact(ctx, transaction, flags);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void AdjustRefcount(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u32 id = rp.Pop<u32>();
- const s32 addval = rp.PopRaw<s32>();
- const u32 type = rp.Pop<u32>();
-
- LOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={:08X}, type={:08X}", id, addval,
- type);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void GetNativeHandle(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u32 id = rp.Pop<u32>();
- const u32 unknown = rp.Pop<u32>();
-
- LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown);
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(server.TryGetProducer(id)->GetNativeHandle());
- }
-
-private:
- Nvnflinger::HosBinderDriverServer& server;
-};
-
-class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> {
-public:
- explicit ISystemDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_)
- : ServiceFramework{system_, "ISystemDisplayService"}, nvnflinger{nvnflinger_} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {1200, nullptr, "GetZOrderCountMin"},
- {1202, nullptr, "GetZOrderCountMax"},
- {1203, nullptr, "GetDisplayLogicalResolution"},
- {1204, nullptr, "SetDisplayMagnification"},
- {2201, nullptr, "SetLayerPosition"},
- {2203, nullptr, "SetLayerSize"},
- {2204, nullptr, "GetLayerZ"},
- {2205, &ISystemDisplayService::SetLayerZ, "SetLayerZ"},
- {2207, &ISystemDisplayService::SetLayerVisibility, "SetLayerVisibility"},
- {2209, nullptr, "SetLayerAlpha"},
- {2210, nullptr, "SetLayerPositionAndSize"},
- {2312, nullptr, "CreateStrayLayer"},
- {2400, nullptr, "OpenIndirectLayer"},
- {2401, nullptr, "CloseIndirectLayer"},
- {2402, nullptr, "FlipIndirectLayer"},
- {3000, nullptr, "ListDisplayModes"},
- {3001, nullptr, "ListDisplayRgbRanges"},
- {3002, nullptr, "ListDisplayContentTypes"},
- {3200, &ISystemDisplayService::GetDisplayMode, "GetDisplayMode"},
- {3201, nullptr, "SetDisplayMode"},
- {3202, nullptr, "GetDisplayUnderscan"},
- {3203, nullptr, "SetDisplayUnderscan"},
- {3204, nullptr, "GetDisplayContentType"},
- {3205, nullptr, "SetDisplayContentType"},
- {3206, nullptr, "GetDisplayRgbRange"},
- {3207, nullptr, "SetDisplayRgbRange"},
- {3208, nullptr, "GetDisplayCmuMode"},
- {3209, nullptr, "SetDisplayCmuMode"},
- {3210, nullptr, "GetDisplayContrastRatio"},
- {3211, nullptr, "SetDisplayContrastRatio"},
- {3214, nullptr, "GetDisplayGamma"},
- {3215, nullptr, "SetDisplayGamma"},
- {3216, nullptr, "GetDisplayCmuLuma"},
- {3217, nullptr, "SetDisplayCmuLuma"},
- {3218, nullptr, "SetDisplayCrcMode"},
- {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"},
- {8225, &ISystemDisplayService::GetSharedBufferMemoryHandleId, "GetSharedBufferMemoryHandleId"},
- {8250, &ISystemDisplayService::OpenSharedLayer, "OpenSharedLayer"},
- {8251, nullptr, "CloseSharedLayer"},
- {8252, &ISystemDisplayService::ConnectSharedLayer, "ConnectSharedLayer"},
- {8253, nullptr, "DisconnectSharedLayer"},
- {8254, &ISystemDisplayService::AcquireSharedFrameBuffer, "AcquireSharedFrameBuffer"},
- {8255, &ISystemDisplayService::PresentSharedFrameBuffer, "PresentSharedFrameBuffer"},
- {8256, &ISystemDisplayService::GetSharedFrameBufferAcquirableEvent, "GetSharedFrameBufferAcquirableEvent"},
- {8257, nullptr, "FillSharedFrameBufferColor"},
- {8258, nullptr, "CancelSharedFrameBuffer"},
- {9000, nullptr, "GetDp2hdmiController"},
- };
- // clang-format on
- RegisterHandlers(functions);
- }
-
-private:
- void GetSharedBufferMemoryHandleId(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 buffer_id = rp.PopRaw<u64>();
- const u64 aruid = ctx.GetPID();
-
- LOG_INFO(Service_VI, "called. buffer_id={:#x}, aruid={:#x}", buffer_id, aruid);
-
- struct OutputParameters {
- s32 nvmap_handle;
- u64 size;
- };
-
- OutputParameters out{};
- Nvnflinger::SharedMemoryPoolLayout layout{};
- const auto result = nvnflinger.GetSystemBufferManager().GetSharedBufferMemoryHandleId(
- &out.size, &out.nvmap_handle, &layout, buffer_id, aruid);
-
- ctx.WriteBuffer(&layout, sizeof(layout));
-
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(result);
- rb.PushRaw(out);
- }
-
- void OpenSharedLayer(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 layer_id = rp.PopRaw<u64>();
-
- LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void ConnectSharedLayer(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 layer_id = rp.PopRaw<u64>();
-
- LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void GetSharedFrameBufferAcquirableEvent(HLERequestContext& ctx) {
- LOG_DEBUG(Service_VI, "called");
-
- IPC::RequestParser rp{ctx};
- const u64 layer_id = rp.PopRaw<u64>();
-
- Kernel::KReadableEvent* event{};
- const auto result = nvnflinger.GetSystemBufferManager().GetSharedFrameBufferAcquirableEvent(
- &event, layer_id);
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(result);
- rb.PushCopyObjects(event);
- }
-
- void AcquireSharedFrameBuffer(HLERequestContext& ctx) {
- LOG_DEBUG(Service_VI, "called");
-
- IPC::RequestParser rp{ctx};
- const u64 layer_id = rp.PopRaw<u64>();
-
- struct OutputParameters {
- android::Fence fence;
- std::array<s32, 4> slots;
- s64 target_slot;
- };
- static_assert(sizeof(OutputParameters) == 0x40, "OutputParameters has wrong size");
-
- OutputParameters out{};
- const auto result = nvnflinger.GetSystemBufferManager().AcquireSharedFrameBuffer(
- &out.fence, out.slots, &out.target_slot, layer_id);
-
- IPC::ResponseBuilder rb{ctx, 18};
- rb.Push(result);
- rb.PushRaw(out);
- }
-
- void PresentSharedFrameBuffer(HLERequestContext& ctx) {
- LOG_DEBUG(Service_VI, "called");
-
- struct InputParameters {
- android::Fence fence;
- Common::Rectangle<s32> crop_region;
- u32 window_transform;
- s32 swap_interval;
- u64 layer_id;
- s64 surface_id;
- };
- static_assert(sizeof(InputParameters) == 0x50, "InputParameters has wrong size");
-
- IPC::RequestParser rp{ctx};
- auto input = rp.PopRaw<InputParameters>();
-
- const auto result = nvnflinger.GetSystemBufferManager().PresentSharedFrameBuffer(
- input.fence, input.crop_region, input.window_transform, input.swap_interval,
- input.layer_id, input.surface_id);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- }
-
- void SetLayerZ(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 layer_id = rp.Pop<u64>();
- const u64 z_value = rp.Pop<u64>();
-
- LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}, z_value=0x{:016X}", layer_id,
- z_value);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- // This function currently does nothing but return a success error code in
- // the vi library itself, so do the same thing, but log out the passed in values.
- void SetLayerVisibility(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 layer_id = rp.Pop<u64>();
- const bool visibility = rp.Pop<bool>();
-
- LOG_DEBUG(Service_VI, "called, layer_id=0x{:08X}, visibility={}", layer_id, visibility);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void GetDisplayMode(HLERequestContext& ctx) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(ResultSuccess);
-
- if (Settings::IsDockedMode()) {
- rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth));
- rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight));
- } else {
- rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth));
- rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight));
- }
-
- rb.PushRaw<float>(60.0f); // This wouldn't seem to be correct for 30 fps games.
- rb.Push<u32>(0);
- }
-
-private:
- Nvnflinger::Nvnflinger& nvnflinger;
-};
-
-class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> {
-public:
- explicit IManagerDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_)
- : ServiceFramework{system_, "IManagerDisplayService"}, nvnflinger{nvnflinger_} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {200, nullptr, "AllocateProcessHeapBlock"},
- {201, nullptr, "FreeProcessHeapBlock"},
- {1020, &IManagerDisplayService::CloseDisplay, "CloseDisplay"},
- {1102, nullptr, "GetDisplayResolution"},
- {2010, &IManagerDisplayService::CreateManagedLayer, "CreateManagedLayer"},
- {2011, nullptr, "DestroyManagedLayer"},
- {2012, nullptr, "CreateStrayLayer"},
- {2050, nullptr, "CreateIndirectLayer"},
- {2051, nullptr, "DestroyIndirectLayer"},
- {2052, nullptr, "CreateIndirectProducerEndPoint"},
- {2053, nullptr, "DestroyIndirectProducerEndPoint"},
- {2054, nullptr, "CreateIndirectConsumerEndPoint"},
- {2055, nullptr, "DestroyIndirectConsumerEndPoint"},
- {2060, nullptr, "CreateWatermarkCompositor"},
- {2062, nullptr, "SetWatermarkText"},
- {2063, nullptr, "SetWatermarkLayerStacks"},
- {2300, nullptr, "AcquireLayerTexturePresentingEvent"},
- {2301, nullptr, "ReleaseLayerTexturePresentingEvent"},
- {2302, nullptr, "GetDisplayHotplugEvent"},
- {2303, nullptr, "GetDisplayModeChangedEvent"},
- {2402, nullptr, "GetDisplayHotplugState"},
- {2501, nullptr, "GetCompositorErrorInfo"},
- {2601, nullptr, "GetDisplayErrorEvent"},
- {2701, nullptr, "GetDisplayFatalErrorEvent"},
- {4201, nullptr, "SetDisplayAlpha"},
- {4203, nullptr, "SetDisplayLayerStack"},
- {4205, nullptr, "SetDisplayPowerState"},
- {4206, nullptr, "SetDefaultDisplay"},
- {4207, nullptr, "ResetDisplayPanel"},
- {4208, nullptr, "SetDisplayFatalErrorEnabled"},
- {4209, nullptr, "IsDisplayPanelOn"},
- {4300, nullptr, "GetInternalPanelId"},
- {6000, &IManagerDisplayService::AddToLayerStack, "AddToLayerStack"},
- {6001, nullptr, "RemoveFromLayerStack"},
- {6002, &IManagerDisplayService::SetLayerVisibility, "SetLayerVisibility"},
- {6003, nullptr, "SetLayerConfig"},
- {6004, nullptr, "AttachLayerPresentationTracer"},
- {6005, nullptr, "DetachLayerPresentationTracer"},
- {6006, nullptr, "StartLayerPresentationRecording"},
- {6007, nullptr, "StopLayerPresentationRecording"},
- {6008, nullptr, "StartLayerPresentationFenceWait"},
- {6009, nullptr, "StopLayerPresentationFenceWait"},
- {6010, nullptr, "GetLayerPresentationAllFencesExpiredEvent"},
- {6011, nullptr, "EnableLayerAutoClearTransitionBuffer"},
- {6012, nullptr, "DisableLayerAutoClearTransitionBuffer"},
- {6013, nullptr, "SetLayerOpacity"},
- {6014, nullptr, "AttachLayerWatermarkCompositor"},
- {6015, nullptr, "DetachLayerWatermarkCompositor"},
- {7000, nullptr, "SetContentVisibility"},
- {8000, nullptr, "SetConductorLayer"},
- {8001, nullptr, "SetTimestampTracking"},
- {8100, nullptr, "SetIndirectProducerFlipOffset"},
- {8200, nullptr, "CreateSharedBufferStaticStorage"},
- {8201, nullptr, "CreateSharedBufferTransferMemory"},
- {8202, nullptr, "DestroySharedBuffer"},
- {8203, nullptr, "BindSharedLowLevelLayerToManagedLayer"},
- {8204, nullptr, "BindSharedLowLevelLayerToIndirectLayer"},
- {8207, nullptr, "UnbindSharedLowLevelLayer"},
- {8208, nullptr, "ConnectSharedLowLevelLayerToSharedBuffer"},
- {8209, nullptr, "DisconnectSharedLowLevelLayerFromSharedBuffer"},
- {8210, nullptr, "CreateSharedLayer"},
- {8211, nullptr, "DestroySharedLayer"},
- {8216, nullptr, "AttachSharedLayerToLowLevelLayer"},
- {8217, nullptr, "ForceDetachSharedLayerFromLowLevelLayer"},
- {8218, nullptr, "StartDetachSharedLayerFromLowLevelLayer"},
- {8219, nullptr, "FinishDetachSharedLayerFromLowLevelLayer"},
- {8220, nullptr, "GetSharedLayerDetachReadyEvent"},
- {8221, nullptr, "GetSharedLowLevelLayerSynchronizedEvent"},
- {8222, nullptr, "CheckSharedLowLevelLayerSynchronized"},
- {8223, nullptr, "RegisterSharedBufferImporterAruid"},
- {8224, nullptr, "UnregisterSharedBufferImporterAruid"},
- {8227, nullptr, "CreateSharedBufferProcessHeap"},
- {8228, nullptr, "GetSharedLayerLayerStacks"},
- {8229, nullptr, "SetSharedLayerLayerStacks"},
- {8291, nullptr, "PresentDetachedSharedFrameBufferToLowLevelLayer"},
- {8292, nullptr, "FillDetachedSharedFrameBufferColor"},
- {8293, nullptr, "GetDetachedSharedFrameBufferImage"},
- {8294, nullptr, "SetDetachedSharedFrameBufferImage"},
- {8295, nullptr, "CopyDetachedSharedFrameBufferImage"},
- {8296, nullptr, "SetDetachedSharedFrameBufferSubImage"},
- {8297, nullptr, "GetSharedFrameBufferContentParameter"},
- {8298, nullptr, "ExpandStartupLogoOnSharedFrameBuffer"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
- }
-
-private:
- void CloseDisplay(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 display = rp.Pop<u64>();
-
- const Result rc = nvnflinger.CloseDisplay(display) ? ResultSuccess : ResultUnknown;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(rc);
- }
-
- void CreateManagedLayer(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u32 unknown = rp.Pop<u32>();
- rp.Skip(1, false);
- const u64 display = rp.Pop<u64>();
- const u64 aruid = rp.Pop<u64>();
-
- LOG_WARNING(Service_VI,
- "(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}",
- unknown, display, aruid);
-
- const auto layer_id = nvnflinger.CreateLayer(display);
- if (!layer_id) {
- LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultNotFound);
- return;
- }
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push(*layer_id);
- }
-
- void AddToLayerStack(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u32 stack = rp.Pop<u32>();
- const u64 layer_id = rp.Pop<u64>();
-
- LOG_WARNING(Service_VI, "(STUBBED) called. stack=0x{:08X}, layer_id=0x{:016X}", stack,
- layer_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void SetLayerVisibility(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 layer_id = rp.Pop<u64>();
- const bool visibility = rp.Pop<bool>();
-
- LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x{:X}, visibility={}", layer_id,
- visibility);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- Nvnflinger::Nvnflinger& nvnflinger;
-};
-
-class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> {
-public:
- IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_)
- : ServiceFramework{system_, "IApplicationDisplayService"}, nvnflinger{nvnflinger_},
- hos_binder_driver_server{hos_binder_driver_server_} {
-
- static const FunctionInfo functions[] = {
- {100, &IApplicationDisplayService::GetRelayService, "GetRelayService"},
- {101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"},
- {102, &IApplicationDisplayService::GetManagerDisplayService,
- "GetManagerDisplayService"},
- {103, &IApplicationDisplayService::GetIndirectDisplayTransactionService,
- "GetIndirectDisplayTransactionService"},
- {1000, &IApplicationDisplayService::ListDisplays, "ListDisplays"},
- {1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"},
- {1011, &IApplicationDisplayService::OpenDefaultDisplay, "OpenDefaultDisplay"},
- {1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"},
- {1101, &IApplicationDisplayService::SetDisplayEnabled, "SetDisplayEnabled"},
- {1102, &IApplicationDisplayService::GetDisplayResolution, "GetDisplayResolution"},
- {2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"},
- {2021, &IApplicationDisplayService::CloseLayer, "CloseLayer"},
- {2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"},
- {2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"},
- {2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"},
- {2102, &IApplicationDisplayService::ConvertScalingMode, "ConvertScalingMode"},
- {2450, &IApplicationDisplayService::GetIndirectLayerImageMap,
- "GetIndirectLayerImageMap"},
- {2451, nullptr, "GetIndirectLayerImageCropMap"},
- {2460, &IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo,
- "GetIndirectLayerImageRequiredMemoryInfo"},
- {5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"},
- {5203, nullptr, "GetDisplayVsyncEventForDebug"},
- };
- RegisterHandlers(functions);
- }
-
- ~IApplicationDisplayService() {
- for (const auto layer_id : stray_layer_ids) {
- nvnflinger.DestroyLayer(layer_id);
- }
- }
-
-private:
- enum class ConvertedScaleMode : u64 {
- Freeze = 0,
- ScaleToWindow = 1,
- ScaleAndCrop = 2,
- None = 3,
- PreserveAspectRatio = 4,
- };
-
- enum class NintendoScaleMode : u32 {
- None = 0,
- Freeze = 1,
- ScaleToWindow = 2,
- ScaleAndCrop = 3,
- PreserveAspectRatio = 4,
- };
-
- void GetRelayService(HLERequestContext& ctx) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IHOSBinderDriver>(system, hos_binder_driver_server);
- }
-
- void GetSystemDisplayService(HLERequestContext& ctx) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<ISystemDisplayService>(system, nvnflinger);
- }
-
- void GetManagerDisplayService(HLERequestContext& ctx) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IManagerDisplayService>(system, nvnflinger);
- }
-
- void GetIndirectDisplayTransactionService(HLERequestContext& ctx) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
+void LoopProcess(Core::System& system, std::stop_token token) {
+ const auto container = std::make_shared<Container>(system);
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IHOSBinderDriver>(system, hos_binder_driver_server);
- }
-
- void OpenDisplay(HLERequestContext& ctx) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
-
- IPC::RequestParser rp{ctx};
- const auto name_buf = rp.PopRaw<std::array<char, 0x40>>();
-
- OpenDisplayImpl(ctx, std::string_view{name_buf.data(), name_buf.size()});
- }
-
- void OpenDefaultDisplay(HLERequestContext& ctx) {
- LOG_DEBUG(Service_VI, "called");
-
- OpenDisplayImpl(ctx, "Default");
- }
-
- void OpenDisplayImpl(HLERequestContext& ctx, std::string_view name) {
- const auto trim_pos = name.find('\0');
-
- if (trim_pos != std::string_view::npos) {
- name.remove_suffix(name.size() - trim_pos);
- }
-
- ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet");
-
- const auto display_id = nvnflinger.OpenDisplay(name);
- if (!display_id) {
- LOG_ERROR(Service_VI, "Display not found! display_name={}", name);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultNotFound);
- return;
- }
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push<u64>(*display_id);
- }
-
- void CloseDisplay(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 display_id = rp.Pop<u64>();
-
- const Result rc = nvnflinger.CloseDisplay(display_id) ? ResultSuccess : ResultUnknown;
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(rc);
- }
-
- // This literally does nothing internally in the actual service itself,
- // and just returns a successful result code regardless of the input.
- void SetDisplayEnabled(HLERequestContext& ctx) {
- LOG_DEBUG(Service_VI, "called.");
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void GetDisplayResolution(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 display_id = rp.Pop<u64>();
-
- LOG_DEBUG(Service_VI, "called. display_id=0x{:016X}", display_id);
-
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(ResultSuccess);
-
- // This only returns the fixed values of 1280x720 and makes no distinguishing
- // between docked and undocked dimensions. We take the liberty of applying
- // the resolution scaling factor here.
- rb.Push(static_cast<u64>(DisplayResolution::UndockedWidth));
- rb.Push(static_cast<u64>(DisplayResolution::UndockedHeight));
- }
-
- void SetLayerScalingMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto scaling_mode = rp.PopEnum<NintendoScaleMode>();
- const u64 unknown = rp.Pop<u64>();
-
- LOG_DEBUG(Service_VI, "called. scaling_mode=0x{:08X}, unknown=0x{:016X}", scaling_mode,
- unknown);
-
- IPC::ResponseBuilder rb{ctx, 2};
-
- if (scaling_mode > NintendoScaleMode::PreserveAspectRatio) {
- LOG_ERROR(Service_VI, "Invalid scaling mode provided.");
- rb.Push(ResultOperationFailed);
- return;
- }
-
- if (scaling_mode != NintendoScaleMode::ScaleToWindow &&
- scaling_mode != NintendoScaleMode::PreserveAspectRatio) {
- LOG_ERROR(Service_VI, "Unsupported scaling mode supplied.");
- rb.Push(ResultNotSupported);
- return;
- }
-
- rb.Push(ResultSuccess);
- }
-
- void ListDisplays(HLERequestContext& ctx) {
- LOG_WARNING(Service_VI, "(STUBBED) called");
-
- const DisplayInfo display_info;
- ctx.WriteBuffer(&display_info, sizeof(DisplayInfo));
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push<u64>(1);
- }
-
- void OpenLayer(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto name_buf = rp.PopRaw<std::array<u8, 0x40>>();
- const std::string display_name(Common::StringFromBuffer(name_buf));
-
- const u64 layer_id = rp.Pop<u64>();
- const u64 aruid = rp.Pop<u64>();
-
- LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid);
-
- const auto display_id = nvnflinger.OpenDisplay(display_name);
- if (!display_id) {
- LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultNotFound);
- return;
- }
-
- const auto buffer_queue_id = nvnflinger.FindBufferQueueId(*display_id, layer_id);
- if (!buffer_queue_id) {
- LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultNotFound);
- return;
- }
-
- if (!nvnflinger.OpenLayer(layer_id)) {
- LOG_WARNING(Service_VI, "Tried to open layer which was already open");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultOperationFailed);
- return;
- }
-
- android::OutputParcel parcel;
- parcel.WriteInterface(NativeWindow{*buffer_queue_id});
-
- const auto buffer_size = ctx.WriteBuffer(parcel.Serialize());
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.Push<u64>(buffer_size);
- }
-
- void CloseLayer(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto layer_id{rp.Pop<u64>()};
-
- LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id);
-
- if (!nvnflinger.CloseLayer(layer_id)) {
- LOG_WARNING(Service_VI, "Tried to close layer which was not open");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultOperationFailed);
- return;
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void CreateStrayLayer(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u32 flags = rp.Pop<u32>();
- rp.Pop<u32>(); // padding
- const u64 display_id = rp.Pop<u64>();
-
- LOG_DEBUG(Service_VI, "called. flags=0x{:08X}, display_id=0x{:016X}", flags, display_id);
-
- // TODO(Subv): What's the difference between a Stray and a Managed layer?
-
- const auto layer_id = nvnflinger.CreateLayer(display_id);
- if (!layer_id) {
- LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultNotFound);
- return;
- }
-
- stray_layer_ids.push_back(*layer_id);
- const auto buffer_queue_id = nvnflinger.FindBufferQueueId(display_id, *layer_id);
- if (!buffer_queue_id) {
- LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultNotFound);
- return;
- }
-
- android::OutputParcel parcel;
- parcel.WriteInterface(NativeWindow{*buffer_queue_id});
-
- const auto buffer_size = ctx.WriteBuffer(parcel.Serialize());
-
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(ResultSuccess);
- rb.Push(*layer_id);
- rb.Push<u64>(buffer_size);
- }
-
- void DestroyStrayLayer(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 layer_id = rp.Pop<u64>();
-
- LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}", layer_id);
- nvnflinger.DestroyLayer(layer_id);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void GetDisplayVsyncEvent(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const u64 display_id = rp.Pop<u64>();
-
- LOG_DEBUG(Service_VI, "called. display_id={}", display_id);
-
- Kernel::KReadableEvent* vsync_event{};
- const auto result = nvnflinger.FindVsyncEvent(&vsync_event, display_id);
- if (result != ResultSuccess) {
- if (result == ResultNotFound) {
- LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id);
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- return;
- }
- if (vsync_event_fetched) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(VI::ResultPermissionDenied);
- return;
- }
- vsync_event_fetched = true;
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(vsync_event);
- }
-
- void ConvertScalingMode(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto mode = rp.PopEnum<NintendoScaleMode>();
- LOG_DEBUG(Service_VI, "called mode={}", mode);
-
- ConvertedScaleMode converted_mode{};
- const auto result = ConvertScalingModeImpl(&converted_mode, mode);
-
- if (result == ResultSuccess) {
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(ResultSuccess);
- rb.PushEnum(converted_mode);
- } else {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- }
- }
-
- void GetIndirectLayerImageMap(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto width = rp.Pop<s64>();
- const auto height = rp.Pop<s64>();
- const auto indirect_layer_consumer_handle = rp.Pop<u64>();
- const auto applet_resource_user_id = rp.Pop<u64>();
-
- LOG_WARNING(Service_VI,
- "(STUBBED) called, width={}, height={}, indirect_layer_consumer_handle={}, "
- "applet_resource_user_id={}",
- width, height, indirect_layer_consumer_handle, applet_resource_user_id);
-
- std::vector<u8> out_buffer(0x46);
- ctx.WriteBuffer(out_buffer);
-
- // TODO: Figure out what these are
-
- constexpr s64 unknown_result_1 = 0;
- constexpr s64 unknown_result_2 = 0;
-
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(unknown_result_1);
- rb.Push(unknown_result_2);
- rb.Push(ResultSuccess);
- }
-
- void GetIndirectLayerImageRequiredMemoryInfo(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const auto width = rp.Pop<u64>();
- const auto height = rp.Pop<u64>();
- LOG_DEBUG(Service_VI, "called width={}, height={}", width, height);
-
- constexpr u64 base_size = 0x20000;
- constexpr u64 alignment = 0x1000;
- const auto texture_size = width * height * 4;
- const auto out_size = (texture_size + base_size - 1) / base_size * base_size;
-
- IPC::ResponseBuilder rb{ctx, 6};
- rb.Push(ResultSuccess);
- rb.Push(out_size);
- rb.Push(alignment);
- }
-
- static Result ConvertScalingModeImpl(ConvertedScaleMode* out_scaling_mode,
- NintendoScaleMode mode) {
- switch (mode) {
- case NintendoScaleMode::None:
- *out_scaling_mode = ConvertedScaleMode::None;
- return ResultSuccess;
- case NintendoScaleMode::Freeze:
- *out_scaling_mode = ConvertedScaleMode::Freeze;
- return ResultSuccess;
- case NintendoScaleMode::ScaleToWindow:
- *out_scaling_mode = ConvertedScaleMode::ScaleToWindow;
- return ResultSuccess;
- case NintendoScaleMode::ScaleAndCrop:
- *out_scaling_mode = ConvertedScaleMode::ScaleAndCrop;
- return ResultSuccess;
- case NintendoScaleMode::PreserveAspectRatio:
- *out_scaling_mode = ConvertedScaleMode::PreserveAspectRatio;
- return ResultSuccess;
- default:
- LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode);
- return ResultOperationFailed;
- }
- }
-
- Nvnflinger::Nvnflinger& nvnflinger;
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server;
- std::vector<u64> stray_layer_ids;
- bool vsync_event_fetched{false};
-};
-
-static bool IsValidServiceAccess(Permission permission, Policy policy) {
- if (permission == Permission::User) {
- return policy == Policy::User;
- }
-
- if (permission == Permission::System || permission == Permission::Manager) {
- return policy == Policy::User || policy == Policy::Compositor;
- }
-
- return false;
-}
-
-void detail::GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system,
- Nvnflinger::Nvnflinger& nvnflinger,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server,
- Permission permission) {
- IPC::RequestParser rp{ctx};
- const auto policy = rp.PopEnum<Policy>();
-
- if (!IsValidServiceAccess(permission, policy)) {
- LOG_ERROR(Service_VI, "Permission denied for policy {}", policy);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultPermissionDenied);
- return;
- }
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IApplicationDisplayService>(system, nvnflinger, hos_binder_driver_server);
-}
-
-void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) {
auto server_manager = std::make_unique<ServerManager>(system);
+ server_manager->RegisterNamedService("vi:m",
+ std::make_shared<IManagerRootService>(system, container));
+ server_manager->RegisterNamedService("vi:s",
+ std::make_shared<ISystemRootService>(system, container));
server_manager->RegisterNamedService(
- "vi:m", std::make_shared<VI_M>(system, nvnflinger, hos_binder_driver_server));
- server_manager->RegisterNamedService(
- "vi:s", std::make_shared<VI_S>(system, nvnflinger, hos_binder_driver_server));
- server_manager->RegisterNamedService(
- "vi:u", std::make_shared<VI_U>(system, nvnflinger, hos_binder_driver_server));
+ "vi:u", std::make_shared<IApplicationRootService>(system, container));
+
+ std::stop_callback cb(token, [=] { container->OnTerminate(); });
+
ServerManager::RunServer(std::move(server_manager));
}
diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h
index ee4bcbcfa..7c1f350d8 100644
--- a/src/core/hle/service/vi/vi.h
+++ b/src/core/hle/service/vi/vi.h
@@ -3,52 +3,14 @@
#pragma once
-#include "common/common_types.h"
+#include "common/polyfill_thread.h"
namespace Core {
class System;
}
-namespace Service {
-class HLERequestContext;
-}
-
-namespace Service::Nvnflinger {
-class HosBinderDriverServer;
-class Nvnflinger;
-} // namespace Service::Nvnflinger
-
namespace Service::VI {
-enum class DisplayResolution : u32 {
- DockedWidth = 1920,
- DockedHeight = 1080,
- UndockedWidth = 1280,
- UndockedHeight = 720,
-};
-
-/// Permission level for a particular VI service instance
-enum class Permission {
- User,
- System,
- Manager,
-};
-
-/// A policy type that may be requested via GetDisplayService and
-/// GetDisplayServiceWithProxyNameExchange
-enum class Policy {
- User,
- Compositor,
-};
-
-namespace detail {
-void GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system,
- Nvnflinger::Nvnflinger& nv_flinger,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server,
- Permission permission);
-} // namespace detail
-
-void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server);
+void LoopProcess(Core::System& system, std::stop_token token);
} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_m.cpp b/src/core/hle/service/vi/vi_m.cpp
deleted file mode 100644
index 0f06dc2f3..000000000
--- a/src/core/hle/service/vi/vi_m.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "common/logging/log.h"
-#include "core/hle/service/vi/vi.h"
-#include "core/hle/service/vi/vi_m.h"
-
-namespace Service::VI {
-
-VI_M::VI_M(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_)
- : ServiceFramework{system_, "vi:m"}, nv_flinger{nv_flinger_}, hos_binder_driver_server{
- hos_binder_driver_server_} {
- static const FunctionInfo functions[] = {
- {2, &VI_M::GetDisplayService, "GetDisplayService"},
- {3, nullptr, "GetDisplayServiceWithProxyNameExchange"},
- {100, nullptr, "PrepareFatal"},
- {101, nullptr, "ShowFatal"},
- {102, nullptr, "DrawFatalRectangle"},
- {103, nullptr, "DrawFatalText32"},
- };
- RegisterHandlers(functions);
-}
-
-VI_M::~VI_M() = default;
-
-void VI_M::GetDisplayService(HLERequestContext& ctx) {
- LOG_DEBUG(Service_VI, "called");
-
- detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server,
- Permission::Manager);
-}
-
-} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_m.h b/src/core/hle/service/vi/vi_m.h
deleted file mode 100644
index 9ca6f3905..000000000
--- a/src/core/hle/service/vi/vi_m.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "core/hle/service/service.h"
-
-namespace Core {
-class System;
-}
-
-namespace Service::Nvnflinger {
-class HosBinderDriverServer;
-class Nvnflinger;
-} // namespace Service::Nvnflinger
-
-namespace Service::VI {
-
-class VI_M final : public ServiceFramework<VI_M> {
-public:
- explicit VI_M(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_);
- ~VI_M() override;
-
-private:
- void GetDisplayService(HLERequestContext& ctx);
-
- Nvnflinger::Nvnflinger& nv_flinger;
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server;
-};
-
-} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_s.cpp b/src/core/hle/service/vi/vi_s.cpp
deleted file mode 100644
index 77f7a88ff..000000000
--- a/src/core/hle/service/vi/vi_s.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "common/logging/log.h"
-#include "core/hle/service/vi/vi.h"
-#include "core/hle/service/vi/vi_s.h"
-
-namespace Service::VI {
-
-VI_S::VI_S(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_)
- : ServiceFramework{system_, "vi:s"}, nv_flinger{nv_flinger_}, hos_binder_driver_server{
- hos_binder_driver_server_} {
- static const FunctionInfo functions[] = {
- {1, &VI_S::GetDisplayService, "GetDisplayService"},
- {3, nullptr, "GetDisplayServiceWithProxyNameExchange"},
- };
- RegisterHandlers(functions);
-}
-
-VI_S::~VI_S() = default;
-
-void VI_S::GetDisplayService(HLERequestContext& ctx) {
- LOG_DEBUG(Service_VI, "called");
-
- detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server,
- Permission::System);
-}
-
-} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_s.h b/src/core/hle/service/vi/vi_s.h
deleted file mode 100644
index 157839c91..000000000
--- a/src/core/hle/service/vi/vi_s.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "core/hle/service/service.h"
-
-namespace Core {
-class System;
-}
-
-namespace Service::Nvnflinger {
-class HosBinderDriverServer;
-class Nvnflinger;
-} // namespace Service::Nvnflinger
-
-namespace Service::VI {
-
-class VI_S final : public ServiceFramework<VI_S> {
-public:
- explicit VI_S(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_);
- ~VI_S() override;
-
-private:
- void GetDisplayService(HLERequestContext& ctx);
-
- Nvnflinger::Nvnflinger& nv_flinger;
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server;
-};
-
-} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_types.h b/src/core/hle/service/vi/vi_types.h
new file mode 100644
index 000000000..95ff66358
--- /dev/null
+++ b/src/core/hle/service/vi/vi_types.h
@@ -0,0 +1,92 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "common/common_funcs.h"
+
+namespace Service::VI {
+
+enum class DisplayResolution : u32 {
+ DockedWidth = 1920,
+ DockedHeight = 1080,
+ UndockedWidth = 1280,
+ UndockedHeight = 720,
+};
+
+/// Permission level for a particular VI service instance
+enum class Permission {
+ User,
+ System,
+ Manager,
+};
+
+/// A policy type that may be requested via GetDisplayService and
+/// GetDisplayServiceWithProxyNameExchange
+enum class Policy : u32 {
+ User,
+ Compositor,
+};
+
+enum class ConvertedScaleMode : u64 {
+ Freeze = 0,
+ ScaleToWindow = 1,
+ ScaleAndCrop = 2,
+ None = 3,
+ PreserveAspectRatio = 4,
+};
+
+enum class NintendoScaleMode : u32 {
+ None = 0,
+ Freeze = 1,
+ ScaleToWindow = 2,
+ ScaleAndCrop = 3,
+ PreserveAspectRatio = 4,
+};
+
+using DisplayName = std::array<char, 0x40>;
+
+struct DisplayInfo {
+ /// The name of this particular display.
+ DisplayName display_name{"Default"};
+
+ /// Whether or not the display has a limited number of layers.
+ u8 has_limited_layers{1};
+ INSERT_PADDING_BYTES(7);
+
+ /// Indicates the total amount of layers supported by the display.
+ /// @note This is only valid if has_limited_layers is set.
+ u64 max_layers{1};
+
+ /// Maximum width in pixels.
+ u64 width{1920};
+
+ /// Maximum height in pixels.
+ u64 height{1080};
+};
+static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo has wrong size");
+
+struct DisplayMode {
+ u32 width;
+ u32 height;
+ f32 refresh_rate;
+ u32 unknown;
+};
+static_assert(sizeof(DisplayMode) == 0x10, "DisplayMode has wrong size");
+
+class NativeWindow final {
+public:
+ constexpr explicit NativeWindow(s32 id_) : id{static_cast<u64>(id_)} {}
+ constexpr explicit NativeWindow(const NativeWindow& other) = default;
+
+private:
+ const u32 magic = 2;
+ const u32 process_id = 1;
+ const u64 id;
+ INSERT_PADDING_WORDS(2);
+ std::array<u8, 8> dispdrv = {'d', 'i', 's', 'p', 'd', 'r', 'v', '\0'};
+ INSERT_PADDING_WORDS(2);
+};
+static_assert(sizeof(NativeWindow) == 0x28, "NativeWindow has wrong size");
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_u.cpp b/src/core/hle/service/vi/vi_u.cpp
deleted file mode 100644
index 59e13c86b..000000000
--- a/src/core/hle/service/vi/vi_u.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "common/logging/log.h"
-#include "core/hle/service/vi/vi.h"
-#include "core/hle/service/vi/vi_u.h"
-
-namespace Service::VI {
-
-VI_U::VI_U(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_)
- : ServiceFramework{system_, "vi:u"}, nv_flinger{nv_flinger_}, hos_binder_driver_server{
- hos_binder_driver_server_} {
- static const FunctionInfo functions[] = {
- {0, &VI_U::GetDisplayService, "GetDisplayService"},
- {1, nullptr, "GetDisplayServiceWithProxyNameExchange"},
- };
- RegisterHandlers(functions);
-}
-
-VI_U::~VI_U() = default;
-
-void VI_U::GetDisplayService(HLERequestContext& ctx) {
- LOG_DEBUG(Service_VI, "called");
-
- detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server,
- Permission::User);
-}
-
-} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_u.h b/src/core/hle/service/vi/vi_u.h
deleted file mode 100644
index 5d9ca54c6..000000000
--- a/src/core/hle/service/vi/vi_u.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include "core/hle/service/service.h"
-
-namespace Core {
-class System;
-}
-
-namespace Service::Nvnflinger {
-class HosBinderDriverServer;
-class Nvnflinger;
-} // namespace Service::Nvnflinger
-
-namespace Service::VI {
-
-class VI_U final : public ServiceFramework<VI_U> {
-public:
- explicit VI_U(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_,
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_);
- ~VI_U() override;
-
-private:
- void GetDisplayService(HLERequestContext& ctx);
-
- Nvnflinger::Nvnflinger& nv_flinger;
- Nvnflinger::HosBinderDriverServer& hos_binder_driver_server;
-};
-
-} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vsync_manager.cpp b/src/core/hle/service/vi/vsync_manager.cpp
new file mode 100644
index 000000000..bdc4dfa96
--- /dev/null
+++ b/src/core/hle/service/vi/vsync_manager.cpp
@@ -0,0 +1,26 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/os/event.h"
+#include "core/hle/service/vi/vsync_manager.h"
+
+namespace Service::VI {
+
+VsyncManager::VsyncManager() = default;
+VsyncManager::~VsyncManager() = default;
+
+void VsyncManager::SignalVsync() {
+ for (auto* event : m_vsync_events) {
+ event->Signal();
+ }
+}
+
+void VsyncManager::LinkVsyncEvent(Event* event) {
+ m_vsync_events.insert(event);
+}
+
+void VsyncManager::UnlinkVsyncEvent(Event* event) {
+ m_vsync_events.erase(event);
+}
+
+} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vsync_manager.h b/src/core/hle/service/vi/vsync_manager.h
new file mode 100644
index 000000000..5d45bb5ee
--- /dev/null
+++ b/src/core/hle/service/vi/vsync_manager.h
@@ -0,0 +1,29 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <set>
+
+namespace Service {
+class Event;
+}
+
+namespace Service::VI {
+
+class DisplayList;
+
+class VsyncManager {
+public:
+ explicit VsyncManager();
+ ~VsyncManager();
+
+ void SignalVsync();
+ void LinkVsyncEvent(Event* event);
+ void UnlinkVsyncEvent(Event* event);
+
+private:
+ std::set<Event*> m_vsync_events;
+};
+
+} // namespace Service::VI
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp
index b84b57d92..d8921e565 100644
--- a/src/core/memory/cheat_engine.cpp
+++ b/src/core/memory/cheat_engine.cpp
@@ -117,9 +117,9 @@ bool StandardVmCallbacks::IsAddressInRange(VAddr in) const {
(in < metadata.heap_extents.base ||
in >= metadata.heap_extents.base + metadata.heap_extents.size) &&
(in < metadata.alias_extents.base ||
- in >= metadata.heap_extents.base + metadata.alias_extents.size) &&
+ in >= metadata.alias_extents.base + metadata.alias_extents.size) &&
(in < metadata.aslr_extents.base ||
- in >= metadata.heap_extents.base + metadata.aslr_extents.size)) {
+ in >= metadata.aslr_extents.base + metadata.aslr_extents.size)) {
LOG_DEBUG(CheatEngine,
"Cheat attempting to access memory at invalid address={:016X}, if this "
"persists, "