Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9ad8a9219 | ||
|
|
6dc06b3ff5 | ||
|
|
a10390e52a | ||
|
|
433110b4d8 | ||
|
|
b94e6d4864 | ||
|
|
44dc29e52b | ||
|
|
ab03d76ed6 | ||
|
|
bd2b2c2747 | ||
|
|
aa7cf5ea15 | ||
|
|
f8fe64ff77 | ||
|
|
1791876eda | ||
|
|
e6204d3c1d | ||
|
|
f0f9ef6f30 | ||
|
|
51ea735cb5 | ||
|
|
069821a2e7 | ||
|
|
0052108e87 | ||
|
|
64c24959cb | ||
|
|
b57390d3cd | ||
|
|
91c136b6d0 | ||
|
|
c00fa2cc8c | ||
|
|
fe3cbde1d3 | ||
|
|
e2dff6bbf8 | ||
|
|
976cd1ce66 | ||
|
|
a4523651c7 | ||
|
|
2702417192 | ||
|
|
72b872df66 | ||
|
|
bb3e2689d4 | ||
|
|
4ced11e533 | ||
|
|
9a0a5a1735 | ||
|
|
e83034624b | ||
|
|
619fe7b14e | ||
|
|
37a07ae545 | ||
|
|
e1eae3ee49 | ||
|
|
49abd6d8e5 | ||
|
|
fbdbf8addf | ||
|
|
2e4ee9c9b6 | ||
|
|
a863e94c25 | ||
|
|
9b6bc7c1b4 | ||
|
|
86b7ea6bf3 | ||
|
|
18bd6d681e | ||
|
|
2dd194d381 | ||
|
|
a8b603dd92 | ||
|
|
a03d4f69f8 | ||
|
|
99bb042bea | ||
|
|
2bcc27d581 | ||
|
|
53c33cd812 | ||
|
|
1d05cf9ce5 | ||
|
|
07f5b0aa5b | ||
|
|
36e1d664ea | ||
|
|
90e2c39015 | ||
|
|
5a90dc0059 | ||
|
|
c19d22ce88 | ||
|
|
5acc263b73 | ||
|
|
bc6e01c422 | ||
|
|
a2eb4fec53 | ||
|
|
32c9c6f515 | ||
|
|
04f7dd02fd | ||
|
|
35907bcfc8 | ||
|
|
61b1bd7ead | ||
|
|
2bad4f47f1 | ||
|
|
5a94adcf26 | ||
|
|
57e37862f4 | ||
|
|
45bae0046a | ||
|
|
a0c91bf96a | ||
|
|
b607993b7b | ||
|
|
1eb72e4b71 | ||
|
|
e5840ab868 | ||
|
|
54999d1507 | ||
|
|
51514f9dc8 | ||
|
|
40229adb14 | ||
|
|
33f8deffbe | ||
|
|
c80e08a642 | ||
|
|
62b2ffd7ca | ||
|
|
cd1d6282b4 | ||
|
|
67f69bb4b3 | ||
|
|
2ba7756c0e | ||
|
|
c6407b37a5 | ||
|
|
410660627d | ||
|
|
852317a071 | ||
|
|
6590f1b55d | ||
|
|
84277f41a1 | ||
|
|
b73c45f1fb | ||
|
|
ddd226f0ea | ||
|
|
3c68c36fa0 | ||
|
|
d54e54b66d | ||
|
|
2f3b66985e | ||
|
|
43799762c7 | ||
|
|
cb501e32ca | ||
|
|
7a7e25f901 | ||
|
|
e690e7e458 | ||
|
|
253d4565f1 | ||
|
|
1f2a935458 | ||
|
|
0c27b63ab4 | ||
|
|
4c106960c5 | ||
|
|
f076d1e1e6 | ||
|
|
7b58340a60 | ||
|
|
5578edf9e4 | ||
|
|
704d8764af | ||
|
|
6523afa69a | ||
|
|
5416f432b5 | ||
|
|
43f3a4816d | ||
|
|
bc0c42b025 | ||
|
|
9f3adb3fc7 | ||
|
|
df6cba6582 | ||
|
|
8cdad0af98 | ||
|
|
801a1e6c38 | ||
|
|
9da088fe29 | ||
|
|
d96f31eda4 | ||
|
|
a5cce58225 | ||
|
|
39e6fc5918 | ||
|
|
2ea344ce3e | ||
|
|
358fbb3ce3 | ||
|
|
aaf441005a | ||
|
|
6e6dd603cb | ||
|
|
22fe14d31d | ||
|
|
2eba7da8e6 | ||
|
|
ca2b7f9b9f | ||
|
|
4780e7c8da | ||
|
|
a318384142 | ||
|
|
53d3f49f45 | ||
|
|
25581ce52f | ||
|
|
6c0c80b7bb | ||
|
|
f9af53f215 | ||
|
|
2fd5b1b4be | ||
|
|
3acf1f6470 | ||
|
|
37f1533dad | ||
|
|
bb652ed840 | ||
|
|
281706fdae | ||
|
|
198fe71cc4 | ||
|
|
b8e2c7060b | ||
|
|
dbb6c87a10 | ||
|
|
7240cbfdab | ||
|
|
7866c7195c | ||
|
|
e26978e664 | ||
|
|
63ed8881a4 | ||
|
|
1be7b9f983 | ||
|
|
471ed347f4 | ||
|
|
cff9b5b65e | ||
|
|
5d28ff5df1 | ||
|
|
7fd0aa95fb | ||
|
|
27ecfaee9c | ||
|
|
ce2afa1d54 | ||
|
|
984c562500 | ||
|
|
f880a00cba | ||
|
|
6cf2cc67d3 | ||
|
|
9e6fecb4ca | ||
|
|
3194bd3fb4 | ||
|
|
fcb5a5c5f8 | ||
|
|
3988eceb8d | ||
|
|
2b2b13273b | ||
|
|
88278ec7c9 | ||
|
|
7d92198ef0 | ||
|
|
23eb67badc | ||
|
|
d5928d99d7 | ||
|
|
3c16105c3b | ||
|
|
5cb688f309 | ||
|
|
7859a5f9d2 | ||
|
|
8b74ea8757 | ||
|
|
2c2ec6e109 | ||
|
|
6c48bd8f93 | ||
|
|
b422cb86f2 | ||
|
|
1fb97734a0 | ||
|
|
7221012593 | ||
|
|
297db8713f | ||
|
|
477ae6c6df | ||
|
|
74fbca8c80 | ||
|
|
433816148a | ||
|
|
5714eb0ba5 | ||
|
|
315f88b0e4 | ||
|
|
8587fca5db | ||
|
|
e2a26f937f | ||
|
|
90ebc7f319 | ||
|
|
67a67feb68 | ||
|
|
9bdacc64aa | ||
|
|
5a921bca46 | ||
|
|
86f453f677 | ||
|
|
7712584bd4 | ||
|
|
bc58dff715 | ||
|
|
0bb6299e39 | ||
|
|
b24524fc75 | ||
|
|
60eb1ce2ec | ||
|
|
9733d8c857 | ||
|
|
5274210ba8 | ||
|
|
1627757608 | ||
|
|
4542020c86 | ||
|
|
b734ceb2e7 | ||
|
|
951d47c94c | ||
|
|
6f07e8453a | ||
|
|
e6cf05cfb7 | ||
|
|
6b6dd6c432 | ||
|
|
ee01d1186f | ||
|
|
2934641237 | ||
|
|
fecb53f86c | ||
|
|
9811e1cc3b | ||
|
|
234f2b4648 | ||
|
|
9e573a9ff2 | ||
|
|
3803c864f7 | ||
|
|
8afa40eaa7 | ||
|
|
c7a576edce | ||
|
|
c72d54bd6a | ||
|
|
040a79ddd1 | ||
|
|
aa094ca948 | ||
|
|
7917520633 | ||
|
|
8651875e59 | ||
|
|
ef70a6e825 | ||
|
|
0869ef421d | ||
|
|
5f86315ae0 | ||
|
|
ab72ce418e | ||
|
|
36cdaac327 | ||
|
|
6d52415d50 | ||
|
|
0603d24a91 | ||
|
|
71f0d5c602 | ||
|
|
763001ee91 | ||
|
|
0f92ea2578 | ||
|
|
e0a0d736c4 | ||
|
|
65320446f0 | ||
|
|
5f6822042d | ||
|
|
302e87c920 | ||
|
|
77cbdd82ab | ||
|
|
41db06b53f | ||
|
|
eeda9c7738 | ||
|
|
c38bf70464 | ||
|
|
43b295892f | ||
|
|
2573cc5fd0 | ||
|
|
4828d4d2d6 | ||
|
|
c5f278ed37 | ||
|
|
b839d4d1a6 | ||
|
|
3616424b26 | ||
|
|
4d6da6542e | ||
|
|
f2aa347608 | ||
|
|
bd7d5faa9f | ||
|
|
a3d09a7427 | ||
|
|
7dad9663b2 | ||
|
|
cae8ae63e3 | ||
|
|
728d84b1fe | ||
|
|
4a51302c58 | ||
|
|
0ea692e9ab | ||
|
|
1e16b338b4 | ||
|
|
14789b536f | ||
|
|
ac30feeddb | ||
|
|
0d80e300a0 | ||
|
|
69384d7bb4 | ||
|
|
4fd2409b8b | ||
|
|
d97851376d | ||
|
|
1c5e30e83f | ||
|
|
414df8432e | ||
|
|
92f63ccc0b | ||
|
|
d75e8b24f7 | ||
|
|
a1af15b907 | ||
|
|
cf5eb22591 | ||
|
|
2f9f79eea2 | ||
|
|
c57d6110c4 | ||
|
|
2a292d1e2e | ||
|
|
f2c8b157ef | ||
|
|
ec00a06caf | ||
|
|
ae6172d86b | ||
|
|
5605cf2141 | ||
|
|
d46ddcee5d | ||
|
|
3750fb2c1f | ||
|
|
86b2773c28 | ||
|
|
11a9011510 | ||
|
|
e66f1fa306 |
@@ -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 [email protected] 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++
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}"
|
||||
|
||||
@@ -30,23 +30,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 }}
|
||||
@@ -134,7 +134,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
|
||||
@@ -213,9 +213,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'
|
||||
|
||||
@@ -69,6 +69,9 @@ CMakeSettings.json
|
||||
*PVS-Studio*
|
||||
PVS/*
|
||||
|
||||
# Zed Editor files
|
||||
.zed/*
|
||||
|
||||
# Ignore other system generated files
|
||||
x64/*
|
||||
rpcs3/x64/*
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -20,6 +20,8 @@ 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)
|
||||
option(protobuf_BUILD_SHARED_LIBS "Build Shared Libraries" OFF)
|
||||
option(protobuf_MSVC_STATIC_RUNTIME "Link static runtime libraries" OFF)
|
||||
|
||||
add_subdirectory(protobuf EXCLUDE_FROM_ALL)
|
||||
target_include_directories(3rdparty_protobuf SYSTEM INTERFACE protobuf/src)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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**)
|
||||
|
||||
|
||||
@@ -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,50 +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([email protected])
|
||||
# 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([email protected])
|
||||
# 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()
|
||||
add_compile_options(/MP)
|
||||
add_compile_options("$<$<COMPILE_LANGUAGE:C,CXX>:/MP>")
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
@@ -142,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)
|
||||
@@ -161,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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 618 B |
|
After Width: | Height: | Size: 497 B |
|
After Width: | Height: | Size: 360 B |
|
After Width: | Height: | Size: 561 B |
|
After Width: | Height: | Size: 472 B |
|
After Width: | Height: | Size: 473 B |
|
After Width: | Height: | Size: 489 B |
|
After Width: | Height: | Size: 384 B |
|
After Width: | Height: | Size: 721 B |
|
After Width: | Height: | Size: 509 B |
|
After Width: | Height: | Size: 702 B |
|
After Width: | Height: | Size: 672 B |
|
After Width: | Height: | Size: 447 B |
|
After Width: | Height: | Size: 587 B |
|
After Width: | Height: | Size: 332 B |
|
After Width: | Height: | Size: 668 B |
|
After Width: | Height: | Size: 659 B |
|
After Width: | Height: | Size: 354 B |
|
After Width: | Height: | Size: 358 KiB |
@@ -96,11 +96,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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
@@ -195,6 +189,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
|
||||
@@ -202,6 +197,7 @@ if(BUILD_RPCS3_TESTS)
|
||||
rpcs3_lib
|
||||
rpcs3_emu
|
||||
GTest::gtest
|
||||
GTest::gmock
|
||||
)
|
||||
|
||||
target_include_directories(rpcs3_test
|
||||
|
||||
@@ -487,6 +487,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
|
||||
@@ -500,6 +501,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
|
||||
@@ -516,6 +519,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
|
||||
@@ -639,6 +645,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
|
||||
|
||||
@@ -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"
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -201,6 +201,13 @@ 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
|
||||
@@ -218,12 +225,66 @@ llvm::Value* cpu_translator::bitcast(llvm::Value* val, llvm::Type* type) const
|
||||
fmt::throw_exception("cpu_translator::bitcast(): incompatible type sizes (%u vs %u)", s1, s2);
|
||||
}
|
||||
|
||||
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 <>
|
||||
|
||||
@@ -567,6 +567,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 +3116,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;
|
||||
@@ -3224,6 +3253,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 +3682,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 +3983,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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -169,18 +169,18 @@ public:
|
||||
static const u32 id_count = 1023;
|
||||
SAVESTATE_INIT_POS(34);
|
||||
|
||||
ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr<CellDmuxCbEsMsg> cbFunc, u32 cbArg, u32 spec);
|
||||
ElementaryStream(Demuxer* dmux, vm::ptr<void> addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr<CellDmuxCbEsMsg> cbFunc, vm::ptr<void> cbArg, u32 spec);
|
||||
|
||||
Demuxer* dmux;
|
||||
const u32 id = idm::last_id();
|
||||
const u32 memAddr;
|
||||
const vm::ptr<void> memAddr;
|
||||
const u32 memSize;
|
||||
const u32 fidMajor;
|
||||
const u32 fidMinor;
|
||||
const u32 sup1;
|
||||
const u32 sup2;
|
||||
const vm::ptr<CellDmuxCbEsMsg> cbFunc;
|
||||
const u32 cbArg;
|
||||
const vm::ptr<void> cbArg;
|
||||
const u32 spec; //addr
|
||||
|
||||
std::vector<u8> raw_data; // demultiplexed data stream (managed by demuxer thread)
|
||||
@@ -208,13 +208,13 @@ public:
|
||||
const u32 memAddr;
|
||||
const u32 memSize;
|
||||
const vm::ptr<CellDmuxCbMsg> cbFunc;
|
||||
const u32 cbArg;
|
||||
const vm::ptr<void> cbArg;
|
||||
volatile bool is_finished = false;
|
||||
volatile bool is_closed = false;
|
||||
atomic_t<bool> is_running = false;
|
||||
atomic_t<bool> is_working = false;
|
||||
|
||||
Demuxer(u32 addr, u32 size, vm::ptr<CellDmuxCbMsg> func, u32 arg)
|
||||
Demuxer(u32 addr, u32 size, vm::ptr<CellDmuxCbMsg> func, vm::ptr<void> arg)
|
||||
: ppu_thread({}, "", 0)
|
||||
, memAddr(addr)
|
||||
, memSize(size)
|
||||
@@ -755,11 +755,11 @@ PesHeader::PesHeader(DemuxerStream& stream)
|
||||
is_ok = true;
|
||||
}
|
||||
|
||||
ElementaryStream::ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr<CellDmuxCbEsMsg> cbFunc, u32 cbArg, u32 spec)
|
||||
: put(utils::align(addr, 128))
|
||||
ElementaryStream::ElementaryStream(Demuxer* dmux, vm::ptr<void> addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr<CellDmuxCbEsMsg> cbFunc, vm::ptr<void> cbArg, u32 spec)
|
||||
: put(utils::align(addr.addr(), 128))
|
||||
, dmux(dmux)
|
||||
, memAddr(utils::align(addr, 128))
|
||||
, memSize(size - (addr - memAddr))
|
||||
, memAddr(vm::ptr<void>::make(utils::align(addr.addr(), 128)))
|
||||
, memSize(size - (addr.addr() - memAddr.addr()))
|
||||
, fidMajor(fidMajor)
|
||||
, fidMinor(fidMinor)
|
||||
, sup1(sup1)
|
||||
@@ -788,9 +788,9 @@ bool ElementaryStream::is_full(u32 space)
|
||||
{
|
||||
return first - put < space + 128;
|
||||
}
|
||||
else if (put + space + 128 > memAddr + memSize)
|
||||
else if (put + space + 128 > memAddr.addr() + memSize)
|
||||
{
|
||||
return first - memAddr < space + 128;
|
||||
return first - memAddr.addr() < space + 128;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -816,35 +816,35 @@ void ElementaryStream::push_au(u32 size, u64 dts, u64 pts, u64 userdata, bool ra
|
||||
std::lock_guard lock(m_mutex);
|
||||
ensure(!is_full(size));
|
||||
|
||||
if (put + size + 128 > memAddr + memSize)
|
||||
if (put + size + 128 > memAddr.addr() + memSize)
|
||||
{
|
||||
put = memAddr;
|
||||
put = memAddr.addr();
|
||||
}
|
||||
|
||||
std::memcpy(vm::base(put + 128), raw_data.data(), size);
|
||||
raw_data.erase(raw_data.begin(), raw_data.begin() + size);
|
||||
|
||||
auto info = vm::ptr<CellDmuxAuInfoEx>::make(put);
|
||||
info->auAddr = put + 128;
|
||||
info->auAddr.set(put + 128);
|
||||
info->auSize = size;
|
||||
info->dts.lower = static_cast<u32>(dts);
|
||||
info->dts.upper = static_cast<u32>(dts >> 32);
|
||||
info->pts.lower = static_cast<u32>(pts);
|
||||
info->pts.upper = static_cast<u32>(pts >> 32);
|
||||
info->isRap = rap;
|
||||
info->reserved = 0;
|
||||
info->auMaxSize = 0;
|
||||
info->userData = userdata;
|
||||
|
||||
auto spec = vm::ptr<u32>::make(put + u32{sizeof(CellDmuxAuInfoEx)});
|
||||
*spec = specific;
|
||||
|
||||
auto inf = vm::ptr<CellDmuxAuInfo>::make(put + 64);
|
||||
inf->auAddr = put + 128;
|
||||
inf->auAddr.set(put + 128);
|
||||
inf->auSize = size;
|
||||
inf->dtsLower = static_cast<u32>(dts);
|
||||
inf->dtsUpper = static_cast<u32>(dts >> 32);
|
||||
inf->ptsLower = static_cast<u32>(pts);
|
||||
inf->ptsUpper = static_cast<u32>(pts >> 32);
|
||||
inf->dts.lower = static_cast<u32>(dts);
|
||||
inf->dts.upper = static_cast<u32>(dts >> 32);
|
||||
inf->pts.lower = static_cast<u32>(pts);
|
||||
inf->pts.upper = static_cast<u32>(pts >> 32);
|
||||
inf->auMaxSize = 0; // ?????
|
||||
inf->userData = userdata;
|
||||
|
||||
@@ -927,7 +927,7 @@ bool ElementaryStream::peek(u32& out_data, bool no_ex, u32& out_spec, bool updat
|
||||
void ElementaryStream::reset()
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
put = memAddr;
|
||||
put = memAddr.addr();
|
||||
entries.clear();
|
||||
put_count = 0;
|
||||
got_count = 0;
|
||||
|
||||
@@ -33,118 +33,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
|
||||
@@ -163,12 +51,6 @@ struct CellDmuxType
|
||||
be_t<u32> reserved[2];
|
||||
};
|
||||
|
||||
struct CellDmuxPamfSpecificInfo
|
||||
{
|
||||
be_t<u32> thisSize;
|
||||
b8 programEndCodeCb;
|
||||
};
|
||||
|
||||
struct CellDmuxType2
|
||||
{
|
||||
be_t<s32> streamType; // CellDmuxStreamType
|
||||
@@ -177,7 +59,7 @@ struct CellDmuxType2
|
||||
|
||||
struct CellDmuxResource
|
||||
{
|
||||
be_t<u32> memAddr;
|
||||
vm::bptr<void> memAddr;
|
||||
be_t<u32> memSize;
|
||||
be_t<u32> ppuThreadPriority;
|
||||
be_t<u32> ppuThreadStackSize;
|
||||
@@ -187,7 +69,7 @@ struct CellDmuxResource
|
||||
|
||||
struct CellDmuxResourceEx
|
||||
{
|
||||
be_t<u32> memAddr;
|
||||
vm::bptr<void> memAddr;
|
||||
be_t<u32> memSize;
|
||||
be_t<u32> ppuThreadPriority;
|
||||
be_t<u32> ppuThreadStackSize;
|
||||
@@ -227,16 +109,16 @@ struct CellDmuxResource2
|
||||
be_t<u32> shit[4];
|
||||
};
|
||||
|
||||
using CellDmuxCbMsg = u32(u32 demuxerHandle, vm::ptr<CellDmuxMsg> demuxerMsg, u32 cbArg);
|
||||
using CellDmuxCbMsg = u32(u32 demuxerHandle, vm::cptr<CellDmuxMsg> demuxerMsg, vm::ptr<void> cbArg);
|
||||
|
||||
using CellDmuxCbEsMsg = u32(u32 demuxerHandle, u32 esHandle, vm::ptr<CellDmuxEsMsg> esMsg, u32 cbArg);
|
||||
using CellDmuxCbEsMsg = u32(u32 demuxerHandle, u32 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 +132,50 @@ 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;
|
||||
};
|
||||
|
||||
using DmuxNotifyDemuxDone = error_code(vm::ptr<void>, u32, vm::ptr<void>);
|
||||
using DmuxNotifyFatalErr = error_code(vm::ptr<void>, u32, vm::ptr<void>);
|
||||
@@ -301,7 +191,7 @@ 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>);
|
||||
@@ -318,7 +208,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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "Emu/Memory/vm_ptr.h"
|
||||
|
||||
// Error Codes
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -550,11 +550,12 @@ void PPUTranslator::CallFunction(u64 target, Value* indirect)
|
||||
else if (_target >= caddr && _target <= cend)
|
||||
{
|
||||
u32 target_last = static_cast<u32>(_target);
|
||||
|
||||
std::unordered_set<u32> passed_targets{target_last};
|
||||
|
||||
// Try to follow unconditional branches as long as there is no infinite loop
|
||||
while (target_last != _target)
|
||||
// !! Triggers compilation issues in Asura's Wrath in other parts of the code
|
||||
// !! See https://github.com/RPCS3/rpcs3/issues/18287
|
||||
while (false)
|
||||
{
|
||||
const ppu_opcode_t op{*ensure(m_info.get_ptr<u32>(target_last))};
|
||||
const ppu_itype::type itype = g_ppu_itype.decode(op.opcode);
|
||||
@@ -1304,7 +1305,7 @@ void PPUTranslator::VMADDFP(ppu_opcode_t op)
|
||||
if (!m_use_fma && data == v128{})
|
||||
{
|
||||
set_vr(op.vd, vec_handle_result(a * c + fsplat<f32[4]>(0.f)));
|
||||
ppu_log.notice("LLVM: VMADDFP with -0 addend at [0x%08x]", m_addr + (m_reloc ? m_reloc->addr : 0));
|
||||
ppu_log.notice("LLVM: VMADDFP with +0 addend at [0x%08x]", m_addr + (m_reloc ? m_reloc->addr : 0));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -3680,9 +3681,7 @@ void PPUTranslator::STVLX(ppu_opcode_t op)
|
||||
const auto addr = op.ra ? m_ir->CreateAdd(GetGpr(op.ra), GetGpr(op.rb)) : GetGpr(op.rb);
|
||||
const auto data = pshufb(get_vr<u8[16]>(op.vs), build<u8[16]>(127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112) + vsplat<u8[16]>(trunc<u8>(value<u64>(addr) & 0xf)));
|
||||
const auto mask = bitcast<bool[16]>(splat<u16>(0xffff) << trunc<u16>(value<u64>(addr) & 0xf));
|
||||
const auto ptr = value<u8(*)[16]>(GetMemory(m_ir->CreateAnd(addr, ~0xfull)));
|
||||
const auto align = splat<u32>(16);
|
||||
eval(llvm_calli<void, decltype(data), decltype(ptr), decltype(align), decltype(mask)>{"llvm.masked.store.v16i8.p0", {data, ptr, align, mask}});
|
||||
m_ir->CreateMaskedStore(data.eval(m_ir), GetMemory(m_ir->CreateAnd(addr, ~0xfull)), llvm::Align(16), mask.eval(m_ir));
|
||||
}
|
||||
|
||||
void PPUTranslator::STDBRX(ppu_opcode_t op)
|
||||
@@ -3710,9 +3709,7 @@ void PPUTranslator::STVRX(ppu_opcode_t op)
|
||||
const auto addr = op.ra ? m_ir->CreateAdd(GetGpr(op.ra), GetGpr(op.rb)) : GetGpr(op.rb);
|
||||
const auto data = pshufb(get_vr<u8[16]>(op.vs), build<u8[16]>(255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240) + vsplat<u8[16]>(trunc<u8>(value<u64>(addr) & 0xf)));
|
||||
const auto mask = bitcast<bool[16]>(trunc<u16>(splat<u64>(0xffff) << (value<u64>(addr) & 0xf) >> 16));
|
||||
const auto ptr = value<u8(*)[16]>(GetMemory(m_ir->CreateAnd(addr, ~0xfull)));
|
||||
const auto align = splat<u32>(16);
|
||||
eval(llvm_calli<void, decltype(data), decltype(ptr), decltype(align), decltype(mask)>{"llvm.masked.store.v16i8.p0", {data, ptr, align, mask}});
|
||||
m_ir->CreateMaskedStore(data.eval(m_ir), GetMemory(m_ir->CreateAnd(addr, ~0xfull)), llvm::Align(16), mask.eval(m_ir));
|
||||
}
|
||||
|
||||
void PPUTranslator::STFSUX(ppu_opcode_t op)
|
||||
|
||||
@@ -13,6 +13,7 @@ struct spu_itype
|
||||
static constexpr struct quadrop_tag{} _quadrop{}; // 4-op Instructions
|
||||
static constexpr struct xfloat_tag{} xfloat{}; // Instructions producing xfloat values
|
||||
static constexpr struct zregmod_tag{} zregmod{}; // Instructions not modifying any GPR
|
||||
static constexpr struct pure_tag{} pure{}; // Instructions that always produce the same values as long as arguments are equal
|
||||
|
||||
enum class type : unsigned char
|
||||
{
|
||||
@@ -158,6 +159,15 @@ struct spu_itype
|
||||
CUFLT,
|
||||
FRDS, // xfloat_tag last
|
||||
|
||||
CFLTS,
|
||||
CFLTU,
|
||||
FCEQ,
|
||||
FCMEQ,
|
||||
FCGT,
|
||||
FCMGT, // floating_tag last
|
||||
FSCRWR,
|
||||
FSCRRD,
|
||||
|
||||
DFA,
|
||||
DFS,
|
||||
DFM,
|
||||
@@ -167,20 +177,11 @@ struct spu_itype
|
||||
DFNMA,
|
||||
FESD,
|
||||
|
||||
CFLTS,
|
||||
CFLTU,
|
||||
FCEQ,
|
||||
FCMEQ,
|
||||
FCGT,
|
||||
FCMGT,
|
||||
FSCRWR,
|
||||
FSCRRD,
|
||||
|
||||
DFCEQ,
|
||||
DFCMEQ,
|
||||
DFCGT,
|
||||
DFCMGT,
|
||||
DFTSV, // floating_tag last
|
||||
DFTSV,
|
||||
|
||||
SHLH, // shiftrot_tag first
|
||||
SHLHI,
|
||||
@@ -248,10 +249,10 @@ struct spu_itype
|
||||
return value >= BR && value <= BISL;
|
||||
}
|
||||
|
||||
// Test for floating point instruction
|
||||
// Test for floating point instruction (32-bit float)
|
||||
friend constexpr bool operator &(type value, floating_tag)
|
||||
{
|
||||
return value >= FMA && value <= DFTSV;
|
||||
return value >= FMA && value <= FCMGT;
|
||||
}
|
||||
|
||||
// Test for 4-op instruction
|
||||
@@ -301,8 +302,16 @@ struct spu_itype
|
||||
{
|
||||
return (value >= HEQ && value <= STQR) || (value >= BR && value <= BIHNZ);
|
||||
}
|
||||
|
||||
// Test for instructions which always produce the same values as long as arguments and immediate values are equal
|
||||
friend constexpr bool operator &(type value, pure_tag)
|
||||
{
|
||||
return (value >= ILH && value <= CLGTI);
|
||||
}
|
||||
};
|
||||
|
||||
using spu_itype_t = spu_itype::type;
|
||||
|
||||
struct spu_iflag
|
||||
{
|
||||
enum
|
||||
@@ -528,6 +537,8 @@ struct spu_iflag
|
||||
}
|
||||
};
|
||||
|
||||
using spu_iflag_t = spu_iflag::flag;
|
||||
|
||||
#define NAME(x) static constexpr const char& x = *#x
|
||||
|
||||
struct spu_iname
|
||||
|
||||
@@ -24,6 +24,20 @@ union spu_opcode_t
|
||||
bf_t<u32, 7, 16> i16; // 9..24
|
||||
bf_t<s32, 7, 16> si16; // 9..24, signed
|
||||
bf_t<u32, 7, 18> i18; // 7..24
|
||||
|
||||
// For 16-bit instructions in the context of 32-bits
|
||||
u32 duplicate_si10() const
|
||||
{
|
||||
const u32 _16 = static_cast<u16>(static_cast<s16>(si10));
|
||||
return (_16 << 16) | _16;
|
||||
}
|
||||
|
||||
// For 8-bit instructions in the context of 32-bits
|
||||
u32 duplicate_duplicate_si10() const
|
||||
{
|
||||
const u32 _8 = static_cast<u8>(si10 & 0xff);
|
||||
return (_8 << 24) | (_8 << 16) | (_8 << 8) | _8;
|
||||
}
|
||||
};
|
||||
|
||||
constexpr u32 spu_branch_target(u32 pc, u32 imm = 0)
|
||||
@@ -42,6 +56,7 @@ constexpr u32 spu_decode(u32 inst)
|
||||
}
|
||||
|
||||
std::array<u32, 2> op_branch_targets(u32 pc, spu_opcode_t op);
|
||||
std::tuple<u32, std::array<u32, 3>, u32> op_register_targets(u32 /*pc*/, spu_opcode_t op);
|
||||
|
||||
// SPU decoder object. D provides functions. T is function pointer type returned.
|
||||
template <typename D, typename T = decltype(&D::UNK)>
|
||||
|
||||
@@ -4,12 +4,23 @@
|
||||
#include "Utilities/lockless.h"
|
||||
#include "Utilities/address_range.h"
|
||||
#include "SPUThread.h"
|
||||
#include "SPUAnalyser.h"
|
||||
#include <vector>
|
||||
#include <bitset>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <deque>
|
||||
|
||||
// std::bitset
|
||||
template <typename CT, typename T>
|
||||
requires requires(CT&& x, T&& y) { x.count(); x.test(y); x.flip(y); }
|
||||
[[nodiscard]] constexpr bool at32(CT&& container, T&& index, std::source_location src_loc = std::source_location::current())
|
||||
{
|
||||
if (container.size() >= std::forward<T>(index)) [[unlikely]]
|
||||
fmt::raw_range_error(src_loc, format_object_simplified(index), csv);
|
||||
return container[std::forward<T>(index)];
|
||||
}
|
||||
|
||||
// Helper class
|
||||
class spu_cache
|
||||
{
|
||||
@@ -201,6 +212,25 @@ public:
|
||||
__bitset_enum_max
|
||||
};
|
||||
|
||||
enum compare_direction : u32
|
||||
{
|
||||
CMP_TURNAROUND_FLAG = 0x1,
|
||||
CMP_NEGATE_FLAG = 0x100,
|
||||
CMP_SLESS = 0,
|
||||
CMP_SGREATER = CMP_SLESS | CMP_TURNAROUND_FLAG,
|
||||
CMP_EQUAL,
|
||||
CMP_EQUAL2 = CMP_EQUAL | CMP_TURNAROUND_FLAG,
|
||||
CMP_LLESS,
|
||||
CMP_LGREATER = CMP_LLESS | CMP_TURNAROUND_FLAG,
|
||||
CMP_SGREATER_EQUAL = CMP_SLESS | CMP_NEGATE_FLAG,
|
||||
CMP_SLOWER_EQUAL = CMP_SGREATER | CMP_NEGATE_FLAG,
|
||||
CMP_NOT_EQUAL = CMP_EQUAL | CMP_NEGATE_FLAG,
|
||||
CMP_NOT_EQUAL2 = CMP_NOT_EQUAL | CMP_TURNAROUND_FLAG,
|
||||
CMP_LGREATER_EQUAL = CMP_LLESS | CMP_NEGATE_FLAG,
|
||||
CMP_LLOWER_EQUAL = CMP_LGREATER | CMP_NEGATE_FLAG,
|
||||
CMP_UNKNOWN,
|
||||
};
|
||||
|
||||
struct reg_state_t
|
||||
{
|
||||
bs_t<vf> flag{+vf::is_null};
|
||||
@@ -273,6 +303,399 @@ public:
|
||||
static u32 alloc_tag(bool reset = false) noexcept;
|
||||
};
|
||||
|
||||
struct reduced_loop_t
|
||||
{
|
||||
bool active = false; // Single block loop detected
|
||||
bool failed = false;
|
||||
u32 loop_pc = SPU_LS_SIZE;
|
||||
u32 loop_end = SPU_LS_SIZE;
|
||||
|
||||
// False: single-block loop
|
||||
// True: loop with a trailing block of aftermath (iteration update) stuff (like for (u32 i = 0; i < 10; /*update*/ i++))
|
||||
bool is_two_block_loop = false;
|
||||
bool has_cond_state = false;
|
||||
|
||||
// Loop stay-in state requirement
|
||||
u64 cond_val_mask = umax;
|
||||
u64 cond_val_min = 0;
|
||||
u64 cond_val_size = 0;
|
||||
compare_direction cond_val_compare{};
|
||||
u64 cond_val_incr = 0;
|
||||
bool cond_val_incr_is_immediate = false;
|
||||
u64 cond_val_register_argument_idx = umax;
|
||||
u64 cond_val_register_idx = umax;
|
||||
bool cond_val_incr_before_cond = false;
|
||||
bool cond_val_incr_before_cond_taken_in_account = false;
|
||||
bool cond_val_is_immediate = false;
|
||||
|
||||
// Loop attributes
|
||||
bool is_constant_expression = false;
|
||||
bool is_secret = false;
|
||||
|
||||
struct supplemental_condition_t
|
||||
{
|
||||
u64 immediate_value = umax;
|
||||
u64 type_size = 0;
|
||||
compare_direction val_compare{};
|
||||
};
|
||||
|
||||
// Supplemental loop condition:
|
||||
// Inner conditions that depend on extrnal values (not produced inside the loop)
|
||||
// all should evaluate to false in order for the optimization to work (at the moment)
|
||||
// So succeeding can be treated linearly
|
||||
u64 expected_sup_conds = 0;
|
||||
u64 current_sup_conds_index = 0;
|
||||
std::vector<supplemental_condition_t> sup_conds;
|
||||
|
||||
void take_cond_val_incr_before_cond_into_account()
|
||||
{
|
||||
if (cond_val_is_immediate && cond_val_incr_before_cond_taken_in_account && !cond_val_incr_before_cond_taken_in_account)
|
||||
{
|
||||
cond_val_min -= cond_val_incr;
|
||||
cond_val_min &= cond_val_mask;
|
||||
cond_val_incr_before_cond_taken_in_account = true;
|
||||
}
|
||||
}
|
||||
|
||||
std::bitset<s_reg_max> loop_args;
|
||||
std::bitset<s_reg_max> loop_dicts;
|
||||
std::bitset<s_reg_max> loop_writes;
|
||||
|
||||
struct origin_t
|
||||
{
|
||||
std::bitset<s_reg_max> regs{};
|
||||
u32 modified = 0;
|
||||
spu_itype_t mod1_type = spu_itype::UNK;
|
||||
spu_itype_t mod2_type = spu_itype::UNK;
|
||||
spu_itype_t mod3_type = spu_itype::UNK;
|
||||
u32 IMM = 0;
|
||||
|
||||
private:
|
||||
// Internal, please access using fixed order
|
||||
spu_itype_t access_type(u32 i) const
|
||||
{
|
||||
if (i > modified)
|
||||
{
|
||||
return spu_itype::UNK;
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1: return mod1_type;
|
||||
case 2: return mod2_type;
|
||||
case 3: return mod3_type;
|
||||
default: return spu_itype::UNK;
|
||||
}
|
||||
|
||||
return spu_itype::UNK;
|
||||
}
|
||||
public:
|
||||
|
||||
spu_itype_t reverse1_type()
|
||||
{
|
||||
return access_type(modified);
|
||||
}
|
||||
|
||||
spu_itype_t reverse2_type()
|
||||
{
|
||||
return access_type(modified - 1);
|
||||
}
|
||||
|
||||
spu_itype_t reverse3_type()
|
||||
{
|
||||
return access_type(modified - 2);
|
||||
}
|
||||
|
||||
origin_t& join_with_this(const origin_t& rhs)
|
||||
{
|
||||
regs |= rhs.regs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
origin_t& join_with_this(u32 rhs)
|
||||
{
|
||||
regs.set(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
origin_t& add_register_origin(u32 reg_val)
|
||||
{
|
||||
regs.set(reg_val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool is_single_reg_access(u32 reg_val) const
|
||||
{
|
||||
if (!modified)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return regs.count() == 1 && ::at32(regs, reg_val);
|
||||
}
|
||||
|
||||
bool is_loop_dictator(u32 reg_val, bool test_predictable = false, bool should_predictable = true) const
|
||||
{
|
||||
if (!modified)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (regs.count() >= 1 && ::at32(regs, reg_val))
|
||||
{
|
||||
if (!test_predictable)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (modified > 1)
|
||||
{
|
||||
return should_predictable ^ true;
|
||||
}
|
||||
|
||||
switch (mod1_type)
|
||||
{
|
||||
case spu_itype::A:
|
||||
{
|
||||
if (regs.count() == 2)
|
||||
{
|
||||
return should_predictable;
|
||||
}
|
||||
|
||||
return should_predictable ^ true;
|
||||
}
|
||||
case spu_itype::AI:
|
||||
case spu_itype::AHI:
|
||||
{
|
||||
if (IMM && regs.count() == 1)
|
||||
{
|
||||
return should_predictable;
|
||||
}
|
||||
|
||||
return should_predictable ^ true;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
return should_predictable ^ true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_predictable_loop_dictator(u32 reg_val) const
|
||||
{
|
||||
return is_loop_dictator(reg_val, true, true);
|
||||
}
|
||||
|
||||
bool is_non_predictable_loop_dictator(u32 reg_val) const
|
||||
{
|
||||
return is_loop_dictator(reg_val, true, false);
|
||||
}
|
||||
|
||||
bool is_null(u32 reg_val) const noexcept
|
||||
{
|
||||
if (modified)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (regs.count() - (::at32(regs, reg_val) ? 1 : 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
origin_t& add_instruction_modifier(spu_itype_t inst_type, u32 imm = 0)
|
||||
{
|
||||
if (inst_type == spu_itype::UNK)
|
||||
{
|
||||
mod1_type = spu_itype::UNK;
|
||||
mod2_type = spu_itype::UNK;
|
||||
mod3_type = spu_itype::UNK;
|
||||
IMM = umax;
|
||||
modified = 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (modified == 1)
|
||||
{
|
||||
if (modified == 3)
|
||||
{
|
||||
mod1_type = spu_itype::UNK;
|
||||
mod2_type = spu_itype::UNK;
|
||||
mod3_type = spu_itype::UNK;
|
||||
IMM = umax;
|
||||
modified = 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool is_ok = false;
|
||||
switch (inst_type)
|
||||
{
|
||||
case spu_itype::XSBH:
|
||||
{
|
||||
const auto prev_type = modified == 1 ? mod1_type : mod2_type;
|
||||
is_ok &= mod1_type == spu_itype::CEQB || mod1_type == spu_itype::CEQBI || mod1_type == spu_itype::CGTB || mod1_type == spu_itype::CGTBI || mod1_type == spu_itype::CLGTB || mod1_type == spu_itype::CLGTBI;
|
||||
break;
|
||||
}
|
||||
case spu_itype::ANDI:
|
||||
{
|
||||
const auto prev_type = modified == 1 ? mod1_type : mod2_type;
|
||||
is_ok &= mod1_type == spu_itype::CEQB || mod1_type == spu_itype::CEQBI || mod1_type == spu_itype::CGTB || mod1_type == spu_itype::CGTBI || mod1_type == spu_itype::CLGTB || mod1_type == spu_itype::CLGTBI;
|
||||
is_ok &= (spu_opcode_t{imm}.si10 & 0xff) == 0xff;
|
||||
break;
|
||||
}
|
||||
case spu_itype::CEQ:
|
||||
case spu_itype::CEQH:
|
||||
case spu_itype::CEQB:
|
||||
case spu_itype::CGT:
|
||||
case spu_itype::CGTH:
|
||||
case spu_itype::CGTB:
|
||||
case spu_itype::CLGT:
|
||||
case spu_itype::CLGTH:
|
||||
case spu_itype::CLGTB:
|
||||
{
|
||||
is_ok = modified == 1 && (mod1_type == spu_itype::AI || mod1_type == spu_itype::AHI);
|
||||
IMM = imm;
|
||||
break;
|
||||
}
|
||||
case spu_itype::CEQI:
|
||||
case spu_itype::CEQHI:
|
||||
case spu_itype::CEQBI:
|
||||
case spu_itype::CGTI:
|
||||
case spu_itype::CGTHI:
|
||||
case spu_itype::CGTBI:
|
||||
case spu_itype::CLGTI:
|
||||
case spu_itype::CLGTHI:
|
||||
case spu_itype::CLGTBI:
|
||||
{
|
||||
is_ok = modified == 1 && (mod1_type == spu_itype::AI || mod1_type == spu_itype::AHI);
|
||||
IMM = spu_opcode_t{imm}.si10;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_ok)
|
||||
{
|
||||
mod1_type = spu_itype::UNK;
|
||||
mod2_type = spu_itype::UNK;
|
||||
mod3_type = spu_itype::UNK;
|
||||
IMM = umax;
|
||||
modified = 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
(modified == 1 ? mod2_type : mod3_type) = inst_type;
|
||||
modified++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
mod1_type = inst_type;
|
||||
modified = 1;
|
||||
|
||||
switch (inst_type)
|
||||
{
|
||||
case spu_itype::AHI:
|
||||
{
|
||||
IMM = spu_opcode_t{imm}.duplicate_si10();
|
||||
return *this;
|
||||
}
|
||||
case spu_itype::AI:
|
||||
case spu_itype::ORI:
|
||||
case spu_itype::XORI:
|
||||
case spu_itype::ANDI:
|
||||
|
||||
case spu_itype::CEQI:
|
||||
case spu_itype::CEQHI:
|
||||
case spu_itype::CEQBI:
|
||||
case spu_itype::CGTI:
|
||||
case spu_itype::CGTHI:
|
||||
case spu_itype::CGTBI:
|
||||
case spu_itype::CLGTI:
|
||||
case spu_itype::CLGTHI:
|
||||
case spu_itype::CLGTBI:
|
||||
{
|
||||
IMM = spu_opcode_t{imm}.si10;
|
||||
return *this;
|
||||
}
|
||||
case spu_itype::ILA:
|
||||
{
|
||||
IMM = spu_opcode_t{imm}.i18;
|
||||
return *this;
|
||||
}
|
||||
case spu_itype::IOHL:
|
||||
case spu_itype::ILH:
|
||||
case spu_itype::ILHU:
|
||||
{
|
||||
IMM = spu_opcode_t{imm}.i16;
|
||||
return *this;
|
||||
}
|
||||
default:
|
||||
{
|
||||
IMM = imm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
static origin_t make_reg(u32 reg_val) noexcept
|
||||
{
|
||||
origin_t org{};
|
||||
org.add_register_origin(reg_val);
|
||||
return org;
|
||||
}
|
||||
|
||||
const origin_t* find_reg(u32 reg_val) const noexcept
|
||||
{
|
||||
for (auto& pair : regs)
|
||||
{
|
||||
if (pair.first == reg_val)
|
||||
{
|
||||
return &pair.second;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
origin_t* find_reg(u32 reg_val) noexcept
|
||||
{
|
||||
return const_cast<origin_t*>(std::as_const(*this).find_reg(reg_val));
|
||||
}
|
||||
|
||||
bool is_reg_null(u32 reg_val) const noexcept
|
||||
{
|
||||
if (const auto reg_found = find_reg(reg_val))
|
||||
{
|
||||
return reg_found->is_null(reg_val);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
origin_t get_reg(u32 reg_val) noexcept
|
||||
{
|
||||
const auto org = find_reg(reg_val);
|
||||
return org ? *org : regs.emplace_back(reg_val, std::remove_reference_t<decltype(*org)>{}).second;
|
||||
}
|
||||
|
||||
std::vector<std::pair<u8, origin_t>> regs;
|
||||
|
||||
// Return old state for error reporting
|
||||
reduced_loop_t discard()
|
||||
{
|
||||
const reduced_loop_t old = *this;
|
||||
*this = reduced_loop_t{};
|
||||
return old;
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
spu_runtime* m_spurt{};
|
||||
|
||||
@@ -326,8 +749,14 @@ protected:
|
||||
// Set if the initial register value in this block may be xfloat
|
||||
std::bitset<s_reg_max> reg_maybe_xf{};
|
||||
|
||||
// Bit mask of the registers used (before modified)
|
||||
std::bitset<s_reg_max> reg_use{};
|
||||
// Set if register is used in floating pont instruction
|
||||
std::bitset<s_reg_max> reg_maybe_float{};
|
||||
|
||||
// Set if register is used as shuffle mask
|
||||
std::bitset<s_reg_max> reg_maybe_shuffle_mask{};
|
||||
|
||||
// Number of times registers are used (before modified)
|
||||
std::array<u32, s_reg_max> reg_use{};
|
||||
|
||||
// Bit mask of the trivial (u32 x 4) constant value resulting in this block
|
||||
std::bitset<s_reg_max> reg_const{};
|
||||
@@ -391,18 +820,23 @@ protected:
|
||||
putllc16,
|
||||
putllc0,
|
||||
rchcnt_loop,
|
||||
reduced_loop,
|
||||
};
|
||||
|
||||
std::vector<inst_attr> m_inst_attrs;
|
||||
|
||||
struct pattern_info
|
||||
{
|
||||
u64 info;
|
||||
// Info via integral
|
||||
u64 info{};
|
||||
|
||||
// Info via additional erased-typed pointer
|
||||
std::shared_ptr<void> info_ptr;
|
||||
};
|
||||
|
||||
std::unordered_map<u32, pattern_info> m_patterns;
|
||||
std::map<u32, pattern_info> m_patterns;
|
||||
|
||||
void add_pattern(inst_attr attr, u32 start, u64 info);
|
||||
void add_pattern(inst_attr attr, u32 start, u64 info, std::shared_ptr<void> info_ptr = nullptr);
|
||||
|
||||
private:
|
||||
// For private use
|
||||
@@ -435,7 +869,7 @@ public:
|
||||
spu_program analyse(const be_t<u32>* ls, u32 entry_point, std::map<u32, std::vector<u32>>* out_target_list = nullptr);
|
||||
|
||||
// Print analyser internal state
|
||||
void dump(const spu_program& result, std::string& out);
|
||||
void dump(const spu_program& result, std::string& out, u32 block_min = 0, u32 block_max = SPU_LS_SIZE);
|
||||
|
||||
// Get SPU Runtime
|
||||
spu_runtime& get_runtime()
|
||||
|
||||
@@ -495,7 +495,8 @@ void do_cell_atomic_128_store(u32 addr, const void* to_write);
|
||||
|
||||
extern thread_local u64 g_tls_fault_spu;
|
||||
|
||||
const spu_decoder<spu_itype> s_spu_itype;
|
||||
const extern spu_decoder<spu_itype> g_spu_itype;
|
||||
const extern spu_decoder<spu_iflag> g_spu_iflag;
|
||||
|
||||
namespace vm
|
||||
{
|
||||
@@ -598,7 +599,7 @@ std::array<u32, 2> op_branch_targets(u32 pc, spu_opcode_t op)
|
||||
{
|
||||
std::array<u32, 2> res{spu_branch_target(pc + 4), umax};
|
||||
|
||||
switch (const auto type = s_spu_itype.decode(op.opcode))
|
||||
switch (const auto type = g_spu_itype.decode(op.opcode))
|
||||
{
|
||||
case spu_itype::BR:
|
||||
case spu_itype::BRA:
|
||||
@@ -639,6 +640,54 @@ std::array<u32, 2> op_branch_targets(u32 pc, spu_opcode_t op)
|
||||
return res;
|
||||
}
|
||||
|
||||
std::tuple<u32, std::array<u32, 3>, u32> op_register_targets(u32 /*pc*/, spu_opcode_t op)
|
||||
{
|
||||
std::tuple<u32, std::array<u32, 3>, u32> result{u32{umax}, std::array<u32, 3>{128, 128, 128}, op.opcode};
|
||||
|
||||
const auto type = g_spu_itype.decode(op.opcode);
|
||||
|
||||
if (type & spu_itype::zregmod)
|
||||
{
|
||||
std::get<2>(result) = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
std::get<0>(result) = type & spu_itype::_quadrop ? op.rt4 : op.rt;
|
||||
|
||||
spu_opcode_t op_masked = op;
|
||||
|
||||
if (type & spu_itype::_quadrop)
|
||||
{
|
||||
op_masked.rt4 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
op_masked.rt = 0;
|
||||
}
|
||||
|
||||
std::get<2>(result) = op_masked.opcode;
|
||||
|
||||
if (auto iflags = g_spu_iflag.decode(op.opcode))
|
||||
{
|
||||
if (+iflags & +spu_iflag::use_ra)
|
||||
{
|
||||
std::get<1>(result)[0] = op.ra;
|
||||
}
|
||||
|
||||
if (+iflags & +spu_iflag::use_rb)
|
||||
{
|
||||
std::get<1>(result)[1] = op.rb;
|
||||
}
|
||||
|
||||
if (+iflags & +spu_iflag::use_rc)
|
||||
{
|
||||
std::get<1>(result)[2] = op.rc;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void spu_int_ctrl_t::set(u64 ints)
|
||||
{
|
||||
// leave only enabled interrupts
|
||||
@@ -988,7 +1037,7 @@ std::vector<std::pair<u32, u32>> spu_thread::dump_callstack_list() const
|
||||
passed[i / 4] = true;
|
||||
|
||||
const spu_opcode_t op{_ref<u32>(i)};
|
||||
const auto type = s_spu_itype.decode(op.opcode);
|
||||
const auto type = g_spu_itype.decode(op.opcode);
|
||||
|
||||
if (start == 0 && type == spu_itype::STQD && op.ra == 1u && op.rt == 0u)
|
||||
{
|
||||
@@ -1090,11 +1139,62 @@ std::vector<std::pair<u32, u32>> spu_thread::dump_callstack_list() const
|
||||
return call_stack_list;
|
||||
}
|
||||
|
||||
std::string spu_thread::dump_misc() const
|
||||
void spu_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);
|
||||
|
||||
fmt::append(ret, "Block Weight: %u (Retreats: %u)", block_counter, block_failure);
|
||||
struct dump_misc_data_t
|
||||
{
|
||||
u32 cpu_id = umax;
|
||||
u64 last_read_time = umax;
|
||||
u64 last_block_counter = umax;
|
||||
u64 update_count = 0;
|
||||
|
||||
std::pair<u64, u64> update(u64 current_block_counter, u64 current_timestamp = get_system_time())
|
||||
{
|
||||
const u64 diff_time = current_timestamp <= last_read_time ? 0 : current_timestamp - last_read_time;
|
||||
const u64 diff_block = current_block_counter <= last_block_counter ? 0 : current_block_counter - last_block_counter;
|
||||
|
||||
if (last_read_time == umax || update_count >= 1000)
|
||||
{
|
||||
last_read_time = current_timestamp;
|
||||
last_block_counter = current_block_counter;
|
||||
update_count = 0;
|
||||
}
|
||||
else if (diff_time >= 100000 && diff_block >= 100)
|
||||
{
|
||||
// Update values to measure rate (but not fully so rate can be measured later)
|
||||
last_read_time += diff_time / 10 * 9;
|
||||
last_block_counter += diff_block / 10 * 9;
|
||||
update_count++;
|
||||
}
|
||||
|
||||
return {diff_time, diff_block};
|
||||
}
|
||||
};
|
||||
|
||||
dump_misc_data_t* func_data = std::any_cast<dump_misc_data_t>(&custom_data);
|
||||
|
||||
if (!func_data)
|
||||
{
|
||||
custom_data.reset();
|
||||
custom_data = std::make_any<dump_misc_data_t>();
|
||||
func_data = ensure(std::any_cast<dump_misc_data_t>(&custom_data));
|
||||
}
|
||||
|
||||
if (func_data->cpu_id != this->id)
|
||||
{
|
||||
*func_data = {};
|
||||
func_data->cpu_id = this->id;
|
||||
}
|
||||
|
||||
const u64 current_block_counter = atomic_storage<u64>::load(block_counter);
|
||||
|
||||
const auto [diff_time, diff_block] = func_data->update(current_block_counter);
|
||||
|
||||
const u64 rate_of_diff = diff_block ? std::max<u64>(1, utils::rational_mul<u64>(diff_block, 1'000'000, std::max<u64>(diff_time, 1))) : 0;
|
||||
|
||||
fmt::append(ret, "Block Weight: log10(%u/second): %.1f (Retreats: %u)", rate_of_diff, std::log10(std::max<u64>(rate_of_diff, 10)), block_failure);
|
||||
|
||||
if (u64 hash = atomic_storage<u64>::load(block_hash))
|
||||
{
|
||||
@@ -1145,8 +1245,6 @@ std::string spu_thread::dump_misc() const
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void spu_thread::cpu_on_stop()
|
||||
@@ -3761,7 +3859,7 @@ bool spu_thread::is_exec_code(u32 addr, std::span<const u8> ls_ptr, u32 base_add
|
||||
|
||||
const u32 addr0 = spu_branch_target(addr);
|
||||
const spu_opcode_t op{read_from_ptr<be_t<u32>>(ls_ptr, addr0 - base_addr)};
|
||||
const auto type = s_spu_itype.decode(op.opcode);
|
||||
const auto type = g_spu_itype.decode(op.opcode);
|
||||
|
||||
if (type == spu_itype::UNK || !op.opcode)
|
||||
{
|
||||
@@ -3907,7 +4005,7 @@ bool spu_thread::is_exec_code(u32 addr, std::span<const u8> ls_ptr, u32 base_add
|
||||
// Test the validity of a single instruction of the optional target
|
||||
// This function can't be too slow and is unlikely to improve results by a great deal
|
||||
const u32 op0 = read_from_ptr<be_t<u32>>(ls_ptr, route_pc - base_addr);
|
||||
const spu_itype::type type0 = s_spu_itype.decode(op0);
|
||||
const spu_itype::type type0 = g_spu_itype.decode(op0);
|
||||
|
||||
if (type0 == spu_itype::UNK || !op0)
|
||||
{
|
||||
@@ -6878,7 +6976,7 @@ spu_exec_object spu_thread::capture_memory_as_elf(std::span<spu_memory_segment_d
|
||||
const u32 op = read_from_ptr<be_t<u32>>(all_data, pc0 - 4);
|
||||
|
||||
// Try to find function entry (if they are placed sequentially search for BI $LR of previous function)
|
||||
if (!op || op == 0x35000000u || s_spu_itype.decode(op) == spu_itype::UNK)
|
||||
if (!op || op == 0x35000000u || g_spu_itype.decode(op) == spu_itype::UNK)
|
||||
{
|
||||
if (is_exec_code(pc0, { all_data.data(), SPU_LS_SIZE }))
|
||||
break;
|
||||
|
||||