diff options
59 files changed, 405 insertions, 249 deletions
diff --git a/CMake/DolphinLibraryTools.cmake b/CMake/DolphinLibraryTools.cmake index bedba9dcbd..99f5f7f8f4 100644 --- a/CMake/DolphinLibraryTools.cmake +++ b/CMake/DolphinLibraryTools.cmake @@ -1,3 +1,6 @@ +include(CheckCXXSourceCompiles) +include(CheckCXXSymbolExists) + # like add_library(new ALIAS old) but avoids add_library cannot create ALIAS target "new" because target "old" is imported but not globally visible. on older cmake # This can be replaced with a direct alias call once our minimum is cmake 3.18 function(dolphin_alias_library new old) @@ -138,3 +141,31 @@ function(dolphin_find_optional_system_library_pkgconfig library search alias bun dolphin_add_bundled_library(${library} ${use_system} ${bundled_path}) endif() endfunction() + +function(dolphin_check_toolset_version LABEL VERSION_VAR MIN_VERSION) + if(NOT DEFINED ${VERSION_VAR}) + return() + endif() + message(STATUS "Using ${LABEL} ${${VERSION_VAR}}") + if(${VERSION_VAR} VERSION_LESS ${MIN_VERSION}) + message(FATAL_ERROR "Requires ${LABEL} ${MIN_VERSION} or higher") + endif() +endfunction() + + +function(dolphin_check_std_version LABEL VERSION_MACRO MIN_VERSION) + check_cxx_symbol_exists(${VERSION_MACRO} version IS_${LABEL}) + if(NOT IS_${LABEL}) + return() + endif() + check_cxx_source_compiles([[ + #include <version> + #if ${VERSION_MACRO} < ${MIN_VERSION} + #error + #endif + int main(){} + ]] HAS_MINIMUM_${LABEL}) + if(NOT HAS_MINIMUM_${LABEL}) + message(FATAL_ERROR "Requires ${LABEL} ${MIN_VERSION} or higher") + endif() +endfunction() diff --git a/CMake/GenerateAchievementHash.cmake b/CMake/GenerateAchievementHash.cmake new file mode 100644 index 0000000000..5f62e43f72 --- /dev/null +++ b/CMake/GenerateAchievementHash.cmake @@ -0,0 +1,5 @@ +# This file exists to be consumed via `add_custom_command` +# so that file changes are picked up without needing a full reconfigure + +file(SHA1 ${JSON_FILE} ACHIEVEMENT_APPROVED_LIST_HASH) +configure_file(${TEMPLATE_FILE} ${OUTPUT_FILE} @ONLY) diff --git a/CMakeLists.txt b/CMakeLists.txt index f54df6b927..2622a18d7c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,10 @@ cmake_policy(SET CMP0080 OLD) # allow using BundleUtilities at configure time # This is inserted into the Info.plist as well. set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0.0" CACHE STRING "") +# When we don't set a sysroot, AppleClang will put /usr/local/include at a higher +# priority than -isystem paths, which can cause weird include issues in Externals +set(CMAKE_OSX_SYSROOT macosx CACHE STRING "") + set(CMAKE_USER_MAKE_RULES_OVERRIDE "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FlagsOverride.cmake") # CMake 3.28 and later scan c++ source files for module imports by default. Since we don't use @@ -19,6 +23,18 @@ set(CMAKE_CXX_SCAN_FOR_MODULES OFF) project(dolphin-emu) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMake) + +# Support functions +include(CheckAndAddFlag) +include(CheckCCompilerFlag) +include(CheckSymbolExists) +include(DolphinCompileDefinitions) +include(DolphinDisableWarningsMSVC) +include(DolphinLibraryTools) +include(GNUInstallDirs) +include(RemoveCompileFlag) + # When using the Visual Studio generator, only show our targets and not the ones from Externals. set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT dolphin-emu) @@ -33,26 +49,36 @@ if (COMPILER STREQUAL "GNU") set(COMPILER "GCC") # prefer printing GCC instead of GNU endif() -# Enforce minimum compiler versions that support the c++23 features we use -set (GCC_min_version 12) -set (Clang_min_version 15) -set (AppleClang_min_version 14.0.3) -set (min_xcode_version "14.3") # corresponding xcode version for AppleClang_min_version -set (MSVC_min_version 19.32) -set (min_vs_version "2022 17.2.3") # corresponding Visual Studio version for MSVC_min_version +# Minimum required versions +# Toolsets +set(Xcode_min_version 14.3) +set(MSVC_toolset_min_version 143) +# Compilers +set(GCC_min_version 12) +set(Clang_min_version 15) +set(AppleClang_min_version 14.0.3) +set(MSVC_min_version 19.32) +# Standard libraries +set(libstdc++_min_version 12) # This should match GCC_min_version's major version. +set(libc++_min_version 150000) # This should match Clang_min_version in the format "xxyyzz" instead of "xx.yy.zz" + +dolphin_check_toolset_version("Xcode" XCODE_VERSION ${Xcode_min_version}) +dolphin_check_toolset_version("MSVC Toolset" MSVC_TOOLSET_VERSION ${MSVC_toolset_min_version}) message(STATUS "Using ${COMPILER} ${CMAKE_CXX_COMPILER_VERSION}") -if ("-" STREQUAL "${${COMPILER}_min_version}-") +if(NOT DEFINED ${COMPILER}_min_version) message(WARNING "Unknown compiler ${COMPILER}, assuming it is new enough") -else() - if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${${COMPILER}_min_version}) - message(FATAL_ERROR "Requires GCC ${GCC_min_version}, Clang ${Clang_min_version}," - " AppleClang ${AppleClang_min_version} (Xcode ${min_xcode_version})," - " or MSVC ${MSVC_min_version} (Visual Studio ${min_vs_version}) or higher") - endif() +elseif(CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${${COMPILER}_min_version}) + message(FATAL_ERROR "Requires ${COMPILER} ${${COMPILER}_min_version} or higher") endif() +# libstdc++ is almost always used on Linux, even when using clang as the compiler. +# libc++ is used on the likes of Android, Apple devices, FreeBSD, and a few (very) rare Linux distros like Chimera Linux. +# Windows uses its own standard library named STL, which we check as part of the toolset above. (outside of MinGW which can use either libstdc++ or libc++) +dolphin_check_std_version("GNU_libstdc++" _GLIBCXX_RELEASE ${libstdc++_min_version}) +dolphin_check_std_version("LLVM_libc++" _LIBCPP_VERSION ${libc++_min_version}) + # Name of the Dolphin distributor. If you redistribute Dolphin builds (forks, # unofficial builds) please consider identifying your distribution with a # unique name here. @@ -142,20 +168,6 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux") endif() endif() -list(APPEND CMAKE_MODULE_PATH - ${CMAKE_CURRENT_SOURCE_DIR}/CMake -) - -# Support functions -include(CheckAndAddFlag) -include(CheckCCompilerFlag) -include(CheckSymbolExists) -include(DolphinCompileDefinitions) -include(DolphinDisableWarningsMSVC) -include(DolphinLibraryTools) -include(GNUInstallDirs) -include(RemoveCompileFlag) - # Enable folders for IDE set_property(GLOBAL PROPERTY USE_FOLDERS ON) @@ -689,6 +701,7 @@ endif() if(ENABLE_SDL) dolphin_find_optional_system_library(SDL3 Externals/SDL 3.2.0) + add_definitions(-DHAVE_SDL3) endif() dolphin_find_optional_system_library(SFML Externals/SFML 3.0 COMPONENTS Network System) diff --git a/Data/Sys/GameSettings/GOWE69.ini b/Data/Sys/GameSettings/GOWE69.ini index dcebb5a8aa..2a612a2184 100644 --- a/Data/Sys/GameSettings/GOWE69.ini +++ b/Data/Sys/GameSettings/GOWE69.ini @@ -1,6 +1,5 @@ # GOWE69 - Need for Speed: Most Wanted [Gecko] -$Unlock Black Edition [Xanvier] -C241EECC 00000001 -00000001 00000000 +$Unlock Black Edition [Ralf] +0441EECC 00000001 diff --git a/Data/Sys/GameSettings/GW5E69.ini b/Data/Sys/GameSettings/GW5E69.ini index 156e63381b..080e5b1fc8 100644 --- a/Data/Sys/GameSettings/GW5E69.ini +++ b/Data/Sys/GameSettings/GW5E69.ini @@ -1,6 +1,5 @@ # GW5E69 - Need for Speed: Carbon -[ActionReplay] -$Unlock Collector's Edition -0AB3E002 18000000 +[Gecko] +$Unlock Collector's Edition [Ralf] 045075B8 00000001 diff --git a/Externals/SDL/SDL b/Externals/SDL/SDL -Subproject d9d5536704d585616d4db3c8ba3c4ff6fc2757e +Subproject f87239e71e42da91ca317a12eefb82cfbf3393e diff --git a/Flatpak/org.DolphinEmu.dolphin-emu.yml b/Flatpak/org.DolphinEmu.dolphin-emu.yml index 93435438f2..72e80b4267 100644 --- a/Flatpak/org.DolphinEmu.dolphin-emu.yml +++ b/Flatpak/org.DolphinEmu.dolphin-emu.yml @@ -31,8 +31,8 @@ modules: - -Ddocumentation=disabled sources: - type: archive - url: https://www.freedesktop.org/software/libevdev/libevdev-1.13.3.tar.xz - sha256: abf1aace86208eebdd5d3550ffded4c8d73bb405b796d51c389c9d0604cbcfbf + url: https://www.freedesktop.org/software/libevdev/libevdev-1.13.6.tar.xz + sha256: 73f215eccbd8233f414737ac06bca2687e67c44b97d2d7576091aa9718551110 x-checker-data: type: anitya project-id: 20540 @@ -53,6 +53,8 @@ modules: - -DENABLE_SDL=ON - -DENABLE_EVDEV=ON - -DDISTRIBUTOR=dolphin-emu.org + # Use the vendored-in SDL since the one from the SDK usually lags far behind + - -DUSE_SYSTEM_SDL3=OFF cleanup: - /share/man post-install: diff --git a/Source/Android/jni/NetPlay/NetPlayUICallbacks.cpp b/Source/Android/jni/NetPlay/NetPlayUICallbacks.cpp index 4b61495f7f..3a72e5a1fd 100644 --- a/Source/Android/jni/NetPlay/NetPlayUICallbacks.cpp +++ b/Source/Android/jni/NetPlay/NetPlayUICallbacks.cpp @@ -3,6 +3,8 @@ #include <android/log.h> +#include <fmt/format.h> + #include "Common/TraversalClient.h" #include "Core/Boot/Boot.h" #include "Core/Core.h" @@ -34,7 +36,7 @@ std::string InetAddressToString(const Common::TraversalInetAddress& addr) } } - return ip + ":" + std::to_string(ntohs(addr.port)); + return fmt::format("{}:{}", ip, ntohs(addr.port)); } const char* FailureReasonToString(Common::TraversalClient::FailureReason reason) diff --git a/Source/Core/AudioCommon/WASAPIStream.cpp b/Source/Core/AudioCommon/WASAPIStream.cpp index 174ffbc9cb..9571b175bc 100644 --- a/Source/Core/AudioCommon/WASAPIStream.cpp +++ b/Source/Core/AudioCommon/WASAPIStream.cpp @@ -15,6 +15,8 @@ #include <thread> +#include <fmt/format.h> + #include "Common/Assert.h" #include "Common/HRWrap.h" #include "Common/Logging/Log.h" @@ -110,7 +112,7 @@ static void ForEachNamedDevice(const std::function<bool(ComPtr<IMMDevice>, std:: { ComPtr<IMMDevice> device; devices->Item(i, &device); - if (!HandleWinAPI("Failed to get device " + std::to_string(i), result)) + if (!HandleWinAPI(fmt::format("Failed to get device {}", i), result)) continue; ComPtr<IPropertyStore> device_properties; diff --git a/Source/Core/Common/CWDemangler.cpp b/Source/Core/Common/CWDemangler.cpp index 8b4d700c2a..fd9503a111 100644 --- a/Source/Core/Common/CWDemangler.cpp +++ b/Source/Core/Common/CWDemangler.cpp @@ -111,7 +111,7 @@ static std::optional<std::size_t> find_split(std::string_view s, bool special, return std::nullopt; } -ParseQualifiersResult parse_qualifiers(std::string_view str) +static ParseQualifiersResult parse_qualifiers(std::string_view str) { std::string pre; std::string post; @@ -171,7 +171,7 @@ ParseQualifiersResult parse_qualifiers(std::string_view str) return {pre, post, str}; } -std::optional<ParseDigitsResult> parse_digits(std::string_view str) +static std::optional<ParseDigitsResult> parse_digits(std::string_view str) { if (str.empty()) return std::nullopt; diff --git a/Source/Core/Common/Crypto/SHA1.cpp b/Source/Core/Common/Crypto/SHA1.cpp index 44d5f9c3dd..bca90ec079 100644 --- a/Source/Core/Common/Crypto/SHA1.cpp +++ b/Source/Core/Common/Crypto/SHA1.cpp @@ -394,8 +394,4 @@ std::string DigestToString(const Digest& digest) return fmt::format("{:02X}", fmt::join(digest, "")); } -std::string DigestToSource(const Digest& digest) -{ - return fmt::format("{{0x{:02X}}}", fmt::join(digest, ", 0x")); -} } // namespace Common::SHA1 diff --git a/Source/Core/Common/Crypto/SHA1.h b/Source/Core/Common/Crypto/SHA1.h index feb92f31fd..cbd287edd5 100644 --- a/Source/Core/Common/Crypto/SHA1.h +++ b/Source/Core/Common/Crypto/SHA1.h @@ -58,5 +58,30 @@ inline Digest CalculateDigest(const std::array<T, Size>& msg) } std::string DigestToString(const Digest& digest); -std::string DigestToSource(const Digest& digest); + +constexpr Digest StringToDigest(std::string_view str) +{ + Digest digest{}; + ASSERT(str.size() == digest.size() * 2); + + for (size_t i = 0; i < str.size(); ++i) + { + const char c = str[i]; + u8 quartet; + if (c >= '0' && c <= '9') + quartet = c - '0'; + else if (c >= 'A' && c <= 'F') + quartet = c - 'A' + 10; + else if (c >= 'a' && c <= 'f') + quartet = c - 'a' + 10; + else + ASSERT(false); + + if (i % 2 == 0) + digest[i / 2] = quartet << 4; + else + digest[i / 2] |= quartet; + } + return digest; +} } // namespace Common::SHA1 diff --git a/Source/Core/Common/Hash.cpp b/Source/Core/Common/Hash.cpp index a3984745f5..3756bdcad4 100644 --- a/Source/Core/Common/Hash.cpp +++ b/Source/Core/Common/Hash.cpp @@ -427,7 +427,7 @@ u64 GetHash64(const u8* src, u32 len, u32 samples) u32 StartCRC32() { - return crc32_z(0L, Z_NULL, 0); + return crc32_z(0L, nullptr, 0); } u32 UpdateCRC32(u32 crc, const u8* data, size_t len) diff --git a/Source/Core/Common/MemArenaUnix.cpp b/Source/Core/Common/MemArenaUnix.cpp index fd4af4e74b..26a123c081 100644 --- a/Source/Core/Common/MemArenaUnix.cpp +++ b/Source/Core/Common/MemArenaUnix.cpp @@ -149,8 +149,8 @@ void* LazyMemoryRegion::Create(size_t size) if (size == 0) return nullptr; - void* memory = - mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); + void* memory = mmap(nullptr, size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); if (memory == MAP_FAILED) { NOTICE_LOG_FMT(MEMMAP, "Memory allocation of {} bytes failed.", size); diff --git a/Source/Core/Common/TimeUtil.cpp b/Source/Core/Common/TimeUtil.cpp index e57078b7e9..fa47e23503 100644 --- a/Source/Core/Common/TimeUtil.cpp +++ b/Source/Core/Common/TimeUtil.cpp @@ -17,7 +17,7 @@ std::optional<std::tm> LocalTime(std::time_t time) #ifdef _MSC_VER if (localtime_s(&local_time, &time) != 0) #else - if (localtime_r(&time, &local_time) == NULL) + if (localtime_r(&time, &local_time) == nullptr) #endif { ERROR_LOG_FMT(COMMON, "Failed to convert time to local time: {}", std::strerror(errno)); diff --git a/Source/Core/Core/ARDecrypt.cpp b/Source/Core/Core/ARDecrypt.cpp index b94b36de5a..64b66528f0 100644 --- a/Source/Core/Core/ARDecrypt.cpp +++ b/Source/Core/Core/ARDecrypt.cpp @@ -152,8 +152,8 @@ constexpr Seeds genseeds = [] { for (size_t i = 0; i < array0.size(); ++i) { - const auto tmp = u8(gentable0[i] - 1); - array0[i] = (u32(0 - (gensubtable[tmp >> 3] & gentable1[tmp & 7])) >> 31); + const auto tmp = static_cast<u8>(gentable0[i] - 1); + array0[i] = (static_cast<u32>(0 - (gensubtable[tmp >> 3] & gentable1[tmp & 7])) >> 31); } for (int i = 0; i < 0x10; ++i) @@ -165,7 +165,7 @@ constexpr Seeds genseeds = [] { for (u32 j = 0; j < 0x38; j++) { - auto tmp = u8(tmp2 + j); + auto tmp = static_cast<u8>(tmp2 + j); if (j > 0x1B) { @@ -347,7 +347,7 @@ static bool GetBitString(u32* ctrl, u32* out, u8 len) static std::optional<GameIDAndRegion> BatchDecrypt(std::span<u32> codes) { - const auto size = u32(codes.size()); + const auto size = static_cast<u32>(codes.size()); assert((size & 1) == 0); assert(size != 0); @@ -383,7 +383,7 @@ static std::optional<GameIDAndRegion> BatchDecrypt(std::span<u32> codes) static u32 GetVal(char chr) { - const auto ret = u32(strchr(filter, Common::ToUpper(chr)) - filter); + const auto ret = static_cast<u32>(strchr(filter, Common::ToUpper(chr)) - filter); switch (ret) { case 32: // 'I' diff --git a/Source/Core/Core/AchievementApprovedHash.h b/Source/Core/Core/AchievementApprovedHash.h deleted file mode 100644 index d7962ebd3c..0000000000 --- a/Source/Core/Core/AchievementApprovedHash.h +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2026 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "Common/Crypto/SHA1.h" - -static constexpr std::string_view ACHIEVEMENT_APPROVED_LIST_FILENAME = "ApprovedInis.json"; -// After building tests, find the new hash with: -// ./Binaries/Tests/tests --gtest_filter=PatchAllowlist.VerifyHashes -static const inline Common::SHA1::Digest ACHIEVEMENT_APPROVED_LIST_HASH = { - 0xE6, 0xCD, 0xD7, 0x85, 0x7A, 0xBA, 0x72, 0xEC, 0x34, 0x11, - 0x2B, 0x16, 0xB1, 0x31, 0xD0, 0x0A, 0x0A, 0xD7, 0xFC, 0xCC}; diff --git a/Source/Core/Core/AchievementApprovedHash.h.in b/Source/Core/Core/AchievementApprovedHash.h.in new file mode 100644 index 0000000000..ed1feaeea3 --- /dev/null +++ b/Source/Core/Core/AchievementApprovedHash.h.in @@ -0,0 +1,10 @@ +// Copyright 2026 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "Common/Crypto/SHA1.h" + +static constexpr std::string_view ACHIEVEMENT_APPROVED_LIST_FILENAME = "ApprovedInis.json"; +static constinit inline Common::SHA1::Digest ACHIEVEMENT_APPROVED_LIST_HASH = + Common::SHA1::StringToDigest("@ACHIEVEMENT_APPROVED_LIST_HASH@"); diff --git a/Source/Core/Core/Boot/DolReader.cpp b/Source/Core/Core/Boot/DolReader.cpp index aa5f3dae0d..b6bf74d808 100644 --- a/Source/Core/Core/Boot/DolReader.cpp +++ b/Source/Core/Core/Boot/DolReader.cpp @@ -55,17 +55,20 @@ bool DolReader::Initialize(std::span<const u8> buffer) { if ((m_dolheader.textAddress[i] & 31) != 0 || (m_dolheader.textSize[i] & 31) != 0) { - ERROR_LOG_FMT(BOOT, + ERROR_LOG_FMT(BOOT, "Text section {} is not 32-byte aligned: address = 0x{:08x}, size = 0x{:x}", i, m_dolheader.textAddress[i], m_dolheader.textSize[i]); return false; } - if (buffer.size() < m_dolheader.textOffset[i] + m_dolheader.textSize[i]) + const std::size_t section_offset = m_dolheader.textOffset[i]; + const std::size_t section_size = m_dolheader.textSize[i]; + + if (buffer.size() < section_offset || (buffer.size() - section_offset) < section_size) return false; - const u8* text_start = &buffer[m_dolheader.textOffset[i]]; - m_text_sections.emplace_back(text_start, &text_start[m_dolheader.textSize[i]]); + const u8* text_start = &buffer[section_offset]; + m_text_sections.emplace_back(text_start, &text_start[section_size]); for (unsigned int j = 0; !m_is_wii && j < (m_dolheader.textSize[i] / sizeof(u32)); ++j) { @@ -86,11 +89,11 @@ bool DolReader::Initialize(std::span<const u8> buffer) { if (m_dolheader.dataSize[i] != 0) { - u32 section_size = m_dolheader.dataSize[i]; - u32 section_offset = m_dolheader.dataOffset[i]; + const std::size_t section_size = m_dolheader.dataSize[i]; + const std::size_t section_offset = m_dolheader.dataOffset[i]; if ((m_dolheader.dataAddress[i] & 31) != 0 || (section_size & 31) != 0) { - ERROR_LOG_FMT(BOOT, + ERROR_LOG_FMT(BOOT, "Data section {} is not 32-byte aligned: address = 0x{:08x}, size = 0x{:x}", i, m_dolheader.dataAddress[i], section_size); return false; @@ -101,8 +104,7 @@ bool DolReader::Initialize(std::span<const u8> buffer) std::vector<u8> data(section_size); const u8* data_start = &buffer[section_offset]; - std::memcpy(&data[0], data_start, - std::min((size_t)section_size, buffer.size() - section_offset)); + std::memcpy(&data[0], data_start, std::min(section_size, buffer.size() - section_offset)); m_data_sections.emplace_back(data); } else diff --git a/Source/Core/Core/Boot/ElfReader.cpp b/Source/Core/Core/Boot/ElfReader.cpp index 8cdc1770a5..1e570c9e9d 100644 --- a/Source/Core/Core/Boot/ElfReader.cpp +++ b/Source/Core/Core/Boot/ElfReader.cpp @@ -195,17 +195,23 @@ bool ElfReader::LoadIntoMemory(Core::System& system, bool only_in_mem1) const { Elf32_Phdr* p = segments + i; - INFO_LOG_FMT(BOOT, "Type: {} Vaddr: {:08x} Filesz: {} Memsz: {}", p->p_type, p->p_vaddr, - p->p_filesz, p->p_memsz); + INFO_LOG_FMT(BOOT, "Type: {} Vaddr: {:08x} Paddr: {:08x} Filesz: {} Memsz: {}", p->p_type, + p->p_vaddr, p->p_paddr, p->p_filesz, p->p_memsz); if (p->p_type == PT_LOAD) { - u32 writeAddr = p->p_vaddr; + // Check LMA (paddr) first - some are nonsense, so fall back to VMA (vaddr) if invalid + u32 writeAddr = p->p_paddr; + if (writeAddr) + writeAddr |= 0x80000000; // map to virtual address + else + writeAddr = p->p_vaddr; // LMA is empty, fall back to VMA + const u8* src = GetSegmentPtr(i); u32 srcSize = p->p_filesz; u32 dstSize = p->p_memsz; - if (only_in_mem1 && p->p_vaddr >= memory.GetRamSizeReal()) + if (only_in_mem1 && writeAddr >= memory.GetRamSizeReal()) continue; memory.CopyToEmu(writeAddr, src, srcSize); diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 996b63e22b..56c8dba3de 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -1,5 +1,4 @@ add_library(core - AchievementApprovedHash.h AchievementManager.cpp AchievementManager.h ActionReplay.cpp @@ -591,6 +590,20 @@ add_library(core WiiUtils.h ) +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/AchievementApprovedHash.h + COMMAND ${CMAKE_COMMAND} + -DJSON_FILE=${CMAKE_SOURCE_DIR}/Data/Sys/ApprovedInis.json + -DTEMPLATE_FILE=${CMAKE_CURRENT_SOURCE_DIR}/AchievementApprovedHash.h.in + -DOUTPUT_FILE=${CMAKE_CURRENT_BINARY_DIR}/AchievementApprovedHash.h + -P ${CMAKE_SOURCE_DIR}/CMake/GenerateAchievementHash.cmake + DEPENDS ${CMAKE_SOURCE_DIR}/Data/Sys/ApprovedInis.json + ${CMAKE_CURRENT_SOURCE_DIR}/AchievementApprovedHash.h.in + COMMENT "Generating AchievementApprovedHash.h" +) + +target_sources(core PRIVATE AchievementApprovedHash.h) + if(_M_X86_64) target_sources(core PRIVATE DSP/Jit/x64/DSPEmitter.cpp diff --git a/Source/Core/Core/FreeLookManager.cpp b/Source/Core/Core/FreeLookManager.cpp index 9dc23e8934..146e71cc1d 100644 --- a/Source/Core/Core/FreeLookManager.cpp +++ b/Source/Core/Core/FreeLookManager.cpp @@ -114,7 +114,7 @@ FreeLookController::FreeLookController(const unsigned int index) : m_index(index std::string FreeLookController::GetName() const { - return std::string("FreeLook") + char('1' + m_index); + return std::string("FreeLook") + static_cast<char>('1' + m_index); } InputConfig* FreeLookController::GetConfig() const diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/AXVoice.h b/Source/Core/Core/HW/DSPHLE/UCodes/AXVoice.h index 54531a85f6..636c22ce65 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/AXVoice.h +++ b/Source/Core/Core/HW/DSPHLE/UCodes/AXVoice.h @@ -59,21 +59,26 @@ PBUpdateData LoadPBUpdates(Memory::MemoryManager& memory, const PB_TYPE& pb) // Apply updates to a PB. void ApplyUpdatesForMs(int curr_ms, PB_TYPE& pb, u16* num_updates, const PBUpdateData& updates) { - auto pb_mem = Common::BitCastToArray<u16>(pb); - u32 start_idx = 0; for (int i = 0; i < curr_ms; ++i) start_idx += num_updates[i]; - for (u32 i = start_idx; i < start_idx + num_updates[curr_ms]; ++i) + if (start_idx < updates.size()) { - u16 update_off = updates[i].pb_offset; - u16 update_val = updates[i].new_value; + const u16 count = num_updates[curr_ms]; + if (count <= updates.size() - start_idx) + { + const u32 end_idx = start_idx + count; + for (u32 i = start_idx; i < end_idx; ++i) + { + const u16 update_off = updates[i].pb_offset; + const u16 update_val = updates[i].new_value; - pb_mem[update_off] = update_val; + if (update_off < (sizeof(pb) / sizeof(u16))) + Common::BitCastPtr<u16>(&pb)[update_off] = update_val; + } + } } - - pb = std::bit_cast<PB_TYPE>(pb_mem); } // Used to pass a large amount of buffers to the mixing function. diff --git a/Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.cpp b/Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.cpp index ccc6e29e16..c7f37ca0b1 100644 --- a/Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.cpp +++ b/Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.cpp @@ -162,8 +162,8 @@ private: u8 m_bits_per_sample = 9; }; -CGBPlayer_mGBA::CGBPlayer_mGBA(Core::System& system, CHSPDevice_GBPlayer* player) - : IGBPlayer(system, player), m_gba_core{m_system, Config::GBPLAYER_GBA_INDEX} +CGBPlayer_mGBA::CGBPlayer_mGBA(Core::System& system, CHSPDevice_GBPlayer* gbplayer) + : IGBPlayer(system, gbplayer), m_gba_core{m_system, Config::GBPLAYER_GBA_INDEX} { auto& core_timing = m_system.GetCoreTiming(); diff --git a/Source/Core/Core/IOS/FS/FileSystemCommon.cpp b/Source/Core/Core/IOS/FS/FileSystemCommon.cpp index aa99f46da3..0e13192c5b 100644 --- a/Source/Core/Core/IOS/FS/FileSystemCommon.cpp +++ b/Source/Core/Core/IOS/FS/FileSystemCommon.cpp @@ -147,7 +147,7 @@ void FileSystem::DoStateRead(PointerWrap& p, const std::string& directory_path) return; } - Metadata metadata; + Metadata metadata{}; p.Do(metadata.uid); p.Do(metadata.gid); p.Do(metadata.attribute); diff --git a/Source/Core/Core/IOS/Network/IP/Top.cpp b/Source/Core/Core/IOS/Network/IP/Top.cpp index 86d206d8e4..e38fd1df01 100644 --- a/Source/Core/Core/IOS/Network/IP/Top.cpp +++ b/Source/Core/Core/IOS/Network/IP/Top.cpp @@ -58,6 +58,12 @@ #include <linux/rtnetlink.h> #endif +auto format_as(addrinfo hints) +{ + return fmt::format("flags={}, family={}, socktype={}, protocol={}, addrlen={}", hints.ai_flags, + hints.ai_family, hints.ai_socktype, hints.ai_protocol, hints.ai_addrlen); +} + namespace IOS::HLE { enum SOResultCode : s32 @@ -66,6 +72,21 @@ enum SOResultCode : s32 SO_ERROR_HOST_NOT_FOUND = -305, }; +namespace +{ +const char* GaiStrError(s32 error) +{ +#ifdef _WIN32 + // gai_strerror isn't thread safe on Windows + return Common::DecodeNetworkError(error); +#else + // Unlike Windows it doesn't return regular error codes + // e.g. EAI_AGAIN vs errno's EAGAIN + return gai_strerror(error); +#endif +} +} // namespace + NetIPTopDevice::NetIPTopDevice(EmulationKernel& ios, const std::string& device_name) : EmulationDevice(ios, device_name) { @@ -1281,10 +1302,10 @@ IPCReply NetIPTopDevice::HandleGetAddressInfoRequest(const IOCtlVRequest& reques addrinfo* result = nullptr; int ret = getaddrinfo(pNodeName, pServiceName, hints_valid ? &hints : nullptr, &result); - u32 addr = request.io_vectors[0].address; - u32 sockoffset = addr + 0x460; if (ret == 0) { + u32 addr = request.io_vectors[0].address; + u32 sockoffset = addr + 0x460; constexpr size_t WII_ADDR_INFO_SIZE = 0x20; for (addrinfo* result_iter = result; result_iter != nullptr; result_iter = result_iter->ai_next) { @@ -1326,6 +1347,15 @@ IPCReply NetIPTopDevice::HandleGetAddressInfoRequest(const IOCtlVRequest& reques } else { + const char* const hostname = pNodeName ? pNodeName : "(null)"; + const char* const service = pServiceName ? pServiceName : "(null)"; + const std::string hints_description{hints_valid ? fmt::format("{}", hints) : "(null)"}; + ERROR_LOG_FMT(IOS_NET, + "getaddrinfo failed with error {}: {}\n" + " - hostname: {}\n" + " - service: {}\n" + " - hints: {}", + ret, GaiStrError(ret), hostname, service, hints_description); ret = SO_ERROR_HOST_NOT_FOUND; } diff --git a/Source/Core/Core/IOS/Network/Socket.h b/Source/Core/Core/IOS/Network/Socket.h index 88a018dc9c..3617e244ce 100644 --- a/Source/Core/Core/IOS/Network/Socket.h +++ b/Source/Core/Core/IOS/Network/Socket.h @@ -17,23 +17,19 @@ typedef pollfd pollfd_t; #elif defined(__linux__) or defined(__APPLE__) or defined(__FreeBSD__) or defined(__NetBSD__) or \ defined(__OpenBSD__) or defined(__HAIKU__) #include <arpa/inet.h> -#include <netdb.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#include <sys/types.h> -#if defined(ANDROID) || defined(__HAIKU__) #include <fcntl.h> -#else -#include <sys/fcntl.h> -#endif #include <net/if.h> +#include <netdb.h> #include <netinet/in.h> #include <poll.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/types.h> typedef struct pollfd pollfd_t; #else +#include <fcntl.h> #include <netinet/in.h> -#include <sys/fcntl.h> #include <sys/socket.h> #include <sys/types.h> #endif diff --git a/Source/Core/Core/IOS/USB/Emulated/LogitechMic.cpp b/Source/Core/Core/IOS/USB/Emulated/LogitechMic.cpp index fccdbd7939..63396632af 100644 --- a/Source/Core/Core/IOS/USB/Emulated/LogitechMic.cpp +++ b/Source/Core/Core/IOS/USB/Emulated/LogitechMic.cpp @@ -6,6 +6,8 @@ #include <algorithm> #include <utility> +#include <fmt/format.h> + #include "Core/Config/MainSettings.h" #include "Core/HW/Memmap.h" #include "Core/System.h" @@ -81,7 +83,7 @@ private: } std::string GetCubebStreamName() const override { - return "Dolphin Emulated Logitech USB Microphone " + std::to_string(m_index); + return fmt::format("Dolphin Emulated Logitech USB Microphone {}", m_index); } s16 GetVolumeModifier() const override { diff --git a/Source/Core/Core/LibusbUtils.cpp b/Source/Core/Core/LibusbUtils.cpp index fdb2ecd209..1c034b44b4 100644 --- a/Source/Core/Core/LibusbUtils.cpp +++ b/Source/Core/Core/LibusbUtils.cpp @@ -168,7 +168,7 @@ std::optional<std::string> GetStringDescriptor(libusb_device_handle* dev_handle, if (lang_id_result != 4 || buffer.length < 4 || buffer.descriptor_type != LIBUSB_DT_STRING) { ERROR_LOG_FMT(IOS_USB, "libusb_get_string_descriptor(desc_index={}, lang_id=0) result:{}", - int(desc_index), lang_id_result); + static_cast<int>(desc_index), lang_id_result); return std::nullopt; } @@ -180,7 +180,7 @@ std::optional<std::string> GetStringDescriptor(libusb_device_handle* dev_handle, if (str_result < 2 || buffer.length > str_result || buffer.descriptor_type != LIBUSB_DT_STRING) { ERROR_LOG_FMT(IOS_USB, "libusb_get_string_descriptor(desc_index={}, lang_id={}) result:{}", - int(desc_index), lang_id, str_result); + static_cast<int>(desc_index), lang_id, str_result); return std::nullopt; } diff --git a/Source/Core/Core/Movie.cpp b/Source/Core/Core/Movie.cpp index c336becd07..047fbfc81a 100644 --- a/Source/Core/Core/Movie.cpp +++ b/Source/Core/Core/Movie.cpp @@ -1226,8 +1226,8 @@ bool MovieManager::PlayWiimote(int wiimote, DesiredWiimoteState* desired_state) if (serialized.length > serialized.data.size()) { - PanicAlertFmtT("Invalid serialized length:{0} in PlayWiimote. byte:{1}", int(serialized.length), - m_current_byte); + PanicAlertFmtT("Invalid serialized length:{0} in PlayWiimote. byte:{1}", + static_cast<int>(serialized.length), m_current_byte); EndPlayInput(!m_read_only); return false; } @@ -1236,7 +1236,7 @@ bool MovieManager::PlayWiimote(int wiimote, DesiredWiimoteState* desired_state) if (m_current_byte + serialized.length > m_temp_input.size()) { PanicAlertFmtT("Premature movie end in PlayWiimote. {0} + {1} > {2}", m_current_byte, - int(serialized.length), m_temp_input.size()); + static_cast<int>(serialized.length), m_temp_input.size()); EndPlayInput(!m_read_only); return false; } diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp index 2cd9ae2801..df54510e53 100644 --- a/Source/Core/Core/NetPlayClient.cpp +++ b/Source/Core/Core/NetPlayClient.cpp @@ -1648,7 +1648,8 @@ void NetPlayClient::ThreadFunc() if (static_cast<int>(netEvent.type) == Common::ENet::SKIPPABLE_EVENT) INFO_LOG_FMT(NETPLAY, "enet_host_service: skippable packet event"); else - ERROR_LOG_FMT(NETPLAY, "enet_host_service: unknown event type: {}", int(netEvent.type)); + ERROR_LOG_FMT(NETPLAY, "enet_host_service: unknown event type: {}", + static_cast<int>(netEvent.type)); break; } } diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index 834544b6b3..20e1096c28 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -326,7 +326,7 @@ void NetPlayServer::ThreadFunc() if (error != ConnectionError::NoError) { - INFO_LOG_FMT(NETPLAY, "Error {} initializing peer {:x}:{}", u8(error), + INFO_LOG_FMT(NETPLAY, "Error {} initializing peer {:x}:{}", static_cast<u8>(error), netEvent.peer->address.host, netEvent.peer->address.port); sf::Packet spac; @@ -391,7 +391,8 @@ void NetPlayServer::ThreadFunc() if (static_cast<int>(netEvent.type) == Common::ENet::SKIPPABLE_EVENT) INFO_LOG_FMT(NETPLAY, "enet_host_service: skippable packet event"); else - ERROR_LOG_FMT(NETPLAY, "enet_host_service: unknown event type: {}", int(netEvent.type)); + ERROR_LOG_FMT(NETPLAY, "enet_host_service: unknown event type: {}", + static_cast<int>(netEvent.type)); break; } } @@ -1157,8 +1158,8 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, Client& player) SyncSaveDataID sub_id; packet >> sub_id; - INFO_LOG_FMT(NETPLAY, "Got client SyncSaveData message: {:x} from client {}", u8(sub_id), - player.pid); + INFO_LOG_FMT(NETPLAY, "Got client SyncSaveData message: {:x} from client {}", + static_cast<u8>(sub_id), player.pid); switch (sub_id) { @@ -1214,8 +1215,8 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, Client& player) SyncCodeID sub_id; packet >> sub_id; - INFO_LOG_FMT(NETPLAY, "Got client SyncCodes message: {:x} from client {}", u8(sub_id), - player.pid); + INFO_LOG_FMT(NETPLAY, "Got client SyncCodes message: {:x} from client {}", + static_cast<u8>(sub_id), player.pid); // Check If Code Sync was successful or not switch (sub_id) diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.h b/Source/Core/Core/PowerPC/JitCommon/JitCache.h index 4b5ac6fd80..8860a42b06 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitCache.h +++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.h @@ -231,7 +231,7 @@ private: // It is used by the assembly dispatcher to quickly // know where to jump based on pc and msr bits. Common::LazyMemoryRegion m_entry_points_arena; - u8** m_entry_points_ptr = 0; + u8** m_entry_points_ptr = nullptr; // An alternative for the above but without a shm segment // in case the shm memory region couldn't be allocated. diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index 765e0d6906..2dcd2cae2b 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -263,15 +263,15 @@ namespace struct SlotWithTimestamp { // 1-based indexing. - int slot; + u32 slot; double timestamp; }; } // namespace // Returns first slot number (1-based indexing) not in the vector. -static std::optional<int> GetEmptySlot(std::span<const SlotWithTimestamp> used_slots) +static std::optional<u32> GetEmptySlot(std::span<const SlotWithTimestamp> used_slots) { - for (int i = 1; i <= int(NUM_STATES); ++i) + for (u32 i = 1; i <= NUM_STATES; ++i) { if (!Common::Contains(used_slots, i, &SlotWithTimestamp::slot)) return i; @@ -303,7 +303,7 @@ static std::string SystemTimeAsDoubleToString(double time) return fmt::format(std::locale{""}, "{:%x %X}", *local_time); } -static std::string MakeStateFilename(int number) +static std::string MakeStateFilename(u32 number) { return fmt::format("{}{}.s{:02d}", File::GetUserPath(D_STATESAVES_IDX), SConfig::GetInstance().GetGameID(), number); @@ -313,7 +313,7 @@ static std::vector<SlotWithTimestamp> GetUsedSlotsWithTimestamp() { std::vector<SlotWithTimestamp> result; StateHeader header; - for (int i = 1; i <= int(NUM_STATES); ++i) + for (u32 i = 1; i <= NUM_STATES; ++i) { std::string filename = MakeStateFilename(i); if (!File::Exists(filename) || !ReadHeader(filename, header)) @@ -337,7 +337,7 @@ static void CompressBufferToFile(std::span<const u8> raw_buffer, File::IOFile& f Common::UniqueBuffer<char> compressed_buffer(LZ4_compressBound(bytes_to_compress)); const int compressed_len = LZ4_compress_default( reinterpret_cast<const char*>(raw_buffer.data()) + total_bytes_compressed, - compressed_buffer.get(), bytes_to_compress, int(compressed_buffer.size())); + compressed_buffer.get(), bytes_to_compress, static_cast<int>(compressed_buffer.size())); if (compressed_len == 0) { @@ -474,7 +474,7 @@ static void SaveAsFromCore(Core::System& system, std::string filename) { // Try with a buffer a bit larger than the previous state. // This will often avoid the "Measure" step. - const auto buffer_size_estimate = std::size_t(s_last_state_size) * 110 / 100; + const auto buffer_size_estimate = static_cast<std::size_t>(s_last_state_size) * 110 / 100; Common::UniqueBuffer<u8> buffer{buffer_size_estimate}; if (const auto actual_size = SaveToBuffer(system, buffer)) @@ -608,7 +608,7 @@ static bool ReadHeader(const std::string& filename, StateHeader& header) return ReadStateHeaderFromFile(header, f, get_version_header); } -std::string GetInfoStringOfSlot(int slot, bool translate) +std::string GetInfoStringOfSlot(u32 slot, bool translate) { std::lock_guard lk{s_state_saves_in_progress}; @@ -623,7 +623,7 @@ std::string GetInfoStringOfSlot(int slot, bool translate) return SystemTimeAsDoubleToString(header.legacy_header.time); } -u64 GetUnixTimeOfSlot(int slot) +u64 GetUnixTimeOfSlot(u32 slot) { std::lock_guard lk{s_state_saves_in_progress}; @@ -902,12 +902,12 @@ void Shutdown() s_flush_unsaved_data_hook.reset(); } -void Save(Core::System& system, int slot) +void Save(Core::System& system, u32 slot) { SaveAs(system, MakeStateFilename(slot)); } -void Load(Core::System& system, int slot) +void Load(Core::System& system, u32 slot) { LoadAs(system, MakeStateFilename(slot)); } @@ -922,7 +922,7 @@ void LoadLastSaved(Core::System& system, int i) s_compress_and_dump_thread.WaitForCompletion(); std::vector<SlotWithTimestamp> used_slots = GetUsedSlotsWithTimestamp(); - if (std::size_t(i) > used_slots.size()) + if (static_cast<std::size_t>(i) > used_slots.size()) { Core::DisplayMessage("State doesn't exist", 2000); return; diff --git a/Source/Core/Core/State.h b/Source/Core/Core/State.h index 1c4eeb0554..cd35ea1af0 100644 --- a/Source/Core/Core/State.h +++ b/Source/Core/Core/State.h @@ -84,16 +84,16 @@ void Shutdown(); // Returns a string containing information of the savestate in the given slot // which can be presented to the user for identification purposes -std::string GetInfoStringOfSlot(int slot, bool translate = true); +std::string GetInfoStringOfSlot(u32 slot, bool translate = true); // Returns when the savestate in the given slot was created, or 0 if the slot is empty. -u64 GetUnixTimeOfSlot(int slot); +u64 GetUnixTimeOfSlot(u32 slot); // These don't happen instantly - they get scheduled as events. // ...But only if we're not in the main CPU thread. // If we're in the main CPU thread then they run immediately instead. -void Save(Core::System& system, int slot); -void Load(Core::System& system, int slot); +void Save(Core::System& system, u32 slot); +void Load(Core::System& system, u32 slot); void SaveAs(Core::System& system, std::string filename); void LoadAs(Core::System& system, std::string filename); diff --git a/Source/Core/Core/WiiUtils.cpp b/Source/Core/Core/WiiUtils.cpp index c22e9c8048..8c462fecf3 100644 --- a/Source/Core/Core/WiiUtils.cpp +++ b/Source/Core/Core/WiiUtils.cpp @@ -329,7 +329,7 @@ std::string SystemUpdater::GetDeviceId() u32 ios_device_id; if (m_ios.GetESCore().GetDeviceId(&ios_device_id) < 0) return ""; - return std::to_string((u64(1) << 32) | ios_device_id); + return std::to_string((1ULL << 32) | ios_device_id); } class OnlineSystemUpdater final : public SystemUpdater diff --git a/Source/Core/DiscIO/DirectoryBlob.cpp b/Source/Core/DiscIO/DirectoryBlob.cpp index d4f9e2bac7..47b9d73e41 100644 --- a/Source/Core/DiscIO/DirectoryBlob.cpp +++ b/Source/Core/DiscIO/DirectoryBlob.cpp @@ -895,8 +895,8 @@ DirectoryBlobPartition::DirectoryBlobPartition( const std::function<void(std::vector<FSTBuilderNode>* fst_nodes, FSTBuilderNode* dol_node)>& fst_callback, DirectoryBlobReader* blob) - : m_wrapped_partition(partition), - m_is_triforce(volume && volume->GetVolumeType() == Platform::Triforce) + : m_is_triforce(volume && volume->GetVolumeType() == Platform::Triforce), + m_wrapped_partition(partition) { std::vector<FSTBuilderNode> sys_nodes; diff --git a/Source/Core/DiscIO/VolumeWii.cpp b/Source/Core/DiscIO/VolumeWii.cpp index 8ee8396d41..40729fb8b5 100644 --- a/Source/Core/DiscIO/VolumeWii.cpp +++ b/Source/Core/DiscIO/VolumeWii.cpp @@ -11,6 +11,7 @@ #include <map> #include <memory> #include <optional> +#include <ranges> #include <string> #include <thread> #include <utility> @@ -249,9 +250,9 @@ bool VolumeWii::HasWiiEncryption() const std::vector<Partition> VolumeWii::GetPartitions() const { - std::vector<Partition> partitions; - for (const auto& pair : m_partitions) - partitions.push_back(pair.first); + std::vector<Partition> partitions(m_partitions.size()); + const auto partitions_view = std::views::keys(m_partitions); + std::ranges::copy(partitions_view, partitions.begin()); return partitions; } diff --git a/Source/Core/DolphinQt/AboutDialog.cpp b/Source/Core/DolphinQt/AboutDialog.cpp index 2736fcf65b..5261decdbd 100644 --- a/Source/Core/DolphinQt/AboutDialog.cpp +++ b/Source/Core/DolphinQt/AboutDialog.cpp @@ -7,6 +7,9 @@ #include <QTextEdit> #include <QVBoxLayout> #include <QtGlobal> +#ifdef HAVE_SDL3 +#include <SDL3/SDL_version.h> +#endif #include "Common/Version.h" @@ -26,6 +29,14 @@ AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent) tr("%1 commit(s) ahead of %2").arg(commits_ahead).arg(QStringLiteral("master"))); } +#ifdef HAVE_SDL3 + const int sdl_version = SDL_GetVersion(); + QString sdl_str = QString::fromStdString("%1.%2.%3") + .arg(SDL_VERSIONNUM_MAJOR(sdl_version)) + .arg(SDL_VERSIONNUM_MINOR(sdl_version)) + .arg(SDL_VERSIONNUM_MICRO(sdl_version)); +#endif + const QString text = QStringLiteral(R"( <p style='font-size:38pt; font-weight:400;'>Dolphin</p> @@ -35,7 +46,8 @@ AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent) <p style='font-size: small;'> %BRANCH%<br> %REVISION%<br><br> -%QT_VERSION% +%QT_VERSION%<br> +%SDL_VERSION% </p> <p> @@ -64,6 +76,11 @@ AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent) tr("Revision: %1").arg(QString::fromUtf8(Common::GetScmRevGitStr().c_str()))) .replace(QStringLiteral("%QT_VERSION%"), tr("Using Qt %1").arg(QStringLiteral(QT_VERSION_STR))) +#ifdef HAVE_SDL3 + .replace(QStringLiteral("%SDL_VERSION%"), tr("Using SDL %1").arg(sdl_str)) +#else + .replace(QStringLiteral("%SDL_VERSION%"), tr("SDL disabled")) +#endif .replace(QStringLiteral("%CHECK_FOR_UPDATES%"), tr("Check for updates")) .replace(QStringLiteral("%ABOUT_DOLPHIN%"), // i18n: The word "free" in the standard phrase "free and open source" diff --git a/Source/Core/DolphinQt/CMakeLists.txt b/Source/Core/DolphinQt/CMakeLists.txt index 2e02eda5c3..1228885c1d 100644 --- a/Source/Core/DolphinQt/CMakeLists.txt +++ b/Source/Core/DolphinQt/CMakeLists.txt @@ -460,6 +460,13 @@ PRIVATE implot ) +if(ENABLE_SDL) + target_link_libraries(dolphin-emu + PRIVATE + SDL3::SDL3 + ) +endif() + if (NEED_QT_GUI_PRIVATE_COMPONENT) target_link_libraries(dolphin-emu PRIVATE @@ -574,6 +581,7 @@ if (WIN32) --no-translations --no-compiler-runtime --no-system-d3d-compiler + --no-system-dxc-compiler --no-opengl-sw "$<TARGET_FILE:dolphin-emu>" ) diff --git a/Source/Core/DolphinQt/Config/ARCodeWidget.cpp b/Source/Core/DolphinQt/Config/ARCodeWidget.cpp index 02c9de4de0..12be8072ac 100644 --- a/Source/Core/DolphinQt/Config/ARCodeWidget.cpp +++ b/Source/Core/DolphinQt/Config/ARCodeWidget.cpp @@ -373,7 +373,7 @@ void ARCodeWidget::OnCodeToggleAllClicked() // file once per code. QSignalBlocker blocker(m_code_list); - for (int i = 0; i < m_ar_codes.size(); ++i) + for (int i = 0; i < static_cast<int>(m_ar_codes.size()); ++i) { m_ar_codes[i].enabled = new_state; m_code_list->item(i)->setCheckState(new_check_state); diff --git a/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp b/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp index ce00e7b53f..8a9da960bf 100644 --- a/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp +++ b/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp @@ -471,7 +471,7 @@ void GeckoCodeWidget::ToggleAllCodes() // file once per code. QSignalBlocker blocker(m_code_list); - for (int i = 0; i < m_gecko_codes.size(); ++i) + for (int i = 0; i < static_cast<int>(m_gecko_codes.size()); ++i) { m_gecko_codes[i].enabled = new_state; m_code_list->item(i)->setCheckState(new_check_state); diff --git a/Source/Core/DolphinQt/Debugger/BreakpointWidget.cpp b/Source/Core/DolphinQt/Debugger/BreakpointWidget.cpp index bdd0cc5d82..198b4db230 100644 --- a/Source/Core/DolphinQt/Debugger/BreakpointWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/BreakpointWidget.cpp @@ -78,7 +78,7 @@ private: opt.decorationSize = QSize(0, 0); // Default draw command for paint. - QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter, 0); + QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter, nullptr); // Draw pixmap at the center of the tablewidget cell QPixmap pix = qvariant_cast<QPixmap>(index.data(Qt::DecorationRole)); diff --git a/Source/Core/DolphinQt/Debugger/RegisterWidget.cpp b/Source/Core/DolphinQt/Debugger/RegisterWidget.cpp index de25c196a3..4f391f4698 100644 --- a/Source/Core/DolphinQt/Debugger/RegisterWidget.cpp +++ b/Source/Core/DolphinQt/Debugger/RegisterWidget.cpp @@ -12,6 +12,8 @@ #include <QTableWidget> #include <QVBoxLayout> +#include <fmt/format.h> + #include "Core/Core.h" #include "Core/Debugger/CodeTrace.h" #include "Core/HW/ProcessorInterface.h" @@ -338,13 +340,13 @@ void RegisterWidget::PopulateTable() { // General purpose registers (int) AddRegister( - i, 0, RegisterType::gpr, "r" + std::to_string(i), + i, 0, RegisterType::gpr, fmt::format("r{}", i), [this, i] { return m_system.GetPPCState().gpr[i]; }, [this, i](u64 value) { m_system.GetPPCState().gpr[i] = value; }); // Floating point registers (double) AddRegister( - i, 2, RegisterType::fpr, "f" + std::to_string(i), + i, 2, RegisterType::fpr, fmt::format("f{}", i), [this, i] { return m_system.GetPPCState().ps[i].PS0AsU64(); }, [this, i](u64 value) { m_system.GetPPCState().ps[i].SetPS0(value); }); @@ -360,7 +362,7 @@ void RegisterWidget::PopulateTable() { // IBAT registers AddRegister( - i, 5, RegisterType::ibat, "IBAT" + std::to_string(i), + i, 5, RegisterType::ibat, fmt::format("IBAT{}", i), [this, i] { const auto& ppc_state = m_system.GetPPCState(); return (static_cast<u64>(ppc_state.spr[SPR_IBAT0U + i * 2]) << 32) + @@ -368,7 +370,7 @@ void RegisterWidget::PopulateTable() }, nullptr); AddRegister( - i + 4, 5, RegisterType::ibat, "IBAT" + std::to_string(4 + i), + i + 4, 5, RegisterType::ibat, fmt::format("IBAT{}", 4 + i), [this, i] { const auto& ppc_state = m_system.GetPPCState(); return (static_cast<u64>(ppc_state.spr[SPR_IBAT4U + i * 2]) << 32) + @@ -378,7 +380,7 @@ void RegisterWidget::PopulateTable() // DBAT registers AddRegister( - i + 8, 5, RegisterType::dbat, "DBAT" + std::to_string(i), + i + 8, 5, RegisterType::dbat, fmt::format("DBAT{}", i), [this, i] { const auto& ppc_state = m_system.GetPPCState(); return (static_cast<u64>(ppc_state.spr[SPR_DBAT0U + i * 2]) << 32) + @@ -386,7 +388,7 @@ void RegisterWidget::PopulateTable() }, nullptr); AddRegister( - i + 12, 5, RegisterType::dbat, "DBAT" + std::to_string(4 + i), + i + 12, 5, RegisterType::dbat, fmt::format("DBAT{}", 4 + i), [this, i] { const auto& ppc_state = m_system.GetPPCState(); return (static_cast<u64>(ppc_state.spr[SPR_DBAT4U + i * 2]) << 32) + @@ -399,7 +401,7 @@ void RegisterWidget::PopulateTable() { // Graphics quantization registers AddRegister( - i + 16, 7, RegisterType::gqr, "GQR" + std::to_string(i), + i + 16, 7, RegisterType::gqr, fmt::format("GQR{}", i), [this, i] { return m_system.GetPPCState().spr[SPR_GQR0 + i]; }, nullptr); } @@ -421,7 +423,7 @@ void RegisterWidget::PopulateTable() { // SR registers AddRegister( - i, 7, RegisterType::sr, "SR" + std::to_string(i), + i, 7, RegisterType::sr, fmt::format("SR{}", i), [this, i] { return m_system.GetPPCState().sr[i]; }, [this, i](u64 value) { m_system.GetPPCState().sr[i] = value; diff --git a/Source/Core/DolphinQt/FIFO/FIFOAnalyzer.cpp b/Source/Core/DolphinQt/FIFO/FIFOAnalyzer.cpp index 3df9dfcbbc..e574c2d6e1 100644 --- a/Source/Core/DolphinQt/FIFO/FIFOAnalyzer.cpp +++ b/Source/Core/DolphinQt/FIFO/FIFOAnalyzer.cpp @@ -155,15 +155,15 @@ void FIFOAnalyzer::UpdateTree() recording_item->addChild(frame_item); - const AnalyzedFrameInfo& frame_info = m_fifo_player.GetAnalyzedFrameInfo(frame); - ASSERT(frame_info.parts.size() != 0); + const auto& [parts, part_type_counts] = m_fifo_player.GetAnalyzedFrameInfo(frame); + ASSERT(parts.size() != 0); Common::EnumMap<u32, FramePartType::EFBCopy> part_counts; u32 part_start = 0; - for (u32 part_nr = 0; part_nr < frame_info.parts.size(); part_nr++) + for (u32 part_nr = 0; part_nr < parts.size(); part_nr++) { - const auto& part = frame_info.parts[part_nr]; + const auto& part = parts[part_nr]; const u32 part_type_nr = part_counts[part.m_type]; part_counts[part.m_type]++; @@ -189,9 +189,9 @@ void FIFOAnalyzer::UpdateTree() } // We shouldn't end on a Command (it should end with an EFB copy) - ASSERT(part_start == frame_info.parts.size()); + ASSERT(part_start == parts.size()); // The counts we computed should match the frame's counts - ASSERT(std::ranges::equal(frame_info.part_type_counts, part_counts)); + ASSERT(std::ranges::equal(part_type_counts, part_counts)); } } @@ -344,18 +344,18 @@ void FIFOAnalyzer::UpdateDetails() const u32 start_part_nr = items[0]->data(0, PART_START_ROLE).toUInt(); const u32 end_part_nr = items[0]->data(0, PART_END_ROLE).toUInt(); - const AnalyzedFrameInfo& frame_info = m_fifo_player.GetAnalyzedFrameInfo(frame_nr); + const auto& [parts, _part_type_counts] = m_fifo_player.GetAnalyzedFrameInfo(frame_nr); const auto& fifo_frame = m_fifo_player.GetFile()->GetFrame(frame_nr); - const u32 object_start = frame_info.parts[start_part_nr].m_start; - const u32 object_end = frame_info.parts[end_part_nr].m_end; + const u32 object_start = parts[start_part_nr].m_start; + const u32 object_end = parts[end_part_nr].m_end; const u32 object_size = object_end - object_start; u32 object_offset = 0; // NOTE: object_info.m_cpmem is the state of cpmem _after_ all of the commands in this object. // However, it doesn't matter that it doesn't match the start, since it will match by the time // primitives are reached. - auto callback = DetailCallback(frame_info.parts[end_part_nr].m_cpmem); + auto callback = DetailCallback(parts[end_part_nr].m_cpmem); while (object_offset < object_size) { @@ -427,11 +427,11 @@ void FIFOAnalyzer::BeginSearch() const u32 start_part_nr = items[0]->data(0, PART_START_ROLE).toUInt(); const u32 end_part_nr = items[0]->data(0, PART_END_ROLE).toUInt(); - const AnalyzedFrameInfo& frame_info = m_fifo_player.GetAnalyzedFrameInfo(frame_nr); + const auto& [parts, _part_type_counts] = m_fifo_player.GetAnalyzedFrameInfo(frame_nr); const FifoFrameInfo& fifo_frame = m_fifo_player.GetFile()->GetFrame(frame_nr); - const u32 object_start = frame_info.parts[start_part_nr].m_start; - const u32 object_end = frame_info.parts[end_part_nr].m_end; + const u32 object_start = parts[start_part_nr].m_start; + const u32 object_end = parts[end_part_nr].m_end; const u32 object_size = object_end - object_start; const u8* const object = &fifo_frame.fifoData[object_start]; @@ -612,7 +612,7 @@ public: text = QObject::tr("Primitive %1").arg(QString::fromStdString(name)); text += QLatin1Char{'\n'}; - const auto& vtx_desc = m_cpmem.vtx_desc; + const auto& [low, high] = m_cpmem.vtx_desc; const auto& vtx_attr = m_cpmem.vtx_attr[vat]; u32 i = 0; @@ -668,22 +668,21 @@ public: ASSERT(i == vertex_num * vertex_size); text += QLatin1Char{'\n'}; - if (vtx_desc.low.PosMatIdx) + if (low.PosMatIdx) process_simple_component(1); - for (auto texmtxidx : vtx_desc.low.TexMatIdx) + for (auto texmtxidx : low.TexMatIdx) { if (texmtxidx) process_simple_component(1); } - process_component(vtx_desc.low.Position, vtx_attr.g0.PosFormat, + process_component(low.Position, vtx_attr.g0.PosFormat, vtx_attr.g0.PosElements == CoordComponentCount::XY ? 2 : 3); - const u32 normal_component_count = - vtx_desc.low.Normal == VertexComponentFormat::Direct ? 3 : 1; + const u32 normal_component_count = low.Normal == VertexComponentFormat::Direct ? 3 : 1; const u32 normal_elements = vtx_attr.g0.NormalElements == NormalComponentCount::NTB ? 3 : 1; - process_component(vtx_desc.low.Normal, vtx_attr.g0.NormalFormat, + process_component(low.Normal, vtx_attr.g0.NormalFormat, normal_component_count * normal_elements, vtx_attr.g0.NormalIndex3 ? normal_elements : 1); - for (u32 c = 0; c < vtx_desc.low.Color.Size(); c++) + for (u32 c = 0; c < low.Color.Size(); c++) { static constexpr Common::EnumMap<u32, ColorFormat::RGBA8888> component_sizes = { 2, // RGB565 @@ -693,7 +692,7 @@ public: 3, // RGBA6666 4, // RGBA8888 }; - switch (vtx_desc.low.Color[c]) + switch (low.Color[c]) { case VertexComponentFormat::Index8: process_simple_component(1); @@ -708,9 +707,9 @@ public: break; } } - for (u32 t = 0; t < vtx_desc.high.TexCoord.Size(); t++) + for (u32 t = 0; t < high.TexCoord.Size(); t++) { - process_component(vtx_desc.high.TexCoord[t], vtx_attr.GetTexFormat(t), + process_component(high.TexCoord[t], vtx_attr.GetTexFormat(t), vtx_attr.GetTexElements(t) == TexComponentCount::ST ? 2 : 1); } } @@ -756,15 +755,15 @@ void FIFOAnalyzer::UpdateDescription() const u32 end_part_nr = items[0]->data(0, PART_END_ROLE).toUInt(); const u32 entry_nr = m_detail_list->currentRow(); - const AnalyzedFrameInfo& frame_info = m_fifo_player.GetAnalyzedFrameInfo(frame_nr); + const auto& [parts, _part_type_counts] = m_fifo_player.GetAnalyzedFrameInfo(frame_nr); const FifoFrameInfo& fifo_frame = m_fifo_player.GetFile()->GetFrame(frame_nr); - const u32 object_start = frame_info.parts[start_part_nr].m_start; - const u32 object_end = frame_info.parts[end_part_nr].m_end; + const u32 object_start = parts[start_part_nr].m_start; + const u32 object_end = parts[end_part_nr].m_end; const u32 object_size = object_end - object_start; const u32 entry_start = m_object_data_offsets[entry_nr]; - auto callback = DescriptionCallback(frame_info.parts[end_part_nr].m_cpmem); + auto callback = DescriptionCallback(parts[end_part_nr].m_cpmem); OpcodeDecoder::RunCommand(&fifo_frame.fifoData[object_start + entry_start], object_size - entry_start, callback); m_entry_detail_browser->setText(callback.text); diff --git a/Source/Core/DolphinQt/HotkeyScheduler.cpp b/Source/Core/DolphinQt/HotkeyScheduler.cpp index 62f89c1d3b..478454ed5a 100644 --- a/Source/Core/DolphinQt/HotkeyScheduler.cpp +++ b/Source/Core/DolphinQt/HotkeyScheduler.cpp @@ -344,7 +344,7 @@ void HotkeyScheduler::Run() OSD::AddMessage(std::string("Volume: ") + (Config::Get(Config::MAIN_AUDIO_MUTED) ? "Muted" : - std::to_string(Config::Get(Config::MAIN_AUDIO_VOLUME)) + "%")); + fmt::format("{}%", Config::Get(Config::MAIN_AUDIO_VOLUME)))); }; // Volume diff --git a/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp b/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp index 48a55dbef8..170208ddad 100644 --- a/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp +++ b/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp @@ -14,6 +14,8 @@ #include <QStyle> #include <QVBoxLayout> +#include <fmt/format.h> + #include "Common/CommonTypes.h" #include "Common/FileUtil.h" #include "Common/MathUtil.h" @@ -395,7 +397,7 @@ void WiiTASInputWindow::LoadExtensionAndMotionPlus() { Common::IniFile ini; ini.Load(File::GetUserPath(D_CONFIG_IDX) + "WiimoteNew.ini"); - const std::string section_name = "Wiimote" + std::to_string(m_num + 1); + const std::string section_name = fmt::format("Wiimote{}", m_num + 1); std::string extension; ini.GetIfExists(section_name, "Extension", &extension); diff --git a/Source/Core/InputCommon/CMakeLists.txt b/Source/Core/InputCommon/CMakeLists.txt index 0e5612f353..5cc6b66ca6 100644 --- a/Source/Core/InputCommon/CMakeLists.txt +++ b/Source/Core/InputCommon/CMakeLists.txt @@ -181,7 +181,6 @@ if(ENABLE_SDL) ControllerInterface/SDL/SDLGamepad.h ) target_link_libraries(inputcommon PRIVATE SDL3::SDL3) - target_compile_definitions(inputcommon PUBLIC HAVE_SDL3=1) endif() if(MSVC) diff --git a/Source/Core/InputCommon/ControllerInterface/CoreDevice.cpp b/Source/Core/InputCommon/ControllerInterface/CoreDevice.cpp index a10edd13c9..9f7e708593 100644 --- a/Source/Core/InputCommon/ControllerInterface/CoreDevice.cpp +++ b/Source/Core/InputCommon/ControllerInterface/CoreDevice.cpp @@ -261,12 +261,7 @@ std::vector<std::shared_ptr<Device>> DeviceContainer::GetAllDevices() const { std::lock_guard lk(m_devices_mutex); - std::vector<std::shared_ptr<Device>> devices; - - for (const auto& d : m_devices) - devices.emplace_back(d); - - return devices; + return m_devices; } std::vector<std::string> DeviceContainer::GetAllDeviceStrings() const diff --git a/Source/Core/InputCommon/ControllerInterface/SDL/SDLGamepad.h b/Source/Core/InputCommon/ControllerInterface/SDL/SDLGamepad.h index 0a431866e7..a997437f61 100644 --- a/Source/Core/InputCommon/ControllerInterface/SDL/SDLGamepad.h +++ b/Source/Core/InputCommon/ControllerInterface/SDL/SDLGamepad.h @@ -7,6 +7,7 @@ #include <SDL3/SDL_gamepad.h> #include <SDL3/SDL_haptic.h> +#include <fmt/format.h> #include "Common/MathUtil.h" @@ -16,17 +17,17 @@ namespace { std::string GetLegacyButtonName(int index) { - return "Button " + std::to_string(index); + return fmt::format("Button {}", index); } std::string GetLegacyAxisName(int index, int range) { - return "Axis " + std::to_string(index) + (range < 0 ? '-' : '+'); + return fmt::format("Axis {}{}", index, range < 0 ? '-' : '+'); } std::string GetLegacyHatName(int index, int direction) { - return "Hat " + std::to_string(index) + ' ' + "NESW"[direction]; + return fmt::format("Hat {} {}", index, "NESW"[direction]); } constexpr int GetDirectionFromHatMask(int mask) diff --git a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp index bb51d0026e..0f6730720f 100644 --- a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp +++ b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp @@ -14,6 +14,8 @@ #include <sys/eventfd.h> #include <unistd.h> +#include <fmt/format.h> + #include "Common/Assert.h" #include "Common/Flag.h" #include "Common/Logging/Log.h" @@ -114,7 +116,7 @@ protected: } } - std::string GetIndexedName() const { return "Button " + std::to_string(m_index); } + std::string GetIndexedName() const { return fmt::format("Button {}", m_index); } const u8 m_index; }; @@ -184,7 +186,7 @@ public: protected: std::string GetIndexedName() const { - return "Axis " + std::to_string(m_index) + (m_range < 0 ? '-' : '+'); + return fmt::format("Axis {}{}", m_index, m_range < 0 ? '-' : '+'); } private: diff --git a/Source/Core/InputCommon/InputProfile.cpp b/Source/Core/InputCommon/InputProfile.cpp index f483e8a9c3..e1db4e8a46 100644 --- a/Source/Core/InputCommon/InputProfile.cpp +++ b/Source/Core/InputCommon/InputProfile.cpp @@ -133,7 +133,7 @@ void ProfileCycler::CycleProfile(CycleDirection cycle_direction, InputConfig* de } else { - Core::DisplayMessage("No controller found for index: " + std::to_string(controller_index), + Core::DisplayMessage(fmt::format("No controller found for index: {}", controller_index), display_message_ms); } } @@ -172,7 +172,7 @@ void ProfileCycler::CycleProfileForGame(CycleDirection cycle_direction, } else { - Core::DisplayMessage("No controller found for index: " + std::to_string(controller_index), + Core::DisplayMessage(fmt::format("No controller found for index: {}", controller_index), display_message_ms); } } diff --git a/Source/Core/UICommon/GameFile.cpp b/Source/Core/UICommon/GameFile.cpp index 818cf2b766..c24bb625f1 100644 --- a/Source/Core/UICommon/GameFile.cpp +++ b/Source/Core/UICommon/GameFile.cpp @@ -622,7 +622,7 @@ std::string GameFile::GetNetPlayName(const Core::TitleDatabase& title_database) if (!GetGameID().empty()) info.push_back(GetGameID()); if (GetRevision() != 0) - info.push_back("Revision " + std::to_string(GetRevision())); + info.push_back(fmt::format("Revision {}", GetRevision())); const std::string name = GetName(title_database); @@ -635,8 +635,7 @@ std::string GameFile::GetNetPlayName(const Core::TitleDatabase& title_database) if (disc_number > 1 && !is_numbered_disc) { - std::string disc_text = "Disc "; - info.push_back(disc_text + std::to_string(disc_number)); + info.push_back(fmt::format("Disc {}", disc_number)); } if (info.empty()) return name; diff --git a/Source/Core/UICommon/NetPlayIndex.cpp b/Source/Core/UICommon/NetPlayIndex.cpp index 1d4b5e0b8a..b6b228b702 100644 --- a/Source/Core/UICommon/NetPlayIndex.cpp +++ b/Source/Core/UICommon/NetPlayIndex.cpp @@ -8,6 +8,7 @@ #include <span> #include <string> +#include <fmt/format.h> #include <picojson.h> #include "Common/Common.h" @@ -128,9 +129,12 @@ void NetPlayIndex::NotificationLoop() { Common::HttpRequest request; auto response = request.Get( - Config::Get(Config::NETPLAY_INDEX_URL) + "/v0/session/active?secret=" + m_secret + - "&player_count=" + std::to_string(m_player_count) + - "&game=" + request.EscapeComponent(m_game) + "&in_game=" + std::to_string(m_in_game), + fmt::format( + "{base}/v0/session/active?secret={secret}&player_count={player_count}&game={game}" + "&in_game={in_game}", + fmt::arg("base", Config::Get(Config::NETPLAY_INDEX_URL)), fmt::arg("secret", m_secret), + fmt::arg("player_count", m_player_count), + fmt::arg("game", request.EscapeComponent(m_game)), fmt::arg("in_game", m_in_game)), {{"X-Is-Dolphin", "1"}}, Common::HttpRequest::AllowedReturnCodes::All); if (!response) @@ -162,16 +166,17 @@ bool NetPlayIndex::Add(const NetPlaySession& session) { Common::HttpRequest request; auto response = request.Get( - Config::Get(Config::NETPLAY_INDEX_URL) + - "/v0/session/add?name=" + request.EscapeComponent(session.name) + - "®ion=" + request.EscapeComponent(session.region) + - "&game=" + request.EscapeComponent(session.game_id) + - "&password=" + std::to_string(session.has_password) + "&method=" + session.method + - "&server_id=" + session.server_id + "&in_game=" + std::to_string(session.in_game) + - "&port=" + std::to_string(session.port) + "&player_count=" + - std::to_string(session.player_count) + "&version=" + Common::GetScmDescStr(), - {{"X-Is-Dolphin", "1"}}, Common::HttpRequest::AllowedReturnCodes::All); - + fmt::format("{base}/v0/session/add?name={name}®ion={region}&game={game}" + "&password={password}&method={method}&server_id={server_id}&in_game={in_game}" + "&port={port}&player_count={player_count}&version={version}", + fmt::arg("base", Config::Get(Config::NETPLAY_INDEX_URL)), + fmt::arg("name", request.EscapeComponent(session.name)), + fmt::arg("region", request.EscapeComponent(session.region)), + fmt::arg("game", request.EscapeComponent(session.game_id)), + fmt::arg("password", session.has_password), fmt::arg("method", session.method), + fmt::arg("server_id", session.server_id), fmt::arg("in_game", session.in_game), + fmt::arg("port", session.port), fmt::arg("player_count", session.player_count), + fmt::arg("version", Common::GetScmDescStr()))); if (!response.has_value()) { m_last_error = "NO_RESPONSE"; diff --git a/Source/Core/UpdaterCommon/UpdaterCommon.cpp b/Source/Core/UpdaterCommon/UpdaterCommon.cpp index 8a400b21d0..f40fb880ca 100644 --- a/Source/Core/UpdaterCommon/UpdaterCommon.cpp +++ b/Source/Core/UpdaterCommon/UpdaterCommon.cpp @@ -10,6 +10,7 @@ #include <OptionParser.h> #include <ed25519.h> +#include <fmt/format.h> #include <mbedtls/base64.h> #include <mbedtls/sha256.h> #include <zlib.h> @@ -225,8 +226,8 @@ static bool DownloadContent(std::span<const TodoList::DownloadOp> to_download, if (File::Exists(temp_path + DIR_SEP + hash_filename)) continue; - UI::SetDescription("Downloading " + download.filename + "... (File " + std::to_string(i + 1) + - " of " + std::to_string(to_download.size()) + ")"); + UI::SetDescription(fmt::format("Downloading {}... (File {} of {})", download.filename, i + 1, + to_download.size())); UI::SetCurrentMarquee(false); // Add slashes where needed. diff --git a/Source/Core/VideoCommon/PerformanceMetrics.cpp b/Source/Core/VideoCommon/PerformanceMetrics.cpp index 98efa64108..7ea96bd183 100644 --- a/Source/Core/VideoCommon/PerformanceMetrics.cpp +++ b/Source/Core/VideoCommon/PerformanceMetrics.cpp @@ -191,7 +191,7 @@ void PerformanceMetrics::DrawImGuiStats(const float backbuffer_scale) if (g_ActiveConfig.bShowGraphs) { // A font size of 13 is small enough to keep the tick numbers from overlapping too much. - ImGui::PushFont(NULL, 13.0f); + ImGui::PushFont(nullptr, 13.0f); ImGui::PushStyleColor(ImGuiCol_ResizeGrip, 0); const auto graph_flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoNav | movable_flag | diff --git a/Source/UnitTests/Common/CWDemanglerTest.cpp b/Source/UnitTests/Common/CWDemanglerTest.cpp index 7320e48472..6bd50caa0a 100644 --- a/Source/UnitTests/Common/CWDemanglerTest.cpp +++ b/Source/UnitTests/Common/CWDemanglerTest.cpp @@ -7,13 +7,13 @@ #include <gtest/gtest.h> #include <optional> #include <string> -#include <tuple> #include "Common/CWDemangler.h" using namespace CWDemangler; -void DoDemangleTemplateArgsTest(std::string mangled, std::string name, std::string template_args) +static void DoDemangleTemplateArgsTest(std::string mangled, std::string name, + std::string template_args) { DemangleOptions options = DemangleOptions(); @@ -28,7 +28,7 @@ void DoDemangleTemplateArgsTest(std::string mangled, std::string name, std::stri } } -void DoDemangleNameTest(std::string mangled, std::string name, std::string full_name) +static void DoDemangleNameTest(std::string mangled, std::string name, std::string full_name) { DemangleOptions options = DemangleOptions(); @@ -44,7 +44,8 @@ void DoDemangleNameTest(std::string mangled, std::string name, std::string full_ } } -void DoDemangleQualifiedNameTest(std::string mangled, std::string base_name, std::string full_name) +static void DoDemangleQualifiedNameTest(std::string mangled, std::string base_name, + std::string full_name) { DemangleOptions options = DemangleOptions(); @@ -60,8 +61,8 @@ void DoDemangleQualifiedNameTest(std::string mangled, std::string base_name, std } } -void DoDemangleArgTest(std::string mangled, std::string type_pre, std::string type_post, - std::string remainder) +static void DoDemangleArgTest(std::string mangled, std::string type_pre, std::string type_post, + std::string remainder) { DemangleOptions options = DemangleOptions(); @@ -77,7 +78,7 @@ void DoDemangleArgTest(std::string mangled, std::string type_pre, std::string ty } } -void DoDemangleFunctionArgsTest(std::string mangled, std::string args, std::string remainder) +static void DoDemangleFunctionArgsTest(std::string mangled, std::string args, std::string remainder) { DemangleOptions options = DemangleOptions(); @@ -92,7 +93,7 @@ void DoDemangleFunctionArgsTest(std::string mangled, std::string args, std::stri } } -void DoDemangleTest(std::string mangled, std::string demangled) +static void DoDemangleTest(std::string mangled, std::string demangled) { DemangleOptions options = DemangleOptions(); @@ -104,8 +105,8 @@ void DoDemangleTest(std::string mangled, std::string demangled) EXPECT_EQ(result, expected); } -void DoDemangleOptionsTest(bool omit_empty_params, bool mw_extensions, std::string mangled, - std::string demangled) +static void DoDemangleOptionsTest(bool omit_empty_params, bool mw_extensions, std::string mangled, + std::string demangled) { DemangleOptions options = DemangleOptions(omit_empty_params, mw_extensions); diff --git a/Source/UnitTests/Core/PatchAllowlistTest.cpp b/Source/UnitTests/Core/PatchAllowlistTest.cpp index b7ac220f61..c689908277 100644 --- a/Source/UnitTests/Core/PatchAllowlistTest.cpp +++ b/Source/UnitTests/Core/PatchAllowlistTest.cpp @@ -131,9 +131,7 @@ TEST(PatchAllowlist, VerifyHashes) if (digest != ACHIEVEMENT_APPROVED_LIST_HASH) { ADD_FAILURE() << "Approved list hash does not match the one in AchievementApprovedHash.h." - << std::endl - << "Please update ACHIEVEMENT_APPROVED_LIST_HASH to the following:" << std::endl - << Common::SHA1::DigestToSource(digest); + << std::endl; } // Compare with old allowlist std::string old_allowlist; diff --git a/Tools/find-includes-cycles.py b/Tools/find-includes-cycles.py index c4139cd7a0..00f10daed4 100755 --- a/Tools/find-includes-cycles.py +++ b/Tools/find-includes-cycles.py @@ -1,26 +1,20 @@ -#! /usr/bin/env python +#! /usr/bin/env python3 ''' Run this script from Source/Core/ to find all the #include cycles. ''' -import subprocess +from typing import Iterator +from pathlib import Path -def get_local_includes_for(path): - lines = open(path).read().split('\n') - includes = [l.strip() for l in lines if l.strip().startswith('#include')] - return [i.split()[1][1:-1] for i in includes if '"' in i.split()[1]] +def get_local_includes_for(path: Path) -> Iterator[str]: + with path.open() as file: + for line in file: + line = line.strip() + if line.startswith("#include") and '"' in line: + yield line.split()[1].strip(' "') -def find_all_files(): - '''Could probably use os.walk, but meh.''' - f = subprocess.check_output(['find', '.', '-name', '*.h'], - universal_newlines=True).strip().split('\n') - return [p[2:] for p in f] - -def make_include_graph(): - return { f: get_local_includes_for(f) for f in find_all_files() } - -def strongly_connected_components(graph): +def strongly_connected_components(graph: dict[str, list[str]]) -> list[tuple[str, ...]]: """ Tarjan's Algorithm (named for its discoverer, Robert Tarjan) is a graph theory algorithm for finding the strongly connected components of a graph. @@ -34,7 +28,7 @@ def strongly_connected_components(graph): index = {} result = [] - def strongconnect(node): + def strongconnect(node: str) -> None: # set the depth index for this node to the smallest unused index index[node] = index_counter[0] lowlinks[node] = index_counter[0] @@ -74,7 +68,12 @@ def strongly_connected_components(graph): return result if __name__ == '__main__': - comp = strongly_connected_components(make_include_graph()) - for c in comp: - if len(c) != 1: - print(c) + paths = Path(".").glob("**/*.h") + graph = { + path.as_posix(): list(get_local_includes_for(path)) + for path in paths + } + components = strongly_connected_components(graph) + for component in components: + if len(component) != 1: + print(component) |
