Merge branch 'master' into windows-clang

This commit is contained in:
qurious-pixel 2026-04-05 14:31:09 -07:00 committed by GitHub
commit 6f420afc18
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
383 changed files with 19656 additions and 5493 deletions

View File

@ -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++

View File

@ -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

View File

@ -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}"

View File

@ -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'

3
.gitignore vendored
View File

@ -69,6 +69,9 @@ CMakeSettings.json
*PVS-Studio*
PVS/*
# Zed Editor files
.zed/*
# Ignore other system generated files
x64/*
rpcs3/x64/*

2
3rdparty/FAudio vendored

@ -1 +1 @@
Subproject commit e67d761ead486de3e69fa11705456bf94df734ca
Subproject commit 0372329dbb56e7814d0dea7b6eafa7a613bd8042

@ -1 +1 @@
Subproject commit 3982730833b6daefe77dcfb32b5c282851640c17
Subproject commit a0fba77b6f9cfbdb71f8bbec58b6ac4e5e3b1097

View File

@ -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()

2
3rdparty/curl/curl vendored

@ -1 +1 @@
Subproject commit 400fffa90f30c7a2dc762fa33009d24851bd2016
Subproject commit 8c908d2d0a6d32abdedda2c52e90bd56ec76c24d

View File

@ -79,12 +79,16 @@
<ClCompile Include="curl\lib\cookie.c" />
<ClCompile Include="curl\lib\cshutdn.c" />
<ClCompile Include="curl\lib\curlx\base64.c" />
<ClCompile Include="curl\lib\curlx\basename.c" />
<ClCompile Include="curl\lib\curlx\dynbuf.c" />
<ClCompile Include="curl\lib\curlx\fopen.c" />
<ClCompile Include="curl\lib\curlx\inet_ntop.c" />
<ClCompile Include="curl\lib\curlx\inet_pton.c" />
<ClCompile Include="curl\lib\curlx\multibyte.c" />
<ClCompile Include="curl\lib\curlx\nonblock.c" />
<ClCompile Include="curl\lib\curlx\snprintf.c" />
<ClCompile Include="curl\lib\curlx\strcopy.c" />
<ClCompile Include="curl\lib\curlx\strdup.c" />
<ClCompile Include="curl\lib\curlx\strerr.c" />
<ClCompile Include="curl\lib\curlx\strparse.c" />
<ClCompile Include="curl\lib\curlx\timediff.c" />
@ -106,6 +110,7 @@
<ClCompile Include="curl\lib\curl_rtmp.c" />
<ClCompile Include="curl\lib\curl_sasl.c" />
<ClCompile Include="curl\lib\curl_sha512_256.c" />
<ClCompile Include="curl\lib\curl_share.c" />
<ClCompile Include="curl\lib\curl_sspi.c" />
<ClCompile Include="curl\lib\curl_threads.c" />
<ClCompile Include="curl\lib\curl_trc.c" />
@ -169,14 +174,13 @@
<ClCompile Include="curl\lib\progress.c" />
<ClCompile Include="curl\lib\psl.c" />
<ClCompile Include="curl\lib\rand.c" />
<ClCompile Include="curl\lib\rename.c" />
<ClCompile Include="curl\lib\ratelimit.c" />
<ClCompile Include="curl\lib\request.c" />
<ClCompile Include="curl\lib\rtsp.c" />
<ClCompile Include="curl\lib\select.c" />
<ClCompile Include="curl\lib\sendf.c" />
<ClCompile Include="curl\lib\setopt.c" />
<ClCompile Include="curl\lib\sha256.c" />
<ClCompile Include="curl\lib\share.c" />
<ClCompile Include="curl\lib\slist.c" />
<ClCompile Include="curl\lib\smb.c" />
<ClCompile Include="curl\lib\smtp.c" />
@ -184,10 +188,8 @@
<ClCompile Include="curl\lib\socks.c" />
<ClCompile Include="curl\lib\socks_gssapi.c" />
<ClCompile Include="curl\lib\socks_sspi.c" />
<ClCompile Include="curl\lib\speedcheck.c" />
<ClCompile Include="curl\lib\splay.c" />
<ClCompile Include="curl\lib\strcase.c" />
<ClCompile Include="curl\lib\strdup.c" />
<ClCompile Include="curl\lib\strequal.c" />
<ClCompile Include="curl\lib\strerror.c" />
<ClCompile Include="curl\lib\system_win32.c" />
@ -204,6 +206,7 @@
<ClCompile Include="curl\lib\version.c" />
<ClCompile Include="curl\lib\vquic\curl_ngtcp2.c" />
<ClCompile Include="curl\lib\vquic\curl_quiche.c" />
<ClCompile Include="curl\lib\vssh\vssh.c" />
<ClCompile Include="curl\lib\vtls\apple.c" />
<ClCompile Include="curl\lib\vtls\cipher_suite.c" />
<ClCompile Include="curl\lib\vtls\hostcheck.c" />
@ -224,13 +227,11 @@
<ClCompile Include="curl\lib\vauth\spnego_sspi.c" />
<ClCompile Include="curl\lib\vauth\vauth.c" />
<ClCompile Include="curl\lib\vquic\vquic.c" />
<ClCompile Include="curl\lib\vssh\curl_path.c" />
<ClCompile Include="curl\lib\vssh\libssh.c" />
<ClCompile Include="curl\lib\vssh\libssh2.c" />
<ClCompile Include="curl\lib\vtls\gtls.c" />
<ClCompile Include="curl\lib\vtls\keylog.c" />
<ClCompile Include="curl\lib\vtls\mbedtls.c" />
<ClCompile Include="curl\lib\vtls\mbedtls_threadlock.c" />
<ClCompile Include="curl\lib\vtls\openssl.c" />
<ClCompile Include="curl\lib\vtls\schannel.c" />
<ClCompile Include="curl\lib\vtls\schannel_verify.c" />
@ -272,6 +273,7 @@
<ClInclude Include="curl\lib\cookie.h" />
<ClInclude Include="curl\lib\cshutdn.h" />
<ClInclude Include="curl\lib\curlx\base64.h" />
<ClInclude Include="curl\lib\curlx\basename.h" />
<ClInclude Include="curl\lib\curlx\binmode.h" />
<ClInclude Include="curl\lib\curlx\curlx.h" />
<ClInclude Include="curl\lib\curlx\dynbuf.h" />
@ -280,6 +282,9 @@
<ClInclude Include="curl\lib\curlx\inet_pton.h" />
<ClInclude Include="curl\lib\curlx\multibyte.h" />
<ClInclude Include="curl\lib\curlx\nonblock.h" />
<ClInclude Include="curl\lib\curlx\snprintf.h" />
<ClInclude Include="curl\lib\curlx\strcopy.h" />
<ClInclude Include="curl\lib\curlx\strdup.h" />
<ClInclude Include="curl\lib\curlx\strerr.h" />
<ClInclude Include="curl\lib\curlx\strparse.h" />
<ClInclude Include="curl\lib\curlx\timediff.h" />
@ -300,9 +305,7 @@
<ClInclude Include="curl\lib\curl_ldap.h" />
<ClInclude Include="curl\lib\curl_md4.h" />
<ClInclude Include="curl\lib\curl_md5.h" />
<ClInclude Include="curl\lib\curl_memory.h" />
<ClInclude Include="curl\lib\curl_memrchr.h" />
<ClInclude Include="curl\lib\curl_mem_undef.h" />
<ClInclude Include="curl\lib\curl_ntlm_core.h" />
<ClInclude Include="curl\lib\curl_printf.h" />
<ClInclude Include="curl\lib\curl_range.h" />
@ -312,6 +315,7 @@
<ClInclude Include="curl\lib\curl_setup_once.h" />
<ClInclude Include="curl\lib\curl_sha256.h" />
<ClInclude Include="curl\lib\curl_sha512_256.h" />
<ClInclude Include="curl\lib\curl_share.h" />
<ClInclude Include="curl\lib\curl_sspi.h" />
<ClInclude Include="curl\lib\curl_threads.h" />
<ClInclude Include="curl\lib\curl_trc.h" />
@ -352,7 +356,6 @@
<ClInclude Include="curl\lib\imap.h" />
<ClInclude Include="curl\lib\llist.h" />
<ClInclude Include="curl\lib\macos.h" />
<ClInclude Include="curl\lib\memdebug.h" />
<ClInclude Include="curl\lib\mime.h" />
<ClInclude Include="curl\lib\mqtt.h" />
<ClInclude Include="curl\lib\multihandle.h" />
@ -367,7 +370,7 @@
<ClInclude Include="curl\lib\progress.h" />
<ClInclude Include="curl\lib\psl.h" />
<ClInclude Include="curl\lib\rand.h" />
<ClInclude Include="curl\lib\rename.h" />
<ClInclude Include="curl\lib\ratelimit.h" />
<ClInclude Include="curl\lib\request.h" />
<ClInclude Include="curl\lib\rtsp.h" />
<ClInclude Include="curl\lib\select.h" />
@ -376,7 +379,6 @@
<ClInclude Include="curl\lib\setup-os400.h" />
<ClInclude Include="curl\lib\setup-vms.h" />
<ClInclude Include="curl\lib\setup-win32.h" />
<ClInclude Include="curl\lib\share.h" />
<ClInclude Include="curl\lib\sigpipe.h" />
<ClInclude Include="curl\lib\slist.h" />
<ClInclude Include="curl\lib\smb.h" />
@ -384,7 +386,6 @@
<ClInclude Include="curl\lib\sockaddr.h" />
<ClInclude Include="curl\lib\socketpair.h" />
<ClInclude Include="curl\lib\socks.h" />
<ClInclude Include="curl\lib\speedcheck.h" />
<ClInclude Include="curl\lib\splay.h" />
<ClInclude Include="curl\lib\strcase.h" />
<ClInclude Include="curl\lib\strdup.h" />
@ -405,6 +406,7 @@
<ClInclude Include="curl\lib\vquic\curl_ngtcp2.h" />
<ClInclude Include="curl\lib\vquic\curl_quiche.h" />
<ClInclude Include="curl\lib\vquic\vquic_int.h" />
<ClInclude Include="curl\lib\vssh\vssh.h" />
<ClInclude Include="curl\lib\vtls\apple.h" />
<ClInclude Include="curl\lib\vtls\cipher_suite.h" />
<ClInclude Include="curl\lib\vtls\hostcheck.h" />
@ -418,12 +420,10 @@
<ClInclude Include="curl\lib\vauth\ntlm.h" />
<ClInclude Include="curl\lib\vauth\vauth.h" />
<ClInclude Include="curl\lib\vquic\vquic.h" />
<ClInclude Include="curl\lib\vssh\curl_path.h" />
<ClInclude Include="curl\lib\vssh\ssh.h" />
<ClInclude Include="curl\lib\vtls\gtls.h" />
<ClInclude Include="curl\lib\vtls\keylog.h" />
<ClInclude Include="curl\lib\vtls\mbedtls.h" />
<ClInclude Include="curl\lib\vtls\mbedtls_threadlock.h" />
<ClInclude Include="curl\lib\vtls\openssl.h" />
<ClInclude Include="curl\lib\vtls\schannel.h" />
<ClInclude Include="curl\lib\vtls\vtls.h" />

View File

@ -204,9 +204,6 @@
<ClCompile Include="curl\lib\rand.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\rename.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\rtsp.c">
<Filter>Source Files</Filter>
</ClCompile>
@ -222,9 +219,6 @@
<ClCompile Include="curl\lib\sha256.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\share.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\slist.c">
<Filter>Source Files</Filter>
</ClCompile>
@ -246,18 +240,12 @@
<ClCompile Include="curl\lib\socks_sspi.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\speedcheck.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\splay.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\strcase.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\strdup.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\strerror.c">
<Filter>Source Files</Filter>
</ClCompile>
@ -318,9 +306,6 @@
<ClCompile Include="curl\lib\vauth\vauth.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\vssh\curl_path.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\vssh\libssh.c">
<Filter>Source Files</Filter>
</ClCompile>
@ -333,9 +318,6 @@
<ClCompile Include="curl\lib\vtls\mbedtls.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\vtls\mbedtls_threadlock.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\vtls\openssl.c">
<Filter>Source Files</Filter>
</ClCompile>
@ -549,6 +531,27 @@
<ClCompile Include="curl\lib\curlx\strerr.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\curlx\strcopy.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\vssh\vssh.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\curl_share.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\ratelimit.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\curlx\basename.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\curlx\snprintf.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\curlx\strdup.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="curl\include\curl\curl.h">
@ -653,9 +656,6 @@
<ClInclude Include="curl\lib\curl_md5.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\curl_memory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\curl_memrchr.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -758,9 +758,6 @@
<ClInclude Include="curl\lib\llist.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\memdebug.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\mime.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -791,9 +788,6 @@
<ClInclude Include="curl\lib\rand.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\rename.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\rtsp.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -812,9 +806,6 @@
<ClInclude Include="curl\lib\setup-vms.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\share.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\sigpipe.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -836,9 +827,6 @@
<ClInclude Include="curl\lib\socks.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\speedcheck.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\splay.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -887,9 +875,6 @@
<ClInclude Include="curl\lib\vauth\vauth.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\vssh\curl_path.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\vssh\ssh.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -899,9 +884,6 @@
<ClInclude Include="curl\lib\vtls\mbedtls.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\vtls\mbedtls_threadlock.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\vtls\openssl.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -1103,9 +1085,6 @@
<ClInclude Include="curl\lib\cf-ip-happy.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\curl_mem_undef.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\curl_fopen.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -1121,6 +1100,27 @@
<ClInclude Include="curl\lib\curlx\strerr.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\curlx\snprintf.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\curlx\strcopy.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\vssh\vssh.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\curl_share.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\ratelimit.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\curlx\basename.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\curlx\strdup.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="curl\lib\libcurl.rc">

@ -1 +1 @@
Subproject commit c3e304954a9cfd154bc0dfbfea2b01cd61d6546d
Subproject commit d5515b5b8be3901aac04e5bd8bd5c89f287bcd33

@ -1 +1 @@
Subproject commit 683181b47cfabd293e3ea409f838915b8297a4fd
Subproject commit 5848e584a1b606de26e3dbd1c7e4ecbc34f807a6

View File

@ -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)

13
3rdparty/qt6.cmake vendored
View File

@ -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)

@ -1 +1 @@
Subproject commit b077c81eb635392e694ccedbab8b644297ec0285
Subproject commit 922d04b3568c6428a9fb905ddee3ef5a68db3108

@ -1 +1 @@
Subproject commit 05c44fcd18074836e21e1eda9fc02b3a4a1529b5
Subproject commit 51a5d623e3fde1f58829a56ba910f1cb33596222

View File

@ -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)

View File

@ -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. `<QtInstallFolder>\6.10.2\msvc2022_64\`
- add and set the `QTDIR` environment variable, e.g. `<QtInstallFolder>\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. `<QtInstallFolder>\6.10.2\msvc2022_64\`
- add and set the `Qt6_ROOT` environment variable to the **Qt** libs path, e.g. `<QtInstallFolder>\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. `<QtInstallFolder>\6.10.2\msvc2022_64`, version will fill in automatically
2) add the path to your Qt installation with compiler e.g. `<QtInstallFolder>\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**)

View File

@ -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$<$<CONFIG:Debug>: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$<$<CONFIG:Debug>: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$<$<CONFIG:Debug>: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("$<$<COMPILE_LANGUAGE:C,CXX>:/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("$<$<COMPILE_LANGUAGE:C,CXX>:/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

View File

@ -362,6 +362,27 @@ std::vector<std::string> cfg::try_to_enum_list(decltype(&fmt_class_string<int>::
return result;
}
size_t cfg::try_to_enum_size(decltype(&fmt_class_string<int>::format) func)
{
size_t result = 0;
for (u64 i = 0;; i++)
{
std::string var;
func(var, i);
std::string hex;
fmt_class_string<u64>::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<const log_entry&>(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);
}

View File

@ -30,6 +30,9 @@ namespace cfg
// Internal hack
std::vector<std::string> try_to_enum_list(decltype(&fmt_class_string<int>::format) func);
// Internal hack
size_t try_to_enum_size(decltype(&fmt_class_string<int>::format) func);
// Config tree entry type.
enum class type : unsigned
{
@ -312,6 +315,11 @@ namespace cfg
{
return try_to_enum_list(&fmt_class_string<T>::format);
}
size_t size() const
{
return try_to_enum_size(&fmt_class_string<T>::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<int_type>(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<float_type>(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<int_type>(value);
}

View File

@ -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<fs::error>::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";

View File

@ -683,6 +683,7 @@ namespace fs
notempty,
readonly,
isdir,
notdir,
toolong,
nospace,
xdev,

View File

@ -493,6 +493,10 @@ inline FT build_function_asm(std::string_view name, F&& builder, ::jit_runtime*
return reinterpret_cast<FT>(uptr(result));
}
#if defined(__INTELLISENSE__) && !defined(LLVM_AVAILABLE)
#define LLVM_AVAILABLE
#endif
#ifdef LLVM_AVAILABLE
namespace llvm

View File

@ -16,12 +16,12 @@
#include <errno.h>
#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"

View File

@ -14,6 +14,11 @@
#include "Emu/CPU/Backends/AArch64/AArch64Signal.h"
#endif
#ifdef __cpp_lib_stacktrace
#include "rpcs3_version.h"
#include <stacktrace>
#endif
#ifdef _WIN32
#include <Windows.h>
#include <Psapi.h>
@ -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<bool(u32 addr, bool is_writing)> 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<named_thread<spu_thread>>(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<void>(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<u32>(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<u32>(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<u64>(info->si_addr) - reinterpret_cast<u64>(vm::g_exec_addr)) / 2;
const u64 exec64_2 = (reinterpret_cast<u64>(info->si_addr) - reinterpret_cast<u64>(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<u32>(exec64), is_writing, context))
if (thread_ctrl::get_current() && handle_access_violation(static_cast<u32>(exec64), is_writing, true, context))
{
return;
}
}
else if (exec64_2 < 0x100000000ull && !is_executing)
{
if (thread_ctrl::get_current() && handle_access_violation(static_cast<u32>(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;

View File

@ -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);

View File

@ -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 */

