3 changed files with 210 additions and 0 deletions
-
2src/core/CMakeLists.txt
-
142src/core/hle/service/mii/mii_database.cpp
-
66src/core/hle/service/mii/mii_database.h
@ -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
|
|||
@ -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 |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue