summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar german772023-09-17 10:47:39 -0600
committerGravatar german772023-09-17 16:06:25 -0600
commita50b50f8b4450331fa44f18b7457affa001ab6c9 (patch)
tree9aa80d98fdc6d742231b4c052d01d8f1da88d540
parentservice: mii: Add device crc16 (diff)
downloadyuzu-a50b50f8b4450331fa44f18b7457affa001ab6c9.tar.gz
yuzu-a50b50f8b4450331fa44f18b7457affa001ab6c9.tar.xz
yuzu-a50b50f8b4450331fa44f18b7457affa001ab6c9.zip
service: mii: Implement figurine database
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/hle/service/mii/mii_database.cpp142
-rw-r--r--src/core/hle/service/mii/mii_database.h66
3 files changed, 210 insertions, 0 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index b2dc71d4c..9d22cc945 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -596,6 +596,8 @@ add_library(core STATIC
596 hle/service/mii/types/ver3_store_data.h 596 hle/service/mii/types/ver3_store_data.h
597 hle/service/mii/mii.cpp 597 hle/service/mii/mii.cpp
598 hle/service/mii/mii.h 598 hle/service/mii/mii.h
599 hle/service/mii/mii_database.cpp
600 hle/service/mii/mii_database.h
599 hle/service/mii/mii_manager.cpp 601 hle/service/mii/mii_manager.cpp
600 hle/service/mii/mii_manager.h 602 hle/service/mii/mii_manager.h
601 hle/service/mii/mii_result.h 603 hle/service/mii/mii_result.h
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 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/service/mii/mii_database.h"
5#include "core/hle/service/mii/mii_result.h"
6#include "core/hle/service/mii/mii_util.h"
7
8namespace Service::Mii {
9
10u8 NintendoFigurineDatabase::GetDatabaseLength() const {
11 return database_length;
12}
13
14bool NintendoFigurineDatabase::IsFull() const {
15 return database_length >= MaxDatabaseLength;
16}
17
18StoreData NintendoFigurineDatabase::Get(std::size_t index) const {
19 StoreData store_data = miis.at(index);
20
21 // This hack is to make external database dump compatible
22 store_data.SetDeviceChecksum();
23
24 return store_data;
25}
26
27u32 NintendoFigurineDatabase::GetCount(const DatabaseSessionMetadata& metadata) const {
28 if (magic == MiiMagic) {
29 return GetDatabaseLength();
30 }
31
32 u32 mii_count{};
33 for (std::size_t index = 0; index < mii_count; ++index) {
34 const auto& store_data = Get(index);
35 if (!store_data.IsSpecial()) {
36 mii_count++;
37 }
38 }
39
40 return mii_count;
41}
42
43bool NintendoFigurineDatabase::GetIndexByCreatorId(u32& out_index,
44 const Common::UUID& create_id) const {
45 for (std::size_t index = 0; index < database_length; ++index) {
46 if (miis[index].GetCreateId() == create_id) {
47 out_index = static_cast<u32>(index);
48 return true;
49 }
50 }
51
52 return false;
53}
54
55Result NintendoFigurineDatabase::Move(u32 current_index, u32 new_index) {
56 if (current_index == new_index) {
57 return ResultNotUpdated;
58 }
59
60 const StoreData store_data = miis[current_index];
61
62 if (new_index > current_index) {
63 // shift left
64 const u32 index_diff = new_index - current_index;
65 for (std::size_t i = 0; i < index_diff; i++) {
66 miis[current_index + i] = miis[current_index + i + 1];
67 }
68 } else {
69 // shift right
70 const u32 index_diff = current_index - new_index;
71 for (std::size_t i = 0; i < index_diff; i++) {
72 miis[current_index - i] = miis[current_index - i - 1];
73 }
74 }
75
76 miis[new_index] = store_data;
77 crc = GenerateDatabaseCrc();
78 return ResultSuccess;
79}
80
81void NintendoFigurineDatabase::Replace(u32 index, const StoreData& store_data) {
82 miis[index] = store_data;
83 crc = GenerateDatabaseCrc();
84}
85
86void NintendoFigurineDatabase::Add(const StoreData& store_data) {
87 miis[database_length] = store_data;
88 database_length++;
89 crc = GenerateDatabaseCrc();
90}
91
92void NintendoFigurineDatabase::Delete(u32 index) {
93 // shift left
94 s32 new_database_size = database_length - 1;
95 if (static_cast<s32>(index) < new_database_size) {
96 for (std::size_t i = index; i < static_cast<std::size_t>(new_database_size); i++) {
97 miis[i] = miis[i + 1];
98 }
99 }
100
101 database_length = static_cast<u8>(new_database_size);
102 crc = GenerateDatabaseCrc();
103}
104
105void NintendoFigurineDatabase::CleanDatabase() {
106 memset(miis.data(), 0, sizeof(miis));
107 version = 1;
108 magic = DatabaseMagic;
109 database_length = 0;
110 crc = GenerateDatabaseCrc();
111}
112
113void NintendoFigurineDatabase::CorruptCrc() {
114 crc = GenerateDatabaseCrc();
115 crc = ~crc;
116}
117
118Result NintendoFigurineDatabase::CheckIntegrity() {
119 if (magic != DatabaseMagic) {
120 return ResultInvalidDatabaseSignature;
121 }
122
123 if (version != 1) {
124 return ResultInvalidDatabaseVersion;
125 }
126
127 if (crc != GenerateDatabaseCrc()) {
128 return ResultInvalidDatabaseChecksum;
129 }
130
131 if (database_length >= MaxDatabaseLength) {
132 return ResultInvalidDatabaseLength;
133 }
134
135 return ResultSuccess;
136}
137
138u16 NintendoFigurineDatabase::GenerateDatabaseCrc() {
139 return MiiUtil::CalculateCrc16(&magic, sizeof(NintendoFigurineDatabase) - sizeof(crc));
140}
141
142} // 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 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/result.h"
7#include "core/hle/service/mii/types/store_data.h"
8
9namespace Service::Mii {
10
11constexpr std::size_t MaxDatabaseLength{100};
12constexpr u32 MiiMagic{0xa523b78f};
13constexpr u32 DatabaseMagic{0x4244464e}; // NFDB
14
15class NintendoFigurineDatabase {
16public:
17 /// Returns the total mii count.
18 u8 GetDatabaseLength() const;
19
20 /// Returns full if database is full.
21 bool IsFull() const;
22
23 /// Returns the mii of the specified index.
24 StoreData Get(std::size_t index) const;
25
26 /// Returns the total mii count. Ignoring special mii.
27 u32 GetCount(const DatabaseSessionMetadata& metadata) const;
28
29 /// Returns the index of a mii. If the mii isn't found returns false.
30 bool GetIndexByCreatorId(u32& out_index, const Common::UUID& create_id) const;
31
32 /// Moves the location of a specific mii.
33 Result Move(u32 current_index, u32 new_index);
34
35 /// Replaces mii with new data.
36 void Replace(u32 index, const StoreData& store_data);
37
38 /// Adds a new mii to the end of the database.
39 void Add(const StoreData& store_data);
40
41 /// Removes mii from database and shifts left the remainding data.
42 void Delete(u32 index);
43
44 /// Deletes all contents with a fresh database
45 void CleanDatabase();
46
47 /// Intentionally sets a bad checksum
48 void CorruptCrc();
49
50 /// Returns success if database is valid otherwise returns the corresponding error code.
51 Result CheckIntegrity();
52
53private:
54 /// Returns the checksum of the database
55 u16 GenerateDatabaseCrc();
56
57 u32 magic{}; // 'NFDB'
58 std::array<StoreData, MaxDatabaseLength> miis{};
59 u8 version{};
60 u8 database_length{};
61 u16 crc{};
62};
63static_assert(sizeof(NintendoFigurineDatabase) == 0x1A98,
64 "NintendoFigurineDatabase has incorrect size.");
65
66}; // namespace Service::Mii