mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-24 14:49:42 -06:00
Merge pull request #8861 from JosJuice/netplay-hash
Make netplay's "same game" check more robust
This commit is contained in:
@ -5,6 +5,7 @@
|
||||
#include "UICommon/GameFile.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cinttypes>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
@ -13,11 +14,13 @@
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <mbedtls/sha1.h>
|
||||
#include <pugixml.hpp>
|
||||
|
||||
#include "Common/ChunkFile.h"
|
||||
@ -532,7 +535,7 @@ std::vector<DiscIO::Language> GameFile::GetLanguages() const
|
||||
return languages;
|
||||
}
|
||||
|
||||
std::string GameFile::GetUniqueIdentifier() const
|
||||
std::string GameFile::GetNetPlayName(const Core::TitleDatabase& title_database) const
|
||||
{
|
||||
std::vector<std::string> info;
|
||||
if (!GetGameID().empty())
|
||||
@ -540,12 +543,7 @@ std::string GameFile::GetUniqueIdentifier() const
|
||||
if (GetRevision() != 0)
|
||||
info.push_back("Revision " + std::to_string(GetRevision()));
|
||||
|
||||
std::string name = GetLongName(DiscIO::Language::English);
|
||||
if (name.empty())
|
||||
{
|
||||
// Use the file name as a fallback. Not necessarily consistent, but it's the best we have
|
||||
name = m_file_name;
|
||||
}
|
||||
const std::string name = GetName(title_database);
|
||||
|
||||
int disc_number = GetDiscNumber() + 1;
|
||||
|
||||
@ -566,6 +564,66 @@ std::string GameFile::GetUniqueIdentifier() const
|
||||
return name + " (" + ss.str() + ")";
|
||||
}
|
||||
|
||||
std::array<u8, 20> GameFile::GetSyncHash() const
|
||||
{
|
||||
std::array<u8, 20> hash{};
|
||||
|
||||
if (m_platform == DiscIO::Platform::ELFOrDOL)
|
||||
{
|
||||
std::string buffer;
|
||||
if (File::ReadFileToString(m_file_path, buffer))
|
||||
mbedtls_sha1_ret(reinterpret_cast<unsigned char*>(buffer.data()), buffer.size(), hash.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (std::unique_ptr<DiscIO::Volume> volume = DiscIO::CreateVolume(m_file_path))
|
||||
hash = volume->GetSyncHash();
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
NetPlay::SyncIdentifier GameFile::GetSyncIdentifier() const
|
||||
{
|
||||
const u64 dol_elf_size = m_platform == DiscIO::Platform::ELFOrDOL ? m_file_size : 0;
|
||||
return NetPlay::SyncIdentifier{dol_elf_size, m_game_id, m_revision,
|
||||
m_disc_number, m_is_datel_disc, GetSyncHash()};
|
||||
}
|
||||
|
||||
NetPlay::SyncIdentifierComparison
|
||||
GameFile::CompareSyncIdentifier(const NetPlay::SyncIdentifier& sync_identifier) const
|
||||
{
|
||||
const bool is_elf_or_dol = m_platform == DiscIO::Platform::ELFOrDOL;
|
||||
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))
|
||||
return NetPlay::SyncIdentifierComparison::DifferentGame;
|
||||
|
||||
if (m_disc_number != sync_identifier.disc_number || m_is_datel_disc != sync_identifier.is_datel)
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (m_revision != sync_identifier.revision)
|
||||
return mismatch_result;
|
||||
|
||||
return GetSyncHash() == sync_identifier.sync_hash ? NetPlay::SyncIdentifierComparison::SameGame :
|
||||
mismatch_result;
|
||||
}
|
||||
|
||||
std::string GameFile::GetWiiFSPath() const
|
||||
{
|
||||
ASSERT(DiscIO::IsWii(m_platform));
|
||||
|
@ -4,11 +4,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Core/SyncIdentifier.h"
|
||||
#include "DiscIO/Blob.h"
|
||||
#include "DiscIO/Enums.h"
|
||||
|
||||
@ -80,7 +82,16 @@ public:
|
||||
u16 GetRevision() const { return m_revision; }
|
||||
// 0 is the first disc, 1 is the second disc
|
||||
u8 GetDiscNumber() const { return m_disc_number; }
|
||||
std::string GetUniqueIdentifier() const;
|
||||
std::string GetNetPlayName(const Core::TitleDatabase& title_database) const;
|
||||
|
||||
// This function is slow
|
||||
std::array<u8, 20> GetSyncHash() const;
|
||||
// This function is slow
|
||||
NetPlay::SyncIdentifier GetSyncIdentifier() const;
|
||||
// This function is slow if all of game_id, revision, disc_number, is_datel are identical
|
||||
NetPlay::SyncIdentifierComparison
|
||||
CompareSyncIdentifier(const NetPlay::SyncIdentifier& sync_identifier) const;
|
||||
|
||||
std::string GetWiiFSPath() const;
|
||||
DiscIO::Region GetRegion() const { return m_region; }
|
||||
DiscIO::Country GetCountry() const { return m_country; }
|
||||
|
Reference in New Issue
Block a user