Просмотр исходного кода

Merge pull request #11569 from german77/lle_applet

service: am: Add support for LLE Mii Edit Applet
liamwhite 2 лет назад
Родитель
Сommit
37a4a6751a

+ 204 - 9
src/core/hle/service/am/am.cpp

@@ -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

+ 33 - 0
src/core/hle/service/am/am.h

@@ -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);

+ 32 - 16
src/core/hle/service/am/applet_ae.cpp

@@ -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,28 +86,36 @@ private:
         rb.PushIpcInterface<IProcessWindingController>(system);
     }
 
-    void GetDebugFunctions(HLERequestContext& ctx) {
+    void GetLibraryAppletCreator(HLERequestContext& ctx) {
         LOG_DEBUG(Service_AM, "called");
 
         IPC::ResponseBuilder rb{ctx, 2, 0, 1};
         rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IDebugFunctions>(system);
+        rb.PushIpcInterface<ILibraryAppletCreator>(system);
     }
 
-    void GetLibraryAppletCreator(HLERequestContext& ctx) {
+    void OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) {
         LOG_DEBUG(Service_AM, "called");
 
         IPC::ResponseBuilder rb{ctx, 2, 0, 1};
         rb.Push(ResultSuccess);
-        rb.PushIpcInterface<ILibraryAppletCreator>(system);
+        rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system);
     }
 
-    void OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) {
+    void GetAppletCommonFunctions(HLERequestContext& ctx) {
         LOG_DEBUG(Service_AM, "called");
 
         IPC::ResponseBuilder rb{ctx, 2, 0, 1};
         rb.Push(ResultSuccess);
-        rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system);
+        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;
@@ -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;
 };

+ 22 - 2
src/core/hle/service/filesystem/fsp_srv.cpp

@@ -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);

+ 2 - 0
src/core/hle/service/filesystem/fsp_srv.h

@@ -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);

+ 1 - 0
src/core/hle/service/hid/controllers/npad.cpp

@@ -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() {

+ 1 - 1
src/core/hle/service/mii/mii_types.h

@@ -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) {

+ 13 - 4
src/core/hle/service/ns/iplatform_service_manager.cpp

@@ -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);

+ 42 - 0
src/yuzu/main.cpp

@@ -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>;

+ 2 - 0
src/yuzu/main.h

@@ -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;

+ 8 - 1
src/yuzu/main.ui

@@ -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>&amp;Verify Installed Contents</string>
    </property>
   </action>
   <action name="action_About">
@@ -368,6 +370,11 @@
     <string>&amp;Capture Screenshot</string>
    </property>
   </action>
+  <action name="action_Load_Mii_Edit">
+    <property name="text">
+      <string>Open &amp;Mii Editor</string>
+    </property>
+  </action>
   <action name="action_Configure_Tas">
    <property name="text">
     <string>&amp;Configure TAS...</string>