Merge pull request #11569 from german77/lle_applet
service: am: Add support for LLE Mii Edit Applet
This commit is contained in:
		@@ -19,6 +19,7 @@
 | 
			
		||||
#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_mii_edit_types.h"
 | 
			
		||||
#include "core/hle/service/am/applets/applet_profile_select.h"
 | 
			
		||||
#include "core/hle/service/am/applets/applet_web_browser.h"
 | 
			
		||||
#include "core/hle/service/am/applets/applets.h"
 | 
			
		||||
@@ -190,7 +191,7 @@ IDisplayController::IDisplayController(Core::System& system_)
 | 
			
		||||
        {5, nullptr, "GetLastForegroundCaptureImageEx"},
 | 
			
		||||
        {6, nullptr, "GetLastApplicationCaptureImageEx"},
 | 
			
		||||
        {7, nullptr, "GetCallerAppletCaptureImageEx"},
 | 
			
		||||
        {8, nullptr, "TakeScreenShotOfOwnLayer"},
 | 
			
		||||
        {8, &IDisplayController::TakeScreenShotOfOwnLayer, "TakeScreenShotOfOwnLayer"},
 | 
			
		||||
        {9, nullptr, "CopyBetweenCaptureBuffers"},
 | 
			
		||||
        {10, nullptr, "AcquireLastApplicationCaptureBuffer"},
 | 
			
		||||
        {11, nullptr, "ReleaseLastApplicationCaptureBuffer"},
 | 
			
		||||
@@ -218,6 +219,13 @@ IDisplayController::IDisplayController(Core::System& system_)
 | 
			
		||||
 | 
			
		||||
IDisplayController::~IDisplayController() = default;
 | 
			
		||||
 | 
			
		||||
