diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/hle/service/mii/mii_database.cpp | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/src/core/hle/service/mii/mii_database.cpp b/src/core/hle/service/mii/mii_database.cpp new file mode 100644 index 000000000..0899f0b45 --- /dev/null +++ b/src/core/hle/service/mii/mii_database.cpp @@ -0,0 +1,142 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/mii/mii_database.h" +#include "core/hle/service/mii/mii_result.h" +#include "core/hle/service/mii/mii_util.h" + +namespace Service::Mii { + +u8 NintendoFigurineDatabase::GetDatabaseLength() const { + return database_length; +} + +bool NintendoFigurineDatabase::IsFull() const { + return database_length >= MaxDatabaseLength; +} + +StoreData NintendoFigurineDatabase::Get(std::size_t index) const { + StoreData store_data = miis.at(index); + + // This hack is to make external database dump compatible + store_data.SetDeviceChecksum(); + + return store_data; +} + +u32 NintendoFigurineDatabase::GetCount(const DatabaseSessionMetadata& metadata) const { + if (magic == MiiMagic) { + return GetDatabaseLength(); + } + + u32 mii_count{}; + for (std::size_t index = 0; index < mii_count; ++index) { + const auto& store_data = Get(index); + if (!store_data.IsSpecial()) { + mii_count++; + } + } + + return mii_count; +} + +bool NintendoFigurineDatabase::GetIndexByCreatorId(u32& out_index, + const Common::UUID& create_id) const { + for (std::size_t index = 0; index < database_length; ++index) { + if (miis[index].GetCreateId() == create_id) { + out_index = static_cast<u32>(index); + return true; + } + } + + return false; +} + +Result NintendoFigurineDatabase::Move(u32 current_index, u32 new_index) { + if (current_index == new_index) { + return ResultNotUpdated; + } + + const StoreData store_data = miis[current_index]; + + if (new_index > current_index) { + // shift left + const u32 index_diff = new_index - current_index; + for (std::size_t i = 0; i < index_diff; i++) { + miis[current_index + i] = miis[current_index + i + 1]; + } + } else { + // shift right + const u32 index_diff = current_index - new_index; + for (std::size_t i = 0; i < index_diff; i++) { + miis[current_index - i] = miis[current_index - i - 1]; + } + } + + miis[new_index] = store_data; + crc = GenerateDatabaseCrc(); + return ResultSuccess; +} + +void NintendoFigurineDatabase::Replace(u32 index, const StoreData& store_data) { + miis[index] = store_data; + crc = GenerateDatabaseCrc(); +} + +void NintendoFigurineDatabase::Add(const StoreData& store_data) { + miis[database_length] = store_data; + database_length++; + crc = GenerateDatabaseCrc(); +} + +void NintendoFigurineDatabase::Delete(u32 index) { + // shift left + s32 new_database_size = database_length - 1; + if (static_cast<s32>(index) < new_database_size) { + for (std::size_t i = index; i < static_cast<std::size_t>(new_database_size); i++) { + miis[i] = miis[i + 1]; + } + } + + database_length = static_cast<u8>(new_database_size); + crc = GenerateDatabaseCrc(); +} + +void NintendoFigurineDatabase::CleanDatabase() { + memset(miis.data(), 0, sizeof(miis)); + version = 1; + magic = DatabaseMagic; + database_length = 0; + crc = GenerateDatabaseCrc(); +} + +void NintendoFigurineDatabase::CorruptCrc() { + crc = GenerateDatabaseCrc(); + crc = ~crc; +} + +Result NintendoFigurineDatabase::CheckIntegrity() { + if (magic != DatabaseMagic) { + return ResultInvalidDatabaseSignature; + } + + if (version != 1) { + return ResultInvalidDatabaseVersion; + } + + if (crc != GenerateDatabaseCrc()) { + return ResultInvalidDatabaseChecksum; + } + + if (database_length >= MaxDatabaseLength) { + return ResultInvalidDatabaseLength; + } + + return ResultSuccess; +} + +u16 NintendoFigurineDatabase::GenerateDatabaseCrc() { + return MiiUtil::CalculateCrc16(&magic, sizeof(NintendoFigurineDatabase) - sizeof(crc)); +} + +} // namespace Service::Mii |