mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-26 15:55:31 +01:00
88431cfbca
Makes it consistent with GetNetworkPatchByPayload()
166 lines
4.3 KiB
C++
166 lines
4.3 KiB
C++
// Copyright 2023 Dolphin Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
// WC24PatchEngine
|
|
// Allows for replacing URLs used in WC24 requests
|
|
|
|
#include "Core/WC24PatchEngine.h"
|
|
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <fmt/format.h>
|
|
|
|
#include "Common/IniFile.h"
|
|
#include "Common/StringUtil.h"
|
|
|
|
#include "Core/CheatCodes.h"
|
|
#include "Core/CommonTitles.h"
|
|
#include "Core/Config/MainSettings.h"
|
|
#include "Core/ConfigManager.h"
|
|
|
|
namespace WC24PatchEngine
|
|
{
|
|
static constexpr std::array<u64, 15> s_wc24_channels{
|
|
Titles::NINTENDO_CHANNEL_NTSC_U,
|
|
Titles::NINTENDO_CHANNEL_NTSC_J,
|
|
Titles::NINTENDO_CHANNEL_PAL,
|
|
Titles::FORECAST_CHANNEL_NTSC_U,
|
|
Titles::FORECAST_CHANNEL_NTSC_J,
|
|
Titles::FORECAST_CHANNEL_PAL,
|
|
Titles::NEWS_CHANNEL_NTSC_U,
|
|
Titles::NEWS_CHANNEL_NTSC_J,
|
|
Titles::NEWS_CHANNEL_PAL,
|
|
Titles::EVERYBODY_VOTES_CHANNEL_NTSC_U,
|
|
Titles::EVERYBODY_VOTES_CHANNEL_NTSC_J,
|
|
Titles::EVERYBODY_VOTES_CHANNEL_PAL,
|
|
Titles::REGION_SELECT_CHANNEL_NTSC_U,
|
|
Titles::REGION_SELECT_CHANNEL_NTSC_J,
|
|
Titles::REGION_SELECT_CHANNEL_PAL,
|
|
};
|
|
|
|
static std::vector<NetworkPatch> s_patches;
|
|
|
|
static bool DeserializeLine(const std::string& line, NetworkPatch* patch)
|
|
{
|
|
const std::vector<std::string> items = SplitString(line, ':');
|
|
|
|
if (items.size() != 3)
|
|
return false;
|
|
|
|
patch->source = items[0];
|
|
patch->replacement = items[1];
|
|
|
|
if (!TryParse(items[2], &patch->is_kd))
|
|
return false;
|
|
|
|
return patch;
|
|
}
|
|
|
|
static void LoadPatchSection(const Common::IniFile& ini)
|
|
{
|
|
std::vector<std::string> lines;
|
|
NetworkPatch patch;
|
|
ini.GetLines("WC24Patch", &lines);
|
|
|
|
for (const std::string& line : lines)
|
|
{
|
|
if (line.empty())
|
|
continue;
|
|
|
|
if (line[0] == '$')
|
|
{
|
|
patch.name = line.substr(1, line.size() - 1);
|
|
}
|
|
else
|
|
{
|
|
if (DeserializeLine(line, &patch))
|
|
{
|
|
s_patches.push_back(patch);
|
|
}
|
|
}
|
|
}
|
|
|
|
ReadEnabledAndDisabled(ini, "WC24Patch", &s_patches);
|
|
}
|
|
|
|
static bool IsWC24Channel()
|
|
{
|
|
const auto& sconfig = SConfig::GetInstance();
|
|
const auto found =
|
|
std::find(s_wc24_channels.begin(), s_wc24_channels.end(), sconfig.GetTitleID());
|
|
|
|
return found != s_wc24_channels.end();
|
|
}
|
|
|
|
static void LoadPatches()
|
|
{
|
|
const auto& sconfig = SConfig::GetInstance();
|
|
// We can only load WC24 Channels.
|
|
if (!IsWC24Channel())
|
|
return;
|
|
|
|
Common::IniFile ini;
|
|
// If WiiLink is enabled then we load the Default Ini as that has the WiiLink URLs.
|
|
if (Config::Get(Config::MAIN_WII_WIILINK_ENABLE))
|
|
ini = sconfig.LoadDefaultGameIni();
|
|
else
|
|
ini = sconfig.LoadLocalGameIni();
|
|
|
|
LoadPatchSection(ini);
|
|
}
|
|
|
|
void Reload()
|
|
{
|
|
s_patches.clear();
|
|
LoadPatches();
|
|
}
|
|
|
|
std::optional<std::string> GetNetworkPatch(std::string_view source, IsKD is_kd)
|
|
{
|
|
const auto patch =
|
|
std::find_if(s_patches.begin(), s_patches.end(), [&source, &is_kd](const NetworkPatch& p) {
|
|
return p.source == source && p.is_kd == is_kd && p.enabled;
|
|
});
|
|
if (patch == s_patches.end())
|
|
return std::nullopt;
|
|
|
|
return patch->replacement;
|
|
}
|
|
|
|
// When we patch for the Socket, we aren't given the URL. Instead, it is in a Host header
|
|
// in the payload that the socket is going to send. We need to manually find which patch to apply.
|
|
std::optional<std::string> GetNetworkPatchByPayload(std::string_view source)
|
|
{
|
|
size_t pos{};
|
|
while (pos < source.size())
|
|
{
|
|
const size_t end_of_line = source.find("\r\n", pos);
|
|
if (source.substr(pos).starts_with("Host: "))
|
|
{
|
|
const std::string_view domain =
|
|
source.substr(pos + 6, end_of_line == std::string_view::npos ? std::string_view::npos :
|
|
(end_of_line - pos - 6));
|
|
for (const WC24PatchEngine::NetworkPatch& patch : s_patches)
|
|
{
|
|
if (patch.is_kd != WC24PatchEngine::IsKD{true} && domain == patch.source && patch.enabled)
|
|
{
|
|
return fmt::format("{}Host: {}{}", source.substr(0, pos), patch.replacement,
|
|
end_of_line == std::string_view::npos ? "" :
|
|
source.substr(end_of_line));
|
|
}
|
|
}
|
|
|
|
// No matching patch
|
|
return std::nullopt;
|
|
}
|
|
|
|
if (end_of_line == std::string_view::npos)
|
|
break;
|
|
|
|
pos = end_of_line + 2;
|
|
}
|
|
|
|
return std::nullopt;
|
|
}
|
|
} // namespace WC24PatchEngine
|