void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) {
 | 
			
		||||
    LOG_WARNING(Service_AM, "(STUBBED) called");
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
    rb.Push(ResultSuccess);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IDebugFunctions::IDebugFunctions(Core::System& system_)
 | 
			
		||||
    : ServiceFramework{system_, "IDebugFunctions"} {
 | 
			
		||||
    // clang-format off
 | 
			
		||||
@@ -724,7 +732,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
 | 
			
		||||
        {110, nullptr, "OpenMyGpuErrorHandler"},
 | 
			
		||||
        {120, nullptr, "GetAppletLaunchedHistory"},
 | 
			
		||||
        {200, nullptr, "GetOperationModeSystemInfo"},
 | 
			
		||||
        {300, nullptr, "GetSettingsPlatformRegion"},
 | 
			
		||||
        {300, &ICommonStateGetter::GetSettingsPlatformRegion, "GetSettingsPlatformRegion"},
 | 
			
		||||
        {400, nullptr, "ActivateMigrationService"},
 | 
			
		||||
        {401, nullptr, "DeactivateMigrationService"},
 | 
			
		||||
        {500, nullptr, "DisableSleepTillShutdown"},
 | 
			
		||||
@@ -736,6 +744,10 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
 | 
			
		||||
    // clang-format on
 | 
			
		||||
 | 
			
		||||
    RegisterHandlers(functions);
 | 
			
		||||
 | 
			
		||||
    // Configure applets to be in foreground state
 | 
			
		||||
    msg_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
 | 
			
		||||
    msg_queue->PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ICommonStateGetter::~ICommonStateGetter() = default;
 | 
			
		||||
@@ -867,6 +879,14 @@ void ICommonStateGetter::PerformSystemButtonPressingIfInFocus(HLERequestContext&
 | 
			
		||||
    rb.Push(ResultSuccess);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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");
 | 
			
		||||
@@ -1324,18 +1344,19 @@ void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) {
 | 
			
		||||
 | 
			
		||||
ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
 | 
			
		||||
    : ServiceFramework{system_, "ILibraryAppletSelfAccessor"} {
 | 
			
		||||
    // clang-format off
 | 
			
		||||
    static const FunctionInfo functions[] = {
 | 
			
		||||
        {0, nullptr, "PopInData"},
 | 
			
		||||
        {1, nullptr, "PushOutData"},
 | 
			
		||||
        {0, &ILibraryAppletSelfAccessor::PopInData, "PopInData"},
 | 
			
		||||
        {1, &ILibraryAppletSelfAccessor::PushOutData, "PushOutData"},
 | 
			
		||||
        {2, nullptr, "PopInteractiveInData"},
 | 
			
		||||
        {3, nullptr, "PushInteractiveOutData"},
 | 
			
		||||
        {5, nullptr, "GetPopInDataEvent"},
 | 
			
		||||
        {6, nullptr, "GetPopInteractiveInDataEvent"},
 | 
			
		||||
        {10, nullptr, "ExitProcessAndReturn"},
 | 
			
		||||
        {11, nullptr, "GetLibraryAppletInfo"},
 | 
			
		||||
        {10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"},
 | 
			
		||||
        {11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"},
 | 
			
		||||
        {12, nullptr, "GetMainAppletIdentityInfo"},
 | 
			
		||||
        {13, nullptr, "CanUseApplicationCore"},
 | 
			
		||||
        {14, nullptr, "GetCallerAppletIdentityInfo"},
 | 
			
		||||
        {14, &ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo, "GetCallerAppletIdentityInfo"},
 | 
			
		||||
        {15, nullptr, "GetMainAppletApplicationControlProperty"},
 | 
			
		||||
        {16, nullptr, "GetMainAppletStorageId"},
 | 
			
		||||
        {17, nullptr, "GetCallerAppletIdentityInfoStack"},
 | 
			
		||||
@@ -1361,10 +1382,142 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
 | 
			
		||||
        {140, nullptr, "SetApplicationMemoryReservation"},
 | 
			
		||||
        {150, nullptr, "ShouldSetGpuTimeSliceManually"},
 | 
			
		||||
    };
 | 
			
		||||
    // clang-format on
 | 
			
		||||
    RegisterHandlers(functions);
 | 
			
		||||
 | 
			
		||||
    PushInShowMiiEditData();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default;
 | 
			
		||||
void ILibraryAppletSelfAccessor::PopInData(HLERequestContext& ctx) {
 | 
			
		||||
    LOG_INFO(Service_AM, "called");
 | 
			
		||||
 | 
			
		||||
    if (queue_data.empty()) {
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(ResultNoDataInChannel);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto data = queue_data.front();
 | 
			
		||||
    queue_data.pop_front();
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
			
		||||
    rb.Push(ResultSuccess);
 | 
			
		||||
    rb.PushIpcInterface<IStorage>(system, std::move(data));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ILibraryAppletSelfAccessor::PushOutData(HLERequestContext& ctx) {
 | 
			
		||||
    LOG_WARNING(Service_AM, "(STUBBED) called");
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
    rb.Push(ResultSuccess);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ILibraryAppletSelfAccessor::ExitProcessAndReturn(HLERequestContext& ctx) {
 | 
			
		||||
    LOG_WARNING(Service_AM, "(STUBBED) called");
 | 
			
		||||
 | 
			
		||||
    system.Exit();
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
    rb.Push(ResultSuccess);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) {
 | 
			
		||||
    struct LibraryAppletInfo {
 | 
			
		||||
        Applets::AppletId applet_id;
 | 
			
		||||
        Applets::LibraryAppletMode library_applet_mode;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    LOG_WARNING(Service_AM, "(STUBBED) called");
 | 
			
		||||
 | 
			
		||||
    const LibraryAppletInfo applet_info{
 | 
			
		||||
        .applet_id = Applets::AppletId::MiiEdit,
 | 
			
		||||
        .library_applet_mode = Applets::LibraryAppletMode::AllForeground,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 4};
 | 
			
		||||
    rb.Push(ResultSuccess);
 | 
			
		||||
    rb.PushRaw(applet_info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) {
 | 
			
		||||
    struct AppletIdentityInfo {
 | 
			
		||||
        Applets::AppletId applet_id;
 | 
			
		||||
        INSERT_PADDING_BYTES(0x4);
 | 
			
		||||
        u64 application_id;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    LOG_WARNING(Service_AM, "(STUBBED) called");
 | 
			
		||||
 | 
			
		||||
    const AppletIdentityInfo applet_info{
 | 
			
		||||
        .applet_id = Applets::AppletId::QLaunch,
 | 
			
		||||
        .application_id = 0x0100000000001000ull,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 6};
 | 
			
		||||
    rb.Push(ResultSuccess);
 | 
			
		||||
    rb.PushRaw(applet_info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ILibraryAppletSelfAccessor::PushInShowMiiEditData() {
 | 
			
		||||
    struct MiiEditV3 {
 | 
			
		||||
        Applets::MiiEditAppletInputCommon common;
 | 
			
		||||
        Applets::MiiEditAppletInputV3 input;
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(MiiEditV3) == 0x100, "MiiEditV3 has incorrect size.");
 | 
			
		||||
 | 
			
		||||
    MiiEditV3 mii_arguments{
 | 
			
		||||
        .common =
 | 
			
		||||
            {
 | 
			
		||||
                .version = Applets::MiiEditAppletVersion::Version3,
 | 
			
		||||
                .applet_mode = Applets::MiiEditAppletMode::ShowMiiEdit,
 | 
			
		||||
            },
 | 
			
		||||
        .input{},
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    std::vector<u8> argument_data(sizeof(mii_arguments));
 | 
			
		||||
    std::memcpy(argument_data.data(), &mii_arguments, sizeof(mii_arguments));
 | 
			
		||||
 | 
			
		||||
    queue_data.emplace_back(std::move(argument_data));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_)
 | 
			
		||||
    : ServiceFramework{system_, "IAppletCommonFunctions"} {
 | 
			
		||||
    // 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"},
 | 
			
		||||
    };
 | 
			
		||||
    // clang-format on
 | 
			
		||||
 | 
			
		||||
    RegisterHandlers(functions);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IAppletCommonFunctions::~IAppletCommonFunctions() = default;
 | 
			
		||||
 | 
			
		||||
void IAppletCommonFunctions::SetCpuBoostRequestPriority(HLERequestContext& ctx) {
 | 
			
		||||
    LOG_WARNING(Service_AM, "(STUBBED) called");
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
    rb.Push(ResultSuccess);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IApplicationFunctions::IApplicationFunctions(Core::System& system_)
 | 
			
		||||
    : ServiceFramework{system_, "IApplicationFunctions"}, service_context{system,
 | 
			
		||||
@@ -2049,8 +2202,8 @@ IProcessWindingController::IProcessWindingController(Core::System& system_)
 | 
			
		||||
    : ServiceFramework{system_, "IProcessWindingController"} {
 | 
			
		||||
    // clang-format off
 | 
			
		||||
    static const FunctionInfo functions[] = {
 | 
			
		||||
        {0, nullptr, "GetLaunchReason"},
 | 
			
		||||
        {11, nullptr, "OpenCallingLibraryApplet"},
 | 
			
		||||
        {0, &IProcessWindingController::GetLaunchReason, "GetLaunchReason"},
 | 
			
		||||
        {11, &IProcessWindingController::OpenCallingLibraryApplet, "OpenCallingLibraryApplet"},
 | 
			
		||||
        {21, nullptr, "PushContext"},
 | 
			
		||||
        {22, nullptr, "PopContext"},
 | 
			
		||||
        {23, nullptr, "CancelWindingReservation"},
 | 
			
		||||
@@ -2064,4 +2217,46 @@ IProcessWindingController::IProcessWindingController(Core::System& system_)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IProcessWindingController::~IProcessWindingController() = default;
 | 
			
		||||
 | 
			
		||||
void IProcessWindingController::GetLaunchReason(HLERequestContext& ctx) {
 | 
			
		||||
    LOG_WARNING(Service_AM, "(STUBBED) called");
 | 
			
		||||
 | 
			
		||||
    struct AppletProcessLaunchReason {
 | 
			
		||||
        u8 flag;
 | 
			
		||||
        INSERT_PADDING_BYTES(3);
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(AppletProcessLaunchReason) == 0x4,
 | 
			
		||||
                  "AppletProcessLaunchReason is an invalid size");
 | 
			
		||||
 | 
			
		||||
    AppletProcessLaunchReason reason{
 | 
			
		||||
        .flag = 0,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 3};
 | 
			
		||||
    rb.Push(ResultSuccess);
 | 
			
		||||
    rb.PushRaw(reason);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) {
 | 
			
		||||
    const auto applet_id = Applets::AppletId::MiiEdit;
 | 
			
		||||
    const auto applet_mode = Applets::LibraryAppletMode::AllForeground;
 | 
			
		||||
 | 
			
		||||
    LOG_WARNING(Service_AM, "(STUBBED) called with applet_id={:08X}, applet_mode={:08X}", applet_id,
 | 
			
		||||
                applet_mode);
 | 
			
		||||
 | 
			
		||||
    const auto& applet_manager{system.GetAppletManager()};
 | 
			
		||||
    const auto applet = applet_manager.GetApplet(applet_id, applet_mode);
 | 
			
		||||
 | 
			
		||||
    if (applet == nullptr) {
 | 
			
		||||
        LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
 | 
			
		||||
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
        rb.Push(ResultUnknown);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
			
		||||
    rb.Push(ResultSuccess);
 | 
			
		||||
    rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet);
 | 
			
		||||
}
 | 
			
		||||
} // namespace Service::AM
 | 
			
		||||
 
 | 
			
		||||
@@ -120,6 +120,9 @@ class IDisplayController final : public ServiceFramework<IDisplayController> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit IDisplayController(Core::System& system_);
 | 
			
		||||
    ~IDisplayController() override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void TakeScreenShotOfOwnLayer(HLERequestContext& ctx);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class IDebugFunctions final : public ServiceFramework<IDebugFunctions> {
 | 
			
		||||
@@ -212,6 +215,11 @@ private:
 | 
			
		||||
        CaptureButtonLongPressing,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    enum class SysPlatformRegion : s32 {
 | 
			
		||||
        Global = 1,
 | 
			
		||||
        Terra = 2,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    void GetEventHandle(HLERequestContext& ctx);
 | 
			
		||||
    void ReceiveMessage(HLERequestContext& ctx);
 | 
			
		||||
    void GetCurrentFocusState(HLERequestContext& ctx);
 | 
			
		||||
@@ -227,6 +235,7 @@ private:
 | 
			
		||||
    void GetDefaultDisplayResolution(HLERequestContext& ctx);
 | 
			
		||||
    void SetCpuBoostMode(HLERequestContext& ctx);
 | 
			
		||||
    void PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx);
 | 
			
		||||
    void GetSettingsPlatformRegion(HLERequestContext& ctx);
 | 
			
		||||
    void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
    std::shared_ptr<AppletMessageQueue> msg_queue;
 | 
			
		||||
@@ -294,6 +303,26 @@ class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletS
 | 
			
		||||
public:
 | 
			
		||||
    explicit ILibraryAppletSelfAccessor(Core::System& system_);
 | 
			
		||||
    ~ILibraryAppletSelfAccessor() override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void PopInData(HLERequestContext& ctx);
 | 
			
		||||
    void PushOutData(HLERequestContext& ctx);
 | 
			
		||||
    void GetLibraryAppletInfo(HLERequestContext& ctx);
 | 
			
		||||
    void ExitProcessAndReturn(HLERequestContext& ctx);
 | 
			
		||||
    void GetCallerAppletIdentityInfo(HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
    void PushInShowMiiEditData();
 | 
			
		||||
 | 
			
		||||
    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> {
 | 
			
		||||
@@ -378,6 +407,10 @@ class IProcessWindingController final : public ServiceFramework<IProcessWindingC
 | 
			
		||||
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);
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,7 @@ public:
 | 
			
		||||
            {10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"},
 | 
			
		||||
            {11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
 | 
			
		||||
            {20, &ILibraryAppletProxy::OpenLibraryAppletSelfAccessor, "OpenLibraryAppletSelfAccessor"},
 | 
			
		||||
            {21, nullptr, "GetAppletCommonFunctions"},
 | 
			
		||||
            {21, &ILibraryAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"},
 | 
			
		||||
            {22, nullptr, "GetHomeMenuFunctions"},
 | 
			
		||||
            {23, nullptr, "GetGlobalStateController"},
 | 
			
		||||
            {1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
 | 
			
		||||
@@ -86,14 +86,6 @@ private:
 | 
			
		||||
        rb.PushIpcInterface<IProcessWindingController>(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 GetLibraryAppletCreator(HLERequestContext& ctx) {
 | 
			
		||||
        LOG_DEBUG(Service_AM, "called");
 | 
			
		||||
 | 
			
		||||
@@ -110,6 +102,22 @@ private:
 | 
			
		||||
        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 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;
 | 
			
		||||
};
 | 
			
		||||
@@ -133,7 +141,7 @@ public:
 | 
			
		||||
            {20, &ISystemAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"},
 | 
			
		||||
            {21, &ISystemAppletProxy::GetGlobalStateController, "GetGlobalStateController"},
 | 
			
		||||
            {22, &ISystemAppletProxy::GetApplicationCreator, "GetApplicationCreator"},
 | 
			
		||||
            {23, nullptr, "GetAppletCommonFunctions"},
 | 
			
		||||
            {23,  &ISystemAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"},
 | 
			
		||||
            {1000, &ISystemAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
 | 
			
		||||
        };
 | 
			
		||||
        // clang-format on
 | 
			
		||||
@@ -182,14 +190,6 @@ private:
 | 
			
		||||
        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 GetLibraryAppletCreator(HLERequestContext& ctx) {
 | 
			
		||||
        LOG_DEBUG(Service_AM, "called");
 | 
			
		||||
 | 
			
		||||
@@ -222,6 +222,22 @@ private:
 | 
			
		||||
        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;
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -698,7 +698,7 @@ FSP_SRV::FSP_SRV(Core::System& system_)
 | 
			
		||||
        {19, nullptr, "FormatSdCardFileSystem"},
 | 
			
		||||
        {21, nullptr, "DeleteSaveDataFileSystem"},
 | 
			
		||||
        {22, &FSP_SRV::CreateSaveDataFileSystem, "CreateSaveDataFileSystem"},
 | 
			
		||||
        {23, nullptr, "CreateSaveDataFileSystemBySystemSaveDataId"},
 | 
			
		||||
        {23, &FSP_SRV::CreateSaveDataFileSystemBySystemSaveDataId, "CreateSaveDataFileSystemBySystemSaveDataId"},
 | 
			
		||||
        {24, nullptr, "RegisterSaveDataFileSystemAtomicDeletion"},
 | 
			
		||||
        {25, nullptr, "DeleteSaveDataFileSystemBySaveDataSpaceId"},
 | 
			
		||||
        {26, nullptr, "FormatSdCardDryRun"},
 | 
			
		||||
@@ -712,7 +712,7 @@ FSP_SRV::FSP_SRV(Core::System& system_)
 | 
			
		||||
        {35, nullptr, "CreateSaveDataFileSystemByHashSalt"},
 | 
			
		||||
        {36, nullptr, "OpenHostFileSystemWithOption"},
 | 
			
		||||
        {51, &FSP_SRV::OpenSaveDataFileSystem, "OpenSaveDataFileSystem"},
 | 
			
		||||
        {52, nullptr, "OpenSaveDataFileSystemBySystemSaveDataId"},
 | 
			
		||||
        {52, &FSP_SRV::OpenSaveDataFileSystemBySystemSaveDataId, "OpenSaveDataFileSystemBySystemSaveDataId"},
 | 
			
		||||
        {53, &FSP_SRV::OpenReadOnlySaveDataFileSystem, "OpenReadOnlySaveDataFileSystem"},
 | 
			
		||||
        {57, nullptr, "ReadSaveDataFileSystemExtraDataBySaveDataSpaceId"},
 | 
			
		||||
        {58, nullptr, "ReadSaveDataFileSystemExtraData"},
 | 
			
		||||
@@ -870,6 +870,21 @@ void FSP_SRV::CreateSaveDataFileSystem(HLERequestContext& ctx) {
 | 
			
		||||
    rb.Push(ResultSuccess);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FSP_SRV::CreateSaveDataFileSystemBySystemSaveDataId(HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
 | 
			
		||||
    auto save_struct = rp.PopRaw<FileSys::SaveDataAttribute>();
 | 
			
		||||
    [[maybe_unused]] auto save_create_struct = rp.PopRaw<std::array<u8, 0x40>>();
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_FS, "called save_struct = {}", save_struct.DebugInfo());
 | 
			
		||||
 | 
			
		||||
    FileSys::VirtualDir save_data_dir{};
 | 
			
		||||
    fsc.CreateSaveData(&save_data_dir, FileSys::SaveDataSpaceId::NandSystem, save_struct);
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
    rb.Push(ResultSuccess);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FSP_SRV::OpenSaveDataFileSystem(HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
 | 
			
		||||
@@ -916,6 +931,11 @@ void FSP_SRV::OpenSaveDataFileSystem(HLERequestContext& ctx) {
 | 
			
		||||
    rb.PushIpcInterface<IFileSystem>(std::move(filesystem));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FSP_SRV::OpenSaveDataFileSystemBySystemSaveDataId(HLERequestContext& ctx) {
 | 
			
		||||
    LOG_WARNING(Service_FS, "(STUBBED) called, delegating to 51 OpenSaveDataFilesystem");
 | 
			
		||||
    OpenSaveDataFileSystem(ctx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FSP_SRV::OpenReadOnlySaveDataFileSystem(HLERequestContext& ctx) {
 | 
			
		||||
    LOG_WARNING(Service_FS, "(STUBBED) called, delegating to 51 OpenSaveDataFilesystem");
 | 
			
		||||
    OpenSaveDataFileSystem(ctx);
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,9 @@ private:
 | 
			
		||||
    void OpenFileSystemWithPatch(HLERequestContext& ctx);
 | 
			
		||||
    void OpenSdCardFileSystem(HLERequestContext& ctx);
 | 
			
		||||
    void CreateSaveDataFileSystem(HLERequestContext& ctx);
 | 
			
		||||
    void CreateSaveDataFileSystemBySystemSaveDataId(HLERequestContext& ctx);
 | 
			
		||||
    void OpenSaveDataFileSystem(HLERequestContext& ctx);
 | 
			
		||||
    void OpenSaveDataFileSystemBySystemSaveDataId(HLERequestContext& ctx);
 | 
			
		||||
    void OpenReadOnlySaveDataFileSystem(HLERequestContext& ctx);
 | 
			
		||||
    void OpenSaveDataInfoReaderBySaveDataSpaceId(HLERequestContext& ctx);
 | 
			
		||||
    void OpenSaveDataInfoReaderOnlyCacheStorage(HLERequestContext& ctx);
 | 
			
		||||
 
 | 
			
		||||
@@ -346,6 +346,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
    }
 | 
			
		||||
    SignalStyleSetChangedEvent(npad_id);
 | 
			
		||||
    WriteEmptyEntry(controller.shared_memory);
 | 
			
		||||
    hid_core.SetLastActiveController(npad_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Controller_NPad::OnInit() {
 | 
			
		||||
 
 | 
			
		||||
@@ -614,7 +614,7 @@ struct Nickname {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::size_t index = 1;
 | 
			
		||||
        while (data[index] != 0) {
 | 
			
		||||
        while (index < MaxNameSize && data[index] != 0) {
 | 
			
		||||
            index++;
 | 
			
		||||
        }
 | 
			
		||||
        while (index < MaxNameSize && data[index] == 0) {
 | 
			
		||||
 
 | 
			
		||||
@@ -144,7 +144,7 @@ IPlatformServiceManager::IPlatformServiceManager(Core::System& system_, const ch
 | 
			
		||||
        {3, &IPlatformServiceManager::GetSharedMemoryAddressOffset, "GetSharedMemoryAddressOffset"},
 | 
			
		||||
        {4, &IPlatformServiceManager::GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"},
 | 
			
		||||
        {5, &IPlatformServiceManager::GetSharedFontInOrderOfPriority, "GetSharedFontInOrderOfPriority"},
 | 
			
		||||
        {6, nullptr, "GetSharedFontInOrderOfPriorityForSystem"},
 | 
			
		||||
        {6, &IPlatformServiceManager::GetSharedFontInOrderOfPriority, "GetSharedFontInOrderOfPriorityForSystem"},
 | 
			
		||||
        {100, nullptr, "RequestApplicationFunctionAuthorization"},
 | 
			
		||||
        {101, nullptr, "RequestApplicationFunctionAuthorizationByProcessId"},
 | 
			
		||||
        {102, nullptr, "RequestApplicationFunctionAuthorizationByApplicationId"},
 | 
			
		||||
@@ -262,8 +262,17 @@ void IPlatformServiceManager::GetSharedMemoryNativeHandle(HLERequestContext& ctx
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void IPlatformServiceManager::GetSharedFontInOrderOfPriority(HLERequestContext& ctx) {
 | 
			
		||||
    // The maximum number of elements that can be returned is 6. Regardless of the available fonts
 | 
			
		||||
    // or buffer size.
 | 
			
		||||
    constexpr std::size_t MaxElementCount = 6;
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
    const u64 language_code{rp.Pop<u64>()}; // TODO(ogniK): Find out what this is used for
 | 
			
		||||
    const std::size_t font_codes_count =
 | 
			
		||||
        std::min(MaxElementCount, ctx.GetWriteBufferNumElements<u32>(0));
 | 
			
		||||
    const std::size_t font_offsets_count =
 | 
			
		||||
        std::min(MaxElementCount, ctx.GetWriteBufferNumElements<u32>(1));
 | 
			
		||||
    const std::size_t font_sizes_count =
 | 
			
		||||
        std::min(MaxElementCount, ctx.GetWriteBufferNumElements<u32>(2));
 | 
			
		||||
    LOG_DEBUG(Service_NS, "called, language_code={:X}", language_code);
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 4};
 | 
			
		||||
@@ -280,9 +289,9 @@ void IPlatformServiceManager::GetSharedFontInOrderOfPriority(HLERequestContext&
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Resize buffers if game requests smaller size output
 | 
			
		||||
    font_codes.resize(std::min(font_codes.size(), ctx.GetWriteBufferNumElements<u32>(0)));
 | 
			
		||||
    font_offsets.resize(std::min(font_offsets.size(), ctx.GetWriteBufferNumElements<u32>(1)));
 | 
			
		||||
    font_sizes.resize(std::min(font_sizes.size(), ctx.GetWriteBufferNumElements<u32>(2)));
 | 
			
		||||
    font_codes.resize(std::min(font_codes.size(), font_codes_count));
 | 
			
		||||
    font_offsets.resize(std::min(font_offsets.size(), font_offsets_count));
 | 
			
		||||
    font_sizes.resize(std::min(font_sizes.size(), font_sizes_count));
 | 
			
		||||
 | 
			
		||||
    ctx.WriteBuffer(font_codes, 0);
 | 
			
		||||
    ctx.WriteBuffer(font_offsets, 1);
 | 
			
		||||
 
 | 
			
		||||
@@ -1551,6 +1551,7 @@ void GMainWindow::ConnectMenuEvents() {
 | 
			
		||||
    // Tools
 | 
			
		||||
    connect_menu(ui->action_Rederive, std::bind(&GMainWindow::OnReinitializeKeys, this,
 | 
			
		||||
                                                ReinitializeKeyBehavior::Warning));
 | 
			
		||||
    connect_menu(ui->action_Load_Mii_Edit, &GMainWindow::OnMiiEdit);
 | 
			
		||||
    connect_menu(ui->action_Capture_Screenshot, &GMainWindow::OnCaptureScreenshot);
 | 
			
		||||
 | 
			
		||||
    // TAS
 | 
			
		||||
@@ -1590,6 +1591,8 @@ void GMainWindow::UpdateMenuState() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    multiplayer_state->UpdateNotificationStatus();
 | 
			
		||||
 | 
			
		||||
    ui->action_Load_Mii_Edit->setEnabled(CheckFirmwarePresence());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GMainWindow::OnDisplayTitleBars(bool show) {
 | 
			
		||||
@@ -4134,6 +4137,27 @@ void GMainWindow::OnToggleStatusBar() {
 | 
			
		||||
    statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GMainWindow::OnMiiEdit() {
 | 
			
		||||
    constexpr u64 MiiEditId = 0x0100000000001009ull;
 | 
			
		||||
    auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
 | 
			
		||||
    if (!bis_system) {
 | 
			
		||||
        QMessageBox::warning(this, tr("No firmware available"),
 | 
			
		||||
                             tr("Please install the firmware to use the Mii editor."));
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto mii_applet_nca = bis_system->GetEntry(MiiEditId, FileSys::ContentRecordType::Program);
 | 
			
		||||
    if (!mii_applet_nca) {
 | 
			
		||||
        QMessageBox::warning(this, tr("Mii Edit Applet"),
 | 
			
		||||
                             tr("Mii editor is not available. Please reinstall firmware."));
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath()));
 | 
			
		||||
    UISettings::values.roms_path = QFileInfo(filename).path();
 | 
			
		||||
    BootGame(filename);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GMainWindow::OnCaptureScreenshot() {
 | 
			
		||||
    if (emu_thread == nullptr || !emu_thread->IsRunning()) {
 | 
			
		||||
        return;
 | 
			
		||||
@@ -4540,6 +4564,8 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
 | 
			
		||||
    if (behavior == ReinitializeKeyBehavior::Warning) {
 | 
			
		||||
        game_list->PopulateAsync(UISettings::values.game_dirs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    UpdateMenuState();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GMainWindow::CheckSystemArchiveDecryption() {
 | 
			
		||||
@@ -4561,6 +4587,22 @@ bool GMainWindow::CheckSystemArchiveDecryption() {
 | 
			
		||||
    return mii_nca->GetRomFS().get() != nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GMainWindow::CheckFirmwarePresence() {
 | 
			
		||||
    constexpr u64 MiiEditId = 0x0100000000001009ull;
 | 
			
		||||
 | 
			
		||||
    auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
 | 
			
		||||
    if (!bis_system) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto mii_applet_nca = bis_system->GetEntry(MiiEditId, FileSys::ContentRecordType::Program);
 | 
			
		||||
    if (!mii_applet_nca) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installed, u64 program_id,
 | 
			
		||||
                                        u64* selected_title_id, u8* selected_content_record_type) {
 | 
			
		||||
    using ContentInfo = std::pair<FileSys::TitleType, FileSys::ContentRecordType>;
 | 
			
		||||
 
 | 
			
		||||
@@ -365,6 +365,7 @@ private slots:
 | 
			
		||||
    void ResetWindowSize720();
 | 
			
		||||
    void ResetWindowSize900();
 | 
			
		||||
    void ResetWindowSize1080();
 | 
			
		||||
    void OnMiiEdit();
 | 
			
		||||
    void OnCaptureScreenshot();
 | 
			
		||||
    void OnReinitializeKeys(ReinitializeKeyBehavior behavior);
 | 
			
		||||
    void OnLanguageChanged(const QString& locale);
 | 
			
		||||
@@ -409,6 +410,7 @@ private:
 | 
			
		||||
    void OpenPerGameConfiguration(u64 title_id, const std::string& file_name);
 | 
			
		||||
    bool CheckDarkMode();
 | 
			
		||||
    bool CheckSystemArchiveDecryption();
 | 
			
		||||
    bool CheckFirmwarePresence();
 | 
			
		||||
    void ConfigureFilesystemProvider(const std::string& filepath);
 | 
			
		||||
 | 
			
		||||
    QString GetTasStateDescription() const;
 | 
			
		||||
 
 | 
			
		||||
@@ -150,6 +150,8 @@
 | 
			
		||||
    <addaction name="action_Rederive"/>
 | 
			
		||||
    <addaction name="action_Verify_installed_contents"/>
 | 
			
		||||
    <addaction name="separator"/>
 | 
			
		||||
    <addaction name="action_Load_Mii_Edit"/>
 | 
			
		||||
    <addaction name="separator"/>
 | 
			
		||||
    <addaction name="action_Capture_Screenshot"/>
 | 
			
		||||
    <addaction name="menuTAS"/>
 | 
			
		||||
   </widget>
 | 
			
		||||
@@ -217,7 +219,7 @@
 | 
			
		||||
  </action>
 | 
			
		||||
  <action name="action_Verify_installed_contents">
 | 
			
		||||
   <property name="text">
 | 
			
		||||
    <string>Verify installed contents</string>
 | 
			
		||||
    <string>&Verify Installed Contents</string>
 | 
			
		||||
   </property>
 | 
			
		||||
  </action>
 | 
			
		||||
  <action name="action_About">
 | 
			
		||||
@@ -368,6 +370,11 @@
 | 
			
		||||
    <string>&Capture Screenshot</string>
 | 
			
		||||
   </property>
 | 
			
		||||
  </action>
 | 
			
		||||
  <action name="action_Load_Mii_Edit">
 | 
			
		||||
    <property name="text">
 | 
			
		||||
      <string>Open &Mii Editor</string>
 | 
			
		||||
    </property>
 | 
			
		||||
  </action>
 | 
			
		||||
  <action name="action_Configure_Tas">
 | 
			
		||||
   <property name="text">
 | 
			
		||||
    <string>&Configure TAS...</string>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user