diff --git a/.ci/build-freebsd.sh b/.ci/build-freebsd.sh index 3244f1a3cf..7f35412b58 100755 --- a/.ci/build-freebsd.sh +++ b/.ci/build-freebsd.sh @@ -1,9 +1,10 @@ #!/bin/sh -ex -# Pull all the submodules except llvm, opencv, libpng, sdl and curl +# Pull all the submodules except some # Note: Tried to use git submodule status, but it takes over 20 seconds # shellcheck disable=SC2046 -git submodule -q update --init --depth 1 $(awk '/path/ && !/llvm/ && !/opencv/ && !/libpng/ && !/libsdl-org/ && !/curl/ { print $3 }' .gitmodules) +git config --global --add safe.directory . +git submodule -q update --init --depth 1 $(awk '/path/ && !/llvm/ && !/opencv/ && !/libpng/ && !/libsdl-org/ && !/curl/ && !/zlib/ && !/libusb/ { print $3 }' .gitmodules) CONFIGURE_ARGS=" -DWITH_LLVM=ON @@ -13,6 +14,7 @@ CONFIGURE_ARGS=" -DUSE_SYSTEM_FFMPEG=ON -DUSE_SYSTEM_CURL=ON -DUSE_SYSTEM_LIBPNG=ON + -DUSE_SYSTEM_LIBUSB=ON -DUSE_SYSTEM_OPENCV=ON " diff --git a/.ci/build-linux-aarch64.sh b/.ci/build-linux-aarch64.sh index e067f23445..1fe640809c 100755 --- a/.ci/build-linux-aarch64.sh +++ b/.ci/build-linux-aarch64.sh @@ -1,16 +1,14 @@ #!/bin/sh -ex -if [ -z "$CIRRUS_CI" ]; then - cd rpcs3 || exit 1 -fi +cd rpcs3 || exit 1 shellcheck .ci/*.sh git config --global --add safe.directory '*' -# Pull all the submodules except llvm, opencv, sdl and curl +# Pull all the submodules except some # shellcheck disable=SC2046 -git submodule -q update --init $(awk '/path/ && !/llvm/ && !/opencv/ && !/libsdl-org/ && !/curl/ { print $3 }' .gitmodules) +git submodule -q update --init $(awk '/path/ && !/llvm/ && !/opencv/ && !/libsdl-org/ && !/curl/ && !/zlib/ { print $3 }' .gitmodules) mkdir build && cd build || exit 1 @@ -52,10 +50,6 @@ ninja; build_status=$?; cd .. # If it compiled succesfully let's deploy. -# Azure and Cirrus publish PRs as artifacts only. -{ [ "$CI_HAS_ARTIFACTS" = "true" ]; -} && SHOULD_DEPLOY="true" || SHOULD_DEPLOY="false" - -if [ "$build_status" -eq 0 ] && [ "$SHOULD_DEPLOY" = "true" ]; then +if [ "$build_status" -eq 0 ]; then .ci/deploy-linux.sh "aarch64" fi diff --git a/.ci/build-linux.sh b/.ci/build-linux.sh index 4d9e9d0d09..13a9e802f3 100755 --- a/.ci/build-linux.sh +++ b/.ci/build-linux.sh @@ -1,17 +1,15 @@ #!/bin/sh -ex -if [ -z "$CIRRUS_CI" ]; then - cd rpcs3 || exit 1 -fi +cd rpcs3 || exit 1 shellcheck .ci/*.sh git config --global --add safe.directory '*' -# Pull all the submodules except llvm, opencv, sdl and curl +# Pull all the submodules except some # Note: Tried to use git submodule status, but it takes over 20 seconds # shellcheck disable=SC2046 -git submodule -q update --init $(awk '/path/ && !/llvm/ && !/opencv/ && !/libsdl-org/ && !/curl/ { print $3 }' .gitmodules) +git submodule -q update --init $(awk '/path/ && !/llvm/ && !/opencv/ && !/libsdl-org/ && !/curl/ && !/zlib/ { print $3 }' .gitmodules) mkdir build && cd build || exit 1 @@ -63,10 +61,6 @@ ninja; build_status=$?; cd .. # If it compiled succesfully let's deploy. -# Azure and Cirrus publish PRs as artifacts only. -{ [ "$CI_HAS_ARTIFACTS" = "true" ]; -} && SHOULD_DEPLOY="true" || SHOULD_DEPLOY="false" - -if [ "$build_status" -eq 0 ] && [ "$SHOULD_DEPLOY" = "true" ]; then +if [ "$build_status" -eq 0 ]; then .ci/deploy-linux.sh "x86_64" fi diff --git a/.ci/build-mac-arm64.sh b/.ci/build-mac-arm64.sh index d1b48c03f9..3c9c864031 100755 --- a/.ci/build-mac-arm64.sh +++ b/.ci/build-mac-arm64.sh @@ -6,14 +6,14 @@ export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 export HOMEBREW_NO_ENV_HINTS=1 export HOMEBREW_NO_INSTALL_CLEANUP=1 -/opt/homebrew/bin/brew install -f --overwrite --quiet nasm ninja p7zip ccache pipenv gnutls freetype #create-dmg +/opt/homebrew/bin/brew install -f --overwrite --quiet nasm ninja p7zip ccache pipenv gnutls freetype googletest #create-dmg /opt/homebrew/bin/brew install -f --quiet ffmpeg@5 /opt/homebrew/bin/brew install --quiet "llvm@$LLVM_COMPILER_VER" glew cmake sdl3 vulkan-headers coreutils /opt/homebrew/bin/brew link -f --quiet "llvm@$LLVM_COMPILER_VER" ffmpeg@5 # moltenvk based on commit for 1.3.0 release wget https://raw.githubusercontent.com/Homebrew/homebrew-core/7255441cbcafabaa8950f67c7ec55ff499dbb2d3/Formula/m/molten-vk.rb -/opt/homebrew/bin/brew install -f --overwrite --formula --quiet ./molten-vk.rb +/opt/homebrew/bin/brew install -f --overwrite --formula --quiet ./molten-vk.rb export CXX=clang++ export CC=clang @@ -32,7 +32,7 @@ if [ ! -d "/tmp/Qt/$QT_VER" ]; then git clone https://github.com/engnr/qt-downloader.git cd qt-downloader git checkout f52efee0f18668c6d6de2dec0234b8c4bc54c597 - # nested Qt 6.9.0 URL workaround + # nested Qt 6.9.1 URL workaround # sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader # sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader # archived Qt 6.7.3 URL workaround @@ -41,7 +41,7 @@ if [ ! -d "/tmp/Qt/$QT_VER" ]; then arch -arm64 "$BREW_PATH/bin/pipenv" run pip3 uninstall py7zr requests semantic_version lxml arch -arm64 "$BREW_PATH/bin/pipenv" run pip3 install py7zr requests semantic_version lxml --no-cache mkdir -p "$QT_VER/macos" ; ln -s "macos" "$QT_VER/clang_64" - # sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader" # Qt 6.9.0 workaround + # sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader" # Qt 6.9.1 workaround arch -arm64 "$BREW_PATH/bin/pipenv" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats # -o "$QT_VER/clang_64" fi @@ -77,8 +77,8 @@ mkdir build && cd build || exit 1 export MACOSX_DEPLOYMENT_TARGET=14.0 "$BREW_PATH/bin/cmake" .. \ - -DBUILD_RPCS3_TESTS=OFF \ - -DRUN_RPCS3_TESTS=OFF \ + -DBUILD_RPCS3_TESTS="${RUN_UNIT_TESTS}" \ + -DRUN_RPCS3_TESTS="${RUN_UNIT_TESTS}" \ -DUSE_SDL=ON \ -DUSE_DISCORD_RPC=ON \ -DUSE_VULKAN=ON \ @@ -115,9 +115,7 @@ export MACOSX_DEPLOYMENT_TARGET=14.0 cd .. -{ [ "$CI_HAS_ARTIFACTS" = "true" ]; -} && SHOULD_DEPLOY="true" || SHOULD_DEPLOY="false" - -if [ "$build_status" -eq 0 ] && [ "$SHOULD_DEPLOY" = "true" ]; then +# If it compiled succesfully let's deploy. +if [ "$build_status" -eq 0 ]; then .ci/deploy-mac-arm64.sh fi diff --git a/.ci/build-mac.sh b/.ci/build-mac.sh index 675811539e..1e6bae01a1 100755 --- a/.ci/build-mac.sh +++ b/.ci/build-mac.sh @@ -36,7 +36,7 @@ if [ ! -d "/tmp/Qt/$QT_VER" ]; then git clone https://github.com/engnr/qt-downloader.git cd qt-downloader git checkout f52efee0f18668c6d6de2dec0234b8c4bc54c597 - # nested Qt 6.9.0 URL workaround + # nested Qt 6.9.1 URL workaround # sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader # sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader # archived Qt 6.7.3 URL workaround @@ -44,7 +44,7 @@ if [ ! -d "/tmp/Qt/$QT_VER" ]; then cd "/tmp/Qt" arch -x86_64 "$BREW_X64_PATH/bin/pipenv" --python "$BREW_X64_PATH/bin/python3" run pip3 install py7zr requests semantic_version lxml mkdir -p "$QT_VER/macos" ; ln -s "macos" "$QT_VER/clang_64" - # sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader" # Qt 6.9.0 workaround + # sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader" # Qt 6.9.1 workaround arch -x86_64 "$BREW_X64_PATH/bin/pipenv" --python "$BREW_X64_PATH/bin/python3" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats # -o "$QT_VER/clang_64" fi @@ -118,9 +118,7 @@ export MACOSX_DEPLOYMENT_TARGET=14.0 cd .. -{ [ "$CI_HAS_ARTIFACTS" = "true" ]; -} && SHOULD_DEPLOY="true" || SHOULD_DEPLOY="false" - -if [ "$build_status" -eq 0 ] && [ "$SHOULD_DEPLOY" = "true" ]; then +# If it compiled succesfully let's deploy. +if [ "$build_status" -eq 0 ]; then .ci/deploy-mac.sh fi diff --git a/.ci/build-windows-clang.sh b/.ci/build-windows-clang.sh new file mode 100644 index 0000000000..0880e7f5ed --- /dev/null +++ b/.ci/build-windows-clang.sh @@ -0,0 +1,61 @@ +#!/bin/sh -ex + +git config --global --add safe.directory '*' + +# Pull all the submodules except some +# Note: Tried to use git submodule status, but it takes over 20 seconds +# shellcheck disable=SC2046 +git submodule -q update --init $(awk '/path/ && !/llvm/ && !/opencv/ && !/ffmpeg/ && !/curl/ && !/FAudio/ && !/zlib/ { print $3 }' .gitmodules) + +mkdir build && cd build || exit 1 + +export CC="clang" +export CXX="clang++" +export LINKER=lld +export LINKER_FLAG="-fuse-ld=${LINKER}" + +if [ -n "$LLVMVER" ]; then + export AR="llvm-ar-$LLVMVER" + export RANLIB="llvm-ranlib-$LLVMVER" +else + export AR="llvm-ar" + export RANLIB="llvm-ranlib" +fi + +cmake .. \ + -DCMAKE_PREFIX_PATH=/clang64 \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DUSE_NATIVE_INSTRUCTIONS=OFF \ + -DUSE_PRECOMPILED_HEADERS=OFF \ + -DCMAKE_C_FLAGS="$CFLAGS" \ + -DCMAKE_CXX_FLAGS="$CFLAGS" \ + -DCMAKE_EXE_LINKER_FLAGS="${LINKER_FLAG}" \ + -DCMAKE_MODULE_LINKER_FLAGS="${LINKER_FLAG}" \ + -DCMAKE_SHARED_LINKER_FLAGS="${LINKER_FLAG}" \ + -DCMAKE_AR="$AR" \ + -DCMAKE_RANLIB="$RANLIB" \ + -DUSE_SYSTEM_CURL=ON \ + -DUSE_FAUDIO=OFF \ + -DUSE_SDL=ON \ + -DUSE_SYSTEM_SDL=OFF \ + -DUSE_SYSTEM_FFMPEG=ON \ + -DUSE_SYSTEM_OPENCV=ON \ + -DUSE_SYSTEM_OPENAL=OFF \ + -DUSE_DISCORD_RPC=ON \ + -DOpenGL_GL_PREFERENCE=LEGACY \ + -DWITH_LLVM=ON \ + -DLLVM_DIR=/clang64/lib/cmake/llvm \ + -DVulkan_LIBRARY=/clang64/lib/libvulkan-1.dll.a \ + -DSTATIC_LINK_LLVM=ON \ + -DBUILD_RPCS3_TESTS=OFF \ + -DRUN_RPCS3_TESTS=OFF \ + -G Ninja + +ninja; build_status=$?; + +cd .. + +# If it compiled succesfully let's deploy. +if [ "$build_status" -eq 0 ]; then + .ci/deploy-windows-clang.sh "x86_64" +fi diff --git a/.ci/deploy-linux.sh b/.ci/deploy-linux.sh index 5f0fe2ef8c..f8c3d849c3 100755 --- a/.ci/deploy-linux.sh +++ b/.ci/deploy-linux.sh @@ -26,9 +26,6 @@ if [ "$DEPLOY_APPIMAGE" = "true" ]; then rm -f ./AppDir/usr/lib/libvulkan.so* # Remove unused Qt6 libraries - rm -f ./AppDir/usr/lib/libQt6OpenGL.so* - rm -f ./AppDir/usr/lib/libQt6Qml*.so* - rm -f ./AppDir/usr/lib/libQt6Quick.so* rm -f ./AppDir/usr/lib/libQt6VirtualKeyboard.so* rm -f ./AppDir/usr/plugins/platforminputcontexts/libqtvirtualkeyboardplugin.so* diff --git a/.ci/deploy-llvm.sh b/.ci/deploy-llvm.sh new file mode 100644 index 0000000000..35e5d780af --- /dev/null +++ b/.ci/deploy-llvm.sh @@ -0,0 +1,20 @@ +#!/bin/sh -ex + +# First let's print some info about our caches +"$(cygpath -u "$CCACHE_BIN_DIR")"/ccache.exe --show-stats -v + +# BUILD_blablabla is Azure specific, so we wrap it for portability +ARTIFACT_DIR="$BUILD_ARTIFACTSTAGINGDIRECTORY" +BUILD="llvmlibs_mt.7z" + +# Package artifacts +7z a -m0=LZMA2 -mx9 "$BUILD" ./build/lib/Release-x64/llvm_build + +# Generate sha256 hashes +# Write to file for GitHub releases +sha256sum "$BUILD" | awk '{ print $1 }' | tee "$BUILD.sha256" +echo "$(cat "$BUILD.sha256");$(stat -c %s "$BUILD")B" > GitHubReleaseMessage.txt + +# Move files to publishing directory +cp -- "$BUILD" "$ARTIFACT_DIR" +cp -- "$BUILD.sha256" "$ARTIFACT_DIR" diff --git a/.ci/deploy-windows-clang.sh b/.ci/deploy-windows-clang.sh new file mode 100644 index 0000000000..d45cb45acf --- /dev/null +++ b/.ci/deploy-windows-clang.sh @@ -0,0 +1,38 @@ +#!/bin/sh -ex + +# source ci-vars.env +# shellcheck disable=SC1091 +. .ci/ci-vars.env + +cd build || exit 1 + +CPU_ARCH="${1:-x86_64}" + +echo "Deploying rpcs3 windows clang $CPU_ARCH" + +# BUILD_blablabla is CI specific, so we wrap it for portability +ARTIFACT_DIR=$(cygpath -u "$BUILD_ARTIFACTSTAGINGDIRECTORY") +MSYS2_CLANG_BIN=$(cygpath -w /clang64/bin) +MSYS2_USR_BIN=$(cygpath -w /usr/bin) + +echo "Installing dependencies of: ./bin/rpcs3.exe (MSYS2 dir is '$MSYS2_CLANG_BIN', usr dir is '$MSYS2_USR_BIN')" +cmake -DMSYS2_CLANG_BIN="$MSYS2_CLANG_BIN" -DMSYS2_USR_BIN="$MSYS2_USR_BIN" -Dexe=./bin/rpcs3.exe -P ../buildfiles/cmake/CopyRuntimeDependencies.cmake + +# Prepare compatibility and SDL database for packaging +mkdir ./bin/config +mkdir ./bin/config/input_configs +curl -fsSL 'https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt' 1> ./bin/config/input_configs/gamecontrollerdb.txt +curl -fsSL 'https://rpcs3.net/compatibility?api=v1&export' | iconv -t UTF-8 1> ./bin/GuiConfigs/compat_database.dat + +# Package artifacts +7z a -m0=LZMA2 -mx9 "$BUILD" ./bin/* + +# Generate sha256 hashes +# Write to file for GitHub releases +sha256sum "$BUILD" | awk '{ print $1 }' | tee "$BUILD.sha256" +echo "$(cat "$BUILD.sha256");$(stat -c %s "$BUILD")B" > GitHubReleaseMessage.txt + +# Move files to publishing directory +mkdir -p "$ARTIFACT_DIR" +cp -- "$BUILD" "$ARTIFACT_DIR" +cp -- "$BUILD.sha256" "$ARTIFACT_DIR" diff --git a/.ci/deploy-windows.sh b/.ci/deploy-windows.sh index bb1212f586..b885831511 100755 --- a/.ci/deploy-windows.sh +++ b/.ci/deploy-windows.sh @@ -1,9 +1,9 @@ #!/bin/sh -ex -# First let's see print some info about our caches +# First let's print some info about our caches "$(cygpath -u "$CCACHE_BIN_DIR")"/ccache.exe --show-stats -v -# BUILD_blablabla is Azure specific, so we wrap it for portability +# BUILD_blablabla is CI specific, so we wrap it for portability ARTIFACT_DIR="$BUILD_ARTIFACTSTAGINGDIRECTORY" # Remove unecessary files diff --git a/.ci/docker.env b/.ci/docker.env index ee037bfb4d..eb70b68c18 100644 --- a/.ci/docker.env +++ b/.ci/docker.env @@ -1,5 +1,4 @@ -# Variables set by Azure Pipelines -CI_HAS_ARTIFACTS +# Variables set by CI BUILD_REASON BUILD_SOURCEVERSION BUILD_ARTIFACTSTAGINGDIRECTORY diff --git a/.ci/export-azure-vars.sh b/.ci/export-azure-vars.sh deleted file mode 100755 index 033dd41cc8..0000000000 --- a/.ci/export-azure-vars.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -e - -# Export variables for later stages of the Azure pipeline -# Values done in this manner will appear as environment variables -# in later stages. - -# From pure-sh-bible -# Setting 'IFS' tells 'read' where to split the string. -while IFS='=' read -r key val; do - # Skip over lines containing comments. - [ "${key##\#*}" ] || continue - echo "##vso[task.setvariable variable=$key]$val" -done < ".ci/ci-vars.env" diff --git a/.ci/export-cirrus-vars.sh b/.ci/export-cirrus-vars.sh deleted file mode 100755 index 561e77e92f..0000000000 --- a/.ci/export-cirrus-vars.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -e - -# Export variables for later stages of the Cirrus pipeline -# Values done in this manner will appear as environment variables -# in later stages. - -# From pure-sh-bible -# Setting 'IFS' tells 'read' where to split the string. -while IFS='=' read -r key val; do - # Skip over lines containing comments. - [ "${key##\#*}" ] || continue - export "$key"="$val" -done < ".ci/ci-vars.env" diff --git a/.ci/install-freebsd.sh b/.ci/install-freebsd.sh index de10561dfa..04efc6c0e9 100755 --- a/.ci/install-freebsd.sh +++ b/.ci/install-freebsd.sh @@ -15,4 +15,4 @@ pkg install "llvm$LLVM_COMPILER_VER" pkg install git ccache cmake ninja "qt$QT_VER_MAIN-multimedia" "qt$QT_VER_MAIN-svg" glew openal-soft ffmpeg # Optional dependencies (libevdev is pulled by qtX-base) -pkg install pkgconf alsa-lib pulseaudio sdl3 evdev-proto vulkan-headers vulkan-loader +pkg install pkgconf alsa-lib pulseaudio sdl3 evdev-proto vulkan-headers vulkan-loader opencv diff --git a/.ci/setup-llvm.sh b/.ci/setup-llvm.sh new file mode 100644 index 0000000000..a54901309e --- /dev/null +++ b/.ci/setup-llvm.sh @@ -0,0 +1,63 @@ +#!/bin/sh -ex + +# Resource/dependency URLs +CCACHE_URL="https://github.com/ccache/ccache/releases/download/v4.11.2/ccache-4.11.2-windows-x86_64.zip" + +DEP_URLS=" \ + $CCACHE_URL" + +# CI doesn't make a cache dir if it doesn't exist, so we do it manually +[ -d "$DEPS_CACHE_DIR" ] || mkdir "$DEPS_CACHE_DIR" + +# Pull the llvm submodule +# shellcheck disable=SC2046 +git submodule -q update --init --depth=1 -- 3rdparty/llvm + +# Git bash doesn't have rev, so here it is +rev() +{ + echo "$1" | awk '{ for(i = length($0); i != 0; --i) { a = a substr($0, i, 1); } } END { print a }' +} + +# Usage: download_and_verify url checksum algo file +# Check to see if a file is already cached, and the checksum matches. If not, download it. +# Tries up to 3 times +download_and_verify() +{ + url="$1" + correctChecksum="$2" + algo="$3" + fileName="$4" + + for _ in 1 2 3; do + [ -e "$DEPS_CACHE_DIR/$fileName" ] || curl -fLo "$DEPS_CACHE_DIR/$fileName" "$url" + fileChecksum=$("${algo}sum" "$DEPS_CACHE_DIR/$fileName" | awk '{ print $1 }') + [ "$fileChecksum" = "$correctChecksum" ] && return 0 + done + + return 1; +} + +# Some dependencies install here +[ -d "./build/lib_ext/Release-x64" ] || mkdir -p "./build/lib_ext/Release-x64" + +for url in $DEP_URLS; do + # Get the filename from the URL and remove query strings (?arg=something). + fileName="$(rev "$(rev "$url" | cut -d'/' -f1)" | cut -d'?' -f1)" + [ -z "$fileName" ] && echo "Unable to parse url: $url" && exit 1 + + # shellcheck disable=SC1003 + case "$url" in + *ccache*) checksum=$CCACHE_SHA; algo="sha256"; outDir="$CCACHE_BIN_DIR" ;; + *) echo "Unknown url resource: $url"; exit 1 ;; + esac + + download_and_verify "$url" "$checksum" "$algo" "$fileName" + 7z x -y "$DEPS_CACHE_DIR/$fileName" -aos -o"$outDir" +done + +# Setup ccache tool +[ -d "$CCACHE_DIR" ] || mkdir -p "$(cygpath -u "$CCACHE_DIR")" +CCACHE_SH_DIR=$(cygpath -u "$CCACHE_BIN_DIR") +mv "$CCACHE_SH_DIR"/ccache-*/* "$CCACHE_SH_DIR" +cp "$CCACHE_SH_DIR"/ccache.exe "$CCACHE_SH_DIR"/cl.exe diff --git a/.ci/setup-windows-ci-vars.sh b/.ci/setup-windows-ci-vars.sh new file mode 100644 index 0000000000..11373e0716 --- /dev/null +++ b/.ci/setup-windows-ci-vars.sh @@ -0,0 +1,39 @@ +#!/bin/sh -ex + +CPU_ARCH="${1:-win64}" +COMPILER="${2:-msvc}" + +# These are CI specific, so we wrap them for portability +REPO_NAME="$BUILD_REPOSITORY_NAME" +REPO_BRANCH="$BUILD_SOURCEBRANCHNAME" +PR_NUMBER="$BUILD_PR_NUMBER" + +# Gather explicit version number and number of commits +COMM_TAG=$(awk '/version{.*}/ { printf("%d.%d.%d", $5, $6, $7) }' ./rpcs3/rpcs3_version.cpp) +COMM_COUNT=$(git rev-list --count HEAD) +COMM_HASH=$(git rev-parse --short=8 HEAD) + +# Format the above into filenames +if [ -n "$PR_NUMBER" ]; then + AVVER="${COMM_TAG}-${COMM_HASH}" + BUILD_RAW="rpcs3-v${AVVER}_${CPU_ARCH}_${COMPILER}" + BUILD="${BUILD_RAW}.7z" +else + AVVER="${COMM_TAG}-${COMM_COUNT}" + BUILD_RAW="rpcs3-v${AVVER}-${COMM_HASH}_${CPU_ARCH}_${COMPILER}" + BUILD="${BUILD_RAW}.7z" +fi + +# BRANCH is used for experimental build warnings for pr builds, used in main_window.cpp. +# BUILD is the name of the release artifact +# BUILD_RAW is just filename +# AVVER is used for GitHub releases, it is the version number. +BRANCH="${REPO_NAME}/${REPO_BRANCH}" + +# SC2129 +{ + echo "BRANCH=$BRANCH" + echo "BUILD=$BUILD" + echo "BUILD_RAW=$BUILD_RAW" + echo "AVVER=$AVVER" +} >> .ci/ci-vars.env diff --git a/.ci/setup-windows.sh b/.ci/setup-windows.sh index 8b6aaa6156..11a68367b8 100755 --- a/.ci/setup-windows.sh +++ b/.ci/setup-windows.sh @@ -1,10 +1,5 @@ #!/bin/sh -ex -# These are Azure specific, so we wrap them for portability -REPO_NAME="$BUILD_REPOSITORY_NAME" -REPO_BRANCH="$SYSTEM_PULLREQUEST_SOURCEBRANCH" -PR_NUMBER="$SYSTEM_PULLREQUEST_PULLREQUESTID" - # Resource/dependency URLs # Qt mirrors can be volatile and slow, so we list 2 #QT_HOST="http://mirrors.ocf.berkeley.edu/qt/" @@ -33,7 +28,7 @@ DEP_URLS=" \ $VULKAN_SDK_URL\ $CCACHE_URL" -# Azure pipelines doesn't make a cache dir if it doesn't exist, so we do it manually +# CI doesn't make a cache dir if it doesn't exist, so we do it manually [ -d "$DEPS_CACHE_DIR" ] || mkdir "$DEPS_CACHE_DIR" # Pull all the submodules except llvm, since it is built separately and we just download that build @@ -99,33 +94,3 @@ done CCACHE_SH_DIR=$(cygpath -u "$CCACHE_BIN_DIR") mv "$CCACHE_SH_DIR"/ccache-*/* "$CCACHE_SH_DIR" cp "$CCACHE_SH_DIR"/ccache.exe "$CCACHE_SH_DIR"/cl.exe - -# Gather explicit version number and number of commits -COMM_TAG=$(awk '/version{.*}/ { printf("%d.%d.%d", $5, $6, $7) }' ./rpcs3/rpcs3_version.cpp) -COMM_COUNT=$(git rev-list --count HEAD) -COMM_HASH=$(git rev-parse --short=8 HEAD) - -# Format the above into filenames -if [ -n "$PR_NUMBER" ]; then - AVVER="${COMM_TAG}-${COMM_HASH}" - BUILD_RAW="rpcs3-v${AVVER}_win64" - BUILD="${BUILD_RAW}.7z" -else - AVVER="${COMM_TAG}-${COMM_COUNT}" - BUILD_RAW="rpcs3-v${AVVER}-${COMM_HASH}_win64" - BUILD="${BUILD_RAW}.7z" -fi - -# BRANCH is used for experimental build warnings for pr builds, used in main_window.cpp. -# BUILD is the name of the release artifact -# BUILD_RAW is just filename -# AVVER is used for GitHub releases, it is the version number. -BRANCH="${REPO_NAME}/${REPO_BRANCH}" - -# SC2129 -{ - echo "BRANCH=$BRANCH" - echo "BUILD=$BUILD" - echo "BUILD_RAW=$BUILD_RAW" - echo "AVVER=$AVVER" -} >> .ci/ci-vars.env diff --git a/.cirrus.yml b/.cirrus.yml deleted file mode 100644 index 41132c0bce..0000000000 --- a/.cirrus.yml +++ /dev/null @@ -1,153 +0,0 @@ -env: - CIRRUS_CLONE_DEPTH: 0 # Unshallow clone to obtain proper GIT_VERSION - BUILD_REPOSITORY_NAME: $CIRRUS_REPO_FULL_NAME - SYSTEM_PULLREQUEST_SOURCEBRANCH: $CIRRUS_BRANCH - SYSTEM_PULLREQUEST_PULLREQUESTID: $CIRRUS_PR - BUILD_SOURCEVERSION: $CIRRUS_CHANGE_IN_REPO - BUILD_SOURCEBRANCHNAME: $CIRRUS_BRANCH - RPCS3_TOKEN: ENCRYPTED[100ebb8e3552bf2021d0ef55dccda3e58d27be5b6cab0b0b92843ef490195d3c4edaefa087e4a3b425caa6392300b9b1] - QT_VER_MAIN: '6' - QT_VER: '6.9.0' - LLVM_COMPILER_VER: '19' - LLVM_VER: '19.1.7' - -# windows_task: -# matrix: -# - name: Cirrus Windows -# windows_container: -# image: cirrusci/windowsservercore:visualstudio2019 -# cpu: 8 -# memory: 16G -# env: -# CIRRUS_SHELL: "bash" -# COMPILER: msvc -# BUILD_ARTIFACTSTAGINGDIRECTORY: ${CIRRUS_WORKING_DIR}\artifacts\ -# QT_VER_MSVC: 'msvc2022' -# QT_DATE: '202503301022' -# QTDIR: C:\Qt\${QT_VER}\${QT_VER_MSVC}_64 -# VULKAN_VER: '1.3.268.0' -# VULKAN_SDK_SHA: '8459ef49bd06b697115ddd3d97c9aec729e849cd775f5be70897718a9b3b9db5' -# VULKAN_SDK: C:\VulkanSDK\${VULKAN_VER} -# CACHE_DIR: "./cache" -# UPLOAD_COMMIT_HASH: 7d09e3be30805911226241afbb14f8cdc2eb054e -# UPLOAD_REPO_FULL_NAME: "rpcs3/rpcs3-binaries-win" -# deps_cache: -# folder: "./cache" -# #obj_cache: -# # folder: "./tmp" -# #obj2_cache: -# # folder: "./rpcs3/x64" -# setup_script: -# - './.ci/get_keys-windows.sh' -# - './.ci/setup-windows.sh' -# rpcs3_script: -# - export PATH=${PATH}:"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin" -# - msbuild.exe rpcs3.sln //p:Configuration=Release //m -# deploy_script: -# - mkdir artifacts -# - source './.ci/export-cirrus-vars.sh' -# - './.ci/deploy-windows.sh' -# artifacts: -# name: Artifact -# path: "*.7z*" -# push_script: | -# if [ "$CIRRUS_REPO_OWNER" = "RPCS3" ] && [ -z "$CIRRUS_PR" ] && [ "$CIRRUS_BRANCH" = "master" ]; then -# source './.ci/export-cirrus-vars.sh' -# './.ci/github-upload.sh' -# fi; - -# linux_task: -# container: -# image: rpcs3/rpcs3-ci-jammy:1.6 -# cpu: 4 -# memory: 16G -# env: -# BUILD_ARTIFACTSTAGINGDIRECTORY: ${CIRRUS_WORKING_DIR}/artifacts -# ARTDIR: ${CIRRUS_WORKING_DIR}/artifacts/ -# CCACHE_DIR: "/tmp/ccache_dir" -# CCACHE_MAXSIZE: 300M -# CI_HAS_ARTIFACTS: true -# UPLOAD_COMMIT_HASH: d812f1254a1157c80fd402f94446310560f54e5f -# UPLOAD_REPO_FULL_NAME: "rpcs3/rpcs3-binaries-linux" -# DEPLOY_APPIMAGE: true -# APPDIR: "./appdir" -# RELEASE_MESSAGE: "../GitHubReleaseMessage.txt" -# ccache_cache: -# folder: "/tmp/ccache_dir" -# matrix: -# - name: Cirrus Linux GCC -# env: -# COMPILER: gcc -# gcc_script: -# - mkdir artifacts -# - ".ci/build-linux.sh" -# - name: Cirrus Linux Clang -# env: -# COMPILER: clang -# clang_script: -# - mkdir artifacts -# - ".ci/build-linux.sh" -# artifacts: -# name: Artifact -# path: "artifacts/*" -# push_script: | -# if [ "$CIRRUS_REPO_OWNER" = "RPCS3" ] && [ -z "$CIRRUS_PR" ] && [ "$CIRRUS_BRANCH" = "master" ] && [ "$COMPILER" = "gcc" ]; then -# COMM_TAG=$(awk '/version{.*}/ { printf("%d.%d.%d", $5, $6, $7) }' ./rpcs3/rpcs3_version.cpp) -# COMM_COUNT=$(git rev-list --count HEAD) -# COMM_HASH=$(git rev-parse --short=8 HEAD) - -# export AVVER="${COMM_TAG}-${COMM_COUNT}" - -# .ci/github-upload.sh -# fi; - -freebsd_task: - matrix: - - name: Cirrus FreeBSD - freebsd_instance: - image_family: freebsd-13-5 - cpu: 8 - memory: 8G - env: - CCACHE_MAXSIZE: 300M # 3x clean build, rounded - CCACHE_DIR: /tmp/ccache_dir - ccache_cache: - folder: /tmp/ccache_dir - install_script: "sh -ex ./.ci/install-freebsd.sh" - script: "./.ci/build-freebsd.sh" - -# linux_aarch64_task: -# env: -# BUILD_ARTIFACTSTAGINGDIRECTORY: ${CIRRUS_WORKING_DIR}/artifacts -# ARTDIR: ${CIRRUS_WORKING_DIR}/artifacts/ -# CCACHE_DIR: "/tmp/ccache_dir" -# CCACHE_MAXSIZE: 300M -# CI_HAS_ARTIFACTS: true -# UPLOAD_COMMIT_HASH: a1d35836e8d45bfc6f63c26f0a3e5d46ef622fe1 -# UPLOAD_REPO_FULL_NAME: "rpcs3/rpcs3-binaries-linux-arm64" -# DEPLOY_APPIMAGE: true -# APPDIR: "./appdir" -# RELEASE_MESSAGE: "../GitHubReleaseMessage.txt" -# COMPILER: clang -# ccache_cache: -# folder: "/tmp/ccache_dir" -# matrix: -# - name: Cirrus Linux AArch64 Clang -# arm_container: -# image: 'docker.io/rpcs3/rpcs3-ci-jammy-aarch64:1.6' -# cpu: 8 -# memory: 8G -# clang_script: -# - mkdir artifacts -# - "sh -ex ./.ci/build-linux-aarch64.sh" -# artifacts: -# name: Artifact -# path: "artifacts/*" -# push_script: | -# if [ "$CIRRUS_REPO_OWNER" = "RPCS3" ] && [ -z "$CIRRUS_PR" ] && [ "$CIRRUS_BRANCH" = "master" ]; then -# COMM_TAG=$(awk '/version{.*}/ { printf("%d.%d.%d", $5, $6, $7) }' ./rpcs3/rpcs3_version.cpp) -# COMM_COUNT=$(git rev-list --count HEAD) -# COMM_HASH=$(git rev-parse --short=8 HEAD) -# export AVVER="${COMM_TAG}-${COMM_COUNT}" -# .ci/github-upload.sh -# fi; diff --git a/.github/workflows/llvm.yml b/.github/workflows/llvm.yml new file mode 100644 index 0000000000..e3e3e76c50 --- /dev/null +++ b/.github/workflows/llvm.yml @@ -0,0 +1,72 @@ +name: Build LLVM + +defaults: + run: + shell: bash +on: + workflow_dispatch: + +concurrency: + group: ${{ github.ref }}-${{ github.event_name }} + cancel-in-progress: true + +env: + BUILD_ARTIFACTSTAGINGDIRECTORY: ${{ github.workspace }}/artifacts/ + +jobs: + Windows_Build: + if: github.event_name == 'workflow_dispatch' + name: LLVM Windows (MSVC) + runs-on: windows-2025 + env: + COMPILER: msvc + CCACHE_SHA: '1f39f3ad5aae3fe915e99ad1302633bc8f6718e58fa7c0de2b0ba7e080f0f08c' + CCACHE_BIN_DIR: 'C:\ccache_bin' + CCACHE_DIR: 'C:\ccache' + CCACHE_INODECACHE: 'true' + CCACHE_SLOPPINESS: 'time_macros' + DEPS_CACHE_DIR: ./dependency_cache + steps: + + - name: Checkout repository + uses: actions/checkout@main + with: + fetch-depth: 0 + + - name: Restore Dependencies Cache + uses: actions/cache/restore@main + id: restore-dependencies-cache + with: + path: ${{ env.DEPS_CACHE_DIR }} + key: "${{ runner.os }}-${{ env.COMPILER }}-llvm-${{ env.CCACHE_SHA }}" + restore-keys: ${{ runner.os }}-${{ env.COMPILER }}-llvm + + - name: Download and unpack dependencies + run: .ci/setup-llvm.sh + + - name: Add msbuild to PATH + uses: microsoft/setup-msbuild@main + + - name: Compile LLVM + shell: pwsh + run: msbuild 3rdparty\llvm\llvm_build.vcxproj /p:SolutionDir="$(pwd)/" /p:Configuration=Release /v:minimal /p:Platform=x64 /p:PreferredToolArchitecture=x64 /p:CLToolPath=${{ env.CCACHE_BIN_DIR }} /p:UseMultiToolTask=true /p:CustomAfterMicrosoftCommonTargets="${{ github.workspace }}\buildfiles\msvc\ci_only.targets" + + - name: Pack up build artifacts + run: | + mkdir -p "${{ env.BUILD_ARTIFACTSTAGINGDIRECTORY }}" + .ci/deploy-llvm.sh + + - name: Upload artifacts (7z) + uses: actions/upload-artifact@main + with: + name: LLVM for Windows (MSVC) + path: ${{ env.BUILD_ARTIFACTSTAGINGDIRECTORY }} + compression-level: 0 + if-no-files-found: error + + - name: Save Dependencies Cache + if: github.ref == 'refs/heads/master' + uses: actions/cache/save@main + with: + path: ${{ env.DEPS_CACHE_DIR }} + key: ${{ steps.restore-dependencies-cache.outputs.cache-primary-key }} diff --git a/.github/workflows/rpcs3.yml b/.github/workflows/rpcs3.yml index afafbc2e20..1981f78edb 100644 --- a/.github/workflows/rpcs3.yml +++ b/.github/workflows/rpcs3.yml @@ -17,6 +17,7 @@ concurrency: env: BUILD_REPOSITORY_NAME: ${{ github.repository }} BUILD_SOURCEBRANCHNAME: ${{ github.ref_name }} + BUILD_PR_NUMBER: ${{ github.event.pull_request.number }} BUILD_SOURCEVERSION: ${{ github.sha }} BUILD_ARTIFACTSTAGINGDIRECTORY: ${{ github.workspace }}/artifacts/ @@ -44,11 +45,14 @@ jobs: 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.6" + build_sh: "/rpcs3/.ci/build-linux-aarch64.sh" + compiler: gcc name: RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} runs-on: ${{ matrix.os }} env: CCACHE_DIR: ${{ github.workspace }}/ccache - CI_HAS_ARTIFACTS: true DEPLOY_APPIMAGE: true APPDIR: "/rpcs3/build/appdir" ARTDIR: "/root/artifacts" @@ -63,19 +67,19 @@ jobs: with: fetch-depth: 0 - - name: Setup Cache - uses: actions/cache@main + - name: Restore build Ccache + uses: actions/cache/restore@main + id: restore-build-ccache with: path: ${{ env.CCACHE_DIR }} key: ${{ runner.os }}-ccache-${{ matrix.compiler }}-${{ runner.arch }}-${{github.run_id}} - restore-keys: | - ${{ runner.os }}-ccache-${{ matrix.compiler }}-${{ runner.arch }}- + restore-keys: ${{ runner.os }}-ccache-${{ matrix.compiler }}-${{ runner.arch }}- - name: Docker setup and build run: | docker pull --quiet ${{ matrix.docker_img }} - docker run \ - -v $PWD:/rpcs3 \ + docker run \ + -v $PWD:/rpcs3 \ --env-file .ci/docker.env \ -v ${{ env.CCACHE_DIR }}:/root/.ccache \ -v ${{ env.BUILD_ARTIFACTSTAGINGDIRECTORY }}:${{ env.ARTDIR }} \ @@ -104,6 +108,13 @@ jobs: export AVVER="${COMM_TAG}-${COMM_COUNT}" .ci/github-upload.sh + - name: Save build Ccache + if: github.ref == 'refs/heads/master' + uses: actions/cache/save@main + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.restore-build-ccache.outputs.cache-primary-key }} + Mac_Build: # Only run push event on master branch of main repo, but run all PRs if: github.event_name != 'push' || (github.repository == 'RPCS3/rpcs3' && github.ref_name == 'master') @@ -123,37 +134,37 @@ jobs: runs-on: macos-14 env: CCACHE_DIR: /tmp/ccache_dir - CI_HAS_ARTIFACTS: true QT_VER: '6.7.3' QT_VER_MAIN: '6' LLVM_COMPILER_VER: '19' RELEASE_MESSAGE: ../GitHubReleaseMessage.txt UPLOAD_COMMIT_HASH: ${{ matrix.UPLOAD_COMMIT_HASH }} UPLOAD_REPO_FULL_NAME: ${{ matrix.UPLOAD_REPO_FULL_NAME }} + RUN_UNIT_TESTS: github.event_name == 'pull_request' && 'ON' || 'OFF' steps: - name: Checkout repository uses: actions/checkout@main with: fetch-depth: 0 - - name: Setup Cache - uses: actions/cache@main + - name: Restore Build Ccache + uses: actions/cache/restore@main + id: restore-build-ccache with: path: ${{ env.CCACHE_DIR }} key: ${{ runner.os }}-ccache-${{ matrix.name }}-${{github.run_id}} - restore-keys: | - ${{ runner.os }}-ccache-${{ matrix.name }}- + restore-keys: ${{ runner.os }}-ccache-${{ matrix.name }}- - - name: Setup Qt Cache - uses: actions/cache@main + - name: Restore Qt Cache + uses: actions/cache/restore@main + id: restore-qt-cache with: path: /tmp/Qt key: ${{ runner.os }}-qt-${{ matrix.name }}-${{ env.QT_VER }} - restore-keys: | - ${{ runner.os }}-qt-${{ matrix.name }}-${{ env.QT_VER }} + restore-keys: ${{ runner.os }}-qt-${{ matrix.name }}-${{ env.QT_VER }} - name: Build - run: ${{ matrix.build_sh }} + run: ${{ matrix.build_sh }} - name: Upload artifacts uses: actions/upload-artifact@main @@ -179,6 +190,20 @@ jobs: RPCS3_TOKEN: ${{ secrets.RPCS3_TOKEN }} run: .ci/github-upload.sh + - name: Save Build Ccache + if: github.ref == 'refs/heads/master' + uses: actions/cache/save@main + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.restore-build-ccache.outputs.cache-primary-key }} + + - name: Save Qt Cache + if: github.ref == 'refs/heads/master' + uses: actions/cache/save@main + with: + path: /tmp/Qt + key: ${{ steps.restore-qt-cache.outputs.cache-primary-key }} + Windows_Build: # Only run push event on master branch of main repo, but run all PRs if: github.event_name != 'push' || (github.repository == 'RPCS3/rpcs3' && github.ref_name == 'master') @@ -187,9 +212,9 @@ jobs: env: COMPILER: msvc QT_VER_MAIN: '6' - QT_VER: '6.9.0' + QT_VER: '6.9.1' QT_VER_MSVC: 'msvc2022' - QT_DATE: '202503301022' + QT_DATE: '202505291653' LLVM_VER: '19.1.7' VULKAN_VER: '1.3.268.0' VULKAN_SDK_SHA: '8459ef49bd06b697115ddd3d97c9aec729e849cd775f5be70897718a9b3b9db5' @@ -223,22 +248,26 @@ jobs: - name: Get Cache Keys run: .ci/get_keys-windows.sh - - name: Setup Build Ccache - uses: actions/cache@main + - name: Restore Build Ccache + uses: actions/cache/restore@main + id: restore-build-ccache with: path: ${{ env.CCACHE_DIR }} key: "${{ runner.os }}-ccache-${{ env.COMPILER }}-${{github.run_id}}" restore-keys: ${{ runner.os }}-ccache-${{ env.COMPILER }}- - - name: Setup Dependencies Cache - uses: actions/cache@main + - name: Restore Dependencies Cache + uses: actions/cache/restore@main + id: restore-dependencies-cache with: path: ${{ env.DEPS_CACHE_DIR }} key: "${{ runner.os }}-${{ env.COMPILER }}-${{ env.QT_VER }}-${{ env.VULKAN_SDK_SHA }}-${{ env.CCACHE_SHA }}-${{ hashFiles('llvm.lock') }}" restore-keys: ${{ runner.os }}-${{ env.COMPILER }}- - name: Download and unpack dependencies - run: .ci/setup-windows.sh + run: | + .ci/setup-windows.sh + .ci/setup-windows-ci-vars.sh win64 msvc - name: Export Variables run: | @@ -281,3 +310,135 @@ jobs: env: RPCS3_TOKEN: ${{ secrets.RPCS3_TOKEN }} run: .ci/github-upload.sh + + - name: Save Build Ccache + if: github.ref == 'refs/heads/master' + uses: actions/cache/save@main + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.restore-build-ccache.outputs.cache-primary-key }} + + - name: Save Dependencies Cache + if: github.ref == 'refs/heads/master' + uses: actions/cache/save@main + with: + path: ${{ env.DEPS_CACHE_DIR }} + key: ${{ steps.restore-dependencies-cache.outputs.cache-primary-key }} + + Windows_Build_Clang: + # Only run push event on master branch of main repo, but run all PRs + if: github.event_name != 'push' || (github.repository == 'RPCS3/rpcs3' && github.ref_name == 'master') + name: RPCS3 Windows Clang + runs-on: windows-2025 + strategy: + matrix: + include: + - msys2: clang64 + compiler: clang + arch: win64 + env: + CCACHE_DIR: 'C:\ccache' + steps: + - name: Checkout repository + uses: actions/checkout@main + with: + fetch-depth: 0 + + - name: Setup msys2 + uses: msys2/setup-msys2@v2 + with: + msystem: ${{ matrix.msys2 }} + update: true + cache: true + install: | + mingw-w64-clang-x86_64-clang + mingw-w64-clang-x86_64-ccache + mingw-w64-clang-x86_64-cmake + mingw-w64-clang-x86_64-lld + mingw-w64-clang-x86_64-ninja + mingw-w64-clang-x86_64-llvm + mingw-w64-clang-x86_64-ffmpeg + mingw-w64-clang-x86_64-opencv + mingw-w64-clang-x86_64-glew + mingw-w64-clang-x86_64-vulkan + mingw-w64-clang-x86_64-vulkan-headers + mingw-w64-clang-x86_64-vulkan-loader + mingw-w64-clang-x86_64-gtest + mingw-w64-clang-x86_64-qt6-base + mingw-w64-clang-x86_64-qt6-declarative + mingw-w64-clang-x86_64-qt6-multimedia + mingw-w64-clang-x86_64-qt6-svg + base-devel + curl + git + p7zip + + - name: Restore build Ccache + uses: actions/cache/restore@main + id: restore-build-ccache + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ runner.os }}-ccache-${{ matrix.compiler }}-${{ runner.arch }}-${{ github.run_id }} + restore-keys: ${{ runner.os }}-ccache-${{ matrix.compiler }}-${{ runner.arch }}- + + - name: Build RPCS3 + shell: msys2 {0} + run: | + export CCACHE_DIR=$(cygpath -u "$CCACHE_DIR") + echo "CCACHE_DIR=$CCACHE_DIR" + .ci/setup-windows-ci-vars.sh ${{ matrix.arch }} ${{ matrix.compiler }} + .ci/build-windows-clang.sh + + - name: Save build Ccache + if: github.ref == 'refs/heads/master' + uses: actions/cache/save@main + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.restore-build-ccache.outputs.cache-primary-key }} + + - name: Upload artifacts + uses: actions/upload-artifact@main + with: + name: RPCS3 for Windows (${{ runner.arch }}, ${{ matrix.compiler }}) + path: ${{ env.BUILD_ARTIFACTSTAGINGDIRECTORY }} + compression-level: 0 + if-no-files-found: error + + FreeBSD_Build: + # Only run push event on master branch of main repo, but run all PRs + if: github.event_name != 'push' || (github.repository == 'RPCS3/rpcs3' && github.ref_name == 'master') + name: RPCS3 FreeBSD + runs-on: ubuntu-latest + timeout-minutes: 60 + env: + CCACHE_DIR: ${{ github.workspace }}/ccache + QT_VER_MAIN: '6' + LLVM_COMPILER_VER: '19' + steps: + - name: Checkout repository + uses: actions/checkout@main + with: + fetch-depth: 0 + + - name: Restore Build Ccache + uses: actions/cache/restore@main + id: restore-build-ccache + with: + path: ${{ env.CCACHE_DIR }} + key: FreeBSD-ccache-${{github.run_id}} + restore-keys: FreeBSD-ccache- + + - name: FreeBSD build + id: root + uses: vmactions/freebsd-vm@v1 + with: + envs: 'QT_VER_MAIN LLVM_COMPILER_VER CCACHE_DIR' + usesh: true + run: .ci/install-freebsd.sh && .ci/build-freebsd.sh + + - name: Save Build Ccache + if: github.ref == 'refs/heads/master' + uses: actions/cache/save@main + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.restore-build-ccache.outputs.cache-primary-key }} diff --git a/3rdparty/OpenAL/CMakeLists.txt b/3rdparty/OpenAL/CMakeLists.txt index f37a776a1f..b9fee23ce5 100644 --- a/3rdparty/OpenAL/CMakeLists.txt +++ b/3rdparty/OpenAL/CMakeLists.txt @@ -11,6 +11,7 @@ if(USE_SYSTEM_OPENAL) else() option(ALSOFT_UTILS "Build utility programs" OFF) option(ALSOFT_EXAMPLES "Build example programs" OFF) + set(LIBTYPE "STATIC") add_subdirectory(openal-soft EXCLUDE_FROM_ALL) add_library(3rdparty_openal INTERFACE) target_link_libraries(3rdparty_openal INTERFACE OpenAL::OpenAL) diff --git a/3rdparty/llvm/CMakeLists.txt b/3rdparty/llvm/CMakeLists.txt index 8723728f4a..d1295886d8 100644 --- a/3rdparty/llvm/CMakeLists.txt +++ b/3rdparty/llvm/CMakeLists.txt @@ -66,12 +66,10 @@ if(WITH_LLVM) find_package(LLVM CONFIG) if (NOT LLVM_FOUND) - message(FATAL_ERROR "Can't find LLVM libraries from the CMAKE_PREFIX_PATH path or LLVM_DIR. \ - Enable BUILD_LLVM option to build LLVM from included as a git submodule.") + message(FATAL_ERROR "Can't find LLVM libraries from the CMAKE_PREFIX_PATH path or LLVM_DIR. Enable BUILD_LLVM option to build LLVM from included as a git submodule.") endif() if (LLVM_VERSION VERSION_LESS 18) - message(FATAL_ERROR "Found LLVM version ${LLVM_VERSION}. Required version 18 or above. \ - Enable BUILD_LLVM option to build LLVM from included as a git submodule.") + message(FATAL_ERROR "Found LLVM version ${LLVM_VERSION}. Required version 18 or above. Enable BUILD_LLVM option to build LLVM from included as a git submodule.") endif() endif() diff --git a/3rdparty/opencv/opencv b/3rdparty/opencv/opencv index f76628fb5b..50fb5e701d 160000 --- a/3rdparty/opencv/opencv +++ b/3rdparty/opencv/opencv @@ -1 +1 @@ -Subproject commit f76628fb5b25746fcb75a7ce85be0d8c6439fc57 +Subproject commit 50fb5e701d8b0d3fe8262ed84668a94cc8cbf0b1 diff --git a/BUILDING.md b/BUILDING.md index 09f523d567..311bbddeee 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -19,26 +19,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.9.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) +- [Qt 6.9.1](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.9.0\msvc2022_64\` +- add and set the `QTDIR` environment variable, e.g. `\6.9.1\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.9.0\msvc2022_64\` +- add and set the `Qt6_ROOT` environment variable to the **Qt** libs path, e.g. `\6.9.1\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.9.0](https://www.qt.io/download-qt-installer) +- [Qt 6.9.1](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) @@ -121,7 +121,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.9.0\msvc2022_64`, version will fill in automatically +2) add the path to your Qt installation with compiler e.g. `\6.9.1\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 09c1c47e63..2f633730fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,12 @@ cmake_minimum_required(VERSION 3.28) +find_program(CCACHE_PATH ccache HINTS ENV PATH) +if(CCACHE_PATH) + message(STATUS "Using ccache: ${CCACHE_PATH}") + set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PATH}") + set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PATH}") +endif() + project(rpcs3 LANGUAGES C CXX) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) @@ -22,16 +29,23 @@ option(STATIC_LINK_LLVM "Link against LLVM statically. This will get set to ON i option(USE_FAUDIO "FAudio audio backend" ON) option(USE_LIBEVDEV "libevdev-based joystick support" ON) option(USE_DISCORD_RPC "Discord rich presence integration" OFF) -option(USE_SYSTEM_ZLIB "Prefer system ZLIB instead of the builtin one" ON) 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_SYSTEM_SDL "Prefer system SDL instead of the builtin one" ON) -option(USE_SYSTEM_FFMPEG "Prefer system ffmpeg instead of the prebuild one" OFF) -option(USE_SYSTEM_OPENAL "Prefer system OpenAL instead of the prebuild one" ON) -option(USE_SYSTEM_CURL "Prefer system Curl instead of the prebuild one" ON) -option(USE_SYSTEM_OPENCV "Prefer system OpenCV instead of the builtin one" 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) +option(USE_SYSTEM_FFMPEG "Prefer system ffmpeg instead of the prebuild one" OFF) +option(USE_SYSTEM_FLATBUFFERS "Prefer system flatbuffers instead of the builtin one" OFF) +option(USE_SYSTEM_LIBPNG "Prefer system libpng instead of the builtin one" OFF) +option(USE_SYSTEM_LIBUSB "Prefer system libusb instead of the builtin one" OFF) +option(USE_SYSTEM_MVK "Prefer system MoltenVK instead of the builtin one" OFF) +option(USE_SYSTEM_OPENAL "Prefer system OpenAL instead of the prebuild one" ON) +option(USE_SYSTEM_OPENCV "Prefer system OpenCV instead of the builtin one" ON) +option(USE_SYSTEM_PUGIXML "Prefer system pugixml instead of the builtin one" OFF) +option(USE_SYSTEM_SDL "Prefer system SDL instead of the builtin one" ON) +option(USE_SYSTEM_WOLFSSL "Prefer system MoltenVK instead of the builtin one" OFF) +option(USE_SYSTEM_ZLIB "Prefer system ZLIB instead of the builtin one" ON) option(HAS_MEMORY_BREAKPOINTS "Add support for memory breakpoints to the interpreter" OFF) option(USE_LTO "Use LTO for building" ON) option(BUILD_RPCS3_TESTS "Build RPCS3 unit tests." OFF) @@ -109,11 +123,6 @@ if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8) message( FATAL_ERROR "RPCS3 can only be compiled on 64-bit platforms." ) endif() -find_program(CCACHE_FOUND ccache) -if(CCACHE_FOUND) - set(CMAKE_CXX_COMPILER_LAUNCHER ccache) -endif() - if(APPLE AND CMAKE_OSX_ARCHITECTURES STREQUAL "arm64") include_directories(/opt/homebrew/include) link_directories(/opt/homebrew/lib) diff --git a/README.md b/README.md index fb49b2dc01..ac6e3cd594 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ RPCS3 ===== -[![Cirrus CI - Base Branch Build Status](https://img.shields.io/cirrus/github/RPCS3/rpcs3/master?label=Cirrus%20CI&logo=cirrus-ci)](https://cirrus-ci.com/github/RPCS3/rpcs3) [![GitHub Actions](https://img.shields.io/github/actions/workflow/status/RPCS3/rpcs3/rpcs3.yml?branch=master&logo=github&label=Actions)](https://github.com/RPCS3/rpcs3/actions/workflows/rpcs3.yml) [![RPCS3 Discord Server](https://img.shields.io/discord/272035812277878785?color=5865F2&label=RPCS3%20Discord&logo=discord&logoColor=white)](https://discord.gg/rpcs3) diff --git a/Utilities/Thread.h b/Utilities/Thread.h index 52096a2702..6dc2dc8cf6 100644 --- a/Utilities/Thread.h +++ b/Utilities/Thread.h @@ -96,7 +96,7 @@ class thread_future thread_future* prev{}; protected: - atomic_t exec{}; + atomic_t exec{}; atomic_t done{0}; @@ -389,7 +389,7 @@ public: : m_args(std::forward(args)...) , m_func(std::forward(func)) { - thread_future::exec.raw() = +[](thread_base* tb, thread_future* tf) + thread_future::exec.raw() = +[](const thread_base* tb, thread_future* tf) { const auto _this = static_cast(tf); diff --git a/Utilities/git-version-gen.cmd b/Utilities/git-version-gen.cmd index 7de2ebf28f..5d9254171d 100644 --- a/Utilities/git-version-gen.cmd +++ b/Utilities/git-version-gen.cmd @@ -94,8 +94,6 @@ if defined BUILD_SOURCEBRANCHNAME ( rem // This must be a CI build - echo SYSTEM_PULLREQUEST_SOURCEBRANCH: %SYSTEM_PULLREQUEST_SOURCEBRANCH% - if defined BUILD_REPOSITORY_NAME ( echo BUILD_REPOSITORY_NAME: %BUILD_REPOSITORY_NAME% ) else ( @@ -110,9 +108,7 @@ if defined BUILD_SOURCEBRANCHNAME ( rem // These environment variables are defined by CI rem // BUILD_REPOSITORY_NAME will look like "RPCS3/rpcs3" - rem // SYSTEM_PULLREQUEST_SOURCEBRANCH will look like "master" rem // BUILD_SOURCEBRANCHNAME will look like "master" - rem // See https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables set GIT_FULL_BRANCH=%BUILD_REPOSITORY_NAME%/%BUILD_SOURCEBRANCHNAME% echo GIT_FULL_BRANCH: !GIT_FULL_BRANCH! @@ -129,12 +125,12 @@ if defined BUILD_SOURCEBRANCHNAME ( rem // This must be a pull request or a build from a fork. echo Assuming pull request build - if "%SYSTEM_PULLREQUEST_SOURCEBRANCH%"=="master" ( + if "%BUILD_SOURCEBRANCHNAME%"=="master" ( rem // If pull request comes from a master branch, GIT_BRANCH = username/branch in order to distinguish from upstream/master for /f "tokens=1* delims=/" %%a in ("%BUILD_REPOSITORY_NAME%") do set user=%%a - set "GIT_BRANCH=!user!/%SYSTEM_PULLREQUEST_SOURCEBRANCH%" + set "GIT_BRANCH=!user!/%BUILD_SOURCEBRANCHNAME%" ) else ( - set GIT_BRANCH=%SYSTEM_PULLREQUEST_SOURCEBRANCH% + set GIT_BRANCH=%BUILD_SOURCEBRANCHNAME% ) rem // Make GIT_VERSION the last commit (shortened); Don't include commit count on non-release builds diff --git a/Utilities/transactional_storage.h b/Utilities/transactional_storage.h index 55e8aa9f95..1be923233e 100644 --- a/Utilities/transactional_storage.h +++ b/Utilities/transactional_storage.h @@ -84,9 +84,8 @@ public: transactional_storage& operator=(const transactional_storage&) = delete; transactional_storage(transactional_storage&& other) + : pool(std::move(other.pool)) { - pool = std::move(other.pool); - std::unique_lock lock_other{other.current_mutex}; const std::shared_ptr other_current = other.current; other.current = nullptr; diff --git a/buildfiles/cmake/CopyRuntimeDependencies.cmake b/buildfiles/cmake/CopyRuntimeDependencies.cmake new file mode 100644 index 0000000000..6724d332da --- /dev/null +++ b/buildfiles/cmake/CopyRuntimeDependencies.cmake @@ -0,0 +1,51 @@ +# Copy remaining DLLS + +cmake_path(GET exe PARENT_PATH exe_dir) +cmake_path(CONVERT "${MSYS2_CLANG_BIN}" TO_CMAKE_PATH_LIST msys2_clang_bin) +cmake_path(CONVERT "${MSYS2_USR_BIN}" TO_CMAKE_PATH_LIST msys2_usr_bin) + +message(STATUS "Getting runtime dependencies for '${exe}' in '${exe_dir}'") +message(STATUS "Dependency dirs: '${msys2_clang_bin}', '${msys2_usr_bin}'") + +file(GET_RUNTIME_DEPENDENCIES EXECUTABLES ${exe} + RESOLVED_DEPENDENCIES_VAR resolved_deps + UNRESOLVED_DEPENDENCIES_VAR unresolved_deps + DIRECTORIES ${msys2_clang_bin} ${msys2_usr_bin}) + +foreach(dep IN LISTS resolved_deps) + cmake_path(GET dep FILENAME dep_filename) + cmake_path(GET dep PARENT_PATH dep_dir_raw) + cmake_path(CONVERT "${dep_dir_raw}" TO_CMAKE_PATH_LIST dep_dir) + + string(COMPARE EQUAL "${dep_dir}" "${msys2_clang_bin}" is_clang_path) + string(COMPARE EQUAL "${dep_dir}" "${msys2_usr_bin}" is_usr_path) + + set(same_path FALSE) + if(is_clang_path OR is_usr_path) + set(same_path TRUE) + endif() + + if(same_path) + set(dest "${exe_dir}/${dep_filename}") + if(NOT EXISTS "${dest}") + file(COPY "${dep}" DESTINATION "${exe_dir}") + message(STATUS "Copied '${dep_filename}' to '${exe_dir}'") + else() + message(STATUS "Already exists: '${dest}', skipping.") + endif() + else() + message(STATUS "Found and ignored '${dep}' in '${dep_dir}'. Is clang path: ${is_clang_path}, is usr path: ${is_usr_path}") + endif() +endforeach() + +# Warn about unresolved dependencies +if(unresolved_deps) + message(WARNING "Unresolved dependencies:") + foreach(dep IN LISTS unresolved_deps) + cmake_path(GET dep PARENT_PATH dep_dir) + string(TOLOWER "${dep_dir}" dep_dir_lower) + if(NOT dep_dir_lower MATCHES ".*(windows[/\\]system32|windows[/\\]winsxs|program files).*") + message(STATUS " - ${dep_dir}/${dep}") + endif() + endforeach() +endif() diff --git a/rpcs3/CMakeLists.txt b/rpcs3/CMakeLists.txt index 150d667af1..b1d10d38eb 100644 --- a/rpcs3/CMakeLists.txt +++ b/rpcs3/CMakeLists.txt @@ -154,11 +154,11 @@ if (NOT ANDROID) COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/GuiConfigs $/GuiConfigs) elseif(WIN32) add_custom_command(TARGET rpcs3 POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy $ $ COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/Icons $/Icons COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/GuiConfigs $/GuiConfigs + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/test $/test COMMAND "${WINDEPLOYQT_EXECUTABLE}" --no-compiler-runtime --no-opengl-sw --no-patchqt - --no-translations --no-system-d3d-compiler --no-system-dxc-compiler --no-ffmpeg --no-quick-import + --no-translations --no-system-d3d-compiler --no-system-dxc-compiler --no-quick-import --plugindir "$,$/plugins,$/share/qt6/plugins>" --verbose 0 "$") endif() diff --git a/rpcs3/Emu/Audio/XAudio2/XAudio2Backend.cpp b/rpcs3/Emu/Audio/XAudio2/XAudio2Backend.cpp index 0a84d747bf..b9a4daeecc 100644 --- a/rpcs3/Emu/Audio/XAudio2/XAudio2Backend.cpp +++ b/rpcs3/Emu/Audio/XAudio2/XAudio2Backend.cpp @@ -337,7 +337,7 @@ f64 XAudio2Backend::GetCallbackFrameLen() return std::max(min_latency, _10ms); // 10ms is the minimum for XAudio } -void XAudio2Backend::OnVoiceProcessingPassStart(UINT32 BytesRequired) +void XAudio2Backend::OnVoiceProcessingPassStart(UINT32 BytesRequired) noexcept { std::unique_lock lock(m_cb_mutex, std::defer_lock); if (BytesRequired && !m_reset_req.observe() && lock.try_lock_for(std::chrono::microseconds{50}) && m_write_callback && m_playing) @@ -366,7 +366,7 @@ void XAudio2Backend::OnVoiceProcessingPassStart(UINT32 BytesRequired) } } -void XAudio2Backend::OnCriticalError(HRESULT Error) +void XAudio2Backend::OnCriticalError(HRESULT Error) noexcept { XAudio.error("OnCriticalError() called: %s (0x%08x)", std::system_category().message(Error), static_cast(Error)); diff --git a/rpcs3/Emu/Audio/XAudio2/XAudio2Backend.h b/rpcs3/Emu/Audio/XAudio2/XAudio2Backend.h index 0312e7f633..1bab624d67 100644 --- a/rpcs3/Emu/Audio/XAudio2/XAudio2Backend.h +++ b/rpcs3/Emu/Audio/XAudio2/XAudio2Backend.h @@ -54,18 +54,18 @@ private: atomic_t m_reset_req = false; // XAudio voice callbacks - void OnVoiceProcessingPassStart(UINT32 BytesRequired) override; - void OnVoiceProcessingPassEnd() override {} - void OnStreamEnd() override {} - void OnBufferStart(void* /* pBufferContext */) override {} - void OnBufferEnd(void* /* pBufferContext*/) override {} - void OnLoopEnd(void* /* pBufferContext */) override {} - void OnVoiceError(void* /* pBufferContext */, HRESULT /* Error */) override {} + void OnVoiceProcessingPassStart(UINT32 BytesRequired) noexcept override; + void OnVoiceProcessingPassEnd() noexcept override {} + void OnStreamEnd() noexcept override {} + void OnBufferStart(void* /* pBufferContext */) noexcept override {} + void OnBufferEnd(void* /* pBufferContext*/) noexcept override {} + void OnLoopEnd(void* /* pBufferContext */) noexcept override {} + void OnVoiceError(void* /* pBufferContext */, HRESULT /* Error */) noexcept override {} // XAudio engine callbacks - void OnProcessingPassStart() override {}; - void OnProcessingPassEnd() override {}; - void OnCriticalError(HRESULT Error) override; + void OnProcessingPassStart() noexcept override {}; + void OnProcessingPassEnd() noexcept override {}; + void OnCriticalError(HRESULT Error) noexcept override; // IMMNotificationClient callbacks IFACEMETHODIMP_(ULONG) AddRef() override { return 1; }; diff --git a/rpcs3/Emu/CMakeLists.txt b/rpcs3/Emu/CMakeLists.txt index 0164376dff..3793c94ea1 100644 --- a/rpcs3/Emu/CMakeLists.txt +++ b/rpcs3/Emu/CMakeLists.txt @@ -29,6 +29,10 @@ if(USE_ASAN) set_source_files_properties(../../Utilities/Thread.cpp PROPERTIES COMPILE_DEFINITIONS USE_ASAN) endif() +if(NOT USE_SYSTEM_OPENAL) + target_compile_definitions(rpcs3_emu PUBLIC AL_LIBTYPE_STATIC) +endif() + if(HAS_MEMORY_BREAKPOINTS) target_compile_definitions(rpcs3_emu PRIVATE RPCS3_HAS_MEMORY_BREAKPOINTS) endif() diff --git a/rpcs3/Emu/CPU/CPUTranslator.h b/rpcs3/Emu/CPU/CPUTranslator.h index 088bd0801b..8d1a5d42aa 100644 --- a/rpcs3/Emu/CPU/CPUTranslator.h +++ b/rpcs3/Emu/CPU/CPUTranslator.h @@ -434,7 +434,7 @@ struct llvm_value_t : llvm_value_t static llvm::Type* get_type(llvm::LLVMContext& context) { - return llvm_value_t::get_type(context)->getPointerTo(); + return llvm::PointerType::getUnqual(context); } }; diff --git a/rpcs3/Emu/Cell/Modules/cellGem.cpp b/rpcs3/Emu/Cell/Modules/cellGem.cpp index bfbeb416df..ba796be28e 100644 --- a/rpcs3/Emu/Cell/Modules/cellGem.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGem.cpp @@ -351,7 +351,7 @@ public: for (u32 i = 0; i < CELL_GEM_MAX_NUM; i++) { const auto& pad = ::at32(handler->GetPads(), pad_num(i)); - const bool connected = pad && pad->is_connected() && i < attribute.max_connect; + const bool connected = pad && pad->is_connected() && !pad->is_copilot() && i < attribute.max_connect; const bool is_real_move = g_cfg.io.move != move_handler::real || pad->m_pad_handler == pad_handler::move; update_connection(i, connected && is_real_move); @@ -407,7 +407,7 @@ public: std::lock_guard pad_lock(pad::g_pad_mutex); const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (pad && pad->m_pad_handler == pad_handler::move) + if (pad && pad->m_pad_handler == pad_handler::move && !pad->is_copilot()) { if (!pad->move_data.calibration_requested || !pad->move_data.calibration_succeeded) { @@ -437,7 +437,7 @@ public: std::lock_guard pad_lock(pad::g_pad_mutex); const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (pad && pad->m_pad_handler == pad_handler::move) + if (pad && pad->m_pad_handler == pad_handler::move && !pad->is_copilot()) { pad->move_data.calibration_requested = false; pad->move_data.calibration_succeeded = false; @@ -469,7 +469,7 @@ public: for (u32 i = 0; i < std::min(attribute.max_connect, CELL_GEM_MAX_NUM); i++) { const auto& pad = ::at32(handler->GetPads(), pad_num(i)); - if (pad && pad->m_pad_handler == pad_handler::move && pad->is_connected()) + if (pad && pad->m_pad_handler == pad_handler::move && pad->is_connected() && !pad->is_copilot()) { connected_controllers++; @@ -490,7 +490,7 @@ public: for (u32 i = 0; i < std::min(attribute.max_connect, CELL_GEM_MAX_NUM); i++) { const auto& pad = ::at32(handler->GetPads(), pad_num(i)); - if (pad && pad->is_connected()) + if (pad && pad->is_connected() && !pad->is_copilot()) { connected_controllers++; @@ -1776,7 +1776,7 @@ static void ds3_input_to_pad(const u32 gem_num, be_t& digital_buttons, be_t const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (!pad->is_connected()) + if (!pad->is_connected() || pad->is_copilot()) { return; } @@ -1864,7 +1864,7 @@ static void ds3_pos_to_gem_state(u32 gem_num, gem_config::gem_controller& contro const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (!pad->is_connected()) + if (!pad->is_connected() || pad->is_copilot()) { return; } @@ -1895,7 +1895,7 @@ static void ps_move_pos_to_gem_state(u32 gem_num, gem_config::gem_controller& co const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (pad->m_pad_handler != pad_handler::move || !pad->is_connected()) + if (pad->m_pad_handler != pad_handler::move || !pad->is_connected() || pad->is_copilot()) { return; } @@ -1940,7 +1940,7 @@ static void ds3_input_to_ext(u32 gem_num, gem_config::gem_controller& controller const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (!pad->is_connected()) + if (!pad->is_connected() || pad->is_copilot()) { return; } @@ -1952,7 +1952,7 @@ static void ds3_input_to_ext(u32 gem_num, gem_config::gem_controller& controller ext.status = controller.ext_status; - for (const AnalogStick& stick : pad->m_sticks) + for (const AnalogStick& stick : pad->m_sticks_external) { switch (stick.m_offset) { @@ -1964,7 +1964,7 @@ static void ds3_input_to_ext(u32 gem_num, gem_config::gem_controller& controller } } - for (const Button& button : pad->m_buttons) + for (const Button& button : pad->m_buttons_external) { if (!button.m_pressed) continue; @@ -2400,7 +2400,7 @@ error_code cellGemEnableMagnetometer(u32 gem_num, u32 enable) const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (pad && pad->m_pad_handler == pad_handler::move) + if (pad && pad->m_pad_handler == pad_handler::move && !pad->is_copilot()) { pad->move_data.magnetometer_enabled = controller.enabled_magnetometer; } @@ -2448,7 +2448,7 @@ error_code cellGemEnableMagnetometer2(u32 gem_num, u32 enable) const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (pad && pad->m_pad_handler == pad_handler::move) + if (pad && pad->m_pad_handler == pad_handler::move && !pad->is_copilot()) { pad->move_data.magnetometer_enabled = controller.enabled_magnetometer; } @@ -2777,7 +2777,7 @@ error_code cellGemGetInertialState(u32 gem_num, u32 state_flag, u64 timestamp, v const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (pad && pad->is_connected()) + if (pad && pad->is_connected() && !pad->is_copilot()) { inertial_state->temperature = pad->move_data.temperature; inertial_state->accelerometer[0] = pad->move_data.accelerometer_x; @@ -3392,7 +3392,7 @@ error_code cellGemReadExternalPortDeviceInfo(u32 gem_num, vm::ptr ext_id, v const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num)); - if (pad->m_pad_handler != pad_handler::move || !pad->is_connected()) + if (pad->m_pad_handler != pad_handler::move || !pad->is_connected() || pad->is_copilot()) { return CELL_GEM_NOT_CONNECTED; } @@ -3706,7 +3706,7 @@ error_code cellGemWriteExternalPort(u32 gem_num, vm::ptrGetPads(), pad_num(gem_num)); - if (pad->m_pad_handler != pad_handler::move || !pad->is_connected()) + if (pad->m_pad_handler != pad_handler::move || !pad->is_connected() || pad->is_copilot()) { return CELL_GEM_NOT_CONNECTED; } diff --git a/rpcs3/Emu/Cell/Modules/cellPad.cpp b/rpcs3/Emu/Cell/Modules/cellPad.cpp index 61e29805aa..086a341854 100644 --- a/rpcs3/Emu/Cell/Modules/cellPad.cpp +++ b/rpcs3/Emu/Cell/Modules/cellPad.cpp @@ -411,60 +411,27 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false) } }; - for (const Button& button : pad->m_buttons) + for (const Button& button : pad->m_buttons_external) { // here we check btns, and set pad accordingly, // if something changed, set btnChanged - bool pressed = button.m_pressed; - u16 value = button.m_value; - - // Merge copilots - if (!pad->copilots.empty()) - { - for (const auto& copilot : pad->copilots) - { - if (!copilot || !copilot->is_connected()) - { - continue; - } - - for (const Button& other : copilot->m_buttons) - { - if (button.m_offset == other.m_offset && button.m_outKeyCode == other.m_outKeyCode) - { - if (other.m_pressed) - { - pressed = true; - - if (value < other.m_value) - { - value = other.m_value; - } - } - - break; - } - } - } - } - switch (button.m_offset) { case CELL_PAD_BTN_OFFSET_DIGITAL1: { - if (pressed) + if (button.m_pressed) pad->m_digital_1 |= button.m_outKeyCode; else pad->m_digital_1 &= ~button.m_outKeyCode; switch (button.m_outKeyCode) { - case CELL_PAD_CTRL_LEFT: set_value(pad->m_press_left, value); break; - case CELL_PAD_CTRL_DOWN: set_value(pad->m_press_down, value); break; - case CELL_PAD_CTRL_RIGHT: set_value(pad->m_press_right, value); break; - case CELL_PAD_CTRL_UP: set_value(pad->m_press_up, value); break; - // These arent pressure btns + case CELL_PAD_CTRL_LEFT: set_value(pad->m_press_left, button.m_value); break; + case CELL_PAD_CTRL_DOWN: set_value(pad->m_press_down, button.m_value); break; + case CELL_PAD_CTRL_RIGHT: set_value(pad->m_press_right, button.m_value); break; + case CELL_PAD_CTRL_UP: set_value(pad->m_press_up, button.m_value); break; + // These aren't pressure btns case CELL_PAD_CTRL_R3: case CELL_PAD_CTRL_L3: case CELL_PAD_CTRL_START: @@ -475,21 +442,21 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false) } case CELL_PAD_BTN_OFFSET_DIGITAL2: { - if (pressed) + if (button.m_pressed) pad->m_digital_2 |= button.m_outKeyCode; else pad->m_digital_2 &= ~button.m_outKeyCode; switch (button.m_outKeyCode) { - case CELL_PAD_CTRL_SQUARE: set_value(pad->m_press_square, value); break; - case CELL_PAD_CTRL_CROSS: set_value(pad->m_press_cross, value); break; - case CELL_PAD_CTRL_CIRCLE: set_value(pad->m_press_circle, value); break; - case CELL_PAD_CTRL_TRIANGLE: set_value(pad->m_press_triangle, value); break; - case CELL_PAD_CTRL_R1: set_value(pad->m_press_R1, value); break; - case CELL_PAD_CTRL_L1: set_value(pad->m_press_L1, value); break; - case CELL_PAD_CTRL_R2: set_value(pad->m_press_R2, value); break; - case CELL_PAD_CTRL_L2: set_value(pad->m_press_L2, value); break; + case CELL_PAD_CTRL_SQUARE: set_value(pad->m_press_square, button.m_value); break; + case CELL_PAD_CTRL_CROSS: set_value(pad->m_press_cross, button.m_value); break; + case CELL_PAD_CTRL_CIRCLE: set_value(pad->m_press_circle, button.m_value); break; + case CELL_PAD_CTRL_TRIANGLE: set_value(pad->m_press_triangle, button.m_value); break; + case CELL_PAD_CTRL_R1: set_value(pad->m_press_R1, button.m_value); break; + case CELL_PAD_CTRL_L1: set_value(pad->m_press_L1, button.m_value); break; + case CELL_PAD_CTRL_R2: set_value(pad->m_press_R2, button.m_value); break; + case CELL_PAD_CTRL_L2: set_value(pad->m_press_L2, button.m_value); break; default: break; } break; @@ -498,18 +465,18 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false) { switch (button.m_outKeyCode) { - case CELL_PAD_CTRL_PRESS_RIGHT: set_value(pad->m_press_right, value, true); break; - case CELL_PAD_CTRL_PRESS_LEFT: set_value(pad->m_press_left, value, true); break; - case CELL_PAD_CTRL_PRESS_UP: set_value(pad->m_press_up, value, true); break; - case CELL_PAD_CTRL_PRESS_DOWN: set_value(pad->m_press_down, value, true); break; - case CELL_PAD_CTRL_PRESS_TRIANGLE: set_value(pad->m_press_triangle, value, true, 255, 63); break; // Infrared on RIDE Skateboard - case CELL_PAD_CTRL_PRESS_CIRCLE: set_value(pad->m_press_circle, value, true, 255, 63); break; // Infrared on RIDE Skateboard - case CELL_PAD_CTRL_PRESS_CROSS: set_value(pad->m_press_cross, value, true, 255, 63); break; // Infrared on RIDE Skateboard - case CELL_PAD_CTRL_PRESS_SQUARE: set_value(pad->m_press_square, value, true, 255, 63); break; // Infrared on RIDE Skateboard - case CELL_PAD_CTRL_PRESS_L1: set_value(pad->m_press_L1, value, true); break; - case CELL_PAD_CTRL_PRESS_R1: set_value(pad->m_press_R1, value, true); break; - case CELL_PAD_CTRL_PRESS_L2: set_value(pad->m_press_L2, value, true); break; - case CELL_PAD_CTRL_PRESS_R2: set_value(pad->m_press_R2, value, true); break; + case CELL_PAD_CTRL_PRESS_RIGHT: set_value(pad->m_press_right, button.m_value, true); break; + case CELL_PAD_CTRL_PRESS_LEFT: set_value(pad->m_press_left, button.m_value, true); break; + case CELL_PAD_CTRL_PRESS_UP: set_value(pad->m_press_up, button.m_value, true); break; + case CELL_PAD_CTRL_PRESS_DOWN: set_value(pad->m_press_down, button.m_value, true); break; + case CELL_PAD_CTRL_PRESS_TRIANGLE: set_value(pad->m_press_triangle, button.m_value, true, 255, 63); break; // Infrared on RIDE Skateboard + case CELL_PAD_CTRL_PRESS_CIRCLE: set_value(pad->m_press_circle, button.m_value, true, 255, 63); break; // Infrared on RIDE Skateboard + case CELL_PAD_CTRL_PRESS_CROSS: set_value(pad->m_press_cross, button.m_value, true, 255, 63); break; // Infrared on RIDE Skateboard + case CELL_PAD_CTRL_PRESS_SQUARE: set_value(pad->m_press_square, button.m_value, true, 255, 63); break; // Infrared on RIDE Skateboard + case CELL_PAD_CTRL_PRESS_L1: set_value(pad->m_press_L1, button.m_value, true); break; + case CELL_PAD_CTRL_PRESS_R1: set_value(pad->m_press_R1, button.m_value, true); break; + case CELL_PAD_CTRL_PRESS_L2: set_value(pad->m_press_L2, button.m_value, true); break; + case CELL_PAD_CTRL_PRESS_R2: set_value(pad->m_press_R2, button.m_value, true); break; default: break; } break; @@ -519,46 +486,14 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false) } } - for (const AnalogStick& stick : pad->m_sticks) + for (const AnalogStick& stick : pad->m_sticks_external) { - u16 value = stick.m_value; - - // Merge copilots - if (!pad->copilots.empty()) - { - const auto normalize = [](s32 value) - { - return (value - 128) / 127.0f; - }; - - f32 accumulated_value = normalize(value); - - for (const auto& copilot : pad->copilots) - { - if (!copilot || !copilot->is_connected()) - { - continue; - } - - for (const AnalogStick& other : copilot->m_sticks) - { - if (stick.m_offset == other.m_offset) - { - accumulated_value += normalize(other.m_value); - break; - } - } - } - - value = static_cast(std::round(std::clamp(accumulated_value * 127.0f + 128.0f, 0.0f, 255.0f))); - } - switch (stick.m_offset) { - case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X: set_value(pad->m_analog_left_x, value); break; - case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y: set_value(pad->m_analog_left_y, value); break; - case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X: set_value(pad->m_analog_right_x, value); break; - case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y: set_value(pad->m_analog_right_y, value); break; + case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X: set_value(pad->m_analog_left_x, stick.m_value); break; + case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y: set_value(pad->m_analog_left_y, stick.m_value); break; + case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X: set_value(pad->m_analog_right_x, stick.m_value); break; + case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y: set_value(pad->m_analog_right_y, stick.m_value); break; default: break; } } @@ -1305,7 +1240,7 @@ error_code cellPadLddGetPortNo(s32 handle) return CELL_PAD_ERROR_UNINITIALIZED; const auto handler = pad::get_pad_thread(); - auto& pads = handler->GetPads(); + const auto& pads = handler->GetPads(); if (handle < 0 || static_cast(handle) >= pads.size()) return CELL_PAD_ERROR_INVALID_PARAMETER; diff --git a/rpcs3/Emu/Cell/Modules/cellPad.h b/rpcs3/Emu/Cell/Modules/cellPad.h index 3394fe6b2b..0d199e488c 100644 --- a/rpcs3/Emu/Cell/Modules/cellPad.h +++ b/rpcs3/Emu/Cell/Modules/cellPad.h @@ -3,7 +3,6 @@ #include "Emu/Io/pad_types.h" #include -#include "util/types.hpp" enum CellPadError : u32 { diff --git a/rpcs3/Emu/Cell/Modules/cellSaveData.cpp b/rpcs3/Emu/Cell/Modules/cellSaveData.cpp index eec2652f21..7ae96fa64d 100644 --- a/rpcs3/Emu/Cell/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSaveData.cpp @@ -700,11 +700,32 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v u32 errDialog, PSetList setList, PSetBuf setBuf, PFuncList funcList, PFuncFixed funcFixed, PFuncStat funcStat, PFuncFile funcFile, u32 container, u32 unk_op_flags /*TODO*/, vm::ptr userdata, u32 userId, PFuncDone funcDone) { - if (const auto& [ok, list] = setList.try_read(); ok) - cellSaveData.notice("savedata_op(): setList = { .sortType=%d, .sortOrder=%d, .dirNamePrefix='%s' }", list.sortType, list.sortOrder, list.dirNamePrefix); + if (setList) + { + if (const auto& [ok, list] = setList.try_read(); ok) + { + cellSaveData.notice("savedata_op(): setList = { .sortType=%d, .sortOrder=%d, .dirNamePrefix='%s' }", list.sortType, list.sortOrder, list.dirNamePrefix); + } + else + { + cellSaveData.error("savedata_op(): Failed to read setList!"); + } + } - if (const auto& [ok, buf] = setBuf.try_read(); ok) - cellSaveData.notice("savedata_op(): setBuf = { .dirListMax=%d, .fileListMax=%d, .bufSize=%d }", buf.dirListMax, buf.fileListMax, buf.bufSize); + if (setBuf) + { + if (const auto& [ok, buf] = setBuf.try_read(); ok) + { + cellSaveData.notice("savedata_op(): setBuf = { .dirListMax=%d, .fileListMax=%d, .bufSize=%d }", buf.dirListMax, buf.fileListMax, buf.bufSize); + } + else + { + cellSaveData.error("savedata_op(): Failed to read setBuf!"); + } + } + + // There is a lot going on in this function, ensure function log and past log commands have completed for ease of debugging + logs::listener::sync_all(); if (const auto ecode = savedata_check_args(operation, version, dirName, errDialog, setList, setBuf, funcList, funcFixed, funcStat, funcFile, container, unk_op_flags, userdata, userId, funcDone)) @@ -858,25 +879,34 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v const u32 order = setList->sortOrder; const u32 type = setList->sortType; - std::sort(save_entries.begin(), save_entries.end(), [=](const SaveDataEntry& entry1, const SaveDataEntry& entry2) + std::sort(save_entries.begin(), save_entries.end(), [order, type](const SaveDataEntry& entry1, const SaveDataEntry& entry2) -> bool { - if (order == CELL_SAVEDATA_SORTORDER_DESCENT && type == CELL_SAVEDATA_SORTTYPE_MODIFIEDTIME) + const bool mtime_lower = entry1.mtime < entry2.mtime; + const bool mtime_equal = entry1.mtime == entry2.mtime; + const bool subtitle_lower = entry1.subtitle < entry2.subtitle; + const bool subtitle_equal = entry1.subtitle == entry2.subtitle; + const bool revert_order = order == CELL_SAVEDATA_SORTORDER_DESCENT; + + if (type == CELL_SAVEDATA_SORTTYPE_MODIFIEDTIME) { - return entry1.mtime >= entry2.mtime; + if (mtime_equal) + { + return subtitle_lower != revert_order; + } + + return mtime_lower != revert_order; } - if (order == CELL_SAVEDATA_SORTORDER_DESCENT && type == CELL_SAVEDATA_SORTTYPE_SUBTITLE) + else if (type == CELL_SAVEDATA_SORTTYPE_SUBTITLE) { - return entry1.subtitle >= entry2.subtitle; - } - if (order == CELL_SAVEDATA_SORTORDER_ASCENT && type == CELL_SAVEDATA_SORTTYPE_MODIFIEDTIME) - { - return entry1.mtime < entry2.mtime; - } - if (order == CELL_SAVEDATA_SORTORDER_ASCENT && type == CELL_SAVEDATA_SORTTYPE_SUBTITLE) - { - return entry1.subtitle < entry2.subtitle; + if (subtitle_equal) + { + return mtime_lower != revert_order; + } + + return subtitle_lower != revert_order; } + ensure(false); return true; }); } diff --git a/rpcs3/Emu/Cell/Modules/sceNp.cpp b/rpcs3/Emu/Cell/Modules/sceNp.cpp index 9a8e0dba6b..5b5b32cefe 100644 --- a/rpcs3/Emu/Cell/Modules/sceNp.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNp.cpp @@ -4265,7 +4265,7 @@ error_code sceNpManagerGetEntitlementById(vm::cptr entId, vm::ptr signInId) diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index b385829f96..784cf27829 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -5760,7 +5760,7 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module& module // Define some types const auto _func = FunctionType::get(translator.get_type(), { translator.get_type(), // Exec base - translator.GetContextType()->getPointerTo(), // PPU context + translator.get_type(), // PPU context translator.get_type(), // Segment address (for PRX) translator.get_type(), // Memory base translator.get_type(), // r0 diff --git a/rpcs3/Emu/Cell/PPUTranslator.cpp b/rpcs3/Emu/Cell/PPUTranslator.cpp index 4d0cb528ca..7380d8123f 100644 --- a/rpcs3/Emu/Cell/PPUTranslator.cpp +++ b/rpcs3/Emu/Cell/PPUTranslator.cpp @@ -340,7 +340,7 @@ Function* PPUTranslator::GetSymbolResolver(const ppu_module& info) const auto ftype = FunctionType::get(get_type(), { get_type(), // Exec base - GetContextType()->getPointerTo(), // PPU context + m_ir->getPtrTy(), // PPU context get_type(), // Segment address (for PRX) get_type(), // Memory base get_type(), // r0 @@ -380,7 +380,7 @@ Function* PPUTranslator::GetSymbolResolver(const ppu_module& info) const auto addr_array = new GlobalVariable(*m_module, addr_array_type, false, GlobalValue::PrivateLinkage, ConstantDataArray::get(m_context, vec_addrs)); // Create an array of function pointers - const auto func_table_type = ArrayType::get(ftype->getPointerTo(), functions.size()); + const auto func_table_type = ArrayType::get(m_ir->getPtrTy(), functions.size()); const auto init_func_table = ConstantArray::get(func_table_type, functions); const auto func_table = new GlobalVariable(*m_module, func_table_type, false, GlobalVariable::PrivateLinkage, init_func_table); @@ -407,7 +407,7 @@ Function* PPUTranslator::GetSymbolResolver(const ppu_module& info) const auto func_pc = ZExt(m_ir->CreateLoad(ptr_inst->getResultElementType(), ptr_inst), get_type()); ptr_inst = dyn_cast(m_ir->CreateGEP(func_table->getValueType(), func_table, {m_ir->getInt64(0), index_value})); - assert(ptr_inst->getResultElementType() == ftype->getPointerTo()); + assert(ptr_inst->getResultElementType() == m_ir->getPtrTy()); const auto faddr = m_ir->CreateLoad(ptr_inst->getResultElementType(), ptr_inst); const auto faddr_int = m_ir->CreatePtrToInt(faddr, get_type()); @@ -612,7 +612,7 @@ void PPUTranslator::CallFunction(u64 target, Value* indirect) const auto pos = m_ir->CreateShl(indirect, 1); const auto ptr = dyn_cast(m_ir->CreateGEP(get_type(), m_exec, pos)); const auto val = m_ir->CreateLoad(get_type(), ptr); - callee = FunctionCallee(type, m_ir->CreateIntToPtr(val, type->getPointerTo())); + callee = FunctionCallee(type, m_ir->CreateIntToPtr(val, m_ir->getPtrTy())); // Load new segment address const auto seg_base_ptr = m_ir->CreateIntToPtr(m_ir->CreateAdd( @@ -2794,8 +2794,8 @@ void PPUTranslator::MFOCRF(ppu_opcode_t op) else if (std::none_of(m_cr + 0, m_cr + 32, [](auto* p) { return p; })) { // MFCR (optimized) - Value* ln0 = m_ir->CreateIntToPtr(m_ir->CreatePtrToInt(m_ir->CreateStructGEP(m_thread_type, m_thread, 99), GetType()), GetType()->getPointerTo()); - Value* ln1 = m_ir->CreateIntToPtr(m_ir->CreatePtrToInt(m_ir->CreateStructGEP(m_thread_type, m_thread, 115), GetType()), GetType()->getPointerTo()); + Value* ln0 = m_ir->CreateIntToPtr(m_ir->CreatePtrToInt(m_ir->CreateStructGEP(m_thread_type, m_thread, 99), GetType()), m_ir->getPtrTy()); + Value* ln1 = m_ir->CreateIntToPtr(m_ir->CreatePtrToInt(m_ir->CreateStructGEP(m_thread_type, m_thread, 115), GetType()), m_ir->getPtrTy()); ln0 = m_ir->CreateLoad(GetType(), ln0); ln1 = m_ir->CreateLoad(GetType(), ln1); @@ -5384,7 +5384,7 @@ MDNode* PPUTranslator::CheckBranchProbability(u32 bo) void PPUTranslator::build_interpreter() { #define BUILD_VEC_INST(i) { \ - m_function = llvm::cast(m_module->getOrInsertFunction("op_" #i, get_type(), m_thread_type->getPointerTo()).getCallee()); \ + m_function = llvm::cast(m_module->getOrInsertFunction("op_" #i, get_type(), m_ir->getPtrTy()).getCallee()); \ std::fill(std::begin(m_globals), std::end(m_globals), nullptr); \ std::fill(std::begin(m_locals), std::end(m_locals), nullptr); \ IRBuilder<> irb(BasicBlock::Create(m_context, "__entry", m_function)); \ diff --git a/rpcs3/Emu/Cell/RawSPUThread.cpp b/rpcs3/Emu/Cell/RawSPUThread.cpp index 01041555e1..81bb6fd89e 100644 --- a/rpcs3/Emu/Cell/RawSPUThread.cpp +++ b/rpcs3/Emu/Cell/RawSPUThread.cpp @@ -130,6 +130,18 @@ bool spu_thread::read_reg(const u32 addr, u32& value) return true; } + case Prxy_QueryMask_offs: + { + value = mfc_prxy_mask; + return true; + } + + case Prxy_QueryType_offs: + { + value = 0; + return true; + } + case SPU_Out_MBox_offs: { value = ch_out_mbox.pop(); @@ -138,7 +150,29 @@ bool spu_thread::read_reg(const u32 addr, u32& value) case SPU_MBox_Status_offs: { - value = (ch_out_mbox.get_count() & 0xff) | ((4 - ch_in_mbox.get_count()) << 8 & 0xff00) | (ch_out_intr_mbox.get_count() << 16 & 0xff0000); + // Load channel counts atomically + auto counts = std::make_tuple(ch_out_mbox.get_count(), ch_in_mbox.get_count(), ch_out_intr_mbox.get_count()); + + while (true) + { + atomic_fence_acquire(); + + const auto counts_check = std::make_tuple(ch_out_mbox.get_count(), ch_in_mbox.get_count(), ch_out_intr_mbox.get_count()); + + if (counts_check == counts) + { + break; + } + + // Update and reload + counts = counts_check; + } + + const u32 out_mbox = std::get<0>(counts); + const u32 in_mbox = 4 - std::get<1>(counts); + const u32 intr_mbox = std::get<2>(counts); + + value = (out_mbox & 0xff) | ((in_mbox << 8) & 0xff00) | ((intr_mbox << 16) & 0xff0000); return true; } @@ -345,6 +379,8 @@ bool spu_thread::test_is_problem_state_register_offset(u32 offset, bool for_read case MFC_QStatus_offs: case SPU_Out_MBox_offs: case SPU_MBox_Status_offs: + case Prxy_QueryType_offs: + case Prxy_QueryMask_offs: case SPU_Status_offs: case Prxy_TagStatus_offs: case SPU_NPC_offs: diff --git a/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp index cc2fea2d38..c226e678ad 100644 --- a/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp @@ -2886,7 +2886,7 @@ public: // Create interpreter table const auto if_type = get_ftype(); - m_function_table = new GlobalVariable(*m_module, ArrayType::get(if_type->getPointerTo(), 1ull << m_interp_magn), true, GlobalValue::InternalLinkage, nullptr); + m_function_table = new GlobalVariable(*m_module, ArrayType::get(m_ir->getPtrTy(), 1ull << m_interp_magn), true, GlobalValue::InternalLinkage, nullptr); init_luts(); @@ -2930,7 +2930,7 @@ public: m_ir->CreateStore(m_ir->CreateCall(get_intrinsic(Intrinsic::read_register), {rsp_name}), native_sp); // Decode (shift) and load function pointer - const auto first = m_ir->CreateLoad(if_type->getPointerTo(), m_ir->CreateGEP(if_type->getPointerTo(), m_interp_table, m_ir->CreateLShr(m_interp_op, 32u - m_interp_magn))); + const auto first = m_ir->CreateLoad(m_ir->getPtrTy(), m_ir->CreateGEP(m_ir->getPtrTy(), m_interp_table, m_ir->CreateLShr(m_interp_op, 32u - m_interp_magn))); const auto call0 = m_ir->CreateCall(if_type, first, {m_lsptr, m_thread, m_interp_pc, m_interp_op, m_interp_table, m_interp_7f0, m_interp_regs}); call0->setCallingConv(CallingConv::GHC); m_ir->CreateRetVoid(); @@ -3074,7 +3074,7 @@ public: const auto next_pc = itype & spu_itype::branch ? m_interp_pc : m_interp_pc_next; const auto be32_op = m_ir->CreateLoad(get_type(), m_ir->CreateGEP(get_type(), m_lsptr, m_ir->CreateZExt(next_pc, get_type()))); const auto next_op = m_ir->CreateCall(get_intrinsic(Intrinsic::bswap), {be32_op}); - const auto next_if = m_ir->CreateLoad(if_type->getPointerTo(), m_ir->CreateGEP(if_type->getPointerTo(), m_interp_table, m_ir->CreateLShr(next_op, 32u - m_interp_magn))); + const auto next_if = m_ir->CreateLoad(m_ir->getPtrTy(), m_ir->CreateGEP(m_ir->getPtrTy(), m_interp_table, m_ir->CreateLShr(next_op, 32u - m_interp_magn))); llvm::cast(next_if)->setVolatile(true); if (!(itype & spu_itype::branch)) @@ -3199,7 +3199,7 @@ public: } } - m_function_table->setInitializer(ConstantArray::get(ArrayType::get(if_type->getPointerTo(), 1ull << m_interp_magn), iptrs)); + m_function_table->setInitializer(ConstantArray::get(ArrayType::get(m_ir->getPtrTy(), 1ull << m_interp_magn), iptrs)); m_function_table = nullptr; for (auto& f : *_module) @@ -7808,7 +7808,7 @@ public: m_ir->CreateStore(splat(-1).eval(m_ir), m_ir->CreateGEP(get_type(), m_thread, stack0.value)); const auto targ = m_ir->CreateAdd(m_ir->CreateLShr(_ret, 32), get_segment_base()); const auto type = m_finfo->chunk->getFunctionType(); - const auto fval = m_ir->CreateIntToPtr(targ, type->getPointerTo()); + const auto fval = m_ir->CreateIntToPtr(targ, m_ir->getPtrTy()); tail_chunk({type, fval}, m_ir->CreateTrunc(m_ir->CreateLShr(link, 32), get_type())); m_ir->SetInsertPoint(fail); } diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index dc6e6f364a..bd474d8122 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -4047,6 +4047,22 @@ void do_cell_atomic_128_store(u32 addr, const void* to_write) auto& sdata = *vm::get_super_ptr(addr); auto& res = *utils::bless>(vm::g_reservations + (addr & 0xff80) / 2); + if (std::memcmp(static_cast(to_write), &sdata, 16) == 0 && std::memcmp(static_cast(to_write) + 64, &sdata[64], 16) == 0) + { + const auto& write_data = *static_cast(to_write); + const u64 at_read_time = vm::reservation_acquire(addr); + + if (!(at_read_time & 127)) + { + if (cmp_rdata(sdata, write_data) && at_read_time == vm::reservation_acquire(addr) && cmp_rdata(sdata, write_data)) + { + // Write of the same data (verified atomically) + vm::try_reservation_update(addr); + return; + } + } + } + for (u64 j = 0;; j++) { auto [_oldd, _ok] = res.fetch_op([&](u128& r) diff --git a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp index 0696481efa..e9f57dbec6 100644 --- a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp @@ -285,8 +285,10 @@ private: libusb_context* ctx = nullptr; +#ifndef _WIN32 #if LIBUSB_API_VERSION >= 0x01000102 libusb_hotplug_callback_handle callback_handle {}; +#endif #endif bool hotplug_supported = false; @@ -302,6 +304,7 @@ void LIBUSB_CALL callback_transfer(struct libusb_transfer* transfer) usbh.transfer_complete(transfer); } +#ifndef _WIN32 #if LIBUSB_API_VERSION >= 0x01000102 static int LIBUSB_CALL hotplug_callback(libusb_context* /*ctx*/, libusb_device * /*dev*/, libusb_hotplug_event event, void * /*user_data*/) { @@ -309,6 +312,7 @@ static int LIBUSB_CALL hotplug_callback(libusb_context* /*ctx*/, libusb_device * return 0; } #endif +#endif #if LIBUSB_API_VERSION >= 0x0100010A static void LIBUSB_CALL log_cb(libusb_context* /*ctx*/, enum libusb_log_level level, const char* str) @@ -597,9 +601,11 @@ usb_handler_thread::~usb_handler_thread() libusb_free_transfer(transfers[index].transfer); } +#ifndef _WIN32 #if LIBUSB_API_VERSION >= 0x01000102 if (ctx && hotplug_supported) libusb_hotplug_deregister_callback(ctx, callback_handle); +#endif #endif if (ctx) diff --git a/rpcs3/Emu/Io/Buzz.cpp b/rpcs3/Emu/Io/Buzz.cpp index d5b7fe4f23..840220b967 100644 --- a/rpcs3/Emu/Io/Buzz.cpp +++ b/rpcs3/Emu/Io/Buzz.cpp @@ -173,7 +173,7 @@ void usb_device_buzz::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpoint*/ { const auto& pad = pads[i]; - if (!pad->is_connected()) + if (!pad->is_connected() || pad->is_copilot()) { continue; } diff --git a/rpcs3/Emu/Io/GHLtar.cpp b/rpcs3/Emu/Io/GHLtar.cpp index 9a2b9d0ce6..0c99c6aabf 100644 --- a/rpcs3/Emu/Io/GHLtar.cpp +++ b/rpcs3/Emu/Io/GHLtar.cpp @@ -152,7 +152,7 @@ void usb_device_ghltar::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpoint const auto handler = pad::get_pad_thread(); const auto& pad = ::at32(handler->GetPads(), m_controller_index); - if (!pad->is_connected()) + if (!pad->is_connected() || pad->is_copilot()) { return; } diff --git a/rpcs3/Emu/Io/GameTablet.cpp b/rpcs3/Emu/Io/GameTablet.cpp index 0b87a709bf..4c2330d908 100644 --- a/rpcs3/Emu/Io/GameTablet.cpp +++ b/rpcs3/Emu/Io/GameTablet.cpp @@ -198,9 +198,9 @@ void usb_device_gametablet::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endp const auto gamepad_handler = pad::get_pad_thread(); const auto& pads = gamepad_handler->GetPads(); const auto& pad = ::at32(pads, m_controller_index); - if (pad->is_connected()) + if (pad->is_connected() && !pad->is_copilot()) { - for (Button& button : pad->m_buttons) + for (Button& button : pad->m_buttons_external) { if (!button.m_pressed) { diff --git a/rpcs3/Emu/Io/GunCon3.cpp b/rpcs3/Emu/Io/GunCon3.cpp index 8dc5688f73..522369d8a4 100644 --- a/rpcs3/Emu/Io/GunCon3.cpp +++ b/rpcs3/Emu/Io/GunCon3.cpp @@ -258,7 +258,7 @@ void usb_device_guncon3::interrupt_transfer(u32 buf_size, u8* buf, u32 endpoint, const auto gamepad_handler = pad::get_pad_thread(); const auto& pads = gamepad_handler->GetPads(); const auto& pad = ::at32(pads, m_controller_index); - if (pad->is_connected()) + if (pad->is_connected() && !pad->is_copilot()) { cfg->handle_input(pad, true, input_callback); } diff --git a/rpcs3/Emu/Io/TopShotElite.cpp b/rpcs3/Emu/Io/TopShotElite.cpp index b7e2b64b98..c241fe1ed4 100644 --- a/rpcs3/Emu/Io/TopShotElite.cpp +++ b/rpcs3/Emu/Io/TopShotElite.cpp @@ -318,7 +318,7 @@ void usb_device_topshotelite::interrupt_transfer(u32 buf_size, u8* buf, u32 /*en const auto gamepad_handler = pad::get_pad_thread(); const auto& pads = gamepad_handler->GetPads(); const auto& pad = ::at32(pads, m_controller_index); - if (pad->is_connected()) + if (pad->is_connected() && !pad->is_copilot()) { cfg->handle_input(pad, true, input_callback); } diff --git a/rpcs3/Emu/Io/TopShotFearmaster.cpp b/rpcs3/Emu/Io/TopShotFearmaster.cpp index 03c634d839..eed7ade977 100644 --- a/rpcs3/Emu/Io/TopShotFearmaster.cpp +++ b/rpcs3/Emu/Io/TopShotFearmaster.cpp @@ -342,7 +342,7 @@ void usb_device_topshotfearmaster::interrupt_transfer(u32 buf_size, u8* buf, u32 const auto gamepad_handler = pad::get_pad_thread(); const auto& pads = gamepad_handler->GetPads(); const auto& pad = ::at32(pads, m_controller_index); - if (pad->is_connected()) + if (pad->is_connected() && !pad->is_copilot()) { cfg->handle_input(pad, true, input_callback); } diff --git a/rpcs3/Emu/Io/Turntable.cpp b/rpcs3/Emu/Io/Turntable.cpp index ec67fabc22..261af88d16 100644 --- a/rpcs3/Emu/Io/Turntable.cpp +++ b/rpcs3/Emu/Io/Turntable.cpp @@ -166,7 +166,7 @@ void usb_device_turntable::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpo const auto& pads = handler->GetPads(); const auto& pad = ::at32(pads, m_controller_index); - if (!pad->is_connected()) + if (!pad->is_connected() || pad->is_copilot()) return; const auto& cfg = ::at32(g_cfg_turntable.players, m_controller_index); diff --git a/rpcs3/Emu/Io/emulated_pad_config.h b/rpcs3/Emu/Io/emulated_pad_config.h index e2b46d3daa..b9bf68a223 100644 --- a/rpcs3/Emu/Io/emulated_pad_config.h +++ b/rpcs3/Emu/Io/emulated_pad_config.h @@ -90,10 +90,10 @@ public: void handle_input(std::shared_ptr pad, bool press_only, const std::function& func) const { - if (!pad) + if (!pad || pad->is_copilot()) return; - for (const Button& button : pad->m_buttons) + for (const Button& button : pad->m_buttons_external) { if (button.m_pressed || !press_only) { @@ -104,7 +104,7 @@ public: } } - for (const AnalogStick& stick : pad->m_sticks) + for (const AnalogStick& stick : pad->m_sticks_external) { if (handle_input(func, stick.m_offset, get_axis_keycode(stick.m_offset, stick.m_value), stick.m_value, true, true)) { diff --git a/rpcs3/Emu/Io/pad_types.h b/rpcs3/Emu/Io/pad_types.h index 57634a66b4..ecbadff3bf 100644 --- a/rpcs3/Emu/Io/pad_types.h +++ b/rpcs3/Emu/Io/pad_types.h @@ -379,20 +379,22 @@ enum special_button_value struct Button { u32 m_offset = 0; - std::set m_key_codes{}; u32 m_outKeyCode = 0; u16 m_value = 0; bool m_pressed = false; + std::set m_key_codes{}; + u16 m_actual_value = 0; // only used in keyboard_pad_handler bool m_analog = false; // only used in keyboard_pad_handler bool m_trigger = false; // only used in keyboard_pad_handler std::map m_pressed_keys{}; // only used in keyboard_pad_handler + Button(){} Button(u32 offset, std::set key_codes, u32 outKeyCode) : m_offset(offset) - , m_key_codes(std::move(key_codes)) , m_outKeyCode(outKeyCode) + , m_key_codes(std::move(key_codes)) { if (offset == CELL_PAD_BTN_OFFSET_DIGITAL1) { @@ -419,9 +421,10 @@ struct Button struct AnalogStick { u32 m_offset = 0; + u16 m_value = 128; + std::set m_key_codes_min{}; std::set m_key_codes_max{}; - u16 m_value = 128; std::map m_pressed_keys_min{}; // only used in keyboard_pad_handler std::map m_pressed_keys_max{}; // only used in keyboard_pad_handler @@ -543,6 +546,9 @@ struct Pad std::array m_sensors{}; std::array m_vibrateMotors{}; + std::vector