Merge pull request #12760 from liamwhite/mp-am
am: rewrite for multiprocess support
This commit is contained in:
commit
7cc7d027f7
|
@ -261,7 +261,7 @@ object NativeLibrary {
|
||||||
/**
|
/**
|
||||||
* Begins emulation.
|
* Begins emulation.
|
||||||
*/
|
*/
|
||||||
external fun run(path: String?, programIndex: Int = 0)
|
external fun run(path: String?, programIndex: Int, frontendInitiated: Boolean)
|
||||||
|
|
||||||
// Surface Handling
|
// Surface Handling
|
||||||
external fun surfaceChanged(surf: Surface?)
|
external fun surfaceChanged(surf: Surface?)
|
||||||
|
|
|
@ -927,7 +927,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
emulationThread.join()
|
emulationThread.join()
|
||||||
emulationThread = Thread({
|
emulationThread = Thread({
|
||||||
Log.debug("[EmulationFragment] Starting emulation thread.")
|
Log.debug("[EmulationFragment] Starting emulation thread.")
|
||||||
NativeLibrary.run(gamePath, programIndex)
|
NativeLibrary.run(gamePath, programIndex, false)
|
||||||
}, "NativeEmulation")
|
}, "NativeEmulation")
|
||||||
emulationThread.start()
|
emulationThread.start()
|
||||||
}
|
}
|
||||||
|
@ -981,7 +981,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
State.STOPPED -> {
|
State.STOPPED -> {
|
||||||
emulationThread = Thread({
|
emulationThread = Thread({
|
||||||
Log.debug("[EmulationFragment] Starting emulation thread.")
|
Log.debug("[EmulationFragment] Starting emulation thread.")
|
||||||
NativeLibrary.run(gamePath, programIndex)
|
NativeLibrary.run(gamePath, programIndex, true)
|
||||||
}, "NativeEmulation")
|
}, "NativeEmulation")
|
||||||
emulationThread.start()
|
emulationThread.start()
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ AndroidKeyboard::ResultData AndroidKeyboard::ResultData::CreateFromFrontend(jobj
|
||||||
const jstring string = reinterpret_cast<jstring>(env->GetObjectField(
|
const jstring string = reinterpret_cast<jstring>(env->GetObjectField(
|
||||||
object, env->GetFieldID(s_keyboard_data_class, "text", "Ljava/lang/String;")));
|
object, env->GetFieldID(s_keyboard_data_class, "text", "Ljava/lang/String;")));
|
||||||
return ResultData{GetJString(env, string),
|
return ResultData{GetJString(env, string),
|
||||||
static_cast<Service::AM::Applets::SwkbdResult>(env->GetIntField(
|
static_cast<Service::AM::Frontend::SwkbdResult>(env->GetIntField(
|
||||||
object, env->GetFieldID(s_keyboard_data_class, "result", "I")))};
|
object, env->GetFieldID(s_keyboard_data_class, "result", "I")))};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ void AndroidKeyboard::ShowNormalKeyboard() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidKeyboard::ShowTextCheckDialog(
|
void AndroidKeyboard::ShowTextCheckDialog(
|
||||||
Service::AM::Applets::SwkbdTextCheckResult text_check_result,
|
Service::AM::Frontend::SwkbdTextCheckResult text_check_result,
|
||||||
std::u16string text_check_message) const {
|
std::u16string text_check_message) const {
|
||||||
LOG_WARNING(Frontend, "(STUBBED) called, backend requested to show the text check dialog.");
|
LOG_WARNING(Frontend, "(STUBBED) called, backend requested to show the text check dialog.");
|
||||||
}
|
}
|
||||||
|
@ -204,7 +204,7 @@ void AndroidKeyboard::InlineTextChanged(
|
||||||
"\ncursor_position={}",
|
"\ncursor_position={}",
|
||||||
Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position);
|
Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position);
|
||||||
|
|
||||||
submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString,
|
submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString,
|
||||||
text_parameters.input_text, text_parameters.cursor_position);
|
text_parameters.input_text, text_parameters.cursor_position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@ void AndroidKeyboard::SubmitInlineKeyboardText(std::u16string submitted_text) {
|
||||||
|
|
||||||
m_current_text += submitted_text;
|
m_current_text += submitted_text;
|
||||||
|
|
||||||
submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString, m_current_text,
|
submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString, m_current_text,
|
||||||
m_current_text.size());
|
m_current_text.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,12 +236,12 @@ void AndroidKeyboard::SubmitInlineKeyboardInput(int key_code) {
|
||||||
case KEYCODE_BACK:
|
case KEYCODE_BACK:
|
||||||
case KEYCODE_ENTER:
|
case KEYCODE_ENTER:
|
||||||
m_is_inline_active = false;
|
m_is_inline_active = false;
|
||||||
submit_inline_callback(Service::AM::Applets::SwkbdReplyType::DecidedEnter, m_current_text,
|
submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::DecidedEnter, m_current_text,
|
||||||
static_cast<s32>(m_current_text.size()));
|
static_cast<s32>(m_current_text.size()));
|
||||||
break;
|
break;
|
||||||
case KEYCODE_DEL:
|
case KEYCODE_DEL:
|
||||||
m_current_text.pop_back();
|
m_current_text.pop_back();
|
||||||
submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString, m_current_text,
|
submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString, m_current_text,
|
||||||
m_current_text.size());
|
m_current_text.size());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ public:
|
||||||
|
|
||||||
void ShowNormalKeyboard() const override;
|
void ShowNormalKeyboard() const override;
|
||||||
|
|
||||||
void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result,
|
void ShowTextCheckDialog(Service::AM::Frontend::SwkbdTextCheckResult text_check_result,
|
||||||
std::u16string text_check_message) const override;
|
std::u16string text_check_message) const override;
|
||||||
|
|
||||||
void ShowInlineKeyboard(
|
void ShowInlineKeyboard(
|
||||||
|
@ -45,7 +45,7 @@ private:
|
||||||
static ResultData CreateFromFrontend(jobject object);
|
static ResultData CreateFromFrontend(jobject object);
|
||||||
|
|
||||||
std::string text;
|
std::string text;
|
||||||
Service::AM::Applets::SwkbdResult result{};
|
Service::AM::Frontend::SwkbdResult result{};
|
||||||
};
|
};
|
||||||
|
|
||||||
void SubmitNormalText(const ResultData& result) const;
|
void SubmitNormalText(const ResultData& result) const;
|
||||||
|
|
|
@ -42,14 +42,15 @@
|
||||||
#include "core/frontend/applets/cabinet.h"
|
#include "core/frontend/applets/cabinet.h"
|
||||||
#include "core/frontend/applets/controller.h"
|
#include "core/frontend/applets/controller.h"
|
||||||
#include "core/frontend/applets/error.h"
|
#include "core/frontend/applets/error.h"
|
||||||
#include "core/frontend/applets/general_frontend.h"
|
#include "core/frontend/applets/general.h"
|
||||||
#include "core/frontend/applets/mii_edit.h"
|
#include "core/frontend/applets/mii_edit.h"
|
||||||
#include "core/frontend/applets/profile_select.h"
|
#include "core/frontend/applets/profile_select.h"
|
||||||
#include "core/frontend/applets/software_keyboard.h"
|
#include "core/frontend/applets/software_keyboard.h"
|
||||||
#include "core/frontend/applets/web_browser.h"
|
#include "core/frontend/applets/web_browser.h"
|
||||||
#include "core/hle/service/am/applet_ae.h"
|
#include "core/hle/service/am/applet_ae.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/applets/applets.h"
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
#include "core/hle/service/filesystem/filesystem.h"
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||||
#include "core/loader/loader.h"
|
#include "core/loader/loader.h"
|
||||||
#include "frontend_common/config.h"
|
#include "frontend_common/config.h"
|
||||||
|
@ -211,8 +212,15 @@ void EmulationSession::InitializeSystem(bool reload) {
|
||||||
m_system.GetFileSystemController().CreateFactories(*m_vfs);
|
m_system.GetFileSystemController().CreateFactories(*m_vfs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmulationSession::SetAppletId(int applet_id) {
|
||||||
|
m_applet_id = applet_id;
|
||||||
|
m_system.GetFrontendAppletHolder().SetCurrentAppletId(
|
||||||
|
static_cast<Service::AM::AppletId>(m_applet_id));
|
||||||
|
}
|
||||||
|
|
||||||
Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath,
|
Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath,
|
||||||
const std::size_t program_index) {
|
const std::size_t program_index,
|
||||||
|
const bool frontend_initiated) {
|
||||||
std::scoped_lock lock(m_mutex);
|
std::scoped_lock lock(m_mutex);
|
||||||
|
|
||||||
// Create the render window.
|
// Create the render window.
|
||||||
|
@ -226,7 +234,7 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
|
||||||
m_system.ApplySettings();
|
m_system.ApplySettings();
|
||||||
Settings::LogSettings();
|
Settings::LogSettings();
|
||||||
m_system.HIDCore().ReloadInputDevices();
|
m_system.HIDCore().ReloadInputDevices();
|
||||||
m_system.SetAppletFrontendSet({
|
m_system.SetFrontendAppletSet({
|
||||||
nullptr, // Amiibo Settings
|
nullptr, // Amiibo Settings
|
||||||
nullptr, // Controller Selector
|
nullptr, // Controller Selector
|
||||||
nullptr, // Error Display
|
nullptr, // Error Display
|
||||||
|
@ -242,8 +250,13 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
|
||||||
ConfigureFilesystemProvider(filepath);
|
ConfigureFilesystemProvider(filepath);
|
||||||
|
|
||||||
// Load the ROM.
|
// Load the ROM.
|
||||||
m_load_result =
|
Service::AM::FrontendAppletParameters params{
|
||||||
m_system.Load(EmulationSession::GetInstance().Window(), filepath, 0, program_index);
|
.applet_id = static_cast<Service::AM::AppletId>(m_applet_id),
|
||||||
|
.launch_type = frontend_initiated ? Service::AM::LaunchType::FrontendInitiated
|
||||||
|
: Service::AM::LaunchType::ApplicationInitiated,
|
||||||
|
.program_index = static_cast<s32>(program_index),
|
||||||
|
};
|
||||||
|
m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params);
|
||||||
if (m_load_result != Core::SystemResultStatus::Success) {
|
if (m_load_result != Core::SystemResultStatus::Success) {
|
||||||
return m_load_result;
|
return m_load_result;
|
||||||
}
|
}
|
||||||
|
@ -339,6 +352,9 @@ void EmulationSession::RunEmulation() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset current applet ID.
|
||||||
|
m_applet_id = static_cast<int>(Service::AM::AppletId::Application);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmulationSession::IsHandheldOnly() {
|
bool EmulationSession::IsHandheldOnly() {
|
||||||
|
@ -434,7 +450,8 @@ u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static Core::SystemResultStatus RunEmulation(const std::string& filepath,
|
static Core::SystemResultStatus RunEmulation(const std::string& filepath,
|
||||||
const size_t program_index = 0) {
|
const size_t program_index,
|
||||||
|
const bool frontend_initiated) {
|
||||||
MicroProfileOnThreadCreate("EmuThread");
|
MicroProfileOnThreadCreate("EmuThread");
|
||||||
SCOPE_EXIT({ MicroProfileShutdown(); });
|
SCOPE_EXIT({ MicroProfileShutdown(); });
|
||||||
|
|
||||||
|
@ -447,7 +464,8 @@ static Core::SystemResultStatus RunEmulation(const std::string& filepath,
|
||||||
|
|
||||||
SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); });
|
SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); });
|
||||||
|
|
||||||
jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath, program_index);
|
jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath, program_index,
|
||||||
|
frontend_initiated);
|
||||||
if (result != Core::SystemResultStatus::Success) {
|
if (result != Core::SystemResultStatus::Success) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -744,10 +762,12 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_logSettings(JNIEnv* env, jobject jobj
|
||||||
}
|
}
|
||||||
|
|
||||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_run(JNIEnv* env, jobject jobj, jstring j_path,
|
void Java_org_yuzu_yuzu_1emu_NativeLibrary_run(JNIEnv* env, jobject jobj, jstring j_path,
|
||||||
jint j_program_index) {
|
jint j_program_index,
|
||||||
|
jboolean j_frontend_initiated) {
|
||||||
const std::string path = GetJString(env, j_path);
|
const std::string path = GetJString(env, j_path);
|
||||||
|
|
||||||
const Core::SystemResultStatus result{RunEmulation(path, j_program_index)};
|
const Core::SystemResultStatus result{
|
||||||
|
RunEmulation(path, j_program_index, j_frontend_initiated)};
|
||||||
if (result != Core::SystemResultStatus::Success) {
|
if (result != Core::SystemResultStatus::Success) {
|
||||||
env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
|
env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
|
||||||
IDCache::GetExitEmulationActivity(), static_cast<int>(result));
|
IDCache::GetExitEmulationActivity(), static_cast<int>(result));
|
||||||
|
@ -809,13 +829,12 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getAppletLaunchPath(JNIEnv* env, j
|
||||||
|
|
||||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCurrentAppletId(JNIEnv* env, jclass clazz,
|
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCurrentAppletId(JNIEnv* env, jclass clazz,
|
||||||
jint jappletId) {
|
jint jappletId) {
|
||||||
EmulationSession::GetInstance().System().GetAppletManager().SetCurrentAppletId(
|
EmulationSession::GetInstance().SetAppletId(jappletId);
|
||||||
static_cast<Service::AM::Applets::AppletId>(jappletId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCabinetMode(JNIEnv* env, jclass clazz,
|
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCabinetMode(JNIEnv* env, jclass clazz,
|
||||||
jint jcabinetMode) {
|
jint jcabinetMode) {
|
||||||
EmulationSession::GetInstance().System().GetAppletManager().SetCabinetMode(
|
EmulationSession::GetInstance().System().GetFrontendAppletHolder().SetCabinetMode(
|
||||||
static_cast<Service::NFP::CabinetMode>(jcabinetMode));
|
static_cast<Service::NFP::CabinetMode>(jcabinetMode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,8 +45,10 @@ public:
|
||||||
const Core::PerfStatsResults& PerfStats();
|
const Core::PerfStatsResults& PerfStats();
|
||||||
void ConfigureFilesystemProvider(const std::string& filepath);
|
void ConfigureFilesystemProvider(const std::string& filepath);
|
||||||
void InitializeSystem(bool reload);
|
void InitializeSystem(bool reload);
|
||||||
|
void SetAppletId(int applet_id);
|
||||||
Core::SystemResultStatus InitializeEmulation(const std::string& filepath,
|
Core::SystemResultStatus InitializeEmulation(const std::string& filepath,
|
||||||
const std::size_t program_index = 0);
|
const std::size_t program_index,
|
||||||
|
const bool frontend_initiated);
|
||||||
|
|
||||||
bool IsHandheldOnly();
|
bool IsHandheldOnly();
|
||||||
void SetDeviceType([[maybe_unused]] int index, int type);
|
void SetDeviceType([[maybe_unused]] int index, int type);
|
||||||
|
@ -79,6 +81,7 @@ private:
|
||||||
std::atomic<bool> m_is_paused = false;
|
std::atomic<bool> m_is_paused = false;
|
||||||
SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{};
|
SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{};
|
||||||
std::unique_ptr<FileSys::ManualContentProvider> m_manual_provider;
|
std::unique_ptr<FileSys::ManualContentProvider> m_manual_provider;
|
||||||
|
int m_applet_id{1};
|
||||||
|
|
||||||
// GPU driver parameters
|
// GPU driver parameters
|
||||||
std::shared_ptr<Common::DynamicLibrary> m_vulkan_library;
|
std::shared_ptr<Common::DynamicLibrary> m_vulkan_library;
|
||||||
|
|
|
@ -176,8 +176,8 @@ add_library(core STATIC
|
||||||
frontend/applets/controller.h
|
frontend/applets/controller.h
|
||||||
frontend/applets/error.cpp
|
frontend/applets/error.cpp
|
||||||
frontend/applets/error.h
|
frontend/applets/error.h
|
||||||
frontend/applets/general_frontend.cpp
|
frontend/applets/general.cpp
|
||||||
frontend/applets/general_frontend.h
|
frontend/applets/general.h
|
||||||
frontend/applets/mii_edit.cpp
|
frontend/applets/mii_edit.cpp
|
||||||
frontend/applets/mii_edit.h
|
frontend/applets/mii_edit.h
|
||||||
frontend/applets/profile_select.cpp
|
frontend/applets/profile_select.cpp
|
||||||
|
@ -390,39 +390,101 @@ add_library(core STATIC
|
||||||
hle/service/acc/errors.h
|
hle/service/acc/errors.h
|
||||||
hle/service/acc/profile_manager.cpp
|
hle/service/acc/profile_manager.cpp
|
||||||
hle/service/acc/profile_manager.h
|
hle/service/acc/profile_manager.h
|
||||||
|
hle/service/am/frontend/applet_cabinet.cpp
|
||||||
|
hle/service/am/frontend/applet_cabinet.h
|
||||||
|
hle/service/am/frontend/applet_controller.cpp
|
||||||
|
hle/service/am/frontend/applet_controller.h
|
||||||
|
hle/service/am/frontend/applet_error.cpp
|
||||||
|
hle/service/am/frontend/applet_error.h
|
||||||
|
hle/service/am/frontend/applet_general.cpp
|
||||||
|
hle/service/am/frontend/applet_general.h
|
||||||
|
hle/service/am/frontend/applet_mii_edit.cpp
|
||||||
|
hle/service/am/frontend/applet_mii_edit.h
|
||||||
|
hle/service/am/frontend/applet_mii_edit_types.h
|
||||||
|
hle/service/am/frontend/applet_profile_select.cpp
|
||||||
|
hle/service/am/frontend/applet_profile_select.h
|
||||||
|
hle/service/am/frontend/applet_software_keyboard.cpp
|
||||||
|
hle/service/am/frontend/applet_software_keyboard.h
|
||||||
|
hle/service/am/frontend/applet_software_keyboard_types.h
|
||||||
|
hle/service/am/frontend/applet_web_browser.cpp
|
||||||
|
hle/service/am/frontend/applet_web_browser.h
|
||||||
|
hle/service/am/frontend/applet_web_browser_types.h
|
||||||
|
hle/service/am/frontend/applets.cpp
|
||||||
|
hle/service/am/frontend/applets.h
|
||||||
hle/service/am/am.cpp
|
hle/service/am/am.cpp
|
||||||
hle/service/am/am.h
|
hle/service/am/am.h
|
||||||
|
hle/service/am/am_results.h
|
||||||
|
hle/service/am/am_types.h
|
||||||
|
hle/service/am/applet.cpp
|
||||||
|
hle/service/am/applet.h
|
||||||
hle/service/am/applet_ae.cpp
|
hle/service/am/applet_ae.cpp
|
||||||
hle/service/am/applet_ae.h
|
hle/service/am/applet_ae.h
|
||||||
|
hle/service/am/applet_manager.cpp
|
||||||
|
hle/service/am/applet_data_broker.cpp
|
||||||
|
hle/service/am/applet_data_broker.h
|
||||||
|
hle/service/am/applet_manager.h
|
||||||
hle/service/am/applet_oe.cpp
|
hle/service/am/applet_oe.cpp
|
||||||
hle/service/am/applet_oe.h
|
hle/service/am/applet_oe.h
|
||||||
hle/service/am/applets/applet_cabinet.cpp
|
hle/service/am/applet_common_functions.cpp
|
||||||
hle/service/am/applets/applet_cabinet.h
|
hle/service/am/applet_common_functions.h
|
||||||
hle/service/am/applets/applet_controller.cpp
|
hle/service/am/applet_message_queue.cpp
|
||||||
hle/service/am/applets/applet_controller.h
|
hle/service/am/applet_message_queue.h
|
||||||
hle/service/am/applets/applet_error.cpp
|
hle/service/am/application_creator.cpp
|
||||||
hle/service/am/applets/applet_error.h
|
hle/service/am/application_creator.h
|
||||||
hle/service/am/applets/applet_general_backend.cpp
|
hle/service/am/application_functions.cpp
|
||||||
hle/service/am/applets/applet_general_backend.h
|
hle/service/am/application_functions.h
|
||||||
hle/service/am/applets/applet_mii_edit.cpp
|
hle/service/am/application_proxy.cpp
|
||||||
hle/service/am/applets/applet_mii_edit.h
|
hle/service/am/application_proxy.h
|
||||||
hle/service/am/applets/applet_mii_edit_types.h
|
hle/service/am/audio_controller.cpp
|
||||||
hle/service/am/applets/applet_profile_select.cpp
|
hle/service/am/audio_controller.h
|
||||||
hle/service/am/applets/applet_profile_select.h
|
hle/service/am/common_state_getter.cpp
|
||||||
hle/service/am/applets/applet_software_keyboard.cpp
|
hle/service/am/common_state_getter.h
|
||||||
hle/service/am/applets/applet_software_keyboard.h
|
hle/service/am/debug_functions.cpp
|
||||||
hle/service/am/applets/applet_software_keyboard_types.h
|
hle/service/am/debug_functions.h
|
||||||
hle/service/am/applets/applet_web_browser.cpp
|
hle/service/am/display_controller.cpp
|
||||||
hle/service/am/applets/applet_web_browser.h
|
hle/service/am/display_controller.h
|
||||||
hle/service/am/applets/applet_web_browser_types.h
|
hle/service/am/global_state_controller.cpp
|
||||||
hle/service/am/applets/applets.cpp
|
hle/service/am/global_state_controller.h
|
||||||
hle/service/am/applets/applets.h
|
hle/service/am/hid_registration.cpp
|
||||||
|
hle/service/am/hid_registration.h
|
||||||
|
hle/service/am/home_menu_functions.cpp
|
||||||
|
hle/service/am/home_menu_functions.h
|
||||||
hle/service/am/idle.cpp
|
hle/service/am/idle.cpp
|
||||||
hle/service/am/idle.h
|
hle/service/am/idle.h
|
||||||
|
hle/service/am/library_applet_accessor.cpp
|
||||||
|
hle/service/am/library_applet_accessor.h
|
||||||
|
hle/service/am/library_applet_creator.cpp
|
||||||
|
hle/service/am/library_applet_creator.h
|
||||||
|
hle/service/am/library_applet_proxy.cpp
|
||||||
|
hle/service/am/library_applet_proxy.h
|
||||||
|
hle/service/am/library_applet_self_accessor.cpp
|
||||||
|
hle/service/am/library_applet_self_accessor.h
|
||||||
|
hle/service/am/library_applet_storage.cpp
|
||||||
|
hle/service/am/library_applet_storage.h
|
||||||
|
hle/service/am/lock_accessor.cpp
|
||||||
|
hle/service/am/lock_accessor.h
|
||||||
|
hle/service/am/managed_layer_holder.cpp
|
||||||
|
hle/service/am/managed_layer_holder.h
|
||||||
hle/service/am/omm.cpp
|
hle/service/am/omm.cpp
|
||||||
hle/service/am/omm.h
|
hle/service/am/omm.h
|
||||||
|
hle/service/am/process_winding_controller.cpp
|
||||||
|
hle/service/am/process_winding_controller.h
|
||||||
|
hle/service/am/process.cpp
|
||||||
|
hle/service/am/process.h
|
||||||
|
hle/service/am/self_controller.cpp
|
||||||
|
hle/service/am/self_controller.h
|
||||||
|
hle/service/am/system_applet_proxy.cpp
|
||||||
|
hle/service/am/system_applet_proxy.h
|
||||||
|
hle/service/am/system_buffer_manager.cpp
|
||||||
|
hle/service/am/system_buffer_manager.h
|
||||||
hle/service/am/spsm.cpp
|
hle/service/am/spsm.cpp
|
||||||
hle/service/am/spsm.h
|
hle/service/am/spsm.h
|
||||||
|
hle/service/am/storage_accessor.cpp
|
||||||
|
hle/service/am/storage_accessor.h
|
||||||
|
hle/service/am/storage.cpp
|
||||||
|
hle/service/am/storage.h
|
||||||
|
hle/service/am/window_controller.cpp
|
||||||
|
hle/service/am/window_controller.h
|
||||||
hle/service/aoc/aoc_u.cpp
|
hle/service/aoc/aoc_u.cpp
|
||||||
hle/service/aoc/aoc_u.h
|
hle/service/aoc/aoc_u.h
|
||||||
hle/service/apm/apm.cpp
|
hle/service/apm/apm.cpp
|
||||||
|
@ -486,6 +548,8 @@ add_library(core STATIC
|
||||||
hle/service/es/es.h
|
hle/service/es/es.h
|
||||||
hle/service/eupld/eupld.cpp
|
hle/service/eupld/eupld.cpp
|
||||||
hle/service/eupld/eupld.h
|
hle/service/eupld/eupld.h
|
||||||
|
hle/service/event.cpp
|
||||||
|
hle/service/event.h
|
||||||
hle/service/fatal/fatal.cpp
|
hle/service/fatal/fatal.cpp
|
||||||
hle/service/fatal/fatal.h
|
hle/service/fatal/fatal.h
|
||||||
hle/service/fatal/fatal_p.cpp
|
hle/service/fatal/fatal_p.cpp
|
||||||
|
|
|
@ -36,7 +36,8 @@
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
#include "core/hle/kernel/physical_core.h"
|
#include "core/hle/kernel/physical_core.h"
|
||||||
#include "core/hle/service/acc/profile_manager.h"
|
#include "core/hle/service/acc/profile_manager.h"
|
||||||
#include "core/hle/service/am/applets/applets.h"
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
#include "core/hle/service/apm/apm_controller.h"
|
#include "core/hle/service/apm/apm_controller.h"
|
||||||
#include "core/hle/service/filesystem/filesystem.h"
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||||
#include "core/hle/service/glue/glue_manager.h"
|
#include "core/hle/service/glue/glue_manager.h"
|
||||||
|
@ -135,8 +136,8 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
|
||||||
|
|
||||||
struct System::Impl {
|
struct System::Impl {
|
||||||
explicit Impl(System& system)
|
explicit Impl(System& system)
|
||||||
: kernel{system}, fs_controller{system}, hid_core{}, room_network{},
|
: kernel{system}, fs_controller{system}, hid_core{}, room_network{}, cpu_manager{system},
|
||||||
cpu_manager{system}, reporter{system}, applet_manager{system}, profile_manager{} {}
|
reporter{system}, applet_manager{system}, frontend_applets{system}, profile_manager{} {}
|
||||||
|
|
||||||
void Initialize(System& system) {
|
void Initialize(System& system) {
|
||||||
device_memory = std::make_unique<Core::DeviceMemory>();
|
device_memory = std::make_unique<Core::DeviceMemory>();
|
||||||
|
@ -157,7 +158,7 @@ struct System::Impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create default implementations of applets if one is not provided.
|
// Create default implementations of applets if one is not provided.
|
||||||
applet_manager.SetDefaultAppletsIfMissing();
|
frontend_applets.SetDefaultAppletsIfMissing();
|
||||||
|
|
||||||
is_async_gpu = Settings::values.use_asynchronous_gpu_emulation.GetValue();
|
is_async_gpu = Settings::values.use_asynchronous_gpu_emulation.GetValue();
|
||||||
|
|
||||||
|
@ -330,16 +331,27 @@ struct System::Impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
|
SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
|
||||||
const std::string& filepath, u64 program_id,
|
const std::string& filepath,
|
||||||
std::size_t program_index) {
|
Service::AM::FrontendAppletParameters& params) {
|
||||||
app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath),
|
app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath),
|
||||||
program_id, program_index);
|
params.program_id, params.program_index);
|
||||||
|
|
||||||
if (!app_loader) {
|
if (!app_loader) {
|
||||||
LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
|
LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
|
||||||
return SystemResultStatus::ErrorGetLoader;
|
return SystemResultStatus::ErrorGetLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (app_loader->ReadProgramId(params.program_id) != Loader::ResultStatus::Success) {
|
||||||
|
LOG_ERROR(Core, "Failed to find title id for ROM!");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name = "Unknown program";
|
||||||
|
if (app_loader->ReadTitle(name) != Loader::ResultStatus::Success) {
|
||||||
|
LOG_ERROR(Core, "Failed to read title for ROM!");
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO(Core, "Loading {} ({})", name, params.program_id);
|
||||||
|
|
||||||
InitializeKernel(system);
|
InitializeKernel(system);
|
||||||
|
|
||||||
// Create the application process.
|
// Create the application process.
|
||||||
|
@ -373,9 +385,14 @@ struct System::Impl {
|
||||||
cheat_engine->Initialize();
|
cheat_engine->Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register with applet manager.
|
||||||
|
applet_manager.CreateAndInsertByFrontendAppletParameters(main_process->GetProcessId(),
|
||||||
|
params);
|
||||||
|
|
||||||
// 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) {
|
||||||
|
@ -386,21 +403,13 @@ struct System::Impl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (app_loader->ReadProgramId(program_id) != Loader::ResultStatus::Success) {
|
perf_stats = std::make_unique<PerfStats>(params.program_id);
|
||||||
LOG_ERROR(Core, "Failed to find title id for ROM (Error {})", load_result);
|
|
||||||
}
|
|
||||||
perf_stats = std::make_unique<PerfStats>(program_id);
|
|
||||||
// Reset counters and set time origin to current frame
|
// Reset counters and set time origin to current frame
|
||||||
GetAndResetPerfStats();
|
GetAndResetPerfStats();
|
||||||
perf_stats->BeginSystemFrame();
|
perf_stats->BeginSystemFrame();
|
||||||
|
|
||||||
std::string name = "Unknown Game";
|
|
||||||
if (app_loader->ReadTitle(name) != Loader::ResultStatus::Success) {
|
|
||||||
LOG_ERROR(Core, "Failed to read title for ROM (Error {})", load_result);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string title_version;
|
std::string title_version;
|
||||||
const FileSys::PatchManager pm(program_id, system.GetFileSystemController(),
|
const FileSys::PatchManager pm(params.program_id, system.GetFileSystemController(),
|
||||||
system.GetContentProvider());
|
system.GetContentProvider());
|
||||||
const auto metadata = pm.GetControlMetadata();
|
const auto metadata = pm.GetControlMetadata();
|
||||||
if (metadata.first != nullptr) {
|
if (metadata.first != nullptr) {
|
||||||
|
@ -409,14 +418,15 @@ struct System::Impl {
|
||||||
if (auto room_member = room_network.GetRoomMember().lock()) {
|
if (auto room_member = room_network.GetRoomMember().lock()) {
|
||||||
Network::GameInfo game_info;
|
Network::GameInfo game_info;
|
||||||
game_info.name = name;
|
game_info.name = name;
|
||||||
game_info.id = program_id;
|
game_info.id = params.program_id;
|
||||||
game_info.version = title_version;
|
game_info.version = title_version;
|
||||||
room_member->SendGameInfo(game_info);
|
room_member->SendGameInfo(game_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Workarounds:
|
// Workarounds:
|
||||||
// Activate this in Super Smash Brothers Ultimate, it only affects AMD cards using AMDVLK
|
// Activate this in Super Smash Brothers Ultimate, it only affects AMD cards using AMDVLK
|
||||||
Settings::values.renderer_amdvlk_depth_bias_workaround = program_id == 0x1006A800016E000ULL;
|
Settings::values.renderer_amdvlk_depth_bias_workaround =
|
||||||
|
params.program_id == 0x1006A800016E000ULL;
|
||||||
|
|
||||||
status = SystemResultStatus::Success;
|
status = SystemResultStatus::Success;
|
||||||
return status;
|
return status;
|
||||||
|
@ -455,6 +465,7 @@ struct System::Impl {
|
||||||
}
|
}
|
||||||
kernel.CloseServices();
|
kernel.CloseServices();
|
||||||
kernel.ShutdownCores();
|
kernel.ShutdownCores();
|
||||||
|
applet_manager.Reset();
|
||||||
services.reset();
|
services.reset();
|
||||||
service_manager.reset();
|
service_manager.reset();
|
||||||
fs_controller.Reset();
|
fs_controller.Reset();
|
||||||
|
@ -566,8 +577,9 @@ struct System::Impl {
|
||||||
|
|
||||||
std::unique_ptr<Tools::RenderdocAPI> renderdoc_api;
|
std::unique_ptr<Tools::RenderdocAPI> renderdoc_api;
|
||||||
|
|
||||||
/// Frontend applets
|
/// Applets
|
||||||
Service::AM::Applets::AppletManager applet_manager;
|
Service::AM::AppletManager applet_manager;
|
||||||
|
Service::AM::Frontend::FrontendAppletHolder frontend_applets;
|
||||||
|
|
||||||
/// APM (Performance) services
|
/// APM (Performance) services
|
||||||
Service::APM::Controller apm_controller{core_timing};
|
Service::APM::Controller apm_controller{core_timing};
|
||||||
|
@ -680,8 +692,8 @@ void System::InitializeDebugger() {
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath,
|
SystemResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath,
|
||||||
u64 program_id, std::size_t program_index) {
|
Service::AM::FrontendAppletParameters& params) {
|
||||||
return impl->Load(*this, emu_window, filepath, program_id, program_index);
|
return impl->Load(*this, emu_window, filepath, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool System::IsPoweredOn() const {
|
bool System::IsPoweredOn() const {
|
||||||
|
@ -871,19 +883,19 @@ void System::RegisterCheatList(const std::vector<Memory::CheatEntry>& list,
|
||||||
impl->cheat_engine->SetMainMemoryParameters(main_region_begin, main_region_size);
|
impl->cheat_engine->SetMainMemoryParameters(main_region_begin, main_region_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set) {
|
void System::SetFrontendAppletSet(Service::AM::Frontend::FrontendAppletSet&& set) {
|
||||||
impl->applet_manager.SetAppletFrontendSet(std::move(set));
|
impl->frontend_applets.SetFrontendAppletSet(std::move(set));
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::SetDefaultAppletFrontendSet() {
|
Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() {
|
||||||
impl->applet_manager.SetDefaultAppletFrontendSet();
|
return impl->frontend_applets;
|
||||||
}
|
}
|
||||||
|
|
||||||
Service::AM::Applets::AppletManager& System::GetAppletManager() {
|
const Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() const {
|
||||||
return impl->applet_manager;
|
return impl->frontend_applets;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Service::AM::Applets::AppletManager& System::GetAppletManager() const {
|
Service::AM::AppletManager& System::GetAppletManager() {
|
||||||
return impl->applet_manager;
|
return impl->applet_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,10 +50,15 @@ namespace Account {
|
||||||
class ProfileManager;
|
class ProfileManager;
|
||||||
} // namespace Account
|
} // namespace Account
|
||||||
|
|
||||||
namespace AM::Applets {
|
namespace AM {
|
||||||
struct AppletFrontendSet;
|
struct FrontendAppletParameters;
|
||||||
class AppletManager;
|
class AppletManager;
|
||||||
} // namespace AM::Applets
|
} // namespace AM
|
||||||
|
|
||||||
|
namespace AM::Frontend {
|
||||||
|
struct FrontendAppletSet;
|
||||||
|
class FrontendAppletHolder;
|
||||||
|
} // namespace AM::Frontend
|
||||||
|
|
||||||
namespace APM {
|
namespace APM {
|
||||||
class Controller;
|
class Controller;
|
||||||
|
@ -203,8 +208,8 @@ public:
|
||||||
* @returns SystemResultStatus code, indicating if the operation succeeded.
|
* @returns SystemResultStatus code, indicating if the operation succeeded.
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] SystemResultStatus Load(Frontend::EmuWindow& emu_window,
|
[[nodiscard]] SystemResultStatus Load(Frontend::EmuWindow& emu_window,
|
||||||
const std::string& filepath, u64 program_id = 0,
|
const std::string& filepath,
|
||||||
std::size_t program_index = 0);
|
Service::AM::FrontendAppletParameters& params);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates if the emulated system is powered on (all subsystems initialized and able to run an
|
* Indicates if the emulated system is powered on (all subsystems initialized and able to run an
|
||||||
|
@ -344,11 +349,13 @@ public:
|
||||||
const std::array<u8, 0x20>& build_id, u64 main_region_begin,
|
const std::array<u8, 0x20>& build_id, u64 main_region_begin,
|
||||||
u64 main_region_size);
|
u64 main_region_size);
|
||||||
|
|
||||||
void SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set);
|
void SetFrontendAppletSet(Service::AM::Frontend::FrontendAppletSet&& set);
|
||||||
void SetDefaultAppletFrontendSet();
|
|
||||||
|
|
||||||
[[nodiscard]] Service::AM::Applets::AppletManager& GetAppletManager();
|
[[nodiscard]] Service::AM::Frontend::FrontendAppletHolder& GetFrontendAppletHolder();
|
||||||
[[nodiscard]] const Service::AM::Applets::AppletManager& GetAppletManager() const;
|
[[nodiscard]] const Service::AM::Frontend::FrontendAppletHolder& GetFrontendAppletHolder()
|
||||||
|
const;
|
||||||
|
|
||||||
|
[[nodiscard]] Service::AM::AppletManager& GetAppletManager();
|
||||||
|
|
||||||
void SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider);
|
void SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider);
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/frontend/applets/general_frontend.h"
|
#include "core/frontend/applets/general.h"
|
||||||
|
|
||||||
namespace Core::Frontend {
|
namespace Core::Frontend {
|
||||||
|
|
|
@ -8,15 +8,15 @@
|
||||||
|
|
||||||
#include "common/uuid.h"
|
#include "common/uuid.h"
|
||||||
#include "core/frontend/applets/applet.h"
|
#include "core/frontend/applets/applet.h"
|
||||||
#include "core/hle/service/am/applets/applet_profile_select.h"
|
#include "core/hle/service/am/frontend/applet_profile_select.h"
|
||||||
|
|
||||||
namespace Core::Frontend {
|
namespace Core::Frontend {
|
||||||
|
|
||||||
struct ProfileSelectParameters {
|
struct ProfileSelectParameters {
|
||||||
Service::AM::Applets::UiMode mode;
|
Service::AM::Frontend::UiMode mode;
|
||||||
std::array<Common::UUID, 8> invalid_uid_list;
|
std::array<Common::UUID, 8> invalid_uid_list;
|
||||||
Service::AM::Applets::UiSettingsDisplayOptions display_options;
|
Service::AM::Frontend::UiSettingsDisplayOptions display_options;
|
||||||
Service::AM::Applets::UserSelectionPurpose purpose;
|
Service::AM::Frontend::UserSelectionPurpose purpose;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ProfileSelectApplet : public Applet {
|
class ProfileSelectApplet : public Applet {
|
||||||
|
|
|
@ -69,7 +69,7 @@ void DefaultSoftwareKeyboardApplet::ShowNormalKeyboard() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefaultSoftwareKeyboardApplet::ShowTextCheckDialog(
|
void DefaultSoftwareKeyboardApplet::ShowTextCheckDialog(
|
||||||
Service::AM::Applets::SwkbdTextCheckResult text_check_result,
|
Service::AM::Frontend::SwkbdTextCheckResult text_check_result,
|
||||||
std::u16string text_check_message) const {
|
std::u16string text_check_message) const {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to show the text check dialog.");
|
LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to show the text check dialog.");
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,7 @@ void DefaultSoftwareKeyboardApplet::InlineTextChanged(InlineTextParameters text_
|
||||||
"\ncursor_position={}",
|
"\ncursor_position={}",
|
||||||
Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position);
|
Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position);
|
||||||
|
|
||||||
submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString,
|
submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString,
|
||||||
text_parameters.input_text, text_parameters.cursor_position);
|
text_parameters.input_text, text_parameters.cursor_position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,22 +127,22 @@ void DefaultSoftwareKeyboardApplet::ExitKeyboard() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefaultSoftwareKeyboardApplet::SubmitNormalText(std::u16string text) const {
|
void DefaultSoftwareKeyboardApplet::SubmitNormalText(std::u16string text) const {
|
||||||
submit_normal_callback(Service::AM::Applets::SwkbdResult::Ok, text, true);
|
submit_normal_callback(Service::AM::Frontend::SwkbdResult::Ok, text, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefaultSoftwareKeyboardApplet::SubmitInlineText(std::u16string_view text) const {
|
void DefaultSoftwareKeyboardApplet::SubmitInlineText(std::u16string_view text) const {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||||
|
|
||||||
for (std::size_t index = 0; index < text.size(); ++index) {
|
for (std::size_t index = 0; index < text.size(); ++index) {
|
||||||
submit_inline_callback(Service::AM::Applets::SwkbdReplyType::ChangedString,
|
submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString,
|
||||||
std::u16string(text.data(), text.data() + index + 1),
|
std::u16string(text.data(), text.data() + index + 1),
|
||||||
static_cast<s32>(index) + 1);
|
static_cast<s32>(index) + 1);
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(250));
|
std::this_thread::sleep_for(std::chrono::milliseconds(250));
|
||||||
}
|
}
|
||||||
|
|
||||||
submit_inline_callback(Service::AM::Applets::SwkbdReplyType::DecidedEnter, std::u16string(text),
|
submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::DecidedEnter,
|
||||||
static_cast<s32>(text.size()));
|
std::u16string(text), static_cast<s32>(text.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Core::Frontend
|
} // namespace Core::Frontend
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
||||||
#include "core/frontend/applets/applet.h"
|
#include "core/frontend/applets/applet.h"
|
||||||
#include "core/hle/service/am/applets/applet_software_keyboard_types.h"
|
#include "core/hle/service/am/frontend/applet_software_keyboard_types.h"
|
||||||
|
|
||||||
namespace Core::Frontend {
|
namespace Core::Frontend {
|
||||||
|
|
||||||
|
@ -23,10 +23,10 @@ struct KeyboardInitializeParameters {
|
||||||
u32 max_text_length;
|
u32 max_text_length;
|
||||||
u32 min_text_length;
|
u32 min_text_length;
|
||||||
s32 initial_cursor_position;
|
s32 initial_cursor_position;
|
||||||
Service::AM::Applets::SwkbdType type;
|
Service::AM::Frontend::SwkbdType type;
|
||||||
Service::AM::Applets::SwkbdPasswordMode password_mode;
|
Service::AM::Frontend::SwkbdPasswordMode password_mode;
|
||||||
Service::AM::Applets::SwkbdTextDrawType text_draw_type;
|
Service::AM::Frontend::SwkbdTextDrawType text_draw_type;
|
||||||
Service::AM::Applets::SwkbdKeyDisableFlags key_disable_flags;
|
Service::AM::Frontend::SwkbdKeyDisableFlags key_disable_flags;
|
||||||
bool use_blur_background;
|
bool use_blur_background;
|
||||||
bool enable_backspace_button;
|
bool enable_backspace_button;
|
||||||
bool enable_return_button;
|
bool enable_return_button;
|
||||||
|
@ -40,8 +40,8 @@ struct InlineAppearParameters {
|
||||||
f32 key_top_scale_y;
|
f32 key_top_scale_y;
|
||||||
f32 key_top_translate_x;
|
f32 key_top_translate_x;
|
||||||
f32 key_top_translate_y;
|
f32 key_top_translate_y;
|
||||||
Service::AM::Applets::SwkbdType type;
|
Service::AM::Frontend::SwkbdType type;
|
||||||
Service::AM::Applets::SwkbdKeyDisableFlags key_disable_flags;
|
Service::AM::Frontend::SwkbdKeyDisableFlags key_disable_flags;
|
||||||
bool key_top_as_floating;
|
bool key_top_as_floating;
|
||||||
bool enable_backspace_button;
|
bool enable_backspace_button;
|
||||||
bool enable_return_button;
|
bool enable_return_button;
|
||||||
|
@ -56,9 +56,9 @@ struct InlineTextParameters {
|
||||||
class SoftwareKeyboardApplet : public Applet {
|
class SoftwareKeyboardApplet : public Applet {
|
||||||
public:
|
public:
|
||||||
using SubmitInlineCallback =
|
using SubmitInlineCallback =
|
||||||
std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>;
|
std::function<void(Service::AM::Frontend::SwkbdReplyType, std::u16string, s32)>;
|
||||||
using SubmitNormalCallback =
|
using SubmitNormalCallback =
|
||||||
std::function<void(Service::AM::Applets::SwkbdResult, std::u16string, bool)>;
|
std::function<void(Service::AM::Frontend::SwkbdResult, std::u16string, bool)>;
|
||||||
|
|
||||||
virtual ~SoftwareKeyboardApplet();
|
virtual ~SoftwareKeyboardApplet();
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ public:
|
||||||
|
|
||||||
virtual void ShowNormalKeyboard() const = 0;
|
virtual void ShowNormalKeyboard() const = 0;
|
||||||
|
|
||||||
virtual void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result,
|
virtual void ShowTextCheckDialog(Service::AM::Frontend::SwkbdTextCheckResult text_check_result,
|
||||||
std::u16string text_check_message) const = 0;
|
std::u16string text_check_message) const = 0;
|
||||||
|
|
||||||
virtual void ShowInlineKeyboard(InlineAppearParameters appear_parameters) const = 0;
|
virtual void ShowInlineKeyboard(InlineAppearParameters appear_parameters) const = 0;
|
||||||
|
@ -93,7 +93,7 @@ public:
|
||||||
|
|
||||||
void ShowNormalKeyboard() const override;
|
void ShowNormalKeyboard() const override;
|
||||||
|
|
||||||
void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result,
|
void ShowTextCheckDialog(Service::AM::Frontend::SwkbdTextCheckResult text_check_result,
|
||||||
std::u16string text_check_message) const override;
|
std::u16string text_check_message) const override;
|
||||||
|
|
||||||
void ShowInlineKeyboard(InlineAppearParameters appear_parameters) const override;
|
void ShowInlineKeyboard(InlineAppearParameters appear_parameters) const override;
|
||||||
|
|
|
@ -18,7 +18,7 @@ void DefaultWebBrowserApplet::OpenLocalWebPage(const std::string& local_url,
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open local web page at {}",
|
LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open local web page at {}",
|
||||||
local_url);
|
local_url);
|
||||||
|
|
||||||
callback(Service::AM::Applets::WebExitReason::WindowClosed, "http://localhost/");
|
callback(Service::AM::Frontend::WebExitReason::WindowClosed, "http://localhost/");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefaultWebBrowserApplet::OpenExternalWebPage(const std::string& external_url,
|
void DefaultWebBrowserApplet::OpenExternalWebPage(const std::string& external_url,
|
||||||
|
@ -26,7 +26,7 @@ void DefaultWebBrowserApplet::OpenExternalWebPage(const std::string& external_ur
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open external web page at {}",
|
LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open external web page at {}",
|
||||||
external_url);
|
external_url);
|
||||||
|
|
||||||
callback(Service::AM::Applets::WebExitReason::WindowClosed, "http://localhost/");
|
callback(Service::AM::Frontend::WebExitReason::WindowClosed, "http://localhost/");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Core::Frontend
|
} // namespace Core::Frontend
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#include "core/frontend/applets/applet.h"
|
#include "core/frontend/applets/applet.h"
|
||||||
#include "core/hle/service/am/applets/applet_web_browser_types.h"
|
#include "core/hle/service/am/frontend/applet_web_browser_types.h"
|
||||||
|
|
||||||
namespace Core::Frontend {
|
namespace Core::Frontend {
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ class WebBrowserApplet : public Applet {
|
||||||
public:
|
public:
|
||||||
using ExtractROMFSCallback = std::function<void()>;
|
using ExtractROMFSCallback = std::function<void()>;
|
||||||
using OpenWebPageCallback =
|
using OpenWebPageCallback =
|
||||||
std::function<void(Service::AM::Applets::WebExitReason, std::string)>;
|
std::function<void(Service::AM::Frontend::WebExitReason, std::string)>;
|
||||||
|
|
||||||
virtual ~WebBrowserApplet();
|
virtual ~WebBrowserApplet();
|
||||||
|
|
||||||
|
|
|
@ -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};
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,20 +1,11 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <chrono>
|
namespace Core {
|
||||||
#include <memory>
|
class System;
|
||||||
#include <queue>
|
}
|
||||||
|
|
||||||
#include "core/hle/service/kernel_helpers.h"
|
|
||||||
#include "core/hle/service/service.h"
|
|
||||||
|
|
||||||
namespace Kernel {
|
|
||||||
class KernelCore;
|
|
||||||
class KReadableEvent;
|
|
||||||
class KTransferMemory;
|
|
||||||
} // namespace Kernel
|
|
||||||
|
|
||||||
namespace Service::Nvnflinger {
|
namespace Service::Nvnflinger {
|
||||||
class Nvnflinger;
|
class Nvnflinger;
|
||||||
|
@ -22,443 +13,6 @@ class Nvnflinger;
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
class AppletMessageQueue {
|
|
||||||
public:
|
|
||||||
// This is nn::am::AppletMessage
|
|
||||||
enum class AppletMessage : u32 {
|
|
||||||
None = 0,
|
|
||||||
ChangeIntoForeground = 1,
|
|
||||||
ChangeIntoBackground = 2,
|
|
||||||
Exit = 4,
|
|
||||||
ApplicationExited = 6,
|
|
||||||
FocusStateChanged = 15,
|
|
||||||
Resume = 16,
|
|
||||||
DetectShortPressingHomeButton = 20,
|
|
||||||
DetectLongPressingHomeButton = 21,
|
|
||||||
DetectShortPressingPowerButton = 22,
|
|
||||||
DetectMiddlePressingPowerButton = 23,
|
|
||||||
DetectLongPressingPowerButton = 24,
|
|
||||||
RequestToPrepareSleep = 25,
|
|
||||||
FinishedSleepSequence = 26,
|
|
||||||
SleepRequiredByHighTemperature = 27,
|
|
||||||
SleepRequiredByLowBattery = 28,
|
|
||||||
AutoPowerDown = 29,
|
|
||||||
OperationModeChanged = 30,
|
|
||||||
PerformanceModeChanged = 31,
|
|
||||||
DetectReceivingCecSystemStandby = 32,
|
|
||||||
SdCardRemoved = 33,
|
|
||||||
LaunchApplicationRequested = 50,
|
|
||||||
RequestToDisplay = 51,
|
|
||||||
ShowApplicationLogo = 55,
|
|
||||||
HideApplicationLogo = 56,
|
|
||||||
ForceHideApplicationLogo = 57,
|
|
||||||
FloatingApplicationDetected = 60,
|
|
||||||
DetectShortPressingCaptureButton = 90,
|
|
||||||
AlbumScreenShotTaken = 92,
|
|
||||||
AlbumRecordingSaved = 93,
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit AppletMessageQueue(Core::System& system);
|
|
||||||
~AppletMessageQueue();
|
|
||||||
|
|
||||||
Kernel::KReadableEvent& GetMessageReceiveEvent();
|
|
||||||
Kernel::KReadableEvent& GetOperationModeChangedEvent();
|
|
||||||
void PushMessage(AppletMessage msg);
|
|
||||||
AppletMessage PopMessage();
|
|
||||||
std::size_t GetMessageCount() const;
|
|
||||||
void RequestExit();
|
|
||||||
void RequestResume();
|
|
||||||
void FocusStateChanged();
|
|
||||||
void OperationModeChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
KernelHelpers::ServiceContext service_context;
|
|
||||||
|
|
||||||
Kernel::KEvent* on_new_message;
|
|
||||||
Kernel::KEvent* on_operation_mode_changed;
|
|
||||||
|
|
||||||
std::queue<AppletMessage> messages;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IWindowController final : public ServiceFramework<IWindowController> {
|
|
||||||
public:
|
|
||||||
explicit IWindowController(Core::System& system_);
|
|
||||||
~IWindowController() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void GetAppletResourceUserId(HLERequestContext& ctx);
|
|
||||||
void GetAppletResourceUserIdOfCallerApplet(HLERequestContext& ctx);
|
|
||||||
void AcquireForegroundRights(HLERequestContext& ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
class IAudioController final : public ServiceFramework<IAudioController> {
|
|
||||||
public:
|
|
||||||
explicit IAudioController(Core::System& system_);
|
|
||||||
~IAudioController() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void SetExpectedMasterVolume(HLERequestContext& ctx);
|
|
||||||
void GetMainAppletExpectedMasterVolume(HLERequestContext& ctx);
|
|
||||||
void GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx);
|
|
||||||
void ChangeMainAppletMasterVolume(HLERequestContext& ctx);
|
|
||||||
void SetTransparentAudioRate(HLERequestContext& ctx);
|
|
||||||
|
|
||||||
static constexpr float min_allowed_volume = 0.0f;
|
|
||||||
static constexpr float max_allowed_volume = 1.0f;
|
|
||||||
|
|
||||||
float main_applet_volume{0.25f};
|
|
||||||
float library_applet_volume{max_allowed_volume};
|
|
||||||
float transparent_volume_rate{min_allowed_volume};
|
|
||||||
|
|
||||||
// Volume transition fade time in nanoseconds.
|
|
||||||
// e.g. If the main applet volume was 0% and was changed to 50%
|
|
||||||
// with a fade of 50ns, then over the course of 50ns,
|
|
||||||
// the volume will gradually fade up to 50%
|
|
||||||
std::chrono::nanoseconds fade_time_ns{0};
|
|
||||||
};
|
|
||||||
|
|
||||||
class IDisplayController final : public ServiceFramework<IDisplayController> {
|
|
||||||
public:
|
|
||||||
explicit IDisplayController(Core::System& system_);
|
|
||||||
~IDisplayController() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void GetCallerAppletCaptureImageEx(HLERequestContext& ctx);
|
|
||||||
void TakeScreenShotOfOwnLayer(HLERequestContext& ctx);
|
|
||||||
void AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx);
|
|
||||||
void ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx);
|
|
||||||
void AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx);
|
|
||||||
void ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
class IDebugFunctions final : public ServiceFramework<IDebugFunctions> {
|
|
||||||
public:
|
|
||||||
explicit IDebugFunctions(Core::System& system_);
|
|
||||||
~IDebugFunctions() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ISelfController final : public ServiceFramework<ISelfController> {
|
|
||||||
public:
|
|
||||||
explicit ISelfController(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_);
|
|
||||||
~ISelfController() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void Exit(HLERequestContext& ctx);
|
|
||||||
void LockExit(HLERequestContext& ctx);
|
|
||||||
void UnlockExit(HLERequestContext& ctx);
|
|
||||||
void EnterFatalSection(HLERequestContext& ctx);
|
|
||||||
void LeaveFatalSection(HLERequestContext& ctx);
|
|
||||||
void GetLibraryAppletLaunchableEvent(HLERequestContext& ctx);
|
|
||||||
void SetScreenShotPermission(HLERequestContext& ctx);
|
|
||||||
void SetOperationModeChangedNotification(HLERequestContext& ctx);
|
|
||||||
void SetPerformanceModeChangedNotification(HLERequestContext& ctx);
|
|
||||||
void SetFocusHandlingMode(HLERequestContext& ctx);
|
|
||||||
void SetRestartMessageEnabled(HLERequestContext& ctx);
|
|
||||||
void SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx);
|
|
||||||
void SetAlbumImageOrientation(HLERequestContext& ctx);
|
|
||||||
void IsSystemBufferSharingEnabled(HLERequestContext& ctx);
|
|
||||||
void GetSystemSharedBufferHandle(HLERequestContext& ctx);
|
|
||||||
void GetSystemSharedLayerHandle(HLERequestContext& ctx);
|
|
||||||
void CreateManagedDisplayLayer(HLERequestContext& ctx);
|
|
||||||
void CreateManagedDisplaySeparableLayer(HLERequestContext& ctx);
|
|
||||||
void SetHandlesRequestToDisplay(HLERequestContext& ctx);
|
|
||||||
void ApproveToDisplay(HLERequestContext& ctx);
|
|
||||||
void SetIdleTimeDetectionExtension(HLERequestContext& ctx);
|
|
||||||
void GetIdleTimeDetectionExtension(HLERequestContext& ctx);
|
|
||||||
void ReportUserIsActive(HLERequestContext& ctx);
|
|
||||||
void SetAutoSleepDisabled(HLERequestContext& ctx);
|
|
||||||
void IsAutoSleepDisabled(HLERequestContext& ctx);
|
|
||||||
void GetAccumulatedSuspendedTickValue(HLERequestContext& ctx);
|
|
||||||
void GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx);
|
|
||||||
void SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx);
|
|
||||||
void SaveCurrentScreenshot(HLERequestContext& ctx);
|
|
||||||
void SetRecordVolumeMuted(HLERequestContext& ctx);
|
|
||||||
|
|
||||||
Result EnsureBufferSharingEnabled();
|
|
||||||
|
|
||||||
enum class ScreenshotPermission : u32 {
|
|
||||||
Inherit = 0,
|
|
||||||
Enable = 1,
|
|
||||||
Disable = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
Nvnflinger::Nvnflinger& nvnflinger;
|
|
||||||
|
|
||||||
KernelHelpers::ServiceContext service_context;
|
|
||||||
|
|
||||||
Kernel::KEvent* launchable_event;
|
|
||||||
Kernel::KEvent* accumulated_suspended_tick_changed_event;
|
|
||||||
|
|
||||||
u32 idle_time_detection_extension = 0;
|
|
||||||
u64 num_fatal_sections_entered = 0;
|
|
||||||
u64 system_shared_buffer_id = 0;
|
|
||||||
u64 system_shared_layer_id = 0;
|
|
||||||
bool is_auto_sleep_disabled = false;
|
|
||||||
bool buffer_sharing_enabled = false;
|
|
||||||
ScreenshotPermission screenshot_permission = ScreenshotPermission::Inherit;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ILockAccessor final : public ServiceFramework<ILockAccessor> {
|
|
||||||
public:
|
|
||||||
explicit ILockAccessor(Core::System& system_);
|
|
||||||
~ILockAccessor() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void TryLock(HLERequestContext& ctx);
|
|
||||||
void Unlock(HLERequestContext& ctx);
|
|
||||||
void GetEvent(HLERequestContext& ctx);
|
|
||||||
void IsLocked(HLERequestContext& ctx);
|
|
||||||
|
|
||||||
bool is_locked{};
|
|
||||||
|
|
||||||
Kernel::KEvent* lock_event;
|
|
||||||
KernelHelpers::ServiceContext service_context;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
|
|
||||||
public:
|
|
||||||
explicit ICommonStateGetter(Core::System& system_,
|
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue_);
|
|
||||||
~ICommonStateGetter() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// This is nn::oe::FocusState
|
|
||||||
enum class FocusState : u8 {
|
|
||||||
InFocus = 1,
|
|
||||||
NotInFocus = 2,
|
|
||||||
Background = 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is nn::oe::OperationMode
|
|
||||||
enum class OperationMode : u8 {
|
|
||||||
Handheld = 0,
|
|
||||||
Docked = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is nn::am::service::SystemButtonType
|
|
||||||
enum class SystemButtonType {
|
|
||||||
None,
|
|
||||||
HomeButtonShortPressing,
|
|
||||||
HomeButtonLongPressing,
|
|
||||||
PowerButtonShortPressing,
|
|
||||||
PowerButtonLongPressing,
|
|
||||||
ShutdownSystem,
|
|
||||||
CaptureButtonShortPressing,
|
|
||||||
CaptureButtonLongPressing,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class SysPlatformRegion : s32 {
|
|
||||||
Global = 1,
|
|
||||||
Terra = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
void GetEventHandle(HLERequestContext& ctx);
|
|
||||||
void ReceiveMessage(HLERequestContext& ctx);
|
|
||||||
void GetCurrentFocusState(HLERequestContext& ctx);
|
|
||||||
void RequestToAcquireSleepLock(HLERequestContext& ctx);
|
|
||||||
void GetAcquiredSleepLockEvent(HLERequestContext& ctx);
|
|
||||||
void GetReaderLockAccessorEx(HLERequestContext& ctx);
|
|
||||||
void GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx);
|
|
||||||
void GetOperationMode(HLERequestContext& ctx);
|
|
||||||
void GetPerformanceMode(HLERequestContext& ctx);
|
|
||||||
void GetBootMode(HLERequestContext& ctx);
|
|
||||||
void IsVrModeEnabled(HLERequestContext& ctx);
|
|
||||||
void SetVrModeEnabled(HLERequestContext& ctx);
|
|
||||||
void SetLcdBacklighOffEnabled(HLERequestContext& ctx);
|
|
||||||
void BeginVrModeEx(HLERequestContext& ctx);
|
|
||||||
void EndVrModeEx(HLERequestContext& ctx);
|
|
||||||
void GetDefaultDisplayResolution(HLERequestContext& ctx);
|
|
||||||
void SetCpuBoostMode(HLERequestContext& ctx);
|
|
||||||
void GetBuiltInDisplayType(HLERequestContext& ctx);
|
|
||||||
void PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx);
|
|
||||||
void GetSettingsPlatformRegion(HLERequestContext& ctx);
|
|
||||||
void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx);
|
|
||||||
|
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue;
|
|
||||||
bool vr_mode_state{};
|
|
||||||
Kernel::KEvent* sleep_lock_event;
|
|
||||||
KernelHelpers::ServiceContext service_context;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IStorageImpl {
|
|
||||||
public:
|
|
||||||
virtual ~IStorageImpl();
|
|
||||||
virtual std::vector<u8>& GetData() = 0;
|
|
||||||
virtual const std::vector<u8>& GetData() const = 0;
|
|
||||||
virtual std::size_t GetSize() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IStorage final : public ServiceFramework<IStorage> {
|
|
||||||
public:
|
|
||||||
explicit IStorage(Core::System& system_, std::vector<u8>&& buffer);
|
|
||||||
~IStorage() override;
|
|
||||||
|
|
||||||
std::vector<u8>& GetData() {
|
|
||||||
return impl->GetData();
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<u8>& GetData() const {
|
|
||||||
return impl->GetData();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t GetSize() const {
|
|
||||||
return impl->GetSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void Register();
|
|
||||||
void Open(HLERequestContext& ctx);
|
|
||||||
|
|
||||||
std::shared_ptr<IStorageImpl> impl;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
|
|
||||||
public:
|
|
||||||
explicit IStorageAccessor(Core::System& system_, IStorage& backing_);
|
|
||||||
~IStorageAccessor() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void GetSize(HLERequestContext& ctx);
|
|
||||||
void Write(HLERequestContext& ctx);
|
|
||||||
void Read(HLERequestContext& ctx);
|
|
||||||
|
|
||||||
IStorage& backing;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
|
|
||||||
public:
|
|
||||||
explicit ILibraryAppletCreator(Core::System& system_);
|
|
||||||
~ILibraryAppletCreator() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void CreateLibraryApplet(HLERequestContext& ctx);
|
|
||||||
void CreateStorage(HLERequestContext& ctx);
|
|
||||||
void CreateTransferMemoryStorage(HLERequestContext& ctx);
|
|
||||||
void CreateHandleStorage(HLERequestContext& ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> {
|
|
||||||
public:
|
|
||||||
explicit ILibraryAppletSelfAccessor(Core::System& system_);
|
|
||||||
~ILibraryAppletSelfAccessor() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void PopInData(HLERequestContext& ctx);
|
|
||||||
void PushOutData(HLERequestContext& ctx);
|
|
||||||
void GetLibraryAppletInfo(HLERequestContext& ctx);
|
|
||||||
void GetMainAppletIdentityInfo(HLERequestContext& ctx);
|
|
||||||
void ExitProcessAndReturn(HLERequestContext& ctx);
|
|
||||||
void GetCallerAppletIdentityInfo(HLERequestContext& ctx);
|
|
||||||
void GetDesirableKeyboardLayout(HLERequestContext& ctx);
|
|
||||||
void GetMainAppletAvailableUsers(HLERequestContext& ctx);
|
|
||||||
void ShouldSetGpuTimeSliceManually(HLERequestContext& ctx);
|
|
||||||
|
|
||||||
void PushInShowAlbum();
|
|
||||||
void PushInShowCabinetData();
|
|
||||||
void PushInShowMiiEditData();
|
|
||||||
void PushInShowSoftwareKeyboard();
|
|
||||||
void PushInShowController();
|
|
||||||
|
|
||||||
std::deque<std::vector<u8>> queue_data;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IAppletCommonFunctions final : public ServiceFramework<IAppletCommonFunctions> {
|
|
||||||
public:
|
|
||||||
explicit IAppletCommonFunctions(Core::System& system_);
|
|
||||||
~IAppletCommonFunctions() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void SetCpuBoostRequestPriority(HLERequestContext& ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
|
|
||||||
public:
|
|
||||||
explicit IApplicationFunctions(Core::System& system_);
|
|
||||||
~IApplicationFunctions() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void PopLaunchParameter(HLERequestContext& ctx);
|
|
||||||
void CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx);
|
|
||||||
void EnsureSaveData(HLERequestContext& ctx);
|
|
||||||
void SetTerminateResult(HLERequestContext& ctx);
|
|
||||||
void GetDisplayVersion(HLERequestContext& ctx);
|
|
||||||
void GetDesiredLanguage(HLERequestContext& ctx);
|
|
||||||
void IsGamePlayRecordingSupported(HLERequestContext& ctx);
|
|
||||||
void InitializeGamePlayRecording(HLERequestContext& ctx);
|
|
||||||
void SetGamePlayRecordingState(HLERequestContext& ctx);
|
|
||||||
void NotifyRunning(HLERequestContext& ctx);
|
|
||||||
void GetPseudoDeviceId(HLERequestContext& ctx);
|
|
||||||
void ExtendSaveData(HLERequestContext& ctx);
|
|
||||||
void GetSaveDataSize(HLERequestContext& ctx);
|
|
||||||
void CreateCacheStorage(HLERequestContext& ctx);
|
|
||||||
void GetSaveDataSizeMax(HLERequestContext& ctx);
|
|
||||||
void BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx);
|
|
||||||
void EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx);
|
|
||||||
void BeginBlockingHomeButton(HLERequestContext& ctx);
|
|
||||||
void EndBlockingHomeButton(HLERequestContext& ctx);
|
|
||||||
void EnableApplicationCrashReport(HLERequestContext& ctx);
|
|
||||||
void InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx);
|
|
||||||
void SetApplicationCopyrightImage(HLERequestContext& ctx);
|
|
||||||
void SetApplicationCopyrightVisibility(HLERequestContext& ctx);
|
|
||||||
void QueryApplicationPlayStatistics(HLERequestContext& ctx);
|
|
||||||
void QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx);
|
|
||||||
void ExecuteProgram(HLERequestContext& ctx);
|
|
||||||
void ClearUserChannel(HLERequestContext& ctx);
|
|
||||||
void UnpopToUserChannel(HLERequestContext& ctx);
|
|
||||||
void GetPreviousProgramIndex(HLERequestContext& ctx);
|
|
||||||
void GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx);
|
|
||||||
void GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx);
|
|
||||||
void TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx);
|
|
||||||
void GetNotificationStorageChannelEvent(HLERequestContext& ctx);
|
|
||||||
void GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx);
|
|
||||||
void PrepareForJit(HLERequestContext& ctx);
|
|
||||||
|
|
||||||
KernelHelpers::ServiceContext service_context;
|
|
||||||
|
|
||||||
bool launch_popped_account_preselect = false;
|
|
||||||
s32 previous_program_index{-1};
|
|
||||||
Kernel::KEvent* gpu_error_detected_event;
|
|
||||||
Kernel::KEvent* friend_invitation_storage_channel_event;
|
|
||||||
Kernel::KEvent* notification_storage_channel_event;
|
|
||||||
Kernel::KEvent* health_warning_disappeared_system_event;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> {
|
|
||||||
public:
|
|
||||||
explicit IHomeMenuFunctions(Core::System& system_);
|
|
||||||
~IHomeMenuFunctions() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void RequestToGetForeground(HLERequestContext& ctx);
|
|
||||||
void GetPopFromGeneralChannelEvent(HLERequestContext& ctx);
|
|
||||||
|
|
||||||
KernelHelpers::ServiceContext service_context;
|
|
||||||
|
|
||||||
Kernel::KEvent* pop_from_general_channel_event;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IGlobalStateController final : public ServiceFramework<IGlobalStateController> {
|
|
||||||
public:
|
|
||||||
explicit IGlobalStateController(Core::System& system_);
|
|
||||||
~IGlobalStateController() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IApplicationCreator final : public ServiceFramework<IApplicationCreator> {
|
|
||||||
public:
|
|
||||||
explicit IApplicationCreator(Core::System& system_);
|
|
||||||
~IApplicationCreator() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IProcessWindingController final : public ServiceFramework<IProcessWindingController> {
|
|
||||||
public:
|
|
||||||
explicit IProcessWindingController(Core::System& system_);
|
|
||||||
~IProcessWindingController() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void GetLaunchReason(HLERequestContext& ctx);
|
|
||||||
void OpenCallingLibraryApplet(HLERequestContext& ctx);
|
|
||||||
};
|
|
||||||
|
|
||||||
void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system);
|
void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system);
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/result.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
constexpr Result ResultNoDataInChannel{ErrorModule::AM, 2};
|
||||||
|
constexpr Result ResultNoMessages{ErrorModule::AM, 3};
|
||||||
|
constexpr Result ResultInvalidOffset{ErrorModule::AM, 503};
|
||||||
|
constexpr Result ResultInvalidStorageType{ErrorModule::AM, 511};
|
||||||
|
constexpr Result ResultFatalSectionCountImbalance{ErrorModule::AM, 512};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,178 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/common_funcs.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
namespace Frontend {
|
||||||
|
class FrontendApplet;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class AppletType {
|
||||||
|
Application,
|
||||||
|
LibraryApplet,
|
||||||
|
SystemApplet,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class GameplayRecordingState : u32 {
|
||||||
|
Disabled,
|
||||||
|
Enabled,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is nn::oe::FocusState
|
||||||
|
enum class FocusState : u8 {
|
||||||
|
InFocus = 1,
|
||||||
|
NotInFocus = 2,
|
||||||
|
Background = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is nn::oe::OperationMode
|
||||||
|
enum class OperationMode : u8 {
|
||||||
|
Handheld = 0,
|
||||||
|
Docked = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is nn::am::service::SystemButtonType
|
||||||
|
enum class SystemButtonType {
|
||||||
|
None,
|
||||||
|
HomeButtonShortPressing,
|
||||||
|
HomeButtonLongPressing,
|
||||||
|
PowerButtonShortPressing,
|
||||||
|
PowerButtonLongPressing,
|
||||||
|
ShutdownSystem,
|
||||||
|
CaptureButtonShortPressing,
|
||||||
|
CaptureButtonLongPressing,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class SysPlatformRegion : s32 {
|
||||||
|
Global = 1,
|
||||||
|
Terra = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AppletProcessLaunchReason {
|
||||||
|
u8 flag;
|
||||||
|
INSERT_PADDING_BYTES(3);
|
||||||
|
};
|
||||||
|
static_assert(sizeof(AppletProcessLaunchReason) == 0x4,
|
||||||
|
"AppletProcessLaunchReason is an invalid size");
|
||||||
|
|
||||||
|
enum class ScreenshotPermission : u32 {
|
||||||
|
Inherit = 0,
|
||||||
|
Enable = 1,
|
||||||
|
Disable = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FocusHandlingMode {
|
||||||
|
bool unknown0;
|
||||||
|
bool unknown1;
|
||||||
|
bool unknown2;
|
||||||
|
bool unknown3;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class IdleTimeDetectionExtension : u32 {
|
||||||
|
Disabled = 0,
|
||||||
|
Extended = 1,
|
||||||
|
ExtendedUnsafe = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class AppletId : u32 {
|
||||||
|
None = 0x00,
|
||||||
|
Application = 0x01,
|
||||||
|
OverlayDisplay = 0x02,
|
||||||
|
QLaunch = 0x03,
|
||||||
|
Starter = 0x04,
|
||||||
|
Auth = 0x0A,
|
||||||
|
Cabinet = 0x0B,
|
||||||
|
Controller = 0x0C,
|
||||||
|
DataErase = 0x0D,
|
||||||
|
Error = 0x0E,
|
||||||
|
NetConnect = 0x0F,
|
||||||
|
ProfileSelect = 0x10,
|
||||||
|
SoftwareKeyboard = 0x11,
|
||||||
|
MiiEdit = 0x12,
|
||||||
|
Web = 0x13,
|
||||||
|
Shop = 0x14,
|
||||||
|
PhotoViewer = 0x15,
|
||||||
|
Settings = 0x16,
|
||||||
|
OfflineWeb = 0x17,
|
||||||
|
LoginShare = 0x18,
|
||||||
|
WebAuth = 0x19,
|
||||||
|
MyPage = 0x1A,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class AppletProgramId : u64 {
|
||||||
|
QLaunch = 0x0100000000001000ull,
|
||||||
|
Auth = 0x0100000000001001ull,
|
||||||
|
Cabinet = 0x0100000000001002ull,
|
||||||
|
Controller = 0x0100000000001003ull,
|
||||||
|
DataErase = 0x0100000000001004ull,
|
||||||
|
Error = 0x0100000000001005ull,
|
||||||
|
NetConnect = 0x0100000000001006ull,
|
||||||
|
ProfileSelect = 0x0100000000001007ull,
|
||||||
|
SoftwareKeyboard = 0x0100000000001008ull,
|
||||||
|
MiiEdit = 0x0100000000001009ull,
|
||||||
|
Web = 0x010000000000100Aull,
|
||||||
|
Shop = 0x010000000000100Bull,
|
||||||
|
OverlayDisplay = 0x010000000000100Cull,
|
||||||
|
PhotoViewer = 0x010000000000100Dull,
|
||||||
|
Settings = 0x010000000000100Eull,
|
||||||
|
OfflineWeb = 0x010000000000100Full,
|
||||||
|
LoginShare = 0x0100000000001010ull,
|
||||||
|
WebAuth = 0x0100000000001011ull,
|
||||||
|
Starter = 0x0100000000001012ull,
|
||||||
|
MyPage = 0x0100000000001013ull,
|
||||||
|
MaxProgramId = 0x0100000000001FFFull,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class LibraryAppletMode : u32 {
|
||||||
|
AllForeground = 0,
|
||||||
|
Background = 1,
|
||||||
|
NoUI = 2,
|
||||||
|
BackgroundIndirectDisplay = 3,
|
||||||
|
AllForegroundInitiallyHidden = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class CommonArgumentVersion : u32 {
|
||||||
|
Version0,
|
||||||
|
Version1,
|
||||||
|
Version2,
|
||||||
|
Version3,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class CommonArgumentSize : u32 {
|
||||||
|
Version3 = 0x20,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ThemeColor : u32 {
|
||||||
|
BasicWhite = 0,
|
||||||
|
BasicBlack = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CommonArguments {
|
||||||
|
CommonArgumentVersion arguments_version;
|
||||||
|
CommonArgumentSize size;
|
||||||
|
u32 library_version;
|
||||||
|
ThemeColor theme_color;
|
||||||
|
bool play_startup_sound;
|
||||||
|
u64 system_tick;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(CommonArguments) == 0x20, "CommonArguments has incorrect size.");
|
||||||
|
|
||||||
|
struct AppletIdentityInfo {
|
||||||
|
AppletId applet_id;
|
||||||
|
INSERT_PADDING_BYTES(0x4);
|
||||||
|
u64 application_id;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(AppletIdentityInfo) == 0x10, "AppletIdentityInfo has incorrect size.");
|
||||||
|
|
||||||
|
using AppletResourceUserId = u64;
|
||||||
|
using ProgramId = u64;
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
class AppletDataBroker;
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,27 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/scope_exit.h"
|
||||||
|
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "core/hle/service/am/am_results.h"
|
||||||
|
#include "core/hle/service/am/applet.h"
|
||||||
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
Applet::Applet(Core::System& system, std::unique_ptr<Process> process_)
|
||||||
|
: context(system, "Applet"), message_queue(system), process(std::move(process_)),
|
||||||
|
hid_registration(system, *process), gpu_error_detected_event(context),
|
||||||
|
friend_invitation_storage_channel_event(context), notification_storage_channel_event(context),
|
||||||
|
health_warning_disappeared_system_event(context), acquired_sleep_lock_event(context),
|
||||||
|
pop_from_general_channel_event(context), library_applet_launchable_event(context),
|
||||||
|
accumulated_suspended_tick_changed_event(context), sleep_lock_event(context) {
|
||||||
|
|
||||||
|
aruid = process->GetProcessId();
|
||||||
|
program_id = process->GetProgramId();
|
||||||
|
}
|
||||||
|
|
||||||
|
Applet::~Applet() = default;
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,133 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include "common/math_util.h"
|
||||||
|
#include "core/hle/service/apm/apm_controller.h"
|
||||||
|
#include "core/hle/service/caps/caps_types.h"
|
||||||
|
#include "core/hle/service/event.h"
|
||||||
|
#include "core/hle/service/kernel_helpers.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
#include "core/hle/service/am/am_types.h"
|
||||||
|
#include "core/hle/service/am/applet_message_queue.h"
|
||||||
|
#include "core/hle/service/am/hid_registration.h"
|
||||||
|
#include "core/hle/service/am/managed_layer_holder.h"
|
||||||
|
#include "core/hle/service/am/process.h"
|
||||||
|
#include "core/hle/service/am/storage.h"
|
||||||
|
#include "core/hle/service/am/system_buffer_manager.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet {
|
||||||
|
explicit Applet(Core::System& system, std::unique_ptr<Process> process_);
|
||||||
|
~Applet();
|
||||||
|
|
||||||
|
// Lock
|
||||||
|
std::mutex lock{};
|
||||||
|
|
||||||
|
// Event creation helper
|
||||||
|
KernelHelpers::ServiceContext context;
|
||||||
|
|
||||||
|
// Applet message queue
|
||||||
|
AppletMessageQueue message_queue;
|
||||||
|
|
||||||
|
// Process
|
||||||
|
std::unique_ptr<Process> process;
|
||||||
|
|
||||||
|
// Creation state
|
||||||
|
AppletId applet_id{};
|
||||||
|
AppletResourceUserId aruid{};
|
||||||
|
AppletProcessLaunchReason launch_reason{};
|
||||||
|
AppletType type{};
|
||||||
|
ProgramId program_id{};
|
||||||
|
LibraryAppletMode library_applet_mode{};
|
||||||
|
s32 previous_program_index{-1};
|
||||||
|
ScreenshotPermission previous_screenshot_permission{ScreenshotPermission::Enable};
|
||||||
|
|
||||||
|
// TODO: some fields above can be AppletIdentityInfo
|
||||||
|
AppletIdentityInfo screen_shot_identity;
|
||||||
|
|
||||||
|
// hid state
|
||||||
|
HidRegistration hid_registration;
|
||||||
|
|
||||||
|
// vi state
|
||||||
|
SystemBufferManager system_buffer_manager{};
|
||||||
|
ManagedLayerHolder managed_layer_holder{};
|
||||||
|
|
||||||
|
// Applet common functions
|
||||||
|
Result terminate_result{};
|
||||||
|
s32 display_logical_width{};
|
||||||
|
s32 display_logical_height{};
|
||||||
|
Common::Rectangle<f32> display_magnification{0, 0, 1, 1};
|
||||||
|
bool home_button_double_click_enabled{};
|
||||||
|
bool home_button_short_pressed_blocked{};
|
||||||
|
bool home_button_long_pressed_blocked{};
|
||||||
|
bool vr_mode_curtain_required{};
|
||||||
|
bool sleep_required_by_high_temperature{};
|
||||||
|
bool sleep_required_by_low_battery{};
|
||||||
|
s32 cpu_boost_request_priority{-1};
|
||||||
|
bool handling_capture_button_short_pressed_message_enabled_for_applet{};
|
||||||
|
bool handling_capture_button_long_pressed_message_enabled_for_applet{};
|
||||||
|
u32 application_core_usage_mode{};
|
||||||
|
|
||||||
|
// Application functions
|
||||||
|
bool gameplay_recording_supported{};
|
||||||
|
GameplayRecordingState gameplay_recording_state{GameplayRecordingState::Disabled};
|
||||||
|
bool jit_service_launched{};
|
||||||
|
bool is_running{};
|
||||||
|
bool application_crash_report_enabled{};
|
||||||
|
|
||||||
|
// Common state
|
||||||
|
FocusState focus_state{};
|
||||||
|
bool sleep_lock_enabled{};
|
||||||
|
bool vr_mode_enabled{};
|
||||||
|
bool lcd_backlight_off_enabled{};
|
||||||
|
APM::CpuBoostMode boost_mode{};
|
||||||
|
bool request_exit_to_library_applet_at_execute_next_program_enabled{};
|
||||||
|
|
||||||
|
// Channels
|
||||||
|
std::deque<std::vector<u8>> user_channel_launch_parameter{};
|
||||||
|
std::deque<std::vector<u8>> preselected_user_launch_parameter{};
|
||||||
|
|
||||||
|
// Caller applet
|
||||||
|
std::weak_ptr<Applet> caller_applet{};
|
||||||
|
std::shared_ptr<AppletDataBroker> caller_applet_broker{};
|
||||||
|
|
||||||
|
// Self state
|
||||||
|
bool exit_locked{};
|
||||||
|
s32 fatal_section_count{};
|
||||||
|
bool operation_mode_changed_notification_enabled{true};
|
||||||
|
bool performance_mode_changed_notification_enabled{true};
|
||||||
|
FocusHandlingMode focus_handling_mode{};
|
||||||
|
bool restart_message_enabled{};
|
||||||
|
bool out_of_focus_suspension_enabled{true};
|
||||||
|
Capture::AlbumImageOrientation album_image_orientation{};
|
||||||
|
bool handles_request_to_display{};
|
||||||
|
ScreenshotPermission screenshot_permission{};
|
||||||
|
IdleTimeDetectionExtension idle_time_detection_extension{};
|
||||||
|
bool auto_sleep_disabled{};
|
||||||
|
u64 suspended_ticks{};
|
||||||
|
bool album_image_taken_notification_enabled{};
|
||||||
|
bool record_volume_muted{};
|
||||||
|
|
||||||
|
// Events
|
||||||
|
Event gpu_error_detected_event;
|
||||||
|
Event friend_invitation_storage_channel_event;
|
||||||
|
Event notification_storage_channel_event;
|
||||||
|
Event health_warning_disappeared_system_event;
|
||||||
|
Event acquired_sleep_lock_event;
|
||||||
|
Event pop_from_general_channel_event;
|
||||||
|
Event library_applet_launchable_event;
|
||||||
|
Event accumulated_suspended_tick_changed_event;
|
||||||
|
Event sleep_lock_event;
|
||||||
|
|
||||||
|
// Frontend state
|
||||||
|
std::shared_ptr<Frontend::FrontendApplet> frontend{};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -1,291 +1,16 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "common/logging/log.h"
|
|
||||||
#include "core/core.h"
|
|
||||||
#include "core/hle/service/am/am.h"
|
|
||||||
#include "core/hle/service/am/applet_ae.h"
|
#include "core/hle/service/am/applet_ae.h"
|
||||||
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
|
#include "core/hle/service/am/library_applet_proxy.h"
|
||||||
|
#include "core/hle/service/am/system_applet_proxy.h"
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
#include "core/hle/service/nvnflinger/nvnflinger.h"
|
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
|
AppletAE::AppletAE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_)
|
||||||
public:
|
: ServiceFramework{system_, "appletAE"}, nvnflinger{nvnflinger_} {
|
||||||
explicit ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue_,
|
|
||||||
Core::System& system_)
|
|
||||||
: ServiceFramework{system_, "ILibraryAppletProxy"},
|
|
||||||
nvnflinger{nvnflinger_}, msg_queue{std::move(msg_queue_)} {
|
|
||||||
// clang-format off
|
|
||||||
static const FunctionInfo functions[] = {
|
|
||||||
{0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
|
|
||||||
{1, &ILibraryAppletProxy::GetSelfController, "GetSelfController"},
|
|
||||||
{2, &ILibraryAppletProxy::GetWindowController, "GetWindowController"},
|
|
||||||
{3, &ILibraryAppletProxy::GetAudioController, "GetAudioController"},
|
|
||||||
{4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"},
|
|
||||||
{10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"},
|
|
||||||
{11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
|
|
||||||
{20, &ILibraryAppletProxy::OpenLibraryAppletSelfAccessor, "OpenLibraryAppletSelfAccessor"},
|
|
||||||
{21, &ILibraryAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"},
|
|
||||||
{22, &ILibraryAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"},
|
|
||||||
{23, &ILibraryAppletProxy::GetGlobalStateController, "GetGlobalStateController"},
|
|
||||||
{1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
|
|
||||||
};
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
RegisterHandlers(functions);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void GetCommonStateGetter(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetSelfController(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<ISelfController>(system, nvnflinger);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetWindowController(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IWindowController>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetAudioController(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IAudioController>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetDisplayController(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IDisplayController>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetProcessWindingController(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IProcessWindingController>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetLibraryAppletCreator(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<ILibraryAppletCreator>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetAppletCommonFunctions(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IAppletCommonFunctions>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetHomeMenuFunctions(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IHomeMenuFunctions>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetGlobalStateController(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IGlobalStateController>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetDebugFunctions(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IDebugFunctions>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
Nvnflinger::Nvnflinger& nvnflinger;
|
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> {
|
|
||||||
public:
|
|
||||||
explicit ISystemAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue_,
|
|
||||||
Core::System& system_)
|
|
||||||
: ServiceFramework{system_, "ISystemAppletProxy"},
|
|
||||||
nvnflinger{nvnflinger_}, msg_queue{std::move(msg_queue_)} {
|
|
||||||
// clang-format off
|
|
||||||
static const FunctionInfo functions[] = {
|
|
||||||
{0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
|
|
||||||
{1, &ISystemAppletProxy::GetSelfController, "GetSelfController"},
|
|
||||||
{2, &ISystemAppletProxy::GetWindowController, "GetWindowController"},
|
|
||||||
{3, &ISystemAppletProxy::GetAudioController, "GetAudioController"},
|
|
||||||
{4, &ISystemAppletProxy::GetDisplayController, "GetDisplayController"},
|
|
||||||
{10, nullptr, "GetProcessWindingController"},
|
|
||||||
{11, &ISystemAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
|
|
||||||
{20, &ISystemAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"},
|
|
||||||
{21, &ISystemAppletProxy::GetGlobalStateController, "GetGlobalStateController"},
|
|
||||||
{22, &ISystemAppletProxy::GetApplicationCreator, "GetApplicationCreator"},
|
|
||||||
{23, &ISystemAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"},
|
|
||||||
{1000, &ISystemAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
|
|
||||||
};
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
RegisterHandlers(functions);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void GetCommonStateGetter(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetSelfController(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<ISelfController>(system, nvnflinger);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetWindowController(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IWindowController>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetAudioController(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IAudioController>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetDisplayController(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IDisplayController>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetLibraryAppletCreator(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<ILibraryAppletCreator>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetHomeMenuFunctions(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IHomeMenuFunctions>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetGlobalStateController(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IGlobalStateController>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetApplicationCreator(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IApplicationCreator>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetAppletCommonFunctions(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IAppletCommonFunctions>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetDebugFunctions(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IDebugFunctions>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
Nvnflinger::Nvnflinger& nvnflinger;
|
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue;
|
|
||||||
};
|
|
||||||
|
|
||||||
void AppletAE::OpenSystemAppletProxy(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
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"},
|
||||||
|
@ -304,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
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/applet.h"
|
||||||
|
#include "core/hle/service/am/applet_common_functions.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_,
|
||||||
|
std::shared_ptr<Applet> applet_)
|
||||||
|
: ServiceFramework{system_, "IAppletCommonFunctions"}, applet{std::move(applet_)} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, nullptr, "SetTerminateResult"},
|
||||||
|
{10, nullptr, "ReadThemeStorage"},
|
||||||
|
{11, nullptr, "WriteThemeStorage"},
|
||||||
|
{20, nullptr, "PushToAppletBoundChannel"},
|
||||||
|
{21, nullptr, "TryPopFromAppletBoundChannel"},
|
||||||
|
{40, nullptr, "GetDisplayLogicalResolution"},
|
||||||
|
{42, nullptr, "SetDisplayMagnification"},
|
||||||
|
{50, nullptr, "SetHomeButtonDoubleClickEnabled"},
|
||||||
|
{51, nullptr, "GetHomeButtonDoubleClickEnabled"},
|
||||||
|
{52, nullptr, "IsHomeButtonShortPressedBlocked"},
|
||||||
|
{60, nullptr, "IsVrModeCurtainRequired"},
|
||||||
|
{61, nullptr, "IsSleepRequiredByHighTemperature"},
|
||||||
|
{62, nullptr, "IsSleepRequiredByLowBattery"},
|
||||||
|
{70, &IAppletCommonFunctions::SetCpuBoostRequestPriority, "SetCpuBoostRequestPriority"},
|
||||||
|
{80, nullptr, "SetHandlingCaptureButtonShortPressedMessageEnabledForApplet"},
|
||||||
|
{81, nullptr, "SetHandlingCaptureButtonLongPressedMessageEnabledForApplet"},
|
||||||
|
{90, nullptr, "OpenNamedChannelAsParent"},
|
||||||
|
{91, nullptr, "OpenNamedChannelAsChild"},
|
||||||
|
{100, nullptr, "SetApplicationCoreUsageMode"},
|
||||||
|
{300, &IAppletCommonFunctions::GetCurrentApplicationId, "GetCurrentApplicationId"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
IAppletCommonFunctions::~IAppletCommonFunctions() = default;
|
||||||
|
|
||||||
|
void IAppletCommonFunctions::SetCpuBoostRequestPriority(HLERequestContext& ctx) {
|
||||||
|
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};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IAppletCommonFunctions::GetCurrentApplicationId(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push<u64>(system.GetApplicationProcessProgramID() & ~0xFFFULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,24 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
|
class IAppletCommonFunctions final : public ServiceFramework<IAppletCommonFunctions> {
|
||||||
|
public:
|
||||||
|
explicit IAppletCommonFunctions(Core::System& system_, std::shared_ptr<Applet> applet_);
|
||||||
|
~IAppletCommonFunctions() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SetCpuBoostRequestPriority(HLERequestContext& ctx);
|
||||||
|
void GetCurrentApplicationId(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
const std::shared_ptr<Applet> applet;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,67 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/scope_exit.h"
|
||||||
|
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "core/hle/service/am/am_results.h"
|
||||||
|
#include "core/hle/service/am/applet_data_broker.h"
|
||||||
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
AppletStorageChannel::AppletStorageChannel(KernelHelpers::ServiceContext& context)
|
||||||
|
: m_event(context) {}
|
||||||
|
AppletStorageChannel::~AppletStorageChannel() = default;
|
||||||
|
|
||||||
|
void AppletStorageChannel::Push(std::shared_ptr<IStorage> storage) {
|
||||||
|
std::scoped_lock lk{m_lock};
|
||||||
|
|
||||||
|
m_data.emplace_back(std::move(storage));
|
||||||
|
m_event.Signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result AppletStorageChannel::Pop(std::shared_ptr<IStorage>* out_storage) {
|
||||||
|
std::scoped_lock lk{m_lock};
|
||||||
|
|
||||||
|
SCOPE_EXIT({
|
||||||
|
if (m_data.empty()) {
|
||||||
|
m_event.Clear();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
R_UNLESS(!m_data.empty(), AM::ResultNoDataInChannel);
|
||||||
|
|
||||||
|
*out_storage = std::move(m_data.front());
|
||||||
|
m_data.pop_front();
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Kernel::KReadableEvent* AppletStorageChannel::GetEvent() {
|
||||||
|
return m_event.GetHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
AppletDataBroker::AppletDataBroker(Core::System& system_)
|
||||||
|
: system(system_), context(system_, "AppletDataBroker"), in_data(context),
|
||||||
|
interactive_in_data(context), out_data(context), interactive_out_data(context),
|
||||||
|
state_changed_event(context), is_completed(false) {}
|
||||||
|
|
||||||
|
AppletDataBroker::~AppletDataBroker() = default;
|
||||||
|
|
||||||
|
void AppletDataBroker::SignalCompletion() {
|
||||||
|
{
|
||||||
|
std::scoped_lock lk{lock};
|
||||||
|
|
||||||
|
if (is_completed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
is_completed = true;
|
||||||
|
state_changed_event.Signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
system.GetAppletManager().FocusStateChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,80 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include "core/hle/service/event.h"
|
||||||
|
#include "core/hle/service/kernel_helpers.h"
|
||||||
|
|
||||||
|
union Result;
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
class IStorage;
|
||||||
|
|
||||||
|
class AppletStorageChannel {
|
||||||
|
public:
|
||||||
|
explicit AppletStorageChannel(KernelHelpers::ServiceContext& ctx);
|
||||||
|
~AppletStorageChannel();
|
||||||
|
|
||||||
|
void Push(std::shared_ptr<IStorage> storage);
|
||||||
|
Result Pop(std::shared_ptr<IStorage>* out_storage);
|
||||||
|
Kernel::KReadableEvent* GetEvent();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::mutex m_lock{};
|
||||||
|
std::deque<std::shared_ptr<IStorage>> m_data{};
|
||||||
|
Event m_event;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AppletDataBroker {
|
||||||
|
public:
|
||||||
|
explicit AppletDataBroker(Core::System& system_);
|
||||||
|
~AppletDataBroker();
|
||||||
|
|
||||||
|
AppletStorageChannel& GetInData() {
|
||||||
|
return in_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
AppletStorageChannel& GetInteractiveInData() {
|
||||||
|
return interactive_in_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
AppletStorageChannel& GetOutData() {
|
||||||
|
return out_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
AppletStorageChannel& GetInteractiveOutData() {
|
||||||
|
return interactive_out_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Event& GetStateChangedEvent() {
|
||||||
|
return state_changed_event;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsCompleted() const {
|
||||||
|
return is_completed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SignalCompletion();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Core::System& system;
|
||||||
|
KernelHelpers::ServiceContext context;
|
||||||
|
|
||||||
|
AppletStorageChannel in_data;
|
||||||
|
AppletStorageChannel interactive_in_data;
|
||||||
|
AppletStorageChannel out_data;
|
||||||
|
AppletStorageChannel interactive_out_data;
|
||||||
|
Event state_changed_event;
|
||||||
|
|
||||||
|
std::mutex lock;
|
||||||
|
bool is_completed;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,361 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/settings.h"
|
||||||
|
#include "common/uuid.h"
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "core/core_timing.h"
|
||||||
|
#include "core/hle/service/acc/profile_manager.h"
|
||||||
|
#include "core/hle/service/am/applet_data_broker.h"
|
||||||
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
|
#include "core/hle/service/am/frontend/applet_cabinet.h"
|
||||||
|
#include "core/hle/service/am/frontend/applet_controller.h"
|
||||||
|
#include "core/hle/service/am/frontend/applet_mii_edit_types.h"
|
||||||
|
#include "core/hle/service/am/frontend/applet_software_keyboard_types.h"
|
||||||
|
#include "hid_core/hid_types.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr u32 LaunchParameterAccountPreselectedUserMagic = 0xC79497CA;
|
||||||
|
|
||||||
|
struct LaunchParameterAccountPreselectedUser {
|
||||||
|
u32 magic;
|
||||||
|
u32 is_account_selected;
|
||||||
|
Common::UUID current_user;
|
||||||
|
INSERT_PADDING_BYTES(0x70);
|
||||||
|
};
|
||||||
|
static_assert(sizeof(LaunchParameterAccountPreselectedUser) == 0x88);
|
||||||
|
|
||||||
|
AppletStorageChannel& InitializeFakeCallerApplet(Core::System& system,
|
||||||
|
std::shared_ptr<Applet>& applet) {
|
||||||
|
applet->caller_applet_broker = std::make_shared<AppletDataBroker>(system);
|
||||||
|
return applet->caller_applet_broker->GetInData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PushInShowAlbum(Core::System& system, AppletStorageChannel& channel) {
|
||||||
|
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));
|
||||||
|
channel.Push(std::make_shared<IStorage>(system, std::move(argument_data)));
|
||||||
|
channel.Push(std::make_shared<IStorage>(system, std::move(settings_data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PushInShowController(Core::System& system, AppletStorageChannel& channel) {
|
||||||
|
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));
|
||||||
|
|
||||||
|
channel.Push(std::make_shared<IStorage>(system, std::move(common_args_data)));
|
||||||
|
channel.Push(std::make_shared<IStorage>(system, std::move(private_args_data)));
|
||||||
|
channel.Push(std::make_shared<IStorage>(system, std::move(user_args_data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PushInShowCabinetData(Core::System& system, AppletStorageChannel& channel) {
|
||||||
|
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));
|
||||||
|
channel.Push(std::make_shared<IStorage>(system, std::move(argument_data)));
|
||||||
|
channel.Push(std::make_shared<IStorage>(system, std::move(settings_data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PushInShowMiiEditData(Core::System& system, AppletStorageChannel& channel) {
|
||||||
|
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));
|
||||||
|
|
||||||
|
channel.Push(std::make_shared<IStorage>(system, std::move(argument_data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PushInShowSoftwareKeyboard(Core::System& system, AppletStorageChannel& channel) {
|
||||||
|
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));
|
||||||
|
|
||||||
|
channel.Push(std::make_shared<IStorage>(system, std::move(argument_data)));
|
||||||
|
channel.Push(std::make_shared<IStorage>(system, std::move(swkbd_data)));
|
||||||
|
channel.Push(std::make_shared<IStorage>(system, std::move(work_buffer)));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
AppletManager::AppletManager(Core::System& system) : m_system(system) {}
|
||||||
|
AppletManager::~AppletManager() {
|
||||||
|
this->Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppletManager::InsertApplet(std::shared_ptr<Applet> applet) {
|
||||||
|
std::scoped_lock lk{m_lock};
|
||||||
|
|
||||||
|
m_applets.emplace(applet->aruid, std::move(applet));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppletManager::TerminateAndRemoveApplet(AppletResourceUserId aruid) {
|
||||||
|
std::shared_ptr<Applet> applet;
|
||||||
|
bool should_stop = false;
|
||||||
|
{
|
||||||
|
std::scoped_lock lk{m_lock};
|
||||||
|
|
||||||
|
const auto it = m_applets.find(aruid);
|
||||||
|
if (it == m_applets.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
applet = it->second;
|
||||||
|
m_applets.erase(it);
|
||||||
|
|
||||||
|
should_stop = m_applets.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Terminate process.
|
||||||
|
applet->process->Terminate();
|
||||||
|
|
||||||
|
// If there were no applets left, stop emulation.
|
||||||
|
if (should_stop) {
|
||||||
|
m_system.Exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppletManager::CreateAndInsertByFrontendAppletParameters(
|
||||||
|
AppletResourceUserId aruid, const FrontendAppletParameters& params) {
|
||||||
|
// TODO: this should be run inside AM so that the events will have a parent process
|
||||||
|
// TODO: have am create the guest process
|
||||||
|
auto applet = std::make_shared<Applet>(m_system, std::make_unique<Process>(m_system));
|
||||||
|
|
||||||
|
applet->aruid = aruid;
|
||||||
|
applet->program_id = params.program_id;
|
||||||
|
applet->applet_id = params.applet_id;
|
||||||
|
applet->type = params.applet_type;
|
||||||
|
applet->previous_program_index = params.previous_program_index;
|
||||||
|
|
||||||
|
// Push UserChannel data from previous application
|
||||||
|
if (params.launch_type == LaunchType::ApplicationInitiated) {
|
||||||
|
applet->user_channel_launch_parameter.swap(m_system.GetUserChannel());
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Read whether we need a preselected user from NACP?
|
||||||
|
// TODO: This can be done quite easily from loader
|
||||||
|
{
|
||||||
|
LaunchParameterAccountPreselectedUser lp{};
|
||||||
|
|
||||||
|
lp.magic = LaunchParameterAccountPreselectedUserMagic;
|
||||||
|
lp.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());
|
||||||
|
lp.current_user = *uuid;
|
||||||
|
|
||||||
|
std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser));
|
||||||
|
std::memcpy(buffer.data(), &lp, buffer.size());
|
||||||
|
|
||||||
|
applet->preselected_user_launch_parameter.push_back(std::move(buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Starting from frontend, some applets require input data.
|
||||||
|
switch (applet->applet_id) {
|
||||||
|
case AppletId::Cabinet:
|
||||||
|
PushInShowCabinetData(m_system, InitializeFakeCallerApplet(m_system, applet));
|
||||||
|
break;
|
||||||
|
case AppletId::MiiEdit:
|
||||||
|
PushInShowMiiEditData(m_system, InitializeFakeCallerApplet(m_system, applet));
|
||||||
|
break;
|
||||||
|
case AppletId::PhotoViewer:
|
||||||
|
PushInShowAlbum(m_system, InitializeFakeCallerApplet(m_system, applet));
|
||||||
|
break;
|
||||||
|
case AppletId::SoftwareKeyboard:
|
||||||
|
PushInShowSoftwareKeyboard(m_system, InitializeFakeCallerApplet(m_system, applet));
|
||||||
|
break;
|
||||||
|
case AppletId::Controller:
|
||||||
|
PushInShowController(m_system, InitializeFakeCallerApplet(m_system, applet));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Applet was started by frontend, so it is foreground.
|
||||||
|
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
|
||||||
|
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
||||||
|
applet->focus_state = FocusState::InFocus;
|
||||||
|
|
||||||
|
this->InsertApplet(std::move(applet));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Applet> AppletManager::GetByAppletResourceUserId(AppletResourceUserId aruid) const {
|
||||||
|
std::scoped_lock lk{m_lock};
|
||||||
|
|
||||||
|
if (const auto it = m_applets.find(aruid); it != m_applets.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppletManager::Reset() {
|
||||||
|
std::scoped_lock lk{m_lock};
|
||||||
|
|
||||||
|
m_applets.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppletManager::RequestExit() {
|
||||||
|
std::scoped_lock lk{m_lock};
|
||||||
|
|
||||||
|
for (const auto& [aruid, applet] : m_applets) {
|
||||||
|
applet->message_queue.RequestExit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppletManager::RequestResume() {
|
||||||
|
std::scoped_lock lk{m_lock};
|
||||||
|
|
||||||
|
for (const auto& [aruid, applet] : m_applets) {
|
||||||
|
applet->message_queue.RequestResume();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppletManager::OperationModeChanged() {
|
||||||
|
std::scoped_lock lk{m_lock};
|
||||||
|
|
||||||
|
for (const auto& [aruid, applet] : m_applets) {
|
||||||
|
applet->message_queue.OperationModeChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppletManager::FocusStateChanged() {
|
||||||
|
std::scoped_lock lk{m_lock};
|
||||||
|
|
||||||
|
for (const auto& [aruid, applet] : m_applets) {
|
||||||
|
applet->message_queue.FocusStateChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,59 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include "core/hle/service/am/applet.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
enum class LaunchType {
|
||||||
|
FrontendInitiated,
|
||||||
|
ApplicationInitiated,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FrontendAppletParameters {
|
||||||
|
ProgramId program_id{};
|
||||||
|
AppletId applet_id{};
|
||||||
|
AppletType applet_type{};
|
||||||
|
LaunchType launch_type{};
|
||||||
|
s32 program_index{};
|
||||||
|
s32 previous_program_index{-1};
|
||||||
|
};
|
||||||
|
|
||||||
|
class AppletManager {
|
||||||
|
public:
|
||||||
|
explicit AppletManager(Core::System& system);
|
||||||
|
~AppletManager();
|
||||||
|
|
||||||
|
void InsertApplet(std::shared_ptr<Applet> applet);
|
||||||
|
void TerminateAndRemoveApplet(AppletResourceUserId aruid);
|
||||||
|
|
||||||
|
void CreateAndInsertByFrontendAppletParameters(AppletResourceUserId aruid,
|
||||||
|
const FrontendAppletParameters& params);
|
||||||
|
std::shared_ptr<Applet> GetByAppletResourceUserId(AppletResourceUserId aruid) const;
|
||||||
|
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
void RequestExit();
|
||||||
|
void RequestResume();
|
||||||
|
void OperationModeChanged();
|
||||||
|
void FocusStateChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Core::System& m_system;
|
||||||
|
|
||||||
|
mutable std::mutex m_lock{};
|
||||||
|
std::map<AppletResourceUserId, std::shared_ptr<Applet>> m_applets{};
|
||||||
|
|
||||||
|
// AudioController state goes here
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,73 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/applet_message_queue.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
AppletMessageQueue::AppletMessageQueue(Core::System& system)
|
||||||
|
: service_context{system, "AppletMessageQueue"} {
|
||||||
|
on_new_message = service_context.CreateEvent("AMMessageQueue:OnMessageReceived");
|
||||||
|
on_operation_mode_changed = service_context.CreateEvent("AMMessageQueue:OperationModeChanged");
|
||||||
|
}
|
||||||
|
|
||||||
|
AppletMessageQueue::~AppletMessageQueue() {
|
||||||
|
service_context.CloseEvent(on_new_message);
|
||||||
|
service_context.CloseEvent(on_operation_mode_changed);
|
||||||
|
}
|
||||||
|
|
||||||
|
Kernel::KReadableEvent& AppletMessageQueue::GetMessageReceiveEvent() {
|
||||||
|
return on_new_message->GetReadableEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
Kernel::KReadableEvent& AppletMessageQueue::GetOperationModeChangedEvent() {
|
||||||
|
return on_operation_mode_changed->GetReadableEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppletMessageQueue::PushMessage(AppletMessage msg) {
|
||||||
|
{
|
||||||
|
std::scoped_lock lk{lock};
|
||||||
|
messages.push(msg);
|
||||||
|
}
|
||||||
|
on_new_message->Signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() {
|
||||||
|
std::scoped_lock lk{lock};
|
||||||
|
if (messages.empty()) {
|
||||||
|
on_new_message->Clear();
|
||||||
|
return AppletMessage::None;
|
||||||
|
}
|
||||||
|
auto msg = messages.front();
|
||||||
|
messages.pop();
|
||||||
|
if (messages.empty()) {
|
||||||
|
on_new_message->Clear();
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t AppletMessageQueue::GetMessageCount() const {
|
||||||
|
std::scoped_lock lk{lock};
|
||||||
|
return messages.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppletMessageQueue::RequestExit() {
|
||||||
|
PushMessage(AppletMessage::Exit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppletMessageQueue::RequestResume() {
|
||||||
|
PushMessage(AppletMessage::Resume);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppletMessageQueue::FocusStateChanged() {
|
||||||
|
PushMessage(AppletMessage::FocusStateChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppletMessageQueue::OperationModeChanged() {
|
||||||
|
PushMessage(AppletMessage::OperationModeChanged);
|
||||||
|
PushMessage(AppletMessage::PerformanceModeChanged);
|
||||||
|
on_operation_mode_changed->Signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,76 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
#include "core/hle/service/kernel_helpers.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
class KReadableEvent;
|
||||||
|
} // namespace Kernel
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
class AppletMessageQueue {
|
||||||
|
public:
|
||||||
|
// This is nn::am::AppletMessage
|
||||||
|
enum class AppletMessage : u32 {
|
||||||
|
None = 0,
|
||||||
|
ChangeIntoForeground = 1,
|
||||||
|
ChangeIntoBackground = 2,
|
||||||
|
Exit = 4,
|
||||||
|
ApplicationExited = 6,
|
||||||
|
FocusStateChanged = 15,
|
||||||
|
Resume = 16,
|
||||||
|
DetectShortPressingHomeButton = 20,
|
||||||
|
DetectLongPressingHomeButton = 21,
|
||||||
|
DetectShortPressingPowerButton = 22,
|
||||||
|
DetectMiddlePressingPowerButton = 23,
|
||||||
|
DetectLongPressingPowerButton = 24,
|
||||||
|
RequestToPrepareSleep = 25,
|
||||||
|
FinishedSleepSequence = 26,
|
||||||
|
SleepRequiredByHighTemperature = 27,
|
||||||
|
SleepRequiredByLowBattery = 28,
|
||||||
|
AutoPowerDown = 29,
|
||||||
|
OperationModeChanged = 30,
|
||||||
|
PerformanceModeChanged = 31,
|
||||||
|
DetectReceivingCecSystemStandby = 32,
|
||||||
|
SdCardRemoved = 33,
|
||||||
|
LaunchApplicationRequested = 50,
|
||||||
|
RequestToDisplay = 51,
|
||||||
|
ShowApplicationLogo = 55,
|
||||||
|
HideApplicationLogo = 56,
|
||||||
|
ForceHideApplicationLogo = 57,
|
||||||
|
FloatingApplicationDetected = 60,
|
||||||
|
DetectShortPressingCaptureButton = 90,
|
||||||
|
AlbumScreenShotTaken = 92,
|
||||||
|
AlbumRecordingSaved = 93,
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit AppletMessageQueue(Core::System& system);
|
||||||
|
~AppletMessageQueue();
|
||||||
|
|
||||||
|
Kernel::KReadableEvent& GetMessageReceiveEvent();
|
||||||
|
Kernel::KReadableEvent& GetOperationModeChangedEvent();
|
||||||
|
void PushMessage(AppletMessage msg);
|
||||||
|
AppletMessage PopMessage();
|
||||||
|
std::size_t GetMessageCount() const;
|
||||||
|
void RequestExit();
|
||||||
|
void RequestResume();
|
||||||
|
void FocusStateChanged();
|
||||||
|
void OperationModeChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
KernelHelpers::ServiceContext service_context;
|
||||||
|
|
||||||
|
Kernel::KEvent* on_new_message;
|
||||||
|
Kernel::KEvent* on_operation_mode_changed;
|
||||||
|
|
||||||
|
mutable std::mutex lock;
|
||||||
|
std::queue<AppletMessage> messages;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -1,119 +1,16 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "common/logging/log.h"
|
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/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/ipc_helpers.h"
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
#include "core/hle/service/nvnflinger/nvnflinger.h"
|
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
|
AppletOE::AppletOE(Nvnflinger::Nvnflinger& nvnflinger_, Core::System& system_)
|
||||||
public:
|
: ServiceFramework{system_, "appletOE"}, nvnflinger{nvnflinger_} {
|
||||||
explicit IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue_,
|
|
||||||
Core::System& system_)
|
|
||||||
: ServiceFramework{system_, "IApplicationProxy"},
|
|
||||||
nvnflinger{nvnflinger_}, msg_queue{std::move(msg_queue_)} {
|
|
||||||
// clang-format off
|
|
||||||
static const FunctionInfo functions[] = {
|
|
||||||
{0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"},
|
|
||||||
{1, &IApplicationProxy::GetSelfController, "GetSelfController"},
|
|
||||||
{2, &IApplicationProxy::GetWindowController, "GetWindowController"},
|
|
||||||
{3, &IApplicationProxy::GetAudioController, "GetAudioController"},
|
|
||||||
{4, &IApplicationProxy::GetDisplayController, "GetDisplayController"},
|
|
||||||
{10, nullptr, "GetProcessWindingController"},
|
|
||||||
{11, &IApplicationProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
|
|
||||||
{20, &IApplicationProxy::GetApplicationFunctions, "GetApplicationFunctions"},
|
|
||||||
{1000, &IApplicationProxy::GetDebugFunctions, "GetDebugFunctions"},
|
|
||||||
};
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
RegisterHandlers(functions);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void GetAudioController(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IAudioController>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetDisplayController(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IDisplayController>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetDebugFunctions(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IDebugFunctions>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetWindowController(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IWindowController>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetSelfController(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<ISelfController>(system, nvnflinger);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetCommonStateGetter(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<ICommonStateGetter>(system, msg_queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetLibraryAppletCreator(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<ILibraryAppletCreator>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetApplicationFunctions(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushIpcInterface<IApplicationFunctions>(system);
|
|
||||||
}
|
|
||||||
|
|
||||||
Nvnflinger::Nvnflinger& nvnflinger;
|
|
||||||
std::shared_ptr<AppletMessageQueue> msg_queue;
|
|
||||||
};
|
|
||||||
|
|
||||||
void AppletOE::OpenApplicationProxy(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_AM, "called");
|
|
||||||
|
|
||||||
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"},
|
||||||
};
|
};
|
||||||
|
@ -122,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
|
||||||
|
|
|
@ -1,338 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
#include "common/assert.h"
|
|
||||||
#include "core/core.h"
|
|
||||||
#include "core/frontend/applets/cabinet.h"
|
|
||||||
#include "core/frontend/applets/controller.h"
|
|
||||||
#include "core/frontend/applets/error.h"
|
|
||||||
#include "core/frontend/applets/general_frontend.h"
|
|
||||||
#include "core/frontend/applets/mii_edit.h"
|
|
||||||
#include "core/frontend/applets/profile_select.h"
|
|
||||||
#include "core/frontend/applets/software_keyboard.h"
|
|
||||||
#include "core/frontend/applets/web_browser.h"
|
|
||||||
#include "core/hle/kernel/k_event.h"
|
|
||||||
#include "core/hle/service/am/am.h"
|
|
||||||
#include "core/hle/service/am/applet_ae.h"
|
|
||||||
#include "core/hle/service/am/applet_oe.h"
|
|
||||||
#include "core/hle/service/am/applets/applet_cabinet.h"
|
|
||||||
#include "core/hle/service/am/applets/applet_controller.h"
|
|
||||||
#include "core/hle/service/am/applets/applet_error.h"
|
|
||||||
#include "core/hle/service/am/applets/applet_general_backend.h"
|
|
||||||
#include "core/hle/service/am/applets/applet_mii_edit.h"
|
|
||||||
#include "core/hle/service/am/applets/applet_profile_select.h"
|
|
||||||
#include "core/hle/service/am/applets/applet_software_keyboard.h"
|
|
||||||
#include "core/hle/service/am/applets/applet_web_browser.h"
|
|
||||||
#include "core/hle/service/am/applets/applets.h"
|
|
||||||
#include "core/hle/service/sm/sm.h"
|
|
||||||
|
|
||||||
namespace Service::AM::Applets {
|
|
||||||
|
|
||||||
AppletDataBroker::AppletDataBroker(Core::System& system_, LibraryAppletMode applet_mode_)
|
|
||||||
: system{system_}, applet_mode{applet_mode_}, service_context{system,
|
|
||||||
"ILibraryAppletAccessor"} {
|
|
||||||
state_changed_event = service_context.CreateEvent("ILibraryAppletAccessor:StateChangedEvent");
|
|
||||||
pop_out_data_event = service_context.CreateEvent("ILibraryAppletAccessor:PopDataOutEvent");
|
|
||||||
pop_interactive_out_data_event =
|
|
||||||
service_context.CreateEvent("ILibraryAppletAccessor:PopInteractiveDataOutEvent");
|
|
||||||
}
|
|
||||||
|
|
||||||
AppletDataBroker::~AppletDataBroker() {
|
|
||||||
service_context.CloseEvent(state_changed_event);
|
|
||||||
service_context.CloseEvent(pop_out_data_event);
|
|
||||||
service_context.CloseEvent(pop_interactive_out_data_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
AppletDataBroker::RawChannelData AppletDataBroker::PeekDataToAppletForDebug() const {
|
|
||||||
std::vector<std::vector<u8>> out_normal;
|
|
||||||
|
|
||||||
for (const auto& storage : in_channel) {
|
|
||||||
out_normal.push_back(storage->GetData());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::vector<u8>> out_interactive;
|
|
||||||
|
|
||||||
for (const auto& storage : in_interactive_channel) {
|
|
||||||
out_interactive.push_back(storage->GetData());
|
|
||||||
}
|
|
||||||
|
|
||||||
return {std::move(out_normal), std::move(out_interactive)};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<IStorage> AppletDataBroker::PopNormalDataToGame() {
|
|
||||||
if (out_channel.empty())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
auto out = std::move(out_channel.front());
|
|
||||||
out_channel.pop_front();
|
|
||||||
pop_out_data_event->Clear();
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<IStorage> AppletDataBroker::PopNormalDataToApplet() {
|
|
||||||
if (in_channel.empty())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
auto out = std::move(in_channel.front());
|
|
||||||
in_channel.pop_front();
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<IStorage> AppletDataBroker::PopInteractiveDataToGame() {
|
|
||||||
if (out_interactive_channel.empty())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
auto out = std::move(out_interactive_channel.front());
|
|
||||||
out_interactive_channel.pop_front();
|
|
||||||
pop_interactive_out_data_event->Clear();
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<IStorage> AppletDataBroker::PopInteractiveDataToApplet() {
|
|
||||||
if (in_interactive_channel.empty())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
auto out = std::move(in_interactive_channel.front());
|
|
||||||
in_interactive_channel.pop_front();
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletDataBroker::PushNormalDataFromGame(std::shared_ptr<IStorage>&& storage) {
|
|
||||||
in_channel.emplace_back(std::move(storage));
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletDataBroker::PushNormalDataFromApplet(std::shared_ptr<IStorage>&& storage) {
|
|
||||||
out_channel.emplace_back(std::move(storage));
|
|
||||||
pop_out_data_event->Signal();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletDataBroker::PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& storage) {
|
|
||||||
in_interactive_channel.emplace_back(std::move(storage));
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletDataBroker::PushInteractiveDataFromApplet(std::shared_ptr<IStorage>&& storage) {
|
|
||||||
out_interactive_channel.emplace_back(std::move(storage));
|
|
||||||
pop_interactive_out_data_event->Signal();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletDataBroker::SignalStateChanged() {
|
|
||||||
state_changed_event->Signal();
|
|
||||||
|
|
||||||
switch (applet_mode) {
|
|
||||||
case LibraryAppletMode::AllForeground:
|
|
||||||
case LibraryAppletMode::AllForegroundInitiallyHidden: {
|
|
||||||
auto applet_oe = system.ServiceManager().GetService<AppletOE>("appletOE");
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Kernel::KReadableEvent& AppletDataBroker::GetNormalDataEvent() {
|
|
||||||
return pop_out_data_event->GetReadableEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
Kernel::KReadableEvent& AppletDataBroker::GetInteractiveDataEvent() {
|
|
||||||
return pop_interactive_out_data_event->GetReadableEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
Kernel::KReadableEvent& AppletDataBroker::GetStateChangedEvent() {
|
|
||||||
return state_changed_event->GetReadableEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
Applet::Applet(Core::System& system_, LibraryAppletMode applet_mode_)
|
|
||||||
: broker{system_, applet_mode_}, applet_mode{applet_mode_} {}
|
|
||||||
|
|
||||||
Applet::~Applet() = default;
|
|
||||||
|
|
||||||
void Applet::Initialize() {
|
|
||||||
const auto common = broker.PopNormalDataToApplet();
|
|
||||||
ASSERT(common != nullptr);
|
|
||||||
|
|
||||||
const auto common_data = common->GetData();
|
|
||||||
|
|
||||||
ASSERT(common_data.size() >= sizeof(CommonArguments));
|
|
||||||
std::memcpy(&common_args, common_data.data(), sizeof(CommonArguments));
|
|
||||||
|
|
||||||
initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
AppletFrontendSet::AppletFrontendSet() = default;
|
|
||||||
|
|
||||||
AppletFrontendSet::AppletFrontendSet(CabinetApplet cabinet_applet,
|
|
||||||
ControllerApplet controller_applet, ErrorApplet error_applet,
|
|
||||||
MiiEdit mii_edit_,
|
|
||||||
ParentalControlsApplet parental_controls_applet,
|
|
||||||
PhotoViewer photo_viewer_, ProfileSelect profile_select_,
|
|
||||||
SoftwareKeyboard software_keyboard_, WebBrowser web_browser_)
|
|
||||||
: cabinet{std::move(cabinet_applet)}, controller{std::move(controller_applet)},
|
|
||||||
error{std::move(error_applet)}, mii_edit{std::move(mii_edit_)},
|
|
||||||
parental_controls{std::move(parental_controls_applet)},
|
|
||||||
photo_viewer{std::move(photo_viewer_)}, profile_select{std::move(profile_select_)},
|
|
||||||
software_keyboard{std::move(software_keyboard_)}, web_browser{std::move(web_browser_)} {}
|
|
||||||
|
|
||||||
AppletFrontendSet::~AppletFrontendSet() = default;
|
|
||||||
|
|
||||||
AppletFrontendSet::AppletFrontendSet(AppletFrontendSet&&) noexcept = default;
|
|
||||||
|
|
||||||
AppletFrontendSet& AppletFrontendSet::operator=(AppletFrontendSet&&) noexcept = default;
|
|
||||||
|
|
||||||
AppletManager::AppletManager(Core::System& system_) : system{system_} {}
|
|
||||||
|
|
||||||
AppletManager::~AppletManager() = default;
|
|
||||||
|
|
||||||
const AppletFrontendSet& AppletManager::GetAppletFrontendSet() const {
|
|
||||||
return frontend;
|
|
||||||
}
|
|
||||||
|
|
||||||
NFP::CabinetMode AppletManager::GetCabinetMode() const {
|
|
||||||
return cabinet_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
AppletId AppletManager::GetCurrentAppletId() const {
|
|
||||||
return current_applet_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) {
|
|
||||||
if (set.cabinet != nullptr) {
|
|
||||||
frontend.cabinet = std::move(set.cabinet);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (set.controller != nullptr) {
|
|
||||||
frontend.controller = std::move(set.controller);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (set.error != nullptr) {
|
|
||||||
frontend.error = std::move(set.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (set.mii_edit != nullptr) {
|
|
||||||
frontend.mii_edit = std::move(set.mii_edit);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (set.parental_controls != nullptr) {
|
|
||||||
frontend.parental_controls = std::move(set.parental_controls);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (set.photo_viewer != nullptr) {
|
|
||||||
frontend.photo_viewer = std::move(set.photo_viewer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (set.profile_select != nullptr) {
|
|
||||||
frontend.profile_select = std::move(set.profile_select);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (set.software_keyboard != nullptr) {
|
|
||||||
frontend.software_keyboard = std::move(set.software_keyboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (set.web_browser != nullptr) {
|
|
||||||
frontend.web_browser = std::move(set.web_browser);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletManager::SetCabinetMode(NFP::CabinetMode mode) {
|
|
||||||
cabinet_mode = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletManager::SetCurrentAppletId(AppletId applet_id) {
|
|
||||||
current_applet_id = applet_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletManager::SetDefaultAppletFrontendSet() {
|
|
||||||
ClearAll();
|
|
||||||
SetDefaultAppletsIfMissing();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletManager::SetDefaultAppletsIfMissing() {
|
|
||||||
if (frontend.cabinet == nullptr) {
|
|
||||||
frontend.cabinet = std::make_unique<Core::Frontend::DefaultCabinetApplet>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frontend.controller == nullptr) {
|
|
||||||
frontend.controller =
|
|
||||||
std::make_unique<Core::Frontend::DefaultControllerApplet>(system.HIDCore());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frontend.error == nullptr) {
|
|
||||||
frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frontend.mii_edit == nullptr) {
|
|
||||||
frontend.mii_edit = std::make_unique<Core::Frontend::DefaultMiiEditApplet>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frontend.parental_controls == nullptr) {
|
|
||||||
frontend.parental_controls =
|
|
||||||
std::make_unique<Core::Frontend::DefaultParentalControlsApplet>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frontend.photo_viewer == nullptr) {
|
|
||||||
frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frontend.profile_select == nullptr) {
|
|
||||||
frontend.profile_select = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frontend.software_keyboard == nullptr) {
|
|
||||||
frontend.software_keyboard =
|
|
||||||
std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frontend.web_browser == nullptr) {
|
|
||||||
frontend.web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppletManager::ClearAll() {
|
|
||||||
frontend = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id, LibraryAppletMode mode) const {
|
|
||||||
switch (id) {
|
|
||||||
case AppletId::Auth:
|
|
||||||
return std::make_shared<Auth>(system, mode, *frontend.parental_controls);
|
|
||||||
case AppletId::Cabinet:
|
|
||||||
return std::make_shared<Cabinet>(system, mode, *frontend.cabinet);
|
|
||||||
case AppletId::Controller:
|
|
||||||
return std::make_shared<Controller>(system, mode, *frontend.controller);
|
|
||||||
case AppletId::Error:
|
|
||||||
return std::make_shared<Error>(system, mode, *frontend.error);
|
|
||||||
case AppletId::ProfileSelect:
|
|
||||||
return std::make_shared<ProfileSelect>(system, mode, *frontend.profile_select);
|
|
||||||
case AppletId::SoftwareKeyboard:
|
|
||||||
return std::make_shared<SoftwareKeyboard>(system, mode, *frontend.software_keyboard);
|
|
||||||
case AppletId::MiiEdit:
|
|
||||||
return std::make_shared<MiiEdit>(system, mode, *frontend.mii_edit);
|
|
||||||
case AppletId::Web:
|
|
||||||
case AppletId::Shop:
|
|
||||||
case AppletId::OfflineWeb:
|
|
||||||
case AppletId::LoginShare:
|
|
||||||
case AppletId::WebAuth:
|
|
||||||
return std::make_shared<WebBrowser>(system, mode, *frontend.web_browser);
|
|
||||||
case AppletId::PhotoViewer:
|
|
||||||
return std::make_shared<PhotoViewer>(system, mode, *frontend.photo_viewer);
|
|
||||||
default:
|
|
||||||
UNIMPLEMENTED_MSG(
|
|
||||||
"No backend implementation exists for applet_id={:02X}! Falling back to stub applet.",
|
|
||||||
static_cast<u8>(id));
|
|
||||||
return std::make_shared<StubApplet>(system, id, mode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Service::AM::Applets
|
|
|
@ -1,289 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <queue>
|
|
||||||
|
|
||||||
#include "common/swap.h"
|
|
||||||
#include "core/hle/service/kernel_helpers.h"
|
|
||||||
|
|
||||||
union Result;
|
|
||||||
|
|
||||||
namespace Core {
|
|
||||||
class System;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Core::Frontend {
|
|
||||||
class CabinetApplet;
|
|
||||||
class ControllerApplet;
|
|
||||||
class ECommerceApplet;
|
|
||||||
class ErrorApplet;
|
|
||||||
class MiiEditApplet;
|
|
||||||
class ParentalControlsApplet;
|
|
||||||
class PhotoViewerApplet;
|
|
||||||
class ProfileSelectApplet;
|
|
||||||
class SoftwareKeyboardApplet;
|
|
||||||
class WebBrowserApplet;
|
|
||||||
} // namespace Core::Frontend
|
|
||||||
|
|
||||||
namespace Kernel {
|
|
||||||
class KernelCore;
|
|
||||||
class KEvent;
|
|
||||||
class KReadableEvent;
|
|
||||||
} // namespace Kernel
|
|
||||||
|
|
||||||
namespace Service::NFP {
|
|
||||||
enum class CabinetMode : u8;
|
|
||||||
} // namespace Service::NFP
|
|
||||||
|
|
||||||
namespace Service::AM {
|
|
||||||
|
|
||||||
class IStorage;
|
|
||||||
|
|
||||||
namespace Applets {
|
|
||||||
|
|
||||||
enum class AppletId : u32 {
|
|
||||||
None = 0x00,
|
|
||||||
Application = 0x01,
|
|
||||||
OverlayDisplay = 0x02,
|
|
||||||
QLaunch = 0x03,
|
|
||||||
Starter = 0x04,
|
|
||||||
Auth = 0x0A,
|
|
||||||
Cabinet = 0x0B,
|
|
||||||
Controller = 0x0C,
|
|
||||||
DataErase = 0x0D,
|
|
||||||
Error = 0x0E,
|
|
||||||
NetConnect = 0x0F,
|
|
||||||
ProfileSelect = 0x10,
|
|
||||||
SoftwareKeyboard = 0x11,
|
|
||||||
MiiEdit = 0x12,
|
|
||||||
Web = 0x13,
|
|
||||||
Shop = 0x14,
|
|
||||||
PhotoViewer = 0x15,
|
|
||||||
Settings = 0x16,
|
|
||||||
OfflineWeb = 0x17,
|
|
||||||
LoginShare = 0x18,
|
|
||||||
WebAuth = 0x19,
|
|
||||||
MyPage = 0x1A,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class AppletProgramId : u64 {
|
|
||||||
QLaunch = 0x0100000000001000ull,
|
|
||||||
Auth = 0x0100000000001001ull,
|
|
||||||
Cabinet = 0x0100000000001002ull,
|
|
||||||
Controller = 0x0100000000001003ull,
|
|
||||||
DataErase = 0x0100000000001004ull,
|
|
||||||
Error = 0x0100000000001005ull,
|
|
||||||
NetConnect = 0x0100000000001006ull,
|
|
||||||
ProfileSelect = 0x0100000000001007ull,
|
|
||||||
SoftwareKeyboard = 0x0100000000001008ull,
|
|
||||||
MiiEdit = 0x0100000000001009ull,
|
|
||||||
Web = 0x010000000000100Aull,
|
|
||||||
Shop = 0x010000000000100Bull,
|
|
||||||
OverlayDisplay = 0x010000000000100Cull,
|
|
||||||
PhotoViewer = 0x010000000000100Dull,
|
|
||||||
Settings = 0x010000000000100Eull,
|
|
||||||
OfflineWeb = 0x010000000000100Full,
|
|
||||||
LoginShare = 0x0100000000001010ull,
|
|
||||||
WebAuth = 0x0100000000001011ull,
|
|
||||||
Starter = 0x0100000000001012ull,
|
|
||||||
MyPage = 0x0100000000001013ull,
|
|
||||||
MaxProgramId = 0x0100000000001FFFull,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class LibraryAppletMode : u32 {
|
|
||||||
AllForeground = 0,
|
|
||||||
Background = 1,
|
|
||||||
NoUI = 2,
|
|
||||||
BackgroundIndirectDisplay = 3,
|
|
||||||
AllForegroundInitiallyHidden = 4,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class CommonArgumentVersion : u32 {
|
|
||||||
Version0,
|
|
||||||
Version1,
|
|
||||||
Version2,
|
|
||||||
Version3,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class CommonArgumentSize : u32 {
|
|
||||||
Version3 = 0x20,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class ThemeColor : u32 {
|
|
||||||
BasicWhite = 0,
|
|
||||||
BasicBlack = 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CommonArguments {
|
|
||||||
CommonArgumentVersion arguments_version;
|
|
||||||
CommonArgumentSize size;
|
|
||||||
u32 library_version;
|
|
||||||
ThemeColor theme_color;
|
|
||||||
bool play_startup_sound;
|
|
||||||
u64_le system_tick;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(CommonArguments) == 0x20, "CommonArguments has incorrect size.");
|
|
||||||
|
|
||||||
class AppletDataBroker final {
|
|
||||||
public:
|
|
||||||
explicit AppletDataBroker(Core::System& system_, LibraryAppletMode applet_mode_);
|
|
||||||
~AppletDataBroker();
|
|
||||||
|
|
||||||
struct RawChannelData {
|
|
||||||
std::vector<std::vector<u8>> normal;
|
|
||||||
std::vector<std::vector<u8>> interactive;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Retrieves but does not pop the data sent to applet.
|
|
||||||
RawChannelData PeekDataToAppletForDebug() const;
|
|
||||||
|
|
||||||
std::shared_ptr<IStorage> PopNormalDataToGame();
|
|
||||||
std::shared_ptr<IStorage> PopNormalDataToApplet();
|
|
||||||
|
|
||||||
std::shared_ptr<IStorage> PopInteractiveDataToGame();
|
|
||||||
std::shared_ptr<IStorage> PopInteractiveDataToApplet();
|
|
||||||
|
|
||||||
void PushNormalDataFromGame(std::shared_ptr<IStorage>&& storage);
|
|
||||||
void PushNormalDataFromApplet(std::shared_ptr<IStorage>&& storage);
|
|
||||||
|
|
||||||
void PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& storage);
|
|
||||||
void PushInteractiveDataFromApplet(std::shared_ptr<IStorage>&& storage);
|
|
||||||
|
|
||||||
void SignalStateChanged();
|
|
||||||
|
|
||||||
Kernel::KReadableEvent& GetNormalDataEvent();
|
|
||||||
Kernel::KReadableEvent& GetInteractiveDataEvent();
|
|
||||||
Kernel::KReadableEvent& GetStateChangedEvent();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Core::System& system;
|
|
||||||
LibraryAppletMode applet_mode;
|
|
||||||
|
|
||||||
KernelHelpers::ServiceContext service_context;
|
|
||||||
|
|
||||||
// Queues are named from applet's perspective
|
|
||||||
|
|
||||||
// PopNormalDataToApplet and PushNormalDataFromGame
|
|
||||||
std::deque<std::shared_ptr<IStorage>> in_channel;
|
|
||||||
|
|
||||||
// PopNormalDataToGame and PushNormalDataFromApplet
|
|
||||||
std::deque<std::shared_ptr<IStorage>> out_channel;
|
|
||||||
|
|
||||||
// PopInteractiveDataToApplet and PushInteractiveDataFromGame
|
|
||||||
std::deque<std::shared_ptr<IStorage>> in_interactive_channel;
|
|
||||||
|
|
||||||
// PopInteractiveDataToGame and PushInteractiveDataFromApplet
|
|
||||||
std::deque<std::shared_ptr<IStorage>> out_interactive_channel;
|
|
||||||
|
|
||||||
Kernel::KEvent* state_changed_event;
|
|
||||||
|
|
||||||
// Signaled on PushNormalDataFromApplet
|
|
||||||
Kernel::KEvent* pop_out_data_event;
|
|
||||||
|
|
||||||
// Signaled on PushInteractiveDataFromApplet
|
|
||||||
Kernel::KEvent* pop_interactive_out_data_event;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Applet {
|
|
||||||
public:
|
|
||||||
explicit Applet(Core::System& system_, LibraryAppletMode applet_mode_);
|
|
||||||
virtual ~Applet();
|
|
||||||
|
|
||||||
virtual void Initialize();
|
|
||||||
|
|
||||||
virtual bool TransactionComplete() const = 0;
|
|
||||||
virtual Result GetStatus() const = 0;
|
|
||||||
virtual void ExecuteInteractive() = 0;
|
|
||||||
virtual void Execute() = 0;
|
|
||||||
virtual Result RequestExit() = 0;
|
|
||||||
|
|
||||||
AppletDataBroker& GetBroker() {
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
const AppletDataBroker& GetBroker() const {
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
LibraryAppletMode GetLibraryAppletMode() const {
|
|
||||||
return applet_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsInitialized() const {
|
|
||||||
return initialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
CommonArguments common_args{};
|
|
||||||
AppletDataBroker broker;
|
|
||||||
LibraryAppletMode applet_mode;
|
|
||||||
bool initialized = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AppletFrontendSet {
|
|
||||||
using CabinetApplet = std::unique_ptr<Core::Frontend::CabinetApplet>;
|
|
||||||
using ControllerApplet = std::unique_ptr<Core::Frontend::ControllerApplet>;
|
|
||||||
using ErrorApplet = std::unique_ptr<Core::Frontend::ErrorApplet>;
|
|
||||||
using MiiEdit = std::unique_ptr<Core::Frontend::MiiEditApplet>;
|
|
||||||
using ParentalControlsApplet = std::unique_ptr<Core::Frontend::ParentalControlsApplet>;
|
|
||||||
using PhotoViewer = std::unique_ptr<Core::Frontend::PhotoViewerApplet>;
|
|
||||||
using ProfileSelect = std::unique_ptr<Core::Frontend::ProfileSelectApplet>;
|
|
||||||
using SoftwareKeyboard = std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet>;
|
|
||||||
using WebBrowser = std::unique_ptr<Core::Frontend::WebBrowserApplet>;
|
|
||||||
|
|
||||||
AppletFrontendSet();
|
|
||||||
AppletFrontendSet(CabinetApplet cabinet_applet, ControllerApplet controller_applet,
|
|
||||||
ErrorApplet error_applet, MiiEdit mii_edit_,
|
|
||||||
ParentalControlsApplet parental_controls_applet, PhotoViewer photo_viewer_,
|
|
||||||
ProfileSelect profile_select_, SoftwareKeyboard software_keyboard_,
|
|
||||||
WebBrowser web_browser_);
|
|
||||||
~AppletFrontendSet();
|
|
||||||
|
|
||||||
AppletFrontendSet(const AppletFrontendSet&) = delete;
|
|
||||||
AppletFrontendSet& operator=(const AppletFrontendSet&) = delete;
|
|
||||||
|
|
||||||
AppletFrontendSet(AppletFrontendSet&&) noexcept;
|
|
||||||
AppletFrontendSet& operator=(AppletFrontendSet&&) noexcept;
|
|
||||||
|
|
||||||
CabinetApplet cabinet;
|
|
||||||
ControllerApplet controller;
|
|
||||||
ErrorApplet error;
|
|
||||||
MiiEdit mii_edit;
|
|
||||||
ParentalControlsApplet parental_controls;
|
|
||||||
PhotoViewer photo_viewer;
|
|
||||||
ProfileSelect profile_select;
|
|
||||||
SoftwareKeyboard software_keyboard;
|
|
||||||
WebBrowser web_browser;
|
|
||||||
};
|
|
||||||
|
|
||||||
class AppletManager {
|
|
||||||
public:
|
|
||||||
explicit AppletManager(Core::System& system_);
|
|
||||||
~AppletManager();
|
|
||||||
|
|
||||||
const AppletFrontendSet& GetAppletFrontendSet() const;
|
|
||||||
NFP::CabinetMode GetCabinetMode() const;
|
|
||||||
AppletId GetCurrentAppletId() const;
|
|
||||||
|
|
||||||
void SetAppletFrontendSet(AppletFrontendSet set);
|
|
||||||
void SetCabinetMode(NFP::CabinetMode mode);
|
|
||||||
void SetCurrentAppletId(AppletId applet_id);
|
|
||||||
void SetDefaultAppletFrontendSet();
|
|
||||||
void SetDefaultAppletsIfMissing();
|
|
||||||
void ClearAll();
|
|
||||||
|
|
||||||
std::shared_ptr<Applet> GetApplet(AppletId id, LibraryAppletMode mode) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
AppletId current_applet_id{};
|
|
||||||
NFP::CabinetMode cabinet_mode{};
|
|
||||||
|
|
||||||
AppletFrontendSet frontend;
|
|
||||||
Core::System& system;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Applets
|
|
||||||
} // namespace Service::AM
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/application_creator.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
IApplicationCreator::IApplicationCreator(Core::System& system_)
|
||||||
|
: ServiceFramework{system_, "IApplicationCreator"} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, nullptr, "CreateApplication"},
|
||||||
|
{1, nullptr, "PopLaunchRequestedApplication"},
|
||||||
|
{10, nullptr, "CreateSystemApplication"},
|
||||||
|
{100, nullptr, "PopFloatingApplicationForDevelopment"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
IApplicationCreator::~IApplicationCreator() = default;
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,16 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
class IApplicationCreator final : public ServiceFramework<IApplicationCreator> {
|
||||||
|
public:
|
||||||
|
explicit IApplicationCreator(Core::System& system_);
|
||||||
|
~IApplicationCreator() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,594 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/settings.h"
|
||||||
|
#include "common/uuid.h"
|
||||||
|
#include "core/file_sys/control_metadata.h"
|
||||||
|
#include "core/file_sys/patch_manager.h"
|
||||||
|
#include "core/file_sys/registered_cache.h"
|
||||||
|
#include "core/file_sys/savedata_factory.h"
|
||||||
|
#include "core/hle/service/acc/profile_manager.h"
|
||||||
|
#include "core/hle/service/am/am_results.h"
|
||||||
|
#include "core/hle/service/am/applet.h"
|
||||||
|
#include "core/hle/service/am/application_functions.h"
|
||||||
|
#include "core/hle/service/am/storage.h"
|
||||||
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||||
|
#include "core/hle/service/filesystem/save_data_controller.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
#include "core/hle/service/ns/ns.h"
|
||||||
|
#include "core/hle/service/sm/sm.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
enum class LaunchParameterKind : u32 {
|
||||||
|
UserChannel = 1,
|
||||||
|
AccountPreselectedUser = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet_)
|
||||||
|
: ServiceFramework{system_, "IApplicationFunctions"}, applet{std::move(applet_)} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"},
|
||||||
|
{10, nullptr, "CreateApplicationAndPushAndRequestToStart"},
|
||||||
|
{11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"},
|
||||||
|
{12, nullptr, "CreateApplicationAndRequestToStart"},
|
||||||
|
{13, &IApplicationFunctions::CreateApplicationAndRequestToStartForQuest, "CreateApplicationAndRequestToStartForQuest"},
|
||||||
|
{14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"},
|
||||||
|
{15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"},
|
||||||
|
{20, &IApplicationFunctions::EnsureSaveData, "EnsureSaveData"},
|
||||||
|
{21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"},
|
||||||
|
{22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
|
||||||
|
{23, &IApplicationFunctions::GetDisplayVersion, "GetDisplayVersion"},
|
||||||
|
{24, nullptr, "GetLaunchStorageInfoForDebug"},
|
||||||
|
{25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"},
|
||||||
|
{26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"},
|
||||||
|
{27, &IApplicationFunctions::CreateCacheStorage, "CreateCacheStorage"},
|
||||||
|
{28, &IApplicationFunctions::GetSaveDataSizeMax, "GetSaveDataSizeMax"},
|
||||||
|
{29, nullptr, "GetCacheStorageMax"},
|
||||||
|
{30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"},
|
||||||
|
{31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"},
|
||||||
|
{32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"},
|
||||||
|
{33, &IApplicationFunctions::EndBlockingHomeButton, "EndBlockingHomeButton"},
|
||||||
|
{34, nullptr, "SelectApplicationLicense"},
|
||||||
|
{35, nullptr, "GetDeviceSaveDataSizeMax"},
|
||||||
|
{36, nullptr, "GetLimitedApplicationLicense"},
|
||||||
|
{37, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"},
|
||||||
|
{40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"},
|
||||||
|
{50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"},
|
||||||
|
{60, nullptr, "SetMediaPlaybackStateForApplication"},
|
||||||
|
{65, &IApplicationFunctions::IsGamePlayRecordingSupported, "IsGamePlayRecordingSupported"},
|
||||||
|
{66, &IApplicationFunctions::InitializeGamePlayRecording, "InitializeGamePlayRecording"},
|
||||||
|
{67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"},
|
||||||
|
{68, nullptr, "RequestFlushGamePlayingMovieForDebug"},
|
||||||
|
{70, nullptr, "RequestToShutdown"},
|
||||||
|
{71, nullptr, "RequestToReboot"},
|
||||||
|
{72, nullptr, "RequestToSleep"},
|
||||||
|
{80, nullptr, "ExitAndRequestToShowThanksMessage"},
|
||||||
|
{90, &IApplicationFunctions::EnableApplicationCrashReport, "EnableApplicationCrashReport"},
|
||||||
|
{100, &IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer, "InitializeApplicationCopyrightFrameBuffer"},
|
||||||
|
{101, &IApplicationFunctions::SetApplicationCopyrightImage, "SetApplicationCopyrightImage"},
|
||||||
|
{102, &IApplicationFunctions::SetApplicationCopyrightVisibility, "SetApplicationCopyrightVisibility"},
|
||||||
|
{110, &IApplicationFunctions::QueryApplicationPlayStatistics, "QueryApplicationPlayStatistics"},
|
||||||
|
{111, &IApplicationFunctions::QueryApplicationPlayStatisticsByUid, "QueryApplicationPlayStatisticsByUid"},
|
||||||
|
{120, &IApplicationFunctions::ExecuteProgram, "ExecuteProgram"},
|
||||||
|
{121, &IApplicationFunctions::ClearUserChannel, "ClearUserChannel"},
|
||||||
|
{122, &IApplicationFunctions::UnpopToUserChannel, "UnpopToUserChannel"},
|
||||||
|
{123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"},
|
||||||
|
{124, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
|
||||||
|
{130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"},
|
||||||
|
{131, nullptr, "SetDelayTimeToAbortOnGpuError"},
|
||||||
|
{140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"},
|
||||||
|
{141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"},
|
||||||
|
{150, &IApplicationFunctions::GetNotificationStorageChannelEvent, "GetNotificationStorageChannelEvent"},
|
||||||
|
{151, nullptr, "TryPopFromNotificationStorageChannel"},
|
||||||
|
{160, &IApplicationFunctions::GetHealthWarningDisappearedSystemEvent, "GetHealthWarningDisappearedSystemEvent"},
|
||||||
|
{170, nullptr, "SetHdcpAuthenticationActivated"},
|
||||||
|
{180, nullptr, "GetLaunchRequiredVersion"},
|
||||||
|
{181, nullptr, "UpgradeLaunchRequiredVersion"},
|
||||||
|
{190, nullptr, "SendServerMaintenanceOverlayNotification"},
|
||||||
|
{200, nullptr, "GetLastApplicationExitReason"},
|
||||||
|
{500, nullptr, "StartContinuousRecordingFlushForDebug"},
|
||||||
|
{1000, nullptr, "CreateMovieMaker"},
|
||||||
|
{1001, &IApplicationFunctions::PrepareForJit, "PrepareForJit"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
IApplicationFunctions::~IApplicationFunctions() = default;
|
||||||
|
|
||||||
|
void IApplicationFunctions::EnableApplicationCrashReport(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->application_crash_report_enabled = true;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::SetApplicationCopyrightImage(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::SetApplicationCopyrightVisibility(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
const auto is_visible = rp.Pop<bool>();
|
||||||
|
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called, is_visible={}", is_visible);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->home_button_long_pressed_blocked = true;
|
||||||
|
applet->home_button_short_pressed_blocked = true;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->home_button_long_pressed_blocked = false;
|
||||||
|
applet->home_button_short_pressed_blocked = false;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::BeginBlockingHomeButton(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->home_button_long_pressed_blocked = true;
|
||||||
|
applet->home_button_short_pressed_blocked = true;
|
||||||
|
applet->home_button_double_click_enabled = true;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::EndBlockingHomeButton(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->home_button_long_pressed_blocked = false;
|
||||||
|
applet->home_button_short_pressed_blocked = false;
|
||||||
|
applet->home_button_double_click_enabled = false;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::PopLaunchParameter(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
const auto kind = rp.PopEnum<LaunchParameterKind>();
|
||||||
|
|
||||||
|
LOG_INFO(Service_AM, "called, kind={:08X}", kind);
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
|
||||||
|
auto& channel = kind == LaunchParameterKind::UserChannel
|
||||||
|
? applet->user_channel_launch_parameter
|
||||||
|
: applet->preselected_user_launch_parameter;
|
||||||
|
|
||||||
|
if (channel.empty()) {
|
||||||
|
LOG_WARNING(Service_AM, "Attempted to pop parameter {} but none was found!", kind);
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(AM::ResultNoDataInChannel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto data = channel.back();
|
||||||
|
channel.pop_back();
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<IStorage>(system, std::move(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::EnsureSaveData(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
u128 user_id = rp.PopRaw<u128>();
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]);
|
||||||
|
|
||||||
|
FileSys::SaveDataAttribute attribute{};
|
||||||
|
attribute.title_id = applet->program_id;
|
||||||
|
attribute.user_id = user_id;
|
||||||
|
attribute.type = FileSys::SaveDataType::SaveData;
|
||||||
|
|
||||||
|
FileSys::VirtualDir save_data{};
|
||||||
|
const auto res = system.GetFileSystemController().OpenSaveDataController()->CreateSaveData(
|
||||||
|
&save_data, FileSys::SaveDataSpaceId::NandUser, attribute);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(res);
|
||||||
|
rb.Push<u64>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::SetTerminateResult(HLERequestContext& ctx) {
|
||||||
|
// Takes an input u32 Result, no output.
|
||||||
|
// For example, in some cases official apps use this with error 0x2A2 then
|
||||||
|
// uses svcBreak.
|
||||||
|
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
u32 result = rp.Pop<u32>();
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called, result=0x{:08X}", result);
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->terminate_result = Result(result);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::GetDisplayVersion(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
std::array<u8, 0x10> version_string{};
|
||||||
|
|
||||||
|
const auto res = [this] {
|
||||||
|
const FileSys::PatchManager pm{applet->program_id, system.GetFileSystemController(),
|
||||||
|
system.GetContentProvider()};
|
||||||
|
auto metadata = pm.GetControlMetadata();
|
||||||
|
if (metadata.first != nullptr) {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(applet->program_id),
|
||||||
|
system.GetFileSystemController(),
|
||||||
|
system.GetContentProvider()};
|
||||||
|
return pm_update.GetControlMetadata();
|
||||||
|
}();
|
||||||
|
|
||||||
|
if (res.first != nullptr) {
|
||||||
|
const auto& version = res.first->GetVersionString();
|
||||||
|
std::copy(version.begin(), version.end(), version_string.begin());
|
||||||
|
} else {
|
||||||
|
static constexpr char default_version[]{"1.0.0"};
|
||||||
|
std::memcpy(version_string.data(), default_version, sizeof(default_version));
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 6};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushRaw(version_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) {
|
||||||
|
// TODO(bunnei): This should be configurable
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
// Get supported languages from NACP, if possible
|
||||||
|
// Default to 0 (all languages supported)
|
||||||
|
u32 supported_languages = 0;
|
||||||
|
|
||||||
|
const auto res = [this] {
|
||||||
|
const FileSys::PatchManager pm{applet->program_id, system.GetFileSystemController(),
|
||||||
|
system.GetContentProvider()};
|
||||||
|
auto metadata = pm.GetControlMetadata();
|
||||||
|
if (metadata.first != nullptr) {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(applet->program_id),
|
||||||
|
system.GetFileSystemController(),
|
||||||
|
system.GetContentProvider()};
|
||||||
|
return pm_update.GetControlMetadata();
|
||||||
|
}();
|
||||||
|
|
||||||
|
if (res.first != nullptr) {
|
||||||
|
supported_languages = res.first->GetSupportedLanguages();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call IApplicationManagerInterface implementation.
|
||||||
|
auto& service_manager = system.ServiceManager();
|
||||||
|
auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2");
|
||||||
|
auto app_man = ns_am2->GetApplicationManagerInterface();
|
||||||
|
|
||||||
|
// Get desired application language
|
||||||
|
u8 desired_language{};
|
||||||
|
const auto res_lang =
|
||||||
|
app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages);
|
||||||
|
if (res_lang != ResultSuccess) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(res_lang);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to settings language code.
|
||||||
|
u64 language_code{};
|
||||||
|
const auto res_code =
|
||||||
|
app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language);
|
||||||
|
if (res_code != ResultSuccess) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(res_code);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push(language_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push(applet->gameplay_recording_supported);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::InitializeGamePlayRecording(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::SetGamePlayRecordingState(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->gameplay_recording_state = rp.PopRaw<GameplayRecordingState>();
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::NotifyRunning(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->is_running = true;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push<u8>(0); // Unknown, seems to be ignored by official processes
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::GetPseudoDeviceId(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 6};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
|
||||||
|
// Returns a 128-bit UUID
|
||||||
|
rb.Push<u64>(0);
|
||||||
|
rb.Push<u64>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::ExtendSaveData(HLERequestContext& ctx) {
|
||||||
|
struct Parameters {
|
||||||
|
FileSys::SaveDataType type;
|
||||||
|
u128 user_id;
|
||||||
|
u64 new_normal_size;
|
||||||
|
u64 new_journal_size;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(Parameters) == 40);
|
||||||
|
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
const auto [type, user_id, new_normal_size, new_journal_size] = rp.PopRaw<Parameters>();
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_AM,
|
||||||
|
"called with type={:02X}, user_id={:016X}{:016X}, new_normal={:016X}, "
|
||||||
|
"new_journal={:016X}",
|
||||||
|
static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size);
|
||||||
|
|
||||||
|
system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize(
|
||||||
|
type, applet->program_id, user_id, {new_normal_size, new_journal_size});
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
|
||||||
|
// The following value is used upon failure to help the system recover.
|
||||||
|
// Since we always succeed, this should be 0.
|
||||||
|
rb.Push<u64>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::GetSaveDataSize(HLERequestContext& ctx) {
|
||||||
|
struct Parameters {
|
||||||
|
FileSys::SaveDataType type;
|
||||||
|
u128 user_id;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(Parameters) == 24);
|
||||||
|
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
const auto [type, user_id] = rp.PopRaw<Parameters>();
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_AM, "called with type={:02X}, user_id={:016X}{:016X}", type, user_id[1],
|
||||||
|
user_id[0]);
|
||||||
|
|
||||||
|
const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize(
|
||||||
|
type, applet->program_id, user_id);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 6};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push(size.normal);
|
||||||
|
rb.Push(size.journal);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::CreateCacheStorage(HLERequestContext& ctx) {
|
||||||
|
struct InputParameters {
|
||||||
|
u16 index;
|
||||||
|
s64 size;
|
||||||
|
s64 journal_size;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(InputParameters) == 24);
|
||||||
|
|
||||||
|
struct OutputParameters {
|
||||||
|
u32 storage_target;
|
||||||
|
u64 required_size;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(OutputParameters) == 16);
|
||||||
|
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
const auto params = rp.PopRaw<InputParameters>();
|
||||||
|
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called with index={}, size={:#x}, journal_size={:#x}",
|
||||||
|
params.index, params.size, params.journal_size);
|
||||||
|
|
||||||
|
const OutputParameters resp{
|
||||||
|
.storage_target = 1,
|
||||||
|
.required_size = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 6};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushRaw(resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::GetSaveDataSizeMax(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
constexpr u64 size_max_normal = 0xFFFFFFF;
|
||||||
|
constexpr u64 size_max_journal = 0xFFFFFFF;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 6};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push(size_max_normal);
|
||||||
|
rb.Push(size_max_journal);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::QueryApplicationPlayStatistics(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push<u32>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push<u32>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::ExecuteProgram(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
[[maybe_unused]] const auto unk_1 = rp.Pop<u32>();
|
||||||
|
[[maybe_unused]] const auto unk_2 = rp.Pop<u32>();
|
||||||
|
const auto program_index = rp.Pop<u64>();
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
|
||||||
|
// Swap user channel ownership into the system so that it will be preserved
|
||||||
|
system.GetUserChannel().swap(applet->user_channel_launch_parameter);
|
||||||
|
system.ExecuteProgram(program_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::ClearUserChannel(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
applet->user_channel_launch_parameter.clear();
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::UnpopToUserChannel(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
const auto storage = rp.PopIpcInterface<IStorage>().lock();
|
||||||
|
if (storage) {
|
||||||
|
applet->user_channel_launch_parameter.push_back(storage->GetData());
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::GetPreviousProgramIndex(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push<s32>(applet->previous_program_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushCopyObjects(applet->gpu_error_detected_event.GetHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushCopyObjects(applet->friend_invitation_storage_channel_event.GetHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(AM::ResultNoDataInChannel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::GetNotificationStorageChannelEvent(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushCopyObjects(applet->notification_storage_channel_event.GetHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushCopyObjects(applet->health_warning_disappeared_system_event.GetHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationFunctions::PrepareForJit(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->jit_service_launched = true;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,58 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/kernel_helpers.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
|
class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
|
||||||
|
public:
|
||||||
|
explicit IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet_);
|
||||||
|
~IApplicationFunctions() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void PopLaunchParameter(HLERequestContext& ctx);
|
||||||
|
void CreateApplicationAndRequestToStartForQuest(HLERequestContext& ctx);
|
||||||
|
void EnsureSaveData(HLERequestContext& ctx);
|
||||||
|
void SetTerminateResult(HLERequestContext& ctx);
|
||||||
|
void GetDisplayVersion(HLERequestContext& ctx);
|
||||||
|
void GetDesiredLanguage(HLERequestContext& ctx);
|
||||||
|
void IsGamePlayRecordingSupported(HLERequestContext& ctx);
|
||||||
|
void InitializeGamePlayRecording(HLERequestContext& ctx);
|
||||||
|
void SetGamePlayRecordingState(HLERequestContext& ctx);
|
||||||
|
void NotifyRunning(HLERequestContext& ctx);
|
||||||
|
void GetPseudoDeviceId(HLERequestContext& ctx);
|
||||||
|
void ExtendSaveData(HLERequestContext& ctx);
|
||||||
|
void GetSaveDataSize(HLERequestContext& ctx);
|
||||||
|
void CreateCacheStorage(HLERequestContext& ctx);
|
||||||
|
void GetSaveDataSizeMax(HLERequestContext& ctx);
|
||||||
|
void BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx);
|
||||||
|
void EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx);
|
||||||
|
void BeginBlockingHomeButton(HLERequestContext& ctx);
|
||||||
|
void EndBlockingHomeButton(HLERequestContext& ctx);
|
||||||
|
void EnableApplicationCrashReport(HLERequestContext& ctx);
|
||||||
|
void InitializeApplicationCopyrightFrameBuffer(HLERequestContext& ctx);
|
||||||
|
void SetApplicationCopyrightImage(HLERequestContext& ctx);
|
||||||
|
void SetApplicationCopyrightVisibility(HLERequestContext& ctx);
|
||||||
|
void QueryApplicationPlayStatistics(HLERequestContext& ctx);
|
||||||
|
void QueryApplicationPlayStatisticsByUid(HLERequestContext& ctx);
|
||||||
|
void ExecuteProgram(HLERequestContext& ctx);
|
||||||
|
void ClearUserChannel(HLERequestContext& ctx);
|
||||||
|
void UnpopToUserChannel(HLERequestContext& ctx);
|
||||||
|
void GetPreviousProgramIndex(HLERequestContext& ctx);
|
||||||
|
void GetGpuErrorDetectedSystemEvent(HLERequestContext& ctx);
|
||||||
|
void GetFriendInvitationStorageChannelEvent(HLERequestContext& ctx);
|
||||||
|
void TryPopFromFriendInvitationStorageChannel(HLERequestContext& ctx);
|
||||||
|
void GetNotificationStorageChannelEvent(HLERequestContext& ctx);
|
||||||
|
void GetHealthWarningDisappearedSystemEvent(HLERequestContext& ctx);
|
||||||
|
void PrepareForJit(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
const std::shared_ptr<Applet> applet;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,115 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/applet_common_functions.h"
|
||||||
|
#include "core/hle/service/am/application_functions.h"
|
||||||
|
#include "core/hle/service/am/application_proxy.h"
|
||||||
|
#include "core/hle/service/am/audio_controller.h"
|
||||||
|
#include "core/hle/service/am/common_state_getter.h"
|
||||||
|
#include "core/hle/service/am/debug_functions.h"
|
||||||
|
#include "core/hle/service/am/display_controller.h"
|
||||||
|
#include "core/hle/service/am/library_applet_creator.h"
|
||||||
|
#include "core/hle/service/am/library_applet_self_accessor.h"
|
||||||
|
#include "core/hle/service/am/process_winding_controller.h"
|
||||||
|
#include "core/hle/service/am/self_controller.h"
|
||||||
|
#include "core/hle/service/am/window_controller.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
IApplicationProxy::IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
||||||
|
std::shared_ptr<Applet> applet_, Core::System& system_)
|
||||||
|
: ServiceFramework{system_, "IApplicationProxy"}, nvnflinger{nvnflinger_}, applet{std::move(
|
||||||
|
applet_)} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"},
|
||||||
|
{1, &IApplicationProxy::GetSelfController, "GetSelfController"},
|
||||||
|
{2, &IApplicationProxy::GetWindowController, "GetWindowController"},
|
||||||
|
{3, &IApplicationProxy::GetAudioController, "GetAudioController"},
|
||||||
|
{4, &IApplicationProxy::GetDisplayController, "GetDisplayController"},
|
||||||
|
{10, &IApplicationProxy::GetProcessWindingController, "GetProcessWindingController"},
|
||||||
|
{11, &IApplicationProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
|
||||||
|
{20, &IApplicationProxy::GetApplicationFunctions, "GetApplicationFunctions"},
|
||||||
|
{1000, &IApplicationProxy::GetDebugFunctions, "GetDebugFunctions"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
IApplicationProxy::~IApplicationProxy() = default;
|
||||||
|
|
||||||
|
void IApplicationProxy::GetAudioController(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<IAudioController>(system);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationProxy::GetDisplayController(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<IDisplayController>(system, applet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationProxy::GetProcessWindingController(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<IProcessWindingController>(system, applet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationProxy::GetDebugFunctions(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<IDebugFunctions>(system);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationProxy::GetWindowController(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<IWindowController>(system, applet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationProxy::GetSelfController(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<ISelfController>(system, applet, nvnflinger);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationProxy::GetCommonStateGetter(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<ICommonStateGetter>(system, applet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<ILibraryAppletCreator>(system, applet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IApplicationProxy::GetApplicationFunctions(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<IApplicationFunctions>(system, applet);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,33 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
|
class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
|
||||||
|
public:
|
||||||
|
explicit IApplicationProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
||||||
|
std::shared_ptr<Applet> msg_queue_, Core::System& system_);
|
||||||
|
~IApplicationProxy();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void GetAudioController(HLERequestContext& ctx);
|
||||||
|
void GetDisplayController(HLERequestContext& ctx);
|
||||||
|
void GetProcessWindingController(HLERequestContext& ctx);
|
||||||
|
void GetDebugFunctions(HLERequestContext& ctx);
|
||||||
|
void GetWindowController(HLERequestContext& ctx);
|
||||||
|
void GetSelfController(HLERequestContext& ctx);
|
||||||
|
void GetCommonStateGetter(HLERequestContext& ctx);
|
||||||
|
void GetLibraryAppletCreator(HLERequestContext& ctx);
|
||||||
|
void GetApplicationFunctions(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
Nvnflinger::Nvnflinger& nvnflinger;
|
||||||
|
std::shared_ptr<Applet> applet;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,91 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/audio_controller.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
IAudioController::IAudioController(Core::System& system_)
|
||||||
|
: ServiceFramework{system_, "IAudioController"} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, &IAudioController::SetExpectedMasterVolume, "SetExpectedMasterVolume"},
|
||||||
|
{1, &IAudioController::GetMainAppletExpectedMasterVolume, "GetMainAppletExpectedMasterVolume"},
|
||||||
|
{2, &IAudioController::GetLibraryAppletExpectedMasterVolume, "GetLibraryAppletExpectedMasterVolume"},
|
||||||
|
{3, &IAudioController::ChangeMainAppletMasterVolume, "ChangeMainAppletMasterVolume"},
|
||||||
|
{4, &IAudioController::SetTransparentAudioRate, "SetTransparentVolumeRate"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
IAudioController::~IAudioController() = default;
|
||||||
|
|
||||||
|
void IAudioController::SetExpectedMasterVolume(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
const float main_applet_volume_tmp = rp.Pop<float>();
|
||||||
|
const float library_applet_volume_tmp = rp.Pop<float>();
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_AM, "called. main_applet_volume={}, library_applet_volume={}",
|
||||||
|
main_applet_volume_tmp, library_applet_volume_tmp);
|
||||||
|
|
||||||
|
// Ensure the volume values remain within the 0-100% range
|
||||||
|
main_applet_volume = std::clamp(main_applet_volume_tmp, min_allowed_volume, max_allowed_volume);
|
||||||
|
library_applet_volume =
|
||||||
|
std::clamp(library_applet_volume_tmp, min_allowed_volume, max_allowed_volume);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IAudioController::GetMainAppletExpectedMasterVolume(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called. main_applet_volume={}", main_applet_volume);
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push(main_applet_volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IAudioController::GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called. library_applet_volume={}", library_applet_volume);
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push(library_applet_volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IAudioController::ChangeMainAppletMasterVolume(HLERequestContext& ctx) {
|
||||||
|
struct Parameters {
|
||||||
|
float volume;
|
||||||
|
s64 fade_time_ns;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(Parameters) == 16);
|
||||||
|
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
const auto parameters = rp.PopRaw<Parameters>();
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_AM, "called. volume={}, fade_time_ns={}", parameters.volume,
|
||||||
|
parameters.fade_time_ns);
|
||||||
|
|
||||||
|
main_applet_volume = std::clamp(parameters.volume, min_allowed_volume, max_allowed_volume);
|
||||||
|
fade_time_ns = std::chrono::nanoseconds{parameters.fade_time_ns};
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IAudioController::SetTransparentAudioRate(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
const float transparent_volume_rate_tmp = rp.Pop<float>();
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_AM, "called. transparent_volume_rate={}", transparent_volume_rate_tmp);
|
||||||
|
|
||||||
|
// Clamp volume range to 0-100%.
|
||||||
|
transparent_volume_rate =
|
||||||
|
std::clamp(transparent_volume_rate_tmp, min_allowed_volume, max_allowed_volume);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,36 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
class IAudioController final : public ServiceFramework<IAudioController> {
|
||||||
|
public:
|
||||||
|
explicit IAudioController(Core::System& system_);
|
||||||
|
~IAudioController() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SetExpectedMasterVolume(HLERequestContext& ctx);
|
||||||
|
void GetMainAppletExpectedMasterVolume(HLERequestContext& ctx);
|
||||||
|
void GetLibraryAppletExpectedMasterVolume(HLERequestContext& ctx);
|
||||||
|
void ChangeMainAppletMasterVolume(HLERequestContext& ctx);
|
||||||
|
void SetTransparentAudioRate(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
static constexpr float min_allowed_volume = 0.0f;
|
||||||
|
static constexpr float max_allowed_volume = 1.0f;
|
||||||
|
|
||||||
|
float main_applet_volume{0.25f};
|
||||||
|
float library_applet_volume{max_allowed_volume};
|
||||||
|
float transparent_volume_rate{min_allowed_volume};
|
||||||
|
|
||||||
|
// Volume transition fade time in nanoseconds.
|
||||||
|
// e.g. If the main applet volume was 0% and was changed to 50%
|
||||||
|
// with a fade of 50ns, then over the course of 50ns,
|
||||||
|
// the volume will gradually fade up to 50%
|
||||||
|
std::chrono::nanoseconds fade_time_ns{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,314 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/settings.h"
|
||||||
|
#include "core/hle/service/am/am_results.h"
|
||||||
|
#include "core/hle/service/am/applet.h"
|
||||||
|
#include "core/hle/service/am/common_state_getter.h"
|
||||||
|
#include "core/hle/service/am/lock_accessor.h"
|
||||||
|
#include "core/hle/service/apm/apm_controller.h"
|
||||||
|
#include "core/hle/service/apm/apm_interface.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
#include "core/hle/service/pm/pm.h"
|
||||||
|
#include "core/hle/service/sm/sm.h"
|
||||||
|
#include "core/hle/service/vi/vi.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
ICommonStateGetter::ICommonStateGetter(Core::System& system_, std::shared_ptr<Applet> applet_)
|
||||||
|
: ServiceFramework{system_, "ICommonStateGetter"}, applet{std::move(applet_)} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"},
|
||||||
|
{1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"},
|
||||||
|
{2, nullptr, "GetThisAppletKind"},
|
||||||
|
{3, nullptr, "AllowToEnterSleep"},
|
||||||
|
{4, nullptr, "DisallowToEnterSleep"},
|
||||||
|
{5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"},
|
||||||
|
{6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"},
|
||||||
|
{7, nullptr, "GetCradleStatus"},
|
||||||
|
{8, &ICommonStateGetter::GetBootMode, "GetBootMode"},
|
||||||
|
{9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"},
|
||||||
|
{10, &ICommonStateGetter::RequestToAcquireSleepLock, "RequestToAcquireSleepLock"},
|
||||||
|
{11, nullptr, "ReleaseSleepLock"},
|
||||||
|
{12, nullptr, "ReleaseSleepLockTransiently"},
|
||||||
|
{13, &ICommonStateGetter::GetAcquiredSleepLockEvent, "GetAcquiredSleepLockEvent"},
|
||||||
|
{14, nullptr, "GetWakeupCount"},
|
||||||
|
{20, nullptr, "PushToGeneralChannel"},
|
||||||
|
{30, nullptr, "GetHomeButtonReaderLockAccessor"},
|
||||||
|
{31, &ICommonStateGetter::GetReaderLockAccessorEx, "GetReaderLockAccessorEx"},
|
||||||
|
{32, nullptr, "GetWriterLockAccessorEx"},
|
||||||
|
{40, nullptr, "GetCradleFwVersion"},
|
||||||
|
{50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"},
|
||||||
|
{51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"},
|
||||||
|
{52, &ICommonStateGetter::SetLcdBacklighOffEnabled, "SetLcdBacklighOffEnabled"},
|
||||||
|
{53, &ICommonStateGetter::BeginVrModeEx, "BeginVrModeEx"},
|
||||||
|
{54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"},
|
||||||
|
{55, nullptr, "IsInControllerFirmwareUpdateSection"},
|
||||||
|
{59, nullptr, "SetVrPositionForDebug"},
|
||||||
|
{60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"},
|
||||||
|
{61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"},
|
||||||
|
{62, nullptr, "GetHdcpAuthenticationState"},
|
||||||
|
{63, nullptr, "GetHdcpAuthenticationStateChangeEvent"},
|
||||||
|
{64, nullptr, "SetTvPowerStateMatchingMode"},
|
||||||
|
{65, nullptr, "GetApplicationIdByContentActionName"},
|
||||||
|
{66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"},
|
||||||
|
{67, nullptr, "CancelCpuBoostMode"},
|
||||||
|
{68, &ICommonStateGetter::GetBuiltInDisplayType, "GetBuiltInDisplayType"},
|
||||||
|
{80, &ICommonStateGetter::PerformSystemButtonPressingIfInFocus, "PerformSystemButtonPressingIfInFocus"},
|
||||||
|
{90, nullptr, "SetPerformanceConfigurationChangedNotification"},
|
||||||
|
{91, nullptr, "GetCurrentPerformanceConfiguration"},
|
||||||
|
{100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"},
|
||||||
|
{110, nullptr, "OpenMyGpuErrorHandler"},
|
||||||
|
{120, &ICommonStateGetter::GetAppletLaunchedHistory, "GetAppletLaunchedHistory"},
|
||||||
|
{200, nullptr, "GetOperationModeSystemInfo"},
|
||||||
|
{300, &ICommonStateGetter::GetSettingsPlatformRegion, "GetSettingsPlatformRegion"},
|
||||||
|
{400, nullptr, "ActivateMigrationService"},
|
||||||
|
{401, nullptr, "DeactivateMigrationService"},
|
||||||
|
{500, nullptr, "DisableSleepTillShutdown"},
|
||||||
|
{501, nullptr, "SuppressDisablingSleepTemporarily"},
|
||||||
|
{502, nullptr, "IsSleepEnabled"},
|
||||||
|
{503, nullptr, "IsDisablingSleepSuppressed"},
|
||||||
|
{900, &ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
ICommonStateGetter::~ICommonStateGetter() = default;
|
||||||
|
|
||||||
|
void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push<u8>(static_cast<u8>(Service::PM::SystemBootMode::Normal)); // Normal boot mode
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICommonStateGetter::GetEventHandle(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushCopyObjects(applet->message_queue.GetMessageReceiveEvent());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICommonStateGetter::ReceiveMessage(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
const auto message = applet->message_queue.PopMessage();
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
|
||||||
|
if (message == AppletMessageQueue::AppletMessage::None) {
|
||||||
|
LOG_ERROR(Service_AM, "Message queue is empty");
|
||||||
|
rb.Push(AM::ResultNoMessages);
|
||||||
|
rb.PushEnum<AppletMessageQueue::AppletMessage>(message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushEnum<AppletMessageQueue::AppletMessage>(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICommonStateGetter::GetCurrentFocusState(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push(static_cast<u8>(applet->focus_state));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICommonStateGetter::GetOperationMode(HLERequestContext& ctx) {
|
||||||
|
const bool use_docked_mode{Settings::IsDockedMode()};
|
||||||
|
LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICommonStateGetter::GetPerformanceMode(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushEnum(system.GetAPMController().GetCurrentPerformanceMode());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICommonStateGetter::RequestToAcquireSleepLock(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
// Sleep lock is acquired immediately.
|
||||||
|
applet->sleep_lock_event.Signal();
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICommonStateGetter::GetReaderLockAccessorEx(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
const auto unknown = rp.Pop<u32>();
|
||||||
|
|
||||||
|
LOG_INFO(Service_AM, "called, unknown={}", unknown);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<ILockAccessor>(system);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICommonStateGetter::GetAcquiredSleepLockEvent(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushCopyObjects(applet->sleep_lock_event.GetHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push(applet->vr_mode_enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICommonStateGetter::SetVrModeEnabled(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->vr_mode_enabled = rp.Pop<bool>();
|
||||||
|
LOG_WARNING(Service_AM, "VR Mode is {}", applet->vr_mode_enabled ? "on" : "off");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICommonStateGetter::SetLcdBacklighOffEnabled(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
const auto is_lcd_backlight_off_enabled = rp.Pop<bool>();
|
||||||
|
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called. is_lcd_backlight_off_enabled={}",
|
||||||
|
is_lcd_backlight_off_enabled);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICommonStateGetter::BeginVrModeEx(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->vr_mode_enabled = true;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICommonStateGetter::EndVrModeEx(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->vr_mode_enabled = false;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushCopyObjects(applet->message_queue.GetOperationModeChangedEvent());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICommonStateGetter::GetDefaultDisplayResolution(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
|
||||||
|
if (Settings::IsDockedMode()) {
|
||||||
|
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth));
|
||||||
|
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight));
|
||||||
|
} else {
|
||||||
|
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth));
|
||||||
|
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICommonStateGetter::SetCpuBoostMode(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called, forwarding to APM:SYS");
|
||||||
|
|
||||||
|
const auto& sm = system.ServiceManager();
|
||||||
|
const auto apm_sys = sm.GetService<APM::APM_Sys>("apm:sys");
|
||||||
|
ASSERT(apm_sys != nullptr);
|
||||||
|
|
||||||
|
apm_sys->SetCpuBoostMode(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICommonStateGetter::GetBuiltInDisplayType(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICommonStateGetter::PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
const auto system_button{rp.PopEnum<SystemButtonType>()};
|
||||||
|
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called, system_button={}", system_button);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICommonStateGetter::GetAppletLaunchedHistory(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::shared_ptr<Applet> current_applet = applet;
|
||||||
|
std::vector<AppletId> result;
|
||||||
|
|
||||||
|
const size_t count = ctx.GetWriteBufferNumElements<AppletId>();
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < count && current_applet != nullptr; i++) {
|
||||||
|
result.push_back(current_applet->applet_id);
|
||||||
|
current_applet = current_applet->caller_applet.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.WriteBuffer(result);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push(static_cast<u32>(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICommonStateGetter::GetSettingsPlatformRegion(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushEnum(SysPlatformRegion::Global);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(
|
||||||
|
HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->request_exit_to_library_applet_at_execute_next_program_enabled = true;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,77 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/kernel_helpers.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
#include "core/hle/service/am/applet_message_queue.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
|
class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
|
||||||
|
public:
|
||||||
|
explicit ICommonStateGetter(Core::System& system_, std::shared_ptr<Applet> applet_);
|
||||||
|
~ICommonStateGetter() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// This is nn::oe::FocusState
|
||||||
|
enum class FocusState : u8 {
|
||||||
|
InFocus = 1,
|
||||||
|
NotInFocus = 2,
|
||||||
|
Background = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is nn::oe::OperationMode
|
||||||
|
enum class OperationMode : u8 {
|
||||||
|
Handheld = 0,
|
||||||
|
Docked = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is nn::am::service::SystemButtonType
|
||||||
|
enum class SystemButtonType {
|
||||||
|
None,
|
||||||
|
HomeButtonShortPressing,
|
||||||
|
HomeButtonLongPressing,
|
||||||
|
PowerButtonShortPressing,
|
||||||
|
PowerButtonLongPressing,
|
||||||
|
ShutdownSystem,
|
||||||
|
CaptureButtonShortPressing,
|
||||||
|
CaptureButtonLongPressing,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class SysPlatformRegion : s32 {
|
||||||
|
Global = 1,
|
||||||
|
Terra = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
void GetEventHandle(HLERequestContext& ctx);
|
||||||
|
void ReceiveMessage(HLERequestContext& ctx);
|
||||||
|
void GetCurrentFocusState(HLERequestContext& ctx);
|
||||||
|
void RequestToAcquireSleepLock(HLERequestContext& ctx);
|
||||||
|
void GetAcquiredSleepLockEvent(HLERequestContext& ctx);
|
||||||
|
void GetReaderLockAccessorEx(HLERequestContext& ctx);
|
||||||
|
void GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx);
|
||||||
|
void GetOperationMode(HLERequestContext& ctx);
|
||||||
|
void GetPerformanceMode(HLERequestContext& ctx);
|
||||||
|
void GetBootMode(HLERequestContext& ctx);
|
||||||
|
void IsVrModeEnabled(HLERequestContext& ctx);
|
||||||
|
void SetVrModeEnabled(HLERequestContext& ctx);
|
||||||
|
void SetLcdBacklighOffEnabled(HLERequestContext& ctx);
|
||||||
|
void BeginVrModeEx(HLERequestContext& ctx);
|
||||||
|
void EndVrModeEx(HLERequestContext& ctx);
|
||||||
|
void GetDefaultDisplayResolution(HLERequestContext& ctx);
|
||||||
|
void SetCpuBoostMode(HLERequestContext& ctx);
|
||||||
|
void GetBuiltInDisplayType(HLERequestContext& ctx);
|
||||||
|
void PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx);
|
||||||
|
void GetAppletLaunchedHistory(HLERequestContext& ctx);
|
||||||
|
void GetSettingsPlatformRegion(HLERequestContext& ctx);
|
||||||
|
void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
const std::shared_ptr<Applet> applet;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,44 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/debug_functions.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
IDebugFunctions::IDebugFunctions(Core::System& system_)
|
||||||
|
: ServiceFramework{system_, "IDebugFunctions"} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, nullptr, "NotifyMessageToHomeMenuForDebug"},
|
||||||
|
{1, nullptr, "OpenMainApplication"},
|
||||||
|
{10, nullptr, "PerformSystemButtonPressing"},
|
||||||
|
{20, nullptr, "InvalidateTransitionLayer"},
|
||||||
|
{30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"},
|
||||||
|
{31, nullptr, "RequestLaunchApplicationByApplicationLaunchInfoForDebug"},
|
||||||
|
{40, nullptr, "GetAppletResourceUsageInfo"},
|
||||||
|
{50, nullptr, "AddSystemProgramIdAndAppletIdForDebug"},
|
||||||
|
{51, nullptr, "AddOperationConfirmedLibraryAppletIdForDebug"},
|
||||||
|
{100, nullptr, "SetCpuBoostModeForApplet"},
|
||||||
|
{101, nullptr, "CancelCpuBoostModeForApplet"},
|
||||||
|
{110, nullptr, "PushToAppletBoundChannelForDebug"},
|
||||||
|
{111, nullptr, "TryPopFromAppletBoundChannelForDebug"},
|
||||||
|
{120, nullptr, "AlarmSettingNotificationEnableAppEventReserve"},
|
||||||
|
{121, nullptr, "AlarmSettingNotificationDisableAppEventReserve"},
|
||||||
|
{122, nullptr, "AlarmSettingNotificationPushAppEventNotify"},
|
||||||
|
{130, nullptr, "FriendInvitationSetApplicationParameter"},
|
||||||
|
{131, nullptr, "FriendInvitationClearApplicationParameter"},
|
||||||
|
{132, nullptr, "FriendInvitationPushApplicationParameter"},
|
||||||
|
{140, nullptr, "RestrictPowerOperationForSecureLaunchModeForDebug"},
|
||||||
|
{200, nullptr, "CreateFloatingLibraryAppletAccepterForDebug"},
|
||||||
|
{300, nullptr, "TerminateAllRunningApplicationsForDebug"},
|
||||||
|
{900, nullptr, "GetGrcProcessLaunchedSystemEvent"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
IDebugFunctions::~IDebugFunctions() = default;
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,16 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
class IDebugFunctions final : public ServiceFramework<IDebugFunctions> {
|
||||||
|
public:
|
||||||
|
explicit IDebugFunctions(Core::System& system_);
|
||||||
|
~IDebugFunctions() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,135 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/applet.h"
|
||||||
|
#include "core/hle/service/am/display_controller.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct OutputParameters {
|
||||||
|
bool was_written;
|
||||||
|
s32 fbshare_layer_index;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(OutputParameters) == 8, "OutputParameters has wrong size");
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
IDisplayController::IDisplayController(Core::System& system_, std::shared_ptr<Applet> applet_)
|
||||||
|
: ServiceFramework{system_, "IDisplayController"}, applet(std::move(applet_)) {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, nullptr, "GetLastForegroundCaptureImage"},
|
||||||
|
{1, nullptr, "UpdateLastForegroundCaptureImage"},
|
||||||
|
{2, nullptr, "GetLastApplicationCaptureImage"},
|
||||||
|
{3, nullptr, "GetCallerAppletCaptureImage"},
|
||||||
|
{4, nullptr, "UpdateCallerAppletCaptureImage"},
|
||||||
|
{5, nullptr, "GetLastForegroundCaptureImageEx"},
|
||||||
|
{6, nullptr, "GetLastApplicationCaptureImageEx"},
|
||||||
|
{7, &IDisplayController::GetCallerAppletCaptureImageEx, "GetCallerAppletCaptureImageEx"},
|
||||||
|
{8, &IDisplayController::TakeScreenShotOfOwnLayer, "TakeScreenShotOfOwnLayer"},
|
||||||
|
{9, nullptr, "CopyBetweenCaptureBuffers"},
|
||||||
|
{10, nullptr, "AcquireLastApplicationCaptureBuffer"},
|
||||||
|
{11, nullptr, "ReleaseLastApplicationCaptureBuffer"},
|
||||||
|
{12, nullptr, "AcquireLastForegroundCaptureBuffer"},
|
||||||
|
{13, nullptr, "ReleaseLastForegroundCaptureBuffer"},
|
||||||
|
{14, nullptr, "AcquireCallerAppletCaptureBuffer"},
|
||||||
|
{15, nullptr, "ReleaseCallerAppletCaptureBuffer"},
|
||||||
|
{16, nullptr, "AcquireLastApplicationCaptureBufferEx"},
|
||||||
|
{17, nullptr, "AcquireLastForegroundCaptureBufferEx"},
|
||||||
|
{18, nullptr, "AcquireCallerAppletCaptureBufferEx"},
|
||||||
|
{20, nullptr, "ClearCaptureBuffer"},
|
||||||
|
{21, nullptr, "ClearAppletTransitionBuffer"},
|
||||||
|
{22, &IDisplayController::AcquireLastApplicationCaptureSharedBuffer, "AcquireLastApplicationCaptureSharedBuffer"},
|
||||||
|
{23, &IDisplayController::ReleaseLastApplicationCaptureSharedBuffer, "ReleaseLastApplicationCaptureSharedBuffer"},
|
||||||
|
{24, &IDisplayController::AcquireLastForegroundCaptureSharedBuffer, "AcquireLastForegroundCaptureSharedBuffer"},
|
||||||
|
{25, &IDisplayController::ReleaseLastForegroundCaptureSharedBuffer, "ReleaseLastForegroundCaptureSharedBuffer"},
|
||||||
|
{26, &IDisplayController::AcquireCallerAppletCaptureSharedBuffer, "AcquireCallerAppletCaptureSharedBuffer"},
|
||||||
|
{27, &IDisplayController::ReleaseCallerAppletCaptureSharedBuffer, "ReleaseCallerAppletCaptureSharedBuffer"},
|
||||||
|
{28, nullptr, "TakeScreenShotOfOwnLayerEx"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
IDisplayController::~IDisplayController() = default;
|
||||||
|
|
||||||
|
void IDisplayController::GetCallerAppletCaptureImageEx(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
OutputParameters params{};
|
||||||
|
const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer(
|
||||||
|
¶ms.was_written, ¶ms.fbshare_layer_index);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(res);
|
||||||
|
rb.PushRaw(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IDisplayController::AcquireLastApplicationCaptureSharedBuffer(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
OutputParameters params{};
|
||||||
|
const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer(
|
||||||
|
¶ms.was_written, ¶ms.fbshare_layer_index);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(res);
|
||||||
|
rb.PushRaw(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IDisplayController::ReleaseLastApplicationCaptureSharedBuffer(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IDisplayController::AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
OutputParameters params{};
|
||||||
|
const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer(
|
||||||
|
¶ms.was_written, ¶ms.fbshare_layer_index);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(res);
|
||||||
|
rb.PushRaw(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IDisplayController::ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IDisplayController::AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
OutputParameters params{};
|
||||||
|
const auto res = applet->system_buffer_manager.WriteAppletCaptureBuffer(
|
||||||
|
¶ms.was_written, ¶ms.fbshare_layer_index);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(res);
|
||||||
|
rb.PushRaw(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IDisplayController::ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,30 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
|
class IDisplayController final : public ServiceFramework<IDisplayController> {
|
||||||
|
public:
|
||||||
|
explicit IDisplayController(Core::System& system_, std::shared_ptr<Applet> applet_);
|
||||||
|
~IDisplayController() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void GetCallerAppletCaptureImageEx(HLERequestContext& ctx);
|
||||||
|
void TakeScreenShotOfOwnLayer(HLERequestContext& ctx);
|
||||||
|
void AcquireLastForegroundCaptureSharedBuffer(HLERequestContext& ctx);
|
||||||
|
void ReleaseLastForegroundCaptureSharedBuffer(HLERequestContext& ctx);
|
||||||
|
void AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx);
|
||||||
|
void ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx);
|
||||||
|
void AcquireLastApplicationCaptureSharedBuffer(HLERequestContext& ctx);
|
||||||
|
void ReleaseLastApplicationCaptureSharedBuffer(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
const std::shared_ptr<Applet> applet;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -8,16 +8,17 @@
|
||||||
#include "core/hle/kernel/k_event.h"
|
#include "core/hle/kernel/k_event.h"
|
||||||
#include "core/hle/kernel/k_readable_event.h"
|
#include "core/hle/kernel/k_readable_event.h"
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
#include "core/hle/service/am/applets/applet_cabinet.h"
|
#include "core/hle/service/am/frontend/applet_cabinet.h"
|
||||||
|
#include "core/hle/service/am/storage.h"
|
||||||
#include "core/hle/service/mii/mii_manager.h"
|
#include "core/hle/service/mii/mii_manager.h"
|
||||||
#include "core/hle/service/nfc/common/device.h"
|
#include "core/hle/service/nfc/common/device.h"
|
||||||
#include "hid_core/hid_core.h"
|
#include "hid_core/hid_core.h"
|
||||||
|
|
||||||
namespace Service::AM::Applets {
|
namespace Service::AM::Frontend {
|
||||||
|
|
||||||
Cabinet::Cabinet(Core::System& system_, LibraryAppletMode applet_mode_,
|
Cabinet::Cabinet(Core::System& system_, std::shared_ptr<Applet> applet_,
|
||||||
const Core::Frontend::CabinetApplet& frontend_)
|
LibraryAppletMode applet_mode_, const Core::Frontend::CabinetApplet& frontend_)
|
||||||
: Applet{system_, applet_mode_}, frontend{frontend_}, system{system_}, service_context{
|
: FrontendApplet{system_, applet_, applet_mode_}, frontend{frontend_}, service_context{
|
||||||
system_,
|
system_,
|
||||||
"CabinetApplet"} {
|
"CabinetApplet"} {
|
||||||
|
|
||||||
|
@ -30,7 +31,7 @@ Cabinet::~Cabinet() {
|
||||||
};
|
};
|
||||||
|
|
||||||
void Cabinet::Initialize() {
|
void Cabinet::Initialize() {
|
||||||
Applet::Initialize();
|
FrontendApplet::Initialize();
|
||||||
|
|
||||||
LOG_INFO(Service_HID, "Initializing Cabinet Applet.");
|
LOG_INFO(Service_HID, "Initializing Cabinet Applet.");
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ void Cabinet::Initialize() {
|
||||||
common_args.play_startup_sound, common_args.size, common_args.system_tick,
|
common_args.play_startup_sound, common_args.size, common_args.system_tick,
|
||||||
common_args.theme_color);
|
common_args.theme_color);
|
||||||
|
|
||||||
const auto storage = broker.PopNormalDataToApplet();
|
std::shared_ptr<IStorage> storage = PopInData();
|
||||||
ASSERT(storage != nullptr);
|
ASSERT(storage != nullptr);
|
||||||
|
|
||||||
const auto applet_input_data = storage->GetData();
|
const auto applet_input_data = storage->GetData();
|
||||||
|
@ -51,10 +52,6 @@ void Cabinet::Initialize() {
|
||||||
sizeof(StartParamForAmiiboSettings));
|
sizeof(StartParamForAmiiboSettings));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Cabinet::TransactionComplete() const {
|
|
||||||
return is_complete;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result Cabinet::GetStatus() const {
|
Result Cabinet::GetStatus() const {
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
@ -160,8 +157,8 @@ void Cabinet::DisplayCompleted(bool apply_changes, std::string_view amiibo_name)
|
||||||
|
|
||||||
is_complete = true;
|
is_complete = true;
|
||||||
|
|
||||||
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data)));
|
PushOutData(std::make_shared<IStorage>(system, std::move(out_data)));
|
||||||
broker.SignalStateChanged();
|
Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cabinet::Cancel() {
|
void Cabinet::Cancel() {
|
||||||
|
@ -175,8 +172,8 @@ void Cabinet::Cancel() {
|
||||||
|
|
||||||
is_complete = true;
|
is_complete = true;
|
||||||
|
|
||||||
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data)));
|
PushOutData(std::make_shared<IStorage>(system, std::move(out_data)));
|
||||||
broker.SignalStateChanged();
|
Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Cabinet::RequestExit() {
|
Result Cabinet::RequestExit() {
|
||||||
|
@ -184,4 +181,4 @@ Result Cabinet::RequestExit() {
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::AM::Applets
|
} // namespace Service::AM::Frontend
|
|
@ -6,7 +6,7 @@
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
#include "core/hle/service/am/applets/applets.h"
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
#include "core/hle/service/kernel_helpers.h"
|
#include "core/hle/service/kernel_helpers.h"
|
||||||
#include "core/hle/service/nfp/nfp_types.h"
|
#include "core/hle/service/nfp/nfp_types.h"
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ namespace Service::NFC {
|
||||||
class NfcDevice;
|
class NfcDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Service::AM::Applets {
|
namespace Service::AM::Frontend {
|
||||||
|
|
||||||
enum class CabinetAppletVersion : u32 {
|
enum class CabinetAppletVersion : u32 {
|
||||||
Version1 = 0x1,
|
Version1 = 0x1,
|
||||||
|
@ -84,15 +84,15 @@ static_assert(sizeof(ReturnValueForAmiiboSettings) == 0x188,
|
||||||
"ReturnValueForAmiiboSettings is an invalid size");
|
"ReturnValueForAmiiboSettings is an invalid size");
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
class Cabinet final : public Applet {
|
class Cabinet final : public FrontendApplet {
|
||||||
public:
|
public:
|
||||||
explicit Cabinet(Core::System& system_, LibraryAppletMode applet_mode_,
|
explicit Cabinet(Core::System& system_, std::shared_ptr<Applet> applet_,
|
||||||
|
LibraryAppletMode applet_mode_,
|
||||||
const Core::Frontend::CabinetApplet& frontend_);
|
const Core::Frontend::CabinetApplet& frontend_);
|
||||||
~Cabinet() override;
|
~Cabinet() override;
|
||||||
|
|
||||||
void Initialize() override;
|
void Initialize() override;
|
||||||
|
|
||||||
bool TransactionComplete() const override;
|
|
||||||
Result GetStatus() const override;
|
Result GetStatus() const override;
|
||||||
void ExecuteInteractive() override;
|
void ExecuteInteractive() override;
|
||||||
void Execute() override;
|
void Execute() override;
|
||||||
|
@ -102,7 +102,6 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Core::Frontend::CabinetApplet& frontend;
|
const Core::Frontend::CabinetApplet& frontend;
|
||||||
Core::System& system;
|
|
||||||
|
|
||||||
bool is_complete{false};
|
bool is_complete{false};
|
||||||
std::shared_ptr<Service::NFC::NfcDevice> nfp_device;
|
std::shared_ptr<Service::NFC::NfcDevice> nfp_device;
|
||||||
|
@ -111,4 +110,4 @@ private:
|
||||||
StartParamForAmiiboSettings applet_input_common{};
|
StartParamForAmiiboSettings applet_input_common{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM::Applets
|
} // namespace Service::AM::Frontend
|
|
@ -11,13 +11,14 @@
|
||||||
#include "core/frontend/applets/controller.h"
|
#include "core/frontend/applets/controller.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
#include "core/hle/service/am/applets/applet_controller.h"
|
#include "core/hle/service/am/frontend/applet_controller.h"
|
||||||
|
#include "core/hle/service/am/storage.h"
|
||||||
#include "hid_core/frontend/emulated_controller.h"
|
#include "hid_core/frontend/emulated_controller.h"
|
||||||
#include "hid_core/hid_core.h"
|
#include "hid_core/hid_core.h"
|
||||||
#include "hid_core/hid_types.h"
|
#include "hid_core/hid_types.h"
|
||||||
#include "hid_core/resources/npad/npad.h"
|
#include "hid_core/resources/npad/npad.h"
|
||||||
|
|
||||||
namespace Service::AM::Applets {
|
namespace Service::AM::Frontend {
|
||||||
|
|
||||||
[[maybe_unused]] constexpr Result ResultControllerSupportCanceled{ErrorModule::HID, 3101};
|
[[maybe_unused]] constexpr Result ResultControllerSupportCanceled{ErrorModule::HID, 3101};
|
||||||
[[maybe_unused]] constexpr Result ResultControllerSupportNotSupportedNpadStyle{ErrorModule::HID,
|
[[maybe_unused]] constexpr Result ResultControllerSupportNotSupportedNpadStyle{ErrorModule::HID,
|
||||||
|
@ -46,14 +47,15 @@ static Core::Frontend::ControllerParameters ConvertToFrontendParameters(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller::Controller(Core::System& system_, LibraryAppletMode applet_mode_,
|
Controller::Controller(Core::System& system_, std::shared_ptr<Applet> applet_,
|
||||||
|
LibraryAppletMode applet_mode_,
|
||||||
const Core::Frontend::ControllerApplet& frontend_)
|
const Core::Frontend::ControllerApplet& frontend_)
|
||||||
: Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {}
|
: FrontendApplet{system_, applet_, applet_mode_}, frontend{frontend_} {}
|
||||||
|
|
||||||
Controller::~Controller() = default;
|
Controller::~Controller() = default;
|
||||||
|
|
||||||
void Controller::Initialize() {
|
void Controller::Initialize() {
|
||||||
Applet::Initialize();
|
FrontendApplet::Initialize();
|
||||||
|
|
||||||
LOG_INFO(Service_HID, "Initializing Controller Applet.");
|
LOG_INFO(Service_HID, "Initializing Controller Applet.");
|
||||||
|
|
||||||
|
@ -66,7 +68,7 @@ void Controller::Initialize() {
|
||||||
|
|
||||||
controller_applet_version = ControllerAppletVersion{common_args.library_version};
|
controller_applet_version = ControllerAppletVersion{common_args.library_version};
|
||||||
|
|
||||||
const auto private_arg_storage = broker.PopNormalDataToApplet();
|
const std::shared_ptr<IStorage> private_arg_storage = PopInData();
|
||||||
ASSERT(private_arg_storage != nullptr);
|
ASSERT(private_arg_storage != nullptr);
|
||||||
|
|
||||||
const auto& private_arg = private_arg_storage->GetData();
|
const auto& private_arg = private_arg_storage->GetData();
|
||||||
|
@ -116,7 +118,7 @@ void Controller::Initialize() {
|
||||||
switch (controller_private_arg.mode) {
|
switch (controller_private_arg.mode) {
|
||||||
case ControllerSupportMode::ShowControllerSupport:
|
case ControllerSupportMode::ShowControllerSupport:
|
||||||
case ControllerSupportMode::ShowControllerStrapGuide: {
|
case ControllerSupportMode::ShowControllerStrapGuide: {
|
||||||
const auto user_arg_storage = broker.PopNormalDataToApplet();
|
const std::shared_ptr<IStorage> user_arg_storage = PopInData();
|
||||||
ASSERT(user_arg_storage != nullptr);
|
ASSERT(user_arg_storage != nullptr);
|
||||||
|
|
||||||
const auto& user_arg = user_arg_storage->GetData();
|
const auto& user_arg = user_arg_storage->GetData();
|
||||||
|
@ -142,7 +144,7 @@ void Controller::Initialize() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ControllerSupportMode::ShowControllerFirmwareUpdate: {
|
case ControllerSupportMode::ShowControllerFirmwareUpdate: {
|
||||||
const auto update_arg_storage = broker.PopNormalDataToApplet();
|
const std::shared_ptr<IStorage> update_arg_storage = PopInData();
|
||||||
ASSERT(update_arg_storage != nullptr);
|
ASSERT(update_arg_storage != nullptr);
|
||||||
|
|
||||||
const auto& update_arg = update_arg_storage->GetData();
|
const auto& update_arg = update_arg_storage->GetData();
|
||||||
|
@ -152,7 +154,7 @@ void Controller::Initialize() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ControllerSupportMode::ShowControllerKeyRemappingForSystem: {
|
case ControllerSupportMode::ShowControllerKeyRemappingForSystem: {
|
||||||
const auto remapping_arg_storage = broker.PopNormalDataToApplet();
|
const std::shared_ptr<IStorage> remapping_arg_storage = PopInData();
|
||||||
ASSERT(remapping_arg_storage != nullptr);
|
ASSERT(remapping_arg_storage != nullptr);
|
||||||
|
|
||||||
const auto& remapping_arg = remapping_arg_storage->GetData();
|
const auto& remapping_arg = remapping_arg_storage->GetData();
|
||||||
|
@ -168,10 +170,6 @@ void Controller::Initialize() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Controller::TransactionComplete() const {
|
|
||||||
return complete;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result Controller::GetStatus() const {
|
Result Controller::GetStatus() const {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -260,8 +258,9 @@ void Controller::ConfigurationComplete(bool is_success) {
|
||||||
complete = true;
|
complete = true;
|
||||||
out_data = std::vector<u8>(sizeof(ControllerSupportResultInfo));
|
out_data = std::vector<u8>(sizeof(ControllerSupportResultInfo));
|
||||||
std::memcpy(out_data.data(), &result_info, out_data.size());
|
std::memcpy(out_data.data(), &result_info, out_data.size());
|
||||||
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data)));
|
|
||||||
broker.SignalStateChanged();
|
PushOutData(std::make_shared<IStorage>(system, std::move(out_data)));
|
||||||
|
Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Controller::RequestExit() {
|
Result Controller::RequestExit() {
|
||||||
|
@ -269,4 +268,4 @@ Result Controller::RequestExit() {
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::AM::Applets
|
} // namespace Service::AM::Frontend
|
|
@ -9,7 +9,7 @@
|
||||||
#include "common/common_funcs.h"
|
#include "common/common_funcs.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
#include "core/hle/service/am/applets/applets.h"
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class System;
|
class System;
|
||||||
|
@ -19,7 +19,7 @@ namespace Core::HID {
|
||||||
enum class NpadStyleSet : u32;
|
enum class NpadStyleSet : u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Service::AM::Applets {
|
namespace Service::AM::Frontend {
|
||||||
|
|
||||||
using IdentificationColor = std::array<u8, 4>;
|
using IdentificationColor = std::array<u8, 4>;
|
||||||
using ExplainText = std::array<char, 0x81>;
|
using ExplainText = std::array<char, 0x81>;
|
||||||
|
@ -122,15 +122,15 @@ struct ControllerSupportResultInfo {
|
||||||
static_assert(sizeof(ControllerSupportResultInfo) == 0xC,
|
static_assert(sizeof(ControllerSupportResultInfo) == 0xC,
|
||||||
"ControllerSupportResultInfo has incorrect size.");
|
"ControllerSupportResultInfo has incorrect size.");
|
||||||
|
|
||||||
class Controller final : public Applet {
|
class Controller final : public FrontendApplet {
|
||||||
public:
|
public:
|
||||||
explicit Controller(Core::System& system_, LibraryAppletMode applet_mode_,
|
explicit Controller(Core::System& system_, std::shared_ptr<Applet> applet_,
|
||||||
|
LibraryAppletMode applet_mode_,
|
||||||
const Core::Frontend::ControllerApplet& frontend_);
|
const Core::Frontend::ControllerApplet& frontend_);
|
||||||
~Controller() override;
|
~Controller() override;
|
||||||
|
|
||||||
void Initialize() override;
|
void Initialize() override;
|
||||||
|
|
||||||
bool TransactionComplete() const override;
|
|
||||||
Result GetStatus() const override;
|
Result GetStatus() const override;
|
||||||
void ExecuteInteractive() override;
|
void ExecuteInteractive() override;
|
||||||
void Execute() override;
|
void Execute() override;
|
||||||
|
@ -140,7 +140,6 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Core::Frontend::ControllerApplet& frontend;
|
const Core::Frontend::ControllerApplet& frontend;
|
||||||
Core::System& system;
|
|
||||||
|
|
||||||
ControllerAppletVersion controller_applet_version;
|
ControllerAppletVersion controller_applet_version;
|
||||||
ControllerSupportArgPrivate controller_private_arg;
|
ControllerSupportArgPrivate controller_private_arg;
|
||||||
|
@ -154,4 +153,4 @@ private:
|
||||||
std::vector<u8> out_data;
|
std::vector<u8> out_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM::Applets
|
} // namespace Service::AM::Frontend
|
|
@ -9,10 +9,11 @@
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/frontend/applets/error.h"
|
#include "core/frontend/applets/error.h"
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
#include "core/hle/service/am/applets/applet_error.h"
|
#include "core/hle/service/am/frontend/applet_error.h"
|
||||||
|
#include "core/hle/service/am/storage.h"
|
||||||
#include "core/reporter.h"
|
#include "core/reporter.h"
|
||||||
|
|
||||||
namespace Service::AM::Applets {
|
namespace Service::AM::Frontend {
|
||||||
|
|
||||||
struct ErrorCode {
|
struct ErrorCode {
|
||||||
u32 error_category{};
|
u32 error_category{};
|
||||||
|
@ -103,18 +104,18 @@ Result Decode64BitError(u64 error) {
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
Error::Error(Core::System& system_, LibraryAppletMode applet_mode_,
|
Error::Error(Core::System& system_, std::shared_ptr<Applet> applet_, LibraryAppletMode applet_mode_,
|
||||||
const Core::Frontend::ErrorApplet& frontend_)
|
const Core::Frontend::ErrorApplet& frontend_)
|
||||||
: Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {}
|
: FrontendApplet{system_, applet_, applet_mode_}, frontend{frontend_} {}
|
||||||
|
|
||||||
Error::~Error() = default;
|
Error::~Error() = default;
|
||||||
|
|
||||||
void Error::Initialize() {
|
void Error::Initialize() {
|
||||||
Applet::Initialize();
|
FrontendApplet::Initialize();
|
||||||
args = std::make_unique<ErrorArguments>();
|
args = std::make_unique<ErrorArguments>();
|
||||||
complete = false;
|
complete = false;
|
||||||
|
|
||||||
const auto storage = broker.PopNormalDataToApplet();
|
const std::shared_ptr<IStorage> storage = PopInData();
|
||||||
ASSERT(storage != nullptr);
|
ASSERT(storage != nullptr);
|
||||||
const auto data = storage->GetData();
|
const auto data = storage->GetData();
|
||||||
|
|
||||||
|
@ -152,10 +153,6 @@ void Error::Initialize() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Error::TransactionComplete() const {
|
|
||||||
return complete;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result Error::GetStatus() const {
|
Result Error::GetStatus() const {
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
@ -210,8 +207,8 @@ void Error::Execute() {
|
||||||
|
|
||||||
void Error::DisplayCompleted() {
|
void Error::DisplayCompleted() {
|
||||||
complete = true;
|
complete = true;
|
||||||
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::vector<u8>{}));
|
PushOutData(std::make_shared<IStorage>(system, std::vector<u8>(0x1000)));
|
||||||
broker.SignalStateChanged();
|
Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Error::RequestExit() {
|
Result Error::RequestExit() {
|
||||||
|
@ -219,4 +216,4 @@ Result Error::RequestExit() {
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::AM::Applets
|
} // namespace Service::AM::Frontend
|
|
@ -4,13 +4,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
#include "core/hle/service/am/applets/applets.h"
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class System;
|
class System;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Service::AM::Applets {
|
namespace Service::AM::Frontend {
|
||||||
|
|
||||||
enum class ErrorAppletMode : u8 {
|
enum class ErrorAppletMode : u8 {
|
||||||
ShowError = 0,
|
ShowError = 0,
|
||||||
|
@ -22,15 +22,14 @@ enum class ErrorAppletMode : u8 {
|
||||||
ShowUpdateEula = 8,
|
ShowUpdateEula = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
class Error final : public Applet {
|
class Error final : public FrontendApplet {
|
||||||
public:
|
public:
|
||||||
explicit Error(Core::System& system_, LibraryAppletMode applet_mode_,
|
explicit Error(Core::System& system_, std::shared_ptr<Applet> applet_,
|
||||||
const Core::Frontend::ErrorApplet& frontend_);
|
LibraryAppletMode applet_mode_, const Core::Frontend::ErrorApplet& frontend_);
|
||||||
~Error() override;
|
~Error() override;
|
||||||
|
|
||||||
void Initialize() override;
|
void Initialize() override;
|
||||||
|
|
||||||
bool TransactionComplete() const override;
|
|
||||||
Result GetStatus() const override;
|
Result GetStatus() const override;
|
||||||
void ExecuteInteractive() override;
|
void ExecuteInteractive() override;
|
||||||
void Execute() override;
|
void Execute() override;
|
||||||
|
@ -47,7 +46,6 @@ private:
|
||||||
std::unique_ptr<ErrorArguments> args;
|
std::unique_ptr<ErrorArguments> args;
|
||||||
|
|
||||||
bool complete = false;
|
bool complete = false;
|
||||||
Core::System& system;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM::Applets
|
} // namespace Service::AM::Frontend
|
|
@ -5,27 +5,28 @@
|
||||||
#include "common/hex_util.h"
|
#include "common/hex_util.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/frontend/applets/general_frontend.h"
|
#include "core/frontend/applets/general.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
#include "core/hle/service/am/applets/applet_general_backend.h"
|
#include "core/hle/service/am/applet_data_broker.h"
|
||||||
|
#include "core/hle/service/am/frontend/applet_general.h"
|
||||||
|
#include "core/hle/service/am/storage.h"
|
||||||
#include "core/reporter.h"
|
#include "core/reporter.h"
|
||||||
|
|
||||||
namespace Service::AM::Applets {
|
namespace Service::AM::Frontend {
|
||||||
|
|
||||||
constexpr Result ERROR_INVALID_PIN{ErrorModule::PCTL, 221};
|
constexpr Result ERROR_INVALID_PIN{ErrorModule::PCTL, 221};
|
||||||
|
|
||||||
static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix) {
|
static void LogCurrentStorage(std::shared_ptr<Applet> applet, std::string_view prefix) {
|
||||||
std::shared_ptr<IStorage> storage = broker.PopNormalDataToApplet();
|
std::shared_ptr<IStorage> storage;
|
||||||
for (; storage != nullptr; storage = broker.PopNormalDataToApplet()) {
|
while (R_SUCCEEDED(applet->caller_applet_broker->GetInData().Pop(&storage))) {
|
||||||
const auto data = storage->GetData();
|
const auto data = storage->GetData();
|
||||||
LOG_INFO(Service_AM,
|
LOG_INFO(Service_AM,
|
||||||
"called (STUBBED), during {} received normal data with size={:08X}, data={}",
|
"called (STUBBED), during {} received normal data with size={:08X}, data={}",
|
||||||
prefix, data.size(), Common::HexToString(data));
|
prefix, data.size(), Common::HexToString(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
storage = broker.PopInteractiveDataToApplet();
|
while (R_SUCCEEDED(applet->caller_applet_broker->GetInteractiveInData().Pop(&storage))) {
|
||||||
for (; storage != nullptr; storage = broker.PopInteractiveDataToApplet()) {
|
|
||||||
const auto data = storage->GetData();
|
const auto data = storage->GetData();
|
||||||
LOG_INFO(Service_AM,
|
LOG_INFO(Service_AM,
|
||||||
"called (STUBBED), during {} received interactive data with size={:08X}, data={}",
|
"called (STUBBED), during {} received interactive data with size={:08X}, data={}",
|
||||||
|
@ -33,17 +34,17 @@ static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Auth::Auth(Core::System& system_, LibraryAppletMode applet_mode_,
|
Auth::Auth(Core::System& system_, std::shared_ptr<Applet> applet_, LibraryAppletMode applet_mode_,
|
||||||
Core::Frontend::ParentalControlsApplet& frontend_)
|
Core::Frontend::ParentalControlsApplet& frontend_)
|
||||||
: Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {}
|
: FrontendApplet{system_, applet_, applet_mode_}, frontend{frontend_} {}
|
||||||
|
|
||||||
Auth::~Auth() = default;
|
Auth::~Auth() = default;
|
||||||
|
|
||||||
void Auth::Initialize() {
|
void Auth::Initialize() {
|
||||||
Applet::Initialize();
|
FrontendApplet::Initialize();
|
||||||
complete = false;
|
complete = false;
|
||||||
|
|
||||||
const auto storage = broker.PopNormalDataToApplet();
|
const std::shared_ptr<IStorage> storage = PopInData();
|
||||||
ASSERT(storage != nullptr);
|
ASSERT(storage != nullptr);
|
||||||
const auto data = storage->GetData();
|
const auto data = storage->GetData();
|
||||||
ASSERT(data.size() >= 0xC);
|
ASSERT(data.size() >= 0xC);
|
||||||
|
@ -67,10 +68,6 @@ void Auth::Initialize() {
|
||||||
arg2 = arg.arg2;
|
arg2 = arg.arg2;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Auth::TransactionComplete() const {
|
|
||||||
return complete;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result Auth::GetStatus() const {
|
Result Auth::GetStatus() const {
|
||||||
return successful ? ResultSuccess : ERROR_INVALID_PIN;
|
return successful ? ResultSuccess : ERROR_INVALID_PIN;
|
||||||
}
|
}
|
||||||
|
@ -146,8 +143,8 @@ void Auth::AuthFinished(bool is_successful) {
|
||||||
std::vector<u8> out(sizeof(Return));
|
std::vector<u8> out(sizeof(Return));
|
||||||
std::memcpy(out.data(), &return_, sizeof(Return));
|
std::memcpy(out.data(), &return_, sizeof(Return));
|
||||||
|
|
||||||
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out)));
|
PushOutData(std::make_shared<IStorage>(system, std::move(out)));
|
||||||
broker.SignalStateChanged();
|
Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Auth::RequestExit() {
|
Result Auth::RequestExit() {
|
||||||
|
@ -155,27 +152,24 @@ Result Auth::RequestExit() {
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
PhotoViewer::PhotoViewer(Core::System& system_, LibraryAppletMode applet_mode_,
|
PhotoViewer::PhotoViewer(Core::System& system_, std::shared_ptr<Applet> applet_,
|
||||||
|
LibraryAppletMode applet_mode_,
|
||||||
const Core::Frontend::PhotoViewerApplet& frontend_)
|
const Core::Frontend::PhotoViewerApplet& frontend_)
|
||||||
: Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {}
|
: FrontendApplet{system_, applet_, applet_mode_}, frontend{frontend_} {}
|
||||||
|
|
||||||
PhotoViewer::~PhotoViewer() = default;
|
PhotoViewer::~PhotoViewer() = default;
|
||||||
|
|
||||||
void PhotoViewer::Initialize() {
|
void PhotoViewer::Initialize() {
|
||||||
Applet::Initialize();
|
FrontendApplet::Initialize();
|
||||||
complete = false;
|
complete = false;
|
||||||
|
|
||||||
const auto storage = broker.PopNormalDataToApplet();
|
const std::shared_ptr<IStorage> storage = PopInData();
|
||||||
ASSERT(storage != nullptr);
|
ASSERT(storage != nullptr);
|
||||||
const auto data = storage->GetData();
|
const auto data = storage->GetData();
|
||||||
ASSERT(!data.empty());
|
ASSERT(!data.empty());
|
||||||
mode = static_cast<PhotoViewerAppletMode>(data[0]);
|
mode = static_cast<PhotoViewerAppletMode>(data[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PhotoViewer::TransactionComplete() const {
|
|
||||||
return complete;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result PhotoViewer::GetStatus() const {
|
Result PhotoViewer::GetStatus() const {
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
@ -203,8 +197,8 @@ void PhotoViewer::Execute() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhotoViewer::ViewFinished() {
|
void PhotoViewer::ViewFinished() {
|
||||||
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::vector<u8>{}));
|
PushOutData(std::make_shared<IStorage>(system, std::vector<u8>{}));
|
||||||
broker.SignalStateChanged();
|
Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result PhotoViewer::RequestExit() {
|
Result PhotoViewer::RequestExit() {
|
||||||
|
@ -212,27 +206,17 @@ Result PhotoViewer::RequestExit() {
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
StubApplet::StubApplet(Core::System& system_, AppletId id_, LibraryAppletMode applet_mode_)
|
StubApplet::StubApplet(Core::System& system_, std::shared_ptr<Applet> applet_, AppletId id_,
|
||||||
: Applet{system_, applet_mode_}, id{id_}, system{system_} {}
|
LibraryAppletMode applet_mode_)
|
||||||
|
: FrontendApplet{system_, applet_, applet_mode_}, id{id_} {}
|
||||||
|
|
||||||
StubApplet::~StubApplet() = default;
|
StubApplet::~StubApplet() = default;
|
||||||
|
|
||||||
void StubApplet::Initialize() {
|
void StubApplet::Initialize() {
|
||||||
LOG_WARNING(Service_AM, "called (STUBBED)");
|
LOG_WARNING(Service_AM, "called (STUBBED)");
|
||||||
Applet::Initialize();
|
FrontendApplet::Initialize();
|
||||||
|
|
||||||
const auto data = broker.PeekDataToAppletForDebug();
|
LogCurrentStorage(applet.lock(), "Initialize");
|
||||||
system.GetReporter().SaveUnimplementedAppletReport(
|
|
||||||
static_cast<u32>(id), static_cast<u32>(common_args.arguments_version),
|
|
||||||
common_args.library_version, static_cast<u32>(common_args.theme_color),
|
|
||||||
common_args.play_startup_sound, common_args.system_tick, data.normal, data.interactive);
|
|
||||||
|
|
||||||
LogCurrentStorage(broker, "Initialize");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool StubApplet::TransactionComplete() const {
|
|
||||||
LOG_WARNING(Service_AM, "called (STUBBED)");
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result StubApplet::GetStatus() const {
|
Result StubApplet::GetStatus() const {
|
||||||
|
@ -242,22 +226,20 @@ Result StubApplet::GetStatus() const {
|
||||||
|
|
||||||
void StubApplet::ExecuteInteractive() {
|
void StubApplet::ExecuteInteractive() {
|
||||||
LOG_WARNING(Service_AM, "called (STUBBED)");
|
LOG_WARNING(Service_AM, "called (STUBBED)");
|
||||||
LogCurrentStorage(broker, "ExecuteInteractive");
|
LogCurrentStorage(applet.lock(), "ExecuteInteractive");
|
||||||
|
|
||||||
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::vector<u8>(0x1000)));
|
PushOutData(std::make_shared<IStorage>(system, std::vector<u8>(0x1000)));
|
||||||
broker.PushInteractiveDataFromApplet(
|
PushInteractiveOutData(std::make_shared<IStorage>(system, std::vector<u8>(0x1000)));
|
||||||
std::make_shared<IStorage>(system, std::vector<u8>(0x1000)));
|
Exit();
|
||||||
broker.SignalStateChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StubApplet::Execute() {
|
void StubApplet::Execute() {
|
||||||
LOG_WARNING(Service_AM, "called (STUBBED)");
|
LOG_WARNING(Service_AM, "called (STUBBED)");
|
||||||
LogCurrentStorage(broker, "Execute");
|
LogCurrentStorage(applet.lock(), "Execute");
|
||||||
|
|
||||||
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::vector<u8>(0x1000)));
|
PushOutData(std::make_shared<IStorage>(system, std::vector<u8>(0x1000)));
|
||||||
broker.PushInteractiveDataFromApplet(
|
PushInteractiveOutData(std::make_shared<IStorage>(system, std::vector<u8>(0x1000)));
|
||||||
std::make_shared<IStorage>(system, std::vector<u8>(0x1000)));
|
Exit();
|
||||||
broker.SignalStateChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result StubApplet::RequestExit() {
|
Result StubApplet::RequestExit() {
|
||||||
|
@ -265,4 +247,4 @@ Result StubApplet::RequestExit() {
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::AM::Applets
|
} // namespace Service::AM::Frontend
|
|
@ -3,13 +3,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/hle/service/am/applets/applets.h"
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class System;
|
class System;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Service::AM::Applets {
|
namespace Service::AM::Frontend {
|
||||||
|
|
||||||
enum class AuthAppletType : u32 {
|
enum class AuthAppletType : u32 {
|
||||||
ShowParentalAuthentication,
|
ShowParentalAuthentication,
|
||||||
|
@ -17,14 +17,14 @@ enum class AuthAppletType : u32 {
|
||||||
ChangeParentalPasscode,
|
ChangeParentalPasscode,
|
||||||
};
|
};
|
||||||
|
|
||||||
class Auth final : public Applet {
|
class Auth final : public FrontendApplet {
|
||||||
public:
|
public:
|
||||||
explicit Auth(Core::System& system_, LibraryAppletMode applet_mode_,
|
explicit Auth(Core::System& system_, std::shared_ptr<Applet> applet_,
|
||||||
|
LibraryAppletMode applet_mode_,
|
||||||
Core::Frontend::ParentalControlsApplet& frontend_);
|
Core::Frontend::ParentalControlsApplet& frontend_);
|
||||||
~Auth() override;
|
~Auth() override;
|
||||||
|
|
||||||
void Initialize() override;
|
void Initialize() override;
|
||||||
bool TransactionComplete() const override;
|
|
||||||
Result GetStatus() const override;
|
Result GetStatus() const override;
|
||||||
void ExecuteInteractive() override;
|
void ExecuteInteractive() override;
|
||||||
void Execute() override;
|
void Execute() override;
|
||||||
|
@ -34,7 +34,6 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Core::Frontend::ParentalControlsApplet& frontend;
|
Core::Frontend::ParentalControlsApplet& frontend;
|
||||||
Core::System& system;
|
|
||||||
bool complete = false;
|
bool complete = false;
|
||||||
bool successful = false;
|
bool successful = false;
|
||||||
|
|
||||||
|
@ -49,14 +48,14 @@ enum class PhotoViewerAppletMode : u8 {
|
||||||
AllApps = 1,
|
AllApps = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
class PhotoViewer final : public Applet {
|
class PhotoViewer final : public FrontendApplet {
|
||||||
public:
|
public:
|
||||||
explicit PhotoViewer(Core::System& system_, LibraryAppletMode applet_mode_,
|
explicit PhotoViewer(Core::System& system_, std::shared_ptr<Applet> applet_,
|
||||||
|
LibraryAppletMode applet_mode_,
|
||||||
const Core::Frontend::PhotoViewerApplet& frontend_);
|
const Core::Frontend::PhotoViewerApplet& frontend_);
|
||||||
~PhotoViewer() override;
|
~PhotoViewer() override;
|
||||||
|
|
||||||
void Initialize() override;
|
void Initialize() override;
|
||||||
bool TransactionComplete() const override;
|
|
||||||
Result GetStatus() const override;
|
Result GetStatus() const override;
|
||||||
void ExecuteInteractive() override;
|
void ExecuteInteractive() override;
|
||||||
void Execute() override;
|
void Execute() override;
|
||||||
|
@ -68,17 +67,16 @@ private:
|
||||||
const Core::Frontend::PhotoViewerApplet& frontend;
|
const Core::Frontend::PhotoViewerApplet& frontend;
|
||||||
bool complete = false;
|
bool complete = false;
|
||||||
PhotoViewerAppletMode mode = PhotoViewerAppletMode::CurrentApp;
|
PhotoViewerAppletMode mode = PhotoViewerAppletMode::CurrentApp;
|
||||||
Core::System& system;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class StubApplet final : public Applet {
|
class StubApplet final : public FrontendApplet {
|
||||||
public:
|
public:
|
||||||
explicit StubApplet(Core::System& system_, AppletId id_, LibraryAppletMode applet_mode_);
|
explicit StubApplet(Core::System& system_, std::shared_ptr<Applet> applet_, AppletId id_,
|
||||||
|
LibraryAppletMode applet_mode_);
|
||||||
~StubApplet() override;
|
~StubApplet() override;
|
||||||
|
|
||||||
void Initialize() override;
|
void Initialize() override;
|
||||||
|
|
||||||
bool TransactionComplete() const override;
|
|
||||||
Result GetStatus() const override;
|
Result GetStatus() const override;
|
||||||
void ExecuteInteractive() override;
|
void ExecuteInteractive() override;
|
||||||
void Execute() override;
|
void Execute() override;
|
||||||
|
@ -86,7 +84,6 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AppletId id;
|
AppletId id;
|
||||||
Core::System& system;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM::Applets
|
} // namespace Service::AM::Frontend
|
|
@ -6,16 +6,17 @@
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/frontend/applets/mii_edit.h"
|
#include "core/frontend/applets/mii_edit.h"
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
#include "core/hle/service/am/applets/applet_mii_edit.h"
|
#include "core/hle/service/am/frontend/applet_mii_edit.h"
|
||||||
|
#include "core/hle/service/am/storage.h"
|
||||||
#include "core/hle/service/mii/mii.h"
|
#include "core/hle/service/mii/mii.h"
|
||||||
#include "core/hle/service/mii/mii_manager.h"
|
#include "core/hle/service/mii/mii_manager.h"
|
||||||
#include "core/hle/service/sm/sm.h"
|
#include "core/hle/service/sm/sm.h"
|
||||||
|
|
||||||
namespace Service::AM::Applets {
|
namespace Service::AM::Frontend {
|
||||||
|
|
||||||
MiiEdit::MiiEdit(Core::System& system_, LibraryAppletMode applet_mode_,
|
MiiEdit::MiiEdit(Core::System& system_, std::shared_ptr<Applet> applet_,
|
||||||
const Core::Frontend::MiiEditApplet& frontend_)
|
LibraryAppletMode applet_mode_, const Core::Frontend::MiiEditApplet& frontend_)
|
||||||
: Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {}
|
: FrontendApplet{system_, applet_, applet_mode_}, frontend{frontend_} {}
|
||||||
|
|
||||||
MiiEdit::~MiiEdit() = default;
|
MiiEdit::~MiiEdit() = default;
|
||||||
|
|
||||||
|
@ -24,7 +25,7 @@ void MiiEdit::Initialize() {
|
||||||
// Instead, it is initialized by an AppletInput storage with size 0x100 bytes.
|
// Instead, it is initialized by an AppletInput storage with size 0x100 bytes.
|
||||||
// Do NOT call Applet::Initialize() here.
|
// Do NOT call Applet::Initialize() here.
|
||||||
|
|
||||||
const auto storage = broker.PopNormalDataToApplet();
|
const std::shared_ptr<IStorage> storage = PopInData();
|
||||||
ASSERT(storage != nullptr);
|
ASSERT(storage != nullptr);
|
||||||
|
|
||||||
const auto applet_input_data = storage->GetData();
|
const auto applet_input_data = storage->GetData();
|
||||||
|
@ -66,10 +67,6 @@ void MiiEdit::Initialize() {
|
||||||
manager->Initialize(metadata);
|
manager->Initialize(metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MiiEdit::TransactionComplete() const {
|
|
||||||
return is_complete;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result MiiEdit::GetStatus() const {
|
Result MiiEdit::GetStatus() const {
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
@ -152,8 +149,8 @@ void MiiEdit::MiiEditOutput(MiiEditResult result, s32 index) {
|
||||||
|
|
||||||
is_complete = true;
|
is_complete = true;
|
||||||
|
|
||||||
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data)));
|
PushOutData(std::make_shared<IStorage>(system, std::move(out_data)));
|
||||||
broker.SignalStateChanged();
|
Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MiiEdit::MiiEditOutputForCharInfoEditing(MiiEditResult result,
|
void MiiEdit::MiiEditOutputForCharInfoEditing(MiiEditResult result,
|
||||||
|
@ -168,8 +165,8 @@ void MiiEdit::MiiEditOutputForCharInfoEditing(MiiEditResult result,
|
||||||
|
|
||||||
is_complete = true;
|
is_complete = true;
|
||||||
|
|
||||||
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data)));
|
PushOutData(std::make_shared<IStorage>(system, std::move(out_data)));
|
||||||
broker.SignalStateChanged();
|
Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MiiEdit::RequestExit() {
|
Result MiiEdit::RequestExit() {
|
||||||
|
@ -177,4 +174,4 @@ Result MiiEdit::RequestExit() {
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::AM::Applets
|
} // namespace Service::AM::Frontend
|
|
@ -4,8 +4,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
#include "core/hle/service/am/applets/applet_mii_edit_types.h"
|
#include "core/hle/service/am/frontend/applet_mii_edit_types.h"
|
||||||
#include "core/hle/service/am/applets/applets.h"
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class System;
|
class System;
|
||||||
|
@ -16,17 +16,17 @@ struct DatabaseSessionMetadata;
|
||||||
class MiiManager;
|
class MiiManager;
|
||||||
} // namespace Service::Mii
|
} // namespace Service::Mii
|
||||||
|
|
||||||
namespace Service::AM::Applets {
|
namespace Service::AM::Frontend {
|
||||||
|
|
||||||
class MiiEdit final : public Applet {
|
class MiiEdit final : public FrontendApplet {
|
||||||
public:
|
public:
|
||||||
explicit MiiEdit(Core::System& system_, LibraryAppletMode applet_mode_,
|
explicit MiiEdit(Core::System& system_, std::shared_ptr<Applet> applet_,
|
||||||
|
LibraryAppletMode applet_mode_,
|
||||||
const Core::Frontend::MiiEditApplet& frontend_);
|
const Core::Frontend::MiiEditApplet& frontend_);
|
||||||
~MiiEdit() override;
|
~MiiEdit() override;
|
||||||
|
|
||||||
void Initialize() override;
|
void Initialize() override;
|
||||||
|
|
||||||
bool TransactionComplete() const override;
|
|
||||||
Result GetStatus() const override;
|
Result GetStatus() const override;
|
||||||
void ExecuteInteractive() override;
|
void ExecuteInteractive() override;
|
||||||
void Execute() override;
|
void Execute() override;
|
||||||
|
@ -38,7 +38,6 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Core::Frontend::MiiEditApplet& frontend;
|
const Core::Frontend::MiiEditApplet& frontend;
|
||||||
Core::System& system;
|
|
||||||
|
|
||||||
MiiEditAppletInputCommon applet_input_common{};
|
MiiEditAppletInputCommon applet_input_common{};
|
||||||
MiiEditAppletInputV3 applet_input_v3{};
|
MiiEditAppletInputV3 applet_input_v3{};
|
||||||
|
@ -49,4 +48,4 @@ private:
|
||||||
Mii::DatabaseSessionMetadata metadata{};
|
Mii::DatabaseSessionMetadata metadata{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM::Applets
|
} // namespace Service::AM::Frontend
|
|
@ -10,7 +10,7 @@
|
||||||
#include "common/uuid.h"
|
#include "common/uuid.h"
|
||||||
#include "core/hle/service/mii/types/char_info.h"
|
#include "core/hle/service/mii/types/char_info.h"
|
||||||
|
|
||||||
namespace Service::AM::Applets {
|
namespace Service::AM::Frontend {
|
||||||
|
|
||||||
enum class MiiEditAppletVersion : s32 {
|
enum class MiiEditAppletVersion : s32 {
|
||||||
Version3 = 0x3, // 1.0.0 - 10.1.1
|
Version3 = 0x3, // 1.0.0 - 10.1.1
|
||||||
|
@ -80,4 +80,4 @@ struct MiiEditAppletOutputForCharInfoEditing {
|
||||||
static_assert(sizeof(MiiEditAppletOutputForCharInfoEditing) == 0x80,
|
static_assert(sizeof(MiiEditAppletOutputForCharInfoEditing) == 0x80,
|
||||||
"MiiEditAppletOutputForCharInfoEditing has incorrect size.");
|
"MiiEditAppletOutputForCharInfoEditing has incorrect size.");
|
||||||
|
|
||||||
} // namespace Service::AM::Applets
|
} // namespace Service::AM::Frontend
|
|
@ -9,13 +9,15 @@
|
||||||
#include "core/frontend/applets/profile_select.h"
|
#include "core/frontend/applets/profile_select.h"
|
||||||
#include "core/hle/service/acc/errors.h"
|
#include "core/hle/service/acc/errors.h"
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
#include "core/hle/service/am/applets/applet_profile_select.h"
|
#include "core/hle/service/am/frontend/applet_profile_select.h"
|
||||||
|
#include "core/hle/service/am/storage.h"
|
||||||
|
|
||||||
namespace Service::AM::Applets {
|
namespace Service::AM::Frontend {
|
||||||
|
|
||||||
ProfileSelect::ProfileSelect(Core::System& system_, LibraryAppletMode applet_mode_,
|
ProfileSelect::ProfileSelect(Core::System& system_, std::shared_ptr<Applet> applet_,
|
||||||
|
LibraryAppletMode applet_mode_,
|
||||||
const Core::Frontend::ProfileSelectApplet& frontend_)
|
const Core::Frontend::ProfileSelectApplet& frontend_)
|
||||||
: Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {}
|
: FrontendApplet{system_, applet_, applet_mode_}, frontend{frontend_} {}
|
||||||
|
|
||||||
ProfileSelect::~ProfileSelect() = default;
|
ProfileSelect::~ProfileSelect() = default;
|
||||||
|
|
||||||
|
@ -24,10 +26,10 @@ void ProfileSelect::Initialize() {
|
||||||
status = ResultSuccess;
|
status = ResultSuccess;
|
||||||
final_data.clear();
|
final_data.clear();
|
||||||
|
|
||||||
Applet::Initialize();
|
FrontendApplet::Initialize();
|
||||||
profile_select_version = ProfileSelectAppletVersion{common_args.library_version};
|
profile_select_version = ProfileSelectAppletVersion{common_args.library_version};
|
||||||
|
|
||||||
const auto user_config_storage = broker.PopNormalDataToApplet();
|
const std::shared_ptr<IStorage> user_config_storage = PopInData();
|
||||||
ASSERT(user_config_storage != nullptr);
|
ASSERT(user_config_storage != nullptr);
|
||||||
const auto& user_config = user_config_storage->GetData();
|
const auto& user_config = user_config_storage->GetData();
|
||||||
|
|
||||||
|
@ -50,10 +52,6 @@ void ProfileSelect::Initialize() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProfileSelect::TransactionComplete() const {
|
|
||||||
return complete;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result ProfileSelect::GetStatus() const {
|
Result ProfileSelect::GetStatus() const {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -64,7 +62,8 @@ void ProfileSelect::ExecuteInteractive() {
|
||||||
|
|
||||||
void ProfileSelect::Execute() {
|
void ProfileSelect::Execute() {
|
||||||
if (complete) {
|
if (complete) {
|
||||||
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(final_data)));
|
PushOutData(std::make_shared<IStorage>(system, std::move(final_data)));
|
||||||
|
Exit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,8 +110,9 @@ void ProfileSelect::SelectionComplete(std::optional<Common::UUID> uuid) {
|
||||||
|
|
||||||
final_data = std::vector<u8>(sizeof(UiReturnArg));
|
final_data = std::vector<u8>(sizeof(UiReturnArg));
|
||||||
std::memcpy(final_data.data(), &output, final_data.size());
|
std::memcpy(final_data.data(), &output, final_data.size());
|
||||||
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(final_data)));
|
|
||||||
broker.SignalStateChanged();
|
PushOutData(std::make_shared<IStorage>(system, std::move(final_data)));
|
||||||
|
Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ProfileSelect::RequestExit() {
|
Result ProfileSelect::RequestExit() {
|
||||||
|
@ -120,4 +120,4 @@ Result ProfileSelect::RequestExit() {
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::AM::Applets
|
} // namespace Service::AM::Frontend
|
|
@ -8,13 +8,13 @@
|
||||||
#include "common/common_funcs.h"
|
#include "common/common_funcs.h"
|
||||||
#include "common/uuid.h"
|
#include "common/uuid.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
#include "core/hle/service/am/applets/applets.h"
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class System;
|
class System;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Service::AM::Applets {
|
namespace Service::AM::Frontend {
|
||||||
|
|
||||||
enum class ProfileSelectAppletVersion : u32 {
|
enum class ProfileSelectAppletVersion : u32 {
|
||||||
Version1 = 0x1, // 1.0.0+
|
Version1 = 0x1, // 1.0.0+
|
||||||
|
@ -111,15 +111,15 @@ struct UiReturnArg {
|
||||||
};
|
};
|
||||||
static_assert(sizeof(UiReturnArg) == 0x18, "UiReturnArg has incorrect size.");
|
static_assert(sizeof(UiReturnArg) == 0x18, "UiReturnArg has incorrect size.");
|
||||||
|
|
||||||
class ProfileSelect final : public Applet {
|
class ProfileSelect final : public FrontendApplet {
|
||||||
public:
|
public:
|
||||||
explicit ProfileSelect(Core::System& system_, LibraryAppletMode applet_mode_,
|
explicit ProfileSelect(Core::System& system_, std::shared_ptr<Applet> applet_,
|
||||||
|
LibraryAppletMode applet_mode_,
|
||||||
const Core::Frontend::ProfileSelectApplet& frontend_);
|
const Core::Frontend::ProfileSelectApplet& frontend_);
|
||||||
~ProfileSelect() override;
|
~ProfileSelect() override;
|
||||||
|
|
||||||
void Initialize() override;
|
void Initialize() override;
|
||||||
|
|
||||||
bool TransactionComplete() const override;
|
|
||||||
Result GetStatus() const override;
|
Result GetStatus() const override;
|
||||||
void ExecuteInteractive() override;
|
void ExecuteInteractive() override;
|
||||||
void Execute() override;
|
void Execute() override;
|
||||||
|
@ -137,7 +137,6 @@ private:
|
||||||
bool complete = false;
|
bool complete = false;
|
||||||
Result status = ResultSuccess;
|
Result status = ResultSuccess;
|
||||||
std::vector<u8> final_data;
|
std::vector<u8> final_data;
|
||||||
Core::System& system;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM::Applets
|
} // namespace Service::AM::Frontend
|
|
@ -5,9 +5,10 @@
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/frontend/applets/software_keyboard.h"
|
#include "core/frontend/applets/software_keyboard.h"
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
#include "core/hle/service/am/applets/applet_software_keyboard.h"
|
#include "core/hle/service/am/frontend/applet_software_keyboard.h"
|
||||||
|
#include "core/hle/service/am/storage.h"
|
||||||
|
|
||||||
namespace Service::AM::Applets {
|
namespace Service::AM::Frontend {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -41,14 +42,15 @@ void SetReplyBase(std::vector<u8>& reply, SwkbdState state, SwkbdReplyType reply
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
SoftwareKeyboard::SoftwareKeyboard(Core::System& system_, LibraryAppletMode applet_mode_,
|
SoftwareKeyboard::SoftwareKeyboard(Core::System& system_, std::shared_ptr<Applet> applet_,
|
||||||
|
LibraryAppletMode applet_mode_,
|
||||||
Core::Frontend::SoftwareKeyboardApplet& frontend_)
|
Core::Frontend::SoftwareKeyboardApplet& frontend_)
|
||||||
: Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {}
|
: FrontendApplet{system_, applet_, applet_mode_}, frontend{frontend_} {}
|
||||||
|
|
||||||
SoftwareKeyboard::~SoftwareKeyboard() = default;
|
SoftwareKeyboard::~SoftwareKeyboard() = default;
|
||||||
|
|
||||||
void SoftwareKeyboard::Initialize() {
|
void SoftwareKeyboard::Initialize() {
|
||||||
Applet::Initialize();
|
FrontendApplet::Initialize();
|
||||||
|
|
||||||
LOG_INFO(Service_AM, "Initializing Software Keyboard Applet with LibraryAppletMode={}",
|
LOG_INFO(Service_AM, "Initializing Software Keyboard Applet with LibraryAppletMode={}",
|
||||||
applet_mode);
|
applet_mode);
|
||||||
|
@ -76,10 +78,6 @@ void SoftwareKeyboard::Initialize() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SoftwareKeyboard::TransactionComplete() const {
|
|
||||||
return complete;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result SoftwareKeyboard::GetStatus() const {
|
Result SoftwareKeyboard::GetStatus() const {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -184,7 +182,7 @@ void SoftwareKeyboard::InitializeForeground() {
|
||||||
|
|
||||||
is_background = false;
|
is_background = false;
|
||||||
|
|
||||||
const auto swkbd_config_storage = broker.PopNormalDataToApplet();
|
const auto swkbd_config_storage = PopInData();
|
||||||
ASSERT(swkbd_config_storage != nullptr);
|
ASSERT(swkbd_config_storage != nullptr);
|
||||||
|
|
||||||
const auto& swkbd_config_data = swkbd_config_storage->GetData();
|
const auto& swkbd_config_data = swkbd_config_storage->GetData();
|
||||||
|
@ -221,7 +219,7 @@ void SoftwareKeyboard::InitializeForeground() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto work_buffer_storage = broker.PopNormalDataToApplet();
|
const auto work_buffer_storage = PopInData();
|
||||||
ASSERT(work_buffer_storage != nullptr);
|
ASSERT(work_buffer_storage != nullptr);
|
||||||
|
|
||||||
if (swkbd_config_common.initial_string_length == 0) {
|
if (swkbd_config_common.initial_string_length == 0) {
|
||||||
|
@ -250,7 +248,7 @@ void SoftwareKeyboard::InitializeBackground(LibraryAppletMode library_applet_mod
|
||||||
|
|
||||||
is_background = true;
|
is_background = true;
|
||||||
|
|
||||||
const auto swkbd_inline_initialize_arg_storage = broker.PopNormalDataToApplet();
|
const auto swkbd_inline_initialize_arg_storage = PopInData();
|
||||||
ASSERT(swkbd_inline_initialize_arg_storage != nullptr);
|
ASSERT(swkbd_inline_initialize_arg_storage != nullptr);
|
||||||
|
|
||||||
const auto& swkbd_inline_initialize_arg = swkbd_inline_initialize_arg_storage->GetData();
|
const auto& swkbd_inline_initialize_arg = swkbd_inline_initialize_arg_storage->GetData();
|
||||||
|
@ -267,7 +265,7 @@ void SoftwareKeyboard::InitializeBackground(LibraryAppletMode library_applet_mod
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftwareKeyboard::ProcessTextCheck() {
|
void SoftwareKeyboard::ProcessTextCheck() {
|
||||||
const auto text_check_storage = broker.PopInteractiveDataToApplet();
|
const auto text_check_storage = PopInteractiveInData();
|
||||||
ASSERT(text_check_storage != nullptr);
|
ASSERT(text_check_storage != nullptr);
|
||||||
|
|
||||||
const auto& text_check_data = text_check_storage->GetData();
|
const auto& text_check_data = text_check_storage->GetData();
|
||||||
|
@ -314,7 +312,7 @@ void SoftwareKeyboard::ProcessTextCheck() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftwareKeyboard::ProcessInlineKeyboardRequest() {
|
void SoftwareKeyboard::ProcessInlineKeyboardRequest() {
|
||||||
const auto request_data_storage = broker.PopInteractiveDataToApplet();
|
const auto request_data_storage = PopInteractiveInData();
|
||||||
ASSERT(request_data_storage != nullptr);
|
ASSERT(request_data_storage != nullptr);
|
||||||
|
|
||||||
const auto& request_data = request_data_storage->GetData();
|
const auto& request_data = request_data_storage->GetData();
|
||||||
|
@ -377,7 +375,7 @@ void SoftwareKeyboard::SubmitNormalOutputAndExit(SwkbdResult result,
|
||||||
submitted_text.size() * sizeof(char16_t));
|
submitted_text.size() * sizeof(char16_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data)));
|
PushOutData(std::make_shared<IStorage>(system, std::move(out_data)));
|
||||||
|
|
||||||
ExitKeyboard();
|
ExitKeyboard();
|
||||||
}
|
}
|
||||||
|
@ -410,7 +408,7 @@ void SoftwareKeyboard::SubmitForTextCheck(std::u16string submitted_text) {
|
||||||
current_text.size() * sizeof(char16_t));
|
current_text.size() * sizeof(char16_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data)));
|
PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(out_data)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftwareKeyboard::SendReply(SwkbdReplyType reply_type) {
|
void SoftwareKeyboard::SendReply(SwkbdReplyType reply_type) {
|
||||||
|
@ -767,7 +765,7 @@ void SoftwareKeyboard::ExitKeyboard() {
|
||||||
|
|
||||||
frontend.ExitKeyboard();
|
frontend.ExitKeyboard();
|
||||||
|
|
||||||
broker.SignalStateChanged();
|
Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result SoftwareKeyboard::RequestExit() {
|
Result SoftwareKeyboard::RequestExit() {
|
||||||
|
@ -967,7 +965,7 @@ void SoftwareKeyboard::ReplyFinishedInitialize() {
|
||||||
|
|
||||||
SetReplyBase(reply, swkbd_state, SwkbdReplyType::FinishedInitialize);
|
SetReplyBase(reply, swkbd_state, SwkbdReplyType::FinishedInitialize);
|
||||||
|
|
||||||
broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
|
PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftwareKeyboard::ReplyDefault() {
|
void SoftwareKeyboard::ReplyDefault() {
|
||||||
|
@ -977,7 +975,7 @@ void SoftwareKeyboard::ReplyDefault() {
|
||||||
|
|
||||||
SetReplyBase(reply, swkbd_state, SwkbdReplyType::Default);
|
SetReplyBase(reply, swkbd_state, SwkbdReplyType::Default);
|
||||||
|
|
||||||
broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
|
PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftwareKeyboard::ReplyChangedString() {
|
void SoftwareKeyboard::ReplyChangedString() {
|
||||||
|
@ -999,7 +997,7 @@ void SoftwareKeyboard::ReplyChangedString() {
|
||||||
std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &changed_string_arg,
|
std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &changed_string_arg,
|
||||||
sizeof(SwkbdChangedStringArg));
|
sizeof(SwkbdChangedStringArg));
|
||||||
|
|
||||||
broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
|
PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftwareKeyboard::ReplyMovedCursor() {
|
void SoftwareKeyboard::ReplyMovedCursor() {
|
||||||
|
@ -1019,7 +1017,7 @@ void SoftwareKeyboard::ReplyMovedCursor() {
|
||||||
std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &moved_cursor_arg,
|
std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &moved_cursor_arg,
|
||||||
sizeof(SwkbdMovedCursorArg));
|
sizeof(SwkbdMovedCursorArg));
|
||||||
|
|
||||||
broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
|
PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftwareKeyboard::ReplyMovedTab() {
|
void SoftwareKeyboard::ReplyMovedTab() {
|
||||||
|
@ -1039,7 +1037,7 @@ void SoftwareKeyboard::ReplyMovedTab() {
|
||||||
std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &moved_tab_arg,
|
std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &moved_tab_arg,
|
||||||
sizeof(SwkbdMovedTabArg));
|
sizeof(SwkbdMovedTabArg));
|
||||||
|
|
||||||
broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
|
PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftwareKeyboard::ReplyDecidedEnter() {
|
void SoftwareKeyboard::ReplyDecidedEnter() {
|
||||||
|
@ -1058,7 +1056,7 @@ void SoftwareKeyboard::ReplyDecidedEnter() {
|
||||||
std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &decided_enter_arg,
|
std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &decided_enter_arg,
|
||||||
sizeof(SwkbdDecidedEnterArg));
|
sizeof(SwkbdDecidedEnterArg));
|
||||||
|
|
||||||
broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
|
PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply)));
|
||||||
|
|
||||||
HideInlineKeyboard();
|
HideInlineKeyboard();
|
||||||
}
|
}
|
||||||
|
@ -1070,7 +1068,7 @@ void SoftwareKeyboard::ReplyDecidedCancel() {
|
||||||
|
|
||||||
SetReplyBase(reply, swkbd_state, SwkbdReplyType::DecidedCancel);
|
SetReplyBase(reply, swkbd_state, SwkbdReplyType::DecidedCancel);
|
||||||
|
|
||||||
broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
|
PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply)));
|
||||||
|
|
||||||
HideInlineKeyboard();
|
HideInlineKeyboard();
|
||||||
}
|
}
|
||||||
|
@ -1095,7 +1093,7 @@ void SoftwareKeyboard::ReplyChangedStringUtf8() {
|
||||||
std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &changed_string_arg,
|
std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &changed_string_arg,
|
||||||
sizeof(SwkbdChangedStringArg));
|
sizeof(SwkbdChangedStringArg));
|
||||||
|
|
||||||
broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
|
PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftwareKeyboard::ReplyMovedCursorUtf8() {
|
void SoftwareKeyboard::ReplyMovedCursorUtf8() {
|
||||||
|
@ -1116,7 +1114,7 @@ void SoftwareKeyboard::ReplyMovedCursorUtf8() {
|
||||||
std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &moved_cursor_arg,
|
std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &moved_cursor_arg,
|
||||||
sizeof(SwkbdMovedCursorArg));
|
sizeof(SwkbdMovedCursorArg));
|
||||||
|
|
||||||
broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
|
PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftwareKeyboard::ReplyDecidedEnterUtf8() {
|
void SoftwareKeyboard::ReplyDecidedEnterUtf8() {
|
||||||
|
@ -1136,7 +1134,7 @@ void SoftwareKeyboard::ReplyDecidedEnterUtf8() {
|
||||||
std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &decided_enter_arg,
|
std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &decided_enter_arg,
|
||||||
sizeof(SwkbdDecidedEnterArg));
|
sizeof(SwkbdDecidedEnterArg));
|
||||||
|
|
||||||
broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
|
PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply)));
|
||||||
|
|
||||||
HideInlineKeyboard();
|
HideInlineKeyboard();
|
||||||
}
|
}
|
||||||
|
@ -1148,7 +1146,7 @@ void SoftwareKeyboard::ReplyUnsetCustomizeDic() {
|
||||||
|
|
||||||
SetReplyBase(reply, swkbd_state, SwkbdReplyType::UnsetCustomizeDic);
|
SetReplyBase(reply, swkbd_state, SwkbdReplyType::UnsetCustomizeDic);
|
||||||
|
|
||||||
broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
|
PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftwareKeyboard::ReplyReleasedUserWordInfo() {
|
void SoftwareKeyboard::ReplyReleasedUserWordInfo() {
|
||||||
|
@ -1158,7 +1156,7 @@ void SoftwareKeyboard::ReplyReleasedUserWordInfo() {
|
||||||
|
|
||||||
SetReplyBase(reply, swkbd_state, SwkbdReplyType::ReleasedUserWordInfo);
|
SetReplyBase(reply, swkbd_state, SwkbdReplyType::ReleasedUserWordInfo);
|
||||||
|
|
||||||
broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
|
PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftwareKeyboard::ReplyUnsetCustomizedDictionaries() {
|
void SoftwareKeyboard::ReplyUnsetCustomizedDictionaries() {
|
||||||
|
@ -1168,7 +1166,7 @@ void SoftwareKeyboard::ReplyUnsetCustomizedDictionaries() {
|
||||||
|
|
||||||
SetReplyBase(reply, swkbd_state, SwkbdReplyType::UnsetCustomizedDictionaries);
|
SetReplyBase(reply, swkbd_state, SwkbdReplyType::UnsetCustomizedDictionaries);
|
||||||
|
|
||||||
broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
|
PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftwareKeyboard::ReplyChangedStringV2() {
|
void SoftwareKeyboard::ReplyChangedStringV2() {
|
||||||
|
@ -1194,7 +1192,7 @@ void SoftwareKeyboard::ReplyChangedStringV2() {
|
||||||
std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdChangedStringArg),
|
std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdChangedStringArg),
|
||||||
&flag, 1);
|
&flag, 1);
|
||||||
|
|
||||||
broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
|
PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftwareKeyboard::ReplyMovedCursorV2() {
|
void SoftwareKeyboard::ReplyMovedCursorV2() {
|
||||||
|
@ -1218,7 +1216,7 @@ void SoftwareKeyboard::ReplyMovedCursorV2() {
|
||||||
std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedCursorArg),
|
std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedCursorArg),
|
||||||
&flag, 1);
|
&flag, 1);
|
||||||
|
|
||||||
broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
|
PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftwareKeyboard::ReplyChangedStringUtf8V2() {
|
void SoftwareKeyboard::ReplyChangedStringUtf8V2() {
|
||||||
|
@ -1245,7 +1243,7 @@ void SoftwareKeyboard::ReplyChangedStringUtf8V2() {
|
||||||
std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdChangedStringArg),
|
std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdChangedStringArg),
|
||||||
&flag, 1);
|
&flag, 1);
|
||||||
|
|
||||||
broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
|
PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftwareKeyboard::ReplyMovedCursorUtf8V2() {
|
void SoftwareKeyboard::ReplyMovedCursorUtf8V2() {
|
||||||
|
@ -1270,7 +1268,7 @@ void SoftwareKeyboard::ReplyMovedCursorUtf8V2() {
|
||||||
std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdMovedCursorArg),
|
std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdMovedCursorArg),
|
||||||
&flag, 1);
|
&flag, 1);
|
||||||
|
|
||||||
broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
|
PushInteractiveOutData(std::make_shared<IStorage>(system, std::move(reply)));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::AM::Applets
|
} // namespace Service::AM::Frontend
|
|
@ -5,8 +5,8 @@
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
#include "core/hle/service/am/applets/applet_software_keyboard_types.h"
|
#include "core/hle/service/am/frontend/applet_software_keyboard_types.h"
|
||||||
#include "core/hle/service/am/applets/applets.h"
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class System;
|
class System;
|
||||||
|
@ -17,17 +17,17 @@ struct KeyboardInitializeParameters;
|
||||||
struct InlineAppearParameters;
|
struct InlineAppearParameters;
|
||||||
} // namespace Core::Frontend
|
} // namespace Core::Frontend
|
||||||
|
|
||||||
namespace Service::AM::Applets {
|
namespace Service::AM::Frontend {
|
||||||
|
|
||||||
class SoftwareKeyboard final : public Applet {
|
class SoftwareKeyboard final : public FrontendApplet {
|
||||||
public:
|
public:
|
||||||
explicit SoftwareKeyboard(Core::System& system_, LibraryAppletMode applet_mode_,
|
explicit SoftwareKeyboard(Core::System& system_, std::shared_ptr<Applet> applet_,
|
||||||
|
LibraryAppletMode applet_mode_,
|
||||||
Core::Frontend::SoftwareKeyboardApplet& frontend_);
|
Core::Frontend::SoftwareKeyboardApplet& frontend_);
|
||||||
~SoftwareKeyboard() override;
|
~SoftwareKeyboard() override;
|
||||||
|
|
||||||
void Initialize() override;
|
void Initialize() override;
|
||||||
|
|
||||||
bool TransactionComplete() const override;
|
|
||||||
Result GetStatus() const override;
|
Result GetStatus() const override;
|
||||||
void ExecuteInteractive() override;
|
void ExecuteInteractive() override;
|
||||||
void Execute() override;
|
void Execute() override;
|
||||||
|
@ -156,7 +156,6 @@ private:
|
||||||
void ReplyMovedCursorUtf8V2();
|
void ReplyMovedCursorUtf8V2();
|
||||||
|
|
||||||
Core::Frontend::SoftwareKeyboardApplet& frontend;
|
Core::Frontend::SoftwareKeyboardApplet& frontend;
|
||||||
Core::System& system;
|
|
||||||
|
|
||||||
SwkbdAppletVersion swkbd_applet_version;
|
SwkbdAppletVersion swkbd_applet_version;
|
||||||
|
|
||||||
|
@ -184,4 +183,4 @@ private:
|
||||||
Result status{ResultSuccess};
|
Result status{ResultSuccess};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM::Applets
|
} // namespace Service::AM::Frontend
|
|
@ -11,7 +11,7 @@
|
||||||
#include "common/swap.h"
|
#include "common/swap.h"
|
||||||
#include "common/uuid.h"
|
#include "common/uuid.h"
|
||||||
|
|
||||||
namespace Service::AM::Applets {
|
namespace Service::AM::Frontend {
|
||||||
|
|
||||||
constexpr std::size_t MAX_OK_TEXT_LENGTH = 8;
|
constexpr std::size_t MAX_OK_TEXT_LENGTH = 8;
|
||||||
constexpr std::size_t MAX_HEADER_TEXT_LENGTH = 64;
|
constexpr std::size_t MAX_HEADER_TEXT_LENGTH = 64;
|
||||||
|
@ -351,4 +351,4 @@ struct SwkbdDecidedEnterArg {
|
||||||
};
|
};
|
||||||
static_assert(sizeof(SwkbdDecidedEnterArg) == 0x4, "SwkbdDecidedEnterArg has incorrect size.");
|
static_assert(sizeof(SwkbdDecidedEnterArg) == 0x4, "SwkbdDecidedEnterArg has incorrect size.");
|
||||||
|
|
||||||
} // namespace Service::AM::Applets
|
} // namespace Service::AM::Frontend
|
|
@ -19,12 +19,13 @@
|
||||||
#include "core/frontend/applets/web_browser.h"
|
#include "core/frontend/applets/web_browser.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
#include "core/hle/service/am/applets/applet_web_browser.h"
|
#include "core/hle/service/am/frontend/applet_web_browser.h"
|
||||||
|
#include "core/hle/service/am/storage.h"
|
||||||
#include "core/hle/service/filesystem/filesystem.h"
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||||
#include "core/hle/service/ns/iplatform_service_manager.h"
|
#include "core/hle/service/ns/iplatform_service_manager.h"
|
||||||
#include "core/loader/loader.h"
|
#include "core/loader/loader.h"
|
||||||
|
|
||||||
namespace Service::AM::Applets {
|
namespace Service::AM::Frontend {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -223,14 +224,15 @@ void ExtractSharedFonts(Core::System& system) {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
WebBrowser::WebBrowser(Core::System& system_, LibraryAppletMode applet_mode_,
|
WebBrowser::WebBrowser(Core::System& system_, std::shared_ptr<Applet> applet_,
|
||||||
|
LibraryAppletMode applet_mode_,
|
||||||
const Core::Frontend::WebBrowserApplet& frontend_)
|
const Core::Frontend::WebBrowserApplet& frontend_)
|
||||||
: Applet{system_, applet_mode_}, frontend(frontend_), system{system_} {}
|
: FrontendApplet{system_, applet_, applet_mode_}, frontend(frontend_) {}
|
||||||
|
|
||||||
WebBrowser::~WebBrowser() = default;
|
WebBrowser::~WebBrowser() = default;
|
||||||
|
|
||||||
void WebBrowser::Initialize() {
|
void WebBrowser::Initialize() {
|
||||||
Applet::Initialize();
|
FrontendApplet::Initialize();
|
||||||
|
|
||||||
LOG_INFO(Service_AM, "Initializing Web Browser Applet.");
|
LOG_INFO(Service_AM, "Initializing Web Browser Applet.");
|
||||||
|
|
||||||
|
@ -243,7 +245,7 @@ void WebBrowser::Initialize() {
|
||||||
|
|
||||||
web_applet_version = WebAppletVersion{common_args.library_version};
|
web_applet_version = WebAppletVersion{common_args.library_version};
|
||||||
|
|
||||||
const auto web_arg_storage = broker.PopNormalDataToApplet();
|
const auto web_arg_storage = PopInData();
|
||||||
ASSERT(web_arg_storage != nullptr);
|
ASSERT(web_arg_storage != nullptr);
|
||||||
|
|
||||||
const auto& web_arg = web_arg_storage->GetData();
|
const auto& web_arg = web_arg_storage->GetData();
|
||||||
|
@ -284,10 +286,6 @@ void WebBrowser::Initialize() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebBrowser::TransactionComplete() const {
|
|
||||||
return complete;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result WebBrowser::GetStatus() const {
|
Result WebBrowser::GetStatus() const {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -358,8 +356,8 @@ void WebBrowser::WebBrowserExit(WebExitReason exit_reason, std::string last_url)
|
||||||
complete = true;
|
complete = true;
|
||||||
std::vector<u8> out_data(sizeof(WebCommonReturnValue));
|
std::vector<u8> out_data(sizeof(WebCommonReturnValue));
|
||||||
std::memcpy(out_data.data(), &web_common_return_value, out_data.size());
|
std::memcpy(out_data.data(), &web_common_return_value, out_data.size());
|
||||||
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data)));
|
PushOutData(std::make_shared<IStorage>(system, std::move(out_data)));
|
||||||
broker.SignalStateChanged();
|
Exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result WebBrowser::RequestExit() {
|
Result WebBrowser::RequestExit() {
|
||||||
|
@ -504,4 +502,4 @@ void WebBrowser::ExecuteLobby() {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called, Lobby Applet is not implemented");
|
LOG_WARNING(Service_AM, "(STUBBED) called, Lobby Applet is not implemented");
|
||||||
WebBrowserExit(WebExitReason::EndButtonPressed);
|
WebBrowserExit(WebExitReason::EndButtonPressed);
|
||||||
}
|
}
|
||||||
} // namespace Service::AM::Applets
|
} // namespace Service::AM::Frontend
|
|
@ -9,8 +9,8 @@
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/file_sys/vfs/vfs_types.h"
|
#include "core/file_sys/vfs/vfs_types.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
#include "core/hle/service/am/applets/applet_web_browser_types.h"
|
#include "core/hle/service/am/frontend/applet_web_browser_types.h"
|
||||||
#include "core/hle/service/am/applets/applets.h"
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class System;
|
class System;
|
||||||
|
@ -20,18 +20,17 @@ namespace FileSys {
|
||||||
enum class ContentRecordType : u8;
|
enum class ContentRecordType : u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Service::AM::Applets {
|
namespace Service::AM::Frontend {
|
||||||
|
|
||||||
class WebBrowser final : public Applet {
|
class WebBrowser final : public FrontendApplet {
|
||||||
public:
|
public:
|
||||||
WebBrowser(Core::System& system_, LibraryAppletMode applet_mode_,
|
WebBrowser(Core::System& system_, std::shared_ptr<Applet> applet_,
|
||||||
const Core::Frontend::WebBrowserApplet& frontend_);
|
LibraryAppletMode applet_mode_, const Core::Frontend::WebBrowserApplet& frontend_);
|
||||||
|
|
||||||
~WebBrowser() override;
|
~WebBrowser() override;
|
||||||
|
|
||||||
void Initialize() override;
|
void Initialize() override;
|
||||||
|
|
||||||
bool TransactionComplete() const override;
|
|
||||||
Result GetStatus() const override;
|
Result GetStatus() const override;
|
||||||
void ExecuteInteractive() override;
|
void ExecuteInteractive() override;
|
||||||
void Execute() override;
|
void Execute() override;
|
||||||
|
@ -80,8 +79,6 @@ private:
|
||||||
FileSys::VirtualFile offline_romfs;
|
FileSys::VirtualFile offline_romfs;
|
||||||
|
|
||||||
std::string external_url;
|
std::string external_url;
|
||||||
|
|
||||||
Core::System& system;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM::Applets
|
} // namespace Service::AM::Frontend
|
|
@ -11,7 +11,7 @@
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/swap.h"
|
#include "common/swap.h"
|
||||||
|
|
||||||
namespace Service::AM::Applets {
|
namespace Service::AM::Frontend {
|
||||||
|
|
||||||
enum class WebAppletVersion : u32_le {
|
enum class WebAppletVersion : u32_le {
|
||||||
Version0 = 0x0, // Only used by WifiWebAuthApplet
|
Version0 = 0x0, // Only used by WifiWebAuthApplet
|
||||||
|
@ -174,4 +174,4 @@ static_assert(sizeof(WebCommonReturnValue) == 0x1010, "WebCommonReturnValue has
|
||||||
|
|
||||||
using WebArgInputTLVMap = std::unordered_map<WebArgInputTLVType, std::vector<u8>>;
|
using WebArgInputTLVMap = std::unordered_map<WebArgInputTLVType, std::vector<u8>>;
|
||||||
|
|
||||||
} // namespace Service::AM::Applets
|
} // namespace Service::AM::Frontend
|
|
@ -0,0 +1,240 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "core/frontend/applets/cabinet.h"
|
||||||
|
#include "core/frontend/applets/controller.h"
|
||||||
|
#include "core/frontend/applets/error.h"
|
||||||
|
#include "core/frontend/applets/general.h"
|
||||||
|
#include "core/frontend/applets/mii_edit.h"
|
||||||
|
#include "core/frontend/applets/profile_select.h"
|
||||||
|
#include "core/frontend/applets/software_keyboard.h"
|
||||||
|
#include "core/frontend/applets/web_browser.h"
|
||||||
|
#include "core/hle/kernel/k_event.h"
|
||||||
|
#include "core/hle/service/am/am.h"
|
||||||
|
#include "core/hle/service/am/applet_ae.h"
|
||||||
|
#include "core/hle/service/am/applet_data_broker.h"
|
||||||
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
|
#include "core/hle/service/am/applet_message_queue.h"
|
||||||
|
#include "core/hle/service/am/applet_oe.h"
|
||||||
|
#include "core/hle/service/am/frontend/applet_cabinet.h"
|
||||||
|
#include "core/hle/service/am/frontend/applet_controller.h"
|
||||||
|
#include "core/hle/service/am/frontend/applet_error.h"
|
||||||
|
#include "core/hle/service/am/frontend/applet_general.h"
|
||||||
|
#include "core/hle/service/am/frontend/applet_mii_edit.h"
|
||||||
|
#include "core/hle/service/am/frontend/applet_profile_select.h"
|
||||||
|
#include "core/hle/service/am/frontend/applet_software_keyboard.h"
|
||||||
|
#include "core/hle/service/am/frontend/applet_web_browser.h"
|
||||||
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
|
#include "core/hle/service/am/storage.h"
|
||||||
|
#include "core/hle/service/sm/sm.h"
|
||||||
|
|
||||||
|
namespace Service::AM::Frontend {
|
||||||
|
|
||||||
|
FrontendApplet::FrontendApplet(Core::System& system_, std::shared_ptr<Applet> applet_,
|
||||||
|
LibraryAppletMode applet_mode_)
|
||||||
|
: system{system_}, applet{std::move(applet_)}, applet_mode{applet_mode_} {}
|
||||||
|
|
||||||
|
FrontendApplet::~FrontendApplet() = default;
|
||||||
|
|
||||||
|
void FrontendApplet::Initialize() {
|
||||||
|
std::shared_ptr<IStorage> common = PopInData();
|
||||||
|
ASSERT(common != nullptr);
|
||||||
|
const auto common_data = common->GetData();
|
||||||
|
|
||||||
|
ASSERT(common_data.size() >= sizeof(CommonArguments));
|
||||||
|
std::memcpy(&common_args, common_data.data(), sizeof(CommonArguments));
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<IStorage> FrontendApplet::PopInData() {
|
||||||
|
std::shared_ptr<IStorage> ret;
|
||||||
|
applet.lock()->caller_applet_broker->GetInData().Pop(&ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<IStorage> FrontendApplet::PopInteractiveInData() {
|
||||||
|
std::shared_ptr<IStorage> ret;
|
||||||
|
applet.lock()->caller_applet_broker->GetInteractiveInData().Pop(&ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrontendApplet::PushOutData(std::shared_ptr<IStorage> storage) {
|
||||||
|
applet.lock()->caller_applet_broker->GetOutData().Push(storage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrontendApplet::PushInteractiveOutData(std::shared_ptr<IStorage> storage) {
|
||||||
|
applet.lock()->caller_applet_broker->GetInteractiveOutData().Push(storage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrontendApplet::Exit() {
|
||||||
|
applet.lock()->caller_applet_broker->SignalCompletion();
|
||||||
|
}
|
||||||
|
|
||||||
|
FrontendAppletSet::FrontendAppletSet() = default;
|
||||||
|
|
||||||
|
FrontendAppletSet::FrontendAppletSet(CabinetApplet cabinet_applet,
|
||||||
|
ControllerApplet controller_applet, ErrorApplet error_applet,
|
||||||
|
MiiEdit mii_edit_,
|
||||||
|
ParentalControlsApplet parental_controls_applet,
|
||||||
|
PhotoViewer photo_viewer_, ProfileSelect profile_select_,
|
||||||
|
SoftwareKeyboard software_keyboard_, WebBrowser web_browser_)
|
||||||
|
: cabinet{std::move(cabinet_applet)}, controller{std::move(controller_applet)},
|
||||||
|
error{std::move(error_applet)}, mii_edit{std::move(mii_edit_)},
|
||||||
|
parental_controls{std::move(parental_controls_applet)},
|
||||||
|
photo_viewer{std::move(photo_viewer_)}, profile_select{std::move(profile_select_)},
|
||||||
|
software_keyboard{std::move(software_keyboard_)}, web_browser{std::move(web_browser_)} {}
|
||||||
|
|
||||||
|
FrontendAppletSet::~FrontendAppletSet() = default;
|
||||||
|
|
||||||
|
FrontendAppletSet::FrontendAppletSet(FrontendAppletSet&&) noexcept = default;
|
||||||
|
|
||||||
|
FrontendAppletSet& FrontendAppletSet::operator=(FrontendAppletSet&&) noexcept = default;
|
||||||
|
|
||||||
|
FrontendAppletHolder::FrontendAppletHolder(Core::System& system_) : system{system_} {}
|
||||||
|
|
||||||
|
FrontendAppletHolder::~FrontendAppletHolder() = default;
|
||||||
|
|
||||||
|
const FrontendAppletSet& FrontendAppletHolder::GetFrontendAppletSet() const {
|
||||||
|
return frontend;
|
||||||
|
}
|
||||||
|
|
||||||
|
NFP::CabinetMode FrontendAppletHolder::GetCabinetMode() const {
|
||||||
|
return cabinet_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
AppletId FrontendAppletHolder::GetCurrentAppletId() const {
|
||||||
|
return current_applet_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrontendAppletHolder::SetFrontendAppletSet(FrontendAppletSet set) {
|
||||||
|
if (set.cabinet != nullptr) {
|
||||||
|
frontend.cabinet = std::move(set.cabinet);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set.controller != nullptr) {
|
||||||
|
frontend.controller = std::move(set.controller);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set.error != nullptr) {
|
||||||
|
frontend.error = std::move(set.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set.mii_edit != nullptr) {
|
||||||
|
frontend.mii_edit = std::move(set.mii_edit);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set.parental_controls != nullptr) {
|
||||||
|
frontend.parental_controls = std::move(set.parental_controls);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set.photo_viewer != nullptr) {
|
||||||
|
frontend.photo_viewer = std::move(set.photo_viewer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set.profile_select != nullptr) {
|
||||||
|
frontend.profile_select = std::move(set.profile_select);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set.software_keyboard != nullptr) {
|
||||||
|
frontend.software_keyboard = std::move(set.software_keyboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set.web_browser != nullptr) {
|
||||||
|
frontend.web_browser = std::move(set.web_browser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrontendAppletHolder::SetCabinetMode(NFP::CabinetMode mode) {
|
||||||
|
cabinet_mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrontendAppletHolder::SetCurrentAppletId(AppletId applet_id) {
|
||||||
|
current_applet_id = applet_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrontendAppletHolder::SetDefaultAppletsIfMissing() {
|
||||||
|
if (frontend.cabinet == nullptr) {
|
||||||
|
frontend.cabinet = std::make_unique<Core::Frontend::DefaultCabinetApplet>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frontend.controller == nullptr) {
|
||||||
|
frontend.controller =
|
||||||
|
std::make_unique<Core::Frontend::DefaultControllerApplet>(system.HIDCore());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frontend.error == nullptr) {
|
||||||
|
frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frontend.mii_edit == nullptr) {
|
||||||
|
frontend.mii_edit = std::make_unique<Core::Frontend::DefaultMiiEditApplet>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frontend.parental_controls == nullptr) {
|
||||||
|
frontend.parental_controls =
|
||||||
|
std::make_unique<Core::Frontend::DefaultParentalControlsApplet>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frontend.photo_viewer == nullptr) {
|
||||||
|
frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frontend.profile_select == nullptr) {
|
||||||
|
frontend.profile_select = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frontend.software_keyboard == nullptr) {
|
||||||
|
frontend.software_keyboard =
|
||||||
|
std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frontend.web_browser == nullptr) {
|
||||||
|
frontend.web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrontendAppletHolder::ClearAll() {
|
||||||
|
frontend = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<FrontendApplet> FrontendAppletHolder::GetApplet(std::shared_ptr<Applet> applet,
|
||||||
|
AppletId id,
|
||||||
|
LibraryAppletMode mode) const {
|
||||||
|
switch (id) {
|
||||||
|
case AppletId::Auth:
|
||||||
|
return std::make_shared<Auth>(system, applet, mode, *frontend.parental_controls);
|
||||||
|
case AppletId::Cabinet:
|
||||||
|
return std::make_shared<Cabinet>(system, applet, mode, *frontend.cabinet);
|
||||||
|
case AppletId::Controller:
|
||||||
|
return std::make_shared<Controller>(system, applet, mode, *frontend.controller);
|
||||||
|
case AppletId::Error:
|
||||||
|
return std::make_shared<Error>(system, applet, mode, *frontend.error);
|
||||||
|
case AppletId::ProfileSelect:
|
||||||
|
return std::make_shared<ProfileSelect>(system, applet, mode, *frontend.profile_select);
|
||||||
|
case AppletId::SoftwareKeyboard:
|
||||||
|
return std::make_shared<SoftwareKeyboard>(system, applet, mode,
|
||||||
|
*frontend.software_keyboard);
|
||||||
|
case AppletId::MiiEdit:
|
||||||
|
return std::make_shared<MiiEdit>(system, applet, mode, *frontend.mii_edit);
|
||||||
|
case AppletId::Web:
|
||||||
|
case AppletId::Shop:
|
||||||
|
case AppletId::OfflineWeb:
|
||||||
|
case AppletId::LoginShare:
|
||||||
|
case AppletId::WebAuth:
|
||||||
|
return std::make_shared<WebBrowser>(system, applet, mode, *frontend.web_browser);
|
||||||
|
case AppletId::PhotoViewer:
|
||||||
|
return std::make_shared<PhotoViewer>(system, applet, mode, *frontend.photo_viewer);
|
||||||
|
default:
|
||||||
|
UNIMPLEMENTED_MSG(
|
||||||
|
"No backend implementation exists for applet_id={:02X}! Falling back to stub applet.",
|
||||||
|
static_cast<u8>(id));
|
||||||
|
return std::make_shared<StubApplet>(system, applet, id, mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM::Frontend
|
|
@ -0,0 +1,146 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
#include "common/swap.h"
|
||||||
|
#include "core/hle/service/am/applet.h"
|
||||||
|
|
||||||
|
union Result;
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Core::Frontend {
|
||||||
|
class CabinetApplet;
|
||||||
|
class ControllerApplet;
|
||||||
|
class ECommerceApplet;
|
||||||
|
class ErrorApplet;
|
||||||
|
class MiiEditApplet;
|
||||||
|
class ParentalControlsApplet;
|
||||||
|
class PhotoViewerApplet;
|
||||||
|
class ProfileSelectApplet;
|
||||||
|
class SoftwareKeyboardApplet;
|
||||||
|
class WebBrowserApplet;
|
||||||
|
} // namespace Core::Frontend
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
class KernelCore;
|
||||||
|
class KEvent;
|
||||||
|
class KReadableEvent;
|
||||||
|
} // namespace Kernel
|
||||||
|
|
||||||
|
namespace Service::NFP {
|
||||||
|
enum class CabinetMode : u8;
|
||||||
|
} // namespace Service::NFP
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
class IStorage;
|
||||||
|
|
||||||
|
namespace Frontend {
|
||||||
|
|
||||||
|
class FrontendApplet {
|
||||||
|
public:
|
||||||
|
explicit FrontendApplet(Core::System& system_, std::shared_ptr<Applet> applet_,
|
||||||
|
LibraryAppletMode applet_mode_);
|
||||||
|
virtual ~FrontendApplet();
|
||||||
|
|
||||||
|
virtual void Initialize();
|
||||||
|
|
||||||
|
virtual Result GetStatus() const = 0;
|
||||||
|
virtual void ExecuteInteractive() = 0;
|
||||||
|
virtual void Execute() = 0;
|
||||||
|
virtual Result RequestExit() = 0;
|
||||||
|
|
||||||
|
LibraryAppletMode GetLibraryAppletMode() const {
|
||||||
|
return applet_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsInitialized() const {
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<IStorage> PopInData();
|
||||||
|
std::shared_ptr<IStorage> PopInteractiveInData();
|
||||||
|
void PushOutData(std::shared_ptr<IStorage> storage);
|
||||||
|
void PushInteractiveOutData(std::shared_ptr<IStorage> storage);
|
||||||
|
void Exit();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Core::System& system;
|
||||||
|
CommonArguments common_args{};
|
||||||
|
std::weak_ptr<Applet> applet{};
|
||||||
|
LibraryAppletMode applet_mode{};
|
||||||
|
bool initialized{false};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FrontendAppletSet {
|
||||||
|
using CabinetApplet = std::unique_ptr<Core::Frontend::CabinetApplet>;
|
||||||
|
using ControllerApplet = std::unique_ptr<Core::Frontend::ControllerApplet>;
|
||||||
|
using ErrorApplet = std::unique_ptr<Core::Frontend::ErrorApplet>;
|
||||||
|
using MiiEdit = std::unique_ptr<Core::Frontend::MiiEditApplet>;
|
||||||
|
using ParentalControlsApplet = std::unique_ptr<Core::Frontend::ParentalControlsApplet>;
|
||||||
|
using PhotoViewer = std::unique_ptr<Core::Frontend::PhotoViewerApplet>;
|
||||||
|
using ProfileSelect = std::unique_ptr<Core::Frontend::ProfileSelectApplet>;
|
||||||
|
using SoftwareKeyboard = std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet>;
|
||||||
|
using WebBrowser = std::unique_ptr<Core::Frontend::WebBrowserApplet>;
|
||||||
|
|
||||||
|
FrontendAppletSet();
|
||||||
|
FrontendAppletSet(CabinetApplet cabinet_applet, ControllerApplet controller_applet,
|
||||||
|
ErrorApplet error_applet, MiiEdit mii_edit_,
|
||||||
|
ParentalControlsApplet parental_controls_applet, PhotoViewer photo_viewer_,
|
||||||
|
ProfileSelect profile_select_, SoftwareKeyboard software_keyboard_,
|
||||||
|
WebBrowser web_browser_);
|
||||||
|
~FrontendAppletSet();
|
||||||
|
|
||||||
|
FrontendAppletSet(const FrontendAppletSet&) = delete;
|
||||||
|
FrontendAppletSet& operator=(const FrontendAppletSet&) = delete;
|
||||||
|
|
||||||
|
FrontendAppletSet(FrontendAppletSet&&) noexcept;
|
||||||
|
FrontendAppletSet& operator=(FrontendAppletSet&&) noexcept;
|
||||||
|
|
||||||
|
CabinetApplet cabinet;
|
||||||
|
ControllerApplet controller;
|
||||||
|
ErrorApplet error;
|
||||||
|
MiiEdit mii_edit;
|
||||||
|
ParentalControlsApplet parental_controls;
|
||||||
|
PhotoViewer photo_viewer;
|
||||||
|
ProfileSelect profile_select;
|
||||||
|
SoftwareKeyboard software_keyboard;
|
||||||
|
WebBrowser web_browser;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FrontendAppletHolder {
|
||||||
|
public:
|
||||||
|
explicit FrontendAppletHolder(Core::System& system_);
|
||||||
|
~FrontendAppletHolder();
|
||||||
|
|
||||||
|
const FrontendAppletSet& GetFrontendAppletSet() const;
|
||||||
|
NFP::CabinetMode GetCabinetMode() const;
|
||||||
|
AppletId GetCurrentAppletId() const;
|
||||||
|
|
||||||
|
void SetFrontendAppletSet(FrontendAppletSet set);
|
||||||
|
void SetCabinetMode(NFP::CabinetMode mode);
|
||||||
|
void SetCurrentAppletId(AppletId applet_id);
|
||||||
|
void SetDefaultAppletsIfMissing();
|
||||||
|
void ClearAll();
|
||||||
|
|
||||||
|
std::shared_ptr<FrontendApplet> GetApplet(std::shared_ptr<Applet> applet, AppletId id,
|
||||||
|
LibraryAppletMode mode) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
AppletId current_applet_id{};
|
||||||
|
NFP::CabinetMode cabinet_mode{};
|
||||||
|
|
||||||
|
FrontendAppletSet frontend;
|
||||||
|
Core::System& system;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Frontend
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,34 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/global_state_controller.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
IGlobalStateController::IGlobalStateController(Core::System& system_)
|
||||||
|
: ServiceFramework{system_, "IGlobalStateController"} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, nullptr, "RequestToEnterSleep"},
|
||||||
|
{1, nullptr, "EnterSleep"},
|
||||||
|
{2, nullptr, "StartSleepSequence"},
|
||||||
|
{3, nullptr, "StartShutdownSequence"},
|
||||||
|
{4, nullptr, "StartRebootSequence"},
|
||||||
|
{9, nullptr, "IsAutoPowerDownRequested"},
|
||||||
|
{10, nullptr, "LoadAndApplyIdlePolicySettings"},
|
||||||
|
{11, nullptr, "NotifyCecSettingsChanged"},
|
||||||
|
{12, nullptr, "SetDefaultHomeButtonLongPressTime"},
|
||||||
|
{13, nullptr, "UpdateDefaultDisplayResolution"},
|
||||||
|
{14, nullptr, "ShouldSleepOnBoot"},
|
||||||
|
{15, nullptr, "GetHdcpAuthenticationFailedEvent"},
|
||||||
|
{30, nullptr, "OpenCradleFirmwareUpdater"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
IGlobalStateController::~IGlobalStateController() = default;
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,16 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
class IGlobalStateController final : public ServiceFramework<IGlobalStateController> {
|
||||||
|
public:
|
||||||
|
explicit IGlobalStateController(Core::System& system_);
|
||||||
|
~IGlobalStateController() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,35 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "core/hle/service/am/hid_registration.h"
|
||||||
|
#include "core/hle/service/am/process.h"
|
||||||
|
#include "core/hle/service/hid/hid_server.h"
|
||||||
|
#include "core/hle/service/sm/sm.h"
|
||||||
|
#include "hid_core/resource_manager.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
HidRegistration::HidRegistration(Core::System& system, Process& process) : m_process(process) {
|
||||||
|
m_hid_server = system.ServiceManager().GetService<HID::IHidServer>("hid");
|
||||||
|
|
||||||
|
if (m_process.IsInitialized()) {
|
||||||
|
m_hid_server->GetResourceManager()->RegisterAppletResourceUserId(m_process.GetProcessId(),
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HidRegistration::~HidRegistration() {
|
||||||
|
if (m_process.IsInitialized()) {
|
||||||
|
m_hid_server->GetResourceManager()->UnregisterAppletResourceUserId(
|
||||||
|
m_process.GetProcessId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HidRegistration::EnableAppletToGetInput(bool enable) {
|
||||||
|
if (m_process.IsInitialized()) {
|
||||||
|
m_hid_server->GetResourceManager()->EnableInput(m_process.GetProcessId(), enable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,32 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::HID {
|
||||||
|
class IHidServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
class Process;
|
||||||
|
|
||||||
|
class HidRegistration {
|
||||||
|
public:
|
||||||
|
explicit HidRegistration(Core::System& system, Process& process);
|
||||||
|
~HidRegistration();
|
||||||
|
|
||||||
|
void EnableAppletToGetInput(bool enable);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Process& m_process;
|
||||||
|
std::shared_ptr<Service::HID::IHidServer> m_hid_server;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,57 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/home_menu_functions.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_)
|
||||||
|
: ServiceFramework{system_, "IHomeMenuFunctions"}, service_context{system,
|
||||||
|
"IHomeMenuFunctions"} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{10, &IHomeMenuFunctions::RequestToGetForeground, "RequestToGetForeground"},
|
||||||
|
{11, nullptr, "LockForeground"},
|
||||||
|
{12, nullptr, "UnlockForeground"},
|
||||||
|
{20, nullptr, "PopFromGeneralChannel"},
|
||||||
|
{21, &IHomeMenuFunctions::GetPopFromGeneralChannelEvent, "GetPopFromGeneralChannelEvent"},
|
||||||
|
{30, nullptr, "GetHomeButtonWriterLockAccessor"},
|
||||||
|
{31, nullptr, "GetWriterLockAccessorEx"},
|
||||||
|
{40, nullptr, "IsSleepEnabled"},
|
||||||
|
{41, nullptr, "IsRebootEnabled"},
|
||||||
|
{50, nullptr, "LaunchSystemApplet"},
|
||||||
|
{51, nullptr, "LaunchStarter"},
|
||||||
|
{100, nullptr, "PopRequestLaunchApplicationForDebug"},
|
||||||
|
{110, nullptr, "IsForceTerminateApplicationDisabledForDebug"},
|
||||||
|
{200, nullptr, "LaunchDevMenu"},
|
||||||
|
{1000, nullptr, "SetLastApplicationExitReason"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
|
||||||
|
pop_from_general_channel_event =
|
||||||
|
service_context.CreateEvent("IHomeMenuFunctions:PopFromGeneralChannelEvent");
|
||||||
|
}
|
||||||
|
|
||||||
|
IHomeMenuFunctions::~IHomeMenuFunctions() {
|
||||||
|
service_context.CloseEvent(pop_from_general_channel_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IHomeMenuFunctions::RequestToGetForeground(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushCopyObjects(pop_from_general_channel_event->GetReadableEvent());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,25 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/kernel_helpers.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> {
|
||||||
|
public:
|
||||||
|
explicit IHomeMenuFunctions(Core::System& system_);
|
||||||
|
~IHomeMenuFunctions() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void RequestToGetForeground(HLERequestContext& ctx);
|
||||||
|
void GetPopFromGeneralChannelEvent(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
KernelHelpers::ServiceContext service_context;
|
||||||
|
|
||||||
|
Kernel::KEvent* pop_from_general_channel_event;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,202 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/scope_exit.h"
|
||||||
|
#include "core/hle/service/am/am_results.h"
|
||||||
|
#include "core/hle/service/am/applet_data_broker.h"
|
||||||
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
|
#include "core/hle/service/am/library_applet_accessor.h"
|
||||||
|
#include "core/hle/service/am/storage.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
ILibraryAppletAccessor::ILibraryAppletAccessor(Core::System& system_,
|
||||||
|
std::shared_ptr<AppletDataBroker> broker_,
|
||||||
|
std::shared_ptr<Applet> applet_)
|
||||||
|
: ServiceFramework{system_, "ILibraryAppletAccessor"}, broker{std::move(broker_)},
|
||||||
|
applet{std::move(applet_)} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"},
|
||||||
|
{1, &ILibraryAppletAccessor::IsCompleted, "IsCompleted"},
|
||||||
|
{10, &ILibraryAppletAccessor::Start, "Start"},
|
||||||
|
{20, &ILibraryAppletAccessor::RequestExit, "RequestExit"},
|
||||||
|
{25, nullptr, "Terminate"},
|
||||||
|
{30, &ILibraryAppletAccessor::GetResult, "GetResult"},
|
||||||
|
{50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"},
|
||||||
|
{60, &ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero, "PresetLibraryAppletGpuTimeSliceZero"},
|
||||||
|
{100, &ILibraryAppletAccessor::PushInData, "PushInData"},
|
||||||
|
{101, &ILibraryAppletAccessor::PopOutData, "PopOutData"},
|
||||||
|
{102, nullptr, "PushExtraStorage"},
|
||||||
|
{103, &ILibraryAppletAccessor::PushInteractiveInData, "PushInteractiveInData"},
|
||||||
|
{104, &ILibraryAppletAccessor::PopInteractiveOutData, "PopInteractiveOutData"},
|
||||||
|
{105, &ILibraryAppletAccessor::GetPopOutDataEvent, "GetPopOutDataEvent"},
|
||||||
|
{106, &ILibraryAppletAccessor::GetPopInteractiveOutDataEvent, "GetPopInteractiveOutDataEvent"},
|
||||||
|
{110, nullptr, "NeedsToExitProcess"},
|
||||||
|
{120, nullptr, "GetLibraryAppletInfo"},
|
||||||
|
{150, nullptr, "RequestForAppletToGetForeground"},
|
||||||
|
{160, &ILibraryAppletAccessor::GetIndirectLayerConsumerHandle, "GetIndirectLayerConsumerHandle"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
ILibraryAppletAccessor::~ILibraryAppletAccessor() = default;
|
||||||
|
|
||||||
|
void ILibraryAppletAccessor::GetAppletStateChangedEvent(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushCopyObjects(broker->GetStateChangedEvent().GetHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletAccessor::IsCompleted(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push<u32>(broker->IsCompleted());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletAccessor::GetResult(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(applet->terminate_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletAccessor::Start(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
applet->process->Run();
|
||||||
|
FrontendExecute();
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletAccessor::RequestExit(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
ASSERT(applet != nullptr);
|
||||||
|
applet->message_queue.RequestExit();
|
||||||
|
FrontendRequestExit();
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletAccessor::PushInData(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
broker->GetInData().Push(rp.PopIpcInterface<IStorage>().lock());
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletAccessor::PopOutData(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
std::shared_ptr<IStorage> data;
|
||||||
|
const auto res = broker->GetOutData().Pop(&data);
|
||||||
|
|
||||||
|
if (res.IsSuccess()) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(res);
|
||||||
|
rb.PushIpcInterface(std::move(data));
|
||||||
|
} else {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletAccessor::PushInteractiveInData(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
broker->GetInteractiveInData().Push(rp.PopIpcInterface<IStorage>().lock());
|
||||||
|
FrontendExecuteInteractive();
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletAccessor::PopInteractiveOutData(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
std::shared_ptr<IStorage> data;
|
||||||
|
const auto res = broker->GetInteractiveOutData().Pop(&data);
|
||||||
|
|
||||||
|
if (res.IsSuccess()) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(res);
|
||||||
|
rb.PushIpcInterface(std::move(data));
|
||||||
|
} else {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletAccessor::GetPopOutDataEvent(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushCopyObjects(broker->GetOutData().GetEvent());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletAccessor::GetPopInteractiveOutDataEvent(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushCopyObjects(broker->GetInteractiveOutData().GetEvent());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletAccessor::GetIndirectLayerConsumerHandle(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
// We require a non-zero handle to be valid. Using 0xdeadbeef allows us to trace if this is
|
||||||
|
// actually used anywhere
|
||||||
|
constexpr u64 handle = 0xdeadbeef;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletAccessor::FrontendExecute() {
|
||||||
|
if (applet->frontend) {
|
||||||
|
applet->frontend->Initialize();
|
||||||
|
applet->frontend->Execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletAccessor::FrontendExecuteInteractive() {
|
||||||
|
if (applet->frontend) {
|
||||||
|
applet->frontend->ExecuteInteractive();
|
||||||
|
applet->frontend->Execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletAccessor::FrontendRequestExit() {
|
||||||
|
if (applet->frontend) {
|
||||||
|
applet->frontend->RequestExit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,43 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
class AppletDataBroker;
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
|
class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
|
||||||
|
public:
|
||||||
|
explicit ILibraryAppletAccessor(Core::System& system_,
|
||||||
|
std::shared_ptr<AppletDataBroker> broker_,
|
||||||
|
std::shared_ptr<Applet> applet_);
|
||||||
|
~ILibraryAppletAccessor();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void GetAppletStateChangedEvent(HLERequestContext& ctx);
|
||||||
|
void IsCompleted(HLERequestContext& ctx);
|
||||||
|
void GetResult(HLERequestContext& ctx);
|
||||||
|
void PresetLibraryAppletGpuTimeSliceZero(HLERequestContext& ctx);
|
||||||
|
void Start(HLERequestContext& ctx);
|
||||||
|
void RequestExit(HLERequestContext& ctx);
|
||||||
|
void PushInData(HLERequestContext& ctx);
|
||||||
|
void PopOutData(HLERequestContext& ctx);
|
||||||
|
void PushInteractiveInData(HLERequestContext& ctx);
|
||||||
|
void PopInteractiveOutData(HLERequestContext& ctx);
|
||||||
|
void GetPopOutDataEvent(HLERequestContext& ctx);
|
||||||
|
void GetPopInteractiveOutDataEvent(HLERequestContext& ctx);
|
||||||
|
void GetIndirectLayerConsumerHandle(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
void FrontendExecute();
|
||||||
|
void FrontendExecuteInteractive();
|
||||||
|
void FrontendRequestExit();
|
||||||
|
|
||||||
|
const std::shared_ptr<AppletDataBroker> broker;
|
||||||
|
const std::shared_ptr<Applet> applet;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,271 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/kernel/k_transfer_memory.h"
|
||||||
|
#include "core/hle/service/am/applet_data_broker.h"
|
||||||
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
|
#include "core/hle/service/am/library_applet_accessor.h"
|
||||||
|
#include "core/hle/service/am/library_applet_creator.h"
|
||||||
|
#include "core/hle/service/am/library_applet_storage.h"
|
||||||
|
#include "core/hle/service/am/storage.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
#include "core/hle/service/sm/sm.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] 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;
|
||||||
|
|
||||||
|
// Set focus state
|
||||||
|
switch (mode) {
|
||||||
|
case LibraryAppletMode::AllForeground:
|
||||||
|
case LibraryAppletMode::NoUI:
|
||||||
|
applet->focus_state = FocusState::InFocus;
|
||||||
|
applet->hid_registration.EnableAppletToGetInput(true);
|
||||||
|
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
|
||||||
|
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
||||||
|
break;
|
||||||
|
case LibraryAppletMode::AllForegroundInitiallyHidden:
|
||||||
|
applet->system_buffer_manager.SetWindowVisibility(false);
|
||||||
|
applet->focus_state = FocusState::NotInFocus;
|
||||||
|
applet->hid_registration.EnableAppletToGetInput(false);
|
||||||
|
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
||||||
|
break;
|
||||||
|
case LibraryAppletMode::Background:
|
||||||
|
case LibraryAppletMode::BackgroundIndirectDisplay:
|
||||||
|
default:
|
||||||
|
applet->focus_state = FocusState::Background;
|
||||||
|
applet->hid_registration.EnableAppletToGetInput(true);
|
||||||
|
applet->message_queue.PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto broker = std::make_shared<AppletDataBroker>(system);
|
||||||
|
applet->caller_applet = caller_applet;
|
||||||
|
applet->caller_applet_broker = broker;
|
||||||
|
|
||||||
|
system.GetAppletManager().InsertApplet(applet);
|
||||||
|
|
||||||
|
return std::make_shared<ILibraryAppletAccessor>(system, broker, applet);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(
|
||||||
|
Core::System& system, std::shared_ptr<Applet> caller_applet, AppletId applet_id,
|
||||||
|
LibraryAppletMode mode) {
|
||||||
|
const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id));
|
||||||
|
|
||||||
|
auto process = std::make_unique<Process>(system);
|
||||||
|
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;
|
||||||
|
|
||||||
|
auto storage = std::make_shared<AppletDataBroker>(system);
|
||||||
|
applet->caller_applet = caller_applet;
|
||||||
|
applet->caller_applet_broker = storage;
|
||||||
|
applet->frontend = system.GetFrontendAppletHolder().GetApplet(applet, applet_id, mode);
|
||||||
|
|
||||||
|
return std::make_shared<ILibraryAppletAccessor>(system, storage, applet);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet_)
|
||||||
|
: ServiceFramework{system_, "ILibraryAppletCreator"}, applet{std::move(applet_)} {
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"},
|
||||||
|
{1, nullptr, "TerminateAllLibraryApplets"},
|
||||||
|
{2, nullptr, "AreAnyLibraryAppletsLeft"},
|
||||||
|
{10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"},
|
||||||
|
{11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"},
|
||||||
|
{12, &ILibraryAppletCreator::CreateHandleStorage, "CreateHandleStorage"},
|
||||||
|
};
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
ILibraryAppletCreator::~ILibraryAppletCreator() = default;
|
||||||
|
|
||||||
|
void ILibraryAppletCreator::CreateLibraryApplet(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
|
const auto applet_id = rp.PopRaw<AppletId>();
|
||||||
|
const auto applet_mode = rp.PopRaw<LibraryAppletMode>();
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id,
|
||||||
|
applet_mode);
|
||||||
|
|
||||||
|
auto library_applet = CreateFrontendApplet(system, applet, applet_id, applet_mode);
|
||||||
|
if (!library_applet) {
|
||||||
|
LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultUnknown);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Applet is created, can now be launched.
|
||||||
|
applet->library_applet_launchable_event.Signal();
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<ILibraryAppletAccessor>(library_applet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletCreator::CreateStorage(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
|
const s64 size{rp.Pop<s64>()};
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_AM, "called, size={}", size);
|
||||||
|
|
||||||
|
if (size <= 0) {
|
||||||
|
LOG_ERROR(Service_AM, "size is less than or equal to 0");
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultUnknown);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<u8> data(size);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<IStorage>(system, AM::CreateStorage(std::move(data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletCreator::CreateTransferMemoryStorage(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
|
struct Parameters {
|
||||||
|
bool is_writable;
|
||||||
|
s64 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto params{rp.PopRaw<Parameters>()};
|
||||||
|
const auto handle{ctx.GetCopyHandle(0)};
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_AM, "called, is_writable={}, size={}, handle={:08X}", params.is_writable,
|
||||||
|
params.size, handle);
|
||||||
|
|
||||||
|
if (params.size <= 0) {
|
||||||
|
LOG_ERROR(Service_AM, "size is less than or equal to 0");
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultUnknown);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle);
|
||||||
|
|
||||||
|
if (transfer_mem.IsNull()) {
|
||||||
|
LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultUnknown);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<IStorage>(
|
||||||
|
system, AM::CreateTransferMemoryStorage(ctx.GetMemory(), transfer_mem.GetPointerUnsafe(),
|
||||||
|
params.is_writable, params.size));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
|
const s64 size{rp.Pop<s64>()};
|
||||||
|
const auto handle{ctx.GetCopyHandle(0)};
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_AM, "called, size={}, handle={:08X}", size, handle);
|
||||||
|
|
||||||
|
if (size <= 0) {
|
||||||
|
LOG_ERROR(Service_AM, "size is less than or equal to 0");
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultUnknown);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle);
|
||||||
|
|
||||||
|
if (transfer_mem.IsNull()) {
|
||||||
|
LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultUnknown);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<IStorage>(
|
||||||
|
system, AM::CreateHandleStorage(ctx.GetMemory(), transfer_mem.GetPointerUnsafe(), size));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,26 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
|
class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
|
||||||
|
public:
|
||||||
|
explicit ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet_);
|
||||||
|
~ILibraryAppletCreator() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void CreateLibraryApplet(HLERequestContext& ctx);
|
||||||
|
void CreateStorage(HLERequestContext& ctx);
|
||||||
|
void CreateTransferMemoryStorage(HLERequestContext& ctx);
|
||||||
|
void CreateHandleStorage(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
const std::shared_ptr<Applet> applet;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,143 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/applet_common_functions.h"
|
||||||
|
#include "core/hle/service/am/audio_controller.h"
|
||||||
|
#include "core/hle/service/am/common_state_getter.h"
|
||||||
|
#include "core/hle/service/am/debug_functions.h"
|
||||||
|
#include "core/hle/service/am/display_controller.h"
|
||||||
|
#include "core/hle/service/am/global_state_controller.h"
|
||||||
|
#include "core/hle/service/am/home_menu_functions.h"
|
||||||
|
#include "core/hle/service/am/library_applet_creator.h"
|
||||||
|
#include "core/hle/service/am/library_applet_proxy.h"
|
||||||
|
#include "core/hle/service/am/library_applet_self_accessor.h"
|
||||||
|
#include "core/hle/service/am/process_winding_controller.h"
|
||||||
|
#include "core/hle/service/am/self_controller.h"
|
||||||
|
#include "core/hle/service/am/window_controller.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
ILibraryAppletProxy::ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
||||||
|
std::shared_ptr<Applet> applet_, Core::System& system_)
|
||||||
|
: ServiceFramework{system_, "ILibraryAppletProxy"}, nvnflinger{nvnflinger_}, applet{std::move(
|
||||||
|
applet_)} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
|
||||||
|
{1, &ILibraryAppletProxy::GetSelfController, "GetSelfController"},
|
||||||
|
{2, &ILibraryAppletProxy::GetWindowController, "GetWindowController"},
|
||||||
|
{3, &ILibraryAppletProxy::GetAudioController, "GetAudioController"},
|
||||||
|
{4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"},
|
||||||
|
{10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"},
|
||||||
|
{11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
|
||||||
|
{20, &ILibraryAppletProxy::OpenLibraryAppletSelfAccessor, "OpenLibraryAppletSelfAccessor"},
|
||||||
|
{21, &ILibraryAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"},
|
||||||
|
{22, &ILibraryAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"},
|
||||||
|
{23, &ILibraryAppletProxy::GetGlobalStateController, "GetGlobalStateController"},
|
||||||
|
{1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
ILibraryAppletProxy::~ILibraryAppletProxy() = default;
|
||||||
|
|
||||||
|
void ILibraryAppletProxy::GetCommonStateGetter(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<ICommonStateGetter>(system, applet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletProxy::GetSelfController(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<ISelfController>(system, applet, nvnflinger);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletProxy::GetWindowController(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<IWindowController>(system, applet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletProxy::GetAudioController(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<IAudioController>(system);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletProxy::GetDisplayController(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<IDisplayController>(system, applet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletProxy::GetProcessWindingController(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<IProcessWindingController>(system, applet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletProxy::GetLibraryAppletCreator(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<ILibraryAppletCreator>(system, applet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletProxy::OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system, applet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletProxy::GetAppletCommonFunctions(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<IAppletCommonFunctions>(system, applet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletProxy::GetHomeMenuFunctions(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<IHomeMenuFunctions>(system);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletProxy::GetGlobalStateController(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<IGlobalStateController>(system);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletProxy::GetDebugFunctions(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<IDebugFunctions>(system);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,36 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
|
class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
|
||||||
|
public:
|
||||||
|
explicit ILibraryAppletProxy(Nvnflinger::Nvnflinger& nvnflinger_,
|
||||||
|
std::shared_ptr<Applet> applet_, Core::System& system_);
|
||||||
|
~ILibraryAppletProxy();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void GetCommonStateGetter(HLERequestContext& ctx);
|
||||||
|
void GetSelfController(HLERequestContext& ctx);
|
||||||
|
void GetWindowController(HLERequestContext& ctx);
|
||||||
|
void GetAudioController(HLERequestContext& ctx);
|
||||||
|
void GetDisplayController(HLERequestContext& ctx);
|
||||||
|
void GetProcessWindingController(HLERequestContext& ctx);
|
||||||
|
void GetLibraryAppletCreator(HLERequestContext& ctx);
|
||||||
|
void OpenLibraryAppletSelfAccessor(HLERequestContext& ctx);
|
||||||
|
void GetAppletCommonFunctions(HLERequestContext& ctx);
|
||||||
|
void GetHomeMenuFunctions(HLERequestContext& ctx);
|
||||||
|
void GetGlobalStateController(HLERequestContext& ctx);
|
||||||
|
void GetDebugFunctions(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
Nvnflinger::Nvnflinger& nvnflinger;
|
||||||
|
std::shared_ptr<Applet> applet;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,338 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/scope_exit.h"
|
||||||
|
#include "core/core_timing.h"
|
||||||
|
#include "core/file_sys/control_metadata.h"
|
||||||
|
#include "core/file_sys/patch_manager.h"
|
||||||
|
#include "core/file_sys/registered_cache.h"
|
||||||
|
#include "core/hle/service/acc/profile_manager.h"
|
||||||
|
#include "core/hle/service/am/am_results.h"
|
||||||
|
#include "core/hle/service/am/applet_data_broker.h"
|
||||||
|
#include "core/hle/service/am/applet_manager.h"
|
||||||
|
#include "core/hle/service/am/frontend/applet_cabinet.h"
|
||||||
|
#include "core/hle/service/am/frontend/applet_controller.h"
|
||||||
|
#include "core/hle/service/am/frontend/applet_mii_edit_types.h"
|
||||||
|
#include "core/hle/service/am/frontend/applet_software_keyboard_types.h"
|
||||||
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
|
#include "core/hle/service/am/library_applet_self_accessor.h"
|
||||||
|
#include "core/hle/service/am/storage.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
#include "core/hle/service/ns/ns.h"
|
||||||
|
#include "core/hle/service/sm/sm.h"
|
||||||
|
#include "hid_core/hid_types.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
AppletIdentityInfo GetCallerIdentity(std::shared_ptr<Applet> applet) {
|
||||||
|
if (const auto caller_applet = applet->caller_applet.lock(); caller_applet) {
|
||||||
|
// TODO: is this actually the application ID?
|
||||||
|
return {
|
||||||
|
.applet_id = caller_applet->applet_id,
|
||||||
|
.application_id = caller_applet->program_id,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
.applet_id = AppletId::QLaunch,
|
||||||
|
.application_id = 0x0100000000001000ull,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_,
|
||||||
|
std::shared_ptr<Applet> applet_)
|
||||||
|
: ServiceFramework{system_, "ILibraryAppletSelfAccessor"}, applet{std::move(applet_)},
|
||||||
|
broker{applet->caller_applet_broker} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, &ILibraryAppletSelfAccessor::PopInData, "PopInData"},
|
||||||
|
{1, &ILibraryAppletSelfAccessor::PushOutData, "PushOutData"},
|
||||||
|
{2, &ILibraryAppletSelfAccessor::PopInteractiveInData, "PopInteractiveInData"},
|
||||||
|
{3, &ILibraryAppletSelfAccessor::PushInteractiveOutData, "PushInteractiveOutData"},
|
||||||
|
{5, &ILibraryAppletSelfAccessor::GetPopInDataEvent, "GetPopInDataEvent"},
|
||||||
|
{6, &ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent, "GetPopInteractiveInDataEvent"},
|
||||||
|
{10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"},
|
||||||
|
{11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"},
|
||||||
|
{12, &ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo, "GetMainAppletIdentityInfo"},
|
||||||
|
{13, &ILibraryAppletSelfAccessor::CanUseApplicationCore, "CanUseApplicationCore"},
|
||||||
|
{14, &ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo, "GetCallerAppletIdentityInfo"},
|
||||||
|
{15, nullptr, "GetMainAppletApplicationControlProperty"},
|
||||||
|
{16, nullptr, "GetMainAppletStorageId"},
|
||||||
|
{17, nullptr, "GetCallerAppletIdentityInfoStack"},
|
||||||
|
{18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"},
|
||||||
|
{19, &ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout, "GetDesirableKeyboardLayout"},
|
||||||
|
{20, nullptr, "PopExtraStorage"},
|
||||||
|
{25, nullptr, "GetPopExtraStorageEvent"},
|
||||||
|
{30, nullptr, "UnpopInData"},
|
||||||
|
{31, nullptr, "UnpopExtraStorage"},
|
||||||
|
{40, nullptr, "GetIndirectLayerProducerHandle"},
|
||||||
|
{50, nullptr, "ReportVisibleError"},
|
||||||
|
{51, nullptr, "ReportVisibleErrorWithErrorContext"},
|
||||||
|
{60, &ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage, "GetMainAppletApplicationDesiredLanguage"},
|
||||||
|
{70, &ILibraryAppletSelfAccessor::GetCurrentApplicationId, "GetCurrentApplicationId"},
|
||||||
|
{80, nullptr, "RequestExitToSelf"},
|
||||||
|
{90, nullptr, "CreateApplicationAndPushAndRequestToLaunch"},
|
||||||
|
{100, nullptr, "CreateGameMovieTrimmer"},
|
||||||
|
{101, nullptr, "ReserveResourceForMovieOperation"},
|
||||||
|
{102, nullptr, "UnreserveResourceForMovieOperation"},
|
||||||
|
{110, &ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers, "GetMainAppletAvailableUsers"},
|
||||||
|
{120, nullptr, "GetLaunchStorageInfoForDebug"},
|
||||||
|
{130, nullptr, "GetGpuErrorDetectedSystemEvent"},
|
||||||
|
{140, nullptr, "SetApplicationMemoryReservation"},
|
||||||
|
{150, &ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually, "ShouldSetGpuTimeSliceManually"},
|
||||||
|
{160, &ILibraryAppletSelfAccessor::Cmd160, "Cmd160"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default;
|
||||||
|
|
||||||
|
void ILibraryAppletSelfAccessor::PopInData(HLERequestContext& ctx) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
|
||||||
|
std::shared_ptr<IStorage> data;
|
||||||
|
const auto res = broker->GetInData().Pop(&data);
|
||||||
|
|
||||||
|
if (res.IsSuccess()) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(res);
|
||||||
|
rb.PushIpcInterface(std::move(data));
|
||||||
|
} else {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletSelfAccessor::PushOutData(HLERequestContext& ctx) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
broker->GetOutData().Push(rp.PopIpcInterface<IStorage>().lock());
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletSelfAccessor::PopInteractiveInData(HLERequestContext& ctx) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
|
||||||
|
std::shared_ptr<IStorage> data;
|
||||||
|
const auto res = broker->GetInteractiveInData().Pop(&data);
|
||||||
|
|
||||||
|
if (res.IsSuccess()) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(res);
|
||||||
|
rb.PushIpcInterface(std::move(data));
|
||||||
|
} else {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletSelfAccessor::PushInteractiveOutData(HLERequestContext& ctx) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
broker->GetInteractiveOutData().Push(rp.PopIpcInterface<IStorage>().lock());
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletSelfAccessor::GetPopInDataEvent(HLERequestContext& ctx) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushCopyObjects(broker->GetInData().GetEvent());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletSelfAccessor::GetPopInteractiveInDataEvent(HLERequestContext& ctx) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushCopyObjects(broker->GetInteractiveInData().GetEvent());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletSelfAccessor::ExitProcessAndReturn(HLERequestContext& ctx) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
|
||||||
|
system.GetAppletManager().TerminateAndRemoveApplet(applet->aruid);
|
||||||
|
broker->SignalCompletion();
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) {
|
||||||
|
struct LibraryAppletInfo {
|
||||||
|
AppletId applet_id;
|
||||||
|
LibraryAppletMode library_applet_mode;
|
||||||
|
};
|
||||||
|
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
const LibraryAppletInfo applet_info{
|
||||||
|
.applet_id = applet->applet_id,
|
||||||
|
.library_applet_mode = applet->library_applet_mode,
|
||||||
|
};
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushRaw(applet_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletSelfAccessor::GetMainAppletIdentityInfo(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
const AppletIdentityInfo applet_info{
|
||||||
|
.applet_id = AppletId::QLaunch,
|
||||||
|
.application_id = 0x0100000000001000ull,
|
||||||
|
};
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 6};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushRaw(applet_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletSelfAccessor::CanUseApplicationCore(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
// TODO: This appears to read the NPDM from state and check the core mask of the applet.
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push<u8>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 6};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushRaw(GetCallerIdentity(applet));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push<u32>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage(HLERequestContext& ctx) {
|
||||||
|
// FIXME: this is copied from IApplicationFunctions::GetDesiredLanguage
|
||||||
|
auto identity = GetCallerIdentity(applet);
|
||||||
|
|
||||||
|
// TODO(bunnei): This should be configurable
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
// Get supported languages from NACP, if possible
|
||||||
|
// Default to 0 (all languages supported)
|
||||||
|
u32 supported_languages = 0;
|
||||||
|
|
||||||
|
const auto res = [this, identity] {
|
||||||
|
const FileSys::PatchManager pm{identity.application_id, system.GetFileSystemController(),
|
||||||
|
system.GetContentProvider()};
|
||||||
|
auto metadata = pm.GetControlMetadata();
|
||||||
|
if (metadata.first != nullptr) {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(identity.application_id),
|
||||||
|
system.GetFileSystemController(),
|
||||||
|
system.GetContentProvider()};
|
||||||
|
return pm_update.GetControlMetadata();
|
||||||
|
}();
|
||||||
|
|
||||||
|
if (res.first != nullptr) {
|
||||||
|
supported_languages = res.first->GetSupportedLanguages();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call IApplicationManagerInterface implementation.
|
||||||
|
auto& service_manager = system.ServiceManager();
|
||||||
|
auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2");
|
||||||
|
auto app_man = ns_am2->GetApplicationManagerInterface();
|
||||||
|
|
||||||
|
// Get desired application language
|
||||||
|
u8 desired_language{};
|
||||||
|
const auto res_lang =
|
||||||
|
app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages);
|
||||||
|
if (res_lang != ResultSuccess) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(res_lang);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to settings language code.
|
||||||
|
u64 language_code{};
|
||||||
|
const auto res_code =
|
||||||
|
app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language);
|
||||||
|
if (res_code != ResultSuccess) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(res_code);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push(language_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletSelfAccessor::GetCurrentApplicationId(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
u64 application_id = 0;
|
||||||
|
if (auto caller_applet = applet->caller_applet.lock(); caller_applet) {
|
||||||
|
application_id = caller_applet->program_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push(application_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(HLERequestContext& ctx) {
|
||||||
|
const Service::Account::ProfileManager manager{};
|
||||||
|
bool is_empty{true};
|
||||||
|
s32 user_count{-1};
|
||||||
|
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
|
||||||
|
if (manager.GetUserCount() > 0) {
|
||||||
|
is_empty = false;
|
||||||
|
user_count = static_cast<s32>(manager.GetUserCount());
|
||||||
|
ctx.WriteBuffer(manager.GetAllUsers());
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push<u8>(is_empty);
|
||||||
|
rb.Push(user_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push<u8>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILibraryAppletSelfAccessor::Cmd160(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push<u64>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,44 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
class AppletDataBroker;
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
|
class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> {
|
||||||
|
public:
|
||||||
|
explicit ILibraryAppletSelfAccessor(Core::System& system_, std::shared_ptr<Applet> applet_);
|
||||||
|
~ILibraryAppletSelfAccessor() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void PopInData(HLERequestContext& ctx);
|
||||||
|
void PushOutData(HLERequestContext& ctx);
|
||||||
|
void PopInteractiveInData(HLERequestContext& ctx);
|
||||||
|
void PushInteractiveOutData(HLERequestContext& ctx);
|
||||||
|
void GetPopInDataEvent(HLERequestContext& ctx);
|
||||||
|
void GetPopInteractiveInDataEvent(HLERequestContext& ctx);
|
||||||
|
void GetLibraryAppletInfo(HLERequestContext& ctx);
|
||||||
|
void GetMainAppletIdentityInfo(HLERequestContext& ctx);
|
||||||
|
void CanUseApplicationCore(HLERequestContext& ctx);
|
||||||
|
void ExitProcessAndReturn(HLERequestContext& ctx);
|
||||||
|
void GetCallerAppletIdentityInfo(HLERequestContext& ctx);
|
||||||
|
void GetDesirableKeyboardLayout(HLERequestContext& ctx);
|
||||||
|
void GetMainAppletApplicationDesiredLanguage(HLERequestContext& ctx);
|
||||||
|
void GetCurrentApplicationId(HLERequestContext& ctx);
|
||||||
|
void GetMainAppletAvailableUsers(HLERequestContext& ctx);
|
||||||
|
void ShouldSetGpuTimeSliceManually(HLERequestContext& ctx);
|
||||||
|
void Cmd160(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
const std::shared_ptr<Applet> applet;
|
||||||
|
const std::shared_ptr<AppletDataBroker> broker;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,140 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/kernel/k_transfer_memory.h"
|
||||||
|
#include "core/hle/service/am/am_results.h"
|
||||||
|
#include "core/hle/service/am/library_applet_storage.h"
|
||||||
|
#include "core/memory.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
Result ValidateOffset(s64 offset, size_t size, size_t data_size) {
|
||||||
|
R_UNLESS(offset >= 0, AM::ResultInvalidOffset);
|
||||||
|
|
||||||
|
const size_t begin = offset;
|
||||||
|
const size_t end = begin + size;
|
||||||
|
|
||||||
|
R_UNLESS(begin <= end && end <= data_size, AM::ResultInvalidOffset);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
class BufferLibraryAppletStorage final : public LibraryAppletStorage {
|
||||||
|
public:
|
||||||
|
explicit BufferLibraryAppletStorage(std::vector<u8>&& data) : m_data(std::move(data)) {}
|
||||||
|
~BufferLibraryAppletStorage() = default;
|
||||||
|
|
||||||
|
Result Read(s64 offset, void* buffer, size_t size) override {
|
||||||
|
R_TRY(ValidateOffset(offset, size, m_data.size()));
|
||||||
|
|
||||||
|
std::memcpy(buffer, m_data.data() + offset, size);
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result Write(s64 offset, const void* buffer, size_t size) override {
|
||||||
|
R_TRY(ValidateOffset(offset, size, m_data.size()));
|
||||||
|
|
||||||
|
std::memcpy(m_data.data() + offset, buffer, size);
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
s64 GetSize() override {
|
||||||
|
return m_data.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
Kernel::KTransferMemory* GetHandle() override {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<u8> m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TransferMemoryLibraryAppletStorage : public LibraryAppletStorage {
|
||||||
|
public:
|
||||||
|
explicit TransferMemoryLibraryAppletStorage(Core::Memory::Memory& memory,
|
||||||
|
Kernel::KTransferMemory* trmem, bool is_writable,
|
||||||
|
s64 size)
|
||||||
|
: m_memory(memory), m_trmem(trmem), m_is_writable(is_writable), m_size(size) {
|
||||||
|
m_trmem->Open();
|
||||||
|
}
|
||||||
|
|
||||||
|
~TransferMemoryLibraryAppletStorage() {
|
||||||
|
m_trmem->Close();
|
||||||
|
m_trmem = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result Read(s64 offset, void* buffer, size_t size) override {
|
||||||
|
R_TRY(ValidateOffset(offset, size, m_size));
|
||||||
|
|
||||||
|
m_memory.ReadBlock(m_trmem->GetSourceAddress(), buffer, size);
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result Write(s64 offset, const void* buffer, size_t size) override {
|
||||||
|
R_UNLESS(m_is_writable, ResultUnknown);
|
||||||
|
R_TRY(ValidateOffset(offset, size, m_size));
|
||||||
|
|
||||||
|
m_memory.WriteBlock(m_trmem->GetSourceAddress(), buffer, size);
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
s64 GetSize() override {
|
||||||
|
return m_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
Kernel::KTransferMemory* GetHandle() override {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Core::Memory::Memory& m_memory;
|
||||||
|
Kernel::KTransferMemory* m_trmem;
|
||||||
|
bool m_is_writable;
|
||||||
|
s64 m_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
class HandleLibraryAppletStorage : public TransferMemoryLibraryAppletStorage {
|
||||||
|
public:
|
||||||
|
explicit HandleLibraryAppletStorage(Core::Memory::Memory& memory,
|
||||||
|
Kernel::KTransferMemory* trmem, s64 size)
|
||||||
|
: TransferMemoryLibraryAppletStorage(memory, trmem, true, size) {}
|
||||||
|
~HandleLibraryAppletStorage() = default;
|
||||||
|
|
||||||
|
Kernel::KTransferMemory* GetHandle() override {
|
||||||
|
return m_trmem;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
LibraryAppletStorage::~LibraryAppletStorage() = default;
|
||||||
|
|
||||||
|
std::vector<u8> LibraryAppletStorage::GetData() {
|
||||||
|
std::vector<u8> data(this->GetSize());
|
||||||
|
this->Read(0, data.data(), data.size());
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<LibraryAppletStorage> CreateStorage(std::vector<u8>&& data) {
|
||||||
|
return std::make_shared<BufferLibraryAppletStorage>(std::move(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<LibraryAppletStorage> CreateTransferMemoryStorage(Core::Memory::Memory& memory,
|
||||||
|
Kernel::KTransferMemory* trmem,
|
||||||
|
bool is_writable, s64 size) {
|
||||||
|
return std::make_shared<TransferMemoryLibraryAppletStorage>(memory, trmem, is_writable, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<LibraryAppletStorage> CreateHandleStorage(Core::Memory::Memory& memory,
|
||||||
|
Kernel::KTransferMemory* trmem,
|
||||||
|
s64 size) {
|
||||||
|
return std::make_shared<HandleLibraryAppletStorage>(memory, trmem, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,36 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Core::Memory {
|
||||||
|
class Memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
class KTransferMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
class LibraryAppletStorage {
|
||||||
|
public:
|
||||||
|
virtual ~LibraryAppletStorage();
|
||||||
|
virtual Result Read(s64 offset, void* buffer, size_t size) = 0;
|
||||||
|
virtual Result Write(s64 offset, const void* buffer, size_t size) = 0;
|
||||||
|
virtual s64 GetSize() = 0;
|
||||||
|
virtual Kernel::KTransferMemory* GetHandle() = 0;
|
||||||
|
|
||||||
|
std::vector<u8> GetData();
|
||||||
|
};
|
||||||
|
|
||||||
|
std::shared_ptr<LibraryAppletStorage> CreateStorage(std::vector<u8>&& data);
|
||||||
|
std::shared_ptr<LibraryAppletStorage> CreateTransferMemoryStorage(Core::Memory::Memory& memory,
|
||||||
|
Kernel::KTransferMemory* trmem,
|
||||||
|
bool is_writable, s64 size);
|
||||||
|
std::shared_ptr<LibraryAppletStorage> CreateHandleStorage(Core::Memory::Memory& memory,
|
||||||
|
Kernel::KTransferMemory* trmem, s64 size);
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,71 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/lock_accessor.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
ILockAccessor::ILockAccessor(Core::System& system_)
|
||||||
|
: ServiceFramework{system_, "ILockAccessor"}, service_context{system_, "ILockAccessor"} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{1, &ILockAccessor::TryLock, "TryLock"},
|
||||||
|
{2, &ILockAccessor::Unlock, "Unlock"},
|
||||||
|
{3, &ILockAccessor::GetEvent, "GetEvent"},
|
||||||
|
{4,&ILockAccessor::IsLocked, "IsLocked"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
|
||||||
|
lock_event = service_context.CreateEvent("ILockAccessor::LockEvent");
|
||||||
|
}
|
||||||
|
|
||||||
|
ILockAccessor::~ILockAccessor() {
|
||||||
|
service_context.CloseEvent(lock_event);
|
||||||
|
};
|
||||||
|
|
||||||
|
void ILockAccessor::TryLock(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
const auto return_handle = rp.Pop<bool>();
|
||||||
|
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called, return_handle={}", return_handle);
|
||||||
|
|
||||||
|
// TODO: When return_handle is true this function should return the lock handle
|
||||||
|
|
||||||
|
is_locked = true;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push<u8>(is_locked);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILockAccessor::Unlock(HLERequestContext& ctx) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
|
||||||
|
is_locked = false;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILockAccessor::GetEvent(HLERequestContext& ctx) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
|
||||||
|
lock_event->Signal();
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushCopyObjects(lock_event->GetReadableEvent());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ILockAccessor::IsLocked(HLERequestContext& ctx) {
|
||||||
|
LOG_INFO(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push<u8>(is_locked);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,28 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/kernel_helpers.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
class ILockAccessor final : public ServiceFramework<ILockAccessor> {
|
||||||
|
public:
|
||||||
|
explicit ILockAccessor(Core::System& system_);
|
||||||
|
~ILockAccessor() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void TryLock(HLERequestContext& ctx);
|
||||||
|
void Unlock(HLERequestContext& ctx);
|
||||||
|
void GetEvent(HLERequestContext& ctx);
|
||||||
|
void IsLocked(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
bool is_locked{};
|
||||||
|
|
||||||
|
Kernel::KEvent* lock_event;
|
||||||
|
KernelHelpers::ServiceContext service_context;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,59 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/managed_layer_holder.h"
|
||||||
|
#include "core/hle/service/nvnflinger/nvnflinger.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
ManagedLayerHolder::ManagedLayerHolder() = default;
|
||||||
|
ManagedLayerHolder::~ManagedLayerHolder() {
|
||||||
|
if (!m_nvnflinger) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& layer : m_managed_display_layers) {
|
||||||
|
m_nvnflinger->DestroyLayer(layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& layer : m_managed_display_recording_layers) {
|
||||||
|
m_nvnflinger->DestroyLayer(layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_nvnflinger = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ManagedLayerHolder::Initialize(Nvnflinger::Nvnflinger* nvnflinger) {
|
||||||
|
m_nvnflinger = nvnflinger;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ManagedLayerHolder::CreateManagedDisplayLayer(u64* out_layer) {
|
||||||
|
// TODO(Subv): Find out how AM determines the display to use, for now just
|
||||||
|
// create the layer in the Default display.
|
||||||
|
const auto display_id = m_nvnflinger->OpenDisplay("Default");
|
||||||
|
const auto layer_id = m_nvnflinger->CreateLayer(*display_id);
|
||||||
|
|
||||||
|
m_managed_display_layers.emplace(*layer_id);
|
||||||
|
|
||||||
|
*out_layer = *layer_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ManagedLayerHolder::CreateManagedDisplaySeparableLayer(u64* out_layer,
|
||||||
|
u64* out_recording_layer) {
|
||||||
|
// TODO(Subv): Find out how AM determines the display to use, for now just
|
||||||
|
// create the layer in the Default display.
|
||||||
|
// This calls nn::vi::CreateRecordingLayer() which creates another layer.
|
||||||
|
// Currently we do not support more than 1 layer per display, output 1 layer id for now.
|
||||||
|
// Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse
|
||||||
|
// side effects.
|
||||||
|
// TODO: Support multiple layers
|
||||||
|
const auto display_id = m_nvnflinger->OpenDisplay("Default");
|
||||||
|
const auto layer_id = m_nvnflinger->CreateLayer(*display_id);
|
||||||
|
|
||||||
|
m_managed_display_layers.emplace(*layer_id);
|
||||||
|
|
||||||
|
*out_layer = *layer_id;
|
||||||
|
*out_recording_layer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,32 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include "common/common_funcs.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
namespace Service::Nvnflinger {
|
||||||
|
class Nvnflinger;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
class ManagedLayerHolder {
|
||||||
|
public:
|
||||||
|
ManagedLayerHolder();
|
||||||
|
~ManagedLayerHolder();
|
||||||
|
|
||||||
|
void Initialize(Nvnflinger::Nvnflinger* nvnflinger);
|
||||||
|
void CreateManagedDisplayLayer(u64* out_layer);
|
||||||
|
void CreateManagedDisplaySeparableLayer(u64* out_layer, u64* out_recording_layer);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Nvnflinger::Nvnflinger* m_nvnflinger{};
|
||||||
|
std::set<u64> m_managed_display_layers{};
|
||||||
|
std::set<u64> m_managed_display_recording_layers{};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,138 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/scope_exit.h"
|
||||||
|
|
||||||
|
#include "core/file_sys/nca_metadata.h"
|
||||||
|
#include "core/file_sys/registered_cache.h"
|
||||||
|
#include "core/hle/kernel/k_process.h"
|
||||||
|
#include "core/hle/service/am/process.h"
|
||||||
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||||
|
#include "core/loader/loader.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
Process::Process(Core::System& system)
|
||||||
|
: m_system(system), m_process(), m_main_thread_priority(), m_main_thread_stack_size(),
|
||||||
|
m_program_id(), m_process_started() {}
|
||||||
|
|
||||||
|
Process::~Process() {
|
||||||
|
this->Finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Process::Initialize(u64 program_id) {
|
||||||
|
// First, ensure we are not holding another process.
|
||||||
|
this->Finalize();
|
||||||
|
|
||||||
|
// Get the filesystem controller.
|
||||||
|
auto& fsc = m_system.GetFileSystemController();
|
||||||
|
|
||||||
|
// Attempt to load program NCA.
|
||||||
|
const FileSys::RegisteredCache* bis_system{};
|
||||||
|
FileSys::VirtualFile nca{};
|
||||||
|
|
||||||
|
// Get the program NCA from built-in storage.
|
||||||
|
bis_system = fsc.GetSystemNANDContents();
|
||||||
|
if (bis_system) {
|
||||||
|
nca = bis_system->GetEntryRaw(program_id, FileSys::ContentRecordType::Program);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure we retrieved a program NCA.
|
||||||
|
if (!nca) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the appropriate loader to parse this NCA.
|
||||||
|
auto app_loader = Loader::GetLoader(m_system, nca, program_id, 0);
|
||||||
|
|
||||||
|
// Ensure we have a loader which can parse the NCA.
|
||||||
|
if (!app_loader) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the process.
|
||||||
|
auto* const process = Kernel::KProcess::Create(m_system.Kernel());
|
||||||
|
Kernel::KProcess::Register(m_system.Kernel(), process);
|
||||||
|
|
||||||
|
// On exit, ensure we free the additional reference to the process.
|
||||||
|
SCOPE_EXIT({ process->Close(); });
|
||||||
|
|
||||||
|
// Insert process modules into memory.
|
||||||
|
const auto [load_result, load_parameters] = app_loader->Load(*process, m_system);
|
||||||
|
|
||||||
|
// Ensure loading was successful.
|
||||||
|
if (load_result != Loader::ResultStatus::Success) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: remove this, kernel already tracks this
|
||||||
|
m_system.Kernel().AppendNewProcess(process);
|
||||||
|
|
||||||
|
// Note the load parameters from NPDM.
|
||||||
|
m_main_thread_priority = load_parameters->main_thread_priority;
|
||||||
|
m_main_thread_stack_size = load_parameters->main_thread_stack_size;
|
||||||
|
|
||||||
|
// This process has not started yet.
|
||||||
|
m_process_started = false;
|
||||||
|
|
||||||
|
// Take ownership of the process object.
|
||||||
|
m_process = process;
|
||||||
|
m_process->Open();
|
||||||
|
|
||||||
|
// We succeeded.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Process::Finalize() {
|
||||||
|
// Terminate, if we are currently holding a process.
|
||||||
|
this->Terminate();
|
||||||
|
|
||||||
|
// Close the process.
|
||||||
|
if (m_process) {
|
||||||
|
m_process->Close();
|
||||||
|
|
||||||
|
// TODO: remove this, kernel already tracks this
|
||||||
|
m_system.Kernel().RemoveProcess(m_process);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up.
|
||||||
|
m_process = nullptr;
|
||||||
|
m_main_thread_priority = 0;
|
||||||
|
m_main_thread_stack_size = 0;
|
||||||
|
m_program_id = 0;
|
||||||
|
m_process_started = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Process::Run() {
|
||||||
|
// If we already started the process, don't start again.
|
||||||
|
if (m_process_started) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start.
|
||||||
|
if (m_process) {
|
||||||
|
m_process->Run(m_main_thread_priority, m_main_thread_stack_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark as started.
|
||||||
|
m_process_started = true;
|
||||||
|
|
||||||
|
// We succeeded.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Process::Terminate() {
|
||||||
|
if (m_process) {
|
||||||
|
m_process->Terminate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 Process::GetProcessId() const {
|
||||||
|
if (m_process) {
|
||||||
|
return m_process->GetProcessId();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,50 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/common_funcs.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
class KProcess;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
class Process {
|
||||||
|
public:
|
||||||
|
explicit Process(Core::System& system);
|
||||||
|
~Process();
|
||||||
|
|
||||||
|
bool Initialize(u64 program_id);
|
||||||
|
void Finalize();
|
||||||
|
|
||||||
|
bool Run();
|
||||||
|
void Terminate();
|
||||||
|
|
||||||
|
bool IsInitialized() const {
|
||||||
|
return m_process != nullptr;
|
||||||
|
}
|
||||||
|
u64 GetProcessId() const;
|
||||||
|
u64 GetProgramId() const {
|
||||||
|
return m_program_id;
|
||||||
|
}
|
||||||
|
Kernel::KProcess* GetProcess() const {
|
||||||
|
return m_process;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Core::System& m_system;
|
||||||
|
Kernel::KProcess* m_process{};
|
||||||
|
s32 m_main_thread_priority{};
|
||||||
|
u64 m_main_thread_stack_size{};
|
||||||
|
u64 m_program_id{};
|
||||||
|
bool m_process_started{};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,56 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
|
#include "core/hle/service/am/library_applet_accessor.h"
|
||||||
|
#include "core/hle/service/am/process_winding_controller.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
IProcessWindingController::IProcessWindingController(Core::System& system_,
|
||||||
|
std::shared_ptr<Applet> applet_)
|
||||||
|
: ServiceFramework{system_, "IProcessWindingController"}, applet{std::move(applet_)} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, &IProcessWindingController::GetLaunchReason, "GetLaunchReason"},
|
||||||
|
{11, &IProcessWindingController::OpenCallingLibraryApplet, "OpenCallingLibraryApplet"},
|
||||||
|
{21, nullptr, "PushContext"},
|
||||||
|
{22, nullptr, "PopContext"},
|
||||||
|
{23, nullptr, "CancelWindingReservation"},
|
||||||
|
{30, nullptr, "WindAndDoReserved"},
|
||||||
|
{40, nullptr, "ReserveToStartAndWaitAndUnwindThis"},
|
||||||
|
{41, nullptr, "ReserveToStartAndWait"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
IProcessWindingController::~IProcessWindingController() = default;
|
||||||
|
|
||||||
|
void IProcessWindingController::GetLaunchReason(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushRaw(applet->launch_reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) {
|
||||||
|
const auto caller_applet = applet->caller_applet.lock();
|
||||||
|
if (caller_applet == nullptr) {
|
||||||
|
LOG_ERROR(Service_AM, "No calling applet available");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultUnknown);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet->caller_applet_broker,
|
||||||
|
caller_applet);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,24 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
|
class IProcessWindingController final : public ServiceFramework<IProcessWindingController> {
|
||||||
|
public:
|
||||||
|
explicit IProcessWindingController(Core::System& system_, std::shared_ptr<Applet> applet_);
|
||||||
|
~IProcessWindingController() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void GetLaunchReason(HLERequestContext& ctx);
|
||||||
|
void OpenCallingLibraryApplet(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
const std::shared_ptr<Applet> applet;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,456 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/am_results.h"
|
||||||
|
#include "core/hle/service/am/frontend/applets.h"
|
||||||
|
#include "core/hle/service/am/self_controller.h"
|
||||||
|
#include "core/hle/service/caps/caps_su.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
|
||||||
|
#include "core/hle/service/nvnflinger/nvnflinger.h"
|
||||||
|
#include "core/hle/service/sm/sm.h"
|
||||||
|
#include "core/hle/service/vi/vi_results.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet> applet_,
|
||||||
|
Nvnflinger::Nvnflinger& nvnflinger_)
|
||||||
|
: ServiceFramework{system_, "ISelfController"}, nvnflinger{nvnflinger_}, applet{std::move(
|
||||||
|
applet_)} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, &ISelfController::Exit, "Exit"},
|
||||||
|
{1, &ISelfController::LockExit, "LockExit"},
|
||||||
|
{2, &ISelfController::UnlockExit, "UnlockExit"},
|
||||||
|
{3, &ISelfController::EnterFatalSection, "EnterFatalSection"},
|
||||||
|
{4, &ISelfController::LeaveFatalSection, "LeaveFatalSection"},
|
||||||
|
{9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"},
|
||||||
|
{10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"},
|
||||||
|
{11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"},
|
||||||
|
{12, &ISelfController::SetPerformanceModeChangedNotification, "SetPerformanceModeChangedNotification"},
|
||||||
|
{13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"},
|
||||||
|
{14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"},
|
||||||
|
{15, &ISelfController::SetScreenShotAppletIdentityInfo, "SetScreenShotAppletIdentityInfo"},
|
||||||
|
{16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"},
|
||||||
|
{17, nullptr, "SetControllerFirmwareUpdateSection"},
|
||||||
|
{18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"},
|
||||||
|
{19, &ISelfController::SetAlbumImageOrientation, "SetAlbumImageOrientation"},
|
||||||
|
{20, nullptr, "SetDesirableKeyboardLayout"},
|
||||||
|
{21, nullptr, "GetScreenShotProgramId"},
|
||||||
|
{40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
|
||||||
|
{41, &ISelfController::IsSystemBufferSharingEnabled, "IsSystemBufferSharingEnabled"},
|
||||||
|
{42, &ISelfController::GetSystemSharedLayerHandle, "GetSystemSharedLayerHandle"},
|
||||||
|
{43, &ISelfController::GetSystemSharedBufferHandle, "GetSystemSharedBufferHandle"},
|
||||||
|
{44, &ISelfController::CreateManagedDisplaySeparableLayer, "CreateManagedDisplaySeparableLayer"},
|
||||||
|
{45, nullptr, "SetManagedDisplayLayerSeparationMode"},
|
||||||
|
{46, nullptr, "SetRecordingLayerCompositionEnabled"},
|
||||||
|
{50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"},
|
||||||
|
{51, &ISelfController::ApproveToDisplay, "ApproveToDisplay"},
|
||||||
|
{60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"},
|
||||||
|
{61, nullptr, "SetMediaPlaybackState"},
|
||||||
|
{62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"},
|
||||||
|
{63, &ISelfController::GetIdleTimeDetectionExtension, "GetIdleTimeDetectionExtension"},
|
||||||
|
{64, nullptr, "SetInputDetectionSourceSet"},
|
||||||
|
{65, &ISelfController::ReportUserIsActive, "ReportUserIsActive"},
|
||||||
|
{66, nullptr, "GetCurrentIlluminance"},
|
||||||
|
{67, nullptr, "IsIlluminanceAvailable"},
|
||||||
|
{68, &ISelfController::SetAutoSleepDisabled, "SetAutoSleepDisabled"},
|
||||||
|
{69, &ISelfController::IsAutoSleepDisabled, "IsAutoSleepDisabled"},
|
||||||
|
{70, nullptr, "ReportMultimediaError"},
|
||||||
|
{71, nullptr, "GetCurrentIlluminanceEx"},
|
||||||
|
{72, nullptr, "SetInputDetectionPolicy"},
|
||||||
|
{80, nullptr, "SetWirelessPriorityMode"},
|
||||||
|
{90, &ISelfController::GetAccumulatedSuspendedTickValue, "GetAccumulatedSuspendedTickValue"},
|
||||||
|
{91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"},
|
||||||
|
{100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"},
|
||||||
|
{110, nullptr, "SetApplicationAlbumUserData"},
|
||||||
|
{120, &ISelfController::SaveCurrentScreenshot, "SaveCurrentScreenshot"},
|
||||||
|
{130, &ISelfController::SetRecordVolumeMuted, "SetRecordVolumeMuted"},
|
||||||
|
{1000, nullptr, "GetDebugStorageChannel"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
ISelfController::~ISelfController() = default;
|
||||||
|
|
||||||
|
void ISelfController::Exit(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
system.Exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::LockExit(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
system.SetExitLocked(true);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::UnlockExit(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
system.SetExitLocked(false);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
|
||||||
|
if (system.GetExitRequested()) {
|
||||||
|
system.Exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::EnterFatalSection(HLERequestContext& ctx) {
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->fatal_section_count++;
|
||||||
|
LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", applet->fatal_section_count);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::LeaveFatalSection(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called.");
|
||||||
|
|
||||||
|
// Entry and exit of fatal sections must be balanced.
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
if (applet->fatal_section_count == 0) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(AM::ResultFatalSectionCountImbalance);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
applet->fatal_section_count--;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::GetLibraryAppletLaunchableEvent(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
applet->library_applet_launchable_event.Signal();
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushCopyObjects(applet->library_applet_launchable_event.GetHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::SetScreenShotPermission(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
const auto permission = rp.PopEnum<ScreenshotPermission>();
|
||||||
|
LOG_DEBUG(Service_AM, "called, permission={}", permission);
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->screenshot_permission = permission;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::SetOperationModeChangedNotification(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
|
const bool notification_enabled = rp.Pop<bool>();
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called notification_enabled={}", notification_enabled);
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->operation_mode_changed_notification_enabled = notification_enabled;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::SetPerformanceModeChangedNotification(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
|
const bool notification_enabled = rp.Pop<bool>();
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called notification_enabled={}", notification_enabled);
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->performance_mode_changed_notification_enabled = notification_enabled;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::SetFocusHandlingMode(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
|
const auto flags = rp.PopRaw<FocusHandlingMode>();
|
||||||
|
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called. unknown0={}, unknown1={}, unknown2={}",
|
||||||
|
flags.unknown0, flags.unknown1, flags.unknown2);
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->focus_handling_mode = flags;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::SetRestartMessageEnabled(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->restart_message_enabled = true;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::SetScreenShotAppletIdentityInfo(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->screen_shot_identity = rp.PopRaw<AppletIdentityInfo>();
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
|
const bool enabled = rp.Pop<bool>();
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled);
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
ASSERT(applet->type == AppletType::Application);
|
||||||
|
applet->out_of_focus_suspension_enabled = enabled;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::SetAlbumImageOrientation(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
|
const auto orientation = rp.PopRaw<Capture::AlbumImageOrientation>();
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called, orientation={}", static_cast<s32>(orientation));
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->album_image_orientation = orientation;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::CreateManagedDisplayLayer(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
u64 layer_id{};
|
||||||
|
applet->managed_layer_holder.Initialize(&nvnflinger);
|
||||||
|
applet->managed_layer_holder.CreateManagedDisplayLayer(&layer_id);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push(layer_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::GetSystemSharedLayerHandle(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
u64 buffer_id, layer_id;
|
||||||
|
applet->system_buffer_manager.GetSystemSharedLayerHandle(&buffer_id, &layer_id);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 6};
|
||||||
|
rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess()));
|
||||||
|
rb.Push<s64>(buffer_id);
|
||||||
|
rb.Push<s64>(layer_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
u64 buffer_id, layer_id;
|
||||||
|
applet->system_buffer_manager.GetSystemSharedLayerHandle(&buffer_id, &layer_id);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(this->EnsureBufferSharingEnabled(ctx.GetThread().GetOwnerProcess()));
|
||||||
|
rb.Push<s64>(buffer_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ISelfController::EnsureBufferSharingEnabled(Kernel::KProcess* process) {
|
||||||
|
if (applet->system_buffer_manager.Initialize(&nvnflinger, process, applet->applet_id)) {
|
||||||
|
return ResultSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
return VI::ResultOperationFailed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
u64 layer_id{};
|
||||||
|
u64 recording_layer_id{};
|
||||||
|
applet->managed_layer_holder.Initialize(&nvnflinger);
|
||||||
|
applet->managed_layer_holder.CreateManagedDisplaySeparableLayer(&layer_id, &recording_layer_id);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 6};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push(layer_id);
|
||||||
|
rb.Push(recording_layer_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::ApproveToDisplay(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
|
const auto extension = rp.PopRaw<IdleTimeDetectionExtension>();
|
||||||
|
LOG_DEBUG(Service_AM, "(STUBBED) called extension={}", extension);
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->idle_time_detection_extension = extension;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::GetIdleTimeDetectionExtension(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushRaw<IdleTimeDetectionExtension>(applet->idle_time_detection_extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::ReportUserIsActive(HLERequestContext& ctx) {
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::SetAutoSleepDisabled(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->auto_sleep_disabled = rp.Pop<bool>();
|
||||||
|
|
||||||
|
// On the system itself, if the previous state of is_auto_sleep_disabled
|
||||||
|
// differed from the current value passed in, it'd signify the internal
|
||||||
|
// window manager to update (and also increment some statistics like update counts)
|
||||||
|
//
|
||||||
|
// It'd also indicate this change to an idle handling context.
|
||||||
|
//
|
||||||
|
// However, given we're emulating this behavior, most of this can be ignored
|
||||||
|
// and it's sufficient to simply set the member variable for querying via
|
||||||
|
// IsAutoSleepDisabled().
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", applet->auto_sleep_disabled);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::IsAutoSleepDisabled(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called.");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push(applet->auto_sleep_disabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::GetAccumulatedSuspendedTickValue(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called.");
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
// This command returns the total number of system ticks since ISelfController creation
|
||||||
|
// where the game was suspended. Since Yuzu doesn't implement game suspension, this command
|
||||||
|
// can just always return 0 ticks.
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push<u64>(applet->suspended_ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called.");
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushCopyObjects(applet->accumulated_suspended_tick_changed_event.GetHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
|
// This service call sets an internal flag whether a notification is shown when an image is
|
||||||
|
// captured. Currently we do not support capturing images via the capture button, so this can be
|
||||||
|
// stubbed for now.
|
||||||
|
const bool enabled = rp.Pop<bool>();
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called. enabled={}", enabled);
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->album_image_taken_notification_enabled = enabled;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::SaveCurrentScreenshot(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
|
const auto report_option = rp.PopEnum<Capture::AlbumReportOption>();
|
||||||
|
|
||||||
|
LOG_INFO(Service_AM, "called, report_option={}", report_option);
|
||||||
|
|
||||||
|
const auto screenshot_service =
|
||||||
|
system.ServiceManager().GetService<Service::Capture::IScreenShotApplicationService>(
|
||||||
|
"caps:su");
|
||||||
|
|
||||||
|
if (screenshot_service) {
|
||||||
|
screenshot_service->CaptureAndSaveScreenshot(report_option);
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::SetRecordVolumeMuted(HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
|
const auto enabled = rp.Pop<bool>();
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called. enabled={}", enabled);
|
||||||
|
|
||||||
|
std::scoped_lock lk{applet->lock};
|
||||||
|
applet->record_volume_muted = enabled;
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,58 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/kernel_helpers.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
struct Applet;
|
||||||
|
|
||||||
|
class ISelfController final : public ServiceFramework<ISelfController> {
|
||||||
|
public:
|
||||||
|
explicit ISelfController(Core::System& system_, std::shared_ptr<Applet> applet_,
|
||||||
|
Nvnflinger::Nvnflinger& nvnflinger_);
|
||||||
|
~ISelfController() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Exit(HLERequestContext& ctx);
|
||||||
|
void LockExit(HLERequestContext& ctx);
|
||||||
|
void UnlockExit(HLERequestContext& ctx);
|
||||||
|
void EnterFatalSection(HLERequestContext& ctx);
|
||||||
|
void LeaveFatalSection(HLERequestContext& ctx);
|
||||||
|
void GetLibraryAppletLaunchableEvent(HLERequestContext& ctx);
|
||||||
|
void SetScreenShotPermission(HLERequestContext& ctx);
|
||||||
|
void SetOperationModeChangedNotification(HLERequestContext& ctx);
|
||||||
|
void SetPerformanceModeChangedNotification(HLERequestContext& ctx);
|
||||||
|
void SetFocusHandlingMode(HLERequestContext& ctx);
|
||||||
|
void SetRestartMessageEnabled(HLERequestContext& ctx);
|
||||||
|
void SetScreenShotAppletIdentityInfo(HLERequestContext& ctx);
|
||||||
|
void SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx);
|
||||||
|
void SetAlbumImageOrientation(HLERequestContext& ctx);
|
||||||
|
void IsSystemBufferSharingEnabled(HLERequestContext& ctx);
|
||||||
|
void GetSystemSharedBufferHandle(HLERequestContext& ctx);
|
||||||
|
void GetSystemSharedLayerHandle(HLERequestContext& ctx);
|
||||||
|
void CreateManagedDisplayLayer(HLERequestContext& ctx);
|
||||||
|
void CreateManagedDisplaySeparableLayer(HLERequestContext& ctx);
|
||||||
|
void SetHandlesRequestToDisplay(HLERequestContext& ctx);
|
||||||
|
void ApproveToDisplay(HLERequestContext& ctx);
|
||||||
|
void SetIdleTimeDetectionExtension(HLERequestContext& ctx);
|
||||||
|
void GetIdleTimeDetectionExtension(HLERequestContext& ctx);
|
||||||
|
void ReportUserIsActive(HLERequestContext& ctx);
|
||||||
|
void SetAutoSleepDisabled(HLERequestContext& ctx);
|
||||||
|
void IsAutoSleepDisabled(HLERequestContext& ctx);
|
||||||
|
void GetAccumulatedSuspendedTickValue(HLERequestContext& ctx);
|
||||||
|
void GetAccumulatedSuspendedTickChangedEvent(HLERequestContext& ctx);
|
||||||
|
void SetAlbumImageTakenNotificationEnabled(HLERequestContext& ctx);
|
||||||
|
void SaveCurrentScreenshot(HLERequestContext& ctx);
|
||||||
|
void SetRecordVolumeMuted(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
Result EnsureBufferSharingEnabled(Kernel::KProcess* process);
|
||||||
|
|
||||||
|
Nvnflinger::Nvnflinger& nvnflinger;
|
||||||
|
const std::shared_ptr<Applet> applet;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,59 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "core/hle/service/am/am_results.h"
|
||||||
|
#include "core/hle/service/am/library_applet_storage.h"
|
||||||
|
#include "core/hle/service/am/storage.h"
|
||||||
|
#include "core/hle/service/am/storage_accessor.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
IStorage::IStorage(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl_)
|
||||||
|
: ServiceFramework{system_, "IStorage"}, impl{std::move(impl_)} {
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, &IStorage::Open, "Open"},
|
||||||
|
{1, &IStorage::OpenTransferStorage, "OpenTransferStorage"},
|
||||||
|
};
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
IStorage::IStorage(Core::System& system_, std::vector<u8>&& data)
|
||||||
|
: IStorage(system_, CreateStorage(std::move(data))) {}
|
||||||
|
|
||||||
|
IStorage::~IStorage() = default;
|
||||||
|
|
||||||
|
void IStorage::Open(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
if (impl->GetHandle() != nullptr) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(AM::ResultInvalidStorageType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<IStorageAccessor>(system, impl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IStorage::OpenTransferStorage(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
|
if (impl->GetHandle() == nullptr) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(AM::ResultInvalidStorageType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<ITransferStorageAccessor>(system, impl);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<u8> IStorage::GetData() const {
|
||||||
|
return impl->GetData();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
|
@ -0,0 +1,31 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::AM {
|
||||||
|
|
||||||
|
class LibraryAppletStorage;
|
||||||
|
|
||||||
|
class IStorage final : public ServiceFramework<IStorage> {
|
||||||
|
public:
|
||||||
|
explicit IStorage(Core::System& system_, std::shared_ptr<LibraryAppletStorage> impl_);
|
||||||
|
explicit IStorage(Core::System& system_, std::vector<u8>&& buffer);
|
||||||
|
~IStorage() override;
|
||||||
|
|
||||||
|
std::shared_ptr<LibraryAppletStorage> GetImpl() const {
|
||||||
|
return impl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<u8> GetData() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Open(HLERequestContext& ctx);
|
||||||
|
void OpenTransferStorage(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
const std::shared_ptr<LibraryAppletStorage> impl;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue