summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorPokechu22 <Pokechu022@gmail.com>2022-05-20 22:25:33 -0700
committerPokechu22 <Pokechu022@gmail.com>2022-05-24 23:20:45 -0700
commit2341ff00ab3484360de03e5dc1c43dbe522f361f (patch)
tree6c475538cb48b42b7c3ce471eeb270b426e7e380 /Source/Core
parentea9b0bff08dab1df92c9aca2da3e748942d85955 (diff)
NetPlay: Make messages about non-matching games clearer
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/SyncIdentifier.h7
-rw-r--r--Source/Core/DolphinQt/NetPlay/NetPlayDialog.cpp33
-rw-r--r--Source/Core/UICommon/GameFile.cpp58
3 files changed, 73 insertions, 25 deletions
diff --git a/Source/Core/Core/SyncIdentifier.h b/Source/Core/Core/SyncIdentifier.h
index 7175f073c4..a144eb58e1 100644
--- a/Source/Core/Core/SyncIdentifier.h
+++ b/Source/Core/Core/SyncIdentifier.h
@@ -34,10 +34,15 @@ struct SyncIdentifier
bool operator!=(const SyncIdentifier& s) const { return !operator==(s); }
};
+// The order of entries in this enum matters, as the lowest value is
+// treated as the "best" available option.
enum class SyncIdentifierComparison
{
SameGame,
- DifferentVersion,
+ DifferentHash,
+ DifferentDiscNumber,
+ DifferentRevision,
+ DifferentRegion,
DifferentGame,
Unknown,
};
diff --git a/Source/Core/DolphinQt/NetPlay/NetPlayDialog.cpp b/Source/Core/DolphinQt/NetPlay/NetPlayDialog.cpp
index 02f7497b82..4a297acea3 100644
--- a/Source/Core/DolphinQt/NetPlay/NetPlayDialog.cpp
+++ b/Source/Core/DolphinQt/NetPlay/NetPlayDialog.cpp
@@ -611,25 +611,42 @@ void NetPlayDialog::UpdateGUI()
{tr("Player"), tr("Game Status"), tr("Ping"), tr("Mapping"), tr("Revision")});
m_players_list->setRowCount(m_player_count);
- static const std::map<NetPlay::SyncIdentifierComparison, QString> player_status{
- {NetPlay::SyncIdentifierComparison::SameGame, tr("OK")},
- {NetPlay::SyncIdentifierComparison::DifferentVersion, tr("Wrong Version")},
- {NetPlay::SyncIdentifierComparison::DifferentGame, tr("Not Found")},
- };
+ static const std::map<NetPlay::SyncIdentifierComparison, std::pair<QString, QString>>
+ player_status{
+ {NetPlay::SyncIdentifierComparison::SameGame, {tr("OK"), tr("OK")}},
+ {NetPlay::SyncIdentifierComparison::DifferentHash,
+ {tr("Wrong hash"),
+ tr("Game file has a different hash; right-click it, select Properties, switch to the "
+ "Verify tab, and select Verify Integrity to check the hash")}},
+ {NetPlay::SyncIdentifierComparison::DifferentDiscNumber,
+ {tr("Wrong disc number"), tr("Game has a different disc number")}},
+ {NetPlay::SyncIdentifierComparison::DifferentRevision,
+ {tr("Wrong revision"), tr("Game has a different revision")}},
+ {NetPlay::SyncIdentifierComparison::DifferentRegion,
+ {tr("Wrong region"), tr("Game region does not match")}},
+ {NetPlay::SyncIdentifierComparison::DifferentGame,
+ {tr("Not found"), tr("No matching game was found")}},
+ };
for (int i = 0; i < m_player_count; i++)
{
const auto* p = players[i];
auto* name_item = new QTableWidgetItem(QString::fromStdString(p->name));
- auto* status_item = new QTableWidgetItem(player_status.count(p->game_status) ?
- player_status.at(p->game_status) :
- QStringLiteral("?"));
+ name_item->setToolTip(name_item->text());
+ const auto& status_info = player_status.count(p->game_status) ?
+ player_status.at(p->game_status) :
+ std::make_pair(QStringLiteral("?"), QStringLiteral("?"));
+ auto* status_item = new QTableWidgetItem(status_info.first);
+ status_item->setToolTip(status_info.second);
auto* ping_item = new QTableWidgetItem(QStringLiteral("%1 ms").arg(p->ping));
+ ping_item->setToolTip(ping_item->text());
auto* mapping_item =
new QTableWidgetItem(QString::fromStdString(NetPlay::GetPlayerMappingString(
p->pid, client->GetPadMapping(), client->GetGBAConfig(), client->GetWiimoteMapping())));
+ mapping_item->setToolTip(mapping_item->text());
auto* revision_item = new QTableWidgetItem(QString::fromStdString(p->revision));
+ revision_item->setToolTip(revision_item->text());
for (auto* item : {name_item, status_item, ping_item, mapping_item, revision_item})
{
diff --git a/Source/Core/UICommon/GameFile.cpp b/Source/Core/UICommon/GameFile.cpp
index d87fb9d168..96628af087 100644
--- a/Source/Core/UICommon/GameFile.cpp
+++ b/Source/Core/UICommon/GameFile.cpp
@@ -720,31 +720,57 @@ GameFile::CompareSyncIdentifier(const NetPlay::SyncIdentifier& sync_identifier)
if ((is_elf_or_dol ? m_file_size : 0) != sync_identifier.dol_elf_size)
return NetPlay::SyncIdentifierComparison::DifferentGame;
- const auto trim = [](const std::string& str, size_t n) {
- return std::string_view(str.data(), std::min(n, str.size()));
- };
-
- if (trim(m_game_id, 3) != trim(sync_identifier.game_id, 3))
+ if (m_is_datel_disc != sync_identifier.is_datel)
return NetPlay::SyncIdentifierComparison::DifferentGame;
- if (m_disc_number != sync_identifier.disc_number || m_is_datel_disc != sync_identifier.is_datel)
+ if (m_game_id.size() != sync_identifier.game_id.size())
return NetPlay::SyncIdentifierComparison::DifferentGame;
- const NetPlay::SyncIdentifierComparison mismatch_result =
- is_elf_or_dol || m_is_datel_disc ? NetPlay::SyncIdentifierComparison::DifferentGame :
- NetPlay::SyncIdentifierComparison::DifferentVersion;
-
- if (m_game_id != sync_identifier.game_id)
+ if (!is_elf_or_dol && !m_is_datel_disc && m_game_id.size() >= 4 && m_game_id.size() <= 6)
+ {
+ // This is a game ID, following specific rules which we can use to give clearer information to
+ // the user.
+
+ // If the first 3 characters don't match, then these are probably different games.
+ // (There are exceptions; in particular Japanese-region games sometimes use a different ID;
+ // for instance, GOYE69, GOYP69, and GGIJ13 are used by GoldenEye: Rogue Agent.)
+ if (std::string_view(&m_game_id[0], 3) != std::string_view(&sync_identifier.game_id[0], 3))
+ return NetPlay::SyncIdentifierComparison::DifferentGame;
+
+ // If the first 3 characters match but the region doesn't match, reject it as such.
+ if (m_game_id[3] != sync_identifier.game_id[3])
+ return NetPlay::SyncIdentifierComparison::DifferentRegion;
+
+ // If the maker code is present, and doesn't match between the two but the main ID does,
+ // these might be different revisions of the same game (e.g. a rerelease with a different
+ // publisher), which we should treat as a different revision.
+ if (std::string_view(&m_game_id[4]) != std::string_view(&sync_identifier.game_id[4]))
+ return NetPlay::SyncIdentifierComparison::DifferentRevision;
+ }
+ else
{
- const bool game_id_is_title_id = m_game_id.size() > 6 || sync_identifier.game_id.size() > 6;
- return game_id_is_title_id ? NetPlay::SyncIdentifierComparison::DifferentGame : mismatch_result;
+ // Numeric title ID or another generated ID that does not follow the rules above
+ if (m_game_id != sync_identifier.game_id)
+ return NetPlay::SyncIdentifierComparison::DifferentGame;
}
if (m_revision != sync_identifier.revision)
- return mismatch_result;
+ return NetPlay::SyncIdentifierComparison::DifferentRevision;
+
+ if (m_disc_number != sync_identifier.disc_number)
+ return NetPlay::SyncIdentifierComparison::DifferentDiscNumber;
+
+ if (GetSyncHash() != sync_identifier.sync_hash)
+ {
+ // Most Datel titles re-use the same game ID (GNHE5d, with that lowercase D, or DTLX01).
+ // So if the hash differs, then it's probably a different game even if the game ID matches.
+ if (m_is_datel_disc)
+ return NetPlay::SyncIdentifierComparison::DifferentGame;
+ else
+ return NetPlay::SyncIdentifierComparison::DifferentHash;
+ }
- return GetSyncHash() == sync_identifier.sync_hash ? NetPlay::SyncIdentifierComparison::SameGame :
- mismatch_result;
+ return NetPlay::SyncIdentifierComparison::SameGame;
}
std::string GameFile::GetWiiFSPath() const