From f0db2e3ef36a77f2f3eaf2dca15ddfe8851edecb Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 24 Dec 2018 13:30:07 -0500 Subject: mii_manager: Cleanup and optimization --- src/core/hle/service/mii/mii_manager.cpp | 68 ++++++++++++++++++-------------- src/core/hle/service/mii/mii_manager.h | 10 ++++- 2 files changed, 46 insertions(+), 32 deletions(-) (limited to 'src/core/hle/service/mii') diff --git a/src/core/hle/service/mii/mii_manager.cpp b/src/core/hle/service/mii/mii_manager.cpp index 25dfd8d48..083c62b1e 100644 --- a/src/core/hle/service/mii/mii_manager.cpp +++ b/src/core/hle/service/mii/mii_manager.cpp @@ -12,8 +12,10 @@ namespace Service::Mii { +namespace { + constexpr char MII_SAVE_DATABASE_PATH[] = "/system/save/8000000000000030/MiiDatabase.dat"; -constexpr std::array DEFAULT_MII_NAME = {'y', 'u', 'z', 'u', '\0'}; +constexpr std::array DEFAULT_MII_NAME = {u'y', u'u', u'z', u'u', u'\0'}; // This value was retrieved from HW test constexpr MiiStoreData DEFAULT_MII = { @@ -30,10 +32,10 @@ constexpr MiiStoreData DEFAULT_MII = { // Default values taken from multiple real databases const MiiDatabase DEFAULT_MII_DATABASE{Common::MakeMagic('N', 'F', 'D', 'B'), {}, {1}, 0, 0}; -template -std::array ResizeArray(const std::array& in) { - std::array out{}; - std::memcpy(out.data(), in.data(), sizeof(T) * std::min(s1, s2)); +template +std::array ResizeArray(const std::array& in) { + std::array out{}; + std::memcpy(out.data(), in.data(), sizeof(T) * std::min(SourceArraySize, DestArraySize)); return out; } @@ -163,12 +165,14 @@ MiiStoreData ConvertInfoToStoreData(const MiiInfo& info) { return out; } +} // namespace + std::u16string MiiInfo::Name() const { return Common::UTF16StringFromFixedZeroTerminatedBuffer(name.data(), name.size()); } bool operator==(const MiiInfo& lhs, const MiiInfo& rhs) { - return std::memcmp(&lhs, &rhs, sizeof(MiiInfo)); + return std::memcmp(&lhs, &rhs, sizeof(MiiInfo)) == 0; } bool operator!=(const MiiInfo& lhs, const MiiInfo& rhs) { @@ -188,27 +192,15 @@ MiiInfo MiiManager::CreateRandom(RandomParameters params) { "(STUBBED) called with params={:08X}{:08X}{:08X}, returning default Mii", params.unknown_1, params.unknown_2, params.unknown_3); - auto new_mii = DEFAULT_MII; - - do { - new_mii.uuid = Common::UUID::Generate(); - } while (IndexOf(new_mii.uuid) == INVALID_INDEX); - - return ConvertStoreDataToInfo(new_mii); + return ConvertStoreDataToInfo(CreateMiiWithUniqueUUID()); } MiiInfo MiiManager::CreateDefault(u32 index) { - auto new_mii = DEFAULT_MII; - - do { - new_mii.uuid = Common::UUID::Generate(); - } while (IndexOf(new_mii.uuid) == INVALID_INDEX); + const auto new_mii = CreateMiiWithUniqueUUID(); - ASSERT(index < MAX_MIIS); - database.miis[index] = new_mii; - std::stable_partition(database.miis.begin(), database.miis.end(), - [](const MiiStoreData& elem) { return elem.uuid; }); + database.miis.at(index) = new_mii; + EnsureDatabasePartition(); return ConvertStoreDataToInfo(new_mii); } @@ -253,8 +245,7 @@ bool MiiManager::Remove(Common::UUID uuid) { return false; *iter = MiiStoreData{}; - std::stable_partition(database.miis.begin(), database.miis.end(), - [](const MiiStoreData& elem) { return elem.uuid; }); + EnsureDatabasePartition(); return true; } @@ -268,9 +259,9 @@ u32 MiiManager::IndexOf(Common::UUID uuid) const { return static_cast(std::distance(database.miis.begin(), iter)); } -u32 MiiManager::IndexOf(MiiInfo info) const { +u32 MiiManager::IndexOf(const MiiInfo& info) const { const auto iter = - std::find_if(database.miis.begin(), database.miis.end(), [info](const MiiStoreData& elem) { + std::find_if(database.miis.begin(), database.miis.end(), [&info](const MiiStoreData& elem) { return ConvertStoreDataToInfo(elem) == info; }); @@ -296,12 +287,11 @@ bool MiiManager::Move(Common::UUID uuid, u32 new_index) { database.miis[new_index] = moving; } - std::stable_partition(database.miis.begin(), database.miis.end(), - [](const MiiStoreData& elem) { return elem.uuid; }); + EnsureDatabasePartition(); return true; } -bool MiiManager::AddOrReplace(MiiStoreData data) { +bool MiiManager::AddOrReplace(const MiiStoreData& data) { const auto index = IndexOf(data.uuid); if (index == INVALID_INDEX) { @@ -341,7 +331,11 @@ void MiiManager::WriteToFile() { } save.Resize(sizeof(MiiDatabase)); - save.WriteBytes(&database, sizeof(MiiDatabase)); + if (save.WriteBytes(&database, sizeof(MiiDatabase)) != sizeof(MiiDatabase)) { + LOG_WARNING(Service_Mii, "Failed to write all data to save file... Data may be malformed " + "and/or regenerated on next run."); + save.Resize(0); + } } void MiiManager::ReadFromFile() { @@ -362,6 +356,20 @@ void MiiManager::ReadFromFile() { return; } + EnsureDatabasePartition(); +} + +MiiStoreData MiiManager::CreateMiiWithUniqueUUID() const { + auto new_mii = DEFAULT_MII; + + do { + new_mii.uuid = Common::UUID::Generate(); + } while (IndexOf(new_mii.uuid) == INVALID_INDEX); + + return new_mii; +} + +void MiiManager::EnsureDatabasePartition() { std::stable_partition(database.miis.begin(), database.miis.end(), [](const MiiStoreData& elem) { return elem.uuid; }); } diff --git a/src/core/hle/service/mii/mii_manager.h b/src/core/hle/service/mii/mii_manager.h index 069247cb6..f7e3d2cf9 100644 --- a/src/core/hle/service/mii/mii_manager.h +++ b/src/core/hle/service/mii/mii_manager.h @@ -84,6 +84,8 @@ struct MiiInfo { std::u16string Name() const; }; static_assert(sizeof(MiiInfo) == 0x58, "MiiInfo has incorrect size."); +static_assert(std::has_unique_object_representations_v, + "All bits of MiiInfo must contribute to its value."); bool operator==(const MiiInfo& lhs, const MiiInfo& rhs); bool operator!=(const MiiInfo& lhs, const MiiInfo& rhs); @@ -238,15 +240,19 @@ public: bool Remove(Common::UUID uuid); u32 IndexOf(Common::UUID uuid) const; - u32 IndexOf(MiiInfo info) const; + u32 IndexOf(const MiiInfo& info) const; bool Move(Common::UUID uuid, u32 new_index); - bool AddOrReplace(MiiStoreData data); + bool AddOrReplace(const MiiStoreData& data); private: void WriteToFile(); void ReadFromFile(); + MiiStoreData CreateMiiWithUniqueUUID() const; + + void EnsureDatabasePartition(); + MiiDatabase database; }; -- cgit v1.2.3