summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Liam2024-01-02 19:22:02 -0500
committerGravatar Liam2024-01-29 18:43:45 -0500
commita7e9d7842dc78e09bfe50ba3bc471b8a75d29b96 (patch)
tree075bbdbcf1d3afa6404220b14490be77fdacc32c /src
parentservice: split am into components (diff)
downloadyuzu-a7e9d7842dc78e09bfe50ba3bc471b8a75d29b96.tar.gz
yuzu-a7e9d7842dc78e09bfe50ba3bc471b8a75d29b96.tar.xz
yuzu-a7e9d7842dc78e09bfe50ba3bc471b8a75d29b96.zip
am: add new datatypes for per-applet state
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt17
-rw-r--r--src/core/hle/service/am/am_types.h171
-rw-r--r--src/core/hle/service/am/applet.cpp63
-rw-r--r--src/core/hle/service/am/applet.h164
-rw-r--r--src/core/hle/service/am/applet_manager.cpp352
-rw-r--r--src/core/hle/service/am/applet_manager.h59
-rw-r--r--src/core/hle/service/am/hid_registration.cpp29
-rw-r--r--src/core/hle/service/am/hid_registration.h30
-rw-r--r--src/core/hle/service/am/library_applet_storage.cpp140
-rw-r--r--src/core/hle/service/am/library_applet_storage.h36
-rw-r--r--src/core/hle/service/am/managed_layer_holder.cpp59
-rw-r--r--src/core/hle/service/am/managed_layer_holder.h32
-rw-r--r--src/core/hle/service/am/process.cpp138
-rw-r--r--src/core/hle/service/am/process.h50
-rw-r--r--src/core/hle/service/am/system_buffer_manager.cpp49
-rw-r--r--src/core/hle/service/am/system_buffer_manager.h44
-rw-r--r--src/core/hle/service/event.cpp31
-rw-r--r--src/core/hle/service/event.h31
-rw-r--r--src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp2
19 files changed, 1496 insertions, 1 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 3a2ba9ed4..049946426 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -393,8 +393,13 @@ add_library(core STATIC
393 hle/service/am/am.cpp 393 hle/service/am/am.cpp
394 hle/service/am/am.h 394 hle/service/am/am.h
395 hle/service/am/am_results.h 395 hle/service/am/am_results.h
396 hle/service/am/am_types.h
397 hle/service/am/applet.cpp
398 hle/service/am/applet.h
396 hle/service/am/applet_ae.cpp 399 hle/service/am/applet_ae.cpp
397 hle/service/am/applet_ae.h 400 hle/service/am/applet_ae.h
401 hle/service/am/applet_manager.cpp
402 hle/service/am/applet_manager.h
398 hle/service/am/applet_oe.cpp 403 hle/service/am/applet_oe.cpp
399 hle/service/am/applet_oe.h 404 hle/service/am/applet_oe.h
400 hle/service/am/applets/applet_cabinet.cpp 405 hle/service/am/applets/applet_cabinet.cpp
@@ -438,6 +443,8 @@ add_library(core STATIC
438 hle/service/am/display_controller.h 443 hle/service/am/display_controller.h
439 hle/service/am/global_state_controller.cpp 444 hle/service/am/global_state_controller.cpp
440 hle/service/am/global_state_controller.h 445 hle/service/am/global_state_controller.h
446 hle/service/am/hid_registration.cpp
447 hle/service/am/hid_registration.h
441 hle/service/am/home_menu_functions.cpp 448 hle/service/am/home_menu_functions.cpp
442 hle/service/am/home_menu_functions.h 449 hle/service/am/home_menu_functions.h
443 hle/service/am/idle.cpp 450 hle/service/am/idle.cpp
@@ -450,16 +457,24 @@ add_library(core STATIC
450 hle/service/am/library_applet_proxy.h 457 hle/service/am/library_applet_proxy.h
451 hle/service/am/library_applet_self_accessor.cpp 458 hle/service/am/library_applet_self_accessor.cpp
452 hle/service/am/library_applet_self_accessor.h 459 hle/service/am/library_applet_self_accessor.h
460 hle/service/am/library_applet_storage.cpp
461 hle/service/am/library_applet_storage.h
453 hle/service/am/lock_accessor.cpp 462 hle/service/am/lock_accessor.cpp
454 hle/service/am/lock_accessor.h 463 hle/service/am/lock_accessor.h
464 hle/service/am/managed_layer_holder.cpp
465 hle/service/am/managed_layer_holder.h
455 hle/service/am/omm.cpp 466 hle/service/am/omm.cpp
456 hle/service/am/omm.h 467 hle/service/am/omm.h
457 hle/service/am/process_winding_controller.cpp 468 hle/service/am/process_winding_controller.cpp
458 hle/service/am/process_winding_controller.h 469 hle/service/am/process_winding_controller.h
470 hle/service/am/process.cpp
471 hle/service/am/process.h
459 hle/service/am/self_controller.cpp 472 hle/service/am/self_controller.cpp
460 hle/service/am/self_controller.h 473 hle/service/am/self_controller.h
461 hle/service/am/system_applet_proxy.cpp 474 hle/service/am/system_applet_proxy.cpp
462 hle/service/am/system_applet_proxy.h 475 hle/service/am/system_applet_proxy.h
476 hle/service/am/system_buffer_manager.cpp
477 hle/service/am/system_buffer_manager.h
463 hle/service/am/spsm.cpp 478 hle/service/am/spsm.cpp
464 hle/service/am/spsm.h 479 hle/service/am/spsm.h
465 hle/service/am/storage_accessor.cpp 480 hle/service/am/storage_accessor.cpp
@@ -531,6 +546,8 @@ add_library(core STATIC
531 hle/service/es/es.h 546 hle/service/es/es.h
532 hle/service/eupld/eupld.cpp 547 hle/service/eupld/eupld.cpp
533 hle/service/eupld/eupld.h 548 hle/service/eupld/eupld.h
549 hle/service/event.cpp
550 hle/service/event.h
534 hle/service/fatal/fatal.cpp 551 hle/service/fatal/fatal.cpp
535 hle/service/fatal/fatal.h 552 hle/service/fatal/fatal.h
536 hle/service/fatal/fatal_p.cpp 553 hle/service/fatal/fatal_p.cpp
diff --git a/src/core/hle/service/am/am_types.h b/src/core/hle/service/am/am_types.h
new file mode 100644
index 000000000..d0a237a7e
--- /dev/null
+++ b/src/core/hle/service/am/am_types.h
@@ -0,0 +1,171 @@
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/common_funcs.h"
7#include "common/common_types.h"
8
9namespace Service::AM {
10
11namespace Frontend {
12class FrontendApplet;
13}
14
15enum class AppletType {
16 Application,
17 LibraryApplet,
18 SystemApplet,
19};
20
21enum class GameplayRecordingState : u32 {
22 Disabled,
23 Enabled,
24};
25
26// This is nn::oe::FocusState
27enum class FocusState : u8 {
28 InFocus = 1,
29 NotInFocus = 2,
30 Background = 3,
31};
32
33// This is nn::oe::OperationMode
34enum class OperationMode : u8 {
35 Handheld = 0,
36 Docked = 1,
37};
38
39// This is nn::am::service::SystemButtonType
40enum class SystemButtonType {
41 None,
42 HomeButtonShortPressing,
43 HomeButtonLongPressing,
44 PowerButtonShortPressing,
45 PowerButtonLongPressing,
46 ShutdownSystem,
47 CaptureButtonShortPressing,
48 CaptureButtonLongPressing,
49};
50
51enum class SysPlatformRegion : s32 {
52 Global = 1,
53 Terra = 2,
54};
55
56struct AppletProcessLaunchReason {
57 u8 flag;
58 INSERT_PADDING_BYTES(3);
59};
60static_assert(sizeof(AppletProcessLaunchReason) == 0x4,
61 "AppletProcessLaunchReason is an invalid size");
62
63enum class ScreenshotPermission : u32 {
64 Inherit = 0,
65 Enable = 1,
66 Disable = 2,
67};
68
69struct FocusHandlingMode {
70 bool unknown0;
71 bool unknown1;
72 bool unknown2;
73 bool unknown3;
74};
75
76enum class IdleTimeDetectionExtension : u32 {
77 Disabled = 0,
78 Extended = 1,
79 ExtendedUnsafe = 2,
80};
81
82enum class AppletId : u32 {
83 None = 0x00,
84 Application = 0x01,
85 OverlayDisplay = 0x02,
86 QLaunch = 0x03,
87 Starter = 0x04,
88 Auth = 0x0A,
89 Cabinet = 0x0B,
90 Controller = 0x0C,
91 DataErase = 0x0D,
92 Error = 0x0E,
93 NetConnect = 0x0F,
94 ProfileSelect = 0x10,
95 SoftwareKeyboard = 0x11,
96 MiiEdit = 0x12,
97 Web = 0x13,
98 Shop = 0x14,
99 PhotoViewer = 0x15,
100 Settings = 0x16,
101 OfflineWeb = 0x17,
102 LoginShare = 0x18,
103 WebAuth = 0x19,
104 MyPage = 0x1A,
105};
106
107enum class AppletProgramId : u64 {
108 QLaunch = 0x0100000000001000ull,
109 Auth = 0x0100000000001001ull,
110 Cabinet = 0x0100000000001002ull,
111 Controller = 0x0100000000001003ull,
112 DataErase = 0x0100000000001004ull,
113 Error = 0x0100000000001005ull,
114 NetConnect = 0x0100000000001006ull,
115 ProfileSelect = 0x0100000000001007ull,
116 SoftwareKeyboard = 0x0100000000001008ull,
117 MiiEdit = 0x0100000000001009ull,
118 Web = 0x010000000000100Aull,
119 Shop = 0x010000000000100Bull,
120 OverlayDisplay = 0x010000000000100Cull,
121 PhotoViewer = 0x010000000000100Dull,
122 Settings = 0x010000000000100Eull,
123 OfflineWeb = 0x010000000000100Full,
124 LoginShare = 0x0100000000001010ull,
125 WebAuth = 0x0100000000001011ull,
126 Starter = 0x0100000000001012ull,
127 MyPage = 0x0100000000001013ull,
128 MaxProgramId = 0x0100000000001FFFull,
129};
130
131enum class LibraryAppletMode : u32 {
132 AllForeground = 0,
133 Background = 1,
134 NoUI = 2,
135 BackgroundIndirectDisplay = 3,
136 AllForegroundInitiallyHidden = 4,
137};
138
139enum class CommonArgumentVersion : u32 {
140 Version0,
141 Version1,
142 Version2,
143 Version3,
144};
145
146enum class CommonArgumentSize : u32 {
147 Version3 = 0x20,
148};
149
150enum class ThemeColor : u32 {
151 BasicWhite = 0,
152 BasicBlack = 3,
153};
154
155struct CommonArguments {
156 CommonArgumentVersion arguments_version;
157 CommonArgumentSize size;
158 u32 library_version;
159 ThemeColor theme_color;
160 bool play_startup_sound;
161 u64 system_tick;
162};
163static_assert(sizeof(CommonArguments) == 0x20, "CommonArguments has incorrect size.");
164
165using AppletResourceUserId = u64;
166using ProgramId = u64;
167
168struct Applet;
169struct AppletStorageHolder;
170
171} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet.cpp b/src/core/hle/service/am/applet.cpp
new file mode 100644
index 000000000..8f44fab33
--- /dev/null
+++ b/src/core/hle/service/am/applet.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 "common/scope_exit.h"
5
6#include "core/hle/service/am/am_results.h"
7#include "core/hle/service/am/applet.h"
8
9namespace Service::AM {
10
11AppletStorageChannel::AppletStorageChannel(KernelHelpers::ServiceContext& context)
12 : m_event(context) {}
13AppletStorageChannel::~AppletStorageChannel() = default;
14
15void AppletStorageChannel::PushData(std::shared_ptr<IStorage> storage) {
16 std::scoped_lock lk{m_lock};
17
18 m_data.emplace_back(std::move(storage));
19 m_event.Signal();
20}
21
22Result AppletStorageChannel::PopData(std::shared_ptr<IStorage>* out_storage) {
23 std::scoped_lock lk{m_lock};
24
25 SCOPE_EXIT({
26 if (m_data.empty()) {
27 m_event.Clear();
28 }
29 });
30
31 R_UNLESS(!m_data.empty(), AM::ResultNoDataInChannel);
32
33 *out_storage = std::move(m_data.front());
34 m_data.pop_front();
35
36 R_SUCCEED();
37}
38
39Kernel::KReadableEvent* AppletStorageChannel::GetEvent() {
40 return m_event.GetHandle();
41}
42
43AppletStorageHolder::AppletStorageHolder(Core::System& system)
44 : context(system, "AppletStorageHolder"), in_data(context), interactive_in_data(context),
45 out_data(context), interactive_out_data(context), state_changed_event(context) {}
46
47AppletStorageHolder::~AppletStorageHolder() = default;
48
49Applet::Applet(Core::System& system, std::unique_ptr<Process> process_)
50 : context(system, "Applet"), message_queue(system), process(std::move(process_)),
51 hid_registration(system, *process), gpu_error_detected_event(context),
52 friend_invitation_storage_channel_event(context), notification_storage_channel_event(context),
53 health_warning_disappeared_system_event(context), acquired_sleep_lock_event(context),
54 pop_from_general_channel_event(context), library_applet_launchable_event(context),
55 accumulated_suspended_tick_changed_event(context), sleep_lock_event(context) {
56
57 aruid = process->GetProcessId();
58 program_id = process->GetProgramId();
59}
60
61Applet::~Applet() = default;
62
63} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet.h b/src/core/hle/service/am/applet.h
new file mode 100644
index 000000000..9650a2615
--- /dev/null
+++ b/src/core/hle/service/am/applet.h
@@ -0,0 +1,164 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <list>
7#include <mutex>
8
9#include "common/math_util.h"
10#include "core/hle/service/apm/apm_controller.h"
11#include "core/hle/service/caps/caps_types.h"
12#include "core/hle/service/event.h"
13#include "core/hle/service/kernel_helpers.h"
14#include "core/hle/service/service.h"
15
16#include "core/hle/service/am/am_types.h"
17#include "core/hle/service/am/applet_message_queue.h"
18#include "core/hle/service/am/hid_registration.h"
19#include "core/hle/service/am/managed_layer_holder.h"
20#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"
23
24namespace Service::Nvnflinger {
25class FbShareBufferManager;
26class Nvnflinger;
27} // namespace Service::Nvnflinger
28
29namespace Service::AM {
30
31class AppletStorageChannel {
32public:
33 explicit AppletStorageChannel(KernelHelpers::ServiceContext& ctx);
34 ~AppletStorageChannel();
35
36 void PushData(std::shared_ptr<IStorage> storage);
37 Result PopData(std::shared_ptr<IStorage>* out_storage);
38 Kernel::KReadableEvent* GetEvent();
39
40private:
41 std::mutex m_lock{};
42 std::deque<std::shared_ptr<IStorage>> m_data{};
43 Event m_event;
44};
45
46struct AppletStorageHolder {
47 explicit AppletStorageHolder(Core::System& system);
48 ~AppletStorageHolder();
49
50 KernelHelpers::ServiceContext context;
51
52 AppletStorageChannel in_data;
53 AppletStorageChannel interactive_in_data;
54 AppletStorageChannel out_data;
55 AppletStorageChannel interactive_out_data;
56 Event state_changed_event;
57};
58
59struct Applet {
60 explicit Applet(Core::System& system, std::unique_ptr<Process> process_);
61 ~Applet();
62
63 // Lock
64 std::mutex lock{};
65
66 // Event creation helper
67 KernelHelpers::ServiceContext context;
68
69 // Applet message queue
70 AppletMessageQueue message_queue;
71
72 // Process
73 std::unique_ptr<Process> process;
74
75 // Creation state
76 AppletId applet_id{};
77 AppletResourceUserId aruid{};
78 AppletProcessLaunchReason launch_reason{};
79 AppletType type{};
80 ProgramId program_id{};
81 LibraryAppletMode library_applet_mode{};
82 s32 previous_program_index{-1};
83 ScreenshotPermission previous_screenshot_permission{ScreenshotPermission::Enable};
84
85 // hid state
86 HidRegistration hid_registration;
87
88 // vi state
89 SystemBufferManager system_buffer_manager{};
90 ManagedLayerHolder managed_layer_holder{};
91
92 // Applet common functions
93 Result terminate_result{};
94 s32 display_logical_width{};
95 s32 display_logical_height{};
96 Common::Rectangle<f32> display_magnification{0, 0, 1, 1};
97 bool home_button_double_click_enabled{};
98 bool home_button_short_pressed_blocked{};
99 bool home_button_long_pressed_blocked{};
100 bool vr_mode_curtain_required{};
101 bool sleep_required_by_high_temperature{};
102 bool sleep_required_by_low_battery{};
103 s32 cpu_boost_request_priority{-1};
104 bool handling_capture_button_short_pressed_message_enabled_for_applet{};
105 bool handling_capture_button_long_pressed_message_enabled_for_applet{};
106 u32 application_core_usage_mode{};
107
108 // Application functions
109 bool gameplay_recording_supported{};
110 GameplayRecordingState gameplay_recording_state{GameplayRecordingState::Disabled};
111 bool jit_service_launched{};
112 bool is_running{};
113 bool application_crash_report_enabled{};
114
115 // Common state
116 FocusState focus_state{};
117 bool sleep_lock_enabled{};
118 bool vr_mode_enabled{};
119 bool lcd_backlight_off_enabled{};
120 APM::CpuBoostMode boost_mode{};
121 bool request_exit_to_library_applet_at_execute_next_program_enabled{};
122
123 // Channels
124 std::deque<std::vector<u8>> user_channel_launch_parameter{};
125 std::deque<std::vector<u8>> preselected_user_launch_parameter{};
126
127 // Caller applet
128 std::weak_ptr<Applet> caller_applet{};
129 std::shared_ptr<AppletStorageHolder> caller_applet_storage{};
130 bool is_completed{};
131
132 // Self state
133 bool exit_locked{};
134 s32 fatal_section_count{};
135 bool operation_mode_changed_notification_enabled{true};
136 bool performance_mode_changed_notification_enabled{true};
137 FocusHandlingMode focus_handling_mode{};
138 bool restart_message_enabled{};
139 bool out_of_focus_suspension_enabled{true};
140 Capture::AlbumImageOrientation album_image_orientation{};
141 bool handles_request_to_display{};
142 ScreenshotPermission screenshot_permission{};
143 IdleTimeDetectionExtension idle_time_detection_extension{};
144 bool auto_sleep_disabled{};
145 u64 suspended_ticks{};
146 bool album_image_taken_notification_enabled{};
147 bool record_volume_muted{};
148
149 // Events
150 Event gpu_error_detected_event;
151 Event friend_invitation_storage_channel_event;
152 Event notification_storage_channel_event;
153 Event health_warning_disappeared_system_event;
154 Event acquired_sleep_lock_event;
155 Event pop_from_general_channel_event;
156 Event library_applet_launchable_event;
157 Event accumulated_suspended_tick_changed_event;
158 Event sleep_lock_event;
159
160 // Frontend state
161 std::shared_ptr<Frontend::FrontendApplet> frontend{};
162};
163
164} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet_manager.cpp b/src/core/hle/service/am/applet_manager.cpp
new file mode 100644
index 000000000..9f7ccfbf2
--- /dev/null
+++ b/src/core/hle/service/am/applet_manager.cpp
@@ -0,0 +1,352 @@
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/core.h"
7#include "core/core_timing.h"
8#include "core/hle/service/acc/profile_manager.h"
9#include "core/hle/service/am/applet_manager.h"
10#include "core/hle/service/am/applets/applet_cabinet.h"
11#include "core/hle/service/am/applets/applet_controller.h"
12#include "core/hle/service/am/applets/applet_mii_edit_types.h"
13#include "core/hle/service/am/applets/applet_software_keyboard_types.h"
14#include "hid_core/hid_types.h"
15
16namespace Service::AM {
17
18namespace {
19
20constexpr u32 LaunchParameterAccountPreselectedUserMagic = 0xC79497CA;
21
22struct LaunchParameterAccountPreselectedUser {
23 u32 magic;
24 u32 is_account_selected;
25 Common::UUID current_user;
26 INSERT_PADDING_BYTES(0x70);
27};
28static_assert(sizeof(LaunchParameterAccountPreselectedUser) == 0x88);
29
30AppletStorageChannel& InitializeFakeCallerApplet(Core::System& system,
31 std::shared_ptr<Applet>& applet) {
32 applet->caller_applet_storage = std::make_shared<AppletStorageHolder>(system);
33 return applet->caller_applet_storage->in_data;
34}
35
36void PushInShowAlbum(Core::System& system, AppletStorageChannel& channel) {
37 const CommonArguments arguments{
38 .arguments_version = CommonArgumentVersion::Version3,
39 .size = CommonArgumentSize::Version3,
40 .library_version = 1,
41 .theme_color = ThemeColor::BasicBlack,
42 .play_startup_sound = true,
43 .system_tick = system.CoreTiming().GetClockTicks(),
44 };
45
46 std::vector<u8> argument_data(sizeof(arguments));
47 std::vector<u8> settings_data{2};
48 std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
49 channel.PushData(std::make_shared<IStorage>(system, std::move(argument_data)));
50 channel.PushData(std::make_shared<IStorage>(system, std::move(settings_data)));
51}
52
53void PushInShowController(Core::System& system, AppletStorageChannel& channel) {
54 const CommonArguments common_args = {
55 .arguments_version = CommonArgumentVersion::Version3,
56 .size = CommonArgumentSize::Version3,
57 .library_version = static_cast<u32>(Applets::ControllerAppletVersion::Version8),
58 .theme_color = ThemeColor::BasicBlack,
59 .play_startup_sound = true,
60 .system_tick = system.CoreTiming().GetClockTicks(),
61 };
62
63 Applets::ControllerSupportArgNew user_args = {
64 .header = {.player_count_min = 1,
65 .player_count_max = 4,
66 .enable_take_over_connection = true,
67 .enable_left_justify = false,
68 .enable_permit_joy_dual = true,
69 .enable_single_mode = false,
70 .enable_identification_color = false},
71 .identification_colors = {},
72 .enable_explain_text = false,
73 .explain_text = {},
74 };
75
76 Applets::ControllerSupportArgPrivate private_args = {
77 .arg_private_size = sizeof(Applets::ControllerSupportArgPrivate),
78 .arg_size = sizeof(Applets::ControllerSupportArgNew),
79 .is_home_menu = true,
80 .flag_1 = true,
81 .mode = Applets::ControllerSupportMode::ShowControllerSupport,
82 .caller = Applets::ControllerSupportCaller::
83 Application, // switchbrew: Always zero except with
84 // ShowControllerFirmwareUpdateForSystem/ShowControllerKeyRemappingForSystem,
85 // which sets this to the input param
86 .style_set = Core::HID::NpadStyleSet::None,
87 .joy_hold_type = 0,
88 };
89 std::vector<u8> common_args_data(sizeof(common_args));
90 std::vector<u8> private_args_data(sizeof(private_args));
91 std::vector<u8> user_args_data(sizeof(user_args));
92
93 std::memcpy(common_args_data.data(), &common_args, sizeof(common_args));
94 std::memcpy(private_args_data.data(), &private_args, sizeof(private_args));
95 std::memcpy(user_args_data.data(), &user_args, sizeof(user_args));
96
97 channel.PushData(std::make_shared<IStorage>(system, std::move(common_args_data)));
98 channel.PushData(std::make_shared<IStorage>(system, std::move(private_args_data)));
99 channel.PushData(std::make_shared<IStorage>(system, std::move(user_args_data)));
100}
101
102void PushInShowCabinetData(Core::System& system, AppletStorageChannel& channel) {
103 const CommonArguments arguments{
104 .arguments_version = CommonArgumentVersion::Version3,
105 .size = CommonArgumentSize::Version3,
106 .library_version = static_cast<u32>(Applets::CabinetAppletVersion::Version1),
107 .theme_color = ThemeColor::BasicBlack,
108 .play_startup_sound = true,
109 .system_tick = system.CoreTiming().GetClockTicks(),
110 };
111
112 const Applets::StartParamForAmiiboSettings amiibo_settings{
113 .param_1 = 0,
114 .applet_mode = system.GetAppletManager().GetCabinetMode(),
115 .flags = Applets::CabinetFlags::None,
116 .amiibo_settings_1 = 0,
117 .device_handle = 0,
118 .tag_info{},
119 .register_info{},
120 .amiibo_settings_3{},
121 };
122
123 std::vector<u8> argument_data(sizeof(arguments));
124 std::vector<u8> settings_data(sizeof(amiibo_settings));
125 std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
126 std::memcpy(settings_data.data(), &amiibo_settings, sizeof(amiibo_settings));
127 channel.PushData(std::make_shared<IStorage>(system, std::move(argument_data)));
128 channel.PushData(std::make_shared<IStorage>(system, std::move(settings_data)));
129}
130
131void PushInShowMiiEditData(Core::System& system, AppletStorageChannel& channel) {
132 struct MiiEditV3 {
133 Applets::MiiEditAppletInputCommon common;
134 Applets::MiiEditAppletInputV3 input;
135 };
136 static_assert(sizeof(MiiEditV3) == 0x100, "MiiEditV3 has incorrect size.");
137
138 MiiEditV3 mii_arguments{
139 .common =
140 {
141 .version = Applets::MiiEditAppletVersion::Version3,
142 .applet_mode = Applets::MiiEditAppletMode::ShowMiiEdit,
143 },
144 .input{},
145 };
146
147 std::vector<u8> argument_data(sizeof(mii_arguments));
148 std::memcpy(argument_data.data(), &mii_arguments, sizeof(mii_arguments));
149
150 channel.PushData(std::make_shared<IStorage>(system, std::move(argument_data)));
151}
152
153void PushInShowSoftwareKeyboard(Core::System& system, AppletStorageChannel& channel) {
154 const CommonArguments arguments{
155 .arguments_version = CommonArgumentVersion::Version3,
156 .size = CommonArgumentSize::Version3,
157 .library_version = static_cast<u32>(Applets::SwkbdAppletVersion::Version524301),
158 .theme_color = ThemeColor::BasicBlack,
159 .play_startup_sound = true,
160 .system_tick = system.CoreTiming().GetClockTicks(),
161 };
162
163 std::vector<char16_t> initial_string(0);
164
165 const Applets::SwkbdConfigCommon swkbd_config{
166 .type = Applets::SwkbdType::Qwerty,
167 .ok_text{},
168 .left_optional_symbol_key{},
169 .right_optional_symbol_key{},
170 .use_prediction = false,
171 .key_disable_flags{},
172 .initial_cursor_position = Applets::SwkbdInitialCursorPosition::Start,
173 .header_text{},
174 .sub_text{},
175 .guide_text{},
176 .max_text_length = 500,
177 .min_text_length = 0,
178 .password_mode = Applets::SwkbdPasswordMode::Disabled,
179 .text_draw_type = Applets::SwkbdTextDrawType::Box,
180 .enable_return_button = true,
181 .use_utf8 = false,
182 .use_blur_background = true,
183 .initial_string_offset{},
184 .initial_string_length = static_cast<u32>(initial_string.size()),
185 .user_dictionary_offset{},
186 .user_dictionary_entries{},
187 .use_text_check = false,
188 };
189
190 Applets::SwkbdConfigNew swkbd_config_new{};
191
192 std::vector<u8> argument_data(sizeof(arguments));
193 std::vector<u8> swkbd_data(sizeof(swkbd_config) + sizeof(swkbd_config_new));
194 std::vector<u8> work_buffer(swkbd_config.initial_string_length * sizeof(char16_t));
195
196 std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
197 std::memcpy(swkbd_data.data(), &swkbd_config, sizeof(swkbd_config));
198 std::memcpy(swkbd_data.data() + sizeof(swkbd_config), &swkbd_config_new,
199 sizeof(Applets::SwkbdConfigNew));
200 std::memcpy(work_buffer.data(), initial_string.data(),
201 swkbd_config.initial_string_length * sizeof(char16_t));
202
203 channel.PushData(std::make_shared<IStorage>(system, std::move(argument_data)));
204 channel.PushData(std::make_shared<IStorage>(system, std::move(swkbd_data)));
205 channel.PushData(std::make_shared<IStorage>(system, std::move(work_buffer)));
206}
207
208} // namespace
209
210AppletManager::AppletManager(Core::System& system) : m_system(system) {}
211AppletManager::~AppletManager() {
212 this->Reset();
213}
214
215void AppletManager::InsertApplet(std::shared_ptr<Applet> applet) {
216 std::scoped_lock lk{m_lock};
217
218 m_applets.emplace(applet->aruid, std::move(applet));
219}
220
221void AppletManager::TerminateAndRemoveApplet(AppletResourceUserId aruid) {
222 std::shared_ptr<Applet> applet;
223 {
224 std::scoped_lock lk{m_lock};
225
226 const auto it = m_applets.find(aruid);
227 if (it == m_applets.end()) {
228 return;
229 }
230
231 applet = it->second;
232 m_applets.erase(it);
233 }
234
235 // Terminate process.
236 applet->process->Terminate();
237}
238
239void AppletManager::CreateAndInsertByFrontendAppletParameters(
240 AppletResourceUserId aruid, const FrontendAppletParameters& params) {
241 // TODO: this should be run inside AM so that the events will have a parent process
242 // TODO: have am create the guest process
243 auto applet = std::make_shared<Applet>(m_system, std::make_unique<Process>(m_system));
244
245 applet->aruid = aruid;
246 applet->program_id = params.program_id;
247 applet->applet_id = params.applet_id;
248 applet->type = params.applet_type;
249 applet->previous_program_index = params.previous_program_index;
250
251 // Push UserChannel data from previous application
252 if (params.launch_type == LaunchType::ApplicationInitiated) {
253 applet->user_channel_launch_parameter.swap(m_system.GetUserChannel());
254 }
255
256 // TODO: Read whether we need a preselected user from NACP?
257 // TODO: This can be done quite easily from loader
258 {
259 LaunchParameterAccountPreselectedUser lp{};
260
261 lp.magic = LaunchParameterAccountPreselectedUserMagic;
262 lp.is_account_selected = 1;
263
264 Account::ProfileManager profile_manager{};
265 const auto uuid = profile_manager.GetUser(static_cast<s32>(Settings::values.current_user));
266 ASSERT(uuid.has_value() && uuid->IsValid());
267 lp.current_user = *uuid;
268
269 std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser));
270 std::memcpy(buffer.data(), &lp, buffer.size());
271
272 applet->preselected_user_launch_parameter.push_back(std::move(buffer));
273 }
274
275 // Starting from frontend, some applets require input data.
276 switch (applet->applet_id) {
277 case AppletId::Cabinet:
278 PushInShowCabinetData(m_system, InitializeFakeCallerApplet(m_system, applet));
279 break;
280 case AppletId::MiiEdit:
281 PushInShowMiiEditData(m_system, InitializeFakeCallerApplet(m_system, applet));
282 break;
283 case AppletId::PhotoViewer:
284 PushInShowAlbum(m_system, InitializeFakeCallerApplet(m_system, applet));
285 break;
286 case AppletId::SoftwareKeyboard:
287 PushInShowSoftwareKeyboard(m_system, InitializeFakeCallerApplet(m_system, applet));
288 break;
289 case AppletId::Controller:
290 PushInShowController(m_system, InitializeFakeCallerApplet(m_system, applet));
291 break;
292 default:
293 break;
294 }
295
296 // Applet was started by frontend, so it is foreground.
297 applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
298 applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
299 applet->focus_state = FocusState::InFocus;
300
301 this->InsertApplet(std::move(applet));
302}
303
304std::shared_ptr<Applet> AppletManager::GetByAppletResourceUserId(AppletResourceUserId aruid) const {
305 std::scoped_lock lk{m_lock};
306
307 if (const auto it = m_applets.find(aruid); it != m_applets.end()) {
308 return it->second;
309 }
310
311 return {};
312}
313
314void AppletManager::Reset() {
315 std::scoped_lock lk{m_lock};
316
317 m_applets.clear();
318}
319
320void AppletManager::RequestExit() {
321 std::scoped_lock lk{m_lock};
322
323 for (const auto& [aruid, applet] : m_applets) {
324 applet->message_queue.RequestExit();
325 }
326}
327
328void AppletManager::RequestResume() {
329 std::scoped_lock lk{m_lock};
330
331 for (const auto& [aruid, applet] : m_applets) {
332 applet->message_queue.RequestResume();
333 }
334}
335
336void AppletManager::OperationModeChanged() {
337 std::scoped_lock lk{m_lock};
338
339 for (const auto& [aruid, applet] : m_applets) {
340 applet->message_queue.OperationModeChanged();
341 }
342}
343
344void AppletManager::FocusStateChanged() {
345 std::scoped_lock lk{m_lock};
346
347 for (const auto& [aruid, applet] : m_applets) {
348 applet->message_queue.FocusStateChanged();
349 }
350}
351
352} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet_manager.h b/src/core/hle/service/am/applet_manager.h
new file mode 100644
index 000000000..4875de309
--- /dev/null
+++ b/src/core/hle/service/am/applet_manager.h
@@ -0,0 +1,59 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <map>
7#include <mutex>
8
9#include "core/hle/service/am/applet.h"
10
11namespace Core {
12class System;
13}
14
15namespace Service::AM {
16
17enum class LaunchType {
18 FrontendInitiated,
19 ApplicationInitiated,
20};
21
22struct FrontendAppletParameters {
23 ProgramId program_id{};
24 AppletId applet_id{};
25 AppletType applet_type{};
26 LaunchType launch_type{};
27 s32 program_index{};
28 s32 previous_program_index{-1};
29};
30
31class AppletManager {
32public:
33 explicit AppletManager(Core::System& system);
34 ~AppletManager();
35
36 void InsertApplet(std::shared_ptr<Applet> applet);
37 void TerminateAndRemoveApplet(AppletResourceUserId aruid);
38
39 void CreateAndInsertByFrontendAppletParameters(AppletResourceUserId aruid,
40 const FrontendAppletParameters& params);
41 std::shared_ptr<Applet> GetByAppletResourceUserId(AppletResourceUserId aruid) const;
42
43 void Reset();
44
45 void RequestExit();
46 void RequestResume();
47 void OperationModeChanged();
48 void FocusStateChanged();
49
50private:
51 Core::System& m_system;
52
53 mutable std::mutex m_lock{};
54 std::map<AppletResourceUserId, std::shared_ptr<Applet>> m_applets{};
55
56 // AudioController state goes here
57};
58
59} // namespace Service::AM
diff --git a/src/core/hle/service/am/hid_registration.cpp b/src/core/hle/service/am/hid_registration.cpp
new file mode 100644
index 000000000..b9426f7b6
--- /dev/null
+++ b/src/core/hle/service/am/hid_registration.cpp
@@ -0,0 +1,29 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/core.h"
5#include "core/hle/service/am/hid_registration.h"
6#include "core/hle/service/am/process.h"
7#include "core/hle/service/hid/hid_server.h"
8#include "core/hle/service/sm/sm.h"
9#include "hid_core/resource_manager.h"
10
11namespace Service::AM {
12
13HidRegistration::HidRegistration(Core::System& system, Process& process) : m_process(process) {
14 m_hid_server = system.ServiceManager().GetService<HID::IHidServer>("hid");
15
16 if (m_process.IsInitialized()) {
17 m_hid_server->GetResourceManager()->RegisterAppletResourceUserId(m_process.GetProcessId(),
18 true);
19 }
20}
21
22HidRegistration::~HidRegistration() {
23 if (m_process.IsInitialized()) {
24 m_hid_server->GetResourceManager()->UnregisterAppletResourceUserId(
25 m_process.GetProcessId());
26 }
27}
28
29} // namespace Service::AM
diff --git a/src/core/hle/service/am/hid_registration.h b/src/core/hle/service/am/hid_registration.h
new file mode 100644
index 000000000..8a732349c
--- /dev/null
+++ b/src/core/hle/service/am/hid_registration.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 <memory>
7
8namespace Core {
9class System;
10}
11
12namespace Service::HID {
13class IHidServer;
14}
15
16namespace Service::AM {
17
18class Process;
19
20class HidRegistration {
21public:
22 explicit HidRegistration(Core::System& system, Process& process);
23 ~HidRegistration();
24
25private:
26 Process& m_process;
27 std::shared_ptr<Service::HID::IHidServer> m_hid_server;
28};
29
30} // namespace Service::AM
diff --git a/src/core/hle/service/am/library_applet_storage.cpp b/src/core/hle/service/am/library_applet_storage.cpp
new file mode 100644
index 000000000..46e6c0111
--- /dev/null
+++ b/src/core/hle/service/am/library_applet_storage.cpp
@@ -0,0 +1,140 @@
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/am_results.h"
6#include "core/hle/service/am/library_applet_storage.h"
7#include "core/memory.h"
8
9namespace Service::AM {
10
11namespace {
12
13Result ValidateOffset(s64 offset, size_t size, size_t data_size) {
14 R_UNLESS(offset >= 0, AM::ResultInvalidOffset);
15
16 const size_t begin = offset;
17 const size_t end = begin + size;
18
19 R_UNLESS(begin <= end && end <= data_size, AM::ResultInvalidOffset);
20 R_SUCCEED();
21}
22
23class BufferLibraryAppletStorage final : public LibraryAppletStorage {
24public:
25 explicit BufferLibraryAppletStorage(std::vector<u8>&& data) : m_data(std::move(data)) {}
26 ~BufferLibraryAppletStorage() = default;
27
28 Result Read(s64 offset, void* buffer, size_t size) override {
29 R_TRY(ValidateOffset(offset, size, m_data.size()));
30
31 std::memcpy(buffer, m_data.data() + offset, size);
32
33 R_SUCCEED();
34 }
35
36 Result Write(s64 offset, const void* buffer, size_t size) override {
37 R_TRY(ValidateOffset(offset, size, m_data.size()));
38
39 std::memcpy(m_data.data() + offset, buffer, size);
40
41 R_SUCCEED();
42 }
43
44 s64 GetSize() override {
45 return m_data.size();
46 }
47
48 Kernel::KTransferMemory* GetHandle() override {
49 return nullptr;
50 }
51
52private:
53 std::vector<u8> m_data;
54};
55
56class TransferMemoryLibraryAppletStorage : public LibraryAppletStorage {
57public:
58 explicit TransferMemoryLibraryAppletStorage(Core::Memory::Memory& memory,
59 Kernel::KTransferMemory* trmem, bool is_writable,
60 s64 size)
61 : m_memory(memory), m_trmem(trmem), m_is_writable(is_writable), m_size(size) {
62 m_trmem->Open();
63 }
64
65 ~TransferMemoryLibraryAppletStorage() {
66 m_trmem->Close();
67 m_trmem = nullptr;
68 }
69
70 Result Read(s64 offset, void* buffer, size_t size) override {
71 R_TRY(ValidateOffset(offset, size, m_size));
72
73 m_memory.ReadBlock(m_trmem->GetSourceAddress(), buffer, size);
74
75 R_SUCCEED();
76 }
77
78 Result Write(s64 offset, const void* buffer, size_t size) override {
79 R_UNLESS(m_is_writable, ResultUnknown);
80 R_TRY(ValidateOffset(offset, size, m_size));
81
82 m_memory.WriteBlock(m_trmem->GetSourceAddress(), buffer, size);
83
84 R_SUCCEED();
85 }
86
87 s64 GetSize() override {
88 return m_size;
89 }
90
91 Kernel::KTransferMemory* GetHandle() override {
92 return nullptr;
93 }
94
95protected:
96 Core::Memory::Memory& m_memory;
97 Kernel::KTransferMemory* m_trmem;
98 bool m_is_writable;
99 s64 m_size;
100};
101
102class HandleLibraryAppletStorage : public TransferMemoryLibraryAppletStorage {
103public:
104 explicit HandleLibraryAppletStorage(Core::Memory::Memory& memory,
105 Kernel::KTransferMemory* trmem, s64 size)
106 : TransferMemoryLibraryAppletStorage(memory, trmem, true, size) {}
107 ~HandleLibraryAppletStorage() = default;
108
109 Kernel::KTransferMemory* GetHandle() override {
110 return m_trmem;
111 }
112};
113
114} // namespace
115
116LibraryAppletStorage::~LibraryAppletStorage() = default;
117
118std::vector<u8> LibraryAppletStorage::GetData() {
119 std::vector<u8> data(this->GetSize());
120 this->Read(0, data.data(), data.size());
121 return data;
122}
123
124std::shared_ptr<LibraryAppletStorage> CreateStorage(std::vector<u8>&& data) {
125 return std::make_shared<BufferLibraryAppletStorage>(std::move(data));
126}
127
128std::shared_ptr<LibraryAppletStorage> CreateTransferMemoryStorage(Core::Memory::Memory& memory,
129 Kernel::KTransferMemory* trmem,
130 bool is_writable, s64 size) {
131 return std::make_shared<TransferMemoryLibraryAppletStorage>(memory, trmem, is_writable, size);
132}
133
134std::shared_ptr<LibraryAppletStorage> CreateHandleStorage(Core::Memory::Memory& memory,
135 Kernel::KTransferMemory* trmem,
136 s64 size) {
137 return std::make_shared<HandleLibraryAppletStorage>(memory, trmem, size);
138}
139
140} // namespace Service::AM
diff --git a/src/core/hle/service/am/library_applet_storage.h b/src/core/hle/service/am/library_applet_storage.h
new file mode 100644
index 000000000..7f53f3a9c
--- /dev/null
+++ b/src/core/hle/service/am/library_applet_storage.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/service.h"
7
8namespace Core::Memory {
9class Memory;
10}
11
12namespace Kernel {
13class KTransferMemory;
14}
15
16namespace Service::AM {
17
18class LibraryAppletStorage {
19public:
20 virtual ~LibraryAppletStorage();
21 virtual Result Read(s64 offset, void* buffer, size_t size) = 0;
22 virtual Result Write(s64 offset, const void* buffer, size_t size) = 0;
23 virtual s64 GetSize() = 0;
24 virtual Kernel::KTransferMemory* GetHandle() = 0;
25
26 std::vector<u8> GetData();
27};
28
29std::shared_ptr<LibraryAppletStorage> CreateStorage(std::vector<u8>&& data);
30std::shared_ptr<LibraryAppletStorage> CreateTransferMemoryStorage(Core::Memory::Memory& memory,
31 Kernel::KTransferMemory* trmem,
32 bool is_writable, s64 size);
33std::shared_ptr<LibraryAppletStorage> CreateHandleStorage(Core::Memory::Memory& memory,
34 Kernel::KTransferMemory* trmem, s64 size);
35
36} // namespace Service::AM
diff --git a/src/core/hle/service/am/managed_layer_holder.cpp b/src/core/hle/service/am/managed_layer_holder.cpp
new file mode 100644
index 000000000..61eb8641a
--- /dev/null
+++ b/src/core/hle/service/am/managed_layer_holder.cpp
@@ -0,0 +1,59 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/managed_layer_holder.h"
5#include "core/hle/service/nvnflinger/nvnflinger.h"
6
7namespace Service::AM {
8
9ManagedLayerHolder::ManagedLayerHolder() = default;
10ManagedLayerHolder::~ManagedLayerHolder() {
11 if (!m_nvnflinger) {
12 return;
13 }
14
15 for (const auto& layer : m_managed_display_layers) {
16 m_nvnflinger->DestroyLayer(layer);
17 }
18
19 for (const auto& layer : m_managed_display_recording_layers) {
20 m_nvnflinger->DestroyLayer(layer);
21 }
22
23 m_nvnflinger = nullptr;
24}
25
26void ManagedLayerHolder::Initialize(Nvnflinger::Nvnflinger* nvnflinger) {
27 m_nvnflinger = nvnflinger;
28}
29
30void ManagedLayerHolder::CreateManagedDisplayLayer(u64* out_layer) {
31 // TODO(Subv): Find out how AM determines the display to use, for now just
32 // create the layer in the Default display.
33 const auto display_id = m_nvnflinger->OpenDisplay("Default");
34 const auto layer_id = m_nvnflinger->CreateLayer(*display_id);
35
36 m_managed_display_layers.emplace(*layer_id);
37
38 *out_layer = *layer_id;
39}
40
41void ManagedLayerHolder::CreateManagedDisplaySeparableLayer(u64* out_layer,
42 u64* out_recording_layer) {
43 // TODO(Subv): Find out how AM determines the display to use, for now just
44 // create the layer in the Default display.
45 // This calls nn::vi::CreateRecordingLayer() which creates another layer.
46 // Currently we do not support more than 1 layer per display, output 1 layer id for now.
47 // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse
48 // side effects.
49 // TODO: Support multiple layers
50 const auto display_id = m_nvnflinger->OpenDisplay("Default");
51 const auto layer_id = m_nvnflinger->CreateLayer(*display_id);
52
53 m_managed_display_layers.emplace(*layer_id);
54
55 *out_layer = *layer_id;
56 *out_recording_layer = 0;
57}
58
59} // namespace Service::AM
diff --git a/src/core/hle/service/am/managed_layer_holder.h b/src/core/hle/service/am/managed_layer_holder.h
new file mode 100644
index 000000000..f7fe03f24
--- /dev/null
+++ b/src/core/hle/service/am/managed_layer_holder.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 <set>
7
8#include "common/common_funcs.h"
9#include "common/common_types.h"
10
11namespace Service::Nvnflinger {
12class Nvnflinger;
13}
14
15namespace Service::AM {
16
17class ManagedLayerHolder {
18public:
19 ManagedLayerHolder();
20 ~ManagedLayerHolder();
21
22 void Initialize(Nvnflinger::Nvnflinger* nvnflinger);
23 void CreateManagedDisplayLayer(u64* out_layer);
24 void CreateManagedDisplaySeparableLayer(u64* out_layer, u64* out_recording_layer);
25
26private:
27 Nvnflinger::Nvnflinger* m_nvnflinger{};
28 std::set<u64> m_managed_display_layers{};
29 std::set<u64> m_managed_display_recording_layers{};
30};
31
32} // namespace Service::AM
diff --git a/src/core/hle/service/am/process.cpp b/src/core/hle/service/am/process.cpp
new file mode 100644
index 000000000..16b685f86
--- /dev/null
+++ b/src/core/hle/service/am/process.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 "common/scope_exit.h"
5
6#include "core/file_sys/nca_metadata.h"
7#include "core/file_sys/registered_cache.h"
8#include "core/hle/kernel/k_process.h"
9#include "core/hle/service/am/process.h"
10#include "core/hle/service/filesystem/filesystem.h"
11#include "core/loader/loader.h"
12
13namespace Service::AM {
14
15Process::Process(Core::System& system)
16 : m_system(system), m_process(), m_main_thread_priority(), m_main_thread_stack_size(),
17 m_program_id(), m_process_started() {}
18
19Process::~Process() {
20 this->Finalize();
21}
22
23bool Process::Initialize(u64 program_id) {
24 // First, ensure we are not holding another process.
25 this->Finalize();
26
27 // Get the filesystem controller.
28 auto& fsc = m_system.GetFileSystemController();
29
30 // Attempt to load program NCA.
31 const FileSys::RegisteredCache* bis_system{};
32 FileSys::VirtualFile nca{};
33
34 // Get the program NCA from built-in storage.
35 bis_system = fsc.GetSystemNANDContents();
36 if (bis_system) {
37 nca = bis_system->GetEntryRaw(program_id, FileSys::ContentRecordType::Program);
38 }
39
40 // Ensure we retrieved a program NCA.
41 if (!nca) {
42 return false;
43 }
44
45 // Get the appropriate loader to parse this NCA.
46 auto app_loader = Loader::GetLoader(m_system, nca, program_id, 0);
47
48 // Ensure we have a loader which can parse the NCA.
49 if (!app_loader) {
50 return false;
51 }
52
53 // Create the process.
54 auto* const process = Kernel::KProcess::Create(m_system.Kernel());
55 Kernel::KProcess::Register(m_system.Kernel(), process);
56
57 // On exit, ensure we free the additional reference to the process.
58 SCOPE_EXIT({ process->Close(); });
59
60 // Insert process modules into memory.
61 const auto [load_result, load_parameters] = app_loader->Load(*process, m_system);
62
63 // Ensure loading was successful.
64 if (load_result != Loader::ResultStatus::Success) {
65 return false;
66 }
67
68 // TODO: remove this, kernel already tracks this
69 m_system.Kernel().AppendNewProcess(process);
70
71 // Note the load parameters from NPDM.
72 m_main_thread_priority = load_parameters->main_thread_priority;
73 m_main_thread_stack_size = load_parameters->main_thread_stack_size;
74
75 // This process has not started yet.
76 m_process_started = false;
77
78 // Take ownership of the process object.
79 m_process = process;
80 m_process->Open();
81
82 // We succeeded.
83 return true;
84}
85
86void Process::Finalize() {
87 // Terminate, if we are currently holding a process.
88 this->Terminate();
89
90 // Close the process.
91 if (m_process) {
92 m_process->Close();
93
94 // TODO: remove this, kernel already tracks this
95 m_system.Kernel().RemoveProcess(m_process);
96 }
97
98 // Clean up.
99 m_process = nullptr;
100 m_main_thread_priority = 0;
101 m_main_thread_stack_size = 0;
102 m_program_id = 0;
103 m_process_started = false;
104}
105
106bool Process::Run() {
107 // If we already started the process, don't start again.
108 if (m_process_started) {
109 return false;
110 }
111
112 // Start.
113 if (m_process) {
114 m_process->Run(m_main_thread_priority, m_main_thread_stack_size);
115 }
116
117 // Mark as started.
118 m_process_started = true;
119
120 // We succeeded.
121 return true;
122}
123
124void Process::Terminate() {
125 if (m_process) {
126 m_process->Terminate();
127 }
128}
129
130u64 Process::GetProcessId() const {
131 if (m_process) {
132 return m_process->GetProcessId();
133 }
134
135 return 0;
136}
137
138} // namespace Service::AM
diff --git a/src/core/hle/service/am/process.h b/src/core/hle/service/am/process.h
new file mode 100644
index 000000000..4b908ade4
--- /dev/null
+++ b/src/core/hle/service/am/process.h
@@ -0,0 +1,50 @@
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/common_funcs.h"
7#include "common/common_types.h"
8
9namespace Kernel {
10class KProcess;
11}
12
13namespace Core {
14class System;
15}
16
17namespace Service::AM {
18
19class Process {
20public:
21 explicit Process(Core::System& system);
22 ~Process();
23
24 bool Initialize(u64 program_id);
25 void Finalize();
26
27 bool Run();
28 void Terminate();
29
30 bool IsInitialized() const {
31 return m_process != nullptr;
32 }
33 u64 GetProcessId() const;
34 u64 GetProgramId() const {
35 return m_program_id;
36 }
37 Kernel::KProcess* GetProcess() const {
38 return m_process;
39 }
40
41private:
42 Core::System& m_system;
43 Kernel::KProcess* m_process{};
44 s32 m_main_thread_priority{};
45 u64 m_main_thread_stack_size{};
46 u64 m_program_id{};
47 bool m_process_started{};
48};
49
50} // namespace Service::AM
diff --git a/src/core/hle/service/am/system_buffer_manager.cpp b/src/core/hle/service/am/system_buffer_manager.cpp
new file mode 100644
index 000000000..7211ef488
--- /dev/null
+++ b/src/core/hle/service/am/system_buffer_manager.cpp
@@ -0,0 +1,49 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/am/system_buffer_manager.h"
5#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
6#include "core/hle/service/nvnflinger/nvnflinger.h"
7
8namespace Service::AM {
9
10SystemBufferManager::SystemBufferManager() = default;
11
12SystemBufferManager::~SystemBufferManager() {
13 if (!m_nvnflinger) {
14 return;
15 }
16
17 // Clean up shared layers.
18 if (m_buffer_sharing_enabled) {
19 }
20}
21
22bool SystemBufferManager::Initialize(Nvnflinger::Nvnflinger* nvnflinger, Kernel::KProcess* process,
23 AppletId applet_id) {
24 if (m_nvnflinger) {
25 return m_buffer_sharing_enabled;
26 }
27
28 m_process = process;
29 m_nvnflinger = nvnflinger;
30 m_buffer_sharing_enabled = false;
31 m_system_shared_buffer_id = 0;
32 m_system_shared_layer_id = 0;
33
34 if (applet_id <= AppletId::Application) {
35 return false;
36 }
37
38 const auto display_id = m_nvnflinger->OpenDisplay("Default").value();
39 const auto res = m_nvnflinger->GetSystemBufferManager().Initialize(
40 &m_system_shared_buffer_id, &m_system_shared_layer_id, display_id);
41
42 if (res.IsSuccess()) {
43 m_buffer_sharing_enabled = true;
44 }
45
46 return m_buffer_sharing_enabled;
47}
48
49} // namespace Service::AM
diff --git a/src/core/hle/service/am/system_buffer_manager.h b/src/core/hle/service/am/system_buffer_manager.h
new file mode 100644
index 000000000..c60d73416
--- /dev/null
+++ b/src/core/hle/service/am/system_buffer_manager.h
@@ -0,0 +1,44 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <set>
7
8#include "common/common_funcs.h"
9#include "common/common_types.h"
10
11#include "core/hle/service/am/am_types.h"
12
13namespace Kernel {
14class KProcess;
15}
16
17namespace Service::Nvnflinger {
18class Nvnflinger;
19}
20
21namespace Service::AM {
22
23class SystemBufferManager {
24public:
25 SystemBufferManager();
26 ~SystemBufferManager();
27
28 bool Initialize(Nvnflinger::Nvnflinger* flinger, Kernel::KProcess* process, AppletId applet_id);
29
30 void GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id,
31 u64* out_system_shared_layer_id) {
32 *out_system_shared_buffer_id = m_system_shared_buffer_id;
33 *out_system_shared_layer_id = m_system_shared_layer_id;
34 }
35
36private:
37 Kernel::KProcess* m_process{};
38 Nvnflinger::Nvnflinger* m_nvnflinger{};
39 bool m_buffer_sharing_enabled{};
40 u64 m_system_shared_buffer_id{};
41 u64 m_system_shared_layer_id{};
42};
43
44} // namespace Service::AM
diff --git a/src/core/hle/service/event.cpp b/src/core/hle/service/event.cpp
new file mode 100644
index 000000000..375660d72
--- /dev/null
+++ b/src/core/hle/service/event.cpp
@@ -0,0 +1,31 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/kernel/k_event.h"
5#include "core/hle/service/event.h"
6#include "core/hle/service/kernel_helpers.h"
7
8namespace Service {
9
10Event::Event(KernelHelpers::ServiceContext& ctx) {
11 m_event = ctx.CreateEvent("Event");
12}
13
14Event::~Event() {
15 m_event->GetReadableEvent().Close();
16 m_event->Close();
17}
18
19void Event::Signal() {
20 m_event->Signal();
21}
22
23void Event::Clear() {
24 m_event->Clear();
25}
26
27Kernel::KReadableEvent* Event::GetHandle() {
28 return &m_event->GetReadableEvent();
29}
30
31} // namespace Service
diff --git a/src/core/hle/service/event.h b/src/core/hle/service/event.h
new file mode 100644
index 000000000..cdbc4635a
--- /dev/null
+++ b/src/core/hle/service/event.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
6namespace Kernel {
7class KEvent;
8class KReadableEvent;
9} // namespace Kernel
10
11namespace Service {
12
13namespace KernelHelpers {
14class ServiceContext;
15}
16
17class Event {
18public:
19 explicit Event(KernelHelpers::ServiceContext& ctx);
20 ~Event();
21
22 void Signal();
23 void Clear();
24
25 Kernel::KReadableEvent* GetHandle();
26
27private:
28 Kernel::KEvent* m_event;
29};
30
31} // namespace Service
diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
index 86e272b41..e71652cdf 100644
--- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
+++ b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
@@ -128,7 +128,7 @@ Result AllocateHandleForBuffer(u32* out_handle, Nvidia::Module& nvdrv, Nvidia::D
128 128
129 // Ensure we maintain a clean state on failure. 129 // Ensure we maintain a clean state on failure.
130 ON_RESULT_FAILURE { 130 ON_RESULT_FAILURE {
131 ASSERT(R_SUCCEEDED(FreeNvMapHandle(*nvmap, *out_handle, nvmap_fd))); 131 R_ASSERT(FreeNvMapHandle(*nvmap, *out_handle, nvmap_fd));
132 }; 132 };
133 133
134 // Assign the allocated memory to the handle. 134 // Assign the allocated memory to the handle.