From 7de6b410305fcfcd34078e62fbe0ceedb43663f9 Mon Sep 17 00:00:00 2001
From: Liam <byteslice@airmail.cc>
Date: Sat, 30 Dec 2023 20:51:23 -0500
Subject: service: split am into components

---
 src/core/hle/service/am/am.cpp                     | 2677 +-------------------
 src/core/hle/service/am/am.h                       |  454 +---
 src/core/hle/service/am/am_results.h               |   14 +
 src/core/hle/service/am/applet_ae.cpp              |  258 +-
 .../hle/service/am/applet_common_functions.cpp     |   47 +
 src/core/hle/service/am/applet_common_functions.h  |   19 +
 src/core/hle/service/am/applet_message_queue.cpp   |   68 +
 src/core/hle/service/am/applet_message_queue.h     |   75 +
 src/core/hle/service/am/applet_oe.cpp              |  100 +-
 src/core/hle/service/am/applets/applet_cabinet.cpp |    6 +-
 .../hle/service/am/applets/applet_controller.cpp   |    1 +
 src/core/hle/service/am/applets/applet_error.cpp   |    1 +
 .../service/am/applets/applet_general_backend.cpp  |    1 +
 .../hle/service/am/applets/applet_mii_edit.cpp     |    1 +
 .../service/am/applets/applet_profile_select.cpp   |    1 +
 .../am/applets/applet_software_keyboard.cpp        |    1 +
 .../hle/service/am/applets/applet_web_browser.cpp  |    1 +
 src/core/hle/service/am/applets/applets.cpp        |    6 +-
 src/core/hle/service/am/application_creator.cpp    |   25 +
 src/core/hle/service/am/application_creator.h      |   16 +
 src/core/hle/service/am/application_functions.cpp  |  610 +++++
 src/core/hle/service/am/application_functions.h    |   63 +
 src/core/hle/service/am/application_proxy.cpp      |  114 +
 src/core/hle/service/am/application_proxy.h        |   32 +
 src/core/hle/service/am/audio_controller.cpp       |   91 +
 src/core/hle/service/am/audio_controller.h         |   36 +
 src/core/hle/service/am/common_state_getter.cpp    |  288 +++
 src/core/hle/service/am/common_state_getter.h      |   78 +
 src/core/hle/service/am/debug_functions.cpp        |   44 +
 src/core/hle/service/am/debug_functions.h          |   16 +
 src/core/hle/service/am/display_controller.cpp     |   97 +
 src/core/hle/service/am/display_controller.h       |   24 +
 .../hle/service/am/global_state_controller.cpp     |   34 +
 src/core/hle/service/am/global_state_controller.h  |   16 +
 src/core/hle/service/am/home_menu_functions.cpp    |   57 +
 src/core/hle/service/am/home_menu_functions.h      |   25 +
 .../hle/service/am/library_applet_accessor.cpp     |  178 ++
 src/core/hle/service/am/library_applet_accessor.h  |   34 +
 src/core/hle/service/am/library_applet_creator.cpp |  145 ++
 src/core/hle/service/am/library_applet_creator.h   |   22 +
 src/core/hle/service/am/library_applet_proxy.cpp   |  142 ++
 src/core/hle/service/am/library_applet_proxy.h     |   35 +
 .../service/am/library_applet_self_accessor.cpp    |  382 +++
 .../hle/service/am/library_applet_self_accessor.h  |   38 +
 src/core/hle/service/am/lock_accessor.cpp          |   71 +
 src/core/hle/service/am/lock_accessor.h            |   28 +
 .../hle/service/am/process_winding_controller.cpp  |   73 +
 .../hle/service/am/process_winding_controller.h    |   20 +
 src/core/hle/service/am/self_controller.cpp        |  438 ++++
 src/core/hle/service/am/self_controller.h          |   72 +
 src/core/hle/service/am/storage.cpp                |   60 +
 src/core/hle/service/am/storage.h                  |   42 +
 src/core/hle/service/am/storage_accessor.cpp       |   82 +
 src/core/hle/service/am/storage_accessor.h         |   24 +
 src/core/hle/service/am/system_applet_proxy.cpp    |  135 +
 src/core/hle/service/am/system_applet_proxy.h      |   34 +
 src/core/hle/service/am/window_controller.cpp      |   55 +
 src/core/hle/service/am/window_controller.h        |   21 +
 58 files changed, 4046 insertions(+), 3482 deletions(-)
 create mode 100644 src/core/hle/service/am/am_results.h
 create mode 100644 src/core/hle/service/am/applet_common_functions.cpp
 create mode 100644 src/core/hle/service/am/applet_common_functions.h
 create mode 100644 src/core/hle/service/am/applet_message_queue.cpp
 create mode 100644 src/core/hle/service/am/applet_message_queue.h
 create mode 100644 src/core/hle/service/am/application_creator.cpp
 create mode 100644 src/core/hle/service/am/application_creator.h
 create mode 100644 src/core/hle/service/am/application_functions.cpp
 create mode 100644 src/core/hle/service/am/application_functions.h
 create mode 100644 src/core/hle/service/am/application_proxy.cpp
 create mode 100644 src/core/hle/service/am/application_proxy.h
 create mode 100644 src/core/hle/service/am/audio_controller.cpp
 create mode 100644 src/core/hle/service/am/audio_controller.h
 create mode 100644 src/core/hle/service/am/common_state_getter.cpp
 create mode 100644 src/core/hle/service/am/common_state_getter.h
 create mode 100644 src/core/hle/service/am/debug_functions.cpp
 create mode 100644 src/core/hle/service/am/debug_functions.h
 create mode 100644 src/core/hle/service/am/display_controller.cpp
 create mode 100644 src/core/hle/service/am/display_controller.h
 create mode 100644 src/core/hle/service/am/global_state_controller.cpp
 create mode 100644 src/core/hle/service/am/global_state_controller.h
 create mode 100644 src/core/hle/service/am/home_menu_functions.cpp
 create mode 100644 src/core/hle/service/am/home_menu_functions.h
 create mode 100644 src/core/hle/service/am/library_applet_accessor.cpp
 create mode 100644 src/core/hle/service/am/library_applet_accessor.h
 create mode 100644 src/core/hle/service/am/library_applet_creator.cpp
 create mode 100644 src/core/hle/service/am/library_applet_creator.h
 create mode 100644 src/core/hle/service/am/library_applet_proxy.cpp
 create mode 100644 src/core/hle/service/am/library_applet_proxy.h
 create mode 100644 src/core/hle/service/am/library_applet_self_accessor.cpp
 create mode 100644 src/core/hle/service/am/library_applet_self_accessor.h
 create mode 100644 src/core/hle/service/am/lock_accessor.cpp
 create mode 100644 src/core/hle/service/am/lock_accessor.h
 create mode 100644 src/core/hle/service/am/process_winding_controller.cpp
 create mode 100644 src/core/hle/service/am/process_winding_controller.h
 create mode 100644 src/core/hle/service/am/self_controller.cpp
 create mode 100644 src/core/hle/service/am/self_controller.h
 create mode 100644 src/core/hle/service/am/storage.cpp
 create mode 100644 src/core/hle/service/am/storage.h
 create mode 100644 src/core/hle/service/am/storage_accessor.cpp
 create mode 100644 src/core/hle/service/am/storage_accessor.h
 create mode 100644 src/core/hle/service/am/system_applet_proxy.cpp
 create mode 100644 src/core/hle/service/am/system_applet_proxy.h
 create mode 100644 src/core/hle/service/am/window_controller.cpp
 create mode 100644 src/core/hle/service/am/window_controller.h

(limited to 'src/core/hle/service/am')

diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 38f67adcd..46bc4f703 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -1,2541 +1,17 @@
 // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 // SPDX-License-Identifier: GPL-2.0-or-later
 
-#include <algorithm>
-#include <array>
-#include <cinttypes>
-#include <cstring>
-#include "common/settings.h"
-#include "common/settings_enums.h"
-#include "core/core.h"
-#include "core/core_timing.h"
-#include "core/file_sys/control_metadata.h"
-#include "core/file_sys/patch_manager.h"
-#include "core/file_sys/registered_cache.h"
-#include "core/file_sys/savedata_factory.h"
-#include "core/hle/kernel/k_event.h"
-#include "core/hle/kernel/k_transfer_memory.h"
-#include "core/hle/result.h"
-#include "core/hle/service/acc/profile_manager.h"
 #include "core/hle/service/am/am.h"
 #include "core/hle/service/am/applet_ae.h"
+#include "core/hle/service/am/applet_message_queue.h"
 #include "core/hle/service/am/applet_oe.h"
-#include "core/hle/service/am/applets/applet_cabinet.h"
-#include "core/hle/service/am/applets/applet_controller.h"
-#include "core/hle/service/am/applets/applet_mii_edit_types.h"
-#include "core/hle/service/am/applets/applet_profile_select.h"
-#include "core/hle/service/am/applets/applet_software_keyboard_types.h"
-#include "core/hle/service/am/applets/applet_web_browser.h"
-#include "core/hle/service/am/applets/applets.h"
 #include "core/hle/service/am/idle.h"
 #include "core/hle/service/am/omm.h"
 #include "core/hle/service/am/spsm.h"
-#include "core/hle/service/apm/apm_controller.h"
-#include "core/hle/service/apm/apm_interface.h"
-#include "core/hle/service/bcat/backend/backend.h"
-#include "core/hle/service/caps/caps_su.h"
-#include "core/hle/service/caps/caps_types.h"
-#include "core/hle/service/filesystem/filesystem.h"
-#include "core/hle/service/filesystem/save_data_controller.h"
-#include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/ns/ns.h"
-#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
-#include "core/hle/service/nvnflinger/nvnflinger.h"
-#include "core/hle/service/pm/pm.h"
 #include "core/hle/service/server_manager.h"
-#include "core/hle/service/sm/sm.h"
-#include "core/hle/service/vi/vi.h"
-#include "core/hle/service/vi/vi_results.h"
-#include "core/memory.h"
-#include "hid_core/hid_types.h"
-#include "hid_core/resources/npad/npad.h"
 
 namespace Service::AM {
 
-constexpr Result ResultNoDataInChannel{ErrorModule::AM, 2};
-constexpr Result ResultNoMessages{ErrorModule::AM, 3};
-constexpr Result ResultInvalidOffset{ErrorModule::AM, 503};
-
-enum class LaunchParameterKind : u32 {
-    UserChannel = 1,
-    AccountPreselectedUser = 2,
-};
-
-constexpr u32 LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC = 0xC79497CA;
-
-struct LaunchParameterAccountPreselectedUser {
-    u32_le magic;
-    u32_le is_account_selected;
-    Common::UUID current_user;
-    INSERT_PADDING_BYTES(0x70);
-};
-static_assert(sizeof(LaunchParameterAccountPreselectedUser) == 0x88);
-
-IWindowController::IWindowController(Core::System& system_)
-    : ServiceFramework{system_, "IWindowController"} {
-    // clang-format off
-    static const FunctionInfo functions[] = {
-        {0, nullptr, "CreateWindow"},
-        {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"},
-        {2, &IWindowController::GetAppletResourceUserIdOfCallerApplet, "GetAppletResourceUserIdOfCallerApplet"},
-        {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"},
-        {11, nullptr, "ReleaseForegroundRights"},
-        {12, nullptr, "RejectToChangeIntoBackground"},
-        {20, nullptr, "SetAppletWindowVisibility"},
-        {21, nullptr, "SetAppletGpuTimeSlice"},
-    };
-    // clang-format on
-
-    RegisterHandlers(functions);
-}
-
-IWindowController::~IWindowController() = default;
-
-void IWindowController::GetAppletResourceUserId(HLERequestContext& ctx) {
-    const u64 process_id = system.ApplicationProcess()->GetProcessId();
-
-    LOG_DEBUG(Service_AM, "called. Process ID=0x{:016X}", process_id);
-
-    IPC::ResponseBuilder rb{ctx, 4};
-    rb.Push(ResultSuccess);
-    rb.Push<u64>(process_id);
-}
-
-void IWindowController::GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx) {
-    const u64 process_id = 0;
-
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 4};
-    rb.Push(ResultSuccess);
-    rb.Push<u64>(process_id);
-}
-
-void IWindowController::AcquireForegroundRights(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-IAudioController::IAudioController(Core::System& system_)
-    : ServiceFramework{system_, "IAudioController"} {
-    // clang-format off
-    static const FunctionInfo functions[] = {
-        {0, &IAudioController::SetExpectedMasterVolume, "SetExpectedMasterVolume"},
-        {1, &IAudioController::GetMainAppletExpectedMasterVolume, "GetMainAppletExpectedMasterVolume"},
-        {2, &IAudioController::GetLibraryAppletExpectedMasterVolume, "GetLibraryAppletExpectedMasterVolume"},
-        {3, &IAudioController::ChangeMainAppletMasterVolume, "ChangeMainAppletMasterVolume"},
-        {4, &IAudioController::SetTransparentAudioRate, "SetTransparentVolumeRate"},
-    };
-    // clang-format on
-
-    RegisterHandlers(functions);
-}
-
-IAudioController::~IAudioController() = default;
-
-void IAudioController::SetExpectedMasterVolume(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-    const float main_applet_volume_tmp = rp.Pop<float>();
-    const float library_applet_volume_tmp = rp.Pop<float>();
-
-    LOG_DEBUG(Service_AM, "called. main_applet_volume={}, library_applet_volume={}",
-              main_applet_volume_tmp, library_applet_volume_tmp);
-
-    // Ensure the volume values remain within the 0-100% range
-    main_applet_volume = std::clamp(main_applet_volume_tmp, min_allowed_volume, max_allowed_volume);
-    library_applet_volume =
-        std::clamp(library_applet_volume_tmp, min_allowed_volume, max_allowed_volume);
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IAudioController::GetMainAppletExpectedMasterVolume(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called. main_applet_volume={}", main_applet_volume);
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.Push(main_applet_volume);
-}
-
-void IAudioController::GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called. library_applet_volume={}", library_applet_volume);
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.Push(library_applet_volume);
-}
-
-void IAudioController::ChangeMainAppletMasterVolume(HLERequestContext& ctx) {
-    struct Parameters {
-        float volume;
-        s64 fade_time_ns;
-    };
-    static_assert(sizeof(Parameters) == 16);
-
-    IPC::RequestParser rp{ctx};
-    const auto parameters = rp.PopRaw<Parameters>();
-
-    LOG_DEBUG(Service_AM, "called. volume={}, fade_time_ns={}", parameters.volume,
-              parameters.fade_time_ns);
-
-    main_applet_volume = std::clamp(parameters.volume, min_allowed_volume, max_allowed_volume);
-    fade_time_ns = std::chrono::nanoseconds{parameters.fade_time_ns};
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IAudioController::SetTransparentAudioRate(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-    const float transparent_volume_rate_tmp = rp.Pop<float>();
-
-    LOG_DEBUG(Service_AM, "called. transparent_volume_rate={}", transparent_volume_rate_tmp);
-
-    // Clamp volume range to 0-100%.
-    transparent_volume_rate =
-        std::clamp(transparent_volume_rate_tmp, min_allowed_volume, max_allowed_volume);
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-IDisplayController::IDisplayController(Core::System& system_)
-    : ServiceFramework{system_, "IDisplayController"} {
-    // clang-format off
-    static const FunctionInfo functions[] = {
-        {0, nullptr, "GetLastForegroundCaptureImage"},
-        {1, nullptr, "UpdateLastForegroundCaptureImage"},
-        {2, nullptr, "GetLastApplicationCaptureImage"},
-        {3, nullptr, "GetCallerAppletCaptureImage"},
-        {4, nullptr, "UpdateCallerAppletCaptureImage"},
-        {5, nullptr, "GetLastForegroundCaptureImageEx"},
-        {6, nullptr, "GetLastApplicationCaptureImageEx"},
-        {7, &IDisplayController::GetCallerAppletCaptureImageEx, "GetCallerAppletCaptureImageEx"},
-        {8, &IDisplayController::TakeScreenShotOfOwnLayer, "TakeScreenShotOfOwnLayer"},
-        {9, nullptr, "CopyBetweenCaptureBuffers"},
-        {10, nullptr, "AcquireLastApplicationCaptureBuffer"},
-        {11, nullptr, "ReleaseLastApplicationCaptureBuffer"},
-        {12, nullptr, "AcquireLastForegroundCaptureBuffer"},
-        {13, nullptr, "ReleaseLastForegroundCaptureBuffer"},
-        {14, nullptr, "AcquireCallerAppletCaptureBuffer"},
-        {15, nullptr, "ReleaseCallerAppletCaptureBuffer"},
-        {16, nullptr, "AcquireLastApplicationCaptureBufferEx"},
-        {17, nullptr, "AcquireLastForegroundCaptureBufferEx"},
-        {18, nullptr, "AcquireCallerAppletCaptureBufferEx"},
-        {20, nullptr, "ClearCaptureBuffer"},
-        {21, nullptr, "ClearAppletTransitionBuffer"},
-        {22, nullptr, "AcquireLastApplicationCaptureSharedBuffer"},
-        {23, nullptr, "ReleaseLastApplicationCaptureSharedBuffer"},
-        {24, &IDisplayController::AcquireLastForegroundCaptureSharedBuffer, "AcquireLastForegroundCaptureSharedBuffer"},
-        {25, &IDisplayController::ReleaseLastForegroundCaptureSharedBuffer, "ReleaseLastForegroundCaptureSharedBuffer"},
-        {26, &IDisplayController::AcquireCallerAppletCaptureSharedBuffer, "AcquireCallerAppletCaptureSharedBuffer"},
-        {27, &IDisplayController::ReleaseCallerAppletCaptureSharedBuffer, "ReleaseCallerAppletCaptureSharedBuffer"},
-        {28, nullptr, "TakeScreenShotOfOwnLayerEx"},
-    };
-    // clang-format on
-
-    RegisterHandlers(functions);
-}
-
-IDisplayController::~IDisplayController() = default;
-
-void IDisplayController::GetCallerAppletCaptureImageEx(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 4};
-    rb.Push(ResultSuccess);
-    rb.Push(1u);
-    rb.Push(0);
-}
-
-void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IDisplayController::AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 4};
-    rb.Push(ResultSuccess);
-    rb.Push(1U);
-    rb.Push(0);
-}
-
-void IDisplayController::ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IDisplayController::AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 4};
-    rb.Push(ResultSuccess);
-    rb.Push(1U);
-    rb.Push(0);
-}
-
-void IDisplayController::ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-IDebugFunctions::IDebugFunctions(Core::System& system_)
-    : ServiceFramework{system_, "IDebugFunctions"} {
-    // clang-format off
-    static const FunctionInfo functions[] = {
-        {0, nullptr, "NotifyMessageToHomeMenuForDebug"},
-        {1, nullptr, "OpenMainApplication"},
-        {10, nullptr, "PerformSystemButtonPressing"},
-        {20, nullptr, "InvalidateTransitionLayer"},
-        {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"},
-        {31, nullptr, "RequestLaunchApplicationByApplicationLaunchInfoForDebug"},
-        {40, nullptr, "GetAppletResourceUsageInfo"},
-        {50, nullptr, "AddSystemProgramIdAndAppletIdForDebug"},
-        {51, nullptr, "AddOperationConfirmedLibraryAppletIdForDebug"},
-        {100, nullptr, "SetCpuBoostModeForApplet"},
-        {101, nullptr, "CancelCpuBoostModeForApplet"},
-        {110, nullptr, "PushToAppletBoundChannelForDebug"},
-        {111, nullptr, "TryPopFromAppletBoundChannelForDebug"},
-        {120, nullptr, "AlarmSettingNotificationEnableAppEventReserve"},
-        {121, nullptr, "AlarmSettingNotificationDisableAppEventReserve"},
-        {122, nullptr, "AlarmSettingNotificationPushAppEventNotify"},
-        {130, nullptr, "FriendInvitationSetApplicationParameter"},
-        {131, nullptr, "FriendInvitationClearApplicationParameter"},
-        {132, nullptr, "FriendInvitationPushApplicationParameter"},
-        {140, nullptr, "RestrictPowerOperationForSecureLaunchModeForDebug"},
-        {200, nullptr, "CreateFloatingLibraryAppletAccepterForDebug"},
-        {300, nullptr, "TerminateAllRunningApplicationsForDebug"},
-        {900, nullptr, "GetGrcProcessLaunchedSystemEvent"},
-    };
-    // clang-format on
-
-    RegisterHandlers(functions);
-}
-
-IDebugFunctions::~IDebugFunctions() = default;
-
-ISelfController::ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_)
-    : ServiceFramework{system_, "ISelfController"}, nvnflinger{nvnflinger_},
-      service_context{system, "ISelfController"} {
-    // clang-format off
-    static const FunctionInfo functions[] = {
-        {0, &ISelfController::Exit, "Exit"},
-        {1, &ISelfController::LockExit, "LockExit"},
-        {2, &ISelfController::UnlockExit, "UnlockExit"},
-        {3, &ISelfController::EnterFatalSection, "EnterFatalSection"},
-        {4, &ISelfController::LeaveFatalSection, "LeaveFatalSection"},
-        {9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"},
-        {10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"},
-        {11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"},
-        {12, &ISelfController::SetPerformanceModeChangedNotification, "SetPerformanceModeChangedNotification"},
-        {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"},
-        {14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"},
-        {15, nullptr, "SetScreenShotAppletIdentityInfo"},
-        {16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"},
-        {17, nullptr, "SetControllerFirmwareUpdateSection"},
-        {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"},
-        {19, &ISelfController::SetAlbumImageOrientation, "SetAlbumImageOrientation"},
-        {20, nullptr, "SetDesirableKeyboardLayout"},
-        {21, nullptr, "GetScreenShotProgramId"},
-        {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
-        {41, &ISelfController::IsSystemBufferSharingEnabled, "IsSystemBufferSharingEnabled"},
-        {42, &ISelfController::GetSystemSharedLayerHandle, "GetSystemSharedLayerHandle"},
-        {43, &ISelfController::GetSystemSharedBufferHandle, "GetSystemSharedBufferHandle"},
-        {44, &ISelfController::CreateManagedDisplaySeparableLayer, "CreateManagedDisplaySeparableLayer"},
-        {45, nullptr, "SetManagedDisplayLayerSeparationMode"},
-        {46, nullptr, "SetRecordingLayerCompositionEnabled"},
-        {50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"},
-        {51, &ISelfController::ApproveToDisplay, "ApproveToDisplay"},
-        {60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"},
-        {61, nullptr, "SetMediaPlaybackState"},
-        {62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"},
-        {63, &ISelfController::GetIdleTimeDetectionExtension, "GetIdleTimeDetectionExtension"},
-        {64, nullptr, "SetInputDetectionSourceSet"},
-        {65, &ISelfController::ReportUserIsActive, "ReportUserIsActive"},
-        {66, nullptr, "GetCurrentIlluminance"},
-        {67, nullptr, "IsIlluminanceAvailable"},
-        {68, &ISelfController::SetAutoSleepDisabled, "SetAutoSleepDisabled"},
-        {69, &ISelfController::IsAutoSleepDisabled, "IsAutoSleepDisabled"},
-        {70, nullptr, "ReportMultimediaError"},
-        {71, nullptr, "GetCurrentIlluminanceEx"},
-        {72, nullptr, "SetInputDetectionPolicy"},
-        {80, nullptr, "SetWirelessPriorityMode"},
-        {90, &ISelfController::GetAccumulatedSuspendedTickValue, "GetAccumulatedSuspendedTickValue"},
-        {91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"},
-        {100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"},
-        {110, nullptr, "SetApplicationAlbumUserData"},
-        {120, &ISelfController::SaveCurrentScreenshot, "SaveCurrentScreenshot"},
-        {130, &ISelfController::SetRecordVolumeMuted, "SetRecordVolumeMuted"},
-        {1000, nullptr, "GetDebugStorageChannel"},
-    };
-    // clang-format on
-
-    RegisterHandlers(functions);
-
-    launchable_event = service_context.CreateEvent("ISelfController:LaunchableEvent");
-
-    // This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is
-    // called. Yuzu can just create it unconditionally, since it doesn't need to support multiple
-    // ISelfControllers. The event is signaled on creation, and on transition from suspended -> not
-    // suspended if the event has previously been created by a call to
-    // GetAccumulatedSuspendedTickChangedEvent.
-
-    accumulated_suspended_tick_changed_event =
-        service_context.CreateEvent("ISelfController:AccumulatedSuspendedTickChangedEvent");
-    accumulated_suspended_tick_changed_event->Signal();
-}
-
-ISelfController::~ISelfController() {
-    service_context.CloseEvent(launchable_event);
-    service_context.CloseEvent(accumulated_suspended_tick_changed_event);
-}
-
-void ISelfController::Exit(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-
-    system.Exit();
-}
-
-void ISelfController::LockExit(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called");
-
-    system.SetExitLocked(true);
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ISelfController::UnlockExit(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called");
-
-    system.SetExitLocked(false);
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-
-    if (system.GetExitRequested()) {
-        system.Exit();
-    }
-}
-
-void ISelfController::EnterFatalSection(HLERequestContext& ctx) {
-    ++num_fatal_sections_entered;
-    LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", num_fatal_sections_entered);
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ISelfController::LeaveFatalSection(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called.");
-
-    // Entry and exit of fatal sections must be balanced.
-    if (num_fatal_sections_entered == 0) {
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(Result{ErrorModule::AM, 512});
-        return;
-    }
-
-    --num_fatal_sections_entered;
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ISelfController::GetLibraryAppletLaunchableEvent(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    launchable_event->Signal();
-
-    IPC::ResponseBuilder rb{ctx, 2, 1};
-    rb.Push(ResultSuccess);
-    rb.PushCopyObjects(launchable_event->GetReadableEvent());
-}
-
-void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-    const auto permission = rp.PopEnum<ScreenshotPermission>();
-    LOG_DEBUG(Service_AM, "called, permission={}", permission);
-
-    screenshot_permission = permission;
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-
-    bool flag = rp.Pop<bool>();
-    LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ISelfController::SetPerformanceModeChangedNotification(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-
-    bool flag = rp.Pop<bool>();
-    LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ISelfController::SetFocusHandlingMode(HLERequestContext& ctx) {
-    // Takes 3 input u8s with each field located immediately after the previous
-    // u8, these are bool flags. No output.
-    IPC::RequestParser rp{ctx};
-
-    struct FocusHandlingModeParams {
-        u8 unknown0;
-        u8 unknown1;
-        u8 unknown2;
-    };
-    const auto flags = rp.PopRaw<FocusHandlingModeParams>();
-
-    LOG_WARNING(Service_AM, "(STUBBED) called. unknown0={}, unknown1={}, unknown2={}",
-                flags.unknown0, flags.unknown1, flags.unknown2);
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ISelfController::SetRestartMessageEnabled(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ISelfController::SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx) {
-    // Takes 3 input u8s with each field located immediately after the previous
-    // u8, these are bool flags. No output.
-    IPC::RequestParser rp{ctx};
-
-    bool enabled = rp.Pop<bool>();
-    LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled);
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ISelfController::CreateManagedDisplayLayer(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    // TODO(Subv): Find out how AM determines the display to use, for now just
-    // create the layer in the Default display.
-    const auto display_id = nvnflinger.OpenDisplay("Default");
-    const auto layer_id = nvnflinger.CreateLayer(*display_id);
-
-    IPC::ResponseBuilder rb{ctx, 4};
-    rb.Push(ResultSuccess);
-    rb.Push(*layer_id);
-}
-
-void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(this->EnsureBufferSharingEnabled());
-}
-
-void ISelfController::GetSystemSharedLayerHandle(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 6};
-    rb.Push(this->EnsureBufferSharingEnabled());
-    rb.Push<s64>(system_shared_buffer_id);
-    rb.Push<s64>(system_shared_layer_id);
-}
-
-void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 4};
-    rb.Push(this->EnsureBufferSharingEnabled());
-    rb.Push<s64>(system_shared_buffer_id);
-}
-
-Result ISelfController::EnsureBufferSharingEnabled() {
-    if (buffer_sharing_enabled) {
-        return ResultSuccess;
-    }
-
-    if (system.GetAppletManager().GetCurrentAppletId() <= Applets::AppletId::Application) {
-        return VI::ResultOperationFailed;
-    }
-
-    const auto display_id = nvnflinger.OpenDisplay("Default");
-    const auto result = nvnflinger.GetSystemBufferManager().Initialize(
-        &system_shared_buffer_id, &system_shared_layer_id, *display_id);
-
-    if (result.IsSuccess()) {
-        buffer_sharing_enabled = true;
-    }
-
-    return result;
-}
-
-void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    // TODO(Subv): Find out how AM determines the display to use, for now just
-    // create the layer in the Default display.
-    // This calls nn::vi::CreateRecordingLayer() which creates another layer.
-    // Currently we do not support more than 1 layer per display, output 1 layer id for now.
-    // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse
-    // side effects.
-    // TODO: Support multiple layers
-    const auto display_id = nvnflinger.OpenDisplay("Default");
-    const auto layer_id = nvnflinger.CreateLayer(*display_id);
-
-    IPC::ResponseBuilder rb{ctx, 4};
-    rb.Push(ResultSuccess);
-    rb.Push(*layer_id);
-}
-
-void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ISelfController::ApproveToDisplay(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-    idle_time_detection_extension = rp.Pop<u32>();
-    LOG_DEBUG(Service_AM, "(STUBBED) called idle_time_detection_extension={}",
-              idle_time_detection_extension);
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ISelfController::GetIdleTimeDetectionExtension(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.Push<u32>(idle_time_detection_extension);
-}
-
-void ISelfController::ReportUserIsActive(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-    is_auto_sleep_disabled = rp.Pop<bool>();
-
-    // On the system itself, if the previous state of is_auto_sleep_disabled
-    // differed from the current value passed in, it'd signify the internal
-    // window manager to update (and also increment some statistics like update counts)
-    //
-    // It'd also indicate this change to an idle handling context.
-    //
-    // However, given we're emulating this behavior, most of this can be ignored
-    // and it's sufficient to simply set the member variable for querying via
-    // IsAutoSleepDisabled().
-
-    LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", is_auto_sleep_disabled);
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ISelfController::IsAutoSleepDisabled(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called.");
-
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.Push(is_auto_sleep_disabled);
-}
-
-void ISelfController::GetAccumulatedSuspendedTickValue(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called.");
-
-    // This command returns the total number of system ticks since ISelfController creation
-    // where the game was suspended. Since Yuzu doesn't implement game suspension, this command
-    // can just always return 0 ticks.
-    IPC::ResponseBuilder rb{ctx, 4};
-    rb.Push(ResultSuccess);
-    rb.Push<u64>(0);
-}
-
-void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called.");
-
-    IPC::ResponseBuilder rb{ctx, 2, 1};
-    rb.Push(ResultSuccess);
-    rb.PushCopyObjects(accumulated_suspended_tick_changed_event->GetReadableEvent());
-}
-
-void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-
-    // This service call sets an internal flag whether a notification is shown when an image is
-    // captured. Currently we do not support capturing images via the capture button, so this can be
-    // stubbed for now.
-    const bool album_image_taken_notification_enabled = rp.Pop<bool>();
-
-    LOG_WARNING(Service_AM, "(STUBBED) called. album_image_taken_notification_enabled={}",
-                album_image_taken_notification_enabled);
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ISelfController::SaveCurrentScreenshot(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-
-    const auto report_option = rp.PopEnum<Capture::AlbumReportOption>();
-
-    LOG_INFO(Service_AM, "called, report_option={}", report_option);
-
-    const auto screenshot_service =
-        system.ServiceManager().GetService<Service::Capture::IScreenShotApplicationService>(
-            "caps:su");
-
-    if (screenshot_service) {
-        screenshot_service->CaptureAndSaveScreenshot(report_option);
-    }
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ISelfController::SetRecordVolumeMuted(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-
-    const auto is_record_volume_muted = rp.Pop<bool>();
-
-    LOG_WARNING(Service_AM, "(STUBBED) called. is_record_volume_muted={}", is_record_volume_muted);
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-AppletMessageQueue::AppletMessageQueue(Core::System& system)
-    : service_context{system, "AppletMessageQueue"} {
-    on_new_message = service_context.CreateEvent("AMMessageQueue:OnMessageReceived");
-    on_operation_mode_changed = service_context.CreateEvent("AMMessageQueue:OperationModeChanged");
-}
-
-AppletMessageQueue::~AppletMessageQueue() {
-    service_context.CloseEvent(on_new_message);
-    service_context.CloseEvent(on_operation_mode_changed);
-}
-
-Kernel::KReadableEvent& AppletMessageQueue::GetMessageReceiveEvent() {
-    return on_new_message->GetReadableEvent();
-}
-
-Kernel::KReadableEvent& AppletMessageQueue::GetOperationModeChangedEvent() {
-    return on_operation_mode_changed->GetReadableEvent();
-}
-
-void AppletMessageQueue::PushMessage(AppletMessage msg) {
-    messages.push(msg);
-    on_new_message->Signal();
-}
-
-AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() {
-    if (messages.empty()) {
-        on_new_message->Clear();
-        return AppletMessage::None;
-    }
-    auto msg = messages.front();
-    messages.pop();
-    if (messages.empty()) {
-        on_new_message->Clear();
-    }
-    return msg;
-}
-
-std::size_t AppletMessageQueue::GetMessageCount() const {
-    return messages.size();
-}
-
-void AppletMessageQueue::RequestExit() {
-    PushMessage(AppletMessage::Exit);
-}
-
-void AppletMessageQueue::RequestResume() {
-    PushMessage(AppletMessage::Resume);
-}
-
-void AppletMessageQueue::FocusStateChanged() {
-    PushMessage(AppletMessage::FocusStateChanged);
-}
-
-void AppletMessageQueue::OperationModeChanged() {
-    PushMessage(AppletMessage::OperationModeChanged);
-    PushMessage(AppletMessage::PerformanceModeChanged);
-    on_operation_mode_changed->Signal();
-}
-
-ILockAccessor::ILockAccessor(Core::System& system_)
-    : ServiceFramework{system_, "ILockAccessor"}, service_context{system_, "ILockAccessor"} {
-    // clang-format off
-        static const FunctionInfo functions[] = {
-            {1, &ILockAccessor::TryLock, "TryLock"},
-            {2, &ILockAccessor::Unlock, "Unlock"},
-            {3, &ILockAccessor::GetEvent, "GetEvent"},
-            {4,&ILockAccessor::IsLocked, "IsLocked"},
-        };
-    // clang-format on
-
-    RegisterHandlers(functions);
-
-    lock_event = service_context.CreateEvent("ILockAccessor::LockEvent");
-}
-
-ILockAccessor::~ILockAccessor() {
-    service_context.CloseEvent(lock_event);
-};
-
-void ILockAccessor::TryLock(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-    const auto return_handle = rp.Pop<bool>();
-
-    LOG_WARNING(Service_AM, "(STUBBED) called, return_handle={}", return_handle);
-
-    // TODO: When return_handle is true this function should return the lock handle
-
-    is_locked = true;
-
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.Push<u8>(is_locked);
-}
-
-void ILockAccessor::Unlock(HLERequestContext& ctx) {
-    LOG_INFO(Service_AM, "called");
-
-    is_locked = false;
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ILockAccessor::GetEvent(HLERequestContext& ctx) {
-    LOG_INFO(Service_AM, "called");
-
-    lock_event->Signal();
-
-    IPC::ResponseBuilder rb{ctx, 2, 1};
-    rb.Push(ResultSuccess);
-    rb.PushCopyObjects(lock_event->GetReadableEvent());
-}
-
-void ILockAccessor::IsLocked(HLERequestContext& ctx) {
-    LOG_INFO(Service_AM, "called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-    rb.Push<u8>(is_locked);
-}
-
-ICommonStateGetter::ICommonStateGetter(Core::System& system_,
-                                       std::shared_ptr<AppletMessageQueue> msg_queue_)
-    : ServiceFramework{system_, "ICommonStateGetter"}, msg_queue{std::move(msg_queue_)},
-      service_context{system_, "ICommonStateGetter"} {
-    // clang-format off
-    static const FunctionInfo functions[] = {
-        {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"},
-        {1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"},
-        {2, nullptr, "GetThisAppletKind"},
-        {3, nullptr, "AllowToEnterSleep"},
-        {4, nullptr, "DisallowToEnterSleep"},
-        {5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"},
-        {6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"},
-        {7, nullptr, "GetCradleStatus"},
-        {8, &ICommonStateGetter::GetBootMode, "GetBootMode"},
-        {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"},
-        {10, &ICommonStateGetter::RequestToAcquireSleepLock, "RequestToAcquireSleepLock"},
-        {11, nullptr, "ReleaseSleepLock"},
-        {12, nullptr, "ReleaseSleepLockTransiently"},
-        {13, &ICommonStateGetter::GetAcquiredSleepLockEvent, "GetAcquiredSleepLockEvent"},
-        {14, nullptr, "GetWakeupCount"},
-        {20, nullptr, "PushToGeneralChannel"},
-        {30, nullptr, "GetHomeButtonReaderLockAccessor"},
-        {31, &ICommonStateGetter::GetReaderLockAccessorEx, "GetReaderLockAccessorEx"},
-        {32, nullptr, "GetWriterLockAccessorEx"},
-        {40, nullptr, "GetCradleFwVersion"},
-        {50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"},
-        {51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"},
-        {52, &ICommonStateGetter::SetLcdBacklighOffEnabled, "SetLcdBacklighOffEnabled"},
-        {53, &ICommonStateGetter::BeginVrModeEx, "BeginVrModeEx"},
-        {54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"},
-        {55, nullptr, "IsInControllerFirmwareUpdateSection"},
-        {59, nullptr, "SetVrPositionForDebug"},
-        {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"},
-        {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"},
-        {62, nullptr, "GetHdcpAuthenticationState"},
-        {63, nullptr, "GetHdcpAuthenticationStateChangeEvent"},
-        {64, nullptr, "SetTvPowerStateMatchingMode"},
-        {65, nullptr, "GetApplicationIdByContentActionName"},
-        {66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"},
-        {67, nullptr, "CancelCpuBoostMode"},
-        {68, &ICommonStateGetter::GetBuiltInDisplayType, "GetBuiltInDisplayType"},
-        {80, &ICommonStateGetter::PerformSystemButtonPressingIfInFocus, "PerformSystemButtonPressingIfInFocus"},
-        {90, nullptr, "SetPerformanceConfigurationChangedNotification"},
-        {91, nullptr, "GetCurrentPerformanceConfiguration"},
-        {100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"},
-        {110, nullptr, "OpenMyGpuErrorHandler"},
-        {120, nullptr, "GetAppletLaunchedHistory"},
-        {200, nullptr, "GetOperationModeSystemInfo"},
-        {300, &ICommonStateGetter::GetSettingsPlatformRegion, "GetSettingsPlatformRegion"},
-        {400, nullptr, "ActivateMigrationService"},
-        {401, nullptr, "DeactivateMigrationService"},
-        {500, nullptr, "DisableSleepTillShutdown"},
-        {501, nullptr, "SuppressDisablingSleepTemporarily"},
-        {502, nullptr, "IsSleepEnabled"},
-        {503, nullptr, "IsDisablingSleepSuppressed"},
-        {900, &ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"},
-    };
-    // clang-format on
-
-    RegisterHandlers(functions);
-
-    sleep_lock_event = service_context.CreateEvent("ICommonStateGetter::SleepLockEvent");
-
-    // Configure applets to be in foreground state
-    msg_queue->PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
-    msg_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
-}
-
-ICommonStateGetter::~ICommonStateGetter() {
-    service_context.CloseEvent(sleep_lock_event);
-};
-
-void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called");
-
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.Push<u8>(static_cast<u8>(Service::PM::SystemBootMode::Normal)); // Normal boot mode
-}
-
-void ICommonStateGetter::GetEventHandle(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called");
-
-    IPC::ResponseBuilder rb{ctx, 2, 1};
-    rb.Push(ResultSuccess);
-    rb.PushCopyObjects(msg_queue->GetMessageReceiveEvent());
-}
-
-void ICommonStateGetter::ReceiveMessage(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called");
-
-    const auto message = msg_queue->PopMessage();
-    IPC::ResponseBuilder rb{ctx, 3};
-
-    if (message == AppletMessageQueue::AppletMessage::None) {
-        LOG_ERROR(Service_AM, "Message queue is empty");
-        rb.Push(AM::ResultNoMessages);
-        rb.PushEnum<AppletMessageQueue::AppletMessage>(message);
-        return;
-    }
-
-    rb.Push(ResultSuccess);
-    rb.PushEnum<AppletMessageQueue::AppletMessage>(message);
-}
-
-void ICommonStateGetter::GetCurrentFocusState(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.Push(static_cast<u8>(FocusState::InFocus));
-}
-
-void ICommonStateGetter::RequestToAcquireSleepLock(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    // Sleep lock is acquired immediately.
-    sleep_lock_event->Signal();
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ICommonStateGetter::GetReaderLockAccessorEx(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-    const auto unknown = rp.Pop<u32>();
-
-    LOG_INFO(Service_AM, "called, unknown={}", unknown);
-
-    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-
-    rb.Push(ResultSuccess);
-    rb.PushIpcInterface<ILockAccessor>(system);
-}
-
-void ICommonStateGetter::GetAcquiredSleepLockEvent(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "called");
-
-    IPC::ResponseBuilder rb{ctx, 2, 1};
-    rb.Push(ResultSuccess);
-    rb.PushCopyObjects(sleep_lock_event->GetReadableEvent());
-}
-
-void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called");
-
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.Push(vr_mode_state);
-}
-
-void ICommonStateGetter::SetVrModeEnabled(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-    vr_mode_state = rp.Pop<bool>();
-
-    LOG_WARNING(Service_AM, "VR Mode is {}", vr_mode_state ? "on" : "off");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ICommonStateGetter::SetLcdBacklighOffEnabled(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-    const auto is_lcd_backlight_off_enabled = rp.Pop<bool>();
-
-    LOG_WARNING(Service_AM, "(STUBBED) called. is_lcd_backlight_off_enabled={}",
-                is_lcd_backlight_off_enabled);
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ICommonStateGetter::BeginVrModeEx(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ICommonStateGetter::EndVrModeEx(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called");
-
-    IPC::ResponseBuilder rb{ctx, 2, 1};
-    rb.Push(ResultSuccess);
-    rb.PushCopyObjects(msg_queue->GetOperationModeChangedEvent());
-}
-
-void ICommonStateGetter::GetDefaultDisplayResolution(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called");
-
-    IPC::ResponseBuilder rb{ctx, 4};
-    rb.Push(ResultSuccess);
-
-    if (Settings::IsDockedMode()) {
-        rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth));
-        rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight));
-    } else {
-        rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth));
-        rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight));
-    }
-}
-
-void ICommonStateGetter::SetCpuBoostMode(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called, forwarding to APM:SYS");
-
-    const auto& sm = system.ServiceManager();
-    const auto apm_sys = sm.GetService<APM::APM_Sys>("apm:sys");
-    ASSERT(apm_sys != nullptr);
-
-    apm_sys->SetCpuBoostMode(ctx);
-}
-
-void ICommonStateGetter::GetBuiltInDisplayType(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.Push(0);
-}
-
-void ICommonStateGetter::PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-    const auto system_button{rp.PopEnum<SystemButtonType>()};
-
-    LOG_WARNING(Service_AM, "(STUBBED) called, system_button={}", system_button);
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ICommonStateGetter::GetSettingsPlatformRegion(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.PushEnum(SysPlatformRegion::Global);
-}
-
-void ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(
-    HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-IStorageImpl::~IStorageImpl() = default;
-
-class StorageDataImpl final : public IStorageImpl {
-public:
-    explicit StorageDataImpl(std::vector<u8>&& buffer_) : buffer{std::move(buffer_)} {}
-
-    std::vector<u8>& GetData() override {
-        return buffer;
-    }
-
-    const std::vector<u8>& GetData() const override {
-        return buffer;
-    }
-
-    std::size_t GetSize() const override {
-        return buffer.size();
-    }
-
-private:
-    std::vector<u8> buffer;
-};
-
-IStorage::IStorage(Core::System& system_, std::vector<u8>&& buffer)
-    : ServiceFramework{system_, "IStorage"}, impl{std::make_shared<StorageDataImpl>(
-                                                 std::move(buffer))} {
-    Register();
-}
-
-void IStorage::Register() {
-    // clang-format off
-        static const FunctionInfo functions[] = {
-            {0, &IStorage::Open, "Open"},
-            {1, nullptr, "OpenTransferStorage"},
-        };
-    // clang-format on
-
-    RegisterHandlers(functions);
-}
-
-IStorage::~IStorage() = default;
-
-void IStorage::Open(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called");
-
-    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-
-    rb.Push(ResultSuccess);
-    rb.PushIpcInterface<IStorageAccessor>(system, *this);
-}
-
-void ICommonStateGetter::GetOperationMode(HLERequestContext& ctx) {
-    const bool use_docked_mode{Settings::IsDockedMode()};
-    LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode);
-
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld));
-}
-
-void ICommonStateGetter::GetPerformanceMode(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called");
-
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.PushEnum(system.GetAPMController().GetCurrentPerformanceMode());
-}
-
-class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
-public:
-    explicit ILibraryAppletAccessor(Core::System& system_, std::shared_ptr<Applets::Applet> applet_)
-        : ServiceFramework{system_, "ILibraryAppletAccessor"}, applet{std::move(applet_)} {
-        // clang-format off
-        static const FunctionInfo functions[] = {
-            {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"},
-            {1, &ILibraryAppletAccessor::IsCompleted, "IsCompleted"},
-            {10, &ILibraryAppletAccessor::Start, "Start"},
-            {20, &ILibraryAppletAccessor::RequestExit, "RequestExit"},
-            {25, nullptr, "Terminate"},
-            {30, &ILibraryAppletAccessor::GetResult, "GetResult"},
-            {50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"},
-            {60, &ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero, "PresetLibraryAppletGpuTimeSliceZero"},
-            {100, &ILibraryAppletAccessor::PushInData, "PushInData"},
-            {101, &ILibraryAppletAccessor::PopOutData, "PopOutData"},
-            {102, nullptr, "PushExtraStorage"},
-            {103, &ILibraryAppletAccessor::PushInteractiveInData, "PushInteractiveInData"},
-            {104, &ILibraryAppletAccessor::PopInteractiveOutData, "PopInteractiveOutData"},
-            {105, &ILibraryAppletAccessor::GetPopOutDataEvent, "GetPopOutDataEvent"},
-            {106, &ILibraryAppletAccessor::GetPopInteractiveOutDataEvent, "GetPopInteractiveOutDataEvent"},
-            {110, nullptr, "NeedsToExitProcess"},
-            {120, nullptr, "GetLibraryAppletInfo"},
-            {150, nullptr, "RequestForAppletToGetForeground"},
-            {160, &ILibraryAppletAccessor::GetIndirectLayerConsumerHandle, "GetIndirectLayerConsumerHandle"},
-        };
-        // clang-format on
-
-        RegisterHandlers(functions);
-    }
-
-private:
-    void GetAppletStateChangedEvent(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 1};
-        rb.Push(ResultSuccess);
-        rb.PushCopyObjects(applet->GetBroker().GetStateChangedEvent());
-    }
-
-    void IsCompleted(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 3};
-        rb.Push(ResultSuccess);
-        rb.Push<u32>(applet->TransactionComplete());
-    }
-
-    void GetResult(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(applet->GetStatus());
-    }
-
-    void PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx) {
-        LOG_WARNING(Service_AM, "(STUBBED) called");
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ResultSuccess);
-    }
-
-    void Start(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        ASSERT(applet != nullptr);
-
-        applet->Initialize();
-        applet->Execute();
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ResultSuccess);
-    }
-
-    void RequestExit(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        ASSERT(applet != nullptr);
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(applet->RequestExit());
-    }
-
-    void PushInData(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::RequestParser rp{ctx};
-        applet->GetBroker().PushNormalDataFromGame(rp.PopIpcInterface<IStorage>().lock());
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ResultSuccess);
-    }
-
-    void PopOutData(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        auto storage = applet->GetBroker().PopNormalDataToGame();
-        if (storage == nullptr) {
-            LOG_DEBUG(Service_AM,
-                      "storage is a nullptr. There is no data in the current normal channel");
-            IPC::ResponseBuilder rb{ctx, 2};
-            rb.Push(AM::ResultNoDataInChannel);
-            return;
-        }
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IStorage>(std::move(storage));
-    }
-
-    void PushInteractiveInData(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::RequestParser rp{ctx};
-        applet->GetBroker().PushInteractiveDataFromGame(rp.PopIpcInterface<IStorage>().lock());
-
-        ASSERT(applet->IsInitialized());
-        applet->ExecuteInteractive();
-        applet->Execute();
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ResultSuccess);
-    }
-
-    void PopInteractiveOutData(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        auto storage = applet->GetBroker().PopInteractiveDataToGame();
-        if (storage == nullptr) {
-            LOG_DEBUG(Service_AM,
-                      "storage is a nullptr. There is no data in the current interactive channel");
-            IPC::ResponseBuilder rb{ctx, 2};
-            rb.Push(AM::ResultNoDataInChannel);
-            return;
-        }
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IStorage>(std::move(storage));
-    }
-
-    void GetPopOutDataEvent(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 1};
-        rb.Push(ResultSuccess);
-        rb.PushCopyObjects(applet->GetBroker().GetNormalDataEvent());
-    }
-
-    void GetPopInteractiveOutDataEvent(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 1};
-        rb.Push(ResultSuccess);
-        rb.PushCopyObjects(applet->GetBroker().GetInteractiveDataEvent());
-    }
-
-    void GetIndirectLayerConsumerHandle(HLERequestContext& ctx) {
-        LOG_WARNING(Service_AM, "(STUBBED) called");
-
-        // We require a non-zero handle to be valid. Using 0xdeadbeef allows us to trace if this is
-        // actually used anywhere
-        constexpr u64 handle = 0xdeadbeef;
-
-        IPC::ResponseBuilder rb{ctx, 4};
-        rb.Push(ResultSuccess);
-        rb.Push(handle);
-    }
-
-    std::shared_ptr<Applets::Applet> applet;
-};
-
-IStorageAccessor::IStorageAccessor(Core::System& system_, IStorage& backing_)
-    : ServiceFramework{system_, "IStorageAccessor"}, backing{backing_} {
-    // clang-format off
-        static const FunctionInfo functions[] = {
-            {0, &IStorageAccessor::GetSize, "GetSize"},
-            {10, &IStorageAccessor::Write, "Write"},
-            {11, &IStorageAccessor::Read, "Read"},
-        };
-    // clang-format on
-
-    RegisterHandlers(functions);
-}
-
-IStorageAccessor::~IStorageAccessor() = default;
-
-void IStorageAccessor::GetSize(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called");
-
-    IPC::ResponseBuilder rb{ctx, 4};
-
-    rb.Push(ResultSuccess);
-    rb.Push(static_cast<u64>(backing.GetSize()));
-}
-
-void IStorageAccessor::Write(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-
-    const u64 offset{rp.Pop<u64>()};
-    const auto data{ctx.ReadBuffer()};
-    const std::size_t size{std::min<u64>(data.size(), backing.GetSize() - offset)};
-
-    LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size);
-
-    if (offset > backing.GetSize()) {
-        LOG_ERROR(Service_AM,
-                  "offset is out of bounds, backing_buffer_sz={}, data_size={}, offset={}",
-                  backing.GetSize(), size, offset);
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(AM::ResultInvalidOffset);
-        return;
-    }
-
-    std::memcpy(backing.GetData().data() + offset, data.data(), size);
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IStorageAccessor::Read(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-
-    const u64 offset{rp.Pop<u64>()};
-    const std::size_t size{std::min<u64>(ctx.GetWriteBufferSize(), backing.GetSize() - offset)};
-
-    LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size);
-
-    if (offset > backing.GetSize()) {
-        LOG_ERROR(Service_AM, "offset is out of bounds, backing_buffer_sz={}, size={}, offset={}",
-                  backing.GetSize(), size, offset);
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(AM::ResultInvalidOffset);
-        return;
-    }
-
-    ctx.WriteBuffer(backing.GetData().data() + offset, size);
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_)
-    : ServiceFramework{system_, "ILibraryAppletCreator"} {
-    static const FunctionInfo functions[] = {
-        {0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"},
-        {1, nullptr, "TerminateAllLibraryApplets"},
-        {2, nullptr, "AreAnyLibraryAppletsLeft"},
-        {10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"},
-        {11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"},
-        {12, &ILibraryAppletCreator::CreateHandleStorage, "CreateHandleStorage"},
-    };
-    RegisterHandlers(functions);
-}
-
-ILibraryAppletCreator::~ILibraryAppletCreator() = default;
-
-void ILibraryAppletCreator::CreateLibraryApplet(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-
-    const auto applet_id = rp.PopRaw<Applets::AppletId>();
-    const auto applet_mode = rp.PopRaw<Applets::LibraryAppletMode>();
-
-    LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id,
-              applet_mode);
-
-    const auto& applet_manager{system.GetAppletManager()};
-    const auto applet = applet_manager.GetApplet(applet_id, applet_mode);
-
-    if (applet == nullptr) {
-        LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ResultUnknown);
-        return;
-    }
-
-    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-
-    rb.Push(ResultSuccess);
-    rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet);
-}
-
-void ILibraryAppletCreator::CreateStorage(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-
-    const s64 size{rp.Pop<s64>()};
-
-    LOG_DEBUG(Service_AM, "called, size={}", size);
-
-    if (size <= 0) {
-        LOG_ERROR(Service_AM, "size is less than or equal to 0");
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ResultUnknown);
-        return;
-    }
-
-    std::vector<u8> buffer(size);
-
-    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-    rb.Push(ResultSuccess);
-    rb.PushIpcInterface<IStorage>(system, std::move(buffer));
-}
-
-void ILibraryAppletCreator::CreateTransferMemoryStorage(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-
-    struct Parameters {
-        u8 permissions;
-        s64 size;
-    };
-
-    const auto parameters{rp.PopRaw<Parameters>()};
-    const auto handle{ctx.GetCopyHandle(0)};
-
-    LOG_DEBUG(Service_AM, "called, permissions={}, size={}, handle={:08X}", parameters.permissions,
-              parameters.size, handle);
-
-    if (parameters.size <= 0) {
-        LOG_ERROR(Service_AM, "size is less than or equal to 0");
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ResultUnknown);
-        return;
-    }
-
-    auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle);
-
-    if (transfer_mem.IsNull()) {
-        LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ResultUnknown);
-        return;
-    }
-
-    std::vector<u8> memory(transfer_mem->GetSize());
-    ctx.GetMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size());
-
-    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-    rb.Push(ResultSuccess);
-    rb.PushIpcInterface<IStorage>(system, std::move(memory));
-}
-
-void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-
-    const s64 size{rp.Pop<s64>()};
-    const auto handle{ctx.GetCopyHandle(0)};
-
-    LOG_DEBUG(Service_AM, "called, size={}, handle={:08X}", size, handle);
-
-    if (size <= 0) {
-        LOG_ERROR(Service_AM, "size is less than or equal to 0");
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ResultUnknown);
-        return;
-    }
-
-    auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle);
-
-    if (transfer_mem.IsNull()) {
-        LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ResultUnknown);
-        return;
-    }
-
-    std::vector<u8> memory(transfer_mem->GetSize());
-    ctx.GetMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size());
-
-    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-    rb.Push(ResultSuccess);
-    rb.PushIpcInterface<IStorage>(system, std::move(memory));
-}
-
-ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
-    : ServiceFramework{system_, "ILibraryAppletSelfAccessor"} {
-    // clang-format off
-    static const FunctionInfo functions[] = {
-        {0, &ILibraryAppletSelfAccessor::PopInData, "PopInData"},
-        {1, &ILibraryAppletSelfAccessor::PushOutData, "PushOutData"},
-        {2, nullptr, "PopInteractiveInData"},
-        {3, nullptr, "PushInteractiveOutData"},
-        {5, nullptr, "GetPopInDataEvent"},
-        {6, nullptr, "GetPopInteractiveInDataEvent"},
-        {10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"},
-        {11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"},
-        {12, &ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo, "GetMainAppletIdentityInfo"},
-        {13, nullptr, "CanUseApplicationCore"},
-        {14, &ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo, "GetCallerAppletIdentityInfo"},
-        {15, nullptr, "GetMainAppletApplicationControlProperty"},
-        {16, nullptr, "GetMainAppletStorageId"},
-        {17, nullptr, "GetCallerAppletIdentityInfoStack"},
-        {18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"},
-        {19, &ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout, "GetDesirableKeyboardLayout"},
-        {20, nullptr, "PopExtraStorage"},
-        {25, nullptr, "GetPopExtraStorageEvent"},
-        {30, nullptr, "UnpopInData"},
-        {31, nullptr, "UnpopExtraStorage"},
-        {40, nullptr, "GetIndirectLayerProducerHandle"},
-        {50, nullptr, "ReportVisibleError"},
-        {51, nullptr, "ReportVisibleErrorWithErrorContext"},
-        {60, nullptr, "GetMainAppletApplicationDesiredLanguage"},
-        {70, nullptr, "GetCurrentApplicationId"},
-        {80, nullptr, "RequestExitToSelf"},
-        {90, nullptr, "CreateApplicationAndPushAndRequestToLaunch"},
-        {100, nullptr, "CreateGameMovieTrimmer"},
-        {101, nullptr, "ReserveResourceForMovieOperation"},
-        {102, nullptr, "UnreserveResourceForMovieOperation"},
-        {110, &ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers, "GetMainAppletAvailableUsers"},
-        {120, nullptr, "GetLaunchStorageInfoForDebug"},
-        {130, nullptr, "GetGpuErrorDetectedSystemEvent"},
-        {140, nullptr, "SetApplicationMemoryReservation"},
-        {150, &ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually, "ShouldSetGpuTimeSliceManually"},
-    };
-    // clang-format on
-    RegisterHandlers(functions);
-
-    switch (system.GetAppletManager().GetCurrentAppletId()) {
-    case Applets::AppletId::Cabinet:
-        PushInShowCabinetData();
-        break;
-    case Applets::AppletId::MiiEdit:
-        PushInShowMiiEditData();
-        break;
-    case Applets::AppletId::PhotoViewer:
-        PushInShowAlbum();
-        break;
-    case Applets::AppletId::SoftwareKeyboard:
-        PushInShowSoftwareKeyboard();
-        break;
-    case Applets::AppletId::Controller:
-        PushInShowController();
-        break;
-    default:
-        break;
-    }
-}
-
-ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default;
-void ILibraryAppletSelfAccessor::PopInData(HLERequestContext& ctx) {
-    LOG_INFO(Service_AM, "called");
-
-    if (queue_data.empty()) {
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ResultNoDataInChannel);
-        return;
-    }
-
-    auto data = queue_data.front();
-    queue_data.pop_front();
-
-    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-    rb.Push(ResultSuccess);
-    rb.PushIpcInterface<IStorage>(system, std::move(data));
-}
-
-void ILibraryAppletSelfAccessor::PushOutData(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ILibraryAppletSelfAccessor::ExitProcessAndReturn(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    system.Exit();
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) {
-    struct LibraryAppletInfo {
-        Applets::AppletId applet_id;
-        Applets::LibraryAppletMode library_applet_mode;
-    };
-
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    const LibraryAppletInfo applet_info{
-        .applet_id = system.GetAppletManager().GetCurrentAppletId(),
-        .library_applet_mode = Applets::LibraryAppletMode::AllForeground,
-    };
-
-    IPC::ResponseBuilder rb{ctx, 4};
-    rb.Push(ResultSuccess);
-    rb.PushRaw(applet_info);
-}
-
-void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ctx) {
-    struct AppletIdentityInfo {
-        Applets::AppletId applet_id;
-        INSERT_PADDING_BYTES(0x4);
-        u64 application_id;
-    };
-    static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size.");
-
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    const AppletIdentityInfo applet_info{
-        .applet_id = Applets::AppletId::QLaunch,
-        .application_id = 0x0100000000001000ull,
-    };
-
-    IPC::ResponseBuilder rb{ctx, 6};
-    rb.Push(ResultSuccess);
-    rb.PushRaw(applet_info);
-}
-
-void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) {
-    struct AppletIdentityInfo {
-        Applets::AppletId applet_id;
-        INSERT_PADDING_BYTES(0x4);
-        u64 application_id;
-    };
-    static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size.");
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    const AppletIdentityInfo applet_info{
-        .applet_id = Applets::AppletId::QLaunch,
-        .application_id = 0x0100000000001000ull,
-    };
-
-    IPC::ResponseBuilder rb{ctx, 6};
-    rb.Push(ResultSuccess);
-    rb.PushRaw(applet_info);
-}
-
-void ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.Push<u32>(0);
-}
-
-void ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(HLERequestContext& ctx) {
-    const Service::Account::ProfileManager manager{};
-    bool is_empty{true};
-    s32 user_count{-1};
-
-    LOG_INFO(Service_AM, "called");
-
-    if (manager.GetUserCount() > 0) {
-        is_empty = false;
-        user_count = static_cast<s32>(manager.GetUserCount());
-        ctx.WriteBuffer(manager.GetAllUsers());
-    }
-
-    IPC::ResponseBuilder rb{ctx, 4};
-    rb.Push(ResultSuccess);
-    rb.Push<u8>(is_empty);
-    rb.Push(user_count);
-}
-
-void ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-    rb.Push<u8>(0);
-}
-
-void ILibraryAppletSelfAccessor::PushInShowAlbum() {
-    const Applets::CommonArguments arguments{
-        .arguments_version = Applets::CommonArgumentVersion::Version3,
-        .size = Applets::CommonArgumentSize::Version3,
-        .library_version = 1,
-        .theme_color = Applets::ThemeColor::BasicBlack,
-        .play_startup_sound = true,
-        .system_tick = system.CoreTiming().GetClockTicks(),
-    };
-
-    std::vector<u8> argument_data(sizeof(arguments));
-    std::vector<u8> settings_data{2};
-    std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
-    queue_data.emplace_back(std::move(argument_data));
-    queue_data.emplace_back(std::move(settings_data));
-}
-
-void ILibraryAppletSelfAccessor::PushInShowController() {
-    const Applets::CommonArguments common_args = {
-        .arguments_version = Applets::CommonArgumentVersion::Version3,
-        .size = Applets::CommonArgumentSize::Version3,
-        .library_version = static_cast<u32>(Applets::ControllerAppletVersion::Version8),
-        .theme_color = Applets::ThemeColor::BasicBlack,
-        .play_startup_sound = true,
-        .system_tick = system.CoreTiming().GetClockTicks(),
-    };
-
-    Applets::ControllerSupportArgNew user_args = {
-        .header = {.player_count_min = 1,
-                   .player_count_max = 4,
-                   .enable_take_over_connection = true,
-                   .enable_left_justify = false,
-                   .enable_permit_joy_dual = true,
-                   .enable_single_mode = false,
-                   .enable_identification_color = false},
-        .identification_colors = {},
-        .enable_explain_text = false,
-        .explain_text = {},
-    };
-
-    Applets::ControllerSupportArgPrivate private_args = {
-        .arg_private_size = sizeof(Applets::ControllerSupportArgPrivate),
-        .arg_size = sizeof(Applets::ControllerSupportArgNew),
-        .is_home_menu = true,
-        .flag_1 = true,
-        .mode = Applets::ControllerSupportMode::ShowControllerSupport,
-        .caller = Applets::ControllerSupportCaller::
-            Application, // switchbrew: Always zero except with
-                         // ShowControllerFirmwareUpdateForSystem/ShowControllerKeyRemappingForSystem,
-                         // which sets this to the input param
-        .style_set = Core::HID::NpadStyleSet::None,
-        .joy_hold_type = 0,
-    };
-    std::vector<u8> common_args_data(sizeof(common_args));
-    std::vector<u8> private_args_data(sizeof(private_args));
-    std::vector<u8> user_args_data(sizeof(user_args));
-
-    std::memcpy(common_args_data.data(), &common_args, sizeof(common_args));
-    std::memcpy(private_args_data.data(), &private_args, sizeof(private_args));
-    std::memcpy(user_args_data.data(), &user_args, sizeof(user_args));
-
-    queue_data.emplace_back(std::move(common_args_data));
-    queue_data.emplace_back(std::move(private_args_data));
-    queue_data.emplace_back(std::move(user_args_data));
-}
-
-void ILibraryAppletSelfAccessor::PushInShowCabinetData() {
-    const Applets::CommonArguments arguments{
-        .arguments_version = Applets::CommonArgumentVersion::Version3,
-        .size = Applets::CommonArgumentSize::Version3,
-        .library_version = static_cast<u32>(Applets::CabinetAppletVersion::Version1),
-        .theme_color = Applets::ThemeColor::BasicBlack,
-        .play_startup_sound = true,
-        .system_tick = system.CoreTiming().GetClockTicks(),
-    };
-
-    const Applets::StartParamForAmiiboSettings amiibo_settings{
-        .param_1 = 0,
-        .applet_mode = system.GetAppletManager().GetCabinetMode(),
-        .flags = Applets::CabinetFlags::None,
-        .amiibo_settings_1 = 0,
-        .device_handle = 0,
-        .tag_info{},
-        .register_info{},
-        .amiibo_settings_3{},
-    };
-
-    std::vector<u8> argument_data(sizeof(arguments));
-    std::vector<u8> settings_data(sizeof(amiibo_settings));
-    std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
-    std::memcpy(settings_data.data(), &amiibo_settings, sizeof(amiibo_settings));
-    queue_data.emplace_back(std::move(argument_data));
-    queue_data.emplace_back(std::move(settings_data));
-}
-
-void ILibraryAppletSelfAccessor::PushInShowMiiEditData() {
-    struct MiiEditV3 {
-        Applets::MiiEditAppletInputCommon common;
-        Applets::MiiEditAppletInputV3 input;
-    };
-    static_assert(sizeof(MiiEditV3) == 0x100, "MiiEditV3 has incorrect size.");
-
-    MiiEditV3 mii_arguments{
-        .common =
-            {
-                .version = Applets::MiiEditAppletVersion::Version3,
-                .applet_mode = Applets::MiiEditAppletMode::ShowMiiEdit,
-            },
-        .input{},
-    };
-
-    std::vector<u8> argument_data(sizeof(mii_arguments));
-    std::memcpy(argument_data.data(), &mii_arguments, sizeof(mii_arguments));
-
-    queue_data.emplace_back(std::move(argument_data));
-}
-
-void ILibraryAppletSelfAccessor::PushInShowSoftwareKeyboard() {
-    const Applets::CommonArguments arguments{
-        .arguments_version = Applets::CommonArgumentVersion::Version3,
-        .size = Applets::CommonArgumentSize::Version3,
-        .library_version = static_cast<u32>(Applets::SwkbdAppletVersion::Version524301),
-        .theme_color = Applets::ThemeColor::BasicBlack,
-        .play_startup_sound = true,
-        .system_tick = system.CoreTiming().GetClockTicks(),
-    };
-
-    std::vector<char16_t> initial_string(0);
-
-    const Applets::SwkbdConfigCommon swkbd_config{
-        .type = Applets::SwkbdType::Qwerty,
-        .ok_text{},
-        .left_optional_symbol_key{},
-        .right_optional_symbol_key{},
-        .use_prediction = false,
-        .key_disable_flags{},
-        .initial_cursor_position = Applets::SwkbdInitialCursorPosition::Start,
-        .header_text{},
-        .sub_text{},
-        .guide_text{},
-        .max_text_length = 500,
-        .min_text_length = 0,
-        .password_mode = Applets::SwkbdPasswordMode::Disabled,
-        .text_draw_type = Applets::SwkbdTextDrawType::Box,
-        .enable_return_button = true,
-        .use_utf8 = false,
-        .use_blur_background = true,
-        .initial_string_offset{},
-        .initial_string_length = static_cast<u32>(initial_string.size()),
-        .user_dictionary_offset{},
-        .user_dictionary_entries{},
-        .use_text_check = false,
-    };
-
-    Applets::SwkbdConfigNew swkbd_config_new{};
-
-    std::vector<u8> argument_data(sizeof(arguments));
-    std::vector<u8> swkbd_data(sizeof(swkbd_config) + sizeof(swkbd_config_new));
-    std::vector<u8> work_buffer(swkbd_config.initial_string_length * sizeof(char16_t));
-
-    std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
-    std::memcpy(swkbd_data.data(), &swkbd_config, sizeof(swkbd_config));
-    std::memcpy(swkbd_data.data() + sizeof(swkbd_config), &swkbd_config_new,
-                sizeof(Applets::SwkbdConfigNew));
-    std::memcpy(work_buffer.data(), initial_string.data(),
-                swkbd_config.initial_string_length * sizeof(char16_t));
-
-    queue_data.emplace_back(std::move(argument_data));
-    queue_data.emplace_back(std::move(swkbd_data));
-    queue_data.emplace_back(std::move(work_buffer));
-}
-
-IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_)
-    : ServiceFramework{system_, "IAppletCommonFunctions"} {
-    // clang-format off
-    static const FunctionInfo functions[] = {
-        {0, nullptr, "SetTerminateResult"},
-        {10, nullptr, "ReadThemeStorage"},
-        {11, nullptr, "WriteThemeStorage"},
-        {20, nullptr, "PushToAppletBoundChannel"},
-        {21, nullptr, "TryPopFromAppletBoundChannel"},
-        {40, nullptr, "GetDisplayLogicalResolution"},
-        {42, nullptr, "SetDisplayMagnification"},
-        {50, nullptr, "SetHomeButtonDoubleClickEnabled"},
-        {51, nullptr, "GetHomeButtonDoubleClickEnabled"},
-        {52, nullptr, "IsHomeButtonShortPressedBlocked"},
-        {60, nullptr, "IsVrModeCurtainRequired"},
-        {61, nullptr, "IsSleepRequiredByHighTemperature"},
-        {62, nullptr, "IsSleepRequiredByLowBattery"},
-        {70, &IAppletCommonFunctions::SetCpuBoostRequestPriority, "SetCpuBoostRequestPriority"},
-        {80, nullptr, "SetHandlingCaptureButtonShortPressedMessageEnabledForApplet"},
-        {81, nullptr, "SetHandlingCaptureButtonLongPressedMessageEnabledForApplet"},
-        {90, nullptr, "OpenNamedChannelAsParent"},
-        {91, nullptr, "OpenNamedChannelAsChild"},
-        {100, nullptr, "SetApplicationCoreUsageMode"},
-    };
-    // clang-format on
-
-    RegisterHandlers(functions);
-}
-
-IAppletCommonFunctions::~IAppletCommonFunctions() = default;
-
-void IAppletCommonFunctions::SetCpuBoostRequestPriority(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-IApplicationFunctions::IApplicationFunctions(Core::System& system_)
-    : ServiceFramework{system_, "IApplicationFunctions"}, service_context{system,
-                                                                          "IApplicationFunctions"} {
-    // clang-format off
-    static const FunctionInfo functions[] = {
-        {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"},
-        {10, nullptr, "CreateApplicationAndPushAndRequestToStart"},
-        {11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"},
-        {12, nullptr, "CreateApplicationAndRequestToStart"},
-        {13, &IApplicationFunctions::CreateApplicationAndRequestToStartForQuest, "CreateApplicationAndRequestToStartForQuest"},
-        {14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"},
-        {15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"},
-        {20, &IApplicationFunctions::EnsureSaveData, "EnsureSaveData"},
-        {21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"},
-        {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
-        {23, &IApplicationFunctions::GetDisplayVersion, "GetDisplayVersion"},
-        {24, nullptr, "GetLaunchStorageInfoForDebug"},
-        {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"},
-        {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"},
-        {27, &IApplicationFunctions::CreateCacheStorage, "CreateCacheStorage"},
-        {28, &IApplicationFunctions::GetSaveDataSizeMax, "GetSaveDataSizeMax"},
-        {29, nullptr, "GetCacheStorageMax"},
-        {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"},
-        {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"},
-        {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"},
-        {33, &IApplicationFunctions::EndBlockingHomeButton, "EndBlockingHomeButton"},
-        {34, nullptr, "SelectApplicationLicense"},
-        {35, nullptr, "GetDeviceSaveDataSizeMax"},
-        {36, nullptr, "GetLimitedApplicationLicense"},
-        {37, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"},
-        {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"},
-        {50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"},
-        {60, nullptr, "SetMediaPlaybackStateForApplication"},
-        {65, &IApplicationFunctions::IsGamePlayRecordingSupported, "IsGamePlayRecordingSupported"},
-        {66, &IApplicationFunctions::InitializeGamePlayRecording, "InitializeGamePlayRecording"},
-        {67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"},
-        {68, nullptr, "RequestFlushGamePlayingMovieForDebug"},
-        {70, nullptr, "RequestToShutdown"},
-        {71, nullptr, "RequestToReboot"},
-        {72, nullptr, "RequestToSleep"},
-        {80, nullptr, "ExitAndRequestToShowThanksMessage"},
-        {90, &IApplicationFunctions::EnableApplicationCrashReport, "EnableApplicationCrashReport"},
-        {100, &IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer, "InitializeApplicationCopyrightFrameBuffer"},
-        {101, &IApplicationFunctions::SetApplicationCopyrightImage, "SetApplicationCopyrightImage"},
-        {102, &IApplicationFunctions::SetApplicationCopyrightVisibility, "SetApplicationCopyrightVisibility"},
-        {110, &IApplicationFunctions::QueryApplicationPlayStatistics, "QueryApplicationPlayStatistics"},
-        {111, &IApplicationFunctions::QueryApplicationPlayStatisticsByUid, "QueryApplicationPlayStatisticsByUid"},
-        {120, &IApplicationFunctions::ExecuteProgram, "ExecuteProgram"},
-        {121, &IApplicationFunctions::ClearUserChannel, "ClearUserChannel"},
-        {122, &IApplicationFunctions::UnpopToUserChannel, "UnpopToUserChannel"},
-        {123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"},
-        {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
-        {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"},
-        {131, nullptr, "SetDelayTimeToAbortOnGpuError"},
-        {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"},
-        {141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"},
-        {150, &IApplicationFunctions::GetNotificationStorageChannelEvent, "GetNotificationStorageChannelEvent"},
-        {151, nullptr, "TryPopFromNotificationStorageChannel"},
-        {160, &IApplicationFunctions::GetHealthWarningDisappearedSystemEvent, "GetHealthWarningDisappearedSystemEvent"},
-        {170, nullptr, "SetHdcpAuthenticationActivated"},
-        {180, nullptr, "GetLaunchRequiredVersion"},
-        {181, nullptr, "UpgradeLaunchRequiredVersion"},
-        {190, nullptr, "SendServerMaintenanceOverlayNotification"},
-        {200, nullptr, "GetLastApplicationExitReason"},
-        {500, nullptr, "StartContinuousRecordingFlushForDebug"},
-        {1000, nullptr, "CreateMovieMaker"},
-        {1001, &IApplicationFunctions::PrepareForJit, "PrepareForJit"},
-    };
-    // clang-format on
-
-    RegisterHandlers(functions);
-
-    gpu_error_detected_event =
-        service_context.CreateEvent("IApplicationFunctions:GpuErrorDetectedSystemEvent");
-    friend_invitation_storage_channel_event =
-        service_context.CreateEvent("IApplicationFunctions:FriendInvitationStorageChannelEvent");
-    notification_storage_channel_event =
-        service_context.CreateEvent("IApplicationFunctions:NotificationStorageChannelEvent");
-    health_warning_disappeared_system_event =
-        service_context.CreateEvent("IApplicationFunctions:HealthWarningDisappearedSystemEvent");
-}
-
-IApplicationFunctions::~IApplicationFunctions() {
-    service_context.CloseEvent(gpu_error_detected_event);
-    service_context.CloseEvent(friend_invitation_storage_channel_event);
-    service_context.CloseEvent(notification_storage_channel_event);
-    service_context.CloseEvent(health_warning_disappeared_system_event);
-}
-
-void IApplicationFunctions::EnableApplicationCrashReport(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::SetApplicationCopyrightImage(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::SetApplicationCopyrightVisibility(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-    const auto is_visible = rp.Pop<bool>();
-
-    LOG_WARNING(Service_AM, "(STUBBED) called, is_visible={}", is_visible);
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::BeginBlockingHomeButton(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::EndBlockingHomeButton(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-    const auto kind = rp.PopEnum<LaunchParameterKind>();
-
-    LOG_INFO(Service_AM, "called, kind={:08X}", kind);
-
-    if (kind == LaunchParameterKind::UserChannel) {
-        auto channel = system.GetUserChannel();
-        if (channel.empty()) {
-            LOG_ERROR(Service_AM, "Attempted to load launch parameter but none was found!");
-            IPC::ResponseBuilder rb{ctx, 2};
-            rb.Push(AM::ResultNoDataInChannel);
-            return;
-        }
-
-        auto data = channel.back();
-        channel.pop_back();
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IStorage>(system, std::move(data));
-    } else if (kind == LaunchParameterKind::AccountPreselectedUser &&
-               !launch_popped_account_preselect) {
-        // TODO: Verify this is hw-accurate
-        LaunchParameterAccountPreselectedUser params{};
-
-        params.magic = LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC;
-        params.is_account_selected = 1;
-
-        Account::ProfileManager profile_manager{};
-        const auto uuid = profile_manager.GetUser(static_cast<s32>(Settings::values.current_user));
-        ASSERT(uuid.has_value() && uuid->IsValid());
-        params.current_user = *uuid;
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-
-        std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser));
-        std::memcpy(buffer.data(), &params, buffer.size());
-
-        rb.PushIpcInterface<IStorage>(system, std::move(buffer));
-        launch_popped_account_preselect = true;
-    } else {
-        LOG_ERROR(Service_AM, "Unknown launch parameter kind.");
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(AM::ResultNoDataInChannel);
-    }
-}
-
-void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::EnsureSaveData(HLERequestContext& ctx) {
-    IPC::RequestParser rp{ctx};
-    u128 user_id = rp.PopRaw<u128>();
-
-    LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]);
-
-    FileSys::SaveDataAttribute attribute{};
-    attribute.title_id = system.GetApplicationProcessProgramID();
-    attribute.user_id = user_id;
-    attribute.type = FileSys::SaveDataType::SaveData;
-
-    FileSys::VirtualDir save_data{};
-    const auto res = system.GetFileSystemController().OpenSaveDataController()->CreateSaveData(
-        &save_data, FileSys::SaveDataSpaceId::NandUser, attribute);
-
-    IPC::ResponseBuilder rb{ctx, 4};
-    rb.Push(res);
-    rb.Push<u64>(0);
-}
-
-void IApplicationFunctions::SetTerminateResult(HLERequestContext& ctx) {
-    // Takes an input u32 Result, no output.
-    // For example, in some cases official apps use this with error 0x2A2 then
-    // uses svcBreak.
-
-    IPC::RequestParser rp{ctx};
-    u32 result = rp.Pop<u32>();
-    LOG_WARNING(Service_AM, "(STUBBED) called, result=0x{:08X}", result);
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::GetDisplayVersion(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called");
-
-    std::array<u8, 0x10> version_string{};
-
-    const auto res = [this] {
-        const auto title_id = system.GetApplicationProcessProgramID();
-
-        const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
-                                       system.GetContentProvider()};
-        auto metadata = pm.GetControlMetadata();
-        if (metadata.first != nullptr) {
-            return metadata;
-        }
-
-        const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id),
-                                              system.GetFileSystemController(),
-                                              system.GetContentProvider()};
-        return pm_update.GetControlMetadata();
-    }();
-
-    if (res.first != nullptr) {
-        const auto& version = res.first->GetVersionString();
-        std::copy(version.begin(), version.end(), version_string.begin());
-    } else {
-        static constexpr char default_version[]{"1.0.0"};
-        std::memcpy(version_string.data(), default_version, sizeof(default_version));
-    }
-
-    IPC::ResponseBuilder rb{ctx, 6};
-    rb.Push(ResultSuccess);
-    rb.PushRaw(version_string);
-}
-
-void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) {
-    // TODO(bunnei): This should be configurable
-    LOG_DEBUG(Service_AM, "called");
-
-    // Get supported languages from NACP, if possible
-    // Default to 0 (all languages supported)
-    u32 supported_languages = 0;
-
-    const auto res = [this] {
-        const auto title_id = system.GetApplicationProcessProgramID();
-
-        const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
-                                       system.GetContentProvider()};
-        auto metadata = pm.GetControlMetadata();
-        if (metadata.first != nullptr) {
-            return metadata;
-        }
-
-        const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id),
-                                              system.GetFileSystemController(),
-                                              system.GetContentProvider()};
-        return pm_update.GetControlMetadata();
-    }();
-
-    if (res.first != nullptr) {
-        supported_languages = res.first->GetSupportedLanguages();
-    }
-
-    // Call IApplicationManagerInterface implementation.
-    auto& service_manager = system.ServiceManager();
-    auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2");
-    auto app_man = ns_am2->GetApplicationManagerInterface();
-
-    // Get desired application language
-    u8 desired_language{};
-    const auto res_lang =
-        app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages);
-    if (res_lang != ResultSuccess) {
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(res_lang);
-        return;
-    }
-
-    // Convert to settings language code.
-    u64 language_code{};
-    const auto res_code =
-        app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language);
-    if (res_code != ResultSuccess) {
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(res_code);
-        return;
-    }
-
-    LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code);
-
-    IPC::ResponseBuilder rb{ctx, 4};
-    rb.Push(ResultSuccess);
-    rb.Push(language_code);
-}
-
-void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    constexpr bool gameplay_recording_supported = false;
-
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.Push(gameplay_recording_supported);
-}
-
-void IApplicationFunctions::InitializeGamePlayRecording(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::SetGamePlayRecordingState(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::NotifyRunning(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.Push<u8>(0); // Unknown, seems to be ignored by official processes
-}
-
-void IApplicationFunctions::GetPseudoDeviceId(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 6};
-    rb.Push(ResultSuccess);
-
-    // Returns a 128-bit UUID
-    rb.Push<u64>(0);
-    rb.Push<u64>(0);
-}
-
-void IApplicationFunctions::ExtendSaveData(HLERequestContext& ctx) {
-    struct Parameters {
-        FileSys::SaveDataType type;
-        u128 user_id;
-        u64 new_normal_size;
-        u64 new_journal_size;
-    };
-    static_assert(sizeof(Parameters) == 40);
-
-    IPC::RequestParser rp{ctx};
-    const auto [type, user_id, new_normal_size, new_journal_size] = rp.PopRaw<Parameters>();
-
-    LOG_DEBUG(Service_AM,
-              "called with type={:02X}, user_id={:016X}{:016X}, new_normal={:016X}, "
-              "new_journal={:016X}",
-              static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size);
-
-    system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize(
-        type, system.GetApplicationProcessProgramID(), user_id,
-        {new_normal_size, new_journal_size});
-
-    IPC::ResponseBuilder rb{ctx, 4};
-    rb.Push(ResultSuccess);
-
-    // The following value is used upon failure to help the system recover.
-    // Since we always succeed, this should be 0.
-    rb.Push<u64>(0);
-}
-
-void IApplicationFunctions::GetSaveDataSize(HLERequestContext& ctx) {
-    struct Parameters {
-        FileSys::SaveDataType type;
-        u128 user_id;
-    };
-    static_assert(sizeof(Parameters) == 24);
-
-    IPC::RequestParser rp{ctx};
-    const auto [type, user_id] = rp.PopRaw<Parameters>();
-
-    LOG_DEBUG(Service_AM, "called with type={:02X}, user_id={:016X}{:016X}", type, user_id[1],
-              user_id[0]);
-
-    const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize(
-        type, system.GetApplicationProcessProgramID(), user_id);
-
-    IPC::ResponseBuilder rb{ctx, 6};
-    rb.Push(ResultSuccess);
-    rb.Push(size.normal);
-    rb.Push(size.journal);
-}
-
-void IApplicationFunctions::CreateCacheStorage(HLERequestContext& ctx) {
-    struct InputParameters {
-        u16 index;
-        s64 size;
-        s64 journal_size;
-    };
-    static_assert(sizeof(InputParameters) == 24);
-
-    struct OutputParameters {
-        u32 storage_target;
-        u64 required_size;
-    };
-    static_assert(sizeof(OutputParameters) == 16);
-
-    IPC::RequestParser rp{ctx};
-    const auto params = rp.PopRaw<InputParameters>();
-
-    LOG_WARNING(Service_AM, "(STUBBED) called with index={}, size={:#x}, journal_size={:#x}",
-                params.index, params.size, params.journal_size);
-
-    const OutputParameters resp{
-        .storage_target = 1,
-        .required_size = 0,
-    };
-
-    IPC::ResponseBuilder rb{ctx, 6};
-    rb.Push(ResultSuccess);
-    rb.PushRaw(resp);
-}
-
-void IApplicationFunctions::GetSaveDataSizeMax(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    constexpr u64 size_max_normal = 0xFFFFFFF;
-    constexpr u64 size_max_journal = 0xFFFFFFF;
-
-    IPC::ResponseBuilder rb{ctx, 6};
-    rb.Push(ResultSuccess);
-    rb.Push(size_max_normal);
-    rb.Push(size_max_journal);
-}
-
-void IApplicationFunctions::QueryApplicationPlayStatistics(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.Push<u32>(0);
-}
-
-void IApplicationFunctions::QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.Push<u32>(0);
-}
-
-void IApplicationFunctions::ExecuteProgram(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::RequestParser rp{ctx};
-    [[maybe_unused]] const auto unk_1 = rp.Pop<u32>();
-    [[maybe_unused]] const auto unk_2 = rp.Pop<u32>();
-    const auto program_index = rp.Pop<u64>();
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-
-    system.ExecuteProgram(program_index);
-}
-
-void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called");
-
-    system.GetUserChannel().clear();
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::UnpopToUserChannel(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called");
-
-    IPC::RequestParser rp{ctx};
-    const auto storage = rp.PopIpcInterface<IStorage>().lock();
-    if (storage) {
-        system.GetUserChannel().push_back(storage->GetData());
-    }
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IApplicationFunctions::GetPreviousProgramIndex(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.Push<s32>(previous_program_index);
-}
-
-void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2, 1};
-    rb.Push(ResultSuccess);
-    rb.PushCopyObjects(gpu_error_detected_event->GetReadableEvent());
-}
-
-void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called");
-
-    IPC::ResponseBuilder rb{ctx, 2, 1};
-    rb.Push(ResultSuccess);
-    rb.PushCopyObjects(friend_invitation_storage_channel_event->GetReadableEvent());
-}
-
-void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(AM::ResultNoDataInChannel);
-}
-
-void IApplicationFunctions::GetNotificationStorageChannelEvent(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called");
-
-    IPC::ResponseBuilder rb{ctx, 2, 1};
-    rb.Push(ResultSuccess);
-    rb.PushCopyObjects(notification_storage_channel_event->GetReadableEvent());
-}
-
-void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx) {
-    LOG_DEBUG(Service_AM, "called");
-
-    IPC::ResponseBuilder rb{ctx, 2, 1};
-    rb.Push(ResultSuccess);
-    rb.PushCopyObjects(health_warning_disappeared_system_event->GetReadableEvent());
-}
-
-void IApplicationFunctions::PrepareForJit(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
 void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) {
     auto message_queue = std::make_shared<AppletMessageQueue>(system);
     auto server_manager = std::make_unique<ServerManager>(system);
@@ -2550,155 +26,4 @@ void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) {
     ServerManager::RunServer(std::move(server_manager));
 }
 
-IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_)
-    : ServiceFramework{system_, "IHomeMenuFunctions"}, service_context{system,
-                                                                       "IHomeMenuFunctions"} {
-    // clang-format off
-    static const FunctionInfo functions[] = {
-        {10, &IHomeMenuFunctions::RequestToGetForeground, "RequestToGetForeground"},
-        {11, nullptr, "LockForeground"},
-        {12, nullptr, "UnlockForeground"},
-        {20, nullptr, "PopFromGeneralChannel"},
-        {21, &IHomeMenuFunctions::GetPopFromGeneralChannelEvent, "GetPopFromGeneralChannelEvent"},
-        {30, nullptr, "GetHomeButtonWriterLockAccessor"},
-        {31, nullptr, "GetWriterLockAccessorEx"},
-        {40, nullptr, "IsSleepEnabled"},
-        {41, nullptr, "IsRebootEnabled"},
-        {50, nullptr, "LaunchSystemApplet"},
-        {51, nullptr, "LaunchStarter"},
-        {100, nullptr, "PopRequestLaunchApplicationForDebug"},
-        {110, nullptr, "IsForceTerminateApplicationDisabledForDebug"},
-        {200, nullptr, "LaunchDevMenu"},
-        {1000, nullptr, "SetLastApplicationExitReason"},
-    };
-    // clang-format on
-
-    RegisterHandlers(functions);
-
-    pop_from_general_channel_event =
-        service_context.CreateEvent("IHomeMenuFunctions:PopFromGeneralChannelEvent");
-}
-
-IHomeMenuFunctions::~IHomeMenuFunctions() {
-    service_context.CloseEvent(pop_from_general_channel_event);
-}
-
-void IHomeMenuFunctions::RequestToGetForeground(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2};
-    rb.Push(ResultSuccess);
-}
-
-void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    IPC::ResponseBuilder rb{ctx, 2, 1};
-    rb.Push(ResultSuccess);
-    rb.PushCopyObjects(pop_from_general_channel_event->GetReadableEvent());
-}
-
-IGlobalStateController::IGlobalStateController(Core::System& system_)
-    : ServiceFramework{system_, "IGlobalStateController"} {
-    // clang-format off
-    static const FunctionInfo functions[] = {
-        {0, nullptr, "RequestToEnterSleep"},
-        {1, nullptr, "EnterSleep"},
-        {2, nullptr, "StartSleepSequence"},
-        {3, nullptr, "StartShutdownSequence"},
-        {4, nullptr, "StartRebootSequence"},
-        {9, nullptr, "IsAutoPowerDownRequested"},
-        {10, nullptr, "LoadAndApplyIdlePolicySettings"},
-        {11, nullptr, "NotifyCecSettingsChanged"},
-        {12, nullptr, "SetDefaultHomeButtonLongPressTime"},
-        {13, nullptr, "UpdateDefaultDisplayResolution"},
-        {14, nullptr, "ShouldSleepOnBoot"},
-        {15, nullptr, "GetHdcpAuthenticationFailedEvent"},
-        {30, nullptr, "OpenCradleFirmwareUpdater"},
-    };
-    // clang-format on
-
-    RegisterHandlers(functions);
-}
-
-IGlobalStateController::~IGlobalStateController() = default;
-
-IApplicationCreator::IApplicationCreator(Core::System& system_)
-    : ServiceFramework{system_, "IApplicationCreator"} {
-    // clang-format off
-    static const FunctionInfo functions[] = {
-        {0, nullptr, "CreateApplication"},
-        {1, nullptr, "PopLaunchRequestedApplication"},
-        {10, nullptr, "CreateSystemApplication"},
-        {100, nullptr, "PopFloatingApplicationForDevelopment"},
-    };
-    // clang-format on
-
-    RegisterHandlers(functions);
-}
-
-IApplicationCreator::~IApplicationCreator() = default;
-
-IProcessWindingController::IProcessWindingController(Core::System& system_)
-    : ServiceFramework{system_, "IProcessWindingController"} {
-    // clang-format off
-    static const FunctionInfo functions[] = {
-        {0, &IProcessWindingController::GetLaunchReason, "GetLaunchReason"},
-        {11, &IProcessWindingController::OpenCallingLibraryApplet, "OpenCallingLibraryApplet"},
-        {21, nullptr, "PushContext"},
-        {22, nullptr, "PopContext"},
-        {23, nullptr, "CancelWindingReservation"},
-        {30, nullptr, "WindAndDoReserved"},
-        {40, nullptr, "ReserveToStartAndWaitAndUnwindThis"},
-        {41, nullptr, "ReserveToStartAndWait"},
-    };
-    // clang-format on
-
-    RegisterHandlers(functions);
-}
-
-IProcessWindingController::~IProcessWindingController() = default;
-
-void IProcessWindingController::GetLaunchReason(HLERequestContext& ctx) {
-    LOG_WARNING(Service_AM, "(STUBBED) called");
-
-    struct AppletProcessLaunchReason {
-        u8 flag;
-        INSERT_PADDING_BYTES(3);
-    };
-    static_assert(sizeof(AppletProcessLaunchReason) == 0x4,
-                  "AppletProcessLaunchReason is an invalid size");
-
-    AppletProcessLaunchReason reason{
-        .flag = 0,
-    };
-
-    IPC::ResponseBuilder rb{ctx, 3};
-    rb.Push(ResultSuccess);
-    rb.PushRaw(reason);
-}
-
-void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) {
-    const auto applet_id = system.GetAppletManager().GetCurrentAppletId();
-    const auto applet_mode = Applets::LibraryAppletMode::AllForeground;
-
-    LOG_WARNING(Service_AM, "(STUBBED) called with applet_id={:08X}, applet_mode={:08X}", applet_id,
-                applet_mode);
-
-    const auto& applet_manager{system.GetAppletManager()};
-    const auto applet = applet_manager.GetApplet(applet_id, applet_mode);
-
-    if (applet == nullptr) {
-        LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
-
-        IPC::ResponseBuilder rb{ctx, 2};
-        rb.Push(ResultUnknown);
-        return;
-    }
-
-    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-    rb.Push(ResultSuccess);
-    rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet);
-}
-
 } // namespace Service::AM
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 905a71b9f..4a2d797bd 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -1,20 +1,11 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 // SPDX-License-Identifier: GPL-2.0-or-later
 
 #pragma once
 
-#include <chrono>
-#include <memory>
-#include <queue>
-
-#include "core/hle/service/kernel_helpers.h"
-#include "core/hle/service/service.h"
-
-namespace Kernel {
-class KernelCore;
-class KReadableEvent;
-class KTransferMemory;
-} // namespace Kernel
+namespace Core {
+class System;
+}
 
 namespace Service::Nvnflinger {
 class Nvnflinger;
@@ -22,443 +13,6 @@ class Nvnflinger;
 
 namespace Service::AM {
 
-class AppletMessageQueue {
-public:
-    // This is nn::am::AppletMessage
-    enum class AppletMessage : u32 {
-        None = 0,
-        ChangeIntoForeground = 1,
-        ChangeIntoBackground = 2,
-        Exit = 4,
-        ApplicationExited = 6,
-        FocusStateChanged = 15,
-        Resume = 16,
-        DetectShortPressingHomeButton = 20,
-        DetectLongPressingHomeButton = 21,
-        DetectShortPressingPowerButton = 22,
-        DetectMiddlePressingPowerButton = 23,
-        DetectLongPressingPowerButton = 24,
-        RequestToPrepareSleep = 25,
-        FinishedSleepSequence = 26,
-        SleepRequiredByHighTemperature = 27,
-        SleepRequiredByLowBattery = 28,
-        AutoPowerDown = 29,
-        OperationModeChanged = 30,
-        PerformanceModeChanged = 31,
-        DetectReceivingCecSystemStandby = 32,
-        SdCardRemoved = 33,
-        LaunchApplicationRequested = 50,
-        RequestToDisplay = 51,
-        ShowApplicationLogo = 55,
-        HideApplicationLogo = 56,
-        ForceHideApplicationLogo = 57,
-        FloatingApplicationDetected = 60,
-        DetectShortPressingCaptureButton = 90,
-        AlbumScreenShotTaken = 92,
-        AlbumRecordingSaved = 93,
-    };
-
-    explicit AppletMessageQueue(Core::System& system);
-    ~AppletMessageQueue();
-
-    Kernel::KReadableEvent& GetMessageReceiveEvent();
-    Kernel::KReadableEvent& GetOperationModeChangedEvent();
-    void PushMessage(AppletMessage msg);
-    AppletMessage PopMessage();
-    std::size_t GetMessageCount() const;
-    void RequestExit();
-    void RequestResume();
-    void FocusStateChanged();
-    void OperationModeChanged();
-
-private:
-    KernelHelpers::ServiceContext service_context;
-
-    Kernel::KEvent* on_new_message;
-    Kernel::KEvent* on_operation_mode_changed;
-
-    std::queue<AppletMessage> messages;
-};
-
-class IWindowController final : public ServiceFramework<IWindowController> {
-public:
-    explicit IWindowController(Core::System& system_);
-    ~IWindowController() override;
-
-private:
-    void GetAppletResourceUserId(HLERequestContext& ctx);
-    void GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx);
-    void AcquireForegroundRights(HLERequestContext& ctx);
-};
-
-class IAudioController final : public ServiceFramework<IAudioController> {
-public:
-    explicit IAudioController(Core::System& system_);
-    ~IAudioController() override;
-
-private:
-    void SetExpectedMasterVolume(HLERequestContext& ctx);
-    void GetMainAppletExpectedMasterVolume(HLERequestContext& ctx);
-    void GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx);
-    void ChangeMainAppletMasterVolume(HLERequestContext& ctx);
-    void SetTransparentAudioRate(HLERequestContext& ctx);
-
-    static constexpr float min_allowed_volume = 0.0f;
-    static constexpr float max_allowed_volume = 1.0f;
-
-    float main_applet_volume{0.25f};
-    float library_applet_volume{max_allowed_volume};
-    float transparent_volume_rate{min_allowed_volume};
-
-    // Volume transition fade time in nanoseconds.
-    // e.g. If the main applet volume was 0% and was changed to 50%
-    //      with a fade of 50ns, then over the course of 50ns,
-    //      the volume will gradually fade up to 50%
-    std::chrono::nanoseconds fade_time_ns{0};
-};
-
-class IDisplayController final : public ServiceFramework<IDisplayController> {
-public:
-    explicit IDisplayController(Core::System& system_);
-    ~IDisplayController() override;
-
-private:
-    void GetCallerAppletCaptureImageEx(HLERequestContext& ctx);
-    void TakeScreenShotOfOwnLayer(HLERequestContext& ctx);
-    void AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx);
-    void ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx);
-    void AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx);
-    void ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx);
-};
-
-class IDebugFunctions final : public ServiceFramework<IDebugFunctions> {
-public:
-    explicit IDebugFunctions(Core::System& system_);
-    ~IDebugFunctions() override;
-};
-
-class ISelfController final : public ServiceFramework<ISelfController> {
-public:
-    explicit ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_);
-    ~ISelfController() override;
-
-private:
-    void Exit(HLERequestContext& ctx);
-    void LockExit(HLERequestContext& ctx);
-    void UnlockExit(HLERequestContext& ctx);
-    void EnterFatalSection(HLERequestContext& ctx);
-    void LeaveFatalSection(HLERequestContext& ctx);
-    void GetLibraryAppletLaunchableEvent(HLERequestContext& ctx);
-    void SetScreenShotPermission(HLERequestContext& ctx);
-    void SetOperationModeChangedNotification(HLERequestContext& ctx);
-    void SetPerformanceModeChangedNotification(HLERequestContext& ctx);
-    void SetFocusHandlingMode(HLERequestContext& ctx);
-    void SetRestartMessageEnabled(HLERequestContext& ctx);
-    void SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx);
-    void SetAlbumImageOrientation(HLERequestContext& ctx);
-    void IsSystemBufferSharingEnabled(HLERequestContext& ctx);
-    void GetSystemSharedBufferHandle(HLERequestContext& ctx);
-    void GetSystemSharedLayerHandle(HLERequestContext& ctx);
-    void CreateManagedDisplayLayer(HLERequestContext& ctx);
-    void CreateManagedDisplaySeparableLayer(HLERequestContext& ctx);
-    void SetHandlesRequestToDisplay(HLERequestContext& ctx);
-    void ApproveToDisplay(HLERequestContext& ctx);
-    void SetIdleTimeDetectionExtension(HLERequestContext& ctx);
-    void GetIdleTimeDetectionExtension(HLERequestContext& ctx);
-    void ReportUserIsActive(HLERequestContext& ctx);
-    void SetAutoSleepDisabled(HLERequestContext& ctx);
-    void IsAutoSleepDisabled(HLERequestContext& ctx);
-    void GetAccumulatedSuspendedTickValue(HLERequestContext& ctx);
-    void GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx);
-    void SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx);
-    void SaveCurrentScreenshot(HLERequestContext& ctx);
-    void SetRecordVolumeMuted(HLERequestContext& ctx);
-
-    Result EnsureBufferSharingEnabled();
-
-    enum class ScreenshotPermission : u32 {
-        Inherit = 0,
-        Enable = 1,
-        Disable = 2,
-    };
-
-    Nvnflinger::Nvnflinger& nvnflinger;
-
-    KernelHelpers::ServiceContext service_context;
-
-    Kernel::KEvent* launchable_event;
-    Kernel::KEvent* accumulated_suspended_tick_changed_event;
-
-    u32 idle_time_detection_extension = 0;
-    u64 num_fatal_sections_entered = 0;
-    u64 system_shared_buffer_id = 0;
-    u64 system_shared_layer_id = 0;
-    bool is_auto_sleep_disabled = false;
-    bool buffer_sharing_enabled = false;
-    ScreenshotPermission screenshot_permission = ScreenshotPermission::Inherit;
-};
-
-class ILockAccessor final : public ServiceFramework<ILockAccessor> {
-public:
-    explicit ILockAccessor(Core::System& system_);
-    ~ILockAccessor() override;
-
-private:
-    void TryLock(HLERequestContext& ctx);
-    void Unlock(HLERequestContext& ctx);
-    void GetEvent(HLERequestContext& ctx);
-    void IsLocked(HLERequestContext& ctx);
-
-    bool is_locked{};
-
-    Kernel::KEvent* lock_event;
-    KernelHelpers::ServiceContext service_context;
-};
-
-class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
-public:
-    explicit ICommonStateGetter(Core::System& system_,
-                                std::shared_ptr<AppletMessageQueue> msg_queue_);
-    ~ICommonStateGetter() override;
-
-private:
-    // This is nn::oe::FocusState
-    enum class FocusState : u8 {
-        InFocus = 1,
-        NotInFocus = 2,
-        Background = 3,
-    };
-
-    // This is nn::oe::OperationMode
-    enum class OperationMode : u8 {
-        Handheld = 0,
-        Docked = 1,
-    };
-
-    // This is nn::am::service::SystemButtonType
-    enum class SystemButtonType {
-        None,
-        HomeButtonShortPressing,
-        HomeButtonLongPressing,
-        PowerButtonShortPressing,
-        PowerButtonLongPressing,
-        ShutdownSystem,
-        CaptureButtonShortPressing,
-        CaptureButtonLongPressing,
-    };
-
-    enum class SysPlatformRegion : s32 {
-        Global = 1,
-        Terra = 2,
-    };
-
-    void GetEventHandle(HLERequestContext& ctx);
-    void ReceiveMessage(HLERequestContext& ctx);
-    void GetCurrentFocusState(HLERequestContext& ctx);
-    void RequestToAcquireSleepLock(HLERequestContext& ctx);
-    void GetAcquiredSleepLockEvent(HLERequestContext& ctx);
-    void GetReaderLockAccessorEx(HLERequestContext& ctx);
-    void GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx);
-    void GetOperationMode(HLERequestContext& ctx);
-    void GetPerformanceMode(HLERequestContext& ctx);
-    void GetBootMode(HLERequestContext& ctx);
-    void IsVrModeEnabled(HLERequestContext& ctx);
-    void SetVrModeEnabled(HLERequestContext& ctx);
-    void SetLcdBacklighOffEnabled(HLERequestContext& ctx);
-    void BeginVrModeEx(HLERequestContext& ctx);
-    void EndVrModeEx(HLERequestContext& ctx);
-    void GetDefaultDisplayResolution(HLERequestContext& ctx);
-    void SetCpuBoostMode(HLERequestContext& ctx);
-    void GetBuiltInDisplayType(HLERequestContext& ctx);
-    void PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx);
-    void GetSettingsPlatformRegion(HLERequestContext& ctx);
-    void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx);
-
-    std::shared_ptr<AppletMessageQueue> msg_queue;
-    bool vr_mode_state{};
-    Kernel::KEvent* sleep_lock_event;
-    KernelHelpers::ServiceContext service_context;
-};
-
-class IStorageImpl {
-public:
-    virtual ~IStorageImpl();
-    virtual std::vector<u8>& GetData() = 0;
-    virtual const std::vector<u8>& GetData() const = 0;
-    virtual std::size_t GetSize() const = 0;
-};
-
-class IStorage final : public ServiceFramework<IStorage> {
-public:
-    explicit IStorage(Core::System& system_, std::vector<u8>&& buffer);
-    ~IStorage() override;
-
-    std::vector<u8>& GetData() {
-        return impl->GetData();
-    }
-
-    const std::vector<u8>& GetData() const {
-        return impl->GetData();
-    }
-
-    std::size_t GetSize() const {
-        return impl->GetSize();
-    }
-
-private:
-    void Register();
-    void Open(HLERequestContext& ctx);
-
-    std::shared_ptr<IStorageImpl> impl;
-};
-
-class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
-public:
-    explicit IStorageAccessor(Core::System& system_, IStorage& backing_);
-    ~IStorageAccessor() override;
-
-private:
-    void GetSize(HLERequestContext& ctx);
-    void Write(HLERequestContext& ctx);
-    void Read(HLERequestContext& ctx);
-
-    IStorage& backing;
-};
-
-class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
-public:
-    explicit ILibraryAppletCreator(Core::System& system_);
-    ~ILibraryAppletCreator() override;
-
-private:
-    void CreateLibraryApplet(HLERequestContext& ctx);
-    void CreateStorage(HLERequestContext& ctx);
-    void CreateTransferMemoryStorage(HLERequestContext& ctx);
-    void CreateHandleStorage(HLERequestContext& ctx);
-};
-
-class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> {
-public:
-    explicit ILibraryAppletSelfAccessor(Core::System& system_);
-    ~ILibraryAppletSelfAccessor() override;
-
-private:
-    void PopInData(HLERequestContext& ctx);
-    void PushOutData(HLERequestContext& ctx);
-    void GetLibraryAppletInfo(HLERequestContext& ctx);
-    void GetMainAppletIdentityInfo(HLERequestContext& ctx);
-    void ExitProcessAndReturn(HLERequestContext& ctx);
-    void GetCallerAppletIdentityInfo(HLERequestContext& ctx);
-    void GetDesirableKeyboardLayout(HLERequestContext& ctx);
-    void GetMainAppletAvailableUsers(HLERequestContext& ctx);
-    void ShouldSetGpuTimeSliceManually(HLERequestContext& ctx);
-
-    void PushInShowAlbum();
-    void PushInShowCabinetData();
-    void PushInShowMiiEditData();
-    void PushInShowSoftwareKeyboard();
-    void PushInShowController();
-
-    std::deque<std::vector<u8>> queue_data;
-};
-
-class IAppletCommonFunctions final : public ServiceFramework<IAppletCommonFunctions> {
-public:
-    explicit IAppletCommonFunctions(Core::System& system_);
-    ~IAppletCommonFunctions() override;
-
-private:
-    void SetCpuBoostRequestPriority(HLERequestContext& ctx);
-};
-
-class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
-public:
-    explicit IApplicationFunctions(Core::System& system_);
-    ~IApplicationFunctions() override;
-
-private:
-    void PopLaunchParameter(HLERequestContext& ctx);
-    void CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx);
-    void EnsureSaveData(HLERequestContext& ctx);
-    void SetTerminateResult(HLERequestContext& ctx);
-    void GetDisplayVersion(HLERequestContext& ctx);
-    void GetDesiredLanguage(HLERequestContext& ctx);
-    void IsGamePlayRecordingSupported(HLERequestContext& ctx);
-    void InitializeGamePlayRecording(HLERequestContext& ctx);
-    void SetGamePlayRecordingState(HLERequestContext& ctx);
-    void NotifyRunning(HLERequestContext& ctx);
-    void GetPseudoDeviceId(HLERequestContext& ctx);
-    void ExtendSaveData(HLERequestContext& ctx);
-    void GetSaveDataSize(HLERequestContext& ctx);
-    void CreateCacheStorage(HLERequestContext& ctx);
-    void GetSaveDataSizeMax(HLERequestContext& ctx);
-    void BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx);
-    void EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx);
-    void BeginBlockingHomeButton(HLERequestContext& ctx);
-    void EndBlockingHomeButton(HLERequestContext& ctx);
-    void EnableApplicationCrashReport(HLERequestContext& ctx);
-    void InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx);
-    void SetApplicationCopyrightImage(HLERequestContext& ctx);
-    void SetApplicationCopyrightVisibility(HLERequestContext& ctx);
-    void QueryApplicationPlayStatistics(HLERequestContext& ctx);
-    void QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx);
-    void ExecuteProgram(HLERequestContext& ctx);
-    void ClearUserChannel(HLERequestContext& ctx);
-    void UnpopToUserChannel(HLERequestContext& ctx);
-    void GetPreviousProgramIndex(HLERequestContext& ctx);
-    void GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx);
-    void GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx);
-    void TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx);
-    void GetNotificationStorageChannelEvent(HLERequestContext& ctx);
-    void GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx);
-    void PrepareForJit(HLERequestContext& ctx);
-
-    KernelHelpers::ServiceContext service_context;
-
-    bool launch_popped_account_preselect = false;
-    s32 previous_program_index{-1};
-    Kernel::KEvent* gpu_error_detected_event;
-    Kernel::KEvent* friend_invitation_storage_channel_event;
-    Kernel::KEvent* notification_storage_channel_event;
-    Kernel::KEvent* health_warning_disappeared_system_event;
-};
-
-class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> {
-public:
-    explicit IHomeMenuFunctions(Core::System& system_);
-    ~IHomeMenuFunctions() override;
-
-private:
-    void RequestToGetForeground(HLERequestContext& ctx);
-    void GetPopFromGeneralChannelEvent(HLERequestContext& ctx);
-
-    KernelHelpers::ServiceContext service_context;
-
-    Kernel::KEvent* pop_from_general_channel_event;
-};
-
-class IGlobalStateController final : public ServiceFramework<IGlobalStateController> {
-public:
-    explicit IGlobalStateController(Core::System& system_);
-    ~IGlobalStateController() override;
-};
-
-class IApplicationCreator final : public ServiceFramework<IApplicationCreator> {
-public:
-    explicit IApplicationCreator(Core::System& system_);
-    ~IApplicationCreator() override;
-};
-
-class IProcessWindingController final : public ServiceFramework<IProcessWindingController> {
-public:
-    explicit IProcessWindingController(Core::System& system_);
-    ~IProcessWindingController() override;
-
-private:
-    void GetLaunchReason(HLERequestContext& ctx);
-    void OpenCallingLibraryApplet(HLERequestContext& ctx);
-};
-
 void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system);
 
 } // namespace Service::AM
