summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/mii/mii_manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/service/mii/mii_manager.cpp')
-rw-r--r--src/core/hle/service/mii/mii_manager.cpp410
1 files changed, 362 insertions, 48 deletions
diff --git a/src/core/hle/service/mii/mii_manager.cpp b/src/core/hle/service/mii/mii_manager.cpp
index 292d63777..a5a2a9232 100644
--- a/src/core/hle/service/mii/mii_manager.cpp
+++ b/src/core/hle/service/mii/mii_manager.cpp
@@ -1,38 +1,63 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include <cstring>
-#include <random>
-
-#include "common/assert.h"
#include "common/logging/log.h"
-#include "common/string_util.h"
-
-#include "core/hle/service/acc/profile_manager.h"
+#include "core/hle/service/mii/mii_database_manager.h"
#include "core/hle/service/mii/mii_manager.h"
#include "core/hle/service/mii/mii_result.h"
#include "core/hle/service/mii/mii_util.h"
+#include "core/hle/service/mii/types/char_info.h"
#include "core/hle/service/mii/types/core_data.h"
#include "core/hle/service/mii/types/raw_data.h"
+#include "core/hle/service/mii/types/store_data.h"
+#include "core/hle/service/mii/types/ver3_store_data.h"
namespace Service::Mii {
constexpr std::size_t DefaultMiiCount{RawData::DefaultMii.size()};
MiiManager::MiiManager() {}
+Result MiiManager::Initialize(DatabaseSessionMetadata& metadata) {
+ database_manager.MountSaveData();
+ database_manager.Initialize(metadata, is_broken_with_clear_flag);
+ return ResultSuccess;
+}
+
+void MiiManager::BuildDefault(CharInfo& out_char_info, u32 index) const {
+ StoreData store_data{};
+ store_data.BuildDefault(index);
+ out_char_info.SetFromStoreData(store_data);
+}
+
+void MiiManager::BuildBase(CharInfo& out_char_info, Gender gender) const {
+ StoreData store_data{};
+ store_data.BuildBase(gender);
+ out_char_info.SetFromStoreData(store_data);
+}
+
+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);
+}
+
+bool MiiManager::IsFullDatabase() const {
+ return database_manager.IsFullDatabase();
+}
+
+void MiiManager::SetInterfaceVersion(DatabaseSessionMetadata& metadata, u32 version) const {
+ metadata.interface_version = version;
+}
+
bool MiiManager::IsUpdated(DatabaseSessionMetadata& metadata, SourceFlag source_flag) const {
if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
return false;
}
- const auto metadata_update_counter = metadata.update_counter;
- metadata.update_counter = update_counter;
- return metadata_update_counter != update_counter;
-}
-
-bool MiiManager::IsFullDatabase() const {
- // TODO(bunnei): We don't implement the Mii database, so it cannot be full
- return false;
+ const u64 metadata_update_counter = metadata.update_counter;
+ const u64 database_update_counter = database_manager.GetUpdateCounter();
+ metadata.update_counter = database_update_counter;
+ return metadata_update_counter != database_update_counter;
}
u32 MiiManager::GetCount(const DatabaseSessionMetadata& metadata, SourceFlag source_flag) const {
@@ -41,72 +66,343 @@ u32 MiiManager::GetCount(const DatabaseSessionMetadata& metadata, SourceFlag sou
mii_count += DefaultMiiCount;
}
if ((source_flag & SourceFlag::Database) != SourceFlag::None) {
- // TODO(bunnei): We don't implement the Mii database, but when we do, update this
+ mii_count += database_manager.GetCount(metadata);
}
return mii_count;
}
-Result MiiManager::UpdateLatest(DatabaseSessionMetadata& metadata, CharInfo& out_char_info,
- const CharInfo& char_info, SourceFlag source_flag) {
- if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
+Result MiiManager::Move(DatabaseSessionMetadata& metadata, u32 index,
+ const Common::UUID& create_id) {
+ const auto result = database_manager.Move(metadata, index, create_id);
+
+ if (result.IsFailure()) {
+ return result;
+ }
+
+ if (!database_manager.IsModified()) {
+ return ResultNotUpdated;
+ }
+
+ return database_manager.SaveDatabase();
+}
+
+Result MiiManager::AddOrReplace(DatabaseSessionMetadata& metadata, const StoreData& store_data) {
+ const auto result = database_manager.AddOrReplace(metadata, store_data);
+
+ if (result.IsFailure()) {
+ return result;
+ }
+
+ if (!database_manager.IsModified()) {
+ return ResultNotUpdated;
+ }
+
+ return database_manager.SaveDatabase();
+}
+
+Result MiiManager::Delete(DatabaseSessionMetadata& metadata, const Common::UUID& create_id) {
+ const auto result = database_manager.Delete(metadata, create_id);
+
+ if (result.IsFailure()) {
+ return result;
+ }
+
+ if (!database_manager.IsModified()) {
+ return ResultNotUpdated;
+ }
+
+ return database_manager.SaveDatabase();
+}
+
+s32 MiiManager::FindIndex(const Common::UUID& create_id, bool is_special) const {
+ s32 index{};
+ const auto result = database_manager.FindIndex(index, create_id, is_special);
+ if (result.IsError()) {
+ index = -1;
+ }
+ return index;
+}
+
+Result MiiManager::GetIndex(const DatabaseSessionMetadata& metadata, const CharInfo& char_info,
+ s32& out_index) const {
+ if (char_info.Verify() != ValidationResult::NoErrors) {
+ return ResultInvalidCharInfo;
+ }
+
+ s32 index{};
+ Result result = {};
+ // FindIndex(index);
+
+ if (result.IsError()) {
+ return ResultNotFound;
+ }
+
+ if (index == -1) {
return ResultNotFound;
}
- // TODO(bunnei): We don't implement the Mii database, so we can't have an entry
- return ResultNotFound;
+ out_index = index;
+ return ResultSuccess;
}
-void MiiManager::BuildDefault(CharInfo& out_char_info, u32 index) const {
- StoreData store_data{};
- store_data.BuildDefault(index);
- out_char_info.SetFromStoreData(store_data);
+Result MiiManager::Append(DatabaseSessionMetadata& metadata, const CharInfo& char_info) {
+ const auto result = database_manager.Append(metadata, char_info);
+
+ if (result.IsError()) {
+ return ResultNotFound;
+ }
+
+ if (!database_manager.IsModified()) {
+ return ResultNotUpdated;
+ }
+
+ return database_manager.SaveDatabase();
}
-void MiiManager::BuildBase(CharInfo& out_char_info, Gender gender) const {
+bool MiiManager::IsBrokenWithClearFlag(DatabaseSessionMetadata& metadata) {
+ const bool is_broken = is_broken_with_clear_flag;
+ if (is_broken_with_clear_flag) {
+ is_broken_with_clear_flag = false;
+ database_manager.Format(metadata);
+ database_manager.SaveDatabase();
+ }
+ return is_broken;
+}
+
+Result MiiManager::DestroyFile(DatabaseSessionMetadata& metadata) {
+ is_broken_with_clear_flag = true;
+ return database_manager.DestroyFile(metadata);
+}
+
+Result MiiManager::DeleteFile() {
+ return database_manager.DeleteFile();
+}
+
+Result MiiManager::Format(DatabaseSessionMetadata& metadata) {
+ database_manager.Format(metadata);
+
+ if (!database_manager.IsModified()) {
+ return ResultNotUpdated;
+ }
+ return database_manager.SaveDatabase();
+}
+
+Result MiiManager::ConvertV3ToCharInfo(CharInfo& out_char_info, const Ver3StoreData& mii_v3) const {
+ if (!mii_v3.IsValid()) {
+ return ResultInvalidCharInfo;
+ }
+
StoreData store_data{};
- store_data.BuildBase(gender);
+ mii_v3.BuildToStoreData(store_data);
+ const auto name = store_data.GetNickname();
+ if (!MiiUtil::IsFontRegionValid(store_data.GetFontRegion(), name.data)) {
+ store_data.SetInvalidName();
+ }
+
out_char_info.SetFromStoreData(store_data);
+ return ResultSuccess;
}
-void MiiManager::BuildRandom(CharInfo& out_char_info, Age age, Gender gender, Race race) const {
+Result MiiManager::ConvertCoreDataToCharInfo(CharInfo& out_char_info,
+ const CoreData& core_data) const {
+ if (core_data.IsValid() != ValidationResult::NoErrors) {
+ return ResultInvalidCharInfo;
+ }
+
StoreData store_data{};
- store_data.BuildRandom(age, gender, race);
+ store_data.BuildWithCoreData(core_data);
+ const auto name = store_data.GetNickname();
+ if (!MiiUtil::IsFontRegionValid(store_data.GetFontRegion(), name.data)) {
+ store_data.SetInvalidName();
+ }
+
out_char_info.SetFromStoreData(store_data);
+ return ResultSuccess;
+}
+
+Result MiiManager::ConvertCharInfoToCoreData(CoreData& out_core_data,
+ const CharInfo& char_info) const {
+ if (char_info.Verify() != ValidationResult::NoErrors) {
+ return ResultInvalidCharInfo;
+ }
+
+ out_core_data.BuildFromCharInfo(char_info);
+ const auto name = out_core_data.GetNickname();
+ if (!MiiUtil::IsFontRegionValid(out_core_data.GetFontRegion(), name.data)) {
+ out_core_data.SetNickname(out_core_data.GetInvalidNickname());
+ }
+
+ return ResultSuccess;
}
-void MiiManager::ConvertV3ToCharInfo(CharInfo& out_char_info, const Ver3StoreData& mii_v3) const {
+Result MiiManager::UpdateLatest(const DatabaseSessionMetadata& metadata, CharInfo& out_char_info,
+ const CharInfo& char_info, SourceFlag source_flag) const {
+ if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
+ return ResultNotFound;
+ }
+
+ if (metadata.IsInterfaceVersionSupported(1)) {
+ if (char_info.Verify() != ValidationResult::NoErrors) {
+ return ResultInvalidCharInfo;
+ }
+ }
+
+ u32 index{};
+ Result result = database_manager.FindIndex(metadata, index, char_info.GetCreateId());
+
+ if (result.IsError()) {
+ return result;
+ }
+
StoreData store_data{};
- mii_v3.BuildToStoreData(store_data);
+ database_manager.Get(store_data, index, metadata);
+
+ if (store_data.GetType() != char_info.GetType()) {
+ return ResultNotFound;
+ }
+
out_char_info.SetFromStoreData(store_data);
+
+ if (char_info == out_char_info) {
+ return ResultNotUpdated;
+ }
+
+ return ResultSuccess;
+}
+
+Result MiiManager::UpdateLatest(const DatabaseSessionMetadata& metadata, StoreData& out_store_data,
+ const StoreData& store_data, SourceFlag source_flag) const {
+ if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
+ return ResultNotFound;
+ }
+
+ if (metadata.IsInterfaceVersionSupported(1)) {
+ if (store_data.IsValid() != ValidationResult::NoErrors) {
+ return ResultInvalidCharInfo;
+ }
+ }
+
+ u32 index{};
+ Result result = database_manager.FindIndex(metadata, index, store_data.GetCreateId());
+
+ if (result.IsError()) {
+ return result;
+ }
+
+ database_manager.Get(out_store_data, index, metadata);
+
+ if (out_store_data.GetType() != store_data.GetType()) {
+ return ResultNotFound;
+ }
+
+ if (store_data == out_store_data) {
+ return ResultNotUpdated;
+ }
+
+ return ResultSuccess;
}
Result MiiManager::Get(const DatabaseSessionMetadata& metadata,
std::span<CharInfoElement> out_elements, u32& out_count,
- SourceFlag source_flag) {
+ SourceFlag source_flag) const {
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
+ const auto mii_count = database_manager.GetCount(metadata);
+
+ for (std::size_t index = 0; index < mii_count; ++index) {
+ if (out_elements.size() <= static_cast<std::size_t>(out_count)) {
+ return ResultInvalidArgumentSize;
+ }
+
+ StoreData store_data{};
+ database_manager.Get(store_data, index, metadata);
+
+ out_elements[out_count].source = Source::Database;
+ out_elements[out_count].char_info.SetFromStoreData(store_data);
+ out_count++;
+ }
// 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) {
+ u32& out_count, SourceFlag source_flag) const {
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
+ const auto mii_count = database_manager.GetCount(metadata);
+
+ for (std::size_t index = 0; index < mii_count; ++index) {
+ if (out_char_info.size() <= static_cast<std::size_t>(out_count)) {
+ return ResultInvalidArgumentSize;
+ }
+
+ StoreData store_data{};
+ database_manager.Get(store_data, index, metadata);
+
+ out_char_info[out_count].SetFromStoreData(store_data);
+ out_count++;
+ }
// Include default Mii at the end of the list
return BuildDefault(out_char_info, out_count, source_flag);
}
+Result MiiManager::Get(const DatabaseSessionMetadata& metadata,
+ std::span<StoreDataElement> out_elements, u32& out_count,
+ SourceFlag source_flag) const {
+ if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
+ return BuildDefault(out_elements, out_count, source_flag);
+ }
+
+ const auto mii_count = database_manager.GetCount(metadata);
+
+ for (std::size_t index = 0; index < mii_count; ++index) {
+ if (out_elements.size() <= static_cast<std::size_t>(out_count)) {
+ return ResultInvalidArgumentSize;
+ }
+
+ StoreData store_data{};
+ database_manager.Get(store_data, index, metadata);
+
+ out_elements[out_count].store_data = store_data;
+ out_elements[out_count].source = Source::Database;
+ out_count++;
+ }
+
+ // 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<StoreData> out_store_data,
+ u32& out_count, SourceFlag source_flag) const {
+ if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
+ return BuildDefault(out_store_data, out_count, source_flag);
+ }
+
+ const auto mii_count = database_manager.GetCount(metadata);
+
+ for (std::size_t index = 0; index < mii_count; ++index) {
+ if (out_store_data.size() <= static_cast<std::size_t>(out_count)) {
+ return ResultInvalidArgumentSize;
+ }
+
+ StoreData store_data{};
+ database_manager.Get(store_data, index, metadata);
+
+ out_store_data[out_count] = store_data;
+ out_count++;
+ }
+
+ // Include default Mii at the end of the list
+ return BuildDefault(out_store_data, out_count, source_flag);
+}
Result MiiManager::BuildDefault(std::span<CharInfoElement> out_elements, u32& out_count,
- SourceFlag source_flag) {
+ SourceFlag source_flag) const {
if ((source_flag & SourceFlag::Default) == SourceFlag::None) {
return ResultSuccess;
}
@@ -129,7 +425,7 @@ Result MiiManager::BuildDefault(std::span<CharInfoElement> out_elements, u32& ou
}
Result MiiManager::BuildDefault(std::span<CharInfo> out_char_info, u32& out_count,
- SourceFlag source_flag) {
+ SourceFlag source_flag) const {
if ((source_flag & SourceFlag::Default) == SourceFlag::None) {
return ResultSuccess;
}
@@ -150,23 +446,41 @@ Result MiiManager::BuildDefault(std::span<CharInfo> out_char_info, u32& out_coun
return ResultSuccess;
}
-Result MiiManager::GetIndex(const DatabaseSessionMetadata& metadata, const CharInfo& char_info,
- s32& out_index) {
-
- if (char_info.Verify() != ValidationResult::NoErrors) {
- return ResultInvalidCharInfo;
+Result MiiManager::BuildDefault(std::span<StoreDataElement> out_elements, u32& out_count,
+ SourceFlag source_flag) const {
+ if ((source_flag & SourceFlag::Default) == SourceFlag::None) {
+ return ResultSuccess;
}
- constexpr u32 INVALID_INDEX{0xFFFFFFFF};
+ for (std::size_t index = 0; index < DefaultMiiCount; ++index) {
+ if (out_elements.size() <= static_cast<std::size_t>(out_count)) {
+ return ResultInvalidArgumentSize;
+ }
- out_index = INVALID_INDEX;
+ out_elements[out_count].store_data.BuildDefault(static_cast<u32>(index));
+ out_elements[out_count].source = Source::Default;
+ out_count++;
+ }
- // TODO(bunnei): We don't implement the Mii database, so we can't have an index
- return ResultNotFound;
+ return ResultSuccess;
}
-void MiiManager::SetInterfaceVersion(DatabaseSessionMetadata& metadata, u32 version) {
- metadata.interface_version = version;
+Result MiiManager::BuildDefault(std::span<StoreData> out_char_info, u32& out_count,
+ SourceFlag source_flag) const {
+ if ((source_flag & SourceFlag::Default) == SourceFlag::None) {
+ return ResultSuccess;
+ }
+
+ for (std::size_t index = 0; index < DefaultMiiCount; ++index) {
+ if (out_char_info.size() <= static_cast<std::size_t>(out_count)) {
+ return ResultInvalidArgumentSize;
+ }
+
+ out_char_info[out_count].BuildDefault(static_cast<u32>(index));
+ out_count++;
+ }
+
+ return ResultSuccess;
}
} // namespace Service::Mii