This commit is contained in:
Nayla Hanegan 2023-06-30 19:21:07 -04:00
commit 69ef86856d
No known key found for this signature in database
GPG key ID: 3075216CED0DB01D
100 changed files with 40756 additions and 25691 deletions

View file

@ -1,7 +1,7 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'org.jetbrains.kotlin.plugin.serialization' version "1.7.20"
id 'org.jetbrains.kotlin.plugin.serialization' version "1.8.21"
}
task copyProfile (type: Copy) {
@ -22,12 +22,12 @@ android {
// Flag to enable support for the new language APIs
coreLibraryDesugaringEnabled true
sourceCompatibility = "11"
targetCompatibility = "11"
sourceCompatibility = "17"
targetCompatibility = "17"
}
kotlinOptions {
jvmTarget = '11'
jvmTarget = '17'
}
lint {
@ -135,26 +135,26 @@ android {
}
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.2'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.core:core-ktx:1.10.1'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.exifinterface:exifinterface:1.3.6'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.6.0'
implementation 'androidx.fragment:fragment:1.5.5'
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.6.1'
implementation 'androidx.fragment:fragment:1.6.0'
implementation 'androidx.slidingpanelayout:slidingpanelayout:1.2.0'
implementation 'com.google.android.material:material:1.8.0'
implementation 'androidx.core:core-splashscreen:1.0.0'
implementation 'com.google.android.material:material:1.9.0'
implementation 'androidx.core:core-splashscreen:1.0.1'
implementation 'androidx.preference:preference:1.2.0'
implementation 'androidx.profileinstaller:profileinstaller:1.2.2'
implementation 'androidx.profileinstaller:profileinstaller:1.3.1'
// Kotlin extensions for lifecycle components
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.0'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.1'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.1'
// Android TV UI libraries.
implementation 'androidx.leanback:leanback:1.0.0'
@ -167,7 +167,7 @@ dependencies {
implementation 'io.coil-kt:coil:2.2.2'
// For loading custom GPU drivers
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.3"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1"
implementation 'com.nononsenseapps:filepicker:4.2.1'
}

View file

@ -41,3 +41,14 @@
# If there is no `java.lang.ClassValue` (for example, in Android), then R8/ProGuard will print a warning.
# However, since in this case they will not be used, we can disable these warnings
-dontwarn kotlinx.serialization.internal.ClassValueReferences
# Required for R8 full mode
-dontwarn org.bouncycastle.jsse.BCSSLParameters
-dontwarn org.bouncycastle.jsse.BCSSLSocket
-dontwarn org.bouncycastle.jsse.provider.BouncyCastleJsseProvider
-dontwarn org.conscrypt.Conscrypt$Version
-dontwarn org.conscrypt.Conscrypt
-dontwarn org.conscrypt.ConscryptHostnameVerifier
-dontwarn org.openjsse.javax.net.ssl.SSLParameters
-dontwarn org.openjsse.javax.net.ssl.SSLSocket
-dontwarn org.openjsse.net.ssl.OpenJSSE

View file

@ -234,9 +234,14 @@ class EmulationActivity : AppCompatActivity(), ThemeProvider {
menuToastShown = true
}
title = NativeLibrary.GetCurrentTitleDescription()
try {
title = NativeLibrary.GetCurrentTitleDescription()
emulationFragment?.refreshInputOverlay()
emulationFragment?.refreshInputOverlay()
} catch (_: IllegalStateException) {
// Most likely the core delivered an onTitleChanged while emulation was shutting down.
// Let's just ignore it, since we're about to shut down anyway.
}
}
override fun onDestroy() {

View file

@ -65,7 +65,12 @@ class SettingsFragmentPresenter(
controllerNumber = menuTag.subType
} else if (menuTag.isSerialPort1Menu) {
serialPort1Type = extras.getInt(ARG_SERIALPORT1_TYPE)
} else if (menuTag == MenuTag.GRAPHICS) {
} else if (
menuTag == MenuTag.GRAPHICS
&& this.gameId.isNullOrEmpty()
&& !NativeLibrary.IsRunning()
&& GpuDriverHelper.supportsCustomDriverLoading()
) {
this.gpuDriver =
GpuDriverHelper.getInstalledDriverMetadata() ?: GpuDriverHelper.getSystemDriverMetadata(
context.applicationContext
@ -1265,7 +1270,11 @@ class SettingsFragmentPresenter(
)
)
if (GpuDriverHelper.supportsCustomDriverLoading() && this.gpuDriver != null) {
if (
this.gpuDriver != null && this.gameId.isNullOrEmpty()
&& !NativeLibrary.IsRunning()
&& GpuDriverHelper.supportsCustomDriverLoading()
) {
sl.add(
SubmenuSetting(
context,

View file

@ -1,6 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '7.4.2' apply false
id 'com.android.library' version '7.4.2' apply false
id 'org.jetbrains.kotlin.android' version '1.8.10' apply false
id 'com.android.application' version '8.0.2' apply false
id 'com.android.library' version '8.0.2' apply false
id 'org.jetbrains.kotlin.android' version '1.8.21' apply false
}

View file

@ -14,3 +14,6 @@ android.enableJetifier=true
android.useAndroidX=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
android.defaults.buildfeatures.buildconfig=true
android.nonTransitiveRClass=false
android.nonFinalResIds=false

View file

@ -83,7 +83,7 @@ PUBLIC
common
PRIVATE
cubeb
cubeb::cubeb
SoundTouch
FreeSurround)

View file

@ -7,12 +7,6 @@
namespace Common
{
template <typename T>
constexpr T AlignUp(T value, size_t size)
{
static_assert(std::is_unsigned<T>(), "T must be an unsigned value.");
return static_cast<T>(value + (size - value % size) % size);
}
template <typename T>
constexpr T AlignDown(T value, size_t size)
@ -21,4 +15,11 @@ constexpr T AlignDown(T value, size_t size)
return static_cast<T>(value - value % size);
}
template <typename T>
constexpr T AlignUp(T value, size_t size)
{
static_assert(std::is_unsigned<T>(), "T must be an unsigned value.");
return AlignDown<T>(static_cast<T>(value + (size - 1)), size);
}
} // namespace Common

View file

@ -135,6 +135,8 @@ add_library(common
WorkQueueThread.h
)
add_dependencies(common dolphin_scmrev)
if(NOT MSVC AND _M_ARM_64)
set_source_files_properties(
Crypto/AES.cpp
@ -145,16 +147,17 @@ endif()
target_link_libraries(common
PUBLIC
${CMAKE_THREAD_LIBS_INIT}
enet
enet::enet
fmt::fmt
${MBEDTLS_LIBRARIES}
minizip-ng
MbedTLS::mbedtls
minizip::minizip
sfml-network
PRIVATE
${CURL_LIBRARIES}
CURL::libcurl
FatFs
Iconv::Iconv
${spng_target}
spng::spng
${VTUNE_LIBRARIES}
)

View file

@ -90,7 +90,8 @@ bool IsTitlePath(const std::string& path, std::optional<FromWhichRoot> from, u64
}
u32 title_id_high, title_id_low;
if (!AsciiToHex(components[0], title_id_high) || !AsciiToHex(components[1], title_id_low))
if (Common::FromChars(components[0], title_id_high, 16).ec != std::errc{} ||
Common::FromChars(components[1], title_id_low, 16).ec != std::errc{})
{
return false;
}
@ -155,8 +156,11 @@ std::string UnescapeFileName(const std::string& filename)
{
u32 character;
if (pos + 6 <= result.size() && result[pos + 4] == '_' && result[pos + 5] == '_')
if (AsciiToHex(result.substr(pos + 2, 2), character))
if (Common::FromChars(std::string_view{result}.substr(pos + 2, 2), character, 16).ec ==
std::errc{})
{
result.replace(pos, 6, {static_cast<char>(character)});
}
++pos;
}

View file

@ -85,25 +85,6 @@ std::string HexDump(const u8* data, size_t size)
return out;
}
// faster than sscanf
bool AsciiToHex(const std::string& _szValue, u32& result)
{
// Set errno to a good state.
errno = 0;
char* endptr = nullptr;
const u32 value = strtoul(_szValue.c_str(), &endptr, 16);
if (!endptr || *endptr)
return false;
if (errno == ERANGE)
return false;
result = value;
return true;
}
bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args)
{
int writtenCount;

View file

@ -3,6 +3,7 @@
#pragma once
#include <charconv>
#include <cstdarg>
#include <cstddef>
#include <cstdlib>
@ -17,6 +18,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 +71,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 +111,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)
{
@ -147,8 +177,24 @@ std::string ValueToString(T value)
// Generates an hexdump-like representation of a binary data blob.
std::string HexDump(const u8* data, size_t size);
// TODO: kill this
bool AsciiToHex(const std::string& _szValue, u32& result);
namespace Common
{
template <typename T, typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
std::from_chars_result FromChars(std::string_view sv, T& value, int base = 10)
{
const char* const first = sv.data();
const char* const last = first + sv.size();
return std::from_chars(first, last, value, base);
}
template <typename T, typename std::enable_if_t<std::is_floating_point_v<T>>* = nullptr>
std::from_chars_result FromChars(std::string_view sv, T& value,
std::chars_format fmt = std::chars_format::general)
{
const char* const first = sv.data();
const char* const last = first + sv.size();
return std::from_chars(first, last, value, fmt);
}
}; // namespace Common
std::string TabsToSpaces(int tab_size, std::string str);

View file

@ -520,6 +520,8 @@ add_library(core
System.h
TitleDatabase.cpp
TitleDatabase.h
WC24PatchEngine.cpp
WC24PatchEngine.h
WiiRoot.cpp
WiiRoot.h
WiiUtils.cpp
@ -607,24 +609,23 @@ target_link_libraries(core
PUBLIC
audiocommon
common
cubeb
discio
enet
enet::enet
expr
inputcommon
${MBEDTLS_LIBRARIES}
MbedTLS::mbedtls
pugixml
RangeSet::RangeSet
sfml-network
sfml-system
videonull
videoogl
videosoftware
PRIVATE
cubeb::cubeb
FatFs
fmt::fmt
${LZO}
LZO::LZO
ZLIB::ZLIB
)
@ -648,9 +649,8 @@ elseif (ANDROID)
)
endif()
if(LIBUSB_FOUND)
# Using shared LibUSB
target_link_libraries(core PUBLIC ${LIBUSB_LIBRARIES})
if(TARGET LibUSB::LibUSB)
target_link_libraries(core PUBLIC LibUSB::LibUSB)
target_sources(core PRIVATE
IOS/USB/LibusbDevice.cpp
IOS/USB/LibusbDevice.h

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

@ -812,7 +812,7 @@ static bool PauseAndLock(Core::System& system, bool do_lock, bool unpause_on_unl
system.GetExpansionInterface().PauseAndLock(do_lock, false);
// audio has to come after CPU, because CPU thread can wait for audio thread (m_throttle).
system.GetDSP().GetDSPEmulator()->PauseAndLock(do_lock, false);
system.GetDSP().GetDSPEmulator()->PauseAndLock(do_lock);
// video has to come after CPU, because CPU thread can wait for video thread
// (s_efbAccessRequested).

View file

@ -18,7 +18,7 @@ public:
virtual void Shutdown() = 0;
virtual void DoState(PointerWrap& p) = 0;
virtual void PauseAndLock(bool do_lock, bool unpause_on_unlock = true) = 0;
virtual void PauseAndLock(bool do_lock) = 0;
virtual void DSP_WriteMailBoxHigh(bool cpu_mailbox, u16 value) = 0;
virtual void DSP_WriteMailBoxLow(bool cpu_mailbox, u16 value) = 0;

View file

@ -14,6 +14,7 @@
#include "Common/Align.h"
#include "Common/GekkoDisassembler.h"
#include "Common/StringUtil.h"
#include "Core/Config/MainSettings.h"
#include "Core/Core.h"
@ -451,22 +452,23 @@ PPCDebugInterface::GetMemoryAddressFromInstruction(const std::string& instructio
if (!std::regex_search(instruction, match, re))
return std::nullopt;
// Output: match.str(1): negative sign for offset or no match. match.str(2): 0xNNNN, 0, or
// rNN. Check next for 'r' to see if a gpr needs to be loaded. match.str(3): will either be p,
// toc, or NN. Always a gpr.
const std::string offset_match = match.str(2);
const std::string register_match = match.str(3);
// match[1]: negative sign for offset or no match.
// match[2]: 0xNNNN, 0, or rNN. Check next for 'r' to see if a gpr needs to be loaded.
// match[3]: will either be p, toc, or NN. Always a gpr.
const std::string_view offset_match{&*match[2].first, size_t(match[2].length())};
const std::string_view register_match{&*match[3].first, size_t(match[3].length())};
constexpr char is_reg = 'r';
u32 offset = 0;
if (is_reg == offset_match[0])
{
const int register_index = std::stoi(offset_match.substr(1), nullptr, 10);
unsigned register_index;
Common::FromChars(offset_match.substr(1), register_index, 10);
offset = (register_index == 0 ? 0 : m_system.GetPPCState().gpr[register_index]);
}
else
{
offset = static_cast<u32>(std::stoi(offset_match, nullptr, 16));
Common::FromChars(offset_match, offset, 16);
}
// sp and rtoc need to be converted to 1 and 2.
@ -479,11 +481,11 @@ PPCDebugInterface::GetMemoryAddressFromInstruction(const std::string& instructio
else if (is_rtoc == register_match[0])
i = 2;
else
i = std::stoi(register_match, nullptr, 10);
Common::FromChars(register_match, i, 10);
const u32 base_address = m_system.GetPPCState().gpr[i];
if (!match.str(1).empty())
if (std::string_view sign{&*match[1].first, size_t(match[1].length())}; !sign.empty())
return base_address - offset;
return base_address + offset;

View file

@ -240,7 +240,7 @@ u16 DSPHLE::DSP_ReadControlRegister()
return m_dsp_control.Hex;
}
void DSPHLE::PauseAndLock(bool do_lock, bool unpause_on_unlock)
void DSPHLE::PauseAndLock(bool do_lock)
{
}
} // namespace DSP::HLE

View file

@ -26,7 +26,7 @@ public:
void Shutdown() override;
bool IsLLE() const override { return false; }
void DoState(PointerWrap& p) override;
void PauseAndLock(bool do_lock, bool unpause_on_unlock = true) override;
void PauseAndLock(bool do_lock) override;
void DSP_WriteMailBoxHigh(bool cpu_mailbox, u16 value) override;
void DSP_WriteMailBoxLow(bool cpu_mailbox, u16 value) override;

View file

@ -288,7 +288,7 @@ u32 DSPLLE::DSP_UpdateRate()
return 12600; // TO BE TWEAKED
}
void DSPLLE::PauseAndLock(bool do_lock, bool unpause_on_unlock)
void DSPLLE::PauseAndLock(bool do_lock)
{
if (do_lock)
{

View file

@ -26,7 +26,7 @@ public:
void Shutdown() override;
bool IsLLE() const override { return true; }
void DoState(PointerWrap& p) override;
void PauseAndLock(bool do_lock, bool unpause_on_unlock = true) override;
void PauseAndLock(bool do_lock) override;
void DSP_WriteMailBoxHigh(bool cpu_mailbox, u16 value) override;
void DSP_WriteMailBoxLow(bool cpu_mailbox, u16 value) override;

View file

@ -298,8 +298,17 @@ int IOWritePerWriteFile(HANDLE& dev_handle, OVERLAPPED& hid_overlap_write,
// Pending is no error!
break;
default:
WARN_LOG_FMT(WIIMOTE, "IOWrite[WWM_WRITE_FILE]: Error on WriteFile: {}",
Common::HRWrap(error));
if (FAILED(error))
{
WARN_LOG_FMT(WIIMOTE, "IOWrite[WWM_WRITE_FILE]: Error on WriteFile: {}",
Common::HRWrap(error));
}
else
{
WARN_LOG_FMT(WIIMOTE,
"IOWrite[WWM_WRITE_FILE]: Unexpected error code from WriteFile: 0x{:08x}",
error);
}
CancelIo(dev_handle);
return 0;
}

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

@ -470,52 +470,74 @@ static bool isCror(const CodeOp& a)
void PPCAnalyzer::ReorderInstructionsCore(u32 instructions, CodeOp* code, bool reverse,
ReorderType type) const
{
// Bubbling an instruction sometimes reveals another opportunity to bubble an instruction, so do
// multiple passes.
// Instruction Reordering Pass
// Carry pass: bubble carry-using instructions as close to each other as possible, so we can avoid
// storing the carry flag.
// Compare pass: bubble compare instructions next to branches, so they can be merged.
const int start = reverse ? instructions - 1 : 0;
const int end = reverse ? 0 : instructions - 1;
const int increment = reverse ? -1 : 1;
int i = start;
int next = start;
bool go_backwards = false;
while (true)
{
// Instruction Reordering Pass
// Carry pass: bubble carry-using instructions as close to each other as possible, so we can
// avoid
// storing the carry flag.
// Compare pass: bubble compare instructions next to branches, so they can be merged.
bool swapped = false;
int increment = reverse ? -1 : 1;
int start = reverse ? instructions - 1 : 0;
int end = reverse ? 0 : instructions - 1;
for (int i = start; i != end; i += increment)
if (go_backwards)
{
CodeOp& a = code[i];
CodeOp& b = code[i + increment];
// Reorder integer compares, rlwinm., and carry-affecting ops
// (if we add more merged branch instructions, add them here!)
if ((type == ReorderType::CROR && isCror(a)) ||
(type == ReorderType::Carry && isCarryOp(a)) ||
(type == ReorderType::CMP && (isCmp(a) || a.outputCR[0])))
i -= increment;
go_backwards = false;
}
else
{
i = next;
next += increment;
}
if (i == end)
break;
CodeOp& a = code[i];
CodeOp& b = code[i + increment];
// Reorder integer compares, rlwinm., and carry-affecting ops
// (if we add more merged branch instructions, add them here!)
if ((type == ReorderType::CROR && isCror(a)) || (type == ReorderType::Carry && isCarryOp(a)) ||
(type == ReorderType::CMP && (isCmp(a) || a.outputCR[0])))
{
// once we're next to a carry instruction, don't move away!
if (type == ReorderType::Carry && i != start)
{
// once we're next to a carry instruction, don't move away!
if (type == ReorderType::Carry && i != start)
// if we read the CA flag, and the previous instruction sets it, don't move away.
if (!reverse && (a.opinfo->flags & FL_READ_CA) &&
(code[i - increment].opinfo->flags & FL_SET_CA))
{
// if we read the CA flag, and the previous instruction sets it, don't move away.
if (!reverse && (a.opinfo->flags & FL_READ_CA) &&
(code[i - increment].opinfo->flags & FL_SET_CA))
continue;
// if we set the CA flag, and the next instruction reads it, don't move away.
if (reverse && (a.opinfo->flags & FL_SET_CA) &&
(code[i - increment].opinfo->flags & FL_READ_CA))
continue;
continue;
}
if (CanSwapAdjacentOps(a, b))
// if we set the CA flag, and the next instruction reads it, don't move away.
if (reverse && (a.opinfo->flags & FL_SET_CA) &&
(code[i - increment].opinfo->flags & FL_READ_CA))
{
// Alright, let's bubble it!
std::swap(a, b);
swapped = true;
continue;
}
}
if (CanSwapAdjacentOps(a, b))
{
// Alright, let's bubble it!
std::swap(a, b);
if (i != start)
{
// Bubbling an instruction sometimes reveals another opportunity to bubble an instruction,
// so go one step backwards and check if we have such an opportunity.
go_backwards = true;
}
}
}
if (!swapped)
return;
}
}

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

@ -75,7 +75,7 @@ PUBLIC
PRIVATE
fmt::fmt
minizip-ng
minizip::minizip
pugixml
ZLIB::ZLIB
)

View file

@ -436,6 +436,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" />
@ -1071,6 +1072,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

@ -83,7 +83,7 @@ void ColorCorrectionConfigWindow::Create()
gamma_layout->addWidget(new QLabel(tr("Game Gamma")), 0, 0);
gamma_layout->addWidget(m_game_gamma, 0, 1);
m_game_gamma->SetDescription(tr(TR_GAME_GAMMA_DESCRIPTION));
m_game_gamma_value = new QLabel(tr(""));
m_game_gamma_value = new QLabel();
gamma_layout->addWidget(m_game_gamma_value, 0, 2);
m_correct_gamma = new ConfigBool(tr("Correct SDR Gamma"), Config::GFX_CC_CORRECT_GAMMA);
@ -99,7 +99,7 @@ void ColorCorrectionConfigWindow::Create()
Config::GFX_CC_SDR_DISPLAY_CUSTOM_GAMMA, 0.01f);
gamma_layout->addWidget(new QLabel(tr("SDR Display Custom Gamma")), 3, 0);
gamma_layout->addWidget(m_sdr_display_custom_gamma, 3, 1);
m_sdr_display_custom_gamma_value = new QLabel(tr(""));
m_sdr_display_custom_gamma_value = new QLabel();
gamma_layout->addWidget(m_sdr_display_custom_gamma_value, 3, 2);
m_sdr_display_gamma_srgb->setEnabled(m_correct_gamma->isChecked());
@ -122,7 +122,7 @@ void ColorCorrectionConfigWindow::Create()
Config::GFX_CC_HDR_PAPER_WHITE_NITS, 1.f);
hdr_layout->addWidget(new QLabel(tr("HDR Paper White Nits")), 0, 0);
hdr_layout->addWidget(m_hdr_paper_white_nits, 0, 1);
m_hdr_paper_white_nits_value = new QLabel(tr(""));
m_hdr_paper_white_nits_value = new QLabel();
hdr_layout->addWidget(m_hdr_paper_white_nits_value, 0, 2);
m_hdr_paper_white_nits_value->setText(

View file

@ -279,7 +279,7 @@ u32 PostProcessingConfigWindow::ConfigGroup::AddInteger(PostProcessingConfigWind
std::ceil(range / static_cast<double>(m_config_option->m_integer_step_values[i]));
const int current_value = std::round(
(m_config_option->m_integer_values[i] - m_config_option->m_integer_min_values[i]) /
static_cast<double>(m_config_option->m_integer_max_values[i]));
static_cast<double>(m_config_option->m_integer_step_values[i]));
auto* const slider = new QSlider(Qt::Orientation::Horizontal);
slider->setMinimum(0);
@ -289,7 +289,7 @@ u32 PostProcessingConfigWindow::ConfigGroup::AddInteger(PostProcessingConfigWind
QObject::connect(slider, &QSlider::valueChanged,
[this, parent](int value) { parent->UpdateInteger(this, value); });
auto* const value_box = new QLineEdit(QString::number(current_value));
auto* const value_box = new QLineEdit(QString::number(m_config_option->m_integer_values[i]));
value_box->setEnabled(false);
grid->addWidget(slider, row, 1);

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;

View file

@ -259,11 +259,22 @@ QVBoxLayout* SkylanderPortalWindow::CreateFinderLayout()
m_game_filters[i] = checkbox;
search_checkbox_layout->addWidget(checkbox);
}
// i18n: Figures for the game Skylanders: Spyro's Adventure. The game has the same title in all
// countries it was released in, except Japan, where it's named スカイランダーズ スパイロの大冒険.
m_game_filters[GetGameID(IOS::HLE::USB::Game::SpyrosAdv)]->setText(tr("Spyro's Adventure"));
// i18n: Figures for the game Skylanders: Giants. The game has the same title in all countries
// it was released in. It was not released in Japan.
m_game_filters[GetGameID(IOS::HLE::USB::Game::Giants)]->setText(tr("Giants"));
// i18n: Figures for the game Skylanders: Swap Force. The game has the same title in all countries
// it was released in. It was not released in Japan.
m_game_filters[GetGameID(IOS::HLE::USB::Game::SwapForce)]->setText(tr("Swap Force"));
// i18n: Figures for the game Skylanders: Trap Team. The game has the same title in all countries
// it was released in. It was not released in Japan.
m_game_filters[GetGameID(IOS::HLE::USB::Game::TrapTeam)]->setText(tr("Trap Team"));
m_game_filters[GetGameID(IOS::HLE::USB::Game::Superchargers)]->setText(tr("Superchargers"));
// i18n: Figures for the games Skylanders: SuperChargers (not available for the Wii) and
// Skylanders: SuperChargers Racing (available for the Wii). The games have the same titles in
// all countries they were released in. They were not released in Japan.
m_game_filters[GetGameID(IOS::HLE::USB::Game::Superchargers)]->setText(tr("SuperChargers"));
search_checkbox_group->setLayout(search_checkbox_layout);
search_checkbox_scroll_area->setWidget(search_checkbox_group);
search_game_layout->addWidget(search_checkbox_scroll_area);
@ -272,6 +283,9 @@ QVBoxLayout* SkylanderPortalWindow::CreateFinderLayout()
search_filters_layout->addWidget(search_game_group);
// WIDGET: Filter by Element
// i18n: Elements are a trait of Skylanders figures. For official translations of this term,
// check the Skylanders SuperChargers manual at https://support.activision.com/manuals
auto* search_element_group = new QGroupBox(tr("Element"));
auto* search_element_layout = new QVBoxLayout();
auto* search_radio_scroll_area = new QScrollArea();
@ -305,13 +319,30 @@ QVBoxLayout* SkylanderPortalWindow::CreateFinderLayout()
m_element_filter[0]->setText(tr("All"));
m_element_filter[0]->setChecked(true);
// i18n: One of the elements in the Skylanders games. Japanese: まほう. For official translations
// in other languages, check the SuperChargers manual at https://support.activision.com/manuals
m_element_filter[1]->setText(tr("Magic"));
// i18n: One of the elements in the Skylanders games. Japanese: 水. For official translations
// in other languages, check the SuperChargers manual at https://support.activision.com/manuals
m_element_filter[2]->setText(tr("Water"));
// i18n: One of the elements in the Skylanders games. Japanese: マシン. For official translations
// in other languages, check the SuperChargers manual at https://support.activision.com/manuals
m_element_filter[3]->setText(tr("Tech"));
// i18n: One of the elements in the Skylanders games. Japanese: 火. For official translations
// in other languages, check the SuperChargers manual at https://support.activision.com/manuals
m_element_filter[4]->setText(tr("Fire"));
// i18n: One of the elements in the Skylanders games. Japanese: 土. For official translations
// in other languages, check the SuperChargers manual at https://support.activision.com/manuals
m_element_filter[5]->setText(tr("Earth"));
// i18n: One of the elements in the Skylanders games. Japanese: ライフ. For official translations
// in other languages, check the SuperChargers manual at https://support.activision.com/manuals
m_element_filter[6]->setText(tr("Life"));
// i18n: One of the elements in the Skylanders games. Japanese: 風. For official translations
// in other languages, check the SuperChargers manual at https://support.activision.com/manuals
m_element_filter[7]->setText(tr("Air"));
// i18n: One of the elements in the Skylanders games. Japanese: アンデッド. For official
// translations in other languages, check the SuperChargers manual at
// https://support.activision.com/manuals
m_element_filter[8]->setText(tr("Undead"));
m_element_filter[9]->setText(tr("Other"));

View file

@ -81,7 +81,8 @@ PUBLIC
PRIVATE
fmt::fmt
${spng_target}
sfml-network
spng::spng
)
if(WIN32)
@ -146,7 +147,7 @@ elseif(ANDROID)
endif()
if(NOT ANDROID)
target_link_libraries(inputcommon PUBLIC ${LIBUSB_LIBRARIES})
target_link_libraries(inputcommon PUBLIC LibUSB::LibUSB)
endif()
if(LIBEVDEV_FOUND AND LIBUDEV_FOUND)
@ -174,12 +175,13 @@ if(UNIX)
)
endif()
if(SDL2_FOUND)
if(ENABLE_SDL)
target_sources(inputcommon PRIVATE
ControllerInterface/SDL/SDL.cpp
ControllerInterface/SDL/SDL.h
)
target_link_libraries(inputcommon PRIVATE SDL2::SDL2)
target_compile_definitions(inputcommon PUBLIC HAVE_SDL2=1)
endif()
if(MSVC)

View file

@ -29,7 +29,7 @@ target_link_libraries(uicommon
PUBLIC
common
cpp-optparse
minizip-ng
minizip::minizip
pugixml
PRIVATE
@ -48,8 +48,8 @@ if(ENABLE_X11 AND X11_FOUND)
target_link_libraries(uicommon PUBLIC ${XRANDR_LIBRARIES})
endif()
if(LIBUSB_FOUND)
target_link_libraries(uicommon PRIVATE ${LIBUSB_LIBRARIES})
if(TARGET LibUSB::LibUSB)
target_link_libraries(uicommon PRIVATE LibUSB::LibUSB)
endif()
if(ENABLE_LLVM)

View file

@ -6,7 +6,7 @@ add_library(updatercommon
target_link_libraries(updatercommon PRIVATE
uicommon
mbedtls
MbedTLS::mbedtls
ZLIB::ZLIB
ed25519
cpp-optparse

View file

@ -392,14 +392,14 @@ void VKGfx::OnConfigChanged(u32 bits)
g_object_cache->ReloadPipelineCache();
// For vsync, we need to change the present mode, which means recreating the swap chain.
if (m_swap_chain && bits & CONFIG_CHANGE_BIT_VSYNC)
if (m_swap_chain && (bits & CONFIG_CHANGE_BIT_VSYNC))
{
ExecuteCommandBuffer(false, true);
m_swap_chain->SetVSync(g_ActiveConfig.bVSyncActive);
}
// For quad-buffered stereo we need to change the layer count, so recreate the swap chain.
if (m_swap_chain && (bits & CONFIG_CHANGE_BIT_STEREO_MODE) || (bits & CONFIG_CHANGE_BIT_HDR))
if (m_swap_chain && ((bits & CONFIG_CHANGE_BIT_STEREO_MODE) || (bits & CONFIG_CHANGE_BIT_HDR)))
{
ExecuteCommandBuffer(false, true);
m_swap_chain->RecreateSwapChain();

View file

@ -195,7 +195,7 @@ PUBLIC
core
PRIVATE
fmt::fmt
${spng_target}
spng::spng
xxhash
imgui
implot