| 1127 | std::vector<GameDatabase::HashDatabaseEntry> s_hash_database; |
| 1128 | |
| 1129 | static bool parseHashDatabaseEntry(const ryml::NodeRef& node) |
| 1130 | { |
| 1131 | if (!node.has_child("name") || !node.has_child("hashes")) |
| 1132 | { |
| 1133 | Console.Warning("[HashDatabase] Incomplete entry found."); |
| 1134 | return false; |
| 1135 | } |
| 1136 | |
| 1137 | GameDatabase::HashDatabaseEntry entry; |
| 1138 | node["name"] >> entry.name; |
| 1139 | if (node.has_child("version")) |
| 1140 | node["version"] >> entry.version; |
| 1141 | if (node.has_child("serial")) |
| 1142 | node["serial"] >> entry.serial; |
| 1143 | |
| 1144 | const u32 index = static_cast<u32>(s_hash_database.size()); |
| 1145 | for (const ryml::ConstNodeRef& n : node["hashes"].children()) |
| 1146 | { |
| 1147 | if (!n.is_map() || !n.has_child("size") || !n.has_child("md5")) |
| 1148 | { |
| 1149 | Console.ErrorFmt("[HashDatabase] Incomplete hash definition in {}", entry.name); |
| 1150 | return false; |
| 1151 | } |
| 1152 | |
| 1153 | GameDatabase::TrackHash th; |
| 1154 | std::string md5; |
| 1155 | n["md5"] >> md5; |
| 1156 | n["size"] >> th.size; |
| 1157 | |
| 1158 | if (!th.parseHash(md5)) |
| 1159 | { |
| 1160 | Console.ErrorFmt("[HashDatabase] Failed to parse hash in {}: '{}'", entry.name, md5); |
| 1161 | return false; |
| 1162 | } |
| 1163 | |
| 1164 | if (entry.tracks.empty() && s_track_hash_to_entry_map.find(th) != s_track_hash_to_entry_map.end()) |
| 1165 | Console.WarningFmt("[HashDatabase] Duplicate first track hash in {}", entry.name); |
| 1166 | |
| 1167 | entry.tracks.push_back(th); |
| 1168 | s_track_hash_to_entry_map.emplace(th, index); |
| 1169 | } |
| 1170 | |
| 1171 | s_hash_database.push_back(std::move(entry)); |
| 1172 | return true; |
| 1173 | } |
| 1174 | |
| 1175 | bool GameDatabase::loadHashDatabase() |
| 1176 | { |
no test coverage detected