mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-15 22:54:00 +00:00
Merge pull request #12993 from liamwhite/am-rewrite-part1
am: rewrite part 1
This commit is contained in:
commit
1e8554b01f
117 changed files with 4241 additions and 4107 deletions
|
@ -49,9 +49,7 @@
|
||||||
#include "core/frontend/applets/profile_select.h"
|
#include "core/frontend/applets/profile_select.h"
|
||||||
#include "core/frontend/applets/software_keyboard.h"
|
#include "core/frontend/applets/software_keyboard.h"
|
||||||
#include "core/frontend/applets/web_browser.h"
|
#include "core/frontend/applets/web_browser.h"
|
||||||
#include "core/hle/service/am/applet_ae.h"
|
|
||||||
#include "core/hle/service/am/applet_manager.h"
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
#include "core/hle/service/am/applet_oe.h"
|
|
||||||
#include "core/hle/service/am/frontend/applets.h"
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
#include "core/hle/service/filesystem/filesystem.h"
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||||
#include "core/loader/loader.h"
|
#include "core/loader/loader.h"
|
||||||
|
|
|
@ -417,74 +417,72 @@ add_library(core STATIC
|
||||||
hle/service/am/am_types.h
|
hle/service/am/am_types.h
|
||||||
hle/service/am/applet.cpp
|
hle/service/am/applet.cpp
|
||||||
hle/service/am/applet.h
|
hle/service/am/applet.h
|
||||||
hle/service/am/applet_ae.cpp
|
|
||||||
hle/service/am/applet_ae.h
|
|
||||||
hle/service/am/applet_manager.cpp
|
hle/service/am/applet_manager.cpp
|
||||||
hle/service/am/applet_data_broker.cpp
|
hle/service/am/applet_data_broker.cpp
|
||||||
hle/service/am/applet_data_broker.h
|
hle/service/am/applet_data_broker.h
|
||||||
hle/service/am/applet_manager.h
|
hle/service/am/applet_manager.h
|
||||||
hle/service/am/applet_oe.cpp
|
|
||||||
hle/service/am/applet_oe.h
|
|
||||||
hle/service/am/applet_common_functions.cpp
|
|
||||||
hle/service/am/applet_common_functions.h
|
|
||||||
hle/service/am/applet_message_queue.cpp
|
hle/service/am/applet_message_queue.cpp
|
||||||
hle/service/am/applet_message_queue.h
|
hle/service/am/applet_message_queue.h
|
||||||
hle/service/am/application_creator.cpp
|
|
||||||
hle/service/am/application_creator.h
|
|
||||||
hle/service/am/application_functions.cpp
|
|
||||||
hle/service/am/application_functions.h
|
|
||||||
hle/service/am/application_proxy.cpp
|
|
||||||
hle/service/am/application_proxy.h
|
|
||||||
hle/service/am/audio_controller.cpp
|
|
||||||
hle/service/am/audio_controller.h
|
|
||||||
hle/service/am/common_state_getter.cpp
|
|
||||||
hle/service/am/common_state_getter.h
|
|
||||||
hle/service/am/debug_functions.cpp
|
|
||||||
hle/service/am/debug_functions.h
|
|
||||||
hle/service/am/display_controller.cpp
|
|
||||||
hle/service/am/display_controller.h
|
|
||||||
hle/service/am/global_state_controller.cpp
|
|
||||||
hle/service/am/global_state_controller.h
|
|
||||||
hle/service/am/hid_registration.cpp
|
hle/service/am/hid_registration.cpp
|
||||||
hle/service/am/hid_registration.h
|
hle/service/am/hid_registration.h
|
||||||
hle/service/am/home_menu_functions.cpp
|
|
||||||
hle/service/am/home_menu_functions.h
|
|
||||||
hle/service/am/idle.cpp
|
|
||||||
hle/service/am/idle.h
|
|
||||||
hle/service/am/library_applet_accessor.cpp
|
|
||||||
hle/service/am/library_applet_accessor.h
|
|
||||||
hle/service/am/library_applet_creator.cpp
|
|
||||||
hle/service/am/library_applet_creator.h
|
|
||||||
hle/service/am/library_applet_proxy.cpp
|
|
||||||
hle/service/am/library_applet_proxy.h
|
|
||||||
hle/service/am/library_applet_self_accessor.cpp
|
|
||||||
hle/service/am/library_applet_self_accessor.h
|
|
||||||
hle/service/am/library_applet_storage.cpp
|
hle/service/am/library_applet_storage.cpp
|
||||||
hle/service/am/library_applet_storage.h
|
hle/service/am/library_applet_storage.h
|
||||||
hle/service/am/lock_accessor.cpp
|
|
||||||
hle/service/am/lock_accessor.h
|
|
||||||
hle/service/am/managed_layer_holder.cpp
|
hle/service/am/managed_layer_holder.cpp
|
||||||
hle/service/am/managed_layer_holder.h
|
hle/service/am/managed_layer_holder.h
|
||||||
hle/service/am/omm.cpp
|
|
||||||
hle/service/am/omm.h
|
|
||||||
hle/service/am/process_winding_controller.cpp
|
|
||||||
hle/service/am/process_winding_controller.h
|
|
||||||
hle/service/am/process.cpp
|
hle/service/am/process.cpp
|
||||||
hle/service/am/process.h
|
hle/service/am/process.h
|
||||||
hle/service/am/self_controller.cpp
|
hle/service/am/service/all_system_applet_proxies_service.cpp
|
||||||
hle/service/am/self_controller.h
|
hle/service/am/service/all_system_applet_proxies_service.h
|
||||||
hle/service/am/system_applet_proxy.cpp
|
hle/service/am/service/applet_common_functions.cpp
|
||||||
hle/service/am/system_applet_proxy.h
|
hle/service/am/service/applet_common_functions.h
|
||||||
|
hle/service/am/service/application_accessor.cpp
|
||||||
|
hle/service/am/service/application_accessor.h
|
||||||
|
hle/service/am/service/application_creator.cpp
|
||||||
|
hle/service/am/service/application_creator.h
|
||||||
|
hle/service/am/service/application_functions.cpp
|
||||||
|
hle/service/am/service/application_functions.h
|
||||||
|
hle/service/am/service/application_proxy_service.cpp
|
||||||
|
hle/service/am/service/application_proxy_service.h
|
||||||
|
hle/service/am/service/application_proxy.cpp
|
||||||
|
hle/service/am/service/application_proxy.h
|
||||||
|
hle/service/am/service/audio_controller.cpp
|
||||||
|
hle/service/am/service/audio_controller.h
|
||||||
|
hle/service/am/service/common_state_getter.cpp
|
||||||
|
hle/service/am/service/common_state_getter.h
|
||||||
|
hle/service/am/service/cradle_firmware_updater.cpp
|
||||||
|
hle/service/am/service/cradle_firmware_updater.h
|
||||||
|
hle/service/am/service/debug_functions.cpp
|
||||||
|
hle/service/am/service/debug_functions.h
|
||||||
|
hle/service/am/service/display_controller.cpp
|
||||||
|
hle/service/am/service/display_controller.h
|
||||||
|
hle/service/am/service/global_state_controller.cpp
|
||||||
|
hle/service/am/service/global_state_controller.h
|
||||||
|
hle/service/am/service/home_menu_functions.cpp
|
||||||
|
hle/service/am/service/home_menu_functions.h
|
||||||
|
hle/service/am/service/library_applet_accessor.cpp
|
||||||
|
hle/service/am/service/library_applet_accessor.h
|
||||||
|
hle/service/am/service/library_applet_creator.cpp
|
||||||
|
hle/service/am/service/library_applet_creator.h
|
||||||
|
hle/service/am/service/library_applet_proxy.cpp
|
||||||
|
hle/service/am/service/library_applet_proxy.h
|
||||||
|
hle/service/am/service/library_applet_self_accessor.cpp
|
||||||
|
hle/service/am/service/library_applet_self_accessor.h
|
||||||
|
hle/service/am/service/lock_accessor.cpp
|
||||||
|
hle/service/am/service/lock_accessor.h
|
||||||
|
hle/service/am/service/process_winding_controller.cpp
|
||||||
|
hle/service/am/service/process_winding_controller.h
|
||||||
|
hle/service/am/service/self_controller.cpp
|
||||||
|
hle/service/am/service/self_controller.h
|
||||||
|
hle/service/am/service/storage_accessor.cpp
|
||||||
|
hle/service/am/service/storage_accessor.h
|
||||||
|
hle/service/am/service/storage.cpp
|
||||||
|
hle/service/am/service/storage.h
|
||||||
|
hle/service/am/service/system_applet_proxy.cpp
|
||||||
|
hle/service/am/service/system_applet_proxy.h
|
||||||
|
hle/service/am/service/window_controller.cpp
|
||||||
|
hle/service/am/service/window_controller.h
|
||||||
hle/service/am/system_buffer_manager.cpp
|
hle/service/am/system_buffer_manager.cpp
|
||||||
hle/service/am/system_buffer_manager.h
|
hle/service/am/system_buffer_manager.h
|
||||||
hle/service/am/spsm.cpp
|
|
||||||
hle/service/am/spsm.h
|
|
||||||
hle/service/am/storage_accessor.cpp
|
|
||||||
hle/service/am/storage_accessor.h
|
|
||||||
hle/service/am/storage.cpp
|
|
||||||
hle/service/am/storage.h
|
|
||||||
hle/service/am/window_controller.cpp
|
|
||||||
hle/service/am/window_controller.h
|
|
||||||
hle/service/aoc/aoc_u.cpp
|
hle/service/aoc/aoc_u.cpp
|
||||||
hle/service/aoc/aoc_u.h
|
hle/service/aoc/aoc_u.h
|
||||||
hle/service/apm/apm.cpp
|
hle/service/apm/apm.cpp
|
||||||
|
@ -823,6 +821,14 @@ add_library(core STATIC
|
||||||
hle/service/nvnflinger/window.h
|
hle/service/nvnflinger/window.h
|
||||||
hle/service/olsc/olsc.cpp
|
hle/service/olsc/olsc.cpp
|
||||||
hle/service/olsc/olsc.h
|
hle/service/olsc/olsc.h
|
||||||
|
hle/service/omm/omm.cpp
|
||||||
|
hle/service/omm/omm.h
|
||||||
|
hle/service/omm/operation_mode_manager.cpp
|
||||||
|
hle/service/omm/operation_mode_manager.h
|
||||||
|
hle/service/omm/policy_manager_system.cpp
|
||||||
|
hle/service/omm/policy_manager_system.h
|
||||||
|
hle/service/omm/power_state_interface.cpp
|
||||||
|
hle/service/omm/power_state_interface.h
|
||||||
hle/service/os/event.cpp
|
hle/service/os/event.cpp
|
||||||
hle/service/os/event.h
|
hle/service/os/event.h
|
||||||
hle/service/os/multi_wait_holder.cpp
|
hle/service/os/multi_wait_holder.cpp
|
||||||
|
|
|
@ -2,11 +2,8 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
#include "core/hle/service/am/applet_ae.h"
|
#include "core/hle/service/am/service/all_system_applet_proxies_service.h"
|
||||||
#include "core/hle/service/am/applet_oe.h"
|
#include "core/hle/service/am/service/application_proxy_service.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/server_manager.h"
|
#include "core/hle/service/server_manager.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
@ -14,13 +11,10 @@ namespace Service::AM {
|
||||||
void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) {
|
void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) {
|
||||||
auto server_manager = std::make_unique<ServerManager>(system);
|
auto server_manager = std::make_unique<ServerManager>(system);
|
||||||
|
|
||||||
server_manager->RegisterNamedService("appletAE",
|
server_manager->RegisterNamedService(
|
||||||
std::make_shared<AppletAE>(nvnflinger, system));
|
"appletAE", std::make_shared<IAllSystemAppletProxiesService>(system, nvnflinger));
|
||||||
server_manager->RegisterNamedService("appletOE",
|
server_manager->RegisterNamedService(
|
||||||
std::make_shared<AppletOE>(nvnflinger, system));
|
"appletOE", std::make_shared<IApplicationProxyService>(system, nvnflinger));
|
||||||
server_manager->RegisterNamedService("idle:sys", std::make_shared<IdleSys>(system));
|
|
||||||
server_manager->RegisterNamedService("omm", std::make_shared<OMM>(system));
|
|
||||||
server_manager->RegisterNamedService("spsm", std::make_shared<SPSM>(system));
|
|
||||||
ServerManager::RunServer(std::move(server_manager));
|
ServerManager::RunServer(std::move(server_manager));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ enum class AppletType {
|
||||||
SystemApplet,
|
SystemApplet,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class GameplayRecordingState : u32 {
|
enum class GamePlayRecordingState : u32 {
|
||||||
Disabled,
|
Disabled,
|
||||||
Enabled,
|
Enabled,
|
||||||
};
|
};
|
||||||
|
@ -67,10 +67,9 @@ enum class ScreenshotPermission : u32 {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FocusHandlingMode {
|
struct FocusHandlingMode {
|
||||||
bool unknown0;
|
bool notify;
|
||||||
bool unknown1;
|
bool background;
|
||||||
bool unknown2;
|
bool suspend;
|
||||||
bool unknown3;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class IdleTimeDetectionExtension : u32 {
|
enum class IdleTimeDetectionExtension : u32 {
|
||||||
|
@ -128,6 +127,40 @@ enum class AppletProgramId : u64 {
|
||||||
MaxProgramId = 0x0100000000001FFFull,
|
MaxProgramId = 0x0100000000001FFFull,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
};
|
||||||
|
|
||||||
enum class LibraryAppletMode : u32 {
|
enum class LibraryAppletMode : u32 {
|
||||||
AllForeground = 0,
|
AllForeground = 0,
|
||||||
PartialForeground = 1,
|
PartialForeground = 1,
|
||||||
|
@ -136,6 +169,11 @@ enum class LibraryAppletMode : u32 {
|
||||||
AllForegroundInitiallyHidden = 4,
|
AllForegroundInitiallyHidden = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class LaunchParameterKind : u32 {
|
||||||
|
UserChannel = 1,
|
||||||
|
AccountPreselectedUser = 2,
|
||||||
|
};
|
||||||
|
|
||||||
enum class CommonArgumentVersion : u32 {
|
enum class CommonArgumentVersion : u32 {
|
||||||
Version0,
|
Version0,
|
||||||
Version1,
|
Version1,
|
||||||
|
@ -152,6 +190,22 @@ enum class ThemeColor : u32 {
|
||||||
BasicBlack = 3,
|
BasicBlack = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class InputDetectionPolicy : u32 {
|
||||||
|
Unknown0 = 0,
|
||||||
|
Unknown1 = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class WindowOriginMode : u32 {
|
||||||
|
LowerLeft = 0,
|
||||||
|
UpperLeft = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ProgramSpecifyKind : u32 {
|
||||||
|
ExecuteProgram = 0,
|
||||||
|
JumpToSubApplicationProgramForDevelopment = 1,
|
||||||
|
RestartProgram = 2,
|
||||||
|
};
|
||||||
|
|
||||||
struct CommonArguments {
|
struct CommonArguments {
|
||||||
CommonArgumentVersion arguments_version;
|
CommonArgumentVersion arguments_version;
|
||||||
CommonArgumentSize size;
|
CommonArgumentSize size;
|
||||||
|
@ -169,6 +223,27 @@ struct AppletIdentityInfo {
|
||||||
};
|
};
|
||||||
static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size.");
|
static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size.");
|
||||||
|
|
||||||
|
struct AppletAttribute {
|
||||||
|
u8 flag;
|
||||||
|
INSERT_PADDING_BYTES_NOINIT(0x7F);
|
||||||
|
};
|
||||||
|
static_assert(sizeof(AppletAttribute) == 0x80, "AppletAttribute has incorrect size.");
|
||||||
|
|
||||||
|
// This is nn::oe::DisplayVersion
|
||||||
|
struct DisplayVersion {
|
||||||
|
std::array<char, 0x10> string;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(DisplayVersion) == 0x10, "DisplayVersion has incorrect size.");
|
||||||
|
|
||||||
|
// This is nn::pdm::ApplicationPlayStatistics
|
||||||
|
struct ApplicationPlayStatistics {
|
||||||
|
u64 application_id;
|
||||||
|
u64 play_time_ns;
|
||||||
|
u64 launch_count;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(ApplicationPlayStatistics) == 0x18,
|
||||||
|
"ApplicationPlayStatistics has incorrect size.");
|
||||||
|
|
||||||
using AppletResourceUserId = u64;
|
using AppletResourceUserId = u64;
|
||||||
using ProgramId = u64;
|
using ProgramId = u64;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <list>
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "common/math_util.h"
|
#include "common/math_util.h"
|
||||||
|
@ -18,7 +17,6 @@
|
||||||
#include "core/hle/service/am/hid_registration.h"
|
#include "core/hle/service/am/hid_registration.h"
|
||||||
#include "core/hle/service/am/managed_layer_holder.h"
|
#include "core/hle/service/am/managed_layer_holder.h"
|
||||||
#include "core/hle/service/am/process.h"
|
#include "core/hle/service/am/process.h"
|
||||||
#include "core/hle/service/am/storage.h"
|
|
||||||
#include "core/hle/service/am/system_buffer_manager.h"
|
#include "core/hle/service/am/system_buffer_manager.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
@ -76,8 +74,8 @@ struct Applet {
|
||||||
u32 application_core_usage_mode{};
|
u32 application_core_usage_mode{};
|
||||||
|
|
||||||
// Application functions
|
// Application functions
|
||||||
bool gameplay_recording_supported{};
|
bool game_play_recording_supported{};
|
||||||
GameplayRecordingState gameplay_recording_state{GameplayRecordingState::Disabled};
|
GamePlayRecordingState game_play_recording_state{GamePlayRecordingState::Disabled};
|
||||||
bool jit_service_launched{};
|
bool jit_service_launched{};
|
||||||
bool is_running{};
|
bool is_running{};
|
||||||
bool application_crash_report_enabled{};
|
bool application_crash_report_enabled{};
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "core/hle/service/am/applet_ae.h"
|
|
||||||
#include "core/hle/service/am/applet_manager.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"
|
|
||||||
|
|
||||||
namespace Service::AM {
|
|
||||||
|
|
||||||
AppletAE::AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_)
|
|
||||||
: ServiceFramework{system_, "appletAE"}, nvnflinger{nvnflinger_} {
|
|
||||||
// clang-format off
|
|
||||||
static const FunctionInfo functions[] = {
|
|
||||||
{100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"},
|
|
||||||
{200, &AppletAE::OpenLibraryAppletProxyOld, "OpenLibraryAppletProxyOld"},
|
|
||||||
{201, &AppletAE::OpenLibraryAppletProxy, "OpenLibraryAppletProxy"},
|
|
||||||
{300, nullptr, "OpenOverlayAppletProxy"},
|
|
||||||
{350, nullptr, "OpenSystemApplicationProxy"},
|
|
||||||
{400, nullptr, "CreateSelfLibraryAppletCreatorForDevelop"},
|
|
||||||
{410, nullptr, "GetSystemAppletControllerForDebug"},
|
|
||||||
{1000, nullptr, "GetDebugFunctions"},
|
|
||||||
};
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
RegisterHandlers(functions);
|
|
||||||
}
|
|
||||||
|
|
||||||
AppletAE::~AppletAE() = default;
|
|
||||||
|
|
||||||
void AppletAE::OpenSystemAppletProxy(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
if (const auto applet = GetAppletFromContext(ctx)) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<ISystemAppletProxy>(nvnflinger, applet, system);
|
|
||||||
} else {
|
|
||||||
UNIMPLEMENTED();
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultUnknown);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletAE::OpenLibraryAppletProxy(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
if (const auto applet = GetAppletFromContext(ctx)) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<ILibraryAppletProxy>(nvnflinger, applet, system);
|
|
||||||
} else {
|
|
||||||
UNIMPLEMENTED();
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultUnknown);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletAE::OpenLibraryAppletProxyOld(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
return OpenLibraryAppletProxy(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<Applet> AppletAE::GetAppletFromContext(HLERequestContext& ctx) {
|
|
||||||
const auto aruid = ctx.GetPID();
|
|
||||||
return system.GetAppletManager().GetByAppletResourceUserId(aruid);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
|
@ -1,39 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "core/hle/service/service.h"
|
|
||||||
|
|
||||||
namespace Service {
|
|
||||||
namespace FileSystem {
|
|
||||||
class FileSystemController;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Nvnflinger {
|
|
||||||
class Nvnflinger;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace AM {
|
|
||||||
|
|
||||||
struct Applet;
|
|
||||||
|
|
||||||
class AppletAE final : public ServiceFramework<AppletAE> {
|
|
||||||
public:
|
|
||||||
explicit AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_);
|
|
||||||
~AppletAE() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void OpenSystemAppletProxy(HLERequestContext& ctx);
|
|
||||||
void OpenLibraryAppletProxy(HLERequestContext& ctx);
|
|
||||||
void OpenLibraryAppletProxyOld(HLERequestContext& ctx);
|
|
||||||
|
|
||||||
std::shared_ptr<Applet> GetAppletFromContext(HLERequestContext& ctx);
|
|
||||||
|
|
||||||
Nvnflinger::Nvnflinger& nvnflinger;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace AM
|
|
||||||
} // namespace Service
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "core/hle/service/am/frontend/applet_controller.h"
|
#include "core/hle/service/am/frontend/applet_controller.h"
|
||||||
#include "core/hle/service/am/frontend/applet_mii_edit_types.h"
|
#include "core/hle/service/am/frontend/applet_mii_edit_types.h"
|
||||||
#include "core/hle/service/am/frontend/applet_software_keyboard_types.h"
|
#include "core/hle/service/am/frontend/applet_software_keyboard_types.h"
|
||||||
|
#include "core/hle/service/am/service/storage.h"
|
||||||
#include "hid_core/hid_types.h"
|
#include "hid_core/hid_types.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
@ -303,8 +304,8 @@ void AppletManager::CreateAndInsertByFrontendAppletParameters(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Applet was started by frontend, so it is foreground.
|
// Applet was started by frontend, so it is foreground.
|
||||||
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
|
applet->message_queue.PushMessage(AppletMessage::ChangeIntoForeground);
|
||||||
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
applet->message_queue.PushMessage(AppletMessage::FocusStateChanged);
|
||||||
applet->focus_state = FocusState::InFocus;
|
applet->focus_state = FocusState::InFocus;
|
||||||
|
|
||||||
this->InsertApplet(std::move(applet));
|
this->InsertApplet(std::move(applet));
|
||||||
|
|
|
@ -33,7 +33,7 @@ void AppletMessageQueue::PushMessage(AppletMessage msg) {
|
||||||
on_new_message->Signal();
|
on_new_message->Signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() {
|
AppletMessage AppletMessageQueue::PopMessage() {
|
||||||
std::scoped_lock lk{lock};
|
std::scoped_lock lk{lock};
|
||||||
if (messages.empty()) {
|
if (messages.empty()) {
|
||||||
on_new_message->Clear();
|
on_new_message->Clear();
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
|
#include "core/hle/service/am/am_types.h"
|
||||||
#include "core/hle/service/kernel_helpers.h"
|
#include "core/hle/service/kernel_helpers.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
@ -16,40 +17,6 @@ namespace Service::AM {
|
||||||
|
|
||||||
class AppletMessageQueue {
|
class AppletMessageQueue {
|
||||||
public:
|
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);
|
explicit AppletMessageQueue(Core::System& system);
|
||||||
~AppletMessageQueue();
|
~AppletMessageQueue();
|
||||||
|
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "core/hle/service/am/am.h"
|
|
||||||
#include "core/hle/service/am/applet_manager.h"
|
|
||||||
#include "core/hle/service/am/applet_oe.h"
|
|
||||||
#include "core/hle/service/am/application_proxy.h"
|
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
|
||||||
|
|
||||||
namespace Service::AM {
|
|
||||||
|
|
||||||
AppletOE::AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_)
|
|
||||||
: ServiceFramework{system_, "appletOE"}, nvnflinger{nvnflinger_} {
|
|
||||||
static const FunctionInfo functions[] = {
|
|
||||||
{0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"},
|
|
||||||
};
|
|
||||||
RegisterHandlers(functions);
|
|
||||||
}
|
|
||||||
|
|
||||||
AppletOE::~AppletOE() = default;
|
|
||||||
|
|
||||||
void AppletOE::OpenApplicationProxy(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
if (const auto applet = GetAppletFromContext(ctx)) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IApplicationProxy>(nvnflinger, applet, system);
|
|
||||||
} else {
|
|
||||||
UNIMPLEMENTED();
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultUnknown);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<Applet> AppletOE::GetAppletFromContext(HLERequestContext& ctx) {
|
|
||||||
const auto aruid = ctx.GetPID();
|
|
||||||
return system.GetAppletManager().GetByAppletResourceUserId(aruid);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
|
@ -1,37 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "core/hle/service/service.h"
|
|
||||||
|
|
||||||
namespace Service {
|
|
||||||
namespace FileSystem {
|
|
||||||
class FileSystemController;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Nvnflinger {
|
|
||||||
class Nvnflinger;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace AM {
|
|
||||||
|
|
||||||
struct Applet;
|
|
||||||
|
|
||||||
class AppletOE final : public ServiceFramework<AppletOE> {
|
|
||||||
public:
|
|
||||||
explicit AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_);
|
|
||||||
~AppletOE() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void OpenApplicationProxy(HLERequestContext& ctx);
|
|
||||||
|
|
||||||
std::shared_ptr<Applet> GetAppletFromContext(HLERequestContext& ctx);
|
|
||||||
|
|
||||||
Nvnflinger::Nvnflinger& nvnflinger;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace AM
|
|
||||||
} // namespace Service
|
|
|
@ -1,594 +0,0 @@
|
||||||
// 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/applet.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,
|
|
||||||
};
|
|
||||||
|
|
||||||
IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet_)
|
|
||||||
: ServiceFramework{system_, "IApplicationFunctions"}, applet{std::move(applet_)} {
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
IApplicationFunctions::~IApplicationFunctions() = default;
|
|
||||||
|
|
||||||
void IApplicationFunctions::EnableApplicationCrashReport(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->application_crash_report_enabled = true;
|
|
||||||
|
|
||||||
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");
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->home_button_long_pressed_blocked = true;
|
|
||||||
applet->home_button_short_pressed_blocked = true;
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->home_button_long_pressed_blocked = false;
|
|
||||||
applet->home_button_short_pressed_blocked = false;
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IApplicationFunctions::BeginBlockingHomeButton(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->home_button_long_pressed_blocked = true;
|
|
||||||
applet->home_button_short_pressed_blocked = true;
|
|
||||||
applet->home_button_double_click_enabled = true;
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IApplicationFunctions::EndBlockingHomeButton(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->home_button_long_pressed_blocked = false;
|
|
||||||
applet->home_button_short_pressed_blocked = false;
|
|
||||||
applet->home_button_double_click_enabled = false;
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
|
|
||||||
auto& channel = kind == LaunchParameterKind::UserChannel
|
|
||||||
? applet->user_channel_launch_parameter
|
|
||||||
: applet->preselected_user_launch_parameter;
|
|
||||||
|
|
||||||
if (channel.empty()) {
|
|
||||||
LOG_WARNING(Service_AM, "Attempted to pop parameter {} but none was found!", kind);
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = applet->program_id;
|
|
||||||
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);
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->terminate_result = Result(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 FileSys::PatchManager pm{applet->program_id, system.GetFileSystemController(),
|
|
||||||
system.GetContentProvider()};
|
|
||||||
auto metadata = pm.GetControlMetadata();
|
|
||||||
if (metadata.first != nullptr) {
|
|
||||||
return metadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(applet->program_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 FileSys::PatchManager pm{applet->program_id, system.GetFileSystemController(),
|
|
||||||
system.GetContentProvider()};
|
|
||||||
auto metadata = pm.GetControlMetadata();
|
|
||||||
if (metadata.first != nullptr) {
|
|
||||||
return metadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(applet->program_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");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.Push(applet->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::RequestParser rp{ctx};
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->gameplay_recording_state = rp.PopRaw<GameplayRecordingState>();
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IApplicationFunctions::NotifyRunning(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->is_running = true;
|
|
||||||
|
|
||||||
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, applet->program_id, 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, applet->program_id, 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);
|
|
||||||
|
|
||||||
// Swap user channel ownership into the system so that it will be preserved
|
|
||||||
system.GetUserChannel().swap(applet->user_channel_launch_parameter);
|
|
||||||
system.ExecuteProgram(program_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
applet->user_channel_launch_parameter.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) {
|
|
||||||
applet->user_channel_launch_parameter.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>(applet->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(applet->gpu_error_detected_event.GetHandle());
|
|
||||||
}
|
|
||||||
|
|
||||||
void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushCopyObjects(applet->friend_invitation_storage_channel_event.GetHandle());
|
|
||||||
}
|
|
||||||
|
|
||||||
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(applet->notification_storage_channel_event.GetHandle());
|
|
||||||
}
|
|
||||||
|
|
||||||
void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushCopyObjects(applet->health_warning_disappeared_system_event.GetHandle());
|
|
||||||
}
|
|
||||||
|
|
||||||
void IApplicationFunctions::PrepareForJit(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->jit_service_launched = true;
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
|
@ -1,58 +0,0 @@
|
||||||
// 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 {
|
|
||||||
|
|
||||||
struct Applet;
|
|
||||||
|
|
||||||
class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
|
|
||||||
public:
|
|
||||||
explicit IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet_);
|
|
||||||
~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);
|
|
||||||
|
|
||||||
const std::shared_ptr<Applet> applet;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
|
@ -1,115 +0,0 @@
|
||||||
// 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<Applet> applet_, Core::System& system_)
|
|
||||||
: ServiceFramework{system_, "IApplicationProxy"}, nvnflinger{nvnflinger_}, applet{std::move(
|
|
||||||
applet_)} {
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
IApplicationProxy::~IApplicationProxy() = default;
|
|
||||||
|
|
||||||
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, applet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IApplicationProxy::GetProcessWindingController(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IProcessWindingController>(system, applet);
|
|
||||||
}
|
|
||||||
|
|
||||||
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, applet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IApplicationProxy::GetSelfController(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<ISelfController>(system, applet, 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, applet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IApplicationProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<ILibraryAppletCreator>(system, applet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IApplicationProxy::GetApplicationFunctions(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IApplicationFunctions>(system, applet);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
|
@ -1,33 +0,0 @@
|
||||||
// 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 {
|
|
||||||
|
|
||||||
struct Applet;
|
|
||||||
|
|
||||||
class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
|
|
||||||
public:
|
|
||||||
explicit IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
|
||||||
std::shared_ptr<Applet> msg_queue_, Core::System& system_);
|
|
||||||
~IApplicationProxy();
|
|
||||||
|
|
||||||
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<Applet> applet;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
|
@ -1,91 +0,0 @@
|
||||||
// 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
|
|
|
@ -1,36 +0,0 @@
|
||||||
// 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
|
|
|
@ -1,314 +0,0 @@
|
||||||
// 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/applet.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<Applet> applet_)
|
|
||||||
: ServiceFramework{system_, "ICommonStateGetter"}, applet{std::move(applet_)} {
|
|
||||||
// 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, &ICommonStateGetter::GetAppletLaunchedHistory, "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);
|
|
||||||
}
|
|
||||||
|
|
||||||
ICommonStateGetter::~ICommonStateGetter() = default;
|
|
||||||
|
|
||||||
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, "(STUBBED) called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushCopyObjects(applet->message_queue.GetMessageReceiveEvent());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ICommonStateGetter::ReceiveMessage(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
const auto message = applet->message_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");
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.Push(static_cast<u8>(applet->focus_state));
|
|
||||||
}
|
|
||||||
|
|
||||||
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.
|
|
||||||
applet->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(applet->sleep_lock_event.GetHandle());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.Push(applet->vr_mode_enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ICommonStateGetter::SetVrModeEnabled(HLERequestContext& ctx) {
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->vr_mode_enabled = rp.Pop<bool>();
|
|
||||||
LOG_WARNING(Service_AM, "VR Mode is {}", applet->vr_mode_enabled ? "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");
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->vr_mode_enabled = true;
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ICommonStateGetter::EndVrModeEx(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->vr_mode_enabled = false;
|
|
||||||
|
|
||||||
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(applet->message_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::GetAppletLaunchedHistory(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
std::shared_ptr<Applet> current_applet = applet;
|
|
||||||
std::vector<AppletId> result;
|
|
||||||
|
|
||||||
const size_t count = ctx.GetWriteBufferNumElements<AppletId>();
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < count && current_applet != nullptr; i++) {
|
|
||||||
result.push_back(current_applet->applet_id);
|
|
||||||
current_applet = current_applet->caller_applet.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.WriteBuffer(result);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.Push(static_cast<u32>(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
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");
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->request_exit_to_library_applet_at_execute_next_program_enabled = true;
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
|
@ -1,77 +0,0 @@
|
||||||
// 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 {
|
|
||||||
|
|
||||||
struct Applet;
|
|
||||||
|
|
||||||
class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
|
|
||||||
public:
|
|
||||||
explicit ICommonStateGetter(Core::System& system_, std::shared_ptr<Applet> applet_);
|
|
||||||
~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 GetAppletLaunchedHistory(HLERequestContext& ctx);
|
|
||||||
void GetSettingsPlatformRegion(HLERequestContext& ctx);
|
|
||||||
void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx);
|
|
||||||
|
|
||||||
const std::shared_ptr<Applet> applet;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
|
@ -1,135 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "core/hle/service/am/applet.h"
|
|
||||||
#include "core/hle/service/am/display_controller.h"
|
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
|
||||||
|
|
||||||
namespace Service::AM {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
struct OutputParameters {
|
|
||||||
bool was_written;
|
|
||||||
s32 fbshare_layer_index;
|
|
||||||
};
|
|
||||||
|
|
||||||
static_assert(sizeof(OutputParameters) == 8, "OutputParameters has wrong size");
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
IDisplayController::IDisplayController(Core::System& system_, std::shared_ptr<Applet> applet_)
|
|
||||||
: ServiceFramework{system_, "IDisplayController"}, applet(std::move(applet_)) {
|
|
||||||
// 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, &IDisplayController::AcquireLastApplicationCaptureSharedBuffer, "AcquireLastApplicationCaptureSharedBuffer"},
|
|
||||||
{23, &IDisplayController::ReleaseLastApplicationCaptureSharedBuffer, "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");
|
|
||||||
|
|
||||||
OutputParameters params{};
|
|
||||||
const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer(
|
|
||||||
¶ms.was_written, ¶ms.fbshare_layer_index);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
|
||||||
rb.Push(res);
|
|
||||||
rb.PushRaw(params);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisplayController::AcquireLastApplicationCaptureSharedBuffer(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
OutputParameters params{};
|
|
||||||
const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer(
|
|
||||||
¶ms.was_written, ¶ms.fbshare_layer_index);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
|
||||||
rb.Push(res);
|
|
||||||
rb.PushRaw(params);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisplayController::ReleaseLastApplicationCaptureSharedBuffer(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");
|
|
||||||
|
|
||||||
OutputParameters params{};
|
|
||||||
const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer(
|
|
||||||
¶ms.was_written, ¶ms.fbshare_layer_index);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
|
||||||
rb.Push(res);
|
|
||||||
rb.PushRaw(params);
|
|
||||||
}
|
|
||||||
|
|
||||||
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");
|
|
||||||
|
|
||||||
OutputParameters params{};
|
|
||||||
const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer(
|
|
||||||
¶ms.was_written, ¶ms.fbshare_layer_index);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
|
||||||
rb.Push(res);
|
|
||||||
rb.PushRaw(params);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisplayController::ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
|
@ -1,30 +0,0 @@
|
||||||
// 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 {
|
|
||||||
|
|
||||||
struct Applet;
|
|
||||||
|
|
||||||
class IDisplayController final : public ServiceFramework<IDisplayController> {
|
|
||||||
public:
|
|
||||||
explicit IDisplayController(Core::System& system_, std::shared_ptr<Applet> applet_);
|
|
||||||
~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);
|
|
||||||
void AcquireLastApplicationCaptureSharedBuffer(HLERequestContext& ctx);
|
|
||||||
void ReleaseLastApplicationCaptureSharedBuffer(HLERequestContext& ctx);
|
|
||||||
|
|
||||||
const std::shared_ptr<Applet> applet;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include "core/hle/kernel/k_readable_event.h"
|
#include "core/hle/kernel/k_readable_event.h"
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
#include "core/hle/service/am/frontend/applet_cabinet.h"
|
#include "core/hle/service/am/frontend/applet_cabinet.h"
|
||||||
#include "core/hle/service/am/storage.h"
|
#include "core/hle/service/am/service/storage.h"
|
||||||
#include "core/hle/service/mii/mii_manager.h"
|
#include "core/hle/service/mii/mii_manager.h"
|
||||||
#include "core/hle/service/nfc/common/device.h"
|
#include "core/hle/service/nfc/common/device.h"
|
||||||
#include "hid_core/hid_core.h"
|
#include "hid_core/hid_core.h"
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
#include "core/hle/service/am/frontend/applet_controller.h"
|
#include "core/hle/service/am/frontend/applet_controller.h"
|
||||||
#include "core/hle/service/am/storage.h"
|
#include "core/hle/service/am/service/storage.h"
|
||||||
#include "hid_core/frontend/emulated_controller.h"
|
#include "hid_core/frontend/emulated_controller.h"
|
||||||
#include "hid_core/hid_core.h"
|
#include "hid_core/hid_core.h"
|
||||||
#include "hid_core/hid_types.h"
|
#include "hid_core/hid_types.h"
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include "core/frontend/applets/error.h"
|
#include "core/frontend/applets/error.h"
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
#include "core/hle/service/am/frontend/applet_error.h"
|
#include "core/hle/service/am/frontend/applet_error.h"
|
||||||
#include "core/hle/service/am/storage.h"
|
#include "core/hle/service/am/service/storage.h"
|
||||||
#include "core/reporter.h"
|
#include "core/reporter.h"
|
||||||
|
|
||||||
namespace Service::AM::Frontend {
|
namespace Service::AM::Frontend {
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
#include "core/hle/service/am/applet_data_broker.h"
|
#include "core/hle/service/am/applet_data_broker.h"
|
||||||
#include "core/hle/service/am/frontend/applet_general.h"
|
#include "core/hle/service/am/frontend/applet_general.h"
|
||||||
#include "core/hle/service/am/storage.h"
|
#include "core/hle/service/am/service/storage.h"
|
||||||
#include "core/reporter.h"
|
#include "core/reporter.h"
|
||||||
|
|
||||||
namespace Service::AM::Frontend {
|
namespace Service::AM::Frontend {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include "core/frontend/applets/mii_edit.h"
|
#include "core/frontend/applets/mii_edit.h"
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
#include "core/hle/service/am/frontend/applet_mii_edit.h"
|
#include "core/hle/service/am/frontend/applet_mii_edit.h"
|
||||||
#include "core/hle/service/am/storage.h"
|
#include "core/hle/service/am/service/storage.h"
|
||||||
#include "core/hle/service/mii/mii.h"
|
#include "core/hle/service/mii/mii.h"
|
||||||
#include "core/hle/service/mii/mii_manager.h"
|
#include "core/hle/service/mii/mii_manager.h"
|
||||||
#include "core/hle/service/sm/sm.h"
|
#include "core/hle/service/sm/sm.h"
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include "core/hle/service/acc/errors.h"
|
#include "core/hle/service/acc/errors.h"
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
#include "core/hle/service/am/frontend/applet_profile_select.h"
|
#include "core/hle/service/am/frontend/applet_profile_select.h"
|
||||||
#include "core/hle/service/am/storage.h"
|
#include "core/hle/service/am/service/storage.h"
|
||||||
|
|
||||||
namespace Service::AM::Frontend {
|
namespace Service::AM::Frontend {
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include "core/frontend/applets/software_keyboard.h"
|
#include "core/frontend/applets/software_keyboard.h"
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
#include "core/hle/service/am/frontend/applet_software_keyboard.h"
|
#include "core/hle/service/am/frontend/applet_software_keyboard.h"
|
||||||
#include "core/hle/service/am/storage.h"
|
#include "core/hle/service/am/service/storage.h"
|
||||||
|
|
||||||
namespace Service::AM::Frontend {
|
namespace Service::AM::Frontend {
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
#include "core/hle/service/am/frontend/applet_web_browser.h"
|
#include "core/hle/service/am/frontend/applet_web_browser.h"
|
||||||
#include "core/hle/service/am/storage.h"
|
#include "core/hle/service/am/service/storage.h"
|
||||||
#include "core/hle/service/filesystem/filesystem.h"
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||||
#include "core/hle/service/ns/iplatform_service_manager.h"
|
#include "core/hle/service/ns/iplatform_service_manager.h"
|
||||||
#include "core/loader/loader.h"
|
#include "core/loader/loader.h"
|
||||||
|
|
|
@ -15,11 +15,8 @@
|
||||||
#include "core/frontend/applets/web_browser.h"
|
#include "core/frontend/applets/web_browser.h"
|
||||||
#include "core/hle/kernel/k_event.h"
|
#include "core/hle/kernel/k_event.h"
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
#include "core/hle/service/am/applet_ae.h"
|
|
||||||
#include "core/hle/service/am/applet_data_broker.h"
|
#include "core/hle/service/am/applet_data_broker.h"
|
||||||
#include "core/hle/service/am/applet_manager.h"
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
#include "core/hle/service/am/applet_message_queue.h"
|
|
||||||
#include "core/hle/service/am/applet_oe.h"
|
|
||||||
#include "core/hle/service/am/frontend/applet_cabinet.h"
|
#include "core/hle/service/am/frontend/applet_cabinet.h"
|
||||||
#include "core/hle/service/am/frontend/applet_controller.h"
|
#include "core/hle/service/am/frontend/applet_controller.h"
|
||||||
#include "core/hle/service/am/frontend/applet_error.h"
|
#include "core/hle/service/am/frontend/applet_error.h"
|
||||||
|
@ -29,7 +26,7 @@
|
||||||
#include "core/hle/service/am/frontend/applet_software_keyboard.h"
|
#include "core/hle/service/am/frontend/applet_software_keyboard.h"
|
||||||
#include "core/hle/service/am/frontend/applet_web_browser.h"
|
#include "core/hle/service/am/frontend/applet_web_browser.h"
|
||||||
#include "core/hle/service/am/frontend/applets.h"
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
#include "core/hle/service/am/storage.h"
|
#include "core/hle/service/am/service/storage.h"
|
||||||
#include "core/hle/service/sm/sm.h"
|
#include "core/hle/service/sm/sm.h"
|
||||||
|
|
||||||
namespace Service::AM::Frontend {
|
namespace Service::AM::Frontend {
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
// 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
|
|
|
@ -1,16 +0,0 @@
|
||||||
// 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
|
|
|
@ -1,57 +0,0 @@
|
||||||
// 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
|
|
|
@ -1,25 +0,0 @@
|
||||||
// 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
|
|
|
@ -1,20 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/service.h"
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
class System;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Service::AM {
|
|
||||||
|
|
||||||
class IdleSys final : public ServiceFramework<IdleSys> {
|
|
||||||
public:
|
|
||||||
explicit IdleSys(Core::System& system_);
|
|
||||||
~IdleSys() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
|
@ -1,202 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "common/scope_exit.h"
|
|
||||||
#include "core/hle/service/am/am_results.h"
|
|
||||||
#include "core/hle/service/am/applet_data_broker.h"
|
|
||||||
#include "core/hle/service/am/frontend/applets.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<AppletDataBroker> broker_,
|
|
||||||
std::shared_ptr<Applet> applet_)
|
|
||||||
: ServiceFramework{system_, "ILibraryAppletAccessor"}, broker{std::move(broker_)},
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
ILibraryAppletAccessor::~ILibraryAppletAccessor() = default;
|
|
||||||
|
|
||||||
void ILibraryAppletAccessor::GetAppletStateChangedEvent(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushCopyObjects(broker->GetStateChangedEvent().GetHandle());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletAccessor::IsCompleted(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.Push<u32>(broker->IsCompleted());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletAccessor::GetResult(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(applet->terminate_result);
|
|
||||||
}
|
|
||||||
|
|
||||||
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");
|
|
||||||
|
|
||||||
applet->process->Run();
|
|
||||||
FrontendExecute();
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletAccessor::RequestExit(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
ASSERT(applet != nullptr);
|
|
||||||
applet->message_queue.RequestExit();
|
|
||||||
FrontendRequestExit();
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletAccessor::PushInData(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
broker->GetInData().Push(rp.PopIpcInterface<IStorage>().lock());
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletAccessor::PopOutData(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
std::shared_ptr<IStorage> data;
|
|
||||||
const auto res = broker->GetOutData().Pop(&data);
|
|
||||||
|
|
||||||
if (res.IsSuccess()) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(res);
|
|
||||||
rb.PushIpcInterface(std::move(data));
|
|
||||||
} else {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletAccessor::PushInteractiveInData(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
broker->GetInteractiveInData().Push(rp.PopIpcInterface<IStorage>().lock());
|
|
||||||
FrontendExecuteInteractive();
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletAccessor::PopInteractiveOutData(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
std::shared_ptr<IStorage> data;
|
|
||||||
const auto res = broker->GetInteractiveOutData().Pop(&data);
|
|
||||||
|
|
||||||
if (res.IsSuccess()) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(res);
|
|
||||||
rb.PushIpcInterface(std::move(data));
|
|
||||||
} else {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletAccessor::GetPopOutDataEvent(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushCopyObjects(broker->GetOutData().GetEvent());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletAccessor::GetPopInteractiveOutDataEvent(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushCopyObjects(broker->GetInteractiveOutData().GetEvent());
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletAccessor::FrontendExecute() {
|
|
||||||
if (applet->frontend) {
|
|
||||||
applet->frontend->Initialize();
|
|
||||||
applet->frontend->Execute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletAccessor::FrontendExecuteInteractive() {
|
|
||||||
if (applet->frontend) {
|
|
||||||
applet->frontend->ExecuteInteractive();
|
|
||||||
applet->frontend->Execute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletAccessor::FrontendRequestExit() {
|
|
||||||
if (applet->frontend) {
|
|
||||||
applet->frontend->RequestExit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
|
@ -1,43 +0,0 @@
|
||||||
// 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 AppletDataBroker;
|
|
||||||
struct Applet;
|
|
||||||
|
|
||||||
class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
|
|
||||||
public:
|
|
||||||
explicit ILibraryAppletAccessor(Core::System& system_,
|
|
||||||
std::shared_ptr<AppletDataBroker> broker_,
|
|
||||||
std::shared_ptr<Applet> applet_);
|
|
||||||
~ILibraryAppletAccessor();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
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);
|
|
||||||
|
|
||||||
void FrontendExecute();
|
|
||||||
void FrontendExecuteInteractive();
|
|
||||||
void FrontendRequestExit();
|
|
||||||
|
|
||||||
const std::shared_ptr<AppletDataBroker> broker;
|
|
||||||
const std::shared_ptr<Applet> applet;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
|
@ -1,26 +0,0 @@
|
||||||
// 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 {
|
|
||||||
|
|
||||||
struct Applet;
|
|
||||||
|
|
||||||
class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
|
|
||||||
public:
|
|
||||||
explicit ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet_);
|
|
||||||
~ILibraryAppletCreator() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void CreateLibraryApplet(HLERequestContext& ctx);
|
|
||||||
void CreateStorage(HLERequestContext& ctx);
|
|
||||||
void CreateTransferMemoryStorage(HLERequestContext& ctx);
|
|
||||||
void CreateHandleStorage(HLERequestContext& ctx);
|
|
||||||
|
|
||||||
const std::shared_ptr<Applet> applet;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
|
@ -1,143 +0,0 @@
|
||||||
// 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<Applet> applet_, Core::System& system_)
|
|
||||||
: ServiceFramework{system_, "ILibraryAppletProxy"}, nvnflinger{nvnflinger_}, applet{std::move(
|
|
||||||
applet_)} {
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
ILibraryAppletProxy::~ILibraryAppletProxy() = default;
|
|
||||||
|
|
||||||
void ILibraryAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<ICommonStateGetter>(system, applet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletProxy::GetSelfController(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<ISelfController>(system, applet, 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, applet);
|
|
||||||
}
|
|
||||||
|
|
||||||
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, applet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletProxy::GetProcessWindingController(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IProcessWindingController>(system, applet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<ILibraryAppletCreator>(system, applet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletProxy::OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system, applet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IAppletCommonFunctions>(system, applet);
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
|
@ -1,36 +0,0 @@
|
||||||
// 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 {
|
|
||||||
|
|
||||||
struct Applet;
|
|
||||||
|
|
||||||
class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
|
|
||||||
public:
|
|
||||||
explicit ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
|
||||||
std::shared_ptr<Applet> applet_, Core::System& system_);
|
|
||||||
~ILibraryAppletProxy();
|
|
||||||
|
|
||||||
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<Applet> applet;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
|
@ -1,338 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "common/scope_exit.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/hle/service/acc/profile_manager.h"
|
|
||||||
#include "core/hle/service/am/am_results.h"
|
|
||||||
#include "core/hle/service/am/applet_data_broker.h"
|
|
||||||
#include "core/hle/service/am/applet_manager.h"
|
|
||||||
#include "core/hle/service/am/frontend/applet_cabinet.h"
|
|
||||||
#include "core/hle/service/am/frontend/applet_controller.h"
|
|
||||||
#include "core/hle/service/am/frontend/applet_mii_edit_types.h"
|
|
||||||
#include "core/hle/service/am/frontend/applet_software_keyboard_types.h"
|
|
||||||
#include "core/hle/service/am/frontend/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 "core/hle/service/ns/ns.h"
|
|
||||||
#include "core/hle/service/sm/sm.h"
|
|
||||||
#include "hid_core/hid_types.h"
|
|
||||||
|
|
||||||
namespace Service::AM {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
AppletIdentityInfo GetCallerIdentity(std::shared_ptr<Applet> applet) {
|
|
||||||
if (const auto caller_applet = applet->caller_applet.lock(); caller_applet) {
|
|
||||||
// TODO: is this actually the application ID?
|
|
||||||
return {
|
|
||||||
.applet_id = caller_applet->applet_id,
|
|
||||||
.application_id = caller_applet->program_id,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
.applet_id = AppletId::QLaunch,
|
|
||||||
.application_id = 0x0100000000001000ull,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_,
|
|
||||||
std::shared_ptr<Applet> applet_)
|
|
||||||
: ServiceFramework{system_, "ILibraryAppletSelfAccessor"}, applet{std::move(applet_)},
|
|
||||||
broker{applet->caller_applet_broker} {
|
|
||||||
// clang-format off
|
|
||||||
static const FunctionInfo functions[] = {
|
|
||||||
{0, &ILibraryAppletSelfAccessor::PopInData, "PopInData"},
|
|
||||||
{1, &ILibraryAppletSelfAccessor::PushOutData, "PushOutData"},
|
|
||||||
{2, &ILibraryAppletSelfAccessor::PopInteractiveInData, "PopInteractiveInData"},
|
|
||||||
{3, &ILibraryAppletSelfAccessor::PushInteractiveOutData, "PushInteractiveOutData"},
|
|
||||||
{5, &ILibraryAppletSelfAccessor::GetPopInDataEvent, "GetPopInDataEvent"},
|
|
||||||
{6, &ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent, "GetPopInteractiveInDataEvent"},
|
|
||||||
{10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"},
|
|
||||||
{11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"},
|
|
||||||
{12, &ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo, "GetMainAppletIdentityInfo"},
|
|
||||||
{13, &ILibraryAppletSelfAccessor::CanUseApplicationCore, "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, &ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage, "GetMainAppletApplicationDesiredLanguage"},
|
|
||||||
{70, &ILibraryAppletSelfAccessor::GetCurrentApplicationId, "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"},
|
|
||||||
{160, &ILibraryAppletSelfAccessor::Cmd160, "Cmd160"},
|
|
||||||
};
|
|
||||||
// clang-format on
|
|
||||||
RegisterHandlers(functions);
|
|
||||||
}
|
|
||||||
|
|
||||||
ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default;
|
|
||||||
|
|
||||||
void ILibraryAppletSelfAccessor::PopInData(HLERequestContext& ctx) {
|
|
||||||
LOG_INFO(Service_AM, "called");
|
|
||||||
|
|
||||||
std::shared_ptr<IStorage> data;
|
|
||||||
const auto res = broker->GetInData().Pop(&data);
|
|
||||||
|
|
||||||
if (res.IsSuccess()) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(res);
|
|
||||||
rb.PushIpcInterface(std::move(data));
|
|
||||||
} else {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletSelfAccessor::PushOutData(HLERequestContext& ctx) {
|
|
||||||
LOG_INFO(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
broker->GetOutData().Push(rp.PopIpcInterface<IStorage>().lock());
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletSelfAccessor::PopInteractiveInData(HLERequestContext& ctx) {
|
|
||||||
LOG_INFO(Service_AM, "called");
|
|
||||||
|
|
||||||
std::shared_ptr<IStorage> data;
|
|
||||||
const auto res = broker->GetInteractiveInData().Pop(&data);
|
|
||||||
|
|
||||||
if (res.IsSuccess()) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(res);
|
|
||||||
rb.PushIpcInterface(std::move(data));
|
|
||||||
} else {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletSelfAccessor::PushInteractiveOutData(HLERequestContext& ctx) {
|
|
||||||
LOG_INFO(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
broker->GetInteractiveOutData().Push(rp.PopIpcInterface<IStorage>().lock());
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletSelfAccessor::GetPopInDataEvent(HLERequestContext& ctx) {
|
|
||||||
LOG_INFO(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushCopyObjects(broker->GetInData().GetEvent());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent(HLERequestContext& ctx) {
|
|
||||||
LOG_INFO(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushCopyObjects(broker->GetInteractiveInData().GetEvent());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletSelfAccessor::ExitProcessAndReturn(HLERequestContext& ctx) {
|
|
||||||
LOG_INFO(Service_AM, "called");
|
|
||||||
|
|
||||||
system.GetAppletManager().TerminateAndRemoveApplet(applet->aruid);
|
|
||||||
broker->SignalCompletion();
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) {
|
|
||||||
struct LibraryAppletInfo {
|
|
||||||
AppletId applet_id;
|
|
||||||
LibraryAppletMode library_applet_mode;
|
|
||||||
};
|
|
||||||
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
const LibraryAppletInfo applet_info{
|
|
||||||
.applet_id = applet->applet_id,
|
|
||||||
.library_applet_mode = applet->library_applet_mode,
|
|
||||||
};
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushRaw(applet_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
const AppletIdentityInfo applet_info{
|
|
||||||
.applet_id = AppletId::QLaunch,
|
|
||||||
.application_id = 0x0100000000001000ull,
|
|
||||||
};
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 6};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushRaw(applet_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletSelfAccessor::CanUseApplicationCore(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
// TODO: This appears to read the NPDM from state and check the core mask of the applet.
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.Push<u8>(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 6};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushRaw(GetCallerIdentity(applet));
|
|
||||||
}
|
|
||||||
|
|
||||||
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::GetMainAppletApplicationDesiredLanguage(HLERequestContext& ctx) {
|
|
||||||
// FIXME: this is copied from IApplicationFunctions::GetDesiredLanguage
|
|
||||||
auto identity = GetCallerIdentity(applet);
|
|
||||||
|
|
||||||
// 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, identity] {
|
|
||||||
const FileSys::PatchManager pm{identity.application_id, system.GetFileSystemController(),
|
|
||||||
system.GetContentProvider()};
|
|
||||||
auto metadata = pm.GetControlMetadata();
|
|
||||||
if (metadata.first != nullptr) {
|
|
||||||
return metadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(identity.application_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 ILibraryAppletSelfAccessor::GetCurrentApplicationId(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
u64 application_id = 0;
|
|
||||||
if (auto caller_applet = applet->caller_applet.lock(); caller_applet) {
|
|
||||||
application_id = caller_applet->program_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.Push(application_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
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::Cmd160(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.Push<u64>(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
|
@ -1,44 +0,0 @@
|
||||||
// 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 AppletDataBroker;
|
|
||||||
struct Applet;
|
|
||||||
|
|
||||||
class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> {
|
|
||||||
public:
|
|
||||||
explicit ILibraryAppletSelfAccessor(Core::System& system_, std::shared_ptr<Applet> applet_);
|
|
||||||
~ILibraryAppletSelfAccessor() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void PopInData(HLERequestContext& ctx);
|
|
||||||
void PushOutData(HLERequestContext& ctx);
|
|
||||||
void PopInteractiveInData(HLERequestContext& ctx);
|
|
||||||
void PushInteractiveOutData(HLERequestContext& ctx);
|
|
||||||
void GetPopInDataEvent(HLERequestContext& ctx);
|
|
||||||
void GetPopInteractiveInDataEvent(HLERequestContext& ctx);
|
|
||||||
void GetLibraryAppletInfo(HLERequestContext& ctx);
|
|
||||||
void GetMainAppletIdentityInfo(HLERequestContext& ctx);
|
|
||||||
void CanUseApplicationCore(HLERequestContext& ctx);
|
|
||||||
void ExitProcessAndReturn(HLERequestContext& ctx);
|
|
||||||
void GetCallerAppletIdentityInfo(HLERequestContext& ctx);
|
|
||||||
void GetDesirableKeyboardLayout(HLERequestContext& ctx);
|
|
||||||
void GetMainAppletApplicationDesiredLanguage(HLERequestContext& ctx);
|
|
||||||
void GetCurrentApplicationId(HLERequestContext& ctx);
|
|
||||||
void GetMainAppletAvailableUsers(HLERequestContext& ctx);
|
|
||||||
void ShouldSetGpuTimeSliceManually(HLERequestContext& ctx);
|
|
||||||
void Cmd160(HLERequestContext& ctx);
|
|
||||||
|
|
||||||
const std::shared_ptr<Applet> applet;
|
|
||||||
const std::shared_ptr<AppletDataBroker> broker;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
|
@ -1,71 +0,0 @@
|
||||||
// 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
|
|
|
@ -1,28 +0,0 @@
|
||||||
// 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
|
|
|
@ -1,20 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/service.h"
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
class System;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Service::AM {
|
|
||||||
|
|
||||||
class OMM final : public ServiceFramework<OMM> {
|
|
||||||
public:
|
|
||||||
explicit OMM(Core::System& system_);
|
|
||||||
~OMM() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
|
@ -1,56 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "core/hle/service/am/frontend/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_,
|
|
||||||
std::shared_ptr<Applet> applet_)
|
|
||||||
: ServiceFramework{system_, "IProcessWindingController"}, applet{std::move(applet_)} {
|
|
||||||
// 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");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushRaw(applet->launch_reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) {
|
|
||||||
const auto caller_applet = applet->caller_applet.lock();
|
|
||||||
if (caller_applet == nullptr) {
|
|
||||||
LOG_ERROR(Service_AM, "No calling applet available");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultUnknown);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet->caller_applet_broker,
|
|
||||||
caller_applet);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
|
@ -1,470 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "common/logging/log.h"
|
|
||||||
#include "core/hle/result.h"
|
|
||||||
#include "core/hle/service/am/am_results.h"
|
|
||||||
#include "core/hle/service/am/frontend/applets.h"
|
|
||||||
#include "core/hle/service/am/self_controller.h"
|
|
||||||
#include "core/hle/service/caps/caps_su.h"
|
|
||||||
#include "core/hle/service/hle_ipc.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_, std::shared_ptr<Applet> applet_,
|
|
||||||
Nvnflinger::Nvnflinger& nvnflinger_)
|
|
||||||
: ServiceFramework{system_, "ISelfController"}, nvnflinger{nvnflinger_}, applet{std::move(
|
|
||||||
applet_)} {
|
|
||||||
// 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, &ISelfController::SetScreenShotAppletIdentityInfo, "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, &ISelfController::SetMediaPlaybackState, "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);
|
|
||||||
}
|
|
||||||
|
|
||||||
ISelfController::~ISelfController() = default;
|
|
||||||
|
|
||||||
void ISelfController::Exit(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
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) {
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->fatal_section_count++;
|
|
||||||
LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", applet->fatal_section_count);
|
|
||||||
|
|
||||||
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.
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
if (applet->fatal_section_count == 0) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(AM::ResultFatalSectionCountImbalance);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
applet->fatal_section_count--;
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ISelfController::GetLibraryAppletLaunchableEvent(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
applet->library_applet_launchable_event.Signal();
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushCopyObjects(applet->library_applet_launchable_event.GetHandle());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) {
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
const auto permission = rp.PopEnum<ScreenshotPermission>();
|
|
||||||
LOG_DEBUG(Service_AM, "called, permission={}", permission);
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->screenshot_permission = permission;
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx) {
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
|
|
||||||
const bool notification_enabled = rp.Pop<bool>();
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called notification_enabled={}", notification_enabled);
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->operation_mode_changed_notification_enabled = notification_enabled;
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ISelfController::SetPerformanceModeChangedNotification(HLERequestContext& ctx) {
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
|
|
||||||
const bool notification_enabled = rp.Pop<bool>();
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called notification_enabled={}", notification_enabled);
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->performance_mode_changed_notification_enabled = notification_enabled;
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ISelfController::SetFocusHandlingMode(HLERequestContext& ctx) {
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
|
|
||||||
const auto flags = rp.PopRaw<FocusHandlingMode>();
|
|
||||||
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called. unknown0={}, unknown1={}, unknown2={}",
|
|
||||||
flags.unknown0, flags.unknown1, flags.unknown2);
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->focus_handling_mode = flags;
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ISelfController::SetRestartMessageEnabled(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->restart_message_enabled = true;
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ISelfController::SetScreenShotAppletIdentityInfo(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->screen_shot_identity = rp.PopRaw<AppletIdentityInfo>();
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ISelfController::SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx) {
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
|
|
||||||
const bool enabled = rp.Pop<bool>();
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled);
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
ASSERT(applet->type == AppletType::Application);
|
|
||||||
applet->out_of_focus_suspension_enabled = enabled;
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) {
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
|
|
||||||
const auto orientation = rp.PopRaw<Capture::AlbumImageOrientation>();
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called, orientation={}", static_cast<s32>(orientation));
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->album_image_orientation = orientation;
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ISelfController::CreateManagedDisplayLayer(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
u64 layer_id{};
|
|
||||||
applet->managed_layer_holder.Initialize(&nvnflinger);
|
|
||||||
applet->managed_layer_holder.CreateManagedDisplayLayer(&layer_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");
|
|
||||||
|
|
||||||
u64 buffer_id, layer_id;
|
|
||||||
applet->system_buffer_manager.GetSystemSharedLayerHandle(&buffer_id, &layer_id);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 6};
|
|
||||||
rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess()));
|
|
||||||
rb.Push<s64>(buffer_id);
|
|
||||||
rb.Push<s64>(layer_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
u64 buffer_id, layer_id;
|
|
||||||
applet->system_buffer_manager.GetSystemSharedLayerHandle(&buffer_id, &layer_id);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
|
||||||
rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess()));
|
|
||||||
rb.Push<s64>(buffer_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result ISelfController::EnsureBufferSharingEnabled(Kernel::KProcess* process) {
|
|
||||||
if (applet->system_buffer_manager.Initialize(&nvnflinger, process, applet->applet_id,
|
|
||||||
applet->library_applet_mode)) {
|
|
||||||
return ResultSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
return VI::ResultOperationFailed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
u64 layer_id{};
|
|
||||||
u64 recording_layer_id{};
|
|
||||||
applet->managed_layer_holder.Initialize(&nvnflinger);
|
|
||||||
applet->managed_layer_holder.CreateManagedDisplaySeparableLayer(&layer_id, &recording_layer_id);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 6};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.Push(layer_id);
|
|
||||||
rb.Push(recording_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::SetMediaPlaybackState(HLERequestContext& ctx) {
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
const u8 state = rp.Pop<u8>();
|
|
||||||
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called, state={}", state);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) {
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
|
|
||||||
const auto extension = rp.PopRaw<IdleTimeDetectionExtension>();
|
|
||||||
LOG_DEBUG(Service_AM, "(STUBBED) called extension={}", extension);
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->idle_time_detection_extension = extension;
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ISelfController::GetIdleTimeDetectionExtension(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushRaw<IdleTimeDetectionExtension>(applet->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};
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->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={}", applet->auto_sleep_disabled);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ISelfController::IsAutoSleepDisabled(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called.");
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.Push(applet->auto_sleep_disabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ISelfController::GetAccumulatedSuspendedTickValue(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called.");
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
// 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>(applet->suspended_ticks);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called.");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushCopyObjects(applet->accumulated_suspended_tick_changed_event.GetHandle());
|
|
||||||
}
|
|
||||||
|
|
||||||
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 enabled = rp.Pop<bool>();
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called. enabled={}", enabled);
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->album_image_taken_notification_enabled = 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 enabled = rp.Pop<bool>();
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called. enabled={}", enabled);
|
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->record_volume_muted = enabled;
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
|
@ -1,60 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/hle_ipc.h"
|
|
||||||
#include "core/hle/service/kernel_helpers.h"
|
|
||||||
#include "core/hle/service/service.h"
|
|
||||||
|
|
||||||
namespace Service::AM {
|
|
||||||
|
|
||||||
struct Applet;
|
|
||||||
|
|
||||||
class ISelfController final : public ServiceFramework<ISelfController> {
|
|
||||||
public:
|
|
||||||
explicit ISelfController(Core::System& system_, std::shared_ptr<Applet> applet_,
|
|
||||||
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 SetScreenShotAppletIdentityInfo(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 SetMediaPlaybackState(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);
|
|
||||||
|
|
||||||
Nvnflinger::Nvnflinger& nvnflinger;
|
|
||||||
const std::shared_ptr<Applet> applet;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
|
#include "core/hle/service/am/service/all_system_applet_proxies_service.h"
|
||||||
|
#include "core/hle/service/am/service/library_applet_proxy.h"
|
||||||
|
#include "core/hle/service/am/service/system_applet_proxy.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& system_,
|
||||||
|
Nvnflinger::Nvnflinger& nvnflinger)
|
||||||
|
: ServiceFramework{system_, "appletAE"}, m_nvnflinger{nvnflinger} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{100, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxy>, "OpenSystemAppletProxy"},
|
||||||
|
{200, D<&IAllSystemAppletProxiesService::OpenLibraryAppletProxyOld>, "OpenLibraryAppletProxyOld"},
|
||||||
|
{201, D<&IAllSystemAppletProxiesService::OpenLibraryAppletProxy>, "OpenLibraryAppletProxy"},
|
||||||
|
{300, nullptr, "OpenOverlayAppletProxy"},
|
||||||
|
{350, nullptr, "OpenSystemApplicationProxy"},
|
||||||
|
{400, nullptr, "CreateSelfLibraryAppletCreatorForDevelop"},
|
||||||
|
{410, nullptr, "GetSystemAppletControllerForDebug"},
|
||||||
|
{1000, nullptr, "GetDebugFunctions"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
IAllSystemAppletProxiesService::~IAllSystemAppletProxiesService() = default;
|
||||||
|
|
||||||
|
Result IAllSystemAppletProxiesService::OpenSystemAppletProxy(
|
||||||
|
Out<SharedPointer<ISystemAppletProxy>> out_system_applet_proxy, ClientProcessId pid,
|
||||||
|
InCopyHandle<Kernel::KProcess> process_handle) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
if (const auto applet = this->GetAppletFromProcessId(pid); applet) {
|
||||||
|
*out_system_applet_proxy = std::make_shared<ISystemAppletProxy>(
|
||||||
|
system, applet, process_handle.Get(), m_nvnflinger);
|
||||||
|
R_SUCCEED();
|
||||||
|
} else {
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
R_THROW(ResultUnknown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IAllSystemAppletProxiesService::OpenLibraryAppletProxy(
|
||||||
|
Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy, ClientProcessId pid,
|
||||||
|
InCopyHandle<Kernel::KProcess> process_handle,
|
||||||
|
InLargeData<AppletAttribute, BufferAttr_HipcMapAlias> attribute) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
if (const auto applet = this->GetAppletFromProcessId(pid); applet) {
|
||||||
|
*out_library_applet_proxy = std::make_shared<ILibraryAppletProxy>(
|
||||||
|
system, applet, process_handle.Get(), m_nvnflinger);
|
||||||
|
R_SUCCEED();
|
||||||
|
} else {
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
R_THROW(ResultUnknown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IAllSystemAppletProxiesService::OpenLibraryAppletProxyOld(
|
||||||
|
Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy, ClientProcessId pid,
|
||||||
|
InCopyHandle<Kernel::KProcess> process_handle) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
AppletAttribute attribute{};
|
||||||
|
R_RETURN(
|
||||||
|
this->OpenLibraryAppletProxy(out_library_applet_proxy, pid, process_handle, attribute));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Applet> IAllSystemAppletProxiesService::GetAppletFromProcessId(
|
||||||
|
ProcessId process_id) {
|
||||||
|
return system.GetAppletManager().GetByAppletResourceUserId(process_id.pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,47 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/cmif_types.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service {
|
||||||
|
|
||||||
|
namespace Nvnflinger {
|
||||||
|
class Nvnflinger;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
struct AppletAttribute;
|
||||||
|
class ILibraryAppletProxy;
|
||||||
|
class ISystemAppletProxy;
|
||||||
|
|
||||||
|
class IAllSystemAppletProxiesService final
|
||||||
|
: public ServiceFramework<IAllSystemAppletProxiesService> {
|
||||||
|
public:
|
||||||
|
explicit IAllSystemAppletProxiesService(Core::System& system_,
|
||||||
|
Nvnflinger::Nvnflinger& nvnflinger);
|
||||||
|
~IAllSystemAppletProxiesService() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result OpenSystemAppletProxy(Out<SharedPointer<ISystemAppletProxy>> out_system_applet_proxy,
|
||||||
|
ClientProcessId pid,
|
||||||
|
InCopyHandle<Kernel::KProcess> process_handle);
|
||||||
|
Result OpenLibraryAppletProxy(Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy,
|
||||||
|
ClientProcessId pid,
|
||||||
|
InCopyHandle<Kernel::KProcess> process_handle,
|
||||||
|
InLargeData<AppletAttribute, BufferAttr_HipcMapAlias> attribute);
|
||||||
|
Result OpenLibraryAppletProxyOld(
|
||||||
|
Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy, ClientProcessId pid,
|
||||||
|
InCopyHandle<Kernel::KProcess> process_handle);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid);
|
||||||
|
Nvnflinger::Nvnflinger& m_nvnflinger;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace AM
|
||||||
|
} // namespace Service
|
|
@ -2,8 +2,8 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "core/hle/service/am/applet.h"
|
#include "core/hle/service/am/applet.h"
|
||||||
#include "core/hle/service/am/applet_common_functions.h"
|
#include "core/hle/service/am/service/applet_common_functions.h"
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
|
@ -20,18 +20,18 @@ IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_,
|
||||||
{40, nullptr, "GetDisplayLogicalResolution"},
|
{40, nullptr, "GetDisplayLogicalResolution"},
|
||||||
{42, nullptr, "SetDisplayMagnification"},
|
{42, nullptr, "SetDisplayMagnification"},
|
||||||
{50, nullptr, "SetHomeButtonDoubleClickEnabled"},
|
{50, nullptr, "SetHomeButtonDoubleClickEnabled"},
|
||||||
{51, nullptr, "GetHomeButtonDoubleClickEnabled"},
|
{51, D<&IAppletCommonFunctions::GetHomeButtonDoubleClickEnabled>, "GetHomeButtonDoubleClickEnabled"},
|
||||||
{52, nullptr, "IsHomeButtonShortPressedBlocked"},
|
{52, nullptr, "IsHomeButtonShortPressedBlocked"},
|
||||||
{60, nullptr, "IsVrModeCurtainRequired"},
|
{60, nullptr, "IsVrModeCurtainRequired"},
|
||||||
{61, nullptr, "IsSleepRequiredByHighTemperature"},
|
{61, nullptr, "IsSleepRequiredByHighTemperature"},
|
||||||
{62, nullptr, "IsSleepRequiredByLowBattery"},
|
{62, nullptr, "IsSleepRequiredByLowBattery"},
|
||||||
{70, &IAppletCommonFunctions::SetCpuBoostRequestPriority, "SetCpuBoostRequestPriority"},
|
{70, D<&IAppletCommonFunctions::SetCpuBoostRequestPriority>, "SetCpuBoostRequestPriority"},
|
||||||
{80, nullptr, "SetHandlingCaptureButtonShortPressedMessageEnabledForApplet"},
|
{80, nullptr, "SetHandlingCaptureButtonShortPressedMessageEnabledForApplet"},
|
||||||
{81, nullptr, "SetHandlingCaptureButtonLongPressedMessageEnabledForApplet"},
|
{81, nullptr, "SetHandlingCaptureButtonLongPressedMessageEnabledForApplet"},
|
||||||
{90, nullptr, "OpenNamedChannelAsParent"},
|
{90, nullptr, "OpenNamedChannelAsParent"},
|
||||||
{91, nullptr, "OpenNamedChannelAsChild"},
|
{91, nullptr, "OpenNamedChannelAsChild"},
|
||||||
{100, nullptr, "SetApplicationCoreUsageMode"},
|
{100, nullptr, "SetApplicationCoreUsageMode"},
|
||||||
{300, &IAppletCommonFunctions::GetCurrentApplicationId, "GetCurrentApplicationId"},
|
{300, D<&IAppletCommonFunctions::GetCurrentApplicationId>, "GetCurrentApplicationId"},
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
@ -40,24 +40,24 @@ IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_,
|
||||||
|
|
||||||
IAppletCommonFunctions::~IAppletCommonFunctions() = default;
|
IAppletCommonFunctions::~IAppletCommonFunctions() = default;
|
||||||
|
|
||||||
void IAppletCommonFunctions::SetCpuBoostRequestPriority(HLERequestContext& ctx) {
|
Result IAppletCommonFunctions::GetHomeButtonDoubleClickEnabled(
|
||||||
|
Out<bool> out_home_button_double_click_enabled) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
*out_home_button_double_click_enabled = false;
|
||||||
IPC::RequestParser rp{ctx};
|
R_SUCCEED();
|
||||||
|
|
||||||
std::scoped_lock lk{applet->lock};
|
|
||||||
applet->cpu_boost_request_priority = rp.Pop<s32>();
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IAppletCommonFunctions::GetCurrentApplicationId(HLERequestContext& ctx) {
|
Result IAppletCommonFunctions::SetCpuBoostRequestPriority(s32 priority) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->cpu_boost_request_priority = priority;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
Result IAppletCommonFunctions::GetCurrentApplicationId(Out<u64> out_application_id) {
|
||||||
rb.Push(ResultSuccess);
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
rb.Push<u64>(system.GetApplicationProcessProgramID() & ~0xFFFULL);
|
*out_application_id = system.GetApplicationProcessProgramID() & ~0xFFFULL;
|
||||||
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/cmif_types.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
@ -15,8 +16,9 @@ public:
|
||||||
~IAppletCommonFunctions() override;
|
~IAppletCommonFunctions() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetCpuBoostRequestPriority(HLERequestContext& ctx);
|
Result GetHomeButtonDoubleClickEnabled(Out<bool> out_home_button_double_click_enabled);
|
||||||
void GetCurrentApplicationId(HLERequestContext& ctx);
|
Result SetCpuBoostRequestPriority(s32 priority);
|
||||||
|
Result GetCurrentApplicationId(Out<u64> out_application_id);
|
||||||
|
|
||||||
const std::shared_ptr<Applet> applet;
|
const std::shared_ptr<Applet> applet;
|
||||||
};
|
};
|
138
src/core/hle/service/am/service/application_accessor.cpp
Normal file
138
src/core/hle/service/am/service/application_accessor.cpp
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/result.h"
|
||||||
|
#include "core/hle/service/am/am_types.h"
|
||||||
|
#include "core/hle/service/am/applet.h"
|
||||||
|
#include "core/hle/service/am/applet_data_broker.h"
|
||||||
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
|
#include "core/hle/service/am/service/application_accessor.h"
|
||||||
|
#include "core/hle/service/am/service/library_applet_accessor.h"
|
||||||
|
#include "core/hle/service/am/service/storage.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
IApplicationAccessor::IApplicationAccessor(Core::System& system_, std::shared_ptr<Applet> applet)
|
||||||
|
: ServiceFramework{system_, "IApplicationAccessor"}, m_applet(std::move(applet)) {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, D<&IApplicationAccessor::GetAppletStateChangedEvent>, "GetAppletStateChangedEvent"},
|
||||||
|
{1, nullptr, "IsCompleted"},
|
||||||
|
{10, D<&IApplicationAccessor::Start>, "Start"},
|
||||||
|
{20, D<&IApplicationAccessor::RequestExit>, "RequestExit"},
|
||||||
|
{25, D<&IApplicationAccessor::Terminate>, "Terminate"},
|
||||||
|
{30, D<&IApplicationAccessor::GetResult>, "GetResult"},
|
||||||
|
{101, D<&IApplicationAccessor::RequestForApplicationToGetForeground>, "RequestForApplicationToGetForeground"},
|
||||||
|
{110, nullptr, "TerminateAllLibraryApplets"},
|
||||||
|
{111, nullptr, "AreAnyLibraryAppletsLeft"},
|
||||||
|
{112, D<&IApplicationAccessor::GetCurrentLibraryApplet>, "GetCurrentLibraryApplet"},
|
||||||
|
{120, nullptr, "GetApplicationId"},
|
||||||
|
{121, D<&IApplicationAccessor::PushLaunchParameter>, "PushLaunchParameter"},
|
||||||
|
{122, D<&IApplicationAccessor::GetApplicationControlProperty>, "GetApplicationControlProperty"},
|
||||||
|
{123, nullptr, "GetApplicationLaunchProperty"},
|
||||||
|
{124, nullptr, "GetApplicationLaunchRequestInfo"},
|
||||||
|
{130, D<&IApplicationAccessor::SetUsers>, "SetUsers"},
|
||||||
|
{131, D<&IApplicationAccessor::CheckRightsEnvironmentAvailable>, "CheckRightsEnvironmentAvailable"},
|
||||||
|
{132, D<&IApplicationAccessor::GetNsRightsEnvironmentHandle>, "GetNsRightsEnvironmentHandle"},
|
||||||
|
{140, nullptr, "GetDesirableUids"},
|
||||||
|
{150, D<&IApplicationAccessor::ReportApplicationExitTimeout>, "ReportApplicationExitTimeout"},
|
||||||
|
{160, nullptr, "SetApplicationAttribute"},
|
||||||
|
{170, nullptr, "HasSaveDataAccessPermission"},
|
||||||
|
{180, nullptr, "PushToFriendInvitationStorageChannel"},
|
||||||
|
{190, nullptr, "PushToNotificationStorageChannel"},
|
||||||
|
{200, nullptr, "RequestApplicationSoftReset"},
|
||||||
|
{201, nullptr, "RestartApplicationTimer"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
IApplicationAccessor::~IApplicationAccessor() = default;
|
||||||
|
|
||||||
|
Result IApplicationAccessor::Start() {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
m_applet->process->Run();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationAccessor::RequestExit() {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
m_applet->message_queue.RequestExit();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationAccessor::Terminate() {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
m_applet->process->Terminate();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationAccessor::GetResult() {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationAccessor::GetAppletStateChangedEvent(
|
||||||
|
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
*out_event = m_applet->caller_applet_broker->GetStateChangedEvent().GetHandle();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationAccessor::PushLaunchParameter(LaunchParameterKind kind,
|
||||||
|
SharedPointer<IStorage> storage) {
|
||||||
|
LOG_INFO(Service_AM, "called, kind={}", kind);
|
||||||
|
|
||||||
|
switch (kind) {
|
||||||
|
case LaunchParameterKind::AccountPreselectedUser:
|
||||||
|
m_applet->preselected_user_launch_parameter.push_back(storage->GetData());
|
||||||
|
R_SUCCEED();
|
||||||
|
default:
|
||||||
|
R_THROW(ResultUnknown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationAccessor::GetApplicationControlProperty(
|
||||||
|
OutBuffer<BufferAttr_HipcMapAlias> out_control_property) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
R_THROW(ResultUnknown);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationAccessor::SetUsers(bool enable,
|
||||||
|
InArray<Common::UUID, BufferAttr_HipcMapAlias> user_ids) {
|
||||||
|
LOG_INFO(Service_AM, "called, enable={} user_id_count={}", enable, user_ids.size());
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationAccessor::GetCurrentLibraryApplet(
|
||||||
|
Out<SharedPointer<ILibraryAppletAccessor>> out_accessor) {
|
||||||
|
LOG_INFO(Service_AM, "(STUBBED) called");
|
||||||
|
*out_accessor = nullptr;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationAccessor::RequestForApplicationToGetForeground() {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
R_THROW(ResultUnknown);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationAccessor::CheckRightsEnvironmentAvailable(Out<bool> out_is_available) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
*out_is_available = true;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationAccessor::GetNsRightsEnvironmentHandle(Out<u64> out_handle) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
*out_handle = 0xdeadbeef;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationAccessor::ReportApplicationExitTimeout() {
|
||||||
|
LOG_ERROR(Service_AM, "called");
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
40
src/core/hle/service/am/service/application_accessor.h
Normal file
40
src/core/hle/service/am/service/application_accessor.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/uuid.h"
|
||||||
|
#include "core/hle/service/am/am_types.h"
|
||||||
|
#include "core/hle/service/cmif_types.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
class ILibraryAppletAccessor;
|
||||||
|
class IStorage;
|
||||||
|
|
||||||
|
class IApplicationAccessor final : public ServiceFramework<IApplicationAccessor> {
|
||||||
|
public:
|
||||||
|
explicit IApplicationAccessor(Core::System& system_, std::shared_ptr<Applet> applet);
|
||||||
|
~IApplicationAccessor() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result Start();
|
||||||
|
Result RequestExit();
|
||||||
|
Result Terminate();
|
||||||
|
Result GetResult();
|
||||||
|
Result GetAppletStateChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
|
Result PushLaunchParameter(LaunchParameterKind kind, SharedPointer<IStorage> storage);
|
||||||
|
Result GetApplicationControlProperty(OutBuffer<BufferAttr_HipcMapAlias> out_control_property);
|
||||||
|
Result SetUsers(bool enable, InArray<Common::UUID, BufferAttr_HipcMapAlias> user_ids);
|
||||||
|
Result GetCurrentLibraryApplet(Out<SharedPointer<ILibraryAppletAccessor>> out_accessor);
|
||||||
|
Result RequestForApplicationToGetForeground();
|
||||||
|
Result CheckRightsEnvironmentAvailable(Out<bool> out_is_available);
|
||||||
|
Result GetNsRightsEnvironmentHandle(Out<u64> out_handle);
|
||||||
|
Result ReportApplicationExitTimeout();
|
||||||
|
|
||||||
|
const std::shared_ptr<Applet> m_applet;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -1,8 +1,12 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "core/hle/service/am/application_creator.h"
|
#include "core/hle/service/am/am_types.h"
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
#include "core/hle/service/am/applet.h"
|
||||||
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
|
#include "core/hle/service/am/service/application_accessor.h"
|
||||||
|
#include "core/hle/service/am/service/application_creator.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
|
@ -10,7 +14,7 @@ IApplicationCreator::IApplicationCreator(Core::System& system_)
|
||||||
: ServiceFramework{system_, "IApplicationCreator"} {
|
: ServiceFramework{system_, "IApplicationCreator"} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, nullptr, "CreateApplication"},
|
{0, D<&IApplicationCreator::CreateApplication>, "CreateApplication"},
|
||||||
{1, nullptr, "PopLaunchRequestedApplication"},
|
{1, nullptr, "PopLaunchRequestedApplication"},
|
||||||
{10, nullptr, "CreateSystemApplication"},
|
{10, nullptr, "CreateSystemApplication"},
|
||||||
{100, nullptr, "PopFloatingApplicationForDevelopment"},
|
{100, nullptr, "PopFloatingApplicationForDevelopment"},
|
||||||
|
@ -22,4 +26,10 @@ IApplicationCreator::IApplicationCreator(Core::System& system_)
|
||||||
|
|
||||||
IApplicationCreator::~IApplicationCreator() = default;
|
IApplicationCreator::~IApplicationCreator() = default;
|
||||||
|
|
||||||
|
Result IApplicationCreator::CreateApplication(
|
||||||
|
Out<SharedPointer<IApplicationAccessor>> out_application_accessor, u64 application_id) {
|
||||||
|
LOG_ERROR(Service_NS, "called, application_id={:x}", application_id);
|
||||||
|
R_THROW(ResultUnknown);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
|
@ -3,14 +3,21 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/cmif_types.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
|
class IApplicationAccessor;
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
class IApplicationCreator final : public ServiceFramework<IApplicationCreator> {
|
class IApplicationCreator final : public ServiceFramework<IApplicationCreator> {
|
||||||
public:
|
public:
|
||||||
explicit IApplicationCreator(Core::System& system_);
|
explicit IApplicationCreator(Core::System& system_);
|
||||||
~IApplicationCreator() override;
|
~IApplicationCreator() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result CreateApplication(Out<SharedPointer<IApplicationAccessor>>, u64 application_id);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
465
src/core/hle/service/am/service/application_functions.cpp
Normal file
465
src/core/hle/service/am/service/application_functions.cpp
Normal file
|
@ -0,0 +1,465 @@
|
||||||
|
// 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/kernel/k_transfer_memory.h"
|
||||||
|
#include "core/hle/service/am/am_results.h"
|
||||||
|
#include "core/hle/service/am/applet.h"
|
||||||
|
#include "core/hle/service/am/service/application_functions.h"
|
||||||
|
#include "core/hle/service/am/service/storage.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||||
|
#include "core/hle/service/filesystem/save_data_controller.h"
|
||||||
|
#include "core/hle/service/ns/ns.h"
|
||||||
|
#include "core/hle/service/sm/sm.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet)
|
||||||
|
: ServiceFramework{system_, "IApplicationFunctions"}, m_applet{std::move(applet)} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{1, D<&IApplicationFunctions::PopLaunchParameter>, "PopLaunchParameter"},
|
||||||
|
{10, nullptr, "CreateApplicationAndPushAndRequestToStart"},
|
||||||
|
{11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"},
|
||||||
|
{12, nullptr, "CreateApplicationAndRequestToStart"},
|
||||||
|
{13, nullptr, "CreateApplicationAndRequestToStartForQuest"},
|
||||||
|
{14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"},
|
||||||
|
{15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"},
|
||||||
|
{20, D<&IApplicationFunctions::EnsureSaveData>, "EnsureSaveData"},
|
||||||
|
{21, D<&IApplicationFunctions::GetDesiredLanguage>, "GetDesiredLanguage"},
|
||||||
|
{22, D<&IApplicationFunctions::SetTerminateResult>, "SetTerminateResult"},
|
||||||
|
{23, D<&IApplicationFunctions::GetDisplayVersion>, "GetDisplayVersion"},
|
||||||
|
{24, nullptr, "GetLaunchStorageInfoForDebug"},
|
||||||
|
{25, D<&IApplicationFunctions::ExtendSaveData>, "ExtendSaveData"},
|
||||||
|
{26, D<&IApplicationFunctions::GetSaveDataSize>, "GetSaveDataSize"},
|
||||||
|
{27, D<&IApplicationFunctions::CreateCacheStorage>, "CreateCacheStorage"},
|
||||||
|
{28, D<&IApplicationFunctions::GetSaveDataSizeMax>, "GetSaveDataSizeMax"},
|
||||||
|
{29, nullptr, "GetCacheStorageMax"},
|
||||||
|
{30, D<&IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed>, "BeginBlockingHomeButtonShortAndLongPressed"},
|
||||||
|
{31, D<&IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed>, "EndBlockingHomeButtonShortAndLongPressed"},
|
||||||
|
{32, D<&IApplicationFunctions::BeginBlockingHomeButton>, "BeginBlockingHomeButton"},
|
||||||
|
{33, D<&IApplicationFunctions::EndBlockingHomeButton>, "EndBlockingHomeButton"},
|
||||||
|
{34, nullptr, "SelectApplicationLicense"},
|
||||||
|
{35, nullptr, "GetDeviceSaveDataSizeMax"},
|
||||||
|
{36, nullptr, "GetLimitedApplicationLicense"},
|
||||||
|
{37, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"},
|
||||||
|
{40, D<&IApplicationFunctions::NotifyRunning>, "NotifyRunning"},
|
||||||
|
{50, D<&IApplicationFunctions::GetPseudoDeviceId>, "GetPseudoDeviceId"},
|
||||||
|
{60, nullptr, "SetMediaPlaybackStateForApplication"},
|
||||||
|
{65, D<&IApplicationFunctions::IsGamePlayRecordingSupported>, "IsGamePlayRecordingSupported"},
|
||||||
|
{66, D<&IApplicationFunctions::InitializeGamePlayRecording>, "InitializeGamePlayRecording"},
|
||||||
|
{67, D<&IApplicationFunctions::SetGamePlayRecordingState>, "SetGamePlayRecordingState"},
|
||||||
|
{68, nullptr, "RequestFlushGamePlayingMovieForDebug"},
|
||||||
|
{70, nullptr, "RequestToShutdown"},
|
||||||
|
{71, nullptr, "RequestToReboot"},
|
||||||
|
{72, nullptr, "RequestToSleep"},
|
||||||
|
{80, nullptr, "ExitAndRequestToShowThanksMessage"},
|
||||||
|
{90, D<&IApplicationFunctions::EnableApplicationCrashReport>, "EnableApplicationCrashReport"},
|
||||||
|
{100, D<&IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer>, "InitializeApplicationCopyrightFrameBuffer"},
|
||||||
|
{101, D<&IApplicationFunctions::SetApplicationCopyrightImage>, "SetApplicationCopyrightImage"},
|
||||||
|
{102, D<&IApplicationFunctions::SetApplicationCopyrightVisibility>, "SetApplicationCopyrightVisibility"},
|
||||||
|
{110, D<&IApplicationFunctions::QueryApplicationPlayStatistics>, "QueryApplicationPlayStatistics"},
|
||||||
|
{111, D<&IApplicationFunctions::QueryApplicationPlayStatisticsByUid>, "QueryApplicationPlayStatisticsByUid"},
|
||||||
|
{120, D<&IApplicationFunctions::ExecuteProgram>, "ExecuteProgram"},
|
||||||
|
{121, D<&IApplicationFunctions::ClearUserChannel>, "ClearUserChannel"},
|
||||||
|
{122, D<&IApplicationFunctions::UnpopToUserChannel>, "UnpopToUserChannel"},
|
||||||
|
{123, D<&IApplicationFunctions::GetPreviousProgramIndex>, "GetPreviousProgramIndex"},
|
||||||
|
{124, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
|
||||||
|
{130, D<&IApplicationFunctions::GetGpuErrorDetectedSystemEvent>, "GetGpuErrorDetectedSystemEvent"},
|
||||||
|
{131, nullptr, "SetDelayTimeToAbortOnGpuError"},
|
||||||
|
{140, D<&IApplicationFunctions::GetFriendInvitationStorageChannelEvent>, "GetFriendInvitationStorageChannelEvent"},
|
||||||
|
{141, D<&IApplicationFunctions::TryPopFromFriendInvitationStorageChannel>, "TryPopFromFriendInvitationStorageChannel"},
|
||||||
|
{150, D<&IApplicationFunctions::GetNotificationStorageChannelEvent>, "GetNotificationStorageChannelEvent"},
|
||||||
|
{151, nullptr, "TryPopFromNotificationStorageChannel"},
|
||||||
|
{160, D<&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, D<&IApplicationFunctions::PrepareForJit>, "PrepareForJit"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
IApplicationFunctions::~IApplicationFunctions() = default;
|
||||||
|
|
||||||
|
Result IApplicationFunctions::PopLaunchParameter(Out<SharedPointer<IStorage>> out_storage,
|
||||||
|
LaunchParameterKind launch_parameter_kind) {
|
||||||
|
LOG_INFO(Service_AM, "called, kind={}", launch_parameter_kind);
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
|
||||||
|
auto& channel = launch_parameter_kind == LaunchParameterKind::UserChannel
|
||||||
|
? m_applet->user_channel_launch_parameter
|
||||||
|
: m_applet->preselected_user_launch_parameter;
|
||||||
|
|
||||||
|
if (channel.empty()) {
|
||||||
|
LOG_WARNING(Service_AM, "Attempted to pop parameter {} but none was found!",
|
||||||
|
launch_parameter_kind);
|
||||||
|
R_THROW(AM::ResultNoDataInChannel);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto data = channel.back();
|
||||||
|
channel.pop_back();
|
||||||
|
|
||||||
|
*out_storage = std::make_shared<IStorage>(system, std::move(data));
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::EnsureSaveData(Out<u64> out_size, Common::UUID user_id) {
|
||||||
|
LOG_INFO(Service_AM, "called, uid={}", user_id.FormattedString());
|
||||||
|
|
||||||
|
FileSys::SaveDataAttribute attribute{};
|
||||||
|
attribute.title_id = m_applet->program_id;
|
||||||
|
attribute.user_id = user_id.AsU128();
|
||||||
|
attribute.type = FileSys::SaveDataType::SaveData;
|
||||||
|
|
||||||
|
FileSys::VirtualDir save_data{};
|
||||||
|
R_TRY(system.GetFileSystemController().OpenSaveDataController()->CreateSaveData(
|
||||||
|
&save_data, FileSys::SaveDataSpaceId::NandUser, attribute));
|
||||||
|
|
||||||
|
*out_size = 0;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::GetDesiredLanguage(Out<u64> out_language_code) {
|
||||||
|
// FIXME: all of this stuff belongs to ns
|
||||||
|
// 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 FileSys::PatchManager pm{m_applet->program_id, system.GetFileSystemController(),
|
||||||
|
system.GetContentProvider()};
|
||||||
|
auto metadata = pm.GetControlMetadata();
|
||||||
|
if (metadata.first != nullptr) {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(m_applet->program_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{};
|
||||||
|
R_TRY(app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages));
|
||||||
|
|
||||||
|
// Convert to settings language code.
|
||||||
|
R_TRY(app_man->ConvertApplicationLanguageToLanguageCode(out_language_code, desired_language));
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_AM, "got desired_language={:016X}", *out_language_code);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::SetTerminateResult(Result terminate_result) {
|
||||||
|
LOG_INFO(Service_AM, "(STUBBED) called, result={:#x} ({}-{})", terminate_result.GetInnerValue(),
|
||||||
|
static_cast<u32>(terminate_result.GetModule()) + 2000,
|
||||||
|
terminate_result.GetDescription());
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->terminate_result = terminate_result;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::GetDisplayVersion(Out<DisplayVersion> out_display_version) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
const auto res = [this] {
|
||||||
|
const FileSys::PatchManager pm{m_applet->program_id, system.GetFileSystemController(),
|
||||||
|
system.GetContentProvider()};
|
||||||
|
auto metadata = pm.GetControlMetadata();
|
||||||
|
if (metadata.first != nullptr) {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(m_applet->program_id),
|
||||||
|
system.GetFileSystemController(),
|
||||||
|
system.GetContentProvider()};
|
||||||
|
return pm_update.GetControlMetadata();
|
||||||
|
}();
|
||||||
|
|
||||||
|
if (res.first != nullptr) {
|
||||||
|
const auto& version = res.first->GetVersionString();
|
||||||
|
std::memcpy(out_display_version->string.data(), version.data(),
|
||||||
|
std::min(version.size(), out_display_version->string.size()));
|
||||||
|
} else {
|
||||||
|
static constexpr char default_version[]{"1.0.0"};
|
||||||
|
std::memcpy(out_display_version->string.data(), default_version, sizeof(default_version));
|
||||||
|
}
|
||||||
|
|
||||||
|
out_display_version->string[out_display_version->string.size() - 1] = '\0';
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::ExtendSaveData(Out<u64> out_required_size, FileSys::SaveDataType type,
|
||||||
|
Common::UUID user_id, u64 normal_size,
|
||||||
|
u64 journal_size) {
|
||||||
|
LOG_DEBUG(Service_AM, "called with type={} user_id={} normal={:#x} journal={:#x}",
|
||||||
|
static_cast<u8>(type), user_id.FormattedString(), normal_size, journal_size);
|
||||||
|
|
||||||
|
system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize(
|
||||||
|
type, m_applet->program_id, user_id.AsU128(), {normal_size, journal_size});
|
||||||
|
|
||||||
|
// The following value is used to indicate the amount of space remaining on failure
|
||||||
|
// due to running out of space. Since we always succeed, this should be 0.
|
||||||
|
*out_required_size = 0;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::GetSaveDataSize(Out<u64> out_normal_size, Out<u64> out_journal_size,
|
||||||
|
FileSys::SaveDataType type, Common::UUID user_id) {
|
||||||
|
LOG_DEBUG(Service_AM, "called with type={} user_id={}", type, user_id.FormattedString());
|
||||||
|
|
||||||
|
const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize(
|
||||||
|
type, m_applet->program_id, user_id.AsU128());
|
||||||
|
|
||||||
|
*out_normal_size = size.normal;
|
||||||
|
*out_journal_size = size.journal;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::CreateCacheStorage(Out<u32> out_target_media,
|
||||||
|
Out<u64> out_required_size, u16 index,
|
||||||
|
u64 normal_size, u64 journal_size) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called with index={} size={:#x} journal_size={:#x}", index,
|
||||||
|
normal_size, journal_size);
|
||||||
|
|
||||||
|
*out_target_media = 1; // Nand
|
||||||
|
*out_required_size = 0;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::GetSaveDataSizeMax(Out<u64> out_max_normal_size,
|
||||||
|
Out<u64> out_max_journal_size) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
*out_max_normal_size = 0xFFFFFFF;
|
||||||
|
*out_max_journal_size = 0xFFFFFFF;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(s64 unused) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->home_button_long_pressed_blocked = true;
|
||||||
|
m_applet->home_button_short_pressed_blocked = true;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed() {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->home_button_long_pressed_blocked = false;
|
||||||
|
m_applet->home_button_short_pressed_blocked = false;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::BeginBlockingHomeButton(s64 timeout_ns) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called, timeout_ns={}", timeout_ns);
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->home_button_long_pressed_blocked = true;
|
||||||
|
m_applet->home_button_short_pressed_blocked = true;
|
||||||
|
m_applet->home_button_double_click_enabled = true;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::EndBlockingHomeButton() {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->home_button_long_pressed_blocked = false;
|
||||||
|
m_applet->home_button_short_pressed_blocked = false;
|
||||||
|
m_applet->home_button_double_click_enabled = false;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::NotifyRunning(Out<bool> out_became_running) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
*out_became_running = true;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::GetPseudoDeviceId(Out<Common::UUID> out_pseudo_device_id) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
*out_pseudo_device_id = {};
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::IsGamePlayRecordingSupported(
|
||||||
|
Out<bool> out_is_game_play_recording_supported) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
*out_is_game_play_recording_supported = m_applet->game_play_recording_supported;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::InitializeGamePlayRecording(
|
||||||
|
u64 transfer_memory_size, InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::SetGamePlayRecordingState(
|
||||||
|
GamePlayRecordingState game_play_recording_state) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->game_play_recording_state = game_play_recording_state;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::EnableApplicationCrashReport(bool enabled) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->application_crash_report_enabled = enabled;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(
|
||||||
|
s32 width, s32 height, u64 transfer_memory_size,
|
||||||
|
InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::SetApplicationCopyrightImage(
|
||||||
|
s32 x, s32 y, s32 width, s32 height, WindowOriginMode window_origin_mode,
|
||||||
|
InBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> image_data) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::SetApplicationCopyrightVisibility(bool visible) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called, is_visible={}", visible);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::QueryApplicationPlayStatistics(
|
||||||
|
Out<s32> out_entries,
|
||||||
|
OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_play_statistics,
|
||||||
|
InArray<u64, BufferAttr_HipcMapAlias> application_ids) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
*out_entries = 0;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::QueryApplicationPlayStatisticsByUid(
|
||||||
|
Out<s32> out_entries,
|
||||||
|
OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_play_statistics,
|
||||||
|
Common::UUID user_id, InArray<u64, BufferAttr_HipcMapAlias> application_ids) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
*out_entries = 0;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::ExecuteProgram(ProgramSpecifyKind kind, u64 value) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called, kind={}, value={}", kind, value);
|
||||||
|
ASSERT(kind == ProgramSpecifyKind::ExecuteProgram ||
|
||||||
|
kind == ProgramSpecifyKind::RestartProgram);
|
||||||
|
|
||||||
|
// Copy user channel ownership into the system so that it will be preserved
|
||||||
|
system.GetUserChannel() = m_applet->user_channel_launch_parameter;
|
||||||
|
system.ExecuteProgram(value);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::ClearUserChannel() {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
m_applet->user_channel_launch_parameter.clear();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::UnpopToUserChannel(SharedPointer<IStorage> storage) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
m_applet->user_channel_launch_parameter.push_back(storage->GetData());
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::GetPreviousProgramIndex(Out<s32> out_previous_program_index) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
*out_previous_program_index = m_applet->previous_program_index;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::GetGpuErrorDetectedSystemEvent(
|
||||||
|
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
*out_event = m_applet->gpu_error_detected_event.GetHandle();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::GetFriendInvitationStorageChannelEvent(
|
||||||
|
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_event = m_applet->friend_invitation_storage_channel_event.GetHandle();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(
|
||||||
|
Out<SharedPointer<IStorage>> out_storage) {
|
||||||
|
LOG_INFO(Service_AM, "(STUBBED) called");
|
||||||
|
R_THROW(AM::ResultNoDataInChannel);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::GetNotificationStorageChannelEvent(
|
||||||
|
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_event = m_applet->notification_storage_channel_event.GetHandle();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(
|
||||||
|
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_event = m_applet->health_warning_disappeared_system_event.GetHandle();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationFunctions::PrepareForJit() {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->jit_service_launched = true;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
83
src/core/hle/service/am/service/application_functions.h
Normal file
83
src/core/hle/service/am/service/application_functions.h
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/uuid.h"
|
||||||
|
#include "core/hle/service/am/am_types.h"
|
||||||
|
#include "core/hle/service/cmif_types.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace FileSys {
|
||||||
|
enum class SaveDataType : u8;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
class KReadableEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
class IStorage;
|
||||||
|
|
||||||
|
class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
|
||||||
|
public:
|
||||||
|
explicit IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet);
|
||||||
|
~IApplicationFunctions() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result PopLaunchParameter(Out<SharedPointer<IStorage>> out_storage,
|
||||||
|
LaunchParameterKind launch_parameter_kind);
|
||||||
|
Result EnsureSaveData(Out<u64> out_size, Common::UUID user_id);
|
||||||
|
Result GetDesiredLanguage(Out<u64> out_language_code);
|
||||||
|
Result SetTerminateResult(Result terminate_result);
|
||||||
|
Result GetDisplayVersion(Out<DisplayVersion> out_display_version);
|
||||||
|
Result ExtendSaveData(Out<u64> out_required_size, FileSys::SaveDataType type,
|
||||||
|
Common::UUID user_id, u64 normal_size, u64 journal_size);
|
||||||
|
Result GetSaveDataSize(Out<u64> out_normal_size, Out<u64> out_journal_size,
|
||||||
|
FileSys::SaveDataType type, Common::UUID user_id);
|
||||||
|
Result CreateCacheStorage(Out<u32> out_target_media, Out<u64> out_required_size, u16 index,
|
||||||
|
u64 normal_size, u64 journal_size);
|
||||||
|
Result GetSaveDataSizeMax(Out<u64> out_max_normal_size, Out<u64> out_max_journal_size);
|
||||||
|
Result BeginBlockingHomeButtonShortAndLongPressed(s64 unused);
|
||||||
|
Result EndBlockingHomeButtonShortAndLongPressed();
|
||||||
|
Result BeginBlockingHomeButton(s64 timeout_ns);
|
||||||
|
Result EndBlockingHomeButton();
|
||||||
|
Result NotifyRunning(Out<bool> out_became_running);
|
||||||
|
Result GetPseudoDeviceId(Out<Common::UUID> out_pseudo_device_id);
|
||||||
|
Result IsGamePlayRecordingSupported(Out<bool> out_is_game_play_recording_supported);
|
||||||
|
Result InitializeGamePlayRecording(
|
||||||
|
u64 transfer_memory_size, InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle);
|
||||||
|
Result SetGamePlayRecordingState(GamePlayRecordingState game_play_recording_state);
|
||||||
|
Result EnableApplicationCrashReport(bool enabled);
|
||||||
|
Result InitializeApplicationCopyrightFrameBuffer(
|
||||||
|
s32 width, s32 height, u64 transfer_memory_size,
|
||||||
|
InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle);
|
||||||
|
Result SetApplicationCopyrightImage(
|
||||||
|
s32 x, s32 y, s32 width, s32 height, WindowOriginMode window_origin_mode,
|
||||||
|
InBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> image_data);
|
||||||
|
Result SetApplicationCopyrightVisibility(bool visible);
|
||||||
|
Result QueryApplicationPlayStatistics(
|
||||||
|
Out<s32> out_entries,
|
||||||
|
OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_play_statistics,
|
||||||
|
InArray<u64, BufferAttr_HipcMapAlias> application_ids);
|
||||||
|
Result QueryApplicationPlayStatisticsByUid(
|
||||||
|
Out<s32> out_entries,
|
||||||
|
OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_play_statistics,
|
||||||
|
Common::UUID user_id, InArray<u64, BufferAttr_HipcMapAlias> application_ids);
|
||||||
|
Result ExecuteProgram(ProgramSpecifyKind kind, u64 value);
|
||||||
|
Result ClearUserChannel();
|
||||||
|
Result UnpopToUserChannel(SharedPointer<IStorage> storage);
|
||||||
|
Result GetPreviousProgramIndex(Out<s32> out_previous_program_index);
|
||||||
|
Result GetGpuErrorDetectedSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
|
Result GetFriendInvitationStorageChannelEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
|
Result TryPopFromFriendInvitationStorageChannel(Out<SharedPointer<IStorage>> out_storage);
|
||||||
|
Result GetNotificationStorageChannelEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
|
Result GetHealthWarningDisappearedSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
|
Result PrepareForJit();
|
||||||
|
|
||||||
|
const std::shared_ptr<Applet> m_applet;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
106
src/core/hle/service/am/service/application_proxy.cpp
Normal file
106
src/core/hle/service/am/service/application_proxy.cpp
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/service/applet_common_functions.h"
|
||||||
|
#include "core/hle/service/am/service/application_functions.h"
|
||||||
|
#include "core/hle/service/am/service/application_proxy.h"
|
||||||
|
#include "core/hle/service/am/service/audio_controller.h"
|
||||||
|
#include "core/hle/service/am/service/common_state_getter.h"
|
||||||
|
#include "core/hle/service/am/service/debug_functions.h"
|
||||||
|
#include "core/hle/service/am/service/display_controller.h"
|
||||||
|
#include "core/hle/service/am/service/library_applet_creator.h"
|
||||||
|
#include "core/hle/service/am/service/process_winding_controller.h"
|
||||||
|
#include "core/hle/service/am/service/self_controller.h"
|
||||||
|
#include "core/hle/service/am/service/window_controller.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
IApplicationProxy::IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
|
Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger)
|
||||||
|
: ServiceFramework{system_, "IApplicationProxy"},
|
||||||
|
m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, D<&IApplicationProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
|
||||||
|
{1, D<&IApplicationProxy::GetSelfController>, "GetSelfController"},
|
||||||
|
{2, D<&IApplicationProxy::GetWindowController>, "GetWindowController"},
|
||||||
|
{3, D<&IApplicationProxy::GetAudioController>, "GetAudioController"},
|
||||||
|
{4, D<&IApplicationProxy::GetDisplayController>, "GetDisplayController"},
|
||||||
|
{10, D<&IApplicationProxy::GetProcessWindingController>, "GetProcessWindingController"},
|
||||||
|
{11, D<&IApplicationProxy::GetLibraryAppletCreator>, "GetLibraryAppletCreator"},
|
||||||
|
{20, D<&IApplicationProxy::GetApplicationFunctions>, "GetApplicationFunctions"},
|
||||||
|
{1000, D<&IApplicationProxy::GetDebugFunctions>, "GetDebugFunctions"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
IApplicationProxy::~IApplicationProxy() = default;
|
||||||
|
|
||||||
|
Result IApplicationProxy::GetAudioController(
|
||||||
|
Out<SharedPointer<IAudioController>> out_audio_controller) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_audio_controller = std::make_shared<IAudioController>(system);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationProxy::GetDisplayController(
|
||||||
|
Out<SharedPointer<IDisplayController>> out_display_controller) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_display_controller = std::make_shared<IDisplayController>(system, m_applet);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationProxy::GetProcessWindingController(
|
||||||
|
Out<SharedPointer<IProcessWindingController>> out_process_winding_controller) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_process_winding_controller = std::make_shared<IProcessWindingController>(system, m_applet);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationProxy::GetDebugFunctions(
|
||||||
|
Out<SharedPointer<IDebugFunctions>> out_debug_functions) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_debug_functions = std::make_shared<IDebugFunctions>(system);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationProxy::GetWindowController(
|
||||||
|
Out<SharedPointer<IWindowController>> out_window_controller) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_window_controller = std::make_shared<IWindowController>(system, m_applet);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationProxy::GetSelfController(
|
||||||
|
Out<SharedPointer<ISelfController>> out_self_controller) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_self_controller =
|
||||||
|
std::make_shared<ISelfController>(system, m_applet, m_process, m_nvnflinger);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationProxy::GetCommonStateGetter(
|
||||||
|
Out<SharedPointer<ICommonStateGetter>> out_common_state_getter) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_common_state_getter = std::make_shared<ICommonStateGetter>(system, m_applet);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationProxy::GetLibraryAppletCreator(
|
||||||
|
Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_library_applet_creator = std::make_shared<ILibraryAppletCreator>(system, m_applet);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IApplicationProxy::GetApplicationFunctions(
|
||||||
|
Out<SharedPointer<IApplicationFunctions>> out_application_functions) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_application_functions = std::make_shared<IApplicationFunctions>(system, m_applet);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
48
src/core/hle/service/am/service/application_proxy.h
Normal file
48
src/core/hle/service/am/service/application_proxy.h
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/cmif_types.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
class IAudioController;
|
||||||
|
class IApplicationFunctions;
|
||||||
|
class ICommonStateGetter;
|
||||||
|
class IDebugFunctions;
|
||||||
|
class IDisplayController;
|
||||||
|
class ILibraryAppletCreator;
|
||||||
|
class IProcessWindingController;
|
||||||
|
class ISelfController;
|
||||||
|
class IWindowController;
|
||||||
|
|
||||||
|
class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
|
||||||
|
public:
|
||||||
|
explicit IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
|
Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger);
|
||||||
|
~IApplicationProxy();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result GetAudioController(Out<SharedPointer<IAudioController>> out_audio_controller);
|
||||||
|
Result GetDisplayController(Out<SharedPointer<IDisplayController>> out_display_controller);
|
||||||
|
Result GetProcessWindingController(
|
||||||
|
Out<SharedPointer<IProcessWindingController>> out_process_winding_controller);
|
||||||
|
Result GetDebugFunctions(Out<SharedPointer<IDebugFunctions>> out_debug_functions);
|
||||||
|
Result GetWindowController(Out<SharedPointer<IWindowController>> out_window_controller);
|
||||||
|
Result GetSelfController(Out<SharedPointer<ISelfController>> out_self_controller);
|
||||||
|
Result GetCommonStateGetter(Out<SharedPointer<ICommonStateGetter>> out_common_state_getter);
|
||||||
|
Result GetLibraryAppletCreator(
|
||||||
|
Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator);
|
||||||
|
Result GetApplicationFunctions(
|
||||||
|
Out<SharedPointer<IApplicationFunctions>> out_application_functions);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Nvnflinger::Nvnflinger& m_nvnflinger;
|
||||||
|
Kernel::KProcess* const m_process;
|
||||||
|
const std::shared_ptr<Applet> m_applet;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,43 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "core/hle/service/am/am.h"
|
||||||
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
|
#include "core/hle/service/am/service/application_proxy.h"
|
||||||
|
#include "core/hle/service/am/service/application_proxy_service.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
IApplicationProxyService::IApplicationProxyService(Core::System& system_,
|
||||||
|
Nvnflinger::Nvnflinger& nvnflinger)
|
||||||
|
: ServiceFramework{system_, "appletOE"}, m_nvnflinger{nvnflinger} {
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, D<&IApplicationProxyService::OpenApplicationProxy>, "OpenApplicationProxy"},
|
||||||
|
};
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
IApplicationProxyService::~IApplicationProxyService() = default;
|
||||||
|
|
||||||
|
Result IApplicationProxyService::OpenApplicationProxy(
|
||||||
|
Out<SharedPointer<IApplicationProxy>> out_application_proxy, ClientProcessId pid,
|
||||||
|
InCopyHandle<Kernel::KProcess> process_handle) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
if (const auto applet = this->GetAppletFromProcessId(pid)) {
|
||||||
|
*out_application_proxy =
|
||||||
|
std::make_shared<IApplicationProxy>(system, applet, process_handle.Get(), m_nvnflinger);
|
||||||
|
R_SUCCEED();
|
||||||
|
} else {
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
R_THROW(ResultUnknown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Applet> IApplicationProxyService::GetAppletFromProcessId(ProcessId process_id) {
|
||||||
|
return system.GetAppletManager().GetByAppletResourceUserId(process_id.pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
35
src/core/hle/service/am/service/application_proxy_service.h
Normal file
35
src/core/hle/service/am/service/application_proxy_service.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/cmif_types.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service {
|
||||||
|
|
||||||
|
namespace Nvnflinger {
|
||||||
|
class Nvnflinger;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
class IApplicationProxy;
|
||||||
|
|
||||||
|
class IApplicationProxyService final : public ServiceFramework<IApplicationProxyService> {
|
||||||
|
public:
|
||||||
|
explicit IApplicationProxyService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger);
|
||||||
|
~IApplicationProxyService() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result OpenApplicationProxy(Out<SharedPointer<IApplicationProxy>> out_application_proxy,
|
||||||
|
ClientProcessId pid, InCopyHandle<Kernel::KProcess> process_handle);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid);
|
||||||
|
Nvnflinger::Nvnflinger& m_nvnflinger;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace AM
|
||||||
|
} // namespace Service
|
69
src/core/hle/service/am/service/audio_controller.cpp
Normal file
69
src/core/hle/service/am/service/audio_controller.cpp
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/service/audio_controller.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
IAudioController::IAudioController(Core::System& system_)
|
||||||
|
: ServiceFramework{system_, "IAudioController"} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, D<&IAudioController::SetExpectedMasterVolume>, "SetExpectedMasterVolume"},
|
||||||
|
{1, D<&IAudioController::GetMainAppletExpectedMasterVolume>, "GetMainAppletExpectedMasterVolume"},
|
||||||
|
{2, D<&IAudioController::GetLibraryAppletExpectedMasterVolume>, "GetLibraryAppletExpectedMasterVolume"},
|
||||||
|
{3, D<&IAudioController::ChangeMainAppletMasterVolume>, "ChangeMainAppletMasterVolume"},
|
||||||
|
{4, D<&IAudioController::SetTransparentVolumeRate>, "SetTransparentVolumeRate"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
IAudioController::~IAudioController() = default;
|
||||||
|
|
||||||
|
Result IAudioController::SetExpectedMasterVolume(f32 main_applet_volume,
|
||||||
|
f32 library_applet_volume) {
|
||||||
|
LOG_DEBUG(Service_AM, "called. main_applet_volume={}, library_applet_volume={}",
|
||||||
|
main_applet_volume, library_applet_volume);
|
||||||
|
|
||||||
|
// Ensure the volume values remain within the 0-100% range
|
||||||
|
m_main_applet_volume = std::clamp(main_applet_volume, MinAllowedVolume, MaxAllowedVolume);
|
||||||
|
m_library_applet_volume = std::clamp(library_applet_volume, MinAllowedVolume, MaxAllowedVolume);
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IAudioController::GetMainAppletExpectedMasterVolume(Out<f32> out_main_applet_volume) {
|
||||||
|
LOG_DEBUG(Service_AM, "called. main_applet_volume={}", m_main_applet_volume);
|
||||||
|
*out_main_applet_volume = m_main_applet_volume;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IAudioController::GetLibraryAppletExpectedMasterVolume(Out<f32> out_library_applet_volume) {
|
||||||
|
LOG_DEBUG(Service_AM, "called. library_applet_volume={}", m_library_applet_volume);
|
||||||
|
*out_library_applet_volume = m_library_applet_volume;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IAudioController::ChangeMainAppletMasterVolume(f32 volume, s64 fade_time_ns) {
|
||||||
|
LOG_DEBUG(Service_AM, "called. volume={}, fade_time_ns={}", volume, fade_time_ns);
|
||||||
|
|
||||||
|
m_main_applet_volume = std::clamp(volume, MinAllowedVolume, MaxAllowedVolume);
|
||||||
|
m_fade_time_ns = std::chrono::nanoseconds{fade_time_ns};
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IAudioController::SetTransparentVolumeRate(f32 transparent_volume_rate) {
|
||||||
|
LOG_DEBUG(Service_AM, "called. transparent_volume_rate={}", transparent_volume_rate);
|
||||||
|
|
||||||
|
// Clamp volume range to 0-100%.
|
||||||
|
m_transparent_volume_rate =
|
||||||
|
std::clamp(transparent_volume_rate, MinAllowedVolume, MaxAllowedVolume);
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
37
src/core/hle/service/am/service/audio_controller.h
Normal file
37
src/core/hle/service/am/service/audio_controller.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/cmif_types.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
class IAudioController final : public ServiceFramework<IAudioController> {
|
||||||
|
public:
|
||||||
|
explicit IAudioController(Core::System& system_);
|
||||||
|
~IAudioController() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result SetExpectedMasterVolume(f32 main_applet_volume, f32 library_applet_volume);
|
||||||
|
Result GetMainAppletExpectedMasterVolume(Out<f32> out_main_applet_volume);
|
||||||
|
Result GetLibraryAppletExpectedMasterVolume(Out<f32> out_library_applet_volume);
|
||||||
|
Result ChangeMainAppletMasterVolume(f32 volume, s64 fade_time_ns);
|
||||||
|
Result SetTransparentVolumeRate(f32 transparent_volume_rate);
|
||||||
|
|
||||||
|
static constexpr float MinAllowedVolume = 0.0f;
|
||||||
|
static constexpr float MaxAllowedVolume = 1.0f;
|
||||||
|
|
||||||
|
float m_main_applet_volume{0.25f};
|
||||||
|
float m_library_applet_volume{MaxAllowedVolume};
|
||||||
|
float m_transparent_volume_rate{MinAllowedVolume};
|
||||||
|
|
||||||
|
// 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 m_fade_time_ns{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
277
src/core/hle/service/am/service/common_state_getter.cpp
Normal file
277
src/core/hle/service/am/service/common_state_getter.cpp
Normal file
|
@ -0,0 +1,277 @@
|
||||||
|
// 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/applet.h"
|
||||||
|
#include "core/hle/service/am/service/common_state_getter.h"
|
||||||
|
#include "core/hle/service/am/service/lock_accessor.h"
|
||||||
|
#include "core/hle/service/apm/apm_interface.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.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<Applet> applet)
|
||||||
|
: ServiceFramework{system_, "ICommonStateGetter"}, m_applet{std::move(applet)} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, D<&ICommonStateGetter::GetEventHandle>, "GetEventHandle"},
|
||||||
|
{1, D<&ICommonStateGetter::ReceiveMessage>, "ReceiveMessage"},
|
||||||
|
{2, nullptr, "GetThisAppletKind"},
|
||||||
|
{3, nullptr, "AllowToEnterSleep"},
|
||||||
|
{4, nullptr, "DisallowToEnterSleep"},
|
||||||
|
{5, D<&ICommonStateGetter::GetOperationMode>, "GetOperationMode"},
|
||||||
|
{6, D<&ICommonStateGetter::GetPerformanceMode>, "GetPerformanceMode"},
|
||||||
|
{7, nullptr, "GetCradleStatus"},
|
||||||
|
{8, D<&ICommonStateGetter::GetBootMode>, "GetBootMode"},
|
||||||
|
{9, D<&ICommonStateGetter::GetCurrentFocusState>, "GetCurrentFocusState"},
|
||||||
|
{10, D<&ICommonStateGetter::RequestToAcquireSleepLock>, "RequestToAcquireSleepLock"},
|
||||||
|
{11, nullptr, "ReleaseSleepLock"},
|
||||||
|
{12, nullptr, "ReleaseSleepLockTransiently"},
|
||||||
|
{13, D<&ICommonStateGetter::GetAcquiredSleepLockEvent>, "GetAcquiredSleepLockEvent"},
|
||||||
|
{14, nullptr, "GetWakeupCount"},
|
||||||
|
{20, nullptr, "PushToGeneralChannel"},
|
||||||
|
{30, nullptr, "GetHomeButtonReaderLockAccessor"},
|
||||||
|
{31, D<&ICommonStateGetter::GetReaderLockAccessorEx>, "GetReaderLockAccessorEx"},
|
||||||
|
{32, D<&ICommonStateGetter::GetWriterLockAccessorEx>, "GetWriterLockAccessorEx"},
|
||||||
|
{40, nullptr, "GetCradleFwVersion"},
|
||||||
|
{50, D<&ICommonStateGetter::IsVrModeEnabled>, "IsVrModeEnabled"},
|
||||||
|
{51, D<&ICommonStateGetter::SetVrModeEnabled>, "SetVrModeEnabled"},
|
||||||
|
{52, D<&ICommonStateGetter::SetLcdBacklighOffEnabled>, "SetLcdBacklighOffEnabled"},
|
||||||
|
{53, D<&ICommonStateGetter::BeginVrModeEx>, "BeginVrModeEx"},
|
||||||
|
{54, D<&ICommonStateGetter::EndVrModeEx>, "EndVrModeEx"},
|
||||||
|
{55, D<&ICommonStateGetter::IsInControllerFirmwareUpdateSection>, "IsInControllerFirmwareUpdateSection"},
|
||||||
|
{59, nullptr, "SetVrPositionForDebug"},
|
||||||
|
{60, D<&ICommonStateGetter::GetDefaultDisplayResolution>, "GetDefaultDisplayResolution"},
|
||||||
|
{61, D<&ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent>, "GetDefaultDisplayResolutionChangeEvent"},
|
||||||
|
{62, nullptr, "GetHdcpAuthenticationState"},
|
||||||
|
{63, nullptr, "GetHdcpAuthenticationStateChangeEvent"},
|
||||||
|
{64, nullptr, "SetTvPowerStateMatchingMode"},
|
||||||
|
{65, nullptr, "GetApplicationIdByContentActionName"},
|
||||||
|
{66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"},
|
||||||
|
{67, nullptr, "CancelCpuBoostMode"},
|
||||||
|
{68, D<&ICommonStateGetter::GetBuiltInDisplayType>, "GetBuiltInDisplayType"},
|
||||||
|
{80, D<&ICommonStateGetter::PerformSystemButtonPressingIfInFocus>, "PerformSystemButtonPressingIfInFocus"},
|
||||||
|
{90, nullptr, "SetPerformanceConfigurationChangedNotification"},
|
||||||
|
{91, nullptr, "GetCurrentPerformanceConfiguration"},
|
||||||
|
{100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"},
|
||||||
|
{110, nullptr, "OpenMyGpuErrorHandler"},
|
||||||
|
{120, D<&ICommonStateGetter::GetAppletLaunchedHistory>, "GetAppletLaunchedHistory"},
|
||||||
|
{200, D<&ICommonStateGetter::GetOperationModeSystemInfo>, "GetOperationModeSystemInfo"},
|
||||||
|
{300, D<&ICommonStateGetter::GetSettingsPlatformRegion>, "GetSettingsPlatformRegion"},
|
||||||
|
{400, nullptr, "ActivateMigrationService"},
|
||||||
|
{401, nullptr, "DeactivateMigrationService"},
|
||||||
|
{500, nullptr, "DisableSleepTillShutdown"},
|
||||||
|
{501, nullptr, "SuppressDisablingSleepTemporarily"},
|
||||||
|
{502, nullptr, "IsSleepEnabled"},
|
||||||
|
{503, nullptr, "IsDisablingSleepSuppressed"},
|
||||||
|
{900, D<&ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled>, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
ICommonStateGetter::~ICommonStateGetter() = default;
|
||||||
|
|
||||||
|
Result ICommonStateGetter::GetEventHandle(OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_event = &m_applet->message_queue.GetMessageReceiveEvent();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICommonStateGetter::ReceiveMessage(Out<AppletMessage> out_applet_message) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
*out_applet_message = m_applet->message_queue.PopMessage();
|
||||||
|
if (*out_applet_message == AppletMessage::None) {
|
||||||
|
LOG_ERROR(Service_AM, "Tried to pop message but none was available!");
|
||||||
|
R_THROW(AM::ResultNoMessages);
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICommonStateGetter::GetCurrentFocusState(Out<FocusState> out_focus_state) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
*out_focus_state = m_applet->focus_state;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICommonStateGetter::RequestToAcquireSleepLock() {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
// Sleep lock is acquired immediately.
|
||||||
|
m_applet->sleep_lock_event.Signal();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICommonStateGetter::GetAcquiredSleepLockEvent(
|
||||||
|
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||||
|
LOG_WARNING(Service_AM, "called");
|
||||||
|
*out_event = m_applet->sleep_lock_event.GetHandle();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICommonStateGetter::GetReaderLockAccessorEx(
|
||||||
|
Out<SharedPointer<ILockAccessor>> out_lock_accessor, u32 button_type) {
|
||||||
|
LOG_INFO(Service_AM, "called, button_type={}", button_type);
|
||||||
|
*out_lock_accessor = std::make_shared<ILockAccessor>(system);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICommonStateGetter::GetWriterLockAccessorEx(
|
||||||
|
Out<SharedPointer<ILockAccessor>> out_lock_accessor, u32 button_type) {
|
||||||
|
LOG_INFO(Service_AM, "called, button_type={}", button_type);
|
||||||
|
*out_lock_accessor = std::make_shared<ILockAccessor>(system);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(
|
||||||
|
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_event = &m_applet->message_queue.GetOperationModeChangedEvent();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICommonStateGetter::GetOperationMode(Out<OperationMode> out_operation_mode) {
|
||||||
|
const bool use_docked_mode{Settings::IsDockedMode()};
|
||||||
|
LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode);
|
||||||
|
*out_operation_mode = use_docked_mode ? OperationMode::Docked : OperationMode::Handheld;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICommonStateGetter::GetPerformanceMode(Out<APM::PerformanceMode> out_performance_mode) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_performance_mode = system.GetAPMController().GetCurrentPerformanceMode();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICommonStateGetter::GetBootMode(Out<PM::SystemBootMode> out_boot_mode) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_boot_mode = Service::PM::SystemBootMode::Normal;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICommonStateGetter::IsVrModeEnabled(Out<bool> out_is_vr_mode_enabled) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
*out_is_vr_mode_enabled = m_applet->vr_mode_enabled;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICommonStateGetter::SetVrModeEnabled(bool is_vr_mode_enabled) {
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->vr_mode_enabled = is_vr_mode_enabled;
|
||||||
|
LOG_WARNING(Service_AM, "VR Mode is {}", m_applet->vr_mode_enabled ? "on" : "off");
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICommonStateGetter::SetLcdBacklighOffEnabled(bool is_lcd_backlight_off_enabled) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called. is_lcd_backlight_off_enabled={}",
|
||||||
|
is_lcd_backlight_off_enabled);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICommonStateGetter::BeginVrModeEx() {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->vr_mode_enabled = true;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICommonStateGetter::EndVrModeEx() {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->vr_mode_enabled = false;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICommonStateGetter::IsInControllerFirmwareUpdateSection(
|
||||||
|
Out<bool> out_is_in_controller_firmware_update_section) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
*out_is_in_controller_firmware_update_section = false;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICommonStateGetter::GetDefaultDisplayResolution(Out<s32> out_width, Out<s32> out_height) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
if (Settings::IsDockedMode()) {
|
||||||
|
*out_width = static_cast<u32>(Service::VI::DisplayResolution::DockedWidth);
|
||||||
|
*out_height = static_cast<u32>(Service::VI::DisplayResolution::DockedHeight);
|
||||||
|
} else {
|
||||||
|
*out_width = static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth);
|
||||||
|
*out_height = static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICommonStateGetter::GetBuiltInDisplayType(Out<s32> out_display_type) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
*out_display_type = 0;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICommonStateGetter::PerformSystemButtonPressingIfInFocus(SystemButtonType type) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called, type={}", type);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICommonStateGetter::GetOperationModeSystemInfo(Out<u32> out_operation_mode_system_info) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
*out_operation_mode_system_info = 0;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICommonStateGetter::GetAppletLaunchedHistory(
|
||||||
|
Out<s32> out_count, OutArray<AppletId, BufferAttr_HipcMapAlias> out_applet_ids) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
|
||||||
|
std::shared_ptr<Applet> current_applet = m_applet;
|
||||||
|
|
||||||
|
for (*out_count = 0;
|
||||||
|
*out_count < static_cast<s32>(out_applet_ids.size()) && current_applet != nullptr;
|
||||||
|
/* ... */) {
|
||||||
|
out_applet_ids[(*out_count)++] = current_applet->applet_id;
|
||||||
|
current_applet = current_applet->caller_applet.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICommonStateGetter::GetSettingsPlatformRegion(
|
||||||
|
Out<SysPlatformRegion> out_settings_platform_region) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
*out_settings_platform_region = SysPlatformRegion::Global;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled() {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->request_exit_to_library_applet_at_execute_next_program_enabled = true;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
61
src/core/hle/service/am/service/common_state_getter.h
Normal file
61
src/core/hle/service/am/service/common_state_getter.h
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/am/am_types.h"
|
||||||
|
#include "core/hle/service/apm/apm_controller.h"
|
||||||
|
#include "core/hle/service/cmif_types.h"
|
||||||
|
#include "core/hle/service/pm/pm.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
class KReadableEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
class ILockAccessor;
|
||||||
|
|
||||||
|
class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
|
||||||
|
public:
|
||||||
|
explicit ICommonStateGetter(Core::System& system_, std::shared_ptr<Applet> applet_);
|
||||||
|
~ICommonStateGetter() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result GetEventHandle(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
|
Result ReceiveMessage(Out<AppletMessage> out_applet_message);
|
||||||
|
Result GetCurrentFocusState(Out<FocusState> out_focus_state);
|
||||||
|
Result RequestToAcquireSleepLock();
|
||||||
|
Result GetAcquiredSleepLockEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
|
Result GetReaderLockAccessorEx(Out<SharedPointer<ILockAccessor>> out_lock_accessor,
|
||||||
|
u32 button_type);
|
||||||
|
Result GetWriterLockAccessorEx(Out<SharedPointer<ILockAccessor>> out_lock_accessor,
|
||||||
|
u32 button_type);
|
||||||
|
Result GetDefaultDisplayResolutionChangeEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
|
Result GetOperationMode(Out<OperationMode> out_operation_mode);
|
||||||
|
Result GetPerformanceMode(Out<APM::PerformanceMode> out_performance_mode);
|
||||||
|
Result GetBootMode(Out<PM::SystemBootMode> out_boot_mode);
|
||||||
|
Result IsVrModeEnabled(Out<bool> out_is_vr_mode_enabled);
|
||||||
|
Result SetVrModeEnabled(bool is_vr_mode_enabled);
|
||||||
|
Result SetLcdBacklighOffEnabled(bool is_lcd_backlight_off_enabled);
|
||||||
|
Result BeginVrModeEx();
|
||||||
|
Result EndVrModeEx();
|
||||||
|
Result IsInControllerFirmwareUpdateSection(
|
||||||
|
Out<bool> out_is_in_controller_firmware_update_section);
|
||||||
|
Result GetDefaultDisplayResolution(Out<s32> out_width, Out<s32> out_height);
|
||||||
|
Result GetBuiltInDisplayType(Out<s32> out_display_type);
|
||||||
|
Result PerformSystemButtonPressingIfInFocus(SystemButtonType type);
|
||||||
|
Result GetOperationModeSystemInfo(Out<u32> out_operation_mode_system_info);
|
||||||
|
Result GetAppletLaunchedHistory(Out<s32> out_count,
|
||||||
|
OutArray<AppletId, BufferAttr_HipcMapAlias> out_applet_ids);
|
||||||
|
Result GetSettingsPlatformRegion(Out<SysPlatformRegion> out_settings_platform_region);
|
||||||
|
Result SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled();
|
||||||
|
|
||||||
|
void SetCpuBoostMode(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
const std::shared_ptr<Applet> m_applet;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
52
src/core/hle/service/am/service/cradle_firmware_updater.cpp
Normal file
52
src/core/hle/service/am/service/cradle_firmware_updater.cpp
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/service/cradle_firmware_updater.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
ICradleFirmwareUpdater::ICradleFirmwareUpdater(Core::System& system_)
|
||||||
|
: ServiceFramework{system_, "ICradleFirmwareUpdater"},
|
||||||
|
m_context{system, "ICradleFirmwareUpdater"}, m_cradle_device_info_event{m_context} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, D<&ICradleFirmwareUpdater::StartUpdate>, "StartUpdate"},
|
||||||
|
{1, D<&ICradleFirmwareUpdater::FinishUpdate>, "FinishUpdate"},
|
||||||
|
{2, D<&ICradleFirmwareUpdater::GetCradleDeviceInfo>, "GetCradleDeviceInfo"},
|
||||||
|
{3, D<&ICradleFirmwareUpdater::GetCradleDeviceInfoChangeEvent>, "GetCradleDeviceInfoChangeEvent"},
|
||||||
|
{4, nullptr, "GetUpdateProgressInfo"},
|
||||||
|
{5, nullptr, "GetLastInternalResult"},
|
||||||
|
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
ICradleFirmwareUpdater::~ICradleFirmwareUpdater() = default;
|
||||||
|
|
||||||
|
Result ICradleFirmwareUpdater::StartUpdate() {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICradleFirmwareUpdater::FinishUpdate() {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICradleFirmwareUpdater::GetCradleDeviceInfo(Out<CradleDeviceInfo> out_cradle_device_info) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
*out_cradle_device_info = {};
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ICradleFirmwareUpdater::GetCradleDeviceInfoChangeEvent(
|
||||||
|
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
*out_event = m_cradle_device_info_event.GetHandle();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
37
src/core/hle/service/am/service/cradle_firmware_updater.h
Normal file
37
src/core/hle/service/am/service/cradle_firmware_updater.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/cmif_types.h"
|
||||||
|
#include "core/hle/service/kernel_helpers.h"
|
||||||
|
#include "core/hle/service/os/event.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct CradleDeviceInfo {
|
||||||
|
bool unknown0;
|
||||||
|
bool unknown1;
|
||||||
|
bool unknown2;
|
||||||
|
u64 unknown3;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(CradleDeviceInfo) == 0x10, "CradleDeviceInfo has incorrect size");
|
||||||
|
|
||||||
|
class ICradleFirmwareUpdater final : public ServiceFramework<ICradleFirmwareUpdater> {
|
||||||
|
public:
|
||||||
|
explicit ICradleFirmwareUpdater(Core::System& system_);
|
||||||
|
~ICradleFirmwareUpdater() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result StartUpdate();
|
||||||
|
Result FinishUpdate();
|
||||||
|
Result GetCradleDeviceInfo(Out<CradleDeviceInfo> out_cradle_device_info);
|
||||||
|
Result GetCradleDeviceInfoChangeEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
|
|
||||||
|
private:
|
||||||
|
KernelHelpers::ServiceContext m_context;
|
||||||
|
Event m_cradle_device_info_event;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -1,8 +1,7 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "core/hle/service/am/debug_functions.h"
|
#include "core/hle/service/am/service/debug_functions.h"
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
105
src/core/hle/service/am/service/display_controller.cpp
Normal file
105
src/core/hle/service/am/service/display_controller.cpp
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/result.h"
|
||||||
|
#include "core/hle/service/am/applet.h"
|
||||||
|
#include "core/hle/service/am/service/display_controller.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
IDisplayController::IDisplayController(Core::System& system_, std::shared_ptr<Applet> applet_)
|
||||||
|
: ServiceFramework{system_, "IDisplayController"}, applet(std::move(applet_)) {
|
||||||
|
// 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, D<&IDisplayController::GetCallerAppletCaptureImageEx>, "GetCallerAppletCaptureImageEx"},
|
||||||
|
{8, D<&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, D<&IDisplayController::ClearCaptureBuffer>, "ClearCaptureBuffer"},
|
||||||
|
{21, nullptr, "ClearAppletTransitionBuffer"},
|
||||||
|
{22, D<&IDisplayController::AcquireLastApplicationCaptureSharedBuffer>, "AcquireLastApplicationCaptureSharedBuffer"},
|
||||||
|
{23, D<&IDisplayController::ReleaseLastApplicationCaptureSharedBuffer>, "ReleaseLastApplicationCaptureSharedBuffer"},
|
||||||
|
{24, D<&IDisplayController::AcquireLastForegroundCaptureSharedBuffer>, "AcquireLastForegroundCaptureSharedBuffer"},
|
||||||
|
{25, D<&IDisplayController::ReleaseLastForegroundCaptureSharedBuffer>, "ReleaseLastForegroundCaptureSharedBuffer"},
|
||||||
|
{26, D<&IDisplayController::AcquireCallerAppletCaptureSharedBuffer>, "AcquireCallerAppletCaptureSharedBuffer"},
|
||||||
|
{27, D<&IDisplayController::ReleaseCallerAppletCaptureSharedBuffer>, "ReleaseCallerAppletCaptureSharedBuffer"},
|
||||||
|
{28, nullptr, "TakeScreenShotOfOwnLayerEx"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
IDisplayController::~IDisplayController() = default;
|
||||||
|
|
||||||
|
Result IDisplayController::GetCallerAppletCaptureImageEx(
|
||||||
|
Out<bool> out_was_written, OutBuffer<BufferAttr_HipcMapAlias> out_image_data) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
*out_was_written = true;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IDisplayController::TakeScreenShotOfOwnLayer(bool unknown0, s32 fbshare_layer_index) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IDisplayController::ClearCaptureBuffer(bool unknown0, s32 fbshare_layer_index, u32 color) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called, unknown0={} fbshare_layer_index={} color={:#x}",
|
||||||
|
unknown0, fbshare_layer_index, color);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IDisplayController::AcquireLastForegroundCaptureSharedBuffer(
|
||||||
|
Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
R_RETURN(applet->system_buffer_manager.WriteAppletCaptureBuffer(out_was_written,
|
||||||
|
out_fbshare_layer_index));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IDisplayController::ReleaseLastForegroundCaptureSharedBuffer() {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IDisplayController::AcquireCallerAppletCaptureSharedBuffer(
|
||||||
|
Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
R_RETURN(applet->system_buffer_manager.WriteAppletCaptureBuffer(out_was_written,
|
||||||
|
out_fbshare_layer_index));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IDisplayController::ReleaseCallerAppletCaptureSharedBuffer() {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IDisplayController::AcquireLastApplicationCaptureSharedBuffer(
|
||||||
|
Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
R_RETURN(applet->system_buffer_manager.WriteAppletCaptureBuffer(out_was_written,
|
||||||
|
out_fbshare_layer_index));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IDisplayController::ReleaseLastApplicationCaptureSharedBuffer() {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
36
src/core/hle/service/am/service/display_controller.h
Normal file
36
src/core/hle/service/am/service/display_controller.h
Normal file
|
@ -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/cmif_types.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
|
class IDisplayController final : public ServiceFramework<IDisplayController> {
|
||||||
|
public:
|
||||||
|
explicit IDisplayController(Core::System& system_, std::shared_ptr<Applet> applet_);
|
||||||
|
~IDisplayController() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result GetCallerAppletCaptureImageEx(Out<bool> out_was_written,
|
||||||
|
OutBuffer<BufferAttr_HipcMapAlias> out_image_data);
|
||||||
|
Result TakeScreenShotOfOwnLayer(bool unknown0, s32 fbshare_layer_index);
|
||||||
|
Result ClearCaptureBuffer(bool unknown0, s32 fbshare_layer_index, u32 color);
|
||||||
|
Result AcquireLastForegroundCaptureSharedBuffer(Out<bool> out_was_written,
|
||||||
|
Out<s32> out_fbshare_layer_index);
|
||||||
|
Result ReleaseLastForegroundCaptureSharedBuffer();
|
||||||
|
Result AcquireCallerAppletCaptureSharedBuffer(Out<bool> out_was_written,
|
||||||
|
Out<s32> out_fbshare_layer_index);
|
||||||
|
Result ReleaseCallerAppletCaptureSharedBuffer();
|
||||||
|
Result AcquireLastApplicationCaptureSharedBuffer(Out<bool> out_was_written,
|
||||||
|
Out<s32> out_fbshare_layer_index);
|
||||||
|
Result ReleaseLastApplicationCaptureSharedBuffer();
|
||||||
|
|
||||||
|
const std::shared_ptr<Applet> applet;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
61
src/core/hle/service/am/service/global_state_controller.cpp
Normal file
61
src/core/hle/service/am/service/global_state_controller.cpp
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/service/cradle_firmware_updater.h"
|
||||||
|
#include "core/hle/service/am/service/global_state_controller.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
IGlobalStateController::IGlobalStateController(Core::System& system_)
|
||||||
|
: ServiceFramework{system_, "IGlobalStateController"},
|
||||||
|
m_context{system_, "IGlobalStateController"}, m_hdcp_authentication_failed_event{m_context} {
|
||||||
|
// 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, D<&IGlobalStateController::LoadAndApplyIdlePolicySettings>, "LoadAndApplyIdlePolicySettings"},
|
||||||
|
{11, nullptr, "NotifyCecSettingsChanged"},
|
||||||
|
{12, nullptr, "SetDefaultHomeButtonLongPressTime"},
|
||||||
|
{13, nullptr, "UpdateDefaultDisplayResolution"},
|
||||||
|
{14, D<&IGlobalStateController::ShouldSleepOnBoot>, "ShouldSleepOnBoot"},
|
||||||
|
{15, D<&IGlobalStateController::GetHdcpAuthenticationFailedEvent>, "GetHdcpAuthenticationFailedEvent"},
|
||||||
|
{30, D<&IGlobalStateController::OpenCradleFirmwareUpdater>, "OpenCradleFirmwareUpdater"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
IGlobalStateController::~IGlobalStateController() = default;
|
||||||
|
|
||||||
|
Result IGlobalStateController::LoadAndApplyIdlePolicySettings() {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IGlobalStateController::ShouldSleepOnBoot(Out<bool> out_should_sleep_on_boot) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
*out_should_sleep_on_boot = false;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IGlobalStateController::GetHdcpAuthenticationFailedEvent(
|
||||||
|
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
*out_event = m_hdcp_authentication_failed_event.GetHandle();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IGlobalStateController::OpenCradleFirmwareUpdater(
|
||||||
|
Out<SharedPointer<ICradleFirmwareUpdater>> out_cradle_firmware_updater) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
*out_cradle_firmware_updater = std::make_shared<ICradleFirmwareUpdater>(system);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
31
src/core/hle/service/am/service/global_state_controller.h
Normal file
31
src/core/hle/service/am/service/global_state_controller.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/cmif_types.h"
|
||||||
|
#include "core/hle/service/kernel_helpers.h"
|
||||||
|
#include "core/hle/service/os/event.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
class ICradleFirmwareUpdater;
|
||||||
|
|
||||||
|
class IGlobalStateController final : public ServiceFramework<IGlobalStateController> {
|
||||||
|
public:
|
||||||
|
explicit IGlobalStateController(Core::System& system_);
|
||||||
|
~IGlobalStateController() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result LoadAndApplyIdlePolicySettings();
|
||||||
|
Result ShouldSleepOnBoot(Out<bool> out_should_sleep_on_boot);
|
||||||
|
Result GetHdcpAuthenticationFailedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
|
Result OpenCradleFirmwareUpdater(
|
||||||
|
Out<SharedPointer<ICradleFirmwareUpdater>> out_cradle_firmware_updater);
|
||||||
|
|
||||||
|
KernelHelpers::ServiceContext m_context;
|
||||||
|
Event m_hdcp_authentication_failed_event;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
74
src/core/hle/service/am/service/home_menu_functions.cpp
Normal file
74
src/core/hle/service/am/service/home_menu_functions.cpp
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/result.h"
|
||||||
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
|
#include "core/hle/service/am/service/home_menu_functions.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_, std::shared_ptr<Applet> applet)
|
||||||
|
: ServiceFramework{system_, "IHomeMenuFunctions"}, m_applet{std::move(applet)},
|
||||||
|
m_context{system, "IHomeMenuFunctions"}, m_pop_from_general_channel_event{m_context} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{10, D<&IHomeMenuFunctions::RequestToGetForeground>, "RequestToGetForeground"},
|
||||||
|
{11, D<&IHomeMenuFunctions::LockForeground>, "LockForeground"},
|
||||||
|
{12, D<&IHomeMenuFunctions::UnlockForeground>, "UnlockForeground"},
|
||||||
|
{20, nullptr, "PopFromGeneralChannel"},
|
||||||
|
{21, D<&IHomeMenuFunctions::GetPopFromGeneralChannelEvent>, "GetPopFromGeneralChannelEvent"},
|
||||||
|
{30, nullptr, "GetHomeButtonWriterLockAccessor"},
|
||||||
|
{31, nullptr, "GetWriterLockAccessorEx"},
|
||||||
|
{40, nullptr, "IsSleepEnabled"},
|
||||||
|
{41, D<&IHomeMenuFunctions::IsRebootEnabled>, "IsRebootEnabled"},
|
||||||
|
{50, nullptr, "LaunchSystemApplet"},
|
||||||
|
{51, nullptr, "LaunchStarter"},
|
||||||
|
{100, nullptr, "PopRequestLaunchApplicationForDebug"},
|
||||||
|
{110, D<&IHomeMenuFunctions::IsForceTerminateApplicationDisabledForDebug>, "IsForceTerminateApplicationDisabledForDebug"},
|
||||||
|
{200, nullptr, "LaunchDevMenu"},
|
||||||
|
{1000, nullptr, "SetLastApplicationExitReason"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
IHomeMenuFunctions::~IHomeMenuFunctions() = default;
|
||||||
|
|
||||||
|
Result IHomeMenuFunctions::RequestToGetForeground() {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IHomeMenuFunctions::LockForeground() {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IHomeMenuFunctions::UnlockForeground() {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IHomeMenuFunctions::GetPopFromGeneralChannelEvent(
|
||||||
|
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
*out_event = m_pop_from_general_channel_event.GetHandle();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IHomeMenuFunctions::IsRebootEnabled(Out<bool> out_is_reboot_enbaled) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
*out_is_reboot_enbaled = true;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IHomeMenuFunctions::IsForceTerminateApplicationDisabledForDebug(
|
||||||
|
Out<bool> out_is_force_terminate_application_disabled_for_debug) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
*out_is_force_terminate_application_disabled_for_debug = false;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
34
src/core/hle/service/am/service/home_menu_functions.h
Normal file
34
src/core/hle/service/am/service/home_menu_functions.h
Normal file
|
@ -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/cmif_types.h"
|
||||||
|
#include "core/hle/service/kernel_helpers.h"
|
||||||
|
#include "core/hle/service/os/event.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
|
class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> {
|
||||||
|
public:
|
||||||
|
explicit IHomeMenuFunctions(Core::System& system_, std::shared_ptr<Applet> applet);
|
||||||
|
~IHomeMenuFunctions() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result RequestToGetForeground();
|
||||||
|
Result LockForeground();
|
||||||
|
Result UnlockForeground();
|
||||||
|
Result GetPopFromGeneralChannelEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
|
Result IsRebootEnabled(Out<bool> out_is_reboot_enbaled);
|
||||||
|
Result IsForceTerminateApplicationDisabledForDebug(
|
||||||
|
Out<bool> out_is_force_terminate_application_disabled_for_debug);
|
||||||
|
|
||||||
|
const std::shared_ptr<Applet> m_applet;
|
||||||
|
KernelHelpers::ServiceContext m_context;
|
||||||
|
Event m_pop_from_general_channel_event;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
157
src/core/hle/service/am/service/library_applet_accessor.cpp
Normal file
157
src/core/hle/service/am/service/library_applet_accessor.cpp
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/applet_data_broker.h"
|
||||||
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
|
#include "core/hle/service/am/service/library_applet_accessor.h"
|
||||||
|
#include "core/hle/service/am/service/storage.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
ILibraryAppletAccessor::ILibraryAppletAccessor(Core::System& system_,
|
||||||
|
std::shared_ptr<AppletDataBroker> broker,
|
||||||
|
std::shared_ptr<Applet> applet)
|
||||||
|
: ServiceFramework{system_, "ILibraryAppletAccessor"}, m_broker{std::move(broker)},
|
||||||
|
m_applet{std::move(applet)} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, D<&ILibraryAppletAccessor::GetAppletStateChangedEvent>, "GetAppletStateChangedEvent"},
|
||||||
|
{1, D<&ILibraryAppletAccessor::IsCompleted>, "IsCompleted"},
|
||||||
|
{10, D<&ILibraryAppletAccessor::Start>, "Start"},
|
||||||
|
{20, D<&ILibraryAppletAccessor::RequestExit>, "RequestExit"},
|
||||||
|
{25, D<&ILibraryAppletAccessor::Terminate>, "Terminate"},
|
||||||
|
{30, D<&ILibraryAppletAccessor::GetResult>, "GetResult"},
|
||||||
|
{50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"},
|
||||||
|
{60, D<&ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero>, "PresetLibraryAppletGpuTimeSliceZero"},
|
||||||
|
{100, D<&ILibraryAppletAccessor::PushInData>, "PushInData"},
|
||||||
|
{101, D<&ILibraryAppletAccessor::PopOutData>, "PopOutData"},
|
||||||
|
{102, nullptr, "PushExtraStorage"},
|
||||||
|
{103, D<&ILibraryAppletAccessor::PushInteractiveInData>, "PushInteractiveInData"},
|
||||||
|
{104, D<&ILibraryAppletAccessor::PopInteractiveOutData>, "PopInteractiveOutData"},
|
||||||
|
{105, D<&ILibraryAppletAccessor::GetPopOutDataEvent>, "GetPopOutDataEvent"},
|
||||||
|
{106, D<&ILibraryAppletAccessor::GetPopInteractiveOutDataEvent>, "GetPopInteractiveOutDataEvent"},
|
||||||
|
{110, nullptr, "NeedsToExitProcess"},
|
||||||
|
{120, nullptr, "GetLibraryAppletInfo"},
|
||||||
|
{150, nullptr, "RequestForAppletToGetForeground"},
|
||||||
|
{160, D<&ILibraryAppletAccessor::GetIndirectLayerConsumerHandle>, "GetIndirectLayerConsumerHandle"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
ILibraryAppletAccessor::~ILibraryAppletAccessor() = default;
|
||||||
|
|
||||||
|
Result ILibraryAppletAccessor::GetAppletStateChangedEvent(
|
||||||
|
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_event = m_broker->GetStateChangedEvent().GetHandle();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletAccessor::IsCompleted(Out<bool> out_is_completed) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_is_completed = m_broker->IsCompleted();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletAccessor::GetResult(Out<Result> out_result) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_result = m_applet->terminate_result;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero() {
|
||||||
|
LOG_INFO(Service_AM, "(STUBBED) called");
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletAccessor::Start() {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
m_applet->process->Run();
|
||||||
|
FrontendExecute();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletAccessor::RequestExit() {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
m_applet->message_queue.RequestExit();
|
||||||
|
FrontendRequestExit();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletAccessor::Terminate() {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
m_applet->process->Terminate();
|
||||||
|
FrontendRequestExit();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletAccessor::PushInData(SharedPointer<IStorage> storage) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
m_broker->GetInData().Push(storage);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletAccessor::PopOutData(Out<SharedPointer<IStorage>> out_storage) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
R_RETURN(m_broker->GetOutData().Pop(out_storage.Get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletAccessor::PushInteractiveInData(SharedPointer<IStorage> storage) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
m_broker->GetInteractiveInData().Push(storage);
|
||||||
|
FrontendExecuteInteractive();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletAccessor::PopInteractiveOutData(Out<SharedPointer<IStorage>> out_storage) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
R_RETURN(m_broker->GetInteractiveOutData().Pop(out_storage.Get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletAccessor::GetPopOutDataEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_event = m_broker->GetOutData().GetEvent();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletAccessor::GetPopInteractiveOutDataEvent(
|
||||||
|
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_event = m_broker->GetInteractiveOutData().GetEvent();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletAccessor::GetIndirectLayerConsumerHandle(Out<u64> out_handle) {
|
||||||
|
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
|
||||||
|
*out_handle = 0xdeadbeef;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletAccessor::FrontendExecute() {
|
||||||
|
if (m_applet->frontend) {
|
||||||
|
m_applet->frontend->Initialize();
|
||||||
|
m_applet->frontend->Execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletAccessor::FrontendExecuteInteractive() {
|
||||||
|
if (m_applet->frontend) {
|
||||||
|
m_applet->frontend->ExecuteInteractive();
|
||||||
|
m_applet->frontend->Execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletAccessor::FrontendRequestExit() {
|
||||||
|
if (m_applet->frontend) {
|
||||||
|
m_applet->frontend->RequestExit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
45
src/core/hle/service/am/service/library_applet_accessor.h
Normal file
45
src/core/hle/service/am/service/library_applet_accessor.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/cmif_types.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
class AppletDataBroker;
|
||||||
|
struct Applet;
|
||||||
|
class IStorage;
|
||||||
|
|
||||||
|
class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
|
||||||
|
public:
|
||||||
|
explicit ILibraryAppletAccessor(Core::System& system_, std::shared_ptr<AppletDataBroker> broker,
|
||||||
|
std::shared_ptr<Applet> applet);
|
||||||
|
~ILibraryAppletAccessor();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result GetAppletStateChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
|
Result IsCompleted(Out<bool> out_is_completed);
|
||||||
|
Result GetResult(Out<Result> out_result);
|
||||||
|
Result PresetLibraryAppletGpuTimeSliceZero();
|
||||||
|
Result Start();
|
||||||
|
Result RequestExit();
|
||||||
|
Result Terminate();
|
||||||
|
Result PushInData(SharedPointer<IStorage> storage);
|
||||||
|
Result PopOutData(Out<SharedPointer<IStorage>> out_storage);
|
||||||
|
Result PushInteractiveInData(SharedPointer<IStorage> storage);
|
||||||
|
Result PopInteractiveOutData(Out<SharedPointer<IStorage>> out_storage);
|
||||||
|
Result GetPopOutDataEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
|
Result GetPopInteractiveOutDataEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
|
Result GetIndirectLayerConsumerHandle(Out<u64> out_handle);
|
||||||
|
|
||||||
|
void FrontendExecute();
|
||||||
|
void FrontendExecuteInteractive();
|
||||||
|
void FrontendRequestExit();
|
||||||
|
|
||||||
|
const std::shared_ptr<AppletDataBroker> m_broker;
|
||||||
|
const std::shared_ptr<Applet> m_applet;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -6,11 +6,11 @@
|
||||||
#include "core/hle/service/am/applet_data_broker.h"
|
#include "core/hle/service/am/applet_data_broker.h"
|
||||||
#include "core/hle/service/am/applet_manager.h"
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
#include "core/hle/service/am/frontend/applets.h"
|
#include "core/hle/service/am/frontend/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/library_applet_storage.h"
|
#include "core/hle/service/am/library_applet_storage.h"
|
||||||
#include "core/hle/service/am/storage.h"
|
#include "core/hle/service/am/service/library_applet_accessor.h"
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
#include "core/hle/service/am/service/library_applet_creator.h"
|
||||||
|
#include "core/hle/service/am/service/storage.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
#include "core/hle/service/sm/sm.h"
|
#include "core/hle/service/sm/sm.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
@ -130,13 +130,13 @@ std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system,
|
||||||
case LibraryAppletMode::PartialForegroundIndirectDisplay:
|
case LibraryAppletMode::PartialForegroundIndirectDisplay:
|
||||||
applet->hid_registration.EnableAppletToGetInput(true);
|
applet->hid_registration.EnableAppletToGetInput(true);
|
||||||
applet->focus_state = FocusState::InFocus;
|
applet->focus_state = FocusState::InFocus;
|
||||||
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
|
applet->message_queue.PushMessage(AppletMessage::ChangeIntoForeground);
|
||||||
break;
|
break;
|
||||||
case LibraryAppletMode::AllForegroundInitiallyHidden:
|
case LibraryAppletMode::AllForegroundInitiallyHidden:
|
||||||
applet->hid_registration.EnableAppletToGetInput(false);
|
applet->hid_registration.EnableAppletToGetInput(false);
|
||||||
applet->focus_state = FocusState::NotInFocus;
|
applet->focus_state = FocusState::NotInFocus;
|
||||||
applet->system_buffer_manager.SetWindowVisibility(false);
|
applet->system_buffer_manager.SetWindowVisibility(false);
|
||||||
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoBackground);
|
applet->message_queue.PushMessage(AppletMessage::ChangeIntoBackground);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,139 +172,97 @@ std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& syste
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet_)
|
ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet)
|
||||||
: ServiceFramework{system_, "ILibraryAppletCreator"}, applet{std::move(applet_)} {
|
: ServiceFramework{system_, "ILibraryAppletCreator"}, m_applet{std::move(applet)} {
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"},
|
{0, D<&ILibraryAppletCreator::CreateLibraryApplet>, "CreateLibraryApplet"},
|
||||||
{1, nullptr, "TerminateAllLibraryApplets"},
|
{1, nullptr, "TerminateAllLibraryApplets"},
|
||||||
{2, nullptr, "AreAnyLibraryAppletsLeft"},
|
{2, nullptr, "AreAnyLibraryAppletsLeft"},
|
||||||
{10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"},
|
{10, D<&ILibraryAppletCreator::CreateStorage>, "CreateStorage"},
|
||||||
{11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"},
|
{11, D<&ILibraryAppletCreator::CreateTransferMemoryStorage>, "CreateTransferMemoryStorage"},
|
||||||
{12, &ILibraryAppletCreator::CreateHandleStorage, "CreateHandleStorage"},
|
{12, D<&ILibraryAppletCreator::CreateHandleStorage>, "CreateHandleStorage"},
|
||||||
};
|
};
|
||||||
RegisterHandlers(functions);
|
RegisterHandlers(functions);
|
||||||
}
|
}
|
||||||
|
|
||||||
ILibraryAppletCreator::~ILibraryAppletCreator() = default;
|
ILibraryAppletCreator::~ILibraryAppletCreator() = default;
|
||||||
|
|
||||||
void ILibraryAppletCreator::CreateLibraryApplet(HLERequestContext& ctx) {
|
Result ILibraryAppletCreator::CreateLibraryApplet(
|
||||||
IPC::RequestParser rp{ctx};
|
Out<SharedPointer<ILibraryAppletAccessor>> out_library_applet_accessor, AppletId applet_id,
|
||||||
|
LibraryAppletMode library_applet_mode) {
|
||||||
const auto applet_id = rp.PopRaw<AppletId>();
|
LOG_DEBUG(Service_AM, "called with applet_id={} applet_mode={}", applet_id,
|
||||||
const auto applet_mode = rp.PopRaw<LibraryAppletMode>();
|
library_applet_mode);
|
||||||
|
|
||||||
LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id,
|
|
||||||
applet_mode);
|
|
||||||
|
|
||||||
std::shared_ptr<ILibraryAppletAccessor> library_applet;
|
std::shared_ptr<ILibraryAppletAccessor> library_applet;
|
||||||
if (ShouldCreateGuestApplet(applet_id)) {
|
if (ShouldCreateGuestApplet(applet_id)) {
|
||||||
library_applet = CreateGuestApplet(system, applet, applet_id, applet_mode);
|
library_applet = CreateGuestApplet(system, m_applet, applet_id, library_applet_mode);
|
||||||
}
|
}
|
||||||
if (!library_applet) {
|
if (!library_applet) {
|
||||||
library_applet = CreateFrontendApplet(system, applet, applet_id, applet_mode);
|
library_applet = CreateFrontendApplet(system, m_applet, applet_id, library_applet_mode);
|
||||||
}
|
}
|
||||||
if (!library_applet) {
|
if (!library_applet) {
|
||||||
LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
|
LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
|
||||||
|
R_THROW(ResultUnknown);
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultUnknown);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Applet is created, can now be launched.
|
// Applet is created, can now be launched.
|
||||||
applet->library_applet_launchable_event.Signal();
|
m_applet->library_applet_launchable_event.Signal();
|
||||||
|
*out_library_applet_accessor = library_applet;
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
R_SUCCEED();
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<ILibraryAppletAccessor>(library_applet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletCreator::CreateStorage(HLERequestContext& ctx) {
|
Result ILibraryAppletCreator::CreateStorage(Out<SharedPointer<IStorage>> out_storage, s64 size) {
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
|
|
||||||
const s64 size{rp.Pop<s64>()};
|
|
||||||
|
|
||||||
LOG_DEBUG(Service_AM, "called, size={}", size);
|
LOG_DEBUG(Service_AM, "called, size={}", size);
|
||||||
|
|
||||||
if (size <= 0) {
|
if (size <= 0) {
|
||||||
LOG_ERROR(Service_AM, "size is less than or equal to 0");
|
LOG_ERROR(Service_AM, "size is less than or equal to 0");
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
R_THROW(ResultUnknown);
|
||||||
rb.Push(ResultUnknown);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> data(size);
|
*out_storage = std::make_shared<IStorage>(system, AM::CreateStorage(std::vector<u8>(size)));
|
||||||
|
R_SUCCEED();
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IStorage>(system, AM::CreateStorage(std::move(data)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletCreator::CreateTransferMemoryStorage(HLERequestContext& ctx) {
|
Result ILibraryAppletCreator::CreateTransferMemoryStorage(
|
||||||
IPC::RequestParser rp{ctx};
|
Out<SharedPointer<IStorage>> out_storage, bool is_writable, s64 size,
|
||||||
|
InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle) {
|
||||||
struct Parameters {
|
LOG_DEBUG(Service_AM, "called, is_writable={} size={}", is_writable, size);
|
||||||
bool is_writable;
|
|
||||||
s64 size;
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto params{rp.PopRaw<Parameters>()};
|
|
||||||
const auto handle{ctx.GetCopyHandle(0)};
|
|
||||||
|
|
||||||
LOG_DEBUG(Service_AM, "called, is_writable={}, size={}, handle={:08X}", params.is_writable,
|
|
||||||
params.size, handle);
|
|
||||||
|
|
||||||
if (params.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IStorage>(
|
|
||||||
system, AM::CreateTransferMemoryStorage(ctx.GetMemory(), transfer_mem.GetPointerUnsafe(),
|
|
||||||
params.is_writable, params.size));
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
if (size <= 0) {
|
||||||
LOG_ERROR(Service_AM, "size is less than or equal to 0");
|
LOG_ERROR(Service_AM, "size is less than or equal to 0");
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
R_THROW(ResultUnknown);
|
||||||
rb.Push(ResultUnknown);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle);
|
if (!transfer_memory_handle) {
|
||||||
|
LOG_ERROR(Service_AM, "transfer_memory_handle is null");
|
||||||
if (transfer_mem.IsNull()) {
|
R_THROW(ResultUnknown);
|
||||||
LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(ResultUnknown);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
*out_storage = std::make_shared<IStorage>(
|
||||||
rb.Push(ResultSuccess);
|
system, AM::CreateTransferMemoryStorage(transfer_memory_handle->GetOwner()->GetMemory(),
|
||||||
rb.PushIpcInterface<IStorage>(
|
transfer_memory_handle.Get(), is_writable, size));
|
||||||
system, AM::CreateHandleStorage(ctx.GetMemory(), transfer_mem.GetPointerUnsafe(), size));
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletCreator::CreateHandleStorage(
|
||||||
|
Out<SharedPointer<IStorage>> out_storage, s64 size,
|
||||||
|
InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle) {
|
||||||
|
LOG_DEBUG(Service_AM, "called, size={}", size);
|
||||||
|
|
||||||
|
if (size <= 0) {
|
||||||
|
LOG_ERROR(Service_AM, "size is less than or equal to 0");
|
||||||
|
R_THROW(ResultUnknown);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!transfer_memory_handle) {
|
||||||
|
LOG_ERROR(Service_AM, "transfer_memory_handle is null");
|
||||||
|
R_THROW(ResultUnknown);
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_storage = std::make_shared<IStorage>(
|
||||||
|
system, AM::CreateHandleStorage(transfer_memory_handle->GetOwner()->GetMemory(),
|
||||||
|
transfer_memory_handle.Get(), size));
|
||||||
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
35
src/core/hle/service/am/service/library_applet_creator.h
Normal file
35
src/core/hle/service/am/service/library_applet_creator.h
Normal file
|
@ -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/am_types.h"
|
||||||
|
#include "core/hle/service/cmif_types.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
class ILibraryAppletAccessor;
|
||||||
|
class IStorage;
|
||||||
|
|
||||||
|
class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
|
||||||
|
public:
|
||||||
|
explicit ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet);
|
||||||
|
~ILibraryAppletCreator() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result CreateLibraryApplet(
|
||||||
|
Out<SharedPointer<ILibraryAppletAccessor>> out_library_applet_accessor, AppletId applet_id,
|
||||||
|
LibraryAppletMode library_applet_mode);
|
||||||
|
Result CreateStorage(Out<SharedPointer<IStorage>> out_storage, s64 size);
|
||||||
|
Result CreateTransferMemoryStorage(
|
||||||
|
Out<SharedPointer<IStorage>> out_storage, bool is_writable, s64 size,
|
||||||
|
InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle);
|
||||||
|
Result CreateHandleStorage(Out<SharedPointer<IStorage>> out_storage, s64 size,
|
||||||
|
InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle);
|
||||||
|
|
||||||
|
const std::shared_ptr<Applet> m_applet;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
134
src/core/hle/service/am/service/library_applet_proxy.cpp
Normal file
134
src/core/hle/service/am/service/library_applet_proxy.cpp
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/service/applet_common_functions.h"
|
||||||
|
#include "core/hle/service/am/service/audio_controller.h"
|
||||||
|
#include "core/hle/service/am/service/common_state_getter.h"
|
||||||
|
#include "core/hle/service/am/service/debug_functions.h"
|
||||||
|
#include "core/hle/service/am/service/display_controller.h"
|
||||||
|
#include "core/hle/service/am/service/global_state_controller.h"
|
||||||
|
#include "core/hle/service/am/service/home_menu_functions.h"
|
||||||
|
#include "core/hle/service/am/service/library_applet_creator.h"
|
||||||
|
#include "core/hle/service/am/service/library_applet_proxy.h"
|
||||||
|
#include "core/hle/service/am/service/library_applet_self_accessor.h"
|
||||||
|
#include "core/hle/service/am/service/process_winding_controller.h"
|
||||||
|
#include "core/hle/service/am/service/self_controller.h"
|
||||||
|
#include "core/hle/service/am/service/window_controller.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
ILibraryAppletProxy::ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
|
Kernel::KProcess* process,
|
||||||
|
Nvnflinger::Nvnflinger& nvnflinger)
|
||||||
|
: ServiceFramework{system_, "ILibraryAppletProxy"},
|
||||||
|
m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, D<&ILibraryAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
|
||||||
|
{1, D<&ILibraryAppletProxy::GetSelfController>, "GetSelfController"},
|
||||||
|
{2, D<&ILibraryAppletProxy::GetWindowController>, "GetWindowController"},
|
||||||
|
{3, D<&ILibraryAppletProxy::GetAudioController>, "GetAudioController"},
|
||||||
|
{4, D<&ILibraryAppletProxy::GetDisplayController>, "GetDisplayController"},
|
||||||
|
{10, D<&ILibraryAppletProxy::GetProcessWindingController>, "GetProcessWindingController"},
|
||||||
|
{11, D<&ILibraryAppletProxy::GetLibraryAppletCreator>, "GetLibraryAppletCreator"},
|
||||||
|
{20, D<&ILibraryAppletProxy::OpenLibraryAppletSelfAccessor>, "OpenLibraryAppletSelfAccessor"},
|
||||||
|
{21, D<&ILibraryAppletProxy::GetAppletCommonFunctions>, "GetAppletCommonFunctions"},
|
||||||
|
{22, D<&ILibraryAppletProxy::GetHomeMenuFunctions>, "GetHomeMenuFunctions"},
|
||||||
|
{23, D<&ILibraryAppletProxy::GetGlobalStateController>, "GetGlobalStateController"},
|
||||||
|
{1000, D<&ILibraryAppletProxy::GetDebugFunctions>, "GetDebugFunctions"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
ILibraryAppletProxy::~ILibraryAppletProxy() = default;
|
||||||
|
|
||||||
|
Result ILibraryAppletProxy::GetAudioController(
|
||||||
|
Out<SharedPointer<IAudioController>> out_audio_controller) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_audio_controller = std::make_shared<IAudioController>(system);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletProxy::GetDisplayController(
|
||||||
|
Out<SharedPointer<IDisplayController>> out_display_controller) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_display_controller = std::make_shared<IDisplayController>(system, m_applet);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletProxy::GetProcessWindingController(
|
||||||
|
Out<SharedPointer<IProcessWindingController>> out_process_winding_controller) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_process_winding_controller = std::make_shared<IProcessWindingController>(system, m_applet);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletProxy::GetDebugFunctions(
|
||||||
|
Out<SharedPointer<IDebugFunctions>> out_debug_functions) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_debug_functions = std::make_shared<IDebugFunctions>(system);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletProxy::GetWindowController(
|
||||||
|
Out<SharedPointer<IWindowController>> out_window_controller) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_window_controller = std::make_shared<IWindowController>(system, m_applet);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletProxy::GetSelfController(
|
||||||
|
Out<SharedPointer<ISelfController>> out_self_controller) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_self_controller =
|
||||||
|
std::make_shared<ISelfController>(system, m_applet, m_process, m_nvnflinger);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletProxy::GetCommonStateGetter(
|
||||||
|
Out<SharedPointer<ICommonStateGetter>> out_common_state_getter) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_common_state_getter = std::make_shared<ICommonStateGetter>(system, m_applet);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletProxy::GetLibraryAppletCreator(
|
||||||
|
Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_library_applet_creator = std::make_shared<ILibraryAppletCreator>(system, m_applet);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletProxy::OpenLibraryAppletSelfAccessor(
|
||||||
|
Out<SharedPointer<ILibraryAppletSelfAccessor>> out_library_applet_self_accessor) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_library_applet_self_accessor =
|
||||||
|
std::make_shared<ILibraryAppletSelfAccessor>(system, m_applet);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletProxy::GetAppletCommonFunctions(
|
||||||
|
Out<SharedPointer<IAppletCommonFunctions>> out_applet_common_functions) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_applet_common_functions = std::make_shared<IAppletCommonFunctions>(system, m_applet);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletProxy::GetHomeMenuFunctions(
|
||||||
|
Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_home_menu_functions = std::make_shared<IHomeMenuFunctions>(system, m_applet);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletProxy::GetGlobalStateController(
|
||||||
|
Out<SharedPointer<IGlobalStateController>> out_global_state_controller) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_global_state_controller = std::make_shared<IGlobalStateController>(system);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
55
src/core/hle/service/am/service/library_applet_proxy.h
Normal file
55
src/core/hle/service/am/service/library_applet_proxy.h
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/cmif_types.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
class IAppletCommonFunctions;
|
||||||
|
class IAudioController;
|
||||||
|
class ICommonStateGetter;
|
||||||
|
class IDebugFunctions;
|
||||||
|
class IDisplayController;
|
||||||
|
class IHomeMenuFunctions;
|
||||||
|
class IGlobalStateController;
|
||||||
|
class ILibraryAppletCreator;
|
||||||
|
class ILibraryAppletSelfAccessor;
|
||||||
|
class IProcessWindingController;
|
||||||
|
class ISelfController;
|
||||||
|
class IWindowController;
|
||||||
|
|
||||||
|
class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
|
||||||
|
public:
|
||||||
|
explicit ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
|
Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger);
|
||||||
|
~ILibraryAppletProxy();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result GetAudioController(Out<SharedPointer<IAudioController>> out_audio_controller);
|
||||||
|
Result GetDisplayController(Out<SharedPointer<IDisplayController>> out_display_controller);
|
||||||
|
Result GetProcessWindingController(
|
||||||
|
Out<SharedPointer<IProcessWindingController>> out_process_winding_controller);
|
||||||
|
Result GetDebugFunctions(Out<SharedPointer<IDebugFunctions>> out_debug_functions);
|
||||||
|
Result GetWindowController(Out<SharedPointer<IWindowController>> out_window_controller);
|
||||||
|
Result GetSelfController(Out<SharedPointer<ISelfController>> out_self_controller);
|
||||||
|
Result GetCommonStateGetter(Out<SharedPointer<ICommonStateGetter>> out_common_state_getter);
|
||||||
|
Result GetLibraryAppletCreator(
|
||||||
|
Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator);
|
||||||
|
Result OpenLibraryAppletSelfAccessor(
|
||||||
|
Out<SharedPointer<ILibraryAppletSelfAccessor>> out_library_applet_self_accessor);
|
||||||
|
Result GetAppletCommonFunctions(
|
||||||
|
Out<SharedPointer<IAppletCommonFunctions>> out_applet_common_functions);
|
||||||
|
Result GetHomeMenuFunctions(Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions);
|
||||||
|
Result GetGlobalStateController(
|
||||||
|
Out<SharedPointer<IGlobalStateController>> out_global_state_controller);
|
||||||
|
|
||||||
|
Nvnflinger::Nvnflinger& m_nvnflinger;
|
||||||
|
Kernel::KProcess* const m_process;
|
||||||
|
const std::shared_ptr<Applet> m_applet;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
322
src/core/hle/service/am/service/library_applet_self_accessor.cpp
Normal file
322
src/core/hle/service/am/service/library_applet_self_accessor.cpp
Normal file
|
@ -0,0 +1,322 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#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/hle/service/acc/profile_manager.h"
|
||||||
|
#include "core/hle/service/am/applet_data_broker.h"
|
||||||
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
|
#include "core/hle/service/am/service/library_applet_self_accessor.h"
|
||||||
|
#include "core/hle/service/am/service/storage.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||||
|
#include "core/hle/service/glue/glue_manager.h"
|
||||||
|
#include "core/hle/service/ns/ns.h"
|
||||||
|
#include "core/hle/service/sm/sm.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
AppletIdentityInfo GetCallerIdentity(Applet& applet) {
|
||||||
|
if (const auto caller_applet = applet.caller_applet.lock(); caller_applet) {
|
||||||
|
// TODO: is this actually the application ID?
|
||||||
|
return {
|
||||||
|
.applet_id = caller_applet->applet_id,
|
||||||
|
.application_id = caller_applet->program_id,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
.applet_id = AppletId::QLaunch,
|
||||||
|
.application_id = 0x0100000000001000ull,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_,
|
||||||
|
std::shared_ptr<Applet> applet)
|
||||||
|
: ServiceFramework{system_, "ILibraryAppletSelfAccessor"}, m_applet{std::move(applet)},
|
||||||
|
m_broker{m_applet->caller_applet_broker} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, D<&ILibraryAppletSelfAccessor::PopInData>, "PopInData"},
|
||||||
|
{1, D<&ILibraryAppletSelfAccessor::PushOutData>, "PushOutData"},
|
||||||
|
{2, D<&ILibraryAppletSelfAccessor::PopInteractiveInData>, "PopInteractiveInData"},
|
||||||
|
{3, D<&ILibraryAppletSelfAccessor::PushInteractiveOutData>, "PushInteractiveOutData"},
|
||||||
|
{5, D<&ILibraryAppletSelfAccessor::GetPopInDataEvent>, "GetPopInDataEvent"},
|
||||||
|
{6, D<&ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent>, "GetPopInteractiveInDataEvent"},
|
||||||
|
{10, D<&ILibraryAppletSelfAccessor::ExitProcessAndReturn>, "ExitProcessAndReturn"},
|
||||||
|
{11, D<&ILibraryAppletSelfAccessor::GetLibraryAppletInfo>, "GetLibraryAppletInfo"},
|
||||||
|
{12, D<&ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo>, "GetMainAppletIdentityInfo"},
|
||||||
|
{13, D<&ILibraryAppletSelfAccessor::CanUseApplicationCore>, "CanUseApplicationCore"},
|
||||||
|
{14, D<&ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo>, "GetCallerAppletIdentityInfo"},
|
||||||
|
{15, D<&ILibraryAppletSelfAccessor::GetMainAppletApplicationControlProperty>, "GetMainAppletApplicationControlProperty"},
|
||||||
|
{16, D<&ILibraryAppletSelfAccessor::GetMainAppletStorageId>, "GetMainAppletStorageId"},
|
||||||
|
{17, D<&ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfoStack>, "GetCallerAppletIdentityInfoStack"},
|
||||||
|
{18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"},
|
||||||
|
{19, D<&ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout>, "GetDesirableKeyboardLayout"},
|
||||||
|
{20, nullptr, "PopExtraStorage"},
|
||||||
|
{25, nullptr, "GetPopExtraStorageEvent"},
|
||||||
|
{30, nullptr, "UnpopInData"},
|
||||||
|
{31, nullptr, "UnpopExtraStorage"},
|
||||||
|
{40, nullptr, "GetIndirectLayerProducerHandle"},
|
||||||
|
{50, D<&ILibraryAppletSelfAccessor::ReportVisibleError>, "ReportVisibleError"},
|
||||||
|
{51, D<&ILibraryAppletSelfAccessor::ReportVisibleErrorWithErrorContext>, "ReportVisibleErrorWithErrorContext"},
|
||||||
|
{60, D<&ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage>, "GetMainAppletApplicationDesiredLanguage"},
|
||||||
|
{70, D<&ILibraryAppletSelfAccessor::GetCurrentApplicationId>, "GetCurrentApplicationId"},
|
||||||
|
{80, nullptr, "RequestExitToSelf"},
|
||||||
|
{90, nullptr, "CreateApplicationAndPushAndRequestToLaunch"},
|
||||||
|
{100, nullptr, "CreateGameMovieTrimmer"},
|
||||||
|
{101, nullptr, "ReserveResourceForMovieOperation"},
|
||||||
|
{102, nullptr, "UnreserveResourceForMovieOperation"},
|
||||||
|
{110, D<&ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers>, "GetMainAppletAvailableUsers"},
|
||||||
|
{120, nullptr, "GetLaunchStorageInfoForDebug"},
|
||||||
|
{130, nullptr, "GetGpuErrorDetectedSystemEvent"},
|
||||||
|
{140, nullptr, "SetApplicationMemoryReservation"},
|
||||||
|
{150, D<&ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually>, "ShouldSetGpuTimeSliceManually"},
|
||||||
|
{160, D<&ILibraryAppletSelfAccessor::Cmd160>, "Cmd160"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default;
|
||||||
|
|
||||||
|
Result ILibraryAppletSelfAccessor::PopInData(Out<SharedPointer<IStorage>> out_storage) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
R_RETURN(m_broker->GetInData().Pop(out_storage));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletSelfAccessor::PushOutData(SharedPointer<IStorage> storage) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
m_broker->GetOutData().Push(storage);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletSelfAccessor::PopInteractiveInData(Out<SharedPointer<IStorage>> out_storage) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
R_RETURN(m_broker->GetInteractiveInData().Pop(out_storage));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletSelfAccessor::PushInteractiveOutData(SharedPointer<IStorage> storage) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
m_broker->GetInteractiveOutData().Push(storage);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletSelfAccessor::GetPopInDataEvent(
|
||||||
|
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
*out_event = m_broker->GetInData().GetEvent();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent(
|
||||||
|
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
*out_event = m_broker->GetInteractiveInData().GetEvent();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletSelfAccessor::GetLibraryAppletInfo(
|
||||||
|
Out<LibraryAppletInfo> out_library_applet_info) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
*out_library_applet_info = {
|
||||||
|
.applet_id = m_applet->applet_id,
|
||||||
|
.library_applet_mode = m_applet->library_applet_mode,
|
||||||
|
};
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(
|
||||||
|
Out<AppletIdentityInfo> out_identity_info) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
*out_identity_info = {
|
||||||
|
.applet_id = AppletId::QLaunch,
|
||||||
|
.application_id = 0x0100000000001000ull,
|
||||||
|
};
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletSelfAccessor::CanUseApplicationCore(Out<bool> out_can_use_application_core) {
|
||||||
|
// TODO: This appears to read the NPDM from state and check the core mask of the applet.
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
*out_can_use_application_core = false;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletSelfAccessor::GetMainAppletApplicationControlProperty(
|
||||||
|
OutLargeData<std::array<u8, 0x4000>, BufferAttr_HipcMapAlias> out_nacp) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
// TODO: this should be the main applet, not the caller applet
|
||||||
|
const auto application = GetCallerIdentity(*m_applet);
|
||||||
|
std::vector<u8> nacp;
|
||||||
|
const auto result =
|
||||||
|
system.GetARPManager().GetControlProperty(&nacp, application.application_id);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(result)) {
|
||||||
|
std::memcpy(out_nacp->data(), nacp.data(), std::min(nacp.size(), out_nacp->size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
R_RETURN(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletSelfAccessor::GetMainAppletStorageId(Out<FileSys::StorageId> out_storage_id) {
|
||||||
|
LOG_INFO(Service_AM, "(STUBBED) called");
|
||||||
|
*out_storage_id = FileSys::StorageId::NandUser;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletSelfAccessor::ExitProcessAndReturn() {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
system.GetAppletManager().TerminateAndRemoveApplet(m_applet->aruid);
|
||||||
|
m_broker->SignalCompletion();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(
|
||||||
|
Out<AppletIdentityInfo> out_identity_info) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
*out_identity_info = GetCallerIdentity(*m_applet);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfoStack(
|
||||||
|
Out<s32> out_count, OutArray<AppletIdentityInfo, BufferAttr_HipcMapAlias> out_identity_info) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
|
||||||
|
std::shared_ptr<Applet> applet = m_applet;
|
||||||
|
*out_count = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (*out_count >= static_cast<s32>(out_identity_info.size())) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
out_identity_info[(*out_count)++] = GetCallerIdentity(*applet);
|
||||||
|
} while ((applet = applet->caller_applet.lock()));
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(Out<u32> out_desirable_layout) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
*out_desirable_layout = 0;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletSelfAccessor::ReportVisibleError(ErrorCode error_code) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called, error {}-{}", error_code.category,
|
||||||
|
error_code.number);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletSelfAccessor::ReportVisibleErrorWithErrorContext(
|
||||||
|
ErrorCode error_code, InLargeData<ErrorContext, BufferAttr_HipcMapAlias> error_context) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called, error {}-{}", error_code.category,
|
||||||
|
error_code.number);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage(
|
||||||
|
Out<u64> out_desired_language) {
|
||||||
|
// FIXME: this is copied from IApplicationFunctions::GetDesiredLanguage
|
||||||
|
// FIXME: all of this stuff belongs to ns
|
||||||
|
auto identity = GetCallerIdentity(*m_applet);
|
||||||
|
|
||||||
|
// 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, identity] {
|
||||||
|
const FileSys::PatchManager pm{identity.application_id, system.GetFileSystemController(),
|
||||||
|
system.GetContentProvider()};
|
||||||
|
auto metadata = pm.GetControlMetadata();
|
||||||
|
if (metadata.first != nullptr) {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(identity.application_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{};
|
||||||
|
R_TRY(app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages));
|
||||||
|
|
||||||
|
// Convert to settings language code.
|
||||||
|
u64 language_code{};
|
||||||
|
R_TRY(app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language));
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code);
|
||||||
|
|
||||||
|
*out_desired_language = language_code;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletSelfAccessor::GetCurrentApplicationId(Out<u64> out_application_id) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
// TODO: this should be the main applet, not the caller applet
|
||||||
|
const auto main_applet = GetCallerIdentity(*m_applet);
|
||||||
|
*out_application_id = main_applet.application_id;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(
|
||||||
|
Out<bool> out_no_users_available, Out<s32> out_users_count,
|
||||||
|
OutArray<Common::UUID, BufferAttr_HipcMapAlias> out_users) {
|
||||||
|
const Service::Account::ProfileManager manager{};
|
||||||
|
|
||||||
|
*out_no_users_available = true;
|
||||||
|
*out_users_count = -1;
|
||||||
|
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
|
||||||
|
if (manager.GetUserCount() > 0) {
|
||||||
|
*out_no_users_available = false;
|
||||||
|
*out_users_count = static_cast<s32>(manager.GetUserCount());
|
||||||
|
|
||||||
|
const auto users = manager.GetAllUsers();
|
||||||
|
for (size_t i = 0; i < users.size() && i < out_users.size(); i++) {
|
||||||
|
out_users[i] = users[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually(
|
||||||
|
Out<bool> out_should_set_gpu_time_slice_manually) {
|
||||||
|
LOG_INFO(Service_AM, "(STUBBED) called");
|
||||||
|
*out_should_set_gpu_time_slice_manually = false;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILibraryAppletSelfAccessor::Cmd160(Out<u64> out_unknown0) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
*out_unknown0 = 0;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,83 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/uuid.h"
|
||||||
|
#include "core/hle/service/am/am_types.h"
|
||||||
|
#include "core/hle/service/cmif_types.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace FileSys {
|
||||||
|
enum class StorageId : u8;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
class KReadableEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
class AppletDataBroker;
|
||||||
|
struct Applet;
|
||||||
|
class IStorage;
|
||||||
|
|
||||||
|
struct LibraryAppletInfo {
|
||||||
|
AppletId applet_id;
|
||||||
|
LibraryAppletMode library_applet_mode;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(LibraryAppletInfo) == 0x8, "LibraryAppletInfo has incorrect size.");
|
||||||
|
|
||||||
|
struct ErrorCode {
|
||||||
|
u32 category;
|
||||||
|
u32 number;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(ErrorCode) == 0x8, "ErrorCode has incorrect size.");
|
||||||
|
|
||||||
|
struct ErrorContext {
|
||||||
|
u8 type;
|
||||||
|
INSERT_PADDING_BYTES_NOINIT(0x7);
|
||||||
|
std::array<u8, 0x1f4> data;
|
||||||
|
Result result;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(ErrorContext) == 0x200, "ErrorContext has incorrect size.");
|
||||||
|
|
||||||
|
class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> {
|
||||||
|
public:
|
||||||
|
explicit ILibraryAppletSelfAccessor(Core::System& system_, std::shared_ptr<Applet> applet);
|
||||||
|
~ILibraryAppletSelfAccessor() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result PopInData(Out<SharedPointer<IStorage>> out_storage);
|
||||||
|
Result PushOutData(SharedPointer<IStorage> storage);
|
||||||
|
Result PopInteractiveInData(Out<SharedPointer<IStorage>> out_storage);
|
||||||
|
Result PushInteractiveOutData(SharedPointer<IStorage> storage);
|
||||||
|
Result GetPopInDataEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
|
Result GetPopInteractiveInDataEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
|
Result GetLibraryAppletInfo(Out<LibraryAppletInfo> out_library_applet_info);
|
||||||
|
Result GetMainAppletIdentityInfo(Out<AppletIdentityInfo> out_identity_info);
|
||||||
|
Result CanUseApplicationCore(Out<bool> out_can_use_application_core);
|
||||||
|
Result GetMainAppletApplicationControlProperty(
|
||||||
|
OutLargeData<std::array<u8, 0x4000>, BufferAttr_HipcMapAlias> out_nacp);
|
||||||
|
Result GetMainAppletStorageId(Out<FileSys::StorageId> out_storage_id);
|
||||||
|
Result ExitProcessAndReturn();
|
||||||
|
Result GetCallerAppletIdentityInfo(Out<AppletIdentityInfo> out_identity_info);
|
||||||
|
Result GetCallerAppletIdentityInfoStack(
|
||||||
|
Out<s32> out_count,
|
||||||
|
OutArray<AppletIdentityInfo, BufferAttr_HipcMapAlias> out_identity_info);
|
||||||
|
Result GetDesirableKeyboardLayout(Out<u32> out_desirable_layout);
|
||||||
|
Result ReportVisibleError(ErrorCode error_code);
|
||||||
|
Result ReportVisibleErrorWithErrorContext(
|
||||||
|
ErrorCode error_code, InLargeData<ErrorContext, BufferAttr_HipcMapAlias> error_context);
|
||||||
|
Result GetMainAppletApplicationDesiredLanguage(Out<u64> out_desired_language);
|
||||||
|
Result GetCurrentApplicationId(Out<u64> out_application_id);
|
||||||
|
Result GetMainAppletAvailableUsers(Out<bool> out_no_users_available, Out<s32> out_users_count,
|
||||||
|
OutArray<Common::UUID, BufferAttr_HipcMapAlias> out_users);
|
||||||
|
Result ShouldSetGpuTimeSliceManually(Out<bool> out_should_set_gpu_time_slice_manually);
|
||||||
|
Result Cmd160(Out<u64> out_unknown0);
|
||||||
|
|
||||||
|
const std::shared_ptr<Applet> m_applet;
|
||||||
|
const std::shared_ptr<AppletDataBroker> m_broker;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
75
src/core/hle/service/am/service/lock_accessor.cpp
Normal file
75
src/core/hle/service/am/service/lock_accessor.cpp
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/service/lock_accessor.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
ILockAccessor::ILockAccessor(Core::System& system_)
|
||||||
|
: ServiceFramework{system_, "ILockAccessor"}, m_context{system_, "ILockAccessor"},
|
||||||
|
m_event{m_context} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{1, D<&ILockAccessor::TryLock>, "TryLock"},
|
||||||
|
{2, D<&ILockAccessor::Unlock>, "Unlock"},
|
||||||
|
{3, D<&ILockAccessor::GetEvent>, "GetEvent"},
|
||||||
|
{4, D<&ILockAccessor::IsLocked>, "IsLocked"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
|
||||||
|
m_event.Signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
ILockAccessor::~ILockAccessor() = default;
|
||||||
|
|
||||||
|
Result ILockAccessor::TryLock(Out<bool> out_is_locked,
|
||||||
|
OutCopyHandle<Kernel::KReadableEvent> out_handle,
|
||||||
|
bool return_handle) {
|
||||||
|
LOG_INFO(Service_AM, "called, return_handle={}", return_handle);
|
||||||
|
|
||||||
|
{
|
||||||
|
std::scoped_lock lk{m_mutex};
|
||||||
|
if (m_is_locked) {
|
||||||
|
*out_is_locked = false;
|
||||||
|
} else {
|
||||||
|
m_is_locked = true;
|
||||||
|
*out_is_locked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (return_handle) {
|
||||||
|
*out_handle = m_event.GetHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILockAccessor::Unlock() {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
|
||||||
|
{
|
||||||
|
std::scoped_lock lk{m_mutex};
|
||||||
|
m_is_locked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_event.Signal();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILockAccessor::GetEvent(OutCopyHandle<Kernel::KReadableEvent> out_handle) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
*out_handle = m_event.GetHandle();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ILockAccessor::IsLocked(Out<bool> out_is_locked) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
std::scoped_lock lk{m_mutex};
|
||||||
|
*out_is_locked = m_is_locked;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
32
src/core/hle/service/am/service/lock_accessor.h
Normal file
32
src/core/hle/service/am/service/lock_accessor.h
Normal file
|
@ -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/cmif_types.h"
|
||||||
|
#include "core/hle/service/kernel_helpers.h"
|
||||||
|
#include "core/hle/service/os/event.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:
|
||||||
|
Result TryLock(Out<bool> out_is_locked, OutCopyHandle<Kernel::KReadableEvent> out_handle,
|
||||||
|
bool return_handle);
|
||||||
|
Result Unlock();
|
||||||
|
Result GetEvent(OutCopyHandle<Kernel::KReadableEvent> out_handle);
|
||||||
|
Result IsLocked(Out<bool> out_is_locked);
|
||||||
|
|
||||||
|
private:
|
||||||
|
KernelHelpers::ServiceContext m_context;
|
||||||
|
Event m_event;
|
||||||
|
std::mutex m_mutex{};
|
||||||
|
bool m_is_locked{};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,54 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
|
#include "core/hle/service/am/service/library_applet_accessor.h"
|
||||||
|
#include "core/hle/service/am/service/process_winding_controller.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
IProcessWindingController::IProcessWindingController(Core::System& system_,
|
||||||
|
std::shared_ptr<Applet> applet)
|
||||||
|
: ServiceFramework{system_, "IProcessWindingController"}, m_applet{std::move(applet)} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, D<&IProcessWindingController::GetLaunchReason>, "GetLaunchReason"},
|
||||||
|
{11, D<&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;
|
||||||
|
|
||||||
|
Result IProcessWindingController::GetLaunchReason(
|
||||||
|
Out<AppletProcessLaunchReason> out_launch_reason) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
*out_launch_reason = m_applet->launch_reason;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IProcessWindingController::OpenCallingLibraryApplet(
|
||||||
|
Out<SharedPointer<ILibraryAppletAccessor>> out_calling_library_applet) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
|
||||||
|
const auto caller_applet = m_applet->caller_applet.lock();
|
||||||
|
if (caller_applet == nullptr) {
|
||||||
|
LOG_ERROR(Service_AM, "No caller applet available");
|
||||||
|
R_THROW(ResultUnknown);
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_calling_library_applet = std::make_shared<ILibraryAppletAccessor>(
|
||||||
|
system, m_applet->caller_applet_broker, caller_applet);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -3,11 +3,14 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/am/am_types.h"
|
||||||
|
#include "core/hle/service/cmif_types.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
struct Applet;
|
struct Applet;
|
||||||
|
class ILibraryAppletAccessor;
|
||||||
|
|
||||||
class IProcessWindingController final : public ServiceFramework<IProcessWindingController> {
|
class IProcessWindingController final : public ServiceFramework<IProcessWindingController> {
|
||||||
public:
|
public:
|
||||||
|
@ -15,10 +18,11 @@ public:
|
||||||
~IProcessWindingController() override;
|
~IProcessWindingController() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void GetLaunchReason(HLERequestContext& ctx);
|
Result GetLaunchReason(Out<AppletProcessLaunchReason> out_launch_reason);
|
||||||
void OpenCallingLibraryApplet(HLERequestContext& ctx);
|
Result OpenCallingLibraryApplet(
|
||||||
|
Out<SharedPointer<ILibraryAppletAccessor>> out_calling_library_applet);
|
||||||
|
|
||||||
const std::shared_ptr<Applet> applet;
|
const std::shared_ptr<Applet> m_applet;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
393
src/core/hle/service/am/service/self_controller.cpp
Normal file
393
src/core/hle/service/am/service/self_controller.cpp
Normal file
|
@ -0,0 +1,393 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/hle/result.h"
|
||||||
|
#include "core/hle/service/am/am_results.h"
|
||||||
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
|
#include "core/hle/service/am/service/self_controller.h"
|
||||||
|
#include "core/hle/service/caps/caps_su.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.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_, std::shared_ptr<Applet> applet,
|
||||||
|
Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger)
|
||||||
|
: ServiceFramework{system_, "ISelfController"},
|
||||||
|
m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, D<&ISelfController::Exit>, "Exit"},
|
||||||
|
{1, D<&ISelfController::LockExit>, "LockExit"},
|
||||||
|
{2, D<&ISelfController::UnlockExit>, "UnlockExit"},
|
||||||
|
{3, D<&ISelfController::EnterFatalSection>, "EnterFatalSection"},
|
||||||
|
{4, D<&ISelfController::LeaveFatalSection>, "LeaveFatalSection"},
|
||||||
|
{9, D<&ISelfController::GetLibraryAppletLaunchableEvent>, "GetLibraryAppletLaunchableEvent"},
|
||||||
|
{10, D<&ISelfController::SetScreenShotPermission>, "SetScreenShotPermission"},
|
||||||
|
{11, D<&ISelfController::SetOperationModeChangedNotification>, "SetOperationModeChangedNotification"},
|
||||||
|
{12, D<&ISelfController::SetPerformanceModeChangedNotification>, "SetPerformanceModeChangedNotification"},
|
||||||
|
{13, D<&ISelfController::SetFocusHandlingMode>, "SetFocusHandlingMode"},
|
||||||
|
{14, D<&ISelfController::SetRestartMessageEnabled>, "SetRestartMessageEnabled"},
|
||||||
|
{15, D<&ISelfController::SetScreenShotAppletIdentityInfo>, "SetScreenShotAppletIdentityInfo"},
|
||||||
|
{16, D<&ISelfController::SetOutOfFocusSuspendingEnabled>, "SetOutOfFocusSuspendingEnabled"},
|
||||||
|
{17, nullptr, "SetControllerFirmwareUpdateSection"},
|
||||||
|
{18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"},
|
||||||
|
{19, D<&ISelfController::SetAlbumImageOrientation>, "SetAlbumImageOrientation"},
|
||||||
|
{20, nullptr, "SetDesirableKeyboardLayout"},
|
||||||
|
{21, nullptr, "GetScreenShotProgramId"},
|
||||||
|
{40, D<&ISelfController::CreateManagedDisplayLayer>, "CreateManagedDisplayLayer"},
|
||||||
|
{41, D<&ISelfController::IsSystemBufferSharingEnabled>, "IsSystemBufferSharingEnabled"},
|
||||||
|
{42, D<&ISelfController::GetSystemSharedLayerHandle>, "GetSystemSharedLayerHandle"},
|
||||||
|
{43, D<&ISelfController::GetSystemSharedBufferHandle>, "GetSystemSharedBufferHandle"},
|
||||||
|
{44, D<&ISelfController::CreateManagedDisplaySeparableLayer>, "CreateManagedDisplaySeparableLayer"},
|
||||||
|
{45, nullptr, "SetManagedDisplayLayerSeparationMode"},
|
||||||
|
{46, nullptr, "SetRecordingLayerCompositionEnabled"},
|
||||||
|
{50, D<&ISelfController::SetHandlesRequestToDisplay>, "SetHandlesRequestToDisplay"},
|
||||||
|
{51, D<&ISelfController::ApproveToDisplay>, "ApproveToDisplay"},
|
||||||
|
{60, D<&ISelfController::OverrideAutoSleepTimeAndDimmingTime>, "OverrideAutoSleepTimeAndDimmingTime"},
|
||||||
|
{61, D<&ISelfController::SetMediaPlaybackState>, "SetMediaPlaybackState"},
|
||||||
|
{62, D<&ISelfController::SetIdleTimeDetectionExtension>, "SetIdleTimeDetectionExtension"},
|
||||||
|
{63, D<&ISelfController::GetIdleTimeDetectionExtension>, "GetIdleTimeDetectionExtension"},
|
||||||
|
{64, nullptr, "SetInputDetectionSourceSet"},
|
||||||
|
{65, D<&ISelfController::ReportUserIsActive>, "ReportUserIsActive"},
|
||||||
|
{66, nullptr, "GetCurrentIlluminance"},
|
||||||
|
{67, nullptr, "IsIlluminanceAvailable"},
|
||||||
|
{68, D<&ISelfController::SetAutoSleepDisabled>, "SetAutoSleepDisabled"},
|
||||||
|
{69, D<&ISelfController::IsAutoSleepDisabled>, "IsAutoSleepDisabled"},
|
||||||
|
{70, nullptr, "ReportMultimediaError"},
|
||||||
|
{71, nullptr, "GetCurrentIlluminanceEx"},
|
||||||
|
{72, D<&ISelfController::SetInputDetectionPolicy>, "SetInputDetectionPolicy"},
|
||||||
|
{80, nullptr, "SetWirelessPriorityMode"},
|
||||||
|
{90, D<&ISelfController::GetAccumulatedSuspendedTickValue>, "GetAccumulatedSuspendedTickValue"},
|
||||||
|
{91, D<&ISelfController::GetAccumulatedSuspendedTickChangedEvent>, "GetAccumulatedSuspendedTickChangedEvent"},
|
||||||
|
{100, D<&ISelfController::SetAlbumImageTakenNotificationEnabled>, "SetAlbumImageTakenNotificationEnabled"},
|
||||||
|
{110, nullptr, "SetApplicationAlbumUserData"},
|
||||||
|
{120, D<&ISelfController::SaveCurrentScreenshot>, "SaveCurrentScreenshot"},
|
||||||
|
{130, D<&ISelfController::SetRecordVolumeMuted>, "SetRecordVolumeMuted"},
|
||||||
|
{1000, nullptr, "GetDebugStorageChannel"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
ISelfController::~ISelfController() = default;
|
||||||
|
|
||||||
|
Result ISelfController::Exit() {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
system.Exit();
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::LockExit() {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
system.SetExitLocked(true);
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::UnlockExit() {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
system.SetExitLocked(false);
|
||||||
|
|
||||||
|
if (system.GetExitRequested()) {
|
||||||
|
system.Exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::EnterFatalSection() {
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
|
||||||
|
m_applet->fatal_section_count++;
|
||||||
|
LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", m_applet->fatal_section_count);
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::LeaveFatalSection() {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
// Entry and exit of fatal sections must be balanced.
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
R_UNLESS(m_applet->fatal_section_count > 0, AM::ResultFatalSectionCountImbalance);
|
||||||
|
m_applet->fatal_section_count--;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::GetLibraryAppletLaunchableEvent(
|
||||||
|
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
m_applet->library_applet_launchable_event.Signal();
|
||||||
|
*out_event = m_applet->library_applet_launchable_event.GetHandle();
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::SetScreenShotPermission(ScreenshotPermission screen_shot_permission) {
|
||||||
|
LOG_DEBUG(Service_AM, "called, permission={}", screen_shot_permission);
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->screenshot_permission = screen_shot_permission;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::SetOperationModeChangedNotification(bool enabled) {
|
||||||
|
LOG_INFO(Service_AM, "called, enabled={}", enabled);
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->operation_mode_changed_notification_enabled = enabled;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::SetPerformanceModeChangedNotification(bool enabled) {
|
||||||
|
LOG_INFO(Service_AM, "called, enabled={}", enabled);
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->performance_mode_changed_notification_enabled = enabled;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::SetFocusHandlingMode(bool notify, bool background, bool suspend) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called, notify={} background={} suspend={}", notify,
|
||||||
|
background, suspend);
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->focus_handling_mode = {notify, background, suspend};
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::SetRestartMessageEnabled(bool enabled) {
|
||||||
|
LOG_INFO(Service_AM, "called, enabled={}", enabled);
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->restart_message_enabled = enabled;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::SetScreenShotAppletIdentityInfo(
|
||||||
|
AppletIdentityInfo screen_shot_applet_identity_info) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->screen_shot_identity = screen_shot_applet_identity_info;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::SetOutOfFocusSuspendingEnabled(bool enabled) {
|
||||||
|
LOG_INFO(Service_AM, "called, enabled={}", enabled);
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->out_of_focus_suspension_enabled = enabled;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::SetAlbumImageOrientation(
|
||||||
|
Capture::AlbumImageOrientation album_image_orientation) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called, orientation={}", album_image_orientation);
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->album_image_orientation = album_image_orientation;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::IsSystemBufferSharingEnabled() {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
R_SUCCEED_IF(m_applet->system_buffer_manager.Initialize(
|
||||||
|
&m_nvnflinger, m_process, m_applet->applet_id, m_applet->library_applet_mode));
|
||||||
|
R_THROW(VI::ResultOperationFailed);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::GetSystemSharedBufferHandle(Out<u64> out_buffer_id) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
R_TRY(this->IsSystemBufferSharingEnabled());
|
||||||
|
|
||||||
|
u64 layer_id;
|
||||||
|
m_applet->system_buffer_manager.GetSystemSharedLayerHandle(out_buffer_id, &layer_id);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::GetSystemSharedLayerHandle(Out<u64> out_buffer_id, Out<u64> out_layer_id) {
|
||||||
|
LOG_INFO(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
R_TRY(this->IsSystemBufferSharingEnabled());
|
||||||
|
|
||||||
|
m_applet->system_buffer_manager.GetSystemSharedLayerHandle(out_buffer_id, out_layer_id);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::CreateManagedDisplayLayer(Out<u64> out_layer_id) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
|
||||||
|
m_applet->managed_layer_holder.Initialize(&m_nvnflinger);
|
||||||
|
m_applet->managed_layer_holder.CreateManagedDisplayLayer(out_layer_id);
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::CreateManagedDisplaySeparableLayer(Out<u64> out_layer_id,
|
||||||
|
Out<u64> out_recording_layer_id) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
m_applet->managed_layer_holder.Initialize(&m_nvnflinger);
|
||||||
|
m_applet->managed_layer_holder.CreateManagedDisplaySeparableLayer(out_layer_id,
|
||||||
|
out_recording_layer_id);
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::SetHandlesRequestToDisplay(bool enable) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called, enable={}", enable);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::ApproveToDisplay() {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::SetMediaPlaybackState(bool state) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called, state={}", state);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::OverrideAutoSleepTimeAndDimmingTime(s32 a, s32 b, s32 c, s32 d) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called, a={}, b={}, c={}, d={}", a, b, c, d);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::SetIdleTimeDetectionExtension(
|
||||||
|
IdleTimeDetectionExtension idle_time_detection_extension) {
|
||||||
|
LOG_DEBUG(Service_AM, "(STUBBED) called extension={}", idle_time_detection_extension);
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->idle_time_detection_extension = idle_time_detection_extension;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::GetIdleTimeDetectionExtension(
|
||||||
|
Out<IdleTimeDetectionExtension> out_idle_time_detection_extension) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
*out_idle_time_detection_extension = m_applet->idle_time_detection_extension;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::ReportUserIsActive() {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::SetAutoSleepDisabled(bool is_auto_sleep_disabled) {
|
||||||
|
LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", is_auto_sleep_disabled);
|
||||||
|
|
||||||
|
// 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().
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->auto_sleep_disabled = is_auto_sleep_disabled;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::IsAutoSleepDisabled(Out<bool> out_is_auto_sleep_disabled) {
|
||||||
|
LOG_DEBUG(Service_AM, "called.");
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
*out_is_auto_sleep_disabled = m_applet->auto_sleep_disabled;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::SetInputDetectionPolicy(InputDetectionPolicy input_detection_policy) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::GetAccumulatedSuspendedTickValue(
|
||||||
|
Out<u64> out_accumulated_suspended_tick_value) {
|
||||||
|
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.
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
*out_accumulated_suspended_tick_value = m_applet->suspended_ticks;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::GetAccumulatedSuspendedTickChangedEvent(
|
||||||
|
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||||
|
LOG_DEBUG(Service_AM, "called.");
|
||||||
|
|
||||||
|
*out_event = m_applet->accumulated_suspended_tick_changed_event.GetHandle();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::SetAlbumImageTakenNotificationEnabled(bool enabled) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called. enabled={}", enabled);
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->album_image_taken_notification_enabled = enabled;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::SaveCurrentScreenshot(Capture::AlbumReportOption album_report_option) {
|
||||||
|
LOG_INFO(Service_AM, "called, report_option={}", album_report_option);
|
||||||
|
|
||||||
|
const auto screenshot_service =
|
||||||
|
system.ServiceManager().GetService<Service::Capture::IScreenShotApplicationService>(
|
||||||
|
"caps:su");
|
||||||
|
|
||||||
|
if (screenshot_service) {
|
||||||
|
screenshot_service->CaptureAndSaveScreenshot(album_report_option);
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::SetRecordVolumeMuted(bool muted) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called. muted={}", muted);
|
||||||
|
|
||||||
|
std::scoped_lock lk{m_applet->lock};
|
||||||
|
m_applet->record_volume_muted = muted;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
72
src/core/hle/service/am/service/self_controller.h
Normal file
72
src/core/hle/service/am/service/self_controller.h
Normal file
|
@ -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/am/am_types.h"
|
||||||
|
#include "core/hle/service/cmif_types.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
class KReadableEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::Capture {
|
||||||
|
enum class AlbumImageOrientation;
|
||||||
|
enum class AlbumReportOption;
|
||||||
|
} // namespace Service::Capture
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
|
class ISelfController final : public ServiceFramework<ISelfController> {
|
||||||
|
public:
|
||||||
|
explicit ISelfController(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
|
Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger);
|
||||||
|
~ISelfController() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result Exit();
|
||||||
|
Result LockExit();
|
||||||
|
Result UnlockExit();
|
||||||
|
Result EnterFatalSection();
|
||||||
|
Result LeaveFatalSection();
|
||||||
|
Result GetLibraryAppletLaunchableEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
|
Result SetScreenShotPermission(ScreenshotPermission screen_shot_permission);
|
||||||
|
Result SetOperationModeChangedNotification(bool enabled);
|
||||||
|
Result SetPerformanceModeChangedNotification(bool enabled);
|
||||||
|
Result SetFocusHandlingMode(bool notify, bool background, bool suspend);
|
||||||
|
Result SetRestartMessageEnabled(bool enabled);
|
||||||
|
Result SetScreenShotAppletIdentityInfo(AppletIdentityInfo screen_shot_applet_identity_info);
|
||||||
|
Result SetOutOfFocusSuspendingEnabled(bool enabled);
|
||||||
|
Result SetAlbumImageOrientation(Capture::AlbumImageOrientation album_image_orientation);
|
||||||
|
Result IsSystemBufferSharingEnabled();
|
||||||
|
Result GetSystemSharedBufferHandle(Out<u64> out_buffer_id);
|
||||||
|
Result GetSystemSharedLayerHandle(Out<u64> out_buffer_id, Out<u64> out_layer_id);
|
||||||
|
Result CreateManagedDisplayLayer(Out<u64> out_layer_id);
|
||||||
|
Result CreateManagedDisplaySeparableLayer(Out<u64> out_layer_id,
|
||||||
|
Out<u64> out_recording_layer_id);
|
||||||
|
Result SetHandlesRequestToDisplay(bool enable);
|
||||||
|
Result ApproveToDisplay();
|
||||||
|
Result SetMediaPlaybackState(bool state);
|
||||||
|
Result OverrideAutoSleepTimeAndDimmingTime(s32 a, s32 b, s32 c, s32 d);
|
||||||
|
Result SetIdleTimeDetectionExtension(IdleTimeDetectionExtension idle_time_detection_extension);
|
||||||
|
Result GetIdleTimeDetectionExtension(
|
||||||
|
Out<IdleTimeDetectionExtension> out_idle_time_detection_extension);
|
||||||
|
Result ReportUserIsActive();
|
||||||
|
Result SetAutoSleepDisabled(bool is_auto_sleep_disabled);
|
||||||
|
Result IsAutoSleepDisabled(Out<bool> out_is_auto_sleep_disabled);
|
||||||
|
Result SetInputDetectionPolicy(InputDetectionPolicy input_detection_policy);
|
||||||
|
Result GetAccumulatedSuspendedTickValue(Out<u64> out_accumulated_suspended_tick_value);
|
||||||
|
Result GetAccumulatedSuspendedTickChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
|
Result SetAlbumImageTakenNotificationEnabled(bool enabled);
|
||||||
|
Result SaveCurrentScreenshot(Capture::AlbumReportOption album_report_option);
|
||||||
|
Result SetRecordVolumeMuted(bool muted);
|
||||||
|
|
||||||
|
Nvnflinger::Nvnflinger& m_nvnflinger;
|
||||||
|
Kernel::KProcess* const m_process;
|
||||||
|
const std::shared_ptr<Applet> m_applet;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
48
src/core/hle/service/am/service/storage.cpp
Normal file
48
src/core/hle/service/am/service/storage.cpp
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
// 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_storage.h"
|
||||||
|
#include "core/hle/service/am/service/storage.h"
|
||||||
|
#include "core/hle/service/am/service/storage_accessor.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
IStorage::IStorage(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl)
|
||||||
|
: ServiceFramework{system_, "IStorage"}, m_impl{std::move(impl)} {
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, D<&IStorage::Open>, "Open"},
|
||||||
|
{1, D<&IStorage::OpenTransferStorage>, "OpenTransferStorage"},
|
||||||
|
};
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
IStorage::IStorage(Core::System& system_, std::vector<u8>&& data)
|
||||||
|
: IStorage(system_, CreateStorage(std::move(data))) {}
|
||||||
|
|
||||||
|
IStorage::~IStorage() = default;
|
||||||
|
|
||||||
|
Result IStorage::Open(Out<SharedPointer<IStorageAccessor>> out_storage_accessor) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
R_UNLESS(m_impl->GetHandle() == nullptr, AM::ResultInvalidStorageType);
|
||||||
|
|
||||||
|
*out_storage_accessor = std::make_shared<IStorageAccessor>(system, m_impl);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IStorage::OpenTransferStorage(
|
||||||
|
Out<SharedPointer<ITransferStorageAccessor>> out_transfer_storage_accessor) {
|
||||||
|
R_UNLESS(m_impl->GetHandle() != nullptr, AM::ResultInvalidStorageType);
|
||||||
|
|
||||||
|
*out_transfer_storage_accessor = std::make_shared<ITransferStorageAccessor>(system, m_impl);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<u8> IStorage::GetData() const {
|
||||||
|
return m_impl->GetData();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -3,29 +3,33 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/cmif_types.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
class LibraryAppletStorage;
|
class LibraryAppletStorage;
|
||||||
|
class IStorageAccessor;
|
||||||
|
class ITransferStorageAccessor;
|
||||||
|
|
||||||
class IStorage final : public ServiceFramework<IStorage> {
|
class IStorage final : public ServiceFramework<IStorage> {
|
||||||
public:
|
public:
|
||||||
explicit IStorage(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl_);
|
explicit IStorage(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl);
|
||||||
explicit IStorage(Core::System& system_, std::vector<u8>&& buffer);
|
explicit IStorage(Core::System& system_, std::vector<u8>&& buffer);
|
||||||
~IStorage() override;
|
~IStorage() override;
|
||||||
|
|
||||||
std::shared_ptr<LibraryAppletStorage> GetImpl() const {
|
std::shared_ptr<LibraryAppletStorage> GetImpl() const {
|
||||||
return impl;
|
return m_impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> GetData() const;
|
std::vector<u8> GetData() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Open(HLERequestContext& ctx);
|
Result Open(Out<SharedPointer<IStorageAccessor>> out_storage_accessor);
|
||||||
void OpenTransferStorage(HLERequestContext& ctx);
|
Result OpenTransferStorage(
|
||||||
|
Out<SharedPointer<ITransferStorageAccessor>> out_transfer_storage_accessor);
|
||||||
|
|
||||||
const std::shared_ptr<LibraryAppletStorage> impl;
|
const std::shared_ptr<LibraryAppletStorage> m_impl;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
68
src/core/hle/service/am/service/storage_accessor.cpp
Normal file
68
src/core/hle/service/am/service/storage_accessor.cpp
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
// 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/library_applet_storage.h"
|
||||||
|
#include "core/hle/service/am/service/storage_accessor.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
IStorageAccessor::IStorageAccessor(Core::System& system_,
|
||||||
|
std::shared_ptr<LibraryAppletStorage> impl)
|
||||||
|
: ServiceFramework{system_, "IStorageAccessor"}, m_impl{std::move(impl)} {
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, D<&IStorageAccessor::GetSize>, "GetSize"},
|
||||||
|
{10, D<&IStorageAccessor::Write>, "Write"},
|
||||||
|
{11, D<&IStorageAccessor::Read>, "Read"},
|
||||||
|
};
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
IStorageAccessor::~IStorageAccessor() = default;
|
||||||
|
|
||||||
|
Result IStorageAccessor::GetSize(Out<s64> out_size) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_size = m_impl->GetSize();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IStorageAccessor::Write(InBuffer<BufferAttr_HipcAutoSelect> buffer, s64 offset) {
|
||||||
|
LOG_DEBUG(Service_AM, "called, offset={} size={}", offset, buffer.size());
|
||||||
|
R_RETURN(m_impl->Write(offset, buffer.data(), buffer.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IStorageAccessor::Read(OutBuffer<BufferAttr_HipcAutoSelect> out_buffer, s64 offset) {
|
||||||
|
LOG_DEBUG(Service_AM, "called, offset={} size={}", offset, out_buffer.size());
|
||||||
|
R_RETURN(m_impl->Read(offset, out_buffer.data(), out_buffer.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
ITransferStorageAccessor::ITransferStorageAccessor(Core::System& system_,
|
||||||
|
std::shared_ptr<LibraryAppletStorage> impl)
|
||||||
|
: ServiceFramework{system_, "ITransferStorageAccessor"}, m_impl{std::move(impl)} {
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, D<&ITransferStorageAccessor::GetSize>, "GetSize"},
|
||||||
|
{1, D<&ITransferStorageAccessor::GetHandle>, "GetHandle"},
|
||||||
|
};
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
ITransferStorageAccessor::~ITransferStorageAccessor() = default;
|
||||||
|
|
||||||
|
Result ITransferStorageAccessor::GetSize(Out<s64> out_size) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_size = m_impl->GetSize();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ITransferStorageAccessor::GetHandle(Out<s64> out_size,
|
||||||
|
OutCopyHandle<Kernel::KTransferMemory> out_handle) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
*out_size = m_impl->GetSize();
|
||||||
|
*out_handle = m_impl->GetHandle();
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -3,35 +3,36 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/hle/service/am/storage.h"
|
#include "core/hle/service/am/library_applet_storage.h"
|
||||||
|
#include "core/hle/service/cmif_types.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
|
class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
|
||||||
public:
|
public:
|
||||||
explicit IStorageAccessor(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl_);
|
explicit IStorageAccessor(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl);
|
||||||
~IStorageAccessor() override;
|
~IStorageAccessor() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void GetSize(HLERequestContext& ctx);
|
Result GetSize(Out<s64> out_size);
|
||||||
void Write(HLERequestContext& ctx);
|
Result Write(InBuffer<BufferAttr_HipcAutoSelect> buffer, s64 offset);
|
||||||
void Read(HLERequestContext& ctx);
|
Result Read(OutBuffer<BufferAttr_HipcAutoSelect> out_buffer, s64 offset);
|
||||||
|
|
||||||
const std::shared_ptr<LibraryAppletStorage> impl;
|
const std::shared_ptr<LibraryAppletStorage> m_impl;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ITransferStorageAccessor final : public ServiceFramework<ITransferStorageAccessor> {
|
class ITransferStorageAccessor final : public ServiceFramework<ITransferStorageAccessor> {
|
||||||
public:
|
public:
|
||||||
explicit ITransferStorageAccessor(Core::System& system_,
|
explicit ITransferStorageAccessor(Core::System& system_,
|
||||||
std::shared_ptr<LibraryAppletStorage> impl_);
|
std::shared_ptr<LibraryAppletStorage> impl);
|
||||||
~ITransferStorageAccessor() override;
|
~ITransferStorageAccessor() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void GetSize(HLERequestContext& ctx);
|
Result GetSize(Out<s64> out_size);
|
||||||
void GetHandle(HLERequestContext& ctx);
|
Result GetHandle(Out<s64> out_size, OutCopyHandle<Kernel::KTransferMemory> out_handle);
|
||||||
|
|
||||||
const std::shared_ptr<LibraryAppletStorage> impl;
|
const std::shared_ptr<LibraryAppletStorage> m_impl;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
133
src/core/hle/service/am/service/system_applet_proxy.cpp
Normal file
133
src/core/hle/service/am/service/system_applet_proxy.cpp
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/service/applet_common_functions.h"
|
||||||
|
#include "core/hle/service/am/service/application_creator.h"
|
||||||
|
#include "core/hle/service/am/service/audio_controller.h"
|
||||||
|
#include "core/hle/service/am/service/common_state_getter.h"
|
||||||
|
#include "core/hle/service/am/service/debug_functions.h"
|
||||||
|
#include "core/hle/service/am/service/display_controller.h"
|
||||||
|
#include "core/hle/service/am/service/global_state_controller.h"
|
||||||
|
#include "core/hle/service/am/service/home_menu_functions.h"
|
||||||
|
#include "core/hle/service/am/service/library_applet_creator.h"
|
||||||
|
#include "core/hle/service/am/service/process_winding_controller.h"
|
||||||
|
#include "core/hle/service/am/service/self_controller.h"
|
||||||
|
#include "core/hle/service/am/service/system_applet_proxy.h"
|
||||||
|
#include "core/hle/service/am/service/window_controller.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
ISystemAppletProxy::ISystemAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
|
Kernel::KProcess* process,
|
||||||
|
Nvnflinger::Nvnflinger& nvnflinger)
|
||||||
|
: ServiceFramework{system_, "ISystemAppletProxy"},
|
||||||
|
m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, D<&ISystemAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
|
||||||
|
{1, D<&ISystemAppletProxy::GetSelfController>, "GetSelfController"},
|
||||||
|
{2, D<&ISystemAppletProxy::GetWindowController>, "GetWindowController"},
|
||||||
|
{3, D<&ISystemAppletProxy::GetAudioController>, "GetAudioController"},
|
||||||
|
{4, D<&ISystemAppletProxy::GetDisplayController>, "GetDisplayController"},
|
||||||
|
{10, D<&ISystemAppletProxy::GetProcessWindingController>, "GetProcessWindingController"},
|
||||||
|
{11, D<&ISystemAppletProxy::GetLibraryAppletCreator>, "GetLibraryAppletCreator"},
|
||||||
|
{20, D<&ISystemAppletProxy::GetHomeMenuFunctions>, "GetHomeMenuFunctions"},
|
||||||
|
{21, D<&ISystemAppletProxy::GetGlobalStateController>, "GetGlobalStateController"},
|
||||||
|
{22, D<&ISystemAppletProxy::GetApplicationCreator>, "GetApplicationCreator"},
|
||||||
|
{23, D<&ISystemAppletProxy::GetAppletCommonFunctions>, "GetAppletCommonFunctions"},
|
||||||
|
{1000, D<&ISystemAppletProxy::GetDebugFunctions>, "GetDebugFunctions"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
ISystemAppletProxy::~ISystemAppletProxy() = default;
|
||||||
|
|
||||||
|
Result ISystemAppletProxy::GetAudioController(
|
||||||
|
Out<SharedPointer<IAudioController>> out_audio_controller) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_audio_controller = std::make_shared<IAudioController>(system);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISystemAppletProxy::GetDisplayController(
|
||||||
|
Out<SharedPointer<IDisplayController>> out_display_controller) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_display_controller = std::make_shared<IDisplayController>(system, m_applet);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISystemAppletProxy::GetProcessWindingController(
|
||||||
|
Out<SharedPointer<IProcessWindingController>> out_process_winding_controller) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_process_winding_controller = std::make_shared<IProcessWindingController>(system, m_applet);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISystemAppletProxy::GetDebugFunctions(
|
||||||
|
Out<SharedPointer<IDebugFunctions>> out_debug_functions) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_debug_functions = std::make_shared<IDebugFunctions>(system);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISystemAppletProxy::GetWindowController(
|
||||||
|
Out<SharedPointer<IWindowController>> out_window_controller) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_window_controller = std::make_shared<IWindowController>(system, m_applet);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISystemAppletProxy::GetSelfController(
|
||||||
|
Out<SharedPointer<ISelfController>> out_self_controller) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_self_controller =
|
||||||
|
std::make_shared<ISelfController>(system, m_applet, m_process, m_nvnflinger);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISystemAppletProxy::GetCommonStateGetter(
|
||||||
|
Out<SharedPointer<ICommonStateGetter>> out_common_state_getter) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_common_state_getter = std::make_shared<ICommonStateGetter>(system, m_applet);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISystemAppletProxy::GetLibraryAppletCreator(
|
||||||
|
Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_library_applet_creator = std::make_shared<ILibraryAppletCreator>(system, m_applet);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISystemAppletProxy::GetApplicationCreator(
|
||||||
|
Out<SharedPointer<IApplicationCreator>> out_application_creator) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_application_creator = std::make_shared<IApplicationCreator>(system);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISystemAppletProxy::GetAppletCommonFunctions(
|
||||||
|
Out<SharedPointer<IAppletCommonFunctions>> out_applet_common_functions) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_applet_common_functions = std::make_shared<IAppletCommonFunctions>(system, m_applet);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISystemAppletProxy::GetHomeMenuFunctions(
|
||||||
|
Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_home_menu_functions = std::make_shared<IHomeMenuFunctions>(system, m_applet);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISystemAppletProxy::GetGlobalStateController(
|
||||||
|
Out<SharedPointer<IGlobalStateController>> out_global_state_controller) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
*out_global_state_controller = std::make_shared<IGlobalStateController>(system);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
54
src/core/hle/service/am/service/system_applet_proxy.h
Normal file
54
src/core/hle/service/am/service/system_applet_proxy.h
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/cmif_types.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
class IAppletCommonFunctions;
|
||||||
|
class IApplicationCreator;
|
||||||
|
class IAudioController;
|
||||||
|
class ICommonStateGetter;
|
||||||
|
class IDebugFunctions;
|
||||||
|
class IDisplayController;
|
||||||
|
class IHomeMenuFunctions;
|
||||||
|
class IGlobalStateController;
|
||||||
|
class ILibraryAppletCreator;
|
||||||
|
class IProcessWindingController;
|
||||||
|
class ISelfController;
|
||||||
|
class IWindowController;
|
||||||
|
|
||||||
|
class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> {
|
||||||
|
public:
|
||||||
|
explicit ISystemAppletProxy(Core::System& system, std::shared_ptr<Applet> applet,
|
||||||
|
Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger);
|
||||||
|
~ISystemAppletProxy();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result GetAudioController(Out<SharedPointer<IAudioController>> out_audio_controller);
|
||||||
|
Result GetDisplayController(Out<SharedPointer<IDisplayController>> out_display_controller);
|
||||||
|
Result GetProcessWindingController(
|
||||||
|
Out<SharedPointer<IProcessWindingController>> out_process_winding_controller);
|
||||||
|
Result GetDebugFunctions(Out<SharedPointer<IDebugFunctions>> out_debug_functions);
|
||||||
|
Result GetWindowController(Out<SharedPointer<IWindowController>> out_window_controller);
|
||||||
|
Result GetSelfController(Out<SharedPointer<ISelfController>> out_self_controller);
|
||||||
|
Result GetCommonStateGetter(Out<SharedPointer<ICommonStateGetter>> out_common_state_getter);
|
||||||
|
Result GetLibraryAppletCreator(
|
||||||
|
Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator);
|
||||||
|
Result GetApplicationCreator(Out<SharedPointer<IApplicationCreator>> out_application_creator);
|
||||||
|
Result GetAppletCommonFunctions(
|
||||||
|
Out<SharedPointer<IAppletCommonFunctions>> out_applet_common_functions);
|
||||||
|
Result GetHomeMenuFunctions(Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions);
|
||||||
|
Result GetGlobalStateController(
|
||||||
|
Out<SharedPointer<IGlobalStateController>> out_global_state_controller);
|
||||||
|
|
||||||
|
Nvnflinger::Nvnflinger& m_nvnflinger;
|
||||||
|
Kernel::KProcess* const m_process;
|
||||||
|
const std::shared_ptr<Applet> m_applet;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
86
src/core/hle/service/am/service/window_controller.cpp
Normal file
86
src/core/hle/service/am/service/window_controller.cpp
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/applet.h"
|
||||||
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
|
#include "core/hle/service/am/service/window_controller.h"
|
||||||
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
IWindowController::IWindowController(Core::System& system_, std::shared_ptr<Applet> applet)
|
||||||
|
: ServiceFramework{system_, "IWindowController"}, m_applet{std::move(applet)} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, nullptr, "CreateWindow"},
|
||||||
|
{1, D<&IWindowController::GetAppletResourceUserId>, "GetAppletResourceUserId"},
|
||||||
|
{2, D<&IWindowController::GetAppletResourceUserIdOfCallerApplet>, "GetAppletResourceUserIdOfCallerApplet"},
|
||||||
|
{10, D<&IWindowController::AcquireForegroundRights>, "AcquireForegroundRights"},
|
||||||
|
{11, D<&IWindowController::ReleaseForegroundRights>, "ReleaseForegroundRights"},
|
||||||
|
{12, D<&IWindowController::RejectToChangeIntoBackground>, "RejectToChangeIntoBackground"},
|
||||||
|
{20, D<&IWindowController::SetAppletWindowVisibility>, "SetAppletWindowVisibility"},
|
||||||
|
{21, D<&IWindowController::SetAppletGpuTimeSlice>, "SetAppletGpuTimeSlice"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
IWindowController::~IWindowController() = default;
|
||||||
|
|
||||||
|
Result IWindowController::GetAppletResourceUserId(Out<AppletResourceUserId> out_aruid) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
*out_aruid = m_applet->aruid;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IWindowController::GetAppletResourceUserIdOfCallerApplet(
|
||||||
|
Out<AppletResourceUserId> out_aruid) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
|
||||||
|
if (auto caller_applet = m_applet->caller_applet.lock(); caller_applet != nullptr) {
|
||||||
|
*out_aruid = caller_applet->aruid;
|
||||||
|
} else {
|
||||||
|
*out_aruid = AppletResourceUserId{};
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IWindowController::AcquireForegroundRights() {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IWindowController::ReleaseForegroundRights() {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IWindowController::RejectToChangeIntoBackground() {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IWindowController::SetAppletWindowVisibility(bool visible) {
|
||||||
|
m_applet->system_buffer_manager.SetWindowVisibility(visible);
|
||||||
|
m_applet->hid_registration.EnableAppletToGetInput(visible);
|
||||||
|
|
||||||
|
if (visible) {
|
||||||
|
m_applet->message_queue.PushMessage(AppletMessage::ChangeIntoForeground);
|
||||||
|
m_applet->focus_state = FocusState::InFocus;
|
||||||
|
} else {
|
||||||
|
m_applet->focus_state = FocusState::NotInFocus;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_applet->message_queue.PushMessage(AppletMessage::FocusStateChanged);
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IWindowController::SetAppletGpuTimeSlice(s64 time_slice) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called, time_slice={}", time_slice);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
30
src/core/hle/service/am/service/window_controller.h
Normal file
30
src/core/hle/service/am/service/window_controller.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/cmif_types.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
|
class IWindowController final : public ServiceFramework<IWindowController> {
|
||||||
|
public:
|
||||||
|
explicit IWindowController(Core::System& system_, std::shared_ptr<Applet> applet);
|
||||||
|
~IWindowController() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result GetAppletResourceUserId(Out<AppletResourceUserId> out_aruid);
|
||||||
|
Result GetAppletResourceUserIdOfCallerApplet(Out<AppletResourceUserId> out_aruid);
|
||||||
|
Result AcquireForegroundRights();
|
||||||
|
Result ReleaseForegroundRights();
|
||||||
|
Result RejectToChangeIntoBackground();
|
||||||
|
Result SetAppletWindowVisibility(bool visible);
|
||||||
|
Result SetAppletGpuTimeSlice(s64 time_slice);
|
||||||
|
|
||||||
|
const std::shared_ptr<Applet> m_applet;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -1,20 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "core/hle/service/service.h"
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
class System;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Service::AM {
|
|
||||||
|
|
||||||
class SPSM final : public ServiceFramework<SPSM> {
|
|
||||||
public:
|
|
||||||
explicit SPSM(Core::System& system_);
|
|
||||||
~SPSM() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue