Przeglądaj źródła

mii: Prepare Interface for new implementation

german77 2 lat temu
rodzic
commit
bd169f417f

+ 7 - 4
src/core/hle/service/am/applets/applet_mii_edit.cpp

@@ -85,15 +85,18 @@ void MiiEdit::Execute() {
         break;
     case MiiEditAppletMode::CreateMii:
     case MiiEditAppletMode::EditMii: {
-        Service::Mii::MiiManager mii_manager;
+        Mii::CharInfo char_info{};
+        Mii::StoreData store_data{};
+        store_data.BuildBase(Mii::Gender::Male);
+        char_info.SetFromStoreData(store_data);
 
-        const MiiEditCharInfo char_info{
+        const MiiEditCharInfo edit_char_info{
             .mii_info{applet_input_common.applet_mode == MiiEditAppletMode::EditMii
                           ? applet_input_v4.char_info.mii_info
-                          : mii_manager.BuildBase(Mii::Gender::Male)},
+                          : char_info},
         };
 
-        MiiEditOutputForCharInfoEditing(MiiEditResult::Success, char_info);
+        MiiEditOutputForCharInfoEditing(MiiEditResult::Success, edit_char_info);
         break;
     }
     default:

+ 65 - 63
src/core/hle/service/mii/mii.cpp

@@ -15,8 +15,8 @@ namespace Service::Mii {
 
 class IDatabaseService final : public ServiceFramework<IDatabaseService> {
 public:
-    explicit IDatabaseService(Core::System& system_)
-        : ServiceFramework{system_, "IDatabaseService"} {
+    explicit IDatabaseService(Core::System& system_, bool is_system_)
+        : ServiceFramework{system_, "IDatabaseService"}, is_system{is_system_} {
         // clang-format off
         static const FunctionInfo functions[] = {
             {0, &IDatabaseService::IsUpdated, "IsUpdated"},
@@ -53,34 +53,27 @@ public:
     }
 
 private:
-    template <typename T>
-    std::vector<u8> SerializeArray(const std::vector<T>& values) {
-        std::vector<u8> out(values.size() * sizeof(T));
-        std::size_t offset{};
-        for (const auto& value : values) {
-            std::memcpy(out.data() + offset, &value, sizeof(T));
-            offset += sizeof(T);
-        }
-        return out;
-    }
-
     void IsUpdated(HLERequestContext& ctx) {
         IPC::RequestParser rp{ctx};
         const auto source_flag{rp.PopRaw<SourceFlag>()};
 
         LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
 
+        const bool is_updated = manager.IsUpdated(metadata, source_flag);
+
         IPC::ResponseBuilder rb{ctx, 3};
         rb.Push(ResultSuccess);
-        rb.Push(manager.CheckAndResetUpdateCounter(source_flag, current_update_counter));
+        rb.Push<u8>(is_updated);
     }
 
     void IsFullDatabase(HLERequestContext& ctx) {
         LOG_DEBUG(Service_Mii, "called");
 
+        const bool is_full_database = manager.IsFullDatabase();
+
         IPC::ResponseBuilder rb{ctx, 3};
         rb.Push(ResultSuccess);
-        rb.Push(manager.IsFullDatabase());
+        rb.Push<u8>(is_full_database);
     }
 
     void GetCount(HLERequestContext& ctx) {
@@ -89,57 +82,63 @@ private:
 
         LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
 
+        const u32 mii_count = manager.GetCount(metadata, source_flag);
+
         IPC::ResponseBuilder rb{ctx, 3};
         rb.Push(ResultSuccess);
-        rb.Push<u32>(manager.GetCount(source_flag));
+        rb.Push(mii_count);
     }
 
     void Get(HLERequestContext& ctx) {
         IPC::RequestParser rp{ctx};
         const auto source_flag{rp.PopRaw<SourceFlag>()};
+        const auto output_size{ctx.GetWriteBufferNumElements<CharInfoElement>()};
 
-        LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
+        LOG_DEBUG(Service_Mii, "called with source_flag={}, out_size={}", source_flag, output_size);
+
+        u32 mii_count{};
+        std::vector<CharInfoElement> char_info_elements(output_size);
+        Result result = manager.Get(metadata, char_info_elements, mii_count, source_flag);
 
-        const auto default_miis{manager.GetDefault(source_flag)};
-        if (default_miis.size() > 0) {
-            ctx.WriteBuffer(SerializeArray(default_miis));
+        if (mii_count != 0) {
+            ctx.WriteBuffer(char_info_elements);
         }
 
         IPC::ResponseBuilder rb{ctx, 3};
-        rb.Push(ResultSuccess);
-        rb.Push<u32>(static_cast<u32>(default_miis.size()));
+        rb.Push(result);
+        rb.Push(mii_count);
     }
 
     void Get1(HLERequestContext& ctx) {
         IPC::RequestParser rp{ctx};
         const auto source_flag{rp.PopRaw<SourceFlag>()};
+        const auto output_size{ctx.GetWriteBufferNumElements<CharInfo>()};
 
-        LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
+        LOG_DEBUG(Service_Mii, "called with source_flag={}, out_size={}", source_flag, output_size);
 
-        const auto default_miis{manager.GetDefault(source_flag)};
+        u32 mii_count{};
+        std::vector<CharInfo> char_info(output_size);
+        Result result = manager.Get(metadata, char_info, mii_count, source_flag);
 
-        std::vector<CharInfo> values;
-        for (const auto& element : default_miis) {
-            values.emplace_back(element.char_info);
+        if (mii_count != 0) {
+            ctx.WriteBuffer(char_info);
         }
 
-        ctx.WriteBuffer(SerializeArray(values));
-
         IPC::ResponseBuilder rb{ctx, 3};
-        rb.Push(ResultSuccess);
-        rb.Push<u32>(static_cast<u32>(default_miis.size()));
+        rb.Push(result);
+        rb.Push(mii_count);
     }
 
     void UpdateLatest(HLERequestContext& ctx) {
         IPC::RequestParser rp{ctx};
-        const auto info{rp.PopRaw<CharInfo>()};
+        const auto char_info{rp.PopRaw<CharInfo>()};
         const auto source_flag{rp.PopRaw<SourceFlag>()};
 
         LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
 
         CharInfo new_char_info{};
-        const auto result{manager.UpdateLatest(&new_char_info, info, source_flag)};
-        if (result != ResultSuccess) {
+        const auto result = manager.UpdateLatest(metadata, new_char_info, char_info, source_flag);
+        if (result.IsFailure()) {
             IPC::ResponseBuilder rb{ctx, 2};
             rb.Push(result);
             return;
@@ -152,7 +151,6 @@ private:
 
     void BuildRandom(HLERequestContext& ctx) {
         IPC::RequestParser rp{ctx};
-
         const auto age{rp.PopRaw<Age>()};
         const auto gender{rp.PopRaw<Gender>()};
         const auto race{rp.PopRaw<Race>()};
@@ -162,46 +160,47 @@ private:
         if (age > Age::All) {
             IPC::ResponseBuilder rb{ctx, 2};
             rb.Push(ResultInvalidArgument);
-            LOG_ERROR(Service_Mii, "invalid age={}", age);
             return;
         }
 
         if (gender > Gender::All) {
             IPC::ResponseBuilder rb{ctx, 2};
             rb.Push(ResultInvalidArgument);
-            LOG_ERROR(Service_Mii, "invalid gender={}", gender);
             return;
         }
 
         if (race > Race::All) {
             IPC::ResponseBuilder rb{ctx, 2};
             rb.Push(ResultInvalidArgument);
-            LOG_ERROR(Service_Mii, "invalid race={}", race);
             return;
         }
 
+        CharInfo char_info{};
+        manager.BuildRandom(char_info, age, gender, race);
+
         IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
         rb.Push(ResultSuccess);
-        rb.PushRaw<CharInfo>(manager.BuildRandom(age, gender, race));
+        rb.PushRaw<CharInfo>(char_info);
     }
 
     void BuildDefault(HLERequestContext& ctx) {
         IPC::RequestParser rp{ctx};
         const auto index{rp.Pop<u32>()};
 
-        LOG_DEBUG(Service_Mii, "called with index={}", index);
+        LOG_INFO(Service_Mii, "called with index={}", index);
 
         if (index > 5) {
-            LOG_ERROR(Service_Mii, "invalid argument, index cannot be greater than 5 but is {:08X}",
-                      index);
             IPC::ResponseBuilder rb{ctx, 2};
             rb.Push(ResultInvalidArgument);
             return;
         }
 
+        CharInfo char_info{};
+        manager.BuildDefault(char_info, index);
+
         IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
         rb.Push(ResultSuccess);
-        rb.PushRaw<CharInfo>(manager.BuildDefault(index));
+        rb.PushRaw<CharInfo>(char_info);
     }
 
     void GetIndex(HLERequestContext& ctx) {
@@ -210,19 +209,21 @@ private:
 
         LOG_DEBUG(Service_Mii, "called");
 
-        u32 index{};
+        s32 index{};
+        const Result result = manager.GetIndex(metadata, info, index);
+
         IPC::ResponseBuilder rb{ctx, 3};
-        rb.Push(manager.GetIndex(info, index));
+        rb.Push(result);
         rb.Push(index);
     }
 
     void SetInterfaceVersion(HLERequestContext& ctx) {
         IPC::RequestParser rp{ctx};
-        current_interface_version = rp.PopRaw<u32>();
+        const auto interface_version{rp.PopRaw<u32>()};
 
-        LOG_DEBUG(Service_Mii, "called, interface_version={:08X}", current_interface_version);
+        LOG_INFO(Service_Mii, "called, interface_version={:08X}", interface_version);
 
-        UNIMPLEMENTED_IF(current_interface_version != 1);
+        manager.SetInterfaceVersion(metadata, interface_version);
 
         IPC::ResponseBuilder rb{ctx, 2};
         rb.Push(ResultSuccess);
@@ -230,30 +231,27 @@ private:
 
     void Convert(HLERequestContext& ctx) {
         IPC::RequestParser rp{ctx};
-
         const auto mii_v3{rp.PopRaw<Ver3StoreData>()};
 
         LOG_INFO(Service_Mii, "called");
 
+        CharInfo char_info{};
+        manager.ConvertV3ToCharInfo(char_info, mii_v3);
+
         IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
         rb.Push(ResultSuccess);
-        rb.PushRaw<CharInfo>(manager.ConvertV3ToCharInfo(mii_v3));
-    }
-
-    constexpr bool IsInterfaceVersionSupported(u32 interface_version) const {
-        return current_interface_version >= interface_version;
+        rb.PushRaw<CharInfo>(char_info);
     }
 
-    MiiManager manager;
-
-    u32 current_interface_version{};
-    u64 current_update_counter{};
+    MiiManager manager{};
+    DatabaseSessionMetadata metadata{};
+    bool is_system{};
 };
 
 class MiiDBModule final : public ServiceFramework<MiiDBModule> {
 public:
-    explicit MiiDBModule(Core::System& system_, const char* name_)
-        : ServiceFramework{system_, name_} {
+    explicit MiiDBModule(Core::System& system_, const char* name_, bool is_system_)
+        : ServiceFramework{system_, name_}, is_system{is_system_} {
         // clang-format off
         static const FunctionInfo functions[] = {
             {0, &MiiDBModule::GetDatabaseService, "GetDatabaseService"},
@@ -267,10 +265,12 @@ private:
     void GetDatabaseService(HLERequestContext& ctx) {
         IPC::ResponseBuilder rb{ctx, 2, 0, 1};
         rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IDatabaseService>(system);
+        rb.PushIpcInterface<IDatabaseService>(system, is_system);
 
         LOG_DEBUG(Service_Mii, "called");
     }
+
+    bool is_system{};
 };
 
 class MiiImg final : public ServiceFramework<MiiImg> {
@@ -302,8 +302,10 @@ public:
 void LoopProcess(Core::System& system) {
     auto server_manager = std::make_unique<ServerManager>(system);
 
-    server_manager->RegisterNamedService("mii:e", std::make_shared<MiiDBModule>(system, "mii:e"));
-    server_manager->RegisterNamedService("mii:u", std::make_shared<MiiDBModule>(system, "mii:u"));
+    server_manager->RegisterNamedService("mii:e",
+                                         std::make_shared<MiiDBModule>(system, "mii:e", true));
+    server_manager->RegisterNamedService("mii:u",
+                                         std::make_shared<MiiDBModule>(system, "mii:u", false));
     server_manager->RegisterNamedService("miiimg", std::make_shared<MiiImg>(system));
     ServerManager::RunServer(std::move(server_manager));
 }

+ 102 - 60
src/core/hle/service/mii/mii_manager.cpp

@@ -16,45 +16,18 @@
 #include "core/hle/service/mii/types/raw_data.h"
 
 namespace Service::Mii {
-
-namespace {
-
 constexpr std::size_t DefaultMiiCount{RawData::DefaultMii.size()};
 
-CharInfo ConvertStoreDataToInfo(const StoreData& data) {
-    CharInfo char_info{};
-    char_info.SetFromStoreData(data);
-    return char_info;
-}
-
-StoreData BuildRandomStoreData(Age age, Gender gender, Race race, const Common::UUID& user_id) {
-    StoreData store_data{};
-    store_data.BuildRandom(age, gender, race);
-
-    return store_data;
-}
+MiiManager::MiiManager() {}
 
-StoreData BuildDefaultStoreData(const DefaultMii& info, const Common::UUID& user_id) {
-    StoreData store_data{};
-    store_data.BuildDefault(0);
-
-    return store_data;
-}
-
-} // namespace
-
-MiiManager::MiiManager() : user_id{Service::Account::ProfileManager().GetLastOpenedUser()} {}
-
-bool MiiManager::CheckAndResetUpdateCounter(SourceFlag source_flag, u64& current_update_counter) {
+bool MiiManager::IsUpdated(DatabaseSessionMetadata& metadata, SourceFlag source_flag) const {
     if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
         return false;
     }
 
-    const bool result{current_update_counter != update_counter};
-
-    current_update_counter = update_counter;
-
-    return result;
+    const auto metadata_update_counter = metadata.update_counter;
+    metadata.update_counter = update_counter;
+    return metadata_update_counter != update_counter;
 }
 
 bool MiiManager::IsFullDatabase() const {
@@ -62,19 +35,19 @@ bool MiiManager::IsFullDatabase() const {
     return false;
 }
 
-u32 MiiManager::GetCount(SourceFlag source_flag) const {
-    std::size_t count{};
-    if ((source_flag & SourceFlag::Database) != SourceFlag::None) {
-        // TODO(bunnei): We don't implement the Mii database, but when we do, update this
-        count += 0;
+u32 MiiManager::GetCount(const DatabaseSessionMetadata& metadata, SourceFlag source_flag) const {
+    u32 mii_count{};
+    if ((source_flag & SourceFlag::Default) == SourceFlag::None) {
+        mii_count += DefaultMiiCount;
     }
-    if ((source_flag & SourceFlag::Default) != SourceFlag::None) {
-        count += DefaultMiiCount;
+    if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
+        // TODO(bunnei): We don't implement the Mii database, but when we do, update this
     }
-    return static_cast<u32>(count);
+    return mii_count;
 }
 
-Result MiiManager::UpdateLatest(CharInfo* out_info, const CharInfo& info, SourceFlag source_flag) {
+Result MiiManager::UpdateLatest(DatabaseSessionMetadata& metadata, CharInfo& out_char_info,
+                                const CharInfo& char_info, SourceFlag source_flag) {
     if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
         return ResultNotFound;
     }
@@ -83,48 +56,117 @@ Result MiiManager::UpdateLatest(CharInfo* out_info, const CharInfo& info, Source
     return ResultNotFound;
 }
 
-CharInfo MiiManager::BuildRandom(Age age, Gender gender, Race race) {
-    return ConvertStoreDataToInfo(BuildRandomStoreData(age, gender, race, user_id));
+void MiiManager::BuildDefault(CharInfo& out_char_info, u32 index) const {
+    StoreData store_data{};
+    store_data.BuildDefault(index);
+    out_char_info.SetFromStoreData(store_data);
 }
 
-CharInfo MiiManager::BuildBase(Gender gender) {
-    const std::size_t index = gender == Gender::Female ? 1 : 0;
-    return ConvertStoreDataToInfo(BuildDefaultStoreData(RawData::BaseMii.at(index), user_id));
+void MiiManager::BuildBase(CharInfo& out_char_info, Gender gender) const {
+    StoreData store_data{};
+    store_data.BuildBase(gender);
+    out_char_info.SetFromStoreData(store_data);
 }
 
-CharInfo MiiManager::BuildDefault(std::size_t index) {
-    return ConvertStoreDataToInfo(BuildDefaultStoreData(RawData::DefaultMii.at(index), user_id));
+void MiiManager::BuildRandom(CharInfo& out_char_info, Age age, Gender gender, Race race) const {
+    StoreData store_data{};
+    store_data.BuildRandom(age, gender, race);
+    out_char_info.SetFromStoreData(store_data);
 }
 
-CharInfo MiiManager::ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const {
-    CharInfo char_info{};
+void MiiManager::ConvertV3ToCharInfo(CharInfo& out_char_info, const Ver3StoreData& mii_v3) const {
     StoreData store_data{};
     mii_v3.BuildToStoreData(store_data);
-    char_info.SetFromStoreData(store_data);
-    return char_info;
+    out_char_info.SetFromStoreData(store_data);
 }
 
-std::vector<CharInfoElement> MiiManager::GetDefault(SourceFlag source_flag) {
-    std::vector<CharInfoElement> result;
+Result MiiManager::Get(const DatabaseSessionMetadata& metadata,
+                       std::span<CharInfoElement> out_elements, u32& out_count,
+                       SourceFlag source_flag) {
+    if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
+        return BuildDefault(out_elements, out_count, source_flag);
+    }
 
+    // TODO(bunnei): We don't implement the Mii database, so we can't have an entry
+
+    // Include default Mii at the end of the list
+    return BuildDefault(out_elements, out_count, source_flag);
+}
+
+Result MiiManager::Get(const DatabaseSessionMetadata& metadata, std::span<CharInfo> out_char_info,
+                       u32& out_count, SourceFlag source_flag) {
+    if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
+        return BuildDefault(out_char_info, out_count, source_flag);
+    }
+
+    // TODO(bunnei): We don't implement the Mii database, so we can't have an entry
+
+    // Include default Mii at the end of the list
+    return BuildDefault(out_char_info, out_count, source_flag);
+}
+
+Result MiiManager::BuildDefault(std::span<CharInfoElement> out_elements, u32& out_count,
+                                SourceFlag source_flag) {
+    if ((source_flag & SourceFlag::Default) == SourceFlag::None) {
+        return ResultSuccess;
+    }
+
+    StoreData store_data{};
+
+    for (std::size_t index = 0; index < DefaultMiiCount; ++index) {
+        if (out_elements.size() <= static_cast<std::size_t>(out_count)) {
+            return ResultInvalidArgumentSize;
+        }
+
+        store_data.BuildDefault(static_cast<u32>(index));
+
+        out_elements[out_count].source = Source::Default;
+        out_elements[out_count].char_info.SetFromStoreData(store_data);
+        out_count++;
+    }
+
+    return ResultSuccess;
+}
+
+Result MiiManager::BuildDefault(std::span<CharInfo> out_char_info, u32& out_count,
+                                SourceFlag source_flag) {
     if ((source_flag & SourceFlag::Default) == SourceFlag::None) {
-        return result;
+        return ResultSuccess;
     }
 
-    for (std::size_t index = 0; index < DefaultMiiCount; index++) {
-        result.emplace_back(BuildDefault(index), Source::Default);
+    StoreData store_data{};
+
+    for (std::size_t index = 0; index < DefaultMiiCount; ++index) {
+        if (out_char_info.size() <= static_cast<std::size_t>(out_count)) {
+            return ResultInvalidArgumentSize;
+        }
+
+        store_data.BuildDefault(static_cast<u32>(index));
+
+        out_char_info[out_count].SetFromStoreData(store_data);
+        out_count++;
     }
 
-    return result;
+    return ResultSuccess;
 }
 
-Result MiiManager::GetIndex([[maybe_unused]] const CharInfo& info, u32& index) {
+Result MiiManager::GetIndex(const DatabaseSessionMetadata& metadata, const CharInfo& char_info,
+                            s32& out_index) {
+
+    if (char_info.Verify() != 0) {
+        return ResultInvalidCharInfo;
+    }
+
     constexpr u32 INVALID_INDEX{0xFFFFFFFF};
 
-    index = INVALID_INDEX;
+    out_index = INVALID_INDEX;
 
     // TODO(bunnei): We don't implement the Mii database, so we can't have an index
     return ResultNotFound;
 }
 
+void MiiManager::SetInterfaceVersion(DatabaseSessionMetadata& metadata, u32 version) {
+    metadata.interface_version = version;
+}
+
 } // namespace Service::Mii

+ 20 - 9
src/core/hle/service/mii/mii_manager.h

@@ -19,16 +19,24 @@ class MiiManager {
 public:
     MiiManager();
 
-    bool CheckAndResetUpdateCounter(SourceFlag source_flag, u64& current_update_counter);
+    bool IsUpdated(DatabaseSessionMetadata& metadata, SourceFlag source_flag) const;
+
     bool IsFullDatabase() const;
-    u32 GetCount(SourceFlag source_flag) const;
-    Result UpdateLatest(CharInfo* out_info, const CharInfo& info, SourceFlag source_flag);
-    CharInfo BuildRandom(Age age, Gender gender, Race race);
-    CharInfo BuildBase(Gender gender);
-    CharInfo BuildDefault(std::size_t index);
-    CharInfo ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const;
+    u32 GetCount(const DatabaseSessionMetadata& metadata, SourceFlag source_flag) const;
+    Result UpdateLatest(DatabaseSessionMetadata& metadata, CharInfo& out_char_info,
+                        const CharInfo& char_info, SourceFlag source_flag);
+    Result Get(const DatabaseSessionMetadata& metadata, std::span<CharInfoElement> out_elements,
+               u32& out_count, SourceFlag source_flag);
+    Result Get(const DatabaseSessionMetadata& metadata, std::span<CharInfo> out_char_info,
+               u32& out_count, SourceFlag source_flag);
+    void BuildDefault(CharInfo& out_char_info, u32 index) const;
+    void BuildBase(CharInfo& out_char_info, Gender gender) const;
+    void BuildRandom(CharInfo& out_char_info, Age age, Gender gender, Race race) const;
+    void ConvertV3ToCharInfo(CharInfo& out_char_info, const Ver3StoreData& mii_v3) const;
     std::vector<CharInfoElement> GetDefault(SourceFlag source_flag);
-    Result GetIndex(const CharInfo& info, u32& index);
+    Result GetIndex(const DatabaseSessionMetadata& metadata, const CharInfo& char_info,
+                    s32& out_index);
+    void SetInterfaceVersion(DatabaseSessionMetadata& metadata, u32 version);
 
     struct MiiDatabase {
         u32 magic{}; // 'NFDB'
@@ -40,7 +48,10 @@ public:
     static_assert(sizeof(MiiDatabase) == 0x1A98, "MiiDatabase has incorrect size.");
 
 private:
-    const Common::UUID user_id{};
+    Result BuildDefault(std::span<CharInfoElement> out_elements, u32& out_count,
+                        SourceFlag source_flag);
+    Result BuildDefault(std::span<CharInfo> out_char_info, u32& out_count, SourceFlag source_flag);
+
     u64 update_counter{};
 };
 

+ 10 - 0
src/core/hle/service/mii/mii_types.h

@@ -165,4 +165,14 @@ struct DefaultMii {
 };
 static_assert(sizeof(DefaultMii) == 0xd8, "MiiStoreData has incorrect size.");
 
+struct DatabaseSessionMetadata {
+    u32 interface_version;
+    u32 magic;
+    u64 update_counter;
+
+    bool IsInterfaceVersionSupported(u32 version) const {
+        return version <= interface_version;
+    }
+};
+
 } // namespace Service::Mii

+ 6 - 2
src/core/hle/service/nfc/common/device.cpp

@@ -680,12 +680,16 @@ Result NfcDevice::GetRegisterInfo(NFP::RegisterInfo& register_info) const {
         return ResultRegistrationIsNotInitialized;
     }
 
-    Service::Mii::MiiManager manager;
+    Mii::CharInfo char_info{};
+    Mii::StoreData store_data{};
+    tag_data.owner_mii.BuildToStoreData(store_data);
+    char_info.SetFromStoreData(store_data);
+
     const auto& settings = tag_data.settings;
 
     // TODO: Validate this data
     register_info = {
-        .mii_char_info = manager.ConvertV3ToCharInfo(tag_data.owner_mii),
+        .mii_char_info = char_info,
         .creation_date = settings.init_date.GetWriteDate(),
         .amiibo_name = GetAmiiboName(settings),
         .font_region = settings.settings.font_region,