am: migrate global state to per-applet state structure
This commit is contained in:
parent
3155f4e96d
commit
182137a9a4
|
@ -392,6 +392,7 @@ struct System::Impl {
|
||||||
// All threads are started, begin main process execution, now that we're in the clear.
|
// All threads are started, begin main process execution, now that we're in the clear.
|
||||||
main_process->Run(load_parameters->main_thread_priority,
|
main_process->Run(load_parameters->main_thread_priority,
|
||||||
load_parameters->main_thread_stack_size);
|
load_parameters->main_thread_stack_size);
|
||||||
|
main_process->Close();
|
||||||
|
|
||||||
if (Settings::values.gamecard_inserted) {
|
if (Settings::values.gamecard_inserted) {
|
||||||
if (Settings::values.gamecard_current_game) {
|
if (Settings::values.gamecard_current_game) {
|
||||||
|
@ -886,10 +887,6 @@ void System::SetFrontendAppletSet(Service::AM::Frontend::FrontendAppletSet&& set
|
||||||
impl->frontend_applets.SetFrontendAppletSet(std::move(set));
|
impl->frontend_applets.SetFrontendAppletSet(std::move(set));
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::SetDefaultAppletFrontendSet() {
|
|
||||||
impl->frontend_applets.SetDefaultAppletFrontendSet();
|
|
||||||
}
|
|
||||||
|
|
||||||
Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() {
|
Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() {
|
||||||
return impl->frontend_applets;
|
return impl->frontend_applets;
|
||||||
}
|
}
|
||||||
|
@ -898,6 +895,10 @@ const Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHold
|
||||||
return impl->frontend_applets;
|
return impl->frontend_applets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Service::AM::AppletManager& System::GetAppletManager() {
|
||||||
|
return impl->applet_manager;
|
||||||
|
}
|
||||||
|
|
||||||
void System::SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider) {
|
void System::SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider) {
|
||||||
impl->content_provider = std::move(provider);
|
impl->content_provider = std::move(provider);
|
||||||
}
|
}
|
||||||
|
|
|
@ -350,12 +350,13 @@ public:
|
||||||
u64 main_region_size);
|
u64 main_region_size);
|
||||||
|
|
||||||
void SetFrontendAppletSet(Service::AM::Frontend::FrontendAppletSet&& set);
|
void SetFrontendAppletSet(Service::AM::Frontend::FrontendAppletSet&& set);
|
||||||
void SetDefaultAppletFrontendSet();
|
|
||||||
|
|
||||||
[[nodiscard]] Service::AM::Frontend::FrontendAppletHolder& GetFrontendAppletHolder();
|
[[nodiscard]] Service::AM::Frontend::FrontendAppletHolder& GetFrontendAppletHolder();
|
||||||
[[nodiscard]] const Service::AM::Frontend::FrontendAppletHolder& GetFrontendAppletHolder()
|
[[nodiscard]] const Service::AM::Frontend::FrontendAppletHolder& GetFrontendAppletHolder()
|
||||||
const;
|
const;
|
||||||
|
|
||||||
|
[[nodiscard]] Service::AM::AppletManager& GetAppletManager();
|
||||||
|
|
||||||
void SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider);
|
void SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider);
|
||||||
|
|
||||||
[[nodiscard]] FileSys::ContentProvider& GetContentProvider();
|
[[nodiscard]] FileSys::ContentProvider& GetContentProvider();
|
||||||
|
|
|
@ -97,8 +97,14 @@ struct KernelCore::Impl {
|
||||||
RegisterHostThread(nullptr);
|
RegisterHostThread(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminateApplicationProcess() {
|
void TerminateAllProcesses() {
|
||||||
application_process.load()->Terminate();
|
std::scoped_lock lk{process_list_lock};
|
||||||
|
for (auto& process : process_list) {
|
||||||
|
process->Terminate();
|
||||||
|
process->Close();
|
||||||
|
process = nullptr;
|
||||||
|
}
|
||||||
|
process_list.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shutdown() {
|
void Shutdown() {
|
||||||
|
@ -107,18 +113,9 @@ struct KernelCore::Impl {
|
||||||
|
|
||||||
CloseServices();
|
CloseServices();
|
||||||
|
|
||||||
auto* old_process = application_process.exchange(nullptr);
|
if (application_process) {
|
||||||
if (old_process) {
|
application_process->Close();
|
||||||
old_process->Close();
|
application_process = nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
std::scoped_lock lk{process_list_lock};
|
|
||||||
for (auto* const process : process_list) {
|
|
||||||
process->Terminate();
|
|
||||||
process->Close();
|
|
||||||
}
|
|
||||||
process_list.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
next_object_id = 0;
|
next_object_id = 0;
|
||||||
|
@ -354,6 +351,7 @@ struct KernelCore::Impl {
|
||||||
|
|
||||||
void MakeApplicationProcess(KProcess* process) {
|
void MakeApplicationProcess(KProcess* process) {
|
||||||
application_process = process;
|
application_process = process;
|
||||||
|
application_process->Open();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline thread_local u8 host_thread_id = UINT8_MAX;
|
static inline thread_local u8 host_thread_id = UINT8_MAX;
|
||||||
|
@ -779,7 +777,7 @@ struct KernelCore::Impl {
|
||||||
// Lists all processes that exist in the current session.
|
// Lists all processes that exist in the current session.
|
||||||
std::mutex process_list_lock;
|
std::mutex process_list_lock;
|
||||||
std::vector<KProcess*> process_list;
|
std::vector<KProcess*> process_list;
|
||||||
std::atomic<KProcess*> application_process{};
|
KProcess* application_process{};
|
||||||
std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context;
|
std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context;
|
||||||
std::unique_ptr<Kernel::KHardwareTimer> hardware_timer;
|
std::unique_ptr<Kernel::KHardwareTimer> hardware_timer;
|
||||||
|
|
||||||
|
@ -1243,7 +1241,7 @@ void KernelCore::SuspendApplication(bool suspended) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void KernelCore::ShutdownCores() {
|
void KernelCore::ShutdownCores() {
|
||||||
impl->TerminateApplicationProcess();
|
impl->TerminateAllProcesses();
|
||||||
|
|
||||||
KScopedSchedulerLock lk{*this};
|
KScopedSchedulerLock lk{*this};
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#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_ae.h"
|
||||||
#include "core/hle/service/am/applet_message_queue.h"
|
|
||||||
#include "core/hle/service/am/applet_oe.h"
|
#include "core/hle/service/am/applet_oe.h"
|
||||||
#include "core/hle/service/am/idle.h"
|
#include "core/hle/service/am/idle.h"
|
||||||
#include "core/hle/service/am/omm.h"
|
#include "core/hle/service/am/omm.h"
|
||||||
|
@ -13,13 +12,12 @@
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) {
|
void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) {
|
||||||
auto message_queue = std::make_shared<AppletMessageQueue>(system);
|
|
||||||
auto server_manager = std::make_unique<ServerManager>(system);
|
auto server_manager = std::make_unique<ServerManager>(system);
|
||||||
|
|
||||||
server_manager->RegisterNamedService(
|
server_manager->RegisterNamedService("appletAE",
|
||||||
"appletAE", std::make_shared<AppletAE>(nvnflinger, message_queue, system));
|
std::make_shared<AppletAE>(nvnflinger, system));
|
||||||
server_manager->RegisterNamedService(
|
server_manager->RegisterNamedService("appletOE",
|
||||||
"appletOE", std::make_shared<AppletOE>(nvnflinger, message_queue, system));
|
std::make_shared<AppletOE>(nvnflinger, system));
|
||||||
server_manager->RegisterNamedService("idle:sys", std::make_shared<IdleSys>(system));
|
server_manager->RegisterNamedService("idle:sys", std::make_shared<IdleSys>(system));
|
||||||
server_manager->RegisterNamedService("omm", std::make_shared<OMM>(system));
|
server_manager->RegisterNamedService("omm", std::make_shared<OMM>(system));
|
||||||
server_manager->RegisterNamedService("spsm", std::make_shared<SPSM>(system));
|
server_manager->RegisterNamedService("spsm", std::make_shared<SPSM>(system));
|
||||||
|
|
|
@ -10,5 +10,6 @@ namespace Service::AM {
|
||||||
constexpr Result ResultNoDataInChannel{ErrorModule::AM, 2};
|
constexpr Result ResultNoDataInChannel{ErrorModule::AM, 2};
|
||||||
constexpr Result ResultNoMessages{ErrorModule::AM, 3};
|
constexpr Result ResultNoMessages{ErrorModule::AM, 3};
|
||||||
constexpr Result ResultInvalidOffset{ErrorModule::AM, 503};
|
constexpr Result ResultInvalidOffset{ErrorModule::AM, 503};
|
||||||
|
constexpr Result ResultFatalSectionCountImbalance{ErrorModule::AM, 512};
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|
|
@ -2,40 +2,15 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "core/hle/service/am/applet_ae.h"
|
#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/library_applet_proxy.h"
|
||||||
#include "core/hle/service/am/system_applet_proxy.h"
|
#include "core/hle/service/am/system_applet_proxy.h"
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
void AppletAE::OpenSystemAppletProxy(HLERequestContext& ctx) {
|
AppletAE::AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_)
|
||||||
LOG_DEBUG(Service_AM, "called");
|
: ServiceFramework{system_, "appletAE"}, nvnflinger{nvnflinger_} {
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<ISystemAppletProxy>(nvnflinger, msg_queue, system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletAE::OpenLibraryAppletProxy(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<ILibraryAppletProxy>(nvnflinger, msg_queue, system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletAE::OpenLibraryAppletProxyOld(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<ILibraryAppletProxy>(nvnflinger, msg_queue, system);
|
|
||||||
}
|
|
||||||
|
|
||||||
AppletAE::AppletAE(Nvnflinger::Nvnflinger& nvnflinger_,
|
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_)
|
|
||||||
: ServiceFramework{system_, "appletAE"}, nvnflinger{nvnflinger_},
|
|
||||||
msg_queue{std::move(msg_queue_)} {
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"},
|
{100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"},
|
||||||
|
@ -54,8 +29,45 @@ AppletAE::AppletAE(Nvnflinger::Nvnflinger& nvnflinger_,
|
||||||
|
|
||||||
AppletAE::~AppletAE() = default;
|
AppletAE::~AppletAE() = default;
|
||||||
|
|
||||||
const std::shared_ptr<AppletMessageQueue>& AppletAE::GetMessageQueue() const {
|
void AppletAE::OpenSystemAppletProxy(HLERequestContext& ctx) {
|
||||||
return msg_queue;
|
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
|
} // namespace Service::AM
|
||||||
|
|
|
@ -18,23 +18,21 @@ class Nvnflinger;
|
||||||
|
|
||||||
namespace AM {
|
namespace AM {
|
||||||
|
|
||||||
class AppletMessageQueue;
|
struct Applet;
|
||||||
|
|
||||||
class AppletAE final : public ServiceFramework<AppletAE> {
|
class AppletAE final : public ServiceFramework<AppletAE> {
|
||||||
public:
|
public:
|
||||||
explicit AppletAE(Nvnflinger::Nvnflinger& nvnflinger_,
|
explicit AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_);
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_);
|
|
||||||
~AppletAE() override;
|
~AppletAE() override;
|
||||||
|
|
||||||
const std::shared_ptr<AppletMessageQueue>& GetMessageQueue() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OpenSystemAppletProxy(HLERequestContext& ctx);
|
void OpenSystemAppletProxy(HLERequestContext& ctx);
|
||||||
void OpenLibraryAppletProxy(HLERequestContext& ctx);
|
void OpenLibraryAppletProxy(HLERequestContext& ctx);
|
||||||
void OpenLibraryAppletProxyOld(HLERequestContext& ctx);
|
void OpenLibraryAppletProxyOld(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
std::shared_ptr<Applet> GetAppletFromContext(HLERequestContext& ctx);
|
||||||
|
|
||||||
Nvnflinger::Nvnflinger& nvnflinger;
|
Nvnflinger::Nvnflinger& nvnflinger;
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace AM
|
} // namespace AM
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
// 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/applet.h"
|
||||||
#include "core/hle/service/am/applet_common_functions.h"
|
#include "core/hle/service/am/applet_common_functions.h"
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_)
|
IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_,
|
||||||
: ServiceFramework{system_, "IAppletCommonFunctions"} {
|
std::shared_ptr<Applet> applet_)
|
||||||
|
: ServiceFramework{system_, "IAppletCommonFunctions"}, applet{std::move(applet_)} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, nullptr, "SetTerminateResult"},
|
{0, nullptr, "SetTerminateResult"},
|
||||||
|
@ -40,6 +42,11 @@ IAppletCommonFunctions::~IAppletCommonFunctions() = default;
|
||||||
void IAppletCommonFunctions::SetCpuBoostRequestPriority(HLERequestContext& ctx) {
|
void IAppletCommonFunctions::SetCpuBoostRequestPriority(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->cpu_boost_request_priority = rp.Pop<s32>();
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,17 @@
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
class IAppletCommonFunctions final : public ServiceFramework<IAppletCommonFunctions> {
|
class IAppletCommonFunctions final : public ServiceFramework<IAppletCommonFunctions> {
|
||||||
public:
|
public:
|
||||||
explicit IAppletCommonFunctions(Core::System& system_);
|
explicit IAppletCommonFunctions(Core::System& system_, std::shared_ptr<Applet> applet_);
|
||||||
~IAppletCommonFunctions() override;
|
~IAppletCommonFunctions() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetCpuBoostRequestPriority(HLERequestContext& ctx);
|
void SetCpuBoostRequestPriority(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
const std::shared_ptr<Applet> applet;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|
|
@ -294,8 +294,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::FocusStateChanged);
|
|
||||||
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
|
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
|
||||||
|
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
||||||
applet->focus_state = FocusState::InFocus;
|
applet->focus_state = FocusState::InFocus;
|
||||||
|
|
||||||
this->InsertApplet(std::move(applet));
|
this->InsertApplet(std::move(applet));
|
||||||
|
|
|
@ -26,11 +26,15 @@ Kernel::KReadableEvent& AppletMessageQueue::GetOperationModeChangedEvent() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppletMessageQueue::PushMessage(AppletMessage msg) {
|
void AppletMessageQueue::PushMessage(AppletMessage msg) {
|
||||||
messages.push(msg);
|
{
|
||||||
|
std::scoped_lock lk{lock};
|
||||||
|
messages.push(msg);
|
||||||
|
}
|
||||||
on_new_message->Signal();
|
on_new_message->Signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() {
|
AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() {
|
||||||
|
std::scoped_lock lk{lock};
|
||||||
if (messages.empty()) {
|
if (messages.empty()) {
|
||||||
on_new_message->Clear();
|
on_new_message->Clear();
|
||||||
return AppletMessage::None;
|
return AppletMessage::None;
|
||||||
|
@ -44,6 +48,7 @@ AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t AppletMessageQueue::GetMessageCount() const {
|
std::size_t AppletMessageQueue::GetMessageCount() const {
|
||||||
|
std::scoped_lock lk{lock};
|
||||||
return messages.size();
|
return messages.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,7 @@ private:
|
||||||
Kernel::KEvent* on_new_message;
|
Kernel::KEvent* on_new_message;
|
||||||
Kernel::KEvent* on_operation_mode_changed;
|
Kernel::KEvent* on_operation_mode_changed;
|
||||||
|
|
||||||
|
mutable std::mutex lock;
|
||||||
std::queue<AppletMessage> messages;
|
std::queue<AppletMessage> messages;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2,24 +2,15 @@
|
||||||
// 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_manager.h"
|
||||||
#include "core/hle/service/am/applet_oe.h"
|
#include "core/hle/service/am/applet_oe.h"
|
||||||
#include "core/hle/service/am/application_proxy.h"
|
#include "core/hle/service/am/application_proxy.h"
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
void AppletOE::OpenApplicationProxy(HLERequestContext& ctx) {
|
AppletOE::AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_)
|
||||||
LOG_DEBUG(Service_AM, "called");
|
: ServiceFramework{system_, "appletOE"}, nvnflinger{nvnflinger_} {
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IApplicationProxy>(nvnflinger, msg_queue, system);
|
|
||||||
}
|
|
||||||
|
|
||||||
AppletOE::AppletOE(Nvnflinger::Nvnflinger& nvnflinger_,
|
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_)
|
|
||||||
: ServiceFramework{system_, "appletOE"}, nvnflinger{nvnflinger_},
|
|
||||||
msg_queue{std::move(msg_queue_)} {
|
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"},
|
{0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"},
|
||||||
};
|
};
|
||||||
|
@ -28,8 +19,24 @@ AppletOE::AppletOE(Nvnflinger::Nvnflinger& nvnflinger_,
|
||||||
|
|
||||||
AppletOE::~AppletOE() = default;
|
AppletOE::~AppletOE() = default;
|
||||||
|
|
||||||
const std::shared_ptr<AppletMessageQueue>& AppletOE::GetMessageQueue() const {
|
void AppletOE::OpenApplicationProxy(HLERequestContext& ctx) {
|
||||||
return msg_queue;
|
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
|
} // namespace Service::AM
|
||||||
|
|
|
@ -18,21 +18,19 @@ class Nvnflinger;
|
||||||
|
|
||||||
namespace AM {
|
namespace AM {
|
||||||
|
|
||||||
class AppletMessageQueue;
|
struct Applet;
|
||||||
|
|
||||||
class AppletOE final : public ServiceFramework<AppletOE> {
|
class AppletOE final : public ServiceFramework<AppletOE> {
|
||||||
public:
|
public:
|
||||||
explicit AppletOE(Nvnflinger::Nvnflinger& nvnflinger_,
|
explicit AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_);
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_);
|
|
||||||
~AppletOE() override;
|
~AppletOE() override;
|
||||||
|
|
||||||
const std::shared_ptr<AppletMessageQueue>& GetMessageQueue() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OpenApplicationProxy(HLERequestContext& ctx);
|
void OpenApplicationProxy(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
std::shared_ptr<Applet> GetAppletFromContext(HLERequestContext& ctx);
|
||||||
|
|
||||||
Nvnflinger::Nvnflinger& nvnflinger;
|
Nvnflinger::Nvnflinger& nvnflinger;
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace AM
|
} // namespace AM
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "core/file_sys/savedata_factory.h"
|
#include "core/file_sys/savedata_factory.h"
|
||||||
#include "core/hle/service/acc/profile_manager.h"
|
#include "core/hle/service/acc/profile_manager.h"
|
||||||
#include "core/hle/service/am/am_results.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/application_functions.h"
|
||||||
#include "core/hle/service/am/storage.h"
|
#include "core/hle/service/am/storage.h"
|
||||||
#include "core/hle/service/filesystem/filesystem.h"
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||||
|
@ -24,19 +25,8 @@ enum class LaunchParameterKind : u32 {
|
||||||
AccountPreselectedUser = 2,
|
AccountPreselectedUser = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr u32 LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC = 0xC79497CA;
|
IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet_)
|
||||||
|
: ServiceFramework{system_, "IApplicationFunctions"}, applet{std::move(applet_)} {
|
||||||
struct LaunchParameterAccountPreselectedUser {
|
|
||||||
u32_le magic;
|
|
||||||
u32_le is_account_selected;
|
|
||||||
Common::UUID current_user;
|
|
||||||
INSERT_PADDING_BYTES(0x70);
|
|
||||||
};
|
|
||||||
static_assert(sizeof(LaunchParameterAccountPreselectedUser) == 0x88);
|
|
||||||
|
|
||||||
IApplicationFunctions::IApplicationFunctions(Core::System& system_)
|
|
||||||
: ServiceFramework{system_, "IApplicationFunctions"},
|
|
||||||
service_context{system, "IApplicationFunctions"} {
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"},
|
{1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"},
|
||||||
|
@ -105,27 +95,16 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
RegisterHandlers(functions);
|
RegisterHandlers(functions);
|
||||||
|
|
||||||
gpu_error_detected_event =
|
|
||||||
service_context.CreateEvent("IApplicationFunctions:GpuErrorDetectedSystemEvent");
|
|
||||||
friend_invitation_storage_channel_event =
|
|
||||||
service_context.CreateEvent("IApplicationFunctions:FriendInvitationStorageChannelEvent");
|
|
||||||
notification_storage_channel_event =
|
|
||||||
service_context.CreateEvent("IApplicationFunctions:NotificationStorageChannelEvent");
|
|
||||||
health_warning_disappeared_system_event =
|
|
||||||
service_context.CreateEvent("IApplicationFunctions:HealthWarningDisappearedSystemEvent");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IApplicationFunctions::~IApplicationFunctions() {
|
IApplicationFunctions::~IApplicationFunctions() = default;
|
||||||
service_context.CloseEvent(gpu_error_detected_event);
|
|
||||||
service_context.CloseEvent(friend_invitation_storage_channel_event);
|
|
||||||
service_context.CloseEvent(notification_storage_channel_event);
|
|
||||||
service_context.CloseEvent(health_warning_disappeared_system_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IApplicationFunctions::EnableApplicationCrashReport(HLERequestContext& ctx) {
|
void IApplicationFunctions::EnableApplicationCrashReport(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->application_crash_report_enabled = true;
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
@ -157,6 +136,10 @@ void IApplicationFunctions::SetApplicationCopyrightVisibility(HLERequestContext&
|
||||||
void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) {
|
void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
@ -164,6 +147,10 @@ void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(HLEReques
|
||||||
void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) {
|
void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
@ -171,6 +158,11 @@ void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(HLERequestC
|
||||||
void IApplicationFunctions::BeginBlockingHomeButton(HLERequestContext& ctx) {
|
void IApplicationFunctions::BeginBlockingHomeButton(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
@ -178,6 +170,11 @@ void IApplicationFunctions::BeginBlockingHomeButton(HLERequestContext& ctx) {
|
||||||
void IApplicationFunctions::EndBlockingHomeButton(HLERequestContext& ctx) {
|
void IApplicationFunctions::EndBlockingHomeButton(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
@ -188,47 +185,25 @@ void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) {
|
||||||
|
|
||||||
LOG_INFO(Service_AM, "called, kind={:08X}", kind);
|
LOG_INFO(Service_AM, "called, kind={:08X}", kind);
|
||||||
|
|
||||||
if (kind == LaunchParameterKind::UserChannel) {
|
std::scoped_lock lk{applet->lock};
|
||||||
auto channel = system.GetUserChannel();
|
|
||||||
if (channel.empty()) {
|
|
||||||
LOG_ERROR(Service_AM, "Attempted to load launch parameter but none was found!");
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(AM::ResultNoDataInChannel);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto data = channel.back();
|
auto& channel = kind == LaunchParameterKind::UserChannel
|
||||||
channel.pop_back();
|
? applet->user_channel_launch_parameter
|
||||||
|
: applet->preselected_user_launch_parameter;
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
if (channel.empty()) {
|
||||||
rb.Push(ResultSuccess);
|
LOG_WARNING(Service_AM, "Attempted to pop parameter {} but none was found!", kind);
|
||||||
rb.PushIpcInterface<IStorage>(system, std::move(data));
|
|
||||||
} else if (kind == LaunchParameterKind::AccountPreselectedUser &&
|
|
||||||
!launch_popped_account_preselect) {
|
|
||||||
// TODO: Verify this is hw-accurate
|
|
||||||
LaunchParameterAccountPreselectedUser params{};
|
|
||||||
|
|
||||||
params.magic = LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC;
|
|
||||||
params.is_account_selected = 1;
|
|
||||||
|
|
||||||
Account::ProfileManager profile_manager{};
|
|
||||||
const auto uuid = profile_manager.GetUser(static_cast<s32>(Settings::values.current_user));
|
|
||||||
ASSERT(uuid.has_value() && uuid->IsValid());
|
|
||||||
params.current_user = *uuid;
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
|
|
||||||
std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser));
|
|
||||||
std::memcpy(buffer.data(), ¶ms, buffer.size());
|
|
||||||
|
|
||||||
rb.PushIpcInterface<IStorage>(system, std::move(buffer));
|
|
||||||
launch_popped_account_preselect = true;
|
|
||||||
} else {
|
|
||||||
LOG_ERROR(Service_AM, "Unknown launch parameter kind.");
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(AM::ResultNoDataInChannel);
|
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) {
|
void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) {
|
||||||
|
@ -245,7 +220,7 @@ void IApplicationFunctions::EnsureSaveData(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]);
|
LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]);
|
||||||
|
|
||||||
FileSys::SaveDataAttribute attribute{};
|
FileSys::SaveDataAttribute attribute{};
|
||||||
attribute.title_id = system.GetApplicationProcessProgramID();
|
attribute.title_id = applet->program_id;
|
||||||
attribute.user_id = user_id;
|
attribute.user_id = user_id;
|
||||||
attribute.type = FileSys::SaveDataType::SaveData;
|
attribute.type = FileSys::SaveDataType::SaveData;
|
||||||
|
|
||||||
|
@ -267,6 +242,9 @@ void IApplicationFunctions::SetTerminateResult(HLERequestContext& ctx) {
|
||||||
u32 result = rp.Pop<u32>();
|
u32 result = rp.Pop<u32>();
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called, result=0x{:08X}", result);
|
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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
@ -277,16 +255,14 @@ void IApplicationFunctions::GetDisplayVersion(HLERequestContext& ctx) {
|
||||||
std::array<u8, 0x10> version_string{};
|
std::array<u8, 0x10> version_string{};
|
||||||
|
|
||||||
const auto res = [this] {
|
const auto res = [this] {
|
||||||
const auto title_id = system.GetApplicationProcessProgramID();
|
const FileSys::PatchManager pm{applet->program_id, system.GetFileSystemController(),
|
||||||
|
|
||||||
const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
|
|
||||||
system.GetContentProvider()};
|
system.GetContentProvider()};
|
||||||
auto metadata = pm.GetControlMetadata();
|
auto metadata = pm.GetControlMetadata();
|
||||||
if (metadata.first != nullptr) {
|
if (metadata.first != nullptr) {
|
||||||
return metadata;
|
return metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id),
|
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(applet->program_id),
|
||||||
system.GetFileSystemController(),
|
system.GetFileSystemController(),
|
||||||
system.GetContentProvider()};
|
system.GetContentProvider()};
|
||||||
return pm_update.GetControlMetadata();
|
return pm_update.GetControlMetadata();
|
||||||
|
@ -314,16 +290,14 @@ void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) {
|
||||||
u32 supported_languages = 0;
|
u32 supported_languages = 0;
|
||||||
|
|
||||||
const auto res = [this] {
|
const auto res = [this] {
|
||||||
const auto title_id = system.GetApplicationProcessProgramID();
|
const FileSys::PatchManager pm{applet->program_id, system.GetFileSystemController(),
|
||||||
|
|
||||||
const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
|
|
||||||
system.GetContentProvider()};
|
system.GetContentProvider()};
|
||||||
auto metadata = pm.GetControlMetadata();
|
auto metadata = pm.GetControlMetadata();
|
||||||
if (metadata.first != nullptr) {
|
if (metadata.first != nullptr) {
|
||||||
return metadata;
|
return metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id),
|
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(applet->program_id),
|
||||||
system.GetFileSystemController(),
|
system.GetFileSystemController(),
|
||||||
system.GetContentProvider()};
|
system.GetContentProvider()};
|
||||||
return pm_update.GetControlMetadata();
|
return pm_update.GetControlMetadata();
|
||||||
|
@ -368,11 +342,9 @@ void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) {
|
||||||
void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) {
|
void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
constexpr bool gameplay_recording_supported = false;
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push(gameplay_recording_supported);
|
rb.Push(applet->gameplay_recording_supported);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationFunctions::InitializeGamePlayRecording(HLERequestContext& ctx) {
|
void IApplicationFunctions::InitializeGamePlayRecording(HLERequestContext& ctx) {
|
||||||
|
@ -385,6 +357,11 @@ void IApplicationFunctions::InitializeGamePlayRecording(HLERequestContext& ctx)
|
||||||
void IApplicationFunctions::SetGamePlayRecordingState(HLERequestContext& ctx) {
|
void IApplicationFunctions::SetGamePlayRecordingState(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
@ -392,6 +369,9 @@ void IApplicationFunctions::SetGamePlayRecordingState(HLERequestContext& ctx) {
|
||||||
void IApplicationFunctions::NotifyRunning(HLERequestContext& ctx) {
|
void IApplicationFunctions::NotifyRunning(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->is_running = true;
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push<u8>(0); // Unknown, seems to be ignored by official processes
|
rb.Push<u8>(0); // Unknown, seems to be ignored by official processes
|
||||||
|
@ -426,8 +406,7 @@ void IApplicationFunctions::ExtendSaveData(HLERequestContext& ctx) {
|
||||||
static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size);
|
static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size);
|
||||||
|
|
||||||
system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize(
|
system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize(
|
||||||
type, system.GetApplicationProcessProgramID(), user_id,
|
type, applet->program_id, user_id, {new_normal_size, new_journal_size});
|
||||||
{new_normal_size, new_journal_size});
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -451,7 +430,7 @@ void IApplicationFunctions::GetSaveDataSize(HLERequestContext& ctx) {
|
||||||
user_id[0]);
|
user_id[0]);
|
||||||
|
|
||||||
const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize(
|
const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize(
|
||||||
type, system.GetApplicationProcessProgramID(), user_id);
|
type, applet->program_id, user_id);
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 6};
|
IPC::ResponseBuilder rb{ctx, 6};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -528,13 +507,15 @@ void IApplicationFunctions::ExecuteProgram(HLERequestContext& ctx) {
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
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);
|
system.ExecuteProgram(program_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) {
|
void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
system.GetUserChannel().clear();
|
applet->user_channel_launch_parameter.clear();
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -546,7 +527,7 @@ void IApplicationFunctions::UnpopToUserChannel(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto storage = rp.PopIpcInterface<IStorage>().lock();
|
const auto storage = rp.PopIpcInterface<IStorage>().lock();
|
||||||
if (storage) {
|
if (storage) {
|
||||||
system.GetUserChannel().push_back(storage->GetData());
|
applet->user_channel_launch_parameter.push_back(storage->GetData());
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
@ -558,7 +539,7 @@ void IApplicationFunctions::GetPreviousProgramIndex(HLERequestContext& ctx) {
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push<s32>(previous_program_index);
|
rb.Push<s32>(applet->previous_program_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx) {
|
void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx) {
|
||||||
|
@ -566,7 +547,7 @@ void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(HLERequestContext& ct
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushCopyObjects(gpu_error_detected_event->GetReadableEvent());
|
rb.PushCopyObjects(applet->gpu_error_detected_event.GetHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx) {
|
void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx) {
|
||||||
|
@ -574,7 +555,7 @@ void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(HLERequestCon
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushCopyObjects(friend_invitation_storage_channel_event->GetReadableEvent());
|
rb.PushCopyObjects(applet->friend_invitation_storage_channel_event.GetHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx) {
|
void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx) {
|
||||||
|
@ -589,7 +570,7 @@ void IApplicationFunctions::GetNotificationStorageChannelEvent(HLERequestContext
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushCopyObjects(notification_storage_channel_event->GetReadableEvent());
|
rb.PushCopyObjects(applet->notification_storage_channel_event.GetHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx) {
|
void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx) {
|
||||||
|
@ -597,12 +578,15 @@ void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(HLERequestCon
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushCopyObjects(health_warning_disappeared_system_event->GetReadableEvent());
|
rb.PushCopyObjects(applet->health_warning_disappeared_system_event.GetHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationFunctions::PrepareForJit(HLERequestContext& ctx) {
|
void IApplicationFunctions::PrepareForJit(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->jit_service_launched = true;
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,11 @@
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
|
class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
|
||||||
public:
|
public:
|
||||||
explicit IApplicationFunctions(Core::System& system_);
|
explicit IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet_);
|
||||||
~IApplicationFunctions() override;
|
~IApplicationFunctions() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -50,14 +52,7 @@ private:
|
||||||
void GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx);
|
void GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx);
|
||||||
void PrepareForJit(HLERequestContext& ctx);
|
void PrepareForJit(HLERequestContext& ctx);
|
||||||
|
|
||||||
KernelHelpers::ServiceContext service_context;
|
const std::shared_ptr<Applet> applet;
|
||||||
|
|
||||||
bool launch_popped_account_preselect = false;
|
|
||||||
s32 previous_program_index{-1};
|
|
||||||
Kernel::KEvent* gpu_error_detected_event;
|
|
||||||
Kernel::KEvent* friend_invitation_storage_channel_event;
|
|
||||||
Kernel::KEvent* notification_storage_channel_event;
|
|
||||||
Kernel::KEvent* health_warning_disappeared_system_event;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|
|
@ -18,10 +18,9 @@
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
IApplicationProxy::IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
IApplicationProxy::IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue_,
|
std::shared_ptr<Applet> applet_, Core::System& system_)
|
||||||
Core::System& system_)
|
: ServiceFramework{system_, "IApplicationProxy"}, nvnflinger{nvnflinger_}, applet{std::move(
|
||||||
: ServiceFramework{system_, "IApplicationProxy"}, nvnflinger{nvnflinger_},
|
applet_)} {
|
||||||
msg_queue{std::move(msg_queue_)} {
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"},
|
{0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"},
|
||||||
|
@ -39,6 +38,8 @@ IApplicationProxy::IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
||||||
RegisterHandlers(functions);
|
RegisterHandlers(functions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IApplicationProxy::~IApplicationProxy() = default;
|
||||||
|
|
||||||
void IApplicationProxy::GetAudioController(HLERequestContext& ctx) {
|
void IApplicationProxy::GetAudioController(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
@ -60,7 +61,7 @@ void IApplicationProxy::GetProcessWindingController(HLERequestContext& ctx) {
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<IProcessWindingController>(system);
|
rb.PushIpcInterface<IProcessWindingController>(system, applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationProxy::GetDebugFunctions(HLERequestContext& ctx) {
|
void IApplicationProxy::GetDebugFunctions(HLERequestContext& ctx) {
|
||||||
|
@ -76,7 +77,7 @@ void IApplicationProxy::GetWindowController(HLERequestContext& ctx) {
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<IWindowController>(system);
|
rb.PushIpcInterface<IWindowController>(system, applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationProxy::GetSelfController(HLERequestContext& ctx) {
|
void IApplicationProxy::GetSelfController(HLERequestContext& ctx) {
|
||||||
|
@ -84,7 +85,7 @@ void IApplicationProxy::GetSelfController(HLERequestContext& ctx) {
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<ISelfController>(system, nvnflinger);
|
rb.PushIpcInterface<ISelfController>(system, applet, nvnflinger);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationProxy::GetCommonStateGetter(HLERequestContext& ctx) {
|
void IApplicationProxy::GetCommonStateGetter(HLERequestContext& ctx) {
|
||||||
|
@ -92,7 +93,7 @@ void IApplicationProxy::GetCommonStateGetter(HLERequestContext& ctx) {
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue);
|
rb.PushIpcInterface<ICommonStateGetter>(system, applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
|
void IApplicationProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
|
||||||
|
@ -100,7 +101,7 @@ void IApplicationProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<ILibraryAppletCreator>(system);
|
rb.PushIpcInterface<ILibraryAppletCreator>(system, applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IApplicationProxy::GetApplicationFunctions(HLERequestContext& ctx) {
|
void IApplicationProxy::GetApplicationFunctions(HLERequestContext& ctx) {
|
||||||
|
@ -108,7 +109,7 @@ void IApplicationProxy::GetApplicationFunctions(HLERequestContext& ctx) {
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<IApplicationFunctions>(system);
|
rb.PushIpcInterface<IApplicationFunctions>(system, applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|
|
@ -3,16 +3,17 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/hle/service/am/applet_message_queue.h"
|
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
|
class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
|
||||||
public:
|
public:
|
||||||
explicit IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
explicit IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue_,
|
std::shared_ptr<Applet> msg_queue_, Core::System& system_);
|
||||||
Core::System& system_);
|
~IApplicationProxy();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void GetAudioController(HLERequestContext& ctx);
|
void GetAudioController(HLERequestContext& ctx);
|
||||||
|
@ -26,7 +27,7 @@ private:
|
||||||
void GetApplicationFunctions(HLERequestContext& ctx);
|
void GetApplicationFunctions(HLERequestContext& ctx);
|
||||||
|
|
||||||
Nvnflinger::Nvnflinger& nvnflinger;
|
Nvnflinger::Nvnflinger& nvnflinger;
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue;
|
std::shared_ptr<Applet> applet;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "core/hle/service/am/am_results.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/common_state_getter.h"
|
||||||
#include "core/hle/service/am/lock_accessor.h"
|
#include "core/hle/service/am/lock_accessor.h"
|
||||||
#include "core/hle/service/apm/apm_controller.h"
|
#include "core/hle/service/apm/apm_controller.h"
|
||||||
|
@ -14,10 +15,8 @@
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
ICommonStateGetter::ICommonStateGetter(Core::System& system_,
|
ICommonStateGetter::ICommonStateGetter(Core::System& system_, std::shared_ptr<Applet> applet_)
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue_)
|
: ServiceFramework{system_, "ICommonStateGetter"}, applet{std::move(applet_)} {
|
||||||
: ServiceFramework{system_, "ICommonStateGetter"}, msg_queue{std::move(msg_queue_)},
|
|
||||||
service_context{system_, "ICommonStateGetter"} {
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"},
|
{0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"},
|
||||||
|
@ -75,17 +74,9 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
RegisterHandlers(functions);
|
RegisterHandlers(functions);
|
||||||
|
|
||||||
sleep_lock_event = service_context.CreateEvent("ICommonStateGetter::SleepLockEvent");
|
|
||||||
|
|
||||||
// Configure applets to be in foreground state
|
|
||||||
msg_queue->PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
|
|
||||||
msg_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ICommonStateGetter::~ICommonStateGetter() {
|
ICommonStateGetter::~ICommonStateGetter() = default;
|
||||||
service_context.CloseEvent(sleep_lock_event);
|
|
||||||
};
|
|
||||||
|
|
||||||
void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) {
|
void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
@ -96,17 +87,17 @@ void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICommonStateGetter::GetEventHandle(HLERequestContext& ctx) {
|
void ICommonStateGetter::GetEventHandle(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushCopyObjects(msg_queue->GetMessageReceiveEvent());
|
rb.PushCopyObjects(applet->message_queue.GetMessageReceiveEvent());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICommonStateGetter::ReceiveMessage(HLERequestContext& ctx) {
|
void ICommonStateGetter::ReceiveMessage(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
const auto message = msg_queue->PopMessage();
|
const auto message = applet->message_queue.PopMessage();
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
|
||||||
if (message == AppletMessageQueue::AppletMessage::None) {
|
if (message == AppletMessageQueue::AppletMessage::None) {
|
||||||
|
@ -123,9 +114,11 @@ void ICommonStateGetter::ReceiveMessage(HLERequestContext& ctx) {
|
||||||
void ICommonStateGetter::GetCurrentFocusState(HLERequestContext& ctx) {
|
void ICommonStateGetter::GetCurrentFocusState(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "(STUBBED) called");
|
LOG_DEBUG(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push(static_cast<u8>(FocusState::InFocus));
|
rb.Push(static_cast<u8>(applet->focus_state));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICommonStateGetter::GetOperationMode(HLERequestContext& ctx) {
|
void ICommonStateGetter::GetOperationMode(HLERequestContext& ctx) {
|
||||||
|
@ -149,7 +142,7 @@ void ICommonStateGetter::RequestToAcquireSleepLock(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
// Sleep lock is acquired immediately.
|
// Sleep lock is acquired immediately.
|
||||||
sleep_lock_event->Signal();
|
applet->sleep_lock_event.Signal();
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -172,22 +165,25 @@ void ICommonStateGetter::GetAcquiredSleepLockEvent(HLERequestContext& ctx) {
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushCopyObjects(sleep_lock_event->GetReadableEvent());
|
rb.PushCopyObjects(applet->sleep_lock_event.GetHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) {
|
void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push(vr_mode_state);
|
rb.Push(applet->vr_mode_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICommonStateGetter::SetVrModeEnabled(HLERequestContext& ctx) {
|
void ICommonStateGetter::SetVrModeEnabled(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
vr_mode_state = rp.Pop<bool>();
|
|
||||||
|
|
||||||
LOG_WARNING(Service_AM, "VR Mode is {}", vr_mode_state ? "on" : "off");
|
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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -207,6 +203,9 @@ void ICommonStateGetter::SetLcdBacklighOffEnabled(HLERequestContext& ctx) {
|
||||||
void ICommonStateGetter::BeginVrModeEx(HLERequestContext& ctx) {
|
void ICommonStateGetter::BeginVrModeEx(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->vr_mode_enabled = true;
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
@ -214,6 +213,9 @@ void ICommonStateGetter::BeginVrModeEx(HLERequestContext& ctx) {
|
||||||
void ICommonStateGetter::EndVrModeEx(HLERequestContext& ctx) {
|
void ICommonStateGetter::EndVrModeEx(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->vr_mode_enabled = false;
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
@ -223,7 +225,7 @@ void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(HLERequestContex
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushCopyObjects(msg_queue->GetOperationModeChangedEvent());
|
rb.PushCopyObjects(applet->message_queue.GetOperationModeChangedEvent());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICommonStateGetter::GetDefaultDisplayResolution(HLERequestContext& ctx) {
|
void ICommonStateGetter::GetDefaultDisplayResolution(HLERequestContext& ctx) {
|
||||||
|
@ -281,6 +283,9 @@ void ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnable
|
||||||
HLERequestContext& ctx) {
|
HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,11 @@
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
|
class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
|
||||||
public:
|
public:
|
||||||
explicit ICommonStateGetter(Core::System& system_,
|
explicit ICommonStateGetter(Core::System& system_, std::shared_ptr<Applet> applet_);
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue_);
|
|
||||||
~ICommonStateGetter() override;
|
~ICommonStateGetter() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -69,10 +70,7 @@ private:
|
||||||
void GetSettingsPlatformRegion(HLERequestContext& ctx);
|
void GetSettingsPlatformRegion(HLERequestContext& ctx);
|
||||||
void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx);
|
void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx);
|
||||||
|
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue;
|
const std::shared_ptr<Applet> applet;
|
||||||
bool vr_mode_state{};
|
|
||||||
Kernel::KEvent* sleep_lock_event;
|
|
||||||
KernelHelpers::ServiceContext service_context;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#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_ae.h"
|
||||||
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
#include "core/hle/service/am/applet_message_queue.h"
|
#include "core/hle/service/am/applet_message_queue.h"
|
||||||
#include "core/hle/service/am/applet_oe.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"
|
||||||
|
@ -122,21 +123,11 @@ void AppletDataBroker::PushInteractiveDataFromApplet(std::shared_ptr<IStorage>&&
|
||||||
void AppletDataBroker::SignalStateChanged() {
|
void AppletDataBroker::SignalStateChanged() {
|
||||||
state_changed_event->Signal();
|
state_changed_event->Signal();
|
||||||
|
|
||||||
|
// TODO proper window management
|
||||||
switch (applet_mode) {
|
switch (applet_mode) {
|
||||||
case LibraryAppletMode::AllForeground:
|
case LibraryAppletMode::AllForeground:
|
||||||
case LibraryAppletMode::AllForegroundInitiallyHidden: {
|
case LibraryAppletMode::AllForegroundInitiallyHidden: {
|
||||||
auto applet_oe = system.ServiceManager().GetService<AppletOE>("appletOE");
|
system.GetAppletManager().FocusStateChanged();
|
||||||
auto applet_ae = system.ServiceManager().GetService<AppletAE>("appletAE");
|
|
||||||
|
|
||||||
if (applet_oe) {
|
|
||||||
applet_oe->GetMessageQueue()->FocusStateChanged();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (applet_ae) {
|
|
||||||
applet_ae->GetMessageQueue()->FocusStateChanged();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -255,11 +246,6 @@ void FrontendAppletHolder::SetCurrentAppletId(AppletId applet_id) {
|
||||||
current_applet_id = applet_id;
|
current_applet_id = applet_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrontendAppletHolder::SetDefaultAppletFrontendSet() {
|
|
||||||
ClearAll();
|
|
||||||
SetDefaultAppletsIfMissing();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FrontendAppletHolder::SetDefaultAppletsIfMissing() {
|
void FrontendAppletHolder::SetDefaultAppletsIfMissing() {
|
||||||
if (frontend.cabinet == nullptr) {
|
if (frontend.cabinet == nullptr) {
|
||||||
frontend.cabinet = std::make_unique<Core::Frontend::DefaultCabinetApplet>();
|
frontend.cabinet = std::make_unique<Core::Frontend::DefaultCabinetApplet>();
|
||||||
|
|
|
@ -188,7 +188,6 @@ public:
|
||||||
void SetFrontendAppletSet(FrontendAppletSet set);
|
void SetFrontendAppletSet(FrontendAppletSet set);
|
||||||
void SetCabinetMode(NFP::CabinetMode mode);
|
void SetCabinetMode(NFP::CabinetMode mode);
|
||||||
void SetCurrentAppletId(AppletId applet_id);
|
void SetCurrentAppletId(AppletId applet_id);
|
||||||
void SetDefaultAppletFrontendSet();
|
|
||||||
void SetDefaultAppletsIfMissing();
|
void SetDefaultAppletsIfMissing();
|
||||||
void ClearAll();
|
void ClearAll();
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
// 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 "common/scope_exit.h"
|
||||||
#include "core/hle/service/am/am_results.h"
|
#include "core/hle/service/am/am_results.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_accessor.h"
|
||||||
#include "core/hle/service/am/storage.h"
|
#include "core/hle/service/am/storage.h"
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
@ -9,8 +11,10 @@
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
ILibraryAppletAccessor::ILibraryAppletAccessor(Core::System& system_,
|
ILibraryAppletAccessor::ILibraryAppletAccessor(Core::System& system_,
|
||||||
std::shared_ptr<Frontend::FrontendApplet> applet_)
|
std::shared_ptr<AppletStorageHolder> storage_,
|
||||||
: ServiceFramework{system_, "ILibraryAppletAccessor"}, applet{std::move(applet_)} {
|
std::shared_ptr<Applet> applet_)
|
||||||
|
: ServiceFramework{system_, "ILibraryAppletAccessor"}, storage{std::move(storage_)},
|
||||||
|
applet{std::move(applet_)} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"},
|
{0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"},
|
||||||
|
@ -38,27 +42,31 @@ ILibraryAppletAccessor::ILibraryAppletAccessor(Core::System& system_,
|
||||||
RegisterHandlers(functions);
|
RegisterHandlers(functions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ILibraryAppletAccessor::~ILibraryAppletAccessor() = default;
|
||||||
|
|
||||||
void ILibraryAppletAccessor::GetAppletStateChangedEvent(HLERequestContext& ctx) {
|
void ILibraryAppletAccessor::GetAppletStateChangedEvent(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushCopyObjects(applet->GetBroker().GetStateChangedEvent());
|
rb.PushCopyObjects(storage->state_changed_event.GetHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletAccessor::IsCompleted(HLERequestContext& ctx) {
|
void ILibraryAppletAccessor::IsCompleted(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push<u32>(applet->TransactionComplete());
|
rb.Push<u32>(applet->is_completed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletAccessor::GetResult(HLERequestContext& ctx) {
|
void ILibraryAppletAccessor::GetResult(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(applet->GetStatus());
|
rb.Push(applet->terminate_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx) {
|
void ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx) {
|
||||||
|
@ -71,10 +79,7 @@ void ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero(HLERequestConte
|
||||||
void ILibraryAppletAccessor::Start(HLERequestContext& ctx) {
|
void ILibraryAppletAccessor::Start(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
ASSERT(applet != nullptr);
|
applet->process->Run();
|
||||||
|
|
||||||
applet->Initialize();
|
|
||||||
applet->Execute();
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -84,16 +89,17 @@ void ILibraryAppletAccessor::RequestExit(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
ASSERT(applet != nullptr);
|
ASSERT(applet != nullptr);
|
||||||
|
applet->message_queue.RequestExit();
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(applet->RequestExit());
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletAccessor::PushInData(HLERequestContext& ctx) {
|
void ILibraryAppletAccessor::PushInData(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
applet->GetBroker().PushNormalDataFromGame(rp.PopIpcInterface<IStorage>().lock());
|
storage->in_data.PushData(rp.PopIpcInterface<IStorage>().lock());
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -102,29 +108,24 @@ void ILibraryAppletAccessor::PushInData(HLERequestContext& ctx) {
|
||||||
void ILibraryAppletAccessor::PopOutData(HLERequestContext& ctx) {
|
void ILibraryAppletAccessor::PopOutData(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
auto storage = applet->GetBroker().PopNormalDataToGame();
|
std::shared_ptr<IStorage> data;
|
||||||
if (storage == nullptr) {
|
const auto res = storage->out_data.PopData(&data);
|
||||||
LOG_DEBUG(Service_AM,
|
|
||||||
"storage is a nullptr. There is no data in the current normal channel");
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(AM::ResultNoDataInChannel);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
if (res.IsSuccess()) {
|
||||||
rb.Push(ResultSuccess);
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.PushIpcInterface<IStorage>(std::move(storage));
|
rb.Push(res);
|
||||||
|
rb.PushIpcInterface(std::move(data));
|
||||||
|
} else {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(res);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletAccessor::PushInteractiveInData(HLERequestContext& ctx) {
|
void ILibraryAppletAccessor::PushInteractiveInData(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
applet->GetBroker().PushInteractiveDataFromGame(rp.PopIpcInterface<IStorage>().lock());
|
storage->interactive_in_data.PushData(rp.PopIpcInterface<IStorage>().lock());
|
||||||
|
|
||||||
ASSERT(applet->IsInitialized());
|
|
||||||
applet->ExecuteInteractive();
|
|
||||||
applet->Execute();
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -133,18 +134,17 @@ void ILibraryAppletAccessor::PushInteractiveInData(HLERequestContext& ctx) {
|
||||||
void ILibraryAppletAccessor::PopInteractiveOutData(HLERequestContext& ctx) {
|
void ILibraryAppletAccessor::PopInteractiveOutData(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
auto storage = applet->GetBroker().PopInteractiveDataToGame();
|
std::shared_ptr<IStorage> data;
|
||||||
if (storage == nullptr) {
|
const auto res = storage->interactive_out_data.PopData(&data);
|
||||||
LOG_DEBUG(Service_AM,
|
|
||||||
"storage is a nullptr. There is no data in the current interactive channel");
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(AM::ResultNoDataInChannel);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
if (res.IsSuccess()) {
|
||||||
rb.Push(ResultSuccess);
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.PushIpcInterface<IStorage>(std::move(storage));
|
rb.Push(res);
|
||||||
|
rb.PushIpcInterface(std::move(data));
|
||||||
|
} else {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(res);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletAccessor::GetPopOutDataEvent(HLERequestContext& ctx) {
|
void ILibraryAppletAccessor::GetPopOutDataEvent(HLERequestContext& ctx) {
|
||||||
|
@ -152,7 +152,7 @@ void ILibraryAppletAccessor::GetPopOutDataEvent(HLERequestContext& ctx) {
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushCopyObjects(applet->GetBroker().GetNormalDataEvent());
|
rb.PushCopyObjects(storage->out_data.GetEvent());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletAccessor::GetPopInteractiveOutDataEvent(HLERequestContext& ctx) {
|
void ILibraryAppletAccessor::GetPopInteractiveOutDataEvent(HLERequestContext& ctx) {
|
||||||
|
@ -160,7 +160,7 @@ void ILibraryAppletAccessor::GetPopInteractiveOutDataEvent(HLERequestContext& ct
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushCopyObjects(applet->GetBroker().GetInteractiveDataEvent());
|
rb.PushCopyObjects(storage->interactive_out_data.GetEvent());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletAccessor::GetIndirectLayerConsumerHandle(HLERequestContext& ctx) {
|
void ILibraryAppletAccessor::GetIndirectLayerConsumerHandle(HLERequestContext& ctx) {
|
||||||
|
|
|
@ -3,17 +3,21 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/hle/service/am/frontend/applets.h"
|
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct AppletStorageHolder;
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
|
class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
|
||||||
public:
|
public:
|
||||||
explicit ILibraryAppletAccessor(Core::System& system_,
|
explicit ILibraryAppletAccessor(Core::System& system_,
|
||||||
std::shared_ptr<Frontend::FrontendApplet> applet_);
|
std::shared_ptr<AppletStorageHolder> storage_,
|
||||||
|
std::shared_ptr<Applet> applet_);
|
||||||
|
~ILibraryAppletAccessor();
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
void GetAppletStateChangedEvent(HLERequestContext& ctx);
|
void GetAppletStateChangedEvent(HLERequestContext& ctx);
|
||||||
void IsCompleted(HLERequestContext& ctx);
|
void IsCompleted(HLERequestContext& ctx);
|
||||||
void GetResult(HLERequestContext& ctx);
|
void GetResult(HLERequestContext& ctx);
|
||||||
|
@ -28,7 +32,8 @@ private:
|
||||||
void GetPopInteractiveOutDataEvent(HLERequestContext& ctx);
|
void GetPopInteractiveOutDataEvent(HLERequestContext& ctx);
|
||||||
void GetIndirectLayerConsumerHandle(HLERequestContext& ctx);
|
void GetIndirectLayerConsumerHandle(HLERequestContext& ctx);
|
||||||
|
|
||||||
std::shared_ptr<Frontend::FrontendApplet> applet;
|
const std::shared_ptr<AppletStorageHolder> storage;
|
||||||
|
const std::shared_ptr<Applet> applet;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|
|
@ -2,16 +2,112 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "core/hle/kernel/k_transfer_memory.h"
|
#include "core/hle/kernel/k_transfer_memory.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_accessor.h"
|
||||||
#include "core/hle/service/am/library_applet_creator.h"
|
#include "core/hle/service/am/library_applet_creator.h"
|
||||||
#include "core/hle/service/am/storage.h"
|
#include "core/hle/service/am/storage.h"
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
#include "core/hle/service/sm/sm.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_)
|
namespace {
|
||||||
: ServiceFramework{system_, "ILibraryAppletCreator"} {
|
|
||||||
|
AppletProgramId AppletIdToProgramId(AppletId applet_id) {
|
||||||
|
switch (applet_id) {
|
||||||
|
case AppletId::OverlayDisplay:
|
||||||
|
return AppletProgramId::OverlayDisplay;
|
||||||
|
case AppletId::QLaunch:
|
||||||
|
return AppletProgramId::QLaunch;
|
||||||
|
case AppletId::Starter:
|
||||||
|
return AppletProgramId::Starter;
|
||||||
|
case AppletId::Auth:
|
||||||
|
return AppletProgramId::Auth;
|
||||||
|
case AppletId::Cabinet:
|
||||||
|
return AppletProgramId::Cabinet;
|
||||||
|
case AppletId::Controller:
|
||||||
|
return AppletProgramId::Controller;
|
||||||
|
case AppletId::DataErase:
|
||||||
|
return AppletProgramId::DataErase;
|
||||||
|
case AppletId::Error:
|
||||||
|
return AppletProgramId::Error;
|
||||||
|
case AppletId::NetConnect:
|
||||||
|
return AppletProgramId::NetConnect;
|
||||||
|
case AppletId::ProfileSelect:
|
||||||
|
return AppletProgramId::ProfileSelect;
|
||||||
|
case AppletId::SoftwareKeyboard:
|
||||||
|
return AppletProgramId::SoftwareKeyboard;
|
||||||
|
case AppletId::MiiEdit:
|
||||||
|
return AppletProgramId::MiiEdit;
|
||||||
|
case AppletId::Web:
|
||||||
|
return AppletProgramId::Web;
|
||||||
|
case AppletId::Shop:
|
||||||
|
return AppletProgramId::Shop;
|
||||||
|
case AppletId::PhotoViewer:
|
||||||
|
return AppletProgramId::PhotoViewer;
|
||||||
|
case AppletId::Settings:
|
||||||
|
return AppletProgramId::Settings;
|
||||||
|
case AppletId::OfflineWeb:
|
||||||
|
return AppletProgramId::OfflineWeb;
|
||||||
|
case AppletId::LoginShare:
|
||||||
|
return AppletProgramId::LoginShare;
|
||||||
|
case AppletId::WebAuth:
|
||||||
|
return AppletProgramId::WebAuth;
|
||||||
|
case AppletId::MyPage:
|
||||||
|
return AppletProgramId::MyPage;
|
||||||
|
default:
|
||||||
|
return static_cast<AppletProgramId>(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system,
|
||||||
|
std::shared_ptr<Applet> caller_applet,
|
||||||
|
AppletId applet_id,
|
||||||
|
LibraryAppletMode mode) {
|
||||||
|
const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id));
|
||||||
|
if (program_id == 0) {
|
||||||
|
// Unknown applet
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto process = std::make_unique<Process>(system);
|
||||||
|
if (!process->Initialize(program_id)) {
|
||||||
|
// Couldn't initialize the guest process
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto applet = std::make_shared<Applet>(system, std::move(process));
|
||||||
|
applet->program_id = program_id;
|
||||||
|
applet->applet_id = applet_id;
|
||||||
|
applet->type = AppletType::LibraryApplet;
|
||||||
|
applet->library_applet_mode = mode;
|
||||||
|
|
||||||
|
// Library applet should be foreground
|
||||||
|
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
|
||||||
|
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
||||||
|
applet->focus_state = FocusState::InFocus;
|
||||||
|
|
||||||
|
auto storage = std::make_shared<AppletStorageHolder>(system);
|
||||||
|
applet->caller_applet = caller_applet;
|
||||||
|
applet->caller_applet_storage = storage;
|
||||||
|
|
||||||
|
system.GetAppletManager().InsertApplet(applet);
|
||||||
|
|
||||||
|
return std::make_shared<ILibraryAppletAccessor>(system, storage, applet);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& system,
|
||||||
|
AppletId applet_id,
|
||||||
|
LibraryAppletMode mode) {
|
||||||
|
UNREACHABLE();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet_)
|
||||||
|
: ServiceFramework{system_, "ILibraryAppletCreator"}, applet{std::move(applet_)} {
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"},
|
{0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"},
|
||||||
{1, nullptr, "TerminateAllLibraryApplets"},
|
{1, nullptr, "TerminateAllLibraryApplets"},
|
||||||
|
@ -34,10 +130,11 @@ void ILibraryAppletCreator::CreateLibraryApplet(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id,
|
LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id,
|
||||||
applet_mode);
|
applet_mode);
|
||||||
|
|
||||||
const auto& holder{system.GetFrontendAppletHolder()};
|
auto library_applet = CreateGuestApplet(system, applet, applet_id, applet_mode);
|
||||||
const auto applet = holder.GetApplet(applet_id, applet_mode);
|
if (!library_applet) {
|
||||||
|
library_applet = CreateFrontendApplet(system, applet_id, applet_mode);
|
||||||
if (applet == nullptr) {
|
}
|
||||||
|
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);
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
@ -45,10 +142,12 @@ void ILibraryAppletCreator::CreateLibraryApplet(HLERequestContext& ctx) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
// Applet is created, can now be launched.
|
||||||
|
applet->library_applet_launchable_event.Signal();
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet);
|
rb.PushIpcInterface<ILibraryAppletAccessor>(library_applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletCreator::CreateStorage(HLERequestContext& ctx) {
|
void ILibraryAppletCreator::CreateStorage(HLERequestContext& ctx) {
|
||||||
|
|
|
@ -7,9 +7,11 @@
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
|
class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
|
||||||
public:
|
public:
|
||||||
explicit ILibraryAppletCreator(Core::System& system_);
|
explicit ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet_);
|
||||||
~ILibraryAppletCreator() override;
|
~ILibraryAppletCreator() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -17,6 +19,8 @@ private:
|
||||||
void CreateStorage(HLERequestContext& ctx);
|
void CreateStorage(HLERequestContext& ctx);
|
||||||
void CreateTransferMemoryStorage(HLERequestContext& ctx);
|
void CreateTransferMemoryStorage(HLERequestContext& ctx);
|
||||||
void CreateHandleStorage(HLERequestContext& ctx);
|
void CreateHandleStorage(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
const std::shared_ptr<Applet> applet;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|
|
@ -19,10 +19,9 @@
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
ILibraryAppletProxy::ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
ILibraryAppletProxy::ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue_,
|
std::shared_ptr<Applet> applet_, Core::System& system_)
|
||||||
Core::System& system_)
|
: ServiceFramework{system_, "ILibraryAppletProxy"}, nvnflinger{nvnflinger_}, applet{std::move(
|
||||||
: ServiceFramework{system_, "ILibraryAppletProxy"}, nvnflinger{nvnflinger_},
|
applet_)} {
|
||||||
msg_queue{std::move(msg_queue_)} {
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
|
{0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
|
||||||
|
@ -43,12 +42,14 @@ ILibraryAppletProxy::ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
||||||
RegisterHandlers(functions);
|
RegisterHandlers(functions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ILibraryAppletProxy::~ILibraryAppletProxy() = default;
|
||||||
|
|
||||||
void ILibraryAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) {
|
void ILibraryAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue);
|
rb.PushIpcInterface<ICommonStateGetter>(system, applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletProxy::GetSelfController(HLERequestContext& ctx) {
|
void ILibraryAppletProxy::GetSelfController(HLERequestContext& ctx) {
|
||||||
|
@ -56,7 +57,7 @@ void ILibraryAppletProxy::GetSelfController(HLERequestContext& ctx) {
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<ISelfController>(system, nvnflinger);
|
rb.PushIpcInterface<ISelfController>(system, applet, nvnflinger);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletProxy::GetWindowController(HLERequestContext& ctx) {
|
void ILibraryAppletProxy::GetWindowController(HLERequestContext& ctx) {
|
||||||
|
@ -64,7 +65,7 @@ void ILibraryAppletProxy::GetWindowController(HLERequestContext& ctx) {
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<IWindowController>(system);
|
rb.PushIpcInterface<IWindowController>(system, applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletProxy::GetAudioController(HLERequestContext& ctx) {
|
void ILibraryAppletProxy::GetAudioController(HLERequestContext& ctx) {
|
||||||
|
@ -88,7 +89,7 @@ void ILibraryAppletProxy::GetProcessWindingController(HLERequestContext& ctx) {
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<IProcessWindingController>(system);
|
rb.PushIpcInterface<IProcessWindingController>(system, applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
|
void ILibraryAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
|
||||||
|
@ -96,7 +97,7 @@ void ILibraryAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<ILibraryAppletCreator>(system);
|
rb.PushIpcInterface<ILibraryAppletCreator>(system, applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletProxy::OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) {
|
void ILibraryAppletProxy::OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) {
|
||||||
|
@ -104,7 +105,7 @@ void ILibraryAppletProxy::OpenLibraryAppletSelfAccessor(HLERequestContext& ctx)
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system);
|
rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system, applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) {
|
void ILibraryAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) {
|
||||||
|
@ -112,7 +113,7 @@ void ILibraryAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) {
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<IAppletCommonFunctions>(system);
|
rb.PushIpcInterface<IAppletCommonFunctions>(system, applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletProxy::GetHomeMenuFunctions(HLERequestContext& ctx) {
|
void ILibraryAppletProxy::GetHomeMenuFunctions(HLERequestContext& ctx) {
|
||||||
|
|
|
@ -3,16 +3,17 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/hle/service/am/applet_message_queue.h"
|
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
|
class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
|
||||||
public:
|
public:
|
||||||
explicit ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
explicit ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue_,
|
std::shared_ptr<Applet> applet_, Core::System& system_);
|
||||||
Core::System& system_);
|
~ILibraryAppletProxy();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void GetCommonStateGetter(HLERequestContext& ctx);
|
void GetCommonStateGetter(HLERequestContext& ctx);
|
||||||
|
@ -29,7 +30,7 @@ private:
|
||||||
void GetDebugFunctions(HLERequestContext& ctx);
|
void GetDebugFunctions(HLERequestContext& ctx);
|
||||||
|
|
||||||
Nvnflinger::Nvnflinger& nvnflinger;
|
Nvnflinger::Nvnflinger& nvnflinger;
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue;
|
std::shared_ptr<Applet> applet;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
// 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 "common/scope_exit.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/hle/service/acc/profile_manager.h"
|
#include "core/hle/service/acc/profile_manager.h"
|
||||||
#include "core/hle/service/am/am_results.h"
|
#include "core/hle/service/am/am_results.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_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_mii_edit_types.h"
|
#include "core/hle/service/am/frontend/applet_mii_edit_types.h"
|
||||||
|
@ -16,16 +18,44 @@
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
|
namespace {
|
||||||
: ServiceFramework{system_, "ILibraryAppletSelfAccessor"} {
|
|
||||||
|
struct AppletIdentityInfo {
|
||||||
|
AppletId applet_id;
|
||||||
|
INSERT_PADDING_BYTES(0x4);
|
||||||
|
u64 application_id;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size.");
|
||||||
|
|
||||||
|
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 = applet->applet_id,
|
||||||
|
.application_id = 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_)},
|
||||||
|
storage{applet->caller_applet_storage} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &ILibraryAppletSelfAccessor::PopInData, "PopInData"},
|
{0, &ILibraryAppletSelfAccessor::PopInData, "PopInData"},
|
||||||
{1, &ILibraryAppletSelfAccessor::PushOutData, "PushOutData"},
|
{1, &ILibraryAppletSelfAccessor::PushOutData, "PushOutData"},
|
||||||
{2, nullptr, "PopInteractiveInData"},
|
{2, &ILibraryAppletSelfAccessor::PopInteractiveInData, "PopInteractiveInData"},
|
||||||
{3, nullptr, "PushInteractiveOutData"},
|
{3, &ILibraryAppletSelfAccessor::PushInteractiveOutData, "PushInteractiveOutData"},
|
||||||
{5, nullptr, "GetPopInDataEvent"},
|
{5, &ILibraryAppletSelfAccessor::GetPopInDataEvent, "GetPopInDataEvent"},
|
||||||
{6, nullptr, "GetPopInteractiveInDataEvent"},
|
{6, &ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent, "GetPopInteractiveInDataEvent"},
|
||||||
{10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"},
|
{10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"},
|
||||||
{11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"},
|
{11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"},
|
||||||
{12, &ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo, "GetMainAppletIdentityInfo"},
|
{12, &ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo, "GetMainAppletIdentityInfo"},
|
||||||
|
@ -58,26 +88,6 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
RegisterHandlers(functions);
|
RegisterHandlers(functions);
|
||||||
|
|
||||||
switch (system.GetFrontendAppletHolder().GetCurrentAppletId()) {
|
|
||||||
case AppletId::Cabinet:
|
|
||||||
PushInShowCabinetData();
|
|
||||||
break;
|
|
||||||
case AppletId::MiiEdit:
|
|
||||||
PushInShowMiiEditData();
|
|
||||||
break;
|
|
||||||
case AppletId::PhotoViewer:
|
|
||||||
PushInShowAlbum();
|
|
||||||
break;
|
|
||||||
case AppletId::SoftwareKeyboard:
|
|
||||||
PushInShowSoftwareKeyboard();
|
|
||||||
break;
|
|
||||||
case AppletId::Controller:
|
|
||||||
PushInShowController();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default;
|
ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default;
|
||||||
|
@ -85,31 +95,81 @@ ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default;
|
||||||
void ILibraryAppletSelfAccessor::PopInData(HLERequestContext& ctx) {
|
void ILibraryAppletSelfAccessor::PopInData(HLERequestContext& ctx) {
|
||||||
LOG_INFO(Service_AM, "called");
|
LOG_INFO(Service_AM, "called");
|
||||||
|
|
||||||
if (queue_data.empty()) {
|
std::shared_ptr<IStorage> data;
|
||||||
|
const auto res = storage->in_data.PopData(&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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(AM::ResultNoDataInChannel);
|
rb.Push(res);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = queue_data.front();
|
|
||||||
queue_data.pop_front();
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IStorage>(system, std::move(data));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletSelfAccessor::PushOutData(HLERequestContext& ctx) {
|
void ILibraryAppletSelfAccessor::PushOutData(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_INFO(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
storage->out_data.PushData(rp.PopIpcInterface<IStorage>().lock());
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletSelfAccessor::ExitProcessAndReturn(HLERequestContext& ctx) {
|
void ILibraryAppletSelfAccessor::PopInteractiveInData(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_INFO(Service_AM, "called");
|
||||||
|
|
||||||
system.Exit();
|
std::shared_ptr<IStorage> data;
|
||||||
|
const auto res = storage->interactive_in_data.PopData(&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};
|
||||||
|
storage->interactive_out_data.PushData(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(storage->in_data.GetEvent());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent(HLERequestContext& ctx) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushCopyObjects(storage->interactive_in_data.GetEvent());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletSelfAccessor::ExitProcessAndReturn(HLERequestContext& ctx) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
|
||||||
|
system.GetAppletManager().TerminateAndRemoveApplet(applet->aruid);
|
||||||
|
|
||||||
|
{
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->is_completed = true;
|
||||||
|
storage->state_changed_event.Signal();
|
||||||
|
}
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -124,8 +184,8 @@ void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
const LibraryAppletInfo applet_info{
|
const LibraryAppletInfo applet_info{
|
||||||
.applet_id = system.GetFrontendAppletHolder().GetCurrentAppletId(),
|
.applet_id = applet->applet_id,
|
||||||
.library_applet_mode = LibraryAppletMode::AllForeground,
|
.library_applet_mode = applet->library_applet_mode,
|
||||||
};
|
};
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
@ -134,13 +194,6 @@ void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ctx) {
|
void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ctx) {
|
||||||
struct AppletIdentityInfo {
|
|
||||||
AppletId applet_id;
|
|
||||||
INSERT_PADDING_BYTES(0x4);
|
|
||||||
u64 application_id;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size.");
|
|
||||||
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
const AppletIdentityInfo applet_info{
|
const AppletIdentityInfo applet_info{
|
||||||
|
@ -154,22 +207,11 @@ void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ct
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) {
|
void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) {
|
||||||
struct AppletIdentityInfo {
|
|
||||||
AppletId applet_id;
|
|
||||||
INSERT_PADDING_BYTES(0x4);
|
|
||||||
u64 application_id;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size.");
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
const AppletIdentityInfo applet_info{
|
|
||||||
.applet_id = AppletId::QLaunch,
|
|
||||||
.application_id = 0x0100000000001000ull,
|
|
||||||
};
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 6};
|
IPC::ResponseBuilder rb{ctx, 6};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushRaw(applet_info);
|
rb.PushRaw(GetCallerIdentity(applet));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(HLERequestContext& ctx) {
|
void ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(HLERequestContext& ctx) {
|
||||||
|
@ -207,176 +249,4 @@ void ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually(HLERequestContext
|
||||||
rb.Push<u8>(0);
|
rb.Push<u8>(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILibraryAppletSelfAccessor::PushInShowAlbum() {
|
|
||||||
const CommonArguments arguments{
|
|
||||||
.arguments_version = CommonArgumentVersion::Version3,
|
|
||||||
.size = CommonArgumentSize::Version3,
|
|
||||||
.library_version = 1,
|
|
||||||
.theme_color = ThemeColor::BasicBlack,
|
|
||||||
.play_startup_sound = true,
|
|
||||||
.system_tick = system.CoreTiming().GetClockTicks(),
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<u8> argument_data(sizeof(arguments));
|
|
||||||
std::vector<u8> settings_data{2};
|
|
||||||
std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
|
|
||||||
queue_data.emplace_back(std::move(argument_data));
|
|
||||||
queue_data.emplace_back(std::move(settings_data));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletSelfAccessor::PushInShowController() {
|
|
||||||
const CommonArguments common_args = {
|
|
||||||
.arguments_version = CommonArgumentVersion::Version3,
|
|
||||||
.size = CommonArgumentSize::Version3,
|
|
||||||
.library_version = static_cast<u32>(Frontend::ControllerAppletVersion::Version8),
|
|
||||||
.theme_color = ThemeColor::BasicBlack,
|
|
||||||
.play_startup_sound = true,
|
|
||||||
.system_tick = system.CoreTiming().GetClockTicks(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Frontend::ControllerSupportArgNew user_args = {
|
|
||||||
.header = {.player_count_min = 1,
|
|
||||||
.player_count_max = 4,
|
|
||||||
.enable_take_over_connection = true,
|
|
||||||
.enable_left_justify = false,
|
|
||||||
.enable_permit_joy_dual = true,
|
|
||||||
.enable_single_mode = false,
|
|
||||||
.enable_identification_color = false},
|
|
||||||
.identification_colors = {},
|
|
||||||
.enable_explain_text = false,
|
|
||||||
.explain_text = {},
|
|
||||||
};
|
|
||||||
|
|
||||||
Frontend::ControllerSupportArgPrivate private_args = {
|
|
||||||
.arg_private_size = sizeof(Frontend::ControllerSupportArgPrivate),
|
|
||||||
.arg_size = sizeof(Frontend::ControllerSupportArgNew),
|
|
||||||
.is_home_menu = true,
|
|
||||||
.flag_1 = true,
|
|
||||||
.mode = Frontend::ControllerSupportMode::ShowControllerSupport,
|
|
||||||
.caller = Frontend::ControllerSupportCaller::
|
|
||||||
Application, // switchbrew: Always zero except with
|
|
||||||
// ShowControllerFirmwareUpdateForSystem/ShowControllerKeyRemappingForSystem,
|
|
||||||
// which sets this to the input param
|
|
||||||
.style_set = Core::HID::NpadStyleSet::None,
|
|
||||||
.joy_hold_type = 0,
|
|
||||||
};
|
|
||||||
std::vector<u8> common_args_data(sizeof(common_args));
|
|
||||||
std::vector<u8> private_args_data(sizeof(private_args));
|
|
||||||
std::vector<u8> user_args_data(sizeof(user_args));
|
|
||||||
|
|
||||||
std::memcpy(common_args_data.data(), &common_args, sizeof(common_args));
|
|
||||||
std::memcpy(private_args_data.data(), &private_args, sizeof(private_args));
|
|
||||||
std::memcpy(user_args_data.data(), &user_args, sizeof(user_args));
|
|
||||||
|
|
||||||
queue_data.emplace_back(std::move(common_args_data));
|
|
||||||
queue_data.emplace_back(std::move(private_args_data));
|
|
||||||
queue_data.emplace_back(std::move(user_args_data));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletSelfAccessor::PushInShowCabinetData() {
|
|
||||||
const CommonArguments arguments{
|
|
||||||
.arguments_version = CommonArgumentVersion::Version3,
|
|
||||||
.size = CommonArgumentSize::Version3,
|
|
||||||
.library_version = static_cast<u32>(Frontend::CabinetAppletVersion::Version1),
|
|
||||||
.theme_color = ThemeColor::BasicBlack,
|
|
||||||
.play_startup_sound = true,
|
|
||||||
.system_tick = system.CoreTiming().GetClockTicks(),
|
|
||||||
};
|
|
||||||
|
|
||||||
const Frontend::StartParamForAmiiboSettings amiibo_settings{
|
|
||||||
.param_1 = 0,
|
|
||||||
.applet_mode = system.GetFrontendAppletHolder().GetCabinetMode(),
|
|
||||||
.flags = Frontend::CabinetFlags::None,
|
|
||||||
.amiibo_settings_1 = 0,
|
|
||||||
.device_handle = 0,
|
|
||||||
.tag_info{},
|
|
||||||
.register_info{},
|
|
||||||
.amiibo_settings_3{},
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<u8> argument_data(sizeof(arguments));
|
|
||||||
std::vector<u8> settings_data(sizeof(amiibo_settings));
|
|
||||||
std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
|
|
||||||
std::memcpy(settings_data.data(), &amiibo_settings, sizeof(amiibo_settings));
|
|
||||||
queue_data.emplace_back(std::move(argument_data));
|
|
||||||
queue_data.emplace_back(std::move(settings_data));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletSelfAccessor::PushInShowMiiEditData() {
|
|
||||||
struct MiiEditV3 {
|
|
||||||
Frontend::MiiEditAppletInputCommon common;
|
|
||||||
Frontend::MiiEditAppletInputV3 input;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(MiiEditV3) == 0x100, "MiiEditV3 has incorrect size.");
|
|
||||||
|
|
||||||
MiiEditV3 mii_arguments{
|
|
||||||
.common =
|
|
||||||
{
|
|
||||||
.version = Frontend::MiiEditAppletVersion::Version3,
|
|
||||||
.applet_mode = Frontend::MiiEditAppletMode::ShowMiiEdit,
|
|
||||||
},
|
|
||||||
.input{},
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<u8> argument_data(sizeof(mii_arguments));
|
|
||||||
std::memcpy(argument_data.data(), &mii_arguments, sizeof(mii_arguments));
|
|
||||||
|
|
||||||
queue_data.emplace_back(std::move(argument_data));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletSelfAccessor::PushInShowSoftwareKeyboard() {
|
|
||||||
const CommonArguments arguments{
|
|
||||||
.arguments_version = CommonArgumentVersion::Version3,
|
|
||||||
.size = CommonArgumentSize::Version3,
|
|
||||||
.library_version = static_cast<u32>(Frontend::SwkbdAppletVersion::Version524301),
|
|
||||||
.theme_color = ThemeColor::BasicBlack,
|
|
||||||
.play_startup_sound = true,
|
|
||||||
.system_tick = system.CoreTiming().GetClockTicks(),
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<char16_t> initial_string(0);
|
|
||||||
|
|
||||||
const Frontend::SwkbdConfigCommon swkbd_config{
|
|
||||||
.type = Frontend::SwkbdType::Qwerty,
|
|
||||||
.ok_text{},
|
|
||||||
.left_optional_symbol_key{},
|
|
||||||
.right_optional_symbol_key{},
|
|
||||||
.use_prediction = false,
|
|
||||||
.key_disable_flags{},
|
|
||||||
.initial_cursor_position = Frontend::SwkbdInitialCursorPosition::Start,
|
|
||||||
.header_text{},
|
|
||||||
.sub_text{},
|
|
||||||
.guide_text{},
|
|
||||||
.max_text_length = 500,
|
|
||||||
.min_text_length = 0,
|
|
||||||
.password_mode = Frontend::SwkbdPasswordMode::Disabled,
|
|
||||||
.text_draw_type = Frontend::SwkbdTextDrawType::Box,
|
|
||||||
.enable_return_button = true,
|
|
||||||
.use_utf8 = false,
|
|
||||||
.use_blur_background = true,
|
|
||||||
.initial_string_offset{},
|
|
||||||
.initial_string_length = static_cast<u32>(initial_string.size()),
|
|
||||||
.user_dictionary_offset{},
|
|
||||||
.user_dictionary_entries{},
|
|
||||||
.use_text_check = false,
|
|
||||||
};
|
|
||||||
|
|
||||||
Frontend::SwkbdConfigNew swkbd_config_new{};
|
|
||||||
|
|
||||||
std::vector<u8> argument_data(sizeof(arguments));
|
|
||||||
std::vector<u8> swkbd_data(sizeof(swkbd_config) + sizeof(swkbd_config_new));
|
|
||||||
std::vector<u8> work_buffer(swkbd_config.initial_string_length * sizeof(char16_t));
|
|
||||||
|
|
||||||
std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
|
|
||||||
std::memcpy(swkbd_data.data(), &swkbd_config, sizeof(swkbd_config));
|
|
||||||
std::memcpy(swkbd_data.data() + sizeof(swkbd_config), &swkbd_config_new,
|
|
||||||
sizeof(Frontend::SwkbdConfigNew));
|
|
||||||
std::memcpy(work_buffer.data(), initial_string.data(),
|
|
||||||
swkbd_config.initial_string_length * sizeof(char16_t));
|
|
||||||
|
|
||||||
queue_data.emplace_back(std::move(argument_data));
|
|
||||||
queue_data.emplace_back(std::move(swkbd_data));
|
|
||||||
queue_data.emplace_back(std::move(work_buffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|
|
@ -10,14 +10,21 @@
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct AppletStorageHolder;
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> {
|
class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> {
|
||||||
public:
|
public:
|
||||||
explicit ILibraryAppletSelfAccessor(Core::System& system_);
|
explicit ILibraryAppletSelfAccessor(Core::System& system_, std::shared_ptr<Applet> applet_);
|
||||||
~ILibraryAppletSelfAccessor() override;
|
~ILibraryAppletSelfAccessor() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void PopInData(HLERequestContext& ctx);
|
void PopInData(HLERequestContext& ctx);
|
||||||
void PushOutData(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 GetLibraryAppletInfo(HLERequestContext& ctx);
|
||||||
void GetMainAppletIdentityInfo(HLERequestContext& ctx);
|
void GetMainAppletIdentityInfo(HLERequestContext& ctx);
|
||||||
void ExitProcessAndReturn(HLERequestContext& ctx);
|
void ExitProcessAndReturn(HLERequestContext& ctx);
|
||||||
|
@ -26,13 +33,8 @@ private:
|
||||||
void GetMainAppletAvailableUsers(HLERequestContext& ctx);
|
void GetMainAppletAvailableUsers(HLERequestContext& ctx);
|
||||||
void ShouldSetGpuTimeSliceManually(HLERequestContext& ctx);
|
void ShouldSetGpuTimeSliceManually(HLERequestContext& ctx);
|
||||||
|
|
||||||
void PushInShowAlbum();
|
const std::shared_ptr<Applet> applet;
|
||||||
void PushInShowCabinetData();
|
const std::shared_ptr<AppletStorageHolder> storage;
|
||||||
void PushInShowMiiEditData();
|
|
||||||
void PushInShowSoftwareKeyboard();
|
|
||||||
void PushInShowController();
|
|
||||||
|
|
||||||
std::deque<std::vector<u8>> queue_data;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|
|
@ -8,8 +8,9 @@
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
IProcessWindingController::IProcessWindingController(Core::System& system_)
|
IProcessWindingController::IProcessWindingController(Core::System& system_,
|
||||||
: ServiceFramework{system_, "IProcessWindingController"} {
|
std::shared_ptr<Applet> applet_)
|
||||||
|
: ServiceFramework{system_, "IProcessWindingController"}, applet{std::move(applet_)} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &IProcessWindingController::GetLaunchReason, "GetLaunchReason"},
|
{0, &IProcessWindingController::GetLaunchReason, "GetLaunchReason"},
|
||||||
|
@ -31,34 +32,15 @@ IProcessWindingController::~IProcessWindingController() = default;
|
||||||
void IProcessWindingController::GetLaunchReason(HLERequestContext& ctx) {
|
void IProcessWindingController::GetLaunchReason(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
struct AppletProcessLaunchReason {
|
|
||||||
u8 flag;
|
|
||||||
INSERT_PADDING_BYTES(3);
|
|
||||||
};
|
|
||||||
static_assert(sizeof(AppletProcessLaunchReason) == 0x4,
|
|
||||||
"AppletProcessLaunchReason is an invalid size");
|
|
||||||
|
|
||||||
AppletProcessLaunchReason reason{
|
|
||||||
.flag = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushRaw(reason);
|
rb.PushRaw(applet->launch_reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) {
|
void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) {
|
||||||
const auto applet_id = system.GetFrontendAppletHolder().GetCurrentAppletId();
|
const auto caller_applet = applet->caller_applet.lock();
|
||||||
const auto applet_mode = LibraryAppletMode::AllForeground;
|
if (caller_applet == nullptr) {
|
||||||
|
LOG_ERROR(Service_AM, "No calling applet available");
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called with applet_id={:08X}, applet_mode={:08X}", applet_id,
|
|
||||||
applet_mode);
|
|
||||||
|
|
||||||
const auto& holder{system.GetFrontendAppletHolder()};
|
|
||||||
const auto applet = holder.GetApplet(applet_id, applet_mode);
|
|
||||||
|
|
||||||
if (applet == nullptr) {
|
|
||||||
LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultUnknown);
|
rb.Push(ResultUnknown);
|
||||||
|
@ -67,7 +49,8 @@ void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx)
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet);
|
rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet->caller_applet_storage,
|
||||||
|
caller_applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|
|
@ -7,14 +7,18 @@
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
class IProcessWindingController final : public ServiceFramework<IProcessWindingController> {
|
class IProcessWindingController final : public ServiceFramework<IProcessWindingController> {
|
||||||
public:
|
public:
|
||||||
explicit IProcessWindingController(Core::System& system_);
|
explicit IProcessWindingController(Core::System& system_, std::shared_ptr<Applet> applet_);
|
||||||
~IProcessWindingController() override;
|
~IProcessWindingController() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void GetLaunchReason(HLERequestContext& ctx);
|
void GetLaunchReason(HLERequestContext& ctx);
|
||||||
void OpenCallingLibraryApplet(HLERequestContext& ctx);
|
void OpenCallingLibraryApplet(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
const std::shared_ptr<Applet> applet;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|
|
@ -1,6 +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/am_results.h"
|
||||||
#include "core/hle/service/am/frontend/applets.h"
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
#include "core/hle/service/am/self_controller.h"
|
#include "core/hle/service/am/self_controller.h"
|
||||||
#include "core/hle/service/caps/caps_su.h"
|
#include "core/hle/service/caps/caps_su.h"
|
||||||
|
@ -12,9 +13,10 @@
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
ISelfController::ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_)
|
ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet> applet_,
|
||||||
: ServiceFramework{system_, "ISelfController"}, nvnflinger{nvnflinger_},
|
Nvnflinger::Nvnflinger& nvnflinger_)
|
||||||
service_context{system, "ISelfController"} {
|
: ServiceFramework{system_, "ISelfController"}, nvnflinger{nvnflinger_}, applet{std::move(
|
||||||
|
applet_)} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &ISelfController::Exit, "Exit"},
|
{0, &ISelfController::Exit, "Exit"},
|
||||||
|
@ -69,24 +71,9 @@ ISelfController::ISelfController(Core::System& system_, Nvnflinger::Nvnflinger&
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
RegisterHandlers(functions);
|
RegisterHandlers(functions);
|
||||||
|
|
||||||
launchable_event = service_context.CreateEvent("ISelfController:LaunchableEvent");
|
|
||||||
|
|
||||||
// This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is
|
|
||||||
// called. Yuzu can just create it unconditionally, since it doesn't need to support multiple
|
|
||||||
// ISelfControllers. The event is signaled on creation, and on transition from suspended -> not
|
|
||||||
// suspended if the event has previously been created by a call to
|
|
||||||
// GetAccumulatedSuspendedTickChangedEvent.
|
|
||||||
|
|
||||||
accumulated_suspended_tick_changed_event =
|
|
||||||
service_context.CreateEvent("ISelfController:AccumulatedSuspendedTickChangedEvent");
|
|
||||||
accumulated_suspended_tick_changed_event->Signal();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ISelfController::~ISelfController() {
|
ISelfController::~ISelfController() = default;
|
||||||
service_context.CloseEvent(launchable_event);
|
|
||||||
service_context.CloseEvent(accumulated_suspended_tick_changed_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ISelfController::Exit(HLERequestContext& ctx) {
|
void ISelfController::Exit(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
@ -94,6 +81,7 @@ void ISelfController::Exit(HLERequestContext& ctx) {
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
|
||||||
|
// TODO
|
||||||
system.Exit();
|
system.Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,8 +108,10 @@ void ISelfController::UnlockExit(HLERequestContext& ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISelfController::EnterFatalSection(HLERequestContext& ctx) {
|
void ISelfController::EnterFatalSection(HLERequestContext& ctx) {
|
||||||
++num_fatal_sections_entered;
|
|
||||||
LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", num_fatal_sections_entered);
|
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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -131,13 +121,14 @@ void ISelfController::LeaveFatalSection(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called.");
|
LOG_DEBUG(Service_AM, "called.");
|
||||||
|
|
||||||
// Entry and exit of fatal sections must be balanced.
|
// Entry and exit of fatal sections must be balanced.
|
||||||
if (num_fatal_sections_entered == 0) {
|
std::scoped_lock lk{applet->lock};
|
||||||
|
if (applet->fatal_section_count == 0) {
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(Result{ErrorModule::AM, 512});
|
rb.Push(AM::ResultFatalSectionCountImbalance);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
--num_fatal_sections_entered;
|
applet->fatal_section_count--;
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -146,11 +137,11 @@ void ISelfController::LeaveFatalSection(HLERequestContext& ctx) {
|
||||||
void ISelfController::GetLibraryAppletLaunchableEvent(HLERequestContext& ctx) {
|
void ISelfController::GetLibraryAppletLaunchableEvent(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
launchable_event->Signal();
|
applet->library_applet_launchable_event.Signal();
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushCopyObjects(launchable_event->GetReadableEvent());
|
rb.PushCopyObjects(applet->library_applet_launchable_event.GetHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) {
|
void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) {
|
||||||
|
@ -158,7 +149,8 @@ void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) {
|
||||||
const auto permission = rp.PopEnum<ScreenshotPermission>();
|
const auto permission = rp.PopEnum<ScreenshotPermission>();
|
||||||
LOG_DEBUG(Service_AM, "called, permission={}", permission);
|
LOG_DEBUG(Service_AM, "called, permission={}", permission);
|
||||||
|
|
||||||
screenshot_permission = permission;
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->screenshot_permission = permission;
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -167,8 +159,11 @@ void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) {
|
||||||
void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx) {
|
void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
bool flag = rp.Pop<bool>();
|
const bool notification_enabled = rp.Pop<bool>();
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
|
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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -177,28 +172,27 @@ void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx
|
||||||
void ISelfController::SetPerformanceModeChangedNotification(HLERequestContext& ctx) {
|
void ISelfController::SetPerformanceModeChangedNotification(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
bool flag = rp.Pop<bool>();
|
const bool notification_enabled = rp.Pop<bool>();
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
|
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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISelfController::SetFocusHandlingMode(HLERequestContext& ctx) {
|
void ISelfController::SetFocusHandlingMode(HLERequestContext& ctx) {
|
||||||
// Takes 3 input u8s with each field located immediately after the previous
|
|
||||||
// u8, these are bool flags. No output.
|
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
struct FocusHandlingModeParams {
|
const auto flags = rp.PopRaw<FocusHandlingMode>();
|
||||||
u8 unknown0;
|
|
||||||
u8 unknown1;
|
|
||||||
u8 unknown2;
|
|
||||||
};
|
|
||||||
const auto flags = rp.PopRaw<FocusHandlingModeParams>();
|
|
||||||
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called. unknown0={}, unknown1={}, unknown2={}",
|
LOG_WARNING(Service_AM, "(STUBBED) called. unknown0={}, unknown1={}, unknown2={}",
|
||||||
flags.unknown0, flags.unknown1, flags.unknown2);
|
flags.unknown0, flags.unknown1, flags.unknown2);
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->focus_handling_mode = flags;
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
@ -206,24 +200,35 @@ void ISelfController::SetFocusHandlingMode(HLERequestContext& ctx) {
|
||||||
void ISelfController::SetRestartMessageEnabled(HLERequestContext& ctx) {
|
void ISelfController::SetRestartMessageEnabled(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->restart_message_enabled = true;
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISelfController::SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx) {
|
void ISelfController::SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx) {
|
||||||
// Takes 3 input u8s with each field located immediately after the previous
|
|
||||||
// u8, these are bool flags. No output.
|
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
bool enabled = rp.Pop<bool>();
|
const bool enabled = rp.Pop<bool>();
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled);
|
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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) {
|
void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -232,14 +237,13 @@ void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) {
|
||||||
void ISelfController::CreateManagedDisplayLayer(HLERequestContext& ctx) {
|
void ISelfController::CreateManagedDisplayLayer(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
// TODO(Subv): Find out how AM determines the display to use, for now just
|
u64 layer_id{};
|
||||||
// create the layer in the Default display.
|
applet->managed_layer_holder.Initialize(&nvnflinger);
|
||||||
const auto display_id = nvnflinger.OpenDisplay("Default");
|
applet->managed_layer_holder.CreateManagedDisplayLayer(&layer_id);
|
||||||
const auto layer_id = nvnflinger.CreateLayer(*display_id);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push(*layer_id);
|
rb.Push(layer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) {
|
void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) {
|
||||||
|
@ -252,56 +256,46 @@ void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) {
|
||||||
void ISelfController::GetSystemSharedLayerHandle(HLERequestContext& ctx) {
|
void ISelfController::GetSystemSharedLayerHandle(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
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};
|
IPC::ResponseBuilder rb{ctx, 6};
|
||||||
rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess()));
|
rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess()));
|
||||||
rb.Push<s64>(system_shared_buffer_id);
|
rb.Push<s64>(buffer_id);
|
||||||
rb.Push<s64>(system_shared_layer_id);
|
rb.Push<s64>(layer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) {
|
void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
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};
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess()));
|
rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess()));
|
||||||
rb.Push<s64>(system_shared_buffer_id);
|
rb.Push<s64>(buffer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ISelfController::EnsureBufferSharingEnabled(Kernel::KProcess* process) {
|
Result ISelfController::EnsureBufferSharingEnabled(Kernel::KProcess* process) {
|
||||||
if (buffer_sharing_enabled) {
|
if (applet->system_buffer_manager.Initialize(&nvnflinger, process, applet->applet_id)) {
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (system.GetFrontendAppletHolder().GetCurrentAppletId() <= AppletId::Application) {
|
return VI::ResultOperationFailed;
|
||||||
return VI::ResultOperationFailed;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto display_id = nvnflinger.OpenDisplay("Default");
|
|
||||||
const auto result = nvnflinger.GetSystemBufferManager().Initialize(
|
|
||||||
&system_shared_buffer_id, &system_shared_layer_id, *display_id);
|
|
||||||
|
|
||||||
if (result.IsSuccess()) {
|
|
||||||
buffer_sharing_enabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) {
|
void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
// TODO(Subv): Find out how AM determines the display to use, for now just
|
u64 layer_id{};
|
||||||
// create the layer in the Default display.
|
u64 recording_layer_id{};
|
||||||
// This calls nn::vi::CreateRecordingLayer() which creates another layer.
|
applet->managed_layer_holder.Initialize(&nvnflinger);
|
||||||
// Currently we do not support more than 1 layer per display, output 1 layer id for now.
|
applet->managed_layer_holder.CreateManagedDisplaySeparableLayer(&layer_id, &recording_layer_id);
|
||||||
// Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse
|
|
||||||
// side effects.
|
|
||||||
// TODO: Support multiple layers
|
|
||||||
const auto display_id = nvnflinger.OpenDisplay("Default");
|
|
||||||
const auto layer_id = nvnflinger.CreateLayer(*display_id);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
IPC::ResponseBuilder rb{ctx, 6};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push(*layer_id);
|
rb.Push(layer_id);
|
||||||
|
rb.Push(recording_layer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) {
|
void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) {
|
||||||
|
@ -320,9 +314,12 @@ void ISelfController::ApproveToDisplay(HLERequestContext& ctx) {
|
||||||
|
|
||||||
void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) {
|
void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
idle_time_detection_extension = rp.Pop<u32>();
|
|
||||||
LOG_DEBUG(Service_AM, "(STUBBED) called idle_time_detection_extension={}",
|
const auto extension = rp.PopRaw<IdleTimeDetectionExtension>();
|
||||||
idle_time_detection_extension);
|
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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -331,9 +328,11 @@ void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) {
|
||||||
void ISelfController::GetIdleTimeDetectionExtension(HLERequestContext& ctx) {
|
void ISelfController::GetIdleTimeDetectionExtension(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push<u32>(idle_time_detection_extension);
|
rb.PushRaw<IdleTimeDetectionExtension>(applet->idle_time_detection_extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISelfController::ReportUserIsActive(HLERequestContext& ctx) {
|
void ISelfController::ReportUserIsActive(HLERequestContext& ctx) {
|
||||||
|
@ -345,7 +344,9 @@ void ISelfController::ReportUserIsActive(HLERequestContext& ctx) {
|
||||||
|
|
||||||
void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) {
|
void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
is_auto_sleep_disabled = rp.Pop<bool>();
|
|
||||||
|
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
|
// 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
|
// differed from the current value passed in, it'd signify the internal
|
||||||
|
@ -357,7 +358,7 @@ void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) {
|
||||||
// and it's sufficient to simply set the member variable for querying via
|
// and it's sufficient to simply set the member variable for querying via
|
||||||
// IsAutoSleepDisabled().
|
// IsAutoSleepDisabled().
|
||||||
|
|
||||||
LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", is_auto_sleep_disabled);
|
LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", applet->auto_sleep_disabled);
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -366,20 +367,23 @@ void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) {
|
||||||
void ISelfController::IsAutoSleepDisabled(HLERequestContext& ctx) {
|
void ISelfController::IsAutoSleepDisabled(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called.");
|
LOG_DEBUG(Service_AM, "called.");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push(is_auto_sleep_disabled);
|
rb.Push(applet->auto_sleep_disabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISelfController::GetAccumulatedSuspendedTickValue(HLERequestContext& ctx) {
|
void ISelfController::GetAccumulatedSuspendedTickValue(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called.");
|
LOG_DEBUG(Service_AM, "called.");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
// This command returns the total number of system ticks since ISelfController creation
|
// 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
|
// where the game was suspended. Since Yuzu doesn't implement game suspension, this command
|
||||||
// can just always return 0 ticks.
|
// can just always return 0 ticks.
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push<u64>(0);
|
rb.Push<u64>(applet->suspended_ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx) {
|
void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx) {
|
||||||
|
@ -387,7 +391,7 @@ void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext&
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushCopyObjects(accumulated_suspended_tick_changed_event->GetReadableEvent());
|
rb.PushCopyObjects(applet->accumulated_suspended_tick_changed_event.GetHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx) {
|
void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx) {
|
||||||
|
@ -396,10 +400,11 @@ void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& c
|
||||||
// This service call sets an internal flag whether a notification is shown when an image is
|
// 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
|
// captured. Currently we do not support capturing images via the capture button, so this can be
|
||||||
// stubbed for now.
|
// stubbed for now.
|
||||||
const bool album_image_taken_notification_enabled = rp.Pop<bool>();
|
const bool enabled = rp.Pop<bool>();
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called. enabled={}", enabled);
|
||||||
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called. album_image_taken_notification_enabled={}",
|
std::scoped_lock lk{applet->lock};
|
||||||
album_image_taken_notification_enabled);
|
applet->album_image_taken_notification_enabled = enabled;
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -427,9 +432,11 @@ void ISelfController::SaveCurrentScreenshot(HLERequestContext& ctx) {
|
||||||
void ISelfController::SetRecordVolumeMuted(HLERequestContext& ctx) {
|
void ISelfController::SetRecordVolumeMuted(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
const auto is_record_volume_muted = rp.Pop<bool>();
|
const auto enabled = rp.Pop<bool>();
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called. enabled={}", enabled);
|
||||||
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called. is_record_volume_muted={}", is_record_volume_muted);
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->record_volume_muted = enabled;
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
|
|
@ -8,9 +8,12 @@
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
class ISelfController final : public ServiceFramework<ISelfController> {
|
class ISelfController final : public ServiceFramework<ISelfController> {
|
||||||
public:
|
public:
|
||||||
explicit ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_);
|
explicit ISelfController(Core::System& system_, std::shared_ptr<Applet> applet_,
|
||||||
|
Nvnflinger::Nvnflinger& nvnflinger_);
|
||||||
~ISelfController() override;
|
~ISelfController() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -47,26 +50,8 @@ private:
|
||||||
|
|
||||||
Result EnsureBufferSharingEnabled(Kernel::KProcess* process);
|
Result EnsureBufferSharingEnabled(Kernel::KProcess* process);
|
||||||
|
|
||||||
enum class ScreenshotPermission : u32 {
|
|
||||||
Inherit = 0,
|
|
||||||
Enable = 1,
|
|
||||||
Disable = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
Nvnflinger::Nvnflinger& nvnflinger;
|
Nvnflinger::Nvnflinger& nvnflinger;
|
||||||
|
const std::shared_ptr<Applet> applet;
|
||||||
KernelHelpers::ServiceContext service_context;
|
|
||||||
|
|
||||||
Kernel::KEvent* launchable_event;
|
|
||||||
Kernel::KEvent* accumulated_suspended_tick_changed_event;
|
|
||||||
|
|
||||||
u32 idle_time_detection_extension = 0;
|
|
||||||
u64 num_fatal_sections_entered = 0;
|
|
||||||
u64 system_shared_buffer_id = 0;
|
|
||||||
u64 system_shared_layer_id = 0;
|
|
||||||
bool is_auto_sleep_disabled = false;
|
|
||||||
bool buffer_sharing_enabled = false;
|
|
||||||
ScreenshotPermission screenshot_permission = ScreenshotPermission::Inherit;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|
|
@ -20,10 +20,9 @@
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
ISystemAppletProxy::ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
ISystemAppletProxy::ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue_,
|
std::shared_ptr<Applet> applet_, Core::System& system_)
|
||||||
Core::System& system_)
|
: ServiceFramework{system_, "ISystemAppletProxy"}, nvnflinger{nvnflinger_}, applet{std::move(
|
||||||
: ServiceFramework{system_, "ISystemAppletProxy"}, nvnflinger{nvnflinger_},
|
applet_)} {
|
||||||
msg_queue{std::move(msg_queue_)} {
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
|
{0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
|
||||||
|
@ -44,12 +43,14 @@ ISystemAppletProxy::ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
||||||
RegisterHandlers(functions);
|
RegisterHandlers(functions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ISystemAppletProxy::~ISystemAppletProxy() = default;
|
||||||
|
|
||||||
void ISystemAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) {
|
void ISystemAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue);
|
rb.PushIpcInterface<ICommonStateGetter>(system, applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISystemAppletProxy::GetSelfController(HLERequestContext& ctx) {
|
void ISystemAppletProxy::GetSelfController(HLERequestContext& ctx) {
|
||||||
|
@ -57,7 +58,7 @@ void ISystemAppletProxy::GetSelfController(HLERequestContext& ctx) {
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<ISelfController>(system, nvnflinger);
|
rb.PushIpcInterface<ISelfController>(system, applet, nvnflinger);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISystemAppletProxy::GetWindowController(HLERequestContext& ctx) {
|
void ISystemAppletProxy::GetWindowController(HLERequestContext& ctx) {
|
||||||
|
@ -65,7 +66,7 @@ void ISystemAppletProxy::GetWindowController(HLERequestContext& ctx) {
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<IWindowController>(system);
|
rb.PushIpcInterface<IWindowController>(system, applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISystemAppletProxy::GetAudioController(HLERequestContext& ctx) {
|
void ISystemAppletProxy::GetAudioController(HLERequestContext& ctx) {
|
||||||
|
@ -89,7 +90,7 @@ void ISystemAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<ILibraryAppletCreator>(system);
|
rb.PushIpcInterface<ILibraryAppletCreator>(system, applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISystemAppletProxy::GetHomeMenuFunctions(HLERequestContext& ctx) {
|
void ISystemAppletProxy::GetHomeMenuFunctions(HLERequestContext& ctx) {
|
||||||
|
@ -121,7 +122,7 @@ void ISystemAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) {
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<IAppletCommonFunctions>(system);
|
rb.PushIpcInterface<IAppletCommonFunctions>(system, applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISystemAppletProxy::GetDebugFunctions(HLERequestContext& ctx) {
|
void ISystemAppletProxy::GetDebugFunctions(HLERequestContext& ctx) {
|
||||||
|
|
|
@ -8,11 +8,13 @@
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> {
|
class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> {
|
||||||
public:
|
public:
|
||||||
explicit ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
explicit ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue_,
|
std::shared_ptr<Applet> applet_, Core::System& system_);
|
||||||
Core::System& system_);
|
~ISystemAppletProxy();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void GetCommonStateGetter(HLERequestContext& ctx);
|
void GetCommonStateGetter(HLERequestContext& ctx);
|
||||||
|
@ -28,7 +30,7 @@ private:
|
||||||
void GetDebugFunctions(HLERequestContext& ctx);
|
void GetDebugFunctions(HLERequestContext& ctx);
|
||||||
|
|
||||||
Nvnflinger::Nvnflinger& nvnflinger;
|
Nvnflinger::Nvnflinger& nvnflinger;
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue;
|
std::shared_ptr<Applet> applet;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
// 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/applet.h"
|
||||||
#include "core/hle/service/am/window_controller.h"
|
#include "core/hle/service/am/window_controller.h"
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
IWindowController::IWindowController(Core::System& system_)
|
IWindowController::IWindowController(Core::System& system_, std::shared_ptr<Applet> applet_)
|
||||||
: ServiceFramework{system_, "IWindowController"} {
|
: ServiceFramework{system_, "IWindowController"}, applet{std::move(applet_)} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, nullptr, "CreateWindow"},
|
{0, nullptr, "CreateWindow"},
|
||||||
|
@ -27,23 +28,22 @@ IWindowController::IWindowController(Core::System& system_)
|
||||||
IWindowController::~IWindowController() = default;
|
IWindowController::~IWindowController() = default;
|
||||||
|
|
||||||
void IWindowController::GetAppletResourceUserId(HLERequestContext& ctx) {
|
void IWindowController::GetAppletResourceUserId(HLERequestContext& ctx) {
|
||||||
const u64 process_id = system.ApplicationProcess()->GetProcessId();
|
|
||||||
|
|
||||||
LOG_DEBUG(Service_AM, "called. Process ID=0x{:016X}", process_id);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push<u64>(process_id);
|
rb.Push<u64>(applet->aruid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IWindowController::GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx) {
|
void IWindowController::GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx) {
|
||||||
const u64 process_id = 0;
|
u64 aruid = 0;
|
||||||
|
if (auto caller = applet->caller_applet.lock(); caller) {
|
||||||
|
aruid = caller->aruid;
|
||||||
|
}
|
||||||
|
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push<u64>(process_id);
|
rb.Push<u64>(aruid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IWindowController::AcquireForegroundRights(HLERequestContext& ctx) {
|
void IWindowController::AcquireForegroundRights(HLERequestContext& ctx) {
|
||||||
|
|
|
@ -7,15 +7,19 @@
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
class IWindowController final : public ServiceFramework<IWindowController> {
|
class IWindowController final : public ServiceFramework<IWindowController> {
|
||||||
public:
|
public:
|
||||||
explicit IWindowController(Core::System& system_);
|
explicit IWindowController(Core::System& system_, std::shared_ptr<Applet> applet_);
|
||||||
~IWindowController() override;
|
~IWindowController() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void GetAppletResourceUserId(HLERequestContext& ctx);
|
void GetAppletResourceUserId(HLERequestContext& ctx);
|
||||||
void GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx);
|
void GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx);
|
||||||
void AcquireForegroundRights(HLERequestContext& ctx);
|
void AcquireForegroundRights(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
const std::shared_ptr<Applet> applet;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|
|
@ -535,6 +535,12 @@ public:
|
||||||
RegisterHandlers(functions);
|
RegisterHandlers(functions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~IApplicationDisplayService() {
|
||||||
|
for (const auto layer_id : stray_layer_ids) {
|
||||||
|
nvnflinger.DestroyLayer(layer_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class ConvertedScaleMode : u64 {
|
enum class ConvertedScaleMode : u64 {
|
||||||
Freeze = 0,
|
Freeze = 0,
|
||||||
|
@ -770,6 +776,7 @@ private:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stray_layer_ids.push_back(*layer_id);
|
||||||
const auto buffer_queue_id = nvnflinger.FindBufferQueueId(display_id, *layer_id);
|
const auto buffer_queue_id = nvnflinger.FindBufferQueueId(display_id, *layer_id);
|
||||||
if (!buffer_queue_id) {
|
if (!buffer_queue_id) {
|
||||||
LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id);
|
LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id);
|
||||||
|
@ -916,6 +923,7 @@ private:
|
||||||
|
|
||||||
Nvnflinger::Nvnflinger& nvnflinger;
|
Nvnflinger::Nvnflinger& nvnflinger;
|
||||||
Nvnflinger::HosBinderDriverServer& hos_binder_driver_server;
|
Nvnflinger::HosBinderDriverServer& hos_binder_driver_server;
|
||||||
|
std::vector<u64> stray_layer_ids;
|
||||||
bool vsync_event_fetched{false};
|
bool vsync_event_fetched{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "core/core.h"
|
#include "core/core.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_ae.h"
|
||||||
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
#include "core/hle/service/am/applet_message_queue.h"
|
#include "core/hle/service/am/applet_message_queue.h"
|
||||||
#include "core/hle/service/am/applet_oe.h"
|
#include "core/hle/service/am/applet_oe.h"
|
||||||
#include "core/hle/service/sm/sm.h"
|
#include "core/hle/service/sm/sm.h"
|
||||||
|
@ -48,22 +49,8 @@ void OnDockedModeChanged(bool last_state, bool new_state, Core::System& system)
|
||||||
if (!system.IsPoweredOn()) {
|
if (!system.IsPoweredOn()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Service::SM::ServiceManager& sm = system.ServiceManager();
|
|
||||||
|
|
||||||
// Message queue is shared between these services, we just need to signal an operation
|
system.GetAppletManager().OperationModeChanged();
|
||||||
// change to one and it will handle both automatically
|
|
||||||
auto applet_oe = sm.GetService<Service::AM::AppletOE>("appletOE");
|
|
||||||
auto applet_ae = sm.GetService<Service::AM::AppletAE>("appletAE");
|
|
||||||
bool has_signalled = false;
|
|
||||||
|
|
||||||
if (applet_oe != nullptr) {
|
|
||||||
applet_oe->GetMessageQueue()->OperationModeChanged();
|
|
||||||
has_signalled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (applet_ae != nullptr && !has_signalled) {
|
|
||||||
applet_ae->GetMessageQueue()->OperationModeChanged();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigureInput::ConfigureInput(Core::System& system_, QWidget* parent)
|
ConfigureInput::ConfigureInput(Core::System& system_, QWidget* parent)
|
||||||
|
|
|
@ -4783,36 +4783,12 @@ void GMainWindow::RequestGameExit() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& sm{system->ServiceManager()};
|
|
||||||
auto applet_oe = sm.GetService<Service::AM::AppletOE>("appletOE");
|
|
||||||
auto applet_ae = sm.GetService<Service::AM::AppletAE>("appletAE");
|
|
||||||
bool has_signalled = false;
|
|
||||||
|
|
||||||
system->SetExitRequested(true);
|
system->SetExitRequested(true);
|
||||||
|
system->GetAppletManager().RequestExit();
|
||||||
if (applet_oe != nullptr) {
|
|
||||||
applet_oe->GetMessageQueue()->RequestExit();
|
|
||||||
has_signalled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (applet_ae != nullptr && !has_signalled) {
|
|
||||||
applet_ae->GetMessageQueue()->RequestExit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::RequestGameResume() {
|
void GMainWindow::RequestGameResume() {
|
||||||
auto& sm{system->ServiceManager()};
|
system->GetAppletManager().RequestResume();
|
||||||
auto applet_oe = sm.GetService<Service::AM::AppletOE>("appletOE");
|
|
||||||
auto applet_ae = sm.GetService<Service::AM::AppletAE>("appletAE");
|
|
||||||
|
|
||||||
if (applet_oe != nullptr) {
|
|
||||||
applet_oe->GetMessageQueue()->RequestResume();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (applet_ae != nullptr) {
|
|
||||||
applet_ae->GetMessageQueue()->RequestResume();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::filterBarSetChecked(bool state) {
|
void GMainWindow::filterBarSetChecked(bool state) {
|
||||||
|
|
Reference in New Issue