aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpineappleEA <pineaea@gmail.com>2024-02-13 04:52:59 +0100
committerpineappleEA <pineaea@gmail.com>2024-02-13 04:52:59 +0100
commit42df6552254e60d74fe0b6a8784f35a2fcbfb1ac (patch)
treedda4e9adf90bfba94108ef0424b2f1a4c3c9bed0
parent765c7bb93a5d63d9ea54d1679f2d1b0c000d26f0 (diff)
early-access version 4136EA-4136
-rwxr-xr-xREADME.md2
-rwxr-xr-xsrc/android/app/src/main/jni/native.cpp2
-rwxr-xr-xsrc/core/CMakeLists.txt122
-rwxr-xr-xsrc/core/device_memory_manager.inc12
-rwxr-xr-xsrc/core/hle/service/am/am.cpp18
-rwxr-xr-xsrc/core/hle/service/am/am_types.h85
-rwxr-xr-xsrc/core/hle/service/am/applet.h6
-rwxr-xr-xsrc/core/hle/service/am/applet_manager.cpp5
-rwxr-xr-xsrc/core/hle/service/am/applet_message_queue.cpp2
-rwxr-xr-xsrc/core/hle/service/am/applet_message_queue.h35
-rwxr-xr-xsrc/core/hle/service/am/frontend/applet_cabinet.cpp2
-rwxr-xr-xsrc/core/hle/service/am/frontend/applet_controller.cpp2
-rwxr-xr-xsrc/core/hle/service/am/frontend/applet_error.cpp2
-rwxr-xr-xsrc/core/hle/service/am/frontend/applet_general.cpp2
-rwxr-xr-xsrc/core/hle/service/am/frontend/applet_mii_edit.cpp2
-rwxr-xr-xsrc/core/hle/service/am/frontend/applet_profile_select.cpp2
-rwxr-xr-xsrc/core/hle/service/am/frontend/applet_software_keyboard.cpp2
-rwxr-xr-xsrc/core/hle/service/am/frontend/applet_web_browser.cpp2
-rwxr-xr-xsrc/core/hle/service/am/frontend/applets.cpp5
-rwxr-xr-xsrc/core/hle/service/am/service/all_system_applet_proxies_service.cpp80
-rwxr-xr-xsrc/core/hle/service/am/service/all_system_applet_proxies_service.h47
-rwxr-xr-xsrc/core/hle/service/am/service/applet_common_functions.cpp63
-rwxr-xr-xsrc/core/hle/service/am/service/applet_common_functions.h26
-rwxr-xr-xsrc/core/hle/service/am/service/application_accessor.cpp138
-rwxr-xr-xsrc/core/hle/service/am/service/application_accessor.h40
-rwxr-xr-xsrc/core/hle/service/am/service/application_creator.cpp35
-rwxr-xr-xsrc/core/hle/service/am/service/application_creator.h23
-rwxr-xr-xsrc/core/hle/service/am/service/application_functions.cpp465
-rwxr-xr-xsrc/core/hle/service/am/service/application_functions.h83
-rwxr-xr-xsrc/core/hle/service/am/service/application_proxy.cpp106
-rwxr-xr-xsrc/core/hle/service/am/service/application_proxy.h48
-rwxr-xr-xsrc/core/hle/service/am/service/application_proxy_service.cpp43
-rwxr-xr-xsrc/core/hle/service/am/service/application_proxy_service.h35
-rwxr-xr-xsrc/core/hle/service/am/service/audio_controller.cpp69
-rwxr-xr-xsrc/core/hle/service/am/service/audio_controller.h37
-rwxr-xr-xsrc/core/hle/service/am/service/common_state_getter.cpp277
-rwxr-xr-xsrc/core/hle/service/am/service/common_state_getter.h61
-rwxr-xr-xsrc/core/hle/service/am/service/cradle_firmware_updater.cpp52
-rwxr-xr-xsrc/core/hle/service/am/service/cradle_firmware_updater.h37
-rwxr-xr-xsrc/core/hle/service/am/service/debug_functions.cpp43
-rwxr-xr-xsrc/core/hle/service/am/service/debug_functions.h16
-rwxr-xr-xsrc/core/hle/service/am/service/display_controller.cpp105
-rwxr-xr-xsrc/core/hle/service/am/service/display_controller.h36
-rwxr-xr-xsrc/core/hle/service/am/service/global_state_controller.cpp61
-rwxr-xr-xsrc/core/hle/service/am/service/global_state_controller.h31
-rwxr-xr-xsrc/core/hle/service/am/service/home_menu_functions.cpp74
-rwxr-xr-xsrc/core/hle/service/am/service/home_menu_functions.h34
-rwxr-xr-xsrc/core/hle/service/am/service/library_applet_accessor.cpp157
-rwxr-xr-xsrc/core/hle/service/am/service/library_applet_accessor.h45
-rwxr-xr-xsrc/core/hle/service/am/service/library_applet_creator.cpp268
-rwxr-xr-xsrc/core/hle/service/am/service/library_applet_creator.h35
-rwxr-xr-xsrc/core/hle/service/am/service/library_applet_proxy.cpp134
-rwxr-xr-xsrc/core/hle/service/am/service/library_applet_proxy.h55
-rwxr-xr-xsrc/core/hle/service/am/service/library_applet_self_accessor.cpp322
-rwxr-xr-xsrc/core/hle/service/am/service/library_applet_self_accessor.h83
-rwxr-xr-xsrc/core/hle/service/am/service/lock_accessor.cpp75
-rwxr-xr-xsrc/core/hle/service/am/service/lock_accessor.h32
-rwxr-xr-xsrc/core/hle/service/am/service/process_winding_controller.cpp54
-rwxr-xr-xsrc/core/hle/service/am/service/process_winding_controller.h28
-rwxr-xr-xsrc/core/hle/service/am/service/self_controller.cpp393
-rwxr-xr-xsrc/core/hle/service/am/service/self_controller.h72
-rwxr-xr-xsrc/core/hle/service/am/service/storage.cpp48
-rwxr-xr-xsrc/core/hle/service/am/service/storage.h35
-rwxr-xr-xsrc/core/hle/service/am/service/storage_accessor.cpp68
-rwxr-xr-xsrc/core/hle/service/am/service/storage_accessor.h38
-rwxr-xr-xsrc/core/hle/service/am/service/system_applet_proxy.cpp133
-rwxr-xr-xsrc/core/hle/service/am/service/system_applet_proxy.h54
-rwxr-xr-xsrc/core/hle/service/am/service/window_controller.cpp86
-rwxr-xr-xsrc/core/hle/service/am/service/window_controller.h30
-rwxr-xr-xsrc/core/hle/service/ldn/lan_discovery.cpp20
-rwxr-xr-xsrc/core/hle/service/ldn/lan_discovery.h5
-rwxr-xr-xsrc/core/hle/service/ldn/ldn.cpp802
-rwxr-xr-xsrc/core/hle/service/ldn/ldn.h6
-rwxr-xr-xsrc/core/hle/service/ldn/ldn_types.h68
-rwxr-xr-xsrc/core/hle/service/ldn/monitor_service.cpp43
-rwxr-xr-xsrc/core/hle/service/ldn/monitor_service.h28
-rwxr-xr-xsrc/core/hle/service/ldn/sf_monitor_service.cpp40
-rwxr-xr-xsrc/core/hle/service/ldn/sf_monitor_service.h26
-rwxr-xr-xsrc/core/hle/service/ldn/sf_service.cpp37
-rwxr-xr-xsrc/core/hle/service/ldn/sf_service.h21
-rwxr-xr-xsrc/core/hle/service/ldn/sf_service_monitor.cpp50
-rwxr-xr-xsrc/core/hle/service/ldn/sf_service_monitor.h26
-rwxr-xr-xsrc/core/hle/service/ldn/system_local_communication_service.cpp56
-rwxr-xr-xsrc/core/hle/service/ldn/system_local_communication_service.h25
-rwxr-xr-xsrc/core/hle/service/ldn/user_local_communication_service.cpp320
-rwxr-xr-xsrc/core/hle/service/ldn/user_local_communication_service.h103
-rwxr-xr-xsrc/core/hle/service/omm/omm.cpp22
-rwxr-xr-xsrc/core/hle/service/omm/omm.h14
-rwxr-xr-xsrc/core/hle/service/omm/operation_mode_manager.cpp49
-rwxr-xr-xsrc/core/hle/service/omm/operation_mode_manager.h20
-rwxr-xr-xsrc/core/hle/service/omm/policy_manager_system.cpp26
-rwxr-xr-xsrc/core/hle/service/omm/policy_manager_system.h20
-rwxr-xr-xsrc/core/hle/service/omm/power_state_interface.cpp32
-rwxr-xr-xsrc/core/hle/service/omm/power_state_interface.h20
-rwxr-xr-xsrc/core/hle/service/service.cpp2
-rwxr-xr-xsrc/video_core/buffer_cache/buffer_cache.h2
-rwxr-xr-xsrc/video_core/surface.cpp14
-rwxr-xr-xsrc/video_core/surface.h2
-rwxr-xr-xsrc/video_core/texture_cache/texture_cache.h6
-rwxr-xr-xsrc/video_core/vulkan_common/vulkan_device.cpp5
-rwxr-xr-xsrc/yuzu/configuration/configure_input.cpp3
-rwxr-xr-xsrc/yuzu/main.cpp3
102 files changed, 5711 insertions, 925 deletions
diff --git a/README.md b/README.md
index 10fd85b8d..8590e042e 100755
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
1yuzu emulator early access 1yuzu emulator early access
2============= 2=============
3 3
4This is the source code for early-access 4134. 4This is the source code for early-access 4136.
5 5
6## Legal Notice 6## Legal Notice
7 7
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp
index 4acc60956..a4d8454e8 100755
--- a/src/android/app/src/main/jni/native.cpp
+++ b/src/android/app/src/main/jni/native.cpp
@@ -49,9 +49,7 @@
49#include "core/frontend/applets/profile_select.h" 49#include "core/frontend/applets/profile_select.h"
50#include "core/frontend/applets/software_keyboard.h" 50#include "core/frontend/applets/software_keyboard.h"
51#include "core/frontend/applets/web_browser.h" 51#include "core/frontend/applets/web_browser.h"
52#include "core/hle/service/am/applet_ae.h"
53#include "core/hle/service/am/applet_manager.h" 52#include "core/hle/service/am/applet_manager.h"
54#include "core/hle/service/am/applet_oe.h"
55#include "core/hle/service/am/frontend/applets.h" 53#include "core/hle/service/am/frontend/applets.h"
56#include "core/hle/service/filesystem/filesystem.h" 54#include "core/hle/service/filesystem/filesystem.h"
57#include "core/loader/loader.h" 55#include "core/loader/loader.h"
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 8c74878ab..3f7a30002 100755
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -417,74 +417,72 @@ add_library(core STATIC
417 hle/service/am/am_types.h 417 hle/service/am/am_types.h
418 hle/service/am/applet.cpp 418 hle/service/am/applet.cpp
419 hle/service/am/applet.h 419 hle/service/am/applet.h
420 hle/service/am/applet_ae.cpp
421 hle/service/am/applet_ae.h
422 hle/service/am/applet_manager.cpp 420 hle/service/am/applet_manager.cpp
423 hle/service/am/applet_data_broker.cpp 421 hle/service/am/applet_data_broker.cpp
424 hle/service/am/applet_data_broker.h 422 hle/service/am/applet_data_broker.h
425 hle/service/am/applet_manager.h 423 hle/service/am/applet_manager.h
426 hle/service/am/applet_oe.cpp
427 hle/service/am/applet_oe.h
428 hle/service/am/applet_common_functions.cpp
429 hle/service/am/applet_common_functions.h
430 hle/service/am/applet_message_queue.cpp 424 hle/service/am/applet_message_queue.cpp
431 hle/service/am/applet_message_queue.h 425 hle/service/am/applet_message_queue.h
432 hle/service/am/application_creator.cpp
433 hle/service/am/application_creator.h
434 hle/service/am/application_functions.cpp
435 hle/service/am/application_functions.h
436 hle/service/am/application_proxy.cpp
437 hle/service/am/application_proxy.h
438 hle/service/am/audio_controller.cpp
439 hle/service/am/audio_controller.h
440 hle/service/am/common_state_getter.cpp
441 hle/service/am/common_state_getter.h
442 hle/service/am/debug_functions.cpp
443 hle/service/am/debug_functions.h
444 hle/service/am/display_controller.cpp
445 hle/service/am/display_controller.h
446 hle/service/am/global_state_controller.cpp
447 hle/service/am/global_state_controller.h
448 hle/service/am/hid_registration.cpp 426 hle/service/am/hid_registration.cpp
449 hle/service/am/hid_registration.h 427 hle/service/am/hid_registration.h
450 hle/service/am/home_menu_functions.cpp
451 hle/service/am/home_menu_functions.h
452 hle/service/am/idle.cpp
453 hle/service/am/idle.h
454 hle/service/am/library_applet_accessor.cpp
455 hle/service/am/library_applet_accessor.h
456 hle/service/am/library_applet_creator.cpp
457 hle/service/am/library_applet_creator.h
458 hle/service/am/library_applet_proxy.cpp
459 hle/service/am/library_applet_proxy.h
460 hle/service/am/library_applet_self_accessor.cpp
461 hle/service/am/library_applet_self_accessor.h
462 hle/service/am/library_applet_storage.cpp 428 hle/service/am/library_applet_storage.cpp
463 hle/service/am/library_applet_storage.h 429 hle/service/am/library_applet_storage.h
464 hle/service/am/lock_accessor.cpp
465 hle/service/am/lock_accessor.h
466 hle/service/am/managed_layer_holder.cpp 430 hle/service/am/managed_layer_holder.cpp
467 hle/service/am/managed_layer_holder.h 431 hle/service/am/managed_layer_holder.h
468 hle/service/am/omm.cpp
469 hle/service/am/omm.h
470 hle/service/am/process_winding_controller.cpp
471 hle/service/am/process_winding_controller.h
472 hle/service/am/process.cpp 432 hle/service/am/process.cpp
473 hle/service/am/process.h 433 hle/service/am/process.h
474 hle/service/am/self_controller.cpp 434 hle/service/am/service/all_system_applet_proxies_service.cpp
475 hle/service/am/self_controller.h 435 hle/service/am/service/all_system_applet_proxies_service.h
476 hle/service/am/system_applet_proxy.cpp 436 hle/service/am/service/applet_common_functions.cpp
477 hle/service/am/system_applet_proxy.h 437 hle/service/am/service/applet_common_functions.h
438 hle/service/am/service/application_accessor.cpp
439 hle/service/am/service/application_accessor.h
440 hle/service/am/service/application_creator.cpp
441 hle/service/am/service/application_creator.h
442 hle/service/am/service/application_functions.cpp
443 hle/service/am/service/application_functions.h
444 hle/service/am/service/application_proxy_service.cpp
445 hle/service/am/service/application_proxy_service.h
446 hle/service/am/service/application_proxy.cpp
447 hle/service/am/service/application_proxy.h
448 hle/service/am/service/audio_controller.cpp
449 hle/service/am/service/audio_controller.h
450 hle/service/am/service/common_state_getter.cpp
451 hle/service/am/service/common_state_getter.h
452 hle/service/am/service/cradle_firmware_updater.cpp
453 hle/service/am/service/cradle_firmware_updater.h
454 hle/service/am/service/debug_functions.cpp
455 hle/service/am/service/debug_functions.h
456 hle/service/am/service/display_controller.cpp
457 hle/service/am/service/display_controller.h
458 hle/service/am/service/global_state_controller.cpp
459 hle/service/am/service/global_state_controller.h
460 hle/service/am/service/home_menu_functions.cpp
461 hle/service/am/service/home_menu_functions.h
462 hle/service/am/service/library_applet_accessor.cpp
463 hle/service/am/service/library_applet_accessor.h
464 hle/service/am/service/library_applet_creator.cpp
465 hle/service/am/service/library_applet_creator.h
466 hle/service/am/service/library_applet_proxy.cpp
467 hle/service/am/service/library_applet_proxy.h
468 hle/service/am/service/library_applet_self_accessor.cpp
469 hle/service/am/service/library_applet_self_accessor.h
470 hle/service/am/service/lock_accessor.cpp
471 hle/service/am/service/lock_accessor.h
472 hle/service/am/service/process_winding_controller.cpp
473 hle/service/am/service/process_winding_controller.h
474 hle/service/am/service/self_controller.cpp
475 hle/service/am/service/self_controller.h
476 hle/service/am/service/storage_accessor.cpp
477 hle/service/am/service/storage_accessor.h
478 hle/service/am/service/storage.cpp
479 hle/service/am/service/storage.h
480 hle/service/am/service/system_applet_proxy.cpp
481 hle/service/am/service/system_applet_proxy.h
482 hle/service/am/service/window_controller.cpp
483 hle/service/am/service/window_controller.h
478 hle/service/am/system_buffer_manager.cpp 484 hle/service/am/system_buffer_manager.cpp
479 hle/service/am/system_buffer_manager.h 485 hle/service/am/system_buffer_manager.h
480 hle/service/am/spsm.cpp
481 hle/service/am/spsm.h
482 hle/service/am/storage_accessor.cpp
483 hle/service/am/storage_accessor.h
484 hle/service/am/storage.cpp
485 hle/service/am/storage.h
486 hle/service/am/window_controller.cpp
487 hle/service/am/window_controller.h
488 hle/service/aoc/aoc_u.cpp 486 hle/service/aoc/aoc_u.cpp
489 hle/service/aoc/aoc_u.h 487 hle/service/aoc/aoc_u.h
490 hle/service/apm/apm.cpp 488 hle/service/apm/apm.cpp
@@ -668,6 +666,18 @@ add_library(core STATIC
668 hle/service/ldn/ldn.h 666 hle/service/ldn/ldn.h
669 hle/service/ldn/ldn_results.h 667 hle/service/ldn/ldn_results.h
670 hle/service/ldn/ldn_types.h 668 hle/service/ldn/ldn_types.h
669 hle/service/ldn/monitor_service.cpp
670 hle/service/ldn/monitor_service.h
671 hle/service/ldn/sf_monitor_service.cpp
672 hle/service/ldn/sf_monitor_service.h
673 hle/service/ldn/sf_service.cpp
674 hle/service/ldn/sf_service.h
675 hle/service/ldn/sf_service_monitor.cpp
676 hle/service/ldn/sf_service_monitor.h
677 hle/service/ldn/system_local_communication_service.cpp
678 hle/service/ldn/system_local_communication_service.h
679 hle/service/ldn/user_local_communication_service.cpp
680 hle/service/ldn/user_local_communication_service.h
671 hle/service/ldr/ldr.cpp 681 hle/service/ldr/ldr.cpp
672 hle/service/ldr/ldr.h 682 hle/service/ldr/ldr.h
673 hle/service/lm/lm.cpp 683 hle/service/lm/lm.cpp
@@ -811,6 +821,14 @@ add_library(core STATIC
811 hle/service/nvnflinger/window.h 821 hle/service/nvnflinger/window.h
812 hle/service/olsc/olsc.cpp 822 hle/service/olsc/olsc.cpp
813 hle/service/olsc/olsc.h 823 hle/service/olsc/olsc.h
824 hle/service/omm/omm.cpp
825 hle/service/omm/omm.h
826 hle/service/omm/operation_mode_manager.cpp
827 hle/service/omm/operation_mode_manager.h
828 hle/service/omm/policy_manager_system.cpp
829 hle/service/omm/policy_manager_system.h
830 hle/service/omm/power_state_interface.cpp
831 hle/service/omm/power_state_interface.h
814 hle/service/os/event.cpp 832 hle/service/os/event.cpp
815 hle/service/os/event.h 833 hle/service/os/event.h
816 hle/service/os/multi_wait_holder.cpp 834 hle/service/os/multi_wait_holder.cpp
diff --git a/src/core/device_memory_manager.inc b/src/core/device_memory_manager.inc
index 6dfee806c..d636621de 100755
--- a/src/core/device_memory_manager.inc
+++ b/src/core/device_memory_manager.inc
@@ -522,13 +522,17 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
522 auto* memory_device_inter = registered_processes[asid.id]; 522 auto* memory_device_inter = registered_processes[asid.id];
523 const auto release_pending = [&] { 523 const auto release_pending = [&] {
524 if (uncache_bytes > 0) { 524 if (uncache_bytes > 0) {
525 MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, 525 if (memory_device_inter != nullptr) {
526 uncache_bytes, false); 526 MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS,
527 uncache_bytes, false);
528 }
527 uncache_bytes = 0; 529 uncache_bytes = 0;
528 } 530 }
529 if (cache_bytes > 0) { 531 if (cache_bytes > 0) {
530 MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, 532 if (memory_device_inter != nullptr) {
531 cache_bytes, true); 533 MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS,
534 cache_bytes, true);
535 }
532 cache_bytes = 0; 536 cache_bytes = 0;
533 } 537 }
534 }; 538 };
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 0081cd3ad..1575b505d 100755
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -2,11 +2,8 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "core/hle/service/am/am.h" 4#include "core/hle/service/am/am.h"
5#include "core/hle/service/am/applet_ae.h" 5#include "core/hle/service/am/service/all_system_applet_proxies_service.h"
6#include "core/hle/service/am/applet_oe.h" 6#include "core/hle/service/am/service/application_proxy_service.h"
7#include "core/hle/service/am/idle.h"
8#include "core/hle/service/am/omm.h"
9#include "core/hle/service/am/spsm.h"
10#include "core/hle/service/server_manager.h" 7#include "core/hle/service/server_manager.h"
11 8
12namespace Service::AM { 9namespace Service::AM {
@@ -14,13 +11,10 @@ namespace Service::AM {
14void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { 11void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) {
15 auto server_manager = std::make_unique<ServerManager>(system); 12 auto server_manager = std::make_unique<ServerManager>(system);
16 13
17 server_manager->RegisterNamedService("appletAE", 14 server_manager->RegisterNamedService(
18 std::make_shared<AppletAE>(nvnflinger, system)); 15 "appletAE", std::make_shared<IAllSystemAppletProxiesService>(system, nvnflinger));
19 server_manager->RegisterNamedService("appletOE", 16 server_manager->RegisterNamedService(
20 std::make_shared<AppletOE>(nvnflinger, system)); 17 "appletOE", std::make_shared<IApplicationProxyService>(system, nvnflinger));
21 server_manager->RegisterNamedService("idle:sys", std::make_shared<IdleSys>(system));
22 server_manager->RegisterNamedService("omm", std::make_shared<OMM>(system));
23 server_manager->RegisterNamedService("spsm", std::make_shared<SPSM>(system));
24 ServerManager::RunServer(std::move(server_manager)); 18 ServerManager::RunServer(std::move(server_manager));
25} 19}
26 20
diff --git a/src/core/hle/service/am/am_types.h b/src/core/hle/service/am/am_types.h
index 8c33feb15..46afb3996 100755
--- a/src/core/hle/service/am/am_types.h
+++ b/src/core/hle/service/am/am_types.h
@@ -18,7 +18,7 @@ enum class AppletType {
18 SystemApplet, 18 SystemApplet,
19}; 19};
20 20
21enum class GameplayRecordingState : u32 { 21enum class GamePlayRecordingState : u32 {
22 Disabled, 22 Disabled,
23 Enabled, 23 Enabled,
24}; 24};
@@ -67,10 +67,9 @@ enum class ScreenshotPermission : u32 {
67}; 67};
68 68
69struct FocusHandlingMode { 69struct FocusHandlingMode {
70 bool unknown0; 70 bool notify;
71 bool unknown1; 71 bool background;
72 bool unknown2; 72 bool suspend;
73 bool unknown3;
74}; 73};
75 74
76enum class IdleTimeDetectionExtension : u32 { 75enum class IdleTimeDetectionExtension : u32 {
@@ -128,6 +127,40 @@ enum class AppletProgramId : u64 {
128 MaxProgramId = 0x0100000000001FFFull, 127 MaxProgramId = 0x0100000000001FFFull,
129}; 128};
130 129
130// This is nn::am::AppletMessage
131enum class AppletMessage : u32 {
132 None = 0,
133 ChangeIntoForeground = 1,
134 ChangeIntoBackground = 2,
135 Exit = 4,
136 ApplicationExited = 6,
137 FocusStateChanged = 15,
138 Resume = 16,
139 DetectShortPressingHomeButton = 20,
140 DetectLongPressingHomeButton = 21,
141 DetectShortPressingPowerButton = 22,
142 DetectMiddlePressingPowerButton = 23,
143 DetectLongPressingPowerButton = 24,
144 RequestToPrepareSleep = 25,
145 FinishedSleepSequence = 26,
146 SleepRequiredByHighTemperature = 27,
147 SleepRequiredByLowBattery = 28,
148 AutoPowerDown = 29,
149 OperationModeChanged = 30,
150 PerformanceModeChanged = 31,
151 DetectReceivingCecSystemStandby = 32,
152 SdCardRemoved = 33,
153 LaunchApplicationRequested = 50,
154 RequestToDisplay = 51,
155 ShowApplicationLogo = 55,
156 HideApplicationLogo = 56,
157 ForceHideApplicationLogo = 57,
158 FloatingApplicationDetected = 60,
159 DetectShortPressingCaptureButton = 90,
160 AlbumScreenShotTaken = 92,
161 AlbumRecordingSaved = 93,
162};
163
131enum class LibraryAppletMode : u32 { 164enum class LibraryAppletMode : u32 {
132 AllForeground = 0, 165 AllForeground = 0,
133 PartialForeground = 1, 166 PartialForeground = 1,
@@ -136,6 +169,11 @@ enum class LibraryAppletMode : u32 {
136 AllForegroundInitiallyHidden = 4, 169 AllForegroundInitiallyHidden = 4,
137}; 170};
138 171
172enum class LaunchParameterKind : u32 {
173 UserChannel = 1,
174 AccountPreselectedUser = 2,
175};
176
139enum class CommonArgumentVersion : u32 { 177enum class CommonArgumentVersion : u32 {
140 Version0, 178 Version0,
141 Version1, 179 Version1,
@@ -152,6 +190,22 @@ enum class ThemeColor : u32 {
152 BasicBlack = 3, 190 BasicBlack = 3,
153}; 191};
154 192
193enum class InputDetectionPolicy : u32 {
194 Unknown0 = 0,
195 Unknown1 = 1,
196};
197
198enum class WindowOriginMode : u32 {
199 LowerLeft = 0,
200 UpperLeft = 1,
201};
202
203enum class ProgramSpecifyKind : u32 {
204 ExecuteProgram = 0,
205 JumpToSubApplicationProgramForDevelopment = 1,
206 RestartProgram = 2,
207};
208
155struct CommonArguments { 209struct CommonArguments {
156 CommonArgumentVersion arguments_version; 210 CommonArgumentVersion arguments_version;
157 CommonArgumentSize size; 211 CommonArgumentSize size;
@@ -169,6 +223,27 @@ struct AppletIdentityInfo {
169}; 223};
170static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size."); 224static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size.");
171 225
226struct AppletAttribute {
227 u8 flag;
228 INSERT_PADDING_BYTES_NOINIT(0x7F);
229};
230static_assert(sizeof(AppletAttribute) == 0x80, "AppletAttribute has incorrect size.");
231
232// This is nn::oe::DisplayVersion
233struct DisplayVersion {
234 std::array<char, 0x10> string;
235};
236static_assert(sizeof(DisplayVersion) == 0x10, "DisplayVersion has incorrect size.");
237
238// This is nn::pdm::ApplicationPlayStatistics
239struct ApplicationPlayStatistics {
240 u64 application_id;
241 u64 play_time_ns;
242 u64 launch_count;
243};
244static_assert(sizeof(ApplicationPlayStatistics) == 0x18,
245 "ApplicationPlayStatistics has incorrect size.");
246
172using AppletResourceUserId = u64; 247using AppletResourceUserId = u64;
173using ProgramId = u64; 248using ProgramId = u64;
174 249
diff --git a/src/core/hle/service/am/applet.h b/src/core/hle/service/am/applet.h
index b29ecdfed..4f34d4811 100755
--- a/src/core/hle/service/am/applet.h
+++ b/src/core/hle/service/am/applet.h
@@ -3,7 +3,6 @@
3 3
4#pragma once 4#pragma once
5 5
6#include <list>
7#include <mutex> 6#include <mutex>
8 7
9#include "common/math_util.h" 8#include "common/math_util.h"
@@ -18,7 +17,6 @@
18#include "core/hle/service/am/hid_registration.h" 17#include "core/hle/service/am/hid_registration.h"
19#include "core/hle/service/am/managed_layer_holder.h" 18#include "core/hle/service/am/managed_layer_holder.h"
20#include "core/hle/service/am/process.h" 19#include "core/hle/service/am/process.h"
21#include "core/hle/service/am/storage.h"
22#include "core/hle/service/am/system_buffer_manager.h" 20#include "core/hle/service/am/system_buffer_manager.h"
23 21
24namespace Service::AM { 22namespace Service::AM {
@@ -76,8 +74,8 @@ struct Applet {
76 u32 application_core_usage_mode{}; 74 u32 application_core_usage_mode{};
77 75
78 // Application functions 76 // Application functions
79 bool gameplay_recording_supported{}; 77 bool game_play_recording_supported{};
80 GameplayRecordingState gameplay_recording_state{GameplayRecordingState::Disabled}; 78 GamePlayRecordingState game_play_recording_state{GamePlayRecordingState::Disabled};
81 bool jit_service_launched{}; 79 bool jit_service_launched{};
82 bool is_running{}; 80 bool is_running{};
83 bool application_crash_report_enabled{}; 81 bool application_crash_report_enabled{};
diff --git a/src/core/hle/service/am/applet_manager.cpp b/src/core/hle/service/am/applet_manager.cpp
index 52200d5b2..4c7266f89 100755
--- a/src/core/hle/service/am/applet_manager.cpp
+++ b/src/core/hle/service/am/applet_manager.cpp
@@ -12,6 +12,7 @@
12#include "core/hle/service/am/frontend/applet_controller.h" 12#include "core/hle/service/am/frontend/applet_controller.h"
13#include "core/hle/service/am/frontend/applet_mii_edit_types.h" 13#include "core/hle/service/am/frontend/applet_mii_edit_types.h"
14#include "core/hle/service/am/frontend/applet_software_keyboard_types.h" 14#include "core/hle/service/am/frontend/applet_software_keyboard_types.h"
15#include "core/hle/service/am/service/storage.h"
15#include "hid_core/hid_types.h" 16#include "hid_core/hid_types.h"
16 17
17namespace Service::AM { 18namespace Service::AM {
@@ -303,8 +304,8 @@ void AppletManager::CreateAndInsertByFrontendAppletParameters(
303 } 304 }
304 305
305 // Applet was started by frontend, so it is foreground. 306 // Applet was started by frontend, so it is foreground.
306 applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground); 307 applet->message_queue.PushMessage(AppletMessage::ChangeIntoForeground);
307 applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); 308 applet->message_queue.PushMessage(AppletMessage::FocusStateChanged);
308 applet->focus_state = FocusState::InFocus; 309 applet->focus_state = FocusState::InFocus;
309 310
310 this->InsertApplet(std::move(applet)); 311 this->InsertApplet(std::move(applet));
diff --git a/src/core/hle/service/am/applet_message_queue.cpp b/src/core/hle/service/am/applet_message_queue.cpp
index 5ed996b70..83c3c5a55 100755
--- a/src/core/hle/service/am/applet_message_queue.cpp
+++ b/src/core/hle/service/am/applet_message_queue.cpp
@@ -33,7 +33,7 @@ void AppletMessageQueue::PushMessage(AppletMessage msg) {
33 on_new_message->Signal(); 33 on_new_message->Signal();
34} 34}
35 35
36AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() { 36AppletMessage AppletMessageQueue::PopMessage() {
37 std::scoped_lock lk{lock}; 37 std::scoped_lock lk{lock};
38 if (messages.empty()) { 38 if (messages.empty()) {
39 on_new_message->Clear(); 39 on_new_message->Clear();
diff --git a/src/core/hle/service/am/applet_message_queue.h b/src/core/hle/service/am/applet_message_queue.h
index 5cb236d47..429b77d37 100755
--- a/src/core/hle/service/am/applet_message_queue.h
+++ b/src/core/hle/service/am/applet_message_queue.h
@@ -5,6 +5,7 @@
5 5
6#include <queue> 6#include <queue>
7 7
8#include "core/hle/service/am/am_types.h"
8#include "core/hle/service/kernel_helpers.h" 9#include "core/hle/service/kernel_helpers.h"
9#include "core/hle/service/service.h" 10#include "core/hle/service/service.h"
10 11
@@ -16,40 +17,6 @@ namespace Service::AM {
16 17
17class AppletMessageQueue { 18class AppletMessageQueue {
18public: 19public:
19 // This is nn::am::AppletMessage
20 enum class AppletMessage : u32 {
21 None = 0,
22 ChangeIntoForeground = 1,
23 ChangeIntoBackground = 2,
24 Exit = 4,
25 ApplicationExited = 6,
26 FocusStateChanged = 15,
27 Resume = 16,
28 DetectShortPressingHomeButton = 20,
29 DetectLongPressingHomeButton = 21,
30 DetectShortPressingPowerButton = 22,
31 DetectMiddlePressingPowerButton = 23,
32 DetectLongPressingPowerButton = 24,
33 RequestToPrepareSleep = 25,
34 FinishedSleepSequence = 26,
35 SleepRequiredByHighTemperature = 27,
36 SleepRequiredByLowBattery = 28,
37 AutoPowerDown = 29,
38 OperationModeChanged = 30,
39 PerformanceModeChanged = 31,
40 DetectReceivingCecSystemStandby = 32,
41 SdCardRemoved = 33,
42 LaunchApplicationRequested = 50,
43 RequestToDisplay = 51,
44 ShowApplicationLogo = 55,
45 HideApplicationLogo = 56,
46 ForceHideApplicationLogo = 57,
47 FloatingApplicationDetected = 60,
48 DetectShortPressingCaptureButton = 90,
49 AlbumScreenShotTaken = 92,
50 AlbumRecordingSaved = 93,
51 };
52
53 explicit AppletMessageQueue(Core::System& system); 20 explicit AppletMessageQueue(Core::System& system);
54 ~AppletMessageQueue(); 21 ~AppletMessageQueue();
55 22
diff --git a/src/core/hle/service/am/frontend/applet_cabinet.cpp b/src/core/hle/service/am/frontend/applet_cabinet.cpp
index 0862c81b6..4cbc80d63 100755
--- a/src/core/hle/service/am/frontend/applet_cabinet.cpp
+++ b/src/core/hle/service/am/frontend/applet_cabinet.cpp
@@ -9,7 +9,7 @@
9#include "core/hle/kernel/k_readable_event.h" 9#include "core/hle/kernel/k_readable_event.h"
10#include "core/hle/service/am/am.h" 10#include "core/hle/service/am/am.h"
11#include "core/hle/service/am/frontend/applet_cabinet.h" 11#include "core/hle/service/am/frontend/applet_cabinet.h"
12#include "core/hle/service/am/storage.h" 12#include "core/hle/service/am/service/storage.h"
13#include "core/hle/service/mii/mii_manager.h" 13#include "core/hle/service/mii/mii_manager.h"
14#include "core/hle/service/nfc/common/device.h" 14#include "core/hle/service/nfc/common/device.h"
15#include "hid_core/hid_core.h" 15#include "hid_core/hid_core.h"
diff --git a/src/core/hle/service/am/frontend/applet_controller.cpp b/src/core/hle/service/am/frontend/applet_controller.cpp
index bd3e49fc4..66f52686d 100755
--- a/src/core/hle/service/am/frontend/applet_controller.cpp
+++ b/src/core/hle/service/am/frontend/applet_controller.cpp
@@ -12,7 +12,7 @@
12#include "core/hle/result.h" 12#include "core/hle/result.h"
13#include "core/hle/service/am/am.h" 13#include "core/hle/service/am/am.h"
14#include "core/hle/service/am/frontend/applet_controller.h" 14#include "core/hle/service/am/frontend/applet_controller.h"
15#include "core/hle/service/am/storage.h" 15#include "core/hle/service/am/service/storage.h"
16#include "hid_core/frontend/emulated_controller.h" 16#include "hid_core/frontend/emulated_controller.h"
17#include "hid_core/hid_core.h" 17#include "hid_core/hid_core.h"
18#include "hid_core/hid_types.h" 18#include "hid_core/hid_types.h"
diff --git a/src/core/hle/service/am/frontend/applet_error.cpp b/src/core/hle/service/am/frontend/applet_error.cpp
index b97a5f3ea..34ec7013b 100755
--- a/src/core/hle/service/am/frontend/applet_error.cpp
+++ b/src/core/hle/service/am/frontend/applet_error.cpp
@@ -10,7 +10,7 @@
10#include "core/frontend/applets/error.h" 10#include "core/frontend/applets/error.h"
11#include "core/hle/service/am/am.h" 11#include "core/hle/service/am/am.h"
12#include "core/hle/service/am/frontend/applet_error.h" 12#include "core/hle/service/am/frontend/applet_error.h"
13#include "core/hle/service/am/storage.h" 13#include "core/hle/service/am/service/storage.h"
14#include "core/reporter.h" 14#include "core/reporter.h"
15 15
16namespace Service::AM::Frontend { 16namespace Service::AM::Frontend {
diff --git a/src/core/hle/service/am/frontend/applet_general.cpp b/src/core/hle/service/am/frontend/applet_general.cpp
index 3c091a602..d2cabb7b5 100755
--- a/src/core/hle/service/am/frontend/applet_general.cpp
+++ b/src/core/hle/service/am/frontend/applet_general.cpp
@@ -10,7 +10,7 @@
10#include "core/hle/service/am/am.h" 10#include "core/hle/service/am/am.h"
11#include "core/hle/service/am/applet_data_broker.h" 11#include "core/hle/service/am/applet_data_broker.h"
12#include "core/hle/service/am/frontend/applet_general.h" 12#include "core/hle/service/am/frontend/applet_general.h"
13#include "core/hle/service/am/storage.h" 13#include "core/hle/service/am/service/storage.h"
14#include "core/reporter.h" 14#include "core/reporter.h"
15 15
16namespace Service::AM::Frontend { 16namespace Service::AM::Frontend {
diff --git a/src/core/hle/service/am/frontend/applet_mii_edit.cpp b/src/core/hle/service/am/frontend/applet_mii_edit.cpp
index e3d19fb3d..0180ab761 100755
--- a/src/core/hle/service/am/frontend/applet_mii_edit.cpp
+++ b/src/core/hle/service/am/frontend/applet_mii_edit.cpp
@@ -7,7 +7,7 @@
7#include "core/frontend/applets/mii_edit.h" 7#include "core/frontend/applets/mii_edit.h"
8#include "core/hle/service/am/am.h" 8#include "core/hle/service/am/am.h"
9#include "core/hle/service/am/frontend/applet_mii_edit.h" 9#include "core/hle/service/am/frontend/applet_mii_edit.h"
10#include "core/hle/service/am/storage.h" 10#include "core/hle/service/am/service/storage.h"
11#include "core/hle/service/mii/mii.h" 11#include "core/hle/service/mii/mii.h"
12#include "core/hle/service/mii/mii_manager.h" 12#include "core/hle/service/mii/mii_manager.h"
13#include "core/hle/service/sm/sm.h" 13#include "core/hle/service/sm/sm.h"
diff --git a/src/core/hle/service/am/frontend/applet_profile_select.cpp b/src/core/hle/service/am/frontend/applet_profile_select.cpp
index efb4053b8..89b5a1eab 100755
--- a/src/core/hle/service/am/frontend/applet_profile_select.cpp
+++ b/src/core/hle/service/am/frontend/applet_profile_select.cpp
@@ -10,7 +10,7 @@
10#include "core/hle/service/acc/errors.h" 10#include "core/hle/service/acc/errors.h"
11#include "core/hle/service/am/am.h" 11#include "core/hle/service/am/am.h"
12#include "core/hle/service/am/frontend/applet_profile_select.h" 12#include "core/hle/service/am/frontend/applet_profile_select.h"
13#include "core/hle/service/am/storage.h" 13#include "core/hle/service/am/service/storage.h"
14 14
15namespace Service::AM::Frontend { 15namespace Service::AM::Frontend {
16 16
diff --git a/src/core/hle/service/am/frontend/applet_software_keyboard.cpp b/src/core/hle/service/am/frontend/applet_software_keyboard.cpp
index 034c62f32..d1bc03018 100755
--- a/src/core/hle/service/am/frontend/applet_software_keyboard.cpp
+++ b/src/core/hle/service/am/frontend/applet_software_keyboard.cpp
@@ -6,7 +6,7 @@
6#include "core/frontend/applets/software_keyboard.h" 6#include "core/frontend/applets/software_keyboard.h"
7#include "core/hle/service/am/am.h" 7#include "core/hle/service/am/am.h"
8#include "core/hle/service/am/frontend/applet_software_keyboard.h" 8#include "core/hle/service/am/frontend/applet_software_keyboard.h"
9#include "core/hle/service/am/storage.h" 9#include "core/hle/service/am/service/storage.h"
10 10
11namespace Service::AM::Frontend { 11namespace Service::AM::Frontend {
12 12
diff --git a/src/core/hle/service/am/frontend/applet_web_browser.cpp b/src/core/hle/service/am/frontend/applet_web_browser.cpp
index 6ee4caf34..bb60260b4 100755
--- a/src/core/hle/service/am/frontend/applet_web_browser.cpp
+++ b/src/core/hle/service/am/frontend/applet_web_browser.cpp
@@ -20,7 +20,7 @@
20#include "core/hle/result.h" 20#include "core/hle/result.h"
21#include "core/hle/service/am/am.h" 21#include "core/hle/service/am/am.h"
22#include "core/hle/service/am/frontend/applet_web_browser.h" 22#include "core/hle/service/am/frontend/applet_web_browser.h"
23#include "core/hle/service/am/storage.h" 23#include "core/hle/service/am/service/storage.h"
24#include "core/hle/service/filesystem/filesystem.h" 24#include "core/hle/service/filesystem/filesystem.h"
25#include "core/hle/service/ns/iplatform_service_manager.h" 25#include "core/hle/service/ns/iplatform_service_manager.h"
26#include "core/loader/loader.h" 26#include "core/loader/loader.h"
diff --git a/src/core/hle/service/am/frontend/applets.cpp b/src/core/hle/service/am/frontend/applets.cpp
index db2b04575..e662c6cd6 100755
--- a/src/core/hle/service/am/frontend/applets.cpp
+++ b/src/core/hle/service/am/frontend/applets.cpp
@@ -15,11 +15,8 @@
15#include "core/frontend/applets/web_browser.h" 15#include "core/frontend/applets/web_browser.h"
16#include "core/hle/kernel/k_event.h" 16#include "core/hle/kernel/k_event.h"
17#include "core/hle/service/am/am.h" 17#include "core/hle/service/am/am.h"
18#include "core/hle/service/am/applet_ae.h"
19#include "core/hle/service/am/applet_data_broker.h" 18#include "core/hle/service/am/applet_data_broker.h"
20#include "core/hle/service/am/applet_manager.h" 19#include "core/hle/service/am/applet_manager.h"
21#include "core/hle/service/am/applet_message_queue.h"
22#include "core/hle/service/am/applet_oe.h"
23#include "core/hle/service/am/frontend/applet_cabinet.h" 20#include "core/hle/service/am/frontend/applet_cabinet.h"
24#include "core/hle/service/am/frontend/applet_controller.h" 21#include "core/hle/service/am/frontend/applet_controller.h"
25#include "core/hle/service/am/frontend/applet_error.h" 22#include "core/hle/service/am/frontend/applet_error.h"
@@ -29,7 +26,7 @@
29#include "core/hle/service/am/frontend/applet_software_keyboard.h" 26#include "core/hle/service/am/frontend/applet_software_keyboard.h"
30#include "core/hle/service/am/frontend/applet_web_browser.h" 27#include "core/hle/service/am/frontend/applet_web_browser.h"
31#include "core/hle/service/am/frontend/applets.h" 28#include "core/hle/service/am/frontend/applets.h"
32#include "core/hle/service/am/storage.h" 29#include "core/hle/service/am/service/storage.h"
33#include "core/hle/service/sm/sm.h" 30#include "core/hle/service/sm/sm.h"
34 31
35namespace Service::AM::Frontend { 32namespace Service::AM::Frontend {
diff --git a/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp b/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp
new file mode 100755
index 000000000..eebd90ba2
--- /dev/null
+++ b/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp
@@ -0,0 +1,80 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/core.h"
5#include "core/hle/service/am/applet_manager.h"
6#include "core/hle/service/am/service/all_system_applet_proxies_service.h"
7#include "core/hle/service/am/service/library_applet_proxy.h"
8#include "core/hle/service/am/service/system_applet_proxy.h"
9#include "core/hle/service/cmif_serialization.h"
10
11namespace Service::AM {
12
13IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& system_,
14 Nvnflinger::Nvnflinger& nvnflinger)
15 : ServiceFramework{system_, "appletAE"}, m_nvnflinger{nvnflinger} {
16 // clang-format off
17 static const FunctionInfo functions[] = {
18 {100, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxy>, "OpenSystemAppletProxy"},
19 {200, D<&IAllSystemAppletProxiesService::OpenLibraryAppletProxyOld>, "OpenLibraryAppletProxyOld"},
20 {201, D<&IAllSystemAppletProxiesService::OpenLibraryAppletProxy>, "OpenLibraryAppletProxy"},
21 {300, nullptr, "OpenOverlayAppletProxy"},
22 {350, nullptr, "OpenSystemApplicationProxy"},
23 {400, nullptr, "CreateSelfLibraryAppletCreatorForDevelop"},
24 {410, nullptr, "GetSystemAppletControllerForDebug"},
25 {1000, nullptr, "GetDebugFunctions"},
26 };
27 // clang-format on
28
29 RegisterHandlers(functions);
30}
31
32IAllSystemAppletProxiesService::~IAllSystemAppletProxiesService() = default;
33
34Result IAllSystemAppletProxiesService::OpenSystemAppletProxy(
35 Out<SharedPointer<ISystemAppletProxy>> out_system_applet_proxy, ClientProcessId pid,
36 InCopyHandle<Kernel::KProcess> process_handle) {
37 LOG_DEBUG(Service_AM, "called");
38
39 if (const auto applet = this->GetAppletFromProcessId(pid); applet) {
40 *out_system_applet_proxy = std::make_shared<ISystemAppletProxy>(
41 system, applet, process_handle.Get(), m_nvnflinger);
42 R_SUCCEED();
43 } else {
44 UNIMPLEMENTED();
45 R_THROW(ResultUnknown);
46 }
47}
48
49Result IAllSystemAppletProxiesService::OpenLibraryAppletProxy(
50 Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy, ClientProcessId pid,
51 InCopyHandle<Kernel::KProcess> process_handle,
52 InLargeData<AppletAttribute, BufferAttr_HipcMapAlias> attribute) {
53 LOG_DEBUG(Service_AM, "called");
54
55 if (const auto applet = this->GetAppletFromProcessId(pid); applet) {
56 *out_library_applet_proxy = std::make_shared<ILibraryAppletProxy>(
57 system, applet, process_handle.Get(), m_nvnflinger);
58 R_SUCCEED();
59 } else {
60 UNIMPLEMENTED();
61 R_THROW(ResultUnknown);
62 }
63}
64
65Result IAllSystemAppletProxiesService::OpenLibraryAppletProxyOld(
66 Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy, ClientProcessId pid,
67 InCopyHandle<Kernel::KProcess> process_handle) {
68 LOG_DEBUG(Service_AM, "called");
69
70 AppletAttribute attribute{};
71 R_RETURN(
72 this->OpenLibraryAppletProxy(out_library_applet_proxy, pid, process_handle, attribute));
73}
74
75std::shared_ptr<Applet> IAllSystemAppletProxiesService::GetAppletFromProcessId(
76 ProcessId process_id) {
77 return system.GetAppletManager().GetByAppletResourceUserId(process_id.pid);
78}
79
80} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/all_system_applet_proxies_service.h b/src/core/hle/service/am/service/all_system_applet_proxies_service.h
new file mode 100755
index 000000000..38b1ca2ea
--- /dev/null
+++ b/src/core/hle/service/am/service/all_system_applet_proxies_service.h
@@ -0,0 +1,47 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/service.h"
8
9namespace Service {
10
11namespace Nvnflinger {
12class Nvnflinger;
13}
14
15namespace AM {
16
17struct Applet;
18struct AppletAttribute;
19class ILibraryAppletProxy;
20class ISystemAppletProxy;
21
22class IAllSystemAppletProxiesService final
23 : public ServiceFramework<IAllSystemAppletProxiesService> {
24public:
25 explicit IAllSystemAppletProxiesService(Core::System& system_,
26 Nvnflinger::Nvnflinger& nvnflinger);
27 ~IAllSystemAppletProxiesService() override;
28
29private:
30 Result OpenSystemAppletProxy(Out<SharedPointer<ISystemAppletProxy>> out_system_applet_proxy,
31 ClientProcessId pid,
32 InCopyHandle<Kernel::KProcess> process_handle);
33 Result OpenLibraryAppletProxy(Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy,
34 ClientProcessId pid,
35 InCopyHandle<Kernel::KProcess> process_handle,
36 InLargeData<AppletAttribute, BufferAttr_HipcMapAlias> attribute);
37 Result OpenLibraryAppletProxyOld(
38 Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy, ClientProcessId pid,
39 InCopyHandle<Kernel::KProcess> process_handle);
40
41private:
42 std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid);
43 Nvnflinger::Nvnflinger& m_nvnflinger;
44};
45
46} // namespace AM
47} // namespace Service
diff --git a/src/core/hle/service/am/service/applet_common_functions.cpp b/src/core/hle/service/am/service/applet_common_functions.cpp
new file mode 100755
index 000000000..0f29ab285
--- /dev/null
+++ b/src/core/hle/service/am/service/applet_common_functions.cpp
@@ -0,0 +1,63 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/applet.h"
5#include "core/hle/service/am/service/applet_common_functions.h"
6#include "core/hle/service/cmif_serialization.h"
7
8namespace Service::AM {
9
10IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_,
11 std::shared_ptr<Applet> applet_)
12 : ServiceFramework{system_, "IAppletCommonFunctions"}, applet{std::move(applet_)} {
13 // clang-format off
14 static const FunctionInfo functions[] = {
15 {0, nullptr, "SetTerminateResult"},
16 {10, nullptr, "ReadThemeStorage"},
17 {11, nullptr, "WriteThemeStorage"},
18 {20, nullptr, "PushToAppletBoundChannel"},
19 {21, nullptr, "TryPopFromAppletBoundChannel"},
20 {40, nullptr, "GetDisplayLogicalResolution"},
21 {42, nullptr, "SetDisplayMagnification"},
22 {50, nullptr, "SetHomeButtonDoubleClickEnabled"},
23 {51, D<&IAppletCommonFunctions::GetHomeButtonDoubleClickEnabled>, "GetHomeButtonDoubleClickEnabled"},
24 {52, nullptr, "IsHomeButtonShortPressedBlocked"},
25 {60, nullptr, "IsVrModeCurtainRequired"},
26 {61, nullptr, "IsSleepRequiredByHighTemperature"},
27 {62, nullptr, "IsSleepRequiredByLowBattery"},
28 {70, D<&IAppletCommonFunctions::SetCpuBoostRequestPriority>, "SetCpuBoostRequestPriority"},
29 {80, nullptr, "SetHandlingCaptureButtonShortPressedMessageEnabledForApplet"},
30 {81, nullptr, "SetHandlingCaptureButtonLongPressedMessageEnabledForApplet"},
31 {90, nullptr, "OpenNamedChannelAsParent"},
32 {91, nullptr, "OpenNamedChannelAsChild"},
33 {100, nullptr, "SetApplicationCoreUsageMode"},
34 {300, D<&IAppletCommonFunctions::GetCurrentApplicationId>, "GetCurrentApplicationId"},
35 };
36 // clang-format on
37
38 RegisterHandlers(functions);
39}
40
41IAppletCommonFunctions::~IAppletCommonFunctions() = default;
42
43Result IAppletCommonFunctions::GetHomeButtonDoubleClickEnabled(
44 Out<bool> out_home_button_double_click_enabled) {
45 LOG_WARNING(Service_AM, "(STUBBED) called");
46 *out_home_button_double_click_enabled = false;
47 R_SUCCEED();
48}
49
50Result IAppletCommonFunctions::SetCpuBoostRequestPriority(s32 priority) {
51 LOG_WARNING(Service_AM, "(STUBBED) called");
52 std::scoped_lock lk{applet->lock};
53 applet->cpu_boost_request_priority = priority;
54 R_SUCCEED();
55}
56
57Result IAppletCommonFunctions::GetCurrentApplicationId(Out<u64> out_application_id) {
58 LOG_WARNING(Service_AM, "(STUBBED) called");
59 *out_application_id = system.GetApplicationProcessProgramID() & ~0xFFFULL;
60 R_SUCCEED();
61}
62
63} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/applet_common_functions.h b/src/core/hle/service/am/service/applet_common_functions.h
new file mode 100755
index 000000000..4424fc83d
--- /dev/null
+++ b/src/core/hle/service/am/service/applet_common_functions.h
@@ -0,0 +1,26 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/service.h"
8
9namespace Service::AM {
10
11struct Applet;
12
13class IAppletCommonFunctions final : public ServiceFramework<IAppletCommonFunctions> {
14public:
15 explicit IAppletCommonFunctions(Core::System& system_, std::shared_ptr<Applet> applet_);
16 ~IAppletCommonFunctions() override;
17
18private:
19 Result GetHomeButtonDoubleClickEnabled(Out<bool> out_home_button_double_click_enabled);
20 Result SetCpuBoostRequestPriority(s32 priority);
21 Result GetCurrentApplicationId(Out<u64> out_application_id);
22
23 const std::shared_ptr<Applet> applet;
24};
25
26} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/application_accessor.cpp b/src/core/hle/service/am/service/application_accessor.cpp
new file mode 100755
index 000000000..6e7d110e8
--- /dev/null
+++ b/src/core/hle/service/am/service/application_accessor.cpp
@@ -0,0 +1,138 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/result.h"
5#include "core/hle/service/am/am_types.h"
6#include "core/hle/service/am/applet.h"
7#include "core/hle/service/am/applet_data_broker.h"
8#include "core/hle/service/am/applet_manager.h"
9#include "core/hle/service/am/service/application_accessor.h"
10#include "core/hle/service/am/service/library_applet_accessor.h"
11#include "core/hle/service/am/service/storage.h"
12#include "core/hle/service/cmif_serialization.h"
13
14namespace Service::AM {
15
16IApplicationAccessor::IApplicationAccessor(Core::System& system_, std::shared_ptr<Applet> applet)
17 : ServiceFramework{system_, "IApplicationAccessor"}, m_applet(std::move(applet)) {
18 // clang-format off
19 static const FunctionInfo functions[] = {
20 {0, D<&IApplicationAccessor::GetAppletStateChangedEvent>, "GetAppletStateChangedEvent"},
21 {1, nullptr, "IsCompleted"},
22 {10, D<&IApplicationAccessor::Start>, "Start"},
23 {20, D<&IApplicationAccessor::RequestExit>, "RequestExit"},
24 {25, D<&IApplicationAccessor::Terminate>, "Terminate"},
25 {30, D<&IApplicationAccessor::GetResult>, "GetResult"},
26 {101, D<&IApplicationAccessor::RequestForApplicationToGetForeground>, "RequestForApplicationToGetForeground"},
27 {110, nullptr, "TerminateAllLibraryApplets"},
28 {111, nullptr, "AreAnyLibraryAppletsLeft"},
29 {112, D<&IApplicationAccessor::GetCurrentLibraryApplet>, "GetCurrentLibraryApplet"},
30 {120, nullptr, "GetApplicationId"},
31 {121, D<&IApplicationAccessor::PushLaunchParameter>, "PushLaunchParameter"},
32 {122, D<&IApplicationAccessor::GetApplicationControlProperty>, "GetApplicationControlProperty"},
33 {123, nullptr, "GetApplicationLaunchProperty"},
34 {124, nullptr, "GetApplicationLaunchRequestInfo"},
35 {130, D<&IApplicationAccessor::SetUsers>, "SetUsers"},
36 {131, D<&IApplicationAccessor::CheckRightsEnvironmentAvailable>, "CheckRightsEnvironmentAvailable"},
37 {132, D<&IApplicationAccessor::GetNsRightsEnvironmentHandle>, "GetNsRightsEnvironmentHandle"},
38 {140, nullptr, "GetDesirableUids"},
39 {150, D<&IApplicationAccessor::ReportApplicationExitTimeout>, "ReportApplicationExitTimeout"},
40 {160, nullptr, "SetApplicationAttribute"},
41 {170, nullptr, "HasSaveDataAccessPermission"},
42 {180, nullptr, "PushToFriendInvitationStorageChannel"},
43 {190, nullptr, "PushToNotificationStorageChannel"},
44 {200, nullptr, "RequestApplicationSoftReset"},
45 {201, nullptr, "RestartApplicationTimer"},
46 };
47 // clang-format on
48
49 RegisterHandlers(functions);
50}
51
52IApplicationAccessor::~IApplicationAccessor() = default;
53
54Result IApplicationAccessor::Start() {
55 LOG_INFO(Service_AM, "called");
56 m_applet->process->Run();
57 R_SUCCEED();
58}
59
60Result IApplicationAccessor::RequestExit() {
61 LOG_INFO(Service_AM, "called");
62 m_applet->message_queue.RequestExit();
63 R_SUCCEED();
64}
65
66Result IApplicationAccessor::Terminate() {
67 LOG_INFO(Service_AM, "called");
68 m_applet->process->Terminate();
69 R_SUCCEED();
70}
71
72Result IApplicationAccessor::GetResult() {
73 LOG_INFO(Service_AM, "called");
74 R_SUCCEED();
75}
76
77Result IApplicationAccessor::GetAppletStateChangedEvent(
78 OutCopyHandle<Kernel::KReadableEvent> out_event) {
79 LOG_INFO(Service_AM, "called");
80 *out_event = m_applet->caller_applet_broker->GetStateChangedEvent().GetHandle();
81 R_SUCCEED();
82}
83
84Result IApplicationAccessor::PushLaunchParameter(LaunchParameterKind kind,
85 SharedPointer<IStorage> storage) {
86 LOG_INFO(Service_AM, "called, kind={}", kind);
87
88 switch (kind) {
89 case LaunchParameterKind::AccountPreselectedUser:
90 m_applet->preselected_user_launch_parameter.push_back(storage->GetData());
91 R_SUCCEED();
92 default:
93 R_THROW(ResultUnknown);
94 }
95}
96
97Result IApplicationAccessor::GetApplicationControlProperty(
98 OutBuffer<BufferAttr_HipcMapAlias> out_control_property) {
99 LOG_WARNING(Service_AM, "(STUBBED) called");
100 R_THROW(ResultUnknown);
101}
102
103Result IApplicationAccessor::SetUsers(bool enable,
104 InArray<Common::UUID, BufferAttr_HipcMapAlias> user_ids) {
105 LOG_INFO(Service_AM, "called, enable={} user_id_count={}", enable, user_ids.size());
106 R_SUCCEED();
107}
108
109Result IApplicationAccessor::GetCurrentLibraryApplet(
110 Out<SharedPointer<ILibraryAppletAccessor>> out_accessor) {
111 LOG_INFO(Service_AM, "(STUBBED) called");
112 *out_accessor = nullptr;
113 R_SUCCEED();
114}
115
116Result IApplicationAccessor::RequestForApplicationToGetForeground() {
117 LOG_WARNING(Service_AM, "(STUBBED) called");
118 R_THROW(ResultUnknown);
119}
120
121Result IApplicationAccessor::CheckRightsEnvironmentAvailable(Out<bool> out_is_available) {
122 LOG_WARNING(Service_AM, "(STUBBED) called");
123 *out_is_available = true;
124 R_SUCCEED();
125}
126
127Result IApplicationAccessor::GetNsRightsEnvironmentHandle(Out<u64> out_handle) {
128 LOG_WARNING(Service_AM, "(STUBBED) called");
129 *out_handle = 0xdeadbeef;
130 R_SUCCEED();
131}
132
133Result IApplicationAccessor::ReportApplicationExitTimeout() {
134 LOG_ERROR(Service_AM, "called");
135 R_SUCCEED();
136}
137
138} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/application_accessor.h b/src/core/hle/service/am/service/application_accessor.h
new file mode 100755
index 000000000..39a9b2153
--- /dev/null
+++ b/src/core/hle/service/am/service/application_accessor.h
@@ -0,0 +1,40 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "common/uuid.h"
7#include "core/hle/service/am/am_types.h"
8#include "core/hle/service/cmif_types.h"
9#include "core/hle/service/service.h"
10
11namespace Service::AM {
12
13struct Applet;
14class ILibraryAppletAccessor;
15class IStorage;
16
17class IApplicationAccessor final : public ServiceFramework<IApplicationAccessor> {
18public:
19 explicit IApplicationAccessor(Core::System& system_, std::shared_ptr<Applet> applet);
20 ~IApplicationAccessor() override;
21
22private:
23 Result Start();
24 Result RequestExit();
25 Result Terminate();
26 Result GetResult();
27 Result GetAppletStateChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
28 Result PushLaunchParameter(LaunchParameterKind kind, SharedPointer<IStorage> storage);
29 Result GetApplicationControlProperty(OutBuffer<BufferAttr_HipcMapAlias> out_control_property);
30 Result SetUsers(bool enable, InArray<Common::UUID, BufferAttr_HipcMapAlias> user_ids);
31 Result GetCurrentLibraryApplet(Out<SharedPointer<ILibraryAppletAccessor>> out_accessor);
32 Result RequestForApplicationToGetForeground();
33 Result CheckRightsEnvironmentAvailable(Out<bool> out_is_available);
34 Result GetNsRightsEnvironmentHandle(Out<u64> out_handle);
35 Result ReportApplicationExitTimeout();
36
37 const std::shared_ptr<Applet> m_applet;
38};
39
40} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/application_creator.cpp b/src/core/hle/service/am/service/application_creator.cpp
new file mode 100755
index 000000000..568bb0122
--- /dev/null
+++ b/src/core/hle/service/am/service/application_creator.cpp
@@ -0,0 +1,35 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/am_types.h"
5#include "core/hle/service/am/applet.h"
6#include "core/hle/service/am/applet_manager.h"
7#include "core/hle/service/am/service/application_accessor.h"
8#include "core/hle/service/am/service/application_creator.h"
9#include "core/hle/service/cmif_serialization.h"
10
11namespace Service::AM {
12
13IApplicationCreator::IApplicationCreator(Core::System& system_)
14 : ServiceFramework{system_, "IApplicationCreator"} {
15 // clang-format off
16 static const FunctionInfo functions[] = {
17 {0, D<&IApplicationCreator::CreateApplication>, "CreateApplication"},
18 {1, nullptr, "PopLaunchRequestedApplication"},
19 {10, nullptr, "CreateSystemApplication"},
20 {100, nullptr, "PopFloatingApplicationForDevelopment"},
21 };
22 // clang-format on
23
24 RegisterHandlers(functions);
25}
26
27IApplicationCreator::~IApplicationCreator() = default;
28
29Result IApplicationCreator::CreateApplication(
30 Out<SharedPointer<IApplicationAccessor>> out_application_accessor, u64 application_id) {
31 LOG_ERROR(Service_NS, "called, application_id={:x}", application_id);
32 R_THROW(ResultUnknown);
33}
34
35} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/application_creator.h b/src/core/hle/service/am/service/application_creator.h
new file mode 100755
index 000000000..9f939ebf6
--- /dev/null
+++ b/src/core/hle/service/am/service/application_creator.h
@@ -0,0 +1,23 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/service.h"
8
9namespace Service::AM {
10
11class IApplicationAccessor;
12struct Applet;
13
14class IApplicationCreator final : public ServiceFramework<IApplicationCreator> {
15public:
16 explicit IApplicationCreator(Core::System& system_);
17 ~IApplicationCreator() override;
18
19private:
20 Result CreateApplication(Out<SharedPointer<IApplicationAccessor>>, u64 application_id);
21};
22
23} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/application_functions.cpp b/src/core/hle/service/am/service/application_functions.cpp
new file mode 100755
index 000000000..b788fddd4
--- /dev/null
+++ b/src/core/hle/service/am/service/application_functions.cpp
@@ -0,0 +1,465 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "common/settings.h"
5#include "common/uuid.h"
6#include "core/file_sys/control_metadata.h"
7#include "core/file_sys/patch_manager.h"
8#include "core/file_sys/registered_cache.h"
9#include "core/file_sys/savedata_factory.h"
10#include "core/hle/kernel/k_transfer_memory.h"
11#include "core/hle/service/am/am_results.h"
12#include "core/hle/service/am/applet.h"
13#include "core/hle/service/am/service/application_functions.h"
14#include "core/hle/service/am/service/storage.h"
15#include "core/hle/service/cmif_serialization.h"
16#include "core/hle/service/filesystem/filesystem.h"
17#include "core/hle/service/filesystem/save_data_controller.h"
18#include "core/hle/service/ns/ns.h"
19#include "core/hle/service/sm/sm.h"
20
21namespace Service::AM {
22
23IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet)
24 : ServiceFramework{system_, "IApplicationFunctions"}, m_applet{std::move(applet)} {
25 // clang-format off
26 static const FunctionInfo functions[] = {
27 {1, D<&IApplicationFunctions::PopLaunchParameter>, "PopLaunchParameter"},
28 {10, nullptr, "CreateApplicationAndPushAndRequestToStart"},
29 {11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"},
30 {12, nullptr, "CreateApplicationAndRequestToStart"},
31 {13, nullptr, "CreateApplicationAndRequestToStartForQuest"},
32 {14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"},
33 {15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"},
34 {20, D<&IApplicationFunctions::EnsureSaveData>, "EnsureSaveData"},
35 {21, D<&IApplicationFunctions::GetDesiredLanguage>, "GetDesiredLanguage"},
36 {22, D<&IApplicationFunctions::SetTerminateResult>, "SetTerminateResult"},
37 {23, D<&IApplicationFunctions::GetDisplayVersion>, "GetDisplayVersion"},
38 {24, nullptr, "GetLaunchStorageInfoForDebug"},
39 {25, D<&IApplicationFunctions::ExtendSaveData>, "ExtendSaveData"},
40 {26, D<&IApplicationFunctions::GetSaveDataSize>, "GetSaveDataSize"},
41 {27, D<&IApplicationFunctions::CreateCacheStorage>, "CreateCacheStorage"},
42 {28, D<&IApplicationFunctions::GetSaveDataSizeMax>, "GetSaveDataSizeMax"},
43 {29, nullptr, "GetCacheStorageMax"},
44 {30, D<&IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed>, "BeginBlockingHomeButtonShortAndLongPressed"},
45 {31, D<&IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed>, "EndBlockingHomeButtonShortAndLongPressed"},
46 {32, D<&IApplicationFunctions::BeginBlockingHomeButton>, "BeginBlockingHomeButton"},
47 {33, D<&IApplicationFunctions::EndBlockingHomeButton>, "EndBlockingHomeButton"},
48 {34, nullptr, "SelectApplicationLicense"},
49 {35, nullptr, "GetDeviceSaveDataSizeMax"},
50 {36, nullptr, "GetLimitedApplicationLicense"},
51 {37, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"},
52 {40, D<&IApplicationFunctions::NotifyRunning>, "NotifyRunning"},
53 {50, D<&IApplicationFunctions::GetPseudoDeviceId>, "GetPseudoDeviceId"},
54 {60, nullptr, "SetMediaPlaybackStateForApplication"},
55 {65, D<&IApplicationFunctions::IsGamePlayRecordingSupported>, "IsGamePlayRecordingSupported"},
56 {66, D<&IApplicationFunctions::InitializeGamePlayRecording>, "InitializeGamePlayRecording"},
57 {67, D<&IApplicationFunctions::SetGamePlayRecordingState>, "SetGamePlayRecordingState"},
58 {68, nullptr, "RequestFlushGamePlayingMovieForDebug"},
59 {70, nullptr, "RequestToShutdown"},
60 {71, nullptr, "RequestToReboot"},
61 {72, nullptr, "RequestToSleep"},
62 {80, nullptr, "ExitAndRequestToShowThanksMessage"},
63 {90, D<&IApplicationFunctions::EnableApplicationCrashReport>, "EnableApplicationCrashReport"},
64 {100, D<&IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer>, "InitializeApplicationCopyrightFrameBuffer"},
65 {101, D<&IApplicationFunctions::SetApplicationCopyrightImage>, "SetApplicationCopyrightImage"},
66 {102, D<&IApplicationFunctions::SetApplicationCopyrightVisibility>, "SetApplicationCopyrightVisibility"},
67 {110, D<&IApplicationFunctions::QueryApplicationPlayStatistics>, "QueryApplicationPlayStatistics"},
68 {111, D<&IApplicationFunctions::QueryApplicationPlayStatisticsByUid>, "QueryApplicationPlayStatisticsByUid"},
69 {120, D<&IApplicationFunctions::ExecuteProgram>, "ExecuteProgram"},
70 {121, D<&IApplicationFunctions::ClearUserChannel>, "ClearUserChannel"},
71 {122, D<&IApplicationFunctions::UnpopToUserChannel>, "UnpopToUserChannel"},
72 {123, D<&IApplicationFunctions::GetPreviousProgramIndex>, "GetPreviousProgramIndex"},
73 {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
74 {130, D<&IApplicationFunctions::GetGpuErrorDetectedSystemEvent>, "GetGpuErrorDetectedSystemEvent"},
75 {131, nullptr, "SetDelayTimeToAbortOnGpuError"},
76 {140, D<&IApplicationFunctions::GetFriendInvitationStorageChannelEvent>, "GetFriendInvitationStorageChannelEvent"},
77 {141, D<&IApplicationFunctions::TryPopFromFriendInvitationStorageChannel>, "TryPopFromFriendInvitationStorageChannel"},
78 {150, D<&IApplicationFunctions::GetNotificationStorageChannelEvent>, "GetNotificationStorageChannelEvent"},
79 {151, nullptr, "TryPopFromNotificationStorageChannel"},
80 {160, D<&IApplicationFunctions::GetHealthWarningDisappearedSystemEvent>, "GetHealthWarningDisappearedSystemEvent"},
81 {170, nullptr, "SetHdcpAuthenticationActivated"},
82 {180, nullptr, "GetLaunchRequiredVersion"},
83 {181, nullptr, "UpgradeLaunchRequiredVersion"},
84 {190, nullptr, "SendServerMaintenanceOverlayNotification"},
85 {200, nullptr, "GetLastApplicationExitReason"},
86 {500, nullptr, "StartContinuousRecordingFlushForDebug"},
87 {1000, nullptr, "CreateMovieMaker"},
88 {1001, D<&IApplicationFunctions::PrepareForJit>, "PrepareForJit"},
89 };
90 // clang-format on
91
92 RegisterHandlers(functions);
93}
94
95IApplicationFunctions::~IApplicationFunctions() = default;
96
97Result IApplicationFunctions::PopLaunchParameter(Out<SharedPointer<IStorage>> out_storage,
98 LaunchParameterKind launch_parameter_kind) {
99 LOG_INFO(Service_AM, "called, kind={}", launch_parameter_kind);
100
101 std::scoped_lock lk{m_applet->lock};
102
103 auto& channel = launch_parameter_kind == LaunchParameterKind::UserChannel
104 ? m_applet->user_channel_launch_parameter
105 : m_applet->preselected_user_launch_parameter;
106
107 if (channel.empty()) {
108 LOG_WARNING(Service_AM, "Attempted to pop parameter {} but none was found!",
109 launch_parameter_kind);
110 R_THROW(AM::ResultNoDataInChannel);
111 }
112
113 auto data = channel.back();
114 channel.pop_back();
115
116 *out_storage = std::make_shared<IStorage>(system, std::move(data));
117 R_SUCCEED();
118}
119
120Result IApplicationFunctions::EnsureSaveData(Out<u64> out_size, Common::UUID user_id) {
121 LOG_INFO(Service_AM, "called, uid={}", user_id.FormattedString());
122
123 FileSys::SaveDataAttribute attribute{};
124 attribute.title_id = m_applet->program_id;
125 attribute.user_id = user_id.AsU128();
126 attribute.type = FileSys::SaveDataType::SaveData;
127
128 FileSys::VirtualDir save_data{};
129 R_TRY(system.GetFileSystemController().OpenSaveDataController()->CreateSaveData(
130 &save_data, FileSys::SaveDataSpaceId::NandUser, attribute));
131
132 *out_size = 0;
133 R_SUCCEED();
134}
135
136Result IApplicationFunctions::GetDesiredLanguage(Out<u64> out_language_code) {
137 // FIXME: all of this stuff belongs to ns
138 // TODO(bunnei): This should be configurable
139 LOG_DEBUG(Service_AM, "called");
140
141 // Get supported languages from NACP, if possible
142 // Default to 0 (all languages supported)
143 u32 supported_languages = 0;
144
145 const auto res = [this] {
146 const FileSys::PatchManager pm{m_applet->program_id, system.GetFileSystemController(),
147 system.GetContentProvider()};
148 auto metadata = pm.GetControlMetadata();
149 if (metadata.first != nullptr) {
150 return metadata;
151 }
152
153 const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(m_applet->program_id),
154 system.GetFileSystemController(),
155 system.GetContentProvider()};
156 return pm_update.GetControlMetadata();
157 }();
158
159 if (res.first != nullptr) {
160 supported_languages = res.first->GetSupportedLanguages();
161 }
162
163 // Call IApplicationManagerInterface implementation.
164 auto& service_manager = system.ServiceManager();
165 auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2");
166 auto app_man = ns_am2->GetApplicationManagerInterface();
167
168 // Get desired application language
169 u8 desired_language{};
170 R_TRY(app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages));
171
172 // Convert to settings language code.
173 R_TRY(app_man->ConvertApplicationLanguageToLanguageCode(out_language_code, desired_language));
174
175 LOG_DEBUG(Service_AM, "got desired_language={:016X}", *out_language_code);
176 R_SUCCEED();
177}
178
179Result IApplicationFunctions::SetTerminateResult(Result terminate_result) {
180 LOG_INFO(Service_AM, "(STUBBED) called, result={:#x} ({}-{})", terminate_result.GetInnerValue(),
181 static_cast<u32>(terminate_result.GetModule()) + 2000,
182 terminate_result.GetDescription());
183
184 std::scoped_lock lk{m_applet->lock};
185 m_applet->terminate_result = terminate_result;
186
187 R_SUCCEED();
188}
189
190Result IApplicationFunctions::GetDisplayVersion(Out<DisplayVersion> out_display_version) {
191 LOG_DEBUG(Service_AM, "called");
192
193 const auto res = [this] {
194 const FileSys::PatchManager pm{m_applet->program_id, system.GetFileSystemController(),
195 system.GetContentProvider()};
196 auto metadata = pm.GetControlMetadata();
197 if (metadata.first != nullptr) {
198 return metadata;
199 }
200
201 const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(m_applet->program_id),
202 system.GetFileSystemController(),
203 system.GetContentProvider()};
204 return pm_update.GetControlMetadata();
205 }();
206
207 if (res.first != nullptr) {
208 const auto& version = res.first->GetVersionString();
209 std::memcpy(out_display_version->string.data(), version.data(),
210 std::min(version.size(), out_display_version->string.size()));
211 } else {
212 static constexpr char default_version[]{"1.0.0"};
213 std::memcpy(out_display_version->string.data(), default_version, sizeof(default_version));
214 }
215
216 out_display_version->string[out_display_version->string.size() - 1] = '\0';
217 R_SUCCEED();
218}
219
220Result IApplicationFunctions::ExtendSaveData(Out<u64> out_required_size, FileSys::SaveDataType type,
221 Common::UUID user_id, u64 normal_size,
222 u64 journal_size) {
223 LOG_DEBUG(Service_AM, "called with type={} user_id={} normal={:#x} journal={:#x}",
224 static_cast<u8>(type), user_id.FormattedString(), normal_size, journal_size);
225
226 system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize(
227 type, m_applet->program_id, user_id.AsU128(), {normal_size, journal_size});
228
229 // The following value is used to indicate the amount of space remaining on failure
230 // due to running out of space. Since we always succeed, this should be 0.
231 *out_required_size = 0;
232
233 R_SUCCEED();
234}
235
236Result IApplicationFunctions::GetSaveDataSize(Out<u64> out_normal_size, Out<u64> out_journal_size,
237 FileSys::SaveDataType type, Common::UUID user_id) {
238 LOG_DEBUG(Service_AM, "called with type={} user_id={}", type, user_id.FormattedString());
239
240 const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize(
241 type, m_applet->program_id, user_id.AsU128());
242
243 *out_normal_size = size.normal;
244 *out_journal_size = size.journal;
245 R_SUCCEED();
246}
247
248Result IApplicationFunctions::CreateCacheStorage(Out<u32> out_target_media,
249 Out<u64> out_required_size, u16 index,
250 u64 normal_size, u64 journal_size) {
251 LOG_WARNING(Service_AM, "(STUBBED) called with index={} size={:#x} journal_size={:#x}", index,
252 normal_size, journal_size);
253
254 *out_target_media = 1; // Nand
255 *out_required_size = 0;
256
257 R_SUCCEED();
258}
259
260Result IApplicationFunctions::GetSaveDataSizeMax(Out<u64> out_max_normal_size,
261 Out<u64> out_max_journal_size) {
262 LOG_WARNING(Service_AM, "(STUBBED) called");
263
264 *out_max_normal_size = 0xFFFFFFF;
265 *out_max_journal_size = 0xFFFFFFF;
266
267 R_SUCCEED();
268}
269
270Result IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(s64 unused) {
271 LOG_WARNING(Service_AM, "(STUBBED) called");
272
273 std::scoped_lock lk{m_applet->lock};
274 m_applet->home_button_long_pressed_blocked = true;
275 m_applet->home_button_short_pressed_blocked = true;
276
277 R_SUCCEED();
278}
279
280Result IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed() {
281 LOG_WARNING(Service_AM, "(STUBBED) called");
282
283 std::scoped_lock lk{m_applet->lock};
284 m_applet->home_button_long_pressed_blocked = false;
285 m_applet->home_button_short_pressed_blocked = false;
286
287 R_SUCCEED();
288}
289
290Result IApplicationFunctions::BeginBlockingHomeButton(s64 timeout_ns) {
291 LOG_WARNING(Service_AM, "(STUBBED) called, timeout_ns={}", timeout_ns);
292
293 std::scoped_lock lk{m_applet->lock};
294 m_applet->home_button_long_pressed_blocked = true;
295 m_applet->home_button_short_pressed_blocked = true;
296 m_applet->home_button_double_click_enabled = true;
297
298 R_SUCCEED();
299}
300
301Result IApplicationFunctions::EndBlockingHomeButton() {
302 LOG_WARNING(Service_AM, "(STUBBED) called");
303
304 std::scoped_lock lk{m_applet->lock};
305 m_applet->home_button_long_pressed_blocked = false;
306 m_applet->home_button_short_pressed_blocked = false;
307 m_applet->home_button_double_click_enabled = false;
308
309 R_SUCCEED();
310}
311
312Result IApplicationFunctions::NotifyRunning(Out<bool> out_became_running) {
313 LOG_WARNING(Service_AM, "(STUBBED) called");
314 *out_became_running = true;
315 R_SUCCEED();
316}
317
318Result IApplicationFunctions::GetPseudoDeviceId(Out<Common::UUID> out_pseudo_device_id) {
319 LOG_WARNING(Service_AM, "(STUBBED) called");
320 *out_pseudo_device_id = {};
321 R_SUCCEED();
322}
323
324Result IApplicationFunctions::IsGamePlayRecordingSupported(
325 Out<bool> out_is_game_play_recording_supported) {
326 LOG_WARNING(Service_AM, "(STUBBED) called");
327 *out_is_game_play_recording_supported = m_applet->game_play_recording_supported;
328 R_SUCCEED();
329}
330
331Result IApplicationFunctions::InitializeGamePlayRecording(
332 u64 transfer_memory_size, InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle) {
333 LOG_WARNING(Service_AM, "(STUBBED) called");
334 R_SUCCEED();
335}
336
337Result IApplicationFunctions::SetGamePlayRecordingState(
338 GamePlayRecordingState game_play_recording_state) {
339 LOG_WARNING(Service_AM, "(STUBBED) called");
340
341 std::scoped_lock lk{m_applet->lock};
342 m_applet->game_play_recording_state = game_play_recording_state;
343
344 R_SUCCEED();
345}
346
347Result IApplicationFunctions::EnableApplicationCrashReport(bool enabled) {
348 LOG_WARNING(Service_AM, "(STUBBED) called");
349
350 std::scoped_lock lk{m_applet->lock};
351 m_applet->application_crash_report_enabled = enabled;
352
353 R_SUCCEED();
354}
355
356Result IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(
357 s32 width, s32 height, u64 transfer_memory_size,
358 InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle) {
359 LOG_WARNING(Service_AM, "(STUBBED) called");
360 R_SUCCEED();
361}
362
363Result IApplicationFunctions::SetApplicationCopyrightImage(
364 s32 x, s32 y, s32 width, s32 height, WindowOriginMode window_origin_mode,
365 InBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> image_data) {
366 LOG_WARNING(Service_AM, "(STUBBED) called");
367 R_SUCCEED();
368}
369
370Result IApplicationFunctions::SetApplicationCopyrightVisibility(bool visible) {
371 LOG_WARNING(Service_AM, "(STUBBED) called, is_visible={}", visible);
372 R_SUCCEED();
373}
374
375Result IApplicationFunctions::QueryApplicationPlayStatistics(
376 Out<s32> out_entries,
377 OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_play_statistics,
378 InArray<u64, BufferAttr_HipcMapAlias> application_ids) {
379 LOG_WARNING(Service_AM, "(STUBBED) called");
380 *out_entries = 0;
381 R_SUCCEED();
382}
383
384Result IApplicationFunctions::QueryApplicationPlayStatisticsByUid(
385 Out<s32> out_entries,
386 OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_play_statistics,
387 Common::UUID user_id, InArray<u64, BufferAttr_HipcMapAlias> application_ids) {
388 LOG_WARNING(Service_AM, "(STUBBED) called");
389 *out_entries = 0;
390 R_SUCCEED();
391}
392
393Result IApplicationFunctions::ExecuteProgram(ProgramSpecifyKind kind, u64 value) {
394 LOG_WARNING(Service_AM, "(STUBBED) called, kind={}, value={}", kind, value);
395 ASSERT(kind == ProgramSpecifyKind::ExecuteProgram ||
396 kind == ProgramSpecifyKind::RestartProgram);
397
398 // Copy user channel ownership into the system so that it will be preserved
399 system.GetUserChannel() = m_applet->user_channel_launch_parameter;
400 system.ExecuteProgram(value);
401 R_SUCCEED();
402}
403
404Result IApplicationFunctions::ClearUserChannel() {
405 LOG_DEBUG(Service_AM, "called");
406 m_applet->user_channel_launch_parameter.clear();
407 R_SUCCEED();
408}
409
410Result IApplicationFunctions::UnpopToUserChannel(SharedPointer<IStorage> storage) {
411 LOG_DEBUG(Service_AM, "called");
412 m_applet->user_channel_launch_parameter.push_back(storage->GetData());
413 R_SUCCEED();
414}
415
416Result IApplicationFunctions::GetPreviousProgramIndex(Out<s32> out_previous_program_index) {
417 LOG_WARNING(Service_AM, "(STUBBED) called");
418 *out_previous_program_index = m_applet->previous_program_index;
419 R_SUCCEED();
420}
421
422Result IApplicationFunctions::GetGpuErrorDetectedSystemEvent(
423 OutCopyHandle<Kernel::KReadableEvent> out_event) {
424 LOG_WARNING(Service_AM, "(STUBBED) called");
425 *out_event = m_applet->gpu_error_detected_event.GetHandle();
426 R_SUCCEED();
427}
428
429Result IApplicationFunctions::GetFriendInvitationStorageChannelEvent(
430 OutCopyHandle<Kernel::KReadableEvent> out_event) {
431 LOG_DEBUG(Service_AM, "called");
432 *out_event = m_applet->friend_invitation_storage_channel_event.GetHandle();
433 R_SUCCEED();
434}
435
436Result IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(
437 Out<SharedPointer<IStorage>> out_storage) {
438 LOG_INFO(Service_AM, "(STUBBED) called");
439 R_THROW(AM::ResultNoDataInChannel);
440}
441
442Result IApplicationFunctions::GetNotificationStorageChannelEvent(
443 OutCopyHandle<Kernel::KReadableEvent> out_event) {
444 LOG_DEBUG(Service_AM, "called");
445 *out_event = m_applet->notification_storage_channel_event.GetHandle();
446 R_SUCCEED();
447}
448
449Result IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(
450 OutCopyHandle<Kernel::KReadableEvent> out_event) {
451 LOG_DEBUG(Service_AM, "called");
452 *out_event = m_applet->health_warning_disappeared_system_event.GetHandle();
453 R_SUCCEED();
454}
455
456Result IApplicationFunctions::PrepareForJit() {
457 LOG_WARNING(Service_AM, "(STUBBED) called");
458
459 std::scoped_lock lk{m_applet->lock};
460 m_applet->jit_service_launched = true;
461
462 R_SUCCEED();
463}
464
465} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/application_functions.h b/src/core/hle/service/am/service/application_functions.h
new file mode 100755
index 000000000..3548202f8
--- /dev/null
+++ b/src/core/hle/service/am/service/application_functions.h
@@ -0,0 +1,83 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "common/uuid.h"
7#include "core/hle/service/am/am_types.h"
8#include "core/hle/service/cmif_types.h"
9#include "core/hle/service/service.h"
10
11namespace FileSys {
12enum class SaveDataType : u8;
13}
14
15namespace Kernel {
16class KReadableEvent;
17}
18
19namespace Service::AM {
20
21struct Applet;
22class IStorage;
23
24class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
25public:
26 explicit IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet);
27 ~IApplicationFunctions() override;
28
29private:
30 Result PopLaunchParameter(Out<SharedPointer<IStorage>> out_storage,
31 LaunchParameterKind launch_parameter_kind);
32 Result EnsureSaveData(Out<u64> out_size, Common::UUID user_id);
33 Result GetDesiredLanguage(Out<u64> out_language_code);
34 Result SetTerminateResult(Result terminate_result);
35 Result GetDisplayVersion(Out<DisplayVersion> out_display_version);
36 Result ExtendSaveData(Out<u64> out_required_size, FileSys::SaveDataType type,
37 Common::UUID user_id, u64 normal_size, u64 journal_size);
38 Result GetSaveDataSize(Out<u64> out_normal_size, Out<u64> out_journal_size,
39 FileSys::SaveDataType type, Common::UUID user_id);
40 Result CreateCacheStorage(Out<u32> out_target_media, Out<u64> out_required_size, u16 index,
41 u64 normal_size, u64 journal_size);
42 Result GetSaveDataSizeMax(Out<u64> out_max_normal_size, Out<u64> out_max_journal_size);
43 Result BeginBlockingHomeButtonShortAndLongPressed(s64 unused);
44 Result EndBlockingHomeButtonShortAndLongPressed();
45 Result BeginBlockingHomeButton(s64 timeout_ns);
46 Result EndBlockingHomeButton();
47 Result NotifyRunning(Out<bool> out_became_running);
48 Result GetPseudoDeviceId(Out<Common::UUID> out_pseudo_device_id);
49 Result IsGamePlayRecordingSupported(Out<bool> out_is_game_play_recording_supported);
50 Result InitializeGamePlayRecording(
51 u64 transfer_memory_size, InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle);
52 Result SetGamePlayRecordingState(GamePlayRecordingState game_play_recording_state);
53 Result EnableApplicationCrashReport(bool enabled);
54 Result InitializeApplicationCopyrightFrameBuffer(
55 s32 width, s32 height, u64 transfer_memory_size,
56 InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle);
57 Result SetApplicationCopyrightImage(
58 s32 x, s32 y, s32 width, s32 height, WindowOriginMode window_origin_mode,
59 InBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> image_data);
60 Result SetApplicationCopyrightVisibility(bool visible);
61 Result QueryApplicationPlayStatistics(
62 Out<s32> out_entries,
63 OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_play_statistics,
64 InArray<u64, BufferAttr_HipcMapAlias> application_ids);
65 Result QueryApplicationPlayStatisticsByUid(
66 Out<s32> out_entries,
67 OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_play_statistics,
68 Common::UUID user_id, InArray<u64, BufferAttr_HipcMapAlias> application_ids);
69 Result ExecuteProgram(ProgramSpecifyKind kind, u64 value);
70 Result ClearUserChannel();
71 Result UnpopToUserChannel(SharedPointer<IStorage> storage);
72 Result GetPreviousProgramIndex(Out<s32> out_previous_program_index);
73 Result GetGpuErrorDetectedSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
74 Result GetFriendInvitationStorageChannelEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
75 Result TryPopFromFriendInvitationStorageChannel(Out<SharedPointer<IStorage>> out_storage);
76 Result GetNotificationStorageChannelEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
77 Result GetHealthWarningDisappearedSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
78 Result PrepareForJit();
79
80 const std::shared_ptr<Applet> m_applet;
81};
82
83} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/application_proxy.cpp b/src/core/hle/service/am/service/application_proxy.cpp
new file mode 100755
index 000000000..776f4552b
--- /dev/null
+++ b/src/core/hle/service/am/service/application_proxy.cpp
@@ -0,0 +1,106 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/service/applet_common_functions.h"
5#include "core/hle/service/am/service/application_functions.h"
6#include "core/hle/service/am/service/application_proxy.h"
7#include "core/hle/service/am/service/audio_controller.h"
8#include "core/hle/service/am/service/common_state_getter.h"
9#include "core/hle/service/am/service/debug_functions.h"
10#include "core/hle/service/am/service/display_controller.h"
11#include "core/hle/service/am/service/library_applet_creator.h"
12#include "core/hle/service/am/service/process_winding_controller.h"
13#include "core/hle/service/am/service/self_controller.h"
14#include "core/hle/service/am/service/window_controller.h"
15#include "core/hle/service/cmif_serialization.h"
16
17namespace Service::AM {
18
19IApplicationProxy::IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet,
20 Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger)
21 : ServiceFramework{system_, "IApplicationProxy"},
22 m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} {
23 // clang-format off
24 static const FunctionInfo functions[] = {
25 {0, D<&IApplicationProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
26 {1, D<&IApplicationProxy::GetSelfController>, "GetSelfController"},
27 {2, D<&IApplicationProxy::GetWindowController>, "GetWindowController"},
28 {3, D<&IApplicationProxy::GetAudioController>, "GetAudioController"},
29 {4, D<&IApplicationProxy::GetDisplayController>, "GetDisplayController"},
30 {10, D<&IApplicationProxy::GetProcessWindingController>, "GetProcessWindingController"},
31 {11, D<&IApplicationProxy::GetLibraryAppletCreator>, "GetLibraryAppletCreator"},
32 {20, D<&IApplicationProxy::GetApplicationFunctions>, "GetApplicationFunctions"},
33 {1000, D<&IApplicationProxy::GetDebugFunctions>, "GetDebugFunctions"},
34 };
35 // clang-format on
36
37 RegisterHandlers(functions);
38}
39
40IApplicationProxy::~IApplicationProxy() = default;
41
42Result IApplicationProxy::GetAudioController(
43 Out<SharedPointer<IAudioController>> out_audio_controller) {
44 LOG_DEBUG(Service_AM, "called");
45 *out_audio_controller = std::make_shared<IAudioController>(system);
46 R_SUCCEED();
47}
48
49Result IApplicationProxy::GetDisplayController(
50 Out<SharedPointer<IDisplayController>> out_display_controller) {
51 LOG_DEBUG(Service_AM, "called");
52 *out_display_controller = std::make_shared<IDisplayController>(system, m_applet);
53 R_SUCCEED();
54}
55
56Result IApplicationProxy::GetProcessWindingController(
57 Out<SharedPointer<IProcessWindingController>> out_process_winding_controller) {
58 LOG_DEBUG(Service_AM, "called");
59 *out_process_winding_controller = std::make_shared<IProcessWindingController>(system, m_applet);
60 R_SUCCEED();
61}
62
63Result IApplicationProxy::GetDebugFunctions(
64 Out<SharedPointer<IDebugFunctions>> out_debug_functions) {
65 LOG_DEBUG(Service_AM, "called");
66 *out_debug_functions = std::make_shared<IDebugFunctions>(system);
67 R_SUCCEED();
68}
69
70Result IApplicationProxy::GetWindowController(
71 Out<SharedPointer<IWindowController>> out_window_controller) {
72 LOG_DEBUG(Service_AM, "called");
73 *out_window_controller = std::make_shared<IWindowController>(system, m_applet);
74 R_SUCCEED();
75}
76
77Result IApplicationProxy::GetSelfController(
78 Out<SharedPointer<ISelfController>> out_self_controller) {
79 LOG_DEBUG(Service_AM, "called");
80 *out_self_controller =
81 std::make_shared<ISelfController>(system, m_applet, m_process, m_nvnflinger);
82 R_SUCCEED();
83}
84
85Result IApplicationProxy::GetCommonStateGetter(
86 Out<SharedPointer<ICommonStateGetter>> out_common_state_getter) {
87 LOG_DEBUG(Service_AM, "called");
88 *out_common_state_getter = std::make_shared<ICommonStateGetter>(system, m_applet);
89 R_SUCCEED();
90}
91
92Result IApplicationProxy::GetLibraryAppletCreator(
93 Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) {
94 LOG_DEBUG(Service_AM, "called");
95 *out_library_applet_creator = std::make_shared<ILibraryAppletCreator>(system, m_applet);
96 R_SUCCEED();
97}
98
99Result IApplicationProxy::GetApplicationFunctions(
100 Out<SharedPointer<IApplicationFunctions>> out_application_functions) {
101 LOG_DEBUG(Service_AM, "called");
102 *out_application_functions = std::make_shared<IApplicationFunctions>(system, m_applet);
103 R_SUCCEED();
104}
105
106} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/application_proxy.h b/src/core/hle/service/am/service/application_proxy.h
new file mode 100755
index 000000000..1ebc593ba
--- /dev/null
+++ b/src/core/hle/service/am/service/application_proxy.h
@@ -0,0 +1,48 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/service.h"
8
9namespace Service::AM {
10
11struct Applet;
12class IAudioController;
13class IApplicationFunctions;
14class ICommonStateGetter;
15class IDebugFunctions;
16class IDisplayController;
17class ILibraryAppletCreator;
18class IProcessWindingController;
19class ISelfController;
20class IWindowController;
21
22class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
23public:
24 explicit IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet,
25 Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger);
26 ~IApplicationProxy();
27
28private:
29 Result GetAudioController(Out<SharedPointer<IAudioController>> out_audio_controller);
30 Result GetDisplayController(Out<SharedPointer<IDisplayController>> out_display_controller);
31 Result GetProcessWindingController(
32 Out<SharedPointer<IProcessWindingController>> out_process_winding_controller);
33 Result GetDebugFunctions(Out<SharedPointer<IDebugFunctions>> out_debug_functions);
34 Result GetWindowController(Out<SharedPointer<IWindowController>> out_window_controller);
35 Result GetSelfController(Out<SharedPointer<ISelfController>> out_self_controller);
36 Result GetCommonStateGetter(Out<SharedPointer<ICommonStateGetter>> out_common_state_getter);
37 Result GetLibraryAppletCreator(
38 Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator);
39 Result GetApplicationFunctions(
40 Out<SharedPointer<IApplicationFunctions>> out_application_functions);
41
42private:
43 Nvnflinger::Nvnflinger& m_nvnflinger;
44 Kernel::KProcess* const m_process;
45 const std::shared_ptr<Applet> m_applet;
46};
47
48} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/application_proxy_service.cpp b/src/core/hle/service/am/service/application_proxy_service.cpp
new file mode 100755
index 000000000..36d4478df
--- /dev/null
+++ b/src/core/hle/service/am/service/application_proxy_service.cpp
@@ -0,0 +1,43 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/core.h"
5#include "core/hle/service/am/am.h"
6#include "core/hle/service/am/applet_manager.h"
7#include "core/hle/service/am/service/application_proxy.h"
8#include "core/hle/service/am/service/application_proxy_service.h"
9#include "core/hle/service/cmif_serialization.h"
10
11namespace Service::AM {
12
13IApplicationProxyService::IApplicationProxyService(Core::System& system_,
14 Nvnflinger::Nvnflinger& nvnflinger)
15 : ServiceFramework{system_, "appletOE"}, m_nvnflinger{nvnflinger} {
16 static const FunctionInfo functions[] = {
17 {0, D<&IApplicationProxyService::OpenApplicationProxy>, "OpenApplicationProxy"},
18 };
19 RegisterHandlers(functions);
20}
21
22IApplicationProxyService::~IApplicationProxyService() = default;
23
24Result IApplicationProxyService::OpenApplicationProxy(
25 Out<SharedPointer<IApplicationProxy>> out_application_proxy, ClientProcessId pid,
26 InCopyHandle<Kernel::KProcess> process_handle) {
27 LOG_DEBUG(Service_AM, "called");
28
29 if (const auto applet = this->GetAppletFromProcessId(pid)) {
30 *out_application_proxy =
31 std::make_shared<IApplicationProxy>(system, applet, process_handle.Get(), m_nvnflinger);
32 R_SUCCEED();
33 } else {
34 UNIMPLEMENTED();
35 R_THROW(ResultUnknown);
36 }
37}
38
39std::shared_ptr<Applet> IApplicationProxyService::GetAppletFromProcessId(ProcessId process_id) {
40 return system.GetAppletManager().GetByAppletResourceUserId(process_id.pid);
41}
42
43} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/application_proxy_service.h b/src/core/hle/service/am/service/application_proxy_service.h
new file mode 100755
index 000000000..1c1d32d0b
--- /dev/null
+++ b/src/core/hle/service/am/service/application_proxy_service.h
@@ -0,0 +1,35 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/service.h"
8
9namespace Service {
10
11namespace Nvnflinger {
12class Nvnflinger;
13}
14
15namespace AM {
16
17struct Applet;
18class IApplicationProxy;
19
20class IApplicationProxyService final : public ServiceFramework<IApplicationProxyService> {
21public:
22 explicit IApplicationProxyService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger);
23 ~IApplicationProxyService() override;
24
25private:
26 Result OpenApplicationProxy(Out<SharedPointer<IApplicationProxy>> out_application_proxy,
27 ClientProcessId pid, InCopyHandle<Kernel::KProcess> process_handle);
28
29private:
30 std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid);
31 Nvnflinger::Nvnflinger& m_nvnflinger;
32};
33
34} // namespace AM
35} // namespace Service
diff --git a/src/core/hle/service/am/service/audio_controller.cpp b/src/core/hle/service/am/service/audio_controller.cpp
new file mode 100755
index 000000000..ad731c7bd
--- /dev/null
+++ b/src/core/hle/service/am/service/audio_controller.cpp
@@ -0,0 +1,69 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/service/audio_controller.h"
5#include "core/hle/service/cmif_serialization.h"
6
7namespace Service::AM {
8
9IAudioController::IAudioController(Core::System& system_)
10 : ServiceFramework{system_, "IAudioController"} {
11 // clang-format off
12 static const FunctionInfo functions[] = {
13 {0, D<&IAudioController::SetExpectedMasterVolume>, "SetExpectedMasterVolume"},
14 {1, D<&IAudioController::GetMainAppletExpectedMasterVolume>, "GetMainAppletExpectedMasterVolume"},
15 {2, D<&IAudioController::GetLibraryAppletExpectedMasterVolume>, "GetLibraryAppletExpectedMasterVolume"},
16 {3, D<&IAudioController::ChangeMainAppletMasterVolume>, "ChangeMainAppletMasterVolume"},
17 {4, D<&IAudioController::SetTransparentVolumeRate>, "SetTransparentVolumeRate"},
18 };
19 // clang-format on
20
21 RegisterHandlers(functions);
22}
23
24IAudioController::~IAudioController() = default;
25
26Result IAudioController::SetExpectedMasterVolume(f32 main_applet_volume,
27 f32 library_applet_volume) {
28 LOG_DEBUG(Service_AM, "called. main_applet_volume={}, library_applet_volume={}",
29 main_applet_volume, library_applet_volume);
30
31 // Ensure the volume values remain within the 0-100% range
32 m_main_applet_volume = std::clamp(main_applet_volume, MinAllowedVolume, MaxAllowedVolume);
33 m_library_applet_volume = std::clamp(library_applet_volume, MinAllowedVolume, MaxAllowedVolume);
34
35 R_SUCCEED();
36}
37
38Result IAudioController::GetMainAppletExpectedMasterVolume(Out<f32> out_main_applet_volume) {
39 LOG_DEBUG(Service_AM, "called. main_applet_volume={}", m_main_applet_volume);
40 *out_main_applet_volume = m_main_applet_volume;
41 R_SUCCEED();
42}
43
44Result IAudioController::GetLibraryAppletExpectedMasterVolume(Out<f32> out_library_applet_volume) {
45 LOG_DEBUG(Service_AM, "called. library_applet_volume={}", m_library_applet_volume);
46 *out_library_applet_volume = m_library_applet_volume;
47 R_SUCCEED();
48}
49
50Result IAudioController::ChangeMainAppletMasterVolume(f32 volume, s64 fade_time_ns) {
51 LOG_DEBUG(Service_AM, "called. volume={}, fade_time_ns={}", volume, fade_time_ns);
52
53 m_main_applet_volume = std::clamp(volume, MinAllowedVolume, MaxAllowedVolume);
54 m_fade_time_ns = std::chrono::nanoseconds{fade_time_ns};
55
56 R_SUCCEED();
57}
58
59Result IAudioController::SetTransparentVolumeRate(f32 transparent_volume_rate) {
60 LOG_DEBUG(Service_AM, "called. transparent_volume_rate={}", transparent_volume_rate);
61
62 // Clamp volume range to 0-100%.
63 m_transparent_volume_rate =
64 std::clamp(transparent_volume_rate, MinAllowedVolume, MaxAllowedVolume);
65
66 R_SUCCEED();
67}
68
69} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/audio_controller.h b/src/core/hle/service/am/service/audio_controller.h
new file mode 100755
index 000000000..4b0f3f9ae
--- /dev/null
+++ b/src/core/hle/service/am/service/audio_controller.h
@@ -0,0 +1,37 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/service.h"
8
9namespace Service::AM {
10
11class IAudioController final : public ServiceFramework<IAudioController> {
12public:
13 explicit IAudioController(Core::System& system_);
14 ~IAudioController() override;
15
16private:
17 Result SetExpectedMasterVolume(f32 main_applet_volume, f32 library_applet_volume);
18 Result GetMainAppletExpectedMasterVolume(Out<f32> out_main_applet_volume);
19 Result GetLibraryAppletExpectedMasterVolume(Out<f32> out_library_applet_volume);
20 Result ChangeMainAppletMasterVolume(f32 volume, s64 fade_time_ns);
21 Result SetTransparentVolumeRate(f32 transparent_volume_rate);
22
23 static constexpr float MinAllowedVolume = 0.0f;
24 static constexpr float MaxAllowedVolume = 1.0f;
25
26 float m_main_applet_volume{0.25f};
27 float m_library_applet_volume{MaxAllowedVolume};
28 float m_transparent_volume_rate{MinAllowedVolume};
29
30 // Volume transition fade time in nanoseconds.
31 // e.g. If the main applet volume was 0% and was changed to 50%
32 // with a fade of 50ns, then over the course of 50ns,
33 // the volume will gradually fade up to 50%
34 std::chrono::nanoseconds m_fade_time_ns{0};
35};
36
37} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/common_state_getter.cpp b/src/core/hle/service/am/service/common_state_getter.cpp
new file mode 100755
index 000000000..12d7e8cb1
--- /dev/null
+++ b/src/core/hle/service/am/service/common_state_getter.cpp
@@ -0,0 +1,277 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "common/settings.h"
5#include "core/hle/service/am/am_results.h"
6#include "core/hle/service/am/applet.h"
7#include "core/hle/service/am/service/common_state_getter.h"
8#include "core/hle/service/am/service/lock_accessor.h"
9#include "core/hle/service/apm/apm_interface.h"
10#include "core/hle/service/cmif_serialization.h"
11#include "core/hle/service/pm/pm.h"
12#include "core/hle/service/sm/sm.h"
13#include "core/hle/service/vi/vi.h"
14
15namespace Service::AM {
16
17ICommonStateGetter::ICommonStateGetter(Core::System& system_, std::shared_ptr<Applet> applet)
18 : ServiceFramework{system_, "ICommonStateGetter"}, m_applet{std::move(applet)} {
19 // clang-format off
20 static const FunctionInfo functions[] = {
21 {0, D<&ICommonStateGetter::GetEventHandle>, "GetEventHandle"},
22 {1, D<&ICommonStateGetter::ReceiveMessage>, "ReceiveMessage"},
23 {2, nullptr, "GetThisAppletKind"},
24 {3, nullptr, "AllowToEnterSleep"},
25 {4, nullptr, "DisallowToEnterSleep"},
26 {5, D<&ICommonStateGetter::GetOperationMode>, "GetOperationMode"},
27 {6, D<&ICommonStateGetter::GetPerformanceMode>, "GetPerformanceMode"},
28 {7, nullptr, "GetCradleStatus"},
29 {8, D<&ICommonStateGetter::GetBootMode>, "GetBootMode"},
30 {9, D<&ICommonStateGetter::GetCurrentFocusState>, "GetCurrentFocusState"},
31 {10, D<&ICommonStateGetter::RequestToAcquireSleepLock>, "RequestToAcquireSleepLock"},
32 {11, nullptr, "ReleaseSleepLock"},
33 {12, nullptr, "ReleaseSleepLockTransiently"},
34 {13, D<&ICommonStateGetter::GetAcquiredSleepLockEvent>, "GetAcquiredSleepLockEvent"},
35 {14, nullptr, "GetWakeupCount"},
36 {20, nullptr, "PushToGeneralChannel"},
37 {30, nullptr, "GetHomeButtonReaderLockAccessor"},
38 {31, D<&ICommonStateGetter::GetReaderLockAccessorEx>, "GetReaderLockAccessorEx"},
39 {32, D<&ICommonStateGetter::GetWriterLockAccessorEx>, "GetWriterLockAccessorEx"},
40 {40, nullptr, "GetCradleFwVersion"},
41 {50, D<&ICommonStateGetter::IsVrModeEnabled>, "IsVrModeEnabled"},
42 {51, D<&ICommonStateGetter::SetVrModeEnabled>, "SetVrModeEnabled"},
43 {52, D<&ICommonStateGetter::SetLcdBacklighOffEnabled>, "SetLcdBacklighOffEnabled"},
44 {53, D<&ICommonStateGetter::BeginVrModeEx>, "BeginVrModeEx"},
45 {54, D<&ICommonStateGetter::EndVrModeEx>, "EndVrModeEx"},
46 {55, D<&ICommonStateGetter::IsInControllerFirmwareUpdateSection>, "IsInControllerFirmwareUpdateSection"},
47 {59, nullptr, "SetVrPositionForDebug"},
48 {60, D<&ICommonStateGetter::GetDefaultDisplayResolution>, "GetDefaultDisplayResolution"},
49 {61, D<&ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent>, "GetDefaultDisplayResolutionChangeEvent"},
50 {62, nullptr, "GetHdcpAuthenticationState"},
51 {63, nullptr, "GetHdcpAuthenticationStateChangeEvent"},
52 {64, nullptr, "SetTvPowerStateMatchingMode"},
53 {65, nullptr, "GetApplicationIdByContentActionName"},
54 {66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"},
55 {67, nullptr, "CancelCpuBoostMode"},
56 {68, D<&ICommonStateGetter::GetBuiltInDisplayType>, "GetBuiltInDisplayType"},
57 {80, D<&ICommonStateGetter::PerformSystemButtonPressingIfInFocus>, "PerformSystemButtonPressingIfInFocus"},
58 {90, nullptr, "SetPerformanceConfigurationChangedNotification"},
59 {91, nullptr, "GetCurrentPerformanceConfiguration"},
60 {100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"},
61 {110, nullptr, "OpenMyGpuErrorHandler"},
62 {120, D<&ICommonStateGetter::GetAppletLaunchedHistory>, "GetAppletLaunchedHistory"},
63 {200, D<&ICommonStateGetter::GetOperationModeSystemInfo>, "GetOperationModeSystemInfo"},
64 {300, D<&ICommonStateGetter::GetSettingsPlatformRegion>, "GetSettingsPlatformRegion"},
65 {400, nullptr, "ActivateMigrationService"},
66 {401, nullptr, "DeactivateMigrationService"},
67 {500, nullptr, "DisableSleepTillShutdown"},
68 {501, nullptr, "SuppressDisablingSleepTemporarily"},
69 {502, nullptr, "IsSleepEnabled"},
70 {503, nullptr, "IsDisablingSleepSuppressed"},
71 {900, D<&ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled>, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"},
72 };
73 // clang-format on
74
75 RegisterHandlers(functions);
76}
77
78ICommonStateGetter::~ICommonStateGetter() = default;
79
80Result ICommonStateGetter::GetEventHandle(OutCopyHandle<Kernel::KReadableEvent> out_event) {
81 LOG_DEBUG(Service_AM, "called");
82 *out_event = &m_applet->message_queue.GetMessageReceiveEvent();
83 R_SUCCEED();
84}
85
86Result ICommonStateGetter::ReceiveMessage(Out<AppletMessage> out_applet_message) {
87 LOG_DEBUG(Service_AM, "called");
88
89 *out_applet_message = m_applet->message_queue.PopMessage();
90 if (*out_applet_message == AppletMessage::None) {
91 LOG_ERROR(Service_AM, "Tried to pop message but none was available!");
92 R_THROW(AM::ResultNoMessages);
93 }
94
95 R_SUCCEED();
96}
97
98Result ICommonStateGetter::GetCurrentFocusState(Out<FocusState> out_focus_state) {
99 LOG_DEBUG(Service_AM, "called");
100
101 std::scoped_lock lk{m_applet->lock};
102 *out_focus_state = m_applet->focus_state;
103
104 R_SUCCEED();
105}
106
107Result ICommonStateGetter::RequestToAcquireSleepLock() {
108 LOG_WARNING(Service_AM, "(STUBBED) called");
109
110 // Sleep lock is acquired immediately.
111 m_applet->sleep_lock_event.Signal();
112 R_SUCCEED();
113}
114
115Result ICommonStateGetter::GetAcquiredSleepLockEvent(
116 OutCopyHandle<Kernel::KReadableEvent> out_event) {
117 LOG_WARNING(Service_AM, "called");
118 *out_event = m_applet->sleep_lock_event.GetHandle();
119 R_SUCCEED();
120}
121
122Result ICommonStateGetter::GetReaderLockAccessorEx(
123 Out<SharedPointer<ILockAccessor>> out_lock_accessor, u32 button_type) {
124 LOG_INFO(Service_AM, "called, button_type={}", button_type);
125 *out_lock_accessor = std::make_shared<ILockAccessor>(system);
126 R_SUCCEED();
127}
128
129Result ICommonStateGetter::GetWriterLockAccessorEx(
130 Out<SharedPointer<ILockAccessor>> out_lock_accessor, u32 button_type) {
131 LOG_INFO(Service_AM, "called, button_type={}", button_type);
132 *out_lock_accessor = std::make_shared<ILockAccessor>(system);
133 R_SUCCEED();
134}
135
136Result ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(
137 OutCopyHandle<Kernel::KReadableEvent> out_event) {
138 LOG_DEBUG(Service_AM, "called");
139 *out_event = &m_applet->message_queue.GetOperationModeChangedEvent();
140 R_SUCCEED();
141}
142
143Result ICommonStateGetter::GetOperationMode(Out<OperationMode> out_operation_mode) {
144 const bool use_docked_mode{Settings::IsDockedMode()};
145 LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode);
146 *out_operation_mode = use_docked_mode ? OperationMode::Docked : OperationMode::Handheld;
147 R_SUCCEED();
148}
149
150Result ICommonStateGetter::GetPerformanceMode(Out<APM::PerformanceMode> out_performance_mode) {
151 LOG_DEBUG(Service_AM, "called");
152 *out_performance_mode = system.GetAPMController().GetCurrentPerformanceMode();
153 R_SUCCEED();
154}
155
156Result ICommonStateGetter::GetBootMode(Out<PM::SystemBootMode> out_boot_mode) {
157 LOG_DEBUG(Service_AM, "called");
158 *out_boot_mode = Service::PM::SystemBootMode::Normal;
159 R_SUCCEED();
160}
161
162Result ICommonStateGetter::IsVrModeEnabled(Out<bool> out_is_vr_mode_enabled) {
163 LOG_DEBUG(Service_AM, "called");
164
165 std::scoped_lock lk{m_applet->lock};
166 *out_is_vr_mode_enabled = m_applet->vr_mode_enabled;
167 R_SUCCEED();
168}
169
170Result ICommonStateGetter::SetVrModeEnabled(bool is_vr_mode_enabled) {
171 std::scoped_lock lk{m_applet->lock};
172 m_applet->vr_mode_enabled = is_vr_mode_enabled;
173 LOG_WARNING(Service_AM, "VR Mode is {}", m_applet->vr_mode_enabled ? "on" : "off");
174 R_SUCCEED();
175}
176
177Result ICommonStateGetter::SetLcdBacklighOffEnabled(bool is_lcd_backlight_off_enabled) {
178 LOG_WARNING(Service_AM, "(STUBBED) called. is_lcd_backlight_off_enabled={}",
179 is_lcd_backlight_off_enabled);
180 R_SUCCEED();
181}
182
183Result ICommonStateGetter::BeginVrModeEx() {
184 LOG_WARNING(Service_AM, "(STUBBED) called");
185 std::scoped_lock lk{m_applet->lock};
186 m_applet->vr_mode_enabled = true;
187 R_SUCCEED();
188}
189
190Result ICommonStateGetter::EndVrModeEx() {
191 LOG_WARNING(Service_AM, "(STUBBED) called");
192 std::scoped_lock lk{m_applet->lock};
193 m_applet->vr_mode_enabled = false;
194 R_SUCCEED();
195}
196
197Result ICommonStateGetter::IsInControllerFirmwareUpdateSection(
198 Out<bool> out_is_in_controller_firmware_update_section) {
199 LOG_INFO(Service_AM, "called");
200 *out_is_in_controller_firmware_update_section = false;
201 R_SUCCEED();
202}
203
204Result ICommonStateGetter::GetDefaultDisplayResolution(Out<s32> out_width, Out<s32> out_height) {
205 LOG_DEBUG(Service_AM, "called");
206
207 if (Settings::IsDockedMode()) {
208 *out_width = static_cast<u32>(Service::VI::DisplayResolution::DockedWidth);
209 *out_height = static_cast<u32>(Service::VI::DisplayResolution::DockedHeight);
210 } else {
211 *out_width = static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth);
212 *out_height = static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight);
213 }
214
215 R_SUCCEED();
216}
217
218void ICommonStateGetter::SetCpuBoostMode(HLERequestContext& ctx) {
219 LOG_DEBUG(Service_AM, "called, forwarding to APM:SYS");
220
221 const auto& sm = system.ServiceManager();
222 const auto apm_sys = sm.GetService<APM::APM_Sys>("apm:sys");
223 ASSERT(apm_sys != nullptr);
224
225 apm_sys->SetCpuBoostMode(ctx);
226}
227
228Result ICommonStateGetter::GetBuiltInDisplayType(Out<s32> out_display_type) {
229 LOG_WARNING(Service_AM, "(STUBBED) called");
230 *out_display_type = 0;
231 R_SUCCEED();
232}
233
234Result ICommonStateGetter::PerformSystemButtonPressingIfInFocus(SystemButtonType type) {
235 LOG_WARNING(Service_AM, "(STUBBED) called, type={}", type);
236 R_SUCCEED();
237}
238
239Result ICommonStateGetter::GetOperationModeSystemInfo(Out<u32> out_operation_mode_system_info) {
240 LOG_WARNING(Service_AM, "(STUBBED) called");
241 *out_operation_mode_system_info = 0;
242 R_SUCCEED();
243}
244
245Result ICommonStateGetter::GetAppletLaunchedHistory(
246 Out<s32> out_count, OutArray<AppletId, BufferAttr_HipcMapAlias> out_applet_ids) {
247 LOG_INFO(Service_AM, "called");
248
249 std::shared_ptr<Applet> current_applet = m_applet;
250
251 for (*out_count = 0;
252 *out_count < static_cast<s32>(out_applet_ids.size()) && current_applet != nullptr;
253 /* ... */) {
254 out_applet_ids[(*out_count)++] = current_applet->applet_id;
255 current_applet = current_applet->caller_applet.lock();
256 }
257
258 R_SUCCEED();
259}
260
261Result ICommonStateGetter::GetSettingsPlatformRegion(
262 Out<SysPlatformRegion> out_settings_platform_region) {
263 LOG_INFO(Service_AM, "called");
264 *out_settings_platform_region = SysPlatformRegion::Global;
265 R_SUCCEED();
266}
267
268Result ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled() {
269 LOG_WARNING(Service_AM, "(STUBBED) called");
270
271 std::scoped_lock lk{m_applet->lock};
272 m_applet->request_exit_to_library_applet_at_execute_next_program_enabled = true;
273
274 R_SUCCEED();
275}
276
277} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/common_state_getter.h b/src/core/hle/service/am/service/common_state_getter.h
new file mode 100755
index 000000000..5a8dca3d6
--- /dev/null
+++ b/src/core/hle/service/am/service/common_state_getter.h
@@ -0,0 +1,61 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/am/am_types.h"
7#include "core/hle/service/apm/apm_controller.h"
8#include "core/hle/service/cmif_types.h"
9#include "core/hle/service/pm/pm.h"
10#include "core/hle/service/service.h"
11
12namespace Kernel {
13class KReadableEvent;
14}
15
16namespace Service::AM {
17
18struct Applet;
19class ILockAccessor;
20
21class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
22public:
23 explicit ICommonStateGetter(Core::System& system_, std::shared_ptr<Applet> applet_);
24 ~ICommonStateGetter() override;
25
26private:
27 Result GetEventHandle(OutCopyHandle<Kernel::KReadableEvent> out_event);
28 Result ReceiveMessage(Out<AppletMessage> out_applet_message);
29 Result GetCurrentFocusState(Out<FocusState> out_focus_state);
30 Result RequestToAcquireSleepLock();
31 Result GetAcquiredSleepLockEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
32 Result GetReaderLockAccessorEx(Out<SharedPointer<ILockAccessor>> out_lock_accessor,
33 u32 button_type);
34 Result GetWriterLockAccessorEx(Out<SharedPointer<ILockAccessor>> out_lock_accessor,
35 u32 button_type);
36 Result GetDefaultDisplayResolutionChangeEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
37 Result GetOperationMode(Out<OperationMode> out_operation_mode);
38 Result GetPerformanceMode(Out<APM::PerformanceMode> out_performance_mode);
39 Result GetBootMode(Out<PM::SystemBootMode> out_boot_mode);
40 Result IsVrModeEnabled(Out<bool> out_is_vr_mode_enabled);
41 Result SetVrModeEnabled(bool is_vr_mode_enabled);
42 Result SetLcdBacklighOffEnabled(bool is_lcd_backlight_off_enabled);
43 Result BeginVrModeEx();
44 Result EndVrModeEx();
45 Result IsInControllerFirmwareUpdateSection(
46 Out<bool> out_is_in_controller_firmware_update_section);
47 Result GetDefaultDisplayResolution(Out<s32> out_width, Out<s32> out_height);
48 Result GetBuiltInDisplayType(Out<s32> out_display_type);
49 Result PerformSystemButtonPressingIfInFocus(SystemButtonType type);
50 Result GetOperationModeSystemInfo(Out<u32> out_operation_mode_system_info);
51 Result GetAppletLaunchedHistory(Out<s32> out_count,
52 OutArray<AppletId, BufferAttr_HipcMapAlias> out_applet_ids);
53 Result GetSettingsPlatformRegion(Out<SysPlatformRegion> out_settings_platform_region);
54 Result SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled();
55
56 void SetCpuBoostMode(HLERequestContext& ctx);
57
58 const std::shared_ptr<Applet> m_applet;
59};
60
61} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/cradle_firmware_updater.cpp b/src/core/hle/service/am/service/cradle_firmware_updater.cpp
new file mode 100755
index 000000000..0a8af0858
--- /dev/null
+++ b/src/core/hle/service/am/service/cradle_firmware_updater.cpp
@@ -0,0 +1,52 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/service/cradle_firmware_updater.h"
5#include "core/hle/service/cmif_serialization.h"
6
7namespace Service::AM {
8
9ICradleFirmwareUpdater::ICradleFirmwareUpdater(Core::System& system_)
10 : ServiceFramework{system_, "ICradleFirmwareUpdater"},
11 m_context{system, "ICradleFirmwareUpdater"}, m_cradle_device_info_event{m_context} {
12 // clang-format off
13 static const FunctionInfo functions[] = {
14 {0, D<&ICradleFirmwareUpdater::StartUpdate>, "StartUpdate"},
15 {1, D<&ICradleFirmwareUpdater::FinishUpdate>, "FinishUpdate"},
16 {2, D<&ICradleFirmwareUpdater::GetCradleDeviceInfo>, "GetCradleDeviceInfo"},
17 {3, D<&ICradleFirmwareUpdater::GetCradleDeviceInfoChangeEvent>, "GetCradleDeviceInfoChangeEvent"},
18 {4, nullptr, "GetUpdateProgressInfo"},
19 {5, nullptr, "GetLastInternalResult"},
20
21 };
22 // clang-format on
23
24 RegisterHandlers(functions);
25}
26
27ICradleFirmwareUpdater::~ICradleFirmwareUpdater() = default;
28
29Result ICradleFirmwareUpdater::StartUpdate() {
30 LOG_WARNING(Service_AM, "(STUBBED) called");
31 R_SUCCEED();
32}
33
34Result ICradleFirmwareUpdater::FinishUpdate() {
35 LOG_WARNING(Service_AM, "(STUBBED) called");
36 R_SUCCEED();
37}
38
39Result ICradleFirmwareUpdater::GetCradleDeviceInfo(Out<CradleDeviceInfo> out_cradle_device_info) {
40 LOG_WARNING(Service_AM, "(STUBBED) called");
41 *out_cradle_device_info = {};
42 R_SUCCEED();
43}
44
45Result ICradleFirmwareUpdater::GetCradleDeviceInfoChangeEvent(
46 OutCopyHandle<Kernel::KReadableEvent> out_event) {
47 LOG_WARNING(Service_AM, "(STUBBED) called");
48 *out_event = m_cradle_device_info_event.GetHandle();
49 R_SUCCEED();
50}
51
52} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/cradle_firmware_updater.h b/src/core/hle/service/am/service/cradle_firmware_updater.h
new file mode 100755
index 000000000..3e803f0ae
--- /dev/null
+++ b/src/core/hle/service/am/service/cradle_firmware_updater.h
@@ -0,0 +1,37 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/kernel_helpers.h"
8#include "core/hle/service/os/event.h"
9#include "core/hle/service/service.h"
10
11namespace Service::AM {
12
13struct CradleDeviceInfo {
14 bool unknown0;
15 bool unknown1;
16 bool unknown2;
17 u64 unknown3;
18};
19static_assert(sizeof(CradleDeviceInfo) == 0x10, "CradleDeviceInfo has incorrect size");
20
21class ICradleFirmwareUpdater final : public ServiceFramework<ICradleFirmwareUpdater> {
22public:
23 explicit ICradleFirmwareUpdater(Core::System& system_);
24 ~ICradleFirmwareUpdater() override;
25
26private:
27 Result StartUpdate();
28 Result FinishUpdate();
29 Result GetCradleDeviceInfo(Out<CradleDeviceInfo> out_cradle_device_info);
30 Result GetCradleDeviceInfoChangeEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
31
32private:
33 KernelHelpers::ServiceContext m_context;
34 Event m_cradle_device_info_event;
35};
36
37} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/debug_functions.cpp b/src/core/hle/service/am/service/debug_functions.cpp
new file mode 100755
index 000000000..fcac4776d
--- /dev/null
+++ b/src/core/hle/service/am/service/debug_functions.cpp
@@ -0,0 +1,43 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/service/debug_functions.h"
5
6namespace Service::AM {
7
8IDebugFunctions::IDebugFunctions(Core::System& system_)
9 : ServiceFramework{system_, "IDebugFunctions"} {
10 // clang-format off
11 static const FunctionInfo functions[] = {
12 {0, nullptr, "NotifyMessageToHomeMenuForDebug"},
13 {1, nullptr, "OpenMainApplication"},
14 {10, nullptr, "PerformSystemButtonPressing"},
15 {20, nullptr, "InvalidateTransitionLayer"},
16 {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"},
17 {31, nullptr, "RequestLaunchApplicationByApplicationLaunchInfoForDebug"},
18 {40, nullptr, "GetAppletResourceUsageInfo"},
19 {50, nullptr, "AddSystemProgramIdAndAppletIdForDebug"},
20 {51, nullptr, "AddOperationConfirmedLibraryAppletIdForDebug"},
21 {100, nullptr, "SetCpuBoostModeForApplet"},
22 {101, nullptr, "CancelCpuBoostModeForApplet"},
23 {110, nullptr, "PushToAppletBoundChannelForDebug"},
24 {111, nullptr, "TryPopFromAppletBoundChannelForDebug"},
25 {120, nullptr, "AlarmSettingNotificationEnableAppEventReserve"},
26 {121, nullptr, "AlarmSettingNotificationDisableAppEventReserve"},
27 {122, nullptr, "AlarmSettingNotificationPushAppEventNotify"},
28 {130, nullptr, "FriendInvitationSetApplicationParameter"},
29 {131, nullptr, "FriendInvitationClearApplicationParameter"},
30 {132, nullptr, "FriendInvitationPushApplicationParameter"},
31 {140, nullptr, "RestrictPowerOperationForSecureLaunchModeForDebug"},
32 {200, nullptr, "CreateFloatingLibraryAppletAccepterForDebug"},
33 {300, nullptr, "TerminateAllRunningApplicationsForDebug"},
34 {900, nullptr, "GetGrcProcessLaunchedSystemEvent"},
35 };
36 // clang-format on
37
38 RegisterHandlers(functions);
39}
40
41IDebugFunctions::~IDebugFunctions() = default;
42
43} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/debug_functions.h b/src/core/hle/service/am/service/debug_functions.h
new file mode 100755
index 000000000..d55968743
--- /dev/null
+++ b/src/core/hle/service/am/service/debug_functions.h
@@ -0,0 +1,16 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/service.h"
7
8namespace Service::AM {
9
10class IDebugFunctions final : public ServiceFramework<IDebugFunctions> {
11public:
12 explicit IDebugFunctions(Core::System& system_);
13 ~IDebugFunctions() override;
14};
15
16} // 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
new file mode 100755
index 000000000..249c73dfb
--- /dev/null
+++ b/src/core/hle/service/am/service/display_controller.cpp
@@ -0,0 +1,105 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/result.h"
5#include "core/hle/service/am/applet.h"
6#include "core/hle/service/am/service/display_controller.h"
7#include "core/hle/service/cmif_serialization.h"
8
9namespace Service::AM {
10
11IDisplayController::IDisplayController(Core::System& system_, std::shared_ptr<Applet> applet_)
12 : ServiceFramework{system_, "IDisplayController"}, applet(std::move(applet_)) {
13 // clang-format off
14 static const FunctionInfo functions[] = {
15 {0, nullptr, "GetLastForegroundCaptureImage"},
16 {1, nullptr, "UpdateLastForegroundCaptureImage"},
17 {2, nullptr, "GetLastApplicationCaptureImage"},
18 {3, nullptr, "GetCallerAppletCaptureImage"},
19 {4, nullptr, "UpdateCallerAppletCaptureImage"},
20 {5, nullptr, "GetLastForegroundCaptureImageEx"},
21 {6, nullptr, "GetLastApplicationCaptureImageEx"},
22 {7, D<&IDisplayController::GetCallerAppletCaptureImageEx>, "GetCallerAppletCaptureImageEx"},
23 {8, D<&IDisplayController::TakeScreenShotOfOwnLayer>, "TakeScreenShotOfOwnLayer"},
24 {9, nullptr, "CopyBetweenCaptureBuffers"},
25 {10, nullptr, "AcquireLastApplicationCaptureBuffer"},
26 {11, nullptr, "ReleaseLastApplicationCaptureBuffer"},
27 {12, nullptr, "AcquireLastForegroundCaptureBuffer"},
28 {13, nullptr, "ReleaseLastForegroundCaptureBuffer"},
29 {14, nullptr, "AcquireCallerAppletCaptureBuffer"},
30 {15, nullptr, "ReleaseCallerAppletCaptureBuffer"},
31 {16, nullptr, "AcquireLastApplicationCaptureBufferEx"},
32 {17, nullptr, "AcquireLastForegroundCaptureBufferEx"},
33 {18, nullptr, "AcquireCallerAppletCaptureBufferEx"},
34 {20, D<&IDisplayController::ClearCaptureBuffer>, "ClearCaptureBuffer"},
35 {21, nullptr, "ClearAppletTransitionBuffer"},
36 {22, D<&IDisplayController::AcquireLastApplicationCaptureSharedBuffer>, "AcquireLastApplicationCaptureSharedBuffer"},
37 {23, D<&IDisplayController::ReleaseLastApplicationCaptureSharedBuffer>, "ReleaseLastApplicationCaptureSharedBuffer"},
38 {24, D<&IDisplayController::AcquireLastForegroundCaptureSharedBuffer>, "AcquireLastForegroundCaptureSharedBuffer"},
39 {25, D<&IDisplayController::ReleaseLastForegroundCaptureSharedBuffer>, "ReleaseLastForegroundCaptureSharedBuffer"},
40 {26, D<&IDisplayController::AcquireCallerAppletCaptureSharedBuffer>, "AcquireCallerAppletCaptureSharedBuffer"},
41 {27, D<&IDisplayController::ReleaseCallerAppletCaptureSharedBuffer>, "ReleaseCallerAppletCaptureSharedBuffer"},
42 {28, nullptr, "TakeScreenShotOfOwnLayerEx"},
43 };
44 // clang-format on
45
46 RegisterHandlers(functions);
47}
48
49IDisplayController::~IDisplayController() = default;
50
51Result IDisplayController::GetCallerAppletCaptureImageEx(
52 Out<bool> out_was_written, OutBuffer<BufferAttr_HipcMapAlias> out_image_data) {
53 LOG_WARNING(Service_AM, "(STUBBED) called");
54 *out_was_written = true;
55 R_SUCCEED();
56}
57
58Result IDisplayController::TakeScreenShotOfOwnLayer(bool unknown0, s32 fbshare_layer_index) {
59 LOG_WARNING(Service_AM, "(STUBBED) called");
60 R_SUCCEED();
61}
62
63Result IDisplayController::ClearCaptureBuffer(bool unknown0, s32 fbshare_layer_index, u32 color) {
64 LOG_WARNING(Service_AM, "(STUBBED) called, unknown0={} fbshare_layer_index={} color={:#x}",
65 unknown0, fbshare_layer_index, color);
66 R_SUCCEED();
67}
68
69Result IDisplayController::AcquireLastForegroundCaptureSharedBuffer(
70 Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
71 LOG_WARNING(Service_AM, "(STUBBED) called");
72 R_RETURN(applet->system_buffer_manager.WriteAppletCaptureBuffer(out_was_written,
73 out_fbshare_layer_index));
74}
75
76Result IDisplayController::ReleaseLastForegroundCaptureSharedBuffer() {
77 LOG_WARNING(Service_AM, "(STUBBED) called");
78 R_SUCCEED();
79}
80
81Result IDisplayController::AcquireCallerAppletCaptureSharedBuffer(
82 Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
83 LOG_WARNING(Service_AM, "(STUBBED) called");
84 R_RETURN(applet->system_buffer_manager.WriteAppletCaptureBuffer(out_was_written,
85 out_fbshare_layer_index));
86}
87
88Result IDisplayController::ReleaseCallerAppletCaptureSharedBuffer() {
89 LOG_WARNING(Service_AM, "(STUBBED) called");
90 R_SUCCEED();
91}
92
93Result IDisplayController::AcquireLastApplicationCaptureSharedBuffer(
94 Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
95 LOG_WARNING(Service_AM, "(STUBBED) called");
96 R_RETURN(applet->system_buffer_manager.WriteAppletCaptureBuffer(out_was_written,
97 out_fbshare_layer_index));
98}
99
100Result IDisplayController::ReleaseLastApplicationCaptureSharedBuffer() {
101 LOG_WARNING(Service_AM, "(STUBBED) called");
102 R_SUCCEED();
103}
104
105} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/display_controller.h b/src/core/hle/service/am/service/display_controller.h
new file mode 100755
index 000000000..406fae21a
--- /dev/null
+++ b/src/core/hle/service/am/service/display_controller.h
@@ -0,0 +1,36 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/service.h"
8
9namespace Service::AM {
10
11struct Applet;
12
13class IDisplayController final : public ServiceFramework<IDisplayController> {
14public:
15 explicit IDisplayController(Core::System& system_, std::shared_ptr<Applet> applet_);
16 ~IDisplayController() override;
17
18private:
19 Result GetCallerAppletCaptureImageEx(Out<bool> out_was_written,
20 OutBuffer<BufferAttr_HipcMapAlias> out_image_data);
21 Result TakeScreenShotOfOwnLayer(bool unknown0, s32 fbshare_layer_index);
22 Result ClearCaptureBuffer(bool unknown0, s32 fbshare_layer_index, u32 color);
23 Result AcquireLastForegroundCaptureSharedBuffer(Out<bool> out_was_written,
24 Out<s32> out_fbshare_layer_index);
25 Result ReleaseLastForegroundCaptureSharedBuffer();
26 Result AcquireCallerAppletCaptureSharedBuffer(Out<bool> out_was_written,
27 Out<s32> out_fbshare_layer_index);
28 Result ReleaseCallerAppletCaptureSharedBuffer();
29 Result AcquireLastApplicationCaptureSharedBuffer(Out<bool> out_was_written,
30 Out<s32> out_fbshare_layer_index);
31 Result ReleaseLastApplicationCaptureSharedBuffer();
32
33 const std::shared_ptr<Applet> applet;
34};
35
36} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/global_state_controller.cpp b/src/core/hle/service/am/service/global_state_controller.cpp
new file mode 100755
index 000000000..dba5d3613
--- /dev/null
+++ b/src/core/hle/service/am/service/global_state_controller.cpp
@@ -0,0 +1,61 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/service/cradle_firmware_updater.h"
5#include "core/hle/service/am/service/global_state_controller.h"
6#include "core/hle/service/cmif_serialization.h"
7
8namespace Service::AM {
9
10IGlobalStateController::IGlobalStateController(Core::System& system_)
11 : ServiceFramework{system_, "IGlobalStateController"},
12 m_context{system_, "IGlobalStateController"}, m_hdcp_authentication_failed_event{m_context} {
13 // clang-format off
14 static const FunctionInfo functions[] = {
15 {0, nullptr, "RequestToEnterSleep"},
16 {1, nullptr, "EnterSleep"},
17 {2, nullptr, "StartSleepSequence"},
18 {3, nullptr, "StartShutdownSequence"},
19 {4, nullptr, "StartRebootSequence"},
20 {9, nullptr, "IsAutoPowerDownRequested"},
21 {10, D<&IGlobalStateController::LoadAndApplyIdlePolicySettings>, "LoadAndApplyIdlePolicySettings"},
22 {11, nullptr, "NotifyCecSettingsChanged"},
23 {12, nullptr, "SetDefaultHomeButtonLongPressTime"},
24 {13, nullptr, "UpdateDefaultDisplayResolution"},
25 {14, D<&IGlobalStateController::ShouldSleepOnBoot>, "ShouldSleepOnBoot"},
26 {15, D<&IGlobalStateController::GetHdcpAuthenticationFailedEvent>, "GetHdcpAuthenticationFailedEvent"},
27 {30, D<&IGlobalStateController::OpenCradleFirmwareUpdater>, "OpenCradleFirmwareUpdater"},
28 };
29 // clang-format on
30
31 RegisterHandlers(functions);
32}
33
34IGlobalStateController::~IGlobalStateController() = default;
35
36Result IGlobalStateController::LoadAndApplyIdlePolicySettings() {
37 LOG_WARNING(Service_AM, "(STUBBED) called");
38 R_SUCCEED();
39}
40
41Result IGlobalStateController::ShouldSleepOnBoot(Out<bool> out_should_sleep_on_boot) {
42 LOG_INFO(Service_AM, "called");
43 *out_should_sleep_on_boot = false;
44 R_SUCCEED();
45}
46
47Result IGlobalStateController::GetHdcpAuthenticationFailedEvent(
48 OutCopyHandle<Kernel::KReadableEvent> out_event) {
49 LOG_INFO(Service_AM, "called");
50 *out_event = m_hdcp_authentication_failed_event.GetHandle();
51 R_SUCCEED();
52}
53
54Result IGlobalStateController::OpenCradleFirmwareUpdater(
55 Out<SharedPointer<ICradleFirmwareUpdater>> out_cradle_firmware_updater) {
56 LOG_INFO(Service_AM, "called");
57 *out_cradle_firmware_updater = std::make_shared<ICradleFirmwareUpdater>(system);
58 R_SUCCEED();
59}
60
61} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/global_state_controller.h b/src/core/hle/service/am/service/global_state_controller.h
new file mode 100755
index 000000000..67c753513
--- /dev/null
+++ b/src/core/hle/service/am/service/global_state_controller.h
@@ -0,0 +1,31 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/kernel_helpers.h"
8#include "core/hle/service/os/event.h"
9#include "core/hle/service/service.h"
10
11namespace Service::AM {
12
13class ICradleFirmwareUpdater;
14
15class IGlobalStateController final : public ServiceFramework<IGlobalStateController> {
16public:
17 explicit IGlobalStateController(Core::System& system_);
18 ~IGlobalStateController() override;
19
20private:
21 Result LoadAndApplyIdlePolicySettings();
22 Result ShouldSleepOnBoot(Out<bool> out_should_sleep_on_boot);
23 Result GetHdcpAuthenticationFailedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
24 Result OpenCradleFirmwareUpdater(
25 Out<SharedPointer<ICradleFirmwareUpdater>> out_cradle_firmware_updater);
26
27 KernelHelpers::ServiceContext m_context;
28 Event m_hdcp_authentication_failed_event;
29};
30
31} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/home_menu_functions.cpp b/src/core/hle/service/am/service/home_menu_functions.cpp
new file mode 100755
index 000000000..0c4d24b58
--- /dev/null
+++ b/src/core/hle/service/am/service/home_menu_functions.cpp
@@ -0,0 +1,74 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/result.h"
5#include "core/hle/service/am/applet_manager.h"
6#include "core/hle/service/am/service/home_menu_functions.h"
7#include "core/hle/service/cmif_serialization.h"
8
9namespace Service::AM {
10
11IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_, std::shared_ptr<Applet> applet)
12 : ServiceFramework{system_, "IHomeMenuFunctions"}, m_applet{std::move(applet)},
13 m_context{system, "IHomeMenuFunctions"}, m_pop_from_general_channel_event{m_context} {
14 // clang-format off
15 static const FunctionInfo functions[] = {
16 {10, D<&IHomeMenuFunctions::RequestToGetForeground>, "RequestToGetForeground"},
17 {11, D<&IHomeMenuFunctions::LockForeground>, "LockForeground"},
18 {12, D<&IHomeMenuFunctions::UnlockForeground>, "UnlockForeground"},
19 {20, nullptr, "PopFromGeneralChannel"},
20 {21, D<&IHomeMenuFunctions::GetPopFromGeneralChannelEvent>, "GetPopFromGeneralChannelEvent"},
21 {30, nullptr, "GetHomeButtonWriterLockAccessor"},
22 {31, nullptr, "GetWriterLockAccessorEx"},
23 {40, nullptr, "IsSleepEnabled"},
24 {41, D<&IHomeMenuFunctions::IsRebootEnabled>, "IsRebootEnabled"},
25 {50, nullptr, "LaunchSystemApplet"},
26 {51, nullptr, "LaunchStarter"},
27 {100, nullptr, "PopRequestLaunchApplicationForDebug"},
28 {110, D<&IHomeMenuFunctions::IsForceTerminateApplicationDisabledForDebug>, "IsForceTerminateApplicationDisabledForDebug"},
29 {200, nullptr, "LaunchDevMenu"},
30 {1000, nullptr, "SetLastApplicationExitReason"},
31 };
32 // clang-format on
33
34 RegisterHandlers(functions);
35}
36
37IHomeMenuFunctions::~IHomeMenuFunctions() = default;
38
39Result IHomeMenuFunctions::RequestToGetForeground() {
40 LOG_WARNING(Service_AM, "(STUBBED) called");
41 R_SUCCEED();
42}
43
44Result IHomeMenuFunctions::LockForeground() {
45 LOG_WARNING(Service_AM, "(STUBBED) called");
46 R_SUCCEED();
47}
48
49Result IHomeMenuFunctions::UnlockForeground() {
50 LOG_WARNING(Service_AM, "(STUBBED) called");
51 R_SUCCEED();
52}
53
54Result IHomeMenuFunctions::GetPopFromGeneralChannelEvent(
55 OutCopyHandle<Kernel::KReadableEvent> out_event) {
56 LOG_INFO(Service_AM, "called");
57 *out_event = m_pop_from_general_channel_event.GetHandle();
58 R_SUCCEED();
59}
60
61Result IHomeMenuFunctions::IsRebootEnabled(Out<bool> out_is_reboot_enbaled) {
62 LOG_INFO(Service_AM, "called");
63 *out_is_reboot_enbaled = true;
64 R_SUCCEED();
65}
66
67Result IHomeMenuFunctions::IsForceTerminateApplicationDisabledForDebug(
68 Out<bool> out_is_force_terminate_application_disabled_for_debug) {
69 LOG_INFO(Service_AM, "called");
70 *out_is_force_terminate_application_disabled_for_debug = false;
71 R_SUCCEED();
72}
73
74} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/home_menu_functions.h b/src/core/hle/service/am/service/home_menu_functions.h
new file mode 100755
index 000000000..caf6fbaab
--- /dev/null
+++ b/src/core/hle/service/am/service/home_menu_functions.h
@@ -0,0 +1,34 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/kernel_helpers.h"
8#include "core/hle/service/os/event.h"
9#include "core/hle/service/service.h"
10
11namespace Service::AM {
12
13struct Applet;
14
15class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> {
16public:
17 explicit IHomeMenuFunctions(Core::System& system_, std::shared_ptr<Applet> applet);
18 ~IHomeMenuFunctions() override;
19
20private:
21 Result RequestToGetForeground();
22 Result LockForeground();
23 Result UnlockForeground();
24 Result GetPopFromGeneralChannelEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
25 Result IsRebootEnabled(Out<bool> out_is_reboot_enbaled);
26 Result IsForceTerminateApplicationDisabledForDebug(
27 Out<bool> out_is_force_terminate_application_disabled_for_debug);
28
29 const std::shared_ptr<Applet> m_applet;
30 KernelHelpers::ServiceContext m_context;
31 Event m_pop_from_general_channel_event;
32};
33
34} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/library_applet_accessor.cpp b/src/core/hle/service/am/service/library_applet_accessor.cpp
new file mode 100755
index 000000000..0c2426d4b
--- /dev/null
+++ b/src/core/hle/service/am/service/library_applet_accessor.cpp
@@ -0,0 +1,157 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/applet_data_broker.h"
5#include "core/hle/service/am/applet_manager.h"
6#include "core/hle/service/am/frontend/applets.h"
7#include "core/hle/service/am/service/library_applet_accessor.h"
8#include "core/hle/service/am/service/storage.h"
9#include "core/hle/service/cmif_serialization.h"
10
11namespace Service::AM {
12
13ILibraryAppletAccessor::ILibraryAppletAccessor(Core::System& system_,
14 std::shared_ptr<AppletDataBroker> broker,
15 std::shared_ptr<Applet> applet)
16 : ServiceFramework{system_, "ILibraryAppletAccessor"}, m_broker{std::move(broker)},
17 m_applet{std::move(applet)} {
18 // clang-format off
19 static const FunctionInfo functions[] = {
20 {0, D<&ILibraryAppletAccessor::GetAppletStateChangedEvent>, "GetAppletStateChangedEvent"},
21 {1, D<&ILibraryAppletAccessor::IsCompleted>, "IsCompleted"},
22 {10, D<&ILibraryAppletAccessor::Start>, "Start"},
23 {20, D<&ILibraryAppletAccessor::RequestExit>, "RequestExit"},
24 {25, D<&ILibraryAppletAccessor::Terminate>, "Terminate"},
25 {30, D<&ILibraryAppletAccessor::GetResult>, "GetResult"},
26 {50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"},
27 {60, D<&ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero>, "PresetLibraryAppletGpuTimeSliceZero"},
28 {100, D<&ILibraryAppletAccessor::PushInData>, "PushInData"},
29 {101, D<&ILibraryAppletAccessor::PopOutData>, "PopOutData"},
30 {102, nullptr, "PushExtraStorage"},
31 {103, D<&ILibraryAppletAccessor::PushInteractiveInData>, "PushInteractiveInData"},
32 {104, D<&ILibraryAppletAccessor::PopInteractiveOutData>, "PopInteractiveOutData"},
33 {105, D<&ILibraryAppletAccessor::GetPopOutDataEvent>, "GetPopOutDataEvent"},
34 {106, D<&ILibraryAppletAccessor::GetPopInteractiveOutDataEvent>, "GetPopInteractiveOutDataEvent"},
35 {110, nullptr, "NeedsToExitProcess"},
36 {120, nullptr, "GetLibraryAppletInfo"},
37 {150, nullptr, "RequestForAppletToGetForeground"},
38 {160, D<&ILibraryAppletAccessor::GetIndirectLayerConsumerHandle>, "GetIndirectLayerConsumerHandle"},
39 };
40 // clang-format on
41
42 RegisterHandlers(functions);
43}
44
45ILibraryAppletAccessor::~ILibraryAppletAccessor() = default;
46
47Result ILibraryAppletAccessor::GetAppletStateChangedEvent(
48 OutCopyHandle<Kernel::KReadableEvent> out_event) {
49 LOG_DEBUG(Service_AM, "called");
50 *out_event = m_broker->GetStateChangedEvent().GetHandle();
51 R_SUCCEED();
52}
53
54Result ILibraryAppletAccessor::IsCompleted(Out<bool> out_is_completed) {
55 LOG_DEBUG(Service_AM, "called");
56 *out_is_completed = m_broker->IsCompleted();
57 R_SUCCEED();
58}
59
60Result ILibraryAppletAccessor::GetResult(Out<Result> out_result) {
61 LOG_DEBUG(Service_AM, "called");
62 *out_result = m_applet->terminate_result;
63 R_SUCCEED();
64}
65
66Result ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero() {
67 LOG_INFO(Service_AM, "(STUBBED) called");
68 R_SUCCEED();
69}
70
71Result ILibraryAppletAccessor::Start() {
72 LOG_DEBUG(Service_AM, "called");
73 m_applet->process->Run();
74 FrontendExecute();
75 R_SUCCEED();
76}
77
78Result ILibraryAppletAccessor::RequestExit() {
79 LOG_DEBUG(Service_AM, "called");
80 m_applet->message_queue.RequestExit();
81 FrontendRequestExit();
82 R_SUCCEED();
83}
84
85Result ILibraryAppletAccessor::Terminate() {
86 LOG_DEBUG(Service_AM, "called");
87 m_applet->process->Terminate();
88 FrontendRequestExit();
89 R_SUCCEED();
90}
91
92Result ILibraryAppletAccessor::PushInData(SharedPointer<IStorage> storage) {
93 LOG_DEBUG(Service_AM, "called");
94 m_broker->GetInData().Push(storage);
95 R_SUCCEED();
96}
97
98Result ILibraryAppletAccessor::PopOutData(Out<SharedPointer<IStorage>> out_storage) {
99 LOG_DEBUG(Service_AM, "called");
100 R_RETURN(m_broker->GetOutData().Pop(out_storage.Get()));
101}
102
103Result ILibraryAppletAccessor::PushInteractiveInData(SharedPointer<IStorage> storage) {
104 LOG_DEBUG(Service_AM, "called");
105 m_broker->GetInteractiveInData().Push(storage);
106 FrontendExecuteInteractive();
107 R_SUCCEED();
108}
109
110Result ILibraryAppletAccessor::PopInteractiveOutData(Out<SharedPointer<IStorage>> out_storage) {
111 LOG_DEBUG(Service_AM, "called");
112 R_RETURN(m_broker->GetInteractiveOutData().Pop(out_storage.Get()));
113}
114
115Result ILibraryAppletAccessor::GetPopOutDataEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
116 LOG_DEBUG(Service_AM, "called");
117 *out_event = m_broker->GetOutData().GetEvent();
118 R_SUCCEED();
119}
120
121Result ILibraryAppletAccessor::GetPopInteractiveOutDataEvent(
122 OutCopyHandle<Kernel::KReadableEvent> out_event) {
123 LOG_DEBUG(Service_AM, "called");
124 *out_event = m_broker->GetInteractiveOutData().GetEvent();
125 R_SUCCEED();
126}
127
128Result ILibraryAppletAccessor::GetIndirectLayerConsumerHandle(Out<u64> out_handle) {
129 LOG_WARNING(Service_AM, "(STUBBED) called");
130
131 // We require a non-zero handle to be valid. Using 0xdeadbeef allows us to trace if this is
132 // actually used anywhere
133 *out_handle = 0xdeadbeef;
134 R_SUCCEED();
135}
136
137void ILibraryAppletAccessor::FrontendExecute() {
138 if (m_applet->frontend) {
139 m_applet->frontend->Initialize();
140 m_applet->frontend->Execute();
141 }
142}
143
144void ILibraryAppletAccessor::FrontendExecuteInteractive() {
145 if (m_applet->frontend) {
146 m_applet->frontend->ExecuteInteractive();
147 m_applet->frontend->Execute();
148 }
149}
150
151void ILibraryAppletAccessor::FrontendRequestExit() {
152 if (m_applet->frontend) {
153 m_applet->frontend->RequestExit();
154 }
155}
156
157} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/library_applet_accessor.h b/src/core/hle/service/am/service/library_applet_accessor.h
new file mode 100755
index 000000000..97d3b6c8a
--- /dev/null
+++ b/src/core/hle/service/am/service/library_applet_accessor.h
@@ -0,0 +1,45 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/service.h"
8
9namespace Service::AM {
10
11class AppletDataBroker;
12struct Applet;
13class IStorage;
14
15class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
16public:
17 explicit ILibraryAppletAccessor(Core::System& system_, std::shared_ptr<AppletDataBroker> broker,
18 std::shared_ptr<Applet> applet);
19 ~ILibraryAppletAccessor();
20
21private:
22 Result GetAppletStateChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
23 Result IsCompleted(Out<bool> out_is_completed);
24 Result GetResult(Out<Result> out_result);
25 Result PresetLibraryAppletGpuTimeSliceZero();
26 Result Start();
27 Result RequestExit();
28 Result Terminate();
29 Result PushInData(SharedPointer<IStorage> storage);
30 Result PopOutData(Out<SharedPointer<IStorage>> out_storage);
31 Result PushInteractiveInData(SharedPointer<IStorage> storage);
32 Result PopInteractiveOutData(Out<SharedPointer<IStorage>> out_storage);
33 Result GetPopOutDataEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
34 Result GetPopInteractiveOutDataEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
35 Result GetIndirectLayerConsumerHandle(Out<u64> out_handle);
36
37 void FrontendExecute();
38 void FrontendExecuteInteractive();
39 void FrontendRequestExit();
40
41 const std::shared_ptr<AppletDataBroker> m_broker;
42 const std::shared_ptr<Applet> m_applet;
43};
44
45} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/library_applet_creator.cpp b/src/core/hle/service/am/service/library_applet_creator.cpp
new file mode 100755
index 000000000..166637d60
--- /dev/null
+++ b/src/core/hle/service/am/service/library_applet_creator.cpp
@@ -0,0 +1,268 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "common/settings.h"
5#include "core/hle/kernel/k_transfer_memory.h"
6#include "core/hle/service/am/applet_data_broker.h"
7#include "core/hle/service/am/applet_manager.h"
8#include "core/hle/service/am/frontend/applets.h"
9#include "core/hle/service/am/library_applet_storage.h"
10#include "core/hle/service/am/service/library_applet_accessor.h"
11#include "core/hle/service/am/service/library_applet_creator.h"
12#include "core/hle/service/am/service/storage.h"
13#include "core/hle/service/cmif_serialization.h"
14#include "core/hle/service/sm/sm.h"
15
16namespace Service::AM {
17
18namespace {
19
20bool ShouldCreateGuestApplet(AppletId applet_id) {
21#define X(Name, name) \
22 if (applet_id == AppletId::Name && \
23 Settings::values.name##_applet_mode.GetValue() != Settings::AppletMode::LLE) { \
24 return false; \
25 }
26
27 X(Cabinet, cabinet)
28 X(Controller, controller)
29 X(DataErase, data_erase)
30 X(Error, error)
31 X(NetConnect, net_connect)
32 X(ProfileSelect, player_select)
33 X(SoftwareKeyboard, swkbd)
34 X(MiiEdit, mii_edit)
35 X(Web, web)
36 X(Shop, shop)
37 X(PhotoViewer, photo_viewer)
38 X(OfflineWeb, offline_web)
39 X(LoginShare, login_share)
40 X(WebAuth, wifi_web_auth)
41 X(MyPage, my_page)
42
43#undef X
44
45 return true;
46}
47
48AppletProgramId AppletIdToProgramId(AppletId applet_id) {
49 switch (applet_id) {
50 case AppletId::OverlayDisplay:
51 return AppletProgramId::OverlayDisplay;
52 case AppletId::QLaunch:
53 return AppletProgramId::QLaunch;
54 case AppletId::Starter:
55 return AppletProgramId::Starter;
56 case AppletId::Auth:
57 return AppletProgramId::Auth;
58 case AppletId::Cabinet:
59 return AppletProgramId::Cabinet;
60 case AppletId::Controller:
61 return AppletProgramId::Controller;
62 case AppletId::DataErase:
63 return AppletProgramId::DataErase;
64 case AppletId::Error:
65 return AppletProgramId::Error;
66 case AppletId::NetConnect:
67 return AppletProgramId::NetConnect;
68 case AppletId::ProfileSelect:
69 return AppletProgramId::ProfileSelect;
70 case AppletId::SoftwareKeyboard:
71 return AppletProgramId::SoftwareKeyboard;
72 case AppletId::MiiEdit:
73 return AppletProgramId::MiiEdit;
74 case AppletId::Web:
75 return AppletProgramId::Web;
76 case AppletId::Shop:
77 return AppletProgramId::Shop;
78 case AppletId::PhotoViewer:
79 return AppletProgramId::PhotoViewer;
80 case AppletId::Settings:
81 return AppletProgramId::Settings;
82 case AppletId::OfflineWeb:
83 return AppletProgramId::OfflineWeb;
84 case AppletId::LoginShare:
85 return AppletProgramId::LoginShare;
86 case AppletId::WebAuth:
87 return AppletProgramId::WebAuth;
88 case AppletId::MyPage:
89 return AppletProgramId::MyPage;
90 default:
91 return static_cast<AppletProgramId>(0);
92 }
93}
94
95std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system,
96 std::shared_ptr<Applet> caller_applet,
97 AppletId applet_id,
98 LibraryAppletMode mode) {
99 const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id));
100 if (program_id == 0) {
101 // Unknown applet
102 return {};
103 }
104
105 // TODO: enable other versions of applets
106 enum : u8 {
107 Firmware1400 = 14,
108 Firmware1500 = 15,
109 Firmware1600 = 16,
110 Firmware1700 = 17,
111 };
112
113 auto process = std::make_unique<Process>(system);
114 if (!process->Initialize(program_id, Firmware1400, Firmware1700)) {
115 // Couldn't initialize the guest process
116 return {};
117 }
118
119 const auto applet = std::make_shared<Applet>(system, std::move(process));
120 applet->program_id = program_id;
121 applet->applet_id = applet_id;
122 applet->type = AppletType::LibraryApplet;
123 applet->library_applet_mode = mode;
124
125 // Set focus state
126 switch (mode) {
127 case LibraryAppletMode::AllForeground:
128 case LibraryAppletMode::NoUi:
129 case LibraryAppletMode::PartialForeground:
130 case LibraryAppletMode::PartialForegroundIndirectDisplay:
131 applet->hid_registration.EnableAppletToGetInput(true);
132 applet->focus_state = FocusState::InFocus;
133 applet->message_queue.PushMessage(AppletMessage::ChangeIntoForeground);
134 break;
135 case LibraryAppletMode::AllForegroundInitiallyHidden:
136 applet->hid_registration.EnableAppletToGetInput(false);
137 applet->focus_state = FocusState::NotInFocus;
138 applet->system_buffer_manager.SetWindowVisibility(false);
139 applet->message_queue.PushMessage(AppletMessage::ChangeIntoBackground);
140 break;
141 }
142
143 auto broker = std::make_shared<AppletDataBroker>(system);
144 applet->caller_applet = caller_applet;
145 applet->caller_applet_broker = broker;
146
147 system.GetAppletManager().InsertApplet(applet);
148
149 return std::make_shared<ILibraryAppletAccessor>(system, broker, applet);
150}
151
152std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& system,
153 std::shared_ptr<Applet> caller_applet,
154 AppletId applet_id,
155 LibraryAppletMode mode) {
156 const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id));
157
158 auto process = std::make_unique<Process>(system);
159 auto applet = std::make_shared<Applet>(system, std::move(process));
160 applet->program_id = program_id;
161 applet->applet_id = applet_id;
162 applet->type = AppletType::LibraryApplet;
163 applet->library_applet_mode = mode;
164
165 auto storage = std::make_shared<AppletDataBroker>(system);
166 applet->caller_applet = caller_applet;
167 applet->caller_applet_broker = storage;
168 applet->frontend = system.GetFrontendAppletHolder().GetApplet(applet, applet_id, mode);
169
170 return std::make_shared<ILibraryAppletAccessor>(system, storage, applet);
171}
172
173} // namespace
174
175ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet)
176 : ServiceFramework{system_, "ILibraryAppletCreator"}, m_applet{std::move(applet)} {
177 static const FunctionInfo functions[] = {
178 {0, D<&ILibraryAppletCreator::CreateLibraryApplet>, "CreateLibraryApplet"},
179 {1, nullptr, "TerminateAllLibraryApplets"},
180 {2, nullptr, "AreAnyLibraryAppletsLeft"},
181 {10, D<&ILibraryAppletCreator::CreateStorage>, "CreateStorage"},
182 {11, D<&ILibraryAppletCreator::CreateTransferMemoryStorage>, "CreateTransferMemoryStorage"},
183 {12, D<&ILibraryAppletCreator::CreateHandleStorage>, "CreateHandleStorage"},
184 };
185 RegisterHandlers(functions);
186}
187
188ILibraryAppletCreator::~ILibraryAppletCreator() = default;
189
190Result ILibraryAppletCreator::CreateLibraryApplet(
191 Out<SharedPointer<ILibraryAppletAccessor>> out_library_applet_accessor, AppletId applet_id,
192 LibraryAppletMode library_applet_mode) {
193 LOG_DEBUG(Service_AM, "called with applet_id={} applet_mode={}", applet_id,
194 library_applet_mode);
195
196 std::shared_ptr<ILibraryAppletAccessor> library_applet;
197 if (ShouldCreateGuestApplet(applet_id)) {
198 library_applet = CreateGuestApplet(system, m_applet, applet_id, library_applet_mode);
199 }
200 if (!library_applet) {
201 library_applet = CreateFrontendApplet(system, m_applet, applet_id, library_applet_mode);
202 }
203 if (!library_applet) {
204 LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
205 R_THROW(ResultUnknown);
206 }
207
208 // Applet is created, can now be launched.
209 m_applet->library_applet_launchable_event.Signal();
210 *out_library_applet_accessor = library_applet;
211 R_SUCCEED();
212}
213
214Result ILibraryAppletCreator::CreateStorage(Out<SharedPointer<IStorage>> out_storage, s64 size) {
215 LOG_DEBUG(Service_AM, "called, size={}", size);
216
217 if (size <= 0) {
218 LOG_ERROR(Service_AM, "size is less than or equal to 0");
219 R_THROW(ResultUnknown);
220 }
221
222 *out_storage = std::make_shared<IStorage>(system, AM::CreateStorage(std::vector<u8>(size)));
223 R_SUCCEED();
224}
225
226Result ILibraryAppletCreator::CreateTransferMemoryStorage(
227 Out<SharedPointer<IStorage>> out_storage, bool is_writable, s64 size,
228 InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle) {
229 LOG_DEBUG(Service_AM, "called, is_writable={} size={}", is_writable, size);
230
231 if (size <= 0) {
232 LOG_ERROR(Service_AM, "size is less than or equal to 0");
233 R_THROW(ResultUnknown);
234 }
235
236 if (!transfer_memory_handle) {
237 LOG_ERROR(Service_AM, "transfer_memory_handle is null");
238 R_THROW(ResultUnknown);
239 }
240
241 *out_storage = std::make_shared<IStorage>(
242 system, AM::CreateTransferMemoryStorage(transfer_memory_handle->GetOwner()->GetMemory(),
243 transfer_memory_handle.Get(), is_writable, size));
244 R_SUCCEED();
245}
246
247Result ILibraryAppletCreator::CreateHandleStorage(
248 Out<SharedPointer<IStorage>> out_storage, s64 size,
249 InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle) {
250 LOG_DEBUG(Service_AM, "called, size={}", size);
251
252 if (size <= 0) {
253 LOG_ERROR(Service_AM, "size is less than or equal to 0");
254 R_THROW(ResultUnknown);
255 }
256
257 if (!transfer_memory_handle) {
258 LOG_ERROR(Service_AM, "transfer_memory_handle is null");
259 R_THROW(ResultUnknown);
260 }
261
262 *out_storage = std::make_shared<IStorage>(
263 system, AM::CreateHandleStorage(transfer_memory_handle->GetOwner()->GetMemory(),
264 transfer_memory_handle.Get(), size));
265 R_SUCCEED();
266}
267
268} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/library_applet_creator.h b/src/core/hle/service/am/service/library_applet_creator.h
new file mode 100755
index 000000000..fe6d40eb3
--- /dev/null
+++ b/src/core/hle/service/am/service/library_applet_creator.h
@@ -0,0 +1,35 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/am/am_types.h"
7#include "core/hle/service/cmif_types.h"
8#include "core/hle/service/service.h"
9
10namespace Service::AM {
11
12struct Applet;
13class ILibraryAppletAccessor;
14class IStorage;
15
16class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
17public:
18 explicit ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet);
19 ~ILibraryAppletCreator() override;
20
21private:
22 Result CreateLibraryApplet(
23 Out<SharedPointer<ILibraryAppletAccessor>> out_library_applet_accessor, AppletId applet_id,
24 LibraryAppletMode library_applet_mode);
25 Result CreateStorage(Out<SharedPointer<IStorage>> out_storage, s64 size);
26 Result CreateTransferMemoryStorage(
27 Out<SharedPointer<IStorage>> out_storage, bool is_writable, s64 size,
28 InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle);
29 Result CreateHandleStorage(Out<SharedPointer<IStorage>> out_storage, s64 size,
30 InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle);
31
32 const std::shared_ptr<Applet> m_applet;
33};
34
35} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/library_applet_proxy.cpp b/src/core/hle/service/am/service/library_applet_proxy.cpp
new file mode 100755
index 000000000..bcb44a71c
--- /dev/null
+++ b/src/core/hle/service/am/service/library_applet_proxy.cpp
@@ -0,0 +1,134 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/service/applet_common_functions.h"
5#include "core/hle/service/am/service/audio_controller.h"
6#include "core/hle/service/am/service/common_state_getter.h"
7#include "core/hle/service/am/service/debug_functions.h"
8#include "core/hle/service/am/service/display_controller.h"
9#include "core/hle/service/am/service/global_state_controller.h"
10#include "core/hle/service/am/service/home_menu_functions.h"
11#include "core/hle/service/am/service/library_applet_creator.h"
12#include "core/hle/service/am/service/library_applet_proxy.h"
13#include "core/hle/service/am/service/library_applet_self_accessor.h"
14#include "core/hle/service/am/service/process_winding_controller.h"
15#include "core/hle/service/am/service/self_controller.h"
16#include "core/hle/service/am/service/window_controller.h"
17#include "core/hle/service/cmif_serialization.h"
18
19namespace Service::AM {
20
21ILibraryAppletProxy::ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
22 Kernel::KProcess* process,
23 Nvnflinger::Nvnflinger& nvnflinger)
24 : ServiceFramework{system_, "ILibraryAppletProxy"},
25 m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} {
26 // clang-format off
27 static const FunctionInfo functions[] = {
28 {0, D<&ILibraryAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
29 {1, D<&ILibraryAppletProxy::GetSelfController>, "GetSelfController"},
30 {2, D<&ILibraryAppletProxy::GetWindowController>, "GetWindowController"},
31 {3, D<&ILibraryAppletProxy::GetAudioController>, "GetAudioController"},
32 {4, D<&ILibraryAppletProxy::GetDisplayController>, "GetDisplayController"},
33 {10, D<&ILibraryAppletProxy::GetProcessWindingController>, "GetProcessWindingController"},
34 {11, D<&ILibraryAppletProxy::GetLibraryAppletCreator>, "GetLibraryAppletCreator"},
35 {20, D<&ILibraryAppletProxy::OpenLibraryAppletSelfAccessor>, "OpenLibraryAppletSelfAccessor"},
36 {21, D<&ILibraryAppletProxy::GetAppletCommonFunctions>, "GetAppletCommonFunctions"},
37 {22, D<&ILibraryAppletProxy::GetHomeMenuFunctions>, "GetHomeMenuFunctions"},
38 {23, D<&ILibraryAppletProxy::GetGlobalStateController>, "GetGlobalStateController"},
39 {1000, D<&ILibraryAppletProxy::GetDebugFunctions>, "GetDebugFunctions"},
40 };
41 // clang-format on
42
43 RegisterHandlers(functions);
44}
45
46ILibraryAppletProxy::~ILibraryAppletProxy() = default;
47
48Result ILibraryAppletProxy::GetAudioController(
49 Out<SharedPointer<IAudioController>> out_audio_controller) {
50 LOG_DEBUG(Service_AM, "called");
51 *out_audio_controller = std::make_shared<IAudioController>(system);
52 R_SUCCEED();
53}
54
55Result ILibraryAppletProxy::GetDisplayController(
56 Out<SharedPointer<IDisplayController>> out_display_controller) {
57 LOG_DEBUG(Service_AM, "called");
58 *out_display_controller = std::make_shared<IDisplayController>(system, m_applet);
59 R_SUCCEED();
60}
61
62Result ILibraryAppletProxy::GetProcessWindingController(
63 Out<SharedPointer<IProcessWindingController>> out_process_winding_controller) {
64 LOG_DEBUG(Service_AM, "called");
65 *out_process_winding_controller = std::make_shared<IProcessWindingController>(system, m_applet);
66 R_SUCCEED();
67}
68
69Result ILibraryAppletProxy::GetDebugFunctions(
70 Out<SharedPointer<IDebugFunctions>> out_debug_functions) {
71 LOG_DEBUG(Service_AM, "called");
72 *out_debug_functions = std::make_shared<IDebugFunctions>(system);
73 R_SUCCEED();
74}
75
76Result ILibraryAppletProxy::GetWindowController(
77 Out<SharedPointer<IWindowController>> out_window_controller) {
78 LOG_DEBUG(Service_AM, "called");
79 *out_window_controller = std::make_shared<IWindowController>(system, m_applet);
80 R_SUCCEED();
81}
82
83Result ILibraryAppletProxy::GetSelfController(
84 Out<SharedPointer<ISelfController>> out_self_controller) {
85 LOG_DEBUG(Service_AM, "called");
86 *out_self_controller =
87 std::make_shared<ISelfController>(system, m_applet, m_process, m_nvnflinger);
88 R_SUCCEED();
89}
90
91Result ILibraryAppletProxy::GetCommonStateGetter(
92 Out<SharedPointer<ICommonStateGetter>> out_common_state_getter) {
93 LOG_DEBUG(Service_AM, "called");
94 *out_common_state_getter = std::make_shared<ICommonStateGetter>(system, m_applet);
95 R_SUCCEED();
96}
97
98Result ILibraryAppletProxy::GetLibraryAppletCreator(
99 Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) {
100 LOG_DEBUG(Service_AM, "called");
101 *out_library_applet_creator = std::make_shared<ILibraryAppletCreator>(system, m_applet);
102 R_SUCCEED();
103}
104
105Result ILibraryAppletProxy::OpenLibraryAppletSelfAccessor(
106 Out<SharedPointer<ILibraryAppletSelfAccessor>> out_library_applet_self_accessor) {
107 LOG_DEBUG(Service_AM, "called");
108 *out_library_applet_self_accessor =
109 std::make_shared<ILibraryAppletSelfAccessor>(system, m_applet);
110 R_SUCCEED();
111}
112
113Result ILibraryAppletProxy::GetAppletCommonFunctions(
114 Out<SharedPointer<IAppletCommonFunctions>> out_applet_common_functions) {
115 LOG_DEBUG(Service_AM, "called");
116 *out_applet_common_functions = std::make_shared<IAppletCommonFunctions>(system, m_applet);
117 R_SUCCEED();
118}
119
120Result ILibraryAppletProxy::GetHomeMenuFunctions(
121 Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions) {
122 LOG_DEBUG(Service_AM, "called");
123 *out_home_menu_functions = std::make_shared<IHomeMenuFunctions>(system, m_applet);
124 R_SUCCEED();
125}
126
127Result ILibraryAppletProxy::GetGlobalStateController(
128 Out<SharedPointer<IGlobalStateController>> out_global_state_controller) {
129 LOG_DEBUG(Service_AM, "called");
130 *out_global_state_controller = std::make_shared<IGlobalStateController>(system);
131 R_SUCCEED();
132}
133
134} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/library_applet_proxy.h b/src/core/hle/service/am/service/library_applet_proxy.h
new file mode 100755
index 000000000..23e64e295
--- /dev/null
+++ b/src/core/hle/service/am/service/library_applet_proxy.h
@@ -0,0 +1,55 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/service.h"
8
9namespace Service::AM {
10
11struct Applet;
12class IAppletCommonFunctions;
13class IAudioController;
14class ICommonStateGetter;
15class IDebugFunctions;
16class IDisplayController;
17class IHomeMenuFunctions;
18class IGlobalStateController;
19class ILibraryAppletCreator;
20class ILibraryAppletSelfAccessor;
21class IProcessWindingController;
22class ISelfController;
23class IWindowController;
24
25class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
26public:
27 explicit ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
28 Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger);
29 ~ILibraryAppletProxy();
30
31private:
32 Result GetAudioController(Out<SharedPointer<IAudioController>> out_audio_controller);
33 Result GetDisplayController(Out<SharedPointer<IDisplayController>> out_display_controller);
34 Result GetProcessWindingController(
35 Out<SharedPointer<IProcessWindingController>> out_process_winding_controller);
36 Result GetDebugFunctions(Out<SharedPointer<IDebugFunctions>> out_debug_functions);
37 Result GetWindowController(Out<SharedPointer<IWindowController>> out_window_controller);
38 Result GetSelfController(Out<SharedPointer<ISelfController>> out_self_controller);
39 Result GetCommonStateGetter(Out<SharedPointer<ICommonStateGetter>> out_common_state_getter);
40 Result GetLibraryAppletCreator(
41 Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator);
42 Result OpenLibraryAppletSelfAccessor(
43 Out<SharedPointer<ILibraryAppletSelfAccessor>> out_library_applet_self_accessor);
44 Result GetAppletCommonFunctions(
45 Out<SharedPointer<IAppletCommonFunctions>> out_applet_common_functions);
46 Result GetHomeMenuFunctions(Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions);
47 Result GetGlobalStateController(
48 Out<SharedPointer<IGlobalStateController>> out_global_state_controller);
49
50 Nvnflinger::Nvnflinger& m_nvnflinger;
51 Kernel::KProcess* const m_process;
52 const std::shared_ptr<Applet> m_applet;
53};
54
55} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/library_applet_self_accessor.cpp b/src/core/hle/service/am/service/library_applet_self_accessor.cpp
new file mode 100755
index 000000000..7a3a86e88
--- /dev/null
+++ b/src/core/hle/service/am/service/library_applet_self_accessor.cpp
@@ -0,0 +1,322 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/core_timing.h"
5#include "core/file_sys/control_metadata.h"
6#include "core/file_sys/patch_manager.h"
7#include "core/file_sys/registered_cache.h"
8#include "core/hle/service/acc/profile_manager.h"
9#include "core/hle/service/am/applet_data_broker.h"
10#include "core/hle/service/am/applet_manager.h"
11#include "core/hle/service/am/frontend/applets.h"
12#include "core/hle/service/am/service/library_applet_self_accessor.h"
13#include "core/hle/service/am/service/storage.h"
14#include "core/hle/service/cmif_serialization.h"
15#include "core/hle/service/filesystem/filesystem.h"
16#include "core/hle/service/glue/glue_manager.h"
17#include "core/hle/service/ns/ns.h"
18#include "core/hle/service/sm/sm.h"
19
20namespace Service::AM {
21
22namespace {
23
24AppletIdentityInfo GetCallerIdentity(Applet& applet) {
25 if (const auto caller_applet = applet.caller_applet.lock(); caller_applet) {
26 // TODO: is this actually the application ID?
27 return {
28 .applet_id = caller_applet->applet_id,
29 .application_id = caller_applet->program_id,
30 };
31 } else {
32 return {
33 .applet_id = AppletId::QLaunch,
34 .application_id = 0x0100000000001000ull,
35 };
36 }
37}
38
39} // namespace
40
41ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_,
42 std::shared_ptr<Applet> applet)
43 : ServiceFramework{system_, "ILibraryAppletSelfAccessor"}, m_applet{std::move(applet)},
44 m_broker{m_applet->caller_applet_broker} {
45 // clang-format off
46 static const FunctionInfo functions[] = {
47 {0, D<&ILibraryAppletSelfAccessor::PopInData>, "PopInData"},
48 {1, D<&ILibraryAppletSelfAccessor::PushOutData>, "PushOutData"},
49 {2, D<&ILibraryAppletSelfAccessor::PopInteractiveInData>, "PopInteractiveInData"},
50 {3, D<&ILibraryAppletSelfAccessor::PushInteractiveOutData>, "PushInteractiveOutData"},
51 {5, D<&ILibraryAppletSelfAccessor::GetPopInDataEvent>, "GetPopInDataEvent"},
52 {6, D<&ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent>, "GetPopInteractiveInDataEvent"},
53 {10, D<&ILibraryAppletSelfAccessor::ExitProcessAndReturn>, "ExitProcessAndReturn"},
54 {11, D<&ILibraryAppletSelfAccessor::GetLibraryAppletInfo>, "GetLibraryAppletInfo"},
55 {12, D<&ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo>, "GetMainAppletIdentityInfo"},
56 {13, D<&ILibraryAppletSelfAccessor::CanUseApplicationCore>, "CanUseApplicationCore"},
57 {14, D<&ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo>, "GetCallerAppletIdentityInfo"},
58 {15, D<&ILibraryAppletSelfAccessor::GetMainAppletApplicationControlProperty>, "GetMainAppletApplicationControlProperty"},
59 {16, D<&ILibraryAppletSelfAccessor::GetMainAppletStorageId>, "GetMainAppletStorageId"},
60 {17, D<&ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfoStack>, "GetCallerAppletIdentityInfoStack"},
61 {18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"},
62 {19, D<&ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout>, "GetDesirableKeyboardLayout"},
63 {20, nullptr, "PopExtraStorage"},
64 {25, nullptr, "GetPopExtraStorageEvent"},
65 {30, nullptr, "UnpopInData"},
66 {31, nullptr, "UnpopExtraStorage"},
67 {40, nullptr, "GetIndirectLayerProducerHandle"},
68 {50, D<&ILibraryAppletSelfAccessor::ReportVisibleError>, "ReportVisibleError"},
69 {51, D<&ILibraryAppletSelfAccessor::ReportVisibleErrorWithErrorContext>, "ReportVisibleErrorWithErrorContext"},
70 {60, D<&ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage>, "GetMainAppletApplicationDesiredLanguage"},
71 {70, D<&ILibraryAppletSelfAccessor::GetCurrentApplicationId>, "GetCurrentApplicationId"},
72 {80, nullptr, "RequestExitToSelf"},
73 {90, nullptr, "CreateApplicationAndPushAndRequestToLaunch"},
74 {100, nullptr, "CreateGameMovieTrimmer"},
75 {101, nullptr, "ReserveResourceForMovieOperation"},
76 {102, nullptr, "UnreserveResourceForMovieOperation"},
77 {110, D<&ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers>, "GetMainAppletAvailableUsers"},
78 {120, nullptr, "GetLaunchStorageInfoForDebug"},
79 {130, nullptr, "GetGpuErrorDetectedSystemEvent"},
80 {140, nullptr, "SetApplicationMemoryReservation"},
81 {150, D<&ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually>, "ShouldSetGpuTimeSliceManually"},
82 {160, D<&ILibraryAppletSelfAccessor::Cmd160>, "Cmd160"},
83 };
84 // clang-format on
85 RegisterHandlers(functions);
86}
87
88ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default;
89
90Result ILibraryAppletSelfAccessor::PopInData(Out<SharedPointer<IStorage>> out_storage) {
91 LOG_INFO(Service_AM, "called");
92 R_RETURN(m_broker->GetInData().Pop(out_storage));
93}
94
95Result ILibraryAppletSelfAccessor::PushOutData(SharedPointer<IStorage> storage) {
96 LOG_INFO(Service_AM, "called");
97 m_broker->GetOutData().Push(storage);
98 R_SUCCEED();
99}
100
101Result ILibraryAppletSelfAccessor::PopInteractiveInData(Out<SharedPointer<IStorage>> out_storage) {
102 LOG_INFO(Service_AM, "called");
103 R_RETURN(m_broker->GetInteractiveInData().Pop(out_storage));
104}
105
106Result ILibraryAppletSelfAccessor::PushInteractiveOutData(SharedPointer<IStorage> storage) {
107 LOG_INFO(Service_AM, "called");
108 m_broker->GetInteractiveOutData().Push(storage);
109 R_SUCCEED();
110}
111
112Result ILibraryAppletSelfAccessor::GetPopInDataEvent(
113 OutCopyHandle<Kernel::KReadableEvent> out_event) {
114 LOG_INFO(Service_AM, "called");
115 *out_event = m_broker->GetInData().GetEvent();
116 R_SUCCEED();
117}
118
119Result ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent(
120 OutCopyHandle<Kernel::KReadableEvent> out_event) {
121 LOG_INFO(Service_AM, "called");
122 *out_event = m_broker->GetInteractiveInData().GetEvent();
123 R_SUCCEED();
124}
125
126Result ILibraryAppletSelfAccessor::GetLibraryAppletInfo(
127 Out<LibraryAppletInfo> out_library_applet_info) {
128 LOG_INFO(Service_AM, "called");
129 *out_library_applet_info = {
130 .applet_id = m_applet->applet_id,
131 .library_applet_mode = m_applet->library_applet_mode,
132 };
133 R_SUCCEED();
134}
135
136Result ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(
137 Out<AppletIdentityInfo> out_identity_info) {
138 LOG_WARNING(Service_AM, "(STUBBED) called");
139 *out_identity_info = {
140 .applet_id = AppletId::QLaunch,
141 .application_id = 0x0100000000001000ull,
142 };
143 R_SUCCEED();
144}
145
146Result ILibraryAppletSelfAccessor::CanUseApplicationCore(Out<bool> out_can_use_application_core) {
147 // TODO: This appears to read the NPDM from state and check the core mask of the applet.
148 LOG_WARNING(Service_AM, "(STUBBED) called");
149 *out_can_use_application_core = false;
150 R_SUCCEED();
151}
152
153Result ILibraryAppletSelfAccessor::GetMainAppletApplicationControlProperty(
154 OutLargeData<std::array<u8, 0x4000>, BufferAttr_HipcMapAlias> out_nacp) {
155 LOG_WARNING(Service_AM, "(STUBBED) called");
156
157 // TODO: this should be the main applet, not the caller applet
158 const auto application = GetCallerIdentity(*m_applet);
159 std::vector<u8> nacp;
160 const auto result =
161 system.GetARPManager().GetControlProperty(&nacp, application.application_id);
162
163 if (R_SUCCEEDED(result)) {
164 std::memcpy(out_nacp->data(), nacp.data(), std::min(nacp.size(), out_nacp->size()));
165 }
166
167 R_RETURN(result);
168}
169
170Result ILibraryAppletSelfAccessor::GetMainAppletStorageId(Out<FileSys::StorageId> out_storage_id) {
171 LOG_INFO(Service_AM, "(STUBBED) called");
172 *out_storage_id = FileSys::StorageId::NandUser;
173 R_SUCCEED();
174}
175
176Result ILibraryAppletSelfAccessor::ExitProcessAndReturn() {
177 LOG_INFO(Service_AM, "called");
178 system.GetAppletManager().TerminateAndRemoveApplet(m_applet->aruid);
179 m_broker->SignalCompletion();
180 R_SUCCEED();
181}
182
183Result ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(
184 Out<AppletIdentityInfo> out_identity_info) {
185 LOG_INFO(Service_AM, "called");
186 *out_identity_info = GetCallerIdentity(*m_applet);
187 R_SUCCEED();
188}
189
190Result ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfoStack(
191 Out<s32> out_count, OutArray<AppletIdentityInfo, BufferAttr_HipcMapAlias> out_identity_info) {
192 LOG_INFO(Service_AM, "called");
193
194 std::shared_ptr<Applet> applet = m_applet;
195 *out_count = 0;
196
197 do {
198 if (*out_count >= static_cast<s32>(out_identity_info.size())) {
199 break;
200 }
201 out_identity_info[(*out_count)++] = GetCallerIdentity(*applet);
202 } while ((applet = applet->caller_applet.lock()));
203
204 R_SUCCEED();
205}
206
207Result ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(Out<u32> out_desirable_layout) {
208 LOG_WARNING(Service_AM, "(STUBBED) called");
209 *out_desirable_layout = 0;
210 R_SUCCEED();
211}
212
213Result ILibraryAppletSelfAccessor::ReportVisibleError(ErrorCode error_code) {
214 LOG_WARNING(Service_AM, "(STUBBED) called, error {}-{}", error_code.category,
215 error_code.number);
216 R_SUCCEED();
217}
218
219Result ILibraryAppletSelfAccessor::ReportVisibleErrorWithErrorContext(
220 ErrorCode error_code, InLargeData<ErrorContext, BufferAttr_HipcMapAlias> error_context) {
221 LOG_WARNING(Service_AM, "(STUBBED) called, error {}-{}", error_code.category,
222 error_code.number);
223 R_SUCCEED();
224}
225
226Result ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage(
227 Out<u64> out_desired_language) {
228 // FIXME: this is copied from IApplicationFunctions::GetDesiredLanguage
229 // FIXME: all of this stuff belongs to ns
230 auto identity = GetCallerIdentity(*m_applet);
231
232 // TODO(bunnei): This should be configurable
233 LOG_DEBUG(Service_AM, "called");
234
235 // Get supported languages from NACP, if possible
236 // Default to 0 (all languages supported)
237 u32 supported_languages = 0;
238
239 const auto res = [this, identity] {
240 const FileSys::PatchManager pm{identity.application_id, system.GetFileSystemController(),
241 system.GetContentProvider()};
242 auto metadata = pm.GetControlMetadata();
243 if (metadata.first != nullptr) {
244 return metadata;
245 }
246
247 const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(identity.application_id),
248 system.GetFileSystemController(),
249 system.GetContentProvider()};
250 return pm_update.GetControlMetadata();
251 }();
252
253 if (res.first != nullptr) {
254 supported_languages = res.first->GetSupportedLanguages();
255 }
256
257 // Call IApplicationManagerInterface implementation.
258 auto& service_manager = system.ServiceManager();
259 auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2");
260 auto app_man = ns_am2->GetApplicationManagerInterface();
261
262 // Get desired application language
263 u8 desired_language{};
264 R_TRY(app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages));
265
266 // Convert to settings language code.
267 u64 language_code{};
268 R_TRY(app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language));
269
270 LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code);
271
272 *out_desired_language = language_code;
273 R_SUCCEED();
274}
275
276Result ILibraryAppletSelfAccessor::GetCurrentApplicationId(Out<u64> out_application_id) {
277 LOG_WARNING(Service_AM, "(STUBBED) called");
278
279 // TODO: this should be the main applet, not the caller applet
280 const auto main_applet = GetCallerIdentity(*m_applet);
281 *out_application_id = main_applet.application_id;
282
283 R_SUCCEED();
284}
285
286Result ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(
287 Out<bool> out_no_users_available, Out<s32> out_users_count,
288 OutArray<Common::UUID, BufferAttr_HipcMapAlias> out_users) {
289 const Service::Account::ProfileManager manager{};
290
291 *out_no_users_available = true;
292 *out_users_count = -1;
293
294 LOG_INFO(Service_AM, "called");
295
296 if (manager.GetUserCount() > 0) {
297 *out_no_users_available = false;
298 *out_users_count = static_cast<s32>(manager.GetUserCount());
299
300 const auto users = manager.GetAllUsers();
301 for (size_t i = 0; i < users.size() && i < out_users.size(); i++) {
302 out_users[i] = users[i];
303 }
304 }
305
306 R_SUCCEED();
307}
308
309Result ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually(
310 Out<bool> out_should_set_gpu_time_slice_manually) {
311 LOG_INFO(Service_AM, "(STUBBED) called");
312 *out_should_set_gpu_time_slice_manually = false;
313 R_SUCCEED();
314}
315
316Result ILibraryAppletSelfAccessor::Cmd160(Out<u64> out_unknown0) {
317 LOG_WARNING(Service_AM, "(STUBBED) called");
318 *out_unknown0 = 0;
319 R_SUCCEED();
320}
321
322} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/library_applet_self_accessor.h b/src/core/hle/service/am/service/library_applet_self_accessor.h
new file mode 100755
index 000000000..a9743569f
--- /dev/null
+++ b/src/core/hle/service/am/service/library_applet_self_accessor.h
@@ -0,0 +1,83 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "common/uuid.h"
7#include "core/hle/service/am/am_types.h"
8#include "core/hle/service/cmif_types.h"
9#include "core/hle/service/service.h"
10
11namespace FileSys {
12enum class StorageId : u8;
13}
14
15namespace Kernel {
16class KReadableEvent;
17}
18
19namespace Service::AM {
20
21class AppletDataBroker;
22struct Applet;
23class IStorage;
24
25struct LibraryAppletInfo {
26 AppletId applet_id;
27 LibraryAppletMode library_applet_mode;
28};
29static_assert(sizeof(LibraryAppletInfo) == 0x8, "LibraryAppletInfo has incorrect size.");
30
31struct ErrorCode {
32 u32 category;
33 u32 number;
34};
35static_assert(sizeof(ErrorCode) == 0x8, "ErrorCode has incorrect size.");
36
37struct ErrorContext {
38 u8 type;
39 INSERT_PADDING_BYTES_NOINIT(0x7);
40 std::array<u8, 0x1f4> data;
41 Result result;
42};
43static_assert(sizeof(ErrorContext) == 0x200, "ErrorContext has incorrect size.");
44
45class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> {
46public:
47 explicit ILibraryAppletSelfAccessor(Core::System& system_, std::shared_ptr<Applet> applet);
48 ~ILibraryAppletSelfAccessor() override;
49
50private:
51 Result PopInData(Out<SharedPointer<IStorage>> out_storage);
52 Result PushOutData(SharedPointer<IStorage> storage);
53 Result PopInteractiveInData(Out<SharedPointer<IStorage>> out_storage);
54 Result PushInteractiveOutData(SharedPointer<IStorage> storage);
55 Result GetPopInDataEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
56 Result GetPopInteractiveInDataEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
57 Result GetLibraryAppletInfo(Out<LibraryAppletInfo> out_library_applet_info);
58 Result GetMainAppletIdentityInfo(Out<AppletIdentityInfo> out_identity_info);
59 Result CanUseApplicationCore(Out<bool> out_can_use_application_core);
60 Result GetMainAppletApplicationControlProperty(
61 OutLargeData<std::array<u8, 0x4000>, BufferAttr_HipcMapAlias> out_nacp);
62 Result GetMainAppletStorageId(Out<FileSys::StorageId> out_storage_id);
63 Result ExitProcessAndReturn();
64 Result GetCallerAppletIdentityInfo(Out<AppletIdentityInfo> out_identity_info);
65 Result GetCallerAppletIdentityInfoStack(
66 Out<s32> out_count,
67 OutArray<AppletIdentityInfo, BufferAttr_HipcMapAlias> out_identity_info);
68 Result GetDesirableKeyboardLayout(Out<u32> out_desirable_layout);
69 Result ReportVisibleError(ErrorCode error_code);
70 Result ReportVisibleErrorWithErrorContext(
71 ErrorCode error_code, InLargeData<ErrorContext, BufferAttr_HipcMapAlias> error_context);
72 Result GetMainAppletApplicationDesiredLanguage(Out<u64> out_desired_language);
73 Result GetCurrentApplicationId(Out<u64> out_application_id);
74 Result GetMainAppletAvailableUsers(Out<bool> out_no_users_available, Out<s32> out_users_count,
75 OutArray<Common::UUID, BufferAttr_HipcMapAlias> out_users);
76 Result ShouldSetGpuTimeSliceManually(Out<bool> out_should_set_gpu_time_slice_manually);
77 Result Cmd160(Out<u64> out_unknown0);
78
79 const std::shared_ptr<Applet> m_applet;
80 const std::shared_ptr<AppletDataBroker> m_broker;
81};
82
83} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/lock_accessor.cpp b/src/core/hle/service/am/service/lock_accessor.cpp
new file mode 100755
index 000000000..8e556fdd6
--- /dev/null
+++ b/src/core/hle/service/am/service/lock_accessor.cpp
@@ -0,0 +1,75 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/service/lock_accessor.h"
5#include "core/hle/service/cmif_serialization.h"
6
7namespace Service::AM {
8
9ILockAccessor::ILockAccessor(Core::System& system_)
10 : ServiceFramework{system_, "ILockAccessor"}, m_context{system_, "ILockAccessor"},
11 m_event{m_context} {
12 // clang-format off
13 static const FunctionInfo functions[] = {
14 {1, D<&ILockAccessor::TryLock>, "TryLock"},
15 {2, D<&ILockAccessor::Unlock>, "Unlock"},
16 {3, D<&ILockAccessor::GetEvent>, "GetEvent"},
17 {4, D<&ILockAccessor::IsLocked>, "IsLocked"},
18 };
19 // clang-format on
20
21 RegisterHandlers(functions);
22
23 m_event.Signal();
24}
25
26ILockAccessor::~ILockAccessor() = default;
27
28Result ILockAccessor::TryLock(Out<bool> out_is_locked,
29 OutCopyHandle<Kernel::KReadableEvent> out_handle,
30 bool return_handle) {
31 LOG_INFO(Service_AM, "called, return_handle={}", return_handle);
32
33 {
34 std::scoped_lock lk{m_mutex};
35 if (m_is_locked) {
36 *out_is_locked = false;
37 } else {
38 m_is_locked = true;
39 *out_is_locked = true;
40 }
41 }
42
43 if (return_handle) {
44 *out_handle = m_event.GetHandle();
45 }
46
47 R_SUCCEED();
48}
49
50Result ILockAccessor::Unlock() {
51 LOG_INFO(Service_AM, "called");
52
53 {
54 std::scoped_lock lk{m_mutex};
55 m_is_locked = false;
56 }
57
58 m_event.Signal();
59 R_SUCCEED();
60}
61
62Result ILockAccessor::GetEvent(OutCopyHandle<Kernel::KReadableEvent> out_handle) {
63 LOG_INFO(Service_AM, "called");
64 *out_handle = m_event.GetHandle();
65 R_SUCCEED();
66}
67
68Result ILockAccessor::IsLocked(Out<bool> out_is_locked) {
69 LOG_INFO(Service_AM, "called");
70 std::scoped_lock lk{m_mutex};
71 *out_is_locked = m_is_locked;
72 R_SUCCEED();
73}
74
75} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/lock_accessor.h b/src/core/hle/service/am/service/lock_accessor.h
new file mode 100755
index 000000000..9bfb5c050
--- /dev/null
+++ b/src/core/hle/service/am/service/lock_accessor.h
@@ -0,0 +1,32 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/kernel_helpers.h"
8#include "core/hle/service/os/event.h"
9#include "core/hle/service/service.h"
10
11namespace Service::AM {
12
13class ILockAccessor final : public ServiceFramework<ILockAccessor> {
14public:
15 explicit ILockAccessor(Core::System& system_);
16 ~ILockAccessor() override;
17
18private:
19 Result TryLock(Out<bool> out_is_locked, OutCopyHandle<Kernel::KReadableEvent> out_handle,
20 bool return_handle);
21 Result Unlock();
22 Result GetEvent(OutCopyHandle<Kernel::KReadableEvent> out_handle);
23 Result IsLocked(Out<bool> out_is_locked);
24
25private:
26 KernelHelpers::ServiceContext m_context;
27 Event m_event;
28 std::mutex m_mutex{};
29 bool m_is_locked{};
30};
31
32} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/process_winding_controller.cpp b/src/core/hle/service/am/service/process_winding_controller.cpp
new file mode 100755
index 000000000..10df830d7
--- /dev/null
+++ b/src/core/hle/service/am/service/process_winding_controller.cpp
@@ -0,0 +1,54 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/frontend/applets.h"
5#include "core/hle/service/am/service/library_applet_accessor.h"
6#include "core/hle/service/am/service/process_winding_controller.h"
7#include "core/hle/service/cmif_serialization.h"
8
9namespace Service::AM {
10
11IProcessWindingController::IProcessWindingController(Core::System& system_,
12 std::shared_ptr<Applet> applet)
13 : ServiceFramework{system_, "IProcessWindingController"}, m_applet{std::move(applet)} {
14 // clang-format off
15 static const FunctionInfo functions[] = {
16 {0, D<&IProcessWindingController::GetLaunchReason>, "GetLaunchReason"},
17 {11, D<&IProcessWindingController::OpenCallingLibraryApplet>, "OpenCallingLibraryApplet"},
18 {21, nullptr, "PushContext"},
19 {22, nullptr, "PopContext"},
20 {23, nullptr, "CancelWindingReservation"},
21 {30, nullptr, "WindAndDoReserved"},
22 {40, nullptr, "ReserveToStartAndWaitAndUnwindThis"},
23 {41, nullptr, "ReserveToStartAndWait"},
24 };
25 // clang-format on
26
27 RegisterHandlers(functions);
28}
29
30IProcessWindingController::~IProcessWindingController() = default;
31
32Result IProcessWindingController::GetLaunchReason(
33 Out<AppletProcessLaunchReason> out_launch_reason) {
34 LOG_INFO(Service_AM, "called");
35 *out_launch_reason = m_applet->launch_reason;
36 R_SUCCEED();
37}
38
39Result IProcessWindingController::OpenCallingLibraryApplet(
40 Out<SharedPointer<ILibraryAppletAccessor>> out_calling_library_applet) {
41 LOG_INFO(Service_AM, "called");
42
43 const auto caller_applet = m_applet->caller_applet.lock();
44 if (caller_applet == nullptr) {
45 LOG_ERROR(Service_AM, "No caller applet available");
46 R_THROW(ResultUnknown);
47 }
48
49 *out_calling_library_applet = std::make_shared<ILibraryAppletAccessor>(
50 system, m_applet->caller_applet_broker, caller_applet);
51 R_SUCCEED();
52}
53
54} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/process_winding_controller.h b/src/core/hle/service/am/service/process_winding_controller.h
new file mode 100755
index 000000000..4408af1f1
--- /dev/null
+++ b/src/core/hle/service/am/service/process_winding_controller.h
@@ -0,0 +1,28 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/am/am_types.h"
7#include "core/hle/service/cmif_types.h"
8#include "core/hle/service/service.h"
9
10namespace Service::AM {
11
12struct Applet;
13class ILibraryAppletAccessor;
14
15class IProcessWindingController final : public ServiceFramework<IProcessWindingController> {
16public:
17 explicit IProcessWindingController(Core::System& system_, std::shared_ptr<Applet> applet_);
18 ~IProcessWindingController() override;
19
20private:
21 Result GetLaunchReason(Out<AppletProcessLaunchReason> out_launch_reason);
22 Result OpenCallingLibraryApplet(
23 Out<SharedPointer<ILibraryAppletAccessor>> out_calling_library_applet);
24
25 const std::shared_ptr<Applet> m_applet;
26};
27
28} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/self_controller.cpp b/src/core/hle/service/am/service/self_controller.cpp
new file mode 100755
index 000000000..5c4c13de1
--- /dev/null
+++ b/src/core/hle/service/am/service/self_controller.cpp
@@ -0,0 +1,393 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "common/logging/log.h"
5#include "core/hle/result.h"
6#include "core/hle/service/am/am_results.h"
7#include "core/hle/service/am/frontend/applets.h"
8#include "core/hle/service/am/service/self_controller.h"
9#include "core/hle/service/caps/caps_su.h"
10#include "core/hle/service/cmif_serialization.h"
11#include "core/hle/service/nvnflinger/nvnflinger.h"
12#include "core/hle/service/sm/sm.h"
13#include "core/hle/service/vi/vi_results.h"
14
15namespace Service::AM {
16
17ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet> applet,
18 Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger)
19 : ServiceFramework{system_, "ISelfController"},
20 m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} {
21 // clang-format off
22 static const FunctionInfo functions[] = {
23 {0, D<&ISelfController::Exit>, "Exit"},
24 {1, D<&ISelfController::LockExit>, "LockExit"},
25 {2, D<&ISelfController::UnlockExit>, "UnlockExit"},
26 {3, D<&ISelfController::EnterFatalSection>, "EnterFatalSection"},
27 {4, D<&ISelfController::LeaveFatalSection>, "LeaveFatalSection"},
28 {9, D<&ISelfController::GetLibraryAppletLaunchableEvent>, "GetLibraryAppletLaunchableEvent"},
29 {10, D<&ISelfController::SetScreenShotPermission>, "SetScreenShotPermission"},
30 {11, D<&ISelfController::SetOperationModeChangedNotification>, "SetOperationModeChangedNotification"},
31 {12, D<&ISelfController::SetPerformanceModeChangedNotification>, "SetPerformanceModeChangedNotification"},
32 {13, D<&ISelfController::SetFocusHandlingMode>, "SetFocusHandlingMode"},
33 {14, D<&ISelfController::SetRestartMessageEnabled>, "SetRestartMessageEnabled"},
34 {15, D<&ISelfController::SetScreenShotAppletIdentityInfo>, "SetScreenShotAppletIdentityInfo"},
35 {16, D<&ISelfController::SetOutOfFocusSuspendingEnabled>, "SetOutOfFocusSuspendingEnabled"},
36 {17, nullptr, "SetControllerFirmwareUpdateSection"},
37 {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"},
38 {19, D<&ISelfController::SetAlbumImageOrientation>, "SetAlbumImageOrientation"},
39 {20, nullptr, "SetDesirableKeyboardLayout"},
40 {21, nullptr, "GetScreenShotProgramId"},
41 {40, D<&ISelfController::CreateManagedDisplayLayer>, "CreateManagedDisplayLayer"},
42 {41, D<&ISelfController::IsSystemBufferSharingEnabled>, "IsSystemBufferSharingEnabled"},
43 {42, D<&ISelfController::GetSystemSharedLayerHandle>, "GetSystemSharedLayerHandle"},
44 {43, D<&ISelfController::GetSystemSharedBufferHandle>, "GetSystemSharedBufferHandle"},
45 {44, D<&ISelfController::CreateManagedDisplaySeparableLayer>, "CreateManagedDisplaySeparableLayer"},
46 {45, nullptr, "SetManagedDisplayLayerSeparationMode"},
47 {46, nullptr, "SetRecordingLayerCompositionEnabled"},
48 {50, D<&ISelfController::SetHandlesRequestToDisplay>, "SetHandlesRequestToDisplay"},
49 {51, D<&ISelfController::ApproveToDisplay>, "ApproveToDisplay"},
50 {60, D<&ISelfController::OverrideAutoSleepTimeAndDimmingTime>, "OverrideAutoSleepTimeAndDimmingTime"},
51 {61, D<&ISelfController::SetMediaPlaybackState>, "SetMediaPlaybackState"},
52 {62, D<&ISelfController::SetIdleTimeDetectionExtension>, "SetIdleTimeDetectionExtension"},
53 {63, D<&ISelfController::GetIdleTimeDetectionExtension>, "GetIdleTimeDetectionExtension"},
54 {64, nullptr, "SetInputDetectionSourceSet"},
55 {65, D<&ISelfController::ReportUserIsActive>, "ReportUserIsActive"},
56 {66, nullptr, "GetCurrentIlluminance"},
57 {67, nullptr, "IsIlluminanceAvailable"},
58 {68, D<&ISelfController::SetAutoSleepDisabled>, "SetAutoSleepDisabled"},
59 {69, D<&ISelfController::IsAutoSleepDisabled>, "IsAutoSleepDisabled"},
60 {70, nullptr, "ReportMultimediaError"},
61 {71, nullptr, "GetCurrentIlluminanceEx"},
62 {72, D<&ISelfController::SetInputDetectionPolicy>, "SetInputDetectionPolicy"},
63 {80, nullptr, "SetWirelessPriorityMode"},
64 {90, D<&ISelfController::GetAccumulatedSuspendedTickValue>, "GetAccumulatedSuspendedTickValue"},
65 {91, D<&ISelfController::GetAccumulatedSuspendedTickChangedEvent>, "GetAccumulatedSuspendedTickChangedEvent"},
66 {100, D<&ISelfController::SetAlbumImageTakenNotificationEnabled>, "SetAlbumImageTakenNotificationEnabled"},
67 {110, nullptr, "SetApplicationAlbumUserData"},
68 {120, D<&ISelfController::SaveCurrentScreenshot>, "SaveCurrentScreenshot"},
69 {130, D<&ISelfController::SetRecordVolumeMuted>, "SetRecordVolumeMuted"},
70 {1000, nullptr, "GetDebugStorageChannel"},
71 };
72 // clang-format on
73
74 RegisterHandlers(functions);
75}
76
77ISelfController::~ISelfController() = default;
78
79Result ISelfController::Exit() {
80 LOG_DEBUG(Service_AM, "called");
81
82 // TODO
83 system.Exit();
84
85 R_SUCCEED();
86}
87
88Result ISelfController::LockExit() {
89 LOG_DEBUG(Service_AM, "called");
90
91 system.SetExitLocked(true);
92
93 R_SUCCEED();
94}
95
96Result ISelfController::UnlockExit() {
97 LOG_DEBUG(Service_AM, "called");
98
99 system.SetExitLocked(false);
100
101 if (system.GetExitRequested()) {
102 system.Exit();
103 }
104
105 R_SUCCEED();
106}
107
108Result ISelfController::EnterFatalSection() {
109 std::scoped_lock lk{m_applet->lock};
110
111 m_applet->fatal_section_count++;
112 LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", m_applet->fatal_section_count);
113
114 R_SUCCEED();
115}
116
117Result ISelfController::LeaveFatalSection() {
118 LOG_DEBUG(Service_AM, "called");
119
120 // Entry and exit of fatal sections must be balanced.
121 std::scoped_lock lk{m_applet->lock};
122 R_UNLESS(m_applet->fatal_section_count > 0, AM::ResultFatalSectionCountImbalance);
123 m_applet->fatal_section_count--;
124
125 R_SUCCEED();
126}
127
128Result ISelfController::GetLibraryAppletLaunchableEvent(
129 OutCopyHandle<Kernel::KReadableEvent> out_event) {
130 LOG_WARNING(Service_AM, "(STUBBED) called");
131
132 m_applet->library_applet_launchable_event.Signal();
133 *out_event = m_applet->library_applet_launchable_event.GetHandle();
134
135 R_SUCCEED();
136}
137
138Result ISelfController::SetScreenShotPermission(ScreenshotPermission screen_shot_permission) {
139 LOG_DEBUG(Service_AM, "called, permission={}", screen_shot_permission);
140
141 std::scoped_lock lk{m_applet->lock};
142 m_applet->screenshot_permission = screen_shot_permission;
143
144 R_SUCCEED();
145}
146
147Result ISelfController::SetOperationModeChangedNotification(bool enabled) {
148 LOG_INFO(Service_AM, "called, enabled={}", enabled);
149
150 std::scoped_lock lk{m_applet->lock};
151 m_applet->operation_mode_changed_notification_enabled = enabled;
152
153 R_SUCCEED();
154}
155
156Result ISelfController::SetPerformanceModeChangedNotification(bool enabled) {
157 LOG_INFO(Service_AM, "called, enabled={}", enabled);
158
159 std::scoped_lock lk{m_applet->lock};
160 m_applet->performance_mode_changed_notification_enabled = enabled;
161
162 R_SUCCEED();
163}
164
165Result ISelfController::SetFocusHandlingMode(bool notify, bool background, bool suspend) {
166 LOG_WARNING(Service_AM, "(STUBBED) called, notify={} background={} suspend={}", notify,
167 background, suspend);
168
169 std::scoped_lock lk{m_applet->lock};
170 m_applet->focus_handling_mode = {notify, background, suspend};
171
172 R_SUCCEED();
173}
174
175Result ISelfController::SetRestartMessageEnabled(bool enabled) {
176 LOG_INFO(Service_AM, "called, enabled={}", enabled);
177
178 std::scoped_lock lk{m_applet->lock};
179 m_applet->restart_message_enabled = enabled;
180
181 R_SUCCEED();
182}
183
184Result ISelfController::SetScreenShotAppletIdentityInfo(
185 AppletIdentityInfo screen_shot_applet_identity_info) {
186 LOG_WARNING(Service_AM, "(STUBBED) called");
187
188 std::scoped_lock lk{m_applet->lock};
189 m_applet->screen_shot_identity = screen_shot_applet_identity_info;
190
191 R_SUCCEED();
192}
193
194Result ISelfController::SetOutOfFocusSuspendingEnabled(bool enabled) {
195 LOG_INFO(Service_AM, "called, enabled={}", enabled);
196
197 std::scoped_lock lk{m_applet->lock};
198 m_applet->out_of_focus_suspension_enabled = enabled;
199
200 R_SUCCEED();
201}
202
203Result ISelfController::SetAlbumImageOrientation(
204 Capture::AlbumImageOrientation album_image_orientation) {
205 LOG_WARNING(Service_AM, "(STUBBED) called, orientation={}", album_image_orientation);
206
207 std::scoped_lock lk{m_applet->lock};
208 m_applet->album_image_orientation = album_image_orientation;
209
210 R_SUCCEED();
211}
212
213Result ISelfController::IsSystemBufferSharingEnabled() {
214 LOG_INFO(Service_AM, "called");
215 R_SUCCEED_IF(m_applet->system_buffer_manager.Initialize(
216 &m_nvnflinger, m_process, m_applet->applet_id, m_applet->library_applet_mode));
217 R_THROW(VI::ResultOperationFailed);
218}
219
220Result ISelfController::GetSystemSharedBufferHandle(Out<u64> out_buffer_id) {
221 LOG_WARNING(Service_AM, "(STUBBED) called");
222
223 R_TRY(this->IsSystemBufferSharingEnabled());
224
225 u64 layer_id;
226 m_applet->system_buffer_manager.GetSystemSharedLayerHandle(out_buffer_id, &layer_id);
227 R_SUCCEED();
228}
229
230Result ISelfController::GetSystemSharedLayerHandle(Out<u64> out_buffer_id, Out<u64> out_layer_id) {
231 LOG_INFO(Service_AM, "(STUBBED) called");
232
233 R_TRY(this->IsSystemBufferSharingEnabled());
234
235 m_applet->system_buffer_manager.GetSystemSharedLayerHandle(out_buffer_id, out_layer_id);
236 R_SUCCEED();
237}
238
239Result ISelfController::CreateManagedDisplayLayer(Out<u64> out_layer_id) {
240 LOG_INFO(Service_AM, "called");
241
242 m_applet->managed_layer_holder.Initialize(&m_nvnflinger);
243 m_applet->managed_layer_holder.CreateManagedDisplayLayer(out_layer_id);
244
245 R_SUCCEED();
246}
247
248Result ISelfController::CreateManagedDisplaySeparableLayer(Out<u64> out_layer_id,
249 Out<u64> out_recording_layer_id) {
250 LOG_WARNING(Service_AM, "(STUBBED) called");
251
252 m_applet->managed_layer_holder.Initialize(&m_nvnflinger);
253 m_applet->managed_layer_holder.CreateManagedDisplaySeparableLayer(out_layer_id,
254 out_recording_layer_id);
255
256 R_SUCCEED();
257}
258
259Result ISelfController::SetHandlesRequestToDisplay(bool enable) {
260 LOG_WARNING(Service_AM, "(STUBBED) called, enable={}", enable);
261 R_SUCCEED();
262}
263
264Result ISelfController::ApproveToDisplay() {
265 LOG_WARNING(Service_AM, "(STUBBED) called");
266 R_SUCCEED();
267}
268
269Result ISelfController::SetMediaPlaybackState(bool state) {
270 LOG_WARNING(Service_AM, "(STUBBED) called, state={}", state);
271 R_SUCCEED();
272}
273
274Result ISelfController::OverrideAutoSleepTimeAndDimmingTime(s32 a, s32 b, s32 c, s32 d) {
275 LOG_WARNING(Service_AM, "(STUBBED) called, a={}, b={}, c={}, d={}", a, b, c, d);
276 R_SUCCEED();
277}
278
279Result ISelfController::SetIdleTimeDetectionExtension(
280 IdleTimeDetectionExtension idle_time_detection_extension) {
281 LOG_DEBUG(Service_AM, "(STUBBED) called extension={}", idle_time_detection_extension);
282
283 std::scoped_lock lk{m_applet->lock};
284 m_applet->idle_time_detection_extension = idle_time_detection_extension;
285
286 R_SUCCEED();
287}
288
289Result ISelfController::GetIdleTimeDetectionExtension(
290 Out<IdleTimeDetectionExtension> out_idle_time_detection_extension) {
291 LOG_WARNING(Service_AM, "(STUBBED) called");
292
293 std::scoped_lock lk{m_applet->lock};
294 *out_idle_time_detection_extension = m_applet->idle_time_detection_extension;
295
296 R_SUCCEED();
297}
298
299Result ISelfController::ReportUserIsActive() {
300 LOG_WARNING(Service_AM, "(STUBBED) called");
301 R_SUCCEED();
302}
303
304Result ISelfController::SetAutoSleepDisabled(bool is_auto_sleep_disabled) {
305 LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", is_auto_sleep_disabled);
306
307 // On the system itself, if the previous state of is_auto_sleep_disabled
308 // differed from the current value passed in, it'd signify the internal
309 // window manager to update (and also increment some statistics like update counts)
310 //
311 // It'd also indicate this change to an idle handling context.
312 //
313 // However, given we're emulating this behavior, most of this can be ignored
314 // and it's sufficient to simply set the member variable for querying via
315 // IsAutoSleepDisabled().
316
317 std::scoped_lock lk{m_applet->lock};
318 m_applet->auto_sleep_disabled = is_auto_sleep_disabled;
319
320 R_SUCCEED();
321}
322
323Result ISelfController::IsAutoSleepDisabled(Out<bool> out_is_auto_sleep_disabled) {
324 LOG_DEBUG(Service_AM, "called.");
325
326 std::scoped_lock lk{m_applet->lock};
327 *out_is_auto_sleep_disabled = m_applet->auto_sleep_disabled;
328
329 R_SUCCEED();
330}
331
332Result ISelfController::SetInputDetectionPolicy(InputDetectionPolicy input_detection_policy) {
333 LOG_WARNING(Service_AM, "(STUBBED) called");
334 R_SUCCEED();
335}
336
337Result ISelfController::GetAccumulatedSuspendedTickValue(
338 Out<u64> out_accumulated_suspended_tick_value) {
339 LOG_DEBUG(Service_AM, "called.");
340
341 // This command returns the total number of system ticks since ISelfController creation
342 // where the game was suspended. Since Yuzu doesn't implement game suspension, this command
343 // can just always return 0 ticks.
344 std::scoped_lock lk{m_applet->lock};
345 *out_accumulated_suspended_tick_value = m_applet->suspended_ticks;
346
347 R_SUCCEED();
348}
349
350Result ISelfController::GetAccumulatedSuspendedTickChangedEvent(
351 OutCopyHandle<Kernel::KReadableEvent> out_event) {
352 LOG_DEBUG(Service_AM, "called.");
353
354 *out_event = m_applet->accumulated_suspended_tick_changed_event.GetHandle();
355 R_SUCCEED();
356}
357
358Result ISelfController::SetAlbumImageTakenNotificationEnabled(bool enabled) {
359 LOG_WARNING(Service_AM, "(STUBBED) called. enabled={}", enabled);
360
361 // This service call sets an internal flag whether a notification is shown when an image is
362 // captured. Currently we do not support capturing images via the capture button, so this can be
363 // stubbed for now.
364 std::scoped_lock lk{m_applet->lock};
365 m_applet->album_image_taken_notification_enabled = enabled;
366
367 R_SUCCEED();
368}
369
370Result ISelfController::SaveCurrentScreenshot(Capture::AlbumReportOption album_report_option) {
371 LOG_INFO(Service_AM, "called, report_option={}", album_report_option);
372
373 const auto screenshot_service =
374 system.ServiceManager().GetService<Service::Capture::IScreenShotApplicationService>(
375 "caps:su");
376
377 if (screenshot_service) {
378 screenshot_service->CaptureAndSaveScreenshot(album_report_option);
379 }
380
381 R_SUCCEED();
382}
383
384Result ISelfController::SetRecordVolumeMuted(bool muted) {
385 LOG_WARNING(Service_AM, "(STUBBED) called. muted={}", muted);
386
387 std::scoped_lock lk{m_applet->lock};
388 m_applet->record_volume_muted = muted;
389
390 R_SUCCEED();
391}
392
393} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/self_controller.h b/src/core/hle/service/am/service/self_controller.h
new file mode 100755
index 000000000..01fa381a3
--- /dev/null
+++ b/src/core/hle/service/am/service/self_controller.h
@@ -0,0 +1,72 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/am/am_types.h"
7#include "core/hle/service/cmif_types.h"
8#include "core/hle/service/service.h"
9
10namespace Kernel {
11class KReadableEvent;
12}
13
14namespace Service::Capture {
15enum class AlbumImageOrientation;
16enum class AlbumReportOption;
17} // namespace Service::Capture
18
19namespace Service::AM {
20
21struct Applet;
22
23class ISelfController final : public ServiceFramework<ISelfController> {
24public:
25 explicit ISelfController(Core::System& system_, std::shared_ptr<Applet> applet,
26 Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger);
27 ~ISelfController() override;
28
29private:
30 Result Exit();
31 Result LockExit();
32 Result UnlockExit();
33 Result EnterFatalSection();
34 Result LeaveFatalSection();
35 Result GetLibraryAppletLaunchableEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
36 Result SetScreenShotPermission(ScreenshotPermission screen_shot_permission);
37 Result SetOperationModeChangedNotification(bool enabled);
38 Result SetPerformanceModeChangedNotification(bool enabled);
39 Result SetFocusHandlingMode(bool notify, bool background, bool suspend);
40 Result SetRestartMessageEnabled(bool enabled);
41 Result SetScreenShotAppletIdentityInfo(AppletIdentityInfo screen_shot_applet_identity_info);
42 Result SetOutOfFocusSuspendingEnabled(bool enabled);
43 Result SetAlbumImageOrientation(Capture::AlbumImageOrientation album_image_orientation);
44 Result IsSystemBufferSharingEnabled();
45 Result GetSystemSharedBufferHandle(Out<u64> out_buffer_id);
46 Result GetSystemSharedLayerHandle(Out<u64> out_buffer_id, Out<u64> out_layer_id);
47 Result CreateManagedDisplayLayer(Out<u64> out_layer_id);
48 Result CreateManagedDisplaySeparableLayer(Out<u64> out_layer_id,
49 Out<u64> out_recording_layer_id);
50 Result SetHandlesRequestToDisplay(bool enable);
51 Result ApproveToDisplay();
52 Result SetMediaPlaybackState(bool state);
53 Result OverrideAutoSleepTimeAndDimmingTime(s32 a, s32 b, s32 c, s32 d);
54 Result SetIdleTimeDetectionExtension(IdleTimeDetectionExtension idle_time_detection_extension);
55 Result GetIdleTimeDetectionExtension(
56 Out<IdleTimeDetectionExtension> out_idle_time_detection_extension);
57 Result ReportUserIsActive();
58 Result SetAutoSleepDisabled(bool is_auto_sleep_disabled);
59 Result IsAutoSleepDisabled(Out<bool> out_is_auto_sleep_disabled);
60 Result SetInputDetectionPolicy(InputDetectionPolicy input_detection_policy);
61 Result GetAccumulatedSuspendedTickValue(Out<u64> out_accumulated_suspended_tick_value);
62 Result GetAccumulatedSuspendedTickChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
63 Result SetAlbumImageTakenNotificationEnabled(bool enabled);
64 Result SaveCurrentScreenshot(Capture::AlbumReportOption album_report_option);
65 Result SetRecordVolumeMuted(bool muted);
66
67 Nvnflinger::Nvnflinger& m_nvnflinger;
68 Kernel::KProcess* const m_process;
69 const std::shared_ptr<Applet> m_applet;
70};
71
72} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/storage.cpp b/src/core/hle/service/am/service/storage.cpp
new file mode 100755
index 000000000..25ee0afbd
--- /dev/null
+++ b/src/core/hle/service/am/service/storage.cpp
@@ -0,0 +1,48 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/am_results.h"
5#include "core/hle/service/am/library_applet_storage.h"
6#include "core/hle/service/am/service/storage.h"
7#include "core/hle/service/am/service/storage_accessor.h"
8#include "core/hle/service/cmif_serialization.h"
9
10namespace Service::AM {
11
12IStorage::IStorage(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl)
13 : ServiceFramework{system_, "IStorage"}, m_impl{std::move(impl)} {
14 static const FunctionInfo functions[] = {
15 {0, D<&IStorage::Open>, "Open"},
16 {1, D<&IStorage::OpenTransferStorage>, "OpenTransferStorage"},
17 };
18
19 RegisterHandlers(functions);
20}
21
22IStorage::IStorage(Core::System& system_, std::vector<u8>&& data)
23 : IStorage(system_, CreateStorage(std::move(data))) {}
24
25IStorage::~IStorage() = default;
26
27Result IStorage::Open(Out<SharedPointer<IStorageAccessor>> out_storage_accessor) {
28 LOG_DEBUG(Service_AM, "called");
29
30 R_UNLESS(m_impl->GetHandle() == nullptr, AM::ResultInvalidStorageType);
31
32 *out_storage_accessor = std::make_shared<IStorageAccessor>(system, m_impl);
33 R_SUCCEED();
34}
35
36Result IStorage::OpenTransferStorage(
37 Out<SharedPointer<ITransferStorageAccessor>> out_transfer_storage_accessor) {
38 R_UNLESS(m_impl->GetHandle() != nullptr, AM::ResultInvalidStorageType);
39
40 *out_transfer_storage_accessor = std::make_shared<ITransferStorageAccessor>(system, m_impl);
41 R_SUCCEED();
42}
43
44std::vector<u8> IStorage::GetData() const {
45 return m_impl->GetData();
46}
47
48} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/storage.h b/src/core/hle/service/am/service/storage.h
new file mode 100755
index 000000000..cde2ed0ea
--- /dev/null
+++ b/src/core/hle/service/am/service/storage.h
@@ -0,0 +1,35 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/service.h"
8
9namespace Service::AM {
10
11class LibraryAppletStorage;
12class IStorageAccessor;
13class ITransferStorageAccessor;
14
15class IStorage final : public ServiceFramework<IStorage> {
16public:
17 explicit IStorage(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl);
18 explicit IStorage(Core::System& system_, std::vector<u8>&& buffer);
19 ~IStorage() override;
20
21 std::shared_ptr<LibraryAppletStorage> GetImpl() const {
22 return m_impl;
23 }
24
25 std::vector<u8> GetData() const;
26
27private:
28 Result Open(Out<SharedPointer<IStorageAccessor>> out_storage_accessor);
29 Result OpenTransferStorage(
30 Out<SharedPointer<ITransferStorageAccessor>> out_transfer_storage_accessor);
31
32 const std::shared_ptr<LibraryAppletStorage> m_impl;
33};
34
35} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/storage_accessor.cpp b/src/core/hle/service/am/service/storage_accessor.cpp
new file mode 100755
index 000000000..84577fee4
--- /dev/null
+++ b/src/core/hle/service/am/service/storage_accessor.cpp
@@ -0,0 +1,68 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/kernel/k_transfer_memory.h"
5#include "core/hle/service/am/library_applet_storage.h"
6#include "core/hle/service/am/service/storage_accessor.h"
7#include "core/hle/service/cmif_serialization.h"
8
9namespace Service::AM {
10
11IStorageAccessor::IStorageAccessor(Core::System& system_,
12 std::shared_ptr<LibraryAppletStorage> impl)
13 : ServiceFramework{system_, "IStorageAccessor"}, m_impl{std::move(impl)} {
14 static const FunctionInfo functions[] = {
15 {0, D<&IStorageAccessor::GetSize>, "GetSize"},
16 {10, D<&IStorageAccessor::Write>, "Write"},
17 {11, D<&IStorageAccessor::Read>, "Read"},
18 };
19
20 RegisterHandlers(functions);
21}
22
23IStorageAccessor::~IStorageAccessor() = default;
24
25Result IStorageAccessor::GetSize(Out<s64> out_size) {
26 LOG_DEBUG(Service_AM, "called");
27 *out_size = m_impl->GetSize();
28 R_SUCCEED();
29}
30
31Result IStorageAccessor::Write(InBuffer<BufferAttr_HipcAutoSelect> buffer, s64 offset) {
32 LOG_DEBUG(Service_AM, "called, offset={} size={}", offset, buffer.size());
33 R_RETURN(m_impl->Write(offset, buffer.data(), buffer.size()));
34}
35
36Result IStorageAccessor::Read(OutBuffer<BufferAttr_HipcAutoSelect> out_buffer, s64 offset) {
37 LOG_DEBUG(Service_AM, "called, offset={} size={}", offset, out_buffer.size());
38 R_RETURN(m_impl->Read(offset, out_buffer.data(), out_buffer.size()));
39}
40
41ITransferStorageAccessor::ITransferStorageAccessor(Core::System& system_,
42 std::shared_ptr<LibraryAppletStorage> impl)
43 : ServiceFramework{system_, "ITransferStorageAccessor"}, m_impl{std::move(impl)} {
44 static const FunctionInfo functions[] = {
45 {0, D<&ITransferStorageAccessor::GetSize>, "GetSize"},
46 {1, D<&ITransferStorageAccessor::GetHandle>, "GetHandle"},
47 };
48
49 RegisterHandlers(functions);
50}
51
52ITransferStorageAccessor::~ITransferStorageAccessor() = default;
53
54Result ITransferStorageAccessor::GetSize(Out<s64> out_size) {
55 LOG_DEBUG(Service_AM, "called");
56 *out_size = m_impl->GetSize();
57 R_SUCCEED();
58}
59
60Result ITransferStorageAccessor::GetHandle(Out<s64> out_size,
61 OutCopyHandle<Kernel::KTransferMemory> out_handle) {
62 LOG_INFO(Service_AM, "called");
63 *out_size = m_impl->GetSize();
64 *out_handle = m_impl->GetHandle();
65 R_SUCCEED();
66}
67
68} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/storage_accessor.h b/src/core/hle/service/am/service/storage_accessor.h
new file mode 100755
index 000000000..1a01730e0
--- /dev/null
+++ b/src/core/hle/service/am/service/storage_accessor.h
@@ -0,0 +1,38 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/am/library_applet_storage.h"
7#include "core/hle/service/cmif_types.h"
8#include "core/hle/service/service.h"
9
10namespace Service::AM {
11
12class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
13public:
14 explicit IStorageAccessor(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl);
15 ~IStorageAccessor() override;
16
17private:
18 Result GetSize(Out<s64> out_size);
19 Result Write(InBuffer<BufferAttr_HipcAutoSelect> buffer, s64 offset);
20 Result Read(OutBuffer<BufferAttr_HipcAutoSelect> out_buffer, s64 offset);
21
22 const std::shared_ptr<LibraryAppletStorage> m_impl;
23};
24
25class ITransferStorageAccessor final : public ServiceFramework<ITransferStorageAccessor> {
26public:
27 explicit ITransferStorageAccessor(Core::System& system_,
28 std::shared_ptr<LibraryAppletStorage> impl);
29 ~ITransferStorageAccessor() override;
30
31private:
32 Result GetSize(Out<s64> out_size);
33 Result GetHandle(Out<s64> out_size, OutCopyHandle<Kernel::KTransferMemory> out_handle);
34
35 const std::shared_ptr<LibraryAppletStorage> m_impl;
36};
37
38} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/system_applet_proxy.cpp b/src/core/hle/service/am/service/system_applet_proxy.cpp
new file mode 100755
index 000000000..5ec509d2e
--- /dev/null
+++ b/src/core/hle/service/am/service/system_applet_proxy.cpp
@@ -0,0 +1,133 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/service/applet_common_functions.h"
5#include "core/hle/service/am/service/application_creator.h"
6#include "core/hle/service/am/service/audio_controller.h"
7#include "core/hle/service/am/service/common_state_getter.h"
8#include "core/hle/service/am/service/debug_functions.h"
9#include "core/hle/service/am/service/display_controller.h"
10#include "core/hle/service/am/service/global_state_controller.h"
11#include "core/hle/service/am/service/home_menu_functions.h"
12#include "core/hle/service/am/service/library_applet_creator.h"
13#include "core/hle/service/am/service/process_winding_controller.h"
14#include "core/hle/service/am/service/self_controller.h"
15#include "core/hle/service/am/service/system_applet_proxy.h"
16#include "core/hle/service/am/service/window_controller.h"
17#include "core/hle/service/cmif_serialization.h"
18
19namespace Service::AM {
20
21ISystemAppletProxy::ISystemAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
22 Kernel::KProcess* process,
23 Nvnflinger::Nvnflinger& nvnflinger)
24 : ServiceFramework{system_, "ISystemAppletProxy"},
25 m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} {
26 // clang-format off
27 static const FunctionInfo functions[] = {
28 {0, D<&ISystemAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
29 {1, D<&ISystemAppletProxy::GetSelfController>, "GetSelfController"},
30 {2, D<&ISystemAppletProxy::GetWindowController>, "GetWindowController"},
31 {3, D<&ISystemAppletProxy::GetAudioController>, "GetAudioController"},
32 {4, D<&ISystemAppletProxy::GetDisplayController>, "GetDisplayController"},
33 {10, D<&ISystemAppletProxy::GetProcessWindingController>, "GetProcessWindingController"},
34 {11, D<&ISystemAppletProxy::GetLibraryAppletCreator>, "GetLibraryAppletCreator"},
35 {20, D<&ISystemAppletProxy::GetHomeMenuFunctions>, "GetHomeMenuFunctions"},
36 {21, D<&ISystemAppletProxy::GetGlobalStateController>, "GetGlobalStateController"},
37 {22, D<&ISystemAppletProxy::GetApplicationCreator>, "GetApplicationCreator"},
38 {23, D<&ISystemAppletProxy::GetAppletCommonFunctions>, "GetAppletCommonFunctions"},
39 {1000, D<&ISystemAppletProxy::GetDebugFunctions>, "GetDebugFunctions"},
40 };
41 // clang-format on
42
43 RegisterHandlers(functions);
44}
45
46ISystemAppletProxy::~ISystemAppletProxy() = default;
47
48Result ISystemAppletProxy::GetAudioController(
49 Out<SharedPointer<IAudioController>> out_audio_controller) {
50 LOG_DEBUG(Service_AM, "called");
51 *out_audio_controller = std::make_shared<IAudioController>(system);
52 R_SUCCEED();
53}
54
55Result ISystemAppletProxy::GetDisplayController(
56 Out<SharedPointer<IDisplayController>> out_display_controller) {
57 LOG_DEBUG(Service_AM, "called");
58 *out_display_controller = std::make_shared<IDisplayController>(system, m_applet);
59 R_SUCCEED();
60}
61
62Result ISystemAppletProxy::GetProcessWindingController(
63 Out<SharedPointer<IProcessWindingController>> out_process_winding_controller) {
64 LOG_DEBUG(Service_AM, "called");
65 *out_process_winding_controller = std::make_shared<IProcessWindingController>(system, m_applet);
66 R_SUCCEED();
67}
68
69Result ISystemAppletProxy::GetDebugFunctions(
70 Out<SharedPointer<IDebugFunctions>> out_debug_functions) {
71 LOG_DEBUG(Service_AM, "called");
72 *out_debug_functions = std::make_shared<IDebugFunctions>(system);
73 R_SUCCEED();
74}
75
76Result ISystemAppletProxy::GetWindowController(
77 Out<SharedPointer<IWindowController>> out_window_controller) {
78 LOG_DEBUG(Service_AM, "called");
79 *out_window_controller = std::make_shared<IWindowController>(system, m_applet);
80 R_SUCCEED();
81}
82
83Result ISystemAppletProxy::GetSelfController(
84 Out<SharedPointer<ISelfController>> out_self_controller) {
85 LOG_DEBUG(Service_AM, "called");
86 *out_self_controller =
87 std::make_shared<ISelfController>(system, m_applet, m_process, m_nvnflinger);
88 R_SUCCEED();
89}
90
91Result ISystemAppletProxy::GetCommonStateGetter(
92 Out<SharedPointer<ICommonStateGetter>> out_common_state_getter) {
93 LOG_DEBUG(Service_AM, "called");
94 *out_common_state_getter = std::make_shared<ICommonStateGetter>(system, m_applet);
95 R_SUCCEED();
96}
97
98Result ISystemAppletProxy::GetLibraryAppletCreator(
99 Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) {
100 LOG_DEBUG(Service_AM, "called");
101 *out_library_applet_creator = std::make_shared<ILibraryAppletCreator>(system, m_applet);
102 R_SUCCEED();
103}
104
105Result ISystemAppletProxy::GetApplicationCreator(
106 Out<SharedPointer<IApplicationCreator>> out_application_creator) {
107 LOG_DEBUG(Service_AM, "called");
108 *out_application_creator = std::make_shared<IApplicationCreator>(system);
109 R_SUCCEED();
110}
111
112Result ISystemAppletProxy::GetAppletCommonFunctions(
113 Out<SharedPointer<IAppletCommonFunctions>> out_applet_common_functions) {
114 LOG_DEBUG(Service_AM, "called");
115 *out_applet_common_functions = std::make_shared<IAppletCommonFunctions>(system, m_applet);
116 R_SUCCEED();
117}
118
119Result ISystemAppletProxy::GetHomeMenuFunctions(
120 Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions) {
121 LOG_DEBUG(Service_AM, "called");
122 *out_home_menu_functions = std::make_shared<IHomeMenuFunctions>(system, m_applet);
123 R_SUCCEED();
124}
125
126Result ISystemAppletProxy::GetGlobalStateController(
127 Out<SharedPointer<IGlobalStateController>> out_global_state_controller) {
128 LOG_DEBUG(Service_AM, "called");
129 *out_global_state_controller = std::make_shared<IGlobalStateController>(system);
130 R_SUCCEED();
131}
132
133} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/system_applet_proxy.h b/src/core/hle/service/am/service/system_applet_proxy.h
new file mode 100755
index 000000000..3d5040315
--- /dev/null
+++ b/src/core/hle/service/am/service/system_applet_proxy.h
@@ -0,0 +1,54 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/service.h"
8
9namespace Service::AM {
10
11struct Applet;
12class IAppletCommonFunctions;
13class IApplicationCreator;
14class IAudioController;
15class ICommonStateGetter;
16class IDebugFunctions;
17class IDisplayController;
18class IHomeMenuFunctions;
19class IGlobalStateController;
20class ILibraryAppletCreator;
21class IProcessWindingController;
22class ISelfController;
23class IWindowController;
24
25class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> {
26public:
27 explicit ISystemAppletProxy(Core::System& system, std::shared_ptr<Applet> applet,
28 Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger);
29 ~ISystemAppletProxy();
30
31private:
32 Result GetAudioController(Out<SharedPointer<IAudioController>> out_audio_controller);
33 Result GetDisplayController(Out<SharedPointer<IDisplayController>> out_display_controller);
34 Result GetProcessWindingController(
35 Out<SharedPointer<IProcessWindingController>> out_process_winding_controller);
36 Result GetDebugFunctions(Out<SharedPointer<IDebugFunctions>> out_debug_functions);
37 Result GetWindowController(Out<SharedPointer<IWindowController>> out_window_controller);
38 Result GetSelfController(Out<SharedPointer<ISelfController>> out_self_controller);
39 Result GetCommonStateGetter(Out<SharedPointer<ICommonStateGetter>> out_common_state_getter);
40 Result GetLibraryAppletCreator(
41 Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator);
42 Result GetApplicationCreator(Out<SharedPointer<IApplicationCreator>> out_application_creator);
43 Result GetAppletCommonFunctions(
44 Out<SharedPointer<IAppletCommonFunctions>> out_applet_common_functions);
45 Result GetHomeMenuFunctions(Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions);
46 Result GetGlobalStateController(
47 Out<SharedPointer<IGlobalStateController>> out_global_state_controller);
48
49 Nvnflinger::Nvnflinger& m_nvnflinger;
50 Kernel::KProcess* const m_process;
51 const std::shared_ptr<Applet> m_applet;
52};
53
54} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/window_controller.cpp b/src/core/hle/service/am/service/window_controller.cpp
new file mode 100755
index 000000000..b874ecb91
--- /dev/null
+++ b/src/core/hle/service/am/service/window_controller.cpp
@@ -0,0 +1,86 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/applet.h"
5#include "core/hle/service/am/applet_manager.h"
6#include "core/hle/service/am/service/window_controller.h"
7#include "core/hle/service/cmif_serialization.h"
8
9namespace Service::AM {
10
11IWindowController::IWindowController(Core::System& system_, std::shared_ptr<Applet> applet)
12 : ServiceFramework{system_, "IWindowController"}, m_applet{std::move(applet)} {
13 // clang-format off
14 static const FunctionInfo functions[] = {
15 {0, nullptr, "CreateWindow"},
16 {1, D<&IWindowController::GetAppletResourceUserId>, "GetAppletResourceUserId"},
17 {2, D<&IWindowController::GetAppletResourceUserIdOfCallerApplet>, "GetAppletResourceUserIdOfCallerApplet"},
18 {10, D<&IWindowController::AcquireForegroundRights>, "AcquireForegroundRights"},
19 {11, D<&IWindowController::ReleaseForegroundRights>, "ReleaseForegroundRights"},
20 {12, D<&IWindowController::RejectToChangeIntoBackground>, "RejectToChangeIntoBackground"},
21 {20, D<&IWindowController::SetAppletWindowVisibility>, "SetAppletWindowVisibility"},
22 {21, D<&IWindowController::SetAppletGpuTimeSlice>, "SetAppletGpuTimeSlice"},
23 };
24 // clang-format on
25
26 RegisterHandlers(functions);
27}
28
29IWindowController::~IWindowController() = default;
30
31Result IWindowController::GetAppletResourceUserId(Out<AppletResourceUserId> out_aruid) {
32 LOG_INFO(Service_AM, "called");
33 *out_aruid = m_applet->aruid;
34 R_SUCCEED();
35}
36
37Result IWindowController::GetAppletResourceUserIdOfCallerApplet(
38 Out<AppletResourceUserId> out_aruid) {
39 LOG_INFO(Service_AM, "called");
40
41 if (auto caller_applet = m_applet->caller_applet.lock(); caller_applet != nullptr) {
42 *out_aruid = caller_applet->aruid;
43 } else {
44 *out_aruid = AppletResourceUserId{};
45 }
46
47 R_SUCCEED();
48}
49
50Result IWindowController::AcquireForegroundRights() {
51 LOG_INFO(Service_AM, "called");
52 R_SUCCEED();
53}
54
55Result IWindowController::ReleaseForegroundRights() {
56 LOG_INFO(Service_AM, "called");
57 R_SUCCEED();
58}
59
60Result IWindowController::RejectToChangeIntoBackground() {
61 LOG_INFO(Service_AM, "called");
62 R_SUCCEED();
63}
64
65Result IWindowController::SetAppletWindowVisibility(bool visible) {
66 m_applet->system_buffer_manager.SetWindowVisibility(visible);
67 m_applet->hid_registration.EnableAppletToGetInput(visible);
68
69 if (visible) {
70 m_applet->message_queue.PushMessage(AppletMessage::ChangeIntoForeground);
71 m_applet->focus_state = FocusState::InFocus;
72 } else {
73 m_applet->focus_state = FocusState::NotInFocus;
74 }
75
76 m_applet->message_queue.PushMessage(AppletMessage::FocusStateChanged);
77
78 R_SUCCEED();
79}
80
81Result IWindowController::SetAppletGpuTimeSlice(s64 time_slice) {
82 LOG_WARNING(Service_AM, "(STUBBED) called, time_slice={}", time_slice);
83 R_SUCCEED();
84}
85
86} // namespace Service::AM
diff --git a/src/core/hle/service/am/service/window_controller.h b/src/core/hle/service/am/service/window_controller.h
new file mode 100755
index 000000000..bfbad9bcc
--- /dev/null
+++ b/src/core/hle/service/am/service/window_controller.h
@@ -0,0 +1,30 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/service.h"
8
9namespace Service::AM {
10
11struct Applet;
12
13class IWindowController final : public ServiceFramework<IWindowController> {
14public:
15 explicit IWindowController(Core::System& system_, std::shared_ptr<Applet> applet);
16 ~IWindowController() override;
17
18private:
19 Result GetAppletResourceUserId(Out<AppletResourceUserId> out_aruid);
20 Result GetAppletResourceUserIdOfCallerApplet(Out<AppletResourceUserId> out_aruid);
21 Result AcquireForegroundRights();
22 Result ReleaseForegroundRights();
23 Result RejectToChangeIntoBackground();
24 Result SetAppletWindowVisibility(bool visible);
25 Result SetAppletGpuTimeSlice(s64 time_slice);
26
27 const std::shared_ptr<Applet> m_applet;
28};
29
30} // namespace Service::AM
diff --git a/src/core/hle/service/ldn/lan_discovery.cpp b/src/core/hle/service/ldn/lan_discovery.cpp
index 478557dda..74c6942a4 100755
--- a/src/core/hle/service/ldn/lan_discovery.cpp
+++ b/src/core/hle/service/ldn/lan_discovery.cpp
@@ -85,15 +85,14 @@ Result LANDiscovery::GetNetworkInfo(NetworkInfo& out_network) const {
85} 85}
86 86
87Result LANDiscovery::GetNetworkInfo(NetworkInfo& out_network, 87Result LANDiscovery::GetNetworkInfo(NetworkInfo& out_network,
88 std::vector<NodeLatestUpdate>& out_updates, 88 std::span<NodeLatestUpdate> out_updates) {
89 std::size_t buffer_count) { 89 if (out_updates.size() > NodeCountMax) {
90 if (buffer_count > NodeCountMax) {
91 return ResultInvalidBufferCount; 90 return ResultInvalidBufferCount;
92 } 91 }
93 92
94 if (state == State::AccessPointCreated || state == State::StationConnected) { 93 if (state == State::AccessPointCreated || state == State::StationConnected) {
95 std::memcpy(&out_network, &network_info, sizeof(network_info)); 94 std::memcpy(&out_network, &network_info, sizeof(network_info));
96 for (std::size_t i = 0; i < buffer_count; i++) { 95 for (std::size_t i = 0; i < out_updates.size(); i++) {
97 out_updates[i].state_change = node_changes[i].state_change; 96 out_updates[i].state_change = node_changes[i].state_change;
98 node_changes[i].state_change = NodeStateChange::None; 97 node_changes[i].state_change = NodeStateChange::None;
99 } 98 }
@@ -107,15 +106,8 @@ DisconnectReason LANDiscovery::GetDisconnectReason() const {
107 return disconnect_reason; 106 return disconnect_reason;
108} 107}
109 108
110Result LANDiscovery::Scan(std::vector<NetworkInfo>& networks, u16& count, 109Result LANDiscovery::Scan(std::span<NetworkInfo> out_networks, s16& out_count,
111 const ScanFilter& filter) { 110 const ScanFilter& filter) {
112 if (!IsFlagSet(filter.flag, ScanFilterFlag::NetworkType) ||
113 filter.network_type <= NetworkType::All) {
114 if (!IsFlagSet(filter.flag, ScanFilterFlag::Ssid) && filter.ssid.length >= SsidLengthMax) {
115 return ResultBadInput;
116 }
117 }
118
119 { 111 {
120 std::scoped_lock lock{packet_mutex}; 112 std::scoped_lock lock{packet_mutex};
121 scan_results.clear(); 113 scan_results.clear();
@@ -128,7 +120,7 @@ Result LANDiscovery::Scan(std::vector<NetworkInfo>& networks, u16& count,
128 120
129 std::scoped_lock lock{packet_mutex}; 121 std::scoped_lock lock{packet_mutex};
130 for (const auto& [key, info] : scan_results) { 122 for (const auto& [key, info] : scan_results) {
131 if (count >= networks.size()) { 123 if (out_count >= static_cast<s16>(out_networks.size())) {
132 break; 124 break;
133 } 125 }
134 126
@@ -159,7 +151,7 @@ Result LANDiscovery::Scan(std::vector<NetworkInfo>& networks, u16& count,
159 } 151 }
160 } 152 }
161 153
162 networks[count++] = info; 154 out_networks[out_count++] = info;
163 } 155 }
164 156
165 return ResultSuccess; 157 return ResultSuccess;
diff --git a/src/core/hle/service/ldn/lan_discovery.h b/src/core/hle/service/ldn/lan_discovery.h
index d2860d6a8..8fd54e8b8 100755
--- a/src/core/hle/service/ldn/lan_discovery.h
+++ b/src/core/hle/service/ldn/lan_discovery.h
@@ -54,11 +54,10 @@ public:
54 void SetState(State new_state); 54 void SetState(State new_state);
55 55
56 Result GetNetworkInfo(NetworkInfo& out_network) const; 56 Result GetNetworkInfo(NetworkInfo& out_network) const;
57 Result GetNetworkInfo(NetworkInfo& out_network, std::vector<NodeLatestUpdate>& out_updates, 57 Result GetNetworkInfo(NetworkInfo& out_network, std::span<NodeLatestUpdate> out_updates);
58 std::size_t buffer_count);
59 58
60 DisconnectReason GetDisconnectReason() const; 59 DisconnectReason GetDisconnectReason() const;
61 Result Scan(std::vector<NetworkInfo>& networks, u16& count, const ScanFilter& filter); 60 Result Scan(std::span<NetworkInfo> out_networks, s16& out_count, const ScanFilter& filter);
62 Result SetAdvertiseData(std::span<const u8> data); 61 Result SetAdvertiseData(std::span<const u8> data);
63 62
64 Result OpenAccessPoint(); 63 Result OpenAccessPoint();
diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp
index c3ba38e72..3f1881119 100755
--- a/src/core/hle/service/ldn/ldn.cpp
+++ b/src/core/hle/service/ldn/ldn.cpp
@@ -1,36 +1,24 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <memory>
5
6#include "core/core.h" 4#include "core/core.h"
7#include "core/hle/service/ldn/lan_discovery.h" 5#include "core/hle/service/cmif_serialization.h"
8#include "core/hle/service/ldn/ldn.h" 6#include "core/hle/service/ldn/ldn.h"
9#include "core/hle/service/ldn/ldn_results.h" 7#include "core/hle/service/ldn/monitor_service.h"
10#include "core/hle/service/ldn/ldn_types.h" 8#include "core/hle/service/ldn/sf_monitor_service.h"
11#include "core/hle/service/server_manager.h" 9#include "core/hle/service/ldn/sf_service.h"
12#include "core/internal_network/network.h" 10#include "core/hle/service/ldn/sf_service_monitor.h"
13#include "core/internal_network/network_interface.h" 11#include "core/hle/service/ldn/system_local_communication_service.h"
14#include "network/network.h" 12#include "core/hle/service/ldn/user_local_communication_service.h"
15
16// This is defined by synchapi.h and conflicts with ServiceContext::CreateEvent
17#undef CreateEvent
18 13
19namespace Service::LDN { 14namespace Service::LDN {
20 15
21class IMonitorService final : public ServiceFramework<IMonitorService> { 16class IMonitorServiceCreator final : public ServiceFramework<IMonitorServiceCreator> {
22public: 17public:
23 explicit IMonitorService(Core::System& system_) : ServiceFramework{system_, "IMonitorService"} { 18 explicit IMonitorServiceCreator(Core::System& system_) : ServiceFramework{system_, "ldn:m"} {
24 // clang-format off 19 // clang-format off
25 static const FunctionInfo functions[] = { 20 static const FunctionInfo functions[] = {
26 {0, &IMonitorService::GetStateForMonitor, "GetStateForMonitor"}, 21 {0, C<&IMonitorServiceCreator::CreateMonitorService>, "CreateMonitorService"}
27 {1, nullptr, "GetNetworkInfoForMonitor"},
28 {2, nullptr, "GetIpv4AddressForMonitor"},
29 {3, nullptr, "GetDisconnectReasonForMonitor"},
30 {4, nullptr, "GetSecurityParameterForMonitor"},
31 {5, nullptr, "GetNetworkConfigForMonitor"},
32 {100, &IMonitorService::InitializeMonitor, "InitializeMonitor"},
33 {101, nullptr, "FinalizeMonitor"},
34 }; 22 };
35 // clang-format on 23 // clang-format on
36 24
@@ -38,84 +26,20 @@ public:
38 } 26 }
39 27
40private: 28private:
41 void GetStateForMonitor(HLERequestContext& ctx) { 29 Result CreateMonitorService(OutInterface<IMonitorService> out_interface) {
42 LOG_INFO(Service_LDN, "called");
43
44 IPC::ResponseBuilder rb{ctx, 3};
45 rb.Push(ResultSuccess);
46 rb.PushEnum(state);
47 }
48
49 void InitializeMonitor(HLERequestContext& ctx) {
50 LOG_INFO(Service_LDN, "called");
51
52 state = State::Initialized;
53
54 IPC::ResponseBuilder rb{ctx, 2};
55 rb.Push(ResultSuccess);
56 }
57
58 State state{State::None};
59};
60
61class LDNM final : public ServiceFramework<LDNM> {
62public:
63 explicit LDNM(Core::System& system_) : ServiceFramework{system_, "ldn:m"} {
64 // clang-format off
65 static const FunctionInfo functions[] = {
66 {0, &LDNM::CreateMonitorService, "CreateMonitorService"}
67 };
68 // clang-format on
69
70 RegisterHandlers(functions);
71 }
72
73 void CreateMonitorService(HLERequestContext& ctx) {
74 LOG_DEBUG(Service_LDN, "called"); 30 LOG_DEBUG(Service_LDN, "called");
75 31
76 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 32 *out_interface = std::make_shared<IMonitorService>(system);
77 rb.Push(ResultSuccess); 33 R_SUCCEED();
78 rb.PushIpcInterface<IMonitorService>(system);
79 } 34 }
80}; 35};
81 36
82class ISystemLocalCommunicationService final 37class ISystemServiceCreator final : public ServiceFramework<ISystemServiceCreator> {
83 : public ServiceFramework<ISystemLocalCommunicationService> {
84public: 38public:
85 explicit ISystemLocalCommunicationService(Core::System& system_) 39 explicit ISystemServiceCreator(Core::System& system_) : ServiceFramework{system_, "ldn:s"} {
86 : ServiceFramework{system_, "ISystemLocalCommunicationService"} {
87 // clang-format off 40 // clang-format off
88 static const FunctionInfo functions[] = { 41 static const FunctionInfo functions[] = {
89 {0, nullptr, "GetState"}, 42 {0, C<&ISystemServiceCreator::CreateSystemLocalCommunicationService>, "CreateSystemLocalCommunicationService"},
90 {1, nullptr, "GetNetworkInfo"},
91 {2, nullptr, "GetIpv4Address"},
92 {3, nullptr, "GetDisconnectReason"},
93 {4, nullptr, "GetSecurityParameter"},
94 {5, nullptr, "GetNetworkConfig"},
95 {100, nullptr, "AttachStateChangeEvent"},
96 {101, nullptr, "GetNetworkInfoLatestUpdate"},
97 {102, nullptr, "Scan"},
98 {103, nullptr, "ScanPrivate"},
99 {104, nullptr, "SetWirelessControllerRestriction"},
100 {200, nullptr, "OpenAccessPoint"},
101 {201, nullptr, "CloseAccessPoint"},
102 {202, nullptr, "CreateNetwork"},
103 {203, nullptr, "CreateNetworkPrivate"},
104 {204, nullptr, "DestroyNetwork"},
105 {205, nullptr, "Reject"},
106 {206, nullptr, "SetAdvertiseData"},
107 {207, nullptr, "SetStationAcceptPolicy"},
108 {208, nullptr, "AddAcceptFilterEntry"},
109 {209, nullptr, "ClearAcceptFilter"},
110 {300, nullptr, "OpenStation"},
111 {301, nullptr, "CloseStation"},
112 {302, nullptr, "Connect"},
113 {303, nullptr, "ConnectPrivate"},
114 {304, nullptr, "Disconnect"},
115 {400, nullptr, "InitializeSystem"},
116 {401, nullptr, "FinalizeSystem"},
117 {402, nullptr, "SetOperationMode"},
118 {403, &ISystemLocalCommunicationService::InitializeSystem2, "InitializeSystem2"},
119 }; 43 };
120 // clang-format on 44 // clang-format on
121 45
@@ -123,687 +47,78 @@ public:
123 } 47 }
124 48
125private: 49private:
126 void InitializeSystem2(HLERequestContext& ctx) { 50 Result CreateSystemLocalCommunicationService(
127 LOG_WARNING(Service_LDN, "(STUBBED) called"); 51 OutInterface<ISystemLocalCommunicationService> out_interface) {
128
129 IPC::ResponseBuilder rb{ctx, 2};
130 rb.Push(ResultSuccess);
131 }
132};
133
134class IUserLocalCommunicationService final
135 : public ServiceFramework<IUserLocalCommunicationService> {
136public:
137 explicit IUserLocalCommunicationService(Core::System& system_)
138 : ServiceFramework{system_, "IUserLocalCommunicationService"},
139 service_context{system, "IUserLocalCommunicationService"},
140 room_network{system_.GetRoomNetwork()}, lan_discovery{room_network} {
141 // clang-format off
142 static const FunctionInfo functions[] = {
143 {0, &IUserLocalCommunicationService::GetState, "GetState"},
144 {1, &IUserLocalCommunicationService::GetNetworkInfo, "GetNetworkInfo"},
145 {2, &IUserLocalCommunicationService::GetIpv4Address, "GetIpv4Address"},
146 {3, &IUserLocalCommunicationService::GetDisconnectReason, "GetDisconnectReason"},
147 {4, &IUserLocalCommunicationService::GetSecurityParameter, "GetSecurityParameter"},
148 {5, &IUserLocalCommunicationService::GetNetworkConfig, "GetNetworkConfig"},
149 {100, &IUserLocalCommunicationService::AttachStateChangeEvent, "AttachStateChangeEvent"},
150 {101, &IUserLocalCommunicationService::GetNetworkInfoLatestUpdate, "GetNetworkInfoLatestUpdate"},
151 {102, &IUserLocalCommunicationService::Scan, "Scan"},
152 {103, &IUserLocalCommunicationService::ScanPrivate, "ScanPrivate"},
153 {104, &IUserLocalCommunicationService::SetWirelessControllerRestriction, "SetWirelessControllerRestriction"},
154 {200, &IUserLocalCommunicationService::OpenAccessPoint, "OpenAccessPoint"},
155 {201, &IUserLocalCommunicationService::CloseAccessPoint, "CloseAccessPoint"},
156 {202, &IUserLocalCommunicationService::CreateNetwork, "CreateNetwork"},
157 {203, &IUserLocalCommunicationService::CreateNetworkPrivate, "CreateNetworkPrivate"},
158 {204, &IUserLocalCommunicationService::DestroyNetwork, "DestroyNetwork"},
159 {205, nullptr, "Reject"},
160 {206, &IUserLocalCommunicationService::SetAdvertiseData, "SetAdvertiseData"},
161 {207, &IUserLocalCommunicationService::SetStationAcceptPolicy, "SetStationAcceptPolicy"},
162 {208, &IUserLocalCommunicationService::AddAcceptFilterEntry, "AddAcceptFilterEntry"},
163 {209, nullptr, "ClearAcceptFilter"},
164 {300, &IUserLocalCommunicationService::OpenStation, "OpenStation"},
165 {301, &IUserLocalCommunicationService::CloseStation, "CloseStation"},
166 {302, &IUserLocalCommunicationService::Connect, "Connect"},
167 {303, nullptr, "ConnectPrivate"},
168 {304, &IUserLocalCommunicationService::Disconnect, "Disconnect"},
169 {400, &IUserLocalCommunicationService::Initialize, "Initialize"},
170 {401, &IUserLocalCommunicationService::Finalize, "Finalize"},
171 {402, &IUserLocalCommunicationService::Initialize2, "Initialize2"},
172 };
173 // clang-format on
174
175 RegisterHandlers(functions);
176
177 state_change_event =
178 service_context.CreateEvent("IUserLocalCommunicationService:StateChangeEvent");
179 }
180
181 ~IUserLocalCommunicationService() {
182 if (is_initialized) {
183 if (auto room_member = room_network.GetRoomMember().lock()) {
184 room_member->Unbind(ldn_packet_received);
185 }
186 }
187
188 service_context.CloseEvent(state_change_event);
189 }
190
191 /// Callback to parse and handle a received LDN packet.
192 void OnLDNPacketReceived(const Network::LDNPacket& packet) {
193 lan_discovery.ReceivePacket(packet);
194 }
195
196 void OnEventFired() {
197 state_change_event->Signal();
198 }
199
200 void GetState(HLERequestContext& ctx) {
201 State state = State::Error;
202
203 if (is_initialized) {
204 state = lan_discovery.GetState();
205 }
206
207 IPC::ResponseBuilder rb{ctx, 3};
208 rb.Push(ResultSuccess);
209 rb.PushEnum(state);
210 }
211
212 void GetNetworkInfo(HLERequestContext& ctx) {
213 const auto write_buffer_size = ctx.GetWriteBufferSize();
214
215 if (write_buffer_size != sizeof(NetworkInfo)) {
216 LOG_ERROR(Service_LDN, "Invalid buffer size {}", write_buffer_size);
217 IPC::ResponseBuilder rb{ctx, 2};
218 rb.Push(ResultBadInput);
219 return;
220 }
221
222 NetworkInfo network_info{};
223 const auto rc = lan_discovery.GetNetworkInfo(network_info);
224 if (rc.IsError()) {
225 LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
226 IPC::ResponseBuilder rb{ctx, 2};
227 rb.Push(rc);
228 return;
229 }
230
231 ctx.WriteBuffer<NetworkInfo>(network_info);
232 IPC::ResponseBuilder rb{ctx, 2};
233 rb.Push(ResultSuccess);
234 }
235
236 void GetIpv4Address(HLERequestContext& ctx) {
237 const auto network_interface = Network::GetSelectedNetworkInterface();
238
239 if (!network_interface) {
240 LOG_ERROR(Service_LDN, "No network interface available");
241 IPC::ResponseBuilder rb{ctx, 2};
242 rb.Push(ResultNoIpAddress);
243 return;
244 }
245
246 Ipv4Address current_address{Network::TranslateIPv4(network_interface->ip_address)};
247 Ipv4Address subnet_mask{Network::TranslateIPv4(network_interface->subnet_mask)};
248
249 // When we're connected to a room, spoof the hosts IP address
250 if (auto room_member = room_network.GetRoomMember().lock()) {
251 if (room_member->IsConnected()) {
252 current_address = room_member->GetFakeIpAddress();
253 }
254 }
255
256 std::reverse(std::begin(current_address), std::end(current_address)); // ntohl
257 std::reverse(std::begin(subnet_mask), std::end(subnet_mask)); // ntohl
258
259 IPC::ResponseBuilder rb{ctx, 4};
260 rb.Push(ResultSuccess);
261 rb.PushRaw(current_address);
262 rb.PushRaw(subnet_mask);
263 }
264
265 void GetDisconnectReason(HLERequestContext& ctx) {
266 IPC::ResponseBuilder rb{ctx, 3};
267 rb.Push(ResultSuccess);
268 rb.PushEnum(lan_discovery.GetDisconnectReason());
269 }
270
271 void GetSecurityParameter(HLERequestContext& ctx) {
272 SecurityParameter security_parameter{};
273 NetworkInfo info{};
274 const Result rc = lan_discovery.GetNetworkInfo(info);
275
276 if (rc.IsError()) {
277 LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
278 IPC::ResponseBuilder rb{ctx, 2};
279 rb.Push(rc);
280 return;
281 }
282
283 security_parameter.session_id = info.network_id.session_id;
284 std::memcpy(security_parameter.data.data(), info.ldn.security_parameter.data(),
285 sizeof(SecurityParameter::data));
286
287 IPC::ResponseBuilder rb{ctx, 10};
288 rb.Push(rc);
289 rb.PushRaw<SecurityParameter>(security_parameter);
290 }
291
292 void GetNetworkConfig(HLERequestContext& ctx) {
293 NetworkConfig config{};
294 NetworkInfo info{};
295 const Result rc = lan_discovery.GetNetworkInfo(info);
296
297 if (rc.IsError()) {
298 LOG_ERROR(Service_LDN, "NetworkConfig is not valid {}", rc.raw);
299 IPC::ResponseBuilder rb{ctx, 2};
300 rb.Push(rc);
301 return;
302 }
303
304 config.intent_id = info.network_id.intent_id;
305 config.channel = info.common.channel;
306 config.node_count_max = info.ldn.node_count_max;
307 config.local_communication_version = info.ldn.nodes[0].local_communication_version;
308
309 IPC::ResponseBuilder rb{ctx, 10};
310 rb.Push(rc);
311 rb.PushRaw<NetworkConfig>(config);
312 }
313
314 void AttachStateChangeEvent(HLERequestContext& ctx) {
315 LOG_INFO(Service_LDN, "called");
316
317 IPC::ResponseBuilder rb{ctx, 2, 1};
318 rb.Push(ResultSuccess);
319 rb.PushCopyObjects(state_change_event->GetReadableEvent());
320 }
321
322 void GetNetworkInfoLatestUpdate(HLERequestContext& ctx) {
323 const std::size_t network_buffer_size = ctx.GetWriteBufferSize(0);
324 const std::size_t node_buffer_count = ctx.GetWriteBufferNumElements<NodeLatestUpdate>(1);
325
326 if (node_buffer_count == 0 || network_buffer_size != sizeof(NetworkInfo)) {
327 LOG_ERROR(Service_LDN, "Invalid buffer, size = {}, count = {}", network_buffer_size,
328 node_buffer_count);
329 IPC::ResponseBuilder rb{ctx, 2};
330 rb.Push(ResultBadInput);
331 return;
332 }
333
334 NetworkInfo info{};
335 std::vector<NodeLatestUpdate> latest_update(node_buffer_count);
336
337 const auto rc = lan_discovery.GetNetworkInfo(info, latest_update, latest_update.size());
338 if (rc.IsError()) {
339 LOG_ERROR(Service_LDN, "NetworkInfo is not valid {}", rc.raw);
340 IPC::ResponseBuilder rb{ctx, 2};
341 rb.Push(rc);
342 return;
343 }
344
345 ctx.WriteBuffer(info, 0);
346 ctx.WriteBuffer(latest_update, 1);
347
348 IPC::ResponseBuilder rb{ctx, 2};
349 rb.Push(ResultSuccess);
350 }
351
352 void Scan(HLERequestContext& ctx) {
353 ScanImpl(ctx);
354 }
355
356 void ScanPrivate(HLERequestContext& ctx) {
357 ScanImpl(ctx, true);
358 }
359
360 void ScanImpl(HLERequestContext& ctx, bool is_private = false) {
361 IPC::RequestParser rp{ctx};
362 const auto channel{rp.PopEnum<WifiChannel>()};
363 const auto scan_filter{rp.PopRaw<ScanFilter>()};
364
365 const std::size_t network_info_size = ctx.GetWriteBufferNumElements<NetworkInfo>();
366
367 if (network_info_size == 0) {
368 LOG_ERROR(Service_LDN, "Invalid buffer size {}", network_info_size);
369 IPC::ResponseBuilder rb{ctx, 2};
370 rb.Push(ResultBadInput);
371 return;
372 }
373
374 u16 count = 0;
375 std::vector<NetworkInfo> network_infos(network_info_size);
376 Result rc = lan_discovery.Scan(network_infos, count, scan_filter);
377
378 LOG_INFO(Service_LDN,
379 "called, channel={}, filter_scan_flag={}, filter_network_type={}, is_private={}",
380 channel, scan_filter.flag, scan_filter.network_type, is_private);
381
382 ctx.WriteBuffer(network_infos);
383
384 IPC::ResponseBuilder rb{ctx, 3};
385 rb.Push(rc);
386 rb.Push<u32>(count);
387 }
388
389 void SetWirelessControllerRestriction(HLERequestContext& ctx) {
390 LOG_WARNING(Service_LDN, "(STUBBED) called");
391
392 IPC::ResponseBuilder rb{ctx, 2};
393 rb.Push(ResultSuccess);
394 }
395
396 void OpenAccessPoint(HLERequestContext& ctx) {
397 LOG_INFO(Service_LDN, "called");
398
399 IPC::ResponseBuilder rb{ctx, 2};
400 rb.Push(lan_discovery.OpenAccessPoint());
401 }
402
403 void CloseAccessPoint(HLERequestContext& ctx) {
404 LOG_INFO(Service_LDN, "called");
405
406 IPC::ResponseBuilder rb{ctx, 2};
407 rb.Push(lan_discovery.CloseAccessPoint());
408 }
409
410 void CreateNetwork(HLERequestContext& ctx) {
411 LOG_INFO(Service_LDN, "called");
412
413 CreateNetworkImpl(ctx);
414 }
415
416 void CreateNetworkPrivate(HLERequestContext& ctx) {
417 LOG_INFO(Service_LDN, "called");
418
419 CreateNetworkImpl(ctx, true);
420 }
421
422 void CreateNetworkImpl(HLERequestContext& ctx, bool is_private = false) {
423 IPC::RequestParser rp{ctx};
424
425 const auto security_config{rp.PopRaw<SecurityConfig>()};
426 [[maybe_unused]] const auto security_parameter{is_private ? rp.PopRaw<SecurityParameter>()
427 : SecurityParameter{}};
428 const auto user_config{rp.PopRaw<UserConfig>()};
429 rp.Pop<u32>(); // Padding
430 const auto network_Config{rp.PopRaw<NetworkConfig>()};
431
432 IPC::ResponseBuilder rb{ctx, 2};
433 rb.Push(lan_discovery.CreateNetwork(security_config, user_config, network_Config));
434 }
435
436 void DestroyNetwork(HLERequestContext& ctx) {
437 LOG_INFO(Service_LDN, "called");
438
439 IPC::ResponseBuilder rb{ctx, 2};
440 rb.Push(lan_discovery.DestroyNetwork());
441 }
442
443 void SetAdvertiseData(HLERequestContext& ctx) {
444 const auto read_buffer = ctx.ReadBuffer();
445
446 IPC::ResponseBuilder rb{ctx, 2};
447 rb.Push(lan_discovery.SetAdvertiseData(read_buffer));
448 }
449
450 void SetStationAcceptPolicy(HLERequestContext& ctx) {
451 LOG_WARNING(Service_LDN, "(STUBBED) called");
452
453 IPC::ResponseBuilder rb{ctx, 2};
454 rb.Push(ResultSuccess);
455 }
456
457 void AddAcceptFilterEntry(HLERequestContext& ctx) {
458 LOG_WARNING(Service_LDN, "(STUBBED) called");
459
460 IPC::ResponseBuilder rb{ctx, 2};
461 rb.Push(ResultSuccess);
462 }
463
464 void OpenStation(HLERequestContext& ctx) {
465 LOG_INFO(Service_LDN, "called");
466
467 IPC::ResponseBuilder rb{ctx, 2};
468 rb.Push(lan_discovery.OpenStation());
469 }
470
471 void CloseStation(HLERequestContext& ctx) {
472 LOG_INFO(Service_LDN, "called");
473
474 IPC::ResponseBuilder rb{ctx, 2};
475 rb.Push(lan_discovery.CloseStation());
476 }
477
478 void Connect(HLERequestContext& ctx) {
479 IPC::RequestParser rp{ctx};
480 struct Parameters {
481 SecurityConfig security_config;
482 UserConfig user_config;
483 u32 local_communication_version;
484 u32 option;
485 };
486 static_assert(sizeof(Parameters) == 0x7C, "Parameters has incorrect size.");
487
488 const auto parameters{rp.PopRaw<Parameters>()};
489
490 LOG_INFO(Service_LDN,
491 "called, passphrase_size={}, security_mode={}, "
492 "local_communication_version={}",
493 parameters.security_config.passphrase_size,
494 parameters.security_config.security_mode, parameters.local_communication_version);
495
496 const auto read_buffer = ctx.ReadBuffer();
497 if (read_buffer.size() != sizeof(NetworkInfo)) {
498 LOG_ERROR(Frontend, "NetworkInfo doesn't match read_buffer size!");
499 IPC::ResponseBuilder rb{ctx, 2};
500 rb.Push(ResultBadInput);
501 return;
502 }
503
504 NetworkInfo network_info{};
505 std::memcpy(&network_info, read_buffer.data(), read_buffer.size());
506
507 IPC::ResponseBuilder rb{ctx, 2};
508 rb.Push(lan_discovery.Connect(network_info, parameters.user_config,
509 static_cast<u16>(parameters.local_communication_version)));
510 }
511
512 void Disconnect(HLERequestContext& ctx) {
513 LOG_INFO(Service_LDN, "called");
514
515 IPC::ResponseBuilder rb{ctx, 2};
516 rb.Push(lan_discovery.Disconnect());
517 }
518
519 void Initialize(HLERequestContext& ctx) {
520 const auto rc = InitializeImpl(ctx);
521 if (rc.IsError()) {
522 LOG_ERROR(Service_LDN, "Network isn't initialized, rc={}", rc.raw);
523 }
524
525 IPC::ResponseBuilder rb{ctx, 2};
526 rb.Push(rc);
527 }
528
529 void Finalize(HLERequestContext& ctx) {
530 if (auto room_member = room_network.GetRoomMember().lock()) {
531 room_member->Unbind(ldn_packet_received);
532 }
533
534 is_initialized = false;
535
536 IPC::ResponseBuilder rb{ctx, 2};
537 rb.Push(lan_discovery.Finalize());
538 }
539
540 void Initialize2(HLERequestContext& ctx) {
541 const auto rc = InitializeImpl(ctx);
542 if (rc.IsError()) {
543 LOG_ERROR(Service_LDN, "Network isn't initialized, rc={}", rc.raw);
544 }
545
546 IPC::ResponseBuilder rb{ctx, 2};
547 rb.Push(rc);
548 }
549
550 Result InitializeImpl(HLERequestContext& ctx) {
551 const auto network_interface = Network::GetSelectedNetworkInterface();
552 if (!network_interface) {
553 LOG_ERROR(Service_LDN, "No network interface is set");
554 return ResultAirplaneModeEnabled;
555 }
556
557 if (auto room_member = room_network.GetRoomMember().lock()) {
558 ldn_packet_received = room_member->BindOnLdnPacketReceived(
559 [this](const Network::LDNPacket& packet) { OnLDNPacketReceived(packet); });
560 } else {
561 LOG_ERROR(Service_LDN, "Couldn't bind callback!");
562 return ResultAirplaneModeEnabled;
563 }
564
565 lan_discovery.Initialize([&]() { OnEventFired(); });
566 is_initialized = true;
567 return ResultSuccess;
568 }
569
570 KernelHelpers::ServiceContext service_context;
571 Kernel::KEvent* state_change_event;
572 Network::RoomNetwork& room_network;
573 LANDiscovery lan_discovery;
574
575 // Callback identifier for the OnLDNPacketReceived event.
576 Network::RoomMember::CallbackHandle<Network::LDNPacket> ldn_packet_received;
577
578 bool is_initialized{};
579};
580
581class LDNS final : public ServiceFramework<LDNS> {
582public:
583 explicit LDNS(Core::System& system_) : ServiceFramework{system_, "ldn:s"} {
584 // clang-format off
585 static const FunctionInfo functions[] = {
586 {0, &LDNS::CreateSystemLocalCommunicationService, "CreateSystemLocalCommunicationService"},
587 };
588 // clang-format on
589
590 RegisterHandlers(functions);
591 }
592
593 void CreateSystemLocalCommunicationService(HLERequestContext& ctx) {
594 LOG_DEBUG(Service_LDN, "called"); 52 LOG_DEBUG(Service_LDN, "called");
595 53
596 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 54 *out_interface = std::make_shared<ISystemLocalCommunicationService>(system);
597 rb.Push(ResultSuccess); 55 R_SUCCEED();
598 rb.PushIpcInterface<ISystemLocalCommunicationService>(system);
599 } 56 }
600}; 57};
601 58
602class LDNU final : public ServiceFramework<LDNU> { 59class IUserServiceCreator final : public ServiceFramework<IUserServiceCreator> {
603public: 60public:
604 explicit LDNU(Core::System& system_) : ServiceFramework{system_, "ldn:u"} { 61 explicit IUserServiceCreator(Core::System& system_) : ServiceFramework{system_, "ldn:u"} {
605 // clang-format off 62 // clang-format off
606 static const FunctionInfo functions[] = { 63 static const FunctionInfo functions[] = {
607 {0, &LDNU::CreateUserLocalCommunicationService, "CreateUserLocalCommunicationService"}, 64 {0, C<&IUserServiceCreator::CreateUserLocalCommunicationService>, "CreateUserLocalCommunicationService"},
608 }; 65 };
609 // clang-format on 66 // clang-format on
610 67
611 RegisterHandlers(functions); 68 RegisterHandlers(functions);
612 } 69 }
613 70
614 void CreateUserLocalCommunicationService(HLERequestContext& ctx) { 71private:
72 Result CreateUserLocalCommunicationService(
73 OutInterface<IUserLocalCommunicationService> out_interface) {
615 LOG_DEBUG(Service_LDN, "called"); 74 LOG_DEBUG(Service_LDN, "called");
616 75
617 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 76 *out_interface = std::make_shared<IUserLocalCommunicationService>(system);
618 rb.Push(ResultSuccess); 77 R_SUCCEED();
619 rb.PushIpcInterface<IUserLocalCommunicationService>(system);
620 } 78 }
621}; 79};
622 80
623class INetworkService final : public ServiceFramework<INetworkService> { 81class ISfServiceCreator final : public ServiceFramework<ISfServiceCreator> {
624public: 82public:
625 explicit INetworkService(Core::System& system_) : ServiceFramework{system_, "INetworkService"} { 83 explicit ISfServiceCreator(Core::System& system_, bool is_system_, const char* name_)
84 : ServiceFramework{system_, name_}, is_system{is_system_} {
626 // clang-format off 85 // clang-format off
627 static const FunctionInfo functions[] = { 86 static const FunctionInfo functions[] = {
628 {0, nullptr, "Initialize"}, 87 {0, C<&ISfServiceCreator::CreateNetworkService>, "CreateNetworkService"},
629 {256, nullptr, "AttachNetworkInterfaceStateChangeEvent"}, 88 {8, C<&ISfServiceCreator::CreateNetworkServiceMonitor>, "CreateNetworkServiceMonitor"},
630 {264, nullptr, "GetNetworkInterfaceLastError"},
631 {272, nullptr, "GetRole"},
632 {280, nullptr, "GetAdvertiseData"},
633 {288, nullptr, "GetGroupInfo"},
634 {296, nullptr, "GetGroupInfo2"},
635 {304, nullptr, "GetGroupOwner"},
636 {312, nullptr, "GetIpConfig"},
637 {320, nullptr, "GetLinkLevel"},
638 {512, nullptr, "Scan"},
639 {768, nullptr, "CreateGroup"},
640 {776, nullptr, "DestroyGroup"},
641 {784, nullptr, "SetAdvertiseData"},
642 {1536, nullptr, "SendToOtherGroup"},
643 {1544, nullptr, "RecvFromOtherGroup"},
644 {1552, nullptr, "AddAcceptableGroupId"},
645 {1560, nullptr, "ClearAcceptableGroupId"},
646 }; 89 };
647 // clang-format on 90 // clang-format on
648 91
649 RegisterHandlers(functions); 92 RegisterHandlers(functions);
650 } 93 }
651};
652
653class INetworkServiceMonitor final : public ServiceFramework<INetworkServiceMonitor> {
654public:
655 explicit INetworkServiceMonitor(Core::System& system_)
656 : ServiceFramework{system_, "INetworkServiceMonitor"} {
657 // clang-format off
658 static const FunctionInfo functions[] = {
659 {0, &INetworkServiceMonitor::Initialize, "Initialize"},
660 {256, nullptr, "AttachNetworkInterfaceStateChangeEvent"},
661 {264, nullptr, "GetNetworkInterfaceLastError"},
662 {272, nullptr, "GetRole"},
663 {280, nullptr, "GetAdvertiseData"},
664 {281, nullptr, "GetAdvertiseData2"},
665 {288, nullptr, "GetGroupInfo"},
666 {296, nullptr, "GetGroupInfo2"},
667 {304, nullptr, "GetGroupOwner"},
668 {312, nullptr, "GetIpConfig"},
669 {320, nullptr, "GetLinkLevel"},
670 {328, nullptr, "AttachJoinEvent"},
671 {336, nullptr, "GetMembers"},
672 };
673 // clang-format on
674
675 RegisterHandlers(functions);
676 }
677
678 void Initialize(HLERequestContext& ctx) {
679 LOG_WARNING(Service_LDN, "(STUBBED) called");
680
681 IPC::ResponseBuilder rb{ctx, 2};
682 rb.Push(ResultDisabled);
683 }
684};
685
686class LP2PAPP final : public ServiceFramework<LP2PAPP> {
687public:
688 explicit LP2PAPP(Core::System& system_) : ServiceFramework{system_, "lp2p:app"} {
689 // clang-format off
690 static const FunctionInfo functions[] = {
691 {0, &LP2PAPP::CreateMonitorService, "CreateNetworkService"},
692 {8, &LP2PAPP::CreateMonitorService, "CreateNetworkServiceMonitor"},
693 };
694 // clang-format on
695
696 RegisterHandlers(functions);
697 }
698
699 void CreateNetworkervice(HLERequestContext& ctx) {
700 IPC::RequestParser rp{ctx};
701 const u64 reserved_input = rp.Pop<u64>();
702 const u32 input = rp.Pop<u32>();
703
704 LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={} input={}", reserved_input,
705 input);
706
707 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
708 rb.Push(ResultSuccess);
709 rb.PushIpcInterface<INetworkService>(system);
710 }
711
712 void CreateMonitorService(HLERequestContext& ctx) {
713 IPC::RequestParser rp{ctx};
714 const u64 reserved_input = rp.Pop<u64>();
715
716 LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={}", reserved_input);
717
718 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
719 rb.Push(ResultSuccess);
720 rb.PushIpcInterface<INetworkServiceMonitor>(system);
721 }
722};
723
724class LP2PSYS final : public ServiceFramework<LP2PSYS> {
725public:
726 explicit LP2PSYS(Core::System& system_) : ServiceFramework{system_, "lp2p:sys"} {
727 // clang-format off
728 static const FunctionInfo functions[] = {
729 {0, &LP2PSYS::CreateMonitorService, "CreateNetworkService"},
730 {8, &LP2PSYS::CreateMonitorService, "CreateNetworkServiceMonitor"},
731 };
732 // clang-format on
733
734 RegisterHandlers(functions);
735 }
736
737 void CreateNetworkervice(HLERequestContext& ctx) {
738 IPC::RequestParser rp{ctx};
739 const u64 reserved_input = rp.Pop<u64>();
740 const u32 input = rp.Pop<u32>();
741 94
95private:
96 Result CreateNetworkService(OutInterface<ISfService> out_interface, u32 input,
97 u64 reserved_input) {
742 LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={} input={}", reserved_input, 98 LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={} input={}", reserved_input,
743 input); 99 input);
744 100
745 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 101 *out_interface = std::make_shared<ISfService>(system);
746 rb.Push(ResultSuccess); 102 R_SUCCEED();
747 rb.PushIpcInterface<INetworkService>(system);
748 } 103 }
749 104
750 void CreateMonitorService(HLERequestContext& ctx) { 105 Result CreateNetworkServiceMonitor(OutInterface<ISfServiceMonitor> out_interface,
751 IPC::RequestParser rp{ctx}; 106 u64 reserved_input) {
752 const u64 reserved_input = rp.Pop<u64>();
753
754 LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={}", reserved_input); 107 LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={}", reserved_input);
755 108
756 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 109 *out_interface = std::make_shared<ISfServiceMonitor>(system);
757 rb.Push(ResultSuccess); 110 R_SUCCEED();
758 rb.PushIpcInterface<INetworkServiceMonitor>(system);
759 } 111 }
760};
761 112
762class ISfMonitorService final : public ServiceFramework<ISfMonitorService> { 113 bool is_system{};
763public:
764 explicit ISfMonitorService(Core::System& system_)
765 : ServiceFramework{system_, "ISfMonitorService"} {
766 // clang-format off
767 static const FunctionInfo functions[] = {
768 {0, &ISfMonitorService::Initialize, "Initialize"},
769 {288, &ISfMonitorService::GetGroupInfo, "GetGroupInfo"},
770 {320, nullptr, "GetLinkLevel"},
771 };
772 // clang-format on
773
774 RegisterHandlers(functions);
775 }
776
777private:
778 void Initialize(HLERequestContext& ctx) {
779 LOG_WARNING(Service_LDN, "(STUBBED) called");
780
781 IPC::ResponseBuilder rb{ctx, 3};
782 rb.Push(ResultSuccess);
783 rb.Push(0);
784 }
785
786 void GetGroupInfo(HLERequestContext& ctx) {
787 LOG_WARNING(Service_LDN, "(STUBBED) called");
788
789 struct GroupInfo {
790 std::array<u8, 0x200> info;
791 };
792
793 GroupInfo group_info{};
794
795 ctx.WriteBuffer(group_info);
796 IPC::ResponseBuilder rb{ctx, 2};
797 rb.Push(ResultSuccess);
798 }
799}; 114};
800 115
801class LP2PM final : public ServiceFramework<LP2PM> { 116class ISfMonitorServiceCreator final : public ServiceFramework<ISfMonitorServiceCreator> {
802public: 117public:
803 explicit LP2PM(Core::System& system_) : ServiceFramework{system_, "lp2p:m"} { 118 explicit ISfMonitorServiceCreator(Core::System& system_) : ServiceFramework{system_, "lp2p:m"} {
804 // clang-format off 119 // clang-format off
805 static const FunctionInfo functions[] = { 120 static const FunctionInfo functions[] = {
806 {0, &LP2PM::CreateMonitorService, "CreateMonitorService"}, 121 {0, C<&ISfMonitorServiceCreator::CreateMonitorService>, "CreateMonitorService"},
807 }; 122 };
808 // clang-format on 123 // clang-format on
809 124
@@ -811,28 +126,27 @@ public:
811 } 126 }
812 127
813private: 128private:
814 void CreateMonitorService(HLERequestContext& ctx) { 129 Result CreateMonitorService(OutInterface<ISfMonitorService> out_interface, u64 reserved_input) {
815 IPC::RequestParser rp{ctx};
816 const u64 reserved_input = rp.Pop<u64>();
817
818 LOG_INFO(Service_LDN, "called, reserved_input={}", reserved_input); 130 LOG_INFO(Service_LDN, "called, reserved_input={}", reserved_input);
819 131
820 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 132 *out_interface = std::make_shared<ISfMonitorService>(system);
821 rb.Push(ResultSuccess); 133 R_SUCCEED();
822 rb.PushIpcInterface<ISfMonitorService>(system);
823 } 134 }
824}; 135};
825 136
826void LoopProcess(Core::System& system) { 137void LoopProcess(Core::System& system) {
827 auto server_manager = std::make_unique<ServerManager>(system); 138 auto server_manager = std::make_unique<ServerManager>(system);
828 139
829 server_manager->RegisterNamedService("ldn:m", std::make_shared<LDNM>(system)); 140 server_manager->RegisterNamedService("ldn:m", std::make_shared<IMonitorServiceCreator>(system));
830 server_manager->RegisterNamedService("ldn:s", std::make_shared<LDNS>(system)); 141 server_manager->RegisterNamedService("ldn:s", std::make_shared<ISystemServiceCreator>(system));
831 server_manager->RegisterNamedService("ldn:u", std::make_shared<LDNU>(system)); 142 server_manager->RegisterNamedService("ldn:u", std::make_shared<IUserServiceCreator>(system));
832 143
833 server_manager->RegisterNamedService("lp2p:app", std::make_shared<LP2PAPP>(system)); 144 server_manager->RegisterNamedService(
834 server_manager->RegisterNamedService("lp2p:sys", std::make_shared<LP2PSYS>(system)); 145 "lp2p:app", std::make_shared<ISfServiceCreator>(system, false, "lp2p:app"));
835 server_manager->RegisterNamedService("lp2p:m", std::make_shared<LP2PM>(system)); 146 server_manager->RegisterNamedService(
147 "lp2p:sys", std::make_shared<ISfServiceCreator>(system, true, "lp2p:sys"));
148 server_manager->RegisterNamedService("lp2p:m",
149 std::make_shared<ISfMonitorServiceCreator>(system));
836 150
837 ServerManager::RunServer(std::move(server_manager)); 151 ServerManager::RunServer(std::move(server_manager));
838} 152}
diff --git a/src/core/hle/service/ldn/ldn.h b/src/core/hle/service/ldn/ldn.h
index 69439a91c..5303e1482 100755
--- a/src/core/hle/service/ldn/ldn.h
+++ b/src/core/hle/service/ldn/ldn.h
@@ -3,12 +3,6 @@
3 3
4#pragma once 4#pragma once
5 5
6#include "core/hle/kernel/k_event.h"
7#include "core/hle/result.h"
8#include "core/hle/service/ipc_helpers.h"
9#include "core/hle/service/kernel_helpers.h"
10#include "core/hle/service/sm/sm.h"
11
12namespace Core { 6namespace Core {
13class System; 7class System;
14} 8}
diff --git a/src/core/hle/service/ldn/ldn_types.h b/src/core/hle/service/ldn/ldn_types.h
index ddbd51989..047ee3570 100755
--- a/src/core/hle/service/ldn/ldn_types.h
+++ b/src/core/hle/service/ldn/ldn_types.h
@@ -123,6 +123,18 @@ enum class NodeStatus : u8 {
123 Connected, 123 Connected,
124}; 124};
125 125
126enum class WirelessControllerRestriction : u32 {
127 None,
128 Default,
129};
130
131struct ConnectOption {
132 union {
133 u32 raw;
134 };
135};
136static_assert(sizeof(ConnectOption) == 0x4, "ConnectOption is an invalid size");
137
126struct NodeLatestUpdate { 138struct NodeLatestUpdate {
127 NodeStateChange state_change; 139 NodeStateChange state_change;
128 INSERT_PADDING_BYTES(0x7); // Unknown 140 INSERT_PADDING_BYTES(0x7); // Unknown
@@ -139,9 +151,9 @@ static_assert(sizeof(SessionId) == 0x10, "SessionId is an invalid size");
139 151
140struct IntentId { 152struct IntentId {
141 u64 local_communication_id; 153 u64 local_communication_id;
142 INSERT_PADDING_BYTES(0x2); // Reserved 154 INSERT_PADDING_BYTES_NOINIT(0x2); // Reserved
143 u16 scene_id; 155 u16 scene_id;
144 INSERT_PADDING_BYTES(0x4); // Reserved 156 INSERT_PADDING_BYTES_NOINIT(0x4); // Reserved
145}; 157};
146static_assert(sizeof(IntentId) == 0x10, "IntentId is an invalid size"); 158static_assert(sizeof(IntentId) == 0x10, "IntentId is an invalid size");
147 159
@@ -152,13 +164,14 @@ struct NetworkId {
152static_assert(sizeof(NetworkId) == 0x20, "NetworkId is an invalid size"); 164static_assert(sizeof(NetworkId) == 0x20, "NetworkId is an invalid size");
153 165
154struct Ssid { 166struct Ssid {
155 u8 length{}; 167 u8 length;
156 std::array<char, SsidLengthMax + 1> raw{}; 168 std::array<char, SsidLengthMax + 1> raw;
157 169
158 Ssid() = default; 170 Ssid() = default;
159 171
160 constexpr explicit Ssid(std::string_view data) { 172 constexpr explicit Ssid(std::string_view data) {
161 length = static_cast<u8>(std::min(data.size(), SsidLengthMax)); 173 length = static_cast<u8>(std::min(data.size(), SsidLengthMax));
174 raw = {};
162 data.copy(raw.data(), length); 175 data.copy(raw.data(), length);
163 raw[length] = 0; 176 raw[length] = 0;
164 } 177 }
@@ -181,7 +194,7 @@ using Ipv4Address = std::array<u8, 4>;
181static_assert(sizeof(Ipv4Address) == 0x4, "Ipv4Address is an invalid size"); 194static_assert(sizeof(Ipv4Address) == 0x4, "Ipv4Address is an invalid size");
182 195
183struct MacAddress { 196struct MacAddress {
184 std::array<u8, 6> raw{}; 197 std::array<u8, 6> raw;
185 198
186 friend bool operator==(const MacAddress& lhs, const MacAddress& rhs) = default; 199 friend bool operator==(const MacAddress& lhs, const MacAddress& rhs) = default;
187}; 200};
@@ -211,7 +224,7 @@ struct CommonNetworkInfo {
211 WifiChannel channel; 224 WifiChannel channel;
212 LinkLevel link_level; 225 LinkLevel link_level;
213 PackedNetworkType network_type; 226 PackedNetworkType network_type;
214 INSERT_PADDING_BYTES(0x4); 227 INSERT_PADDING_BYTES_NOINIT(0x4);
215}; 228};
216static_assert(sizeof(CommonNetworkInfo) == 0x30, "CommonNetworkInfo is an invalid size"); 229static_assert(sizeof(CommonNetworkInfo) == 0x30, "CommonNetworkInfo is an invalid size");
217 230
@@ -221,9 +234,9 @@ struct NodeInfo {
221 s8 node_id; 234 s8 node_id;
222 u8 is_connected; 235 u8 is_connected;
223 std::array<u8, UserNameBytesMax + 1> user_name; 236 std::array<u8, UserNameBytesMax + 1> user_name;
224 INSERT_PADDING_BYTES(0x1); // Reserved 237 INSERT_PADDING_BYTES_NOINIT(0x1); // Reserved
225 s16 local_communication_version; 238 s16 local_communication_version;
226 INSERT_PADDING_BYTES(0x10); // Reserved 239 INSERT_PADDING_BYTES_NOINIT(0x10); // Reserved
227}; 240};
228static_assert(sizeof(NodeInfo) == 0x40, "NodeInfo is an invalid size"); 241static_assert(sizeof(NodeInfo) == 0x40, "NodeInfo is an invalid size");
229 242
@@ -232,14 +245,14 @@ struct LdnNetworkInfo {
232 SecurityMode security_mode; 245 SecurityMode security_mode;
233 AcceptPolicy station_accept_policy; 246 AcceptPolicy station_accept_policy;
234 u8 has_action_frame; 247 u8 has_action_frame;
235 INSERT_PADDING_BYTES(0x2); // Padding 248 INSERT_PADDING_BYTES_NOINIT(0x2); // Padding
236 u8 node_count_max; 249 u8 node_count_max;
237 u8 node_count; 250 u8 node_count;
238 std::array<NodeInfo, NodeCountMax> nodes; 251 std::array<NodeInfo, NodeCountMax> nodes;
239 INSERT_PADDING_BYTES(0x2); // Reserved 252 INSERT_PADDING_BYTES_NOINIT(0x2); // Reserved
240 u16 advertise_data_size; 253 u16 advertise_data_size;
241 std::array<u8, AdvertiseDataSizeMax> advertise_data; 254 std::array<u8, AdvertiseDataSizeMax> advertise_data;
242 INSERT_PADDING_BYTES(0x8C); // Reserved 255 INSERT_PADDING_BYTES_NOINIT(0x8C); // Reserved
243 u64 random_authentication_id; 256 u64 random_authentication_id;
244}; 257};
245static_assert(sizeof(LdnNetworkInfo) == 0x430, "LdnNetworkInfo is an invalid size"); 258static_assert(sizeof(LdnNetworkInfo) == 0x430, "LdnNetworkInfo is an invalid size");
@@ -250,6 +263,7 @@ struct NetworkInfo {
250 LdnNetworkInfo ldn; 263 LdnNetworkInfo ldn;
251}; 264};
252static_assert(sizeof(NetworkInfo) == 0x480, "NetworkInfo is an invalid size"); 265static_assert(sizeof(NetworkInfo) == 0x480, "NetworkInfo is an invalid size");
266static_assert(std::is_trivial_v<NetworkInfo>, "NetworkInfo type must be trivially copyable.");
253 267
254struct SecurityConfig { 268struct SecurityConfig {
255 SecurityMode security_mode; 269 SecurityMode security_mode;
@@ -303,4 +317,36 @@ struct AddressList {
303}; 317};
304static_assert(sizeof(AddressList) == 0x60, "AddressList is an invalid size"); 318static_assert(sizeof(AddressList) == 0x60, "AddressList is an invalid size");
305 319
320struct GroupInfo {
321 std::array<u8, 0x200> info;
322};
323
324struct CreateNetworkConfig {
325 SecurityConfig security_config;
326 UserConfig user_config;
327 INSERT_PADDING_BYTES(0x4);
328 NetworkConfig network_config;
329};
330static_assert(sizeof(CreateNetworkConfig) == 0x98, "CreateNetworkConfig is an invalid size");
331
332#pragma pack(push, 4)
333struct CreateNetworkConfigPrivate {
334 SecurityConfig security_config;
335 SecurityParameter security_parameter;
336 UserConfig user_config;
337 INSERT_PADDING_BYTES(0x4);
338 NetworkConfig network_config;
339};
340#pragma pack(pop)
341static_assert(sizeof(CreateNetworkConfigPrivate) == 0xB8,
342 "CreateNetworkConfigPrivate is an invalid size");
343
344struct ConnectNetworkData {
345 SecurityConfig security_config;
346 UserConfig user_config;
347 s32 local_communication_version;
348 ConnectOption option;
349};
350static_assert(sizeof(ConnectNetworkData) == 0x7c, "ConnectNetworkData is an invalid size");
351
306} // namespace Service::LDN 352} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/monitor_service.cpp b/src/core/hle/service/ldn/monitor_service.cpp
new file mode 100755
index 000000000..3471f69da
--- /dev/null
+++ b/src/core/hle/service/ldn/monitor_service.cpp
@@ -0,0 +1,43 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "core/hle/service/cmif_serialization.h"
5#include "core/hle/service/ldn/monitor_service.h"
6
7namespace Service::LDN {
8
9IMonitorService::IMonitorService(Core::System& system_)
10 : ServiceFramework{system_, "IMonitorService"} {
11 // clang-format off
12 static const FunctionInfo functions[] = {
13 {0, C<&IMonitorService::GetStateForMonitor>, "GetStateForMonitor"},
14 {1, nullptr, "GetNetworkInfoForMonitor"},
15 {2, nullptr, "GetIpv4AddressForMonitor"},
16 {3, nullptr, "GetDisconnectReasonForMonitor"},
17 {4, nullptr, "GetSecurityParameterForMonitor"},
18 {5, nullptr, "GetNetworkConfigForMonitor"},
19 {100, C<&IMonitorService::InitializeMonitor>, "InitializeMonitor"},
20 {101, nullptr, "FinalizeMonitor"},
21 };
22 // clang-format on
23
24 RegisterHandlers(functions);
25}
26
27IMonitorService::~IMonitorService() = default;
28
29Result IMonitorService::GetStateForMonitor(Out<State> out_state) {
30 LOG_INFO(Service_LDN, "called");
31
32 *out_state = state;
33 R_SUCCEED();
34}
35
36Result IMonitorService::InitializeMonitor() {
37 LOG_INFO(Service_LDN, "called");
38
39 state = State::Initialized;
40 R_SUCCEED();
41}
42
43} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/monitor_service.h b/src/core/hle/service/ldn/monitor_service.h
new file mode 100755
index 000000000..61aacef30
--- /dev/null
+++ b/src/core/hle/service/ldn/monitor_service.h
@@ -0,0 +1,28 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/ldn/ldn_types.h"
8#include "core/hle/service/service.h"
9
10namespace Core {
11class System;
12}
13
14namespace Service::LDN {
15
16class IMonitorService final : public ServiceFramework<IMonitorService> {
17public:
18 explicit IMonitorService(Core::System& system_);
19 ~IMonitorService() override;
20
21private:
22 Result GetStateForMonitor(Out<State> out_state);
23 Result InitializeMonitor();
24
25 State state{State::None};
26};
27
28} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/sf_monitor_service.cpp b/src/core/hle/service/ldn/sf_monitor_service.cpp
new file mode 100755
index 000000000..9e6736ff2
--- /dev/null
+++ b/src/core/hle/service/ldn/sf_monitor_service.cpp
@@ -0,0 +1,40 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "core/hle/service/cmif_serialization.h"
5#include "core/hle/service/ldn/ldn_types.h"
6#include "core/hle/service/ldn/sf_monitor_service.h"
7
8namespace Service::LDN {
9
10ISfMonitorService::ISfMonitorService(Core::System& system_)
11 : ServiceFramework{system_, "ISfMonitorService"} {
12 // clang-format off
13 static const FunctionInfo functions[] = {
14 {0, C<&ISfMonitorService::Initialize>, "Initialize"},
15 {288, C<&ISfMonitorService::GetGroupInfo>, "GetGroupInfo"},
16 {320, nullptr, "GetLinkLevel"},
17 };
18 // clang-format on
19
20 RegisterHandlers(functions);
21}
22
23ISfMonitorService::~ISfMonitorService() = default;
24
25Result ISfMonitorService::Initialize(Out<u32> out_value) {
26 LOG_WARNING(Service_LDN, "(STUBBED) called");
27
28 *out_value = 0;
29 R_SUCCEED();
30}
31
32Result ISfMonitorService::GetGroupInfo(
33 OutLargeData<GroupInfo, BufferAttr_HipcAutoSelect> out_group_info) {
34 LOG_WARNING(Service_LDN, "(STUBBED) called");
35
36 *out_group_info = GroupInfo{};
37 R_SUCCEED();
38}
39
40} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/sf_monitor_service.h b/src/core/hle/service/ldn/sf_monitor_service.h
new file mode 100755
index 000000000..d02115201
--- /dev/null
+++ b/src/core/hle/service/ldn/sf_monitor_service.h
@@ -0,0 +1,26 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/service.h"
8
9namespace Core {
10class System;
11}
12
13namespace Service::LDN {
14struct GroupInfo;
15
16class ISfMonitorService final : public ServiceFramework<ISfMonitorService> {
17public:
18 explicit ISfMonitorService(Core::System& system_);
19 ~ISfMonitorService() override;
20
21private:
22 Result Initialize(Out<u32> out_value);
23 Result GetGroupInfo(OutLargeData<GroupInfo, BufferAttr_HipcAutoSelect> out_group_info);
24};
25
26} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/sf_service.cpp b/src/core/hle/service/ldn/sf_service.cpp
new file mode 100755
index 000000000..61cabe219
--- /dev/null
+++ b/src/core/hle/service/ldn/sf_service.cpp
@@ -0,0 +1,37 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "core/hle/service/ldn/sf_service.h"
5
6namespace Service::LDN {
7
8ISfService::ISfService(Core::System& system_) : ServiceFramework{system_, "ISfService"} {
9 // clang-format off
10 static const FunctionInfo functions[] = {
11 {0, nullptr, "Initialize"},
12 {256, nullptr, "AttachNetworkInterfaceStateChangeEvent"},
13 {264, nullptr, "GetNetworkInterfaceLastError"},
14 {272, nullptr, "GetRole"},
15 {280, nullptr, "GetAdvertiseData"},
16 {288, nullptr, "GetGroupInfo"},
17 {296, nullptr, "GetGroupInfo2"},
18 {304, nullptr, "GetGroupOwner"},
19 {312, nullptr, "GetIpConfig"},
20 {320, nullptr, "GetLinkLevel"},
21 {512, nullptr, "Scan"},
22 {768, nullptr, "CreateGroup"},
23 {776, nullptr, "DestroyGroup"},
24 {784, nullptr, "SetAdvertiseData"},
25 {1536, nullptr, "SendToOtherGroup"},
26 {1544, nullptr, "RecvFromOtherGroup"},
27 {1552, nullptr, "AddAcceptableGroupId"},
28 {1560, nullptr, "ClearAcceptableGroupId"},
29 };
30 // clang-format on
31
32 RegisterHandlers(functions);
33}
34
35ISfService::~ISfService() = default;
36
37} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/sf_service.h b/src/core/hle/service/ldn/sf_service.h
new file mode 100755
index 000000000..05534b567
--- /dev/null
+++ b/src/core/hle/service/ldn/sf_service.h
@@ -0,0 +1,21 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/service.h"
8
9namespace Core {
10class System;
11}
12
13namespace Service::LDN {
14
15class ISfService final : public ServiceFramework<ISfService> {
16public:
17 explicit ISfService(Core::System& system_);
18 ~ISfService() override;
19};
20
21} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/sf_service_monitor.cpp b/src/core/hle/service/ldn/sf_service_monitor.cpp
new file mode 100755
index 000000000..33e3c1d69
--- /dev/null
+++ b/src/core/hle/service/ldn/sf_service_monitor.cpp
@@ -0,0 +1,50 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "core/hle/service/cmif_serialization.h"
5#include "core/hle/service/ldn/ldn_types.h"
6#include "core/hle/service/ldn/sf_service_monitor.h"
7
8namespace Service::LDN {
9
10ISfServiceMonitor::ISfServiceMonitor(Core::System& system_)
11 : ServiceFramework{system_, "ISfServiceMonitor"} {
12 // clang-format off
13 static const FunctionInfo functions[] = {
14 {0, C<&ISfServiceMonitor::Initialize>, "Initialize"},
15 {256, nullptr, "AttachNetworkInterfaceStateChangeEvent"},
16 {264, nullptr, "GetNetworkInterfaceLastError"},
17 {272, nullptr, "GetRole"},
18 {280, nullptr, "GetAdvertiseData"},
19 {281, nullptr, "GetAdvertiseData2"},
20 {288, C<&ISfServiceMonitor::GetGroupInfo>, "GetGroupInfo"},
21 {296, nullptr, "GetGroupInfo2"},
22 {304, nullptr, "GetGroupOwner"},
23 {312, nullptr, "GetIpConfig"},
24 {320, nullptr, "GetLinkLevel"},
25 {328, nullptr, "AttachJoinEvent"},
26 {336, nullptr, "GetMembers"},
27 };
28 // clang-format on
29
30 RegisterHandlers(functions);
31}
32
33ISfServiceMonitor::~ISfServiceMonitor() = default;
34
35Result ISfServiceMonitor::Initialize(Out<u32> out_value) {
36 LOG_WARNING(Service_LDN, "(STUBBED) called");
37
38 *out_value = 0;
39 R_SUCCEED();
40}
41
42Result ISfServiceMonitor::GetGroupInfo(
43 OutLargeData<GroupInfo, BufferAttr_HipcAutoSelect> out_group_info) {
44 LOG_WARNING(Service_LDN, "(STUBBED) called");
45
46 *out_group_info = GroupInfo{};
47 R_SUCCEED();
48}
49
50} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/sf_service_monitor.h b/src/core/hle/service/ldn/sf_service_monitor.h
new file mode 100755
index 000000000..3cfc5005e
--- /dev/null
+++ b/src/core/hle/service/ldn/sf_service_monitor.h
@@ -0,0 +1,26 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/service.h"
8
9namespace Core {
10class System;
11}
12
13namespace Service::LDN {
14struct GroupInfo;
15
16class ISfServiceMonitor final : public ServiceFramework<ISfServiceMonitor> {
17public:
18 explicit ISfServiceMonitor(Core::System& system_);
19 ~ISfServiceMonitor() override;
20
21private:
22 Result Initialize(Out<u32> out_value);
23 Result GetGroupInfo(OutLargeData<GroupInfo, BufferAttr_HipcAutoSelect> out_group_info);
24};
25
26} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/system_local_communication_service.cpp b/src/core/hle/service/ldn/system_local_communication_service.cpp
new file mode 100755
index 000000000..7b52223cd
--- /dev/null
+++ b/src/core/hle/service/ldn/system_local_communication_service.cpp
@@ -0,0 +1,56 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include "core/hle/service/cmif_serialization.h"
5#include "core/hle/service/ldn/system_local_communication_service.h"
6
7namespace Service::LDN {
8
9ISystemLocalCommunicationService::ISystemLocalCommunicationService(Core::System& system_)
10 : ServiceFramework{system_, "ISystemLocalCommunicationService"} {
11 // clang-format off
12 static const FunctionInfo functions[] = {
13 {0, nullptr, "GetState"},
14 {1, nullptr, "GetNetworkInfo"},
15 {2, nullptr, "GetIpv4Address"},
16 {3, nullptr, "GetDisconnectReason"},
17 {4, nullptr, "GetSecurityParameter"},
18 {5, nullptr, "GetNetworkConfig"},
19 {100, nullptr, "AttachStateChangeEvent"},
20 {101, nullptr, "GetNetworkInfoLatestUpdate"},
21 {102, nullptr, "Scan"},
22 {103, nullptr, "ScanPrivate"},
23 {104, nullptr, "SetWirelessControllerRestriction"},
24 {200, nullptr, "OpenAccessPoint"},
25 {201, nullptr, "CloseAccessPoint"},
26 {202, nullptr, "CreateNetwork"},
27 {203, nullptr, "CreateNetworkPrivate"},
28 {204, nullptr, "DestroyNetwork"},
29 {205, nullptr, "Reject"},
30 {206, nullptr, "SetAdvertiseData"},
31 {207, nullptr, "SetStationAcceptPolicy"},
32 {208, nullptr, "AddAcceptFilterEntry"},
33 {209, nullptr, "ClearAcceptFilter"},
34 {300, nullptr, "OpenStation"},
35 {301, nullptr, "CloseStation"},
36 {302, nullptr, "Connect"},
37 {303, nullptr, "ConnectPrivate"},
38 {304, nullptr, "Disconnect"},
39 {400, nullptr, "InitializeSystem"},
40 {401, nullptr, "FinalizeSystem"},
41 {402, nullptr, "SetOperationMode"},
42 {403, C<&ISystemLocalCommunicationService::InitializeSystem2>, "InitializeSystem2"},
43 };
44 // clang-format on
45
46 RegisterHandlers(functions);
47}
48
49ISystemLocalCommunicationService::~ISystemLocalCommunicationService() = default;
50
51Result ISystemLocalCommunicationService::InitializeSystem2() {
52 LOG_WARNING(Service_LDN, "(STUBBED) called");
53 R_SUCCEED();
54}
55
56} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/system_local_communication_service.h b/src/core/hle/service/ldn/system_local_communication_service.h
new file mode 100755
index 000000000..a02b097ea
--- /dev/null
+++ b/src/core/hle/service/ldn/system_local_communication_service.h
@@ -0,0 +1,25 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/service.h"
8
9namespace Core {
10class System;
11}
12
13namespace Service::LDN {
14
15class ISystemLocalCommunicationService final
16 : public ServiceFramework<ISystemLocalCommunicationService> {
17public:
18 explicit ISystemLocalCommunicationService(Core::System& system_);
19 ~ISystemLocalCommunicationService() override;
20
21private:
22 Result InitializeSystem2();
23};
24
25} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/user_local_communication_service.cpp b/src/core/hle/service/ldn/user_local_communication_service.cpp
new file mode 100755
index 000000000..f28368962
--- /dev/null
+++ b/src/core/hle/service/ldn/user_local_communication_service.cpp
@@ -0,0 +1,320 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include <memory>
5
6#include "core/core.h"
7#include "core/hle/kernel/k_event.h"
8#include "core/hle/service/cmif_serialization.h"
9#include "core/hle/service/ldn/ldn_results.h"
10#include "core/hle/service/ldn/ldn_types.h"
11#include "core/hle/service/ldn/user_local_communication_service.h"
12#include "core/hle/service/server_manager.h"
13#include "core/internal_network/network.h"
14#include "core/internal_network/network_interface.h"
15#include "network/network.h"
16
17// This is defined by synchapi.h and conflicts with ServiceContext::CreateEvent
18#undef CreateEvent
19
20namespace Service::LDN {
21
22IUserLocalCommunicationService::IUserLocalCommunicationService(Core::System& system_)
23 : ServiceFramework{system_, "IUserLocalCommunicationService"},
24 service_context{system, "IUserLocalCommunicationService"},
25 room_network{system_.GetRoomNetwork()}, lan_discovery{room_network} {
26 // clang-format off
27 static const FunctionInfo functions[] = {
28 {0, C<&IUserLocalCommunicationService::GetState>, "GetState"},
29 {1, C<&IUserLocalCommunicationService::GetNetworkInfo>, "GetNetworkInfo"},
30 {2, C<&IUserLocalCommunicationService::GetIpv4Address>, "GetIpv4Address"},
31 {3, C<&IUserLocalCommunicationService::GetDisconnectReason>, "GetDisconnectReason"},
32 {4, C<&IUserLocalCommunicationService::GetSecurityParameter>, "GetSecurityParameter"},
33 {5, C<&IUserLocalCommunicationService::GetNetworkConfig>, "GetNetworkConfig"},
34 {100, C<&IUserLocalCommunicationService::AttachStateChangeEvent>, "AttachStateChangeEvent"},
35 {101, C<&IUserLocalCommunicationService::GetNetworkInfoLatestUpdate>, "GetNetworkInfoLatestUpdate"},
36 {102, C<&IUserLocalCommunicationService::Scan>, "Scan"},
37 {103, C<&IUserLocalCommunicationService::ScanPrivate>, "ScanPrivate"},
38 {104, C<&IUserLocalCommunicationService::SetWirelessControllerRestriction>, "SetWirelessControllerRestriction"},
39 {200, C<&IUserLocalCommunicationService::OpenAccessPoint>, "OpenAccessPoint"},
40 {201, C<&IUserLocalCommunicationService::CloseAccessPoint>, "CloseAccessPoint"},
41 {202, C<&IUserLocalCommunicationService::CreateNetwork>, "CreateNetwork"},
42 {203, C<&IUserLocalCommunicationService::CreateNetworkPrivate>, "CreateNetworkPrivate"},
43 {204, C<&IUserLocalCommunicationService::DestroyNetwork>, "DestroyNetwork"},
44 {205, nullptr, "Reject"},
45 {206, C<&IUserLocalCommunicationService::SetAdvertiseData>, "SetAdvertiseData"},
46 {207, C<&IUserLocalCommunicationService::SetStationAcceptPolicy>, "SetStationAcceptPolicy"},
47 {208, C<&IUserLocalCommunicationService::AddAcceptFilterEntry>, "AddAcceptFilterEntry"},
48 {209, nullptr, "ClearAcceptFilter"},
49 {300, C<&IUserLocalCommunicationService::OpenStation>, "OpenStation"},
50 {301, C<&IUserLocalCommunicationService::CloseStation>, "CloseStation"},
51 {302, C<&IUserLocalCommunicationService::Connect>, "Connect"},
52 {303, nullptr, "ConnectPrivate"},
53 {304, C<&IUserLocalCommunicationService::Disconnect>, "Disconnect"},
54 {400, C<&IUserLocalCommunicationService::Initialize>, "Initialize"},
55 {401, C<&IUserLocalCommunicationService::Finalize>, "Finalize"},
56 {402, C<&IUserLocalCommunicationService::Initialize2>, "Initialize2"},
57 };
58 // clang-format on
59
60 RegisterHandlers(functions);
61
62 state_change_event =
63 service_context.CreateEvent("IUserLocalCommunicationService:StateChangeEvent");
64}
65
66IUserLocalCommunicationService::~IUserLocalCommunicationService() {
67 if (is_initialized) {
68 if (auto room_member = room_network.GetRoomMember().lock()) {
69 room_member->Unbind(ldn_packet_received);
70 }
71 }
72
73 service_context.CloseEvent(state_change_event);
74}
75
76Result IUserLocalCommunicationService::GetState(Out<State> out_state) {
77 *out_state = State::Error;
78
79 if (is_initialized) {
80 *out_state = lan_discovery.GetState();
81 }
82
83 LOG_INFO(Service_LDN, "called, state={}", *out_state);
84
85 R_SUCCEED();
86}
87
88Result IUserLocalCommunicationService::GetNetworkInfo(
89 OutLargeData<NetworkInfo, BufferAttr_HipcPointer> out_network_info) {
90 LOG_INFO(Service_LDN, "called");
91
92 R_RETURN(lan_discovery.GetNetworkInfo(*out_network_info));
93}
94
95Result IUserLocalCommunicationService::GetIpv4Address(Out<Ipv4Address> out_current_address,
96 Out<Ipv4Address> out_subnet_mask) {
97 LOG_INFO(Service_LDN, "called");
98 const auto network_interface = Network::GetSelectedNetworkInterface();
99
100 R_UNLESS(network_interface.has_value(), ResultNoIpAddress);
101
102 *out_current_address = {Network::TranslateIPv4(network_interface->ip_address)};
103 *out_subnet_mask = {Network::TranslateIPv4(network_interface->subnet_mask)};
104
105 // When we're connected to a room, spoof the hosts IP address
106 if (auto room_member = room_network.GetRoomMember().lock()) {
107 if (room_member->IsConnected()) {
108 *out_current_address = room_member->GetFakeIpAddress();
109 }
110 }
111
112 std::reverse(std::begin(*out_current_address), std::end(*out_current_address)); // ntohl
113 std::reverse(std::begin(*out_subnet_mask), std::end(*out_subnet_mask)); // ntohl
114 R_SUCCEED();
115}
116
117Result IUserLocalCommunicationService::GetDisconnectReason(
118 Out<DisconnectReason> out_disconnect_reason) {
119 LOG_INFO(Service_LDN, "called");
120
121 *out_disconnect_reason = lan_discovery.GetDisconnectReason();
122 R_SUCCEED();
123}
124
125Result IUserLocalCommunicationService::GetSecurityParameter(
126 Out<SecurityParameter> out_security_parameter) {
127 LOG_INFO(Service_LDN, "called");
128
129 NetworkInfo info{};
130 R_TRY(lan_discovery.GetNetworkInfo(info));
131
132 out_security_parameter->session_id = info.network_id.session_id;
133 std::memcpy(out_security_parameter->data.data(), info.ldn.security_parameter.data(),
134 sizeof(SecurityParameter::data));
135 R_SUCCEED();
136}
137
138Result IUserLocalCommunicationService::GetNetworkConfig(Out<NetworkConfig> out_network_config) {
139 LOG_INFO(Service_LDN, "called");
140
141 NetworkInfo info{};
142 R_TRY(lan_discovery.GetNetworkInfo(info));
143
144 out_network_config->intent_id = info.network_id.intent_id;
145 out_network_config->channel = info.common.channel;
146 out_network_config->node_count_max = info.ldn.node_count_max;
147 out_network_config->local_communication_version = info.ldn.nodes[0].local_communication_version;
148 R_SUCCEED();
149}
150
151Result IUserLocalCommunicationService::AttachStateChangeEvent(
152 OutCopyHandle<Kernel::KReadableEvent> out_event) {
153 LOG_INFO(Service_LDN, "called");
154
155 *out_event = &state_change_event->GetReadableEvent();
156 R_SUCCEED();
157}
158
159Result IUserLocalCommunicationService::GetNetworkInfoLatestUpdate(
160 OutLargeData<NetworkInfo, BufferAttr_HipcPointer> out_network_info,
161 OutArray<NodeLatestUpdate, BufferAttr_HipcPointer> out_node_latest_update) {
162 LOG_INFO(Service_LDN, "called");
163
164 R_UNLESS(!out_node_latest_update.empty(), ResultBadInput);
165
166 R_RETURN(lan_discovery.GetNetworkInfo(*out_network_info, out_node_latest_update));
167}
168
169Result IUserLocalCommunicationService::Scan(
170 Out<s16> network_count, WifiChannel channel, const ScanFilter& scan_filter,
171 OutArray<NetworkInfo, BufferAttr_HipcAutoSelect> out_network_info) {
172 LOG_INFO(Service_LDN, "called, channel={}, filter_scan_flag={}, filter_network_type={}",
173 channel, scan_filter.flag, scan_filter.network_type);
174
175 R_UNLESS(!out_network_info.empty(), ResultBadInput);
176 R_RETURN(lan_discovery.Scan(out_network_info, *network_count, scan_filter));
177}
178
179Result IUserLocalCommunicationService::ScanPrivate(
180 Out<s16> network_count, WifiChannel channel, const ScanFilter& scan_filter,
181 OutArray<NetworkInfo, BufferAttr_HipcAutoSelect> out_network_info) {
182 LOG_INFO(Service_LDN, "called, channel={}, filter_scan_flag={}, filter_network_type={}",
183 channel, scan_filter.flag, scan_filter.network_type);
184
185 R_UNLESS(out_network_info.empty(), ResultBadInput);
186 R_RETURN(lan_discovery.Scan(out_network_info, *network_count, scan_filter));
187}
188
189Result IUserLocalCommunicationService::SetWirelessControllerRestriction(
190 WirelessControllerRestriction wireless_restriction) {
191 LOG_WARNING(Service_LDN, "(STUBBED) called");
192 R_SUCCEED();
193}
194
195Result IUserLocalCommunicationService::OpenAccessPoint() {
196 LOG_INFO(Service_LDN, "called");
197
198 R_RETURN(lan_discovery.OpenAccessPoint());
199}
200
201Result IUserLocalCommunicationService::CloseAccessPoint() {
202 LOG_INFO(Service_LDN, "called");
203
204 R_RETURN(lan_discovery.CloseAccessPoint());
205}
206
207Result IUserLocalCommunicationService::CreateNetwork(const CreateNetworkConfig& create_config) {
208 LOG_INFO(Service_LDN, "called");
209
210 R_RETURN(lan_discovery.CreateNetwork(create_config.security_config, create_config.user_config,
211 create_config.network_config));
212}
213
214Result IUserLocalCommunicationService::CreateNetworkPrivate(
215 const CreateNetworkConfigPrivate& create_config,
216 InArray<AddressEntry, BufferAttr_HipcPointer> address_list) {
217 LOG_INFO(Service_LDN, "called");
218
219 R_RETURN(lan_discovery.CreateNetwork(create_config.security_config, create_config.user_config,
220 create_config.network_config));
221}
222
223Result IUserLocalCommunicationService::DestroyNetwork() {
224 LOG_INFO(Service_LDN, "called");
225
226 R_RETURN(lan_discovery.DestroyNetwork());
227}
228
229Result IUserLocalCommunicationService::SetAdvertiseData(
230 InBuffer<BufferAttr_HipcAutoSelect> buffer_data) {
231 LOG_INFO(Service_LDN, "called");
232
233 R_RETURN(lan_discovery.SetAdvertiseData(buffer_data));
234}
235
236Result IUserLocalCommunicationService::SetStationAcceptPolicy(AcceptPolicy accept_policy) {
237 LOG_WARNING(Service_LDN, "(STUBBED) called");
238 R_SUCCEED();
239}
240
241Result IUserLocalCommunicationService::AddAcceptFilterEntry(MacAddress mac_address) {
242 LOG_WARNING(Service_LDN, "(STUBBED) called");
243 R_SUCCEED();
244}
245
246Result IUserLocalCommunicationService::OpenStation() {
247 LOG_INFO(Service_LDN, "called");
248
249 R_RETURN(lan_discovery.OpenStation());
250}
251
252Result IUserLocalCommunicationService::CloseStation() {
253 LOG_INFO(Service_LDN, "called");
254
255 R_RETURN(lan_discovery.CloseStation());
256}
257
258Result IUserLocalCommunicationService::Connect(
259 const ConnectNetworkData& connect_data,
260 InLargeData<NetworkInfo, BufferAttr_HipcPointer> network_info) {
261 LOG_INFO(Service_LDN,
262 "called, passphrase_size={}, security_mode={}, "
263 "local_communication_version={}",
264 connect_data.security_config.passphrase_size,
265 connect_data.security_config.security_mode, connect_data.local_communication_version);
266
267 R_RETURN(lan_discovery.Connect(*network_info, connect_data.user_config,
268 static_cast<u16>(connect_data.local_communication_version)));
269}
270
271Result IUserLocalCommunicationService::Disconnect() {
272 LOG_INFO(Service_LDN, "called");
273
274 R_RETURN(lan_discovery.Disconnect());
275}
276
277Result IUserLocalCommunicationService::Initialize(ClientProcessId aruid) {
278 LOG_INFO(Service_LDN, "called, process_id={}", aruid.pid);
279
280 const auto network_interface = Network::GetSelectedNetworkInterface();
281 R_UNLESS(network_interface, ResultAirplaneModeEnabled);
282
283 if (auto room_member = room_network.GetRoomMember().lock()) {
284 ldn_packet_received = room_member->BindOnLdnPacketReceived(
285 [this](const Network::LDNPacket& packet) { OnLDNPacketReceived(packet); });
286 } else {
287 LOG_ERROR(Service_LDN, "Couldn't bind callback!");
288 R_RETURN(ResultAirplaneModeEnabled);
289 }
290
291 lan_discovery.Initialize([&]() { OnEventFired(); });
292 is_initialized = true;
293 R_SUCCEED();
294}
295
296Result IUserLocalCommunicationService::Finalize() {
297 LOG_INFO(Service_LDN, "called");
298 if (auto room_member = room_network.GetRoomMember().lock()) {
299 room_member->Unbind(ldn_packet_received);
300 }
301
302 is_initialized = false;
303
304 R_RETURN(lan_discovery.Finalize());
305}
306
307Result IUserLocalCommunicationService::Initialize2(u32 version, ClientProcessId process_id) {
308 LOG_INFO(Service_LDN, "called, version={}, process_id={}", version, process_id.pid);
309 R_RETURN(Initialize(process_id));
310}
311
312void IUserLocalCommunicationService::OnLDNPacketReceived(const Network::LDNPacket& packet) {
313 lan_discovery.ReceivePacket(packet);
314}
315
316void IUserLocalCommunicationService::OnEventFired() {
317 state_change_event->Signal();
318}
319
320} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/user_local_communication_service.h b/src/core/hle/service/ldn/user_local_communication_service.h
new file mode 100755
index 000000000..6698d10d2
--- /dev/null
+++ b/src/core/hle/service/ldn/user_local_communication_service.h
@@ -0,0 +1,103 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "core/hle/service/cmif_types.h"
7#include "core/hle/service/kernel_helpers.h"
8#include "core/hle/service/ldn/lan_discovery.h"
9#include "core/hle/service/ldn/ldn_types.h"
10#include "core/hle/service/service.h"
11
12namespace Core {
13class System;
14}
15
16namespace Network {
17class RoomNetwork;
18}
19
20namespace Service::LDN {
21
22class IUserLocalCommunicationService final
23 : public ServiceFramework<IUserLocalCommunicationService> {
24public:
25 explicit IUserLocalCommunicationService(Core::System& system_);
26 ~IUserLocalCommunicationService() override;
27
28private:
29 Result GetState(Out<State> out_state);
30
31 Result GetNetworkInfo(OutLargeData<NetworkInfo, BufferAttr_HipcPointer> out_network_info);
32
33 Result GetIpv4Address(Out<Ipv4Address> out_current_address, Out<Ipv4Address> out_subnet_mask);
34
35 Result GetDisconnectReason(Out<DisconnectReason> out_disconnect_reason);
36
37 Result GetSecurityParameter(Out<SecurityParameter> out_security_parameter);
38
39 Result GetNetworkConfig(Out<NetworkConfig> out_network_config);
40
41 Result AttachStateChangeEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
42
43 Result GetNetworkInfoLatestUpdate(
44 OutLargeData<NetworkInfo, BufferAttr_HipcPointer> out_network_info,
45 OutArray<NodeLatestUpdate, BufferAttr_HipcPointer> out_node_latest_update);
46
47 Result Scan(Out<s16> network_count, WifiChannel channel, const ScanFilter& scan_filter,
48 OutArray<NetworkInfo, BufferAttr_HipcAutoSelect> out_network_info);
49
50 Result ScanPrivate(Out<s16> network_count, WifiChannel channel, const ScanFilter& scan_filter,
51 OutArray<NetworkInfo, BufferAttr_HipcAutoSelect> out_network_info);
52
53 Result SetWirelessControllerRestriction(WirelessControllerRestriction wireless_restriction);
54
55 Result OpenAccessPoint();
56
57 Result CloseAccessPoint();
58
59 Result CreateNetwork(const CreateNetworkConfig& create_network_Config);
60
61 Result CreateNetworkPrivate(const CreateNetworkConfigPrivate& create_network_Config,
62 InArray<AddressEntry, BufferAttr_HipcPointer> address_list);
63
64 Result DestroyNetwork();
65
66 Result SetAdvertiseData(InBuffer<BufferAttr_HipcAutoSelect> buffer_data);
67
68 Result SetStationAcceptPolicy(AcceptPolicy accept_policy);
69
70 Result AddAcceptFilterEntry(MacAddress mac_address);
71
72 Result OpenStation();
73
74 Result CloseStation();
75
76 Result Connect(const ConnectNetworkData& connect_data,
77 InLargeData<NetworkInfo, BufferAttr_HipcPointer> network_info);
78
79 Result Disconnect();
80
81 Result Initialize(ClientProcessId aruid);
82
83 Result Finalize();
84
85 Result Initialize2(u32 version, ClientProcessId aruid);
86
87private:
88 /// Callback to parse and handle a received LDN packet.
89 void OnLDNPacketReceived(const Network::LDNPacket& packet);
90 void OnEventFired();
91
92 KernelHelpers::ServiceContext service_context;
93 Kernel::KEvent* state_change_event;
94 Network::RoomNetwork& room_network;
95 LANDiscovery lan_discovery;
96
97 // Callback identifier for the OnLDNPacketReceived event.
98 Network::RoomMember::CallbackHandle<Network::LDNPacket> ldn_packet_received;
99
100 bool is_initialized{};
101};
102
103} // namespace Service::LDN
diff --git a/src/core/hle/service/omm/omm.cpp b/src/core/hle/service/omm/omm.cpp
new file mode 100755
index 000000000..b95319e26
--- /dev/null
+++ b/src/core/hle/service/omm/omm.cpp
@@ -0,0 +1,22 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/omm/omm.h"
5#include "core/hle/service/omm/operation_mode_manager.h"
6#include "core/hle/service/omm/policy_manager_system.h"
7#include "core/hle/service/omm/power_state_interface.h"
8#include "core/hle/service/server_manager.h"
9
10namespace Service::OMM {
11
12void LoopProcess(Core::System& system) {
13 auto server_manager = std::make_unique<ServerManager>(system);
14
15 server_manager->RegisterNamedService("idle:sys",
16 std::make_shared<IPolicyManagerSystem>(system));
17 server_manager->RegisterNamedService("omm", std::make_shared<IOperationModeManager>(system));
18 server_manager->RegisterNamedService("spsm", std::make_shared<IPowerStateInterface>(system));
19 ServerManager::RunServer(std::move(server_manager));
20}
21
22} // namespace Service::OMM
diff --git a/src/core/hle/service/omm/omm.h b/src/core/hle/service/omm/omm.h
new file mode 100755
index 000000000..7bf04688a
--- /dev/null
+++ b/src/core/hle/service/omm/omm.h
@@ -0,0 +1,14 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6namespace Core {
7class System;
8}
9
10namespace Service::OMM {
11
12void LoopProcess(Core::System& system);
13
14} // namespace Service::OMM
diff --git a/src/core/hle/service/omm/operation_mode_manager.cpp b/src/core/hle/service/omm/operation_mode_manager.cpp
new file mode 100755
index 000000000..fe7ed84a7
--- /dev/null
+++ b/src/core/hle/service/omm/operation_mode_manager.cpp
@@ -0,0 +1,49 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/omm/operation_mode_manager.h"
5
6namespace Service::OMM {
7
8IOperationModeManager::IOperationModeManager(Core::System& system_)
9 : ServiceFramework{system_, "omm"} {
10 // clang-format off
11 static const FunctionInfo functions[] = {
12 {0, nullptr, "GetOperationMode"},
13 {1, nullptr, "GetOperationModeChangeEvent"},
14 {2, nullptr, "EnableAudioVisual"},
15 {3, nullptr, "DisableAudioVisual"},
16 {4, nullptr, "EnterSleepAndWait"},
17 {5, nullptr, "GetCradleStatus"},
18 {6, nullptr, "FadeInDisplay"},
19 {7, nullptr, "FadeOutDisplay"},
20 {8, nullptr, "GetCradleFwVersion"},
21 {9, nullptr, "NotifyCecSettingsChanged"},
22 {10, nullptr, "SetOperationModePolicy"},
23 {11, nullptr, "GetDefaultDisplayResolution"},
24 {12, nullptr, "GetDefaultDisplayResolutionChangeEvent"},
25 {13, nullptr, "UpdateDefaultDisplayResolution"},
26 {14, nullptr, "ShouldSleepOnBoot"},
27 {15, nullptr, "NotifyHdcpApplicationExecutionStarted"},
28 {16, nullptr, "NotifyHdcpApplicationExecutionFinished"},
29 {17, nullptr, "NotifyHdcpApplicationDrawingStarted"},
30 {18, nullptr, "NotifyHdcpApplicationDrawingFinished"},
31 {19, nullptr, "GetHdcpAuthenticationFailedEvent"},
32 {20, nullptr, "GetHdcpAuthenticationFailedEmulationEnabled"},
33 {21, nullptr, "SetHdcpAuthenticationFailedEmulation"},
34 {22, nullptr, "GetHdcpStateChangeEvent"},
35 {23, nullptr, "GetHdcpState"},
36 {24, nullptr, "ShowCardUpdateProcessing"},
37 {25, nullptr, "SetApplicationCecSettingsAndNotifyChanged"},
38 {26, nullptr, "GetOperationModeSystemInfo"},
39 {27, nullptr, "GetAppletFullAwakingSystemEvent"},
40 {28, nullptr, "CreateCradleFirmwareUpdater"},
41 };
42 // clang-format on
43
44 RegisterHandlers(functions);
45}
46
47IOperationModeManager::~IOperationModeManager() = default;
48
49} // namespace Service::OMM
diff --git a/src/core/hle/service/omm/operation_mode_manager.h b/src/core/hle/service/omm/operation_mode_manager.h
new file mode 100755
index 000000000..32bc7b2f9
--- /dev/null
+++ b/src/core/hle/service/omm/operation_mode_manager.h
@@ -0,0 +1,20 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/service.h"
7
8namespace Core {
9class System;
10}
11
12namespace Service::OMM {
13
14class IOperationModeManager final : public ServiceFramework<IOperationModeManager> {
15public:
16 explicit IOperationModeManager(Core::System& system_);
17 ~IOperationModeManager() override;
18};
19
20} // namespace Service::OMM
diff --git a/src/core/hle/service/omm/policy_manager_system.cpp b/src/core/hle/service/omm/policy_manager_system.cpp
new file mode 100755
index 000000000..1cd6fd807
--- /dev/null
+++ b/src/core/hle/service/omm/policy_manager_system.cpp
@@ -0,0 +1,26 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/omm/policy_manager_system.h"
5
6namespace Service::OMM {
7
8IPolicyManagerSystem::IPolicyManagerSystem(Core::System& system_)
9 : ServiceFramework{system_, "idle:sys"} {
10 // clang-format off
11 static const FunctionInfo functions[] = {
12 {0, nullptr, "GetAutoPowerDownEvent"},
13 {1, nullptr, "IsAutoPowerDownRequested"},
14 {2, nullptr, "Unknown2"},
15 {3, nullptr, "SetHandlingContext"},
16 {4, nullptr, "LoadAndApplySettings"},
17 {5, nullptr, "ReportUserIsActive"},
18 };
19 // clang-format on
20
21 RegisterHandlers(functions);
22}
23
24IPolicyManagerSystem::~IPolicyManagerSystem() = default;
25
26} // namespace Service::OMM
diff --git a/src/core/hle/service/omm/policy_manager_system.h b/src/core/hle/service/omm/policy_manager_system.h
new file mode 100755
index 000000000..151ca0d2e
--- /dev/null
+++ b/src/core/hle/service/omm/policy_manager_system.h
@@ -0,0 +1,20 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/service.h"
7
8namespace Core {
9class System;
10}
11
12namespace Service::OMM {
13
14class IPolicyManagerSystem final : public ServiceFramework<IPolicyManagerSystem> {
15public:
16 explicit IPolicyManagerSystem(Core::System& system_);
17 ~IPolicyManagerSystem() override;
18};
19
20} // namespace Service::OMM
diff --git a/src/core/hle/service/omm/power_state_interface.cpp b/src/core/hle/service/omm/power_state_interface.cpp
new file mode 100755
index 000000000..22cac8259
--- /dev/null
+++ b/src/core/hle/service/omm/power_state_interface.cpp
@@ -0,0 +1,32 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/omm/power_state_interface.h"
5
6namespace Service::OMM {
7
8IPowerStateInterface::IPowerStateInterface(Core::System& system_)
9 : ServiceFramework{system_, "spsm"} {
10 // clang-format off
11 static const FunctionInfo functions[] = {
12 {0, nullptr, "GetState"},
13 {1, nullptr, "EnterSleep"},
14 {2, nullptr, "GetLastWakeReason"},
15 {3, nullptr, "Shutdown"},
16 {4, nullptr, "GetNotificationMessageEventHandle"},
17 {5, nullptr, "ReceiveNotificationMessage"},
18 {6, nullptr, "AnalyzeLogForLastSleepWakeSequence"},
19 {7, nullptr, "ResetEventLog"},
20 {8, nullptr, "AnalyzePerformanceLogForLastSleepWakeSequence"},
21 {9, nullptr, "ChangeHomeButtonLongPressingTime"},
22 {10, nullptr, "PutErrorState"},
23 {11, nullptr, "InvalidateCurrentHomeButtonPressing"},
24 };
25 // clang-format on
26
27 RegisterHandlers(functions);
28}
29
30IPowerStateInterface::~IPowerStateInterface() = default;
31
32} // namespace Service::OMM
diff --git a/src/core/hle/service/omm/power_state_interface.h b/src/core/hle/service/omm/power_state_interface.h
new file mode 100755
index 000000000..825a6512d
--- /dev/null
+++ b/src/core/hle/service/omm/power_state_interface.h
@@ -0,0 +1,20 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/service/service.h"
7
8namespace Core {
9class System;
10}
11
12namespace Service::OMM {
13
14class IPowerStateInterface final : public ServiceFramework<IPowerStateInterface> {
15public:
16 explicit IPowerStateInterface(Core::System& system_);
17 ~IPowerStateInterface() override;
18};
19
20} // namespace Service::OMM
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 87e8eeed8..5a1a286f1 100755
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -52,6 +52,7 @@
52#include "core/hle/service/nvnflinger/hos_binder_driver_server.h" 52#include "core/hle/service/nvnflinger/hos_binder_driver_server.h"
53#include "core/hle/service/nvnflinger/nvnflinger.h" 53#include "core/hle/service/nvnflinger/nvnflinger.h"
54#include "core/hle/service/olsc/olsc.h" 54#include "core/hle/service/olsc/olsc.h"
55#include "core/hle/service/omm/omm.h"
55#include "core/hle/service/pcie/pcie.h" 56#include "core/hle/service/pcie/pcie.h"
56#include "core/hle/service/pctl/pctl_module.h" 57#include "core/hle/service/pctl/pctl_module.h"
57#include "core/hle/service/pcv/pcv.h" 58#include "core/hle/service/pcv/pcv.h"
@@ -266,6 +267,7 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system
266 kernel.RunOnGuestCoreProcess("npns", [&] { NPNS::LoopProcess(system); }); 267 kernel.RunOnGuestCoreProcess("npns", [&] { NPNS::LoopProcess(system); });
267 kernel.RunOnGuestCoreProcess("ns", [&] { NS::LoopProcess(system); }); 268 kernel.RunOnGuestCoreProcess("ns", [&] { NS::LoopProcess(system); });
268 kernel.RunOnGuestCoreProcess("olsc", [&] { OLSC::LoopProcess(system); }); 269 kernel.RunOnGuestCoreProcess("olsc", [&] { OLSC::LoopProcess(system); });
270 kernel.RunOnGuestCoreProcess("omm", [&] { OMM::LoopProcess(system); });
269 kernel.RunOnGuestCoreProcess("pcie", [&] { PCIe::LoopProcess(system); }); 271 kernel.RunOnGuestCoreProcess("pcie", [&] { PCIe::LoopProcess(system); });
270 kernel.RunOnGuestCoreProcess("pctl", [&] { PCTL::LoopProcess(system); }); 272 kernel.RunOnGuestCoreProcess("pctl", [&] { PCTL::LoopProcess(system); });
271 kernel.RunOnGuestCoreProcess("pcv", [&] { PCV::LoopProcess(system); }); 273 kernel.RunOnGuestCoreProcess("pcv", [&] { PCV::LoopProcess(system); });
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 1f33301b7..1d6c117b1 100755
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -35,7 +35,7 @@ BufferCache<P>::BufferCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, R
35 const s64 min_spacing_critical = device_local_memory - 512_MiB; 35 const s64 min_spacing_critical = device_local_memory - 512_MiB;
36 const s64 mem_threshold = std::min(device_local_memory, TARGET_THRESHOLD); 36 const s64 mem_threshold = std::min(device_local_memory, TARGET_THRESHOLD);
37 const s64 min_vacancy_expected = (6 * mem_threshold) / 10; 37 const s64 min_vacancy_expected = (6 * mem_threshold) / 10;
38 const s64 min_vacancy_critical = (3 * mem_threshold) / 10; 38 const s64 min_vacancy_critical = (2 * mem_threshold) / 10;
39 minimum_memory = static_cast<u64>( 39 minimum_memory = static_cast<u64>(
40 std::max(std::min(device_local_memory - min_vacancy_expected, min_spacing_expected), 40 std::max(std::min(device_local_memory - min_vacancy_expected, min_spacing_expected),
41 DEFAULT_EXPECTED_MEMORY)); 41 DEFAULT_EXPECTED_MEMORY));
diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp
index c48e19ffa..a94d2371a 100755
--- a/src/video_core/surface.cpp
+++ b/src/video_core/surface.cpp
@@ -3,6 +3,7 @@
3 3
4#include "common/common_types.h" 4#include "common/common_types.h"
5#include "common/math_util.h" 5#include "common/math_util.h"
6#include "common/settings.h"
6#include "video_core/surface.h" 7#include "video_core/surface.h"
7 8
8namespace VideoCore::Surface { 9namespace VideoCore::Surface {
@@ -400,11 +401,20 @@ std::pair<u32, u32> GetASTCBlockSize(PixelFormat format) {
400 return {DefaultBlockWidth(format), DefaultBlockHeight(format)}; 401 return {DefaultBlockWidth(format), DefaultBlockHeight(format)};
401} 402}
402 403
403u64 EstimatedDecompressedSize(u64 base_size, PixelFormat format) { 404u64 TranscodedAstcSize(u64 base_size, PixelFormat format) {
404 constexpr u64 RGBA8_PIXEL_SIZE = 4; 405 constexpr u64 RGBA8_PIXEL_SIZE = 4;
405 const u64 base_block_size = static_cast<u64>(DefaultBlockWidth(format)) * 406 const u64 base_block_size = static_cast<u64>(DefaultBlockWidth(format)) *
406 static_cast<u64>(DefaultBlockHeight(format)) * RGBA8_PIXEL_SIZE; 407 static_cast<u64>(DefaultBlockHeight(format)) * RGBA8_PIXEL_SIZE;
407 return (base_size * base_block_size) / BytesPerBlock(format); 408 const u64 uncompressed_size = (base_size * base_block_size) / BytesPerBlock(format);
409
410 switch (Settings::values.astc_recompression.GetValue()) {
411 case Settings::AstcRecompression::Bc1:
412 return uncompressed_size / 8;
413 case Settings::AstcRecompression::Bc3:
414 return uncompressed_size / 4;
415 default:
416 return uncompressed_size;
417 }
408} 418}
409 419
410} // namespace VideoCore::Surface 420} // namespace VideoCore::Surface
diff --git a/src/video_core/surface.h b/src/video_core/surface.h
index 9ac9b6343..2c212a6b1 100755
--- a/src/video_core/surface.h
+++ b/src/video_core/surface.h
@@ -517,6 +517,6 @@ size_t PixelComponentSizeBitsInteger(PixelFormat format);
517 517
518std::pair<u32, u32> GetASTCBlockSize(PixelFormat format); 518std::pair<u32, u32> GetASTCBlockSize(PixelFormat format);
519 519
520u64 EstimatedDecompressedSize(u64 base_size, PixelFormat format); 520u64 TranscodedAstcSize(u64 base_size, PixelFormat format);
521 521
522} // namespace VideoCore::Surface 522} // namespace VideoCore::Surface
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 47ea0bd96..f790897ef 100755
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -55,7 +55,7 @@ TextureCache<P>::TextureCache(Runtime& runtime_, Tegra::MaxwellDeviceMemoryManag
55 const s64 min_spacing_critical = device_local_memory - 512_MiB; 55 const s64 min_spacing_critical = device_local_memory - 512_MiB;
56 const s64 mem_threshold = std::min(device_local_memory, TARGET_THRESHOLD); 56 const s64 mem_threshold = std::min(device_local_memory, TARGET_THRESHOLD);
57 const s64 min_vacancy_expected = (6 * mem_threshold) / 10; 57 const s64 min_vacancy_expected = (6 * mem_threshold) / 10;
58 const s64 min_vacancy_critical = (3 * mem_threshold) / 10; 58 const s64 min_vacancy_critical = (2 * mem_threshold) / 10;
59 expected_memory = static_cast<u64>( 59 expected_memory = static_cast<u64>(
60 std::max(std::min(device_local_memory - min_vacancy_expected, min_spacing_expected), 60 std::max(std::min(device_local_memory - min_vacancy_expected, min_spacing_expected),
61 DEFAULT_EXPECTED_MEMORY)); 61 DEFAULT_EXPECTED_MEMORY));
@@ -1979,7 +1979,7 @@ void TextureCache<P>::RegisterImage(ImageId image_id) {
1979 if ((IsPixelFormatASTC(image.info.format) && 1979 if ((IsPixelFormatASTC(image.info.format) &&
1980 True(image.flags & ImageFlagBits::AcceleratedUpload)) || 1980 True(image.flags & ImageFlagBits::AcceleratedUpload)) ||
1981 True(image.flags & ImageFlagBits::Converted)) { 1981 True(image.flags & ImageFlagBits::Converted)) {
1982 tentative_size = EstimatedDecompressedSize(tentative_size, image.info.format); 1982 tentative_size = TranscodedAstcSize(tentative_size, image.info.format);
1983 } 1983 }
1984 total_used_memory += Common::AlignUp(tentative_size, 1024); 1984 total_used_memory += Common::AlignUp(tentative_size, 1024);
1985 image.lru_index = lru_cache.Insert(image_id, frame_tick); 1985 image.lru_index = lru_cache.Insert(image_id, frame_tick);
@@ -2149,7 +2149,7 @@ void TextureCache<P>::DeleteImage(ImageId image_id, bool immediate_delete) {
2149 if ((IsPixelFormatASTC(image.info.format) && 2149 if ((IsPixelFormatASTC(image.info.format) &&
2150 True(image.flags & ImageFlagBits::AcceleratedUpload)) || 2150 True(image.flags & ImageFlagBits::AcceleratedUpload)) ||
2151 True(image.flags & ImageFlagBits::Converted)) { 2151 True(image.flags & ImageFlagBits::Converted)) {
2152 tentative_size = EstimatedDecompressedSize(tentative_size, image.info.format); 2152 tentative_size = TranscodedAstcSize(tentative_size, image.info.format);
2153 } 2153 }
2154 total_used_memory -= Common::AlignUp(tentative_size, 1024); 2154 total_used_memory -= Common::AlignUp(tentative_size, 1024);
2155 const GPUVAddr gpu_addr = image.gpu_addr; 2155 const GPUVAddr gpu_addr = image.gpu_addr;
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index bd77057b0..940cc0a54 100755
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -1290,10 +1290,6 @@ u64 Device::GetDeviceMemoryUsage() const {
1290} 1290}
1291 1291
1292void Device::CollectPhysicalMemoryInfo() { 1292void Device::CollectPhysicalMemoryInfo() {
1293 // Account for resolution scaling in memory limits
1294 const size_t normal_memory = 6_GiB;
1295 const size_t scaler_memory = 1_GiB * Settings::values.resolution_info.ScaleUp(1);
1296
1297 // Calculate limits using memory budget 1293 // Calculate limits using memory budget
1298 VkPhysicalDeviceMemoryBudgetPropertiesEXT budget{}; 1294 VkPhysicalDeviceMemoryBudgetPropertiesEXT budget{};
1299 budget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT; 1295 budget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT;
@@ -1324,7 +1320,6 @@ void Device::CollectPhysicalMemoryInfo() {
1324 if (!is_integrated) { 1320 if (!is_integrated) {
1325 const u64 reserve_memory = std::min<u64>(device_access_memory / 8, 1_GiB); 1321 const u64 reserve_memory = std::min<u64>(device_access_memory / 8, 1_GiB);
1326 device_access_memory -= reserve_memory; 1322 device_access_memory -= reserve_memory;
1327 device_access_memory = std::min<u64>(device_access_memory, normal_memory + scaler_memory);
1328 return; 1323 return;
1329 } 1324 }
1330 const s64 available_memory = static_cast<s64>(device_access_memory - device_initial_usage); 1325 const s64 available_memory = static_cast<s64>(device_access_memory - device_initial_usage);
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index 5ec8296a6..abbfdd7a6 100755
--- a/src/yuzu/configuration/configure_input.cpp
+++ b/src/yuzu/configuration/configure_input.cpp
@@ -8,10 +8,7 @@
8#include "common/settings_enums.h" 8#include "common/settings_enums.h"
9#include "core/core.h" 9#include "core/core.h"
10#include "core/hle/service/am/am.h" 10#include "core/hle/service/am/am.h"
11#include "core/hle/service/am/applet_ae.h"
12#include "core/hle/service/am/applet_manager.h" 11#include "core/hle/service/am/applet_manager.h"
13#include "core/hle/service/am/applet_message_queue.h"
14#include "core/hle/service/am/applet_oe.h"
15#include "core/hle/service/sm/sm.h" 12#include "core/hle/service/sm/sm.h"
16#include "hid_core/frontend/emulated_controller.h" 13#include "hid_core/frontend/emulated_controller.h"
17#include "hid_core/hid_core.h" 14#include "hid_core/hid_core.h"
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 010dd82a8..97814836f 100755
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -44,9 +44,6 @@
44#include "core/frontend/applets/mii_edit.h" 44#include "core/frontend/applets/mii_edit.h"
45#include "core/frontend/applets/software_keyboard.h" 45#include "core/frontend/applets/software_keyboard.h"
46#include "core/hle/service/acc/profile_manager.h" 46#include "core/hle/service/acc/profile_manager.h"
47#include "core/hle/service/am/applet_ae.h"
48#include "core/hle/service/am/applet_message_queue.h"
49#include "core/hle/service/am/applet_oe.h"
50#include "core/hle/service/am/frontend/applets.h" 47#include "core/hle/service/am/frontend/applets.h"
51#include "core/hle/service/set/system_settings_server.h" 48#include "core/hle/service/set/system_settings_server.h"
52#include "frontend_common/content_manager.h" 49#include "frontend_common/content_manager.h"