diff --git a/Data/Sys/triforcetdb-en.txt b/Data/Sys/triforcetdb-en.txt new file mode 100644 index 0000000000..a397bb0419 --- /dev/null +++ b/Data/Sys/triforcetdb-en.txt @@ -0,0 +1,10 @@ +TITLES = (type: Triforce language: EN version: 20210908) +S000 = Triforce Firmware Update For Compact Flash Box (4.01) +SBEY = Virtua Striker 2002 +SBFX = The Key Of Avalon +SBGG = F-Zero AX +SBHZ = Virtua Striker 4 (Asia) +SBJA = Virtua Striker 4 (Export) +SBJN = The Key Of Avalon 2.5: War of the Key +SBLK = Virtua Striker 4 Ver.2006 (Japan) +SBLL = Virtua Striker 4 Ver.2006 (Export) diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp index 9101df907a..a480c7622d 100644 --- a/Source/Core/Core/ConfigManager.cpp +++ b/Source/Core/Core/ConfigManager.cpp @@ -126,6 +126,12 @@ const std::string SConfig::GetTitleDescription() const return m_title_description; } +std::string SConfig::GetTriforceID() const +{ + std::lock_guard lock(m_metadata_lock); + return m_triforce_id; +} + u64 SConfig::GetTitleID() const { std::lock_guard lock(m_metadata_lock); @@ -141,7 +147,7 @@ u16 SConfig::GetRevision() const void SConfig::ResetRunningGameMetadata() { std::lock_guard lock(m_metadata_lock); - SetRunningGameMetadata("00000000", "", 0, 0, DiscIO::Region::Unknown); + SetRunningGameMetadata("00000000", "", "", 0, 0, DiscIO::Region::Unknown); } void SConfig::SetRunningGameMetadata(const DiscIO::Volume& volume, @@ -150,14 +156,14 @@ void SConfig::SetRunningGameMetadata(const DiscIO::Volume& volume, std::lock_guard lock(m_metadata_lock); if (partition == volume.GetGamePartition()) { - SetRunningGameMetadata(volume.GetGameID(), volume.GetGameTDBID(), + SetRunningGameMetadata(volume.GetGameID(), volume.GetGameTDBID(), volume.GetTriforceID(), volume.GetTitleID().value_or(0), volume.GetRevision().value_or(0), volume.GetRegion()); } else { SetRunningGameMetadata(volume.GetGameID(partition), volume.GetGameTDBID(partition), - volume.GetTitleID(partition).value_or(0), + volume.GetTriforceID(), volume.GetTitleID(partition).value_or(0), volume.GetRevision(partition).value_or(0), volume.GetRegion()); } } @@ -175,25 +181,28 @@ void SConfig::SetRunningGameMetadata(const IOS::ES::TMDReader& tmd, DiscIO::Plat !Core::System::GetInstance().GetDVDInterface().UpdateRunningGameMetadata(tmd_title_id)) { // If not launching a disc game, just read everything from the TMD. - SetRunningGameMetadata(tmd.GetGameID(), tmd.GetGameTDBID(), tmd_title_id, tmd.GetTitleVersion(), - tmd.GetRegion()); + SetRunningGameMetadata(tmd.GetGameID(), tmd.GetGameTDBID(), "", tmd_title_id, + tmd.GetTitleVersion(), tmd.GetRegion()); } } void SConfig::SetRunningGameMetadata(const std::string& game_id) { std::lock_guard lock(m_metadata_lock); - SetRunningGameMetadata(game_id, "", 0, 0, DiscIO::Region::Unknown); + SetRunningGameMetadata(game_id, "", "", 0, 0, DiscIO::Region::Unknown); } void SConfig::SetRunningGameMetadata(const std::string& game_id, const std::string& gametdb_id, - u64 title_id, u16 revision, DiscIO::Region region) + std::string triforce_id, u64 title_id, u16 revision, + DiscIO::Region region) { std::lock_guard lock(m_metadata_lock); const bool was_changed = m_game_id != game_id || m_gametdb_id != gametdb_id || - m_title_id != title_id || m_revision != revision; + m_triforce_id != triforce_id || m_title_id != title_id || + m_revision != revision; m_game_id = game_id; m_gametdb_id = gametdb_id; + m_triforce_id = triforce_id; m_title_id = title_id; m_revision = revision; @@ -226,7 +235,7 @@ void SConfig::SetRunningGameMetadata(const std::string& game_id, const std::stri const Core::TitleDatabase title_database; auto& system = Core::System::GetInstance(); const DiscIO::Language language = GetLanguageAdjustedForRegion(system.IsWii(), region); - m_title_name = title_database.GetTitleName(m_gametdb_id, language); + m_title_name = title_database.GetTitleName(m_gametdb_id, m_triforce_id, language); m_title_description = title_database.Describe(m_gametdb_id, language); NOTICE_LOG_FMT(CORE, "Active title: {}", m_title_description); Host_TitleChanged(); diff --git a/Source/Core/Core/ConfigManager.h b/Source/Core/Core/ConfigManager.h index 84be081b64..f441cd888b 100644 --- a/Source/Core/Core/ConfigManager.h +++ b/Source/Core/Core/ConfigManager.h @@ -67,6 +67,7 @@ struct SConfig const std::string GetGameTDBID() const; const std::string GetTitleName() const; const std::string GetTitleDescription() const; + std::string GetTriforceID() const; u64 GetTitleID() const; u16 GetRevision() const; void ResetRunningGameMetadata(); @@ -121,13 +122,15 @@ private: static void ReloadTextures(Core::System& system); void SetRunningGameMetadata(const std::string& game_id, const std::string& gametdb_id, - u64 title_id, u16 revision, DiscIO::Region region); + std::string triforce_id, u64 title_id, u16 revision, + DiscIO::Region region); static SConfig* m_Instance; mutable std::recursive_mutex m_metadata_lock; std::string m_game_id; std::string m_gametdb_id; + std::string m_triforce_id; std::string m_title_name; std::string m_title_description; u64 m_title_id; diff --git a/Source/Core/Core/TitleDatabase.cpp b/Source/Core/Core/TitleDatabase.cpp index 391a0dc044..4609cfddb1 100644 --- a/Source/Core/Core/TitleDatabase.cpp +++ b/Source/Core/Core/TitleDatabase.cpp @@ -56,6 +56,9 @@ void TitleDatabase::AddLazyMap(DiscIO::Language language, const std::string& lan m_title_maps[language] = [language_code]() -> Map { return LoadMap(File::GetSysDirectory() + "wiitdb-" + language_code + ".txt"); }; + m_triforce_title_maps[language] = [language_code]() -> Map { + return LoadMap(File::GetSysDirectory() + "triforcetdb-" + language_code + ".txt"); + }; } TitleDatabase::TitleDatabase() @@ -91,8 +94,32 @@ TitleDatabase::TitleDatabase() TitleDatabase::~TitleDatabase() = default; const std::string& TitleDatabase::GetTitleName(const std::string& gametdb_id, + const std::string& triforce_id, DiscIO::Language language) const { + if (triforce_id != "") + { + const Map& map = *m_triforce_title_maps.at(DiscIO::Language::English); + auto it = map.find(triforce_id); + if (it != map.end()) + return it->second; + + // This code has been commented out as there is currently only a english title map, and all + // Triforce games are detected as Japanese. + + // if (language != DiscIO::Language::English) + //{ + // const Map& english_triforce_map = *m_triforce_title_maps.at(DiscIO::Language::English); + // it = english_triforce_map.find(triforce_id); + // if (it != english_triforce_map.end()) + // return it->second; + //} + + // it = m_base_map.find(triforce_id); + // if (it != m_base_map.end()) + // return it->second; + } + auto it = m_user_title_map.find(gametdb_id); if (it != m_user_title_map.end()) return it->second; @@ -125,12 +152,12 @@ const std::string& TitleDatabase::GetChannelName(u64 title_id, DiscIO::Language const std::string id{ {static_cast((title_id >> 24) & 0xff), static_cast((title_id >> 16) & 0xff), static_cast((title_id >> 8) & 0xff), static_cast(title_id & 0xff)}}; - return GetTitleName(id, language); + return GetTitleName(id, "", language); } std::string TitleDatabase::Describe(const std::string& gametdb_id, DiscIO::Language language) const { - const std::string& title_name = GetTitleName(gametdb_id, language); + const std::string& title_name = GetTitleName(gametdb_id, "", language); if (title_name.empty()) return gametdb_id; return fmt::format("{} ({})", title_name, gametdb_id); diff --git a/Source/Core/Core/TitleDatabase.h b/Source/Core/Core/TitleDatabase.h index 2d26477bea..dff9a56dfe 100644 --- a/Source/Core/Core/TitleDatabase.h +++ b/Source/Core/Core/TitleDatabase.h @@ -25,7 +25,8 @@ public: // Get a user friendly title name for a GameTDB ID. // This falls back to returning an empty string if none could be found. - const std::string& GetTitleName(const std::string& gametdb_id, DiscIO::Language language) const; + const std::string& GetTitleName(const std::string& gametdb_id, const std::string& triforce_id, + DiscIO::Language language) const; // Same as above, but takes a title ID instead of a GameTDB ID, and only works for channels. const std::string& GetChannelName(u64 title_id, DiscIO::Language language) const; @@ -38,6 +39,8 @@ private: std::unordered_map>> m_title_maps; + std::unordered_map>> + m_triforce_title_maps; std::unordered_map m_base_map; std::unordered_map m_user_title_map; }; diff --git a/Source/Core/DiscIO/Volume.h b/Source/Core/DiscIO/Volume.h index 838ae28984..a7273b0f0e 100644 --- a/Source/Core/DiscIO/Volume.h +++ b/Source/Core/DiscIO/Volume.h @@ -96,6 +96,7 @@ public: } virtual std::string GetGameID(const Partition& partition = PARTITION_NONE) const = 0; virtual std::string GetGameTDBID(const Partition& partition = PARTITION_NONE) const = 0; + virtual std::string GetTriforceID() const { return ""; } virtual std::string GetMakerID(const Partition& partition = PARTITION_NONE) const = 0; virtual std::optional GetRevision(const Partition& partition = PARTITION_NONE) const = 0; virtual std::string GetInternalName(const Partition& partition = PARTITION_NONE) const = 0; diff --git a/Source/Core/DiscIO/VolumeGC.cpp b/Source/Core/DiscIO/VolumeGC.cpp index ebd005f158..8cc255570a 100644 --- a/Source/Core/DiscIO/VolumeGC.cpp +++ b/Source/Core/DiscIO/VolumeGC.cpp @@ -48,11 +48,14 @@ VolumeGC::VolumeGC(std::unique_ptr reader) std::unique_ptr file_info = tmp_fs->FindFileInfo("boot.id"); if (!file_info) return; - u32 triforce_magic; // "BTID" + BootID triforce_header; const u64 file_size = ReadFile(*this, PARTITION_NONE, file_info.get(), - reinterpret_cast(&triforce_magic), sizeof(triforce_magic)); - if (file_size >= 4 && triforce_magic == BTID_MAGIC) + reinterpret_cast(&triforce_header), sizeof(BootID)); + if (file_size >= 4 && triforce_header.magic == BTID_MAGIC) + { m_is_triforce = true; + m_triforce_id = triforce_header.id; + } } } @@ -90,6 +93,14 @@ std::string VolumeGC::GetGameTDBID(const Partition& partition) const return GetGameID(partition); } +std::string VolumeGC::GetTriforceID() const +{ + if (m_is_triforce) + return (std::string(m_triforce_id.data(), m_triforce_id.size())); + else + return ""; +} + Region VolumeGC::GetRegion() const { return RegionCodeToRegion(m_reader->ReadSwapped(0x458)); diff --git a/Source/Core/DiscIO/VolumeGC.h b/Source/Core/DiscIO/VolumeGC.h index 1c8297defb..5cf4ea0eed 100644 --- a/Source/Core/DiscIO/VolumeGC.h +++ b/Source/Core/DiscIO/VolumeGC.h @@ -34,6 +34,7 @@ public: const Partition& partition = PARTITION_NONE) const override; const FileSystem* GetFileSystem(const Partition& partition = PARTITION_NONE) const override; std::string GetGameTDBID(const Partition& partition = PARTITION_NONE) const override; + std::string GetTriforceID() const override; std::map GetShortNames() const override; std::map GetLongNames() const override; std::map GetShortMakers() const override; @@ -76,6 +77,13 @@ private: // (only one for BNR1 type) }; + struct BootID + { + u32 magic; // "BTID" + u32 padding[11]; + std::array id; + }; + struct ConvertedGCBanner { ConvertedGCBanner(); @@ -105,6 +113,7 @@ private: std::unique_ptr m_reader; bool m_is_triforce; + std::array m_triforce_id; }; } // namespace DiscIO diff --git a/Source/Core/DolphinQt/Config/InfoWidget.cpp b/Source/Core/DolphinQt/Config/InfoWidget.cpp index 1cddafcd0c..6a41b7de12 100644 --- a/Source/Core/DolphinQt/Config/InfoWidget.cpp +++ b/Source/Core/DolphinQt/Config/InfoWidget.cpp @@ -106,11 +106,13 @@ QGroupBox* InfoWidget::CreateGameDetails() .arg(m_game.GetRevision())); QString game_id_string = QString::fromStdString(m_game.GetGameID()); + QString triforce_id_string = QString::fromStdString(m_game.GetTriforceID()); if (const u64 title_id = m_game.GetTitleID()) game_id_string += QStringLiteral(" (%1)").arg(title_id, 16, 16, QLatin1Char('0')); QLineEdit* game_id = CreateValueDisplay(game_id_string); + QLineEdit* triforce_id = CreateValueDisplay(triforce_id_string); QLineEdit* country = CreateValueDisplay(DiscIO::GetName(m_game.GetCountry(), true)); @@ -121,6 +123,8 @@ QGroupBox* InfoWidget::CreateGameDetails() m_game.GetMakerID() + ")"); layout->addRow(tr("Name:"), internal_name); + if (m_game.GetPlatform() == DiscIO::Platform::Triforce) + layout->addRow(tr("Triforce ID:"), triforce_id); layout->addRow(tr("Game ID:"), game_id); layout->addRow(tr("Country:"), country); layout->addRow(tr("Maker:"), maker); diff --git a/Source/Core/UICommon/GameFile.cpp b/Source/Core/UICommon/GameFile.cpp index b35349b8b0..66fb5a3a57 100644 --- a/Source/Core/UICommon/GameFile.cpp +++ b/Source/Core/UICommon/GameFile.cpp @@ -131,6 +131,7 @@ GameFile::GameFile(std::string path) : m_file_path(std::move(path)) m_internal_name = volume->GetInternalName(); m_game_id = volume->GetGameID(); m_gametdb_id = volume->GetGameTDBID(); + m_triforce_id = volume->GetTriforceID(); m_title_id = volume->GetTitleID().value_or(0); m_maker_id = volume->GetMakerID(); m_revision = volume->GetRevision().value_or(0); @@ -311,6 +312,7 @@ void GameFile::DoState(PointerWrap& p) p.Do(m_internal_name); p.Do(m_game_id); p.Do(m_gametdb_id); + p.Do(m_triforce_id); p.Do(m_title_id); p.Do(m_maker_id); @@ -499,7 +501,8 @@ const std::string& GameFile::GetName(const Core::TitleDatabase& title_database) if (IsModDescriptor()) return GetName(Variant::LongAndPossiblyCustom); - const std::string& database_name = title_database.GetTitleName(m_gametdb_id, GetConfigLanguage()); + const std::string& database_name = + title_database.GetTitleName(m_gametdb_id, m_triforce_id, GetConfigLanguage()); return database_name.empty() ? GetName(Variant::LongAndPossiblyCustom) : database_name; } diff --git a/Source/Core/UICommon/GameFile.h b/Source/Core/UICommon/GameFile.h index e43950143b..f015fa9725 100644 --- a/Source/Core/UICommon/GameFile.h +++ b/Source/Core/UICommon/GameFile.h @@ -76,6 +76,7 @@ public: const std::string& GetInternalName() const { return m_internal_name; } const std::string& GetGameID() const { return m_game_id; } const std::string& GetGameTDBID() const { return m_gametdb_id; } + std::string GetTriforceID() const { return m_triforce_id; } u64 GetTitleID() const { return m_title_id; } const std::string& GetMakerID() const { return m_maker_id; } u16 GetRevision() const { return m_revision; } @@ -159,6 +160,7 @@ private: std::string m_internal_name; std::string m_game_id; std::string m_gametdb_id; + std::string m_triforce_id; u64 m_title_id{}; std::string m_maker_id;