diff --git a/Data/Sys/Resources/Platform_Triforce.png b/Data/Sys/Resources/Platform_Triforce.png new file mode 100644 index 0000000000..e6a3b26b76 Binary files /dev/null and b/Data/Sys/Resources/Platform_Triforce.png differ diff --git a/Data/Sys/Resources/Platform_Triforce@2x.png b/Data/Sys/Resources/Platform_Triforce@2x.png new file mode 100644 index 0000000000..3efae35bd5 Binary files /dev/null and b/Data/Sys/Resources/Platform_Triforce@2x.png differ diff --git a/Data/Sys/Resources/Platform_Triforce@4x.png b/Data/Sys/Resources/Platform_Triforce@4x.png new file mode 100644 index 0000000000..85bf7c272d Binary files /dev/null and b/Data/Sys/Resources/Platform_Triforce@4x.png differ diff --git a/Source/Core/Core/Config/MainSettings.cpp b/Source/Core/Core/Config/MainSettings.cpp index 37f2a6054e..7af0fd2766 100644 --- a/Source/Core/Core/Config/MainSettings.cpp +++ b/Source/Core/Core/Config/MainSettings.cpp @@ -437,6 +437,7 @@ const Info MAIN_GAMELIST_LIST_WAD{{System::Main, "GameList", "ListWad"}, t const Info MAIN_GAMELIST_LIST_ELF_DOL{{System::Main, "GameList", "ListElfDol"}, true}; const Info MAIN_GAMELIST_LIST_WII{{System::Main, "GameList", "ListWii"}, true}; const Info MAIN_GAMELIST_LIST_GC{{System::Main, "GameList", "ListGC"}, true}; +const Info MAIN_GAMELIST_LIST_TRI{{System::Main, "GameList", "ListTriforce"}, true}; const Info MAIN_GAMELIST_LIST_JPN{{System::Main, "GameList", "ListJap"}, true}; const Info MAIN_GAMELIST_LIST_PAL{{System::Main, "GameList", "ListPal"}, true}; const Info MAIN_GAMELIST_LIST_USA{{System::Main, "GameList", "ListUsa"}, true}; diff --git a/Source/Core/Core/Config/MainSettings.h b/Source/Core/Core/Config/MainSettings.h index 51aa7ec8aa..344263ba10 100644 --- a/Source/Core/Core/Config/MainSettings.h +++ b/Source/Core/Core/Config/MainSettings.h @@ -269,6 +269,7 @@ extern const Info MAIN_GAMELIST_LIST_WAD; extern const Info MAIN_GAMELIST_LIST_ELF_DOL; extern const Info MAIN_GAMELIST_LIST_WII; extern const Info MAIN_GAMELIST_LIST_GC; +extern const Info MAIN_GAMELIST_LIST_TRI; extern const Info MAIN_GAMELIST_LIST_JPN; extern const Info MAIN_GAMELIST_LIST_PAL; extern const Info MAIN_GAMELIST_LIST_USA; diff --git a/Source/Core/DiscIO/Enums.cpp b/Source/Core/DiscIO/Enums.cpp index 2d6f22d164..28487d346e 100644 --- a/Source/Core/DiscIO/Enums.cpp +++ b/Source/Core/DiscIO/Enums.cpp @@ -139,7 +139,8 @@ std::string GetName(Region region, bool translate) bool IsDisc(Platform volume_type) { - return volume_type == Platform::GameCubeDisc || volume_type == Platform::WiiDisc; + return volume_type == Platform::GameCubeDisc || volume_type == Platform::Triforce || + volume_type == Platform::WiiDisc; } bool IsWii(Platform volume_type) diff --git a/Source/Core/DiscIO/Enums.h b/Source/Core/DiscIO/Enums.h index 4881a8d980..9b5e274de9 100644 --- a/Source/Core/DiscIO/Enums.h +++ b/Source/Core/DiscIO/Enums.h @@ -15,6 +15,7 @@ namespace DiscIO enum class Platform { GameCubeDisc = 0, + Triforce, WiiDisc, WiiWAD, ELFOrDOL, diff --git a/Source/Core/DiscIO/VolumeGC.cpp b/Source/Core/DiscIO/VolumeGC.cpp index 8a95e0bb31..ebd005f158 100644 --- a/Source/Core/DiscIO/VolumeGC.cpp +++ b/Source/Core/DiscIO/VolumeGC.cpp @@ -29,7 +29,8 @@ namespace DiscIO { -VolumeGC::VolumeGC(std::unique_ptr reader) : m_reader(std::move(reader)) +VolumeGC::VolumeGC(std::unique_ptr reader) + : m_reader(std::move(reader)), m_is_triforce(false) { ASSERT(m_reader); @@ -39,6 +40,20 @@ VolumeGC::VolumeGC(std::unique_ptr reader) : m_reader(std::move(read }; m_converted_banner = [this] { return LoadBannerFile(); }; + + constexpr u32 BTID_MAGIC = 0x44495442; + auto tmp_fs = GetFileSystem(PARTITION_NONE); + if (tmp_fs) + { + std::unique_ptr file_info = tmp_fs->FindFileInfo("boot.id"); + if (!file_info) + return; + u32 triforce_magic; // "BTID" + 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) + m_is_triforce = true; + } } VolumeGC::~VolumeGC() = default; @@ -139,7 +154,10 @@ const BlobReader& VolumeGC::GetBlobReader() const Platform VolumeGC::GetVolumeType() const { - return Platform::GameCubeDisc; + if (m_is_triforce) + return Platform::Triforce; + else + return Platform::GameCubeDisc; } bool VolumeGC::IsDatelDisc() const diff --git a/Source/Core/DiscIO/VolumeGC.h b/Source/Core/DiscIO/VolumeGC.h index d877bc7719..1c8297defb 100644 --- a/Source/Core/DiscIO/VolumeGC.h +++ b/Source/Core/DiscIO/VolumeGC.h @@ -103,6 +103,8 @@ private: Common::Lazy> m_file_system; std::unique_ptr m_reader; + + bool m_is_triforce; }; } // namespace DiscIO diff --git a/Source/Core/DiscIO/VolumeVerifier.cpp b/Source/Core/DiscIO/VolumeVerifier.cpp index 414e4ae3a1..bbe02e7d22 100644 --- a/Source/Core/DiscIO/VolumeVerifier.cpp +++ b/Source/Core/DiscIO/VolumeVerifier.cpp @@ -402,6 +402,7 @@ void VolumeVerifier::Start() m_is_tgc = m_volume.GetBlobType() == BlobType::TGC; m_is_datel = m_volume.IsDatelDisc(); + m_is_triforce = m_volume.GetVolumeType() == Platform::Triforce; m_is_not_retail = (m_volume.GetVolumeType() == Platform::WiiDisc && !m_volume.HasWiiHashes()) || IsDebugSigned(); @@ -1373,6 +1374,13 @@ void VolumeVerifier::Finish() return; } + if (m_is_triforce) + { + m_result.summary_text = + Common::GetStringT("Dolphin is currently unable to verify Triforce games."); + return; + } + if (m_result.redump.status == RedumpVerifier::Status::BadDump && highest_severity <= Severity::Low) { diff --git a/Source/Core/DiscIO/VolumeVerifier.h b/Source/Core/DiscIO/VolumeVerifier.h index 934e60b7b1..7a5c342e1b 100644 --- a/Source/Core/DiscIO/VolumeVerifier.h +++ b/Source/Core/DiscIO/VolumeVerifier.h @@ -165,6 +165,7 @@ private: Result m_result; bool m_is_tgc = false; bool m_is_datel = false; + bool m_is_triforce = false; bool m_is_not_retail = false; bool m_redump_verification; diff --git a/Source/Core/DolphinQt/Config/InfoWidget.cpp b/Source/Core/DolphinQt/Config/InfoWidget.cpp index a13b31ea34..1cddafcd0c 100644 --- a/Source/Core/DolphinQt/Config/InfoWidget.cpp +++ b/Source/Core/DolphinQt/Config/InfoWidget.cpp @@ -93,6 +93,7 @@ QGroupBox* InfoWidget::CreateGameDetails() const QString game_name = QString::fromStdString(m_game.GetInternalName()); bool is_disc_based = m_game.GetPlatform() == DiscIO::Platform::GameCubeDisc || + m_game.GetPlatform() == DiscIO::Platform::Triforce || m_game.GetPlatform() == DiscIO::Platform::WiiDisc; QLineEdit* internal_name = diff --git a/Source/Core/DolphinQt/GameList/GameListModel.cpp b/Source/Core/DolphinQt/GameList/GameListModel.cpp index c8c1d8b165..42a911ce49 100644 --- a/Source/Core/DolphinQt/GameList/GameListModel.cpp +++ b/Source/Core/DolphinQt/GameList/GameListModel.cpp @@ -303,6 +303,8 @@ bool GameListModel::ShouldDisplayGameListItem(int index) const { case DiscIO::Platform::GameCubeDisc: return Config::Get(Config::MAIN_GAMELIST_LIST_GC); + case DiscIO::Platform::Triforce: + return Config::Get(Config::MAIN_GAMELIST_LIST_TRI); case DiscIO::Platform::WiiDisc: return Config::Get(Config::MAIN_GAMELIST_LIST_WII); case DiscIO::Platform::WiiWAD: diff --git a/Source/Core/DolphinQt/MenuBar.cpp b/Source/Core/DolphinQt/MenuBar.cpp index 24c6cc2d04..a4e2b17c0d 100644 --- a/Source/Core/DolphinQt/MenuBar.cpp +++ b/Source/Core/DolphinQt/MenuBar.cpp @@ -726,6 +726,7 @@ void MenuBar::AddShowPlatformsMenu(QMenu* view_menu) static const QMap*> platform_map{ {tr("Show Wii"), &Config::MAIN_GAMELIST_LIST_WII}, {tr("Show GameCube"), &Config::MAIN_GAMELIST_LIST_GC}, + {tr("Show Triforce"), &Config::MAIN_GAMELIST_LIST_TRI}, {tr("Show WAD"), &Config::MAIN_GAMELIST_LIST_WAD}, {tr("Show ELF/DOL"), &Config::MAIN_GAMELIST_LIST_ELF_DOL}}; diff --git a/Source/Core/DolphinQt/Resources.cpp b/Source/Core/DolphinQt/Resources.cpp index 84fbcc8df8..015074142d 100644 --- a/Source/Core/DolphinQt/Resources.cpp +++ b/Source/Core/DolphinQt/Resources.cpp @@ -80,7 +80,7 @@ void Resources::Init() m_svg_supported = QImageReader::supportedImageFormats().contains("svg"); for (std::string_view platform : - {"Platform_Gamecube", "Platform_Wii", "Platform_Wad", "Platform_File"}) + {"Platform_Gamecube", "Platform_Triforce", "Platform_Wii", "Platform_Wad", "Platform_File"}) { m_platforms.append(GetResourceIcon(platform)); }