Implement Triforce ID parsing
This commit is contained in:
parent
5c94ed2da8
commit
252ee32444
|
@ -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)
|
|
@ -126,6 +126,12 @@ const std::string SConfig::GetTitleDescription() const
|
|||
return m_title_description;
|
||||
}
|
||||
|
||||
std::string SConfig::GetTriID() const
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(m_metadata_lock);
|
||||
return m_tri_id;
|
||||
}
|
||||
|
||||
u64 SConfig::GetTitleID() const
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(m_metadata_lock);
|
||||
|
@ -141,7 +147,7 @@ u16 SConfig::GetRevision() const
|
|||
void SConfig::ResetRunningGameMetadata()
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> 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<std::recursive_mutex> lock(m_metadata_lock);
|
||||
if (partition == volume.GetGamePartition())
|
||||
{
|
||||
SetRunningGameMetadata(volume.GetGameID(), volume.GetGameTDBID(),
|
||||
SetRunningGameMetadata(volume.GetGameID(), volume.GetGameTDBID(), volume.GetTriID(),
|
||||
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.GetTriID(), volume.GetTitleID(partition).value_or(0),
|
||||
volume.GetRevision(partition).value_or(0), volume.GetRegion());
|
||||
}
|
||||
}
|
||||
|
@ -175,25 +181,27 @@ 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<std::recursive_mutex> 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 tri_id, u64 title_id, u16 revision,
|
||||
DiscIO::Region region)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> 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_tri_id != tri_id || m_title_id != title_id || m_revision != revision;
|
||||
m_game_id = game_id;
|
||||
m_gametdb_id = gametdb_id;
|
||||
m_tri_id = tri_id;
|
||||
m_title_id = title_id;
|
||||
m_revision = revision;
|
||||
|
||||
|
@ -226,7 +234,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_tri_id, language);
|
||||
m_title_description = title_database.Describe(m_gametdb_id, language);
|
||||
NOTICE_LOG_FMT(CORE, "Active title: {}", m_title_description);
|
||||
Host_TitleChanged();
|
||||
|
|
|
@ -67,8 +67,10 @@ struct SConfig
|
|||
const std::string GetGameTDBID() const;
|
||||
const std::string GetTitleName() const;
|
||||
const std::string GetTitleDescription() const;
|
||||
std::string GetTriID() const;
|
||||
u64 GetTitleID() const;
|
||||
u16 GetRevision() const;
|
||||
|
||||
void ResetRunningGameMetadata();
|
||||
void SetRunningGameMetadata(const DiscIO::Volume& volume, const DiscIO::Partition& partition);
|
||||
void SetRunningGameMetadata(const IOS::ES::TMDReader& tmd, DiscIO::Platform platform);
|
||||
|
@ -121,13 +123,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 tri_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_tri_id;
|
||||
std::string m_title_name;
|
||||
std::string m_title_description;
|
||||
u64 m_title_id;
|
||||
|
|
|
@ -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_trititle_maps[language] = [language_code]() -> Map {
|
||||
return LoadMap(File::GetSysDirectory() + "tritdb-" + 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& tri_id,
|
||||
DiscIO::Language language) const
|
||||
{
|
||||
if (tri_id != "")
|
||||
{
|
||||
const Map& map = *m_trititle_maps.at(DiscIO::Language::English);
|
||||
auto it = map.find(tri_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_trimap = *m_trititle_maps.at(DiscIO::Language::English);
|
||||
// it = english_trimap.find(tri_id);
|
||||
// if (it != english_trimap.end())
|
||||
// return it->second;
|
||||
//}
|
||||
|
||||
// it = m_base_map.find(tri_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<char>((title_id >> 24) & 0xff), static_cast<char>((title_id >> 16) & 0xff),
|
||||
static_cast<char>((title_id >> 8) & 0xff), static_cast<char>(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);
|
||||
|
|
|
@ -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& tri_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<DiscIO::Language, Common::Lazy<std::unordered_map<std::string, std::string>>>
|
||||
m_title_maps;
|
||||
std::unordered_map<DiscIO::Language, Common::Lazy<std::unordered_map<std::string, std::string>>>
|
||||
m_trititle_maps;
|
||||
std::unordered_map<std::string, std::string> m_base_map;
|
||||
std::unordered_map<std::string, std::string> m_user_title_map;
|
||||
};
|
||||
|
|
|
@ -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 GetTriID() const { return ""; }
|
||||
virtual std::string GetMakerID(const Partition& partition = PARTITION_NONE) const = 0;
|
||||
virtual std::optional<u16> GetRevision(const Partition& partition = PARTITION_NONE) const = 0;
|
||||
virtual std::string GetInternalName(const Partition& partition = PARTITION_NONE) const = 0;
|
||||
|
|
|
@ -48,11 +48,14 @@ VolumeGC::VolumeGC(std::unique_ptr<BlobReader> reader)
|
|||
std::unique_ptr<FileInfo> 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<u8*>(&triforce_magic), sizeof(triforce_magic));
|
||||
if (file_size >= 4 && triforce_magic == BTID_MAGIC)
|
||||
reinterpret_cast<u8*>(&triforce_header), sizeof(BootID));
|
||||
if (file_size >= 4 && triforce_header.magic == BTID_MAGIC)
|
||||
{
|
||||
m_is_triforce = true;
|
||||
m_tri_id = triforce_header.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,6 +95,14 @@ std::string VolumeGC::GetGameTDBID(const Partition& partition) const
|
|||
return GetGameID(partition);
|
||||
}
|
||||
|
||||
std::string VolumeGC::GetTriID() const
|
||||
{
|
||||
if (m_is_triforce)
|
||||
return (std::string(m_tri_id.data(), m_tri_id.size()));
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
Region VolumeGC::GetRegion() const
|
||||
{
|
||||
return RegionCodeToRegion(m_reader->ReadSwapped<u32>(0x458));
|
||||
|
|
|
@ -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 GetTriID() const override;
|
||||
std::map<Language, std::string> GetShortNames() const override;
|
||||
std::map<Language, std::string> GetLongNames() const override;
|
||||
std::map<Language, std::string> GetShortMakers() const override;
|
||||
|
@ -76,6 +77,13 @@ private:
|
|||
// (only one for BNR1 type)
|
||||
};
|
||||
|
||||
struct BootID
|
||||
{
|
||||
u32 magic; // "BTID"
|
||||
u32 padding[11];
|
||||
std::array<char, 4> id;
|
||||
};
|
||||
|
||||
struct ConvertedGCBanner
|
||||
{
|
||||
ConvertedGCBanner();
|
||||
|
@ -105,6 +113,7 @@ private:
|
|||
std::unique_ptr<BlobReader> m_reader;
|
||||
|
||||
bool m_is_triforce;
|
||||
std::array<char, 4> m_tri_id;
|
||||
};
|
||||
|
||||
} // namespace DiscIO
|
||||
|
|
|
@ -106,11 +106,13 @@ QGroupBox* InfoWidget::CreateGameDetails()
|
|||
.arg(m_game.GetRevision()));
|
||||
|
||||
QString game_id_string = QString::fromStdString(m_game.GetGameID());
|
||||
QString tri_id_string = QString::fromStdString(m_game.GetTriID());
|
||||
|
||||
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* tri_id = CreateValueDisplay(tri_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("Boot (Triforce) ID:"), tri_id);
|
||||
layout->addRow(tr("Game ID:"), game_id);
|
||||
layout->addRow(tr("Country:"), country);
|
||||
layout->addRow(tr("Maker:"), maker);
|
||||
|
|
|
@ -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_tri_id = volume->GetTriID();
|
||||
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_tri_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_tri_id, GetConfigLanguage());
|
||||
return database_name.empty() ? GetName(Variant::LongAndPossiblyCustom) : database_name;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 GetTriID() const { return m_tri_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_tri_id;
|
||||
u64 m_title_id{};
|
||||
std::string m_maker_id;
|
||||
|
||||
|
|
Loading…
Reference in New Issue