From 494e2c05c217c6ba80ceecba7c3d7ce339ea55a9 Mon Sep 17 00:00:00 2001 From: Zopolis4 Date: Wed, 21 Jul 2021 02:18:44 +1000 Subject: [PATCH 1/7] Adding support for detecting .bin images --- .../dolphinemu/utils/FileBrowserHelper.java | 4 ++-- Source/Core/Core/Boot/Boot.cpp | 3 ++- Source/Core/DolphinQt/GameList/GameTracker.cpp | 14 +++++++------- Source/Core/DolphinQt/Info.plist.in | 1 + Source/Core/DolphinQt/MainWindow.cpp | 2 +- Source/Core/DolphinQt/Settings/PathPane.cpp | 2 +- Source/Core/UICommon/GameFileCache.cpp | 6 +++--- 7 files changed, 17 insertions(+), 15 deletions(-) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/FileBrowserHelper.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/FileBrowserHelper.java index c7401c2bc5..f13578d7ae 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/FileBrowserHelper.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/FileBrowserHelper.java @@ -30,8 +30,8 @@ import java.util.Set; public final class FileBrowserHelper { public static final HashSet GAME_EXTENSIONS = new HashSet<>(Arrays.asList( - "gcm", "tgc", "iso", "ciso", "gcz", "wbfs", "wia", "rvz", "nfs", "wad", "dol", "elf", - "json")); + "gcm", "tgc", "bin", "iso", "ciso", "gcz", "wbfs", "wia", "rvz", "nfs", "wad", "dol", + "elf", "json")); public static final HashSet GAME_LIKE_EXTENSIONS = new HashSet<>(GAME_EXTENSIONS); diff --git a/Source/Core/Core/Boot/Boot.cpp b/Source/Core/Core/Boot/Boot.cpp index 1340d19c84..4e08ccfd12 100644 --- a/Source/Core/Core/Boot/Boot.cpp +++ b/Source/Core/Core/Boot/Boot.cpp @@ -236,7 +236,8 @@ std::unique_ptr BootParameters::GenerateFromFile(std::vector disc_image_extensions = { - {".gcm", ".iso", ".tgc", ".wbfs", ".ciso", ".gcz", ".wia", ".rvz", ".nfs", ".dol", ".elf"}}; + {".gcm", ".bin", ".iso", ".tgc", ".wbfs", ".ciso", ".gcz", ".wia", ".rvz", ".nfs", ".dol", + ".elf"}}; if (disc_image_extensions.contains(extension)) { std::unique_ptr disc = DiscIO::CreateDisc(path); diff --git a/Source/Core/DolphinQt/GameList/GameTracker.cpp b/Source/Core/DolphinQt/GameList/GameTracker.cpp index 9428729997..6031d37a32 100644 --- a/Source/Core/DolphinQt/GameList/GameTracker.cpp +++ b/Source/Core/DolphinQt/GameList/GameTracker.cpp @@ -22,13 +22,13 @@ // NOTE: Qt likes to be case-sensitive here even though it shouldn't be thus this ugly regex hack static const QStringList game_filters{ - QStringLiteral("*.[gG][cC][mM]"), QStringLiteral("*.[iI][sS][oO]"), - QStringLiteral("*.[tT][gG][cC]"), QStringLiteral("*.[cC][iI][sS][oO]"), - QStringLiteral("*.[gG][cC][zZ]"), QStringLiteral("*.[wW][bB][fF][sS]"), - QStringLiteral("*.[wW][iI][aA]"), QStringLiteral("*.[rR][vV][zZ]"), - QStringLiteral("hif_000000.nfs"), QStringLiteral("*.[wW][aA][dD]"), - QStringLiteral("*.[eE][lL][fF]"), QStringLiteral("*.[dD][oO][lL]"), - QStringLiteral("*.[jJ][sS][oO][nN]")}; + QStringLiteral("*.[gG][cC][mM]"), QStringLiteral("*.[bB][iI][nN]"), + QStringLiteral("*.[iI][sS][oO]"), QStringLiteral("*.[tT][gG][cC]"), + QStringLiteral("*.[cC][iI][sS][oO]"), QStringLiteral("*.[gG][cC][zZ]"), + QStringLiteral("*.[wW][bB][fF][sS]"), QStringLiteral("*.[wW][iI][aA]"), + QStringLiteral("*.[rR][vV][zZ]"), QStringLiteral("hif_000000.nfs"), + QStringLiteral("*.[wW][aA][dD]"), QStringLiteral("*.[eE][lL][fF]"), + QStringLiteral("*.[dD][oO][lL]"), QStringLiteral("*.[jJ][sS][oO][nN]")}; GameTracker::GameTracker(QObject* parent) : QFileSystemWatcher(parent) { diff --git a/Source/Core/DolphinQt/Info.plist.in b/Source/Core/DolphinQt/Info.plist.in index ddd2ed4182..0550533969 100644 --- a/Source/Core/DolphinQt/Info.plist.in +++ b/Source/Core/DolphinQt/Info.plist.in @@ -7,6 +7,7 @@ CFBundleTypeExtensions + bin ciso dol elf diff --git a/Source/Core/DolphinQt/MainWindow.cpp b/Source/Core/DolphinQt/MainWindow.cpp index 93ad16a59e..6cb0a39a06 100644 --- a/Source/Core/DolphinQt/MainWindow.cpp +++ b/Source/Core/DolphinQt/MainWindow.cpp @@ -787,7 +787,7 @@ QStringList MainWindow::PromptFileNames() QStringList paths = DolphinFileDialog::getOpenFileNames( this, tr("Select a File"), settings.value(QStringLiteral("mainwindow/lastdir"), QString{}).toString(), - QStringLiteral("%1 (*.elf *.dol *.gcm *.iso *.tgc *.wbfs *.ciso *.gcz *.wia *.rvz " + QStringLiteral("%1 (*.elf *.dol *.gcm *.bin *.iso *.tgc *.wbfs *.ciso *.gcz *.wia *.rvz " "hif_000000.nfs *.wad *.dff *.m3u *.json);;%2 (*)") .arg(tr("All GC/Wii files")) .arg(tr("All Files"))); diff --git a/Source/Core/DolphinQt/Settings/PathPane.cpp b/Source/Core/DolphinQt/Settings/PathPane.cpp index 8d91e31d50..bcbcbf3248 100644 --- a/Source/Core/DolphinQt/Settings/PathPane.cpp +++ b/Source/Core/DolphinQt/Settings/PathPane.cpp @@ -45,7 +45,7 @@ void PathPane::BrowseDefaultGame() { QString file = QDir::toNativeSeparators(DolphinFileDialog::getOpenFileName( this, tr("Select a Game"), Settings::Instance().GetDefaultGame(), - QStringLiteral("%1 (*.elf *.dol *.gcm *.iso *.tgc *.wbfs *.ciso *.gcz *.wia *.rvz " + QStringLiteral("%1 (*.elf *.dol *.gcm *.bin *.iso *.tgc *.wbfs *.ciso *.gcz *.wia *.rvz " "hif_000000.nfs *.wad *.m3u *.json);;%2 (*)") .arg(tr("All GC/Wii files")) .arg(tr("All Files")))); diff --git a/Source/Core/UICommon/GameFileCache.cpp b/Source/Core/UICommon/GameFileCache.cpp index 90dd0c63fc..f72f47c11e 100644 --- a/Source/Core/UICommon/GameFileCache.cpp +++ b/Source/Core/UICommon/GameFileCache.cpp @@ -26,14 +26,14 @@ namespace UICommon { -static constexpr u32 CACHE_REVISION = 25; // Last changed in PR 12702 +static constexpr u32 CACHE_REVISION = 26; // Last changed in PR 10084 std::vector FindAllGamePaths(const std::vector& directories_to_scan, bool recursive_scan) { static const std::vector search_extensions = { - ".gcm", ".tgc", ".iso", ".ciso", ".gcz", ".wbfs", ".wia", - ".rvz", ".nfs", ".wad", ".dol", ".elf", ".json"}; + ".gcm", ".tgc", ".bin", ".iso", ".ciso", ".gcz", ".wbfs", + ".wia", ".rvz", ".nfs", ".wad", ".dol", ".elf", ".json"}; // TODO: We could process paths iteratively as they are found return Common::DoFileSearch(directories_to_scan, search_extensions, recursive_scan); From 71f654cdc45ecb44e455ce35d8be910732aa6f7c Mon Sep 17 00:00:00 2001 From: Zopolis4 Date: Tue, 10 Aug 2021 07:49:34 +1000 Subject: [PATCH 2/7] Add Triforce platform and preliminary boot.id parsing --- Data/Sys/Resources/Platform_Triforce.png | Bin 0 -> 2396 bytes Data/Sys/Resources/Platform_Triforce@2x.png | Bin 0 -> 4176 bytes Data/Sys/Resources/Platform_Triforce@4x.png | Bin 0 -> 8404 bytes Source/Core/Core/Config/MainSettings.cpp | 1 + Source/Core/Core/Config/MainSettings.h | 1 + Source/Core/DiscIO/Enums.cpp | 3 ++- Source/Core/DiscIO/Enums.h | 1 + Source/Core/DiscIO/VolumeGC.cpp | 22 ++++++++++++++++-- Source/Core/DiscIO/VolumeGC.h | 2 ++ Source/Core/DiscIO/VolumeVerifier.cpp | 8 +++++++ Source/Core/DiscIO/VolumeVerifier.h | 1 + Source/Core/DolphinQt/Config/InfoWidget.cpp | 1 + .../Core/DolphinQt/GameList/GameListModel.cpp | 2 ++ Source/Core/DolphinQt/MenuBar.cpp | 1 + Source/Core/DolphinQt/Resources.cpp | 2 +- 15 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 Data/Sys/Resources/Platform_Triforce.png create mode 100644 Data/Sys/Resources/Platform_Triforce@2x.png create mode 100644 Data/Sys/Resources/Platform_Triforce@4x.png diff --git a/Data/Sys/Resources/Platform_Triforce.png b/Data/Sys/Resources/Platform_Triforce.png new file mode 100644 index 0000000000000000000000000000000000000000..e6a3b26b765709a41fe2efd8aa0d45d237d09e2b GIT binary patch literal 2396 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 SPpk^m=l68=b6Mw<&;$Td5E1ME literal 0 HcmV?d00001 diff --git a/Data/Sys/Resources/Platform_Triforce@4x.png b/Data/Sys/Resources/Platform_Triforce@4x.png new file mode 100644 index 0000000000000000000000000000000000000000..85bf7c272d7f832d9e36ecedf941baa0fb11e93f GIT binary patch literal 8404 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

yRFE6FK?lD(@iA= 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 kLk|xRwwWW)?A4!oCI&{W+kNbpK@~ literal 0 HcmV?d00001 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)); } From 8d94d25203b5b03d1fd9d6408b2aca3d71df1a14 Mon Sep 17 00:00:00 2001 From: Zopolis4 Date: Fri, 17 Dec 2021 18:56:48 +1100 Subject: [PATCH 3/7] Implement Triforce ID parsing --- Data/Sys/triforcetdb-en.txt | 10 +++++++ Source/Core/Core/ConfigManager.cpp | 27 ++++++++++++------ Source/Core/Core/ConfigManager.h | 5 +++- Source/Core/Core/TitleDatabase.cpp | 31 +++++++++++++++++++-- Source/Core/Core/TitleDatabase.h | 5 +++- Source/Core/DiscIO/Volume.h | 1 + Source/Core/DiscIO/VolumeGC.cpp | 17 +++++++++-- Source/Core/DiscIO/VolumeGC.h | 9 ++++++ Source/Core/DolphinQt/Config/InfoWidget.cpp | 4 +++ Source/Core/UICommon/GameFile.cpp | 5 +++- Source/Core/UICommon/GameFile.h | 2 ++ 11 files changed, 99 insertions(+), 17 deletions(-) create mode 100644 Data/Sys/triforcetdb-en.txt 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; From 2baa09d5b417e08e5092dedb85bc055c0fddd8be Mon Sep 17 00:00:00 2001 From: Zopolis4 Date: Mon, 23 Aug 2021 20:41:22 +1000 Subject: [PATCH 4/7] Implement endian swapping and lazy decryption of Triforce DI commands --- Source/Core/Core/Boot/Boot_BS2Emu.cpp | 7 +++++++ Source/Core/Core/HW/DVD/DVDInterface.cpp | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/Source/Core/Core/Boot/Boot_BS2Emu.cpp b/Source/Core/Core/Boot/Boot_BS2Emu.cpp index baf2079677..884a11bd87 100644 --- a/Source/Core/Core/Boot/Boot_BS2Emu.cpp +++ b/Source/Core/Core/Boot/Boot_BS2Emu.cpp @@ -227,6 +227,13 @@ bool CBoot::RunApploader(Core::System& system, const Core::CPUThreadGuard& guard ppc_state.pc = ppc_state.gpr[3]; branch_watch.SetRecordingActive(guard, resume_branch_watch); + // Blank out session key (https://debugmo.de/2008/05/part-2-dumping-the-media-board/) + if (volume.GetVolumeType() == DiscIO::Platform::Triforce) + { + auto& memory = system.GetMemory(); + + memory.Memset(0, 0, 12); + } return true; } diff --git a/Source/Core/Core/HW/DVD/DVDInterface.cpp b/Source/Core/Core/HW/DVD/DVDInterface.cpp index babb500902..f6e7954b02 100644 --- a/Source/Core/Core/HW/DVD/DVDInterface.cpp +++ b/Source/Core/Core/HW/DVD/DVDInterface.cpp @@ -753,6 +753,15 @@ void DVDInterface::ExecuteCommand(ReplyType reply_type) DIInterruptType interrupt_type = DIInterruptType::TCINT; bool command_handled_by_thread = false; + // Swaps endian of Triforce DI commands, and zeroes out random bytes to prevent unknown read + // subcommand errors + auto& dvd_thread = m_system.GetDVDThread(); + if (dvd_thread.GetDiscType() == DiscIO::Platform::Triforce) + { + // TODO(C++23): Use std::byteswap and a bitwise AND for increased clarity + m_DICMDBUF[0] <<= 24; + } + // DVDLowRequestError needs access to the error code set by the previous command if (static_cast(m_DICMDBUF[0] >> 24) != DICommand::RequestError) SetDriveError(DriveError::None); From 660232a12c03698c9df3114046da3a45fdd9806f Mon Sep 17 00:00:00 2001 From: Zopolis4 Date: Sun, 7 Nov 2021 03:19:59 +1100 Subject: [PATCH 5/7] Preliminary implementation of the Triforce Baseboard --- Source/Core/Core/CMakeLists.txt | 2 + Source/Core/Core/ConfigManager.cpp | 2 + Source/Core/Core/HW/EXI/EXI.cpp | 13 +++++ Source/Core/Core/HW/EXI/EXI.h | 1 + Source/Core/Core/HW/EXI/EXI_Device.cpp | 6 +- Source/Core/Core/HW/EXI/EXI_Device.h | 6 +- .../Core/Core/HW/EXI/EXI_DeviceBaseboard.cpp | 57 +++++++++++++++++++ Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.h | 27 +++++++++ Source/Core/Core/State.cpp | 2 +- Source/Core/Core/System.h | 3 + Source/Core/DolphinLib.props | 2 + 11 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.cpp create mode 100644 Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.h diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index b4437747e8..09b69a620e 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -203,6 +203,8 @@ add_library(core HW/EXI/EXI_DeviceAD16.h HW/EXI/EXI_DeviceAGP.cpp HW/EXI/EXI_DeviceAGP.h + HW/EXI/EXI_DeviceBaseboard.cpp + HW/EXI/EXI_DeviceBaseboard.h HW/EXI/EXI_DeviceDummy.cpp HW/EXI/EXI_DeviceDummy.h HW/EXI/EXI_DeviceEthernet.cpp diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp index a480c7622d..e005e78341 100644 --- a/Source/Core/Core/ConfigManager.cpp +++ b/Source/Core/Core/ConfigManager.cpp @@ -307,6 +307,7 @@ void SConfig::LoadDefaults() auto& system = Core::System::GetInstance(); system.SetIsWii(false); + system.SetIsTriforce(false); ResetRunningGameMetadata(); } @@ -330,6 +331,7 @@ struct SetGameMetadata { *region = disc.volume->GetRegion(); system.SetIsWii(disc.volume->GetVolumeType() == DiscIO::Platform::WiiDisc); + system.SetIsTriforce(disc.volume->GetVolumeType() == DiscIO::Platform::Triforce); config->m_disc_booted_from_game_list = true; config->SetRunningGameMetadata(*disc.volume, disc.volume->GetGamePartition()); return true; diff --git a/Source/Core/Core/HW/EXI/EXI.cpp b/Source/Core/Core/HW/EXI/EXI.cpp index 303191c574..d676dc4845 100644 --- a/Source/Core/Core/HW/EXI/EXI.cpp +++ b/Source/Core/Core/HW/EXI/EXI.cpp @@ -66,6 +66,18 @@ void ExpansionInterfaceManager::AddMemoryCard(Slot slot) m_channels[SlotToEXIChannel(slot)]->AddDevice(memorycard_device, SlotToEXIDevice(slot)); } +void ExpansionInterfaceManager::AddSP1Device() +{ + EXIDeviceType sp1_device = EXIDeviceType::Baseboard; + auto& system = Core::System::GetInstance(); + if (system.IsTriforce()) + { + sp1_device = Config::Get(Config::MAIN_SERIAL_PORT_1); + } + + m_channels[0]->AddDevice(sp1_device, SlotToEXIDevice(Slot::SP1)); +} + u8 SlotToEXIChannel(Slot slot) { switch (slot) @@ -145,6 +157,7 @@ void ExpansionInterfaceManager::Init(const Sram* override_sram) AddMemoryCard(slot); m_channels[0]->AddDevice(EXIDeviceType::MaskROM, 1); + AddSP1Device(); m_channels[SlotToEXIChannel(Slot::SP1)]->AddDevice(Config::Get(Config::MAIN_SERIAL_PORT_1), SlotToEXIDevice(Slot::SP1)); m_channels[SlotToEXIChannel(Slot::SP2)]->AddDevice(Config::Get(Config::MAIN_SERIAL_PORT_2), diff --git a/Source/Core/Core/HW/EXI/EXI.h b/Source/Core/Core/HW/EXI/EXI.h index 7ded905b98..f0ea5fbfb5 100644 --- a/Source/Core/Core/HW/EXI/EXI.h +++ b/Source/Core/Core/HW/EXI/EXI.h @@ -89,6 +89,7 @@ public: private: void AddMemoryCard(Slot slot); + void AddSP1Device(); static void ChangeDeviceCallback(Core::System& system, u64 userdata, s64 cycles_late); static void UpdateInterruptsCallback(Core::System& system, u64 userdata, s64 cycles_late); diff --git a/Source/Core/Core/HW/EXI/EXI_Device.cpp b/Source/Core/Core/HW/EXI/EXI_Device.cpp index 6c416d5387..ac92c7b723 100644 --- a/Source/Core/Core/HW/EXI/EXI_Device.cpp +++ b/Source/Core/Core/HW/EXI/EXI_Device.cpp @@ -9,6 +9,7 @@ #include "Common/MsgHandler.h" #include "Core/HW/EXI/EXI_DeviceAD16.h" #include "Core/HW/EXI/EXI_DeviceAGP.h" +#include "Core/HW/EXI/EXI_DeviceBaseboard.h" #include "Core/HW/EXI/EXI_DeviceDummy.h" #include "Core/HW/EXI/EXI_DeviceEthernet.h" #include "Core/HW/EXI/EXI_DeviceGecko.h" @@ -171,7 +172,10 @@ std::unique_ptr EXIDevice_Create(Core::System& system, const EXIDevi result = std::make_unique(system, slot); break; - case EXIDeviceType::AMBaseboard: + case EXIDeviceType::Baseboard: + result = std::make_unique(system); + break; + case EXIDeviceType::None: default: result = std::make_unique(system); diff --git a/Source/Core/Core/HW/EXI/EXI_Device.h b/Source/Core/Core/HW/EXI/EXI_Device.h index db74306df0..25263af425 100644 --- a/Source/Core/Core/HW/EXI/EXI_Device.h +++ b/Source/Core/Core/HW/EXI/EXI_Device.h @@ -30,9 +30,7 @@ enum class EXIDeviceType : int AD16, Microphone, Ethernet, - // Was used for Triforce in the past, but the implementation is no longer in Dolphin. - // It's kept here so that values below will stay constant. - AMBaseboard, + Baseboard, Gecko, // Only used when creating a device by EXIDevice_Create. // Converted to MemoryCard internally. @@ -98,7 +96,7 @@ struct fmt::formatter _trans("AD16"), _trans("Microphone"), _trans("Broadband Adapter (TAP)"), - _trans("Triforce AM Baseboard"), + _trans("Triforce Baseboard"), _trans("USB Gecko"), _trans("GCI Folder"), _trans("Advance Game Port"), diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.cpp b/Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.cpp new file mode 100644 index 0000000000..a9200ac85a --- /dev/null +++ b/Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.cpp @@ -0,0 +1,57 @@ +// Copyright 2013 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "Core/HW/EXI/EXI_DeviceBaseboard.h" + +#include "Common/Assert.h" +#include "Common/ChunkFile.h" +#include "Common/CommonTypes.h" +#include "Common/Logging/Log.h" + +namespace ExpansionInterface +{ +CEXIBaseboard::CEXIBaseboard(Core::System& system) : IEXIDevice(system) +{ +} + +void CEXIBaseboard::SetCS(int cs) +{ + if (cs) + m_position = 0; +} + +bool CEXIBaseboard::IsPresent() const +{ + return true; +} + +void CEXIBaseboard::TransferByte(u8& byte) +{ + if (m_position == 0) + { + m_command = byte; + } + else + { + switch (m_command) + { + case 0x00: + { + static constexpr std::array ID = {0x06, 0x04, 0x10, 0x00}; + byte = ID[(m_position - 2) & 3]; + break; + } + default: + ERROR_LOG_FMT(EXPANSIONINTERFACE, "EXI BASEBOARD: Unhandled command {:#x} {:#x}", m_command, + m_position); + } + } + m_position++; +} + +void CEXIBaseboard::DoState(PointerWrap& p) +{ + p.Do(m_position); + p.Do(m_command); +} +} // namespace ExpansionInterface diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.h b/Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.h new file mode 100644 index 0000000000..4c534428c9 --- /dev/null +++ b/Source/Core/Core/HW/EXI/EXI_DeviceBaseboard.h @@ -0,0 +1,27 @@ +// Copyright 2013 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "Core/HW/EXI/EXI_Device.h" + +class PointerWrap; + +namespace ExpansionInterface +{ +class CEXIBaseboard : public IEXIDevice +{ +public: + CEXIBaseboard(Core::System& system); + void SetCS(int cs) override; + bool IsPresent() const override; + void DoState(PointerWrap& p) override; + +private: + // STATE_TO_SAVE + u32 m_position = 0; + u32 m_command = 0; + + void TransferByte(u8& byte) override; +}; +} // namespace ExpansionInterface diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index 44465b3f42..9620cfccd4 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -99,7 +99,7 @@ static size_t s_state_writes_in_queue; static std::condition_variable s_state_write_queue_is_empty; // Don't forget to increase this after doing changes on the savestate system -constexpr u32 STATE_VERSION = 172; // Last changed in PR 13385 +constexpr u32 STATE_VERSION = 173; // Last changed in PR 10084 // Increase this if the StateExtendedHeader definition changes constexpr u32 EXTENDED_HEADER_VERSION = 1; // Last changed in PR 12217 diff --git a/Source/Core/Core/System.h b/Source/Core/Core/System.h index 9ec8391ff0..0ab86e658d 100644 --- a/Source/Core/Core/System.h +++ b/Source/Core/Core/System.h @@ -141,10 +141,12 @@ public: bool IsMMUMode() const { return m_mmu_enabled; } bool IsPauseOnPanicMode() const { return m_pause_on_panic_enabled; } bool IsMIOS() const { return m_is_mios; } + bool IsTriforce() const { return m_is_triforce; } bool IsWii() const { return m_is_wii; } bool IsBranchWatchIgnoreApploader() { return m_branch_watch_ignore_apploader; } void SetIsMIOS(bool is_mios) { m_is_mios = is_mios; } + void SetIsTriforce(bool is_triforce) { m_is_triforce = is_triforce; } void SetIsWii(bool is_wii) { m_is_wii = is_wii; } void SetIsBranchWatchIgnoreApploader(bool enable) { m_branch_watch_ignore_apploader = enable; } @@ -205,6 +207,7 @@ private: bool m_mmu_enabled = false; bool m_pause_on_panic_enabled = false; bool m_is_mios = false; + bool m_is_triforce = false; bool m_is_wii = false; bool m_branch_watch_ignore_apploader = false; }; diff --git a/Source/Core/DolphinLib.props b/Source/Core/DolphinLib.props index 388367afd1..4c7764202d 100644 --- a/Source/Core/DolphinLib.props +++ b/Source/Core/DolphinLib.props @@ -281,6 +281,7 @@ + @@ -948,6 +949,7 @@ + From 2238967d93007a9ccff49fec3a9d9f0e6aa000cc Mon Sep 17 00:00:00 2001 From: Zopolis4 Date: Sun, 22 Jan 2023 21:02:05 +1100 Subject: [PATCH 6/7] Add Triforce IPL hash --- Source/Core/Core/Boot/Boot.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Source/Core/Core/Boot/Boot.cpp b/Source/Core/Core/Boot/Boot.cpp index 4e08ccfd12..e95984f122 100644 --- a/Source/Core/Core/Boot/Boot.cpp +++ b/Source/Core/Core/Boot/Boot.cpp @@ -407,6 +407,7 @@ bool CBoot::Load_BS2(Core::System& system, const std::string& boot_rom_filename) constexpr u32 PAL_v1_0 = 0x4F319F43; // DOL-101(EUR) (PAL Revision 1.2) constexpr u32 PAL_v1_2 = 0xAD1B7F16; + constexpr u32 Triforce = 0xD1883221; // The Triforce's special IPL // Load the IPL ROM dump, limited to 2MiB which is the size of the official IPLs. constexpr size_t max_ipl_size = 2 * 1024 * 1024; @@ -424,6 +425,7 @@ bool CBoot::Load_BS2(Core::System& system, const std::string& boot_rom_filename) const u32 ipl_hash = Common::ComputeCRC32(data.data(), data.size()); bool known_ipl = false; bool pal_ipl = false; + bool triforce_ipl = false; switch (ipl_hash) { case NTSC_v1_0: @@ -438,6 +440,9 @@ bool CBoot::Load_BS2(Core::System& system, const std::string& boot_rom_filename) pal_ipl = true; known_ipl = true; break; + case Triforce: + known_ipl = true; + triforce_ipl = true; default: PanicAlertFmtT("The IPL file is not a known good dump. (CRC32: {0:x})", ipl_hash); break; From 89fdc0b9e0db9b65b7ba81b8ee33114415e8666c Mon Sep 17 00:00:00 2001 From: Zopolis4 Date: Tue, 28 Sep 2021 10:48:24 +1000 Subject: [PATCH 7/7] Fix Triforce GameINIs --- Data/Sys/ApprovedInis.json | 4 ---- Data/Sys/GameSettings/GVS.ini | 7 ++++++- Data/Sys/GameSettings/GVS46E.ini | 18 ------------------ Data/Sys/GameSettings/GVS46J.ini | 18 ------------------ Data/Sys/GameSettings/RELJAB.ini | 18 ------------------ Source/Core/Core/AchievementManager.h | 4 ++-- 6 files changed, 8 insertions(+), 61 deletions(-) delete mode 100644 Data/Sys/GameSettings/GVS46E.ini delete mode 100644 Data/Sys/GameSettings/GVS46J.ini delete mode 100644 Data/Sys/GameSettings/RELJAB.ini diff --git a/Data/Sys/ApprovedInis.json b/Data/Sys/ApprovedInis.json index 9d3b37c8d9..a73ed032f0 100644 --- a/Data/Sys/ApprovedInis.json +++ b/Data/Sys/ApprovedInis.json @@ -932,10 +932,6 @@ "title": "Region Select", "AD12237401ABE9FE4A545AADB5C5AE10355E2076": "RSAPatch" }, - "RELJAB": { - "title": "SegaBoot", - "130F3594CAB57B85616F95C7126F4748AAC5867D": "DI Seed Blanker" - }, "RGQE70": { "title": "Ghostbusters", "5F4CF8D4DA19A0FF74FF9EB925AC0236069BFD59": "crashfix" diff --git a/Data/Sys/GameSettings/GVS.ini b/Data/Sys/GameSettings/GVS.ini index 780267fa56..90641b1723 100644 --- a/Data/Sys/GameSettings/GVS.ini +++ b/Data/Sys/GameSettings/GVS.ini @@ -1,4 +1,5 @@ -# GVSE8P, GVSP8P - Virtua Striker 3 ver. 2002 +# GVSP8P, GVSE8P, GVSJ8P - Virtua Striker 2002 (GC) +# GVSJ8P - Virtua Striker 2002 (Triforce), Virtua Striker 4, Virtua Striker 4 ver. 2006 [Core] # Values set here will override the main Dolphin settings. @@ -10,3 +11,7 @@ FPRF = True [ActionReplay] # Add action replay cheats here. +[Video] +# Add memory patches to be applied every frame here. + +[Video_Settings] diff --git a/Data/Sys/GameSettings/GVS46E.ini b/Data/Sys/GameSettings/GVS46E.ini deleted file mode 100644 index 40061416f8..0000000000 --- a/Data/Sys/GameSettings/GVS46E.ini +++ /dev/null @@ -1,18 +0,0 @@ -# GVS46E, GVS46J - Virtua Striker 4 ver. 2006 -# Because Triforce games have weird IDs, properties are inherited from GVS.ini (Virtua Striker 3 ver. 2002)! - -[Core] -# Values set here will override the main Dolphin settings. -FPRF = True - -[OnFrame] -# Add memory patches to be applied every frame here. - -[ActionReplay] -# Add action replay cheats here. - -[Video] -# Add memory patches to be applied every frame here. - -[Video_Settings] - diff --git a/Data/Sys/GameSettings/GVS46J.ini b/Data/Sys/GameSettings/GVS46J.ini deleted file mode 100644 index 40061416f8..0000000000 --- a/Data/Sys/GameSettings/GVS46J.ini +++ /dev/null @@ -1,18 +0,0 @@ -# GVS46E, GVS46J - Virtua Striker 4 ver. 2006 -# Because Triforce games have weird IDs, properties are inherited from GVS.ini (Virtua Striker 3 ver. 2002)! - -[Core] -# Values set here will override the main Dolphin settings. -FPRF = True - -[OnFrame] -# Add memory patches to be applied every frame here. - -[ActionReplay] -# Add action replay cheats here. - -[Video] -# Add memory patches to be applied every frame here. - -[Video_Settings] - diff --git a/Data/Sys/GameSettings/RELJAB.ini b/Data/Sys/GameSettings/RELJAB.ini deleted file mode 100644 index 872c654b6e..0000000000 --- a/Data/Sys/GameSettings/RELJAB.ini +++ /dev/null @@ -1,18 +0,0 @@ -# RELJAB - SegaBoot - -[Core] -# Values set here will override the main Dolphin settings. - -[OnFrame] -# Add memory patches to be applied every frame here. -$DI Seed Blanker -0x80000000:dword:0x00000000 -0x80000004:dword:0x00000000 -0x80000008:dword:0x00000000 - -[Patches_RetroAchievements_Verified] -$DI Seed Blanker - -[ActionReplay] -# Add action replay cheats here. - diff --git a/Source/Core/Core/AchievementManager.h b/Source/Core/Core/AchievementManager.h index f46b7e9da3..dfa6bb535e 100644 --- a/Source/Core/Core/AchievementManager.h +++ b/Source/Core/Core/AchievementManager.h @@ -80,8 +80,8 @@ public: static constexpr std::string_view BLUE = "#0B71C1"; static constexpr std::string_view APPROVED_LIST_FILENAME = "ApprovedInis.json"; static const inline Common::SHA1::Digest APPROVED_LIST_HASH = { - 0x4F, 0x45, 0xB7, 0xA3, 0xC4, 0x6E, 0xAF, 0x80, 0x58, 0xA5, - 0x53, 0x99, 0xF8, 0x05, 0xC3, 0x83, 0x22, 0xA4, 0x5F, 0x65}; + 0xE1, 0x29, 0xD1, 0x33, 0x4D, 0xF2, 0xF8, 0xA8, 0x4E, 0xCA, + 0xF6, 0x87, 0xE6, 0xEC, 0xEC, 0xB3, 0x18, 0x69, 0x34, 0x45}; struct LeaderboardEntry {