From 241900824241a164291cdae62dc994051c1944c7 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 23 Aug 2023 17:32:12 +1000 Subject: [PATCH] GameDatabase: Parse discSetName/discSetSerials --- src/core/game_database.cpp | 62 +++++++++++++++++++++--- src/core/game_database.h | 5 +- src/core/game_list.cpp | 8 +-- src/core/game_list.h | 2 +- src/duckstation-qt/gamesummarywidget.cpp | 4 +- 5 files changed, 65 insertions(+), 16 deletions(-) diff --git a/src/core/game_database.cpp b/src/core/game_database.cpp index 4870d9f8a..f8bec8692 100644 --- a/src/core/game_database.cpp +++ b/src/core/game_database.cpp @@ -29,7 +29,7 @@ namespace GameDatabase { enum : u32 { GAME_DATABASE_CACHE_SIGNATURE = 0x45434C48, - GAME_DATABASE_CACHE_VERSION = 3, + GAME_DATABASE_CACHE_VERSION = 4, }; static Entry* GetMutableEntry(const std::string_view& serial); @@ -427,9 +427,9 @@ void GameDatabase::Entry::ApplySettings(Settings& settings, bool display_osd_mes settings.cpu_fastmem_mode = CPUFastmemMode::LUT; } -#define BIT_FOR(ctype) (static_cast(1) << static_cast(ctype)) +#define BIT_FOR(ctype) (static_cast(1) << static_cast(ctype)) - if (supported_controllers != 0 && supported_controllers != static_cast(-1)) + if (supported_controllers != 0 && supported_controllers != static_cast(-1)) { for (u32 i = 0; i < NUM_CONTROLLER_AND_CARD_PORTS; i++) { @@ -558,13 +558,14 @@ bool GameDatabase::LoadFromCache() constexpr u32 num_bytes = (static_cast(Trait::Count) + 7) / 8; std::array bits; u8 compatibility; + u32 num_disc_set_serials; if (!stream->ReadSizePrefixedString(&entry.serial) || !stream->ReadSizePrefixedString(&entry.title) || !stream->ReadSizePrefixedString(&entry.genre) || !stream->ReadSizePrefixedString(&entry.developer) || !stream->ReadSizePrefixedString(&entry.publisher) || !stream->ReadU64(&entry.release_date) || !stream->ReadU8(&entry.min_players) || !stream->ReadU8(&entry.max_players) || !stream->ReadU8(&entry.min_blocks) || !stream->ReadU8(&entry.max_blocks) || - !stream->ReadU32(&entry.supported_controllers) || !stream->ReadU8(&compatibility) || + !stream->ReadU16(&entry.supported_controllers) || !stream->ReadU8(&compatibility) || compatibility >= static_cast(GameDatabase::CompatibilityRating::Count) || !stream->Read2(bits.data(), num_bytes) || !ReadOptionalFromStream(stream.get(), &entry.display_active_start_offset) || @@ -576,12 +577,26 @@ bool GameDatabase::LoadFromCache() !ReadOptionalFromStream(stream.get(), &entry.gpu_fifo_size) || !ReadOptionalFromStream(stream.get(), &entry.gpu_max_run_ahead) || !ReadOptionalFromStream(stream.get(), &entry.gpu_pgxp_tolerance) || - !ReadOptionalFromStream(stream.get(), &entry.gpu_pgxp_depth_threshold)) + !ReadOptionalFromStream(stream.get(), &entry.gpu_pgxp_depth_threshold) || + !stream->ReadSizePrefixedString(&entry.disc_set_name) || !stream->ReadU32(&num_disc_set_serials)) { Log_DevPrintf("Cache entry is corrupted."); return false; } + if (num_disc_set_serials > 0) + { + entry.disc_set_serials.reserve(num_disc_set_serials); + for (u32 j = 0; j < num_disc_set_serials; j++) + { + if (!stream->ReadSizePrefixedString(&entry.disc_set_serials.emplace_back())) + { + Log_DevPrintf("Cache entry is corrupted."); + return false; + } + } + } + entry.compatibility = static_cast(compatibility); entry.traits.reset(); for (u32 j = 0; j < static_cast(Trait::Count); j++) @@ -640,7 +655,7 @@ bool GameDatabase::SaveToCache() result = result && stream->WriteU8(entry.max_players); result = result && stream->WriteU8(entry.min_blocks); result = result && stream->WriteU8(entry.max_blocks); - result = result && stream->WriteU32(entry.supported_controllers); + result = result && stream->WriteU16(entry.supported_controllers); result = result && stream->WriteU8(static_cast(entry.compatibility)); constexpr u32 num_bytes = (static_cast(Trait::Count) + 7) / 8; @@ -664,6 +679,11 @@ bool GameDatabase::SaveToCache() result = result && WriteOptionalToStream(stream.get(), entry.gpu_max_run_ahead); result = result && WriteOptionalToStream(stream.get(), entry.gpu_pgxp_tolerance); result = result && WriteOptionalToStream(stream.get(), entry.gpu_pgxp_depth_threshold); + + result = result && stream->WriteSizePrefixedString(entry.disc_set_name); + result = result && stream->WriteU32(static_cast(entry.disc_set_serials.size())); + for (const std::string& serial : entry.disc_set_serials) + result = result && stream->WriteSizePrefixedString(serial); } for (const auto& it : s_code_lookup) @@ -852,7 +872,7 @@ bool GameDatabase::ParseJsonEntry(Entry* entry, const rapidjson::Value& value) } } - entry->supported_controllers = ~0u; + entry->supported_controllers = static_cast(~0u); const auto controllers = value.FindMember("controllers"); if (controllers != value.MemberEnd()) { @@ -880,7 +900,7 @@ bool GameDatabase::ParseJsonEntry(Entry* entry, const rapidjson::Value& value) first = false; } - entry->supported_controllers |= (1u << static_cast(ctype.value())); + entry->supported_controllers |= (1u << static_cast(ctype.value())); } } else @@ -937,6 +957,32 @@ bool GameDatabase::ParseJsonEntry(Entry* entry, const rapidjson::Value& value) } } + GetStringFromObject(value, "discSetName", &entry->disc_set_name); + const auto disc_set_serials = value.FindMember("discSetSerials"); + if (disc_set_serials != value.MemberEnd()) + { + if (disc_set_serials->value.IsArray()) + { + const auto disc_set_serials_array = disc_set_serials->value.GetArray(); + entry->disc_set_serials.reserve(disc_set_serials_array.Size()); + for (const rapidjson::Value& serial : disc_set_serials_array) + { + if (serial.IsString()) + { + entry->disc_set_serials.emplace_back(serial.GetString(), serial.GetStringLength()); + } + else + { + Log_WarningPrintf("discSetSerial is not a string"); + } + } + } + else + { + Log_WarningPrintf("discSetSerials is not an array"); + } + } + return true; } diff --git a/src/core/game_database.h b/src/core/game_database.h index 5fafff5d4..3433c8d97 100644 --- a/src/core/game_database.h +++ b/src/core/game_database.h @@ -65,7 +65,7 @@ struct Entry u8 max_players; u8 min_blocks; u8 max_blocks; - u32 supported_controllers; + u16 supported_controllers; CompatibilityRating compatibility; std::bitset(Trait::Count)> traits{}; @@ -80,6 +80,9 @@ struct Entry std::optional gpu_pgxp_tolerance; std::optional gpu_pgxp_depth_threshold; + std::string disc_set_name; + std::vector disc_set_serials; + ALWAYS_INLINE bool HasTrait(Trait trait) const { return traits[static_cast(trait)]; } void ApplySettings(Settings& settings, bool display_osd_messages) const; diff --git a/src/core/game_list.cpp b/src/core/game_list.cpp index 5fcaf42bb..013c505da 100644 --- a/src/core/game_list.cpp +++ b/src/core/game_list.cpp @@ -41,7 +41,7 @@ namespace GameList { enum : u32 { GAME_LIST_CACHE_SIGNATURE = 0x45434C47, - GAME_LIST_CACHE_VERSION = 33, + GAME_LIST_CACHE_VERSION = 34, PLAYED_TIME_SERIAL_LENGTH = 32, PLAYED_TIME_LAST_TIME_LENGTH = 20, // uint64 @@ -244,7 +244,7 @@ bool GameList::GetDiscListEntry(const std::string& path, Entry* entry) entry->max_players = 0; entry->min_blocks = 0; entry->max_blocks = 0; - entry->supported_controllers = ~0u; + entry->supported_controllers = static_cast(~0u); } // region detection @@ -319,7 +319,7 @@ bool GameList::LoadEntriesFromCache(ByteStream* stream) !stream->ReadSizePrefixedString(&ge.genre) || !stream->ReadSizePrefixedString(&ge.publisher) || !stream->ReadSizePrefixedString(&ge.developer) || !stream->ReadU64(&ge.hash) || !stream->ReadU64(&ge.total_size) || !stream->ReadU64(reinterpret_cast(&ge.last_modified_time)) || - !stream->ReadU64(&ge.release_date) || !stream->ReadU32(&ge.supported_controllers) || + !stream->ReadU64(&ge.release_date) || !stream->ReadU16(&ge.supported_controllers) || !stream->ReadU8(&ge.min_players) || !stream->ReadU8(&ge.max_players) || !stream->ReadU8(&ge.min_blocks) || !stream->ReadU8(&ge.max_blocks) || !stream->ReadU8(&compatibility_rating) || region >= static_cast(DiscRegion::Count) || type >= static_cast(EntryType::Count) || @@ -359,7 +359,7 @@ bool GameList::WriteEntryToCache(const Entry* entry) result &= s_cache_write_stream->WriteU64(entry->total_size); result &= s_cache_write_stream->WriteU64(entry->last_modified_time); result &= s_cache_write_stream->WriteU64(entry->release_date); - result &= s_cache_write_stream->WriteU32(entry->supported_controllers); + result &= s_cache_write_stream->WriteU16(entry->supported_controllers); result &= s_cache_write_stream->WriteU8(entry->min_players); result &= s_cache_write_stream->WriteU8(entry->max_players); result &= s_cache_write_stream->WriteU8(entry->min_blocks); diff --git a/src/core/game_list.h b/src/core/game_list.h index e4b0a5e6c..b0384b926 100644 --- a/src/core/game_list.h +++ b/src/core/game_list.h @@ -48,7 +48,7 @@ struct Entry std::time_t total_played_time = 0; u64 release_date = 0; - u32 supported_controllers = ~static_cast(0); + u16 supported_controllers = static_cast(~0u); u8 min_players = 1; u8 max_players = 1; u8 min_blocks = 0; diff --git a/src/duckstation-qt/gamesummarywidget.cpp b/src/duckstation-qt/gamesummarywidget.cpp index a00adc329..3f874a962 100644 --- a/src/duckstation-qt/gamesummarywidget.cpp +++ b/src/duckstation-qt/gamesummarywidget.cpp @@ -105,11 +105,11 @@ void GameSummaryWidget::populateUi(const std::string& path, const std::string& s m_ui.releaseInfo->setText(tr("Unknown")); QString controllers; - if (entry->supported_controllers != 0 && entry->supported_controllers != static_cast(-1)) + if (entry->supported_controllers != 0 && entry->supported_controllers != static_cast(-1)) { for (u32 i = 0; i < static_cast(ControllerType::Count); i++) { - if ((entry->supported_controllers & (1u << i)) != 0) + if ((entry->supported_controllers & static_cast(1u << i)) != 0) { if (!controllers.isEmpty()) controllers.append(", ");