diff --git a/src/core/hle/service/am/am_results.h b/src/core/hle/service/am/am_results.h
new file mode 100644
index 000000000..528b334ad
--- /dev/null
+++ b/src/core/hle/service/am/am_results.h
@@ -0,0 +1,14 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/result.h"
+
+namespace Service::AM {
+
+constexpr Result ResultNoDataInChannel{ErrorModule::AM, 2};
+constexpr Result ResultNoMessages{ErrorModule::AM, 3};
+constexpr Result ResultInvalidOffset{ErrorModule::AM, 503};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp
index e30e6478a..bd9e5f505 100644
--- a/src/core/hle/service/am/applet_ae.cpp
+++ b/src/core/hle/service/am/applet_ae.cpp
@@ -1,263 +1,13 @@
 // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 // SPDX-License-Identifier: GPL-2.0-or-later
 
-#include "common/logging/log.h"
-#include "core/core.h"
-#include "core/hle/service/am/am.h"
 #include "core/hle/service/am/applet_ae.h"
+#include "core/hle/service/am/library_applet_proxy.h"
+#include "core/hle/service/am/system_applet_proxy.h"
 #include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/nvnflinger/nvnflinger.h"
 
 namespace Service::AM {
 
-class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
-public:
-    explicit ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
-                                 std::shared_ptr<AppletMessageQueue> msg_queue_,
-                                 Core::System& system_)
-        : ServiceFramework{system_, "ILibraryAppletProxy"},
-          nvnflinger{nvnflinger_}, msg_queue{std::move(msg_queue_)} {
-        // clang-format off
-        static const FunctionInfo functions[] = {
-            {0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
-            {1, &ILibraryAppletProxy::GetSelfController, "GetSelfController"},
-            {2, &ILibraryAppletProxy::GetWindowController, "GetWindowController"},
-            {3, &ILibraryAppletProxy::GetAudioController, "GetAudioController"},
-            {4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"},
-            {10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"},
-            {11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
-            {20, &ILibraryAppletProxy::OpenLibraryAppletSelfAccessor, "OpenLibraryAppletSelfAccessor"},
-            {21, &ILibraryAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"},
-            {22, &ILibraryAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"},
-            {23, &ILibraryAppletProxy::GetGlobalStateController, "GetGlobalStateController"},
-            {1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
-        };
-        // clang-format on
-
-        RegisterHandlers(functions);
-    }
-
-private:
-    void GetCommonStateGetter(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue);
-    }
-
-    void GetSelfController(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<ISelfController>(system, nvnflinger);
-    }
-
-    void GetWindowController(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IWindowController>(system);
-    }
-
-    void GetAudioController(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IAudioController>(system);
-    }
-
-    void GetDisplayController(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IDisplayController>(system);
-    }
-
-    void GetProcessWindingController(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IProcessWindingController>(system);
-    }
-
-    void GetLibraryAppletCreator(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<ILibraryAppletCreator>(system);
-    }
-
-    void OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system);
-    }
-
-    void GetAppletCommonFunctions(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IAppletCommonFunctions>(system);
-    }
-
-    void GetHomeMenuFunctions(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IHomeMenuFunctions>(system);
-    }
-
-    void GetGlobalStateController(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IGlobalStateController>(system);
-    }
-
-    void GetDebugFunctions(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IDebugFunctions>(system);
-    }
-
-    Nvnflinger::Nvnflinger& nvnflinger;
-    std::shared_ptr<AppletMessageQueue> msg_queue;
-};
-
-class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> {
-public:
-    explicit ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
-                                std::shared_ptr<AppletMessageQueue> msg_queue_,
-                                Core::System& system_)
-        : ServiceFramework{system_, "ISystemAppletProxy"},
-          nvnflinger{nvnflinger_}, msg_queue{std::move(msg_queue_)} {
-        // clang-format off
-        static const FunctionInfo functions[] = {
-            {0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
-            {1, &ISystemAppletProxy::GetSelfController, "GetSelfController"},
-            {2, &ISystemAppletProxy::GetWindowController, "GetWindowController"},
-            {3, &ISystemAppletProxy::GetAudioController, "GetAudioController"},
-            {4, &ISystemAppletProxy::GetDisplayController, "GetDisplayController"},
-            {10, nullptr, "GetProcessWindingController"},
-            {11, &ISystemAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
-            {20, &ISystemAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"},
-            {21, &ISystemAppletProxy::GetGlobalStateController, "GetGlobalStateController"},
-            {22, &ISystemAppletProxy::GetApplicationCreator, "GetApplicationCreator"},
-            {23,  &ISystemAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"},
-            {1000, &ISystemAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
-        };
-        // clang-format on
-
-        RegisterHandlers(functions);
-    }
-
-private:
-    void GetCommonStateGetter(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue);
-    }
-
-    void GetSelfController(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<ISelfController>(system, nvnflinger);
-    }
-
-    void GetWindowController(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IWindowController>(system);
-    }
-
-    void GetAudioController(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IAudioController>(system);
-    }
-
-    void GetDisplayController(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IDisplayController>(system);
-    }
-
-    void GetLibraryAppletCreator(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<ILibraryAppletCreator>(system);
-    }
-
-    void GetHomeMenuFunctions(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IHomeMenuFunctions>(system);
-    }
-
-    void GetGlobalStateController(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IGlobalStateController>(system);
-    }
-
-    void GetApplicationCreator(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IApplicationCreator>(system);
-    }
-
-    void GetAppletCommonFunctions(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IAppletCommonFunctions>(system);
-    }
-
-    void GetDebugFunctions(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IDebugFunctions>(system);
-    }
-
-    Nvnflinger::Nvnflinger& nvnflinger;
-    std::shared_ptr<AppletMessageQueue> msg_queue;
-};
-
 void AppletAE::OpenSystemAppletProxy(HLERequestContext& ctx) {
     LOG_DEBUG(Service_AM, "called");
 
@@ -284,8 +34,8 @@ void AppletAE::OpenLibraryAppletProxyOld(HLERequestContext& ctx) {
 
 AppletAE::AppletAE(Nvnflinger::Nvnflinger& nvnflinger_,
                    std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_)
-    : ServiceFramework{system_, "appletAE"}, nvnflinger{nvnflinger_}, msg_queue{
-                                                                          std::move(msg_queue_)} {
+    : ServiceFramework{system_, "appletAE"}, nvnflinger{nvnflinger_},
+      msg_queue{std::move(msg_queue_)} {
     // clang-format off
     static const FunctionInfo functions[] = {
         {100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"},
diff --git a/src/core/hle/service/am/applet_common_functions.cpp b/src/core/hle/service/am/applet_common_functions.cpp
new file mode 100644
index 000000000..81c01a48b
--- /dev/null
+++ b/src/core/hle/service/am/applet_common_functions.cpp
@@ -0,0 +1,47 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/applet_common_functions.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::AM {
+
+IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_)
+    : ServiceFramework{system_, "IAppletCommonFunctions"} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, nullptr, "SetTerminateResult"},
+        {10, nullptr, "ReadThemeStorage"},
+        {11, nullptr, "WriteThemeStorage"},
+        {20, nullptr, "PushToAppletBoundChannel"},
+        {21, nullptr, "TryPopFromAppletBoundChannel"},
+        {40, nullptr, "GetDisplayLogicalResolution"},
+        {42, nullptr, "SetDisplayMagnification"},
+        {50, nullptr, "SetHomeButtonDoubleClickEnabled"},
+        {51, nullptr, "GetHomeButtonDoubleClickEnabled"},
+        {52, nullptr, "IsHomeButtonShortPressedBlocked"},
+        {60, nullptr, "IsVrModeCurtainRequired"},
+        {61, nullptr, "IsSleepRequiredByHighTemperature"},
+        {62, nullptr, "IsSleepRequiredByLowBattery"},
+        {70, &IAppletCommonFunctions::SetCpuBoostRequestPriority, "SetCpuBoostRequestPriority"},
+        {80, nullptr, "SetHandlingCaptureButtonShortPressedMessageEnabledForApplet"},
+        {81, nullptr, "SetHandlingCaptureButtonLongPressedMessageEnabledForApplet"},
+        {90, nullptr, "OpenNamedChannelAsParent"},
+        {91, nullptr, "OpenNamedChannelAsChild"},
+        {100, nullptr, "SetApplicationCoreUsageMode"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+IAppletCommonFunctions::~IAppletCommonFunctions() = default;
+
+void IAppletCommonFunctions::SetCpuBoostRequestPriority(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet_common_functions.h b/src/core/hle/service/am/applet_common_functions.h
new file mode 100644
index 000000000..be87b3820
--- /dev/null
+++ b/src/core/hle/service/am/applet_common_functions.h
@@ -0,0 +1,19 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class IAppletCommonFunctions final : public ServiceFramework<IAppletCommonFunctions> {
+public:
+    explicit IAppletCommonFunctions(Core::System& system_);
+    ~IAppletCommonFunctions() override;
+
+private:
+    void SetCpuBoostRequestPriority(HLERequestContext& ctx);
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet_message_queue.cpp b/src/core/hle/service/am/applet_message_queue.cpp
new file mode 100644
index 000000000..e4931031d
--- /dev/null
+++ b/src/core/hle/service/am/applet_message_queue.cpp
@@ -0,0 +1,68 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/applet_message_queue.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::AM {
+
+AppletMessageQueue::AppletMessageQueue(Core::System& system)
+    : service_context{system, "AppletMessageQueue"} {
+    on_new_message = service_context.CreateEvent("AMMessageQueue:OnMessageReceived");
+    on_operation_mode_changed = service_context.CreateEvent("AMMessageQueue:OperationModeChanged");
+}
+
+AppletMessageQueue::~AppletMessageQueue() {
+    service_context.CloseEvent(on_new_message);
+    service_context.CloseEvent(on_operation_mode_changed);
+}
+
+Kernel::KReadableEvent& AppletMessageQueue::GetMessageReceiveEvent() {
+    return on_new_message->GetReadableEvent();
+}
+
+Kernel::KReadableEvent& AppletMessageQueue::GetOperationModeChangedEvent() {
+    return on_operation_mode_changed->GetReadableEvent();
+}
+
+void AppletMessageQueue::PushMessage(AppletMessage msg) {
+    messages.push(msg);
+    on_new_message->Signal();
+}
+
+AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() {
+    if (messages.empty()) {
+        on_new_message->Clear();
+        return AppletMessage::None;
+    }
+    auto msg = messages.front();
+    messages.pop();
+    if (messages.empty()) {
+        on_new_message->Clear();
+    }
+    return msg;
+}
+
+std::size_t AppletMessageQueue::GetMessageCount() const {
+    return messages.size();
+}
+
+void AppletMessageQueue::RequestExit() {
+    PushMessage(AppletMessage::Exit);
+}
+
+void AppletMessageQueue::RequestResume() {
+    PushMessage(AppletMessage::Resume);
+}
+
+void AppletMessageQueue::FocusStateChanged() {
+    PushMessage(AppletMessage::FocusStateChanged);
+}
+
+void AppletMessageQueue::OperationModeChanged() {
+    PushMessage(AppletMessage::OperationModeChanged);
+    PushMessage(AppletMessage::PerformanceModeChanged);
+    on_operation_mode_changed->Signal();
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet_message_queue.h b/src/core/hle/service/am/applet_message_queue.h
new file mode 100644
index 000000000..60145aae9
--- /dev/null
+++ b/src/core/hle/service/am/applet_message_queue.h
@@ -0,0 +1,75 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <queue>
+
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/service.h"
+
+namespace Kernel {
+class KReadableEvent;
+} // namespace Kernel
+
+namespace Service::AM {
+
+class AppletMessageQueue {
+public:
+    // This is nn::am::AppletMessage
+    enum class AppletMessage : u32 {
+        None = 0,
+        ChangeIntoForeground = 1,
+        ChangeIntoBackground = 2,
+        Exit = 4,
+        ApplicationExited = 6,
+        FocusStateChanged = 15,
+        Resume = 16,
+        DetectShortPressingHomeButton = 20,
+        DetectLongPressingHomeButton = 21,
+        DetectShortPressingPowerButton = 22,
+        DetectMiddlePressingPowerButton = 23,
+        DetectLongPressingPowerButton = 24,
+        RequestToPrepareSleep = 25,
+        FinishedSleepSequence = 26,
+        SleepRequiredByHighTemperature = 27,
+        SleepRequiredByLowBattery = 28,
+        AutoPowerDown = 29,
+        OperationModeChanged = 30,
+        PerformanceModeChanged = 31,
+        DetectReceivingCecSystemStandby = 32,
+        SdCardRemoved = 33,
+        LaunchApplicationRequested = 50,
+        RequestToDisplay = 51,
+        ShowApplicationLogo = 55,
+        HideApplicationLogo = 56,
+        ForceHideApplicationLogo = 57,
+        FloatingApplicationDetected = 60,
+        DetectShortPressingCaptureButton = 90,
+        AlbumScreenShotTaken = 92,
+        AlbumRecordingSaved = 93,
+    };
+
+    explicit AppletMessageQueue(Core::System& system);
+    ~AppletMessageQueue();
+
+    Kernel::KReadableEvent& GetMessageReceiveEvent();
+    Kernel::KReadableEvent& GetOperationModeChangedEvent();
+    void PushMessage(AppletMessage msg);
+    AppletMessage PopMessage();
+    std::size_t GetMessageCount() const;
+    void RequestExit();
+    void RequestResume();
+    void FocusStateChanged();
+    void OperationModeChanged();
+
+private:
+    KernelHelpers::ServiceContext service_context;
+
+    Kernel::KEvent* on_new_message;
+    Kernel::KEvent* on_operation_mode_changed;
+
+    std::queue<AppletMessage> messages;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp
index d6c565d85..f373d1136 100644
--- a/src/core/hle/service/am/applet_oe.cpp
+++ b/src/core/hle/service/am/applet_oe.cpp
@@ -1,107 +1,13 @@
 // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 // SPDX-License-Identifier: GPL-2.0-or-later
 
-#include "common/logging/log.h"
 #include "core/hle/service/am/am.h"
 #include "core/hle/service/am/applet_oe.h"
+#include "core/hle/service/am/application_proxy.h"
 #include "core/hle/service/ipc_helpers.h"
-#include "core/hle/service/nvnflinger/nvnflinger.h"
 
 namespace Service::AM {
 
-class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
-public:
-    explicit IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_,
-                               std::shared_ptr<AppletMessageQueue> msg_queue_,
-                               Core::System& system_)
-        : ServiceFramework{system_, "IApplicationProxy"},
-          nvnflinger{nvnflinger_}, msg_queue{std::move(msg_queue_)} {
-        // clang-format off
-        static const FunctionInfo functions[] = {
-            {0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"},
-            {1, &IApplicationProxy::GetSelfController, "GetSelfController"},
-            {2, &IApplicationProxy::GetWindowController, "GetWindowController"},
-            {3, &IApplicationProxy::GetAudioController, "GetAudioController"},
-            {4, &IApplicationProxy::GetDisplayController, "GetDisplayController"},
-            {10, nullptr, "GetProcessWindingController"},
-            {11, &IApplicationProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
-            {20, &IApplicationProxy::GetApplicationFunctions, "GetApplicationFunctions"},
-            {1000, &IApplicationProxy::GetDebugFunctions, "GetDebugFunctions"},
-        };
-        // clang-format on
-
-        RegisterHandlers(functions);
-    }
-
-private:
-    void GetAudioController(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IAudioController>(system);
-    }
-
-    void GetDisplayController(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IDisplayController>(system);
-    }
-
-    void GetDebugFunctions(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IDebugFunctions>(system);
-    }
-
-    void GetWindowController(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IWindowController>(system);
-    }
-
-    void GetSelfController(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<ISelfController>(system, nvnflinger);
-    }
-
-    void GetCommonStateGetter(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue);
-    }
-
-    void GetLibraryAppletCreator(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<ILibraryAppletCreator>(system);
-    }
-
-    void GetApplicationFunctions(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IApplicationFunctions>(system);
-    }
-
-    Nvnflinger::Nvnflinger& nvnflinger;
-    std::shared_ptr<AppletMessageQueue> msg_queue;
-};
-
 void AppletOE::OpenApplicationProxy(HLERequestContext& ctx) {
     LOG_DEBUG(Service_AM, "called");
 
@@ -112,8 +18,8 @@ void AppletOE::OpenApplicationProxy(HLERequestContext& ctx) {
 
 AppletOE::AppletOE(Nvnflinger::Nvnflinger& nvnflinger_,
                    std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_)
-    : ServiceFramework{system_, "appletOE"}, nvnflinger{nvnflinger_}, msg_queue{
-                                                                          std::move(msg_queue_)} {
+    : ServiceFramework{system_, "appletOE"}, nvnflinger{nvnflinger_},
+      msg_queue{std::move(msg_queue_)} {
     static const FunctionInfo functions[] = {
         {0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"},
     };
diff --git a/src/core/hle/service/am/applets/applet_cabinet.cpp b/src/core/hle/service/am/applets/applet_cabinet.cpp
index c2ff444a6..1b756fbd7 100644
--- a/src/core/hle/service/am/applets/applet_cabinet.cpp
+++ b/src/core/hle/service/am/applets/applet_cabinet.cpp
@@ -9,6 +9,7 @@
 #include "core/hle/kernel/k_readable_event.h"
 #include "core/hle/service/am/am.h"
 #include "core/hle/service/am/applets/applet_cabinet.h"
+#include "core/hle/service/am/storage.h"
 #include "core/hle/service/mii/mii_manager.h"
 #include "core/hle/service/nfc/common/device.h"
 #include "hid_core/hid_core.h"
@@ -17,9 +18,8 @@ namespace Service::AM::Applets {
 
 Cabinet::Cabinet(Core::System& system_, LibraryAppletMode applet_mode_,
                  const Core::Frontend::CabinetApplet& frontend_)
-    : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_}, service_context{
-                                                                               system_,
-                                                                               "CabinetApplet"} {
+    : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_},
+      service_context{system_, "CabinetApplet"} {
 
     availability_change_event =
         service_context.CreateEvent("CabinetApplet:AvailabilityChangeEvent");
diff --git a/src/core/hle/service/am/applets/applet_controller.cpp b/src/core/hle/service/am/applets/applet_controller.cpp
index 0e4d9cc39..bc8de6b60 100644
--- a/src/core/hle/service/am/applets/applet_controller.cpp
+++ b/src/core/hle/service/am/applets/applet_controller.cpp
@@ -12,6 +12,7 @@
 #include "core/hle/result.h"
 #include "core/hle/service/am/am.h"
 #include "core/hle/service/am/applets/applet_controller.h"
+#include "core/hle/service/am/storage.h"
 #include "hid_core/frontend/emulated_controller.h"
 #include "hid_core/hid_core.h"
 #include "hid_core/hid_types.h"
diff --git a/src/core/hle/service/am/applets/applet_error.cpp b/src/core/hle/service/am/applets/applet_error.cpp
index 084bc138c..96126832c 100644
--- a/src/core/hle/service/am/applets/applet_error.cpp
+++ b/src/core/hle/service/am/applets/applet_error.cpp
@@ -10,6 +10,7 @@
 #include "core/frontend/applets/error.h"
 #include "core/hle/service/am/am.h"
 #include "core/hle/service/am/applets/applet_error.h"
+#include "core/hle/service/am/storage.h"
 #include "core/reporter.h"
 
 namespace Service::AM::Applets {
diff --git a/src/core/hle/service/am/applets/applet_general_backend.cpp b/src/core/hle/service/am/applets/applet_general_backend.cpp
index c0032f652..c010c78e2 100644
--- a/src/core/hle/service/am/applets/applet_general_backend.cpp
+++ b/src/core/hle/service/am/applets/applet_general_backend.cpp
@@ -9,6 +9,7 @@
 #include "core/hle/result.h"
 #include "core/hle/service/am/am.h"
 #include "core/hle/service/am/applets/applet_general_backend.h"
+#include "core/hle/service/am/storage.h"
 #include "core/reporter.h"
 
 namespace Service::AM::Applets {
diff --git a/src/core/hle/service/am/applets/applet_mii_edit.cpp b/src/core/hle/service/am/applets/applet_mii_edit.cpp
index e83e931c5..1576b45c4 100644
--- a/src/core/hle/service/am/applets/applet_mii_edit.cpp
+++ b/src/core/hle/service/am/applets/applet_mii_edit.cpp
@@ -7,6 +7,7 @@
 #include "core/frontend/applets/mii_edit.h"
 #include "core/hle/service/am/am.h"
 #include "core/hle/service/am/applets/applet_mii_edit.h"
+#include "core/hle/service/am/storage.h"
 #include "core/hle/service/mii/mii.h"
 #include "core/hle/service/mii/mii_manager.h"
 #include "core/hle/service/sm/sm.h"
diff --git a/src/core/hle/service/am/applets/applet_profile_select.cpp b/src/core/hle/service/am/applets/applet_profile_select.cpp
index 89cb323e9..f32db6842 100644
--- a/src/core/hle/service/am/applets/applet_profile_select.cpp
+++ b/src/core/hle/service/am/applets/applet_profile_select.cpp
@@ -10,6 +10,7 @@
 #include "core/hle/service/acc/errors.h"
 #include "core/hle/service/am/am.h"
 #include "core/hle/service/am/applets/applet_profile_select.h"
+#include "core/hle/service/am/storage.h"
 
 namespace Service::AM::Applets {
 
diff --git a/src/core/hle/service/am/applets/applet_software_keyboard.cpp b/src/core/hle/service/am/applets/applet_software_keyboard.cpp
index 4145bb84f..a6a07cef3 100644
--- a/src/core/hle/service/am/applets/applet_software_keyboard.cpp
+++ b/src/core/hle/service/am/applets/applet_software_keyboard.cpp
@@ -6,6 +6,7 @@
 #include "core/frontend/applets/software_keyboard.h"
 #include "core/hle/service/am/am.h"
 #include "core/hle/service/am/applets/applet_software_keyboard.h"
+#include "core/hle/service/am/storage.h"
 
 namespace Service::AM::Applets {
 
diff --git a/src/core/hle/service/am/applets/applet_web_browser.cpp b/src/core/hle/service/am/applets/applet_web_browser.cpp
index 19057ad7b..871737b3e 100644
--- a/src/core/hle/service/am/applets/applet_web_browser.cpp
+++ b/src/core/hle/service/am/applets/applet_web_browser.cpp
@@ -20,6 +20,7 @@
 #include "core/hle/result.h"
 #include "core/hle/service/am/am.h"
 #include "core/hle/service/am/applets/applet_web_browser.h"
+#include "core/hle/service/am/storage.h"
 #include "core/hle/service/filesystem/filesystem.h"
 #include "core/hle/service/ns/iplatform_service_manager.h"
 #include "core/loader/loader.h"
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index 89d5434af..6a47f4b7a 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -16,6 +16,7 @@
 #include "core/hle/kernel/k_event.h"
 #include "core/hle/service/am/am.h"
 #include "core/hle/service/am/applet_ae.h"
+#include "core/hle/service/am/applet_message_queue.h"
 #include "core/hle/service/am/applet_oe.h"
 #include "core/hle/service/am/applets/applet_cabinet.h"
 #include "core/hle/service/am/applets/applet_controller.h"
@@ -26,13 +27,14 @@
 #include "core/hle/service/am/applets/applet_software_keyboard.h"
 #include "core/hle/service/am/applets/applet_web_browser.h"
 #include "core/hle/service/am/applets/applets.h"
+#include "core/hle/service/am/storage.h"
 #include "core/hle/service/sm/sm.h"
 
 namespace Service::AM::Applets {
 
 AppletDataBroker::AppletDataBroker(Core::System& system_, LibraryAppletMode applet_mode_)
-    : system{system_}, applet_mode{applet_mode_}, service_context{system,
-                                                                  "ILibraryAppletAccessor"} {
+    : system{system_}, applet_mode{applet_mode_},
+      service_context{system, "ILibraryAppletAccessor"} {
     state_changed_event = service_context.CreateEvent("ILibraryAppletAccessor:StateChangedEvent");
     pop_out_data_event = service_context.CreateEvent("ILibraryAppletAccessor:PopDataOutEvent");
     pop_interactive_out_data_event =
diff --git a/src/core/hle/service/am/application_creator.cpp b/src/core/hle/service/am/application_creator.cpp
new file mode 100644
index 000000000..79ea045a3
--- /dev/null
+++ b/src/core/hle/service/am/application_creator.cpp
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/application_creator.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::AM {
+
+IApplicationCreator::IApplicationCreator(Core::System& system_)
+    : ServiceFramework{system_, "IApplicationCreator"} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, nullptr, "CreateApplication"},
+        {1, nullptr, "PopLaunchRequestedApplication"},
+        {10, nullptr, "CreateSystemApplication"},
+        {100, nullptr, "PopFloatingApplicationForDevelopment"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+IApplicationCreator::~IApplicationCreator() = default;
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/application_creator.h b/src/core/hle/service/am/application_creator.h
new file mode 100644
index 000000000..375a3c476
--- /dev/null
+++ b/src/core/hle/service/am/application_creator.h
@@ -0,0 +1,16 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class IApplicationCreator final : public ServiceFramework<IApplicationCreator> {
+public:
+    explicit IApplicationCreator(Core::System& system_);
+    ~IApplicationCreator() override;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/application_functions.cpp b/src/core/hle/service/am/application_functions.cpp
new file mode 100644
index 000000000..fef45c732
--- /dev/null
+++ b/src/core/hle/service/am/application_functions.cpp
@@ -0,0 +1,610 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/settings.h"
+#include "common/uuid.h"
+#include "core/file_sys/control_metadata.h"
+#include "core/file_sys/patch_manager.h"
+#include "core/file_sys/registered_cache.h"
+#include "core/file_sys/savedata_factory.h"
+#include "core/hle/service/acc/profile_manager.h"
+#include "core/hle/service/am/am_results.h"
+#include "core/hle/service/am/application_functions.h"
+#include "core/hle/service/am/storage.h"
+#include "core/hle/service/filesystem/filesystem.h"
+#include "core/hle/service/filesystem/save_data_controller.h"
+#include "core/hle/service/ipc_helpers.h"
+#include "core/hle/service/ns/ns.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::AM {
+
+enum class LaunchParameterKind : u32 {
+    UserChannel = 1,
+    AccountPreselectedUser = 2,
+};
+
+constexpr u32 LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC = 0xC79497CA;
+
+struct LaunchParameterAccountPreselectedUser {
+    u32_le magic;
+    u32_le is_account_selected;
+    Common::UUID current_user;
+    INSERT_PADDING_BYTES(0x70);
+};
+static_assert(sizeof(LaunchParameterAccountPreselectedUser) == 0x88);
+
+IApplicationFunctions::IApplicationFunctions(Core::System& system_)
+    : ServiceFramework{system_, "IApplicationFunctions"},
+      service_context{system, "IApplicationFunctions"} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"},
+        {10, nullptr, "CreateApplicationAndPushAndRequestToStart"},
+        {11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"},
+        {12, nullptr, "CreateApplicationAndRequestToStart"},
+        {13, &IApplicationFunctions::CreateApplicationAndRequestToStartForQuest, "CreateApplicationAndRequestToStartForQuest"},
+        {14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"},
+        {15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"},
+        {20, &IApplicationFunctions::EnsureSaveData, "EnsureSaveData"},
+        {21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"},
+        {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
+        {23, &IApplicationFunctions::GetDisplayVersion, "GetDisplayVersion"},
+        {24, nullptr, "GetLaunchStorageInfoForDebug"},
+        {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"},
+        {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"},
+        {27, &IApplicationFunctions::CreateCacheStorage, "CreateCacheStorage"},
+        {28, &IApplicationFunctions::GetSaveDataSizeMax, "GetSaveDataSizeMax"},
+        {29, nullptr, "GetCacheStorageMax"},
+        {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"},
+        {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"},
+        {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"},
+        {33, &IApplicationFunctions::EndBlockingHomeButton, "EndBlockingHomeButton"},
+        {34, nullptr, "SelectApplicationLicense"},
+        {35, nullptr, "GetDeviceSaveDataSizeMax"},
+        {36, nullptr, "GetLimitedApplicationLicense"},
+        {37, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"},
+        {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"},
+        {50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"},
+        {60, nullptr, "SetMediaPlaybackStateForApplication"},
+        {65, &IApplicationFunctions::IsGamePlayRecordingSupported, "IsGamePlayRecordingSupported"},
+        {66, &IApplicationFunctions::InitializeGamePlayRecording, "InitializeGamePlayRecording"},
+        {67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"},
+        {68, nullptr, "RequestFlushGamePlayingMovieForDebug"},
+        {70, nullptr, "RequestToShutdown"},
+        {71, nullptr, "RequestToReboot"},
+        {72, nullptr, "RequestToSleep"},
+        {80, nullptr, "ExitAndRequestToShowThanksMessage"},
+        {90, &IApplicationFunctions::EnableApplicationCrashReport, "EnableApplicationCrashReport"},
+        {100, &IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer, "InitializeApplicationCopyrightFrameBuffer"},
+        {101, &IApplicationFunctions::SetApplicationCopyrightImage, "SetApplicationCopyrightImage"},
+        {102, &IApplicationFunctions::SetApplicationCopyrightVisibility, "SetApplicationCopyrightVisibility"},
+        {110, &IApplicationFunctions::QueryApplicationPlayStatistics, "QueryApplicationPlayStatistics"},
+        {111, &IApplicationFunctions::QueryApplicationPlayStatisticsByUid, "QueryApplicationPlayStatisticsByUid"},
+        {120, &IApplicationFunctions::ExecuteProgram, "ExecuteProgram"},
+        {121, &IApplicationFunctions::ClearUserChannel, "ClearUserChannel"},
+        {122, &IApplicationFunctions::UnpopToUserChannel, "UnpopToUserChannel"},
+        {123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"},
+        {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
+        {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"},
+        {131, nullptr, "SetDelayTimeToAbortOnGpuError"},
+        {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"},
+        {141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"},
+        {150, &IApplicationFunctions::GetNotificationStorageChannelEvent, "GetNotificationStorageChannelEvent"},
+        {151, nullptr, "TryPopFromNotificationStorageChannel"},
+        {160, &IApplicationFunctions::GetHealthWarningDisappearedSystemEvent, "GetHealthWarningDisappearedSystemEvent"},
+        {170, nullptr, "SetHdcpAuthenticationActivated"},
+        {180, nullptr, "GetLaunchRequiredVersion"},
+        {181, nullptr, "UpgradeLaunchRequiredVersion"},
+        {190, nullptr, "SendServerMaintenanceOverlayNotification"},
+        {200, nullptr, "GetLastApplicationExitReason"},
+        {500, nullptr, "StartContinuousRecordingFlushForDebug"},
+        {1000, nullptr, "CreateMovieMaker"},
+        {1001, &IApplicationFunctions::PrepareForJit, "PrepareForJit"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+
+    gpu_error_detected_event =
+        service_context.CreateEvent("IApplicationFunctions:GpuErrorDetectedSystemEvent");
+    friend_invitation_storage_channel_event =
+        service_context.CreateEvent("IApplicationFunctions:FriendInvitationStorageChannelEvent");
+    notification_storage_channel_event =
+        service_context.CreateEvent("IApplicationFunctions:NotificationStorageChannelEvent");
+    health_warning_disappeared_system_event =
+        service_context.CreateEvent("IApplicationFunctions:HealthWarningDisappearedSystemEvent");
+}
+
+IApplicationFunctions::~IApplicationFunctions() {
+    service_context.CloseEvent(gpu_error_detected_event);
+    service_context.CloseEvent(friend_invitation_storage_channel_event);
+    service_context.CloseEvent(notification_storage_channel_event);
+    service_context.CloseEvent(health_warning_disappeared_system_event);
+}
+
+void IApplicationFunctions::EnableApplicationCrashReport(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IApplicationFunctions::SetApplicationCopyrightImage(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IApplicationFunctions::SetApplicationCopyrightVisibility(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const auto is_visible = rp.Pop<bool>();
+
+    LOG_WARNING(Service_AM, "(STUBBED) called, is_visible={}", is_visible);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IApplicationFunctions::BeginBlockingHomeButton(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IApplicationFunctions::EndBlockingHomeButton(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const auto kind = rp.PopEnum<LaunchParameterKind>();
+
+    LOG_INFO(Service_AM, "called, kind={:08X}", kind);
+
+    if (kind == LaunchParameterKind::UserChannel) {
+        auto channel = system.GetUserChannel();
+        if (channel.empty()) {
+            LOG_ERROR(Service_AM, "Attempted to load launch parameter but none was found!");
+            IPC::ResponseBuilder rb{ctx, 2};
+            rb.Push(AM::ResultNoDataInChannel);
+            return;
+        }
+
+        auto data = channel.back();
+        channel.pop_back();
+
+        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+        rb.Push(ResultSuccess);
+        rb.PushIpcInterface<IStorage>(system, std::move(data));
+    } else if (kind == LaunchParameterKind::AccountPreselectedUser &&
+               !launch_popped_account_preselect) {
+        // TODO: Verify this is hw-accurate
+        LaunchParameterAccountPreselectedUser params{};
+
+        params.magic = LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC;
+        params.is_account_selected = 1;
+
+        Account::ProfileManager profile_manager{};
+        const auto uuid = profile_manager.GetUser(static_cast<s32>(Settings::values.current_user));
+        ASSERT(uuid.has_value() && uuid->IsValid());
+        params.current_user = *uuid;
+
+        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+        rb.Push(ResultSuccess);
+
+        std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser));
+        std::memcpy(buffer.data(), &params, buffer.size());
+
+        rb.PushIpcInterface<IStorage>(system, std::move(buffer));
+        launch_popped_account_preselect = true;
+    } else {
+        LOG_ERROR(Service_AM, "Unknown launch parameter kind.");
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(AM::ResultNoDataInChannel);
+    }
+}
+
+void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IApplicationFunctions::EnsureSaveData(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    u128 user_id = rp.PopRaw<u128>();
+
+    LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]);
+
+    FileSys::SaveDataAttribute attribute{};
+    attribute.title_id = system.GetApplicationProcessProgramID();
+    attribute.user_id = user_id;
+    attribute.type = FileSys::SaveDataType::SaveData;
+
+    FileSys::VirtualDir save_data{};
+    const auto res = system.GetFileSystemController().OpenSaveDataController()->CreateSaveData(
+        &save_data, FileSys::SaveDataSpaceId::NandUser, attribute);
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(res);
+    rb.Push<u64>(0);
+}
+
+void IApplicationFunctions::SetTerminateResult(HLERequestContext& ctx) {
+    // Takes an input u32 Result, no output.
+    // For example, in some cases official apps use this with error 0x2A2 then
+    // uses svcBreak.
+
+    IPC::RequestParser rp{ctx};
+    u32 result = rp.Pop<u32>();
+    LOG_WARNING(Service_AM, "(STUBBED) called, result=0x{:08X}", result);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IApplicationFunctions::GetDisplayVersion(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    std::array<u8, 0x10> version_string{};
+
+    const auto res = [this] {
+        const auto title_id = system.GetApplicationProcessProgramID();
+
+        const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
+                                       system.GetContentProvider()};
+        auto metadata = pm.GetControlMetadata();
+        if (metadata.first != nullptr) {
+            return metadata;
+        }
+
+        const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id),
+                                              system.GetFileSystemController(),
+                                              system.GetContentProvider()};
+        return pm_update.GetControlMetadata();
+    }();
+
+    if (res.first != nullptr) {
+        const auto& version = res.first->GetVersionString();
+        std::copy(version.begin(), version.end(), version_string.begin());
+    } else {
+        static constexpr char default_version[]{"1.0.0"};
+        std::memcpy(version_string.data(), default_version, sizeof(default_version));
+    }
+
+    IPC::ResponseBuilder rb{ctx, 6};
+    rb.Push(ResultSuccess);
+    rb.PushRaw(version_string);
+}
+
+void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) {
+    // TODO(bunnei): This should be configurable
+    LOG_DEBUG(Service_AM, "called");
+
+    // Get supported languages from NACP, if possible
+    // Default to 0 (all languages supported)
+    u32 supported_languages = 0;
+
+    const auto res = [this] {
+        const auto title_id = system.GetApplicationProcessProgramID();
+
+        const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
+                                       system.GetContentProvider()};
+        auto metadata = pm.GetControlMetadata();
+        if (metadata.first != nullptr) {
+            return metadata;
+        }
+
+        const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id),
+                                              system.GetFileSystemController(),
+                                              system.GetContentProvider()};
+        return pm_update.GetControlMetadata();
+    }();
+
+    if (res.first != nullptr) {
+        supported_languages = res.first->GetSupportedLanguages();
+    }
+
+    // Call IApplicationManagerInterface implementation.
+    auto& service_manager = system.ServiceManager();
+    auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2");
+    auto app_man = ns_am2->GetApplicationManagerInterface();
+
+    // Get desired application language
+    u8 desired_language{};
+    const auto res_lang =
+        app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages);
+    if (res_lang != ResultSuccess) {
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(res_lang);
+        return;
+    }
+
+    // Convert to settings language code.
+    u64 language_code{};
+    const auto res_code =
+        app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language);
+    if (res_code != ResultSuccess) {
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(res_code);
+        return;
+    }
+
+    LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code);
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(ResultSuccess);
+    rb.Push(language_code);
+}
+
+void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    constexpr bool gameplay_recording_supported = false;
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push(gameplay_recording_supported);
+}
+
+void IApplicationFunctions::InitializeGamePlayRecording(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IApplicationFunctions::SetGamePlayRecordingState(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IApplicationFunctions::NotifyRunning(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push<u8>(0); // Unknown, seems to be ignored by official processes
+}
+
+void IApplicationFunctions::GetPseudoDeviceId(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 6};
+    rb.Push(ResultSuccess);
+
+    // Returns a 128-bit UUID
+    rb.Push<u64>(0);
+    rb.Push<u64>(0);
+}
+
+void IApplicationFunctions::ExtendSaveData(HLERequestContext& ctx) {
+    struct Parameters {
+        FileSys::SaveDataType type;
+        u128 user_id;
+        u64 new_normal_size;
+        u64 new_journal_size;
+    };
+    static_assert(sizeof(Parameters) == 40);
+
+    IPC::RequestParser rp{ctx};
+    const auto [type, user_id, new_normal_size, new_journal_size] = rp.PopRaw<Parameters>();
+
+    LOG_DEBUG(Service_AM,
+              "called with type={:02X}, user_id={:016X}{:016X}, new_normal={:016X}, "
+              "new_journal={:016X}",
+              static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size);
+
+    system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize(
+        type, system.GetApplicationProcessProgramID(), user_id,
+        {new_normal_size, new_journal_size});
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(ResultSuccess);
+
+    // The following value is used upon failure to help the system recover.
+    // Since we always succeed, this should be 0.
+    rb.Push<u64>(0);
+}
+
+void IApplicationFunctions::GetSaveDataSize(HLERequestContext& ctx) {
+    struct Parameters {
+        FileSys::SaveDataType type;
+        u128 user_id;
+    };
+    static_assert(sizeof(Parameters) == 24);
+
+    IPC::RequestParser rp{ctx};
+    const auto [type, user_id] = rp.PopRaw<Parameters>();
+
+    LOG_DEBUG(Service_AM, "called with type={:02X}, user_id={:016X}{:016X}", type, user_id[1],
+              user_id[0]);
+
+    const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize(
+        type, system.GetApplicationProcessProgramID(), user_id);
+
+    IPC::ResponseBuilder rb{ctx, 6};
+    rb.Push(ResultSuccess);
+    rb.Push(size.normal);
+    rb.Push(size.journal);
+}
+
+void IApplicationFunctions::CreateCacheStorage(HLERequestContext& ctx) {
+    struct InputParameters {
+        u16 index;
+        s64 size;
+        s64 journal_size;
+    };
+    static_assert(sizeof(InputParameters) == 24);
+
+    struct OutputParameters {
+        u32 storage_target;
+        u64 required_size;
+    };
+    static_assert(sizeof(OutputParameters) == 16);
+
+    IPC::RequestParser rp{ctx};
+    const auto params = rp.PopRaw<InputParameters>();
+
+    LOG_WARNING(Service_AM, "(STUBBED) called with index={}, size={:#x}, journal_size={:#x}",
+                params.index, params.size, params.journal_size);
+
+    const OutputParameters resp{
+        .storage_target = 1,
+        .required_size = 0,
+    };
+
+    IPC::ResponseBuilder rb{ctx, 6};
+    rb.Push(ResultSuccess);
+    rb.PushRaw(resp);
+}
+
+void IApplicationFunctions::GetSaveDataSizeMax(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    constexpr u64 size_max_normal = 0xFFFFFFF;
+    constexpr u64 size_max_journal = 0xFFFFFFF;
+
+    IPC::ResponseBuilder rb{ctx, 6};
+    rb.Push(ResultSuccess);
+    rb.Push(size_max_normal);
+    rb.Push(size_max_journal);
+}
+
+void IApplicationFunctions::QueryApplicationPlayStatistics(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push<u32>(0);
+}
+
+void IApplicationFunctions::QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push<u32>(0);
+}
+
+void IApplicationFunctions::ExecuteProgram(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::RequestParser rp{ctx};
+    [[maybe_unused]] const auto unk_1 = rp.Pop<u32>();
+    [[maybe_unused]] const auto unk_2 = rp.Pop<u32>();
+    const auto program_index = rp.Pop<u64>();
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+
+    system.ExecuteProgram(program_index);
+}
+
+void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    system.GetUserChannel().clear();
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IApplicationFunctions::UnpopToUserChannel(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::RequestParser rp{ctx};
+    const auto storage = rp.PopIpcInterface<IStorage>().lock();
+    if (storage) {
+        system.GetUserChannel().push_back(storage->GetData());
+    }
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IApplicationFunctions::GetPreviousProgramIndex(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push<s32>(previous_program_index);
+}
+
+void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 1};
+    rb.Push(ResultSuccess);
+    rb.PushCopyObjects(gpu_error_detected_event->GetReadableEvent());
+}
+
+void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 1};
+    rb.Push(ResultSuccess);
+    rb.PushCopyObjects(friend_invitation_storage_channel_event->GetReadableEvent());
+}
+
+void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(AM::ResultNoDataInChannel);
+}
+
+void IApplicationFunctions::GetNotificationStorageChannelEvent(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 1};
+    rb.Push(ResultSuccess);
+    rb.PushCopyObjects(notification_storage_channel_event->GetReadableEvent());
+}
+
+void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 1};
+    rb.Push(ResultSuccess);
+    rb.PushCopyObjects(health_warning_disappeared_system_event->GetReadableEvent());
+}
+
+void IApplicationFunctions::PrepareForJit(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/application_functions.h b/src/core/hle/service/am/application_functions.h
new file mode 100644
index 000000000..22aab1c8f
--- /dev/null
+++ b/src/core/hle/service/am/application_functions.h
@@ -0,0 +1,63 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
+public:
+    explicit IApplicationFunctions(Core::System& system_);
+    ~IApplicationFunctions() override;
+
+private:
+    void PopLaunchParameter(HLERequestContext& ctx);
+    void CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx);
+    void EnsureSaveData(HLERequestContext& ctx);
+    void SetTerminateResult(HLERequestContext& ctx);
+    void GetDisplayVersion(HLERequestContext& ctx);
+    void GetDesiredLanguage(HLERequestContext& ctx);
+    void IsGamePlayRecordingSupported(HLERequestContext& ctx);
+    void InitializeGamePlayRecording(HLERequestContext& ctx);
+    void SetGamePlayRecordingState(HLERequestContext& ctx);
+    void NotifyRunning(HLERequestContext& ctx);
+    void GetPseudoDeviceId(HLERequestContext& ctx);
+    void ExtendSaveData(HLERequestContext& ctx);
+    void GetSaveDataSize(HLERequestContext& ctx);
+    void CreateCacheStorage(HLERequestContext& ctx);
+    void GetSaveDataSizeMax(HLERequestContext& ctx);
+    void BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx);
+    void EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx);
+    void BeginBlockingHomeButton(HLERequestContext& ctx);
+    void EndBlockingHomeButton(HLERequestContext& ctx);
+    void EnableApplicationCrashReport(HLERequestContext& ctx);
+    void InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx);
+    void SetApplicationCopyrightImage(HLERequestContext& ctx);
+    void SetApplicationCopyrightVisibility(HLERequestContext& ctx);
+    void QueryApplicationPlayStatistics(HLERequestContext& ctx);
+    void QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx);
+    void ExecuteProgram(HLERequestContext& ctx);
+    void ClearUserChannel(HLERequestContext& ctx);
+    void UnpopToUserChannel(HLERequestContext& ctx);
+    void GetPreviousProgramIndex(HLERequestContext& ctx);
+    void GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx);
+    void GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx);
+    void TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx);
+    void GetNotificationStorageChannelEvent(HLERequestContext& ctx);
+    void GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx);
+    void PrepareForJit(HLERequestContext& ctx);
+
+    KernelHelpers::ServiceContext service_context;
+
+    bool launch_popped_account_preselect = false;
+    s32 previous_program_index{-1};
+    Kernel::KEvent* gpu_error_detected_event;
+    Kernel::KEvent* friend_invitation_storage_channel_event;
+    Kernel::KEvent* notification_storage_channel_event;
+    Kernel::KEvent* health_warning_disappeared_system_event;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/application_proxy.cpp b/src/core/hle/service/am/application_proxy.cpp
new file mode 100644
index 000000000..e9cd0aa71
--- /dev/null
+++ b/src/core/hle/service/am/application_proxy.cpp
@@ -0,0 +1,114 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/applet_common_functions.h"
+#include "core/hle/service/am/application_functions.h"
+#include "core/hle/service/am/application_proxy.h"
+#include "core/hle/service/am/audio_controller.h"
+#include "core/hle/service/am/common_state_getter.h"
+#include "core/hle/service/am/debug_functions.h"
+#include "core/hle/service/am/display_controller.h"
+#include "core/hle/service/am/library_applet_creator.h"
+#include "core/hle/service/am/library_applet_self_accessor.h"
+#include "core/hle/service/am/process_winding_controller.h"
+#include "core/hle/service/am/self_controller.h"
+#include "core/hle/service/am/window_controller.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::AM {
+
+IApplicationProxy::IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_,
+                                     std::shared_ptr<AppletMessageQueue> msg_queue_,
+                                     Core::System& system_)
+    : ServiceFramework{system_, "IApplicationProxy"}, nvnflinger{nvnflinger_},
+      msg_queue{std::move(msg_queue_)} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"},
+        {1, &IApplicationProxy::GetSelfController, "GetSelfController"},
+        {2, &IApplicationProxy::GetWindowController, "GetWindowController"},
+        {3, &IApplicationProxy::GetAudioController, "GetAudioController"},
+        {4, &IApplicationProxy::GetDisplayController, "GetDisplayController"},
+        {10, &IApplicationProxy::GetProcessWindingController, "GetProcessWindingController"},
+        {11, &IApplicationProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
+        {20, &IApplicationProxy::GetApplicationFunctions, "GetApplicationFunctions"},
+        {1000, &IApplicationProxy::GetDebugFunctions, "GetDebugFunctions"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+void IApplicationProxy::GetAudioController(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IAudioController>(system);
+}
+
+void IApplicationProxy::GetDisplayController(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IDisplayController>(system);
+}
+
+void IApplicationProxy::GetProcessWindingController(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IProcessWindingController>(system);
+}
+
+void IApplicationProxy::GetDebugFunctions(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IDebugFunctions>(system);
+}
+
+void IApplicationProxy::GetWindowController(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IWindowController>(system);
+}
+
+void IApplicationProxy::GetSelfController(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<ISelfController>(system, nvnflinger);
+}
+
+void IApplicationProxy::GetCommonStateGetter(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue);
+}
+
+void IApplicationProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<ILibraryAppletCreator>(system);
+}
+
+void IApplicationProxy::GetApplicationFunctions(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IApplicationFunctions>(system);
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/application_proxy.h b/src/core/hle/service/am/application_proxy.h
new file mode 100644
index 000000000..4f620242b
--- /dev/null
+++ b/src/core/hle/service/am/application_proxy.h
@@ -0,0 +1,32 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/am/applet_message_queue.h"
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
+public:
+    explicit IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_,
+                               std::shared_ptr<AppletMessageQueue> msg_queue_,
+                               Core::System& system_);
+
+private:
+    void GetAudioController(HLERequestContext& ctx);
+    void GetDisplayController(HLERequestContext& ctx);
+    void GetProcessWindingController(HLERequestContext& ctx);
+    void GetDebugFunctions(HLERequestContext& ctx);
+    void GetWindowController(HLERequestContext& ctx);
+    void GetSelfController(HLERequestContext& ctx);
+    void GetCommonStateGetter(HLERequestContext& ctx);
+    void GetLibraryAppletCreator(HLERequestContext& ctx);
+    void GetApplicationFunctions(HLERequestContext& ctx);
+
+    Nvnflinger::Nvnflinger& nvnflinger;
+    std::shared_ptr<AppletMessageQueue> msg_queue;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/audio_controller.cpp b/src/core/hle/service/am/audio_controller.cpp
new file mode 100644
index 000000000..ae75db174
--- /dev/null
+++ b/src/core/hle/service/am/audio_controller.cpp
@@ -0,0 +1,91 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/audio_controller.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::AM {
+
+IAudioController::IAudioController(Core::System& system_)
+    : ServiceFramework{system_, "IAudioController"} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, &IAudioController::SetExpectedMasterVolume, "SetExpectedMasterVolume"},
+        {1, &IAudioController::GetMainAppletExpectedMasterVolume, "GetMainAppletExpectedMasterVolume"},
+        {2, &IAudioController::GetLibraryAppletExpectedMasterVolume, "GetLibraryAppletExpectedMasterVolume"},
+        {3, &IAudioController::ChangeMainAppletMasterVolume, "ChangeMainAppletMasterVolume"},
+        {4, &IAudioController::SetTransparentAudioRate, "SetTransparentVolumeRate"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+IAudioController::~IAudioController() = default;
+
+void IAudioController::SetExpectedMasterVolume(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const float main_applet_volume_tmp = rp.Pop<float>();
+    const float library_applet_volume_tmp = rp.Pop<float>();
+
+    LOG_DEBUG(Service_AM, "called. main_applet_volume={}, library_applet_volume={}",
+              main_applet_volume_tmp, library_applet_volume_tmp);
+
+    // Ensure the volume values remain within the 0-100% range
+    main_applet_volume = std::clamp(main_applet_volume_tmp, min_allowed_volume, max_allowed_volume);
+    library_applet_volume =
+        std::clamp(library_applet_volume_tmp, min_allowed_volume, max_allowed_volume);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IAudioController::GetMainAppletExpectedMasterVolume(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called. main_applet_volume={}", main_applet_volume);
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push(main_applet_volume);
+}
+
+void IAudioController::GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called. library_applet_volume={}", library_applet_volume);
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push(library_applet_volume);
+}
+
+void IAudioController::ChangeMainAppletMasterVolume(HLERequestContext& ctx) {
+    struct Parameters {
+        float volume;
+        s64 fade_time_ns;
+    };
+    static_assert(sizeof(Parameters) == 16);
+
+    IPC::RequestParser rp{ctx};
+    const auto parameters = rp.PopRaw<Parameters>();
+
+    LOG_DEBUG(Service_AM, "called. volume={}, fade_time_ns={}", parameters.volume,
+              parameters.fade_time_ns);
+
+    main_applet_volume = std::clamp(parameters.volume, min_allowed_volume, max_allowed_volume);
+    fade_time_ns = std::chrono::nanoseconds{parameters.fade_time_ns};
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IAudioController::SetTransparentAudioRate(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const float transparent_volume_rate_tmp = rp.Pop<float>();
+
+    LOG_DEBUG(Service_AM, "called. transparent_volume_rate={}", transparent_volume_rate_tmp);
+
+    // Clamp volume range to 0-100%.
+    transparent_volume_rate =
+        std::clamp(transparent_volume_rate_tmp, min_allowed_volume, max_allowed_volume);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/audio_controller.h b/src/core/hle/service/am/audio_controller.h
new file mode 100644
index 000000000..a47e3bad8
--- /dev/null
+++ b/src/core/hle/service/am/audio_controller.h
@@ -0,0 +1,36 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class IAudioController final : public ServiceFramework<IAudioController> {
+public:
+    explicit IAudioController(Core::System& system_);
+    ~IAudioController() override;
+
+private:
+    void SetExpectedMasterVolume(HLERequestContext& ctx);
+    void GetMainAppletExpectedMasterVolume(HLERequestContext& ctx);
+    void GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx);
+    void ChangeMainAppletMasterVolume(HLERequestContext& ctx);
+    void SetTransparentAudioRate(HLERequestContext& ctx);
+
+    static constexpr float min_allowed_volume = 0.0f;
+    static constexpr float max_allowed_volume = 1.0f;
+
+    float main_applet_volume{0.25f};
+    float library_applet_volume{max_allowed_volume};
+    float transparent_volume_rate{min_allowed_volume};
+
+    // Volume transition fade time in nanoseconds.
+    // e.g. If the main applet volume was 0% and was changed to 50%
+    //      with a fade of 50ns, then over the course of 50ns,
+    //      the volume will gradually fade up to 50%
+    std::chrono::nanoseconds fade_time_ns{0};
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/common_state_getter.cpp b/src/core/hle/service/am/common_state_getter.cpp
new file mode 100644
index 000000000..0b54b769d
--- /dev/null
+++ b/src/core/hle/service/am/common_state_getter.cpp
@@ -0,0 +1,288 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/settings.h"
+#include "core/hle/service/am/am_results.h"
+#include "core/hle/service/am/common_state_getter.h"
+#include "core/hle/service/am/lock_accessor.h"
+#include "core/hle/service/apm/apm_controller.h"
+#include "core/hle/service/apm/apm_interface.h"
+#include "core/hle/service/ipc_helpers.h"
+#include "core/hle/service/pm/pm.h"
+#include "core/hle/service/sm/sm.h"
+#include "core/hle/service/vi/vi.h"
+
+namespace Service::AM {
+
+ICommonStateGetter::ICommonStateGetter(Core::System& system_,
+                                       std::shared_ptr<AppletMessageQueue> msg_queue_)
+    : ServiceFramework{system_, "ICommonStateGetter"}, msg_queue{std::move(msg_queue_)},
+      service_context{system_, "ICommonStateGetter"} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"},
+        {1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"},
+        {2, nullptr, "GetThisAppletKind"},
+        {3, nullptr, "AllowToEnterSleep"},
+        {4, nullptr, "DisallowToEnterSleep"},
+        {5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"},
+        {6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"},
+        {7, nullptr, "GetCradleStatus"},
+        {8, &ICommonStateGetter::GetBootMode, "GetBootMode"},
+        {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"},
+        {10, &ICommonStateGetter::RequestToAcquireSleepLock, "RequestToAcquireSleepLock"},
+        {11, nullptr, "ReleaseSleepLock"},
+        {12, nullptr, "ReleaseSleepLockTransiently"},
+        {13, &ICommonStateGetter::GetAcquiredSleepLockEvent, "GetAcquiredSleepLockEvent"},
+        {14, nullptr, "GetWakeupCount"},
+        {20, nullptr, "PushToGeneralChannel"},
+        {30, nullptr, "GetHomeButtonReaderLockAccessor"},
+        {31, &ICommonStateGetter::GetReaderLockAccessorEx, "GetReaderLockAccessorEx"},
+        {32, nullptr, "GetWriterLockAccessorEx"},
+        {40, nullptr, "GetCradleFwVersion"},
+        {50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"},
+        {51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"},
+        {52, &ICommonStateGetter::SetLcdBacklighOffEnabled, "SetLcdBacklighOffEnabled"},
+        {53, &ICommonStateGetter::BeginVrModeEx, "BeginVrModeEx"},
+        {54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"},
+        {55, nullptr, "IsInControllerFirmwareUpdateSection"},
+        {59, nullptr, "SetVrPositionForDebug"},
+        {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"},
+        {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"},
+        {62, nullptr, "GetHdcpAuthenticationState"},
+        {63, nullptr, "GetHdcpAuthenticationStateChangeEvent"},
+        {64, nullptr, "SetTvPowerStateMatchingMode"},
+        {65, nullptr, "GetApplicationIdByContentActionName"},
+        {66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"},
+        {67, nullptr, "CancelCpuBoostMode"},
+        {68, &ICommonStateGetter::GetBuiltInDisplayType, "GetBuiltInDisplayType"},
+        {80, &ICommonStateGetter::PerformSystemButtonPressingIfInFocus, "PerformSystemButtonPressingIfInFocus"},
+        {90, nullptr, "SetPerformanceConfigurationChangedNotification"},
+        {91, nullptr, "GetCurrentPerformanceConfiguration"},
+        {100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"},
+        {110, nullptr, "OpenMyGpuErrorHandler"},
+        {120, nullptr, "GetAppletLaunchedHistory"},
+        {200, nullptr, "GetOperationModeSystemInfo"},
+        {300, &ICommonStateGetter::GetSettingsPlatformRegion, "GetSettingsPlatformRegion"},
+        {400, nullptr, "ActivateMigrationService"},
+        {401, nullptr, "DeactivateMigrationService"},
+        {500, nullptr, "DisableSleepTillShutdown"},
+        {501, nullptr, "SuppressDisablingSleepTemporarily"},
+        {502, nullptr, "IsSleepEnabled"},
+        {503, nullptr, "IsDisablingSleepSuppressed"},
+        {900, &ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+
+    sleep_lock_event = service_context.CreateEvent("ICommonStateGetter::SleepLockEvent");
+
+    // Configure applets to be in foreground state
+    msg_queue->PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
+    msg_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
+}
+
+ICommonStateGetter::~ICommonStateGetter() {
+    service_context.CloseEvent(sleep_lock_event);
+};
+
+void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push<u8>(static_cast<u8>(Service::PM::SystemBootMode::Normal)); // Normal boot mode
+}
+
+void ICommonStateGetter::GetEventHandle(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 1};
+    rb.Push(ResultSuccess);
+    rb.PushCopyObjects(msg_queue->GetMessageReceiveEvent());
+}
+
+void ICommonStateGetter::ReceiveMessage(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    const auto message = msg_queue->PopMessage();
+    IPC::ResponseBuilder rb{ctx, 3};
+
+    if (message == AppletMessageQueue::AppletMessage::None) {
+        LOG_ERROR(Service_AM, "Message queue is empty");
+        rb.Push(AM::ResultNoMessages);
+        rb.PushEnum<AppletMessageQueue::AppletMessage>(message);
+        return;
+    }
+
+    rb.Push(ResultSuccess);
+    rb.PushEnum<AppletMessageQueue::AppletMessage>(message);
+}
+
+void ICommonStateGetter::GetCurrentFocusState(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push(static_cast<u8>(FocusState::InFocus));
+}
+
+void ICommonStateGetter::GetOperationMode(HLERequestContext& ctx) {
+    const bool use_docked_mode{Settings::IsDockedMode()};
+    LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode);
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld));
+}
+
+void ICommonStateGetter::GetPerformanceMode(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.PushEnum(system.GetAPMController().GetCurrentPerformanceMode());
+}
+
+void ICommonStateGetter::RequestToAcquireSleepLock(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    // Sleep lock is acquired immediately.
+    sleep_lock_event->Signal();
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ICommonStateGetter::GetReaderLockAccessorEx(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const auto unknown = rp.Pop<u32>();
+
+    LOG_INFO(Service_AM, "called, unknown={}", unknown);
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<ILockAccessor>(system);
+}
+
+void ICommonStateGetter::GetAcquiredSleepLockEvent(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 1};
+    rb.Push(ResultSuccess);
+    rb.PushCopyObjects(sleep_lock_event->GetReadableEvent());
+}
+
+void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push(vr_mode_state);
+}
+
+void ICommonStateGetter::SetVrModeEnabled(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    vr_mode_state = rp.Pop<bool>();
+
+    LOG_WARNING(Service_AM, "VR Mode is {}", vr_mode_state ? "on" : "off");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ICommonStateGetter::SetLcdBacklighOffEnabled(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const auto is_lcd_backlight_off_enabled = rp.Pop<bool>();
+
+    LOG_WARNING(Service_AM, "(STUBBED) called. is_lcd_backlight_off_enabled={}",
+                is_lcd_backlight_off_enabled);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ICommonStateGetter::BeginVrModeEx(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ICommonStateGetter::EndVrModeEx(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 1};
+    rb.Push(ResultSuccess);
+    rb.PushCopyObjects(msg_queue->GetOperationModeChangedEvent());
+}
+
+void ICommonStateGetter::GetDefaultDisplayResolution(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(ResultSuccess);
+
+    if (Settings::IsDockedMode()) {
+        rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth));
+        rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight));
+    } else {
+        rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth));
+        rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight));
+    }
+}
+
+void ICommonStateGetter::SetCpuBoostMode(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called, forwarding to APM:SYS");
+
+    const auto& sm = system.ServiceManager();
+    const auto apm_sys = sm.GetService<APM::APM_Sys>("apm:sys");
+    ASSERT(apm_sys != nullptr);
+
+    apm_sys->SetCpuBoostMode(ctx);
+}
+
+void ICommonStateGetter::GetBuiltInDisplayType(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push(0);
+}
+
+void ICommonStateGetter::PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const auto system_button{rp.PopEnum<SystemButtonType>()};
+
+    LOG_WARNING(Service_AM, "(STUBBED) called, system_button={}", system_button);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ICommonStateGetter::GetSettingsPlatformRegion(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.PushEnum(SysPlatformRegion::Global);
+}
+
+void ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(
+    HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/common_state_getter.h b/src/core/hle/service/am/common_state_getter.h
new file mode 100644
index 000000000..11d66f10a
--- /dev/null
+++ b/src/core/hle/service/am/common_state_getter.h
@@ -0,0 +1,78 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/service.h"
+
+#include "core/hle/service/am/applet_message_queue.h"
+
+namespace Service::AM {
+
+class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
+public:
+    explicit ICommonStateGetter(Core::System& system_,
+                                std::shared_ptr<AppletMessageQueue> msg_queue_);
+    ~ICommonStateGetter() override;
+
+private:
+    // This is nn::oe::FocusState
+    enum class FocusState : u8 {
+        InFocus = 1,
+        NotInFocus = 2,
+        Background = 3,
+    };
+
+    // This is nn::oe::OperationMode
+    enum class OperationMode : u8 {
+        Handheld = 0,
+        Docked = 1,
+    };
+
+    // This is nn::am::service::SystemButtonType
+    enum class SystemButtonType {
+        None,
+        HomeButtonShortPressing,
+        HomeButtonLongPressing,
+        PowerButtonShortPressing,
+        PowerButtonLongPressing,
+        ShutdownSystem,
+        CaptureButtonShortPressing,
+        CaptureButtonLongPressing,
+    };
+
+    enum class SysPlatformRegion : s32 {
+        Global = 1,
+        Terra = 2,
+    };
+
+    void GetEventHandle(HLERequestContext& ctx);
+    void ReceiveMessage(HLERequestContext& ctx);
+    void GetCurrentFocusState(HLERequestContext& ctx);
+    void RequestToAcquireSleepLock(HLERequestContext& ctx);
+    void GetAcquiredSleepLockEvent(HLERequestContext& ctx);
+    void GetReaderLockAccessorEx(HLERequestContext& ctx);
+    void GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx);
+    void GetOperationMode(HLERequestContext& ctx);
+    void GetPerformanceMode(HLERequestContext& ctx);
+    void GetBootMode(HLERequestContext& ctx);
+    void IsVrModeEnabled(HLERequestContext& ctx);
+    void SetVrModeEnabled(HLERequestContext& ctx);
+    void SetLcdBacklighOffEnabled(HLERequestContext& ctx);
+    void BeginVrModeEx(HLERequestContext& ctx);
+    void EndVrModeEx(HLERequestContext& ctx);
+    void GetDefaultDisplayResolution(HLERequestContext& ctx);
+    void SetCpuBoostMode(HLERequestContext& ctx);
+    void GetBuiltInDisplayType(HLERequestContext& ctx);
+    void PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx);
+    void GetSettingsPlatformRegion(HLERequestContext& ctx);
+    void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx);
+
+    std::shared_ptr<AppletMessageQueue> msg_queue;
+    bool vr_mode_state{};
+    Kernel::KEvent* sleep_lock_event;
+    KernelHelpers::ServiceContext service_context;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/debug_functions.cpp b/src/core/hle/service/am/debug_functions.cpp
new file mode 100644
index 000000000..f80b970f2
--- /dev/null
+++ b/src/core/hle/service/am/debug_functions.cpp
@@ -0,0 +1,44 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/debug_functions.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::AM {
+
+IDebugFunctions::IDebugFunctions(Core::System& system_)
+    : ServiceFramework{system_, "IDebugFunctions"} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, nullptr, "NotifyMessageToHomeMenuForDebug"},
+        {1, nullptr, "OpenMainApplication"},
+        {10, nullptr, "PerformSystemButtonPressing"},
+        {20, nullptr, "InvalidateTransitionLayer"},
+        {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"},
+        {31, nullptr, "RequestLaunchApplicationByApplicationLaunchInfoForDebug"},
+        {40, nullptr, "GetAppletResourceUsageInfo"},
+        {50, nullptr, "AddSystemProgramIdAndAppletIdForDebug"},
+        {51, nullptr, "AddOperationConfirmedLibraryAppletIdForDebug"},
+        {100, nullptr, "SetCpuBoostModeForApplet"},
+        {101, nullptr, "CancelCpuBoostModeForApplet"},
+        {110, nullptr, "PushToAppletBoundChannelForDebug"},
+        {111, nullptr, "TryPopFromAppletBoundChannelForDebug"},
+        {120, nullptr, "AlarmSettingNotificationEnableAppEventReserve"},
+        {121, nullptr, "AlarmSettingNotificationDisableAppEventReserve"},
+        {122, nullptr, "AlarmSettingNotificationPushAppEventNotify"},
+        {130, nullptr, "FriendInvitationSetApplicationParameter"},
+        {131, nullptr, "FriendInvitationClearApplicationParameter"},
+        {132, nullptr, "FriendInvitationPushApplicationParameter"},
+        {140, nullptr, "RestrictPowerOperationForSecureLaunchModeForDebug"},
+        {200, nullptr, "CreateFloatingLibraryAppletAccepterForDebug"},
+        {300, nullptr, "TerminateAllRunningApplicationsForDebug"},
+        {900, nullptr, "GetGrcProcessLaunchedSystemEvent"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+IDebugFunctions::~IDebugFunctions() = default;
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/debug_functions.h b/src/core/hle/service/am/debug_functions.h
new file mode 100644
index 000000000..d55968743
--- /dev/null
+++ b/src/core/hle/service/am/debug_functions.h
@@ -0,0 +1,16 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class IDebugFunctions final : public ServiceFramework<IDebugFunctions> {
+public:
+    explicit IDebugFunctions(Core::System& system_);
+    ~IDebugFunctions() override;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/display_controller.cpp b/src/core/hle/service/am/display_controller.cpp
new file mode 100644
index 000000000..d4d3d60e7
--- /dev/null
+++ b/src/core/hle/service/am/display_controller.cpp
@@ -0,0 +1,97 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/display_controller.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::AM {
+
+IDisplayController::IDisplayController(Core::System& system_)
+    : ServiceFramework{system_, "IDisplayController"} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, nullptr, "GetLastForegroundCaptureImage"},
+        {1, nullptr, "UpdateLastForegroundCaptureImage"},
+        {2, nullptr, "GetLastApplicationCaptureImage"},
+        {3, nullptr, "GetCallerAppletCaptureImage"},
+        {4, nullptr, "UpdateCallerAppletCaptureImage"},
+        {5, nullptr, "GetLastForegroundCaptureImageEx"},
+        {6, nullptr, "GetLastApplicationCaptureImageEx"},
+        {7, &IDisplayController::GetCallerAppletCaptureImageEx, "GetCallerAppletCaptureImageEx"},
+        {8, &IDisplayController::TakeScreenShotOfOwnLayer, "TakeScreenShotOfOwnLayer"},
+        {9, nullptr, "CopyBetweenCaptureBuffers"},
+        {10, nullptr, "AcquireLastApplicationCaptureBuffer"},
+        {11, nullptr, "ReleaseLastApplicationCaptureBuffer"},
+        {12, nullptr, "AcquireLastForegroundCaptureBuffer"},
+        {13, nullptr, "ReleaseLastForegroundCaptureBuffer"},
+        {14, nullptr, "AcquireCallerAppletCaptureBuffer"},
+        {15, nullptr, "ReleaseCallerAppletCaptureBuffer"},
+        {16, nullptr, "AcquireLastApplicationCaptureBufferEx"},
+        {17, nullptr, "AcquireLastForegroundCaptureBufferEx"},
+        {18, nullptr, "AcquireCallerAppletCaptureBufferEx"},
+        {20, nullptr, "ClearCaptureBuffer"},
+        {21, nullptr, "ClearAppletTransitionBuffer"},
+        {22, nullptr, "AcquireLastApplicationCaptureSharedBuffer"},
+        {23, nullptr, "ReleaseLastApplicationCaptureSharedBuffer"},
+        {24, &IDisplayController::AcquireLastForegroundCaptureSharedBuffer, "AcquireLastForegroundCaptureSharedBuffer"},
+        {25, &IDisplayController::ReleaseLastForegroundCaptureSharedBuffer, "ReleaseLastForegroundCaptureSharedBuffer"},
+        {26, &IDisplayController::AcquireCallerAppletCaptureSharedBuffer, "AcquireCallerAppletCaptureSharedBuffer"},
+        {27, &IDisplayController::ReleaseCallerAppletCaptureSharedBuffer, "ReleaseCallerAppletCaptureSharedBuffer"},
+        {28, nullptr, "TakeScreenShotOfOwnLayerEx"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+IDisplayController::~IDisplayController() = default;
+
+void IDisplayController::GetCallerAppletCaptureImageEx(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(ResultSuccess);
+    rb.Push(1u);
+    rb.Push(1);
+}
+
+void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IDisplayController::AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(ResultSuccess);
+    rb.Push(1U);
+    rb.Push(1);
+}
+
+void IDisplayController::ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IDisplayController::AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(ResultSuccess);
+    rb.Push(1U);
+    rb.Push(1);
+}
+
+void IDisplayController::ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/display_controller.h b/src/core/hle/service/am/display_controller.h
new file mode 100644
index 000000000..32f819294
--- /dev/null
+++ b/src/core/hle/service/am/display_controller.h
@@ -0,0 +1,24 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class IDisplayController final : public ServiceFramework<IDisplayController> {
+public:
+    explicit IDisplayController(Core::System& system_);
+    ~IDisplayController() override;
+
+private:
+    void GetCallerAppletCaptureImageEx(HLERequestContext& ctx);
+    void TakeScreenShotOfOwnLayer(HLERequestContext& ctx);
+    void AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx);
+    void ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx);
+    void AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx);
+    void ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx);
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/global_state_controller.cpp b/src/core/hle/service/am/global_state_controller.cpp
new file mode 100644
index 000000000..ed0eb7108
--- /dev/null
+++ b/src/core/hle/service/am/global_state_controller.cpp
@@ -0,0 +1,34 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/global_state_controller.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::AM {
+
+IGlobalStateController::IGlobalStateController(Core::System& system_)
+    : ServiceFramework{system_, "IGlobalStateController"} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, nullptr, "RequestToEnterSleep"},
+        {1, nullptr, "EnterSleep"},
+        {2, nullptr, "StartSleepSequence"},
+        {3, nullptr, "StartShutdownSequence"},
+        {4, nullptr, "StartRebootSequence"},
+        {9, nullptr, "IsAutoPowerDownRequested"},
+        {10, nullptr, "LoadAndApplyIdlePolicySettings"},
+        {11, nullptr, "NotifyCecSettingsChanged"},
+        {12, nullptr, "SetDefaultHomeButtonLongPressTime"},
+        {13, nullptr, "UpdateDefaultDisplayResolution"},
+        {14, nullptr, "ShouldSleepOnBoot"},
+        {15, nullptr, "GetHdcpAuthenticationFailedEvent"},
+        {30, nullptr, "OpenCradleFirmwareUpdater"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+IGlobalStateController::~IGlobalStateController() = default;
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/global_state_controller.h b/src/core/hle/service/am/global_state_controller.h
new file mode 100644
index 000000000..7125464a1
--- /dev/null
+++ b/src/core/hle/service/am/global_state_controller.h
@@ -0,0 +1,16 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class IGlobalStateController final : public ServiceFramework<IGlobalStateController> {
+public:
+    explicit IGlobalStateController(Core::System& system_);
+    ~IGlobalStateController() override;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/home_menu_functions.cpp b/src/core/hle/service/am/home_menu_functions.cpp
new file mode 100644
index 000000000..640e9fbb7
--- /dev/null
+++ b/src/core/hle/service/am/home_menu_functions.cpp
@@ -0,0 +1,57 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/home_menu_functions.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::AM {
+
+IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_)
+    : ServiceFramework{system_, "IHomeMenuFunctions"}, service_context{system,
+                                                                       "IHomeMenuFunctions"} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {10, &IHomeMenuFunctions::RequestToGetForeground, "RequestToGetForeground"},
+        {11, nullptr, "LockForeground"},
+        {12, nullptr, "UnlockForeground"},
+        {20, nullptr, "PopFromGeneralChannel"},
+        {21, &IHomeMenuFunctions::GetPopFromGeneralChannelEvent, "GetPopFromGeneralChannelEvent"},
+        {30, nullptr, "GetHomeButtonWriterLockAccessor"},
+        {31, nullptr, "GetWriterLockAccessorEx"},
+        {40, nullptr, "IsSleepEnabled"},
+        {41, nullptr, "IsRebootEnabled"},
+        {50, nullptr, "LaunchSystemApplet"},
+        {51, nullptr, "LaunchStarter"},
+        {100, nullptr, "PopRequestLaunchApplicationForDebug"},
+        {110, nullptr, "IsForceTerminateApplicationDisabledForDebug"},
+        {200, nullptr, "LaunchDevMenu"},
+        {1000, nullptr, "SetLastApplicationExitReason"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+
+    pop_from_general_channel_event =
+        service_context.CreateEvent("IHomeMenuFunctions:PopFromGeneralChannelEvent");
+}
+
+IHomeMenuFunctions::~IHomeMenuFunctions() {
+    service_context.CloseEvent(pop_from_general_channel_event);
+}
+
+void IHomeMenuFunctions::RequestToGetForeground(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 1};
+    rb.Push(ResultSuccess);
+    rb.PushCopyObjects(pop_from_general_channel_event->GetReadableEvent());
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/home_menu_functions.h b/src/core/hle/service/am/home_menu_functions.h
new file mode 100644
index 000000000..e082d5d73
--- /dev/null
+++ b/src/core/hle/service/am/home_menu_functions.h
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> {
+public:
+    explicit IHomeMenuFunctions(Core::System& system_);
+    ~IHomeMenuFunctions() override;
+
+private:
+    void RequestToGetForeground(HLERequestContext& ctx);
+    void GetPopFromGeneralChannelEvent(HLERequestContext& ctx);
+
+    KernelHelpers::ServiceContext service_context;
+
+    Kernel::KEvent* pop_from_general_channel_event;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/library_applet_accessor.cpp b/src/core/hle/service/am/library_applet_accessor.cpp
new file mode 100644
index 000000000..1cccdfcf2
--- /dev/null
+++ b/src/core/hle/service/am/library_applet_accessor.cpp
@@ -0,0 +1,178 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/am_results.h"
+#include "core/hle/service/am/library_applet_accessor.h"
+#include "core/hle/service/am/storage.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::AM {
+
+ILibraryAppletAccessor::ILibraryAppletAccessor(Core::System& system_,
+                                               std::shared_ptr<Applets::Applet> applet_)
+    : ServiceFramework{system_, "ILibraryAppletAccessor"}, applet{std::move(applet_)} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"},
+        {1, &ILibraryAppletAccessor::IsCompleted, "IsCompleted"},
+        {10, &ILibraryAppletAccessor::Start, "Start"},
+        {20, &ILibraryAppletAccessor::RequestExit, "RequestExit"},
+        {25, nullptr, "Terminate"},
+        {30, &ILibraryAppletAccessor::GetResult, "GetResult"},
+        {50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"},
+        {60, &ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero, "PresetLibraryAppletGpuTimeSliceZero"},
+        {100, &ILibraryAppletAccessor::PushInData, "PushInData"},
+        {101, &ILibraryAppletAccessor::PopOutData, "PopOutData"},
+        {102, nullptr, "PushExtraStorage"},
+        {103, &ILibraryAppletAccessor::PushInteractiveInData, "PushInteractiveInData"},
+        {104, &ILibraryAppletAccessor::PopInteractiveOutData, "PopInteractiveOutData"},
+        {105, &ILibraryAppletAccessor::GetPopOutDataEvent, "GetPopOutDataEvent"},
+        {106, &ILibraryAppletAccessor::GetPopInteractiveOutDataEvent, "GetPopInteractiveOutDataEvent"},
+        {110, nullptr, "NeedsToExitProcess"},
+        {120, nullptr, "GetLibraryAppletInfo"},
+        {150, nullptr, "RequestForAppletToGetForeground"},
+        {160, &ILibraryAppletAccessor::GetIndirectLayerConsumerHandle, "GetIndirectLayerConsumerHandle"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+void ILibraryAppletAccessor::GetAppletStateChangedEvent(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 1};
+    rb.Push(ResultSuccess);
+    rb.PushCopyObjects(applet->GetBroker().GetStateChangedEvent());
+}
+
+void ILibraryAppletAccessor::IsCompleted(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push<u32>(applet->TransactionComplete());
+}
+
+void ILibraryAppletAccessor::GetResult(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(applet->GetStatus());
+}
+
+void ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ILibraryAppletAccessor::Start(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    ASSERT(applet != nullptr);
+
+    applet->Initialize();
+    applet->Execute();
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ILibraryAppletAccessor::RequestExit(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    ASSERT(applet != nullptr);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(applet->RequestExit());
+}
+
+void ILibraryAppletAccessor::PushInData(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::RequestParser rp{ctx};
+    applet->GetBroker().PushNormalDataFromGame(rp.PopIpcInterface<IStorage>().lock());
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ILibraryAppletAccessor::PopOutData(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    auto storage = applet->GetBroker().PopNormalDataToGame();
+    if (storage == nullptr) {
+        LOG_DEBUG(Service_AM,
+                  "storage is a nullptr. There is no data in the current normal channel");
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(AM::ResultNoDataInChannel);
+        return;
+    }
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IStorage>(std::move(storage));
+}
+
+void ILibraryAppletAccessor::PushInteractiveInData(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::RequestParser rp{ctx};
+    applet->GetBroker().PushInteractiveDataFromGame(rp.PopIpcInterface<IStorage>().lock());
+
+    ASSERT(applet->IsInitialized());
+    applet->ExecuteInteractive();
+    applet->Execute();
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ILibraryAppletAccessor::PopInteractiveOutData(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    auto storage = applet->GetBroker().PopInteractiveDataToGame();
+    if (storage == nullptr) {
+        LOG_DEBUG(Service_AM,
+                  "storage is a nullptr. There is no data in the current interactive channel");
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(AM::ResultNoDataInChannel);
+        return;
+    }
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IStorage>(std::move(storage));
+}
+
+void ILibraryAppletAccessor::GetPopOutDataEvent(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 1};
+    rb.Push(ResultSuccess);
+    rb.PushCopyObjects(applet->GetBroker().GetNormalDataEvent());
+}
+
+void ILibraryAppletAccessor::GetPopInteractiveOutDataEvent(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 1};
+    rb.Push(ResultSuccess);
+    rb.PushCopyObjects(applet->GetBroker().GetInteractiveDataEvent());
+}
+
+void ILibraryAppletAccessor::GetIndirectLayerConsumerHandle(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    // We require a non-zero handle to be valid. Using 0xdeadbeef allows us to trace if this is
+    // actually used anywhere
+    constexpr u64 handle = 0xdeadbeef;
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(ResultSuccess);
+    rb.Push(handle);
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/library_applet_accessor.h b/src/core/hle/service/am/library_applet_accessor.h
new file mode 100644
index 000000000..698467233
--- /dev/null
+++ b/src/core/hle/service/am/library_applet_accessor.h
@@ -0,0 +1,34 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/am/applets/applets.h"
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
+public:
+    explicit ILibraryAppletAccessor(Core::System& system_,
+                                    std::shared_ptr<Applets::Applet> applet_);
+
+private:
+    void GetAppletStateChangedEvent(HLERequestContext& ctx);
+    void IsCompleted(HLERequestContext& ctx);
+    void GetResult(HLERequestContext& ctx);
+    void PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx);
+    void Start(HLERequestContext& ctx);
+    void RequestExit(HLERequestContext& ctx);
+    void PushInData(HLERequestContext& ctx);
+    void PopOutData(HLERequestContext& ctx);
+    void PushInteractiveInData(HLERequestContext& ctx);
+    void PopInteractiveOutData(HLERequestContext& ctx);
+    void GetPopOutDataEvent(HLERequestContext& ctx);
+    void GetPopInteractiveOutDataEvent(HLERequestContext& ctx);
+    void GetIndirectLayerConsumerHandle(HLERequestContext& ctx);
+
+    std::shared_ptr<Applets::Applet> applet;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/library_applet_creator.cpp b/src/core/hle/service/am/library_applet_creator.cpp
new file mode 100644
index 000000000..c33f50a40
--- /dev/null
+++ b/src/core/hle/service/am/library_applet_creator.cpp
@@ -0,0 +1,145 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/kernel/k_transfer_memory.h"
+#include "core/hle/service/am/applets/applets.h"
+#include "core/hle/service/am/library_applet_accessor.h"
+#include "core/hle/service/am/library_applet_creator.h"
+#include "core/hle/service/am/storage.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::AM {
+
+ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_)
+    : ServiceFramework{system_, "ILibraryAppletCreator"} {
+    static const FunctionInfo functions[] = {
+        {0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"},
+        {1, nullptr, "TerminateAllLibraryApplets"},
+        {2, nullptr, "AreAnyLibraryAppletsLeft"},
+        {10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"},
+        {11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"},
+        {12, &ILibraryAppletCreator::CreateHandleStorage, "CreateHandleStorage"},
+    };
+    RegisterHandlers(functions);
+}
+
+ILibraryAppletCreator::~ILibraryAppletCreator() = default;
+
+void ILibraryAppletCreator::CreateLibraryApplet(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    const auto applet_id = rp.PopRaw<Applets::AppletId>();
+    const auto applet_mode = rp.PopRaw<Applets::LibraryAppletMode>();
+
+    LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id,
+              applet_mode);
+
+    const auto& applet_manager{system.GetAppletManager()};
+    const auto applet = applet_manager.GetApplet(applet_id, applet_mode);
+
+    if (applet == nullptr) {
+        LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultUnknown);
+        return;
+    }
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet);
+}
+
+void ILibraryAppletCreator::CreateStorage(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    const s64 size{rp.Pop<s64>()};
+
+    LOG_DEBUG(Service_AM, "called, size={}", size);
+
+    if (size <= 0) {
+        LOG_ERROR(Service_AM, "size is less than or equal to 0");
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultUnknown);
+        return;
+    }
+
+    std::vector<u8> buffer(size);
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IStorage>(system, std::move(buffer));
+}
+
+void ILibraryAppletCreator::CreateTransferMemoryStorage(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    struct Parameters {
+        u8 permissions;
+        s64 size;
+    };
+
+    const auto parameters{rp.PopRaw<Parameters>()};
+    const auto handle{ctx.GetCopyHandle(0)};
+
+    LOG_DEBUG(Service_AM, "called, permissions={}, size={}, handle={:08X}", parameters.permissions,
+              parameters.size, handle);
+
+    if (parameters.size <= 0) {
+        LOG_ERROR(Service_AM, "size is less than or equal to 0");
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultUnknown);
+        return;
+    }
+
+    auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle);
+
+    if (transfer_mem.IsNull()) {
+        LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultUnknown);
+        return;
+    }
+
+    std::vector<u8> memory(transfer_mem->GetSize());
+    ctx.GetMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size());
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IStorage>(system, std::move(memory));
+}
+
+void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    const s64 size{rp.Pop<s64>()};
+    const auto handle{ctx.GetCopyHandle(0)};
+
+    LOG_DEBUG(Service_AM, "called, size={}, handle={:08X}", size, handle);
+
+    if (size <= 0) {
+        LOG_ERROR(Service_AM, "size is less than or equal to 0");
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultUnknown);
+        return;
+    }
+
+    auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle);
+
+    if (transfer_mem.IsNull()) {
+        LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultUnknown);
+        return;
+    }
+
+    std::vector<u8> memory(transfer_mem->GetSize());
+    ctx.GetMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size());
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IStorage>(system, std::move(memory));
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/library_applet_creator.h b/src/core/hle/service/am/library_applet_creator.h
new file mode 100644
index 000000000..97f236fbc
--- /dev/null
+++ b/src/core/hle/service/am/library_applet_creator.h
@@ -0,0 +1,22 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
+public:
+    explicit ILibraryAppletCreator(Core::System& system_);
+    ~ILibraryAppletCreator() override;
+
+private:
+    void CreateLibraryApplet(HLERequestContext& ctx);
+    void CreateStorage(HLERequestContext& ctx);
+    void CreateTransferMemoryStorage(HLERequestContext& ctx);
+    void CreateHandleStorage(HLERequestContext& ctx);
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/library_applet_proxy.cpp b/src/core/hle/service/am/library_applet_proxy.cpp
new file mode 100644
index 000000000..047fc40f4
--- /dev/null
+++ b/src/core/hle/service/am/library_applet_proxy.cpp
@@ -0,0 +1,142 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/applet_common_functions.h"
+#include "core/hle/service/am/audio_controller.h"
+#include "core/hle/service/am/common_state_getter.h"
+#include "core/hle/service/am/debug_functions.h"
+#include "core/hle/service/am/display_controller.h"
+#include "core/hle/service/am/global_state_controller.h"
+#include "core/hle/service/am/home_menu_functions.h"
+#include "core/hle/service/am/library_applet_creator.h"
+#include "core/hle/service/am/library_applet_proxy.h"
+#include "core/hle/service/am/library_applet_self_accessor.h"
+#include "core/hle/service/am/process_winding_controller.h"
+#include "core/hle/service/am/self_controller.h"
+#include "core/hle/service/am/window_controller.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::AM {
+
+ILibraryAppletProxy::ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
+                                         std::shared_ptr<AppletMessageQueue> msg_queue_,
+                                         Core::System& system_)
+    : ServiceFramework{system_, "ILibraryAppletProxy"}, nvnflinger{nvnflinger_},
+      msg_queue{std::move(msg_queue_)} {
+    // clang-format off
+        static const FunctionInfo functions[] = {
+            {0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
+            {1, &ILibraryAppletProxy::GetSelfController, "GetSelfController"},
+            {2, &ILibraryAppletProxy::GetWindowController, "GetWindowController"},
+            {3, &ILibraryAppletProxy::GetAudioController, "GetAudioController"},
+            {4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"},
+            {10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"},
+            {11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
+            {20, &ILibraryAppletProxy::OpenLibraryAppletSelfAccessor, "OpenLibraryAppletSelfAccessor"},
+            {21, &ILibraryAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"},
+            {22, &ILibraryAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"},
+            {23, &ILibraryAppletProxy::GetGlobalStateController, "GetGlobalStateController"},
+            {1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
+        };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+void ILibraryAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue);
+}
+
+void ILibraryAppletProxy::GetSelfController(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<ISelfController>(system, nvnflinger);
+}
+
+void ILibraryAppletProxy::GetWindowController(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IWindowController>(system);
+}
+
+void ILibraryAppletProxy::GetAudioController(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IAudioController>(system);
+}
+
+void ILibraryAppletProxy::GetDisplayController(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IDisplayController>(system);
+}
+
+void ILibraryAppletProxy::GetProcessWindingController(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IProcessWindingController>(system);
+}
+
+void ILibraryAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<ILibraryAppletCreator>(system);
+}
+
+void ILibraryAppletProxy::OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system);
+}
+
+void ILibraryAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IAppletCommonFunctions>(system);
+}
+
+void ILibraryAppletProxy::GetHomeMenuFunctions(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IHomeMenuFunctions>(system);
+}
+
+void ILibraryAppletProxy::GetGlobalStateController(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IGlobalStateController>(system);
+}
+
+void ILibraryAppletProxy::GetDebugFunctions(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IDebugFunctions>(system);
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/library_applet_proxy.h b/src/core/hle/service/am/library_applet_proxy.h
new file mode 100644
index 000000000..cd9e6d02b
--- /dev/null
+++ b/src/core/hle/service/am/library_applet_proxy.h
@@ -0,0 +1,35 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/am/applet_message_queue.h"
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
+public:
+    explicit ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
+                                 std::shared_ptr<AppletMessageQueue> msg_queue_,
+                                 Core::System& system_);
+
+private:
+    void GetCommonStateGetter(HLERequestContext& ctx);
+    void GetSelfController(HLERequestContext& ctx);
+    void GetWindowController(HLERequestContext& ctx);
+    void GetAudioController(HLERequestContext& ctx);
+    void GetDisplayController(HLERequestContext& ctx);
+    void GetProcessWindingController(HLERequestContext& ctx);
+    void GetLibraryAppletCreator(HLERequestContext& ctx);
+    void OpenLibraryAppletSelfAccessor(HLERequestContext& ctx);
+    void GetAppletCommonFunctions(HLERequestContext& ctx);
+    void GetHomeMenuFunctions(HLERequestContext& ctx);
+    void GetGlobalStateController(HLERequestContext& ctx);
+    void GetDebugFunctions(HLERequestContext& ctx);
+
+    Nvnflinger::Nvnflinger& nvnflinger;
+    std::shared_ptr<AppletMessageQueue> msg_queue;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/library_applet_self_accessor.cpp b/src/core/hle/service/am/library_applet_self_accessor.cpp
new file mode 100644
index 000000000..0a12afbbd
--- /dev/null
+++ b/src/core/hle/service/am/library_applet_self_accessor.cpp
@@ -0,0 +1,382 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/core_timing.h"
+#include "core/hle/service/acc/profile_manager.h"
+#include "core/hle/service/am/am_results.h"
+#include "core/hle/service/am/applets/applet_cabinet.h"
+#include "core/hle/service/am/applets/applet_controller.h"
+#include "core/hle/service/am/applets/applet_mii_edit_types.h"
+#include "core/hle/service/am/applets/applet_software_keyboard_types.h"
+#include "core/hle/service/am/applets/applets.h"
+#include "core/hle/service/am/library_applet_self_accessor.h"
+#include "core/hle/service/am/storage.h"
+#include "core/hle/service/ipc_helpers.h"
+#include "hid_core/hid_types.h"
+
+namespace Service::AM {
+
+ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
+    : ServiceFramework{system_, "ILibraryAppletSelfAccessor"} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, &ILibraryAppletSelfAccessor::PopInData, "PopInData"},
+        {1, &ILibraryAppletSelfAccessor::PushOutData, "PushOutData"},
+        {2, nullptr, "PopInteractiveInData"},
+        {3, nullptr, "PushInteractiveOutData"},
+        {5, nullptr, "GetPopInDataEvent"},
+        {6, nullptr, "GetPopInteractiveInDataEvent"},
+        {10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"},
+        {11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"},
+        {12, &ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo, "GetMainAppletIdentityInfo"},
+        {13, nullptr, "CanUseApplicationCore"},
+        {14, &ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo, "GetCallerAppletIdentityInfo"},
+        {15, nullptr, "GetMainAppletApplicationControlProperty"},
+        {16, nullptr, "GetMainAppletStorageId"},
+        {17, nullptr, "GetCallerAppletIdentityInfoStack"},
+        {18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"},
+        {19, &ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout, "GetDesirableKeyboardLayout"},
+        {20, nullptr, "PopExtraStorage"},
+        {25, nullptr, "GetPopExtraStorageEvent"},
+        {30, nullptr, "UnpopInData"},
+        {31, nullptr, "UnpopExtraStorage"},
+        {40, nullptr, "GetIndirectLayerProducerHandle"},
+        {50, nullptr, "ReportVisibleError"},
+        {51, nullptr, "ReportVisibleErrorWithErrorContext"},
+        {60, nullptr, "GetMainAppletApplicationDesiredLanguage"},
+        {70, nullptr, "GetCurrentApplicationId"},
+        {80, nullptr, "RequestExitToSelf"},
+        {90, nullptr, "CreateApplicationAndPushAndRequestToLaunch"},
+        {100, nullptr, "CreateGameMovieTrimmer"},
+        {101, nullptr, "ReserveResourceForMovieOperation"},
+        {102, nullptr, "UnreserveResourceForMovieOperation"},
+        {110, &ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers, "GetMainAppletAvailableUsers"},
+        {120, nullptr, "GetLaunchStorageInfoForDebug"},
+        {130, nullptr, "GetGpuErrorDetectedSystemEvent"},
+        {140, nullptr, "SetApplicationMemoryReservation"},
+        {150, &ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually, "ShouldSetGpuTimeSliceManually"},
+    };
+    // clang-format on
+    RegisterHandlers(functions);
+
+    switch (system.GetAppletManager().GetCurrentAppletId()) {
+    case Applets::AppletId::Cabinet:
+        PushInShowCabinetData();
+        break;
+    case Applets::AppletId::MiiEdit:
+        PushInShowMiiEditData();
+        break;
+    case Applets::AppletId::PhotoViewer:
+        PushInShowAlbum();
+        break;
+    case Applets::AppletId::SoftwareKeyboard:
+        PushInShowSoftwareKeyboard();
+        break;
+    case Applets::AppletId::Controller:
+        PushInShowController();
+        break;
+    default:
+        break;
+    }
+}
+
+ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default;
+
+void ILibraryAppletSelfAccessor::PopInData(HLERequestContext& ctx) {
+    LOG_INFO(Service_AM, "called");
+
+    if (queue_data.empty()) {
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(AM::ResultNoDataInChannel);
+        return;
+    }
+
+    auto data = queue_data.front();
+    queue_data.pop_front();
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IStorage>(system, std::move(data));
+}
+
+void ILibraryAppletSelfAccessor::PushOutData(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ILibraryAppletSelfAccessor::ExitProcessAndReturn(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    system.Exit();
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) {
+    struct LibraryAppletInfo {
+        Applets::AppletId applet_id;
+        Applets::LibraryAppletMode library_applet_mode;
+    };
+
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    const LibraryAppletInfo applet_info{
+        .applet_id = system.GetAppletManager().GetCurrentAppletId(),
+        .library_applet_mode = Applets::LibraryAppletMode::AllForeground,
+    };
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(ResultSuccess);
+    rb.PushRaw(applet_info);
+}
+
+void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ctx) {
+    struct AppletIdentityInfo {
+        Applets::AppletId applet_id;
+        INSERT_PADDING_BYTES(0x4);
+        u64 application_id;
+    };
+    static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size.");
+
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    const AppletIdentityInfo applet_info{
+        .applet_id = Applets::AppletId::QLaunch,
+        .application_id = 0x0100000000001000ull,
+    };
+
+    IPC::ResponseBuilder rb{ctx, 6};
+    rb.Push(ResultSuccess);
+    rb.PushRaw(applet_info);
+}
+
+void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) {
+    struct AppletIdentityInfo {
+        Applets::AppletId applet_id;
+        INSERT_PADDING_BYTES(0x4);
+        u64 application_id;
+    };
+    static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size.");
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    const AppletIdentityInfo applet_info{
+        .applet_id = Applets::AppletId::QLaunch,
+        .application_id = 0x0100000000001000ull,
+    };
+
+    IPC::ResponseBuilder rb{ctx, 6};
+    rb.Push(ResultSuccess);
+    rb.PushRaw(applet_info);
+}
+
+void ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push<u32>(0);
+}
+
+void ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(HLERequestContext& ctx) {
+    const Service::Account::ProfileManager manager{};
+    bool is_empty{true};
+    s32 user_count{-1};
+
+    LOG_INFO(Service_AM, "called");
+
+    if (manager.GetUserCount() > 0) {
+        is_empty = false;
+        user_count = static_cast<s32>(manager.GetUserCount());
+        ctx.WriteBuffer(manager.GetAllUsers());
+    }
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(ResultSuccess);
+    rb.Push<u8>(is_empty);
+    rb.Push(user_count);
+}
+
+void ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push<u8>(0);
+}
+
+void ILibraryAppletSelfAccessor::PushInShowAlbum() {
+    const Applets::CommonArguments arguments{
+        .arguments_version = Applets::CommonArgumentVersion::Version3,
+        .size = Applets::CommonArgumentSize::Version3,
+        .library_version = 1,
+        .theme_color = Applets::ThemeColor::BasicBlack,
+        .play_startup_sound = true,
+        .system_tick = system.CoreTiming().GetClockTicks(),
+    };
+
+    std::vector<u8> argument_data(sizeof(arguments));
+    std::vector<u8> settings_data{2};
+    std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
+    queue_data.emplace_back(std::move(argument_data));
+    queue_data.emplace_back(std::move(settings_data));
+}
+
+void ILibraryAppletSelfAccessor::PushInShowController() {
+    const Applets::CommonArguments common_args = {
+        .arguments_version = Applets::CommonArgumentVersion::Version3,
+        .size = Applets::CommonArgumentSize::Version3,
+        .library_version = static_cast<u32>(Applets::ControllerAppletVersion::Version8),
+        .theme_color = Applets::ThemeColor::BasicBlack,
+        .play_startup_sound = true,
+        .system_tick = system.CoreTiming().GetClockTicks(),
+    };
+
+    Applets::ControllerSupportArgNew user_args = {
+        .header = {.player_count_min = 1,
+                   .player_count_max = 4,
+                   .enable_take_over_connection = true,
+                   .enable_left_justify = false,
+                   .enable_permit_joy_dual = true,
+                   .enable_single_mode = false,
+                   .enable_identification_color = false},
+        .identification_colors = {},
+        .enable_explain_text = false,
+        .explain_text = {},
+    };
+
+    Applets::ControllerSupportArgPrivate private_args = {
+        .arg_private_size = sizeof(Applets::ControllerSupportArgPrivate),
+        .arg_size = sizeof(Applets::ControllerSupportArgNew),
+        .is_home_menu = true,
+        .flag_1 = true,
+        .mode = Applets::ControllerSupportMode::ShowControllerSupport,
+        .caller = Applets::ControllerSupportCaller::
+            Application, // switchbrew: Always zero except with
+                         // ShowControllerFirmwareUpdateForSystem/ShowControllerKeyRemappingForSystem,
+                         // which sets this to the input param
+        .style_set = Core::HID::NpadStyleSet::None,
+        .joy_hold_type = 0,
+    };
+    std::vector<u8> common_args_data(sizeof(common_args));
+    std::vector<u8> private_args_data(sizeof(private_args));
+    std::vector<u8> user_args_data(sizeof(user_args));
+
+    std::memcpy(common_args_data.data(), &common_args, sizeof(common_args));
+    std::memcpy(private_args_data.data(), &private_args, sizeof(private_args));
+    std::memcpy(user_args_data.data(), &user_args, sizeof(user_args));
+
+    queue_data.emplace_back(std::move(common_args_data));
+    queue_data.emplace_back(std::move(private_args_data));
+    queue_data.emplace_back(std::move(user_args_data));
+}
+
+void ILibraryAppletSelfAccessor::PushInShowCabinetData() {
+    const Applets::CommonArguments arguments{
+        .arguments_version = Applets::CommonArgumentVersion::Version3,
+        .size = Applets::CommonArgumentSize::Version3,
+        .library_version = static_cast<u32>(Applets::CabinetAppletVersion::Version1),
+        .theme_color = Applets::ThemeColor::BasicBlack,
+        .play_startup_sound = true,
+        .system_tick = system.CoreTiming().GetClockTicks(),
+    };
+
+    const Applets::StartParamForAmiiboSettings amiibo_settings{
+        .param_1 = 0,
+        .applet_mode = system.GetAppletManager().GetCabinetMode(),
+        .flags = Applets::CabinetFlags::None,
+        .amiibo_settings_1 = 0,
+        .device_handle = 0,
+        .tag_info{},
+        .register_info{},
+        .amiibo_settings_3{},
+    };
+
+    std::vector<u8> argument_data(sizeof(arguments));
+    std::vector<u8> settings_data(sizeof(amiibo_settings));
+    std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
+    std::memcpy(settings_data.data(), &amiibo_settings, sizeof(amiibo_settings));
+    queue_data.emplace_back(std::move(argument_data));
+    queue_data.emplace_back(std::move(settings_data));
+}
+
+void ILibraryAppletSelfAccessor::PushInShowMiiEditData() {
+    struct MiiEditV3 {
+        Applets::MiiEditAppletInputCommon common;
+        Applets::MiiEditAppletInputV3 input;
+    };
+    static_assert(sizeof(MiiEditV3) == 0x100, "MiiEditV3 has incorrect size.");
+
+    MiiEditV3 mii_arguments{
+        .common =
+            {
+                .version = Applets::MiiEditAppletVersion::Version3,
+                .applet_mode = Applets::MiiEditAppletMode::ShowMiiEdit,
+            },
+        .input{},
+    };
+
+    std::vector<u8> argument_data(sizeof(mii_arguments));
+    std::memcpy(argument_data.data(), &mii_arguments, sizeof(mii_arguments));
+
+    queue_data.emplace_back(std::move(argument_data));
+}
+
+void ILibraryAppletSelfAccessor::PushInShowSoftwareKeyboard() {
+    const Applets::CommonArguments arguments{
+        .arguments_version = Applets::CommonArgumentVersion::Version3,
+        .size = Applets::CommonArgumentSize::Version3,
+        .library_version = static_cast<u32>(Applets::SwkbdAppletVersion::Version524301),
+        .theme_color = Applets::ThemeColor::BasicBlack,
+        .play_startup_sound = true,
+        .system_tick = system.CoreTiming().GetClockTicks(),
+    };
+
+    std::vector<char16_t> initial_string(0);
+
+    const Applets::SwkbdConfigCommon swkbd_config{
+        .type = Applets::SwkbdType::Qwerty,
+        .ok_text{},
+        .left_optional_symbol_key{},
+        .right_optional_symbol_key{},
+        .use_prediction = false,
+        .key_disable_flags{},
+        .initial_cursor_position = Applets::SwkbdInitialCursorPosition::Start,
+        .header_text{},
+        .sub_text{},
+        .guide_text{},
+        .max_text_length = 500,
+        .min_text_length = 0,
+        .password_mode = Applets::SwkbdPasswordMode::Disabled,
+        .text_draw_type = Applets::SwkbdTextDrawType::Box,
+        .enable_return_button = true,
+        .use_utf8 = false,
+        .use_blur_background = true,
+        .initial_string_offset{},
+        .initial_string_length = static_cast<u32>(initial_string.size()),
+        .user_dictionary_offset{},
+        .user_dictionary_entries{},
+        .use_text_check = false,
+    };
+
+    Applets::SwkbdConfigNew swkbd_config_new{};
+
+    std::vector<u8> argument_data(sizeof(arguments));
+    std::vector<u8> swkbd_data(sizeof(swkbd_config) + sizeof(swkbd_config_new));
+    std::vector<u8> work_buffer(swkbd_config.initial_string_length * sizeof(char16_t));
+
+    std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
+    std::memcpy(swkbd_data.data(), &swkbd_config, sizeof(swkbd_config));
+    std::memcpy(swkbd_data.data() + sizeof(swkbd_config), &swkbd_config_new,
+                sizeof(Applets::SwkbdConfigNew));
+    std::memcpy(work_buffer.data(), initial_string.data(),
+                swkbd_config.initial_string_length * sizeof(char16_t));
+
+    queue_data.emplace_back(std::move(argument_data));
+    queue_data.emplace_back(std::move(swkbd_data));
+    queue_data.emplace_back(std::move(work_buffer));
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/library_applet_self_accessor.h b/src/core/hle/service/am/library_applet_self_accessor.h
new file mode 100644
index 000000000..45b325b77
--- /dev/null
+++ b/src/core/hle/service/am/library_applet_self_accessor.h
@@ -0,0 +1,38 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <deque>
+#include <vector>
+
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> {
+public:
+    explicit ILibraryAppletSelfAccessor(Core::System& system_);
+    ~ILibraryAppletSelfAccessor() override;
+
+private:
+    void PopInData(HLERequestContext& ctx);
+    void PushOutData(HLERequestContext& ctx);
+    void GetLibraryAppletInfo(HLERequestContext& ctx);
+    void GetMainAppletIdentityInfo(HLERequestContext& ctx);
+    void ExitProcessAndReturn(HLERequestContext& ctx);
+    void GetCallerAppletIdentityInfo(HLERequestContext& ctx);
+    void GetDesirableKeyboardLayout(HLERequestContext& ctx);
+    void GetMainAppletAvailableUsers(HLERequestContext& ctx);
+    void ShouldSetGpuTimeSliceManually(HLERequestContext& ctx);
+
+    void PushInShowAlbum();
+    void PushInShowCabinetData();
+    void PushInShowMiiEditData();
+    void PushInShowSoftwareKeyboard();
+    void PushInShowController();
+
+    std::deque<std::vector<u8>> queue_data;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/lock_accessor.cpp b/src/core/hle/service/am/lock_accessor.cpp
new file mode 100644
index 000000000..d0bd8d95e
--- /dev/null
+++ b/src/core/hle/service/am/lock_accessor.cpp
@@ -0,0 +1,71 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/lock_accessor.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::AM {
+
+ILockAccessor::ILockAccessor(Core::System& system_)
+    : ServiceFramework{system_, "ILockAccessor"}, service_context{system_, "ILockAccessor"} {
+    // clang-format off
+        static const FunctionInfo functions[] = {
+            {1, &ILockAccessor::TryLock, "TryLock"},
+            {2, &ILockAccessor::Unlock, "Unlock"},
+            {3, &ILockAccessor::GetEvent, "GetEvent"},
+            {4,&ILockAccessor::IsLocked, "IsLocked"},
+        };
+    // clang-format on
+
+    RegisterHandlers(functions);
+
+    lock_event = service_context.CreateEvent("ILockAccessor::LockEvent");
+}
+
+ILockAccessor::~ILockAccessor() {
+    service_context.CloseEvent(lock_event);
+};
+
+void ILockAccessor::TryLock(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const auto return_handle = rp.Pop<bool>();
+
+    LOG_WARNING(Service_AM, "(STUBBED) called, return_handle={}", return_handle);
+
+    // TODO: When return_handle is true this function should return the lock handle
+
+    is_locked = true;
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push<u8>(is_locked);
+}
+
+void ILockAccessor::Unlock(HLERequestContext& ctx) {
+    LOG_INFO(Service_AM, "called");
+
+    is_locked = false;
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ILockAccessor::GetEvent(HLERequestContext& ctx) {
+    LOG_INFO(Service_AM, "called");
+
+    lock_event->Signal();
+
+    IPC::ResponseBuilder rb{ctx, 2, 1};
+    rb.Push(ResultSuccess);
+    rb.PushCopyObjects(lock_event->GetReadableEvent());
+}
+
+void ILockAccessor::IsLocked(HLERequestContext& ctx) {
+    LOG_INFO(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+    rb.Push<u8>(is_locked);
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/lock_accessor.h b/src/core/hle/service/am/lock_accessor.h
new file mode 100644
index 000000000..626f60e07
--- /dev/null
+++ b/src/core/hle/service/am/lock_accessor.h
@@ -0,0 +1,28 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class ILockAccessor final : public ServiceFramework<ILockAccessor> {
+public:
+    explicit ILockAccessor(Core::System& system_);
+    ~ILockAccessor() override;
+
+private:
+    void TryLock(HLERequestContext& ctx);
+    void Unlock(HLERequestContext& ctx);
+    void GetEvent(HLERequestContext& ctx);
+    void IsLocked(HLERequestContext& ctx);
+
+    bool is_locked{};
+
+    Kernel::KEvent* lock_event;
+    KernelHelpers::ServiceContext service_context;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/process_winding_controller.cpp b/src/core/hle/service/am/process_winding_controller.cpp
new file mode 100644
index 000000000..7b3ab157f
--- /dev/null
+++ b/src/core/hle/service/am/process_winding_controller.cpp
@@ -0,0 +1,73 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/applets/applets.h"
+#include "core/hle/service/am/library_applet_accessor.h"
+#include "core/hle/service/am/process_winding_controller.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::AM {
+
+IProcessWindingController::IProcessWindingController(Core::System& system_)
+    : ServiceFramework{system_, "IProcessWindingController"} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, &IProcessWindingController::GetLaunchReason, "GetLaunchReason"},
+        {11, &IProcessWindingController::OpenCallingLibraryApplet, "OpenCallingLibraryApplet"},
+        {21, nullptr, "PushContext"},
+        {22, nullptr, "PopContext"},
+        {23, nullptr, "CancelWindingReservation"},
+        {30, nullptr, "WindAndDoReserved"},
+        {40, nullptr, "ReserveToStartAndWaitAndUnwindThis"},
+        {41, nullptr, "ReserveToStartAndWait"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+IProcessWindingController::~IProcessWindingController() = default;
+
+void IProcessWindingController::GetLaunchReason(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    struct AppletProcessLaunchReason {
+        u8 flag;
+        INSERT_PADDING_BYTES(3);
+    };
+    static_assert(sizeof(AppletProcessLaunchReason) == 0x4,
+                  "AppletProcessLaunchReason is an invalid size");
+
+    AppletProcessLaunchReason reason{
+        .flag = 0,
+    };
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.PushRaw(reason);
+}
+
+void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) {
+    const auto applet_id = system.GetAppletManager().GetCurrentAppletId();
+    const auto applet_mode = Applets::LibraryAppletMode::AllForeground;
+
+    LOG_WARNING(Service_AM, "(STUBBED) called with applet_id={:08X}, applet_mode={:08X}", applet_id,
+                applet_mode);
+
+    const auto& applet_manager{system.GetAppletManager()};
+    const auto applet = applet_manager.GetApplet(applet_id, applet_mode);
+
+    if (applet == nullptr) {
+        LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultUnknown);
+        return;
+    }
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet);
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/process_winding_controller.h b/src/core/hle/service/am/process_winding_controller.h
new file mode 100644
index 000000000..9b9704201
--- /dev/null
+++ b/src/core/hle/service/am/process_winding_controller.h
@@ -0,0 +1,20 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class IProcessWindingController final : public ServiceFramework<IProcessWindingController> {
+public:
+    explicit IProcessWindingController(Core::System& system_);
+    ~IProcessWindingController() override;
+
+private:
+    void GetLaunchReason(HLERequestContext& ctx);
+    void OpenCallingLibraryApplet(HLERequestContext& ctx);
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/self_controller.cpp b/src/core/hle/service/am/self_controller.cpp
new file mode 100644
index 000000000..0f495c871
--- /dev/null
+++ b/src/core/hle/service/am/self_controller.cpp
@@ -0,0 +1,438 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/applets/applets.h"
+#include "core/hle/service/am/self_controller.h"
+#include "core/hle/service/caps/caps_su.h"
+#include "core/hle/service/ipc_helpers.h"
+#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
+#include "core/hle/service/nvnflinger/nvnflinger.h"
+#include "core/hle/service/sm/sm.h"
+#include "core/hle/service/vi/vi_results.h"
+
+namespace Service::AM {
+
+ISelfController::ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_)
+    : ServiceFramework{system_, "ISelfController"}, nvnflinger{nvnflinger_},
+      service_context{system, "ISelfController"} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, &ISelfController::Exit, "Exit"},
+        {1, &ISelfController::LockExit, "LockExit"},
+        {2, &ISelfController::UnlockExit, "UnlockExit"},
+        {3, &ISelfController::EnterFatalSection, "EnterFatalSection"},
+        {4, &ISelfController::LeaveFatalSection, "LeaveFatalSection"},
+        {9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"},
+        {10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"},
+        {11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"},
+        {12, &ISelfController::SetPerformanceModeChangedNotification, "SetPerformanceModeChangedNotification"},
+        {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"},
+        {14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"},
+        {15, nullptr, "SetScreenShotAppletIdentityInfo"},
+        {16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"},
+        {17, nullptr, "SetControllerFirmwareUpdateSection"},
+        {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"},
+        {19, &ISelfController::SetAlbumImageOrientation, "SetAlbumImageOrientation"},
+        {20, nullptr, "SetDesirableKeyboardLayout"},
+        {21, nullptr, "GetScreenShotProgramId"},
+        {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
+        {41, &ISelfController::IsSystemBufferSharingEnabled, "IsSystemBufferSharingEnabled"},
+        {42, &ISelfController::GetSystemSharedLayerHandle, "GetSystemSharedLayerHandle"},
+        {43, &ISelfController::GetSystemSharedBufferHandle, "GetSystemSharedBufferHandle"},
+        {44, &ISelfController::CreateManagedDisplaySeparableLayer, "CreateManagedDisplaySeparableLayer"},
+        {45, nullptr, "SetManagedDisplayLayerSeparationMode"},
+        {46, nullptr, "SetRecordingLayerCompositionEnabled"},
+        {50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"},
+        {51, &ISelfController::ApproveToDisplay, "ApproveToDisplay"},
+        {60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"},
+        {61, nullptr, "SetMediaPlaybackState"},
+        {62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"},
+        {63, &ISelfController::GetIdleTimeDetectionExtension, "GetIdleTimeDetectionExtension"},
+        {64, nullptr, "SetInputDetectionSourceSet"},
+        {65, &ISelfController::ReportUserIsActive, "ReportUserIsActive"},
+        {66, nullptr, "GetCurrentIlluminance"},
+        {67, nullptr, "IsIlluminanceAvailable"},
+        {68, &ISelfController::SetAutoSleepDisabled, "SetAutoSleepDisabled"},
+        {69, &ISelfController::IsAutoSleepDisabled, "IsAutoSleepDisabled"},
+        {70, nullptr, "ReportMultimediaError"},
+        {71, nullptr, "GetCurrentIlluminanceEx"},
+        {72, nullptr, "SetInputDetectionPolicy"},
+        {80, nullptr, "SetWirelessPriorityMode"},
+        {90, &ISelfController::GetAccumulatedSuspendedTickValue, "GetAccumulatedSuspendedTickValue"},
+        {91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"},
+        {100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"},
+        {110, nullptr, "SetApplicationAlbumUserData"},
+        {120, &ISelfController::SaveCurrentScreenshot, "SaveCurrentScreenshot"},
+        {130, &ISelfController::SetRecordVolumeMuted, "SetRecordVolumeMuted"},
+        {1000, nullptr, "GetDebugStorageChannel"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+
+    launchable_event = service_context.CreateEvent("ISelfController:LaunchableEvent");
+
+    // This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is
+    // called. Yuzu can just create it unconditionally, since it doesn't need to support multiple
+    // ISelfControllers. The event is signaled on creation, and on transition from suspended -> not
+    // suspended if the event has previously been created by a call to
+    // GetAccumulatedSuspendedTickChangedEvent.
+
+    accumulated_suspended_tick_changed_event =
+        service_context.CreateEvent("ISelfController:AccumulatedSuspendedTickChangedEvent");
+    accumulated_suspended_tick_changed_event->Signal();
+}
+
+ISelfController::~ISelfController() {
+    service_context.CloseEvent(launchable_event);
+    service_context.CloseEvent(accumulated_suspended_tick_changed_event);
+}
+
+void ISelfController::Exit(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+
+    system.Exit();
+}
+
+void ISelfController::LockExit(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    system.SetExitLocked(true);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ISelfController::UnlockExit(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    system.SetExitLocked(false);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+
+    if (system.GetExitRequested()) {
+        system.Exit();
+    }
+}
+
+void ISelfController::EnterFatalSection(HLERequestContext& ctx) {
+    ++num_fatal_sections_entered;
+    LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", num_fatal_sections_entered);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ISelfController::LeaveFatalSection(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called.");
+
+    // Entry and exit of fatal sections must be balanced.
+    if (num_fatal_sections_entered == 0) {
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(Result{ErrorModule::AM, 512});
+        return;
+    }
+
+    --num_fatal_sections_entered;
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ISelfController::GetLibraryAppletLaunchableEvent(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    launchable_event->Signal();
+
+    IPC::ResponseBuilder rb{ctx, 2, 1};
+    rb.Push(ResultSuccess);
+    rb.PushCopyObjects(launchable_event->GetReadableEvent());
+}
+
+void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const auto permission = rp.PopEnum<ScreenshotPermission>();
+    LOG_DEBUG(Service_AM, "called, permission={}", permission);
+
+    screenshot_permission = permission;
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    bool flag = rp.Pop<bool>();
+    LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ISelfController::SetPerformanceModeChangedNotification(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    bool flag = rp.Pop<bool>();
+    LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ISelfController::SetFocusHandlingMode(HLERequestContext& ctx) {
+    // Takes 3 input u8s with each field located immediately after the previous
+    // u8, these are bool flags. No output.
+    IPC::RequestParser rp{ctx};
+
+    struct FocusHandlingModeParams {
+        u8 unknown0;
+        u8 unknown1;
+        u8 unknown2;
+    };
+    const auto flags = rp.PopRaw<FocusHandlingModeParams>();
+
+    LOG_WARNING(Service_AM, "(STUBBED) called. unknown0={}, unknown1={}, unknown2={}",
+                flags.unknown0, flags.unknown1, flags.unknown2);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ISelfController::SetRestartMessageEnabled(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ISelfController::SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx) {
+    // Takes 3 input u8s with each field located immediately after the previous
+    // u8, these are bool flags. No output.
+    IPC::RequestParser rp{ctx};
+
+    bool enabled = rp.Pop<bool>();
+    LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ISelfController::CreateManagedDisplayLayer(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    // TODO(Subv): Find out how AM determines the display to use, for now just
+    // create the layer in the Default display.
+    const auto display_id = nvnflinger.OpenDisplay("Default");
+    const auto layer_id = nvnflinger.CreateLayer(*display_id);
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(ResultSuccess);
+    rb.Push(*layer_id);
+}
+
+void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess()));
+}
+
+void ISelfController::GetSystemSharedLayerHandle(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 6};
+    rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess()));
+    rb.Push<s64>(system_shared_buffer_id);
+    rb.Push<s64>(system_shared_layer_id);
+}
+
+void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess()));
+    rb.Push<s64>(system_shared_buffer_id);
+}
+
+Result ISelfController::EnsureBufferSharingEnabled(Kernel::KProcess* process) {
+    if (buffer_sharing_enabled) {
+        return ResultSuccess;
+    }
+
+    if (system.GetAppletManager().GetCurrentAppletId() <= Applets::AppletId::Application) {
+        return VI::ResultOperationFailed;
+    }
+
+    const auto display_id = nvnflinger.OpenDisplay("Default");
+    const auto result = nvnflinger.GetSystemBufferManager().Initialize(
+        &system_shared_buffer_id, &system_shared_layer_id, *display_id);
+
+    if (result.IsSuccess()) {
+        buffer_sharing_enabled = true;
+    }
+
+    return result;
+}
+
+void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    // TODO(Subv): Find out how AM determines the display to use, for now just
+    // create the layer in the Default display.
+    // This calls nn::vi::CreateRecordingLayer() which creates another layer.
+    // Currently we do not support more than 1 layer per display, output 1 layer id for now.
+    // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse
+    // side effects.
+    // TODO: Support multiple layers
+    const auto display_id = nvnflinger.OpenDisplay("Default");
+    const auto layer_id = nvnflinger.CreateLayer(*display_id);
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(ResultSuccess);
+    rb.Push(*layer_id);
+}
+
+void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ISelfController::ApproveToDisplay(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    idle_time_detection_extension = rp.Pop<u32>();
+    LOG_DEBUG(Service_AM, "(STUBBED) called idle_time_detection_extension={}",
+              idle_time_detection_extension);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ISelfController::GetIdleTimeDetectionExtension(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push<u32>(idle_time_detection_extension);
+}
+
+void ISelfController::ReportUserIsActive(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    is_auto_sleep_disabled = rp.Pop<bool>();
+
+    // On the system itself, if the previous state of is_auto_sleep_disabled
+    // differed from the current value passed in, it'd signify the internal
+    // window manager to update (and also increment some statistics like update counts)
+    //
+    // It'd also indicate this change to an idle handling context.
+    //
+    // However, given we're emulating this behavior, most of this can be ignored
+    // and it's sufficient to simply set the member variable for querying via
+    // IsAutoSleepDisabled().
+
+    LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", is_auto_sleep_disabled);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ISelfController::IsAutoSleepDisabled(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called.");
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push(is_auto_sleep_disabled);
+}
+
+void ISelfController::GetAccumulatedSuspendedTickValue(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called.");
+
+    // This command returns the total number of system ticks since ISelfController creation
+    // where the game was suspended. Since Yuzu doesn't implement game suspension, this command
+    // can just always return 0 ticks.
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(ResultSuccess);
+    rb.Push<u64>(0);
+}
+
+void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called.");
+
+    IPC::ResponseBuilder rb{ctx, 2, 1};
+    rb.Push(ResultSuccess);
+    rb.PushCopyObjects(accumulated_suspended_tick_changed_event->GetReadableEvent());
+}
+
+void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    // This service call sets an internal flag whether a notification is shown when an image is
+    // captured. Currently we do not support capturing images via the capture button, so this can be
+    // stubbed for now.
+    const bool album_image_taken_notification_enabled = rp.Pop<bool>();
+
+    LOG_WARNING(Service_AM, "(STUBBED) called. album_image_taken_notification_enabled={}",
+                album_image_taken_notification_enabled);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ISelfController::SaveCurrentScreenshot(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    const auto report_option = rp.PopEnum<Capture::AlbumReportOption>();
+
+    LOG_INFO(Service_AM, "called, report_option={}", report_option);
+
+    const auto screenshot_service =
+        system.ServiceManager().GetService<Service::Capture::IScreenShotApplicationService>(
+            "caps:su");
+
+    if (screenshot_service) {
+        screenshot_service->CaptureAndSaveScreenshot(report_option);
+    }
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ISelfController::SetRecordVolumeMuted(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    const auto is_record_volume_muted = rp.Pop<bool>();
+
+    LOG_WARNING(Service_AM, "(STUBBED) called. is_record_volume_muted={}", is_record_volume_muted);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/self_controller.h b/src/core/hle/service/am/self_controller.h
new file mode 100644
index 000000000..f157bb826
--- /dev/null
+++ b/src/core/hle/service/am/self_controller.h
@@ -0,0 +1,72 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class ISelfController final : public ServiceFramework<ISelfController> {
+public:
+    explicit ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_);
+    ~ISelfController() override;
+
+private:
+    void Exit(HLERequestContext& ctx);
+    void LockExit(HLERequestContext& ctx);
+    void UnlockExit(HLERequestContext& ctx);
+    void EnterFatalSection(HLERequestContext& ctx);
+    void LeaveFatalSection(HLERequestContext& ctx);
+    void GetLibraryAppletLaunchableEvent(HLERequestContext& ctx);
+    void SetScreenShotPermission(HLERequestContext& ctx);
+    void SetOperationModeChangedNotification(HLERequestContext& ctx);
+    void SetPerformanceModeChangedNotification(HLERequestContext& ctx);
+    void SetFocusHandlingMode(HLERequestContext& ctx);
+    void SetRestartMessageEnabled(HLERequestContext& ctx);
+    void SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx);
+    void SetAlbumImageOrientation(HLERequestContext& ctx);
+    void IsSystemBufferSharingEnabled(HLERequestContext& ctx);
+    void GetSystemSharedBufferHandle(HLERequestContext& ctx);
+    void GetSystemSharedLayerHandle(HLERequestContext& ctx);
+    void CreateManagedDisplayLayer(HLERequestContext& ctx);
+    void CreateManagedDisplaySeparableLayer(HLERequestContext& ctx);
+    void SetHandlesRequestToDisplay(HLERequestContext& ctx);
+    void ApproveToDisplay(HLERequestContext& ctx);
+    void SetIdleTimeDetectionExtension(HLERequestContext& ctx);
+    void GetIdleTimeDetectionExtension(HLERequestContext& ctx);
+    void ReportUserIsActive(HLERequestContext& ctx);
+    void SetAutoSleepDisabled(HLERequestContext& ctx);
+    void IsAutoSleepDisabled(HLERequestContext& ctx);
+    void GetAccumulatedSuspendedTickValue(HLERequestContext& ctx);
+    void GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx);
+    void SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx);
+    void SaveCurrentScreenshot(HLERequestContext& ctx);
+    void SetRecordVolumeMuted(HLERequestContext& ctx);
+
+    Result EnsureBufferSharingEnabled(Kernel::KProcess* process);
+
+    enum class ScreenshotPermission : u32 {
+        Inherit = 0,
+        Enable = 1,
+        Disable = 2,
+    };
+
+    Nvnflinger::Nvnflinger& nvnflinger;
+
+    KernelHelpers::ServiceContext service_context;
+
+    Kernel::KEvent* launchable_event;
+    Kernel::KEvent* accumulated_suspended_tick_changed_event;
+
+    u32 idle_time_detection_extension = 0;
+    u64 num_fatal_sections_entered = 0;
+    u64 system_shared_buffer_id = 0;
+    u64 system_shared_layer_id = 0;
+    bool is_auto_sleep_disabled = false;
+    bool buffer_sharing_enabled = false;
+    ScreenshotPermission screenshot_permission = ScreenshotPermission::Inherit;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/storage.cpp b/src/core/hle/service/am/storage.cpp
new file mode 100644
index 000000000..9a86c867a
--- /dev/null
+++ b/src/core/hle/service/am/storage.cpp
@@ -0,0 +1,60 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/storage.h"
+#include "core/hle/service/am/storage_accessor.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::AM {
+
+IStorageImpl::~IStorageImpl() = default;
+
+class StorageDataImpl final : public IStorageImpl {
+public:
+    explicit StorageDataImpl(std::vector<u8>&& buffer_) : buffer{std::move(buffer_)} {}
+
+    std::vector<u8>& GetData() override {
+        return buffer;
+    }
+
+    const std::vector<u8>& GetData() const override {
+        return buffer;
+    }
+
+    std::size_t GetSize() const override {
+        return buffer.size();
+    }
+
+private:
+    std::vector<u8> buffer;
+};
+
+IStorage::IStorage(Core::System& system_, std::vector<u8>&& buffer)
+    : ServiceFramework{system_, "IStorage"},
+      impl{std::make_shared<StorageDataImpl>(std::move(buffer))} {
+    Register();
+}
+
+void IStorage::Register() {
+    // clang-format off
+        static const FunctionInfo functions[] = {
+            {0, &IStorage::Open, "Open"},
+            {1, nullptr, "OpenTransferStorage"},
+        };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+IStorage::~IStorage() = default;
+
+void IStorage::Open(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IStorageAccessor>(system, *this);
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/storage.h b/src/core/hle/service/am/storage.h
new file mode 100644
index 000000000..d47a8d89f
--- /dev/null
+++ b/src/core/hle/service/am/storage.h
@@ -0,0 +1,42 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class IStorageImpl {
+public:
+    virtual ~IStorageImpl();
+    virtual std::vector<u8>& GetData() = 0;
+    virtual const std::vector<u8>& GetData() const = 0;
+    virtual std::size_t GetSize() const = 0;
+};
+
+class IStorage final : public ServiceFramework<IStorage> {
+public:
+    explicit IStorage(Core::System& system_, std::vector<u8>&& buffer);
+    ~IStorage() override;
+
+    std::vector<u8>& GetData() {
+        return impl->GetData();
+    }
+
+    const std::vector<u8>& GetData() const {
+        return impl->GetData();
+    }
+
+    std::size_t GetSize() const {
+        return impl->GetSize();
+    }
+
+private:
+    void Register();
+    void Open(HLERequestContext& ctx);
+
+    std::shared_ptr<IStorageImpl> impl;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/storage_accessor.cpp b/src/core/hle/service/am/storage_accessor.cpp
new file mode 100644
index 000000000..7d8c82de3
--- /dev/null
+++ b/src/core/hle/service/am/storage_accessor.cpp
@@ -0,0 +1,82 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/am_results.h"
+#include "core/hle/service/am/storage_accessor.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::AM {
+
+IStorageAccessor::IStorageAccessor(Core::System& system_, IStorage& backing_)
+    : ServiceFramework{system_, "IStorageAccessor"}, backing{backing_} {
+    // clang-format off
+        static const FunctionInfo functions[] = {
+            {0, &IStorageAccessor::GetSize, "GetSize"},
+            {10, &IStorageAccessor::Write, "Write"},
+            {11, &IStorageAccessor::Read, "Read"},
+        };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+IStorageAccessor::~IStorageAccessor() = default;
+
+void IStorageAccessor::GetSize(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 4};
+
+    rb.Push(ResultSuccess);
+    rb.Push(static_cast<u64>(backing.GetSize()));
+}
+
+void IStorageAccessor::Write(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    const u64 offset{rp.Pop<u64>()};
+    const auto data{ctx.ReadBuffer()};
+    const std::size_t size{std::min<u64>(data.size(), backing.GetSize() - offset)};
+
+    LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size);
+
+    if (offset > backing.GetSize()) {
+        LOG_ERROR(Service_AM,
+                  "offset is out of bounds, backing_buffer_sz={}, data_size={}, offset={}",
+                  backing.GetSize(), size, offset);
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(AM::ResultInvalidOffset);
+        return;
+    }
+
+    std::memcpy(backing.GetData().data() + offset, data.data(), size);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void IStorageAccessor::Read(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+
+    const u64 offset{rp.Pop<u64>()};
+    const std::size_t size{std::min<u64>(ctx.GetWriteBufferSize(), backing.GetSize() - offset)};
+
+    LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size);
+
+    if (offset > backing.GetSize()) {
+        LOG_ERROR(Service_AM, "offset is out of bounds, backing_buffer_sz={}, size={}, offset={}",
+                  backing.GetSize(), size, offset);
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(AM::ResultInvalidOffset);
+        return;
+    }
+
+    ctx.WriteBuffer(backing.GetData().data() + offset, size);
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/storage_accessor.h b/src/core/hle/service/am/storage_accessor.h
new file mode 100644
index 000000000..8648bfc13
--- /dev/null
+++ b/src/core/hle/service/am/storage_accessor.h
@@ -0,0 +1,24 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/am/storage.h"
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
+public:
+    explicit IStorageAccessor(Core::System& system_, IStorage& backing_);
+    ~IStorageAccessor() override;
+
+private:
+    void GetSize(HLERequestContext& ctx);
+    void Write(HLERequestContext& ctx);
+    void Read(HLERequestContext& ctx);
+
+    IStorage& backing;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/system_applet_proxy.cpp b/src/core/hle/service/am/system_applet_proxy.cpp
new file mode 100644
index 000000000..d51a2c8db
--- /dev/null
+++ b/src/core/hle/service/am/system_applet_proxy.cpp
@@ -0,0 +1,135 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/applet_common_functions.h"
+#include "core/hle/service/am/application_creator.h"
+#include "core/hle/service/am/audio_controller.h"
+#include "core/hle/service/am/common_state_getter.h"
+#include "core/hle/service/am/debug_functions.h"
+#include "core/hle/service/am/display_controller.h"
+#include "core/hle/service/am/global_state_controller.h"
+#include "core/hle/service/am/home_menu_functions.h"
+#include "core/hle/service/am/library_applet_creator.h"
+#include "core/hle/service/am/library_applet_self_accessor.h"
+#include "core/hle/service/am/process_winding_controller.h"
+#include "core/hle/service/am/self_controller.h"
+#include "core/hle/service/am/system_applet_proxy.h"
+#include "core/hle/service/am/window_controller.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::AM {
+
+ISystemAppletProxy::ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
+                                       std::shared_ptr<AppletMessageQueue> msg_queue_,
+                                       Core::System& system_)
+    : ServiceFramework{system_, "ISystemAppletProxy"}, nvnflinger{nvnflinger_},
+      msg_queue{std::move(msg_queue_)} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
+        {1, &ISystemAppletProxy::GetSelfController, "GetSelfController"},
+        {2, &ISystemAppletProxy::GetWindowController, "GetWindowController"},
+        {3, &ISystemAppletProxy::GetAudioController, "GetAudioController"},
+        {4, &ISystemAppletProxy::GetDisplayController, "GetDisplayController"},
+        {10, nullptr, "GetProcessWindingController"},
+        {11, &ISystemAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
+        {20, &ISystemAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"},
+        {21, &ISystemAppletProxy::GetGlobalStateController, "GetGlobalStateController"},
+        {22, &ISystemAppletProxy::GetApplicationCreator, "GetApplicationCreator"},
+        {23,  &ISystemAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"},
+        {1000, &ISystemAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+void ISystemAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue);
+}
+
+void ISystemAppletProxy::GetSelfController(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<ISelfController>(system, nvnflinger);
+}
+
+void ISystemAppletProxy::GetWindowController(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IWindowController>(system);
+}
+
+void ISystemAppletProxy::GetAudioController(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IAudioController>(system);
+}
+
+void ISystemAppletProxy::GetDisplayController(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IDisplayController>(system);
+}
+
+void ISystemAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<ILibraryAppletCreator>(system);
+}
+
+void ISystemAppletProxy::GetHomeMenuFunctions(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IHomeMenuFunctions>(system);
+}
+
+void ISystemAppletProxy::GetGlobalStateController(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IGlobalStateController>(system);
+}
+
+void ISystemAppletProxy::GetApplicationCreator(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IApplicationCreator>(system);
+}
+
+void ISystemAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IAppletCommonFunctions>(system);
+}
+
+void ISystemAppletProxy::GetDebugFunctions(HLERequestContext& ctx) {
+    LOG_DEBUG(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IDebugFunctions>(system);
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/system_applet_proxy.h b/src/core/hle/service/am/system_applet_proxy.h
new file mode 100644
index 000000000..b8855b1d6
--- /dev/null
+++ b/src/core/hle/service/am/system_applet_proxy.h
@@ -0,0 +1,34 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/am/applet_message_queue.h"
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> {
+public:
+    explicit ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
+                                std::shared_ptr<AppletMessageQueue> msg_queue_,
+                                Core::System& system_);
+
+private:
+    void GetCommonStateGetter(HLERequestContext& ctx);
+    void GetSelfController(HLERequestContext& ctx);
+    void GetWindowController(HLERequestContext& ctx);
+    void GetAudioController(HLERequestContext& ctx);
+    void GetDisplayController(HLERequestContext& ctx);
+    void GetLibraryAppletCreator(HLERequestContext& ctx);
+    void GetHomeMenuFunctions(HLERequestContext& ctx);
+    void GetGlobalStateController(HLERequestContext& ctx);
+    void GetApplicationCreator(HLERequestContext& ctx);
+    void GetAppletCommonFunctions(HLERequestContext& ctx);
+    void GetDebugFunctions(HLERequestContext& ctx);
+
+    Nvnflinger::Nvnflinger& nvnflinger;
+    std::shared_ptr<AppletMessageQueue> msg_queue;
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/window_controller.cpp b/src/core/hle/service/am/window_controller.cpp
new file mode 100644
index 000000000..f2ba3c134
--- /dev/null
+++ b/src/core/hle/service/am/window_controller.cpp
@@ -0,0 +1,55 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/am/window_controller.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::AM {
+
+IWindowController::IWindowController(Core::System& system_)
+    : ServiceFramework{system_, "IWindowController"} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, nullptr, "CreateWindow"},
+        {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"},
+        {2, &IWindowController::GetAppletResourceUserIdOfCallerApplet, "GetAppletResourceUserIdOfCallerApplet"},
+        {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"},
+        {11, nullptr, "ReleaseForegroundRights"},
+        {12, nullptr, "RejectToChangeIntoBackground"},
+        {20, nullptr, "SetAppletWindowVisibility"},
+        {21, nullptr, "SetAppletGpuTimeSlice"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+IWindowController::~IWindowController() = default;
+
+void IWindowController::GetAppletResourceUserId(HLERequestContext& ctx) {
+    const u64 process_id = system.ApplicationProcess()->GetProcessId();
+
+    LOG_DEBUG(Service_AM, "called. Process ID=0x{:016X}", process_id);
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(ResultSuccess);
+    rb.Push<u64>(process_id);
+}
+
+void IWindowController::GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx) {
+    const u64 process_id = 0;
+
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(ResultSuccess);
+    rb.Push<u64>(process_id);
+}
+
+void IWindowController::AcquireForegroundRights(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/window_controller.h b/src/core/hle/service/am/window_controller.h
new file mode 100644
index 000000000..07b0e0e17
--- /dev/null
+++ b/src/core/hle/service/am/window_controller.h
@@ -0,0 +1,21 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class IWindowController final : public ServiceFramework<IWindowController> {
+public:
+    explicit IWindowController(Core::System& system_);
+    ~IWindowController() override;
+
+private:
+    void GetAppletResourceUserId(HLERequestContext& ctx);
+    void GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx);
+    void AcquireForegroundRights(HLERequestContext& ctx);
+};
+
+} // namespace Service::AM
-- 
cgit v1.2.3