summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMake/DolphinLibraryTools.cmake31
-rw-r--r--CMake/GenerateAchievementHash.cmake5
-rw-r--r--CMakeLists.txt69
-rw-r--r--Data/Sys/GameSettings/GOWE69.ini5
-rw-r--r--Data/Sys/GameSettings/GW5E69.ini5
m---------Externals/SDL/SDL0
-rw-r--r--Flatpak/org.DolphinEmu.dolphin-emu.yml6
-rw-r--r--Source/Android/jni/NetPlay/NetPlayUICallbacks.cpp4
-rw-r--r--Source/Core/AudioCommon/WASAPIStream.cpp4
-rw-r--r--Source/Core/Common/CWDemangler.cpp4
-rw-r--r--Source/Core/Common/Crypto/SHA1.cpp4
-rw-r--r--Source/Core/Common/Crypto/SHA1.h27
-rw-r--r--Source/Core/Common/Hash.cpp2
-rw-r--r--Source/Core/Common/MemArenaUnix.cpp4
-rw-r--r--Source/Core/Common/TimeUtil.cpp2
-rw-r--r--Source/Core/Core/ARDecrypt.cpp10
-rw-r--r--Source/Core/Core/AchievementApprovedHash.h13
-rw-r--r--Source/Core/Core/AchievementApprovedHash.h.in10
-rw-r--r--Source/Core/Core/Boot/DolReader.cpp20
-rw-r--r--Source/Core/Core/Boot/ElfReader.cpp14
-rw-r--r--Source/Core/Core/CMakeLists.txt15
-rw-r--r--Source/Core/Core/FreeLookManager.cpp2
-rw-r--r--Source/Core/Core/HW/DSPHLE/UCodes/AXVoice.h21
-rw-r--r--Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.cpp4
-rw-r--r--Source/Core/Core/IOS/FS/FileSystemCommon.cpp2
-rw-r--r--Source/Core/Core/IOS/Network/IP/Top.cpp34
-rw-r--r--Source/Core/Core/IOS/Network/Socket.h14
-rw-r--r--Source/Core/Core/IOS/USB/Emulated/LogitechMic.cpp4
-rw-r--r--Source/Core/Core/LibusbUtils.cpp4
-rw-r--r--Source/Core/Core/Movie.cpp6
-rw-r--r--Source/Core/Core/NetPlayClient.cpp3
-rw-r--r--Source/Core/Core/NetPlayServer.cpp13
-rw-r--r--Source/Core/Core/PowerPC/JitCommon/JitCache.h2
-rw-r--r--Source/Core/Core/State.cpp24
-rw-r--r--Source/Core/Core/State.h8
-rw-r--r--Source/Core/Core/WiiUtils.cpp2
-rw-r--r--Source/Core/DiscIO/DirectoryBlob.cpp4
-rw-r--r--Source/Core/DiscIO/VolumeWii.cpp7
-rw-r--r--Source/Core/DolphinQt/AboutDialog.cpp19
-rw-r--r--Source/Core/DolphinQt/CMakeLists.txt8
-rw-r--r--Source/Core/DolphinQt/Config/ARCodeWidget.cpp2
-rw-r--r--Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp2
-rw-r--r--Source/Core/DolphinQt/Debugger/BreakpointWidget.cpp2
-rw-r--r--Source/Core/DolphinQt/Debugger/RegisterWidget.cpp18
-rw-r--r--Source/Core/DolphinQt/FIFO/FIFOAnalyzer.cpp55
-rw-r--r--Source/Core/DolphinQt/HotkeyScheduler.cpp2
-rw-r--r--Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp4
-rw-r--r--Source/Core/InputCommon/CMakeLists.txt1
-rw-r--r--Source/Core/InputCommon/ControllerInterface/CoreDevice.cpp7
-rw-r--r--Source/Core/InputCommon/ControllerInterface/SDL/SDLGamepad.h7
-rw-r--r--Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp6
-rw-r--r--Source/Core/InputCommon/InputProfile.cpp4
-rw-r--r--Source/Core/UICommon/GameFile.cpp5
-rw-r--r--Source/Core/UICommon/NetPlayIndex.cpp31
-rw-r--r--Source/Core/UpdaterCommon/UpdaterCommon.cpp5
-rw-r--r--Source/Core/VideoCommon/PerformanceMetrics.cpp2
-rw-r--r--Source/UnitTests/Common/CWDemanglerTest.cpp21
-rw-r--r--Source/UnitTests/Core/PatchAllowlistTest.cpp4
-rwxr-xr-xTools/find-includes-cycles.py41
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) +
- "&region=" + 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}&region={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)