View File

@ -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;

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 618 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 497 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 561 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 472 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 473 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 702 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 587 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 668 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 B

BIN
bin/Icons/ui/loading.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 KiB

View File

@ -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()

View File

@ -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)

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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"
};

View File

@ -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<CPUDisAsm> 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<std::pair<u32, u32>> 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

View File

@ -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<cpu_flag> 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<std::pair<u32, u32>> 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;

View File

@ -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<llvm::Constant>(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<llvm::CastInst>(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<llvm::CastInst>(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<llvm::CastInst>(*bci->use_begin());
}
}
// Do bitcast on the source
if (const auto c1 = llvm::dyn_cast<llvm::Constant>(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 <>

View File

@ -43,6 +43,7 @@
#include <functional>
#include <unordered_map>
#include <source_location>
// Helper function
llvm::Value* peek_through_bitcasts(llvm::Value*);
@ -567,6 +568,32 @@ struct llvm_placeholder_t
}
};
template <typename T, typename U = llvm_common_t<llvm_value_t<T>>>
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<T>::get_type(value->getContext()))
{
return {};
}
value = nullptr;
return {};
}
};
template <typename T, bool ForceSigned = false>
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 <typename T>
llvm::Value* bitcast(llvm::Value* val)
@ -3224,6 +3254,12 @@ public:
return {};
}
template <typename T>
static llvm_place_stealer_t<T> match_stealer()
{
return {};
}
template <typename T>
requires requires { typename llvm_common_t<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<u8[16]>()), m_ir->CreateBitCast(data2, get_type<u8[16]>())});
#else
result.value = m_ir->CreateCall(get_intrinsic(llvm::Intrinsic::x86_avx512_vpdpbusd_128), {data0, data1, data2});
#endif
return result;
}
#ifdef ARCH_ARM64
template <typename T1, typename T2, typename T3>
value_t<u32[4]> udot(T1 a, T2 b, T3 c)
{
value_t<u32[4]> 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<u32[4], u8[16]>(llvm::Intrinsic::aarch64_neon_udot), {data0, data1, data2});
return result;
}
template <typename T1, typename T2, typename T3>
value_t<u32[4]> sdot(T1 a, T2 b, T3 c)
{
value_t<u32[4]> 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<u32[4], u8[16]>(llvm::Intrinsic::aarch64_neon_sdot), {data0, data1, data2});
return result;
}
template <typename T1, typename T2>
auto addp(T1 a, T2 b)
{
using T_vector = typename is_llvm_expr<T1>::type;
const auto data1 = a.eval(m_ir);
const auto data2 = b.eval(m_ir);
const auto func = get_intrinsic<T_vector>(llvm::Intrinsic::aarch64_neon_addp);
value_t<T_vector> result;
result.value = m_ir->CreateCall(func, {data1, data2});
return result;
}
#endif
template <typename T1, typename T2>
value_t<u8[16]> 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<llvm::Function>(m_ir->GetInsertBlock()->getParent()->getParent()->getOrInsertFunction("llvm.debugtrap", type).getCallee());
m_ir->CreateCall(func);
}
template <typename T, typename U>
static auto pshufb(T&& a, U&& b)
{

View File

@ -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<u32>(sys_mutex_lock(ppu, output_mutex, 0) != CELL_OK);
error_occurred |= static_cast<u32>(lv2_syscall<sys_mutex_lock>(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<sys_cond_wait>(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<sys_mutex_lock>(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<sys_mutex_unlock>(ppu, queue_mutex) == CELL_OK); // Error code isn't checked on LLE
cellAdec.trace("Command type: %d", static_cast<u32>(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<u32>(sys_mutex_unlock(ppu, output_mutex) != CELL_OK);
error_occurred |= static_cast<u32>(lv2_syscall<sys_mutex_unlock>(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<u32>(sys_mutex_unlock(ppu, output_mutex) != CELL_OK);
error_occurred |= static_cast<u32>(lv2_syscall<sys_mutex_unlock>(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<sys_mutex_unlock>(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<u32>(sys_mutex_unlock(ppu, output_mutex) != CELL_OK);
error_occurred |= static_cast<u32>(lv2_syscall<sys_mutex_unlock>(ppu, output_mutex) != CELL_OK);
const vm::var<CellAdecLpcmInfo> bsi_info{{ lpcm_param->channelNumber, lpcm_param->sampleRate, static_cast<u32>(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<sys_mutex_lock>(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<sys_mutex_unlock>(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<sys_mutex_lock>(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<sys_mutex_unlock>(ppu, queue_size_mutex) == CELL_OK); // Error code isn't checked on LLE
return ret;
}
cmd_queue.emplace(type, std::forward<decltype(args)>(args)...);
if (error_code ret = sys_mutex_unlock(ppu, queue_mutex); ret != CELL_OK
if (error_code ret = lv2_syscall<sys_mutex_unlock>(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<sys_mutex_unlock>(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<sys_mutex_unlock>(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<sys_mutex_lock>(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<sys_cond_signal>(ppu, output_consumed); ret != CELL_OK)
{
return ret; // LLE doesn't unlock the mutex
}
return sys_mutex_unlock(ppu, output_mutex);
return lv2_syscall<sys_mutex_unlock>(ppu, output_mutex);
}
void lpcmDecEntry(ppu_thread& ppu, vm::ptr<LpcmDecContext> lpcm_dec)
@ -820,13 +820,13 @@ error_code _CellAdecCoreOpOpenExt_lpcm(ppu_thread& ppu, vm::ptr<LpcmDecContext>
const vm::var<sys_mutex_attribute_t> 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<sys_cond_attribute_t> 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<sys_mutex_create>(ppu, handle.ptr(&LpcmDecContext::queue_size_mutex), mutex_attr);
ret = ret ? ret : lv2_syscall<sys_cond_create>(ppu, handle.ptr(&LpcmDecContext::queue_size_cond), handle->queue_size_mutex, cond_attr);
ret = ret ? ret : lv2_syscall<sys_mutex_create>(ppu, handle.ptr(&LpcmDecContext::unk_mutex), mutex_attr);
ret = ret ? ret : lv2_syscall<sys_cond_create>(ppu, handle.ptr(&LpcmDecContext::unk_cond), handle->unk_mutex, cond_attr);
ret = ret ? ret : lv2_syscall<sys_mutex_create>(ppu, handle.ptr(&LpcmDecContext::output_mutex), output_mutex_attr);
ret = ret ? ret : lv2_syscall<sys_cond_create>(ppu, handle.ptr(&LpcmDecContext::output_consumed), handle->output_mutex, cond_attr);
ret = ret ? ret : lv2_syscall<sys_mutex_create>(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<LpcmDecContext>
const auto entry = g_fxo->get<ppu_function_manager>().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<sys_mutex_create>(ppu, handle.ptr(&LpcmDecContext::spurs_queue_pop_mutex), mutex_attr);
ret = ret ? ret : lv2_syscall<sys_mutex_create>(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<LpcmDecContext> 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<sys_mutex_lock>(ppu, handle->queue_size_mutex, 0); ret != CELL_OK
|| (ret = lv2_syscall<sys_mutex_lock>(ppu, handle->queue_mutex, 0)) != CELL_OK)
{
return ret;
}
@ -875,14 +875,14 @@ error_code _CellAdecCoreOpClose_lpcm(ppu_thread& ppu, vm::ptr<LpcmDecContext> 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<sys_mutex_unlock>(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<sys_mutex_unlock>(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<LpcmDecContext> 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<sys_mutex_unlock>(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<sys_mutex_unlock>(ppu, handle->queue_size_mutex);
ret = ret ? ret : handle->release_output(ppu);
vm::var<u64> thread_ret;
ret = ret ? ret : sys_ppu_thread_join(ppu, static_cast<u32>(handle->thread_id), +thread_ret);
ret = ret ? ret : lv2_syscall<sys_ppu_thread_join>(ppu, static_cast<u32>(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<sys_cond_destroy>(ppu, handle->queue_size_cond);
ret = ret ? ret : lv2_syscall<sys_cond_destroy>(ppu, handle->unk_cond);
ret = ret ? ret : lv2_syscall<sys_cond_destroy>(ppu, handle->output_consumed);
ret = ret ? ret : lv2_syscall<sys_mutex_destroy>(ppu, handle->queue_mutex);
ret = ret ? ret : lv2_syscall<sys_mutex_destroy>(ppu, handle->queue_size_mutex);
ret = ret ? ret : lv2_syscall<sys_mutex_destroy>(ppu, handle->unk_mutex);
ret = ret ? ret : lv2_syscall<sys_mutex_destroy>(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<sys_mutex_destroy>(ppu, handle->spurs_queue_pop_mutex);
ret = ret ? ret : lv2_syscall<sys_mutex_destroy>(ppu, handle->spurs_queue_push_mutex);
return ret;
}
@ -1091,11 +1091,11 @@ error_code AdecContext::set_pcm_item(s32 pcm_handle, vm::ptr<void> 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<sys_mutex_lock>(ppu, mutex, 0) == CELL_OK); // Error code isn't checked on LLE
if (verify_pcm_handle(pcm_handle) == static_cast<s32>(CELL_ADEC_ERROR_FATAL))
{
ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_unlock>(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<sys_mutex_unlock>(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<sys_mutex_unlock>(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<sys_mutex_lock>(ppu, mutex, 0) == CELL_OK); // Error code isn't checked on LLE
if (verify_pcm_handle(pcm_handle) == static_cast<s32>(CELL_ADEC_ERROR_FATAL))
{
ensure(sys_mutex_unlock(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_unlock>(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<sys_mutex_unlock>(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<sys_mutex_unlock>(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<sys_mutex_unlock>(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<CellAdecType> type, vm::cptr<CellAd
frames[i].prev = 0;
}
ensure(sys_mutex_create(ppu, _this.ptr(&AdecContext::mutex), _this.ptr(&AdecContext::mutex_attribute)) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_create>(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<AdecContext> handle)
return ret;
}
if (error_code ret = sys_mutex_destroy(ppu, handle->mutex); ret != CELL_OK)
if (error_code ret = lv2_syscall<sys_mutex_destroy>(ppu, handle->mutex); ret != CELL_OK)
{
return ret;
}

View File

@ -485,6 +485,19 @@ struct AdecFrame
CHECK_SIZE(AdecFrame, 0x68);
template <auto Syscall>
static auto lv2_syscall(ppu_thread& ppu, auto&&... args)
{
const auto ret = Syscall(ppu, std::forward<decltype(args)>(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<sys_mutex_attribute_t> 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<sys_mutex_create>(ppu, _this.ptr(&AdecOutputQueue::mutex), mutex_attr) == CELL_OK); // Error code isn't checked on LLE
const vm::var<sys_cond_attribute_t> 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<sys_cond_create>(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<sys_cond_destroy>(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<sys_mutex_destroy>(ppu, mutex); ret != CELL_OK)
{
return ret;
}
@ -539,11 +552,11 @@ public:
error_code push(ppu_thread& ppu, vm::ptr<CellAdecPcmItem> pcm_item, s32 pcm_handle)
{
ensure(sys_mutex_lock(ppu, mutex, 0) == CELL_OK); // Error code isn't checked on LLE
ensure(lv2_syscall<sys_mutex_lock>(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<sys_mutex_unlock>(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<sys_mutex_unlock>(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<sys_mutex_lock>(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<sys_mutex_unlock>(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<sys_mutex_unlock>(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<sys_mutex_lock>(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<sys_mutex_unlock>(ppu, mutex) == CELL_OK); // Error code isn't checked on LLE
return ret;
}
};
@ -708,39 +721,39 @@ public:
const vm::var<sys_mutex_attribute_t> 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<sys_cond_attribute_t> 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<sys_mutex_create>(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<sys_cond_create>(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<sys_cond_destroy>(ppu, cond); ret != CELL_OK)
{
return ret;
}
return sys_mutex_destroy(ppu, mutex);
return lv2_syscall<sys_mutex_destroy>(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<sys_mutex_lock>(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<sys_cond_signal>(ppu, cond); ret != CELL_OK)
{
return ret; // LLE doesn't unlock the mutex
}
return sys_mutex_unlock(ppu, mutex);
return lv2_syscall<sys_mutex_unlock>(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<sys_mutex_lock>(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<sys_cond_wait>(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<sys_mutex_unlock>(ppu, mutex);
}
};

View File

@ -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<sys_mutex_lock>(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<sys_cond_wait>(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<sys_mutex_unlock>(ppu, queue_mutex) == CELL_OK);
}
cmd_queue.pop(cmd);
ensure(sys_mutex_unlock(ppu, queue_mutex) == CELL_OK);
ensure(lv2_syscall<sys_mutex_unlock>(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<sys_mutex_lock>(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<sys_mutex_unlock>(ppu, run_thread_mutex) == CELL_OK);
return;
}
ensure(sys_mutex_unlock(ppu, run_thread_mutex) == CELL_OK);
ensure(lv2_syscall<sys_mutex_unlock>(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<sys_mutex_lock>(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<sys_cond_wait>(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<sys_mutex_lock>(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<sys_mutex_unlock>(ppu, run_thread_mutex) == CELL_OK);
ensure(lv2_syscall<sys_mutex_unlock>(ppu, output_mutex) == CELL_OK);
return;
}
ensure(sys_mutex_unlock(ppu, run_thread_mutex) == CELL_OK);
ensure(lv2_syscall<sys_mutex_unlock>(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<sys_mutex_unlock>(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<sys_mutex_lock>(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<sys_mutex_unlock>(ppu, queue_mutex) == CELL_OK);
return {};
}
}
if (cmd_queue.full())
{
ensure(sys_mutex_unlock(ppu, queue_mutex) == CELL_OK);
ensure(lv2_syscall<sys_mutex_unlock>(ppu, queue_mutex) == CELL_OK);
return CELL_ADEC_ERROR_ATX_BUSY;
}
cmd_queue.emplace(std::forward<AtracXdecCmdType>(type), std::forward<decltype(args)>(args)...);
ensure(sys_mutex_unlock(ppu, queue_mutex) == CELL_OK);
ensure(lv2_syscall<sys_mutex_unlock>(ppu, queue_mutex) == CELL_OK);
}
ensure(sys_cond_signal(ppu, queue_not_empty) == CELL_OK);
ensure(lv2_syscall<sys_cond_signal>(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<AtracXdecConte
const vm::var<sys_mutex_attribute_t> 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<sys_cond_attribute_t> 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<sys_mutex_create>(ppu, handle.ptr(&AtracXdecContext::queue_mutex), mutex_attr) == CELL_OK);
ensure(lv2_syscall<sys_cond_create>(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<sys_mutex_create>(ppu, handle.ptr(&AtracXdecContext::run_thread_mutex), mutex_attr) == CELL_OK);
ensure(lv2_syscall<sys_cond_create>(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<sys_mutex_create>(ppu, handle.ptr(&AtracXdecContext::output_mutex), mutex_attr) == CELL_OK);
ensure(lv2_syscall<sys_cond_create>(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<sys_mutex_lock>(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<sys_cond_signal>(ppu, handle->output_consumed) == CELL_OK);
ensure(lv2_syscall<sys_mutex_unlock>(ppu, handle->output_mutex) == CELL_OK);
const vm::var<char[]> _name = vm::make_str("HLE ATRAC3plus decoder");
const auto entry = g_fxo->get<ppu_function_manager>().func_addr(FIND_FUNC(atracXdecEntry));
@ -829,26 +829,26 @@ error_code _CellAdecCoreOpClose_atracx(ppu_thread& ppu, vm::ptr<AtracXdecContext
ensure(!!handle); // Not checked on LLE
ensure(sys_mutex_lock(ppu, handle->run_thread_mutex, 0) == CELL_OK);
ensure(lv2_syscall<sys_mutex_lock>(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<sys_mutex_unlock>(ppu, handle->run_thread_mutex) == CELL_OK);
handle->send_command<AtracXdecCmdType::close>(ppu);
ensure(sys_mutex_lock(ppu, handle->output_mutex, 0) == CELL_OK);
ensure(lv2_syscall<sys_mutex_lock>(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<sys_mutex_unlock>(ppu, handle->output_mutex) == CELL_OK);
ensure(lv2_syscall<sys_cond_signal>(ppu, handle->output_consumed) == CELL_OK);
vm::var<u64> thread_ret;
ensure(sys_ppu_thread_join(ppu, static_cast<u32>(handle->thread_id), +thread_ret) == CELL_OK);
ensure(lv2_syscall<sys_ppu_thread_join>(ppu, static_cast<u32>(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<sys_cond_destroy>(ppu, handle->queue_not_empty);
ret = ret ? ret : lv2_syscall<sys_cond_destroy>(ppu, handle->run_thread_cond);
ret = ret ? ret : lv2_syscall<sys_cond_destroy>(ppu, handle->output_consumed);
ret = ret ? ret : lv2_syscall<sys_mutex_destroy>(ppu, handle->queue_mutex);
ret = ret ? ret : lv2_syscall<sys_mutex_destroy>(ppu, handle->run_thread_mutex);
ret = ret ? ret : lv2_syscall<sys_mutex_destroy>(ppu, handle->output_mutex);
return ret != CELL_OK ? static_cast<error_code>(CELL_ADEC_ERROR_FATAL) : CELL_OK;
}
@ -921,7 +921,7 @@ error_code _CellAdecCoreOpReleasePcm_atracx(ppu_thread& ppu, vm::ptr<AtracXdecCo
if (!signal)
{
ensure(sys_mutex_lock(ppu, handle->output_mutex, 0) == CELL_OK);
ensure(lv2_syscall<sys_mutex_lock>(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::ptr<AtracXdecCo
handle->output_locked = false;
}
ensure(sys_cond_signal(ppu, handle->output_consumed) == CELL_OK);
ensure(lv2_syscall<sys_cond_signal>(ppu, handle->output_consumed) == CELL_OK);
if (ppu.state & cpu_flag::again)
{
@ -939,7 +939,7 @@ error_code _CellAdecCoreOpReleasePcm_atracx(ppu_thread& ppu, vm::ptr<AtracXdecCo
return {};
}
ensure(sys_mutex_unlock(ppu, handle->output_mutex) == CELL_OK);
ensure(lv2_syscall<sys_mutex_unlock>(ppu, handle->output_mutex) == CELL_OK);
return CELL_OK;
}

View File

@ -919,7 +919,7 @@ error_code cellCameraGetAttribute(s32 dev_num, s32 attrib, vm::ptr<u32> 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<u32> 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<u32> arg1, vm
if (!attr_name) // invalid attributes don't have a name
{
return CELL_CAMERA_ERROR_PARAM;
return { CELL_CAMERA_ERROR_PARAM, "attrib=0x%x", attrib };
}
if (arg1)
@ -983,7 +983,7 @@ error_code cellCameraSetAttribute(s32 dev_num, s32 attrib, u32 arg1, u32 arg2)
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)
@ -1004,7 +1004,7 @@ error_code cellCameraSetAttribute(s32 dev_num, s32 attrib, u32 arg1, u32 arg2)
if (!attr_name) // invalid attributes don't have a name
{
return CELL_CAMERA_ERROR_PARAM;
return { CELL_CAMERA_ERROR_PARAM, "attrib=0x%x", attrib };
}
g_camera.set_attr(attrib, arg1, arg2);

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,8 @@
#pragma once
#include "Emu/Memory/vm_ptr.h"
#include "cellPamf.h"
#include "Emu/Cell/ErrorCodes.h"
#include "Utilities/BitField.h"
// Error Codes
enum CellDmuxError :u32
@ -18,6 +19,10 @@ enum CellDmuxStreamType : s32
CELL_DMUX_STREAM_TYPE_UNDEF = 0,
CELL_DMUX_STREAM_TYPE_PAMF = 1,
CELL_DMUX_STREAM_TYPE_TERMINATOR = 2,
// Only used in cellSail
CELL_DMUX_STREAM_TYPE_MP4 = 0x81,
CELL_DMUX_STREAM_TYPE_AVI = 0x82
};
enum CellDmuxMsgType : s32
@ -33,118 +38,6 @@ enum CellDmuxEsMsgType : s32
CELL_DMUX_ES_MSG_TYPE_FLUSH_DONE = 1,
};
enum CellDmuxPamfM2vLevel : s32
{
CELL_DMUX_PAMF_M2V_MP_LL = 0,
CELL_DMUX_PAMF_M2V_MP_ML,
CELL_DMUX_PAMF_M2V_MP_H14,
CELL_DMUX_PAMF_M2V_MP_HL,
};
enum CellDmuxPamfAvcLevel : s32
{
CELL_DMUX_PAMF_AVC_LEVEL_2P1 = 21,
CELL_DMUX_PAMF_AVC_LEVEL_3P0 = 30,
CELL_DMUX_PAMF_AVC_LEVEL_3P1 = 31,
CELL_DMUX_PAMF_AVC_LEVEL_3P2 = 32,
CELL_DMUX_PAMF_AVC_LEVEL_4P1 = 41,
CELL_DMUX_PAMF_AVC_LEVEL_4P2 = 42,
};
struct CellDmuxPamfAuSpecificInfoM2v
{
be_t<u32> reserved1;
};
struct CellDmuxPamfAuSpecificInfoAvc
{
be_t<u32> reserved1;
};
struct CellDmuxPamfAuSpecificInfoLpcm
{
u8 channelAssignmentInfo;
u8 samplingFreqInfo;
u8 bitsPerSample;
};
struct CellDmuxPamfAuSpecificInfoAc3
{
be_t<u32> reserved1;
};
struct CellDmuxPamfAuSpecificInfoAtrac3plus
{
be_t<u32> reserved1;
};
struct CellDmuxPamfAuSpecificInfoUserData
{
be_t<u32> reserved1;
};
struct CellDmuxPamfEsSpecificInfoM2v
{
be_t<u32> profileLevel;
};
struct CellDmuxPamfEsSpecificInfoAvc
{
be_t<u32> level;
};
struct CellDmuxPamfEsSpecificInfoLpcm
{
be_t<u32> samplingFreq;
be_t<u32> numOfChannels;
be_t<u32> bitsPerSample;
};
struct CellDmuxPamfEsSpecificInfoAc3
{
be_t<u32> reserved1;
};
struct CellDmuxPamfEsSpecificInfoAtrac3plus
{
be_t<u32> reserved1;
};
struct CellDmuxPamfEsSpecificInfoUserData
{
be_t<u32> reserved1;
};
enum CellDmuxPamfSamplingFrequency : s32
{
CELL_DMUX_PAMF_FS_48K = 48000,
};
enum CellDmuxPamfBitsPerSample : s32
{
CELL_DMUX_PAMF_BITS_PER_SAMPLE_16 = 16,
CELL_DMUX_PAMF_BITS_PER_SAMPLE_24 = 24,
};
enum CellDmuxPamfLpcmChannelAssignmentInfo : s32
{
CELL_DMUX_PAMF_LPCM_CH_M1 = 1,
CELL_DMUX_PAMF_LPCM_CH_LR = 3,
CELL_DMUX_PAMF_LPCM_CH_LRCLSRSLFE = 9,
CELL_DMUX_PAMF_LPCM_CH_LRCLSCS1CS2RSLFE = 11,
};
enum CellDmuxPamfLpcmFs : s32
{
CELL_DMUX_PAMF_LPCM_FS_48K = 1,
};
enum CellDmuxPamfLpcmBitsPerSamples : s32
{
CELL_DMUX_PAMF_LPCM_BITS_PER_SAMPLE_16 = 1,
CELL_DMUX_PAMF_LPCM_BITS_PER_SAMPLE_24 = 3,
};
struct CellDmuxMsg
{
be_t<s32> msgType; // CellDmuxMsgType
@ -160,24 +53,19 @@ struct CellDmuxEsMsg
struct CellDmuxType
{
be_t<s32> streamType; // CellDmuxStreamType
be_t<u32> reserved[2];
};
struct CellDmuxPamfSpecificInfo
{
be_t<u32> thisSize;
b8 programEndCodeCb;
be_t<s32> reserved1;
be_t<s32> reserved2;
};
struct CellDmuxType2
{
be_t<s32> streamType; // CellDmuxStreamType
be_t<u32> streamSpecificInfo;
be_t<s32> streamType;
vm::bcptr<void> streamSpecificInfo;
};
struct CellDmuxResource
{
be_t<u32> memAddr;
vm::bptr<void> memAddr;
be_t<u32> memSize;
be_t<u32> ppuThreadPriority;
be_t<u32> ppuThreadStackSize;
@ -187,12 +75,12 @@ struct CellDmuxResource
struct CellDmuxResourceEx
{
be_t<u32> memAddr;
vm::bptr<void> memAddr;
be_t<u32> memSize;
be_t<u32> ppuThreadPriority;
be_t<u32> ppuThreadStackSize;
be_t<u32> spurs_addr;
u8 priority[8];
vm::bptr<void> spurs; // CellSpurs*
be_t<u64, 1> priority;
be_t<u32> maxContention;
};
@ -203,40 +91,30 @@ struct CellDmuxResourceSpurs
be_t<u32> maxContention;
};
/*
struct CellDmuxResource2Ex
{
b8 isResourceEx; //true
CellDmuxResourceEx resourceEx;
};
struct CellDmuxResource2NoEx
{
b8 isResourceEx; //false
CellDmuxResource resource;
};
*/
struct CellDmuxResource2
{
b8 isResourceEx;
be_t<u32> memAddr;
be_t<u32> memSize;
be_t<u32> ppuThreadPriority;
be_t<u32> ppuThreadStackSize;
be_t<u32> shit[4];
union
{
CellDmuxResource resource;
CellDmuxResourceEx resourceEx;
};
};
using CellDmuxCbMsg = u32(u32 demuxerHandle, vm::ptr<CellDmuxMsg> demuxerMsg, u32 cbArg);
struct DmuxContext;
struct DmuxEsContext;
using CellDmuxCbEsMsg = u32(u32 demuxerHandle, u32 esHandle, vm::ptr<CellDmuxEsMsg> esMsg, u32 cbArg);
using CellDmuxCbMsg = u32(vm::ptr<DmuxContext> demuxerHandle, vm::cptr<CellDmuxMsg> demuxerMsg, vm::ptr<void> cbArg);
using CellDmuxCbEsMsg = u32(vm::ptr<DmuxContext> demuxerHandle, vm::ptr<DmuxEsContext> esHandle, vm::cptr<CellDmuxEsMsg> esMsg, vm::ptr<void> cbArg);
// Used for internal callbacks as well
template <typename F>
struct DmuxCb
{
vm::bptr<F> cbFunc;
be_t<u32> cbArg;
vm::bptr<void> cbArg;
};
using CellDmuxCb = DmuxCb<CellDmuxCbMsg>;
@ -250,42 +128,114 @@ struct CellDmuxAttr
be_t<u32> demuxerVerLower;
};
struct CellDmuxPamfAttr
{
be_t<u32> maxEnabledEsNum;
be_t<u32> version;
be_t<u32> memSize;
};
struct CellDmuxEsAttr
{
be_t<u32> memSize;
};
struct CellDmuxPamfEsAttr
{
be_t<u32> auQueueMaxSize;
be_t<u32> memSize;
be_t<u32> specificInfoSize;
};
struct CellDmuxEsResource
{
be_t<u32> memAddr;
vm::bptr<void> memAddr;
be_t<u32> memSize;
};
struct CellDmuxAuInfo
{
be_t<u32> auAddr;
vm::bptr<void> auAddr;
be_t<u32> auSize;
be_t<u32> auMaxSize;
be_t<u64> userData;
be_t<u32> ptsUpper;
be_t<u32> ptsLower;
be_t<u32> dtsUpper;
be_t<u32> dtsLower;
};
struct CellDmuxAuInfoEx
{
be_t<u32> auAddr;
be_t<u32> auSize;
be_t<u32> reserved;
b8 isRap;
be_t<u64> userData;
CellCodecTimeStamp pts;
CellCodecTimeStamp dts;
};
struct CellDmuxPamfAttr;
struct CellDmuxPamfEsAttr;
using CellDmuxAuInfoEx = CellDmuxAuInfo;
struct DmuxAuInfo
{
CellDmuxAuInfo info;
vm::bptr<void> specific_info;
be_t<u32> specific_info_size;
};
struct DmuxAuQueueElement
{
be_t<u32> index;
u8 unk; // unused
DmuxAuInfo au_info;
};
CHECK_SIZE(DmuxAuQueueElement, 0x38);
enum DmuxState : u32
{
DMUX_STOPPED = 1 << 0,
DMUX_RUNNING = 1 << 1,
};
struct alignas(0x10) DmuxContext // CellDmuxHandle = DmuxContext*
{
vm::bptr<DmuxContext> _this;
be_t<u32> _this_size;
be_t<u32> version;
be_t<u32> dmux_state;
CellDmuxType dmux_type;
CellDmuxCb dmux_cb;
b8 stream_is_set;
vm::bptr<void> core_handle;
be_t<u32> version_; // Same value as 'version'
be_t<u64> user_data;
be_t<s32> max_enabled_es_num;
be_t<s32> enabled_es_num;
be_t<u32> _dx_mhd; // sys_mutex_t
u8 reserved[0x7c];
};
CHECK_SIZE_ALIGN(DmuxContext, 0xc0, 0x10);
struct alignas(0x10) DmuxEsContext // CellDmuxEsHandle = DmuxEsContext*
{
be_t<u32> _dx_mes; // sys_mutex_t
be_t<u32> is_enabled;
be_t<u32> error_mem_size;
be_t<u32> error_count;
vm::bptr<void> error_mem_addr;
vm::bptr<DmuxEsContext> _this;
be_t<u32> _this_size;
be_t<s32> _this_index;
vm::bptr<DmuxContext> dmux_handle;
CellDmuxEsCb es_cb;
vm::bptr<void> core_es_handle;
bf_t<be_t<u32>, 0, 1> flush_started;
struct
{
be_t<s32> max_size;
be_t<s32> allocated_size;
be_t<s32> size;
be_t<s32> front;
be_t<s32> back;
be_t<s32> allocated_back;
}
au_queue;
};
CHECK_SIZE_ALIGN(DmuxEsContext, 0x50, 0x10);
using DmuxNotifyDemuxDone = error_code(vm::ptr<void>, u32, vm::ptr<void>);
using DmuxNotifyFatalErr = error_code(vm::ptr<void>, u32, vm::ptr<void>);
@ -301,13 +251,13 @@ using CellDmuxCoreOpResetStream = error_code(vm::ptr<void>);
using CellDmuxCoreOpCreateThread = error_code(vm::ptr<void>);
using CellDmuxCoreOpJoinThread = error_code(vm::ptr<void>);
using CellDmuxCoreOpSetStream = error_code(vm::ptr<void>, vm::cptr<void>, u32, b8, u64);
using CellDmuxCoreOpFreeMemory = error_code(vm::ptr<void>, vm::ptr<void>, u32);
using CellDmuxCoreOpReleaseAu = error_code(vm::ptr<void>, vm::ptr<void>, u32);
using CellDmuxCoreOpQueryEsAttr = error_code(vm::cptr<void>, vm::cptr<void>, vm::ptr<CellDmuxPamfEsAttr>);
using CellDmuxCoreOpEnableEs = error_code(vm::ptr<void>, vm::cptr<void>, vm::cptr<CellDmuxEsResource>, vm::cptr<DmuxCb<DmuxEsNotifyAuFound>>, vm::cptr<DmuxCb<DmuxEsNotifyFlushDone>>, vm::cptr<void>, vm::pptr<void>);
using CellDmuxCoreOpDisableEs = u32(vm::ptr<void>);
using CellDmuxCoreOpFlushEs = u32(vm::ptr<void>);
using CellDmuxCoreOpResetEs = u32(vm::ptr<void>);
using CellDmuxCoreOpResetStreamAndWaitDone = u32(vm::ptr<void>);
using CellDmuxCoreOpDisableEs = error_code(vm::ptr<void>);
using CellDmuxCoreOpFlushEs = error_code(vm::ptr<void>);
using CellDmuxCoreOpResetEs = error_code(vm::ptr<void>);
using CellDmuxCoreOpResetStreamAndWaitDone = error_code(vm::ptr<void>);
struct CellDmuxCoreOps
{
@ -318,7 +268,7 @@ struct CellDmuxCoreOps
vm::bptr<CellDmuxCoreOpCreateThread> createThread;
vm::bptr<CellDmuxCoreOpJoinThread> joinThread;
vm::bptr<CellDmuxCoreOpSetStream> setStream;
vm::bptr<CellDmuxCoreOpFreeMemory> freeMemory;
vm::bptr<CellDmuxCoreOpReleaseAu> releaseAu;
vm::bptr<CellDmuxCoreOpQueryEsAttr> queryEsAttr;
vm::bptr<CellDmuxCoreOpEnableEs> enableEs;
vm::bptr<CellDmuxCoreOpDisableEs> disableEs;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -770,8 +770,8 @@ namespace gem
if constexpr (use_gain)
{
dst0[0] = static_cast<u8>(std::clamp(r * gain_r, 0.0f, 255.0f));
dst0[1] = static_cast<u8>(std::clamp(b * gain_b, 0.0f, 255.0f));
dst0[2] = static_cast<u8>(std::clamp(g * gain_g, 0.0f, 255.0f));
dst0[1] = static_cast<u8>(std::clamp(g * gain_g, 0.0f, 255.0f));
dst0[2] = static_cast<u8>(std::clamp(b * gain_b, 0.0f, 255.0f));
}
else
{
@ -822,8 +822,8 @@ namespace gem
if constexpr (use_gain)
{
dst0[0] = static_cast<u8>(std::clamp(r * gain_r, 0.0f, 255.0f));
dst0[1] = static_cast<u8>(std::clamp(b * gain_b, 0.0f, 255.0f));
dst0[2] = static_cast<u8>(std::clamp(g * gain_g, 0.0f, 255.0f));
dst0[1] = static_cast<u8>(std::clamp(g * gain_g, 0.0f, 255.0f));
dst0[2] = static_cast<u8>(std::clamp(b * gain_b, 0.0f, 255.0f));
}
else
{
@ -845,6 +845,53 @@ namespace gem
debayer_raw8_impl<false>(src, dst, alpha, gain_r, gain_g, gain_b);
}
template <bool use_gain>
static inline void debayer_raw8_downscale_impl(const u8* src, u8* dst, u8 alpha, f32 gain_r, f32 gain_g, f32 gain_b)
{
constexpr u32 in_pitch = 640;
constexpr u32 out_pitch = 320 * 4;
// Simple debayer
for (s32 y = 0; y < 240; y++)
{
const u8* src0 = src + y * 2 * in_pitch;
const u8* src1 = src0 + in_pitch;
u8* dst0 = dst + y * out_pitch;
for (s32 x = 0; x < 320; x++, dst0 += 4, src0 += 2, src1 += 2)
{
const u8 b = src0[0];
const u8 g0 = src0[1];
const u8 g1 = src1[0];
const u8 r = src1[1];
const u8 g = (g0 + g1) >> 1;
if constexpr (use_gain)
{
dst0[0] = static_cast<u8>(std::clamp(r * gain_r, 0.0f, 255.0f));
dst0[1] = static_cast<u8>(std::clamp(g * gain_g, 0.0f, 255.0f));
dst0[2] = static_cast<u8>(std::clamp(b * gain_b, 0.0f, 255.0f));
}
else
{
dst0[0] = r;
dst0[1] = g;
dst0[2] = b;
}
dst0[3] = alpha;
}
}
}
static void debayer_raw8_downscale(const u8* src, u8* dst, u8 alpha, f32 gain_r, f32 gain_g, f32 gain_b)
{
if (gain_r != 1.0f || gain_g != 1.0f || gain_b != 1.0f)
debayer_raw8_downscale_impl<true>(src, dst, alpha, gain_r, gain_g, gain_b);
else
debayer_raw8_downscale_impl<false>(src, dst, alpha, gain_r, gain_g, gain_b);
}
bool convert_image_format(CellCameraFormat input_format, const CellGemVideoConvertAttribute& vc,
const std::vector<u8>& video_data_in, u32 width, u32 height,
u8* video_data_out, u32 video_data_out_size, u8* buffer_memory,
@ -881,9 +928,9 @@ namespace gem
const u8* src_data = video_data_in.data();
const u8 alpha = vc.alpha;
const f32 gain_r = vc.gain * vc.blue_gain;
const f32 gain_r = vc.gain * vc.red_gain;
const f32 gain_g = vc.gain * vc.green_gain;
const f32 gain_b = vc.gain * vc.red_gain;
const f32 gain_b = vc.gain * vc.blue_gain;
// Only RAW8 should be relevant for cellGem unless I'm mistaken
if (input_format == CELL_CAMERA_RAW8)
@ -1183,34 +1230,7 @@ namespace gem
{
case CELL_CAMERA_RAW8:
{
const u32 in_pitch = width;
const u32 out_pitch = width * 4 / 2;
for (u32 y = 0; y < height - 1; y += 2)
{
const u8* src0 = src_data + y * in_pitch;
const u8* src1 = src0 + in_pitch;
u8* dst0 = video_data_out + (y / 2) * out_pitch;
u8* dst1 = dst0 + out_pitch;
for (u32 x = 0; x < width - 1; x += 2, src0 += 2, src1 += 2, dst0 += 4, dst1 += 4)
{
const u8 b = src0[0];
const u8 g0 = src0[1];
const u8 g1 = src1[0];
const u8 r = src1[1];
const u8 top[4] = { r, g0, b, alpha };
const u8 bottom[4] = { r, g1, b, alpha };
// Top-Left
std::memcpy(dst0, top, 4);
// Bottom-Left Pixel
std::memcpy(dst1, bottom, 4);
}
}
debayer_raw8_downscale(src_data, video_data_out, alpha, gain_r, gain_g, gain_b);
break;
}
case CELL_CAMERA_RGBA:
@ -1609,13 +1629,8 @@ public:
return false;
}
if (!m_camera_info.bytesize)
{
cellGem.error("gem_tracker: unexpected image size: %d", m_camera_info.bytesize);
return false;
}
m_tracker.set_image_data(m_camera_info.buffer.get_ptr(), m_camera_info.bytesize, m_camera_info.width, m_camera_info.height, m_camera_info.format);
m_framenumber++; // using framenumber instead of timestamp since the timestamp could be identical
return true;
}
@ -1648,6 +1663,7 @@ public:
}
auto& gem = g_fxo->get<gem_config>();
u64 last_framenumber = 0;
while (thread_ctrl::state() != thread_state::aborting)
{
@ -1663,6 +1679,13 @@ public:
}
}
if (std::exchange(last_framenumber, m_framenumber.load()) == last_framenumber)
{
cellGem.warning("Tracker woke up without new frame. Skipping processing (framenumber=%d)", last_framenumber);
tracker_done();
continue;
}
m_busy.release(true);
// Update PS Move LED colors
@ -1751,9 +1774,16 @@ public:
shared_mutex mutex;
gem_tracker& operator=(thread_state) noexcept
{
wake_up_tracker();
return *this;
}
private:
atomic_t<u32> m_wake_up_tracker = 0;
atomic_t<u32> m_tracker_done = 0;
atomic_t<u64> m_framenumber = 0;
atomic_t<bool> m_busy = false;
ps_move_tracker<false> m_tracker{};
CellCameraInfoEx m_camera_info{};
@ -1873,21 +1903,10 @@ static inline void pos_to_gem_state(u32 gem_num, gem_config::gem_controller& con
gem_state->pos[2] = controller.distance_mm;
gem_state->pos[3] = 0.f;
// TODO: calculate handle position based on our world coordinate and the angles
gem_state->handle_pos[0] = camera_x;
gem_state->handle_pos[1] = camera_y;
gem_state->handle_pos[2] = controller.distance_mm + 10.0f;
gem_state->handle_pos[3] = 0.f;
// Calculate orientation
if (g_cfg.io.move == move_handler::real || (g_cfg.io.move == move_handler::fake && move_data.orientation_enabled))
{
gem_state->quat[0] = move_data.quaternion.x();
gem_state->quat[1] = move_data.quaternion.y();
gem_state->quat[2] = move_data.quaternion.z();
gem_state->quat[3] = move_data.quaternion.w();
}
else
ps_move_data::vect<4> quat = move_data.quaternion;
if (g_cfg.io.move != move_handler::real && !(g_cfg.io.move == move_handler::fake && move_data.orientation_enabled))
{
const f32 max_angle_per_side_h = g_cfg.io.fake_move_rotation_cone_h / 2.0f;
const f32 max_angle_per_side_v = g_cfg.io.fake_move_rotation_cone_v / 2.0f;
@ -1901,17 +1920,27 @@ static inline void pos_to_gem_state(u32 gem_num, gem_config::gem_controller& con
const f32 cy = std::cos(yaw * 0.5f);
const f32 sy = std::sin(yaw * 0.5f);
const f32 q_x = sr * cp * cy - cr * sp * sy;
const f32 q_y = cr * sp * cy + sr * cp * sy;
const f32 q_z = cr * cp * sy - sr * sp * cy;
const f32 q_w = cr * cp * cy + sr * sp * sy;
gem_state->quat[0] = q_x;
gem_state->quat[1] = q_y;
gem_state->quat[2] = q_z;
gem_state->quat[3] = q_w;
quat.x() = sr * cp * cy - cr * sp * sy;
quat.y() = cr * sp * cy + sr * cp * sy;
quat.z() = cr * cp * sy - sr * sp * cy;
quat.w() = cr * cp * cy + sr * sp * sy;
}
gem_state->quat[0] = quat.x();
gem_state->quat[1] = quat.y();
gem_state->quat[2] = quat.z();
gem_state->quat[3] = quat.w();
// Calculate handle position based on our world coordinate and the current orientation
constexpr ps_move_data::vect<3> offset_local_mm({0.f, 0.f, -45.f}); // handle is ~45 mm below sphere
const ps_move_data::vect<3> offset_world = ps_move_data::rotate_vector(quat, offset_local_mm);
gem_state->handle_pos[0] = gem_state->pos[0] - offset_world.x(); // Flip x offset
gem_state->handle_pos[1] = gem_state->pos[1] - offset_world.y(); // Flip y offset
gem_state->handle_pos[2] = gem_state->pos[2] + offset_world.z();
gem_state->handle_pos[3] = 0.f;
// Calculate velocity
if constexpr (!ps_move_data::use_imu_for_velocity)
{
move_data.update_velocity(shared_data.frame_timestamp_us, gem_state->pos);
@ -1920,6 +1949,10 @@ static inline void pos_to_gem_state(u32 gem_num, gem_config::gem_controller& con
{
gem_state->vel[i] = move_data.vel_world[i];
gem_state->accel[i] = move_data.accel_world[i];
// TODO: maybe this also needs to be adjusted depending on the orientation
gem_state->handle_vel[i] = gem_state->vel[i];
gem_state->handle_accel[i] = gem_state->accel[i];
}
}
@ -3612,7 +3645,7 @@ error_code cellGemReadExternalPortDeviceInfo(u32 gem_num, vm::ptr<u32> ext_id, v
if (!pad->move_data.external_device_read_requested)
{
*ext_id = controller.ext_id = pad->move_data.external_device_id;
std::memcpy(pad->move_data.external_device_read.data(), ext_info.get_ptr(), CELL_GEM_EXTERNAL_PORT_OUTPUT_SIZE);
std::memcpy(ext_info.get_ptr(), pad->move_data.external_device_read.data(), CELL_GEM_EXTERNAL_PORT_DEVICE_INFO_SIZE);
break;
}
}
@ -3876,13 +3909,15 @@ error_code cellGemUpdateStart(vm::cptr<void> camera_frame, u64 timestamp)
gem.camera_frame = camera_frame.addr();
if (!tracker.set_image(gem.camera_frame))
const bool image_set = tracker.set_image(gem.camera_frame);
tracker.wake_up_tracker();
if (!image_set)
{
return not_an_error(CELL_GEM_NO_VIDEO);
}
tracker.wake_up_tracker();
return CELL_OK;
}

View File

@ -192,7 +192,46 @@ error_code cellNetCtlDelHandler(s32 hid)
error_code cellNetCtlGetInfo(s32 code, vm::ptr<CellNetCtlInfo> info)
{
cellNetCtl.warning("cellNetCtlGetInfo(code=0x%x (%s), info=*0x%x)", code, InfoCodeToName(code), info);
bool log_it_once = false;
switch (code)
{
case CELL_NET_CTL_INFO_ETHER_ADDR:
case CELL_NET_CTL_INFO_DEVICE:
case CELL_NET_CTL_INFO_MTU:
case CELL_NET_CTL_INFO_LINK_TYPE:
case CELL_NET_CTL_INFO_IP_CONFIG:
case CELL_NET_CTL_INFO_IP_ADDRESS:
case CELL_NET_CTL_INFO_NETMASK:
case CELL_NET_CTL_INFO_DEFAULT_ROUTE:
case CELL_NET_CTL_INFO_HTTP_PROXY_CONFIG:
case CELL_NET_CTL_INFO_UPNP_CONFIG:
{
log_it_once = true;
break;
}
default:
{
break;
}
}
bool log_it = true;
if (log_it_once && vm::check_addr(info.addr()))
{
struct logged_t
{
std::array<atomic_t<bool>, 256> logged_code{};
};
if (g_fxo->get<logged_t>().logged_code[::narrow<u8>(code)].exchange(true))
{
log_it = false;
}
}
(log_it ? cellNetCtl.warning : cellNetCtl.trace)("cellNetCtlGetInfo(code=0x%x (%s), info=*0x%x)", code, InfoCodeToName(code), info);
auto& nph = g_fxo->get<named_thread<np::np_handler>>();

View File

@ -5,14 +5,6 @@
#include <bitset>
#include "cellPamf.h"
const std::function<bool()> SQUEUE_ALWAYS_EXIT = []() { return true; };
const std::function<bool()> SQUEUE_NEVER_EXIT = []() { return false; };
bool squeue_test_exit()
{
return Emu.IsStopped();
}
LOG_CHANNEL(cellPamf);
template<>

View File

@ -1,5 +1,6 @@
#pragma once
#include "Emu/Cell/ErrorCodes.h"
#include "Emu/Memory/vm_ptr.h"
// Error Codes
@ -594,345 +595,3 @@ struct CellPamfReader
CHECK_SIZE(CellPamfReader, 128);
error_code cellPamfReaderInitialize(vm::ptr<CellPamfReader> pSelf, vm::cptr<PamfHeader> pAddr, u64 fileSize, u32 attribute);
#include <mutex>
#include <condition_variable>
extern const std::function<bool()> SQUEUE_ALWAYS_EXIT;
extern const std::function<bool()> SQUEUE_NEVER_EXIT;
bool squeue_test_exit();
// TODO: eliminate this boolshit
template<typename T, u32 sq_size = 256>
class squeue_t
{
struct squeue_sync_var_t
{
struct
{
u32 position : 31;
u32 pop_lock : 1;
};
struct
{
u32 count : 31;
u32 push_lock : 1;
};
};
atomic_t<squeue_sync_var_t> m_sync;
mutable std::mutex m_rcv_mutex;
mutable std::mutex m_wcv_mutex;
mutable std::condition_variable m_rcv;
mutable std::condition_variable m_wcv;
T m_data[sq_size];
enum squeue_sync_var_result : u32
{
SQSVR_OK = 0,
SQSVR_LOCKED = 1,
SQSVR_FAILED = 2,
};
public:
squeue_t()
: m_sync(squeue_sync_var_t{})
{
}
static u32 get_max_size()
{
return sq_size;
}
bool is_full() const
{
return m_sync.load().count == sq_size;
}
bool push(const T& data, const std::function<bool()>& test_exit)
{
u32 pos = 0;
while (u32 res = m_sync.atomic_op([&pos](squeue_sync_var_t& sync) -> u32
{
ensure(sync.count <= sq_size);
ensure(sync.position < sq_size);
if (sync.push_lock)
{
return SQSVR_LOCKED;
}
if (sync.count == sq_size)
{
return SQSVR_FAILED;
}
sync.push_lock = 1;
pos = sync.position + sync.count;
return SQSVR_OK;
}))
{
if (res == SQSVR_FAILED && (test_exit() || squeue_test_exit()))
{
return false;
}
std::unique_lock<std::mutex> wcv_lock(m_wcv_mutex);
m_wcv.wait_for(wcv_lock, std::chrono::milliseconds(1));
}
m_data[pos >= sq_size ? pos - sq_size : pos] = data;
m_sync.atomic_op([](squeue_sync_var_t& sync)
{
ensure(sync.count <= sq_size);
ensure(sync.position < sq_size);
ensure(!!sync.push_lock);
sync.push_lock = 0;
sync.count++;
});
m_rcv.notify_one();
m_wcv.notify_one();
return true;
}
bool push(const T& data, const volatile bool* do_exit)
{
return push(data, [do_exit]() { return do_exit && *do_exit; });
}
bool push(const T& data)
{
return push(data, SQUEUE_NEVER_EXIT);
}
bool try_push(const T& data)
{
return push(data, SQUEUE_ALWAYS_EXIT);
}
bool pop(T& data, const std::function<bool()>& test_exit)
{
u32 pos = 0;
while (u32 res = m_sync.atomic_op([&pos](squeue_sync_var_t& sync) -> u32
{
ensure(sync.count <= sq_size);
ensure(sync.position < sq_size);
if (!sync.count)
{
return SQSVR_FAILED;
}
if (sync.pop_lock)
{
return SQSVR_LOCKED;
}
sync.pop_lock = 1;
pos = sync.position;
return SQSVR_OK;
}))
{
if (res == SQSVR_FAILED && (test_exit() || squeue_test_exit()))
{
return false;
}
std::unique_lock<std::mutex> rcv_lock(m_rcv_mutex);
m_rcv.wait_for(rcv_lock, std::chrono::milliseconds(1));
}
data = m_data[pos];
m_sync.atomic_op([](squeue_sync_var_t& sync)
{
ensure(sync.count <= sq_size);
ensure(sync.position < sq_size);
ensure(!!sync.pop_lock);
sync.pop_lock = 0;
sync.position++;
sync.count--;
if (sync.position == sq_size)
{
sync.position = 0;
}
});
m_rcv.notify_one();
m_wcv.notify_one();
return true;
}
bool pop(T& data, const volatile bool* do_exit)
{
return pop(data, [do_exit]() { return do_exit && *do_exit; });
}
bool pop(T& data)
{
return pop(data, SQUEUE_NEVER_EXIT);
}
bool try_pop(T& data)
{
return pop(data, SQUEUE_ALWAYS_EXIT);
}
bool peek(T& data, u32 start_pos, const std::function<bool()>& test_exit)
{
ensure(start_pos < sq_size);
u32 pos = 0;
while (u32 res = m_sync.atomic_op([&pos, start_pos](squeue_sync_var_t& sync) -> u32
{
ensure(sync.count <= sq_size);
ensure(sync.position < sq_size);
if (sync.count <= start_pos)
{
return SQSVR_FAILED;
}
if (sync.pop_lock)
{
return SQSVR_LOCKED;
}
sync.pop_lock = 1;
pos = sync.position + start_pos;
return SQSVR_OK;
}))
{
if (res == SQSVR_FAILED && (test_exit() || squeue_test_exit()))
{
return false;
}
std::unique_lock<std::mutex> rcv_lock(m_rcv_mutex);
m_rcv.wait_for(rcv_lock, std::chrono::milliseconds(1));
}
data = m_data[pos >= sq_size ? pos - sq_size : pos];
m_sync.atomic_op([](squeue_sync_var_t& sync)
{
ensure(sync.count <= sq_size);
ensure(sync.position < sq_size);
ensure(!!sync.pop_lock);
sync.pop_lock = 0;
});
m_rcv.notify_one();
return true;
}
bool peek(T& data, u32 start_pos, const volatile bool* do_exit)
{
return peek(data, start_pos, [do_exit]() { return do_exit && *do_exit; });
}
bool peek(T& data, u32 start_pos = 0)
{
return peek(data, start_pos, SQUEUE_NEVER_EXIT);
}
bool try_peek(T& data, u32 start_pos = 0)
{
return peek(data, start_pos, SQUEUE_ALWAYS_EXIT);
}
class squeue_data_t
{
T* const m_data;
const u32 m_pos;
const u32 m_count;
squeue_data_t(T* data, u32 pos, u32 count)
: m_data(data)
, m_pos(pos)
, m_count(count)
{
}
public:
T& operator [] (u32 index)
{
ensure(index < m_count);
index += m_pos;
index = index < sq_size ? index : index - sq_size;
return m_data[index];
}
};
void process(void(*proc)(squeue_data_t data))
{
u32 pos, count;
while (m_sync.atomic_op([&pos, &count](squeue_sync_var_t& sync) -> u32
{
ensure(sync.count <= sq_size);
ensure(sync.position < sq_size);
if (sync.pop_lock || sync.push_lock)
{
return SQSVR_LOCKED;
}
pos = sync.position;
count = sync.count;
sync.pop_lock = 1;
sync.push_lock = 1;
return SQSVR_OK;
}))
{
std::unique_lock<std::mutex> rcv_lock(m_rcv_mutex);
m_rcv.wait_for(rcv_lock, std::chrono::milliseconds(1));
}
proc(squeue_data_t(m_data, pos, count));
m_sync.atomic_op([](squeue_sync_var_t& sync)
{
ensure(sync.count <= sq_size);
ensure(sync.position < sq_size);
ensure(!!sync.pop_lock);
ensure(!!sync.push_lock);
sync.pop_lock = 0;
sync.push_lock = 0;
});
m_wcv.notify_one();
m_rcv.notify_one();
}
void clear()
{
while (m_sync.atomic_op([](squeue_sync_var_t& sync) -> u32
{
ensure(sync.count <= sq_size);
ensure(sync.position < sq_size);
if (sync.pop_lock || sync.push_lock)
{
return SQSVR_LOCKED;
}
sync.pop_lock = 1;
sync.push_lock = 1;
return SQSVR_OK;
}))
{
std::unique_lock<std::mutex> rcv_lock(m_rcv_mutex);
m_rcv.wait_for(rcv_lock, std::chrono::milliseconds(1));
}
m_sync.exchange({});
m_wcv.notify_one();
m_rcv.notify_one();
}
};

View File

@ -1267,6 +1267,11 @@ struct SceNpOnlineId
{
char data[SCE_NET_NP_ONLINEID_MAX_LENGTH + 1]; // char term;
char dummy[3];
bool operator<(const SceNpOnlineId& other) const
{
return memcmp(data, other.data, sizeof(data)) < 0;
}
};
// NP ID structure
@ -1283,6 +1288,11 @@ struct SceNpId
};
u8 reserved[8];
bool operator<(const SceNpId& other) const
{
return handle < other.handle;
}
};
CHECK_SIZE_ALIGN(SceNpId, 0x24, 1);
@ -1689,12 +1699,22 @@ struct SceNpLobbyId
{
u8 opt[28];
u8 reserved[8];
bool operator<(const SceNpLobbyId& other) const
{
return memcmp(opt, other.opt, sizeof(opt)) < 0;
}
};
struct SceNpRoomId
{
u8 opt[28];
u8 reserved[8];
bool operator<(const SceNpRoomId& other) const
{
return memcmp(opt, other.opt, sizeof(opt)) < 0;
}
};
struct SceNpMatchingAttr

View File

@ -2535,7 +2535,7 @@ bool ppu_module<lv2_obj>::analyse(u32 lib_toc, u32 entry, const u32 sec_end, con
// SLDI mnemonic
reg_state_t rs = get_reg(op.rs);
if (!rs.shift_left(op.sh32, reg_tag_allocator))
if (!rs.shift_left(sh, reg_tag_allocator))
{
unmap_reg(op.ra);
}

View File

@ -1004,7 +1004,7 @@ static import_result_t ppu_load_imports(const ppu_module<lv2_obj>& _module, std:
// Check address
// TODO: The address of use should be extracted from analyser instead
if (fstub && fstub >= _module.segs[0].addr && fstub <= _module.segs[0].addr + _module.segs[0].size)
if (fstub && fstub >= _module.segs[0].addr && fstub < _module.segs[0].addr + _module.segs[0].size)
{
nid_to_use_addr.emplace(fnid, fstub);
}
@ -1895,7 +1895,7 @@ shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object& elf, bool virtual_load, c
}
else
{
ppu_loader.error("Library %s: PRX library info not found");
ppu_loader.error("Library: PRX library info not found");
}
prx->start.set(prx->specials[0xbc9a0086]);
@ -3192,7 +3192,7 @@ bool ppu_load_rel_exec(const ppu_rel_object& elf)
for (const auto& s : elf.shdrs)
{
if (s.sh_type != sec_type::sht_progbits)
if (s.sh_type == sec_type::sht_progbits)
{
memsize = utils::align<u32>(memsize + vm::cast(s.sh_size), 128);
}

View File

@ -1286,7 +1286,7 @@ extern bool ppu_patch(u32 addr, u32 value)
{
if (addr % 4)
{
ppu_log.fatal("Patch failed at 0x%x: unanligned memory address.", addr);
ppu_log.fatal("Patch failed at 0x%x: unaligned memory address.", addr);
return false;
}
@ -1364,9 +1364,7 @@ void ppu_thread::dump_regs(std::string& ret, std::any& custom_data) const
u32 preferred_cr_field_index = 7;
};
dump_registers_data_t* func_data = nullptr;
func_data = std::any_cast<dump_registers_data_t>(&custom_data);
dump_registers_data_t* func_data = std::any_cast<dump_registers_data_t>(&custom_data);
if (!func_data)
{
@ -2039,9 +2037,9 @@ std::vector<std::pair<u32, u32>> ppu_thread::dump_callstack_list() const
return call_stack_list;
}
std::string ppu_thread::dump_misc() const
void ppu_thread::dump_misc(std::string& ret, std::any& custom_data) const
{
std::string ret = cpu_thread::dump_misc();
cpu_thread::dump_misc(ret, custom_data);
if (ack_suspend)
{
@ -2096,7 +2094,6 @@ std::string ppu_thread::dump_misc() const
{
ret += '\n';
}
return ret;
}
void ppu_thread::dump_all(std::string& ret) const
@ -3867,12 +3864,12 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
if (mself.read(hdr) && hdr.get_count(mself.size()))
{
std::set<u64> offs;
for (u32 j = 0; j < hdr.count; j++)
{
mself_record rec{};
std::set<u64> offs;
if (mself.read(rec) && rec.get_pos(mself.size()))
{
if (rec.size <= 0x20)

View File

@ -145,7 +145,7 @@ public:
virtual void dump_regs(std::string&, std::any& custom_data) const override;
virtual std::string dump_callstack() const override;
virtual std::vector<std::pair<u32, u32>> dump_callstack_list() const override;
virtual std::string dump_misc() const override;
virtual void dump_misc(std::string& ret, std::any& custom_data) const override;
virtual void dump_all(std::string&) const override;
virtual void cpu_task() override final;
virtual void cpu_sleep() override;

Some files were not shown because too many files have changed in this diff Show More