8 changed files with 408 additions and 387 deletions
-
4src/core/CMakeLists.txt
-
338src/core/hle/service/am/library_applet_self_accessor.cpp
-
44src/core/hle/service/am/library_applet_self_accessor.h
-
1src/core/hle/service/am/service/application_proxy.cpp
-
2src/core/hle/service/am/service/library_applet_proxy.cpp
-
322src/core/hle/service/am/service/library_applet_self_accessor.cpp
-
83src/core/hle/service/am/service/library_applet_self_accessor.h
-
1src/core/hle/service/am/service/system_applet_proxy.cpp
@ -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 |
|||
@ -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/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 |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue