8 changed files with 590 additions and 658 deletions
-
4src/core/CMakeLists.txt
-
38src/core/hle/service/am/am_types.h
-
4src/core/hle/service/am/applet.h
-
594src/core/hle/service/am/application_functions.cpp
-
58src/core/hle/service/am/application_functions.h
-
465src/core/hle/service/am/service/application_functions.cpp
-
83src/core/hle/service/am/service/application_functions.h
-
2src/core/hle/service/am/service/application_proxy.cpp
@ -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 |
|||
@ -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/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
|
|||
@ -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 |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue