diff --git a/.ci/build-mac.sh b/.ci/build-mac.sh
index 2f43e05e74..9e16fce4ec 100755
--- a/.ci/build-mac.sh
+++ b/.ci/build-mac.sh
@@ -13,15 +13,16 @@ export HOMEBREW_NO_AUTO_UPDATE=1
export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1
export HOMEBREW_NO_ENV_HINTS=1
export HOMEBREW_NO_INSTALL_CLEANUP=1
+brew update
brew install -f --overwrite --quiet ccache "llvm@$LLVM_COMPILER_VER"
brew link -f --overwrite --quiet "llvm@$LLVM_COMPILER_VER"
if [ "$AARCH64" -eq 1 ]; then
- brew install -f --overwrite --quiet googletest opencv@4 sdl3 vulkan-headers vulkan-loader molten-vk
- brew unlink --quiet ffmpeg fmt qtbase qtsvg qtdeclarative protobuf
+ brew install -f --overwrite --quiet googletest opencv@4 sdl3 vulkan-headers vulkan-loader molten-vk
+ brew unlink --quiet ffmpeg fmt qtbase qtsvg qtdeclarative protobuf || true
else
arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
arch -x86_64 /usr/local/bin/brew install -f --overwrite --quiet python@3.14 opencv@4 "llvm@$LLVM_COMPILER_VER" sdl3 vulkan-headers vulkan-loader molten-vk
- arch -x86_64 /usr/local/bin/brew unlink --quiet ffmpeg qtbase qtsvg qtdeclarative
+ arch -x86_64 /usr/local/bin/brew unlink --quiet ffmpeg qtbase qtsvg qtdeclarative protobuf || true
fi
export CXX=clang++
diff --git a/.ci/deploy-mac.sh b/.ci/deploy-mac.sh
index 70db614b59..819e0725bc 100755
--- a/.ci/deploy-mac.sh
+++ b/.ci/deploy-mac.sh
@@ -21,7 +21,7 @@ rm -rf "rpcs3.app/Contents/Frameworks/QtPdf.framework" \
"rpcs3.app/Contents/Frameworks/QtVirtualKeyboard.framework" \
"rpcs3.app/Contents/Plugins/platforminputcontexts" \
"rpcs3.app/Contents/Plugins/virtualkeyboard" \
-"rpcs3.app/Contents/Resources/git"
+"rpcs3.app/Contents/Resources/git" || true
../../.ci/optimize-mac.sh rpcs3.app
@@ -49,7 +49,7 @@ QT_TRANS="$WORKDIR/qt-downloader/$QT_VER/clang_64/translations"
cp $QT_TRANS/qt_*.qm rpcs3.app/Contents/translations
cp $QT_TRANS/qtbase_*.qm rpcs3.app/Contents/translations
cp $QT_TRANS/qtmultimedia_*.qm rpcs3.app/Contents/translations
-rm -f rpcs3.app/Contents/translations/qt_help_*.qm
+rm -f rpcs3.app/Contents/translations/qt_help_*.qm || true
# Need to do this rename hack due to case insensitive filesystem
mv rpcs3.app RPCS3_.app
diff --git a/.ci/setup-windows.sh b/.ci/setup-windows.sh
index cee6d624de..d8016d8c13 100755
--- a/.ci/setup-windows.sh
+++ b/.ci/setup-windows.sh
@@ -6,7 +6,7 @@
QT_HOST="http://qt.mirror.constant.com/"
QT_URL_VER=$(echo "$QT_VER" | sed "s/\.//g")
QT_VER_MSVC_UP=$(echo "${QT_VER_MSVC}" | tr '[:lower:]' '[:upper:]')
-QT_PREFIX="online/qtsdkrepository/windows_x86/desktop/qt${QT_VER_MAIN}_${QT_URL_VER}/qt${QT_VER_MAIN}_${QT_URL_VER}/qt.qt${QT_VER_MAIN}.${QT_URL_VER}."
+QT_PREFIX="online/qtsdkrepository/windows_x86/desktop/qt${QT_VER_MAIN}_${QT_URL_VER}/qt${QT_VER_MAIN}_${QT_URL_VER}_${QT_VER_MSVC}_64/qt.qt${QT_VER_MAIN}.${QT_URL_VER}."
QT_PREFIX_2="win64_${QT_VER_MSVC}_64/${QT_VER}-0-${QT_DATE}"
QT_SUFFIX="-Windows-Windows_11_24H2-${QT_VER_MSVC_UP}-Windows-Windows_11_24H2-X86_64.7z"
QT_BASE_URL="${QT_HOST}${QT_PREFIX}${QT_PREFIX_2}qtbase${QT_SUFFIX}"
diff --git a/.github/workflows/rpcs3.yml b/.github/workflows/rpcs3.yml
index 2e6434e24b..325b1e01ee 100644
--- a/.github/workflows/rpcs3.yml
+++ b/.github/workflows/rpcs3.yml
@@ -33,23 +33,23 @@ jobs:
matrix:
include:
- os: ubuntu-24.04
- docker_img: "rpcs3/rpcs3-ci-jammy:1.9"
+ docker_img: "rpcs3/rpcs3-ci-jammy:1.10"
build_sh: "/rpcs3/.ci/build-linux.sh"
compiler: clang
UPLOAD_COMMIT_HASH: d812f1254a1157c80fd402f94446310560f54e5f
UPLOAD_REPO_FULL_NAME: "rpcs3/rpcs3-binaries-linux"
- os: ubuntu-24.04
- docker_img: "rpcs3/rpcs3-ci-jammy:1.9"
+ docker_img: "rpcs3/rpcs3-ci-jammy:1.10"
build_sh: "/rpcs3/.ci/build-linux.sh"
compiler: gcc
- os: ubuntu-24.04-arm
- docker_img: "rpcs3/rpcs3-ci-jammy-aarch64:1.9"
+ docker_img: "rpcs3/rpcs3-ci-jammy-aarch64:1.10"
build_sh: "/rpcs3/.ci/build-linux-aarch64.sh"
compiler: clang
UPLOAD_COMMIT_HASH: a1d35836e8d45bfc6f63c26f0a3e5d46ef622fe1
UPLOAD_REPO_FULL_NAME: "rpcs3/rpcs3-binaries-linux-arm64"
- os: ubuntu-24.04-arm
- docker_img: "rpcs3/rpcs3-ci-jammy-aarch64:1.9"
+ docker_img: "rpcs3/rpcs3-ci-jammy-aarch64:1.10"
build_sh: "/rpcs3/.ci/build-linux-aarch64.sh"
compiler: gcc
name: RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }}
@@ -137,7 +137,7 @@ jobs:
runs-on: macos-14
env:
CCACHE_DIR: /tmp/ccache_dir
- QT_VER: '6.10.2'
+ QT_VER: '6.11.0'
QT_VER_MAIN: '6'
LLVM_COMPILER_VER: '21'
RELEASE_MESSAGE: ../GitHubReleaseMessage.txt
@@ -216,9 +216,9 @@ jobs:
env:
COMPILER: msvc
QT_VER_MAIN: '6'
- QT_VER: '6.10.2'
+ QT_VER: '6.11.0'
QT_VER_MSVC: 'msvc2022'
- QT_DATE: '202601261212'
+ QT_DATE: '202603180535'
LLVM_VER: '19.1.7'
VULKAN_VER: '1.3.268.0'
VULKAN_SDK_SHA: '8459ef49bd06b697115ddd3d97c9aec729e849cd775f5be70897718a9b3b9db5'
diff --git a/.gitignore b/.gitignore
index 4688d5fa52..a3911be3a0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -69,6 +69,9 @@ CMakeSettings.json
*PVS-Studio*
PVS/*
+# Zed Editor files
+.zed/*
+
# Ignore other system generated files
x64/*
rpcs3/x64/*
diff --git a/3rdparty/FAudio b/3rdparty/FAudio
index e67d761ead..0372329dbb 160000
--- a/3rdparty/FAudio
+++ b/3rdparty/FAudio
@@ -1 +1 @@
-Subproject commit e67d761ead486de3e69fa11705456bf94df734ca
+Subproject commit 0372329dbb56e7814d0dea7b6eafa7a613bd8042
diff --git a/3rdparty/SoundTouch/soundtouch b/3rdparty/SoundTouch/soundtouch
index 3982730833..a0fba77b6f 160000
--- a/3rdparty/SoundTouch/soundtouch
+++ b/3rdparty/SoundTouch/soundtouch
@@ -1 +1 @@
-Subproject commit 3982730833b6daefe77dcfb32b5c282851640c17
+Subproject commit a0fba77b6f9cfbdb71f8bbec58b6ac4e5e3b1097
diff --git a/3rdparty/curl/CMakeLists.txt b/3rdparty/curl/CMakeLists.txt
index b20763af65..2b725169f9 100644
--- a/3rdparty/curl/CMakeLists.txt
+++ b/3rdparty/curl/CMakeLists.txt
@@ -18,9 +18,6 @@ else()
set(USE_LIBIDN2 OFF CACHE BOOL "Use libidn2 for IDN support") # Disabled because MacOS CI doesn't work otherwise
set(CURL_CA_PATH "none" CACHE STRING "Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
option(CURL_DISABLE_INSTALL "Disable installation targets" ON)
- if(USE_MSVC_STATIC_CRT)
- set(CURL_STATIC_CRT ON CACHE BOOL "Use static crt to build curl")
- endif()
if(WIN32)
set(ENABLE_UNICODE ON CACHE BOOL "enable Unicode")
endif()
diff --git a/3rdparty/curl/curl b/3rdparty/curl/curl
index 400fffa90f..8c908d2d0a 160000
--- a/3rdparty/curl/curl
+++ b/3rdparty/curl/curl
@@ -1 +1 @@
-Subproject commit 400fffa90f30c7a2dc762fa33009d24851bd2016
+Subproject commit 8c908d2d0a6d32abdedda2c52e90bd56ec76c24d
diff --git a/3rdparty/curl/libcurl.vcxproj b/3rdparty/curl/libcurl.vcxproj
index dae28be346..4db28782a3 100644
--- a/3rdparty/curl/libcurl.vcxproj
+++ b/3rdparty/curl/libcurl.vcxproj
@@ -79,12 +79,16 @@
+
+
+
+
@@ -106,6 +110,7 @@
+
@@ -169,14 +174,13 @@
-
+
-
@@ -184,10 +188,8 @@
-
-
@@ -204,6 +206,7 @@
+
@@ -224,13 +227,11 @@
-
-
@@ -272,6 +273,7 @@
+
@@ -280,6 +282,9 @@
+
+
+
@@ -300,9 +305,7 @@
-
-
@@ -312,6 +315,7 @@
+
@@ -352,7 +356,6 @@
-
@@ -367,7 +370,7 @@
-
+
@@ -376,7 +379,6 @@
-
@@ -384,7 +386,6 @@
-
@@ -405,6 +406,7 @@
+
@@ -418,12 +420,10 @@
-
-
diff --git a/3rdparty/curl/libcurl.vcxproj.filters b/3rdparty/curl/libcurl.vcxproj.filters
index 17f760c54b..d38316e767 100644
--- a/3rdparty/curl/libcurl.vcxproj.filters
+++ b/3rdparty/curl/libcurl.vcxproj.filters
@@ -204,9 +204,6 @@
Source Files
-
- Source Files
-
Source Files
@@ -222,9 +219,6 @@
Source Files
-
- Source Files
-
Source Files
@@ -246,18 +240,12 @@
Source Files
-
- Source Files
-
Source Files
Source Files
-
- Source Files
-
Source Files
@@ -318,9 +306,6 @@
Source Files
-
- Source Files
-
Source Files
@@ -333,9 +318,6 @@
Source Files
-
- Source Files
-
Source Files
@@ -549,6 +531,27 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
@@ -653,9 +656,6 @@
Header Files
-
- Header Files
-
Header Files
@@ -758,9 +758,6 @@
Header Files
-
- Header Files
-
Header Files
@@ -791,9 +788,6 @@
Header Files
-
- Header Files
-
Header Files
@@ -812,9 +806,6 @@
Header Files
-
- Header Files
-
Header Files
@@ -836,9 +827,6 @@
Header Files
-
- Header Files
-
Header Files
@@ -887,9 +875,6 @@
Header Files
-
- Header Files
-
Header Files
@@ -899,9 +884,6 @@
Header Files
-
- Header Files
-
Header Files
@@ -1103,9 +1085,6 @@
Header Files
-
- Header Files
-
Header Files
@@ -1121,6 +1100,27 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
diff --git a/3rdparty/libpng/libpng b/3rdparty/libpng/libpng
index c3e304954a..d5515b5b8b 160000
--- a/3rdparty/libpng/libpng
+++ b/3rdparty/libpng/libpng
@@ -1 +1 @@
-Subproject commit c3e304954a9cfd154bc0dfbfea2b01cd61d6546d
+Subproject commit d5515b5b8be3901aac04e5bd8bd5c89f287bcd33
diff --git a/3rdparty/libsdl-org/SDL b/3rdparty/libsdl-org/SDL
index 683181b47c..5848e584a1 160000
--- a/3rdparty/libsdl-org/SDL
+++ b/3rdparty/libsdl-org/SDL
@@ -1 +1 @@
-Subproject commit 683181b47cfabd293e3ea409f838915b8297a4fd
+Subproject commit 5848e584a1b606de26e3dbd1c7e4ecbc34f807a6
diff --git a/3rdparty/protobuf/CMakeLists.txt b/3rdparty/protobuf/CMakeLists.txt
index 6c4b35e99d..9f7ead1347 100644
--- a/3rdparty/protobuf/CMakeLists.txt
+++ b/3rdparty/protobuf/CMakeLists.txt
@@ -20,10 +20,13 @@ else()
option(protobuf_DISABLE_RTTI "Remove runtime type information in the binaries" OFF)
option(protobuf_FORCE_FETCH_DEPENDENCIES "Force all dependencies to be downloaded from GitHub. Local installations will be ignored." OFF)
option(protobuf_LOCAL_DEPENDENCIES_ONLY "Prevent downloading any dependencies from GitHub. If this option is set, the dependency must be available locally as an installed package." OFF)
- if(VCPKG_TOOLCHAIN)
+ option(protobuf_BUILD_SHARED_LIBS "Build Shared Libraries" OFF)
+ option(protobuf_MSVC_STATIC_RUNTIME "Link static runtime libraries" OFF)
+ if(VCPKG_TOOLCHAIN)
set(protobuf_BUILD_SHARED_LIBS ON CACHE BOOL "" FORCE)
message(STATUS "VCPKG detected: Building Protobuf as a shared library")
endif()
+
add_subdirectory(protobuf EXCLUDE_FROM_ALL)
target_include_directories(3rdparty_protobuf SYSTEM INTERFACE protobuf/src)
target_link_libraries(3rdparty_protobuf INTERFACE libprotobuf)
diff --git a/3rdparty/qt6.cmake b/3rdparty/qt6.cmake
index e15e0abdcb..969967fa40 100644
--- a/3rdparty/qt6.cmake
+++ b/3rdparty/qt6.cmake
@@ -6,15 +6,22 @@ find_package(Qt6 ${QT_MIN_VER} CONFIG COMPONENTS Widgets Concurrent Multimedia M
if(WIN32)
target_link_libraries(3rdparty_qt6 INTERFACE Qt6::Widgets Qt6::Concurrent Qt6::Multimedia Qt6::MultimediaWidgets Qt6::Svg Qt6::SvgWidgets)
else()
- set(QT_NO_PRIVATE_MODULE_WARNING ON)
- find_package(Qt6 ${QT_MIN_VER} COMPONENTS DBus Gui GuiPrivate)
+ find_package(Qt6 ${QT_MIN_VER} COMPONENTS DBus Gui)
+ if(Qt6_VERSION VERSION_GREATER_EQUAL "6.10.0")
+ set(QT_NO_PRIVATE_MODULE_WARNING ON)
+ find_package(Qt6 ${QT_MIN_VER} COMPONENTS GuiPrivate)
+ endif()
if(Qt6DBus_FOUND)
target_link_libraries(3rdparty_qt6 INTERFACE Qt6::Widgets Qt6::DBus Qt6::Concurrent Qt6::Multimedia Qt6::MultimediaWidgets Qt6::Svg Qt6::SvgWidgets)
target_compile_definitions(3rdparty_qt6 INTERFACE -DHAVE_QTDBUS)
else()
target_link_libraries(3rdparty_qt6 INTERFACE Qt6::Widgets Qt6::Concurrent Qt6::Multimedia Qt6::MultimediaWidgets Qt6::Svg Qt6::SvgWidgets)
endif()
- target_link_libraries(3rdparty_qt6 INTERFACE Qt6::GuiPrivate)
+ if(Qt6_VERSION VERSION_GREATER_EQUAL "6.10.0")
+ target_link_libraries(3rdparty_qt6 INTERFACE Qt6::GuiPrivate)
+ else()
+ target_include_directories(3rdparty_qt6 INTERFACE ${Qt6Gui_PRIVATE_INCLUDE_DIRS})
+ endif()
endif()
if(Qt6Widgets_FOUND)
diff --git a/3rdparty/wolfssl/wolfssl b/3rdparty/wolfssl/wolfssl
index b077c81eb6..922d04b356 160000
--- a/3rdparty/wolfssl/wolfssl
+++ b/3rdparty/wolfssl/wolfssl
@@ -1 +1 @@
-Subproject commit b077c81eb635392e694ccedbab8b644297ec0285
+Subproject commit 922d04b3568c6428a9fb905ddee3ef5a68db3108
diff --git a/3rdparty/yaml-cpp/yaml-cpp b/3rdparty/yaml-cpp/yaml-cpp
index 05c44fcd18..51a5d623e3 160000
--- a/3rdparty/yaml-cpp/yaml-cpp
+++ b/3rdparty/yaml-cpp/yaml-cpp
@@ -1 +1 @@
-Subproject commit 05c44fcd18074836e21e1eda9fc02b3a4a1529b5
+Subproject commit 51a5d623e3fde1f58829a56ba910f1cb33596222
diff --git a/3rdparty/zlib/CMakeLists.txt b/3rdparty/zlib/CMakeLists.txt
index 55d7353acf..47645d290c 100644
--- a/3rdparty/zlib/CMakeLists.txt
+++ b/3rdparty/zlib/CMakeLists.txt
@@ -6,7 +6,8 @@ if (USE_SYSTEM_ZLIB)
target_link_libraries(3rdparty_zlib INTERFACE ZLIB::ZLIB)
target_compile_definitions(3rdparty_zlib INTERFACE -DZLIB_CONST=1)
else()
- option(ZLIB_BUILD_EXAMPLES "Enable Zlib Examples" OFF)
+ option(ZLIB_BUILD_TESTING "Enable Zlib Examples as tests" OFF)
+ option(ZLIB_BUILD_SHARED "Enable building zlib shared library" OFF)
message(STATUS "RPCS3: Using builtin ZLIB")
set(SKIP_INSTALL_ALL ON)
add_subdirectory(zlib EXCLUDE_FROM_ALL)
diff --git a/BUILDING.md b/BUILDING.md
index 597621e810..c1774908fd 100644
--- a/BUILDING.md
+++ b/BUILDING.md
@@ -20,26 +20,26 @@ The following tools are required to build RPCS3 on Windows 10 or later:
with standalone **CMake** tool.
- [Python 3.6+](https://www.python.org/downloads/) (add to PATH)
-- [Qt 6.10.2](https://www.qt.io/download-qt-installer) In case you can't download from the official installer, you can use [Another Qt installer](https://github.com/miurahr/aqtinstall) (In that case you will need to manually add the "qtmultimedia" module when installing Qt)
+- [Qt 6.11.0](https://www.qt.io/download-qt-installer) In case you can't download from the official installer, you can use [Another Qt installer](https://github.com/miurahr/aqtinstall) (In that case you will need to manually add the "qtmultimedia" module when installing Qt)
- [Vulkan SDK 1.3.268.0](https://vulkan.lunarg.com/sdk/home) (see "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/windows/getting_started.html)) for now future SDKs don't work. You need precisely 1.3.268.0.
The `sln` solution available only on **Visual Studio** is the preferred building solution. It easily allows to build the **RPCS3** application in `Release` and `Debug` mode.
In order to build **RPCS3** with the `sln` solution (with **Visual Studio**), **Qt** libs need to be detected. To detect the libs:
-- add and set the `QTDIR` environment variable, e.g. `\6.10.2\msvc2022_64\`
+- add and set the `QTDIR` environment variable, e.g. `\6.11.0\msvc2022_64\`
- or use the [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2022)
**NOTE:** If you have issues with the **Visual Studio Qt Plugin**, you may want to uninstall it and install the [Legacy Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.LEGACYQtVisualStudioTools2022) instead.
In order to build **RPCS3** with the `CMake` solution (with both **Visual Studio** and standalone **CMake** tool):
-- add and set the `Qt6_ROOT` environment variable to the **Qt** libs path, e.g. `\6.10.2\msvc2022_64\`
+- add and set the `Qt6_ROOT` environment variable to the **Qt** libs path, e.g. `\6.11.0\msvc2022_64\`
### Linux
These are the essentials tools to build RPCS3 on Linux. Some of them can be installed through your favorite package manager:
- Clang 17+ or GCC 13+
- [CMake 3.28.0+](https://www.cmake.org/download/)
-- [Qt 6.10.2](https://www.qt.io/download-qt-installer)
+- [Qt 6.11.0](https://www.qt.io/download-qt-installer)
- [Vulkan SDK 1.3.268.0](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/linux/getting_started.html)) for now future SDKs don't work. You need precisely 1.3.268.0.
- [SDL3](https://github.com/libsdl-org/SDL/releases) (for the FAudio backend)
@@ -123,7 +123,7 @@ Start **Visual Studio**, click on `Open a project or solution` and select the `r
##### Configuring the Qt Plugin (if used)
1) go to `Extensions->Qt VS Tools->Qt Versions`
-2) add the path to your Qt installation with compiler e.g. `\6.10.2\msvc2022_64`, version will fill in automatically
+2) add the path to your Qt installation with compiler e.g. `\6.11.0\msvc2022_64`, version will fill in automatically
3) go to `Extensions->Qt VS Tools->Options->Legacy Project Format`. (Only available in the **Legacy Qt Plugin**)
4) set `Build: Run pre-build setup` to `true`. (Only available in the **Legacy Qt Plugin**)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 50cf946fda..217c40f341 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -37,7 +37,7 @@ option(USE_LIBEVDEV "libevdev-based joystick support" ON)
option(USE_DISCORD_RPC "Discord rich presence integration" OFF)
option(USE_VULKAN "Vulkan render backend" ON)
option(USE_PRECOMPILED_HEADERS "Use precompiled headers" OFF)
-option(USE_SDL "Enables SDL input handler" OFF)
+option(USE_SDL "Enables SDL input handler" ON)
option(USE_SYSTEM_CUBEB "Prefer system cubeb instead of the builtin one" OFF)
option(USE_SYSTEM_CURL "Prefer system Curl instead of the prebuild one" ON)
option(USE_SYSTEM_FAUDIO "Prefer system FAudio instead of the builtin one" OFF)
@@ -86,52 +86,7 @@ if(CMAKE_BUILD_TYPE MATCHES "Debug" AND NOT MSVC)
endif()
if(MSVC)
- option(USE_MSVC_STATIC_CRT "Use static MSVC C runtime" OFF)
-
- # TODO(cjj19970505@live.cn)
- # DiscordRPC binary in 3rdparty is compiled /MT
- # So theoretically we should enable DiscordRPC in Release and static CRT build
- # since we might encounter some rumtime issues when more than one CRT version are presented.
- # https://docs.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features?view=msvc-160#what-problems-exist-if-an-application-uses-more-than-one-crt-version
- # Add other DiscordRPC binaries(compiled with /MTd, /MD, /MDd) or compile it from source may address this issue.
- if(NOT IS_MULTI_CONFIG)
- if(NOT(CMAKE_BUILD_TYPE MATCHES "Release" AND USE_MSVC_STATIC_CRT))
- set(USE_DISCORD_RPC OFF CACHE BOOL "Discord RPC is only available in Release and static CRT build." FORCE)
- endif()
- endif()
-
- if(USE_MSVC_STATIC_CRT)
- set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>")
- else()
- # though doc ( https://cmake.org/cmake/help/latest/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html )
- # says if that property is not set then CMake uses the default value MultiThreaded$<$:Debug>DLL
- # to select a MSVC runtime library.
- # But yaml-cpp set /MT(d) if CMAKE_MSVC_RUNTIME_LIBRARY is undefined
- # So we have to define it explicitly
- set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL")
- endif()
-
- # TODO(cjj19970505@live.cn)
- # offical QT uses dynamic CRT.
- # When building our lib with static CRT and debug build type
- # and linking with Qt with dynamic CRT and debug build,
- # error is encountered in runtime (which is expected).
- # But building our lib with static CRT and release build type,
- # and linking with Qt with dynamic CRT and release build seems to be working,
- # which is the same config with VS solution.
- # (though technically it might still have some hidden errors).
- # So we allow static CRT in both relase and debug build, but prompt warning in debug build.
- # For more info:
- # https://docs.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features?view=msvc-160#what-problems-exist-if-an-application-uses-more-than-one-crt-version
- # https://wiki.qt.io/Technical_FAQ#Why_does_a_statically_built_Qt_use_the_dynamic_Visual_Studio_runtime_libraries_.3F_Do_I_need_to_deploy_those_with_my_application_.3F
- if(USE_MSVC_STATIC_CRT)
- if(IS_MULTI_CONFIG OR CMAKE_BUILD_TYPE MATCHES "Debug")
- message(AUTHOR_WARNING "Debug build currently can not work with static CRT.")
- endif()
- endif()
- if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
- add_compile_options(/MP)
- endif()
+ add_compile_options("$<$:/MP>")
endif()
if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
@@ -144,7 +99,7 @@ if(APPLE AND CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
endif()
if(MSVC)
- add_compile_options(/wd4530 /utf-8) # C++ exception handler used, but unwind semantics are not enabled
+ add_compile_options("$<$:/wd4530;/utf-8>") # C++ exception handler used, but unwind semantics are not enabled
endif()
add_subdirectory(3rdparty)
@@ -163,10 +118,6 @@ if (NOT FOUND_LTO EQUAL -1)
message(FATAL_ERROR "RPCS3 doesn't support building with LTO, use -DDISABLE_LTO=TRUE to force-disable it")
endif()
-if(NOT WIN32)
- add_compile_options(-pthread)
-endif()
-
## Look for Gamemode if its installed on Linux
if(LINUX)
## User chooses whether to Enable GameMode features or not
diff --git a/Utilities/Config.cpp b/Utilities/Config.cpp
index cee928def7..bd0fe7a8b8 100644
--- a/Utilities/Config.cpp
+++ b/Utilities/Config.cpp
@@ -362,6 +362,27 @@ std::vector cfg::try_to_enum_list(decltype(&fmt_class_string::
return result;
}
+size_t cfg::try_to_enum_size(decltype(&fmt_class_string::format) func)
+{
+ size_t result = 0;
+ for (u64 i = 0;; i++)
+ {
+ std::string var;
+ func(var, i);
+
+ std::string hex;
+ fmt_class_string::format(hex, i);
+ if (var == hex)
+ {
+ break;
+ }
+
+ result++;
+ }
+
+ return result;
+}
+
void cfg::encode(YAML::Emitter& out, const cfg::_base& rhs)
{
switch (rhs.get_type())
@@ -416,7 +437,7 @@ void cfg::encode(YAML::Emitter& out, const cfg::_base& rhs)
out << YAML::BeginMap;
for (const auto& np : static_cast(rhs).get_map())
{
- if (np.second == logs::level::notice) continue;
+ if (np.second == logs::level::_default) continue;
out << YAML::Key << np.first;
out << YAML::Value << fmt::format("%s", np.second);
}
diff --git a/Utilities/Config.h b/Utilities/Config.h
index 35dcddc1a6..4c79cbf31c 100644
--- a/Utilities/Config.h
+++ b/Utilities/Config.h
@@ -30,6 +30,9 @@ namespace cfg
// Internal hack
std::vector try_to_enum_list(decltype(&fmt_class_string::format) func);
+ // Internal hack
+ size_t try_to_enum_size(decltype(&fmt_class_string::format) func);
+
// Config tree entry type.
enum class type : unsigned
{
@@ -312,6 +315,11 @@ namespace cfg
{
return try_to_enum_list(&fmt_class_string::format);
}
+
+ size_t size() const
+ {
+ return try_to_enum_size(&fmt_class_string::format);
+ }
};
// Signed 32/64-bit integer entry with custom Min/Max range.
@@ -385,7 +393,7 @@ namespace cfg
void set(const s64& value)
{
- ensure(value >= Min && value <= Max);
+ if (value < Min || value > Max) fmt::throw_exception("'%s': value %d out of bounds (min=%d, max=%d)", m_name, value, Min, Max);
m_value = static_cast(value);
}
@@ -476,7 +484,7 @@ namespace cfg
void set(const f64& value)
{
- ensure(value >= Min && value <= Max);
+ if (value < Min || value > Max) fmt::throw_exception("'%s': value %d out of bounds (min=%d, max=%d)", m_name, value, Min, Max);
m_value = static_cast(value);
}
@@ -563,7 +571,7 @@ namespace cfg
void set(const u64& value)
{
- ensure(value >= Min && value <= Max);
+ if (value < Min || value > Max) fmt::throw_exception("'%s': value %d out of bounds (min=%d, max=%d)", m_name, value, Min, Max);
m_value = static_cast(value);
}
diff --git a/Utilities/File.cpp b/Utilities/File.cpp
index 490605c792..aff4537dea 100644
--- a/Utilities/File.cpp
+++ b/Utilities/File.cpp
@@ -166,6 +166,7 @@ static fs::error to_error(int e)
case ENOTEMPTY: return fs::error::notempty;
case EROFS: return fs::error::readonly;
case EISDIR: return fs::error::isdir;
+ case ENOTDIR: return fs::error::notdir;
case ENOSPC: return fs::error::nospace;
case EXDEV: return fs::error::xdev;
default: return fs::error::unknown;
@@ -2833,6 +2834,7 @@ void fmt_class_string::format(std::string& out, u64 arg)
case fs::error::notempty: return "Not empty";
case fs::error::readonly: return "Read only";
case fs::error::isdir: return "Is a directory";
+ case fs::error::notdir: return "Not a directory";
case fs::error::toolong: return "Path too long";
case fs::error::nospace: return "Not enough space on the device";
case fs::error::xdev: return "Device mismatch";
diff --git a/Utilities/File.h b/Utilities/File.h
index dd2db42a46..3d332dd0be 100644
--- a/Utilities/File.h
+++ b/Utilities/File.h
@@ -683,6 +683,7 @@ namespace fs
notempty,
readonly,
isdir,
+ notdir,
toolong,
nospace,
xdev,
diff --git a/Utilities/JIT.h b/Utilities/JIT.h
index 6dfa9e7cd0..86fc72ed55 100644
--- a/Utilities/JIT.h
+++ b/Utilities/JIT.h
@@ -493,6 +493,10 @@ inline FT build_function_asm(std::string_view name, F&& builder, ::jit_runtime*
return reinterpret_cast(uptr(result));
}
+#if defined(__INTELLISENSE__) && !defined(LLVM_AVAILABLE)
+#define LLVM_AVAILABLE
+#endif
+
#ifdef LLVM_AVAILABLE
namespace llvm
diff --git a/Utilities/StrFmt.cpp b/Utilities/StrFmt.cpp
index 26fb1a09da..62f8365339 100644
--- a/Utilities/StrFmt.cpp
+++ b/Utilities/StrFmt.cpp
@@ -16,12 +16,12 @@
#include
#endif
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4996)
-#elif defined(__clang__)
+#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#elif defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4996)
#else
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp
index 08dce12315..b22c1aeb52 100644
--- a/Utilities/Thread.cpp
+++ b/Utilities/Thread.cpp
@@ -14,6 +14,11 @@
#include "Emu/CPU/Backends/AArch64/AArch64Signal.h"
#endif
+#ifdef __cpp_lib_stacktrace
+#include "rpcs3_version.h"
+#include
+#endif
+
#ifdef _WIN32
#include
#include
@@ -102,7 +107,7 @@ thread_local u64 g_tls_fault_rsx = 0;
thread_local u64 g_tls_fault_spu = 0;
thread_local u64 g_tls_wait_time = 0;
thread_local u64 g_tls_wait_fail = 0;
-thread_local bool g_tls_access_violation_recovered = false;
+thread_local u64 g_tls_access_violation_recovered = umax;
extern thread_local std::string(*g_tls_log_prefix)();
namespace stx
@@ -1264,7 +1269,7 @@ namespace rsx
extern std::function g_access_violation_handler;
}
-bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noexcept
+bool handle_access_violation(u32 addr, bool is_writing, bool is_exec, ucontext_t* context) noexcept
{
g_tls_fault_all++;
@@ -1300,7 +1305,7 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
}
} spu_protection{cpu};
- if (addr < RAW_SPU_BASE_ADDR && vm::check_addr(addr) && rsx::g_access_violation_handler)
+ if (!is_exec && addr < RAW_SPU_BASE_ADDR && vm::check_addr(addr) && rsx::g_access_violation_handler)
{
bool state_changed = false;
@@ -1366,7 +1371,7 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
{
auto thread = idm::get_unlocked>(spu_thread::find_raw_spu((addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET));
- if (!thread)
+ if (!thread || is_exec)
{
break;
}
@@ -1498,7 +1503,9 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
static_cast(context);
#endif /* ARCH_ */
- if (vm::check_addr(addr, is_writing ? vm::page_writable : vm::page_readable))
+ const auto required_page_perms = (is_writing ? vm::page_writable : vm::page_readable) + (is_exec ? vm::page_executable : 0);
+
+ if (vm::check_addr(addr, required_page_perms))
{
return true;
}
@@ -1506,9 +1513,7 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
// Hack: allocate memory in case the emulator is stopping
const auto hack_alloc = [&]()
{
- g_tls_access_violation_recovered = true;
-
- if (vm::check_addr(addr, is_writing ? vm::page_writable : vm::page_readable))
+ if (vm::check_addr(addr, required_page_perms))
{
return true;
}
@@ -1520,17 +1525,45 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
return false;
}
+ extern void ppu_register_range(u32 addr, u32 size);
+
+ bool reprotected = false;
+
if (vm::writer_lock mlock; area->flags & vm::preallocated || vm::check_addr(addr, 0))
{
// For allocated memory with protection lower than required (such as protection::no or read-only while writing to it)
utils::memory_protect(vm::base(addr & -0x1000), 0x1000, utils::protection::rw);
+ reprotected = true;
+ }
+
+ if (reprotected)
+ {
+ if (is_exec && !vm::check_addr(addr, vm::page_executable))
+ {
+ ppu_register_range(addr & -0x10000, 0x10000);
+ }
+
+ g_tls_access_violation_recovered = addr;
return true;
}
- return area->falloc(addr & -0x10000, 0x10000) || vm::check_addr(addr, is_writing ? vm::page_writable : vm::page_readable);
+ const bool allocated = area->falloc(addr & -0x10000, 0x10000);
+
+ if (allocated)
+ {
+ if (is_exec && !vm::check_addr(addr, vm::page_executable))
+ {
+ ppu_register_range(addr & -0x10000, 0x10000);
+ }
+
+ g_tls_access_violation_recovered = addr;
+ return true;
+ }
+
+ return false;
};
- if (cpu && (cpu->get_class() == thread_class::ppu || cpu->get_class() == thread_class::spu))
+ if (cpu && (cpu->get_class() == thread_class::ppu || cpu->get_class() == thread_class::spu) && !is_exec)
{
vm::temporary_unlock(*cpu);
u32 pf_port_id = 0;
@@ -1673,7 +1706,7 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
if (cpu->get_class() == thread_class::spu)
{
- if (!g_tls_access_violation_recovered)
+ if (g_tls_access_violation_recovered != addr)
{
vm_log.notice("\n%s", dump_useful_thread_info());
vm_log.always()("[%s] Access violation %s location 0x%x (%s)", cpu->get_name(), is_writing ? "writing" : "reading", addr, (is_writing && vm::check_addr(addr)) ? "read-only memory" : "unmapped memory");
@@ -1709,10 +1742,10 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
// Note: a thread may access violate more than once after hack_alloc recovery
// Do not log any further access violations in this case.
- if (!g_tls_access_violation_recovered)
+ if (g_tls_access_violation_recovered != addr)
{
vm_log.notice("\n%s", dump_useful_thread_info());
- vm_log.fatal("Access violation %s location 0x%x (%s)", is_writing ? "writing" : (cpu && cpu->get_class() == thread_class::ppu && cpu->get_pc() == addr ? "executing" : "reading"), addr, (is_writing && vm::check_addr(addr)) ? "read-only memory" : "unmapped memory");
+ vm_log.fatal("Access violation %s location 0x%x (%s)", is_writing ? "writing" : (is_exec ? "executing" : "reading"), addr, (is_writing && vm::check_addr(addr)) ? "read-only memory" : "unmapped memory");
}
while (Emu.IsPausedOrReady())
@@ -1761,8 +1794,13 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
}
}
- if (Emu.IsStopped() && !hack_alloc())
+ if (Emu.IsStopped())
{
+ while (!hack_alloc())
+ {
+ thread_ctrl::wait_for(1000);
+ }
+
return false;
}
@@ -1801,6 +1839,7 @@ static LONG exception_handler(PEXCEPTION_POINTERS pExp) noexcept
if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && !is_executing)
{
u32 addr = 0;
+ bool is_exec = false;
if (auto [addr0, ok] = vm::try_get_addr(ptr); ok)
{
@@ -1808,14 +1847,21 @@ static LONG exception_handler(PEXCEPTION_POINTERS pExp) noexcept
}
else if (const usz exec64 = (ptr - vm::g_exec_addr) / 2; exec64 <= u32{umax})
{
+ is_exec = true;
addr = static_cast(exec64);
}
- else
+ else if (const usz exec64 = (ptr - vm::g_exec_addr - vm::g_exec_addr_seg_offset); exec64 <= u32{umax})
{
+ is_exec = true;
+ addr = static_cast(exec64);
+ }
+ else
+ {
+ std::this_thread::sleep_for(1ms);
return EXCEPTION_CONTINUE_SEARCH;
}
- if (thread_ctrl::get_current() && handle_access_violation(addr, is_writing, pExp->ContextRecord))
+ if (thread_ctrl::get_current() && handle_access_violation(addr, is_writing, is_exec, pExp->ContextRecord))
{
return EXCEPTION_CONTINUE_EXECUTION;
}
@@ -2022,12 +2068,13 @@ static void signal_handler(int /*sig*/, siginfo_t* info, void* uct) noexcept
#endif
const u64 exec64 = (reinterpret_cast(info->si_addr) - reinterpret_cast(vm::g_exec_addr)) / 2;
+ const u64 exec64_2 = (reinterpret_cast(info->si_addr) - reinterpret_cast(vm::g_exec_addr)) - vm::g_exec_addr_seg_offset;
const auto cause = is_executing ? "executing" : is_writing ? "writing" : "reading";
if (auto [addr, ok] = vm::try_get_addr(info->si_addr); ok && !is_executing)
{
// Try to process access violation
- if (thread_ctrl::get_current() && handle_access_violation(addr, is_writing, context))
+ if (thread_ctrl::get_current() && handle_access_violation(addr, is_writing, false, context))
{
return;
}
@@ -2035,7 +2082,14 @@ static void signal_handler(int /*sig*/, siginfo_t* info, void* uct) noexcept
if (exec64 < 0x100000000ull && !is_executing)
{
- if (thread_ctrl::get_current() && handle_access_violation(static_cast(exec64), is_writing, context))
+ if (thread_ctrl::get_current() && handle_access_violation(static_cast(exec64), is_writing, true, context))
+ {
+ return;
+ }
+ }
+ else if (exec64_2 < 0x100000000ull && !is_executing)
+ {
+ if (thread_ctrl::get_current() && handle_access_violation(static_cast(exec64_2), is_writing, true, context))
{
return;
}
@@ -2354,7 +2408,7 @@ thread_base::native_entry thread_base::finalize(u64 _self) noexcept
g_tls_fault_spu = 0;
g_tls_wait_time = 0;
g_tls_wait_fail = 0;
- g_tls_access_violation_recovered = false;
+ g_tls_access_violation_recovered = umax;
g_tls_log_prefix = []() -> std::string { return {}; };
@@ -2800,6 +2854,16 @@ void thread_base::exec()
[[noreturn]] void thread_ctrl::emergency_exit(std::string_view reason)
{
+ // Print stacktrace
+#ifdef __cpp_lib_stacktrace
+ if (rpcs3::is_local_build())
+ {
+ std::ostringstream oss;
+ oss << std::stacktrace::current();
+ sys_log.notice("StackTrace\n\n%s\n", oss.str());
+ }
+#endif
+
if (const std::string info = dump_useful_thread_info(); !info.empty())
{
sys_log.notice("\n%s", info);
@@ -2815,6 +2879,16 @@ void thread_base::exec()
}
}
+ if (auto [total, current] = utils::get_memory_usage(); total - current <= 256 * 1024 * 1024)
+ {
+ if (reason_buf.empty())
+ {
+ reason_buf = std::string{reason};
+ }
+
+ fmt::append(reason_buf, " (Possible RAM deficiency: free RAM: %dMB)", (total - current) / (1024 * 1024));
+ }
+
if (!reason_buf.empty())
{
reason = reason_buf;
diff --git a/bin/GuiConfigs/Classic (Bright).qss b/bin/GuiConfigs/Classic (Bright).qss
index 143e42df94..f961e63e00 100644
--- a/bin/GuiConfigs/Classic (Bright).qss
+++ b/bin/GuiConfigs/Classic (Bright).qss
@@ -37,10 +37,6 @@ QSlider#sizeSlider::handle:horizontal {
QLabel#toolbar_icon_color {
color: rgba(64,64,64,255);
}
-/* thumbnail icon color stylesheet */
-QLabel#thumbnail_icon_color {
- color: rgba(0,100,231,255);
-}
/* gamelist icon color stylesheet */
QLabel#gamelist_icon_background_color {
color: rgba(209,209,209,255);
diff --git a/bin/GuiConfigs/Darker Style by TheMitoSan.qss b/bin/GuiConfigs/Darker Style by TheMitoSan.qss
index 47270a211e..8797ffd3c9 100644
--- a/bin/GuiConfigs/Darker Style by TheMitoSan.qss
+++ b/bin/GuiConfigs/Darker Style by TheMitoSan.qss
@@ -237,11 +237,6 @@ QLabel#gamelist_icon_background_color {
color: transparent;
}
-/* Set Windows Taskbar Thumbnail colors */
-QLabel#thumbnail_icon_color {
- color: #262626;
-}
-
/* Set Log colors */
QPlainTextEdit#log_frame {
background-color: #000; /* Black */
diff --git a/bin/GuiConfigs/Envy.qss b/bin/GuiConfigs/Envy.qss
index a78ba04f58..3e2e1ddc35 100644
--- a/bin/GuiConfigs/Envy.qss
+++ b/bin/GuiConfigs/Envy.qss
@@ -573,11 +573,6 @@ QLabel#gamelist_icon_background_color {
color: transparent;
}
-/* Set Windows Taskbar Thumbnail colors */
-QLabel#thumbnail_icon_color {
- color: #23262d;
-}
-
/* Log colors */
QPlainTextEdit#log_frame {
background-color: #23262d;
diff --git a/bin/GuiConfigs/Kuroi (Dark) by Ani.qss b/bin/GuiConfigs/Kuroi (Dark) by Ani.qss
index 54c667213b..2cd81267f1 100644
--- a/bin/GuiConfigs/Kuroi (Dark) by Ani.qss
+++ b/bin/GuiConfigs/Kuroi (Dark) by Ani.qss
@@ -265,11 +265,6 @@ QLabel#gamelist_icon_background_color {
color: transparent;
}
-/* Set Taskbar Thumbnail colors */
-QLabel#thumbnail_icon_color {
- color: #444444;
-}
-
/* Memory Viewer */
QLabel#memory_viewer_address_panel {
color: #00cbff; /* Font Color: Blue */
diff --git a/bin/GuiConfigs/ModernBlue Theme by TheMitoSan.qss b/bin/GuiConfigs/ModernBlue Theme by TheMitoSan.qss
index 410db682f7..96b84a9196 100644
--- a/bin/GuiConfigs/ModernBlue Theme by TheMitoSan.qss
+++ b/bin/GuiConfigs/ModernBlue Theme by TheMitoSan.qss
@@ -244,11 +244,6 @@ QLabel#gamelist_icon_background_color {
color: transparent;
}
-/* Set Windows Taskbar Thumbnail colors */
-QLabel#thumbnail_icon_color {
- color: #262626;
-}
-
/* Set Log colors */
QPlainTextEdit#log_frame {
background-color: #181d24; /* Black */
diff --git a/bin/GuiConfigs/Nekotekina by GooseWing.qss b/bin/GuiConfigs/Nekotekina by GooseWing.qss
index 435d550755..93fadcdd68 100755
--- a/bin/GuiConfigs/Nekotekina by GooseWing.qss
+++ b/bin/GuiConfigs/Nekotekina by GooseWing.qss
@@ -397,12 +397,6 @@ QLabel#gamelist_icon_background_color {
}
-/* Set Windows Taskbar Thumbnail colors */
-QLabel#thumbnail_icon_color {
- color: #ffd785;
-}
-
-
QLabel#log_level_always {
color: #00ffff; /* Cyan */
}
diff --git a/bin/GuiConfigs/Skyline (Nightfall).qss b/bin/GuiConfigs/Skyline (Nightfall).qss
index 625a6a28b6..4729a59173 100644
--- a/bin/GuiConfigs/Skyline (Nightfall).qss
+++ b/bin/GuiConfigs/Skyline (Nightfall).qss
@@ -656,11 +656,6 @@ QLabel#color_button {
background: transparent;
}
-/* Set Windows Taskbar Thumbnail colors */
-QLabel#thumbnail_icon_color {
- color: #370048;
-}
-
/* Debugger colors */
QLabel#debugger_frame_breakpoint {
color: #000; /* Font Color: Black */
diff --git a/bin/GuiConfigs/Skyline.qss b/bin/GuiConfigs/Skyline.qss
index ef3c7c6857..1004dc0016 100644
--- a/bin/GuiConfigs/Skyline.qss
+++ b/bin/GuiConfigs/Skyline.qss
@@ -664,11 +664,6 @@ QLabel#color_button {
background: transparent;
}
-/* Set Windows Taskbar Thumbnail colors */
-QLabel#thumbnail_icon_color {
- color: #8500ae;
-}
-
/* Debugger colors */
QLabel#debugger_frame_breakpoint {
color: #000; /* Font Color: Black */
diff --git a/bin/GuiConfigs/YoRHa by Ani.qss b/bin/GuiConfigs/YoRHa by Ani.qss
index c772f25196..51f09897b1 100644
--- a/bin/GuiConfigs/YoRHa by Ani.qss
+++ b/bin/GuiConfigs/YoRHa by Ani.qss
@@ -379,11 +379,6 @@ QLabel#gamelist_icon_background_color {
color: transparent;
}
-/* Set Windows Taskbar Thumbnail colors */
-QLabel#thumbnail_icon_color {
- color: #4d4940;
-}
-
QLabel#log_level_always {
color: #00ffff; /* Cyan */
}
diff --git a/bin/Icons/ui/home/256/bug-solid.png b/bin/Icons/ui/home/256/bug-solid.png
new file mode 100644
index 0000000000..2c88980603
Binary files /dev/null and b/bin/Icons/ui/home/256/bug-solid.png differ
diff --git a/bin/Icons/ui/home/256/circle-left-solid.png b/bin/Icons/ui/home/256/circle-left-solid.png
new file mode 100644
index 0000000000..f6b2e58768
Binary files /dev/null and b/bin/Icons/ui/home/256/circle-left-solid.png differ
diff --git a/bin/Icons/ui/home/256/display-solid.png b/bin/Icons/ui/home/256/display-solid.png
new file mode 100644
index 0000000000..84cc043b07
Binary files /dev/null and b/bin/Icons/ui/home/256/display-solid.png differ
diff --git a/bin/Icons/ui/home/256/floppy-disk-solid.png b/bin/Icons/ui/home/256/floppy-disk-solid.png
new file mode 100644
index 0000000000..3701361569
Binary files /dev/null and b/bin/Icons/ui/home/256/floppy-disk-solid.png differ
diff --git a/bin/Icons/ui/home/256/gamepad-solid.png b/bin/Icons/ui/home/256/gamepad-solid.png
new file mode 100644
index 0000000000..fe08f1bc58
Binary files /dev/null and b/bin/Icons/ui/home/256/gamepad-solid.png differ
diff --git a/bin/Icons/ui/home/256/gauge-solid.png b/bin/Icons/ui/home/256/gauge-solid.png
new file mode 100644
index 0000000000..5b6d731a9d
Binary files /dev/null and b/bin/Icons/ui/home/256/gauge-solid.png differ
diff --git a/bin/Icons/ui/home/256/headphones-solid.png b/bin/Icons/ui/home/256/headphones-solid.png
new file mode 100644
index 0000000000..feb015695d
Binary files /dev/null and b/bin/Icons/ui/home/256/headphones-solid.png differ
diff --git a/bin/Icons/ui/home/256/home.png b/bin/Icons/ui/home/256/home.png
new file mode 100644
index 0000000000..622984c913
Binary files /dev/null and b/bin/Icons/ui/home/256/home.png differ
diff --git a/bin/Icons/ui/home/256/maximize-solid.png b/bin/Icons/ui/home/256/maximize-solid.png
new file mode 100644
index 0000000000..65eaa43308
Binary files /dev/null and b/bin/Icons/ui/home/256/maximize-solid.png differ
diff --git a/bin/Icons/ui/home/256/play-button-arrowhead.png b/bin/Icons/ui/home/256/play-button-arrowhead.png
new file mode 100644
index 0000000000..37e9cefe93
Binary files /dev/null and b/bin/Icons/ui/home/256/play-button-arrowhead.png differ
diff --git a/bin/Icons/ui/home/256/power-off-solid.png b/bin/Icons/ui/home/256/power-off-solid.png
new file mode 100644
index 0000000000..cf0ab44839
Binary files /dev/null and b/bin/Icons/ui/home/256/power-off-solid.png differ
diff --git a/bin/Icons/ui/home/256/rotate-left-solid.png b/bin/Icons/ui/home/256/rotate-left-solid.png
new file mode 100644
index 0000000000..5eaf29edba
Binary files /dev/null and b/bin/Icons/ui/home/256/rotate-left-solid.png differ
diff --git a/bin/Icons/ui/home/256/screenshot.png b/bin/Icons/ui/home/256/screenshot.png
new file mode 100644
index 0000000000..091e2bbc2e
Binary files /dev/null and b/bin/Icons/ui/home/256/screenshot.png differ
diff --git a/bin/Icons/ui/home/256/settings.png b/bin/Icons/ui/home/256/settings.png
new file mode 100644
index 0000000000..d682b9b27c
Binary files /dev/null and b/bin/Icons/ui/home/256/settings.png differ
diff --git a/bin/Icons/ui/home/256/sliders-solid.png b/bin/Icons/ui/home/256/sliders-solid.png
new file mode 100644
index 0000000000..cfb030721e
Binary files /dev/null and b/bin/Icons/ui/home/256/sliders-solid.png differ
diff --git a/bin/Icons/ui/home/256/trophy-solid.png b/bin/Icons/ui/home/256/trophy-solid.png
new file mode 100644
index 0000000000..1bd98a9ac9
Binary files /dev/null and b/bin/Icons/ui/home/256/trophy-solid.png differ
diff --git a/bin/Icons/ui/home/256/user-group-solid.png b/bin/Icons/ui/home/256/user-group-solid.png
new file mode 100644
index 0000000000..a154fa5ba9
Binary files /dev/null and b/bin/Icons/ui/home/256/user-group-solid.png differ
diff --git a/bin/Icons/ui/home/256/video-camera.png b/bin/Icons/ui/home/256/video-camera.png
new file mode 100644
index 0000000000..9f5460fba6
Binary files /dev/null and b/bin/Icons/ui/home/256/video-camera.png differ
diff --git a/bin/Icons/ui/home/32/bug-solid.png b/bin/Icons/ui/home/32/bug-solid.png
new file mode 100644
index 0000000000..401fa0ea27
Binary files /dev/null and b/bin/Icons/ui/home/32/bug-solid.png differ
diff --git a/bin/Icons/ui/home/32/circle-left-solid.png b/bin/Icons/ui/home/32/circle-left-solid.png
new file mode 100644
index 0000000000..1acf201d63
Binary files /dev/null and b/bin/Icons/ui/home/32/circle-left-solid.png differ
diff --git a/bin/Icons/ui/home/32/display-solid.png b/bin/Icons/ui/home/32/display-solid.png
new file mode 100644
index 0000000000..8a48c89494
Binary files /dev/null and b/bin/Icons/ui/home/32/display-solid.png differ
diff --git a/bin/Icons/ui/home/32/floppy-disk-solid.png b/bin/Icons/ui/home/32/floppy-disk-solid.png
new file mode 100644
index 0000000000..836c6523c3
Binary files /dev/null and b/bin/Icons/ui/home/32/floppy-disk-solid.png differ
diff --git a/bin/Icons/ui/home/32/gamepad-solid.png b/bin/Icons/ui/home/32/gamepad-solid.png
new file mode 100644
index 0000000000..b783fee792
Binary files /dev/null and b/bin/Icons/ui/home/32/gamepad-solid.png differ
diff --git a/bin/Icons/ui/home/32/gauge-solid.png b/bin/Icons/ui/home/32/gauge-solid.png
new file mode 100644
index 0000000000..9853811ae2
Binary files /dev/null and b/bin/Icons/ui/home/32/gauge-solid.png differ
diff --git a/bin/Icons/ui/home/32/headphones-solid.png b/bin/Icons/ui/home/32/headphones-solid.png
new file mode 100644
index 0000000000..e2cfabb07c
Binary files /dev/null and b/bin/Icons/ui/home/32/headphones-solid.png differ
diff --git a/bin/Icons/ui/home/32/home.png b/bin/Icons/ui/home/32/home.png
new file mode 100644
index 0000000000..2ec05eab24
Binary files /dev/null and b/bin/Icons/ui/home/32/home.png differ
diff --git a/bin/Icons/ui/home/32/maximize-solid.png b/bin/Icons/ui/home/32/maximize-solid.png
new file mode 100644
index 0000000000..7a0a9e4fb6
Binary files /dev/null and b/bin/Icons/ui/home/32/maximize-solid.png differ
diff --git a/bin/Icons/ui/home/32/play-button-arrowhead.png b/bin/Icons/ui/home/32/play-button-arrowhead.png
new file mode 100644
index 0000000000..6ce5505f4d
Binary files /dev/null and b/bin/Icons/ui/home/32/play-button-arrowhead.png differ
diff --git a/bin/Icons/ui/home/32/power-off-solid.png b/bin/Icons/ui/home/32/power-off-solid.png
new file mode 100644
index 0000000000..21ebad8e69
Binary files /dev/null and b/bin/Icons/ui/home/32/power-off-solid.png differ
diff --git a/bin/Icons/ui/home/32/rotate-left-solid.png b/bin/Icons/ui/home/32/rotate-left-solid.png
new file mode 100644
index 0000000000..b466d28a8e
Binary files /dev/null and b/bin/Icons/ui/home/32/rotate-left-solid.png differ
diff --git a/bin/Icons/ui/home/32/screenshot.png b/bin/Icons/ui/home/32/screenshot.png
new file mode 100644
index 0000000000..97255279b4
Binary files /dev/null and b/bin/Icons/ui/home/32/screenshot.png differ
diff --git a/bin/Icons/ui/home/32/settings.png b/bin/Icons/ui/home/32/settings.png
new file mode 100644
index 0000000000..eeaeceef7d
Binary files /dev/null and b/bin/Icons/ui/home/32/settings.png differ
diff --git a/bin/Icons/ui/home/32/sliders-solid.png b/bin/Icons/ui/home/32/sliders-solid.png
new file mode 100644
index 0000000000..ca4c75df23
Binary files /dev/null and b/bin/Icons/ui/home/32/sliders-solid.png differ
diff --git a/bin/Icons/ui/home/32/trophy-solid.png b/bin/Icons/ui/home/32/trophy-solid.png
new file mode 100644
index 0000000000..9d94e14b97
Binary files /dev/null and b/bin/Icons/ui/home/32/trophy-solid.png differ
diff --git a/bin/Icons/ui/home/32/user-group-solid.png b/bin/Icons/ui/home/32/user-group-solid.png
new file mode 100644
index 0000000000..114c45599d
Binary files /dev/null and b/bin/Icons/ui/home/32/user-group-solid.png differ
diff --git a/bin/Icons/ui/home/32/video-camera.png b/bin/Icons/ui/home/32/video-camera.png
new file mode 100644
index 0000000000..d8fa8dfaaf
Binary files /dev/null and b/bin/Icons/ui/home/32/video-camera.png differ
diff --git a/bin/Icons/ui/loading.png b/bin/Icons/ui/loading.png
new file mode 100644
index 0000000000..33288035c7
Binary files /dev/null and b/bin/Icons/ui/loading.png differ
diff --git a/buildfiles/cmake/ConfigureCompiler.cmake b/buildfiles/cmake/ConfigureCompiler.cmake
index 1685e4d13e..a5fe614029 100644
--- a/buildfiles/cmake/ConfigureCompiler.cmake
+++ b/buildfiles/cmake/ConfigureCompiler.cmake
@@ -107,11 +107,6 @@ else()
# This hides our LLVM from mesa's LLVM, otherwise we get some unresolvable conflicts.
add_link_options(-Wl,--exclude-libs,ALL)
elseif(WIN32)
- add_compile_definitions(__STDC_FORMAT_MACROS=1)
-
- # Workaround for mingw64 (MSYS2)
- add_link_options(-Wl,--allow-multiple-definition)
-
# Increase stack limit to 8 MB
add_link_options(-Wl,--stack -Wl,8388608)
endif()
diff --git a/buildfiles/cmake/FindWolfSSL.cmake b/buildfiles/cmake/FindWolfSSL.cmake
index d2e30be60b..35f316837c 100644
--- a/buildfiles/cmake/FindWolfSSL.cmake
+++ b/buildfiles/cmake/FindWolfSSL.cmake
@@ -1,4 +1,3 @@
-set(WOLFSSL_LIBRARY ON)
-set(WOLFSSL_INCLUDE_DIR ON)
-set(WOLFSSL_LIBRARIES wolfssl)
+set(WOLFSSL_LIBRARY wolfssl)
+set(WOLFSSL_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/3rdparty/wolfssl)
set(WOLFSSL_FOUND TRUE)
diff --git a/buildfiles/cmake/FindZLIB.cmake b/buildfiles/cmake/FindZLIB.cmake
index 0a29abafa9..ff5869a5f7 100644
--- a/buildfiles/cmake/FindZLIB.cmake
+++ b/buildfiles/cmake/FindZLIB.cmake
@@ -3,9 +3,9 @@ if(USE_SYSTEM_ZLIB)
find_package(ZLIB)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
else()
- add_library(ZLIB::ZLIB INTERFACE IMPORTED)
+ add_library(ZLIB::ZLIB STATIC IMPORTED)
set_target_properties(ZLIB::ZLIB PROPERTIES
- INTERFACE_LINK_LIBRARIES zlibstatic
+ IMPORTED_LOCATION "${CMAKE_BINARY_DIR}/3rdparty/zlib/zlib/libzlibstatic.a"
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/3rdparty/zlib/zlib;${CMAKE_BINARY_DIR}/3rdparty/zlib/zlib")
set(ZLIB_FOUND TRUE)
endif()
diff --git a/rpcs3/CMakeLists.txt b/rpcs3/CMakeLists.txt
index 5ab98ab419..e5df95ffd5 100644
--- a/rpcs3/CMakeLists.txt
+++ b/rpcs3/CMakeLists.txt
@@ -87,12 +87,6 @@ if (NOT ANDROID)
message(FATAL_ERROR "RPCS3 requires either X11 or Wayland (or both) for Vulkan.")
endif()
- if(UNIX)
- set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
- find_package(Threads REQUIRED)
- target_link_libraries(rpcs3_lib PRIVATE Threads::Threads)
- endif()
-
if(WIN32)
target_link_libraries(rpcs3_lib PRIVATE ws2_32 Iphlpapi Winmm Psapi gdi32 setupapi)
else()
@@ -200,6 +194,7 @@ if(BUILD_RPCS3_TESTS)
tests/test_address_range.cpp
tests/test_rsx_cfg.cpp
tests/test_rsx_fp_asm.cpp
+ tests/test_dmux_pamf.cpp
)
target_link_libraries(rpcs3_test
@@ -207,6 +202,7 @@ if(BUILD_RPCS3_TESTS)
rpcs3_lib
rpcs3_emu
GTest::gtest
+ GTest::gmock
)
target_include_directories(rpcs3_test
diff --git a/rpcs3/Emu/CMakeLists.txt b/rpcs3/Emu/CMakeLists.txt
index 2f9678263f..3e465b1b62 100644
--- a/rpcs3/Emu/CMakeLists.txt
+++ b/rpcs3/Emu/CMakeLists.txt
@@ -488,6 +488,7 @@ target_sources(rpcs3_emu PRIVATE
RSX/NV47/HW/nv406e.cpp
RSX/NV47/HW/nv4097.cpp
RSX/Overlays/FriendsList/overlay_friends_list_dialog.cpp
+ RSX/Overlays/HomeMenu/overlay_home_icons.cpp
RSX/Overlays/HomeMenu/overlay_home_menu.cpp
RSX/Overlays/HomeMenu/overlay_home_menu_components.cpp
RSX/Overlays/HomeMenu/overlay_home_menu_main_menu.cpp
@@ -501,6 +502,8 @@ target_sources(rpcs3_emu PRIVATE
RSX/Overlays/overlays.cpp
RSX/Overlays/overlay_animated_icon.cpp
RSX/Overlays/overlay_animation.cpp
+ RSX/Overlays/overlay_audio.cpp
+ RSX/Overlays/overlay_checkbox.cpp
RSX/Overlays/overlay_compile_notification.cpp
RSX/Overlays/overlay_controls.cpp
RSX/Overlays/overlay_cursor.cpp
@@ -517,6 +520,9 @@ target_sources(rpcs3_emu PRIVATE
RSX/Overlays/overlay_perf_metrics.cpp
RSX/Overlays/overlay_progress_bar.cpp
RSX/Overlays/overlay_save_dialog.cpp
+ RSX/Overlays/overlay_select.cpp
+ RSX/Overlays/overlay_slider.cpp
+ RSX/Overlays/overlay_tabs.cpp
RSX/Overlays/overlay_trophy_notification.cpp
RSX/Overlays/overlay_user_list_dialog.cpp
RSX/Overlays/overlay_utils.cpp
@@ -640,6 +646,9 @@ if(TARGET 3rdparty_vulkan)
endif()
endif()
+if(NOT WIN32)
+ set(THREADS_PREFER_PTHREAD_FLAG ON)
+endif()
find_package(Threads REQUIRED)
target_link_libraries(rpcs3_emu
diff --git a/rpcs3/Emu/CPU/Backends/AArch64/AArch64Common.h b/rpcs3/Emu/CPU/Backends/AArch64/AArch64Common.h
index dff06dfb81..2ce4fa68b3 100644
--- a/rpcs3/Emu/CPU/Backends/AArch64/AArch64Common.h
+++ b/rpcs3/Emu/CPU/Backends/AArch64/AArch64Common.h
@@ -20,19 +20,19 @@ namespace aarch64
sp
};
- static const char* gpr_names[] =
+ [[maybe_unused]] static const char* gpr_names[] =
{
"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9",
"x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19",
"x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30"
};
- static const char* spr_names[] =
+ [[maybe_unused]] static const char* spr_names[] =
{
"xzr", "pc", "sp"
};
- static const char* spr_asm_names[] =
+ [[maybe_unused]] static const char* spr_asm_names[] =
{
"xzr", ".", "sp"
};
diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp
index e37e6ed0da..4bd5fc9157 100644
--- a/rpcs3/Emu/CPU/CPUThread.cpp
+++ b/rpcs3/Emu/CPU/CPUThread.cpp
@@ -888,6 +888,14 @@ bool cpu_thread::check_state() noexcept
store = true;
}
+ if (flags & cpu_flag::req_exit)
+ {
+ // A request for the thread to quit has been made
+ flags -= cpu_flag::req_exit;
+ flags += cpu_flag::exit;
+ store = true;
+ }
+
// Can't process dbg_step if we only paused temporarily
if (cpu_can_stop && flags & cpu_flag::dbg_step)
{
@@ -1157,13 +1165,13 @@ void cpu_thread::notify()
cpu_thread& cpu_thread::operator=(thread_state)
{
- if (state & cpu_flag::exit)
+ if (state & (cpu_flag::exit + cpu_flag::req_exit))
{
// Must be notified elsewhere or self-raised
return *this;
}
- const auto old = state.fetch_add(cpu_flag::exit);
+ const auto old = state.fetch_add(cpu_flag::req_exit);
if (old & cpu_flag::wait && old.none_of(cpu_flag::again + cpu_flag::exit))
{
@@ -1322,8 +1330,9 @@ extern std::shared_ptr make_disasm(const cpu_thread* cpu, shared_ptr<
void cpu_thread::dump_all(std::string& ret) const
{
std::any func_data;
+ std::any misc_data;
- ret += dump_misc();
+ dump_misc(ret, misc_data);
ret += '\n';
dump_regs(ret, func_data);
ret += '\n';
@@ -1371,9 +1380,9 @@ std::vector> cpu_thread::dump_callstack_list() const
return {};
}
-std::string cpu_thread::dump_misc() const
+void cpu_thread::dump_misc(std::string& ret, std::any& /*custom_data*/) const
{
- return fmt::format("Type: %s; State: %s\n", get_class() == thread_class::ppu ? "PPU" : get_class() == thread_class::spu ? "SPU" : "RSX", state.load());
+ fmt::append(ret, "%s[0x%x]; State: %s\n", get_class() == thread_class::ppu ? "PPU" : get_class() == thread_class::spu ? "SPU" : "RSX", id, state.load());
}
bool cpu_thread::suspend_work::push(cpu_thread* _this) noexcept
diff --git a/rpcs3/Emu/CPU/CPUThread.h b/rpcs3/Emu/CPU/CPUThread.h
index 5e3484f7f5..e723fd2d4b 100644
--- a/rpcs3/Emu/CPU/CPUThread.h
+++ b/rpcs3/Emu/CPU/CPUThread.h
@@ -29,6 +29,7 @@ enum class cpu_flag : u32
yield, // Thread is being requested to yield its execution time if it's running
preempt, // Thread is being requested to preempt the execution of all CPU threads
+ req_exit, // Request the thread to exit
dbg_global_pause, // Emulation paused
dbg_pause, // Thread paused
dbg_step, // Thread forced to pause after one step (one instruction, etc)
@@ -39,7 +40,7 @@ enum class cpu_flag : u32
// Test stopped state
constexpr bool is_stopped(bs_t state)
{
- return !!(state & (cpu_flag::stop + cpu_flag::exit + cpu_flag::again));
+ return !!(state & (cpu_flag::stop + cpu_flag::exit + cpu_flag::again + cpu_flag::req_exit));
}
// Test paused state
@@ -176,7 +177,7 @@ public:
virtual std::vector> dump_callstack_list() const;
// Get CPU dump of misc information
- virtual std::string dump_misc() const;
+ virtual void dump_misc(std::string& ret, std::any& /*custom_data*/) const;
// Thread entry point function
virtual void cpu_task() = 0;
diff --git a/rpcs3/Emu/CPU/CPUTranslator.cpp b/rpcs3/Emu/CPU/CPUTranslator.cpp
index f799e4b6be..6bd7924ea5 100644
--- a/rpcs3/Emu/CPU/CPUTranslator.cpp
+++ b/rpcs3/Emu/CPU/CPUTranslator.cpp
@@ -201,9 +201,16 @@ void cpu_translator::initialize(llvm::LLVMContext& context, llvm::ExecutionEngin
m_use_vnni = true;
m_use_gfni = true;
}
+
+#ifdef ARCH_ARM64
+ if (utils::has_dotprod())
+ {
+ m_use_dotprod = true;
+ }
+#endif
}
-llvm::Value* cpu_translator::bitcast(llvm::Value* val, llvm::Type* type) const
+llvm::Value* cpu_translator::bitcast(llvm::Value* val, llvm::Type* type, std::source_location src_loc) const
{
uint s1 = type->getScalarSizeInBits();
uint s2 = val->getType()->getScalarSizeInBits();
@@ -215,15 +222,69 @@ llvm::Value* cpu_translator::bitcast(llvm::Value* val, llvm::Type* type) const
if (s1 != s2)
{
- fmt::throw_exception("cpu_translator::bitcast(): incompatible type sizes (%u vs %u)", s1, s2);
+ fmt::throw_exception("cpu_translator::bitcast(): incompatible type sizes (%u vs %u)\nCalled from: %s", s1, s2, src_loc);
}
- if (const auto c1 = llvm::dyn_cast(val))
+ if (val->getType() == type)
+ {
+ return val;
+ }
+
+ llvm::CastInst* i;
+ llvm::Value* source_val = val;
+
+ // Try to reuse older bitcasts
+ while ((i = llvm::dyn_cast_or_null(source_val)) && i->getOpcode() == llvm::Instruction::BitCast)
+ {
+ source_val = i->getOperand(0);
+
+ if (source_val->getType() == type)
+ {
+ return source_val;
+ }
+ }
+
+ for (auto it = source_val->use_begin(); it != source_val->use_end(); ++it)
+ {
+ llvm::Value* it_val = *it;
+
+ if (!it_val)
+ {
+ continue;
+ }
+
+ llvm::CastInst* bci = llvm::dyn_cast_or_null(it_val);
+
+ // Walk through bitcasts
+ while (bci && bci->getOpcode() == llvm::Instruction::BitCast)
+ {
+ if (bci->getParent() != m_ir->GetInsertBlock())
+ {
+ break;
+ }
+
+ if (bci->getType() == type)
+ {
+ return bci;
+ }
+
+ if (bci->use_begin() == bci->use_end())
+ {
+ break;
+ }
+
+ bci = llvm::dyn_cast_or_null(*bci->use_begin());
+ }
+ }
+
+ // Do bitcast on the source
+
+ if (const auto c1 = llvm::dyn_cast(source_val))
{
return ensure(llvm::ConstantFoldCastOperand(llvm::Instruction::BitCast, c1, type, m_module->getDataLayout()));
}
- return m_ir->CreateBitCast(val, type);
+ return m_ir->CreateBitCast(source_val, type);
}
template <>
diff --git a/rpcs3/Emu/CPU/CPUTranslator.h b/rpcs3/Emu/CPU/CPUTranslator.h
index 99ddafde0a..ab2aed8156 100644
--- a/rpcs3/Emu/CPU/CPUTranslator.h
+++ b/rpcs3/Emu/CPU/CPUTranslator.h
@@ -43,6 +43,7 @@
#include
#include
+#include
// Helper function
llvm::Value* peek_through_bitcasts(llvm::Value*);
@@ -567,6 +568,32 @@ struct llvm_placeholder_t
}
};
+template >>
+struct llvm_place_stealer_t
+{
+ // TODO: placeholder extracting actual constant values (u64, f64, vector, etc)
+
+ using type = T;
+
+ static constexpr bool is_ok = true;
+
+ llvm::Value* eval(llvm::IRBuilder<>*) const
+ {
+ return nullptr;
+ }
+
+ std::tuple<> match(llvm::Value*& value, llvm::Module*) const
+ {
+ if (value && value->getType() == llvm_value_t::get_type(value->getContext()))
+ {
+ return {};
+ }
+
+ value = nullptr;
+ return {};
+ }
+};
+
template
struct llvm_const_int
{
@@ -3090,6 +3117,9 @@ protected:
// For now, setting this flag will speed up SPU verification
// but I will remove this later with explicit parralelism - Whatcookie
bool m_use_avx = true;
+
+ // ARMv8 SDOT/UDOT
+ bool m_use_dotprod = false;
#else
// Allow FMA
bool m_use_fma = false;
@@ -3210,7 +3240,7 @@ public:
}
// Bitcast with immediate constant folding
- llvm::Value* bitcast(llvm::Value* val, llvm::Type* type) const;
+ llvm::Value* bitcast(llvm::Value* val, llvm::Type* type, std::source_location src_loc = std::source_location::current()) const;
template
llvm::Value* bitcast(llvm::Value* val)
@@ -3224,6 +3254,12 @@ public:
return {};
}
+ template
+ static llvm_place_stealer_t match_stealer()
+ {
+ return {};
+ }
+
template
requires requires { typename llvm_common_t; }
static auto match_expr(llvm::Value* v, llvm::Module* _m, T&& expr)
@@ -3647,10 +3683,59 @@ public:
const auto data0 = a.eval(m_ir);
const auto data1 = b.eval(m_ir);
const auto data2 = c.eval(m_ir);
+
+#if LLVM_VERSION_MAJOR >= 22
+ // LLVM 22+ changed the intrinsic signature from v4i32 to v16i8 for operands 2 and 3
+ result.value = m_ir->CreateCall(get_intrinsic(llvm::Intrinsic::x86_avx512_vpdpbusd_128),
+ {data0, m_ir->CreateBitCast(data1, get_type()), m_ir->CreateBitCast(data2, get_type())});
+#else
result.value = m_ir->CreateCall(get_intrinsic(llvm::Intrinsic::x86_avx512_vpdpbusd_128), {data0, data1, data2});
+#endif
return result;
}
+#ifdef ARCH_ARM64
+template
+ value_t udot(T1 a, T2 b, T3 c)
+ {
+ value_t result;
+
+ const auto data0 = a.eval(m_ir);
+ const auto data1 = b.eval(m_ir);
+ const auto data2 = c.eval(m_ir);
+
+ result.value = m_ir->CreateCall(get_intrinsic(llvm::Intrinsic::aarch64_neon_udot), {data0, data1, data2});
+ return result;
+ }
+
+ template
+ value_t sdot(T1 a, T2 b, T3 c)
+ {
+ value_t result;
+
+ const auto data0 = a.eval(m_ir);
+ const auto data1 = b.eval(m_ir);
+ const auto data2 = c.eval(m_ir);
+
+ result.value = m_ir->CreateCall(get_intrinsic(llvm::Intrinsic::aarch64_neon_sdot), {data0, data1, data2});
+ return result;
+ }
+
+template
+ auto addp(T1 a, T2 b)
+ {
+ using T_vector = typename is_llvm_expr::type;
+ const auto data1 = a.eval(m_ir);
+ const auto data2 = b.eval(m_ir);
+
+ const auto func = get_intrinsic(llvm::Intrinsic::aarch64_neon_addp);
+
+ value_t result;
+ result.value = m_ir->CreateCall(func, {data1, data2});
+ return result;
+ }
+#endif
+
template
value_t vpermb(T1 a, T2 b)
{
@@ -3899,6 +3984,15 @@ public:
erase_stores({args.value...});
}
+ // Debug breakpoint
+ void debugtrap()
+ {
+ const auto _rty = llvm::Type::getVoidTy(m_context);
+ const auto type = llvm::FunctionType::get(_rty, {}, false);
+ const auto func = llvm::cast(m_ir->GetInsertBlock()->getParent()->getParent()->getOrInsertFunction("llvm.debugtrap", type).getCallee());
+ m_ir->CreateCall(func);
+ }
+
template
static auto pshufb(T&& a, U&& b)
{
diff --git a/rpcs3/Emu/Cell/Modules/cellAdec.cpp b/rpcs3/Emu/Cell/Modules/cellAdec.cpp
index dfc91c8d2f..0d0c4481e9 100644
--- a/rpcs3/Emu/Cell/Modules/cellAdec.cpp
+++ b/rpcs3/Emu/Cell/Modules/cellAdec.cpp
@@ -261,7 +261,7 @@ void LpcmDecContext::exec(ppu_thread& ppu)
savestate = lpcm_dec_state::waiting_for_output_mutex_lock;
output_mutex_lock:
- error_occurred |= static_cast(sys_mutex_lock(ppu, output_mutex, 0) != CELL_OK);
+ error_occurred |= static_cast(lv2_syscall(ppu, output_mutex, 0) != CELL_OK);
if (ppu.state & cpu_flag::again)
{
@@ -273,7 +273,7 @@ void LpcmDecContext::exec(ppu_thread& ppu)
savestate = lpcm_dec_state::waiting_for_output_cond_wait;
output_cond_wait:
- ensure(sys_cond_wait(ppu, output_consumed, 0) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, output_consumed, 0) == CELL_OK); // Error code isn't checked on LLE
if (ppu.state & cpu_flag::again)
{
@@ -287,7 +287,7 @@ void LpcmDecContext::exec(ppu_thread& ppu)
savestate = lpcm_dec_state::queue_mutex_lock;
queue_mutex_lock:
- ensure(sys_mutex_lock(ppu, queue_mutex, 0) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, queue_mutex, 0) == CELL_OK); // Error code isn't checked on LLE
if (ppu.state & cpu_flag::again)
{
@@ -296,7 +296,7 @@ void LpcmDecContext::exec(ppu_thread& ppu)
cmd_queue.pop(cmd);
- ensure(sys_mutex_unlock(ppu, queue_mutex) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, queue_mutex) == CELL_OK); // Error code isn't checked on LLE
cellAdec.trace("Command type: %d", static_cast(cmd.type.get()));
@@ -307,7 +307,7 @@ void LpcmDecContext::exec(ppu_thread& ppu)
{
case LpcmDecCmdType::start_seq:
// LLE sends a command to the SPU thread. The SPU thread consumes the command without doing anything, however
- error_occurred |= static_cast(sys_mutex_unlock(ppu, output_mutex) != CELL_OK);
+ error_occurred |= static_cast(lv2_syscall(ppu, output_mutex) != CELL_OK);
break;
case LpcmDecCmdType::end_seq:
@@ -324,11 +324,11 @@ void LpcmDecContext::exec(ppu_thread& ppu)
// Doesn't do anything else
notify_seq_done.cbFunc(ppu, notify_seq_done.cbArg);
- error_occurred |= static_cast(sys_mutex_unlock(ppu, output_mutex) != CELL_OK);
+ error_occurred |= static_cast(lv2_syscall(ppu, output_mutex) != CELL_OK);
break;
}
case LpcmDecCmdType::close:
- ensure(sys_mutex_unlock(ppu, output_mutex) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, output_mutex) == CELL_OK); // Error code isn't checked on LLE
return;
case LpcmDecCmdType::decode_au:
@@ -685,7 +685,7 @@ void LpcmDecContext::exec(ppu_thread& ppu)
notify_au_done.cbFunc(ppu, cmd.pcm_handle, notify_au_done.cbArg);
output_locked = true;
- error_occurred |= static_cast(sys_mutex_unlock(ppu, output_mutex) != CELL_OK);
+ error_occurred |= static_cast(lv2_syscall(ppu, output_mutex) != CELL_OK);
const vm::var bsi_info{{ lpcm_param->channelNumber, lpcm_param->sampleRate, static_cast(output_size) }};
@@ -703,14 +703,14 @@ error_code LpcmDecContext::send_command(ppu_thread& ppu, auto&&... args)
{
ppu.state += cpu_flag::wait;
- if (error_code ret = sys_mutex_lock(ppu, queue_size_mutex, 0); ret != CELL_OK)
+ if (error_code ret = lv2_syscall(ppu, queue_size_mutex, 0); ret != CELL_OK)
{
return ret;
}
if (cmd_queue.full())
{
- ensure(sys_mutex_unlock(ppu, queue_size_mutex) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, queue_size_mutex) == CELL_OK); // Error code isn't checked on LLE
return CELL_ADEC_ERROR_BUSY;
}
@@ -720,39 +720,39 @@ error_code LpcmDecContext::send_command(ppu_thread& ppu, auto&&... args)
*lpcm_param = { args... };
}
- if (error_code ret = sys_mutex_lock(ppu, queue_mutex, 0); ret != CELL_OK)
+ if (error_code ret = lv2_syscall(ppu, queue_mutex, 0); ret != CELL_OK)
{
- ensure(sys_mutex_unlock(ppu, queue_size_mutex) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, queue_size_mutex) == CELL_OK); // Error code isn't checked on LLE
return ret;
}
cmd_queue.emplace(type, std::forward(args)...);
- if (error_code ret = sys_mutex_unlock(ppu, queue_mutex); ret != CELL_OK
+ if (error_code ret = lv2_syscall(ppu, queue_mutex); ret != CELL_OK
|| (ret = cmd_available.release(ppu)) != CELL_OK)
{
- ensure(sys_mutex_unlock(ppu, queue_size_mutex) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, queue_size_mutex) == CELL_OK); // Error code isn't checked on LLE
return ret;
}
- return sys_mutex_unlock(ppu, queue_size_mutex);
+ return lv2_syscall(ppu, queue_size_mutex);
}
inline error_code LpcmDecContext::release_output(ppu_thread& ppu)
{
- if (error_code ret = sys_mutex_lock(ppu, output_mutex, 0); ret != CELL_OK)
+ if (error_code ret = lv2_syscall(ppu, output_mutex, 0); ret != CELL_OK)
{
return ret;
}
output_locked = false;
- if (error_code ret = sys_cond_signal(ppu, output_consumed); ret != CELL_OK)
+ if (error_code ret = lv2_syscall(ppu, output_consumed); ret != CELL_OK)
{
return ret; // LLE doesn't unlock the mutex
}
- return sys_mutex_unlock(ppu, output_mutex);
+ return lv2_syscall(ppu, output_mutex);
}
void lpcmDecEntry(ppu_thread& ppu, vm::ptr lpcm_dec)
@@ -820,13 +820,13 @@ error_code _CellAdecCoreOpOpenExt_lpcm(ppu_thread& ppu, vm::ptr
const vm::var queue_mutex_attr{{ SYS_SYNC_PRIORITY, SYS_SYNC_NOT_RECURSIVE, SYS_SYNC_NOT_PROCESS_SHARED, SYS_SYNC_NOT_ADAPTIVE, 0, 0, 0, { "_adem06"_u64 } }};
const vm::var cond_attr{{ SYS_SYNC_NOT_PROCESS_SHARED, 0, 0, { "_adec03"_u64 } }};
- error_code ret = sys_mutex_create(ppu, handle.ptr(&LpcmDecContext::queue_size_mutex), mutex_attr);
- ret = ret ? ret : sys_cond_create(ppu, handle.ptr(&LpcmDecContext::queue_size_cond), handle->queue_size_mutex, cond_attr);
- ret = ret ? ret : sys_mutex_create(ppu, handle.ptr(&LpcmDecContext::unk_mutex), mutex_attr);
- ret = ret ? ret : sys_cond_create(ppu, handle.ptr(&LpcmDecContext::unk_cond), handle->unk_mutex, cond_attr);
- ret = ret ? ret : sys_mutex_create(ppu, handle.ptr(&LpcmDecContext::output_mutex), output_mutex_attr);
- ret = ret ? ret : sys_cond_create(ppu, handle.ptr(&LpcmDecContext::output_consumed), handle->output_mutex, cond_attr);
- ret = ret ? ret : sys_mutex_create(ppu, handle.ptr(&LpcmDecContext::queue_mutex), queue_mutex_attr);
+ error_code ret = lv2_syscall(ppu, handle.ptr(&LpcmDecContext::queue_size_mutex), mutex_attr);
+ ret = ret ? ret : lv2_syscall(ppu, handle.ptr(&LpcmDecContext::queue_size_cond), handle->queue_size_mutex, cond_attr);
+ ret = ret ? ret : lv2_syscall(ppu, handle.ptr(&LpcmDecContext::unk_mutex), mutex_attr);
+ ret = ret ? ret : lv2_syscall(ppu, handle.ptr(&LpcmDecContext::unk_cond), handle->unk_mutex, cond_attr);
+ ret = ret ? ret : lv2_syscall(ppu, handle.ptr(&LpcmDecContext::output_mutex), output_mutex_attr);
+ ret = ret ? ret : lv2_syscall(ppu, handle.ptr(&LpcmDecContext::output_consumed), handle->output_mutex, cond_attr);
+ ret = ret ? ret : lv2_syscall(ppu, handle.ptr(&LpcmDecContext::queue_mutex), queue_mutex_attr);
ret = ret ? ret : handle->release_output(ppu);
ret = ret ? ret : handle->cmd_available.init(ppu, handle.ptr(&LpcmDecContext::cmd_available), 0);
ret = ret ? ret : handle->reserved2.init(ppu, handle.ptr(&LpcmDecContext::reserved2), 0);
@@ -844,8 +844,8 @@ error_code _CellAdecCoreOpOpenExt_lpcm(ppu_thread& ppu, vm::ptr
const auto entry = g_fxo->get().func_addr(FIND_FUNC(lpcmDecEntry));
ret = ppu_execute<&sys_ppu_thread_create>(ppu, handle.ptr(&LpcmDecContext::thread_id), entry, handle.addr(), +res->ppuThreadPriority, +res->ppuThreadStackSize, SYS_PPU_THREAD_CREATE_JOINABLE, +_name);
- ret = ret ? ret : sys_mutex_create(ppu, handle.ptr(&LpcmDecContext::spurs_queue_pop_mutex), mutex_attr);
- ret = ret ? ret : sys_mutex_create(ppu, handle.ptr(&LpcmDecContext::spurs_queue_push_mutex), mutex_attr);
+ ret = ret ? ret : lv2_syscall(ppu, handle.ptr(&LpcmDecContext::spurs_queue_pop_mutex), mutex_attr);
+ ret = ret ? ret : lv2_syscall(ppu, handle.ptr(&LpcmDecContext::spurs_queue_push_mutex), mutex_attr);
return ret;
}
@@ -865,8 +865,8 @@ error_code _CellAdecCoreOpClose_lpcm(ppu_thread& ppu, vm::ptr ha
cellAdec.notice("_CellAdecCoreOpClose_lpcm(handle=*0x%x)", handle);
- if (error_code ret = sys_mutex_lock(ppu, handle->queue_size_mutex, 0); ret != CELL_OK
- || (ret = sys_mutex_lock(ppu, handle->queue_mutex, 0)) != CELL_OK)
+ if (error_code ret = lv2_syscall(ppu, handle->queue_size_mutex, 0); ret != CELL_OK
+ || (ret = lv2_syscall(ppu, handle->queue_mutex, 0)) != CELL_OK)
{
return ret;
}
@@ -875,14 +875,14 @@ error_code _CellAdecCoreOpClose_lpcm(ppu_thread& ppu, vm::ptr ha
{
handle->cmd_queue.emplace(LpcmDecCmdType::close);
- if (error_code ret = sys_mutex_unlock(ppu, handle->queue_mutex); ret != CELL_OK)
+ if (error_code ret = lv2_syscall(ppu, handle->queue_mutex); ret != CELL_OK)
{
return ret; // LLE doesn't unlock the queue size mutex
}
if (error_code ret = handle->cmd_available.release(ppu); ret != CELL_OK)
{
- ensure(sys_mutex_unlock(ppu, handle->queue_size_mutex) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, handle->queue_size_mutex) == CELL_OK); // Error code isn't checked on LLE
return ret;
}
}
@@ -893,29 +893,29 @@ error_code _CellAdecCoreOpClose_lpcm(ppu_thread& ppu, vm::ptr ha
cmd.type = LpcmDecCmdType::close;
}
- if (error_code ret = sys_mutex_unlock(ppu, handle->queue_mutex); ret != CELL_OK)
+ if (error_code ret = lv2_syscall(ppu, handle->queue_mutex); ret != CELL_OK)
{
return ret; // LLE doesn't unlock the queue size mutex
}
}
- error_code ret = sys_mutex_unlock(ppu, handle->queue_size_mutex);
+ error_code ret = lv2_syscall(ppu, handle->queue_size_mutex);
ret = ret ? ret : handle->release_output(ppu);
vm::var thread_ret;
- ret = ret ? ret : sys_ppu_thread_join(ppu, static_cast(handle->thread_id), +thread_ret);
+ ret = ret ? ret : lv2_syscall(ppu, static_cast(handle->thread_id), +thread_ret);
- ret = ret ? ret : sys_cond_destroy(ppu, handle->queue_size_cond);
- ret = ret ? ret : sys_cond_destroy(ppu, handle->unk_cond);
- ret = ret ? ret : sys_cond_destroy(ppu, handle->output_consumed);
- ret = ret ? ret : sys_mutex_destroy(ppu, handle->queue_mutex);
- ret = ret ? ret : sys_mutex_destroy(ppu, handle->queue_size_mutex);
- ret = ret ? ret : sys_mutex_destroy(ppu, handle->unk_mutex);
- ret = ret ? ret : sys_mutex_destroy(ppu, handle->output_mutex);
+ ret = ret ? ret : lv2_syscall(ppu, handle->queue_size_cond);
+ ret = ret ? ret : lv2_syscall(ppu, handle->unk_cond);
+ ret = ret ? ret : lv2_syscall(ppu, handle->output_consumed);
+ ret = ret ? ret : lv2_syscall(ppu, handle->queue_mutex);
+ ret = ret ? ret : lv2_syscall(ppu, handle->queue_size_mutex);
+ ret = ret ? ret : lv2_syscall(ppu, handle->unk_mutex);
+ ret = ret ? ret : lv2_syscall(ppu, handle->output_mutex);
ret = ret ? ret : handle->cmd_available.finalize(ppu);
ret = ret ? ret : handle->reserved2.finalize(ppu);
- ret = ret ? ret : sys_mutex_destroy(ppu, handle->spurs_queue_pop_mutex);
- ret = ret ? ret : sys_mutex_destroy(ppu, handle->spurs_queue_push_mutex);
+ ret = ret ? ret : lv2_syscall(ppu, handle->spurs_queue_pop_mutex);
+ ret = ret ? ret : lv2_syscall(ppu, handle->spurs_queue_push_mutex);
return ret;
}
@@ -1091,11 +1091,11 @@ error_code AdecContext::set_pcm_item(s32 pcm_handle, vm::ptr pcm_addr, u32
error_code AdecContext::link_frame(ppu_thread& ppu, s32 pcm_handle)
{
- ensure(sys_mutex_lock(ppu, mutex, 0) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, mutex, 0) == CELL_OK); // Error code isn't checked on LLE
if (verify_pcm_handle(pcm_handle) == static_cast(CELL_ADEC_ERROR_FATAL))
{
- ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return CELL_ADEC_ERROR_FATAL;
}
@@ -1115,27 +1115,27 @@ error_code AdecContext::link_frame(ppu_thread& ppu, s32 pcm_handle)
}
else
{
- ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return CELL_ADEC_ERROR_FATAL;
}
- ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return CELL_OK;
}
error_code AdecContext::unlink_frame(ppu_thread& ppu, s32 pcm_handle)
{
- ensure(sys_mutex_lock(ppu, mutex, 0) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, mutex, 0) == CELL_OK); // Error code isn't checked on LLE
if (verify_pcm_handle(pcm_handle) == static_cast(CELL_ADEC_ERROR_FATAL))
{
- ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return CELL_ADEC_ERROR_FATAL;
}
if (frames_head == -1 || frames_tail == -1)
{
- ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return CELL_ADEC_ERROR_FATAL;
}
@@ -1146,7 +1146,7 @@ error_code AdecContext::unlink_frame(ppu_thread& ppu, s32 pcm_handle)
{
if (pcm_handle != frames_tail)
{
- ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return CELL_ADEC_ERROR_FATAL;
}
@@ -1171,7 +1171,7 @@ error_code AdecContext::unlink_frame(ppu_thread& ppu, s32 pcm_handle)
frames[prev].next = next;
}
- ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return CELL_OK;
}
@@ -1557,7 +1557,7 @@ error_code adecOpen(ppu_thread& ppu, vm::ptr type, vm::cptr(ppu, _this.ptr(&AdecContext::mutex), _this.ptr(&AdecContext::mutex_attribute)) == CELL_OK); // Error code isn't checked on LLE
*handle = _this;
@@ -1626,7 +1626,7 @@ error_code cellAdecClose(ppu_thread& ppu, vm::ptr handle)
return ret;
}
- if (error_code ret = sys_mutex_destroy(ppu, handle->mutex); ret != CELL_OK)
+ if (error_code ret = lv2_syscall(ppu, handle->mutex); ret != CELL_OK)
{
return ret;
}
diff --git a/rpcs3/Emu/Cell/Modules/cellAdec.h b/rpcs3/Emu/Cell/Modules/cellAdec.h
index a43c3f0aef..2216561516 100644
--- a/rpcs3/Emu/Cell/Modules/cellAdec.h
+++ b/rpcs3/Emu/Cell/Modules/cellAdec.h
@@ -485,6 +485,19 @@ struct AdecFrame
CHECK_SIZE(AdecFrame, 0x68);
+template
+static auto lv2_syscall(ppu_thread& ppu, auto&&... args)
+{
+ const auto ret = Syscall(ppu, std::forward(args)...);
+
+ if (ppu.test_stopped())
+ {
+ ppu.state += cpu_flag::again;
+ }
+
+ return ret;
+}
+
class AdecOutputQueue
{
struct entry
@@ -511,10 +524,10 @@ public:
this->size = 0;
const vm::var mutex_attr = {{ SYS_SYNC_PRIORITY, SYS_SYNC_NOT_RECURSIVE, SYS_SYNC_NOT_PROCESS_SHARED, SYS_SYNC_NOT_ADAPTIVE, 0, 0, 0, { "_adem07"_u64 } }};
- ensure(sys_mutex_create(ppu, _this.ptr(&AdecOutputQueue::mutex), mutex_attr) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, _this.ptr(&AdecOutputQueue::mutex), mutex_attr) == CELL_OK); // Error code isn't checked on LLE
const vm::var cond_attr = {{ SYS_SYNC_NOT_PROCESS_SHARED, 0, 0, { "_adec05"_u64 } }};
- ensure(sys_cond_create(ppu, _this.ptr(&AdecOutputQueue::cond), mutex, cond_attr) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, _this.ptr(&AdecOutputQueue::cond), mutex, cond_attr) == CELL_OK); // Error code isn't checked on LLE
for (s32 i = 0; i < 4; i++)
{
@@ -524,12 +537,12 @@ public:
error_code finalize(ppu_thread& ppu) const
{
- if (error_code ret = sys_cond_destroy(ppu, cond); ret != CELL_OK)
+ if (error_code ret = lv2_syscall(ppu, cond); ret != CELL_OK)
{
return ret;
}
- if (error_code ret = sys_mutex_destroy(ppu, mutex); ret != CELL_OK)
+ if (error_code ret = lv2_syscall(ppu, mutex); ret != CELL_OK)
{
return ret;
}
@@ -539,11 +552,11 @@ public:
error_code push(ppu_thread& ppu, vm::ptr pcm_item, s32 pcm_handle)
{
- ensure(sys_mutex_lock(ppu, mutex, 0) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, mutex, 0) == CELL_OK); // Error code isn't checked on LLE
if (entries[back].state != 0xff)
{
- ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return true; // LLE returns the result of the comparison above
}
@@ -554,13 +567,13 @@ public:
back = (back + 1) & 3;
size++;
- ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return CELL_OK;
}
const entry* pop(ppu_thread& ppu)
{
- ensure(sys_mutex_lock(ppu, mutex, 0) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, mutex, 0) == CELL_OK); // Error code isn't checked on LLE
if (ppu.state & cpu_flag::again) // Savestate was created while waiting on the mutex
{
@@ -569,7 +582,7 @@ public:
if (entries[front].state == 0xff)
{
- ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return nullptr;
}
@@ -581,15 +594,15 @@ public:
front = (front + 1) & 3;
size--;
- ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return ret;
}
const entry& peek(ppu_thread& ppu) const
{
- ensure(sys_mutex_lock(ppu, mutex, 0) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, mutex, 0) == CELL_OK); // Error code isn't checked on LLE
const entry& ret = entries[front];
- ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
+ ensure(lv2_syscall(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return ret;
}
};
@@ -708,39 +721,39 @@ public:
const vm::var mutex_attr{{ SYS_SYNC_PRIORITY, SYS_SYNC_NOT_RECURSIVE, SYS_SYNC_NOT_PROCESS_SHARED, SYS_SYNC_NOT_ADAPTIVE, 0, 0, 0, { "_adem01"_u64 } }};
const vm::var cond_attr{{ SYS_SYNC_NOT_PROCESS_SHARED, 0, 0, { "_adec01"_u64 } }};
- if (error_code ret = sys_mutex_create(ppu, _this.ptr(&LpcmDecSemaphore::mutex), mutex_attr); ret != CELL_OK)
+ if (error_code ret = lv2_syscall(ppu, _this.ptr(&LpcmDecSemaphore::mutex), mutex_attr); ret != CELL_OK)
{
return ret;
}
- return sys_cond_create(ppu, _this.ptr(&LpcmDecSemaphore::cond), mutex, cond_attr);
+ return lv2_syscall(ppu, _this.ptr(&LpcmDecSemaphore::cond), mutex, cond_attr);
}
error_code finalize(ppu_thread& ppu) const
{
- if (error_code ret = sys_cond_destroy(ppu, cond); ret != CELL_OK)
+ if (error_code ret = lv2_syscall(ppu, cond); ret != CELL_OK)
{
return ret;
}
- return sys_mutex_destroy(ppu, mutex);
+ return lv2_syscall(ppu, mutex);
}
error_code release(ppu_thread& ppu)
{
- if (error_code ret = sys_mutex_lock(ppu, mutex, 0); ret != CELL_OK)
+ if (error_code ret = lv2_syscall(ppu, mutex, 0); ret != CELL_OK)
{
return ret;
}
value++;
- if (error_code ret = sys_cond_signal(ppu, cond); ret != CELL_OK)
+ if (error_code ret = lv2_syscall(ppu, cond); ret != CELL_OK)
{
return ret; // LLE doesn't unlock the mutex
}
- return sys_mutex_unlock(ppu, mutex);
+ return lv2_syscall(ppu, mutex);
}
error_code acquire(ppu_thread& ppu, lpcm_dec_state& savestate)
@@ -752,7 +765,7 @@ public:
savestate = lpcm_dec_state::waiting_for_cmd_mutex_lock;
- if (error_code ret = sys_mutex_lock(ppu, mutex, 0); ret != CELL_OK)
+ if (error_code ret = lv2_syscall(ppu, mutex, 0); ret != CELL_OK)
{
return ret;
}
@@ -767,7 +780,7 @@ public:
savestate = lpcm_dec_state::waiting_for_cmd_cond_wait;
cond_wait:
- if (error_code ret = sys_cond_wait(ppu, cond, 0); ret != CELL_OK)
+ if (error_code ret = lv2_syscall(ppu, cond, 0); ret != CELL_OK)
{
return ret; // LLE doesn't unlock the mutex
}
@@ -780,7 +793,7 @@ public:
value--;
- return sys_mutex_unlock(ppu, mutex);
+ return lv2_syscall(ppu, mutex);
}
};
diff --git a/rpcs3/Emu/Cell/Modules/cellAtracXdec.cpp b/rpcs3/Emu/Cell/Modules/cellAtracXdec.cpp
index c55cf7b60f..fb3191bcb4 100644
--- a/rpcs3/Emu/Cell/Modules/cellAtracXdec.cpp
+++ b/rpcs3/Emu/Cell/Modules/cellAtracXdec.cpp
@@ -295,7 +295,7 @@ void AtracXdecContext::exec(ppu_thread& ppu)
{
savestate = atracxdec_state::initial;
- ensure(sys_mutex_lock(ppu, queue_mutex, 0) == CELL_OK);
+ ensure(lv2_syscall(ppu, queue_mutex, 0) == CELL_OK);
if (ppu.state & cpu_flag::again)
{
@@ -310,24 +310,24 @@ void AtracXdecContext::exec(ppu_thread& ppu)
savestate = atracxdec_state::waiting_for_cmd;
label1_wait_for_cmd_state:
- ensure(sys_cond_wait(ppu, queue_not_empty, 0) == CELL_OK);
+ ensure(lv2_syscall(ppu, queue_not_empty, 0) == CELL_OK);
if (ppu.state & cpu_flag::again)
{
return;
}
- ensure(sys_mutex_unlock(ppu, queue_mutex) == CELL_OK);
+ ensure(lv2_syscall(ppu, queue_mutex) == CELL_OK);
}
cmd_queue.pop(cmd);
- ensure(sys_mutex_unlock(ppu, queue_mutex) == CELL_OK);
+ ensure(lv2_syscall(ppu, queue_mutex) == CELL_OK);
savestate = atracxdec_state::checking_run_thread_1;
label2_check_run_thread_1_state:
- ensure(sys_mutex_lock(ppu, run_thread_mutex, 0) == CELL_OK);
+ ensure(lv2_syscall(ppu, run_thread_mutex, 0) == CELL_OK);
if (ppu.state & cpu_flag::again)
{
@@ -336,11 +336,11 @@ void AtracXdecContext::exec(ppu_thread& ppu)
if (!run_thread)
{
- ensure(sys_mutex_unlock(ppu, run_thread_mutex) == CELL_OK);
+ ensure(lv2_syscall(ppu, run_thread_mutex) == CELL_OK);
return;
}
- ensure(sys_mutex_unlock(ppu, run_thread_mutex) == CELL_OK);
+ ensure(lv2_syscall(ppu, run_thread_mutex) == CELL_OK);
savestate = atracxdec_state::executing_cmd;
label3_execute_cmd_state:
@@ -392,7 +392,7 @@ void AtracXdecContext::exec(ppu_thread& ppu)
cellAtracXdec.trace("Waiting for output to be consumed...");
- ensure(sys_mutex_lock(ppu, output_mutex, 0) == CELL_OK);
+ ensure(lv2_syscall(ppu, output_mutex, 0) == CELL_OK);
if (ppu.state & cpu_flag::again)
{
@@ -404,7 +404,7 @@ void AtracXdecContext::exec(ppu_thread& ppu)
savestate = atracxdec_state::waiting_for_output;
label4_wait_for_output_state:
- ensure(sys_cond_wait(ppu, output_consumed, 0) == CELL_OK);
+ ensure(lv2_syscall(ppu, output_consumed, 0) == CELL_OK);
if (ppu.state & cpu_flag::again)
{
@@ -417,7 +417,7 @@ void AtracXdecContext::exec(ppu_thread& ppu)
savestate = atracxdec_state::checking_run_thread_2;
label5_check_run_thread_2_state:
- ensure(sys_mutex_lock(ppu, run_thread_mutex, 0) == CELL_OK);
+ ensure(lv2_syscall(ppu, run_thread_mutex, 0) == CELL_OK);
if (ppu.state & cpu_flag::again)
{
@@ -426,12 +426,12 @@ void AtracXdecContext::exec(ppu_thread& ppu)
if (!run_thread)
{
- ensure(sys_mutex_unlock(ppu, run_thread_mutex) == CELL_OK);
- ensure(sys_mutex_unlock(ppu, output_mutex) == CELL_OK);
+ ensure(lv2_syscall(ppu, run_thread_mutex) == CELL_OK);
+ ensure(lv2_syscall(ppu, output_mutex) == CELL_OK);
return;
}
- ensure(sys_mutex_unlock(ppu, run_thread_mutex) == CELL_OK);
+ ensure(lv2_syscall(ppu, run_thread_mutex) == CELL_OK);
savestate = atracxdec_state::decoding;
label6_decode_state:
@@ -645,7 +645,7 @@ void AtracXdecContext::exec(ppu_thread& ppu)
notify_au_done.cbFunc(ppu, cmd.pcm_handle, notify_au_done.cbArg);
output_locked = true;
- ensure(sys_mutex_unlock(ppu, output_mutex) == CELL_OK);
+ ensure(lv2_syscall(ppu, output_mutex) == CELL_OK);
const u32 output_size = decoded_samples_num * (decoder.bw_pcm & 0x7fu) * decoder.nch_out;
@@ -680,7 +680,7 @@ error_code AtracXdecContext::send_command(ppu_thread& ppu, auto&&... args)
if (!signal)
{
- ensure(sys_mutex_lock(ppu, queue_mutex, 0) == CELL_OK);
+ ensure(lv2_syscall(ppu, queue_mutex, 0) == CELL_OK);
if (ppu.state & cpu_flag::again)
{
@@ -692,23 +692,23 @@ error_code AtracXdecContext::send_command(ppu_thread& ppu, auto&&... args)
// Close command is only sent if the queue is empty on LLE
if (!cmd_queue.empty())
{
- ensure(sys_mutex_unlock(ppu, queue_mutex) == CELL_OK);
+ ensure(lv2_syscall(ppu, queue_mutex) == CELL_OK);
return {};
}
}
if (cmd_queue.full())
{
- ensure(sys_mutex_unlock(ppu, queue_mutex) == CELL_OK);
+ ensure(lv2_syscall(ppu, queue_mutex) == CELL_OK);
return CELL_ADEC_ERROR_ATX_BUSY;
}
cmd_queue.emplace(std::forward(type), std::forward(args)...);
- ensure(sys_mutex_unlock(ppu, queue_mutex) == CELL_OK);
+ ensure(lv2_syscall(ppu, queue_mutex) == CELL_OK);
}
- ensure(sys_cond_signal(ppu, queue_not_empty) == CELL_OK);
+ ensure(lv2_syscall(ppu, queue_not_empty) == CELL_OK);
if (ppu.state & cpu_flag::again)
{
@@ -779,25 +779,25 @@ error_code _CellAdecCoreOpOpenExt_atracx(ppu_thread& ppu, vm::ptr mutex_attr{{ SYS_SYNC_PRIORITY, SYS_SYNC_NOT_RECURSIVE, SYS_SYNC_NOT_PROCESS_SHARED, SYS_SYNC_NOT_ADAPTIVE, 0, 0, 0, { "_atd001"_u64 } }};
const vm::var cond_attr{{ SYS_SYNC_NOT_PROCESS_SHARED, 0, 0, { "_atd002"_u64 } }};
- ensure(sys_mutex_create(ppu, handle.ptr(&AtracXdecContext::queue_mutex), mutex_attr) == CELL_OK);
- ensure(sys_cond_create(ppu, handle.ptr(&AtracXdecContext::queue_not_empty), handle->queue_mutex, cond_attr) == CELL_OK);
+ ensure(lv2_syscall(ppu, handle.ptr(&AtracXdecContext::queue_mutex), mutex_attr) == CELL_OK);
+ ensure(lv2_syscall(ppu, handle.ptr(&AtracXdecContext::queue_not_empty), handle->queue_mutex, cond_attr) == CELL_OK);
mutex_attr->name_u64 = "_atd003"_u64;
cond_attr->name_u64 = "_atd004"_u64;
- ensure(sys_mutex_create(ppu, handle.ptr(&AtracXdecContext::run_thread_mutex), mutex_attr) == CELL_OK);
- ensure(sys_cond_create(ppu, handle.ptr(&AtracXdecContext::run_thread_cond), handle->run_thread_mutex, cond_attr) == CELL_OK);
+ ensure(lv2_syscall(ppu, handle.ptr(&AtracXdecContext::run_thread_mutex), mutex_attr) == CELL_OK);
+ ensure(lv2_syscall(ppu, handle.ptr(&AtracXdecContext::run_thread_cond), handle->run_thread_mutex, cond_attr) == CELL_OK);
mutex_attr->name_u64 = "_atd005"_u64;
cond_attr->name_u64 = "_atd006"_u64;
- ensure(sys_mutex_create(ppu, handle.ptr(&AtracXdecContext::output_mutex), mutex_attr) == CELL_OK);
- ensure(sys_cond_create(ppu, handle.ptr(&AtracXdecContext::output_consumed), handle->output_mutex, cond_attr) == CELL_OK);
+ ensure(lv2_syscall(ppu, handle.ptr(&AtracXdecContext::output_mutex), mutex_attr) == CELL_OK);
+ ensure(lv2_syscall(ppu, handle.ptr(&AtracXdecContext::output_consumed), handle->output_mutex, cond_attr) == CELL_OK);
- ensure(sys_mutex_lock(ppu, handle->output_mutex, 0) == CELL_OK);
+ ensure(lv2_syscall(ppu, handle->output_mutex, 0) == CELL_OK);
handle->output_locked = false;
- ensure(sys_cond_signal(ppu, handle->output_consumed) == CELL_OK);
- ensure(sys_mutex_unlock(ppu, handle->output_mutex) == CELL_OK);
+ ensure(lv2_syscall(ppu, handle->output_consumed) == CELL_OK);
+ ensure(lv2_syscall(ppu, handle->output_mutex) == CELL_OK);
const vm::var _name = vm::make_str("HLE ATRAC3plus decoder");
const auto entry = g_fxo->get().func_addr(FIND_FUNC(atracXdecEntry));
@@ -829,26 +829,26 @@ error_code _CellAdecCoreOpClose_atracx(ppu_thread& ppu, vm::ptrrun_thread_mutex, 0) == CELL_OK);
+ ensure(lv2_syscall(ppu, handle->run_thread_mutex, 0) == CELL_OK);
handle->run_thread = false;
- ensure(sys_mutex_unlock(ppu, handle->run_thread_mutex) == CELL_OK);
+ ensure(lv2_syscall(ppu, handle->run_thread_mutex) == CELL_OK);
handle->send_command(ppu);
- ensure(sys_mutex_lock(ppu, handle->output_mutex, 0) == CELL_OK);
+ ensure(lv2_syscall(ppu, handle->output_mutex, 0) == CELL_OK);
handle->output_locked = false;
- ensure(sys_mutex_unlock(ppu, handle->output_mutex) == CELL_OK);
- ensure(sys_cond_signal(ppu, handle->output_consumed) == CELL_OK);
+ ensure(lv2_syscall(ppu, handle->output_mutex) == CELL_OK);
+ ensure(lv2_syscall(ppu, handle->output_consumed) == CELL_OK);
vm::var thread_ret;
- ensure(sys_ppu_thread_join(ppu, static_cast(handle->thread_id), +thread_ret) == CELL_OK);
+ ensure(lv2_syscall(ppu, static_cast(handle->thread_id), +thread_ret) == CELL_OK);
- error_code ret = sys_cond_destroy(ppu, handle->queue_not_empty);
- ret = ret ? ret : sys_cond_destroy(ppu, handle->run_thread_cond);
- ret = ret ? ret : sys_cond_destroy(ppu, handle->output_consumed);
- ret = ret ? ret : sys_mutex_destroy(ppu, handle->queue_mutex);
- ret = ret ? ret : sys_mutex_destroy(ppu, handle->run_thread_mutex);
- ret = ret ? ret : sys_mutex_destroy(ppu, handle->output_mutex);
+ error_code ret = lv2_syscall(ppu, handle->queue_not_empty);
+ ret = ret ? ret : lv2_syscall(ppu, handle->run_thread_cond);
+ ret = ret ? ret : lv2_syscall(ppu, handle->output_consumed);
+ ret = ret ? ret : lv2_syscall(ppu, handle->queue_mutex);
+ ret = ret ? ret : lv2_syscall(ppu, handle->run_thread_mutex);
+ ret = ret ? ret : lv2_syscall(ppu, handle->output_mutex);
return ret != CELL_OK ? static_cast(CELL_ADEC_ERROR_FATAL) : CELL_OK;
}
@@ -921,7 +921,7 @@ error_code _CellAdecCoreOpReleasePcm_atracx(ppu_thread& ppu, vm::ptroutput_mutex, 0) == CELL_OK);
+ ensure(lv2_syscall(ppu, handle->output_mutex, 0) == CELL_OK);
if (ppu.state & cpu_flag::again)
{
@@ -931,7 +931,7 @@ error_code _CellAdecCoreOpReleasePcm_atracx(ppu_thread& ppu, vm::ptroutput_locked = false;
}
- ensure(sys_cond_signal(ppu, handle->output_consumed) == CELL_OK);
+ ensure(lv2_syscall(ppu, handle->output_consumed) == CELL_OK);
if (ppu.state & cpu_flag::again)
{
@@ -939,7 +939,7 @@ error_code _CellAdecCoreOpReleasePcm_atracx(ppu_thread& ppu, vm::ptroutput_mutex) == CELL_OK);
+ ensure(lv2_syscall(ppu, handle->output_mutex) == CELL_OK);
return CELL_OK;
}
diff --git a/rpcs3/Emu/Cell/Modules/cellCamera.cpp b/rpcs3/Emu/Cell/Modules/cellCamera.cpp
index 096f9330f4..10f9a89cf0 100644
--- a/rpcs3/Emu/Cell/Modules/cellCamera.cpp
+++ b/rpcs3/Emu/Cell/Modules/cellCamera.cpp
@@ -919,7 +919,7 @@ error_code cellCameraGetAttribute(s32 dev_num, s32 attrib, vm::ptr arg1, vm
if (!check_dev_num(dev_num))
{
- return CELL_CAMERA_ERROR_PARAM;
+ return { CELL_CAMERA_ERROR_PARAM, "dev_num=%d", dev_num };
}
if (g_cfg.io.camera == camera_handler::null)
@@ -935,7 +935,7 @@ error_code cellCameraGetAttribute(s32 dev_num, s32 attrib, vm::ptr arg1, vm
if (!arg1)
{
- return CELL_CAMERA_ERROR_PARAM;
+ return { CELL_CAMERA_ERROR_PARAM, "arg1=null" };
}
if (error_code error = check_resolution(dev_num))
@@ -952,7 +952,7 @@ error_code cellCameraGetAttribute(s32 dev_num, s32 attrib, vm::ptr