Add default support for WiiLink + configuration

This commit is contained in:
Sketch 2023-06-07 21:11:05 -04:00
parent 63090d411d
commit f9f8e94e30
20 changed files with 473 additions and 25 deletions

View File

@ -0,0 +1,8 @@
# HAFx01 - Forecast Channel
[WC24Patch]
$Main
weather.wapp.wii.com:fore.wiilink24.com:1
[WC24Patch_Enabled]
$Main

View File

@ -1,20 +0,0 @@
# HATE01 - Nintendo Channel
[Core]
# Values set here will override the main Dolphin settings.
[OnLoad]
# Add memory patches to be loaded once on boot here.
[OnFrame]
# Add memory patches to be applied every frame here.
[ActionReplay]
# Add action replay cheats here.
[Video]
[Video_Settings]
[Video_Hacks]
ImmediateXFBEnable = False

View File

@ -0,0 +1,56 @@
# HATE01 - Nintendo Channel (NTSC-U)
[Core]
# Values set here will override the main Dolphin settings.
[OnLoad]
# Add memory patches to be loaded once on boot here.
[OnFrame]
# Add memory patches to be applied every frame here.
[ActionReplay]
# Add action replay cheats here.
[Video]
[Video_Settings]
[Video_Hacks]
ImmediateXFBEnable = False
[Gecko]
$SSL Patch [Palapeli]
2A35AB5C 00003A2F
80010000 0035AA4D
8A00570F 0035AA4C
80010000 0035AACD
8A00380F 0035AACC
80010000 0035AB0D
8A004A0F 0035AB0C
80010000 0035AB5D
8A00390F 0035AB5C
80010000 0035ABF9
8A00170F 0035ABF8
80010000 0035AC15
8A00170F 0035AC14
E2000001 00000000
[Gecko_Enabled]
$SSL Patch
[WC24Patch]
$Main
a248.e.akamai.net:dol.n.wiinoma.com:0
$Suggestions
entup.wapp.wii.com:post.n.wiinoma.com:0
$Info
entuc.wapp.wii.com:conf.n.wiinoma.com:0
$WC24
entu.wapp.wii.com:ncc.wiilink24.com:1
[WC24Patch_Enabled]
$Main
$Suggestions
$Info
$WC24

View File

@ -0,0 +1,54 @@
# HATJ01 - Nintendo Channel (NTSC-J)
[Core]
# Values set here will override the main Dolphin settings.
[OnLoad]
# Add memory patches to be loaded once on boot here.
[OnFrame]
# Add memory patches to be applied every frame here.
[ActionReplay]
# Add action replay cheats here.
[Video]
[Video_Settings]
[Video_Hacks]
ImmediateXFBEnable = False
[Gecko]
$SSL Patch [Palapeli]
2A390014 00003A2F
80010000 00390015
8A00570F 00390014
80010000 00390095
8A00380F 00390094
80010000 003900D5
8A00390F 003900D4
80010000 00390171
8A00170F 00390170
80010000 0039018D
8A00170F 0039018C
E2000001 00000000
[Gecko_Enabled]
$SSL Patch
[WC24Patch]
$Main
a248.e.akamai.net:dol.n.wiinoma.com:0
$Suggestions
entjp.wapp.wii.com:post.n.wiinoma.com:0
$Info
entjc.wapp.wii.com:conf.n.wiinoma.com:0
$WC24
entj.wapp.wii.com:ncc.wiilink24.com:1
[WC24Patch_Enabled]
$Main
$Suggestions
$Info
$WC24

View File

@ -0,0 +1,56 @@
# HATP01 - Nintendo Channel (PAL)
[Core]
# Values set here will override the main Dolphin settings.
[OnLoad]
# Add memory patches to be loaded once on boot here.
[OnFrame]
# Add memory patches to be applied every frame here.
[ActionReplay]
# Add action replay cheats here.
[Video]
[Video_Settings]
[Video_Hacks]
ImmediateXFBEnable = False
[Gecko]
$SSL Patch [Palapeli]
2A357D3C 00003A2F
80010000 00357D3D
8A00570F 00357D3C
80010000 00357DBD
8A00380F 00357DBC
80010000 00357DFD
8A004B0F 00357DFC
80010000 00357E4D
8A00390F 00357E4C
80010000 00357EE9
8A00170F 00357EE8
80010000 00357F05
8A00170F 00357F04
E2000001 00000000
[Gecko_Enabled]
$SSL Patch
[WC24Patch]
$Main
a248.e.akamai.net:dol.n.wiinoma.com:0
$Suggestions
entep.wapp.wii.com:post.n.wiinoma.com:0
$Info
entec.wapp.wii.com:conf.n.wiinoma.com:0
$WC24
ente.wapp.wii.com:ncc.wiilink24.com:1
[WC24Patch_Enabled]
$Main
$Suggestions
$Info
$WC24

View File

@ -17,6 +17,22 @@
#include "Common/CommonTypes.h"
namespace detail
{
template <typename T>
constexpr bool IsBooleanEnum()
{
if constexpr (std::is_enum_v<T>)
{
return std::is_same_v<std::underlying_type_t<T>, bool>;
}
else
{
return false;
}
}
} // namespace detail
std::string StringFromFormatV(const char* format, va_list args);
std::string StringFromFormat(const char* format, ...)
@ -54,8 +70,10 @@ void TruncateToCString(std::string* s);
bool TryParse(const std::string& str, bool* output);
template <typename T, std::enable_if_t<std::is_integral_v<T> || std::is_enum_v<T>>* = nullptr>
bool TryParse(const std::string& str, T* output, int base = 0)
template <typename T>
requires(std::is_integral_v<T> ||
(std::is_enum_v<T> && !detail::IsBooleanEnum<T>())) bool TryParse(const std::string& str,
T* output, int base = 0)
{
char* end_ptr = nullptr;
@ -92,6 +110,17 @@ bool TryParse(const std::string& str, T* output, int base = 0)
return true;
}
template <typename T>
requires(detail::IsBooleanEnum<T>()) bool TryParse(const std::string& str, T* output)
{
bool value;
if (!TryParse(str, &value))
return false;
*output = static_cast<T>(value);
return true;
}
template <typename T, std::enable_if_t<std::is_floating_point_v<T>>* = nullptr>
bool TryParse(std::string str, T* const output)
{

View File

@ -516,6 +516,8 @@ add_library(core
System.h
TitleDatabase.cpp
TitleDatabase.h
WC24PatchEngine.cpp
WC24PatchEngine.h
WiiRoot.cpp
WiiRoot.h
WiiUtils.cpp

View File

@ -15,6 +15,30 @@ constexpr u64 SHOP = 0x0001000248414241;
constexpr u64 KOREAN_SHOP = 0x000100024841424b;
constexpr u64 FORECAST_CHANNEL_NTSC_U = 0x0001000248414645;
constexpr u64 FORECAST_CHANNEL_NTSC_J = 0x000100024841464a;
constexpr u64 FORECAST_CHANNEL_PAL = 0x0001000248414650;
constexpr u64 NINTENDO_CHANNEL_NTSC_U = 0x0001000148415445;
constexpr u64 NINTENDO_CHANNEL_NTSC_J = 0x000100014841544a;
constexpr u64 NINTENDO_CHANNEL_PAL = 0x0001000148415450;
constexpr u64 NEWS_CHANNEL_NTSC_U = 0x0001000248414745;
constexpr u64 NEWS_CHANNEL_NTSC_J = 0x000100024841474a;
constexpr u64 NEWS_CHANNEL_PAL = 0x0001000248414750;
constexpr u64 EVERYBODY_VOTES_CHANNEL_NTSC_U = 0x0001000148414a45;
constexpr u64 EVERYBODY_VOTES_CHANNEL_NTSC_J = 0x0001000148414a4a;
constexpr u64 EVERYBODY_VOTES_CHANNEL_PAL = 0x0001000148414a50;
constexpr u64 IOS(u32 major_version)
{
return 0x0000000100000000 | major_version;

View File

@ -241,6 +241,7 @@ const Info<bool> MAIN_ALLOW_SD_WRITES{{System::Main, "Core", "WiiSDCardAllowWrit
const Info<bool> MAIN_ENABLE_SAVESTATES{{System::Main, "Core", "EnableSaveStates"}, false};
const Info<bool> MAIN_REAL_WII_REMOTE_REPEAT_REPORTS{
{System::Main, "Core", "RealWiiRemoteRepeatReports"}, true};
const Info<bool> MAIN_WII_WIILINK_ENABLE{{System::Main, "Core", "EnableWiiLink"}, false};
// Empty means use the Dolphin default URL
const Info<std::string> MAIN_WII_NUS_SHOP_URL{{System::Main, "Core", "WiiNusShopUrl"}, ""};

View File

@ -150,6 +150,7 @@ extern const Info<DiscIO::Region> MAIN_FALLBACK_REGION;
extern const Info<bool> MAIN_REAL_WII_REMOTE_REPEAT_REPORTS;
extern const Info<s32> MAIN_OVERRIDE_BOOT_IOS;
extern const Info<std::string> MAIN_WII_NUS_SHOP_URL;
extern const Info<bool> MAIN_WII_WIILINK_ENABLE;
// Main.DSP

View File

@ -52,6 +52,8 @@
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
#include "Core/TitleDatabase.h"
#include "Core/WC24PatchEngine.h"
#include "VideoCommon/HiresTextures.h"
#include "DiscIO/Enums.h"
@ -206,6 +208,7 @@ void SConfig::OnNewTitleLoad(const Core::CPUThreadGuard& guard)
HLE::Reload(system);
PatchEngine::Reload();
HiresTexture::Update();
WC24PatchEngine::Reload();
}
void SConfig::LoadDefaults()

View File

@ -32,6 +32,7 @@
#include "Core/IOS/Network/MACUtils.h"
#include "Core/IOS/Network/Socket.h"
#include "Core/System.h"
#include "Core/WC24PatchEngine.h"
#ifdef _WIN32
#include <iphlpapi.h>
@ -1056,6 +1057,11 @@ IPCReply NetIPTopDevice::HandleGetAddressInfoRequest(const IOCtlVRequest& reques
if (!request.in_vectors.empty() && request.in_vectors[0].size > 0)
{
nodeNameStr = memory.GetString(request.in_vectors[0].address, request.in_vectors[0].size);
if (std::optional<std::string> patch =
WC24PatchEngine::GetNetworkPatch(nodeNameStr, WC24PatchEngine::IsKD{false}))
{
nodeNameStr = patch.value();
}
pNodeName = nodeNameStr.c_str();
}

View File

@ -139,5 +139,4 @@ void NWC24Dl::SetVersion(u32 version)
{
m_data.header.version = Common::swap32(version);
}
} // namespace IOS::HLE::NWC24

View File

@ -24,6 +24,7 @@
#include "Core/IOS/Network/Socket.h"
#include "Core/IOS/Uids.h"
#include "Core/System.h"
#include "Core/WC24PatchEngine.h"
namespace IOS::HLE
{
@ -217,7 +218,23 @@ NWC24::ErrorCode NetKDRequestDevice::KDDownload(const u16 entry_index,
// Content metadata
const std::string content_name = m_dl_list.GetVFFContentName(entry_index, subtask_id);
const std::string url = m_dl_list.GetDownloadURL(entry_index, subtask_id);
std::string url = m_dl_list.GetDownloadURL(entry_index, subtask_id);
// Reroute to custom server if enabled.
const std::vector<std::string> parts = SplitString(url, '/');
if (parts.size() < 3)
{
// Invalid URL
LogError(ErrorType::KD_Download, NWC24::WC24_ERR_SERVER);
return NWC24::WC24_ERR_SERVER;
}
if (std::optional<std::string> patch =
WC24PatchEngine::GetNetworkPatch(parts[2], WC24PatchEngine::IsKD{true}))
{
const size_t index = url.find(parts[2]);
url.replace(index, parts[2].size(), patch.value());
}
INFO_LOG_FMT(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_DOWNLOAD_NOW_EX - NI - URL: {}", url);

View File

@ -27,6 +27,7 @@
#include "Core/IOS/IOS.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
#include "Core/WC24PatchEngine.h"
#ifdef _WIN32
#define ERRORCODE(name) WSA##name
@ -580,7 +581,14 @@ void WiiSocket::Update(bool read, bool write, bool except)
u32 has_destaddr = memory.Read_U32(BufferIn2 + 0x08);
// Not a string, Windows requires a const char* for sendto
const char* data = (const char*)memory.GetPointer(BufferIn);
const char* data = (const char*)memory.GetPointerForRange(BufferIn, BufferInSize);
const std::optional<std::string> patch =
WC24PatchEngine::GetNetworkPatchByPayload(std::string_view{data, BufferInSize});
if (patch)
{
data = patch->c_str();
BufferInSize = static_cast<u32>(patch->size());
}
// Act as non blocking when SO_MSG_NONBLOCK is specified
forceNonBlock = ((flags & SO_MSG_NONBLOCK) == SO_MSG_NONBLOCK);

View File

@ -0,0 +1,161 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
// WC24PatchEngine
// Allows for replacing URLs used in WC24 requests
#include <algorithm>
#include <array>
#include <fmt/format.h>
#include "Common/StringUtil.h"
#include "Core/CheatCodes.h"
#include "Core/CommonTitles.h"
#include "Core/Config/MainSettings.h"
#include "Core/ConfigManager.h"
#include "Core/WC24PatchEngine.h"
namespace WC24PatchEngine
{
static std::array<u64, 12> s_wc24_channels{
// Nintendo Channel
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,
};
static std::vector<NetworkPatch> s_patches;
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;
}
void LoadPatchSection(const Common::IniFile& ini)
{
std::vector<std::string> lines;
NetworkPatch patch;
ini.GetLines("WC24Patch", &lines);
for (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);
}
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);
}
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();
}
void Reload()
{
s_patches.clear();
LoadPatches();
}
std::optional<std::string> GetNetworkPatch(const std::string& source, IsKD is_kd)
{
const auto patch =
std::find_if(s_patches.begin(), s_patches.end(), [&source, &is_kd](NetworkPatch& patch) {
return patch.source == source && patch.is_kd == is_kd && patch.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

View File

@ -0,0 +1,30 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <optional>
#include <string>
#include "Common/IniFile.h"
namespace WC24PatchEngine
{
enum class IsKD : bool;
struct NetworkPatch final
{
std::string name;
std::string source;
std::string replacement;
bool enabled = false;
IsKD is_kd = IsKD{false};
};
void Reload();
bool DeserializeLine(const std::string& line, NetworkPatch* patch);
bool IsWC24Channel();
void LoadPatchSection(const Common::IniFile& ini);
std::optional<std::string> GetNetworkPatch(const std::string& source, IsKD is_kd);
std::optional<std::string> GetNetworkPatchByPayload(std::string_view source);
} // namespace WC24PatchEngine

View File

@ -435,6 +435,7 @@
<ClInclude Include="Core\SysConf.h" />
<ClInclude Include="Core\System.h" />
<ClInclude Include="Core\TitleDatabase.h" />
<ClInclude Include="Core\WC24PatchEngine.h" />
<ClInclude Include="Core\WiiRoot.h" />
<ClInclude Include="Core\WiiUtils.h" />
<ClInclude Include="DiscIO\Blob.h" />
@ -1070,6 +1071,7 @@
<ClCompile Include="Core\TitleDatabase.cpp" />
<ClCompile Include="Core\WiiRoot.cpp" />
<ClCompile Include="Core\WiiUtils.cpp" />
<ClCompile Include="Core\WC24PatchEngine.cpp" />
<ClCompile Include="DiscIO\Blob.cpp" />
<ClCompile Include="DiscIO\CISOBlob.cpp" />
<ClCompile Include="DiscIO\CompressedBlob.cpp" />

View File

@ -121,6 +121,7 @@ void WiiPane::ConnectLayout()
&QCheckBox::setChecked);
connect(&Settings::Instance(), &Settings::USBKeyboardConnectionChanged,
m_connect_keyboard_checkbox, &QCheckBox::setChecked);
connect(m_wiilink_checkbox, &QCheckBox::toggled, this, &WiiPane::OnSaveConfig);
// SD Card Settings
connect(m_sd_card_checkbox, &QCheckBox::toggled, this, &WiiPane::OnSaveConfig);
@ -157,6 +158,7 @@ void WiiPane::CreateMisc()
m_main_layout->addWidget(misc_settings_group);
m_pal60_mode_checkbox = new QCheckBox(tr("Use PAL60 Mode (EuRGB60)"));
m_screensaver_checkbox = new QCheckBox(tr("Enable Screen Saver"));
m_wiilink_checkbox = new QCheckBox(tr("Enable WiiConnect24 via WiiLink"));
m_connect_keyboard_checkbox = new QCheckBox(tr("Connect USB Keyboard"));
m_aspect_ratio_choice_label = new QLabel(tr("Aspect Ratio:"));
@ -187,12 +189,17 @@ void WiiPane::CreateMisc()
m_pal60_mode_checkbox->setToolTip(tr("Sets the Wii display mode to 60Hz (480i) instead of 50Hz "
"(576i) for PAL games.\nMay not work for all games."));
m_screensaver_checkbox->setToolTip(tr("Dims the screen after five minutes of inactivity."));
m_wiilink_checkbox->setToolTip(tr(
"Enables the WiiLink service for WiiConnect24 channels.\nWiiLink is an alternate provider "
"for the discontinued WiiConnect24 Channels such as the Forecast and Nintendo Channels\nRead "
"the Terms of Service at: https://www.wiilink24.com/tos"));
m_system_language_choice->setToolTip(tr("Sets the Wii system language."));
m_connect_keyboard_checkbox->setToolTip(tr("May cause slow down in Wii Menu and some games."));
misc_settings_group_layout->addWidget(m_pal60_mode_checkbox, 0, 0, 1, 1);
misc_settings_group_layout->addWidget(m_connect_keyboard_checkbox, 0, 1, 1, 1);
misc_settings_group_layout->addWidget(m_screensaver_checkbox, 1, 0, 1, 1);
misc_settings_group_layout->addWidget(m_wiilink_checkbox, 1, 1, 1, 1);
misc_settings_group_layout->addWidget(m_aspect_ratio_choice_label, 2, 0, 1, 1);
misc_settings_group_layout->addWidget(m_aspect_ratio_choice, 2, 1, 1, 1);
misc_settings_group_layout->addWidget(m_system_language_choice_label, 3, 0, 1, 1);
@ -386,6 +393,7 @@ void WiiPane::OnEmulationStateChanged(bool running)
m_wiimote_speaker_volume->setEnabled(!running);
m_wiimote_ir_sensitivity->setEnabled(!running);
m_wiimote_ir_sensor_position->setEnabled(!running);
m_wiilink_checkbox->setEnabled(!running);
}
void WiiPane::LoadConfig()
@ -396,6 +404,7 @@ void WiiPane::LoadConfig()
m_aspect_ratio_choice->setCurrentIndex(Config::Get(Config::SYSCONF_WIDESCREEN));
m_system_language_choice->setCurrentIndex(Config::Get(Config::SYSCONF_LANGUAGE));
m_sound_mode_choice->setCurrentIndex(Config::Get(Config::SYSCONF_SOUND_MODE));
m_wiilink_checkbox->setChecked(Config::Get(Config::MAIN_WII_WIILINK_ENABLE));
m_sd_card_checkbox->setChecked(Settings::Instance().IsSDCardInserted());
m_allow_sd_writes_checkbox->setChecked(Config::Get(Config::MAIN_ALLOW_SD_WRITES));
@ -433,6 +442,7 @@ void WiiPane::OnSaveConfig()
Config::SetBase<bool>(Config::SYSCONF_WIDESCREEN, m_aspect_ratio_choice->currentIndex());
Config::SetBase<u32>(Config::SYSCONF_SOUND_MODE, m_sound_mode_choice->currentIndex());
Config::SetBase(Config::SYSCONF_WIIMOTE_MOTOR, m_wiimote_motor->isChecked());
Config::SetBase(Config::MAIN_WII_WIILINK_ENABLE, m_wiilink_checkbox->isChecked());
Settings::Instance().SetSDCardInserted(m_sd_card_checkbox->isChecked());
Config::SetBase(Config::MAIN_ALLOW_SD_WRITES, m_allow_sd_writes_checkbox->isChecked());

View File

@ -51,6 +51,7 @@ private:
QCheckBox* m_screensaver_checkbox;
QCheckBox* m_pal60_mode_checkbox;
QCheckBox* m_connect_keyboard_checkbox;
QCheckBox* m_wiilink_checkbox;
QComboBox* m_system_language_choice;
QLabel* m_system_language_choice_label;
QComboBox* m_aspect_ratio_choice;