diff options
Diffstat (limited to 'src/core/hle/service')
| -rw-r--r-- | src/core/hle/service/mii/mii_database.cpp | 142 | ||||
| -rw-r--r-- | src/core/hle/service/mii/mii_database.h | 66 | 
2 files changed, 208 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 diff --git a/src/core/hle/service/mii/mii_database.h b/src/core/hle/service/mii/mii_database.h new file mode 100644 index 000000000..01764999f --- /dev/null +++ b/src/core/hle/service/mii/mii_database.h @@ -0,0 +1,66 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "core/hle/result.h" +#include "core/hle/service/mii/types/store_data.h" + +namespace Service::Mii { + +constexpr std::size_t MaxDatabaseLength{100}; +constexpr u32 MiiMagic{0xa523b78f}; +constexpr u32 DatabaseMagic{0x4244464e}; // NFDB + +class NintendoFigurineDatabase { +public: +    /// Returns the total mii count. +    u8 GetDatabaseLength() const; + +    /// Returns full if database is full. +    bool IsFull() const; + +    /// Returns the mii of the specified index. +    StoreData Get(std::size_t index) const; + +    ///  Returns the total mii count. Ignoring special mii. +    u32 GetCount(const DatabaseSessionMetadata& metadata) const; + +    /// Returns the index of a mii. If the mii isn't found returns false. +    bool GetIndexByCreatorId(u32& out_index, const Common::UUID& create_id) const; + +    /// Moves the location of a specific mii. +    Result Move(u32 current_index, u32 new_index); + +    /// Replaces mii with new data. +    void Replace(u32 index, const StoreData& store_data); + +    /// Adds a new mii to the end of the database. +    void Add(const StoreData& store_data); + +    /// Removes mii from database and shifts left the remainding data. +    void Delete(u32 index); + +    /// Deletes all contents with a fresh database +    void CleanDatabase(); + +    /// Intentionally sets a bad checksum +    void CorruptCrc(); + +    /// Returns success if database is valid otherwise returns the corresponding error code. +    Result CheckIntegrity(); + +private: +    /// Returns the checksum of the database +    u16 GenerateDatabaseCrc(); + +    u32 magic{}; // 'NFDB' +    std::array<StoreData, MaxDatabaseLength> miis{}; +    u8 version{}; +    u8 database_length{}; +    u16 crc{}; +}; +static_assert(sizeof(NintendoFigurineDatabase) == 0x1A98, +              "NintendoFigurineDatabase has incorrect size."); + +}; // namespace Service::Mii | 
