mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-12-06 07:12:28 +01:00
Compare commits
279 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54206c62b3 | ||
|
|
67f7119717 | ||
|
|
133b19f205 | ||
|
|
fce393024a | ||
|
|
7d3cf831d5 | ||
|
|
dc27047ed4 | ||
|
|
b9a9c1af07 | ||
|
|
e3f5f2d14e | ||
|
|
ff9401303b | ||
|
|
2a6f1cf35c | ||
|
|
b86b4d15c6 | ||
|
|
23ffa4ccdb | ||
|
|
cbba687ffa | ||
|
|
613d428ced | ||
|
|
6489fca16b | ||
|
|
3c747b377f | ||
|
|
a859e14e19 | ||
|
|
6dd37cb2d5 | ||
|
|
7e8ed5ecc1 | ||
|
|
d396a778b7 | ||
|
|
25badf9534 | ||
|
|
314b69c7d8 | ||
|
|
bc55f7787e | ||
|
|
4bda2f9b0f | ||
|
|
d822d85ea1 | ||
|
|
7001940483 | ||
|
|
3c5c74c496 | ||
|
|
c80aba2342 | ||
|
|
84d5e42896 | ||
|
|
53edd410c7 | ||
|
|
7f9cc357e8 | ||
|
|
e2cbbcf646 | ||
|
|
e938b93f48 | ||
|
|
4a042ae84f | ||
|
|
c48ae344a8 | ||
|
|
e09be04df6 | ||
|
|
d625c1d004 | ||
|
|
cae77784db | ||
|
|
14bd6b0cc5 | ||
|
|
e11f8df064 | ||
|
|
e2da6d36ba | ||
|
|
27c2f2ae4d | ||
|
|
727f3dd7a1 | ||
|
|
7b560e5ffa | ||
|
|
50c9a91942 | ||
|
|
d9f913016c | ||
|
|
a442cb91a1 | ||
|
|
41aaa912e7 | ||
|
|
6ebdb0c0c1 | ||
|
|
914b52cf4a | ||
|
|
b451dfe877 | ||
|
|
7986ee58de | ||
|
|
5a9083e4fc | ||
|
|
6a398f9947 | ||
|
|
8495a138c6 | ||
|
|
2c1d962bdc | ||
|
|
0fbd0e8cc7 | ||
|
|
5c187f5cda | ||
|
|
cb7650240c | ||
|
|
9d92e190eb | ||
|
|
42d9065c11 | ||
|
|
f300832edb | ||
|
|
683baf46b2 | ||
|
|
89a13b75f7 | ||
|
|
7472d95b0c | ||
|
|
ecba1d2cb7 | ||
|
|
fcff16b6f7 | ||
|
|
a3f7c0d67f | ||
|
|
98ca15699b | ||
|
|
dec6fba68d | ||
|
|
e1eb7421fb | ||
|
|
ea7183b6bd | ||
|
|
d6a36f4b60 | ||
|
|
6e11978638 | ||
|
|
7f6842705c | ||
|
|
9deb6cd4fa | ||
|
|
e6d723c675 | ||
|
|
400b4e71cf | ||
|
|
3c3197d72d | ||
|
|
cffc13696d | ||
|
|
ff72f944ba | ||
|
|
b067688c8e | ||
|
|
8ccc30725a | ||
|
|
c38b8c6d12 | ||
|
|
107d9dc533 | ||
|
|
c669a0beb7 | ||
|
|
f992ccdcad | ||
|
|
e6dc0d98f5 | ||
|
|
1250e428a7 | ||
|
|
ddecade935 | ||
|
|
de914247be | ||
|
|
6a51cd9f7f | ||
|
|
2042b54d2d | ||
|
|
5267c87ca7 | ||
|
|
6731feb751 | ||
|
|
10f8a49e36 | ||
|
|
a6371ef5d3 | ||
|
|
2d3e6c6d02 | ||
|
|
9b1d39c14e | ||
|
|
5893851029 | ||
|
|
42177add17 | ||
|
|
84fdd2e056 | ||
|
|
bc01863654 | ||
|
|
cbb4dd8f22 | ||
|
|
0439b62257 | ||
|
|
a93197cdcb | ||
|
|
b8031f4510 | ||
|
|
db8437b01c | ||
|
|
63f7bcf652 | ||
|
|
109abea454 | ||
|
|
c7ae97f8ea | ||
|
|
d61f4101ad | ||
|
|
ec70c9691f | ||
|
|
18111ac8bc | ||
|
|
5a761c7184 | ||
|
|
510ed00b11 | ||
|
|
fa06fed86f | ||
|
|
871dd729b2 | ||
|
|
7e209a7275 | ||
|
|
0bb84b374e | ||
|
|
92e24a5779 | ||
|
|
e48ba283d8 | ||
|
|
0bf9ee9fa5 | ||
|
|
c60e5cc48a | ||
|
|
642005cf1d | ||
|
|
b0956a8f74 | ||
|
|
2fb8cbda38 | ||
|
|
c16278a5ab | ||
|
|
bfe54a29ae | ||
|
|
265d6643e5 | ||
|
|
d87f055bb2 | ||
|
|
1af5afdaab | ||
|
|
864bb9f0db | ||
|
|
1007aaee4c | ||
|
|
8126a199f5 | ||
|
|
b435deac9d | ||
|
|
8a9b15dee3 | ||
|
|
c5a54a3d4f | ||
|
|
bcdf2ef36f | ||
|
|
3df0c8caef | ||
|
|
50eb46d294 | ||
|
|
ff922f6324 | ||
|
|
1e1da422ea | ||
|
|
3e5a035046 | ||
|
|
6e5338d091 | ||
|
|
d73a7e0ff3 | ||
|
|
a6c0433a2e | ||
|
|
ca5a43a3ab | ||
|
|
4710b38505 | ||
|
|
9cde97c22b | ||
|
|
323f504138 | ||
|
|
d7df929ada | ||
|
|
2667d5de0f | ||
|
|
49548b913d | ||
|
|
17c148d90e | ||
|
|
17621d2a5e | ||
|
|
8984c2b316 | ||
|
|
5d906e1da4 | ||
|
|
dba48d6387 | ||
|
|
0403231a0d | ||
|
|
8712414123 | ||
|
|
2485a98d4f | ||
|
|
cc8929ef4a | ||
|
|
ede8382c6a | ||
|
|
dc22584f72 | ||
|
|
7cb4a68043 | ||
|
|
ded91329bc | ||
|
|
81f5be30aa | ||
|
|
ba2518f862 | ||
|
|
3a6c71e523 | ||
|
|
8013129c5b | ||
|
|
5ea92df4ca | ||
|
|
afffd3061a | ||
|
|
8ea2109b37 | ||
|
|
fa8f35ea38 | ||
|
|
50576d044b | ||
|
|
3f797b2de3 | ||
|
|
9124d08fdb | ||
|
|
e4ae5bdce1 | ||
|
|
5f37f2c8df | ||
|
|
9dc66b46fc | ||
|
|
0ca4f85dc7 | ||
|
|
9c512849ef | ||
|
|
9550d5b67d | ||
|
|
dd40f49e5f | ||
|
|
90fb81d1d9 | ||
|
|
3c401e7b3d | ||
|
|
dc53a3ba42 | ||
|
|
3c1ebe9f4a | ||
|
|
73c984a637 | ||
|
|
ae30cb5557 | ||
|
|
311e7a9992 | ||
|
|
2f86f95c3f | ||
|
|
f61aaf83f6 | ||
|
|
66920b4d8f | ||
|
|
038ee090b7 | ||
|
|
6a028b1883 | ||
|
|
64e5a8c099 | ||
|
|
abad7f2790 | ||
|
|
c683b47ac3 | ||
|
|
0c4e7fc178 | ||
|
|
c4fba680d1 | ||
|
|
0d1a05ecd1 | ||
|
|
eb453462c1 | ||
|
|
5a91ed01eb | ||
|
|
2fcd542b0b | ||
|
|
146619de91 | ||
|
|
41a122a266 | ||
|
|
1c0fa2ad58 | ||
|
|
a053abfba4 | ||
|
|
e5848f4731 | ||
|
|
32a18795fb | ||
|
|
6b556ca5b0 | ||
|
|
a5b5ac1ed5 | ||
|
|
1cae72c872 | ||
|
|
878bb12a72 | ||
|
|
e0249b05d2 | ||
|
|
1fa5286c87 | ||
|
|
f3f0c7d8da | ||
|
|
afb814788f | ||
|
|
efa4c6c34e | ||
|
|
f3e34e1d44 | ||
|
|
ce304f33de | ||
|
|
c42fe42787 | ||
|
|
20a7297ac4 | ||
|
|
21809731e2 | ||
|
|
d770c7d7fa | ||
|
|
89e1c3ecfa | ||
|
|
f76ae4619b | ||
|
|
2945ff1016 | ||
|
|
51e1ff4976 | ||
|
|
87677cfc85 | ||
|
|
3ee626ce3c | ||
|
|
c4426b0f07 | ||
|
|
1a5ec26392 | ||
|
|
2275e689ce | ||
|
|
10741a97ea | ||
|
|
1cc0446bc1 | ||
|
|
cec7ace28b | ||
|
|
6e4f380e36 | ||
|
|
d68e4acb50 | ||
|
|
052ebe5acf | ||
|
|
128267a236 | ||
|
|
b1365a051d | ||
|
|
3452aaf5d5 | ||
|
|
335f3dbe2f | ||
|
|
97620c4e17 | ||
|
|
75f759079a | ||
|
|
315ffed12f | ||
|
|
c347435151 | ||
|
|
183acd4196 | ||
|
|
1e40081d1f | ||
|
|
cd3e4fc8f1 | ||
|
|
e860cc9fad | ||
|
|
aa119e1413 | ||
|
|
33e4b11509 | ||
|
|
5911330f8b | ||
|
|
e0e0d1ee0b | ||
|
|
3188cb4a5a | ||
|
|
a3e6bdd8e4 | ||
|
|
ecc0fe4678 | ||
|
|
a819b9fc2a | ||
|
|
a4eccb259a | ||
|
|
6e1436f1cd | ||
|
|
9e49b9100f | ||
|
|
950c7768bc | ||
|
|
13bb9a2041 | ||
|
|
44e875618f | ||
|
|
25fbdfb43a | ||
|
|
43c4947cb9 | ||
|
|
b18a0830f3 | ||
|
|
48bf30aa2d | ||
|
|
f05fabdb79 | ||
|
|
274fec7bd0 | ||
|
|
86b7ccef93 | ||
|
|
054000fb37 | ||
|
|
76cdcc9f32 | ||
|
|
e8aa1caa4e | ||
|
|
4141f76105 |
|
|
@ -6,12 +6,13 @@ export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1
|
||||||
export HOMEBREW_NO_ENV_HINTS=1
|
export HOMEBREW_NO_ENV_HINTS=1
|
||||||
export HOMEBREW_NO_INSTALL_CLEANUP=1
|
export HOMEBREW_NO_INSTALL_CLEANUP=1
|
||||||
|
|
||||||
brew install -f --overwrite --quiet ccache pipenv googletest ffmpeg@5 "llvm@$LLVM_COMPILER_VER" glew sdl3 vulkan-headers
|
brew install -f --overwrite --quiet pipenv googletest opencv@4 ffmpeg@5 "llvm@$LLVM_COMPILER_VER" glew sdl3 vulkan-headers
|
||||||
|
brew unlink --quiet ffmpeg qtbase qtsvg qtdeclarative
|
||||||
brew link -f --quiet "llvm@$LLVM_COMPILER_VER" ffmpeg@5
|
brew link -f --quiet "llvm@$LLVM_COMPILER_VER" ffmpeg@5
|
||||||
|
|
||||||
# moltenvk based on commit for 1.3.0 release
|
# moltenvk based on commit for 1.4.0 release
|
||||||
export HOMEBREW_DEVELOPER=1 # Prevents blocking of local formulae
|
export HOMEBREW_DEVELOPER=1 # Prevents blocking of local formulae
|
||||||
wget https://raw.githubusercontent.com/Homebrew/homebrew-core/7255441cbcafabaa8950f67c7ec55ff499dbb2d3/Formula/m/molten-vk.rb
|
wget https://raw.githubusercontent.com/Homebrew/homebrew-core/ea2bec5f1f4384e188d7fc0702ab21a20a2ced08/Formula/m/molten-vk.rb
|
||||||
/opt/homebrew/bin/brew install -f --overwrite --formula --quiet ./molten-vk.rb
|
/opt/homebrew/bin/brew install -f --overwrite --formula --quiet ./molten-vk.rb
|
||||||
export HOMEBREW_DEVELOPER=0
|
export HOMEBREW_DEVELOPER=0
|
||||||
|
|
||||||
|
|
@ -27,23 +28,25 @@ export CMAKE_EXTRA_OPTS='-DLLVM_TARGETS_TO_BUILD=arm64'
|
||||||
export WORKDIR;
|
export WORKDIR;
|
||||||
WORKDIR="$(pwd)"
|
WORKDIR="$(pwd)"
|
||||||
|
|
||||||
|
# Setup ccache
|
||||||
|
if [ ! -d "$CCACHE_DIR" ]; then
|
||||||
|
mkdir -p "$CCACHE_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
# Get Qt
|
# Get Qt
|
||||||
if [ ! -d "/tmp/Qt/$QT_VER" ]; then
|
if [ ! -d "/tmp/Qt/$QT_VER" ]; then
|
||||||
mkdir -p "/tmp/Qt"
|
mkdir -p "/tmp/Qt"
|
||||||
git clone https://github.com/engnr/qt-downloader.git
|
git clone https://github.com/engnr/qt-downloader.git
|
||||||
cd qt-downloader
|
cd qt-downloader
|
||||||
git checkout f52efee0f18668c6d6de2dec0234b8c4bc54c597
|
git checkout f52efee0f18668c6d6de2dec0234b8c4bc54c597
|
||||||
# nested Qt 6.9.3 URL workaround
|
sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader
|
||||||
# sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader
|
sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader
|
||||||
# sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader
|
|
||||||
# archived Qt 6.7.3 URL workaround
|
|
||||||
sed -i '' "s/official_releases/archive/g" qt-downloader
|
|
||||||
cd "/tmp/Qt"
|
cd "/tmp/Qt"
|
||||||
"$BREW_PATH/bin/pipenv" run pip3 uninstall py7zr requests semantic_version lxml
|
"$BREW_PATH/bin/pipenv" run pip3 uninstall py7zr requests semantic_version lxml
|
||||||
"$BREW_PATH/bin/pipenv" run pip3 install py7zr requests semantic_version lxml --no-cache
|
"$BREW_PATH/bin/pipenv" run pip3 install py7zr requests semantic_version lxml --no-cache
|
||||||
mkdir -p "$QT_VER/macos" ; ln -s "macos" "$QT_VER/clang_64"
|
mkdir -p "$QT_VER/macos" ; ln -s "macos" "$QT_VER/clang_64"
|
||||||
# sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader" # Qt 6.9.3 workaround
|
sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader"
|
||||||
"$BREW_PATH/bin/pipenv" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats # -o "$QT_VER/clang_64"
|
"$BREW_PATH/bin/pipenv" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats -o "$QT_VER/clang_64"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd "$WORKDIR"
|
cd "$WORKDIR"
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,17 @@ export HOMEBREW_NO_INSTALL_CLEANUP=1
|
||||||
|
|
||||||
brew install -f --overwrite --quiet ccache pipenv "llvm@$LLVM_COMPILER_VER"
|
brew install -f --overwrite --quiet ccache pipenv "llvm@$LLVM_COMPILER_VER"
|
||||||
brew link -f --overwrite --quiet "llvm@$LLVM_COMPILER_VER"
|
brew link -f --overwrite --quiet "llvm@$LLVM_COMPILER_VER"
|
||||||
|
# shellcheck disable=SC3009
|
||||||
|
rm /usr/local/bin/{idle3.14,pip3.14,pydoc3.14,python3.14,python3.14-config} && \
|
||||||
|
rm /usr/local/bin/{idle3,pip3,pydoc3,python3,python3-config}
|
||||||
arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
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 ffmpeg@5 "llvm@$LLVM_COMPILER_VER" glew sdl3 vulkan-headers
|
arch -x86_64 /usr/local/bin/brew install -f --overwrite --quiet opencv@4 ffmpeg@5 "llvm@$LLVM_COMPILER_VER" glew sdl3 vulkan-headers
|
||||||
|
arch -x86_64 /usr/local/bin/brew unlink --quiet ffmpeg qtbase qtsvg qtdeclarative
|
||||||
arch -x86_64 /usr/local/bin/brew link -f --overwrite --quiet "llvm@$LLVM_COMPILER_VER" ffmpeg@5
|
arch -x86_64 /usr/local/bin/brew link -f --overwrite --quiet "llvm@$LLVM_COMPILER_VER" ffmpeg@5
|
||||||
|
|
||||||
# moltenvk based on commit for 1.3.0 release
|
# moltenvk based on commit for 1.4.0 release
|
||||||
export HOMEBREW_DEVELOPER=1 # Prevents blocking of local formulae
|
export HOMEBREW_DEVELOPER=1 # Prevents blocking of local formulae
|
||||||
wget https://raw.githubusercontent.com/Homebrew/homebrew-core/7255441cbcafabaa8950f67c7ec55ff499dbb2d3/Formula/m/molten-vk.rb
|
wget https://raw.githubusercontent.com/Homebrew/homebrew-core/ea2bec5f1f4384e188d7fc0702ab21a20a2ced08/Formula/m/molten-vk.rb
|
||||||
arch -x86_64 /usr/local/bin/brew install -f --overwrite --formula --quiet ./molten-vk.rb
|
arch -x86_64 /usr/local/bin/brew install -f --overwrite --formula --quiet ./molten-vk.rb
|
||||||
export HOMEBREW_DEVELOPER=0
|
export HOMEBREW_DEVELOPER=0
|
||||||
export CXX=clang++
|
export CXX=clang++
|
||||||
|
|
@ -35,16 +39,13 @@ if [ ! -d "/tmp/Qt/$QT_VER" ]; then
|
||||||
git clone https://github.com/engnr/qt-downloader.git
|
git clone https://github.com/engnr/qt-downloader.git
|
||||||
cd qt-downloader
|
cd qt-downloader
|
||||||
git checkout f52efee0f18668c6d6de2dec0234b8c4bc54c597
|
git checkout f52efee0f18668c6d6de2dec0234b8c4bc54c597
|
||||||
# nested Qt 6.9.3 URL workaround
|
sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader
|
||||||
# sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader
|
sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader
|
||||||
# sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader
|
|
||||||
# archived Qt 6.7.3 URL workaround
|
|
||||||
sed -i '' "s/official_releases/archive/g" qt-downloader
|
|
||||||
cd "/tmp/Qt"
|
cd "/tmp/Qt"
|
||||||
"/opt/homebrew/bin/pipenv" --python "/opt/homebrew/bin/python3" run pip3 install py7zr requests semantic_version lxml
|
"/opt/homebrew/bin/pipenv" --python "/opt/homebrew/bin/python3" run pip3 install py7zr requests semantic_version lxml
|
||||||
mkdir -p "$QT_VER/macos" ; ln -s "macos" "$QT_VER/clang_64"
|
mkdir -p "$QT_VER/macos" ; ln -s "macos" "$QT_VER/clang_64"
|
||||||
# sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader" # Qt 6.9.3 workaround
|
sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader"
|
||||||
"/opt/homebrew/bin/pipenv" --python "/opt/homebrew/bin/python3" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats # -o "$QT_VER/clang_64"
|
"/opt/homebrew/bin/pipenv" --python "/opt/homebrew/bin/python3" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats -o "$QT_VER/clang_64"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd "$WORKDIR"
|
cd "$WORKDIR"
|
||||||
|
|
@ -54,7 +55,8 @@ export Qt6_DIR="$WORKDIR/qt-downloader/$QT_VER/clang_64/lib/cmake/Qt$QT_VER_MAIN
|
||||||
export SDL3_DIR="$BREW_X64_PATH/opt/sdl3/lib/cmake/SDL3"
|
export SDL3_DIR="$BREW_X64_PATH/opt/sdl3/lib/cmake/SDL3"
|
||||||
|
|
||||||
export PATH="/opt/homebrew/opt/llvm@$LLVM_COMPILER_VER/bin:$WORKDIR/qt-downloader/$QT_VER/clang_64/bin:$BREW_BIN:$BREW_SBIN:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Library/Apple/usr/bin:$PATH"
|
export PATH="/opt/homebrew/opt/llvm@$LLVM_COMPILER_VER/bin:$WORKDIR/qt-downloader/$QT_VER/clang_64/bin:$BREW_BIN:$BREW_SBIN:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Library/Apple/usr/bin:$PATH"
|
||||||
export LDFLAGS="-L$BREW_X64_PATH/lib -Wl,-rpath,$BREW_X64_PATH/lib"
|
# shellcheck disable=SC2155
|
||||||
|
export LDFLAGS="-L$BREW_X64_PATH/lib -Wl,-rpath,$BREW_X64_PATH/lib,-L$(brew --prefix llvm)/lib/c++"
|
||||||
export CPPFLAGS="-I$BREW_X64_PATH/include -msse -msse2 -mcx16 -no-pie -D__MAC_OS_X_VERSION_MIN_REQUIRED=140000"
|
export CPPFLAGS="-I$BREW_X64_PATH/include -msse -msse2 -mcx16 -no-pie -D__MAC_OS_X_VERSION_MIN_REQUIRED=140000"
|
||||||
export CFLAGS="-D__MAC_OS_X_VERSION_MIN_REQUIRED=140000"
|
export CFLAGS="-D__MAC_OS_X_VERSION_MIN_REQUIRED=140000"
|
||||||
export LIBRARY_PATH="$BREW_X64_PATH/opt/llvm@$LLVM_COMPILER_VER/lib:$BREW_X64_PATH/lib"
|
export LIBRARY_PATH="$BREW_X64_PATH/opt/llvm@$LLVM_COMPILER_VER/lib:$BREW_X64_PATH/lib"
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ if [ "$DEPLOY_APPIMAGE" = "true" ]; then
|
||||||
curl -fsSLo linuxdeploy-plugin-checkrt.sh https://github.com/darealshinji/linuxdeploy-plugin-checkrt/releases/download/continuous/linuxdeploy-plugin-checkrt.sh
|
curl -fsSLo linuxdeploy-plugin-checkrt.sh https://github.com/darealshinji/linuxdeploy-plugin-checkrt/releases/download/continuous/linuxdeploy-plugin-checkrt.sh
|
||||||
chmod +x ./linuxdeploy-plugin-checkrt.sh
|
chmod +x ./linuxdeploy-plugin-checkrt.sh
|
||||||
|
|
||||||
export EXTRA_PLATFORM_PLUGINS="libqwayland-egl.so;libqwayland-generic.so"
|
export EXTRA_PLATFORM_PLUGINS="libqwayland.so"
|
||||||
export EXTRA_QT_PLUGINS="svg;wayland-decoration-client;wayland-graphics-integration-client;wayland-shell-integration;waylandcompositor"
|
export EXTRA_QT_PLUGINS="svg;wayland-decoration-client;wayland-graphics-integration-client;wayland-shell-integration;waylandcompositor"
|
||||||
|
|
||||||
APPIMAGE_EXTRACT_AND_RUN=1 linuxdeploy --appdir AppDir --plugin qt --plugin checkrt
|
APPIMAGE_EXTRACT_AND_RUN=1 linuxdeploy --appdir AppDir --plugin qt --plugin checkrt
|
||||||
|
|
@ -32,6 +32,25 @@ if [ "$DEPLOY_APPIMAGE" = "true" ]; then
|
||||||
# Remove git directory containing local commit history file
|
# Remove git directory containing local commit history file
|
||||||
rm -rf ./AppDir/usr/share/rpcs3/git
|
rm -rf ./AppDir/usr/share/rpcs3/git
|
||||||
|
|
||||||
|
# Download translations
|
||||||
|
mkdir -p "./AppDir/usr/translations"
|
||||||
|
ZIP_URL=$(curl -fsSL "https://api.github.com/repos/RPCS3/rpcs3_translations/releases/latest" \
|
||||||
|
| grep "browser_download_url" \
|
||||||
|
| grep "RPCS3-languages.zip" \
|
||||||
|
| cut -d '"' -f 4)
|
||||||
|
if [ -z "$ZIP_URL" ]; then
|
||||||
|
echo "Failed to find RPCS3-languages.zip in the latest release. Continuing without translations."
|
||||||
|
else
|
||||||
|
echo "Downloading translations from: $ZIP_URL"
|
||||||
|
curl -L -o translations.zip "$ZIP_URL" || {
|
||||||
|
echo "Failed to download translations.zip. Continuing without translations."
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
unzip -o translations.zip -d "./AppDir/usr/translations" >/dev/null 2>&1 || \
|
||||||
|
echo "Failed to extract translations.zip. Continuing without translations."
|
||||||
|
rm -f translations.zip
|
||||||
|
fi
|
||||||
|
|
||||||
curl -fsSLo /uruntime "https://github.com/VHSgunzo/uruntime/releases/download/v0.3.4/uruntime-appimage-dwarfs-$CPU_ARCH"
|
curl -fsSLo /uruntime "https://github.com/VHSgunzo/uruntime/releases/download/v0.3.4/uruntime-appimage-dwarfs-$CPU_ARCH"
|
||||||
chmod +x /uruntime
|
chmod +x /uruntime
|
||||||
/uruntime --appimage-mkdwarfs -f --set-owner 0 --set-group 0 --no-history --no-create-timestamp \
|
/uruntime --appimage-mkdwarfs -f --set-owner 0 --set-group 0 --no-history --no-create-timestamp \
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ cd bin
|
||||||
mkdir "rpcs3.app/Contents/lib/" || true
|
mkdir "rpcs3.app/Contents/lib/" || true
|
||||||
|
|
||||||
cp "$(realpath /opt/homebrew/opt/llvm@$LLVM_COMPILER_VER/lib/c++/libc++abi.1.0.dylib)" "rpcs3.app/Contents/Frameworks/libc++abi.1.dylib"
|
cp "$(realpath /opt/homebrew/opt/llvm@$LLVM_COMPILER_VER/lib/c++/libc++abi.1.0.dylib)" "rpcs3.app/Contents/Frameworks/libc++abi.1.dylib"
|
||||||
|
cp "$(realpath /opt/homebrew/opt/gcc/lib/gcc/current/libgcc_s.1.1.dylib)" "rpcs3.app/Contents/Frameworks/libgcc_s.1.1.dylib"
|
||||||
cp "$(realpath /opt/homebrew/lib/libsharpyuv.0.dylib)" "rpcs3.app/Contents/lib/libsharpyuv.0.dylib"
|
cp "$(realpath /opt/homebrew/lib/libsharpyuv.0.dylib)" "rpcs3.app/Contents/lib/libsharpyuv.0.dylib"
|
||||||
cp "$(realpath /opt/homebrew/lib/libintl.8.dylib)" "rpcs3.app/Contents/lib/libintl.8.dylib"
|
cp "$(realpath /opt/homebrew/lib/libintl.8.dylib)" "rpcs3.app/Contents/lib/libintl.8.dylib"
|
||||||
|
|
||||||
|
|
@ -31,11 +32,28 @@ rm -rf "rpcs3.app/Contents/Frameworks/QtPdf.framework" \
|
||||||
|
|
||||||
../../.ci/optimize-mac.sh rpcs3.app
|
../../.ci/optimize-mac.sh rpcs3.app
|
||||||
|
|
||||||
|
# Download translations
|
||||||
|
mkdir -p "rpcs3.app/Contents/translations"
|
||||||
|
ZIP_URL=$(curl -fsSL "https://api.github.com/repos/RPCS3/rpcs3_translations/releases/latest" \
|
||||||
|
| grep "browser_download_url" \
|
||||||
|
| grep "RPCS3-languages.zip" \
|
||||||
|
| cut -d '"' -f 4)
|
||||||
|
if [ -z "$ZIP_URL" ]; then
|
||||||
|
echo "Failed to find RPCS3-languages.zip in the latest release. Continuing without translations."
|
||||||
|
else
|
||||||
|
echo "Downloading translations from: $ZIP_URL"
|
||||||
|
curl -L -o translations.zip "$ZIP_URL" || {
|
||||||
|
echo "Failed to download translations.zip. Continuing without translations."
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
unzip -o translations.zip -d "rpcs3.app/Contents/translations" >/dev/null 2>&1 || \
|
||||||
|
echo "Failed to extract translations.zip. Continuing without translations."
|
||||||
|
rm -f translations.zip
|
||||||
|
fi
|
||||||
|
|
||||||
# Hack
|
# Hack
|
||||||
install_name_tool \
|
install_name_tool -delete_rpath /opt/homebrew/lib RPCS3.app/Contents/MacOS/rpcs3 || echo "Hack for deleting rpath /opt/homebrew/lib not needed"
|
||||||
-delete_rpath /opt/homebrew/lib \
|
install_name_tool -delete_rpath /opt/homebrew/opt/llvm@$LLVM_COMPILER_VER/lib RPCS3.app/Contents/MacOS/rpcs3 || echo "Hack for deleting rpath /opt/homebrew/opt/llvm@$LLVM_COMPILER_VER/lib not needed"
|
||||||
-delete_rpath /opt/homebrew/opt/llvm@$LLVM_COMPILER_VER/lib RPCS3.app/Contents/MacOS/rpcs3
|
|
||||||
#-delete_rpath /opt/homebrew1/Cellar/sdl3/3.2.8/lib
|
|
||||||
|
|
||||||
# Need to do this rename hack due to case insensitive filesystem
|
# Need to do this rename hack due to case insensitive filesystem
|
||||||
mv rpcs3.app RPCS3_.app
|
mv rpcs3.app RPCS3_.app
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,9 @@ echo "AVVER=$AVVER" >> ../.ci/ci-vars.env
|
||||||
cd bin
|
cd bin
|
||||||
mkdir "rpcs3.app/Contents/lib/"
|
mkdir "rpcs3.app/Contents/lib/"
|
||||||
|
|
||||||
cp "/usr/local/opt/llvm@$LLVM_COMPILER_VER/lib/c++/libc++abi.1.0.dylib" "rpcs3.app/Contents/lib/libc++abi.1.dylib"
|
cp "$(realpath /usr/local/opt/llvm@$LLVM_COMPILER_VER/lib/c++/libc++abi.1.0.dylib)" "rpcs3.app/Contents/Frameworks/libc++abi.1.dylib"
|
||||||
|
cp "$(realpath /usr/local/opt/llvm@$LLVM_COMPILER_VER/lib/unwind/libunwind.1.dylib)" "rpcs3.app/Contents/Frameworks/libunwind.1.dylib"
|
||||||
|
cp "$(realpath /usr/local/opt/gcc/lib/gcc/current/libgcc_s.1.1.dylib)" "rpcs3.app/Contents/Frameworks/libgcc_s.1.1.dylib"
|
||||||
cp "$(realpath /usr/local/lib/libsharpyuv.0.dylib)" "rpcs3.app/Contents/lib/libsharpyuv.0.dylib"
|
cp "$(realpath /usr/local/lib/libsharpyuv.0.dylib)" "rpcs3.app/Contents/lib/libsharpyuv.0.dylib"
|
||||||
cp "$(realpath /usr/local/lib/libintl.8.dylib)" "rpcs3.app/Contents/lib/libintl.8.dylib"
|
cp "$(realpath /usr/local/lib/libintl.8.dylib)" "rpcs3.app/Contents/lib/libintl.8.dylib"
|
||||||
|
|
||||||
|
|
@ -31,6 +33,25 @@ rm -rf "rpcs3.app/Contents/Frameworks/QtPdf.framework" \
|
||||||
|
|
||||||
../../.ci/optimize-mac.sh rpcs3.app
|
../../.ci/optimize-mac.sh rpcs3.app
|
||||||
|
|
||||||
|
# Download translations
|
||||||
|
mkdir -p "rpcs3.app/Contents/translations"
|
||||||
|
ZIP_URL=$(curl -fsSL "https://api.github.com/repos/RPCS3/rpcs3_translations/releases/latest" \
|
||||||
|
| grep "browser_download_url" \
|
||||||
|
| grep "RPCS3-languages.zip" \
|
||||||
|
| cut -d '"' -f 4)
|
||||||
|
if [ -z "$ZIP_URL" ]; then
|
||||||
|
echo "Failed to find RPCS3-languages.zip in the latest release. Continuing without translations."
|
||||||
|
else
|
||||||
|
echo "Downloading translations from: $ZIP_URL"
|
||||||
|
curl -L -o translations.zip "$ZIP_URL" || {
|
||||||
|
echo "Failed to download translations.zip. Continuing without translations."
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
unzip -o translations.zip -d "rpcs3.app/Contents/translations" >/dev/null 2>&1 || \
|
||||||
|
echo "Failed to extract translations.zip. Continuing without translations."
|
||||||
|
rm -f translations.zip
|
||||||
|
fi
|
||||||
|
|
||||||
# Need to do this rename hack due to case insensitive filesystem
|
# Need to do this rename hack due to case insensitive filesystem
|
||||||
mv rpcs3.app RPCS3_.app
|
mv rpcs3.app RPCS3_.app
|
||||||
mv RPCS3_.app RPCS3.app
|
mv RPCS3_.app RPCS3.app
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,25 @@ mkdir ./bin/config/input_configs
|
||||||
curl -fsSL 'https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt' 1> ./bin/config/input_configs/gamecontrollerdb.txt
|
curl -fsSL 'https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt' 1> ./bin/config/input_configs/gamecontrollerdb.txt
|
||||||
curl -fsSL 'https://rpcs3.net/compatibility?api=v1&export' | iconv -t UTF-8 1> ./bin/GuiConfigs/compat_database.dat
|
curl -fsSL 'https://rpcs3.net/compatibility?api=v1&export' | iconv -t UTF-8 1> ./bin/GuiConfigs/compat_database.dat
|
||||||
|
|
||||||
|
# Download translations
|
||||||
|
mkdir -p ./bin/share/qt6/translations
|
||||||
|
ZIP_URL=$(curl -fsSL "https://api.github.com/repos/RPCS3/rpcs3_translations/releases/latest" \
|
||||||
|
| grep "browser_download_url" \
|
||||||
|
| grep "RPCS3-languages.zip" \
|
||||||
|
| cut -d '"' -f 4)
|
||||||
|
if [ -z "$ZIP_URL" ]; then
|
||||||
|
echo "Failed to find RPCS3-languages.zip in the latest release. Continuing without translations."
|
||||||
|
else
|
||||||
|
echo "Downloading translations from: $ZIP_URL"
|
||||||
|
curl -L -o translations.zip "$ZIP_URL" || {
|
||||||
|
echo "Failed to download translations.zip. Continuing without translations."
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
unzip -o translations.zip -d "./bin/share/qt6/translations" >/dev/null 2>&1 || \
|
||||||
|
echo "Failed to extract translations.zip. Continuing without translations."
|
||||||
|
rm -f translations.zip
|
||||||
|
fi
|
||||||
|
|
||||||
# Package artifacts
|
# Package artifacts
|
||||||
7z a -m0=LZMA2 -mx9 "$BUILD" ./bin/*
|
7z a -m0=LZMA2 -mx9 "$BUILD" ./bin/*
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,25 @@ mkdir ./bin/config/input_configs
|
||||||
curl -fsSL 'https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt' 1> ./bin/config/input_configs/gamecontrollerdb.txt
|
curl -fsSL 'https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt' 1> ./bin/config/input_configs/gamecontrollerdb.txt
|
||||||
curl -fsSL 'https://rpcs3.net/compatibility?api=v1&export' | iconv -t UTF-8 1> ./bin/GuiConfigs/compat_database.dat
|
curl -fsSL 'https://rpcs3.net/compatibility?api=v1&export' | iconv -t UTF-8 1> ./bin/GuiConfigs/compat_database.dat
|
||||||
|
|
||||||
|
# Download translations
|
||||||
|
mkdir -p ./bin/qt6/translations
|
||||||
|
ZIP_URL=$(curl -fsSL "https://api.github.com/repos/RPCS3/rpcs3_translations/releases/latest" \
|
||||||
|
| grep "browser_download_url" \
|
||||||
|
| grep "RPCS3-languages.zip" \
|
||||||
|
| cut -d '"' -f 4)
|
||||||
|
if [ -z "$ZIP_URL" ]; then
|
||||||
|
echo "Failed to find RPCS3-languages.zip in the latest release. Continuing without translations."
|
||||||
|
else
|
||||||
|
echo "Downloading translations from: $ZIP_URL"
|
||||||
|
curl -L -o translations.zip "$ZIP_URL" || {
|
||||||
|
echo "Failed to download translations.zip. Continuing without translations."
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
unzip -o translations.zip -d "./bin/qt6/translations" >/dev/null 2>&1 || \
|
||||||
|
echo "Failed to extract translations.zip. Continuing without translations."
|
||||||
|
rm -f translations.zip
|
||||||
|
fi
|
||||||
|
|
||||||
# Download SSL certificate (not needed with CURLSSLOPT_NATIVE_CA)
|
# Download SSL certificate (not needed with CURLSSLOPT_NATIVE_CA)
|
||||||
#curl -fsSL 'https://curl.haxx.se/ca/cacert.pem' 1> ./bin/cacert.pem
|
#curl -fsSL 'https://curl.haxx.se/ca/cacert.pem' 1> ./bin/cacert.pem
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ pkg info # debug
|
||||||
pkg install "llvm$LLVM_COMPILER_VER"
|
pkg install "llvm$LLVM_COMPILER_VER"
|
||||||
|
|
||||||
# Mandatory dependencies (qtX-base is pulled via qtX-multimedia)
|
# Mandatory dependencies (qtX-base is pulled via qtX-multimedia)
|
||||||
pkg install git ccache cmake ninja "qt$QT_VER_MAIN-multimedia" "qt$QT_VER_MAIN-svg" glew openal-soft ffmpeg
|
pkg install git ccache cmake ninja "qt$QT_VER_MAIN-multimedia" "qt$QT_VER_MAIN-svg" glew openal-soft ffmpeg pcre2
|
||||||
|
|
||||||
# Optional dependencies (libevdev is pulled by qtX-base)
|
# Optional dependencies (libevdev is pulled by qtX-base)
|
||||||
pkg install pkgconf alsa-lib pulseaudio sdl3 evdev-proto vulkan-headers vulkan-loader opencv
|
pkg install pkgconf alsa-lib pulseaudio sdl3 evdev-proto vulkan-headers vulkan-loader opencv
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ QT_URL_VER=$(echo "$QT_VER" | sed "s/\.//g")
|
||||||
QT_VER_MSVC_UP=$(echo "${QT_VER_MSVC}" | tr '[:lower:]' '[:upper:]')
|
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.qt${QT_VER_MAIN}.${QT_URL_VER}."
|
||||||
QT_PREFIX_2="win64_${QT_VER_MSVC}_64/${QT_VER}-0-${QT_DATE}"
|
QT_PREFIX_2="win64_${QT_VER_MSVC}_64/${QT_VER}-0-${QT_DATE}"
|
||||||
QT_SUFFIX="-Windows-Windows_11_23H2-${QT_VER_MSVC_UP}-Windows-Windows_11_23H2-X86_64.7z"
|
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}"
|
QT_BASE_URL="${QT_HOST}${QT_PREFIX}${QT_PREFIX_2}qtbase${QT_SUFFIX}"
|
||||||
QT_DECL_URL="${QT_HOST}${QT_PREFIX}${QT_PREFIX_2}qtdeclarative${QT_SUFFIX}"
|
QT_DECL_URL="${QT_HOST}${QT_PREFIX}${QT_PREFIX_2}qtdeclarative${QT_SUFFIX}"
|
||||||
QT_TOOL_URL="${QT_HOST}${QT_PREFIX}${QT_PREFIX_2}qttools${QT_SUFFIX}"
|
QT_TOOL_URL="${QT_HOST}${QT_PREFIX}${QT_PREFIX_2}qttools${QT_SUFFIX}"
|
||||||
|
|
|
||||||
16
.github/workflows/rpcs3.yml
vendored
16
.github/workflows/rpcs3.yml
vendored
|
|
@ -30,23 +30,23 @@ jobs:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: ubuntu-24.04
|
- os: ubuntu-24.04
|
||||||
docker_img: "rpcs3/rpcs3-ci-jammy:1.6"
|
docker_img: "rpcs3/rpcs3-ci-jammy:1.7"
|
||||||
build_sh: "/rpcs3/.ci/build-linux.sh"
|
build_sh: "/rpcs3/.ci/build-linux.sh"
|
||||||
compiler: clang
|
compiler: clang
|
||||||
UPLOAD_COMMIT_HASH: d812f1254a1157c80fd402f94446310560f54e5f
|
UPLOAD_COMMIT_HASH: d812f1254a1157c80fd402f94446310560f54e5f
|
||||||
UPLOAD_REPO_FULL_NAME: "rpcs3/rpcs3-binaries-linux"
|
UPLOAD_REPO_FULL_NAME: "rpcs3/rpcs3-binaries-linux"
|
||||||
- os: ubuntu-24.04
|
- os: ubuntu-24.04
|
||||||
docker_img: "rpcs3/rpcs3-ci-jammy:1.6"
|
docker_img: "rpcs3/rpcs3-ci-jammy:1.7"
|
||||||
build_sh: "/rpcs3/.ci/build-linux.sh"
|
build_sh: "/rpcs3/.ci/build-linux.sh"
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
- os: ubuntu-24.04-arm
|
- os: ubuntu-24.04-arm
|
||||||
docker_img: "rpcs3/rpcs3-ci-jammy-aarch64:1.6"
|
docker_img: "rpcs3/rpcs3-ci-jammy-aarch64:1.7"
|
||||||
build_sh: "/rpcs3/.ci/build-linux-aarch64.sh"
|
build_sh: "/rpcs3/.ci/build-linux-aarch64.sh"
|
||||||
compiler: clang
|
compiler: clang
|
||||||
UPLOAD_COMMIT_HASH: a1d35836e8d45bfc6f63c26f0a3e5d46ef622fe1
|
UPLOAD_COMMIT_HASH: a1d35836e8d45bfc6f63c26f0a3e5d46ef622fe1
|
||||||
UPLOAD_REPO_FULL_NAME: "rpcs3/rpcs3-binaries-linux-arm64"
|
UPLOAD_REPO_FULL_NAME: "rpcs3/rpcs3-binaries-linux-arm64"
|
||||||
- os: ubuntu-24.04-arm
|
- os: ubuntu-24.04-arm
|
||||||
docker_img: "rpcs3/rpcs3-ci-jammy-aarch64:1.6"
|
docker_img: "rpcs3/rpcs3-ci-jammy-aarch64:1.7"
|
||||||
build_sh: "/rpcs3/.ci/build-linux-aarch64.sh"
|
build_sh: "/rpcs3/.ci/build-linux-aarch64.sh"
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
name: RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }}
|
name: RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }}
|
||||||
|
|
@ -134,9 +134,9 @@ jobs:
|
||||||
runs-on: macos-14
|
runs-on: macos-14
|
||||||
env:
|
env:
|
||||||
CCACHE_DIR: /tmp/ccache_dir
|
CCACHE_DIR: /tmp/ccache_dir
|
||||||
QT_VER: '6.7.3'
|
QT_VER: '6.10.1'
|
||||||
QT_VER_MAIN: '6'
|
QT_VER_MAIN: '6'
|
||||||
LLVM_COMPILER_VER: '19'
|
LLVM_COMPILER_VER: '21'
|
||||||
RELEASE_MESSAGE: ../GitHubReleaseMessage.txt
|
RELEASE_MESSAGE: ../GitHubReleaseMessage.txt
|
||||||
UPLOAD_COMMIT_HASH: ${{ matrix.UPLOAD_COMMIT_HASH }}
|
UPLOAD_COMMIT_HASH: ${{ matrix.UPLOAD_COMMIT_HASH }}
|
||||||
UPLOAD_REPO_FULL_NAME: ${{ matrix.UPLOAD_REPO_FULL_NAME }}
|
UPLOAD_REPO_FULL_NAME: ${{ matrix.UPLOAD_REPO_FULL_NAME }}
|
||||||
|
|
@ -212,9 +212,9 @@ jobs:
|
||||||
env:
|
env:
|
||||||
COMPILER: msvc
|
COMPILER: msvc
|
||||||
QT_VER_MAIN: '6'
|
QT_VER_MAIN: '6'
|
||||||
QT_VER: '6.9.3'
|
QT_VER: '6.10.1'
|
||||||
QT_VER_MSVC: 'msvc2022'
|
QT_VER_MSVC: 'msvc2022'
|
||||||
QT_DATE: '202509261208'
|
QT_DATE: '202511161843'
|
||||||
LLVM_VER: '19.1.7'
|
LLVM_VER: '19.1.7'
|
||||||
VULKAN_VER: '1.3.268.0'
|
VULKAN_VER: '1.3.268.0'
|
||||||
VULKAN_SDK_SHA: '8459ef49bd06b697115ddd3d97c9aec729e849cd775f5be70897718a9b3b9db5'
|
VULKAN_SDK_SHA: '8459ef49bd06b697115ddd3d97c9aec729e849cd775f5be70897718a9b3b9db5'
|
||||||
|
|
|
||||||
2
.gitmodules
vendored
2
.gitmodules
vendored
|
|
@ -21,7 +21,7 @@
|
||||||
ignore = dirty
|
ignore = dirty
|
||||||
[submodule "3rdparty/hidapi"]
|
[submodule "3rdparty/hidapi"]
|
||||||
path = 3rdparty/hidapi/hidapi
|
path = 3rdparty/hidapi/hidapi
|
||||||
url = ../../RPCS3/hidapi.git
|
url = ../../libusb/hidapi.git
|
||||||
branch = master
|
branch = master
|
||||||
ignore = dirty
|
ignore = dirty
|
||||||
[submodule "3rdparty/pugixml"]
|
[submodule "3rdparty/pugixml"]
|
||||||
|
|
|
||||||
2
3rdparty/CMakeLists.txt
vendored
2
3rdparty/CMakeLists.txt
vendored
|
|
@ -278,7 +278,7 @@ if(USE_FAUDIO)
|
||||||
target_compile_definitions(FAudio-static INTERFACE -DHAVE_FAUDIO)
|
target_compile_definitions(FAudio-static INTERFACE -DHAVE_FAUDIO)
|
||||||
set(FAUDIO_TARGET FAudio-static)
|
set(FAUDIO_TARGET FAudio-static)
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR
|
message(WARNING
|
||||||
"-- RPCS3: 3rdparty FAudio requires SDL 3.2.0 or newer. Since a valid SDL3"
|
"-- RPCS3: 3rdparty FAudio requires SDL 3.2.0 or newer. Since a valid SDL3"
|
||||||
">=3.2.0 version cannot be found, building with FAudio will be skipped.")
|
">=3.2.0 version cannot be found, building with FAudio will be skipped.")
|
||||||
set(USE_FAUDIO OFF CACHE BOOL "Disabled FAudio with SDL < 3.2.0" FORCE)
|
set(USE_FAUDIO OFF CACHE BOOL "Disabled FAudio with SDL < 3.2.0" FORCE)
|
||||||
|
|
|
||||||
2
3rdparty/FAudio
vendored
2
3rdparty/FAudio
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit 8a87fdc9242a7b507cf5c96c539334a1760c1ec7
|
Subproject commit 4ea8afea6ba857c24e40877f487d000d559b196d
|
||||||
2
3rdparty/MoltenVK/CMakeLists.txt
vendored
2
3rdparty/MoltenVK/CMakeLists.txt
vendored
|
|
@ -3,7 +3,7 @@ include(ExternalProject)
|
||||||
|
|
||||||
ExternalProject_Add(moltenvk
|
ExternalProject_Add(moltenvk
|
||||||
GIT_REPOSITORY https://github.com/KhronosGroup/MoltenVK.git
|
GIT_REPOSITORY https://github.com/KhronosGroup/MoltenVK.git
|
||||||
GIT_TAG 49b97f2
|
GIT_TAG 4588705
|
||||||
BUILD_IN_SOURCE 1
|
BUILD_IN_SOURCE 1
|
||||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK
|
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK
|
||||||
CONFIGURE_COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK/fetchDependencies" --macos
|
CONFIGURE_COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK/fetchDependencies" --macos
|
||||||
|
|
|
||||||
2
3rdparty/OpenAL/openal-soft
vendored
2
3rdparty/OpenAL/openal-soft
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit dc7d7054a5b4f3bec1dc23a42fd616a0847af948
|
Subproject commit 0e5e98e4ac8adae92e4f7653dd6eee17aa9c8791
|
||||||
4
3rdparty/OpenAL/openal-soft.vcxproj
vendored
4
3rdparty/OpenAL/openal-soft.vcxproj
vendored
|
|
@ -49,11 +49,11 @@
|
||||||
<PropertyGroup Label="UserMacros">
|
<PropertyGroup Label="UserMacros">
|
||||||
<CmakeReleaseCLI>call vsdevcmd.bat -arch=amd64
|
<CmakeReleaseCLI>call vsdevcmd.bat -arch=amd64
|
||||||
cd "$(SolutionDir)build\tmp\$(ProjectName)-$(Configuration)-$(Platform)"
|
cd "$(SolutionDir)build\tmp\$(ProjectName)-$(Configuration)-$(Platform)"
|
||||||
cmake -G Ninja -DCMAKE_CXX_COMPILER="cl.exe" -DCMAKE_C_COMPILER="cl.exe" -DCMAKE_BUILD_TYPE="Release" -DCMAKE_INSTALL_PREFIX="./Release" -DCMAKE_SYSTEM_VERSION=10.0 -DLIBTYPE=STATIC -DFORCE_STATIC_VCRT=true -DALSOFT_UTILS=false -DALSOFT_EXAMPLES=false -DALSOFT_INSTALL=false -DALSOFT_INSTALL_CONFIG=false -DALSOFT_INSTALL_HRTF_DATA=false -DALSOFT_INSTALL_AMBDEC_PRESETS=false -DALSOFT_INSTALL_EXAMPLES=false -DALSOFT_INSTALL_UTILS=false "$(SolutionDir)3rdparty\OpenAL\openal-soft"
|
cmake -G Ninja -DCMAKE_CXX_COMPILER="cl.exe" -DCMAKE_C_COMPILER="cl.exe" -DCMAKE_BUILD_TYPE="Release" -DCMAKE_INSTALL_PREFIX="./Release" -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded -DCMAKE_SYSTEM_VERSION=10.0 -DLIBTYPE=STATIC -DFORCE_STATIC_VCRT=true -DALSOFT_UTILS=false -DALSOFT_EXAMPLES=false -DALSOFT_INSTALL=false -DALSOFT_INSTALL_CONFIG=false -DALSOFT_INSTALL_HRTF_DATA=false -DALSOFT_INSTALL_AMBDEC_PRESETS=false -DALSOFT_INSTALL_EXAMPLES=false -DALSOFT_INSTALL_UTILS=false "$(SolutionDir)3rdparty\OpenAL\openal-soft"
|
||||||
</CmakeReleaseCLI>
|
</CmakeReleaseCLI>
|
||||||
<CmakeDebugCLI>call vsdevcmd.bat -arch=amd64
|
<CmakeDebugCLI>call vsdevcmd.bat -arch=amd64
|
||||||
cd "$(SolutionDir)build\tmp\$(ProjectName)-$(Configuration)-$(Platform)"
|
cd "$(SolutionDir)build\tmp\$(ProjectName)-$(Configuration)-$(Platform)"
|
||||||
cmake -G Ninja -DCMAKE_CXX_COMPILER="cl.exe" -DCMAKE_C_COMPILER="cl.exe" -DCMAKE_BUILD_TYPE="Debug" -DCMAKE_INSTALL_PREFIX="./Debug" -DCMAKE_SYSTEM_VERSION=10.0 -DLIBTYPE=STATIC -DALSOFT_UTILS=false -DALSOFT_EXAMPLES=false -DALSOFT_INSTALL=false -DALSOFT_INSTALL_CONFIG=false -DALSOFT_INSTALL_HRTF_DATA=false -DALSOFT_INSTALL_AMBDEC_PRESETS=false -DALSOFT_INSTALL_EXAMPLES=false -DALSOFT_INSTALL_UTILS=false "$(SolutionDir)3rdparty\OpenAL\openal-soft"
|
cmake -G Ninja -DCMAKE_CXX_COMPILER="cl.exe" -DCMAKE_C_COMPILER="cl.exe" -DCMAKE_BUILD_TYPE="Debug" -DCMAKE_INSTALL_PREFIX="./Debug" -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDebug -DCMAKE_SYSTEM_VERSION=10.0 -DLIBTYPE=STATIC -DALSOFT_UTILS=false -DALSOFT_EXAMPLES=false -DALSOFT_INSTALL=false -DALSOFT_INSTALL_CONFIG=false -DALSOFT_INSTALL_HRTF_DATA=false -DALSOFT_INSTALL_AMBDEC_PRESETS=false -DALSOFT_INSTALL_EXAMPLES=false -DALSOFT_INSTALL_UTILS=false "$(SolutionDir)3rdparty\OpenAL\openal-soft"
|
||||||
</CmakeDebugCLI>
|
</CmakeDebugCLI>
|
||||||
<CmakeCopyCLI>
|
<CmakeCopyCLI>
|
||||||
echo Copying..
|
echo Copying..
|
||||||
|
|
|
||||||
2
3rdparty/curl/curl
vendored
2
3rdparty/curl/curl
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit 11b991232fbcaa88e2b1faecac224416b0001e35
|
Subproject commit 400fffa90f30c7a2dc762fa33009d24851bd2016
|
||||||
17
3rdparty/curl/libcurl.vcxproj
vendored
17
3rdparty/curl/libcurl.vcxproj
vendored
|
|
@ -80,10 +80,12 @@
|
||||||
<ClCompile Include="curl\lib\cshutdn.c" />
|
<ClCompile Include="curl\lib\cshutdn.c" />
|
||||||
<ClCompile Include="curl\lib\curlx\base64.c" />
|
<ClCompile Include="curl\lib\curlx\base64.c" />
|
||||||
<ClCompile Include="curl\lib\curlx\dynbuf.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_ntop.c" />
|
||||||
<ClCompile Include="curl\lib\curlx\inet_pton.c" />
|
<ClCompile Include="curl\lib\curlx\inet_pton.c" />
|
||||||
<ClCompile Include="curl\lib\curlx\multibyte.c" />
|
<ClCompile Include="curl\lib\curlx\multibyte.c" />
|
||||||
<ClCompile Include="curl\lib\curlx\nonblock.c" />
|
<ClCompile Include="curl\lib\curlx\nonblock.c" />
|
||||||
|
<ClCompile Include="curl\lib\curlx\strerr.c" />
|
||||||
<ClCompile Include="curl\lib\curlx\strparse.c" />
|
<ClCompile Include="curl\lib\curlx\strparse.c" />
|
||||||
<ClCompile Include="curl\lib\curlx\timediff.c" />
|
<ClCompile Include="curl\lib\curlx\timediff.c" />
|
||||||
<ClCompile Include="curl\lib\curlx\timeval.c" />
|
<ClCompile Include="curl\lib\curlx\timeval.c" />
|
||||||
|
|
@ -92,9 +94,9 @@
|
||||||
<ClCompile Include="curl\lib\curlx\warnless.c" />
|
<ClCompile Include="curl\lib\curlx\warnless.c" />
|
||||||
<ClCompile Include="curl\lib\curlx\winapi.c" />
|
<ClCompile Include="curl\lib\curlx\winapi.c" />
|
||||||
<ClCompile Include="curl\lib\curl_addrinfo.c" />
|
<ClCompile Include="curl\lib\curl_addrinfo.c" />
|
||||||
<ClCompile Include="curl\lib\curl_des.c" />
|
|
||||||
<ClCompile Include="curl\lib\curl_endian.c" />
|
<ClCompile Include="curl\lib\curl_endian.c" />
|
||||||
<ClCompile Include="curl\lib\curl_fnmatch.c" />
|
<ClCompile Include="curl\lib\curl_fnmatch.c" />
|
||||||
|
<ClCompile Include="curl\lib\curl_fopen.c" />
|
||||||
<ClCompile Include="curl\lib\curl_gethostname.c" />
|
<ClCompile Include="curl\lib\curl_gethostname.c" />
|
||||||
<ClCompile Include="curl\lib\curl_get_line.c" />
|
<ClCompile Include="curl\lib\curl_get_line.c" />
|
||||||
<ClCompile Include="curl\lib\curl_gssapi.c" />
|
<ClCompile Include="curl\lib\curl_gssapi.c" />
|
||||||
|
|
@ -120,7 +122,6 @@
|
||||||
<ClCompile Include="curl\lib\fake_addrinfo.c" />
|
<ClCompile Include="curl\lib\fake_addrinfo.c" />
|
||||||
<ClCompile Include="curl\lib\file.c" />
|
<ClCompile Include="curl\lib\file.c" />
|
||||||
<ClCompile Include="curl\lib\fileinfo.c" />
|
<ClCompile Include="curl\lib\fileinfo.c" />
|
||||||
<ClCompile Include="curl\lib\fopen.c" />
|
|
||||||
<ClCompile Include="curl\lib\formdata.c" />
|
<ClCompile Include="curl\lib\formdata.c" />
|
||||||
<ClCompile Include="curl\lib\ftp.c" />
|
<ClCompile Include="curl\lib\ftp.c" />
|
||||||
<ClCompile Include="curl\lib\ftplistparser.c" />
|
<ClCompile Include="curl\lib\ftplistparser.c" />
|
||||||
|
|
@ -147,7 +148,6 @@
|
||||||
<ClCompile Include="curl\lib\idn.c" />
|
<ClCompile Include="curl\lib\idn.c" />
|
||||||
<ClCompile Include="curl\lib\if2ip.c" />
|
<ClCompile Include="curl\lib\if2ip.c" />
|
||||||
<ClCompile Include="curl\lib\imap.c" />
|
<ClCompile Include="curl\lib\imap.c" />
|
||||||
<ClCompile Include="curl\lib\krb5.c" />
|
|
||||||
<ClCompile Include="curl\lib\ldap.c" />
|
<ClCompile Include="curl\lib\ldap.c" />
|
||||||
<ClCompile Include="curl\lib\llist.c" />
|
<ClCompile Include="curl\lib\llist.c" />
|
||||||
<ClCompile Include="curl\lib\macos.c" />
|
<ClCompile Include="curl\lib\macos.c" />
|
||||||
|
|
@ -159,6 +159,7 @@
|
||||||
<ClCompile Include="curl\lib\mqtt.c" />
|
<ClCompile Include="curl\lib\mqtt.c" />
|
||||||
<ClCompile Include="curl\lib\multi.c" />
|
<ClCompile Include="curl\lib\multi.c" />
|
||||||
<ClCompile Include="curl\lib\multi_ev.c" />
|
<ClCompile Include="curl\lib\multi_ev.c" />
|
||||||
|
<ClCompile Include="curl\lib\multi_ntfy.c" />
|
||||||
<ClCompile Include="curl\lib\netrc.c" />
|
<ClCompile Include="curl\lib\netrc.c" />
|
||||||
<ClCompile Include="curl\lib\noproxy.c" />
|
<ClCompile Include="curl\lib\noproxy.c" />
|
||||||
<ClCompile Include="curl\lib\openldap.c" />
|
<ClCompile Include="curl\lib\openldap.c" />
|
||||||
|
|
@ -203,6 +204,7 @@
|
||||||
<ClCompile Include="curl\lib\version.c" />
|
<ClCompile Include="curl\lib\version.c" />
|
||||||
<ClCompile Include="curl\lib\vquic\curl_ngtcp2.c" />
|
<ClCompile Include="curl\lib\vquic\curl_ngtcp2.c" />
|
||||||
<ClCompile Include="curl\lib\vquic\curl_quiche.c" />
|
<ClCompile Include="curl\lib\vquic\curl_quiche.c" />
|
||||||
|
<ClCompile Include="curl\lib\vtls\apple.c" />
|
||||||
<ClCompile Include="curl\lib\vtls\cipher_suite.c" />
|
<ClCompile Include="curl\lib\vtls\cipher_suite.c" />
|
||||||
<ClCompile Include="curl\lib\vtls\hostcheck.c" />
|
<ClCompile Include="curl\lib\vtls\hostcheck.c" />
|
||||||
<ClCompile Include="curl\lib\vtls\rustls.c" />
|
<ClCompile Include="curl\lib\vtls\rustls.c" />
|
||||||
|
|
@ -225,7 +227,6 @@
|
||||||
<ClCompile Include="curl\lib\vssh\curl_path.c" />
|
<ClCompile Include="curl\lib\vssh\curl_path.c" />
|
||||||
<ClCompile Include="curl\lib\vssh\libssh.c" />
|
<ClCompile Include="curl\lib\vssh\libssh.c" />
|
||||||
<ClCompile Include="curl\lib\vssh\libssh2.c" />
|
<ClCompile Include="curl\lib\vssh\libssh2.c" />
|
||||||
<ClCompile Include="curl\lib\vssh\wolfssh.c" />
|
|
||||||
<ClCompile Include="curl\lib\vtls\gtls.c" />
|
<ClCompile Include="curl\lib\vtls\gtls.c" />
|
||||||
<ClCompile Include="curl\lib\vtls\keylog.c" />
|
<ClCompile Include="curl\lib\vtls\keylog.c" />
|
||||||
<ClCompile Include="curl\lib\vtls\mbedtls.c" />
|
<ClCompile Include="curl\lib\vtls\mbedtls.c" />
|
||||||
|
|
@ -274,10 +275,12 @@
|
||||||
<ClInclude Include="curl\lib\curlx\binmode.h" />
|
<ClInclude Include="curl\lib\curlx\binmode.h" />
|
||||||
<ClInclude Include="curl\lib\curlx\curlx.h" />
|
<ClInclude Include="curl\lib\curlx\curlx.h" />
|
||||||
<ClInclude Include="curl\lib\curlx\dynbuf.h" />
|
<ClInclude Include="curl\lib\curlx\dynbuf.h" />
|
||||||
|
<ClInclude Include="curl\lib\curlx\fopen.h" />
|
||||||
<ClInclude Include="curl\lib\curlx\inet_ntop.h" />
|
<ClInclude Include="curl\lib\curlx\inet_ntop.h" />
|
||||||
<ClInclude Include="curl\lib\curlx\inet_pton.h" />
|
<ClInclude Include="curl\lib\curlx\inet_pton.h" />
|
||||||
<ClInclude Include="curl\lib\curlx\multibyte.h" />
|
<ClInclude Include="curl\lib\curlx\multibyte.h" />
|
||||||
<ClInclude Include="curl\lib\curlx\nonblock.h" />
|
<ClInclude Include="curl\lib\curlx\nonblock.h" />
|
||||||
|
<ClInclude Include="curl\lib\curlx\strerr.h" />
|
||||||
<ClInclude Include="curl\lib\curlx\strparse.h" />
|
<ClInclude Include="curl\lib\curlx\strparse.h" />
|
||||||
<ClInclude Include="curl\lib\curlx\timediff.h" />
|
<ClInclude Include="curl\lib\curlx\timediff.h" />
|
||||||
<ClInclude Include="curl\lib\curlx\timeval.h" />
|
<ClInclude Include="curl\lib\curlx\timeval.h" />
|
||||||
|
|
@ -287,14 +290,13 @@
|
||||||
<ClInclude Include="curl\lib\curlx\winapi.h" />
|
<ClInclude Include="curl\lib\curlx\winapi.h" />
|
||||||
<ClInclude Include="curl\lib\curl_addrinfo.h" />
|
<ClInclude Include="curl\lib\curl_addrinfo.h" />
|
||||||
<ClInclude Include="curl\lib\curl_ctype.h" />
|
<ClInclude Include="curl\lib\curl_ctype.h" />
|
||||||
<ClInclude Include="curl\lib\curl_des.h" />
|
|
||||||
<ClInclude Include="curl\lib\curl_endian.h" />
|
<ClInclude Include="curl\lib\curl_endian.h" />
|
||||||
<ClInclude Include="curl\lib\curl_fnmatch.h" />
|
<ClInclude Include="curl\lib\curl_fnmatch.h" />
|
||||||
|
<ClInclude Include="curl\lib\curl_fopen.h" />
|
||||||
<ClInclude Include="curl\lib\curl_gethostname.h" />
|
<ClInclude Include="curl\lib\curl_gethostname.h" />
|
||||||
<ClInclude Include="curl\lib\curl_get_line.h" />
|
<ClInclude Include="curl\lib\curl_get_line.h" />
|
||||||
<ClInclude Include="curl\lib\curl_gssapi.h" />
|
<ClInclude Include="curl\lib\curl_gssapi.h" />
|
||||||
<ClInclude Include="curl\lib\curl_hmac.h" />
|
<ClInclude Include="curl\lib\curl_hmac.h" />
|
||||||
<ClInclude Include="curl\lib\curl_krb5.h" />
|
|
||||||
<ClInclude Include="curl\lib\curl_ldap.h" />
|
<ClInclude Include="curl\lib\curl_ldap.h" />
|
||||||
<ClInclude Include="curl\lib\curl_md4.h" />
|
<ClInclude Include="curl\lib\curl_md4.h" />
|
||||||
<ClInclude Include="curl\lib\curl_md5.h" />
|
<ClInclude Include="curl\lib\curl_md5.h" />
|
||||||
|
|
@ -325,7 +327,6 @@
|
||||||
<ClInclude Include="curl\lib\fake_addrinfo.h" />
|
<ClInclude Include="curl\lib\fake_addrinfo.h" />
|
||||||
<ClInclude Include="curl\lib\file.h" />
|
<ClInclude Include="curl\lib\file.h" />
|
||||||
<ClInclude Include="curl\lib\fileinfo.h" />
|
<ClInclude Include="curl\lib\fileinfo.h" />
|
||||||
<ClInclude Include="curl\lib\fopen.h" />
|
|
||||||
<ClInclude Include="curl\lib\formdata.h" />
|
<ClInclude Include="curl\lib\formdata.h" />
|
||||||
<ClInclude Include="curl\lib\ftp.h" />
|
<ClInclude Include="curl\lib\ftp.h" />
|
||||||
<ClInclude Include="curl\lib\ftplistparser.h" />
|
<ClInclude Include="curl\lib\ftplistparser.h" />
|
||||||
|
|
@ -357,6 +358,7 @@
|
||||||
<ClInclude Include="curl\lib\multihandle.h" />
|
<ClInclude Include="curl\lib\multihandle.h" />
|
||||||
<ClInclude Include="curl\lib\multiif.h" />
|
<ClInclude Include="curl\lib\multiif.h" />
|
||||||
<ClInclude Include="curl\lib\multi_ev.h" />
|
<ClInclude Include="curl\lib\multi_ev.h" />
|
||||||
|
<ClInclude Include="curl\lib\multi_ntfy.h" />
|
||||||
<ClInclude Include="curl\lib\netrc.h" />
|
<ClInclude Include="curl\lib\netrc.h" />
|
||||||
<ClInclude Include="curl\lib\noproxy.h" />
|
<ClInclude Include="curl\lib\noproxy.h" />
|
||||||
<ClInclude Include="curl\lib\parsedate.h" />
|
<ClInclude Include="curl\lib\parsedate.h" />
|
||||||
|
|
@ -403,6 +405,7 @@
|
||||||
<ClInclude Include="curl\lib\vquic\curl_ngtcp2.h" />
|
<ClInclude Include="curl\lib\vquic\curl_ngtcp2.h" />
|
||||||
<ClInclude Include="curl\lib\vquic\curl_quiche.h" />
|
<ClInclude Include="curl\lib\vquic\curl_quiche.h" />
|
||||||
<ClInclude Include="curl\lib\vquic\vquic_int.h" />
|
<ClInclude Include="curl\lib\vquic\vquic_int.h" />
|
||||||
|
<ClInclude Include="curl\lib\vtls\apple.h" />
|
||||||
<ClInclude Include="curl\lib\vtls\cipher_suite.h" />
|
<ClInclude Include="curl\lib\vtls\cipher_suite.h" />
|
||||||
<ClInclude Include="curl\lib\vtls\hostcheck.h" />
|
<ClInclude Include="curl\lib\vtls\hostcheck.h" />
|
||||||
<ClInclude Include="curl\lib\vtls\rustls.h" />
|
<ClInclude Include="curl\lib\vtls\rustls.h" />
|
||||||
|
|
|
||||||
51
3rdparty/curl/libcurl.vcxproj.filters
vendored
51
3rdparty/curl/libcurl.vcxproj.filters
vendored
|
|
@ -42,9 +42,6 @@
|
||||||
<ClCompile Include="curl\lib\curl_addrinfo.c">
|
<ClCompile Include="curl\lib\curl_addrinfo.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="curl\lib\curl_des.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="curl\lib\curl_endian.c">
|
<ClCompile Include="curl\lib\curl_endian.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
@ -159,9 +156,6 @@
|
||||||
<ClCompile Include="curl\lib\imap.c">
|
<ClCompile Include="curl\lib\imap.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="curl\lib\krb5.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="curl\lib\ldap.c">
|
<ClCompile Include="curl\lib\ldap.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
@ -333,9 +327,6 @@
|
||||||
<ClCompile Include="curl\lib\vssh\libssh2.c">
|
<ClCompile Include="curl\lib\vssh\libssh2.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="curl\lib\vssh\wolfssh.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="curl\lib\vtls\gtls.c">
|
<ClCompile Include="curl\lib\vtls\gtls.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
@ -396,9 +387,6 @@
|
||||||
<ClCompile Include="curl\lib\headers.c">
|
<ClCompile Include="curl\lib\headers.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="curl\lib\fopen.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="curl\lib\noproxy.c">
|
<ClCompile Include="curl\lib\noproxy.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
@ -546,6 +534,21 @@
|
||||||
<ClCompile Include="curl\lib\cf-ip-happy.c">
|
<ClCompile Include="curl\lib\cf-ip-happy.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="curl\lib\curl_fopen.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="curl\lib\multi_ntfy.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="curl\lib\vtls\apple.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="curl\lib\curlx\fopen.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="curl\lib\curlx\strerr.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="curl\include\curl\curl.h">
|
<ClInclude Include="curl\include\curl\curl.h">
|
||||||
|
|
@ -623,9 +626,6 @@
|
||||||
<ClInclude Include="curl\lib\curl_ctype.h">
|
<ClInclude Include="curl\lib\curl_ctype.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="curl\lib\curl_des.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="curl\lib\curl_endian.h">
|
<ClInclude Include="curl\lib\curl_endian.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
@ -926,9 +926,6 @@
|
||||||
<ClInclude Include="curl\lib\vtls\keylog.h">
|
<ClInclude Include="curl\lib\vtls\keylog.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="curl\lib\curl_krb5.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="curl\lib\easyoptions.h">
|
<ClInclude Include="curl\lib\easyoptions.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
@ -953,9 +950,6 @@
|
||||||
<ClInclude Include="curl\lib\easy_lock.h">
|
<ClInclude Include="curl\lib\easy_lock.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="curl\lib\fopen.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="curl\lib\functypes.h">
|
<ClInclude Include="curl\lib\functypes.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
@ -1112,6 +1106,21 @@
|
||||||
<ClInclude Include="curl\lib\curl_mem_undef.h">
|
<ClInclude Include="curl\lib\curl_mem_undef.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="curl\lib\curl_fopen.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="curl\lib\multi_ntfy.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="curl\lib\vtls\apple.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="curl\lib\curlx\fopen.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="curl\lib\curlx\strerr.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="curl\lib\libcurl.rc">
|
<ResourceCompile Include="curl\lib\libcurl.rc">
|
||||||
|
|
|
||||||
2
3rdparty/fusion/fusion
vendored
2
3rdparty/fusion/fusion
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit 066d4a63b2c714b20b0a8073a01fda7c5c6763f6
|
Subproject commit 759ac5d698baefca53f1975a0bb1d2dcbdb9f836
|
||||||
2
3rdparty/hidapi/hidapi
vendored
2
3rdparty/hidapi/hidapi
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit f42423643ec9011c98cccc0bb790722bbbd3f30b
|
Subproject commit d6b2a974608dec3b76fb1e36c189f22b9cf3650c
|
||||||
2
3rdparty/libpng/libpng
vendored
2
3rdparty/libpng/libpng
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit 2b978915d82377df13fcbb1fb56660195ded868a
|
Subproject commit 49363adcfaf098748d7a4c8c624ad8c45a8c3a86
|
||||||
2
3rdparty/libsdl-org/SDL
vendored
2
3rdparty/libsdl-org/SDL
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit a96677bdf6b4acb84af4ec294e5f60a4e8cbbe03
|
Subproject commit 7f3ae3d57459e59943a4ecfefc8f6277ec6bf540
|
||||||
1
3rdparty/libsdl-org/SDL.vcxproj
vendored
1
3rdparty/libsdl-org/SDL.vcxproj
vendored
|
|
@ -384,7 +384,6 @@
|
||||||
<ClCompile Include="SDL\src\render\opengl\SDL_shaders_gl.c" />
|
<ClCompile Include="SDL\src\render\opengl\SDL_shaders_gl.c" />
|
||||||
<ClCompile Include="SDL\src\render\opengles2\SDL_render_gles2.c" />
|
<ClCompile Include="SDL\src\render\opengles2\SDL_render_gles2.c" />
|
||||||
<ClCompile Include="SDL\src\render\opengles2\SDL_shaders_gles2.c" />
|
<ClCompile Include="SDL\src\render\opengles2\SDL_shaders_gles2.c" />
|
||||||
<ClCompile Include="SDL\src\render\SDL_d3dmath.c" />
|
|
||||||
<ClCompile Include="SDL\src\render\SDL_render.c" />
|
<ClCompile Include="SDL\src\render\SDL_render.c" />
|
||||||
<ClCompile Include="SDL\src\render\SDL_render_unsupported.c" />
|
<ClCompile Include="SDL\src\render\SDL_render_unsupported.c" />
|
||||||
<ClCompile Include="SDL\src\render\SDL_yuv_sw.c" />
|
<ClCompile Include="SDL\src\render\SDL_yuv_sw.c" />
|
||||||
|
|
|
||||||
6
3rdparty/libsdl-org/SDL.vcxproj.filters
vendored
6
3rdparty/libsdl-org/SDL.vcxproj.filters
vendored
|
|
@ -172,9 +172,6 @@
|
||||||
<Filter Include="render\direct3d12">
|
<Filter Include="render\direct3d12">
|
||||||
<UniqueIdentifier>{f48c2b17-1bee-4fec-a7c8-24cf619abe08}</UniqueIdentifier>
|
<UniqueIdentifier>{f48c2b17-1bee-4fec-a7c8-24cf619abe08}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter Include="video\intrin">
|
|
||||||
<UniqueIdentifier>{653672cc-90ae-4eba-a256-6479f2c31804}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="main">
|
<Filter Include="main">
|
||||||
<UniqueIdentifier>{00001967ea2801028a046a722a070000}</UniqueIdentifier>
|
<UniqueIdentifier>{00001967ea2801028a046a722a070000}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
|
@ -1460,9 +1457,6 @@
|
||||||
<ClCompile Include="SDL\src\sensor\windows\SDL_windowssensor.c">
|
<ClCompile Include="SDL\src\sensor\windows\SDL_windowssensor.c">
|
||||||
<Filter>sensor\windows</Filter>
|
<Filter>sensor\windows</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="SDL\src\render\SDL_d3dmath.c">
|
|
||||||
<Filter>render</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="SDL\src\render\SDL_render.c">
|
<ClCompile Include="SDL\src\render\SDL_render.c">
|
||||||
<Filter>render</Filter>
|
<Filter>render</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
|
||||||
5
3rdparty/qt6.cmake
vendored
5
3rdparty/qt6.cmake
vendored
|
|
@ -6,14 +6,15 @@ find_package(Qt6 ${QT_MIN_VER} CONFIG COMPONENTS Widgets Concurrent Multimedia M
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_link_libraries(3rdparty_qt6 INTERFACE Qt6::Widgets Qt6::Concurrent Qt6::Multimedia Qt6::MultimediaWidgets Qt6::Svg Qt6::SvgWidgets)
|
target_link_libraries(3rdparty_qt6 INTERFACE Qt6::Widgets Qt6::Concurrent Qt6::Multimedia Qt6::MultimediaWidgets Qt6::Svg Qt6::SvgWidgets)
|
||||||
else()
|
else()
|
||||||
find_package(Qt6 ${QT_MIN_VER} COMPONENTS DBus Gui)
|
set(QT_NO_PRIVATE_MODULE_WARNING ON)
|
||||||
|
find_package(Qt6 ${QT_MIN_VER} COMPONENTS DBus Gui GuiPrivate)
|
||||||
if(Qt6DBus_FOUND)
|
if(Qt6DBus_FOUND)
|
||||||
target_link_libraries(3rdparty_qt6 INTERFACE Qt6::Widgets Qt6::DBus Qt6::Concurrent Qt6::Multimedia Qt6::MultimediaWidgets Qt6::Svg Qt6::SvgWidgets)
|
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)
|
target_compile_definitions(3rdparty_qt6 INTERFACE -DHAVE_QTDBUS)
|
||||||
else()
|
else()
|
||||||
target_link_libraries(3rdparty_qt6 INTERFACE Qt6::Widgets Qt6::Concurrent Qt6::Multimedia Qt6::MultimediaWidgets Qt6::Svg Qt6::SvgWidgets)
|
target_link_libraries(3rdparty_qt6 INTERFACE Qt6::Widgets Qt6::Concurrent Qt6::Multimedia Qt6::MultimediaWidgets Qt6::Svg Qt6::SvgWidgets)
|
||||||
endif()
|
endif()
|
||||||
target_include_directories(3rdparty_qt6 INTERFACE ${Qt6Gui_PRIVATE_INCLUDE_DIRS})
|
target_link_libraries(3rdparty_qt6 INTERFACE Qt6::GuiPrivate)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(Qt6Widgets_FOUND)
|
if(Qt6Widgets_FOUND)
|
||||||
|
|
|
||||||
2
3rdparty/zstd/CMakeLists.txt
vendored
2
3rdparty/zstd/CMakeLists.txt
vendored
|
|
@ -10,7 +10,7 @@ else()
|
||||||
option(ZSTD_BUILD_STATIC "BUILD STATIC LIBRARIES" ON)
|
option(ZSTD_BUILD_STATIC "BUILD STATIC LIBRARIES" ON)
|
||||||
option(ZSTD_BUILD_TESTS "BUILD TESTS" OFF)
|
option(ZSTD_BUILD_TESTS "BUILD TESTS" OFF)
|
||||||
|
|
||||||
add_subdirectory(zstd/build/cmake EXLUDE_FROM_ALL)
|
add_subdirectory(zstd/build/cmake EXCLUDE_FROM_ALL)
|
||||||
add_library(3rdparty_zstd INTERFACE)
|
add_library(3rdparty_zstd INTERFACE)
|
||||||
target_link_libraries(3rdparty_zstd INTERFACE libzstd_static)
|
target_link_libraries(3rdparty_zstd INTERFACE libzstd_static)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
||||||
15
BUILDING.md
15
BUILDING.md
|
|
@ -8,37 +8,38 @@ Other instructions may be found [here](https://wiki.rpcs3.net/index.php?title=Bu
|
||||||
### Windows 10 or later
|
### Windows 10 or later
|
||||||
|
|
||||||
The following tools are required to build RPCS3 on Windows 10 or later:
|
The following tools are required to build RPCS3 on Windows 10 or later:
|
||||||
- [Visual Studio 2022](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community)
|
- [Visual Studio 2022/2026](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community)
|
||||||
- **Optional** - [CMake 3.28.0+](https://www.cmake.org/download/) (add to PATH)
|
- **Optional** - [CMake 3.28.0+](https://www.cmake.org/download/) (add to PATH)
|
||||||
|
|
||||||
**NOTES:**
|
**NOTES:**
|
||||||
- **Visual Studio 2022** integrates **CMake 3.29+** and it also supports both the `sln` solution (`.sln`, `.vcxproj`) and `CMake` solution (`CMakeLists.txt`, `CMakePresets.json`).
|
- **Visual Studio 2026** needs at least **CMake 4.2.0+**.
|
||||||
|
- **Visual Studio 2022/2026** integrates **CMake 3.29+** and it also supports both the `sln` solution (`.sln`, `.vcxproj`) and `CMake` solution (`CMakeLists.txt`, `CMakePresets.json`).
|
||||||
See sections [Building with Visual Studio sln solution](#building-with-visual-studio-sln-solution) and [Building with Visual Studio CMake solution](#building-with-visual-studio-cmake-solution)
|
See sections [Building with Visual Studio sln solution](#building-with-visual-studio-sln-solution) and [Building with Visual Studio CMake solution](#building-with-visual-studio-cmake-solution)
|
||||||
on how to build the project with **Visual Studio**.
|
on how to build the project with **Visual Studio**.
|
||||||
- Install and use this standalone **CMake** tool just in case of your preference. See section [Building with standalone CMake tool](#building-with-standalone-cmake-tool) on how to build the project
|
- Install and use this standalone **CMake** tool just in case of your preference. See section [Building with standalone CMake tool](#building-with-standalone-cmake-tool) on how to build the project
|
||||||
with standalone **CMake** tool.
|
with standalone **CMake** tool.
|
||||||
|
|
||||||
- [Python 3.6+](https://www.python.org/downloads/) (add to PATH)
|
- [Python 3.6+](https://www.python.org/downloads/) (add to PATH)
|
||||||
- [Qt 6.9.3](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.10.1](https://www.qt.io/download-qt-installer) In case you can't download from the official installer, you can use [Another Qt installer](https://github.com/miurahr/aqtinstall) (In that case you will need to manually add the "qtmultimedia" module when installing Qt)
|
||||||
- [Vulkan SDK 1.3.268.0](https://vulkan.lunarg.com/sdk/home) (see "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/windows/getting_started.html)) for now future SDKs don't work. You need precisely 1.3.268.0.
|
- [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.
|
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:
|
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.9.3\msvc2022_64\`
|
- add and set the `QTDIR` environment variable, e.g. `<QtInstallFolder>\6.10.1\msvc2022_64\`
|
||||||
- or use the [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2022)
|
- 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.
|
**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):
|
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.9.3\msvc2022_64\`
|
- add and set the `Qt6_ROOT` environment variable to the **Qt** libs path, e.g. `<QtInstallFolder>\6.10.1\msvc2022_64\`
|
||||||
|
|
||||||
### Linux
|
### Linux
|
||||||
|
|
||||||
These are the essentials tools to build RPCS3 on Linux. Some of them can be installed through your favorite package manager:
|
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+
|
- Clang 17+ or GCC 13+
|
||||||
- [CMake 3.28.0+](https://www.cmake.org/download/)
|
- [CMake 3.28.0+](https://www.cmake.org/download/)
|
||||||
- [Qt 6.9.3](https://www.qt.io/download-qt-installer)
|
- [Qt 6.10.1](https://www.qt.io/download-qt-installer)
|
||||||
- [Vulkan SDK 1.3.268.0](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/linux/getting_started.html)) for now future SDKs don't work. You need precisely 1.3.268.0.
|
- [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)
|
- [SDL3](https://github.com/libsdl-org/SDL/releases) (for the FAudio backend)
|
||||||
|
|
||||||
|
|
@ -121,7 +122,7 @@ Start **Visual Studio**, click on `Open a project or solution` and select the `r
|
||||||
##### Configuring the Qt Plugin (if used)
|
##### Configuring the Qt Plugin (if used)
|
||||||
|
|
||||||
1) go to `Extensions->Qt VS Tools->Qt Versions`
|
1) go to `Extensions->Qt VS Tools->Qt Versions`
|
||||||
2) add the path to your Qt installation with compiler e.g. `<QtInstallFolder>\6.9.3\msvc2022_64`, version will fill in automatically
|
2) add the path to your Qt installation with compiler e.g. `<QtInstallFolder>\6.10.1\msvc2022_64`, version will fill in automatically
|
||||||
3) go to `Extensions->Qt VS Tools->Options->Legacy Project Format`. (Only available in the **Legacy Qt Plugin**)
|
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**)
|
4) set `Build: Run pre-build setup` to `true`. (Only available in the **Legacy Qt Plugin**)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,7 @@ if(MSVC)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
|
if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
message( FATAL_ERROR "RPCS3 can only be compiled on 64-bit platforms." )
|
message(FATAL_ERROR "RPCS3 can only be compiled on 64-bit platforms.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(APPLE AND CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
|
if(APPLE AND CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
|
||||||
|
|
|
||||||
|
|
@ -166,6 +166,55 @@ bool try_to_uint64(u64* out, std::string_view value, u64 min, u64 max)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool try_to_uint128(u128* out, std::string_view value)
|
||||||
|
{
|
||||||
|
if (value.empty())
|
||||||
|
{
|
||||||
|
if (out) cfg_log.error("cfg::try_to_uint128(): called with an empty string");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 result_low = 0, result_high = 0;
|
||||||
|
const char* start_high64 = value.data();
|
||||||
|
const char* end = value.data() + value.size();
|
||||||
|
|
||||||
|
if (start_high64[0] == '0' && value.size() >= 2 && (start_high64[1] == 'x' || start_high64[1] == 'X'))
|
||||||
|
{
|
||||||
|
// Hex support
|
||||||
|
start_high64 += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* start_low64 = end - std::min<usz>(end - start_high64, 16);
|
||||||
|
|
||||||
|
// Hexadecimal-only
|
||||||
|
constexpr int base = 16;
|
||||||
|
|
||||||
|
auto ret = std::from_chars(start_low64, end, result_low, base);
|
||||||
|
|
||||||
|
if (ret.ec != std::errc() || ret.ptr != end)
|
||||||
|
{
|
||||||
|
if (out) cfg_log.error("cfg::try_to_uint128('%s'): invalid integer", value);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start_high64 == start_low64)
|
||||||
|
{
|
||||||
|
if (out) *out = result_low;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = std::from_chars(start_high64, start_low64, result_high, base);
|
||||||
|
|
||||||
|
if (ret.ec != std::errc() || ret.ptr != start_low64)
|
||||||
|
{
|
||||||
|
if (out) cfg_log.error("cfg::try_to_uint128('%s'): invalid integer", value);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out) *out = result_low + (u128{result_high} << 64);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::string> cfg::make_float_range(f64 min, f64 max)
|
std::vector<std::string> cfg::make_float_range(f64 min, f64 max)
|
||||||
{
|
{
|
||||||
return {std::to_string(min), std::to_string(max)};
|
return {std::to_string(min), std::to_string(max)};
|
||||||
|
|
@ -278,6 +327,19 @@ bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) f
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string cfg::uint128::to_string(u128 value) noexcept
|
||||||
|
{
|
||||||
|
std::string result = "0x";
|
||||||
|
result.resize(result.size() + 32);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
result[result.size() - 1 - i] = "0123456789ABCDEF"[static_cast<u64>(value >> (i * 4)) % 16];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::string> cfg::try_to_enum_list(decltype(&fmt_class_string<int>::format) func)
|
std::vector<std::string> cfg::try_to_enum_list(decltype(&fmt_class_string<int>::format) func)
|
||||||
{
|
{
|
||||||
std::vector<std::string> result;
|
std::vector<std::string> result;
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ namespace cfg
|
||||||
_enum, // cfg::_enum type
|
_enum, // cfg::_enum type
|
||||||
_int, // cfg::_int type
|
_int, // cfg::_int type
|
||||||
uint, // cfg::uint type
|
uint, // cfg::uint type
|
||||||
|
uint128, // cfg::uint128 type
|
||||||
string, // cfg::string type
|
string, // cfg::string type
|
||||||
set, // cfg::set_entry type
|
set, // cfg::set_entry type
|
||||||
map, // cfg::map_entry type
|
map, // cfg::map_entry type
|
||||||
|
|
@ -578,6 +579,86 @@ namespace cfg
|
||||||
// Alias for 64 bit int
|
// Alias for 64 bit int
|
||||||
using uint64 = uint<0, u64{umax}>;
|
using uint64 = uint<0, u64{umax}>;
|
||||||
|
|
||||||
|
// Unsigned 128-bit integer entry.
|
||||||
|
class uint128 final : public _base
|
||||||
|
{
|
||||||
|
using int_type = u128;
|
||||||
|
|
||||||
|
atomic_t<int_type> m_value{};
|
||||||
|
int_type original_def = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
int_type def;
|
||||||
|
|
||||||
|
uint128(node* owner, const std::string& name, int_type def = 0, bool dynamic = false)
|
||||||
|
: _base(type::uint128, owner, name, dynamic)
|
||||||
|
, m_value(def)
|
||||||
|
, original_def(def)
|
||||||
|
, def(def)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
operator int_type() const
|
||||||
|
{
|
||||||
|
return m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator ullong() const
|
||||||
|
{
|
||||||
|
return static_cast<ullong>(m_value.load());
|
||||||
|
}
|
||||||
|
|
||||||
|
int_type get() const
|
||||||
|
{
|
||||||
|
return m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void from_default() override
|
||||||
|
{
|
||||||
|
m_value = def;
|
||||||
|
}
|
||||||
|
|
||||||
|
void restore_defaults() override
|
||||||
|
{
|
||||||
|
def = original_def;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string to_string(u128 value) noexcept;
|
||||||
|
|
||||||
|
std::string to_string() const override
|
||||||
|
{
|
||||||
|
return to_string(m_value.load());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string def_to_string() const override
|
||||||
|
{
|
||||||
|
return to_string(def);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool from_string(std::string_view value, bool /*dynamic*/ = false) override
|
||||||
|
{
|
||||||
|
u128 result;
|
||||||
|
if (try_to_uint128(&result, value))
|
||||||
|
{
|
||||||
|
m_value = result;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(u128 value)
|
||||||
|
{
|
||||||
|
m_value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> to_list() const override
|
||||||
|
{
|
||||||
|
// Should not be used
|
||||||
|
return make_uint_range(0, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Simple string entry with mutex
|
// Simple string entry with mutex
|
||||||
class string : public _base
|
class string : public _base
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -658,7 +658,11 @@ jit_compiler::jit_compiler(const std::unordered_map<std::string, u64>& _link, co
|
||||||
std::string result;
|
std::string result;
|
||||||
|
|
||||||
auto null_mod = std::make_unique<llvm::Module> ("null_", *m_context);
|
auto null_mod = std::make_unique<llvm::Module> ("null_", *m_context);
|
||||||
|
#if LLVM_VERSION_MAJOR >= 21 && (LLVM_VERSION_MINOR >= 1 || LLVM_VERSION_MAJOR >= 22)
|
||||||
|
null_mod->setTargetTriple(llvm::Triple(jit_compiler::triple1()));
|
||||||
|
#else
|
||||||
null_mod->setTargetTriple(jit_compiler::triple1());
|
null_mod->setTargetTriple(jit_compiler::triple1());
|
||||||
|
#endif
|
||||||
|
|
||||||
std::unique_ptr<llvm::RTDyldMemoryManager> mem;
|
std::unique_ptr<llvm::RTDyldMemoryManager> mem;
|
||||||
|
|
||||||
|
|
@ -672,7 +676,11 @@ jit_compiler::jit_compiler(const std::unordered_map<std::string, u64>& _link, co
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mem = std::make_unique<MemoryManager2>(std::move(symbols_cement));
|
mem = std::make_unique<MemoryManager2>(std::move(symbols_cement));
|
||||||
|
#if LLVM_VERSION_MAJOR >= 21 && (LLVM_VERSION_MINOR >= 1 || LLVM_VERSION_MAJOR >= 22)
|
||||||
|
null_mod->setTargetTriple(llvm::Triple(jit_compiler::triple2()));
|
||||||
|
#else
|
||||||
null_mod->setTargetTriple(jit_compiler::triple2());
|
null_mod->setTargetTriple(jit_compiler::triple2());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -394,7 +394,7 @@ namespace fmt
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(_MSC_VER) || defined(__clang__)
|
#if !defined(_MSC_VER) || defined(__clang__)
|
||||||
[[noreturn]] ~throw_exception();
|
[[noreturn]] ~throw_exception() = default;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,9 @@ bool try_to_int64(s64* out, std::string_view value, s64 min, s64 max);
|
||||||
// Convert string to unsigned integer
|
// Convert string to unsigned integer
|
||||||
bool try_to_uint64(u64* out, std::string_view value, u64 min, u64 max);
|
bool try_to_uint64(u64* out, std::string_view value, u64 min, u64 max);
|
||||||
|
|
||||||
|
// Convert string to unsigned int128_t
|
||||||
|
bool try_to_uint128(u128* out, std::string_view value);
|
||||||
|
|
||||||
// Convert string to float
|
// Convert string to float
|
||||||
bool try_to_float(f64* out, std::string_view value, f64 min, f64 max);
|
bool try_to_float(f64* out, std::string_view value, f64 min, f64 max);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,11 @@ thread_local u64 g_tls_wait_fail = 0;
|
||||||
thread_local bool g_tls_access_violation_recovered = false;
|
thread_local bool g_tls_access_violation_recovered = false;
|
||||||
extern thread_local std::string(*g_tls_log_prefix)();
|
extern thread_local std::string(*g_tls_log_prefix)();
|
||||||
|
|
||||||
|
namespace stx
|
||||||
|
{
|
||||||
|
atomic_t<u32> g_launch_retainer{0};
|
||||||
|
}
|
||||||
|
|
||||||
// Report error and call std::abort(), defined in main.cpp
|
// Report error and call std::abort(), defined in main.cpp
|
||||||
[[noreturn]] void report_fatal_error(std::string_view text, bool is_html = false, bool include_help_text = true);
|
[[noreturn]] void report_fatal_error(std::string_view text, bool is_html = false, bool include_help_text = true);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -465,6 +465,8 @@ public:
|
||||||
namespace stx
|
namespace stx
|
||||||
{
|
{
|
||||||
struct launch_retainer;
|
struct launch_retainer;
|
||||||
|
|
||||||
|
extern atomic_t<u32> g_launch_retainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Derived from the callable object Context, possibly a lambda
|
// Derived from the callable object Context, possibly a lambda
|
||||||
|
|
@ -481,6 +483,11 @@ class named_thread final : public Context, result_storage<Context>, thread_base
|
||||||
|
|
||||||
u64 entry_point2()
|
u64 entry_point2()
|
||||||
{
|
{
|
||||||
|
while (u32 value = stx::g_launch_retainer)
|
||||||
|
{
|
||||||
|
stx::g_launch_retainer.wait(value);
|
||||||
|
}
|
||||||
|
|
||||||
thread::initialize([]()
|
thread::initialize([]()
|
||||||
{
|
{
|
||||||
if constexpr (!result::empty)
|
if constexpr (!result::empty)
|
||||||
|
|
|
||||||
27
Utilities/deferred_op.hpp
Normal file
27
Utilities/deferred_op.hpp
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Generic deferred routine wrapper
|
||||||
|
// Use-case is similar to "defer" statement in other languages, just invokes a callback when the object goes out of scope
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace utils
|
||||||
|
{
|
||||||
|
template <typename F>
|
||||||
|
requires std::is_invocable_v<F>
|
||||||
|
class deferred_op
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
deferred_op(F&& callback)
|
||||||
|
: m_callback(callback)
|
||||||
|
{}
|
||||||
|
|
||||||
|
~deferred_op()
|
||||||
|
{
|
||||||
|
m_callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
F m_callback;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -201,7 +201,7 @@ QPushButton::disabled {
|
||||||
/* QSpinBox (Settings -> Emulator -> width/height) */
|
/* QSpinBox (Settings -> Emulator -> width/height) */
|
||||||
/* QDoubleSpinBox (Pads -> Mouse Acceleration -> x/y) */
|
/* QDoubleSpinBox (Pads -> Mouse Acceleration -> x/y) */
|
||||||
QSpinBox, QDoubleSpinBox {
|
QSpinBox, QDoubleSpinBox {
|
||||||
height: 0.1em;
|
height: 1.50em;
|
||||||
background-color: #b3ac98;
|
background-color: #b3ac98;
|
||||||
}
|
}
|
||||||
QSpinBox::disabled, QDoubleSpinBox::disabled {
|
QSpinBox::disabled, QDoubleSpinBox::disabled {
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ if(MSVC)
|
||||||
add_compile_definitions(
|
add_compile_definitions(
|
||||||
_CRT_SECURE_NO_DEPRECATE=1 _CRT_NON_CONFORMING_SWPRINTFS=1 _SCL_SECURE_NO_WARNINGS=1
|
_CRT_SECURE_NO_DEPRECATE=1 _CRT_NON_CONFORMING_SWPRINTFS=1 _SCL_SECURE_NO_WARNINGS=1
|
||||||
NOMINMAX _ENABLE_EXTENDED_ALIGNED_STORAGE=1 _HAS_EXCEPTIONS=0)
|
NOMINMAX _ENABLE_EXTENDED_ALIGNED_STORAGE=1 _HAS_EXCEPTIONS=0)
|
||||||
add_link_options(/DYNAMICBASE)
|
|
||||||
|
|
||||||
#TODO: Some of these could be cleaned up
|
#TODO: Some of these could be cleaned up
|
||||||
add_compile_options(/wd4805) # Comparing boolean and int
|
add_compile_options(/wd4805) # Comparing boolean and int
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ else ()
|
||||||
|
|
||||||
find_package_handle_standard_args(FFMPEG
|
find_package_handle_standard_args(FFMPEG
|
||||||
DEFAULT_MSG
|
DEFAULT_MSG
|
||||||
FFMPEG_LIBAVCODEC FFMPEG_LIBAVFORMAT FFMPEG_LIBSWSCALE FFMPEG_LIBSWRESAMPLE
|
FFMPEG_LIBAVCODEC FFMPEG_LIBAVFORMAT FFMPEG_LIBAVUTIL FFMPEG_LIBSWSCALE FFMPEG_LIBSWRESAMPLE
|
||||||
)
|
)
|
||||||
|
|
||||||
if (FFMPEG_FOUND)
|
if (FFMPEG_FOUND)
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <charconv>
|
#include <charconv>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
std::string to_hex(std::uint64_t value, bool prfx = true)
|
std::string to_hex(std::uint64_t value, bool prfx = true)
|
||||||
{
|
{
|
||||||
|
|
@ -85,7 +86,7 @@ int main(int argc, char* argv[])
|
||||||
// Decode address and try to find the object
|
// Decode address and try to find the object
|
||||||
std::uint64_t addr = -1;
|
std::uint64_t addr = -1;
|
||||||
|
|
||||||
std::from_chars(arg.data() + strlen("--start-address=0x"), arg.data() + arg.size(), addr, 16);
|
std::from_chars(arg.data() + ("--start-address=0x"sv).size(), arg.data() + arg.size(), addr, 16);
|
||||||
|
|
||||||
for (int j = 0; j < 0x100'0000; j++)
|
for (int j = 0; j < 0x100'0000; j++)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -10,16 +10,6 @@ include(CheckFunctionExists)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
|
||||||
set(ADDITIONAL_LIBS "")
|
|
||||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
|
||||||
#on some Linux distros shm_unlink and similar functions are in librt only
|
|
||||||
list(APPEND ADDITIONAL_LIBS "rt")
|
|
||||||
elseif(NOT WIN32 AND NOT CMAKE_CXX_FLAGS MATCHES "LIBICONV_PLUG")
|
|
||||||
#it seems like glibc includes the iconv functions we use but other libc
|
|
||||||
#implementations like the one on OSX don't seem implement them
|
|
||||||
list(APPEND ADDITIONAL_LIBS "iconv")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE AND NOT ANDROID)
|
if(UNIX AND NOT APPLE AND NOT ANDROID)
|
||||||
add_compile_definitions(DATADIR="${CMAKE_INSTALL_FULL_DATADIR}/rpcs3")
|
add_compile_definitions(DATADIR="${CMAKE_INSTALL_FULL_DATADIR}/rpcs3")
|
||||||
# Optionally enable X11 for window management
|
# Optionally enable X11 for window management
|
||||||
|
|
@ -78,8 +68,16 @@ if (NOT ANDROID)
|
||||||
3rdparty::libcurl
|
3rdparty::libcurl
|
||||||
3rdparty::zlib
|
3rdparty::zlib
|
||||||
3rdparty::opencv
|
3rdparty::opencv
|
||||||
3rdparty::fusion
|
3rdparty::fusion)
|
||||||
${ADDITIONAL_LIBS})
|
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
#on some Linux distros shm_unlink and similar functions are in librt only
|
||||||
|
target_link_libraries(rpcs3_lib PRIVATE rt)
|
||||||
|
elseif(NOT WIN32 AND NOT CMAKE_CXX_FLAGS MATCHES "LIBICONV_PLUG")
|
||||||
|
#it seems like glibc includes the iconv functions we use but other libc
|
||||||
|
#implementations like the one on OSX don't seem implement them
|
||||||
|
target_link_libraries(rpcs3_lib PRIVATE iconv)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Unix display manager
|
# Unix display manager
|
||||||
if(X11_FOUND)
|
if(X11_FOUND)
|
||||||
|
|
@ -106,19 +104,16 @@ if (NOT ANDROID)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Build rpcs3 executable
|
# Build rpcs3 executable
|
||||||
|
add_executable(rpcs3 WIN32 MACOSX_BUNDLE)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
add_executable(rpcs3 WIN32)
|
|
||||||
target_sources(rpcs3 PRIVATE rpcs3.rc)
|
target_sources(rpcs3 PRIVATE rpcs3.rc)
|
||||||
target_compile_definitions(rpcs3 PRIVATE UNICODE _UNICODE)
|
target_compile_definitions(rpcs3 PRIVATE UNICODE _UNICODE)
|
||||||
elseif(APPLE)
|
elseif(APPLE)
|
||||||
add_executable(rpcs3 MACOSX_BUNDLE)
|
|
||||||
target_sources(rpcs3 PRIVATE rpcs3.icns update_helper.sh)
|
target_sources(rpcs3 PRIVATE rpcs3.icns update_helper.sh)
|
||||||
set_source_files_properties(update_helper.sh PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
set_source_files_properties(update_helper.sh PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||||
set_target_properties(rpcs3
|
set_target_properties(rpcs3
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/rpcs3.plist.in")
|
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/rpcs3.plist.in")
|
||||||
else()
|
|
||||||
add_executable(rpcs3)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_sources(rpcs3
|
target_sources(rpcs3
|
||||||
|
|
@ -137,17 +132,12 @@ if (NOT ANDROID)
|
||||||
|
|
||||||
# Copy icons to executable directory
|
# Copy icons to executable directory
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
if (CMAKE_BUILD_TYPE MATCHES "Debug" OR CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo")
|
|
||||||
set(QT_DEPLOY_FLAGS "-no-strip")
|
|
||||||
else()
|
|
||||||
set(QT_DEPLOY_FLAGS "")
|
|
||||||
endif()
|
|
||||||
qt_finalize_target(rpcs3)
|
qt_finalize_target(rpcs3)
|
||||||
add_custom_command(TARGET rpcs3 POST_BUILD
|
add_custom_command(TARGET rpcs3 POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/rpcs3.icns $<TARGET_FILE_DIR:rpcs3>/../Resources/rpcs3.icns
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/rpcs3.icns $<TARGET_FILE_DIR:rpcs3>/../Resources/rpcs3.icns
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/Icons $<TARGET_FILE_DIR:rpcs3>/../Resources/Icons
|
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/Icons $<TARGET_FILE_DIR:rpcs3>/../Resources/Icons
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/GuiConfigs $<TARGET_FILE_DIR:rpcs3>/../Resources/GuiConfigs
|
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/GuiConfigs $<TARGET_FILE_DIR:rpcs3>/../Resources/GuiConfigs
|
||||||
COMMAND "${MACDEPLOYQT_EXECUTABLE}" "${PROJECT_BINARY_DIR}/bin/rpcs3.app" "${QT_DEPLOY_FLAGS}")
|
COMMAND "${MACDEPLOYQT_EXECUTABLE}" "${PROJECT_BINARY_DIR}/bin/rpcs3.app" "$<$<CONFIG:Debug,RelWithDebInfo>:-no-strip>")
|
||||||
elseif(UNIX)
|
elseif(UNIX)
|
||||||
add_custom_command(TARGET rpcs3 POST_BUILD
|
add_custom_command(TARGET rpcs3 POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/Icons $<TARGET_FILE_DIR:rpcs3>/Icons
|
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/Icons $<TARGET_FILE_DIR:rpcs3>/Icons
|
||||||
|
|
@ -198,8 +188,11 @@ if(BUILD_RPCS3_TESTS)
|
||||||
PRIVATE
|
PRIVATE
|
||||||
tests/test.cpp
|
tests/test.cpp
|
||||||
tests/test_fmt.cpp
|
tests/test_fmt.cpp
|
||||||
|
tests/test_pair.cpp
|
||||||
|
tests/test_tuple.cpp
|
||||||
tests/test_simple_array.cpp
|
tests/test_simple_array.cpp
|
||||||
tests/test_address_range.cpp
|
tests/test_address_range.cpp
|
||||||
|
tests/test_rsx_cfg.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(rpcs3_test
|
target_link_libraries(rpcs3_test
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,10 @@ SELF_KEY::SELF_KEY(u64 ver_start, u64 ver_end, u16 rev, u32 type, const std::str
|
||||||
version_end = ver_end;
|
version_end = ver_end;
|
||||||
revision = rev;
|
revision = rev;
|
||||||
self_type = type;
|
self_type = type;
|
||||||
hex_to_bytes(erk, e.c_str(), 0);
|
hex_to_bytes(erk, e, 0);
|
||||||
hex_to_bytes(riv, r.c_str(), 0);
|
hex_to_bytes(riv, r, 0);
|
||||||
hex_to_bytes(pub, pb.c_str(), 0);
|
hex_to_bytes(pub, pb, 0);
|
||||||
hex_to_bytes(priv, pr.c_str(), 0);
|
hex_to_bytes(priv, pr, 0);
|
||||||
curve_type = ct;
|
curve_type = ct;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,11 @@
|
||||||
#include "sha1.h"
|
#include "sha1.h"
|
||||||
#include "sha256.h"
|
#include "sha256.h"
|
||||||
#include "key_vault.h"
|
#include "key_vault.h"
|
||||||
|
#include <charconv>
|
||||||
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <time.h>
|
#include <ctime>
|
||||||
#include "Utilities/StrUtil.h"
|
#include "Utilities/StrUtil.h"
|
||||||
#include "Utilities/File.h"
|
#include "Utilities/File.h"
|
||||||
|
|
||||||
|
|
@ -21,50 +23,24 @@
|
||||||
// Auxiliary functions (endian swap, xor).
|
// Auxiliary functions (endian swap, xor).
|
||||||
|
|
||||||
// Hex string conversion auxiliary functions.
|
// Hex string conversion auxiliary functions.
|
||||||
u64 hex_to_u64(const char* hex_str)
|
void hex_to_bytes(unsigned char* data, std::string_view hex_str, unsigned int str_length)
|
||||||
{
|
{
|
||||||
auto length = std::strlen(hex_str);
|
const auto strn_length = (str_length > 0) ? str_length : hex_str.size();
|
||||||
u64 tmp = 0;
|
|
||||||
u64 result = 0;
|
|
||||||
char c;
|
|
||||||
|
|
||||||
while (length--)
|
|
||||||
{
|
|
||||||
c = *hex_str++;
|
|
||||||
if((c >= '0') && (c <= '9'))
|
|
||||||
tmp = c - '0';
|
|
||||||
else if((c >= 'a') && (c <= 'f'))
|
|
||||||
tmp = c - 'a' + 10;
|
|
||||||
else if((c >= 'A') && (c <= 'F'))
|
|
||||||
tmp = c - 'A' + 10;
|
|
||||||
else
|
|
||||||
tmp = 0;
|
|
||||||
result |= (tmp << (length * 4));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void hex_to_bytes(unsigned char* data, const char* hex_str, unsigned int str_length)
|
|
||||||
{
|
|
||||||
const auto strn_length = (str_length > 0) ? str_length : std::strlen(hex_str);
|
|
||||||
auto data_length = strn_length / 2;
|
|
||||||
char tmp_buf[3] = {0, 0, 0};
|
|
||||||
|
|
||||||
// Don't convert if the string length is odd.
|
// Don't convert if the string length is odd.
|
||||||
if ((strn_length % 2) == 0)
|
if ((strn_length % 2) == 0)
|
||||||
{
|
{
|
||||||
while (data_length--)
|
for (size_t i = 0; i < strn_length; i += 2)
|
||||||
{
|
{
|
||||||
tmp_buf[0] = *hex_str++;
|
const auto [ptr, err] = std::from_chars(hex_str.data() + i, hex_str.data() + i + 2, *data++, 16);
|
||||||
tmp_buf[1] = *hex_str++;
|
if (err != std::errc())
|
||||||
|
{
|
||||||
*data++ = static_cast<u8>(hex_to_u64(tmp_buf) & 0xFF);
|
fmt::throw_exception("Failed to read hex string: %s", std::make_error_code(err).message());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Crypto functions (AES128-CBC, AES128-ECB, SHA1-HMAC and AES-CMAC).
|
// Crypto functions (AES128-CBC, AES128-ECB, SHA1-HMAC and AES-CMAC).
|
||||||
void aescbc128_decrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, usz len)
|
void aescbc128_decrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, usz len)
|
||||||
{
|
{
|
||||||
|
|
@ -181,7 +157,7 @@ std::array<u8, PASSPHRASE_KEY_LEN> sc_combine_laid_paid(s64 laid, s64 paid)
|
||||||
{
|
{
|
||||||
const std::string paid_laid = fmt::format("%016llx%016llx", laid, paid);
|
const std::string paid_laid = fmt::format("%016llx%016llx", laid, paid);
|
||||||
std::array<u8, PASSPHRASE_KEY_LEN> out{};
|
std::array<u8, PASSPHRASE_KEY_LEN> out{};
|
||||||
hex_to_bytes(out.data(), paid_laid.c_str(), PASSPHRASE_KEY_LEN * 2);
|
hex_to_bytes(out.data(), paid_laid, PASSPHRASE_KEY_LEN * 2);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@
|
||||||
|
|
||||||
#include "util/types.hpp"
|
#include "util/types.hpp"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <cstdlib>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
enum { CRYPTO_MAX_PATH = 4096 };
|
enum { CRYPTO_MAX_PATH = 4096 };
|
||||||
|
|
||||||
|
|
@ -15,8 +16,7 @@ char* extract_file_name(const char* file_path, char real_file_name[CRYPTO_MAX_PA
|
||||||
std::string sha256_get_hash(const char* data, usz size, bool lower_case);
|
std::string sha256_get_hash(const char* data, usz size, bool lower_case);
|
||||||
|
|
||||||
// Hex string conversion auxiliary functions.
|
// Hex string conversion auxiliary functions.
|
||||||
u64 hex_to_u64(const char* hex_str);
|
void hex_to_bytes(unsigned char* data, std::string_view hex_str, unsigned int str_length);
|
||||||
void hex_to_bytes(unsigned char *data, const char *hex_str, unsigned int str_length);
|
|
||||||
|
|
||||||
// Crypto functions (AES128-CBC, AES128-ECB, SHA1-HMAC and AES-CMAC).
|
// Crypto functions (AES128-CBC, AES128-ECB, SHA1-HMAC and AES-CMAC).
|
||||||
void aescbc128_decrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, usz len);
|
void aescbc128_decrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, usz len);
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,6 @@ namespace audio
|
||||||
g_cfg.audio.volume.set(std::clamp<s32>(new_volume, g_cfg.audio.volume.min, g_cfg.audio.volume.max));
|
g_cfg.audio.volume.set(std::clamp<s32>(new_volume, g_cfg.audio.volume.min, g_cfg.audio.volume.max));
|
||||||
Emu.GetCallbacks().update_emu_settings();
|
Emu.GetCallbacks().update_emu_settings();
|
||||||
|
|
||||||
rsx::overlays::queue_message(get_localized_string(localized_string_id::AUDIO_CHANGED, fmt::format("%d%%", g_cfg.audio.volume.get()).c_str()), 3'000'000);
|
rsx::overlays::queue_message(localized_string(localized_string_id::AUDIO_CHANGED, "%d%%", g_cfg.audio.volume.get()), 3'000'000, {}, rsx::overlays::message_pin_location::top_left, {}, true, true);
|
||||||
}
|
}
|
||||||
} // namespace audio
|
} // namespace audio
|
||||||
|
|
|
||||||
|
|
@ -402,6 +402,7 @@ target_sources(rpcs3_emu PRIVATE
|
||||||
Io/GunCon3.cpp
|
Io/GunCon3.cpp
|
||||||
Io/Infinity.cpp
|
Io/Infinity.cpp
|
||||||
Io/interception.cpp
|
Io/interception.cpp
|
||||||
|
Io/KamenRider.cpp
|
||||||
Io/KeyboardHandler.cpp
|
Io/KeyboardHandler.cpp
|
||||||
Io/midi_config_types.cpp
|
Io/midi_config_types.cpp
|
||||||
Io/mouse_config.cpp
|
Io/mouse_config.cpp
|
||||||
|
|
@ -515,6 +516,7 @@ target_sources(rpcs3_emu PRIVATE
|
||||||
RSX/Overlays/overlay_video.cpp
|
RSX/Overlays/overlay_video.cpp
|
||||||
RSX/Overlays/Shaders/shader_loading_dialog.cpp
|
RSX/Overlays/Shaders/shader_loading_dialog.cpp
|
||||||
RSX/Overlays/Shaders/shader_loading_dialog_native.cpp
|
RSX/Overlays/Shaders/shader_loading_dialog_native.cpp
|
||||||
|
RSX/Program/Assembler/FPToCFG.cpp
|
||||||
RSX/Program/CgBinaryProgram.cpp
|
RSX/Program/CgBinaryProgram.cpp
|
||||||
RSX/Program/CgBinaryFragmentProgram.cpp
|
RSX/Program/CgBinaryFragmentProgram.cpp
|
||||||
RSX/Program/CgBinaryVertexProgram.cpp
|
RSX/Program/CgBinaryVertexProgram.cpp
|
||||||
|
|
@ -577,6 +579,7 @@ if(TARGET 3rdparty_vulkan)
|
||||||
RSX/VK/vkutils/buffer_object.cpp
|
RSX/VK/vkutils/buffer_object.cpp
|
||||||
RSX/VK/vkutils/chip_class.cpp
|
RSX/VK/vkutils/chip_class.cpp
|
||||||
RSX/VK/vkutils/commands.cpp
|
RSX/VK/vkutils/commands.cpp
|
||||||
|
RSX/VK/vkutils/ex.cpp
|
||||||
RSX/VK/vkutils/data_heap.cpp
|
RSX/VK/vkutils/data_heap.cpp
|
||||||
RSX/VK/vkutils/descriptors.cpp
|
RSX/VK/vkutils/descriptors.cpp
|
||||||
RSX/VK/vkutils/image.cpp
|
RSX/VK/vkutils/image.cpp
|
||||||
|
|
@ -589,6 +592,7 @@ if(TARGET 3rdparty_vulkan)
|
||||||
RSX/VK/vkutils/device.cpp
|
RSX/VK/vkutils/device.cpp
|
||||||
RSX/VK/vkutils/sampler.cpp
|
RSX/VK/vkutils/sampler.cpp
|
||||||
RSX/VK/vkutils/shared.cpp
|
RSX/VK/vkutils/shared.cpp
|
||||||
|
RSX/VK/vkutils/unique_resource.cpp
|
||||||
RSX/VK/VKAsyncScheduler.cpp
|
RSX/VK/VKAsyncScheduler.cpp
|
||||||
RSX/VK/VKCommandStream.cpp
|
RSX/VK/VKCommandStream.cpp
|
||||||
RSX/VK/VKCommonDecompiler.cpp
|
RSX/VK/VKCommonDecompiler.cpp
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,7 @@ struct cpu_prof
|
||||||
reservation_samples = 0;
|
reservation_samples = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string format(const std::multimap<u64, u64, std::greater<u64>>& chart, u64 samples, u64 idle, bool extended_print = false)
|
static std::string format(const std::multimap<u64, u64, std::greater<u64>>& chart, u64 samples, u64 idle, u32 type_id, bool extended_print = false)
|
||||||
{
|
{
|
||||||
// Print results
|
// Print results
|
||||||
std::string results;
|
std::string results;
|
||||||
|
|
@ -204,11 +204,18 @@ struct cpu_prof
|
||||||
const f64 _frac = count / busy / samples;
|
const f64 _frac = count / busy / samples;
|
||||||
|
|
||||||
// Print only 7 hash characters out of 11 (which covers roughly 48 bits)
|
// Print only 7 hash characters out of 11 (which covers roughly 48 bits)
|
||||||
fmt::append(results, "\n\t[%s", fmt::base57(be_t<u64>{name}));
|
if (type_id == 2)
|
||||||
results.resize(results.size() - 4);
|
{
|
||||||
|
fmt::append(results, "\n\t[%s", fmt::base57(be_t<u64>{name}));
|
||||||
|
results.resize(results.size() - 4);
|
||||||
|
|
||||||
// Print chunk address from lowest 16 bits
|
// Print chunk address from lowest 16 bits
|
||||||
fmt::append(results, "...chunk-0x%05x]: %.4f%% (%u)", (name & 0xffff) * 4, _frac * 100., count);
|
fmt::append(results, "...chunk-0x%05x]: %.4f%% (%u)", (name & 0xffff) * 4, _frac * 100., count);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fmt::append(results, "\n\t[0x%07x]: %.4f%% (%u)", name, _frac * 100., count);
|
||||||
|
}
|
||||||
|
|
||||||
if (results.size() >= (extended_print ? 10000 : 5000))
|
if (results.size() >= (extended_print ? 10000 : 5000))
|
||||||
{
|
{
|
||||||
|
|
@ -257,27 +264,37 @@ struct cpu_prof
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print results
|
// Print results
|
||||||
const std::string results = format(chart, samples, idle);
|
const std::string results = format(chart, samples, idle, ptr->id_type());
|
||||||
profiler.notice("Thread \"%s\" [0x%08x]: %u samples (%.4f%% idle), %u new, %u reservation (%.4f%%):\n%s", ptr->get_name(), ptr->id, samples, get_percent(idle, samples), new_samples, reservation_samples, get_percent(reservation_samples, samples - idle), results);
|
profiler.notice("Thread \"%s\" [0x%08x]: %u samples (%.4f%% idle), %u new, %u reservation (%.4f%%):\n%s", ptr->get_name(), ptr->id, samples, get_percent(idle, samples), new_samples, reservation_samples, get_percent(reservation_samples, samples - idle), results);
|
||||||
|
|
||||||
new_samples = 0;
|
new_samples = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_all(std::unordered_map<shared_ptr<cpu_thread>, sample_info>& threads, sample_info& all_info)
|
static void print_all(std::unordered_map<shared_ptr<cpu_thread>, sample_info>& threads, sample_info& all_info, u32 type_id)
|
||||||
{
|
{
|
||||||
u64 new_samples = 0;
|
u64 new_samples = 0;
|
||||||
|
|
||||||
// Print all results and cleanup
|
// Print all results and cleanup
|
||||||
for (auto& [ptr, info] : threads)
|
for (auto& [ptr, info] : threads)
|
||||||
{
|
{
|
||||||
|
if (ptr->id_type() != type_id)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
new_samples += info.new_samples;
|
new_samples += info.new_samples;
|
||||||
info.print(ptr);
|
info.print(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::multimap<u64, u64, std::greater<u64>> chart;
|
std::multimap<u64, u64, std::greater<u64>> chart;
|
||||||
|
|
||||||
for (auto& [_, info] : threads)
|
for (auto& [ptr, info] : threads)
|
||||||
{
|
{
|
||||||
|
if (ptr->id_type() != type_id)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// This function collects thread information regardless of 'new_samples' member state
|
// This function collects thread information regardless of 'new_samples' member state
|
||||||
for (auto& [name, count] : info.freq)
|
for (auto& [name, count] : info.freq)
|
||||||
{
|
{
|
||||||
|
|
@ -301,7 +318,7 @@ struct cpu_prof
|
||||||
|
|
||||||
if (new_samples < min_print_all_samples && thread_ctrl::state() != thread_state::aborting)
|
if (new_samples < min_print_all_samples && thread_ctrl::state() != thread_state::aborting)
|
||||||
{
|
{
|
||||||
profiler.notice("All Threads: %u samples (%.4f%% idle), %u new, %u reservation (%.4f%%): Not enough new samples have been collected since the last print.", samples, get_percent(idle, samples), new_samples, reservation, get_percent(reservation, samples - idle));
|
profiler.notice("All %s Threads: %u samples (%.4f%% idle), %u new, %u reservation (%.4f%%): Not enough new samples have been collected since the last print.", type_id == 1 ? "PPU" : "SPU", samples, get_percent(idle, samples), new_samples, reservation, get_percent(reservation, samples - idle));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -310,12 +327,13 @@ struct cpu_prof
|
||||||
chart.emplace(count, name);
|
chart.emplace(count, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string results = format(chart, samples, idle, true);
|
const std::string results = format(chart, samples, idle, type_id, true);
|
||||||
profiler.notice("All Threads: %u samples (%.4f%% idle), %u new, %u reservation (%.4f%%):%s", samples, get_percent(idle, samples), new_samples, reservation, get_percent(reservation, samples - idle), results);
|
profiler.notice("All %s Threads: %u samples (%.4f%% idle), %u new, %u reservation (%.4f%%):%s", type_id == 1 ? "PPU" : "SPU", samples, get_percent(idle, samples), new_samples, reservation, get_percent(reservation, samples - idle), results);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
sample_info all_threads_info{};
|
sample_info all_spu_threads_info{};
|
||||||
|
sample_info all_ppu_threads_info{};
|
||||||
|
|
||||||
void operator()()
|
void operator()()
|
||||||
{
|
{
|
||||||
|
|
@ -376,8 +394,11 @@ struct cpu_prof
|
||||||
{
|
{
|
||||||
if (auto state = +ptr->state; cpu_flag::exit - state)
|
if (auto state = +ptr->state; cpu_flag::exit - state)
|
||||||
{
|
{
|
||||||
|
const auto spu = ptr->try_get<spu_thread>();
|
||||||
|
const auto ppu = ptr->try_get<ppu_thread>();
|
||||||
|
|
||||||
// Get short function hash
|
// Get short function hash
|
||||||
const u64 name = atomic_storage<u64>::load(ptr->block_hash);
|
const u64 name = ppu ? atomic_storage<u32>::load(ppu->cia) : atomic_storage<u64>::load(ptr->block_hash);
|
||||||
|
|
||||||
// Append occurrence
|
// Append occurrence
|
||||||
info.samples++;
|
info.samples++;
|
||||||
|
|
@ -387,17 +408,17 @@ struct cpu_prof
|
||||||
info.freq[name]++;
|
info.freq[name]++;
|
||||||
info.new_samples++;
|
info.new_samples++;
|
||||||
|
|
||||||
if (auto spu = ptr->try_get<spu_thread>())
|
if (spu)
|
||||||
{
|
{
|
||||||
if (spu->raddr)
|
if (spu->raddr)
|
||||||
{
|
{
|
||||||
info.reservation_samples++;
|
info.reservation_samples++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Append verification time to fixed common name 0000000...chunk-0x3fffc
|
// Append verification time to fixed common name 0000000...chunk-0x3fffc
|
||||||
if (name >> 16 && (name & 0xffff) == 0)
|
if (name >> 16 && (name & 0xffff) == 0)
|
||||||
info.freq[0xffff]++;
|
info.freq[0xffff]++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -420,8 +441,10 @@ struct cpu_prof
|
||||||
{
|
{
|
||||||
profiler.success("Flushing profiling results...");
|
profiler.success("Flushing profiling results...");
|
||||||
|
|
||||||
all_threads_info = {};
|
all_ppu_threads_info = {};
|
||||||
sample_info::print_all(threads, all_threads_info);
|
all_spu_threads_info = {};
|
||||||
|
sample_info::print_all(threads, all_ppu_threads_info, 1);
|
||||||
|
sample_info::print_all(threads, all_spu_threads_info, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Emu.IsPaused())
|
if (Emu.IsPaused())
|
||||||
|
|
@ -442,7 +465,8 @@ struct cpu_prof
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print all remaining results
|
// Print all remaining results
|
||||||
sample_info::print_all(threads, all_threads_info);
|
sample_info::print_all(threads, all_ppu_threads_info, 1);
|
||||||
|
sample_info::print_all(threads, all_spu_threads_info, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr auto thread_name = "CPU Profiler"sv;
|
static constexpr auto thread_name = "CPU Profiler"sv;
|
||||||
|
|
@ -459,7 +483,7 @@ extern f64 get_cpu_program_usage_percent(u64 hash)
|
||||||
{
|
{
|
||||||
u64 total = 0;
|
u64 total = 0;
|
||||||
|
|
||||||
for (auto [name, count] : prof->all_threads_info.freq)
|
for (auto [name, count] : prof->all_spu_threads_info.freq)
|
||||||
{
|
{
|
||||||
if ((name & -65536) == hash)
|
if ((name & -65536) == hash)
|
||||||
{
|
{
|
||||||
|
|
@ -472,7 +496,7 @@ extern f64 get_cpu_program_usage_percent(u64 hash)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::max<f64>(0.0001, static_cast<f64>(total) * 100 / (prof->all_threads_info.samples - prof->all_threads_info.idle));
|
return std::max<f64>(0.0001, static_cast<f64>(total) * 100 / (prof->all_spu_threads_info.samples - prof->all_spu_threads_info.idle));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -639,27 +663,22 @@ void cpu_thread::operator()()
|
||||||
thread_ctrl::set_thread_affinity_mask(thread_ctrl::get_affinity_mask(get_class()));
|
thread_ctrl::set_thread_affinity_mask(thread_ctrl::get_affinity_mask(get_class()));
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!g_fxo->is_init<cpu_profiler>())
|
ensure(g_fxo->is_init<cpu_profiler>());
|
||||||
{
|
|
||||||
if (Emu.IsStopped())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can we have a little race, right? First thread is started concurrently with g_fxo->init()
|
|
||||||
thread_ctrl::wait_for(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (get_class())
|
switch (get_class())
|
||||||
{
|
{
|
||||||
case thread_class::ppu:
|
case thread_class::ppu:
|
||||||
{
|
{
|
||||||
//g_fxo->get<cpu_profiler>().registered.push(id);
|
if (g_cfg.core.ppu_prof)
|
||||||
|
{
|
||||||
|
g_fxo->get<cpu_profiler>().registered.push(id);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case thread_class::spu:
|
case thread_class::spu:
|
||||||
{
|
{
|
||||||
if (g_cfg.core.spu_prof)
|
if (g_cfg.core.spu_prof || g_cfg.core.spu_debug)
|
||||||
{
|
{
|
||||||
g_fxo->get<cpu_profiler>().registered.push(id);
|
g_fxo->get<cpu_profiler>().registered.push(id);
|
||||||
}
|
}
|
||||||
|
|
@ -1546,7 +1565,7 @@ void cpu_thread::flush_profilers() noexcept
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_cfg.core.spu_prof)
|
if (g_cfg.core.spu_prof || g_cfg.core.spu_debug || g_cfg.core.ppu_prof)
|
||||||
{
|
{
|
||||||
g_fxo->get<cpu_profiler>().registered.push(0);
|
g_fxo->get<cpu_profiler>().registered.push(0);
|
||||||
}
|
}
|
||||||
|
|
@ -1585,22 +1604,30 @@ extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool reve
|
||||||
|
|
||||||
idm::select<named_thread<spu_thread>>([&](u32 id, spu_thread& spu)
|
idm::select<named_thread<spu_thread>>([&](u32 id, spu_thread& spu)
|
||||||
{
|
{
|
||||||
spu_list.emplace_back(ensure(idm::get_unlocked<named_thread<spu_thread>>(id)));
|
if (give_up)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (spu.current_func && spu.unsavable)
|
if (spu.current_func && spu.unsavable && !force_collect)
|
||||||
{
|
{
|
||||||
const u64 start = spu.start_time;
|
const u64 start = spu.start_time;
|
||||||
|
|
||||||
// Automatically give up if it is asleep 15 seconds or more
|
// Automatically give up if it is asleep 5 seconds or more
|
||||||
if (start && current > start && current - start >= 15'000'000)
|
if (start && current > start && current - start >= 5'000'000)
|
||||||
{
|
{
|
||||||
give_up = true;
|
give_up = true;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spu_list.emplace_back(ensure(idm::get_unlocked<named_thread<spu_thread>>(id)));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!force_collect && give_up)
|
if (give_up)
|
||||||
{
|
{
|
||||||
|
spu_list.clear();
|
||||||
|
old_counter = umax;
|
||||||
return decltype(&spu_list){};
|
return decltype(&spu_list){};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1625,6 +1652,7 @@ extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool reve
|
||||||
}
|
}
|
||||||
else if (get_system_time() - start >= 150'000)
|
else if (get_system_time() - start >= 150'000)
|
||||||
{
|
{
|
||||||
|
std::this_thread::sleep_for(1ms);
|
||||||
passed_count++;
|
passed_count++;
|
||||||
start = 0;
|
start = 0;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -1636,37 +1664,29 @@ extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool reve
|
||||||
if (!spu_list)
|
if (!spu_list)
|
||||||
{
|
{
|
||||||
// Give up for now
|
// Give up for now
|
||||||
std::this_thread::sleep_for(10ms);
|
std::this_thread::sleep_for(50ms);
|
||||||
passed_count++;
|
passed_count++;
|
||||||
start = 0;
|
start = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Avoid using suspend_all when more than 2 threads known to be unsavable
|
// Avoid using suspend_all when more than 2 threads known to be unsavable
|
||||||
u32 unsavable_threads = 0;
|
u32 savable_threads = 0;
|
||||||
|
|
||||||
for (auto& spu : *spu_list)
|
for (auto& spu : *spu_list)
|
||||||
{
|
{
|
||||||
if (spu->unsavable)
|
if (!spu->unsavable)
|
||||||
{
|
{
|
||||||
unsavable_threads++;
|
savable_threads++;
|
||||||
|
|
||||||
if (unsavable_threads >= 3)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unsavable_threads >= 3)
|
if (!savable_threads)
|
||||||
{
|
{
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flag for optimization
|
|
||||||
bool paused_anyone = false;
|
|
||||||
|
|
||||||
if (cpu_thread::suspend_all(nullptr, {}, [&]()
|
if (cpu_thread::suspend_all(nullptr, {}, [&]()
|
||||||
{
|
{
|
||||||
if (!get_spus(false, true))
|
if (!get_spus(false, true))
|
||||||
|
|
@ -1695,19 +1715,13 @@ extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool reve
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
paused_anyone = true;
|
|
||||||
ensure(!spu->state.test_and_set(cpu_flag::dbg_global_pause));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (failed && paused_anyone)
|
for (auto& spu : *spu_list)
|
||||||
{
|
{
|
||||||
// For faster signalling, first remove state flags then batch notifications
|
if (!failed && !is_emu_paused)
|
||||||
for (auto& spu : *spu_list)
|
|
||||||
{
|
{
|
||||||
spu->state -= cpu_flag::dbg_global_pause;
|
ensure(!spu->state.test_and_set(cpu_flag::dbg_global_pause));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1719,13 +1733,6 @@ extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool reve
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!paused_anyone)
|
|
||||||
{
|
|
||||||
// Need not do anything
|
|
||||||
std::this_thread::yield();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& spu : *spu_list)
|
for (auto& spu : *spu_list)
|
||||||
{
|
{
|
||||||
if (spu->state & cpu_flag::wait)
|
if (spu->state & cpu_flag::wait)
|
||||||
|
|
@ -1755,7 +1762,7 @@ extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates(bool reve
|
||||||
{
|
{
|
||||||
spu->state.notify_one();
|
spu->state.notify_one();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4007,7 +4007,7 @@ llvm::CallInst* llvm_asm(
|
||||||
const std::string& constraints,
|
const std::string& constraints,
|
||||||
llvm::LLVMContext& context)
|
llvm::LLVMContext& context)
|
||||||
{
|
{
|
||||||
llvm::ArrayRef<llvm::Type*> types_ref = std::nullopt;
|
llvm::ArrayRef<llvm::Type*> types_ref {};
|
||||||
std::vector<llvm::Type*> types;
|
std::vector<llvm::Type*> types;
|
||||||
types.reserve(args.size());
|
types.reserve(args.size());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,41 @@ void AtracXdecDecoder::alloc_avcodec()
|
||||||
fmt::throw_exception("avcodec_find_decoder() failed");
|
fmt::throw_exception("avcodec_find_decoder() failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
ensure(!(codec->capabilities & AV_CODEC_CAP_SUBFRAMES));
|
packet = av_packet_alloc();
|
||||||
|
if (!packet)
|
||||||
|
{
|
||||||
|
fmt::throw_exception("av_packet_alloc() failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
frame = av_frame_alloc();
|
||||||
|
if (!frame)
|
||||||
|
{
|
||||||
|
fmt::throw_exception("av_frame_alloc() failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtracXdecDecoder::free_avcodec()
|
||||||
|
{
|
||||||
|
if (packet)
|
||||||
|
{
|
||||||
|
av_packet_free(&packet);
|
||||||
|
}
|
||||||
|
if (frame)
|
||||||
|
{
|
||||||
|
av_frame_free(&frame);
|
||||||
|
}
|
||||||
|
if (ctx)
|
||||||
|
{
|
||||||
|
avcodec_free_context(&ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtracXdecDecoder::init_avcodec()
|
||||||
|
{
|
||||||
|
if (ctx)
|
||||||
|
{
|
||||||
|
avcodec_free_context(&ctx);
|
||||||
|
}
|
||||||
|
|
||||||
ctx = avcodec_alloc_context3(codec);
|
ctx = avcodec_alloc_context3(codec);
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
|
|
@ -133,34 +167,6 @@ void AtracXdecDecoder::alloc_avcodec()
|
||||||
frame->buf[0] = av_buffer_create(frame->data[0], ATXDEC_SAMPLES_PER_FRAME * sizeof(f32) * frame->ch_layout.nb_channels, [](void*, uint8_t*){}, nullptr, 0);
|
frame->buf[0] = av_buffer_create(frame->data[0], ATXDEC_SAMPLES_PER_FRAME * sizeof(f32) * frame->ch_layout.nb_channels, [](void*, uint8_t*){}, nullptr, 0);
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
packet = av_packet_alloc();
|
|
||||||
if (!packet)
|
|
||||||
{
|
|
||||||
fmt::throw_exception("av_packet_alloc() failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
frame = av_frame_alloc();
|
|
||||||
if (!frame)
|
|
||||||
{
|
|
||||||
fmt::throw_exception("av_frame_alloc() failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AtracXdecDecoder::free_avcodec()
|
|
||||||
{
|
|
||||||
av_packet_free(&packet);
|
|
||||||
av_frame_free(&frame);
|
|
||||||
avcodec_free_context(&ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AtracXdecDecoder::init_avcodec()
|
|
||||||
{
|
|
||||||
if (int err = avcodec_close(ctx); err)
|
|
||||||
{
|
|
||||||
fmt::throw_exception("avcodec_close() failed (err=0x%x='%s')", err, utils::av_error_to_string(err));
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->block_align = nbytes;
|
ctx->block_align = nbytes;
|
||||||
ctx->ch_layout.nb_channels = nch_in;
|
ctx->ch_layout.nb_channels = nch_in;
|
||||||
ctx->sample_rate = sampling_freq;
|
ctx->sample_rate = sampling_freq;
|
||||||
|
|
|
||||||
|
|
@ -192,10 +192,10 @@ struct AtracXdecDecoder
|
||||||
|
|
||||||
// HLE exclusive
|
// HLE exclusive
|
||||||
b8 config_is_set = false; // For savestates
|
b8 config_is_set = false; // For savestates
|
||||||
const AVCodec* codec;
|
const AVCodec* codec = nullptr;
|
||||||
AVCodecContext* ctx;
|
AVCodecContext* ctx = nullptr;
|
||||||
AVPacket* packet;
|
AVPacket* packet = nullptr;
|
||||||
AVFrame* frame;
|
AVFrame* frame = nullptr;
|
||||||
|
|
||||||
u8 spurs_stuff[84]; // 120 bytes on LLE, pointers to CellSpurs, CellSpursTaskset, etc.
|
u8 spurs_stuff[84]; // 120 bytes on LLE, pointers to CellSpurs, CellSpursTaskset, etc.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1139,8 +1139,10 @@ error_code cellCameraGetBufferInfo(s32 dev_num, vm::ptr<CellCameraInfo> info)
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code cellCameraGetBufferInfoEx(s32 dev_num, vm::ptr<CellCameraInfoEx> info)
|
error_code cellCameraGetBufferInfoEx(ppu_thread& ppu, s32 dev_num, vm::ptr<CellCameraInfoEx> info)
|
||||||
{
|
{
|
||||||
|
ppu.state += cpu_flag::wait;
|
||||||
|
|
||||||
cellCamera.notice("cellCameraGetBufferInfoEx(dev_num=%d, info=0x%x)", dev_num, info);
|
cellCamera.notice("cellCameraGetBufferInfoEx(dev_num=%d, info=0x%x)", dev_num, info);
|
||||||
|
|
||||||
// calls cellCameraGetBufferInfo
|
// calls cellCameraGetBufferInfo
|
||||||
|
|
@ -1151,10 +1153,16 @@ error_code cellCameraGetBufferInfoEx(s32 dev_num, vm::ptr<CellCameraInfoEx> info
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& g_camera = g_fxo->get<camera_thread>();
|
auto& g_camera = g_fxo->get<camera_thread>();
|
||||||
std::lock_guard lock(g_camera.mutex);
|
|
||||||
|
|
||||||
*info = g_camera.info;
|
CellCameraInfoEx info_out;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard lock(g_camera.mutex);
|
||||||
|
|
||||||
|
info_out = g_camera.info;
|
||||||
|
}
|
||||||
|
|
||||||
|
*info = info_out;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -464,6 +464,8 @@ error_code cellHddGameCheck(ppu_thread& ppu, u32 version, vm::cptr<char> dirName
|
||||||
{
|
{
|
||||||
get->isNewData = CELL_HDDGAME_ISNEWDATA_NODIR;
|
get->isNewData = CELL_HDDGAME_ISNEWDATA_NODIR;
|
||||||
get->getParam = {};
|
get->getParam = {};
|
||||||
|
|
||||||
|
cellGame.warning("cellHddGameCheck(): New data.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -476,13 +478,22 @@ error_code cellHddGameCheck(ppu_thread& ppu, u32 version, vm::cptr<char> dirName
|
||||||
if (psf.contains("RESOLUTION")) get->getParam.resolution = ::at32(psf, "RESOLUTION").as_integer();
|
if (psf.contains("RESOLUTION")) get->getParam.resolution = ::at32(psf, "RESOLUTION").as_integer();
|
||||||
if (psf.contains("SOUND_FORMAT")) get->getParam.soundFormat = ::at32(psf, "SOUND_FORMAT").as_integer();
|
if (psf.contains("SOUND_FORMAT")) get->getParam.soundFormat = ::at32(psf, "SOUND_FORMAT").as_integer();
|
||||||
if (psf.contains("TITLE")) strcpy_trunc(get->getParam.title, ::at32(psf, "TITLE").as_string());
|
if (psf.contains("TITLE")) strcpy_trunc(get->getParam.title, ::at32(psf, "TITLE").as_string());
|
||||||
if (psf.contains("APP_VER")) strcpy_trunc(get->getParam.dataVersion, ::at32(psf, "APP_VER").as_string());
|
|
||||||
if (psf.contains("TITLE_ID")) strcpy_trunc(get->getParam.titleId, ::at32(psf, "TITLE_ID").as_string());
|
// Old games do not have APP_VER key
|
||||||
|
strcpy_trunc(get->getParam.dataVersion, psf::get_string(psf, "APP_VER", psf::get_string(sfo, "VERSION", "")));
|
||||||
|
|
||||||
|
if (psf.contains("TITLE_ID"))
|
||||||
|
{
|
||||||
|
strcpy_trunc(get->getParam.titleId, ::at32(psf, "TITLE_ID").as_string());
|
||||||
|
}
|
||||||
|
|
||||||
for (u32 i = 0; i < CELL_HDDGAME_SYSP_LANGUAGE_NUM; i++)
|
for (u32 i = 0; i < CELL_HDDGAME_SYSP_LANGUAGE_NUM; i++)
|
||||||
{
|
{
|
||||||
strcpy_trunc(get->getParam.titleLang[i], psf::get_string(psf, fmt::format("TITLE_%02d", i)));
|
strcpy_trunc(get->getParam.titleLang[i], psf::get_string(psf, fmt::format("TITLE_%02d", i)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cellGame.warning("cellHddGameCheck(): Data exists:\nATTRIBUTE: 0x%x, RESOLUTION: 0x%x, RESOLUTION: 0x%x, SOUND_FORMAT: 0x%x, dataVersion: %s"
|
||||||
|
, get->getParam.attribute, get->getParam.resolution, get->getParam.soundFormat, get->getParam.soundFormat, std::span<const u8>(reinterpret_cast<const u8*>(get->getParam.dataVersion), 6));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO ?
|
// TODO ?
|
||||||
|
|
@ -550,7 +561,7 @@ error_code cellHddGameCheck(ppu_thread& ppu, u32 version, vm::cptr<char> dirName
|
||||||
|
|
||||||
case CELL_HDDGAME_CBRESULT_ERR_NOSPACE:
|
case CELL_HDDGAME_CBRESULT_ERR_NOSPACE:
|
||||||
cellGame.error("cellHddGameCheck(): callback returned CELL_HDDGAME_CBRESULT_ERR_NOSPACE. Space Needed: %d KB", result->errNeedSizeKB);
|
cellGame.error("cellHddGameCheck(): callback returned CELL_HDDGAME_CBRESULT_ERR_NOSPACE. Space Needed: %d KB", result->errNeedSizeKB);
|
||||||
error_msg = get_localized_string(localized_string_id::CELL_HDD_GAME_CHECK_NOSPACE, fmt::format("%d", result->errNeedSizeKB).c_str());
|
error_msg = get_localized_string(localized_string_id::CELL_HDD_GAME_CHECK_NOSPACE, "%d", result->errNeedSizeKB);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CELL_HDDGAME_CBRESULT_ERR_BROKEN:
|
case CELL_HDDGAME_CBRESULT_ERR_BROKEN:
|
||||||
|
|
@ -565,12 +576,12 @@ error_code cellHddGameCheck(ppu_thread& ppu, u32 version, vm::cptr<char> dirName
|
||||||
|
|
||||||
case CELL_HDDGAME_CBRESULT_ERR_INVALID:
|
case CELL_HDDGAME_CBRESULT_ERR_INVALID:
|
||||||
cellGame.error("cellHddGameCheck(): callback returned CELL_HDDGAME_CBRESULT_ERR_INVALID. Error message: %s", result->invalidMsg);
|
cellGame.error("cellHddGameCheck(): callback returned CELL_HDDGAME_CBRESULT_ERR_INVALID. Error message: %s", result->invalidMsg);
|
||||||
error_msg = get_localized_string(localized_string_id::CELL_HDD_GAME_CHECK_INVALID, fmt::format("%s", result->invalidMsg).c_str());
|
error_msg = get_localized_string(localized_string_id::CELL_HDD_GAME_CHECK_INVALID, "%s", result->invalidMsg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
cellGame.error("cellHddGameCheck(): callback returned unknown error (code=0x%x). Error message: %s", result->invalidMsg);
|
cellGame.error("cellHddGameCheck(): callback returned unknown error (code=0x%x). Error message: %s", result->invalidMsg);
|
||||||
error_msg = get_localized_string(localized_string_id::CELL_HDD_GAME_CHECK_INVALID, fmt::format("%s", result->invalidMsg).c_str());
|
error_msg = get_localized_string(localized_string_id::CELL_HDD_GAME_CHECK_INVALID, "%s", result->invalidMsg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1169,7 +1180,7 @@ error_code cellGameDataCheckCreate2(ppu_thread& ppu, u32 version, vm::cptr<char>
|
||||||
}
|
}
|
||||||
case CELL_GAMEDATA_CBRESULT_ERR_NOSPACE:
|
case CELL_GAMEDATA_CBRESULT_ERR_NOSPACE:
|
||||||
cellGame.error("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_NOSPACE. Space Needed: %d KB", cbResult->errNeedSizeKB);
|
cellGame.error("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_NOSPACE. Space Needed: %d KB", cbResult->errNeedSizeKB);
|
||||||
error_msg = get_localized_string(localized_string_id::CELL_GAMEDATA_CHECK_NOSPACE, fmt::format("%d", cbResult->errNeedSizeKB).c_str());
|
error_msg = get_localized_string(localized_string_id::CELL_GAMEDATA_CHECK_NOSPACE, "%d", cbResult->errNeedSizeKB);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CELL_GAMEDATA_CBRESULT_ERR_BROKEN:
|
case CELL_GAMEDATA_CBRESULT_ERR_BROKEN:
|
||||||
|
|
@ -1184,12 +1195,12 @@ error_code cellGameDataCheckCreate2(ppu_thread& ppu, u32 version, vm::cptr<char>
|
||||||
|
|
||||||
case CELL_GAMEDATA_CBRESULT_ERR_INVALID:
|
case CELL_GAMEDATA_CBRESULT_ERR_INVALID:
|
||||||
cellGame.error("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_INVALID. Error message: %s", cbResult->invalidMsg);
|
cellGame.error("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_INVALID. Error message: %s", cbResult->invalidMsg);
|
||||||
error_msg = get_localized_string(localized_string_id::CELL_GAMEDATA_CHECK_INVALID, fmt::format("%s", cbResult->invalidMsg).c_str());
|
error_msg = get_localized_string(localized_string_id::CELL_GAMEDATA_CHECK_INVALID, "%s", cbResult->invalidMsg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
cellGame.error("cellGameDataCheckCreate2(): callback returned unknown error (code=0x%x). Error message: %s", cbResult->invalidMsg);
|
cellGame.error("cellGameDataCheckCreate2(): callback returned unknown error (code=0x%x). Error message: %s", cbResult->invalidMsg);
|
||||||
error_msg = get_localized_string(localized_string_id::CELL_GAMEDATA_CHECK_INVALID, fmt::format("%s", cbResult->invalidMsg).c_str());
|
error_msg = get_localized_string(localized_string_id::CELL_GAMEDATA_CHECK_INVALID, "%s", cbResult->invalidMsg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1686,7 +1697,7 @@ error_code cellGameContentErrorDialog(s32 type, s32 errNeedSizeKB, vm::cptr<char
|
||||||
break;
|
break;
|
||||||
case CELL_GAME_ERRDIALOG_NOSPACE:
|
case CELL_GAME_ERRDIALOG_NOSPACE:
|
||||||
// Not enough available space. The application will continue.
|
// Not enough available space. The application will continue.
|
||||||
error_msg = get_localized_string(localized_string_id::CELL_GAME_ERROR_NOSPACE, fmt::format("%d", errNeedSizeKB).c_str());
|
error_msg = get_localized_string(localized_string_id::CELL_GAME_ERROR_NOSPACE, "%d", errNeedSizeKB);
|
||||||
break;
|
break;
|
||||||
case CELL_GAME_ERRDIALOG_BROKEN_EXIT_GAMEDATA:
|
case CELL_GAME_ERRDIALOG_BROKEN_EXIT_GAMEDATA:
|
||||||
// Game data is corrupted. The application will be terminated.
|
// Game data is corrupted. The application will be terminated.
|
||||||
|
|
@ -1698,7 +1709,7 @@ error_code cellGameContentErrorDialog(s32 type, s32 errNeedSizeKB, vm::cptr<char
|
||||||
break;
|
break;
|
||||||
case CELL_GAME_ERRDIALOG_NOSPACE_EXIT:
|
case CELL_GAME_ERRDIALOG_NOSPACE_EXIT:
|
||||||
// Not enough available space. The application will be terminated.
|
// Not enough available space. The application will be terminated.
|
||||||
error_msg = get_localized_string(localized_string_id::CELL_GAME_ERROR_NOSPACE_EXIT, fmt::format("%d", errNeedSizeKB).c_str());
|
error_msg = get_localized_string(localized_string_id::CELL_GAME_ERROR_NOSPACE_EXIT, "%d", errNeedSizeKB);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return CELL_GAME_ERROR_PARAM;
|
return CELL_GAME_ERROR_PARAM;
|
||||||
|
|
@ -1712,7 +1723,7 @@ error_code cellGameContentErrorDialog(s32 type, s32 errNeedSizeKB, vm::cptr<char
|
||||||
}
|
}
|
||||||
|
|
||||||
error_msg += '\n';
|
error_msg += '\n';
|
||||||
error_msg += get_localized_string(localized_string_id::CELL_GAME_ERROR_DIR_NAME, fmt::format("%s", dirName).c_str());
|
error_msg += get_localized_string(localized_string_id::CELL_GAME_ERROR_DIR_NAME, "%s", dirName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return open_exit_dialog(error_msg, type > CELL_GAME_ERRDIALOG_NOSPACE, msg_dialog_source::_cellGame);
|
return open_exit_dialog(error_msg, type > CELL_GAME_ERRDIALOG_NOSPACE, msg_dialog_source::_cellGame);
|
||||||
|
|
|
||||||
|
|
@ -224,8 +224,8 @@ enum
|
||||||
struct CellGameDataSystemFileParam
|
struct CellGameDataSystemFileParam
|
||||||
{
|
{
|
||||||
char title[CELL_GAMEDATA_SYSP_TITLE_SIZE];
|
char title[CELL_GAMEDATA_SYSP_TITLE_SIZE];
|
||||||
char titleLang[CELL_GAMEDATA_SYSP_LANGUAGE_NUM][CELL_GAMEDATA_SYSP_TITLE_SIZE];
|
char titleLang[CELL_GAMEDATA_SYSP_LANGUAGE_NUM][CELL_GAMEDATA_SYSP_TITLE_SIZE]; // 0x80
|
||||||
char titleId[CELL_GAMEDATA_SYSP_TITLEID_SIZE];
|
char titleId[CELL_GAMEDATA_SYSP_TITLEID_SIZE]; // 0xA80
|
||||||
char reserved0[2];
|
char reserved0[2];
|
||||||
char dataVersion[CELL_GAMEDATA_SYSP_VERSION_SIZE];
|
char dataVersion[CELL_GAMEDATA_SYSP_VERSION_SIZE];
|
||||||
char reserved1[2];
|
char reserved1[2];
|
||||||
|
|
@ -248,13 +248,13 @@ struct CellGameDataStatGet
|
||||||
{
|
{
|
||||||
be_t<s32> hddFreeSizeKB;
|
be_t<s32> hddFreeSizeKB;
|
||||||
be_t<u32> isNewData;
|
be_t<u32> isNewData;
|
||||||
char contentInfoPath[CELL_GAMEDATA_PATH_MAX];
|
char contentInfoPath[CELL_GAMEDATA_PATH_MAX]; // 0x8
|
||||||
char gameDataPath[CELL_GAMEDATA_PATH_MAX];
|
char gameDataPath[CELL_GAMEDATA_PATH_MAX]; // 0x427
|
||||||
char reserved0[2];
|
char reserved0[2]; // 0x846
|
||||||
be_t<s64> st_atime_;
|
be_t<s64> st_atime_; // 0x848
|
||||||
be_t<s64> st_mtime_;
|
be_t<s64> st_mtime_; // 0x850
|
||||||
be_t<s64> st_ctime_;
|
be_t<s64> st_ctime_; // 0x858
|
||||||
CellGameDataSystemFileParam getParam;
|
CellGameDataSystemFileParam getParam; // 0x860
|
||||||
be_t<s32> sizeKB;
|
be_t<s32> sizeKB;
|
||||||
be_t<s32> sysSizeKB;
|
be_t<s32> sysSizeKB;
|
||||||
char reserved1[68];
|
char reserved1[68];
|
||||||
|
|
|
||||||
|
|
@ -361,7 +361,7 @@ public:
|
||||||
case move_handler::mouse:
|
case move_handler::mouse:
|
||||||
case move_handler::raw_mouse:
|
case move_handler::raw_mouse:
|
||||||
{
|
{
|
||||||
auto& handler = g_fxo->get<MouseHandlerBase>();
|
auto& handler = *ensure(g_fxo->try_get<MouseHandlerBase>());
|
||||||
std::lock_guard mouse_lock(handler.mutex);
|
std::lock_guard mouse_lock(handler.mutex);
|
||||||
const MouseInfo& info = handler.GetInfo();
|
const MouseInfo& info = handler.GetInfo();
|
||||||
|
|
||||||
|
|
@ -374,7 +374,7 @@ public:
|
||||||
#ifdef HAVE_LIBEVDEV
|
#ifdef HAVE_LIBEVDEV
|
||||||
case move_handler::gun:
|
case move_handler::gun:
|
||||||
{
|
{
|
||||||
gun_thread& gun = g_fxo->get<gun_thread>();
|
gun_thread& gun = *ensure(g_fxo->try_get<gun_thread>());
|
||||||
std::scoped_lock lock(gun.handler.mutex);
|
std::scoped_lock lock(gun.handler.mutex);
|
||||||
gun.num_devices = gun.handler.init() ? gun.handler.get_num_guns() : 0;
|
gun.num_devices = gun.handler.init() ? gun.handler.get_num_guns() : 0;
|
||||||
|
|
||||||
|
|
@ -505,7 +505,7 @@ public:
|
||||||
case move_handler::mouse:
|
case move_handler::mouse:
|
||||||
case move_handler::raw_mouse:
|
case move_handler::raw_mouse:
|
||||||
{
|
{
|
||||||
auto& handler = g_fxo->get<MouseHandlerBase>();
|
auto& handler = *ensure(g_fxo->try_get<MouseHandlerBase>());
|
||||||
std::lock_guard mouse_lock(handler.mutex);
|
std::lock_guard mouse_lock(handler.mutex);
|
||||||
|
|
||||||
// Make sure that the mouse handler is initialized
|
// Make sure that the mouse handler is initialized
|
||||||
|
|
@ -522,7 +522,7 @@ public:
|
||||||
#ifdef HAVE_LIBEVDEV
|
#ifdef HAVE_LIBEVDEV
|
||||||
case move_handler::gun:
|
case move_handler::gun:
|
||||||
{
|
{
|
||||||
gun_thread& gun = g_fxo->get<gun_thread>();
|
gun_thread& gun = *ensure(g_fxo->try_get<gun_thread>());
|
||||||
std::scoped_lock lock(gun.handler.mutex);
|
std::scoped_lock lock(gun.handler.mutex);
|
||||||
gun.num_devices = gun.handler.init() ? gun.handler.get_num_guns() : 0;
|
gun.num_devices = gun.handler.init() ? gun.handler.get_num_guns() : 0;
|
||||||
connected_controllers = std::min<u32>(std::min<u32>(attribute.max_connect, CELL_GEM_MAX_NUM), gun.num_devices);
|
connected_controllers = std::min<u32>(std::min<u32>(attribute.max_connect, CELL_GEM_MAX_NUM), gun.num_devices);
|
||||||
|
|
@ -2284,6 +2284,8 @@ error_code cellGemClearStatusFlags(u32 gem_num, u64 mask)
|
||||||
|
|
||||||
error_code cellGemConvertVideoFinish(ppu_thread& ppu)
|
error_code cellGemConvertVideoFinish(ppu_thread& ppu)
|
||||||
{
|
{
|
||||||
|
ppu.state += cpu_flag::wait;
|
||||||
|
|
||||||
cellGem.warning("cellGemConvertVideoFinish()");
|
cellGem.warning("cellGemConvertVideoFinish()");
|
||||||
|
|
||||||
auto& gem = g_fxo->get<gem_config>();
|
auto& gem = g_fxo->get<gem_config>();
|
||||||
|
|
@ -2306,8 +2308,10 @@ error_code cellGemConvertVideoFinish(ppu_thread& ppu)
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code cellGemConvertVideoStart(vm::cptr<void> video_frame)
|
error_code cellGemConvertVideoStart(ppu_thread& ppu, vm::cptr<void> video_frame)
|
||||||
{
|
{
|
||||||
|
ppu.state += cpu_flag::wait;
|
||||||
|
|
||||||
cellGem.warning("cellGemConvertVideoStart(video_frame=*0x%x)", video_frame);
|
cellGem.warning("cellGemConvertVideoStart(video_frame=*0x%x)", video_frame);
|
||||||
|
|
||||||
auto& gem = g_fxo->get<gem_config>();
|
auto& gem = g_fxo->get<gem_config>();
|
||||||
|
|
@ -2459,6 +2463,8 @@ error_code cellGemEnableMagnetometer2(u32 gem_num, u32 enable)
|
||||||
|
|
||||||
error_code cellGemEnd(ppu_thread& ppu)
|
error_code cellGemEnd(ppu_thread& ppu)
|
||||||
{
|
{
|
||||||
|
ppu.state += cpu_flag::wait;
|
||||||
|
|
||||||
cellGem.warning("cellGemEnd()");
|
cellGem.warning("cellGemEnd()");
|
||||||
|
|
||||||
auto& gem = g_fxo->get<gem_config>();
|
auto& gem = g_fxo->get<gem_config>();
|
||||||
|
|
@ -3263,7 +3269,7 @@ error_code cellGemPrepareCamera(s32 max_exposure, f32 image_quality)
|
||||||
|
|
||||||
extern error_code cellCameraGetAttribute(s32 dev_num, s32 attrib, vm::ptr<u32> arg1, vm::ptr<u32> arg2);
|
extern error_code cellCameraGetAttribute(s32 dev_num, s32 attrib, vm::ptr<u32> arg1, vm::ptr<u32> arg2);
|
||||||
extern error_code cellCameraSetAttribute(s32 dev_num, s32 attrib, u32 arg1, u32 arg2);
|
extern error_code cellCameraSetAttribute(s32 dev_num, s32 attrib, u32 arg1, u32 arg2);
|
||||||
extern error_code cellCameraGetBufferInfoEx(s32 dev_num, vm::ptr<CellCameraInfoEx> info);
|
extern error_code cellCameraGetBufferInfoEx(ppu_thread&, s32 dev_num, vm::ptr<CellCameraInfoEx> info);
|
||||||
|
|
||||||
vm::var<CellCameraInfoEx> info = vm::make_var<CellCameraInfoEx>({});
|
vm::var<CellCameraInfoEx> info = vm::make_var<CellCameraInfoEx>({});
|
||||||
vm::var<u32> arg1 = vm::make_var<u32>({});
|
vm::var<u32> arg1 = vm::make_var<u32>({});
|
||||||
|
|
@ -3271,7 +3277,7 @@ error_code cellGemPrepareCamera(s32 max_exposure, f32 image_quality)
|
||||||
|
|
||||||
cellCameraGetAttribute(0, 0x3e6, arg1, arg2);
|
cellCameraGetAttribute(0, 0x3e6, arg1, arg2);
|
||||||
cellCameraSetAttribute(0, 0x3e6, 0x3e, *arg2 | 0x80);
|
cellCameraSetAttribute(0, 0x3e6, 0x3e, *arg2 | 0x80);
|
||||||
cellCameraGetBufferInfoEx(0, info);
|
cellCameraGetBufferInfoEx(*cpu_thread::get_current<ppu_thread>(), 0, info);
|
||||||
|
|
||||||
if (info->width == 640)
|
if (info->width == 640)
|
||||||
{
|
{
|
||||||
|
|
@ -3603,6 +3609,8 @@ error_code cellGemTrackHues(vm::cptr<u32> req_hues, vm::ptr<u32> res_hues)
|
||||||
|
|
||||||
error_code cellGemUpdateFinish(ppu_thread& ppu)
|
error_code cellGemUpdateFinish(ppu_thread& ppu)
|
||||||
{
|
{
|
||||||
|
ppu.state += cpu_flag::wait;
|
||||||
|
|
||||||
cellGem.warning("cellGemUpdateFinish()");
|
cellGem.warning("cellGemUpdateFinish()");
|
||||||
|
|
||||||
auto& gem = g_fxo->get<gem_config>();
|
auto& gem = g_fxo->get<gem_config>();
|
||||||
|
|
|
||||||
|
|
@ -2498,7 +2498,7 @@ s32 UCS2stoSBCSs(vm::cptr<u16> src, vm::ptr<u32> src_len, vm::ptr<u8> dst, vm::p
|
||||||
|
|
||||||
for (u32 src_pos = 0; src_pos < *src_len; src_pos++)
|
for (u32 src_pos = 0; src_pos < *src_len; src_pos++)
|
||||||
{
|
{
|
||||||
const s16 ucs2 = src[src_pos];
|
const u16 ucs2 = src[src_pos];
|
||||||
|
|
||||||
if (ucs2 >= 0xfffe)
|
if (ucs2 >= 0xfffe)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -506,7 +506,7 @@ error_code cellMsgDialogOpenErrorCode(u32 errorCode, vm::ptr<CellMsgDialogCallba
|
||||||
default: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_DEFAULT; break; // An error has occurred.
|
default: string_id = localized_string_id::CELL_MSG_DIALOG_ERROR_DEFAULT; break; // An error has occurred.
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string error = get_localized_string(string_id, fmt::format("%08x", errorCode).c_str());
|
const std::string error = get_localized_string(string_id, "%08x", errorCode);
|
||||||
|
|
||||||
return cellMsgDialogOpen2(CELL_MSGDIALOG_TYPE_SE_TYPE_ERROR | CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK, vm::make_str(error), callback, userData, extParam);
|
return cellMsgDialogOpen2(CELL_MSGDIALOG_TYPE_SE_TYPE_ERROR | CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK, vm::make_str(error), callback, userData, extParam);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -575,12 +575,12 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
|
||||||
|
|
||||||
if (setting & CELL_PAD_SETTING_PRESS_ON)
|
if (setting & CELL_PAD_SETTING_PRESS_ON)
|
||||||
{
|
{
|
||||||
constexpr u32 copy_size = (CELL_PAD_LEN_CHANGE_PRESS_ON - CELL_PAD_BTN_OFFSET_DIGITAL1) * sizeof(u16);
|
constexpr u32 copy_size = (static_cast<u32>(CELL_PAD_LEN_CHANGE_PRESS_ON) - static_cast<u32>(CELL_PAD_BTN_OFFSET_DIGITAL1)) * sizeof(u16);
|
||||||
std::memcpy(&data->button[CELL_PAD_BTN_OFFSET_DIGITAL1], &output.button[CELL_PAD_BTN_OFFSET_DIGITAL1], copy_size);
|
std::memcpy(&data->button[CELL_PAD_BTN_OFFSET_DIGITAL1], &output.button[CELL_PAD_BTN_OFFSET_DIGITAL1], copy_size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
constexpr u32 copy_size = (CELL_PAD_LEN_CHANGE_DEFAULT - CELL_PAD_BTN_OFFSET_DIGITAL1) * sizeof(u16);
|
constexpr u32 copy_size = (static_cast<u32>(CELL_PAD_LEN_CHANGE_DEFAULT) - static_cast<u32>(CELL_PAD_BTN_OFFSET_DIGITAL1)) * sizeof(u16);
|
||||||
std::memcpy(&data->button[CELL_PAD_BTN_OFFSET_DIGITAL1], &output.button[CELL_PAD_BTN_OFFSET_DIGITAL1], copy_size);
|
std::memcpy(&data->button[CELL_PAD_BTN_OFFSET_DIGITAL1], &output.button[CELL_PAD_BTN_OFFSET_DIGITAL1], copy_size);
|
||||||
|
|
||||||
// Clear area if setting is not used
|
// Clear area if setting is not used
|
||||||
|
|
@ -590,7 +590,7 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
|
||||||
|
|
||||||
if (data->len == CELL_PAD_LEN_CHANGE_SENSOR_ON)
|
if (data->len == CELL_PAD_LEN_CHANGE_SENSOR_ON)
|
||||||
{
|
{
|
||||||
constexpr u32 copy_size = (CELL_PAD_LEN_CHANGE_SENSOR_ON - CELL_PAD_BTN_OFFSET_SENSOR_X) * sizeof(u16);
|
constexpr u32 copy_size = (static_cast<u32>(CELL_PAD_LEN_CHANGE_SENSOR_ON) - static_cast<u32>(CELL_PAD_BTN_OFFSET_SENSOR_X)) * sizeof(u16);
|
||||||
std::memcpy(&data->button[CELL_PAD_BTN_OFFSET_SENSOR_X], &output.button[CELL_PAD_BTN_OFFSET_SENSOR_X], copy_size);
|
std::memcpy(&data->button[CELL_PAD_BTN_OFFSET_SENSOR_X], &output.button[CELL_PAD_BTN_OFFSET_SENSOR_X], copy_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1051,7 +1051,15 @@ error_code cellPadSetPortSetting(u32 port_no, u32 port_setting)
|
||||||
if (port_no >= CELL_PAD_MAX_PORT_NUM)
|
if (port_no >= CELL_PAD_MAX_PORT_NUM)
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
|
|
||||||
config.port_setting[port_no] = port_setting;
|
if (port_setting & CELL_PAD_SETTING_PRESS_ON)
|
||||||
|
config.port_setting[port_no] |= CELL_PAD_SETTING_PRESS_ON;
|
||||||
|
else
|
||||||
|
config.port_setting[port_no] &= ~CELL_PAD_SETTING_PRESS_ON;
|
||||||
|
|
||||||
|
if (port_setting & CELL_PAD_SETTING_SENSOR_ON)
|
||||||
|
config.port_setting[port_no] |= CELL_PAD_SETTING_SENSOR_ON;
|
||||||
|
else
|
||||||
|
config.port_setting[port_no] &= ~CELL_PAD_SETTING_SENSOR_ON;
|
||||||
|
|
||||||
// can also return CELL_PAD_ERROR_UNSUPPORTED_GAMEPAD <- Update: seems to be just internal and ignored
|
// can also return CELL_PAD_ERROR_UNSUPPORTED_GAMEPAD <- Update: seems to be just internal and ignored
|
||||||
|
|
||||||
|
|
@ -1123,7 +1131,7 @@ error_code cellPadSetPressMode(u32 port_no, u32 mode)
|
||||||
if (!config.max_connect)
|
if (!config.max_connect)
|
||||||
return CELL_PAD_ERROR_UNINITIALIZED;
|
return CELL_PAD_ERROR_UNINITIALIZED;
|
||||||
|
|
||||||
if (port_no >= CELL_PAD_MAX_PORT_NUM)
|
if (port_no >= CELL_MAX_PADS || mode > 1)
|
||||||
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
// CELL_PAD_ERROR_NO_DEVICE is not returned in this case.
|
// CELL_PAD_ERROR_NO_DEVICE is not returned in this case.
|
||||||
|
|
@ -1157,7 +1165,7 @@ error_code cellPadSetSensorMode(u32 port_no, u32 mode)
|
||||||
if (!config.max_connect)
|
if (!config.max_connect)
|
||||||
return CELL_PAD_ERROR_UNINITIALIZED;
|
return CELL_PAD_ERROR_UNINITIALIZED;
|
||||||
|
|
||||||
if (port_no >= CELL_MAX_PADS)
|
if (port_no >= CELL_MAX_PADS || mode > 1)
|
||||||
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
return CELL_PAD_ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
// CELL_PAD_ERROR_NO_DEVICE is not returned in this case.
|
// CELL_PAD_ERROR_NO_DEVICE is not returned in this case.
|
||||||
|
|
|
||||||
|
|
@ -396,7 +396,7 @@ static error_code display_callback_result_error_message(ppu_thread& ppu, const C
|
||||||
switch (result.result)
|
switch (result.result)
|
||||||
{
|
{
|
||||||
case CELL_SAVEDATA_CBRESULT_ERR_NOSPACE:
|
case CELL_SAVEDATA_CBRESULT_ERR_NOSPACE:
|
||||||
msg = get_localized_string(localized_string_id::CELL_SAVEDATA_CB_NO_SPACE, fmt::format("%d", result.errNeedSizeKB).c_str());
|
msg = get_localized_string(localized_string_id::CELL_SAVEDATA_CB_NO_SPACE, "%d", result.errNeedSizeKB);
|
||||||
break;
|
break;
|
||||||
case CELL_SAVEDATA_CBRESULT_ERR_FAILURE:
|
case CELL_SAVEDATA_CBRESULT_ERR_FAILURE:
|
||||||
msg = get_localized_string(localized_string_id::CELL_SAVEDATA_CB_FAILURE);
|
msg = get_localized_string(localized_string_id::CELL_SAVEDATA_CB_FAILURE);
|
||||||
|
|
|
||||||
|
|
@ -1230,7 +1230,7 @@ s32 _spurs::initialize(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 revision,
|
||||||
if (flags & SAF_UNKNOWN_FLAG_9) spuTgAttr->type |= 0x0800;
|
if (flags & SAF_UNKNOWN_FLAG_9) spuTgAttr->type |= 0x0800;
|
||||||
if (flags & SAF_SYSTEM_WORKLOAD_ENABLED) spuTgAttr->type |= SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM;
|
if (flags & SAF_SYSTEM_WORKLOAD_ENABLED) spuTgAttr->type |= SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM;
|
||||||
|
|
||||||
if (s32 rc = sys_spu_thread_group_create(ppu, spurs.ptr(&CellSpurs::spuTG), nSpus, spuPriority, spuTgAttr))
|
if (s32 rc = sys_spu_thread_group_create(ppu, spurs.ptr(&CellSpurs::spuTG), nSpus, spuPriority, vm::unsafe_ptr_cast<reduced_sys_spu_thread_group_attribute>(spuTgAttr)))
|
||||||
{
|
{
|
||||||
ppu_execute<&sys_spu_image_close>(ppu, spurs.ptr(&CellSpurs::spuImg));
|
ppu_execute<&sys_spu_image_close>(ppu, spurs.ptr(&CellSpurs::spuImg));
|
||||||
return rollback(), rc;
|
return rollback(), rc;
|
||||||
|
|
|
||||||
|
|
@ -3198,7 +3198,7 @@ error_code sceNpLookupTerm()
|
||||||
|
|
||||||
error_code sceNpLookupCreateTitleCtx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpId> selfNpId)
|
error_code sceNpLookupCreateTitleCtx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpId> selfNpId)
|
||||||
{
|
{
|
||||||
sceNp.warning("sceNpLookupCreateTitleCtx(communicationId=*0x%x(%s), selfNpId=0x%x)", communicationId, communicationId ? communicationId->data : "", selfNpId);
|
sceNp.warning("sceNpLookupCreateTitleCtx(communicationId=*0x%x(%s), selfNpId=0x%x)", communicationId, communicationId ? std::string_view(communicationId->data, 9) : "", selfNpId);
|
||||||
|
|
||||||
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
|
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
|
||||||
|
|
||||||
|
|
@ -3930,8 +3930,8 @@ error_code sceNpManagerGetMyLanguages(vm::ptr<SceNpMyLanguages> myLanguages)
|
||||||
return SCE_NP_ERROR_INVALID_STATE;
|
return SCE_NP_ERROR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
myLanguages->language1 = SCE_NP_LANG_ENGLISH_US;
|
myLanguages->language1 = g_cfg.sys.language;
|
||||||
myLanguages->language2 = g_cfg.sys.language != CELL_SYSUTIL_LANG_ENGLISH_US ? g_cfg.sys.language : -1;
|
myLanguages->language2 = g_cfg.sys.language != CELL_SYSUTIL_LANG_ENGLISH_US ? CELL_SYSUTIL_LANG_ENGLISH_US : -1;
|
||||||
myLanguages->language3 = -1;
|
myLanguages->language3 = -1;
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
|
|
@ -3968,7 +3968,7 @@ error_code sceNpManagerGetAccountRegion(vm::ptr<SceNpCountryCode> countryCode, v
|
||||||
ensure(ccode.size() == sizeof(SceNpCountryCode::data));
|
ensure(ccode.size() == sizeof(SceNpCountryCode::data));
|
||||||
std::memcpy(countryCode->data, ccode.data(), sizeof(SceNpCountryCode::data));
|
std::memcpy(countryCode->data, ccode.data(), sizeof(SceNpCountryCode::data));
|
||||||
|
|
||||||
*language = CELL_SYSUTIL_LANG_ENGLISH_US;
|
*language = g_cfg.sys.language;
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
@ -6962,7 +6962,7 @@ error_code sceNpSignalingGetConnectionFromPeerAddress(u32 ctx_id, np_in_addr_t p
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code sceNpSignalingGetLocalNetInfo(u32 ctx_id, vm::ptr<SceNpSignalingNetInfo> info)
|
error_code sceNpSignalingGetLocalNetInfo(u32 ctx_id, vm::ptr<SceNpSignalingNetInfoDeprecated> info)
|
||||||
{
|
{
|
||||||
sceNp.warning("sceNpSignalingGetLocalNetInfo(ctx_id=%d, info=*0x%x)", ctx_id, info);
|
sceNp.warning("sceNpSignalingGetLocalNetInfo(ctx_id=%d, info=*0x%x)", ctx_id, info);
|
||||||
|
|
||||||
|
|
@ -6973,7 +6973,8 @@ error_code sceNpSignalingGetLocalNetInfo(u32 ctx_id, vm::ptr<SceNpSignalingNetIn
|
||||||
return SCE_NP_SIGNALING_ERROR_NOT_INITIALIZED;
|
return SCE_NP_SIGNALING_ERROR_NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!info || info->size != sizeof(SceNpSignalingNetInfo))
|
// Library has backward support for a version of SceNpSignalingNetInfo without npport
|
||||||
|
if (!info || (info->size != sizeof(SceNpSignalingNetInfo) && info->size != sizeof(SceNpSignalingNetInfoDeprecated)))
|
||||||
{
|
{
|
||||||
return SCE_NP_SIGNALING_ERROR_INVALID_ARGUMENT;
|
return SCE_NP_SIGNALING_ERROR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
@ -6985,7 +6986,12 @@ error_code sceNpSignalingGetLocalNetInfo(u32 ctx_id, vm::ptr<SceNpSignalingNetIn
|
||||||
info->nat_status = SCE_NP_SIGNALING_NETINFO_NAT_STATUS_TYPE2;
|
info->nat_status = SCE_NP_SIGNALING_NETINFO_NAT_STATUS_TYPE2;
|
||||||
info->upnp_status = nph.get_upnp_status();
|
info->upnp_status = nph.get_upnp_status();
|
||||||
info->npport_status = SCE_NP_SIGNALING_NETINFO_NPPORT_STATUS_OPEN;
|
info->npport_status = SCE_NP_SIGNALING_NETINFO_NPPORT_STATUS_OPEN;
|
||||||
info->npport = SCE_NP_PORT;
|
|
||||||
|
if (info->size == sizeof(SceNpSignalingNetInfo))
|
||||||
|
{
|
||||||
|
auto new_info = vm::unsafe_ptr_cast<SceNpSignalingNetInfo>(info);
|
||||||
|
new_info->npport = SCE_NP_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1584,6 +1584,16 @@ struct SceNpSignalingNetInfo
|
||||||
be_t<u16> npport;
|
be_t<u16> npport;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SceNpSignalingNetInfoDeprecated
|
||||||
|
{
|
||||||
|
be_t<u32> size;
|
||||||
|
be_t<u32> local_addr; // in_addr
|
||||||
|
be_t<u32> mapped_addr; // in_addr
|
||||||
|
be_t<s32> nat_status;
|
||||||
|
be_t<s32> upnp_status;
|
||||||
|
be_t<s32> npport_status;
|
||||||
|
};
|
||||||
|
|
||||||
struct SceNpCustomMenuAction
|
struct SceNpCustomMenuAction
|
||||||
{
|
{
|
||||||
be_t<u32> options;
|
be_t<u32> options;
|
||||||
|
|
|
||||||
|
|
@ -1300,7 +1300,7 @@ error_code sceNpMatching2GrantRoomOwner(
|
||||||
error_code sceNpMatching2CreateContext(
|
error_code sceNpMatching2CreateContext(
|
||||||
vm::cptr<SceNpId> npId, vm::cptr<SceNpCommunicationId> commId, vm::cptr<SceNpCommunicationPassphrase> passPhrase, vm::ptr<SceNpMatching2ContextId> ctxId, s32 option)
|
vm::cptr<SceNpId> npId, vm::cptr<SceNpCommunicationId> commId, vm::cptr<SceNpCommunicationPassphrase> passPhrase, vm::ptr<SceNpMatching2ContextId> ctxId, s32 option)
|
||||||
{
|
{
|
||||||
sceNp2.warning("sceNpMatching2CreateContext(npId=*0x%x, commId=*0x%x(%s), passPhrase=*0x%x, ctxId=*0x%x, option=%d)", npId, commId, commId ? commId->data : "", passPhrase, ctxId, option);
|
sceNp2.warning("sceNpMatching2CreateContext(npId=*0x%x, commId=*0x%x(%s), passPhrase=*0x%x, ctxId=*0x%x, option=%d)", npId, commId, commId ? std::string_view(commId->data, 9) : "", passPhrase, ctxId, option);
|
||||||
|
|
||||||
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
|
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
#include "util/types.hpp"
|
#include "util/types.hpp"
|
||||||
#include "Emu/Memory/vm_ptr.h"
|
#include "Emu/Memory/vm_ptr.h"
|
||||||
#include "Emu/Cell/ErrorCodes.h"
|
#include "Emu/Cell/ErrorCodes.h"
|
||||||
#include <mutex>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -221,7 +221,7 @@ std::pair<PPUDisAsm::const_op, u64> PPUDisAsm::try_get_const_op_gpr_value(u32 re
|
||||||
|
|
||||||
GET_CONST_REG(reg_rs, op.rs);
|
GET_CONST_REG(reg_rs, op.rs);
|
||||||
|
|
||||||
return { form, utils::rol64(reg_rs, op.sh64) & (~0ull << (op.mbe64 ^ 63)) };
|
return {form, std::rotl<u64>(reg_rs, op.sh64) & (~0ull << (op.mbe64 ^ 63))};
|
||||||
}
|
}
|
||||||
case ppu_itype::OR:
|
case ppu_itype::OR:
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3483,7 +3483,7 @@ auto RLWIMI()
|
||||||
|
|
||||||
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
|
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
|
||||||
const u64 mask = ppu_rotate_mask(32 + op.mb32, 32 + op.me32);
|
const u64 mask = ppu_rotate_mask(32 + op.mb32, 32 + op.me32);
|
||||||
ppu.gpr[op.ra] = (ppu.gpr[op.ra] & ~mask) | (dup32(utils::rol32(static_cast<u32>(ppu.gpr[op.rs]), op.sh32)) & mask);
|
ppu.gpr[op.ra] = (ppu.gpr[op.ra] & ~mask) | (dup32(std::rotl<u32>(static_cast<u32>(ppu.gpr[op.rs]), op.sh32)) & mask);
|
||||||
if constexpr (((Flags == has_rc) || ...))
|
if constexpr (((Flags == has_rc) || ...))
|
||||||
ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
||||||
};
|
};
|
||||||
|
|
@ -3497,7 +3497,7 @@ auto RLWINM()
|
||||||
return ppu_exec_select<Flags...>::template select<>();
|
return ppu_exec_select<Flags...>::template select<>();
|
||||||
|
|
||||||
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
|
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
|
||||||
ppu.gpr[op.ra] = dup32(utils::rol32(static_cast<u32>(ppu.gpr[op.rs]), op.sh32)) & ppu_rotate_mask(32 + op.mb32, 32 + op.me32);
|
ppu.gpr[op.ra] = dup32(std::rotl<u32>(static_cast<u32>(ppu.gpr[op.rs]), op.sh32)) & ppu_rotate_mask(32 + op.mb32, 32 + op.me32);
|
||||||
if constexpr (((Flags == has_rc) || ...))
|
if constexpr (((Flags == has_rc) || ...))
|
||||||
ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
||||||
};
|
};
|
||||||
|
|
@ -3511,7 +3511,7 @@ auto RLWNM()
|
||||||
return ppu_exec_select<Flags...>::template select<>();
|
return ppu_exec_select<Flags...>::template select<>();
|
||||||
|
|
||||||
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
|
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
|
||||||
ppu.gpr[op.ra] = dup32(utils::rol32(static_cast<u32>(ppu.gpr[op.rs]), ppu.gpr[op.rb] & 0x1f)) & ppu_rotate_mask(32 + op.mb32, 32 + op.me32);
|
ppu.gpr[op.ra] = dup32(std::rotl<u32>(static_cast<u32>(ppu.gpr[op.rs]), ppu.gpr[op.rb] & 0x1f)) & ppu_rotate_mask(32 + op.mb32, 32 + op.me32);
|
||||||
if constexpr (((Flags == has_rc) || ...))
|
if constexpr (((Flags == has_rc) || ...))
|
||||||
ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
||||||
};
|
};
|
||||||
|
|
@ -3599,7 +3599,7 @@ auto RLDICL()
|
||||||
return ppu_exec_select<Flags...>::template select<>();
|
return ppu_exec_select<Flags...>::template select<>();
|
||||||
|
|
||||||
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
|
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
|
||||||
ppu.gpr[op.ra] = utils::rol64(ppu.gpr[op.rs], op.sh64) & (~0ull >> op.mbe64);
|
ppu.gpr[op.ra] = std::rotl<u64>(ppu.gpr[op.rs], op.sh64) & (~0ull >> op.mbe64);
|
||||||
if constexpr (((Flags == has_rc) || ...))
|
if constexpr (((Flags == has_rc) || ...))
|
||||||
ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
||||||
};
|
};
|
||||||
|
|
@ -3613,7 +3613,7 @@ auto RLDICR()
|
||||||
return ppu_exec_select<Flags...>::template select<>();
|
return ppu_exec_select<Flags...>::template select<>();
|
||||||
|
|
||||||
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
|
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
|
||||||
ppu.gpr[op.ra] = utils::rol64(ppu.gpr[op.rs], op.sh64) & (~0ull << (op.mbe64 ^ 63));
|
ppu.gpr[op.ra] = std::rotl<u64>(ppu.gpr[op.rs], op.sh64) & (~0ull << (op.mbe64 ^ 63));
|
||||||
if constexpr (((Flags == has_rc) || ...))
|
if constexpr (((Flags == has_rc) || ...))
|
||||||
ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
||||||
};
|
};
|
||||||
|
|
@ -3627,7 +3627,7 @@ auto RLDIC()
|
||||||
return ppu_exec_select<Flags...>::template select<>();
|
return ppu_exec_select<Flags...>::template select<>();
|
||||||
|
|
||||||
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
|
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
|
||||||
ppu.gpr[op.ra] = utils::rol64(ppu.gpr[op.rs], op.sh64) & ppu_rotate_mask(op.mbe64, op.sh64 ^ 63);
|
ppu.gpr[op.ra] = std::rotl<u64>(ppu.gpr[op.rs], op.sh64) & ppu_rotate_mask(op.mbe64, op.sh64 ^ 63);
|
||||||
if constexpr (((Flags == has_rc) || ...))
|
if constexpr (((Flags == has_rc) || ...))
|
||||||
ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
||||||
};
|
};
|
||||||
|
|
@ -3642,7 +3642,7 @@ auto RLDIMI()
|
||||||
|
|
||||||
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
|
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
|
||||||
const u64 mask = ppu_rotate_mask(op.mbe64, op.sh64 ^ 63);
|
const u64 mask = ppu_rotate_mask(op.mbe64, op.sh64 ^ 63);
|
||||||
ppu.gpr[op.ra] = (ppu.gpr[op.ra] & ~mask) | (utils::rol64(ppu.gpr[op.rs], op.sh64) & mask);
|
ppu.gpr[op.ra] = (ppu.gpr[op.ra] & ~mask) | (std::rotl<u64>(ppu.gpr[op.rs], op.sh64) & mask);
|
||||||
if constexpr (((Flags == has_rc) || ...))
|
if constexpr (((Flags == has_rc) || ...))
|
||||||
ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
||||||
};
|
};
|
||||||
|
|
@ -3656,7 +3656,7 @@ auto RLDCL()
|
||||||
return ppu_exec_select<Flags...>::template select<>();
|
return ppu_exec_select<Flags...>::template select<>();
|
||||||
|
|
||||||
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
|
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
|
||||||
ppu.gpr[op.ra] = utils::rol64(ppu.gpr[op.rs], ppu.gpr[op.rb] & 0x3f) & (~0ull >> op.mbe64);
|
ppu.gpr[op.ra] = std::rotl<u64>(ppu.gpr[op.rs], ppu.gpr[op.rb] & 0x3f) & (~0ull >> op.mbe64);
|
||||||
if constexpr (((Flags == has_rc) || ...))
|
if constexpr (((Flags == has_rc) || ...))
|
||||||
ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
||||||
};
|
};
|
||||||
|
|
@ -3670,7 +3670,7 @@ auto RLDCR()
|
||||||
return ppu_exec_select<Flags...>::template select<>();
|
return ppu_exec_select<Flags...>::template select<>();
|
||||||
|
|
||||||
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
|
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
|
||||||
ppu.gpr[op.ra] = utils::rol64(ppu.gpr[op.rs], ppu.gpr[op.rb] & 0x3f) & (~0ull << (op.mbe64 ^ 63));
|
ppu.gpr[op.ra] = std::rotl<u64>(ppu.gpr[op.rs], ppu.gpr[op.rb] & 0x3f) & (~0ull << (op.mbe64 ^ 63));
|
||||||
if constexpr (((Flags == has_rc) || ...))
|
if constexpr (((Flags == has_rc) || ...))
|
||||||
ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
ppu_cr_set<s64>(ppu, 0, ppu.gpr[op.ra], 0);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -832,6 +832,9 @@ extern void ppu_register_function_at(u32 addr, u32 size, ppu_intrp_func_t ptr =
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size = utils::align<u32>(size + addr % 4, 4);
|
||||||
|
addr &= -4;
|
||||||
|
|
||||||
// Initialize interpreter cache
|
// Initialize interpreter cache
|
||||||
while (size)
|
while (size)
|
||||||
{
|
{
|
||||||
|
|
@ -2308,7 +2311,7 @@ void ppu_thread::cpu_sleep()
|
||||||
raddr = 0;
|
raddr = 0;
|
||||||
|
|
||||||
// Setup wait flag and memory flags to relock itself
|
// Setup wait flag and memory flags to relock itself
|
||||||
state += g_use_rtm ? cpu_flag::wait : cpu_flag::wait + cpu_flag::memory;
|
state += cpu_flag::wait + cpu_flag::memory;
|
||||||
|
|
||||||
if (auto ptr = vm::g_tls_locked)
|
if (auto ptr = vm::g_tls_locked)
|
||||||
{
|
{
|
||||||
|
|
@ -2454,10 +2457,8 @@ ppu_thread::ppu_thread(const ppu_thread_params& param, std::string_view name, u3
|
||||||
// Trigger the scheduler
|
// Trigger the scheduler
|
||||||
state += cpu_flag::suspend;
|
state += cpu_flag::suspend;
|
||||||
|
|
||||||
if (!g_use_rtm)
|
// Acquire memory passive lock
|
||||||
{
|
state += cpu_flag::memory;
|
||||||
state += cpu_flag::memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
call_history.data.resize(g_cfg.core.ppu_call_history ? call_history_max_size : 1);
|
call_history.data.resize(g_cfg.core.ppu_call_history ? call_history_max_size : 1);
|
||||||
syscall_history.data.resize(g_cfg.core.ppu_call_history ? syscall_history_max_size : 1);
|
syscall_history.data.resize(g_cfg.core.ppu_call_history ? syscall_history_max_size : 1);
|
||||||
|
|
@ -2703,11 +2704,7 @@ ppu_thread::ppu_thread(utils::serial& ar)
|
||||||
|
|
||||||
// Trigger the scheduler
|
// Trigger the scheduler
|
||||||
state += cpu_flag::suspend;
|
state += cpu_flag::suspend;
|
||||||
|
state += cpu_flag::memory;
|
||||||
if (!g_use_rtm)
|
|
||||||
{
|
|
||||||
state += cpu_flag::memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
ppu_tname = make_single<std::string>(ar.pop<std::string>());
|
ppu_tname = make_single<std::string>(ar.pop<std::string>());
|
||||||
|
|
||||||
|
|
@ -3191,221 +3188,6 @@ extern u64 ppu_ldarx(ppu_thread& ppu, u32 addr)
|
||||||
return ppu_load_acquire_reservation<u64>(ppu, addr);
|
return ppu_load_acquire_reservation<u64>(ppu, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto ppu_stcx_accurate_tx = build_function_asm<u64(*)(u32 raddr, u64 rtime, const void* _old, u64 _new)>("ppu_stcx_accurate_tx", [](native_asm& c, auto& args)
|
|
||||||
{
|
|
||||||
using namespace asmjit;
|
|
||||||
|
|
||||||
#if defined(ARCH_X64)
|
|
||||||
Label fall = c.newLabel();
|
|
||||||
Label fail = c.newLabel();
|
|
||||||
Label _ret = c.newLabel();
|
|
||||||
Label load = c.newLabel();
|
|
||||||
|
|
||||||
//if (utils::has_avx() && !s_tsx_avx)
|
|
||||||
//{
|
|
||||||
// c.vzeroupper();
|
|
||||||
//}
|
|
||||||
|
|
||||||
// Create stack frame if necessary (Windows ABI has only 6 volatile vector registers)
|
|
||||||
c.push(x86::rbp);
|
|
||||||
c.push(x86::r13);
|
|
||||||
c.push(x86::r14);
|
|
||||||
c.sub(x86::rsp, 48);
|
|
||||||
#ifdef _WIN32
|
|
||||||
if (!s_tsx_avx)
|
|
||||||
{
|
|
||||||
c.movups(x86::oword_ptr(x86::rsp, 0), x86::xmm6);
|
|
||||||
c.movups(x86::oword_ptr(x86::rsp, 16), x86::xmm7);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Prepare registers
|
|
||||||
build_swap_rdx_with(c, args, x86::r10);
|
|
||||||
c.movabs(x86::rbp, reinterpret_cast<u64>(&vm::g_sudo_addr));
|
|
||||||
c.mov(x86::rbp, x86::qword_ptr(x86::rbp));
|
|
||||||
c.lea(x86::rbp, x86::qword_ptr(x86::rbp, args[0]));
|
|
||||||
c.and_(x86::rbp, -128);
|
|
||||||
c.prefetchw(x86::byte_ptr(x86::rbp, 0));
|
|
||||||
c.prefetchw(x86::byte_ptr(x86::rbp, 64));
|
|
||||||
c.movzx(args[0].r32(), args[0].r16());
|
|
||||||
c.shr(args[0].r32(), 1);
|
|
||||||
c.movabs(x86::r11, reinterpret_cast<u64>(+vm::g_reservations));
|
|
||||||
c.lea(x86::r11, x86::qword_ptr(x86::r11, args[0]));
|
|
||||||
c.and_(x86::r11, -128 / 2);
|
|
||||||
c.and_(args[0].r32(), 63);
|
|
||||||
|
|
||||||
// Prepare data
|
|
||||||
if (s_tsx_avx)
|
|
||||||
{
|
|
||||||
c.vmovups(x86::ymm0, x86::ymmword_ptr(args[2], 0));
|
|
||||||
c.vmovups(x86::ymm1, x86::ymmword_ptr(args[2], 32));
|
|
||||||
c.vmovups(x86::ymm2, x86::ymmword_ptr(args[2], 64));
|
|
||||||
c.vmovups(x86::ymm3, x86::ymmword_ptr(args[2], 96));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
c.movaps(x86::xmm0, x86::oword_ptr(args[2], 0));
|
|
||||||
c.movaps(x86::xmm1, x86::oword_ptr(args[2], 16));
|
|
||||||
c.movaps(x86::xmm2, x86::oword_ptr(args[2], 32));
|
|
||||||
c.movaps(x86::xmm3, x86::oword_ptr(args[2], 48));
|
|
||||||
c.movaps(x86::xmm4, x86::oword_ptr(args[2], 64));
|
|
||||||
c.movaps(x86::xmm5, x86::oword_ptr(args[2], 80));
|
|
||||||
c.movaps(x86::xmm6, x86::oword_ptr(args[2], 96));
|
|
||||||
c.movaps(x86::xmm7, x86::oword_ptr(args[2], 112));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alloc r14 to stamp0
|
|
||||||
const auto stamp0 = x86::r14;
|
|
||||||
build_get_tsc(c, stamp0);
|
|
||||||
|
|
||||||
Label fail2 = c.newLabel();
|
|
||||||
|
|
||||||
Label tx1 = build_transaction_enter(c, fall, [&]()
|
|
||||||
{
|
|
||||||
build_get_tsc(c);
|
|
||||||
c.sub(x86::rax, stamp0);
|
|
||||||
c.movabs(x86::r13, reinterpret_cast<u64>(&g_rtm_tx_limit2));
|
|
||||||
c.cmp(x86::rax, x86::qword_ptr(x86::r13));
|
|
||||||
c.jae(fall);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Check pause flag
|
|
||||||
c.bt(x86::dword_ptr(args[2], ::offset32(&ppu_thread::state) - ::offset32(&ppu_thread::rdata)), static_cast<u32>(cpu_flag::pause));
|
|
||||||
c.jc(fall);
|
|
||||||
c.xbegin(tx1);
|
|
||||||
|
|
||||||
if (s_tsx_avx)
|
|
||||||
{
|
|
||||||
c.vxorps(x86::ymm0, x86::ymm0, x86::ymmword_ptr(x86::rbp, 0));
|
|
||||||
c.vxorps(x86::ymm1, x86::ymm1, x86::ymmword_ptr(x86::rbp, 32));
|
|
||||||
c.vxorps(x86::ymm2, x86::ymm2, x86::ymmword_ptr(x86::rbp, 64));
|
|
||||||
c.vxorps(x86::ymm3, x86::ymm3, x86::ymmword_ptr(x86::rbp, 96));
|
|
||||||
c.vorps(x86::ymm0, x86::ymm0, x86::ymm1);
|
|
||||||
c.vorps(x86::ymm1, x86::ymm2, x86::ymm3);
|
|
||||||
c.vorps(x86::ymm0, x86::ymm1, x86::ymm0);
|
|
||||||
c.vptest(x86::ymm0, x86::ymm0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
c.xorps(x86::xmm0, x86::oword_ptr(x86::rbp, 0));
|
|
||||||
c.xorps(x86::xmm1, x86::oword_ptr(x86::rbp, 16));
|
|
||||||
c.xorps(x86::xmm2, x86::oword_ptr(x86::rbp, 32));
|
|
||||||
c.xorps(x86::xmm3, x86::oword_ptr(x86::rbp, 48));
|
|
||||||
c.xorps(x86::xmm4, x86::oword_ptr(x86::rbp, 64));
|
|
||||||
c.xorps(x86::xmm5, x86::oword_ptr(x86::rbp, 80));
|
|
||||||
c.xorps(x86::xmm6, x86::oword_ptr(x86::rbp, 96));
|
|
||||||
c.xorps(x86::xmm7, x86::oword_ptr(x86::rbp, 112));
|
|
||||||
c.orps(x86::xmm0, x86::xmm1);
|
|
||||||
c.orps(x86::xmm2, x86::xmm3);
|
|
||||||
c.orps(x86::xmm4, x86::xmm5);
|
|
||||||
c.orps(x86::xmm6, x86::xmm7);
|
|
||||||
c.orps(x86::xmm0, x86::xmm2);
|
|
||||||
c.orps(x86::xmm4, x86::xmm6);
|
|
||||||
c.orps(x86::xmm0, x86::xmm4);
|
|
||||||
c.ptest(x86::xmm0, x86::xmm0);
|
|
||||||
}
|
|
||||||
|
|
||||||
c.jnz(fail);
|
|
||||||
|
|
||||||
// Store 8 bytes
|
|
||||||
c.mov(x86::qword_ptr(x86::rbp, args[0], 1, 0), args[3]);
|
|
||||||
|
|
||||||
c.xend();
|
|
||||||
c.lock().add(x86::qword_ptr(x86::r11), 64);
|
|
||||||
build_get_tsc(c);
|
|
||||||
c.sub(x86::rax, stamp0);
|
|
||||||
c.jmp(_ret);
|
|
||||||
|
|
||||||
// XABORT is expensive so try to finish with xend instead
|
|
||||||
c.bind(fail);
|
|
||||||
|
|
||||||
// Load old data to store back in rdata
|
|
||||||
if (s_tsx_avx)
|
|
||||||
{
|
|
||||||
c.vmovaps(x86::ymm0, x86::ymmword_ptr(x86::rbp, 0));
|
|
||||||
c.vmovaps(x86::ymm1, x86::ymmword_ptr(x86::rbp, 32));
|
|
||||||
c.vmovaps(x86::ymm2, x86::ymmword_ptr(x86::rbp, 64));
|
|
||||||
c.vmovaps(x86::ymm3, x86::ymmword_ptr(x86::rbp, 96));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
c.movaps(x86::xmm0, x86::oword_ptr(x86::rbp, 0));
|
|
||||||
c.movaps(x86::xmm1, x86::oword_ptr(x86::rbp, 16));
|
|
||||||
c.movaps(x86::xmm2, x86::oword_ptr(x86::rbp, 32));
|
|
||||||
c.movaps(x86::xmm3, x86::oword_ptr(x86::rbp, 48));
|
|
||||||
c.movaps(x86::xmm4, x86::oword_ptr(x86::rbp, 64));
|
|
||||||
c.movaps(x86::xmm5, x86::oword_ptr(x86::rbp, 80));
|
|
||||||
c.movaps(x86::xmm6, x86::oword_ptr(x86::rbp, 96));
|
|
||||||
c.movaps(x86::xmm7, x86::oword_ptr(x86::rbp, 112));
|
|
||||||
}
|
|
||||||
|
|
||||||
c.xend();
|
|
||||||
c.jmp(fail2);
|
|
||||||
|
|
||||||
c.bind(fall);
|
|
||||||
c.mov(x86::rax, -1);
|
|
||||||
c.jmp(_ret);
|
|
||||||
|
|
||||||
c.bind(fail2);
|
|
||||||
c.lock().sub(x86::qword_ptr(x86::r11), 64);
|
|
||||||
c.bind(load);
|
|
||||||
|
|
||||||
// Store previous data back to rdata
|
|
||||||
if (s_tsx_avx)
|
|
||||||
{
|
|
||||||
c.vmovaps(x86::ymmword_ptr(args[2], 0), x86::ymm0);
|
|
||||||
c.vmovaps(x86::ymmword_ptr(args[2], 32), x86::ymm1);
|
|
||||||
c.vmovaps(x86::ymmword_ptr(args[2], 64), x86::ymm2);
|
|
||||||
c.vmovaps(x86::ymmword_ptr(args[2], 96), x86::ymm3);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
c.movaps(x86::oword_ptr(args[2], 0), x86::xmm0);
|
|
||||||
c.movaps(x86::oword_ptr(args[2], 16), x86::xmm1);
|
|
||||||
c.movaps(x86::oword_ptr(args[2], 32), x86::xmm2);
|
|
||||||
c.movaps(x86::oword_ptr(args[2], 48), x86::xmm3);
|
|
||||||
c.movaps(x86::oword_ptr(args[2], 64), x86::xmm4);
|
|
||||||
c.movaps(x86::oword_ptr(args[2], 80), x86::xmm5);
|
|
||||||
c.movaps(x86::oword_ptr(args[2], 96), x86::xmm6);
|
|
||||||
c.movaps(x86::oword_ptr(args[2], 112), x86::xmm7);
|
|
||||||
}
|
|
||||||
|
|
||||||
c.mov(x86::rax, -1);
|
|
||||||
c.mov(x86::qword_ptr(args[2], ::offset32(&ppu_thread::last_ftime) - ::offset32(&ppu_thread::rdata)), x86::rax);
|
|
||||||
c.xor_(x86::eax, x86::eax);
|
|
||||||
//c.jmp(_ret);
|
|
||||||
|
|
||||||
c.bind(_ret);
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
if (!s_tsx_avx)
|
|
||||||
{
|
|
||||||
c.vmovups(x86::xmm6, x86::oword_ptr(x86::rsp, 0));
|
|
||||||
c.vmovups(x86::xmm7, x86::oword_ptr(x86::rsp, 16));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (s_tsx_avx)
|
|
||||||
{
|
|
||||||
c.vzeroupper();
|
|
||||||
}
|
|
||||||
|
|
||||||
c.add(x86::rsp, 48);
|
|
||||||
c.pop(x86::r14);
|
|
||||||
c.pop(x86::r13);
|
|
||||||
c.pop(x86::rbp);
|
|
||||||
|
|
||||||
maybe_flush_lbr(c);
|
|
||||||
c.ret();
|
|
||||||
#else
|
|
||||||
UNUSED(args);
|
|
||||||
|
|
||||||
// Unimplemented should fail.
|
|
||||||
c.brk(Imm(0x42));
|
|
||||||
c.ret(a64::x30);
|
|
||||||
#endif
|
|
||||||
});
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value)
|
static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value)
|
||||||
{
|
{
|
||||||
|
|
@ -3486,77 +3268,6 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_use_rtm) [[likely]]
|
|
||||||
{
|
|
||||||
switch (u64 count = ppu_stcx_accurate_tx(addr & -8, rtime, ppu.rdata, std::bit_cast<u64>(new_data)))
|
|
||||||
{
|
|
||||||
case umax:
|
|
||||||
{
|
|
||||||
auto& all_data = *vm::get_super_ptr<spu_rdata_t>(addr & -128);
|
|
||||||
auto& sdata = *vm::get_super_ptr<atomic_be_t<u64>>(addr & -8);
|
|
||||||
|
|
||||||
const bool ok = cpu_thread::suspend_all<+3>(&ppu, {all_data, all_data + 64, &res}, [&]
|
|
||||||
{
|
|
||||||
if ((res & -128) == rtime && cmp_rdata(ppu.rdata, all_data))
|
|
||||||
{
|
|
||||||
sdata.release(new_data);
|
|
||||||
res += 64;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
mov_rdata_nt(ppu.rdata, all_data);
|
|
||||||
res -= 64;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (ok)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ppu.last_ftime = -1;
|
|
||||||
[[fallthrough]];
|
|
||||||
}
|
|
||||||
case 0:
|
|
||||||
{
|
|
||||||
if (ppu.last_faddr == addr)
|
|
||||||
{
|
|
||||||
ppu.last_fail++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ppu.last_ftime != umax)
|
|
||||||
{
|
|
||||||
ppu.last_faddr = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
utils::prefetch_read(ppu.rdata);
|
|
||||||
utils::prefetch_read(ppu.rdata + 64);
|
|
||||||
ppu.last_faddr = addr;
|
|
||||||
ppu.last_ftime = res.load() & -128;
|
|
||||||
ppu.last_ftsc = utils::get_tsc();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
if (count > 20000 && g_cfg.core.perf_report) [[unlikely]]
|
|
||||||
{
|
|
||||||
perf_log.warning("STCX: took too long: %.3fus (%u c)", count / (utils::get_tsc_freq() / 1000'000.), count);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ppu.last_faddr == addr)
|
|
||||||
{
|
|
||||||
ppu.last_succ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
ppu.last_faddr = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Align address: we do not need the lower 7 bits anymore
|
// Align address: we do not need the lower 7 bits anymore
|
||||||
addr &= -128;
|
addr &= -128;
|
||||||
|
|
||||||
|
|
@ -4007,7 +3718,7 @@ extern void ppu_finalize(const ppu_module<lv2_obj>& info, bool force_mem_release
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_module<lv2_obj>*>* loaded_modules)
|
extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_module<lv2_obj>*>* loaded_modules, bool is_fast_compilation)
|
||||||
{
|
{
|
||||||
if (g_cfg.core.ppu_decoder != ppu_decoder_type::llvm)
|
if (g_cfg.core.ppu_decoder != ppu_decoder_type::llvm)
|
||||||
{
|
{
|
||||||
|
|
@ -4455,6 +4166,12 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_fast_compilation)
|
||||||
|
{
|
||||||
|
// Skip overlays in fast mode
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (!wait_for_memory())
|
if (!wait_for_memory())
|
||||||
{
|
{
|
||||||
// Emulation stopped
|
// Emulation stopped
|
||||||
|
|
@ -4749,7 +4466,7 @@ extern void ppu_initialize()
|
||||||
|
|
||||||
progress_dialog.reset();
|
progress_dialog.reset();
|
||||||
|
|
||||||
ppu_precompile(dir_queue, &module_list);
|
ppu_precompile(dir_queue, &module_list, false);
|
||||||
|
|
||||||
if (Emu.IsStopped())
|
if (Emu.IsStopped())
|
||||||
{
|
{
|
||||||
|
|
@ -5803,7 +5520,11 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module<lv2_obj>& module
|
||||||
std::unique_ptr<Module> _module = std::make_unique<Module>(obj_name, jit.get_context());
|
std::unique_ptr<Module> _module = std::make_unique<Module>(obj_name, jit.get_context());
|
||||||
|
|
||||||
// Initialize target
|
// Initialize target
|
||||||
|
#if LLVM_VERSION_MAJOR >= 21 && (LLVM_VERSION_MINOR >= 1 || LLVM_VERSION_MAJOR >= 22)
|
||||||
|
_module->setTargetTriple(Triple(jit_compiler::triple1()));
|
||||||
|
#else
|
||||||
_module->setTargetTriple(jit_compiler::triple1());
|
_module->setTargetTriple(jit_compiler::triple1());
|
||||||
|
#endif
|
||||||
_module->setDataLayout(jit.get_engine().getTargetMachine()->createDataLayout());
|
_module->setDataLayout(jit.get_engine().getTargetMachine()->createDataLayout());
|
||||||
|
|
||||||
// Initialize translator
|
// Initialize translator
|
||||||
|
|
|
||||||
|
|
@ -416,7 +416,6 @@ Function* PPUTranslator::GetSymbolResolver(const ppu_module<lv2_obj>& info)
|
||||||
assert(ptr_inst->getResultElementType() == m_ir->getPtrTy());
|
assert(ptr_inst->getResultElementType() == m_ir->getPtrTy());
|
||||||
|
|
||||||
const auto faddr = m_ir->CreateLoad(ptr_inst->getResultElementType(), ptr_inst);
|
const auto faddr = m_ir->CreateLoad(ptr_inst->getResultElementType(), ptr_inst);
|
||||||
const auto faddr_int = m_ir->CreatePtrToInt(faddr, get_type<uptr>());
|
|
||||||
const auto pos_32 = m_reloc ? m_ir->CreateAdd(func_pc, m_seg0) : func_pc;
|
const auto pos_32 = m_reloc ? m_ir->CreateAdd(func_pc, m_seg0) : func_pc;
|
||||||
const auto pos = m_ir->CreateShl(pos_32, 1);
|
const auto pos = m_ir->CreateShl(pos_32, 1);
|
||||||
const auto ptr = m_ir->CreatePtrAdd(m_exec, pos);
|
const auto ptr = m_ir->CreatePtrAdd(m_exec, pos);
|
||||||
|
|
@ -427,7 +426,7 @@ Function* PPUTranslator::GetSymbolResolver(const ppu_module<lv2_obj>& info)
|
||||||
const auto seg_val = m_ir->CreateTrunc(m_ir->CreateLShr(m_seg0, 13), get_type<u16>());
|
const auto seg_val = m_ir->CreateTrunc(m_ir->CreateLShr(m_seg0, 13), get_type<u16>());
|
||||||
|
|
||||||
// Store to jumptable
|
// Store to jumptable
|
||||||
m_ir->CreateStore(faddr_int, ptr);
|
m_ir->CreateStore(faddr, ptr);
|
||||||
m_ir->CreateStore(seg_val, seg_ptr);
|
m_ir->CreateStore(seg_val, seg_ptr);
|
||||||
|
|
||||||
// Increment index and branch back to loop
|
// Increment index and branch back to loop
|
||||||
|
|
@ -593,6 +592,11 @@ void PPUTranslator::CallFunction(u64 target, Value* indirect)
|
||||||
{
|
{
|
||||||
callee = m_module->getOrInsertFunction(fmt::format("__0x%x", target_last - base), type);
|
callee = m_module->getOrInsertFunction(fmt::format("__0x%x", target_last - base), type);
|
||||||
cast<Function>(callee.getCallee())->setCallingConv(CallingConv::GHC);
|
cast<Function>(callee.getCallee())->setCallingConv(CallingConv::GHC);
|
||||||
|
|
||||||
|
if (g_cfg.core.ppu_prof)
|
||||||
|
{
|
||||||
|
m_ir->CreateStore(GetAddr(target_last - m_addr), m_ir->CreateStructGEP(m_thread_type, m_thread, static_cast<uint>(&m_cia - m_locals)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1115,7 +1119,24 @@ void PPUTranslator::VCFSX(ppu_opcode_t op)
|
||||||
void PPUTranslator::VCFUX(ppu_opcode_t op)
|
void PPUTranslator::VCFUX(ppu_opcode_t op)
|
||||||
{
|
{
|
||||||
const auto b = get_vr<u32[4]>(op.vb);
|
const auto b = get_vr<u32[4]>(op.vb);
|
||||||
set_vr(op.vd, fpcast<f32[4]>(b) * fsplat<f32[4]>(std::pow(2, -static_cast<int>(op.vuimm))));
|
|
||||||
|
#ifdef ARCH_ARM64
|
||||||
|
return set_vr(op.vd, fpcast<f32[4]>(b) * fsplat<f32[4]>(std::pow(2, -static_cast<int>(op.vuimm))));
|
||||||
|
#else
|
||||||
|
if (m_use_avx512)
|
||||||
|
{
|
||||||
|
return set_vr(op.vd, fpcast<f32[4]>(b) * fsplat<f32[4]>(std::pow(2, -static_cast<int>(op.vuimm))));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int bit_shift = 9;
|
||||||
|
const auto shifted = (b >> bit_shift);
|
||||||
|
const auto cleared = shifted << bit_shift;
|
||||||
|
const auto low_bits = b - cleared;
|
||||||
|
const auto high_part = fpcast<f32[4]>(noncast<s32[4]>(shifted)) * fsplat<f32[4]>(static_cast<f32>(1u << bit_shift));
|
||||||
|
const auto low_part = fpcast<f32[4]>(noncast<s32[4]>(low_bits));
|
||||||
|
const auto temp = high_part + low_part;
|
||||||
|
set_vr(op.vd, temp * fsplat<f32[4]>(std::pow(2, -static_cast<int>(op.vuimm))));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPUTranslator::VCMPBFP(ppu_opcode_t op)
|
void PPUTranslator::VCMPBFP(ppu_opcode_t op)
|
||||||
|
|
|
||||||
|
|
@ -186,7 +186,7 @@ spu_function_t spu_recompiler::compile(spu_program&& _func)
|
||||||
c->cmp(SPU_OFF_32(state), 0);
|
c->cmp(SPU_OFF_32(state), 0);
|
||||||
c->jnz(label_stop);
|
c->jnz(label_stop);
|
||||||
|
|
||||||
if (g_cfg.core.spu_prof && g_cfg.core.spu_verification)
|
if ((g_cfg.core.spu_prof || g_cfg.core.spu_debug) && g_cfg.core.spu_verification)
|
||||||
{
|
{
|
||||||
c->mov(x86::rax, m_hash_start & -0xffff);
|
c->mov(x86::rax, m_hash_start & -0xffff);
|
||||||
c->mov(SPU_OFF_64(block_hash), x86::rax);
|
c->mov(SPU_OFF_64(block_hash), x86::rax);
|
||||||
|
|
@ -755,7 +755,7 @@ spu_function_t spu_recompiler::compile(spu_program&& _func)
|
||||||
c->add(SPU_OFF_64(block_counter), ::size32(words) / (words_align / 4));
|
c->add(SPU_OFF_64(block_counter), ::size32(words) / (words_align / 4));
|
||||||
|
|
||||||
// Set block hash for profiling (if enabled)
|
// Set block hash for profiling (if enabled)
|
||||||
if (g_cfg.core.spu_prof)
|
if (g_cfg.core.spu_prof || g_cfg.core.spu_debug)
|
||||||
{
|
{
|
||||||
c->mov(x86::rax, m_hash_start | 0xffff);
|
c->mov(x86::rax, m_hash_start | 0xffff);
|
||||||
c->mov(SPU_OFF_64(block_hash), x86::rax);
|
c->mov(SPU_OFF_64(block_hash), x86::rax);
|
||||||
|
|
@ -1199,7 +1199,7 @@ void spu_recompiler::branch_set_link(u32 target)
|
||||||
c->movdqa(x86::dqword_ptr(*cpu, *qw1, 0, ::offset32(&spu_thread::stack_mirror)), x86::xmm0);
|
c->movdqa(x86::dqword_ptr(*cpu, *qw1, 0, ::offset32(&spu_thread::stack_mirror)), x86::xmm0);
|
||||||
|
|
||||||
// Set block hash for profiling (if enabled)
|
// Set block hash for profiling (if enabled)
|
||||||
if (g_cfg.core.spu_prof)
|
if (g_cfg.core.spu_prof || g_cfg.core.spu_debug)
|
||||||
{
|
{
|
||||||
c->mov(x86::rax, m_hash_start | 0xffff);
|
c->mov(x86::rax, m_hash_start | 0xffff);
|
||||||
c->mov(SPU_OFF_64(block_hash), x86::rax);
|
c->mov(SPU_OFF_64(block_hash), x86::rax);
|
||||||
|
|
@ -3212,7 +3212,7 @@ void spu_recompiler::ROTQBYI(spu_opcode_t op)
|
||||||
}
|
}
|
||||||
else if (s == 4 || s == 8 || s == 12)
|
else if (s == 4 || s == 8 || s == 12)
|
||||||
{
|
{
|
||||||
c->pshufd(va, va, utils::rol8(0xE4, s / 2));
|
c->pshufd(va, va, std::rotl<u8>(0xE4, s / 2));
|
||||||
}
|
}
|
||||||
else if (utils::has_ssse3())
|
else if (utils::has_ssse3())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -38,26 +38,9 @@ constexpr u32 s_reg_max = spu_recompiler_base::s_reg_max;
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct span_less
|
struct span_less
|
||||||
{
|
{
|
||||||
static int compare(const std::span<T>& lhs, const std::span<T>& rhs) noexcept
|
static auto compare(const std::span<T>& lhs, const std::span<T>& rhs) noexcept
|
||||||
{
|
{
|
||||||
// TODO: Replace with std::lexicographical_compare_three_way when it becomes available to all compilers
|
return std::lexicographical_compare_three_way(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
|
||||||
for (usz i = 0, last = std::min(lhs.size(), rhs.size()); i != last; i++)
|
|
||||||
{
|
|
||||||
const T vl = lhs[i];
|
|
||||||
const T vr = rhs[i];
|
|
||||||
|
|
||||||
if (vl != vr)
|
|
||||||
{
|
|
||||||
return vl < vr ? -1 : 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lhs.size() != rhs.size())
|
|
||||||
{
|
|
||||||
return lhs.size() < rhs.size() ? -1 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator()(const std::span<T>& lhs, const std::span<T>& rhs) const noexcept
|
bool operator()(const std::span<T>& lhs, const std::span<T>& rhs) const noexcept
|
||||||
|
|
@ -737,9 +720,19 @@ void spu_cache::initialize(bool build_existing_cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SPU cache file (version + block size type)
|
// SPU cache file (version + block size type)
|
||||||
const std::string loc = ppu_cache + "spu-" + fmt::to_lower(g_cfg.core.spu_block_size.to_string()) + "-v1-tane.dat";
|
const std::string filename = "spu-" + fmt::to_lower(g_cfg.core.spu_block_size.to_string()) + "-v1-tane.dat";
|
||||||
|
const std::string loc = ppu_cache + filename;
|
||||||
|
const std::string loc_debug = fs::get_cache_dir() + "DEBUG/" + filename;
|
||||||
|
|
||||||
spu_cache cache(loc);
|
bool is_debug = false;
|
||||||
|
|
||||||
|
if (fs::is_file(loc_debug))
|
||||||
|
{
|
||||||
|
spu_log.success("SPU Cache override applied!");
|
||||||
|
is_debug = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
spu_cache cache(is_debug ? loc_debug : loc);
|
||||||
|
|
||||||
if (!cache)
|
if (!cache)
|
||||||
{
|
{
|
||||||
|
|
@ -1309,7 +1302,7 @@ bool spu_program::operator<(const spu_program& rhs) const noexcept
|
||||||
std::span<const u32> lhs_data(data.data() + lhs_offs, data.size() - lhs_offs);
|
std::span<const u32> lhs_data(data.data() + lhs_offs, data.size() - lhs_offs);
|
||||||
std::span<const u32> rhs_data(rhs.data.data() + rhs_offs, rhs.data.size() - rhs_offs);
|
std::span<const u32> rhs_data(rhs.data.data() + rhs_offs, rhs.data.size() - rhs_offs);
|
||||||
|
|
||||||
const int cmp0 = span_less<const u32>::compare(lhs_data, rhs_data);
|
const auto cmp0 = span_less<const u32>::compare(lhs_data, rhs_data);
|
||||||
|
|
||||||
if (cmp0 < 0)
|
if (cmp0 < 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1320,7 +1313,7 @@ bool spu_program::operator<(const spu_program& rhs) const noexcept
|
||||||
lhs_data = {data.data(), lhs_offs};
|
lhs_data = {data.data(), lhs_offs};
|
||||||
rhs_data = {rhs.data.data(), rhs_offs};
|
rhs_data = {rhs.data.data(), rhs_offs};
|
||||||
|
|
||||||
const int cmp1 = span_less<const u32>::compare(lhs_data, rhs_data);
|
const auto cmp1 = span_less<const u32>::compare(lhs_data, rhs_data);
|
||||||
|
|
||||||
if (cmp1 < 0)
|
if (cmp1 < 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -2333,7 +2326,7 @@ std::vector<u32> spu_thread::discover_functions(u32 base_addr, std::span<const u
|
||||||
// Search for BRSL LR and BRASL LR or BR
|
// Search for BRSL LR and BRASL LR or BR
|
||||||
// TODO: BISL
|
// TODO: BISL
|
||||||
const v128 inst = read_from_ptr<be_t<v128>>(ls.data(), i - base_addr);
|
const v128 inst = read_from_ptr<be_t<v128>>(ls.data(), i - base_addr);
|
||||||
const v128 cleared_i16 = gv_and32(inst, v128::from32p(utils::rol32(~0xffff, 7)));
|
const v128 cleared_i16 = gv_and32(inst, v128::from32p(std::rotl<u32>(~0xffff, 7)));
|
||||||
const v128 eq_brsl = gv_eq32(cleared_i16, v128::from32p(0x66u << 23));
|
const v128 eq_brsl = gv_eq32(cleared_i16, v128::from32p(0x66u << 23));
|
||||||
const v128 eq_brasl = gv_eq32(cleared_i16, brasl_mask);
|
const v128 eq_brasl = gv_eq32(cleared_i16, brasl_mask);
|
||||||
const v128 eq_br = gv_eq32(cleared_i16, v128::from32p(0x64u << 23));
|
const v128 eq_br = gv_eq32(cleared_i16, v128::from32p(0x64u << 23));
|
||||||
|
|
@ -3086,6 +3079,39 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
values[op.rt] = pos + 4;
|
values[op.rt] = pos + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const u32 pos_next = wa;
|
||||||
|
|
||||||
|
bool is_no_return = false;
|
||||||
|
|
||||||
|
if (pos_next >= lsa && pos_next < limit)
|
||||||
|
{
|
||||||
|
const u32 data_next = ls[pos_next / 4];
|
||||||
|
const auto type_next = g_spu_itype.decode(data_next);
|
||||||
|
const auto flag_next = g_spu_iflag.decode(data_next);
|
||||||
|
const auto op_next = spu_opcode_t{data_next};
|
||||||
|
|
||||||
|
if (!(type_next & spu_itype::zregmod) && !(type_next & spu_itype::branch))
|
||||||
|
{
|
||||||
|
if (auto iflags = g_spu_iflag.decode(data_next))
|
||||||
|
{
|
||||||
|
if (+flag_next & +spu_iflag::use_ra)
|
||||||
|
{
|
||||||
|
is_no_return = is_no_return || (op_next.ra >= 4 && op_next.ra < 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (+flag_next & +spu_iflag::use_rb)
|
||||||
|
{
|
||||||
|
is_no_return = is_no_return || (op_next.rb >= 4 && op_next.rb < 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type_next & spu_itype::_quadrop && +iflags & +spu_iflag::use_rc)
|
||||||
|
{
|
||||||
|
is_no_return = is_no_return || (op_next.ra >= 4 && op_next.rb < 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (af & vf::is_const)
|
if (af & vf::is_const)
|
||||||
{
|
{
|
||||||
const u32 target = spu_branch_target(av);
|
const u32 target = spu_branch_target(av);
|
||||||
|
|
@ -3122,7 +3148,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
limit = std::min<u32>(limit, target);
|
limit = std::min<u32>(limit, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sl && g_cfg.core.spu_block_size != spu_block_size_type::safe)
|
if (!is_no_return && sl && g_cfg.core.spu_block_size != spu_block_size_type::safe)
|
||||||
{
|
{
|
||||||
m_ret_info[pos / 4 + 1] = true;
|
m_ret_info[pos / 4 + 1] = true;
|
||||||
m_entry_info[pos / 4 + 1] = true;
|
m_entry_info[pos / 4 + 1] = true;
|
||||||
|
|
@ -3139,7 +3165,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
u64 dabs = 0;
|
u64 dabs = 0;
|
||||||
u64 drel = 0;
|
u64 drel = 0;
|
||||||
|
|
||||||
for (u32 i = start; i < limit; i += 4)
|
for (u32 i = start, abs_fail = 0, rel_fail = 0; i < limit; i += 4)
|
||||||
{
|
{
|
||||||
const u32 target = ls[i / 4];
|
const u32 target = ls[i / 4];
|
||||||
|
|
||||||
|
|
@ -3149,16 +3175,39 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (target >= SPU_LS_SIZE && target <= 0u - SPU_LS_SIZE)
|
||||||
|
{
|
||||||
|
if (g_spu_itype.decode(target) != spu_itype::UNK)
|
||||||
|
{
|
||||||
|
// End of jumptable: valid instruction
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (target >= lsa && target < SPU_LS_SIZE)
|
if (target >= lsa && target < SPU_LS_SIZE)
|
||||||
{
|
{
|
||||||
// Possible jump table entry (absolute)
|
// Possible jump table entry (absolute)
|
||||||
jt_abs.push_back(target);
|
if (!abs_fail)
|
||||||
|
{
|
||||||
|
jt_abs.push_back(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
abs_fail++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target + start >= lsa && target + start < SPU_LS_SIZE)
|
if (target + start >= lsa && target + start < SPU_LS_SIZE)
|
||||||
{
|
{
|
||||||
// Possible jump table entry (relative)
|
// Possible jump table entry (relative)
|
||||||
jt_rel.push_back(target + start);
|
if (!rel_fail)
|
||||||
|
{
|
||||||
|
jt_rel.push_back(target + start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rel_fail++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::max(jt_abs.size(), jt_rel.size()) * 4 + start <= i)
|
if (std::max(jt_abs.size(), jt_rel.size()) * 4 + start <= i)
|
||||||
|
|
@ -3170,6 +3219,35 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (usz i = 0; i < jt_abs.size(); i++)
|
||||||
|
{
|
||||||
|
if (jt_abs[i] == start + jt_abs.size() * 4)
|
||||||
|
{
|
||||||
|
// If jumptable contains absolute address of code start after the jumptable itself
|
||||||
|
// It is likely an absolute-type jumptable
|
||||||
|
|
||||||
|
bool is_good_conclusion = true;
|
||||||
|
|
||||||
|
// For verification: make sure there is none like this in relative table
|
||||||
|
|
||||||
|
for (u32 target : jt_rel)
|
||||||
|
{
|
||||||
|
if (target == start + jt_rel.size() * 4)
|
||||||
|
{
|
||||||
|
is_good_conclusion = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_good_conclusion)
|
||||||
|
{
|
||||||
|
jt_rel.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Choose position after the jt as an anchor and compute the average distance
|
// Choose position after the jt as an anchor and compute the average distance
|
||||||
for (u32 target : jt_abs)
|
for (u32 target : jt_abs)
|
||||||
{
|
{
|
||||||
|
|
@ -3268,9 +3346,9 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
spu_log.notice("[0x%x] At 0x%x: ignoring indirect branch (SYNC)", entry_point, pos);
|
spu_log.notice("[0x%x] At 0x%x: ignoring indirect branch (SYNC)", entry_point, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == spu_itype::BI || sl)
|
if (type == spu_itype::BI || sl || is_no_return)
|
||||||
{
|
{
|
||||||
if (type == spu_itype::BI || g_cfg.core.spu_block_size == spu_block_size_type::safe)
|
if (type == spu_itype::BI || g_cfg.core.spu_block_size == spu_block_size_type::safe || is_no_return)
|
||||||
{
|
{
|
||||||
m_targets[pos];
|
m_targets[pos];
|
||||||
}
|
}
|
||||||
|
|
@ -3307,9 +3385,42 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const u32 pos_next = wa;
|
||||||
|
|
||||||
|
bool is_no_return = false;
|
||||||
|
|
||||||
|
if (pos_next >= lsa && pos_next < limit)
|
||||||
|
{
|
||||||
|
const u32 data_next = ls[pos_next / 4];
|
||||||
|
const auto type_next = g_spu_itype.decode(data_next);
|
||||||
|
const auto flag_next = g_spu_iflag.decode(data_next);
|
||||||
|
const auto op_next = spu_opcode_t{data_next};
|
||||||
|
|
||||||
|
if (!(type_next & spu_itype::zregmod) && !(type_next & spu_itype::branch))
|
||||||
|
{
|
||||||
|
if (auto iflags = g_spu_iflag.decode(data_next))
|
||||||
|
{
|
||||||
|
if (+flag_next & +spu_iflag::use_ra)
|
||||||
|
{
|
||||||
|
is_no_return = is_no_return || (op_next.ra >= 4 && op_next.ra < 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (+flag_next & +spu_iflag::use_rb)
|
||||||
|
{
|
||||||
|
is_no_return = is_no_return || (op_next.rb >= 4 && op_next.rb < 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type_next & spu_itype::_quadrop && +iflags & +spu_iflag::use_rc)
|
||||||
|
{
|
||||||
|
is_no_return = is_no_return || (op_next.rc >= 4 && op_next.rc < 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_targets[pos].push_back(target);
|
m_targets[pos].push_back(target);
|
||||||
|
|
||||||
if (g_cfg.core.spu_block_size != spu_block_size_type::safe)
|
if (!is_no_return && g_cfg.core.spu_block_size != spu_block_size_type::safe)
|
||||||
{
|
{
|
||||||
m_ret_info[pos / 4 + 1] = true;
|
m_ret_info[pos / 4 + 1] = true;
|
||||||
m_entry_info[pos / 4 + 1] = true;
|
m_entry_info[pos / 4 + 1] = true;
|
||||||
|
|
@ -3317,7 +3428,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
add_block(pos + 4);
|
add_block(pos + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_cfg.core.spu_block_size == spu_block_size_type::giga && !sync)
|
if (!is_no_return && g_cfg.core.spu_block_size == spu_block_size_type::giga && !sync)
|
||||||
{
|
{
|
||||||
m_entry_info[target / 4] = true;
|
m_entry_info[target / 4] = true;
|
||||||
add_block(target);
|
add_block(target);
|
||||||
|
|
@ -4862,6 +4973,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
u32 lsa_last_pc = SPU_LS_SIZE; // PC of first LSA write
|
u32 lsa_last_pc = SPU_LS_SIZE; // PC of first LSA write
|
||||||
u32 get_pc = SPU_LS_SIZE; // PC of GETLLAR
|
u32 get_pc = SPU_LS_SIZE; // PC of GETLLAR
|
||||||
u32 put_pc = SPU_LS_SIZE; // PC of PUTLLC
|
u32 put_pc = SPU_LS_SIZE; // PC of PUTLLC
|
||||||
|
u32 rdatomic_pc = SPU_LS_SIZE; // PC of last RdAtomcStat read
|
||||||
reg_state_t ls{}; // state of LS load/store address register
|
reg_state_t ls{}; // state of LS load/store address register
|
||||||
reg_state_t ls_offs = reg_state_t::from_value(0); // Added value to ls
|
reg_state_t ls_offs = reg_state_t::from_value(0); // Added value to ls
|
||||||
reg_state_t lsa{}; // state of LSA register on GETLLAR
|
reg_state_t lsa{}; // state of LSA register on GETLLAR
|
||||||
|
|
@ -4877,20 +4989,27 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
bool select_16_or_0_at_runtime = false;
|
bool select_16_or_0_at_runtime = false;
|
||||||
bool put_active = false; // PUTLLC happened
|
bool put_active = false; // PUTLLC happened
|
||||||
bool get_rdatomic = false; // True if MFC_RdAtomicStat was read after GETLLAR
|
bool get_rdatomic = false; // True if MFC_RdAtomicStat was read after GETLLAR
|
||||||
|
u32 required_pc = SPU_LS_SIZE; // Require program to be location specific for this optimization (SPU_LS_SIZE - no requirement)
|
||||||
u32 mem_count = 0;
|
u32 mem_count = 0;
|
||||||
|
u32 break_cause = 100;
|
||||||
|
u32 break_pc = SPU_LS_SIZE;
|
||||||
|
|
||||||
// Return old state for error reporting
|
// Return old state for error reporting
|
||||||
atomic16_t discard()
|
atomic16_t discard()
|
||||||
{
|
{
|
||||||
const u32 pc = lsa_pc;
|
const u32 pc = lsa_pc;
|
||||||
const u32 last_pc = lsa_last_pc;
|
const u32 last_pc = lsa_last_pc;
|
||||||
|
const u32 cause = break_cause;
|
||||||
|
const u32 break_pos = break_pc;
|
||||||
|
|
||||||
const atomic16_t old = *this;
|
const atomic16_t old = *this;
|
||||||
*this = atomic16_t{};
|
*this = atomic16_t{};
|
||||||
|
|
||||||
// Keep some members
|
// Keep some members
|
||||||
lsa_pc = pc;
|
this->lsa_pc = pc;
|
||||||
lsa_last_pc = last_pc;
|
this->lsa_last_pc = last_pc;
|
||||||
|
this->break_cause = cause;
|
||||||
|
this->break_pc = break_pos;
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4900,7 +5019,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
ls_invalid = true;
|
ls_invalid = true;
|
||||||
ls_write |= write;
|
ls_write |= write;
|
||||||
|
|
||||||
if (write)
|
if (ls_write)
|
||||||
{
|
{
|
||||||
return discard();
|
return discard();
|
||||||
}
|
}
|
||||||
|
|
@ -5097,15 +5216,17 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
{
|
{
|
||||||
if (previous.active && likely_putllc_loop && getllar_starts.contains(previous.lsa_pc))
|
if (previous.active && likely_putllc_loop && getllar_starts.contains(previous.lsa_pc))
|
||||||
{
|
{
|
||||||
const bool is_first = !std::exchange(getllar_starts[previous.lsa_pc], true);
|
had_putllc_evaluation = true;
|
||||||
|
|
||||||
if (!is_first)
|
if (cause != 24)
|
||||||
{
|
{
|
||||||
|
atomic16->break_cause = cause;
|
||||||
|
atomic16->break_pc = pos;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
had_putllc_evaluation = true;
|
cause = atomic16->break_cause;
|
||||||
|
getllar_starts[previous.lsa_pc] = true;
|
||||||
g_fxo->get<putllc16_statistics_t>().breaking_reason[cause]++;
|
g_fxo->get<putllc16_statistics_t>().breaking_reason[cause]++;
|
||||||
|
|
||||||
if (!spu_log.notice)
|
if (!spu_log.notice)
|
||||||
|
|
@ -5113,7 +5234,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string break_error = fmt::format("PUTLLC pattern breakage [%x mem=%d lsa_const=%d cause=%u] (lsa_pc=0x%x)", pos, previous.mem_count, u32{!previous.ls_offs.is_const()} * 2 + previous.lsa.is_const(), cause, previous.lsa_pc);
|
std::string break_error = fmt::format("PUTLLC pattern breakage [%x mem=%d lsa_const=%d cause=%u] (lsa_pc=0x%x)", atomic16->break_pc, previous.mem_count, u32{!previous.ls_offs.is_const()} * 2 + previous.lsa.is_const(), cause, previous.lsa_pc);
|
||||||
|
|
||||||
const auto values = sort_breakig_reasons(g_fxo->get<putllc16_statistics_t>().breaking_reason);
|
const auto values = sort_breakig_reasons(g_fxo->get<putllc16_statistics_t>().breaking_reason);
|
||||||
|
|
||||||
|
|
@ -5396,7 +5517,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
const usz block_tail = duplicate_positions[it_begin - it_tail];
|
const usz block_tail = duplicate_positions[it_begin - it_tail];
|
||||||
|
|
||||||
// Check if the distance is precisely two times from the end
|
// Check if the distance is precisely two times from the end
|
||||||
if (reg_state_it.size() - block_start != utils::rol64(reg_state_it.size() - block_tail, 1))
|
if (reg_state_it.size() - block_start != std::rotl<u64>(reg_state_it.size() - block_tail, 1))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -6213,6 +6334,8 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
atomic16->rdatomic_pc = pos;
|
||||||
|
|
||||||
const auto it = atomic16_all.find(pos);
|
const auto it = atomic16_all.find(pos);
|
||||||
|
|
||||||
if (it == atomic16_all.end())
|
if (it == atomic16_all.end())
|
||||||
|
|
@ -6275,6 +6398,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
existing.ls_invalid |= atomic16->ls_invalid;
|
existing.ls_invalid |= atomic16->ls_invalid;
|
||||||
existing.ls_access |= atomic16->ls_access;
|
existing.ls_access |= atomic16->ls_access;
|
||||||
existing.mem_count = std::max<u32>(existing.mem_count, atomic16->mem_count);
|
existing.mem_count = std::max<u32>(existing.mem_count, atomic16->mem_count);
|
||||||
|
existing.required_pc = std::min<u32>(existing.required_pc, atomic16->required_pc);
|
||||||
existing.select_16_or_0_at_runtime |= atomic16->select_16_or_0_at_runtime;
|
existing.select_16_or_0_at_runtime |= atomic16->select_16_or_0_at_runtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -6289,6 +6413,24 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
invalidate = false;
|
invalidate = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (atomic16->break_cause != 100 && atomic16->lsa_pc != SPU_LS_SIZE)
|
||||||
|
{
|
||||||
|
const auto it = atomic16_all.find(pos);
|
||||||
|
|
||||||
|
if (it == atomic16_all.end())
|
||||||
|
{
|
||||||
|
// Ensure future failure
|
||||||
|
atomic16_all.emplace(pos, *atomic16);
|
||||||
|
break_putllc16(24, FN(x.active = true, x)(as_rvalue(*atomic16)));
|
||||||
|
}
|
||||||
|
else if (it->second.active && atomic16->break_cause != 100)
|
||||||
|
{
|
||||||
|
it->second = *atomic16;
|
||||||
|
break_putllc16(24, FN(x.active = true, x)(as_rvalue(*atomic16)));
|
||||||
|
}
|
||||||
|
|
||||||
|
atomic16->break_cause = 100;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -6359,6 +6501,10 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
|
|
||||||
// Do not clear lower 16 bytes addressing because the program can move on 4-byte basis
|
// Do not clear lower 16 bytes addressing because the program can move on 4-byte basis
|
||||||
const u32 offs = spu_branch_target(pos - result.lower_bound, op.si16);
|
const u32 offs = spu_branch_target(pos - result.lower_bound, op.si16);
|
||||||
|
const u32 true_offs = spu_branch_target(pos, op.si16);
|
||||||
|
|
||||||
|
// Make this optimization depend on the location of the program
|
||||||
|
atomic16->required_pc = result.lower_bound;
|
||||||
|
|
||||||
if (atomic16->lsa.is_const() && [&]()
|
if (atomic16->lsa.is_const() && [&]()
|
||||||
{
|
{
|
||||||
|
|
@ -6383,6 +6529,10 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
{
|
{
|
||||||
// Ignore memory access in this case
|
// Ignore memory access in this case
|
||||||
}
|
}
|
||||||
|
else if (atomic16->lsa.is_const() && !atomic16->lsa.compare_with_mask_indifference(true_offs, SPU_LS_MASK_128))
|
||||||
|
{
|
||||||
|
// Same
|
||||||
|
}
|
||||||
else if (atomic16->ls_invalid && is_store)
|
else if (atomic16->ls_invalid && is_store)
|
||||||
{
|
{
|
||||||
break_putllc16(35, atomic16->set_invalid_ls(is_store));
|
break_putllc16(35, atomic16->set_invalid_ls(is_store));
|
||||||
|
|
@ -7126,7 +7276,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
|
|
||||||
for (const auto& [pc_commited, pattern] : atomic16_all)
|
for (const auto& [pc_commited, pattern] : atomic16_all)
|
||||||
{
|
{
|
||||||
if (!pattern.active)
|
if (!pattern.active || pattern.lsa_pc >= pattern.rdatomic_pc)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -7136,27 +7286,44 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string pattern_hash;
|
||||||
|
{
|
||||||
|
sha1_context ctx;
|
||||||
|
u8 output[20]{};
|
||||||
|
|
||||||
|
sha1_starts(&ctx);
|
||||||
|
sha1_update(&ctx, reinterpret_cast<const u8*>(result.data.data()) + (pattern.lsa_pc - result.lower_bound), pattern.rdatomic_pc - pattern.lsa_pc);
|
||||||
|
sha1_finish(&ctx, output);
|
||||||
|
fmt::append(pattern_hash, "%s", fmt::base57(output));
|
||||||
|
}
|
||||||
|
|
||||||
|
union putllc16_or_0_info
|
||||||
|
{
|
||||||
|
u64 data;
|
||||||
|
bf_t<u64, 32, 18> required_pc;
|
||||||
|
bf_t<u64, 30, 2> type;
|
||||||
|
bf_t<u64, 29, 1> runtime16_select;
|
||||||
|
bf_t<u64, 28, 1> no_notify;
|
||||||
|
bf_t<u64, 18, 8> reg;
|
||||||
|
bf_t<u64, 0, 18> off18;
|
||||||
|
bf_t<u64, 0, 8> reg2;
|
||||||
|
} value{};
|
||||||
|
|
||||||
auto& stats = g_fxo->get<putllc16_statistics_t>();
|
auto& stats = g_fxo->get<putllc16_statistics_t>();
|
||||||
had_putllc_evaluation = true;
|
had_putllc_evaluation = true;
|
||||||
|
|
||||||
if (!pattern.ls_write)
|
if (!pattern.ls_write)
|
||||||
{
|
{
|
||||||
spu_log.success("PUTLLC0 Pattern Detected! (put_pc=0x%x, %s) (putllc0=%d, putllc16+0=%d, all=%d)", pattern.put_pc, func_hash, ++stats.nowrite, ++stats.single, +stats.all);
|
if (pattern.required_pc != SPU_LS_SIZE)
|
||||||
add_pattern(false, inst_attr::putllc0, pattern.put_pc - lsa);
|
{
|
||||||
|
value.required_pc = pattern.required_pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// spu_log.success("PUTLLC0 Pattern Detected! (put_pc=0x%x, %s) (putllc0=%d, putllc16+0=%d, all=%d)", pattern.put_pc, func_hash, ++stats.nowrite, ++stats.single, +stats.all);
|
||||||
|
// add_pattern(false, inst_attr::putllc0, pattern.put_pc - lsa, value.data);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
union putllc16_info
|
|
||||||
{
|
|
||||||
u32 data;
|
|
||||||
bf_t<u32, 30, 2> type;
|
|
||||||
bf_t<u32, 29, 1> runtime16_select;
|
|
||||||
bf_t<u32, 28, 1> no_notify;
|
|
||||||
bf_t<u32, 18, 8> reg;
|
|
||||||
bf_t<u32, 0, 18> off18;
|
|
||||||
bf_t<u32, 0, 8> reg2;
|
|
||||||
} value{};
|
|
||||||
|
|
||||||
enum : u32
|
enum : u32
|
||||||
{
|
{
|
||||||
v_const = 0,
|
v_const = 0,
|
||||||
|
|
@ -7187,6 +7354,11 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
value.runtime16_select = pattern.select_16_or_0_at_runtime;
|
value.runtime16_select = pattern.select_16_or_0_at_runtime;
|
||||||
value.reg = s_reg_max;
|
value.reg = s_reg_max;
|
||||||
|
|
||||||
|
if (pattern.required_pc != SPU_LS_SIZE)
|
||||||
|
{
|
||||||
|
value.required_pc = pattern.required_pc;
|
||||||
|
}
|
||||||
|
|
||||||
if (pattern.ls.is_const())
|
if (pattern.ls.is_const())
|
||||||
{
|
{
|
||||||
ensure(pattern.reg == s_reg_max && pattern.reg2 == s_reg_max && pattern.ls_offs.is_const(), "Unexpected register usage");
|
ensure(pattern.reg == s_reg_max && pattern.reg2 == s_reg_max && pattern.ls_offs.is_const(), "Unexpected register usage");
|
||||||
|
|
@ -7215,16 +7387,35 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
value.reg2 = pattern.reg2;
|
value.reg2 = pattern.reg2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool allow_pattern = true;
|
||||||
|
|
||||||
if (g_cfg.core.spu_accurate_reservations)
|
if (g_cfg.core.spu_accurate_reservations)
|
||||||
{
|
{
|
||||||
// Because enabling it is a hack, as it turns out
|
// The problem with PUTLLC16 optimization, that it is in theory correct at the bounds of the spu function.
|
||||||
continue;
|
// But if the SPU code reuses the cache line data observed, it is not truly atomic.
|
||||||
|
// So we may enable it only for known cases where SPU atomic data is not used after the function leaves.
|
||||||
|
|
||||||
|
// So the two options are:
|
||||||
|
|
||||||
|
// 1. Atomic compare exchange 16 bytes operation. (rest of data is not read) -> good for RPCS3 to optimize.
|
||||||
|
// 2. Fetch 128 bytes (read them later), modify only 16 bytes. -> Bad for RPCS3 to optimize.
|
||||||
|
|
||||||
|
// This difference cannot be known at analyzer time but from observing callers.
|
||||||
|
static constexpr std::initializer_list<std::string_view> allowed_patterns =
|
||||||
|
{
|
||||||
|
"620oYSe8uQqq9eTkhWfMqoEXX0us"sv, // CellSpurs JobChain acquire pattern
|
||||||
|
};
|
||||||
|
|
||||||
|
allow_pattern = std::any_of(allowed_patterns.begin(), allowed_patterns.end(), FN(pattern_hash == x));
|
||||||
}
|
}
|
||||||
|
|
||||||
add_pattern(false, inst_attr::putllc16, pattern.put_pc - result.entry_point, value.data);
|
if (allow_pattern)
|
||||||
|
{
|
||||||
|
add_pattern(false, inst_attr::putllc16, pattern.put_pc - result.entry_point, value.data);
|
||||||
|
}
|
||||||
|
|
||||||
spu_log.success("PUTLLC16 Pattern Detected! (mem_count=%d, put_pc=0x%x, pc_rel=%d, offset=0x%x, const=%u, two_regs=%d, reg=%u, runtime=%d, 0x%x-%s) (putllc0=%d, putllc16+0=%d, all=%d)"
|
spu_log.success("PUTLLC16 Pattern Detected! (mem_count=%d, put_pc=0x%x, pc_rel=%d, offset=0x%x, const=%u, two_regs=%d, reg=%u, runtime=%d, 0x%x-%s, pattern-hash=%s) (putllc0=%d, putllc16+0=%d, all=%d)"
|
||||||
, pattern.mem_count, pattern.put_pc, value.type == v_relative, value.off18, value.type == v_const, value.type == v_reg2, value.reg, value.runtime16_select, entry_point, func_hash, +stats.nowrite, ++stats.single, +stats.all);
|
, pattern.mem_count, pattern.put_pc, value.type == v_relative, value.off18, value.type == v_const, value.type == v_reg2, value.reg, value.runtime16_select, entry_point, func_hash, pattern_hash, +stats.nowrite, ++stats.single, +stats.all);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& [read_pc, pattern] : rchcnt_loop_all)
|
for (const auto& [read_pc, pattern] : rchcnt_loop_all)
|
||||||
|
|
@ -7242,7 +7433,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
|
|
||||||
if (inst_attr attr = m_inst_attrs[(read_pc - entry_point) / 4]; attr == inst_attr::none)
|
if (inst_attr attr = m_inst_attrs[(read_pc - entry_point) / 4]; attr == inst_attr::none)
|
||||||
{
|
{
|
||||||
add_pattern(false, inst_attr::rchcnt_loop, read_pc - result.entry_point);
|
add_pattern(false, inst_attr::rchcnt_loop, read_pc - result.entry_point, 0);
|
||||||
|
|
||||||
spu_log.error("Channel Loop Pattern Detected! Report to developers! (read_pc=0x%x, branch_pc=0x%x, branch_target=0x%x, 0x%x-%s)", read_pc, pattern.branch_pc, pattern.branch_target, entry_point, func_hash);
|
spu_log.error("Channel Loop Pattern Detected! Report to developers! (read_pc=0x%x, branch_pc=0x%x, branch_target=0x%x, 0x%x-%s)", read_pc, pattern.branch_pc, pattern.branch_target, entry_point, func_hash);
|
||||||
}
|
}
|
||||||
|
|
@ -7258,6 +7449,26 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
// Blocks starting from 0x0 or invalid instruction won't be compiled, may need special interpreter fallback
|
// Blocks starting from 0x0 or invalid instruction won't be compiled, may need special interpreter fallback
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!m_patterns.empty())
|
||||||
|
{
|
||||||
|
std::string out_dump;
|
||||||
|
dump(result, out_dump);
|
||||||
|
spu_log.notice("Dump SPU Function with pattern(s):\n%s", out_dump);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < result.data.size(); i++)
|
||||||
|
{
|
||||||
|
const be_t<u32> ls_val = ls[result.lower_bound / 4 + i];
|
||||||
|
|
||||||
|
if (result.data[i] && std::bit_cast<u32>(ls_val) != result.data[i])
|
||||||
|
{
|
||||||
|
std::string out_dump;
|
||||||
|
dump(result, out_dump);
|
||||||
|
spu_log.error("SPU Function Dump:\n%s", out_dump);
|
||||||
|
fmt::throw_exception("SPU Analyzer failed: Instruction mismatch at 0x%x [read: 0x%x vs LS: 0x%x] (i=0x%x)", result.lower_bound + i * 4, std::bit_cast<be_t<u32>>(result.data[i]), ls_val, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -8267,8 +8478,9 @@ std::array<reg_state_t, s_reg_max>& block_reg_info::evaluate_start_state(const s
|
||||||
{
|
{
|
||||||
// TODO: The true maximum occurence count need to depend on the amount of branching-outs passed through
|
// TODO: The true maximum occurence count need to depend on the amount of branching-outs passed through
|
||||||
// Currently allow 2 for short-term code and 1 for long-term code
|
// Currently allow 2 for short-term code and 1 for long-term code
|
||||||
|
// Ignore large jumptables as well
|
||||||
const bool loop_terminator_detected = std::count(been_there.begin(), been_there.end(), prev_pc) >= (qi < 20 ? 2u : 1u);
|
const bool loop_terminator_detected = std::count(been_there.begin(), been_there.end(), prev_pc) >= (qi < 20 ? 2u : 1u);
|
||||||
const bool avoid_extensive_analysis = qi >= (extensive_evaluation ? 22 : 16);
|
const bool avoid_extensive_analysis = qi >= (extensive_evaluation ? 22 : 16) || it->state_prev.size() >= 8;
|
||||||
|
|
||||||
if (!loop_terminator_detected && !avoid_extensive_analysis)
|
if (!loop_terminator_detected && !avoid_extensive_analysis)
|
||||||
{
|
{
|
||||||
|
|
@ -8307,19 +8519,10 @@ std::array<reg_state_t, s_reg_max>& block_reg_info::evaluate_start_state(const s
|
||||||
return walkby_state;
|
return walkby_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void spu_recompiler_base::add_pattern(bool fill_all, inst_attr attr, u32 start, u32 end)
|
void spu_recompiler_base::add_pattern(bool fill_all, inst_attr attr, u32 start, u64 info)
|
||||||
{
|
{
|
||||||
if (end == umax)
|
m_patterns[start] = pattern_info{info};
|
||||||
{
|
m_inst_attrs[start / 4] = attr;
|
||||||
end = start;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_patterns[start] = pattern_info{utils::address_range32::start_end(start, end)};
|
|
||||||
|
|
||||||
for (u32 i = start; i <= (fill_all ? end : start); i += 4)
|
|
||||||
{
|
|
||||||
m_inst_attrs[i / 4] = attr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern std::string format_spu_func_info(u32 addr, cpu_thread* spu)
|
extern std::string format_spu_func_info(u32 addr, cpu_thread* spu)
|
||||||
|
|
|
||||||
|
|
@ -291,7 +291,7 @@ bool ROT(spu_thread& spu, spu_opcode_t op)
|
||||||
|
|
||||||
for (u32 i = 0; i < 4; i++)
|
for (u32 i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
spu.gpr[op.rt]._u32[i] = utils::rol32(a._u32[i], b._u32[i]);
|
spu.gpr[op.rt]._u32[i] = std::rotl<u32>(a._u32[i], b._u32[i]);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -346,7 +346,7 @@ bool ROTH(spu_thread& spu, spu_opcode_t op)
|
||||||
|
|
||||||
for (u32 i = 0; i < 8; i++)
|
for (u32 i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
spu.gpr[op.rt]._u16[i] = utils::rol16(a._u16[i], b._u16[i]);
|
spu.gpr[op.rt]._u16[i] = std::rotl<u16>(a._u16[i], b._u16[i]);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1080,7 +1080,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
|
||||||
m_ir->SetInsertPoint(_body);
|
m_ir->SetInsertPoint(_body);
|
||||||
}
|
}
|
||||||
|
|
||||||
void putllc16_pattern(const spu_program& /*prog*/, utils::address_range32 range)
|
void putllc16_pattern(const spu_program& /*prog*/, u64 pattern_info)
|
||||||
{
|
{
|
||||||
// Prevent store elimination
|
// Prevent store elimination
|
||||||
m_block->store_context_ctr[s_reg_mfc_eal]++;
|
m_block->store_context_ctr[s_reg_mfc_eal]++;
|
||||||
|
|
@ -1109,16 +1109,17 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const union putllc16_info
|
const union putllc16_or_0_info
|
||||||
{
|
{
|
||||||
u32 data;
|
u64 data;
|
||||||
bf_t<u32, 30, 2> type;
|
bf_t<u64, 32, 18> required_pc;
|
||||||
bf_t<u32, 29, 1> runtime16_select;
|
bf_t<u64, 30, 2> type;
|
||||||
bf_t<u32, 28, 1> no_notify;
|
bf_t<u64, 29, 1> runtime16_select;
|
||||||
bf_t<u32, 18, 8> reg;
|
bf_t<u64, 28, 1> no_notify;
|
||||||
bf_t<u32, 0, 18> off18;
|
bf_t<u64, 18, 8> reg;
|
||||||
bf_t<u32, 0, 8> reg2;
|
bf_t<u64, 0, 18> off18;
|
||||||
} info = std::bit_cast<putllc16_info>(range.end);
|
bf_t<u64, 0, 8> reg2;
|
||||||
|
} info = std::bit_cast<putllc16_or_0_info>(pattern_info);
|
||||||
|
|
||||||
enum : u32
|
enum : u32
|
||||||
{
|
{
|
||||||
|
|
@ -1150,8 +1151,10 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
|
||||||
value_t<u32> eal_val;
|
value_t<u32> eal_val;
|
||||||
eal_val.value = _eal;
|
eal_val.value = _eal;
|
||||||
|
|
||||||
auto get_reg32 = [&](u32 reg)
|
auto get_reg32 = [&](u64 reg_)
|
||||||
{
|
{
|
||||||
|
const u32 reg = static_cast<u32>(reg_);
|
||||||
|
|
||||||
if (get_reg_type(reg) != get_type<u32[4]>())
|
if (get_reg_type(reg) != get_type<u32[4]>())
|
||||||
{
|
{
|
||||||
return get_reg_fixed(reg, get_type<u32>());
|
return get_reg_fixed(reg, get_type<u32>());
|
||||||
|
|
@ -1170,6 +1173,19 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
|
||||||
}
|
}
|
||||||
else if (info.type == v_relative)
|
else if (info.type == v_relative)
|
||||||
{
|
{
|
||||||
|
if (info.required_pc && info.required_pc != SPU_LS_SIZE)
|
||||||
|
{
|
||||||
|
const auto short_op = llvm::BasicBlock::Create(m_context, "__putllc16_short_op", m_function);
|
||||||
|
const auto heavy_op = llvm::BasicBlock::Create(m_context, "__putllc16_heavy_op", m_function);
|
||||||
|
|
||||||
|
m_ir->CreateCondBr(m_ir->CreateICmpNE(m_ir->getInt32(info.required_pc), m_base_pc), heavy_op, short_op);
|
||||||
|
m_ir->SetInsertPoint(heavy_op);
|
||||||
|
update_pc();
|
||||||
|
call("spu_exec_mfc_cmd", &exec_mfc_cmd<false>, m_thread);
|
||||||
|
m_ir->CreateBr(_final);
|
||||||
|
m_ir->SetInsertPoint(short_op);
|
||||||
|
}
|
||||||
|
|
||||||
dest = m_ir->CreateAnd(get_pc(spu_branch_target(info.off18 + m_base)), 0x3fff0);
|
dest = m_ir->CreateAnd(get_pc(spu_branch_target(info.off18 + m_base)), 0x3fff0);
|
||||||
}
|
}
|
||||||
else if (info.type == v_reg_offs)
|
else if (info.type == v_reg_offs)
|
||||||
|
|
@ -1268,17 +1284,18 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
|
||||||
const auto _new = m_ir->CreateAlignedLoad(get_type<u128>(), _ptr(m_lsptr, dest), llvm::MaybeAlign{16});
|
const auto _new = m_ir->CreateAlignedLoad(get_type<u128>(), _ptr(m_lsptr, dest), llvm::MaybeAlign{16});
|
||||||
const auto _rdata = m_ir->CreateAlignedLoad(get_type<u128>(), _ptr(spu_ptr(&spu_thread::rdata), m_ir->CreateAnd(diff, 0x70)), llvm::MaybeAlign{16});
|
const auto _rdata = m_ir->CreateAlignedLoad(get_type<u128>(), _ptr(spu_ptr(&spu_thread::rdata), m_ir->CreateAnd(diff, 0x70)), llvm::MaybeAlign{16});
|
||||||
|
|
||||||
const bool is_accurate_op = !!g_cfg.core.spu_accurate_reservations;
|
const bool is_accurate_op = true || !!g_cfg.core.spu_accurate_reservations;
|
||||||
|
|
||||||
const auto compare_data_change_res = is_accurate_op ? m_ir->getTrue() : m_ir->CreateICmpNE(_new, _rdata);
|
const auto compare_data_change_res = m_ir->CreateICmpNE(_new, _rdata);
|
||||||
|
const auto second_test_for_complete_op = is_accurate_op ? m_ir->getTrue() : compare_data_change_res;
|
||||||
|
|
||||||
if (info.runtime16_select)
|
if (info.runtime16_select)
|
||||||
{
|
{
|
||||||
m_ir->CreateCondBr(m_ir->CreateAnd(m_ir->CreateICmpULT(diff, m_ir->getInt64(128)), compare_data_change_res), _begin_op, _inc_res, m_md_likely);
|
m_ir->CreateCondBr(m_ir->CreateAnd(m_ir->CreateICmpULT(diff, m_ir->getInt64(128)), second_test_for_complete_op), _begin_op, _inc_res, m_md_likely);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_ir->CreateCondBr(compare_data_change_res, _begin_op, _inc_res, m_md_unlikely);
|
m_ir->CreateCondBr(second_test_for_complete_op, _begin_op, _inc_res, m_md_unlikely);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ir->SetInsertPoint(_begin_op);
|
m_ir->SetInsertPoint(_begin_op);
|
||||||
|
|
@ -1323,7 +1340,14 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
|
||||||
|
|
||||||
if (!info.no_notify)
|
if (!info.no_notify)
|
||||||
{
|
{
|
||||||
|
const auto notify_block = llvm::BasicBlock::Create(m_context, "__putllc16_block_notify", m_function);
|
||||||
|
const auto notify_next = llvm::BasicBlock::Create(m_context, "__putllc16_block_notify_next", m_function);
|
||||||
|
|
||||||
|
m_ir->CreateCondBr(compare_data_change_res, notify_block, notify_next);
|
||||||
|
m_ir->SetInsertPoint(notify_block);
|
||||||
call("atomic_wait_engine::notify_all", static_cast<void(*)(const void*)>(atomic_wait_engine::notify_all), rptr);
|
call("atomic_wait_engine::notify_all", static_cast<void(*)(const void*)>(atomic_wait_engine::notify_all), rptr);
|
||||||
|
m_ir->CreateBr(notify_next);
|
||||||
|
m_ir->SetInsertPoint(notify_next);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ir->CreateBr(_success);
|
m_ir->CreateBr(_success);
|
||||||
|
|
@ -1373,7 +1397,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
|
||||||
m_ir->SetInsertPoint(_final);
|
m_ir->SetInsertPoint(_final);
|
||||||
}
|
}
|
||||||
|
|
||||||
void putllc0_pattern(const spu_program& /*prog*/, utils::address_range32 /*range*/)
|
void putllc0_pattern(const spu_program& /*prog*/, u64 pattern_info)
|
||||||
{
|
{
|
||||||
// Prevent store elimination
|
// Prevent store elimination
|
||||||
m_block->store_context_ctr[s_reg_mfc_eal]++;
|
m_block->store_context_ctr[s_reg_mfc_eal]++;
|
||||||
|
|
@ -1401,6 +1425,18 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const union putllc16_or_0_info
|
||||||
|
{
|
||||||
|
u64 data;
|
||||||
|
bf_t<u64, 32, 18> required_pc;
|
||||||
|
bf_t<u64, 30, 2> type;
|
||||||
|
bf_t<u64, 29, 1> runtime16_select;
|
||||||
|
bf_t<u64, 28, 1> no_notify;
|
||||||
|
bf_t<u64, 18, 8> reg;
|
||||||
|
bf_t<u64, 0, 18> off18;
|
||||||
|
bf_t<u64, 0, 8> reg2;
|
||||||
|
} info = std::bit_cast<putllc16_or_0_info>(pattern_info);
|
||||||
|
|
||||||
const auto _next = llvm::BasicBlock::Create(m_context, "", m_function);
|
const auto _next = llvm::BasicBlock::Create(m_context, "", m_function);
|
||||||
const auto _next0 = llvm::BasicBlock::Create(m_context, "", m_function);
|
const auto _next0 = llvm::BasicBlock::Create(m_context, "", m_function);
|
||||||
const auto _fail = llvm::BasicBlock::Create(m_context, "", m_function);
|
const auto _fail = llvm::BasicBlock::Create(m_context, "", m_function);
|
||||||
|
|
@ -1409,6 +1445,19 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
|
||||||
const auto _eal = (get_reg_fixed<u32>(s_reg_mfc_eal) & -128).eval(m_ir);
|
const auto _eal = (get_reg_fixed<u32>(s_reg_mfc_eal) & -128).eval(m_ir);
|
||||||
const auto _raddr = m_ir->CreateLoad(get_type<u32>(), spu_ptr(&spu_thread::raddr));
|
const auto _raddr = m_ir->CreateLoad(get_type<u32>(), spu_ptr(&spu_thread::raddr));
|
||||||
|
|
||||||
|
if (info.required_pc && info.required_pc != SPU_LS_SIZE)
|
||||||
|
{
|
||||||
|
const auto short_op = llvm::BasicBlock::Create(m_context, "__putllc0_short_op", m_function);
|
||||||
|
const auto heavy_op = llvm::BasicBlock::Create(m_context, "__putllc0_heavy_op", m_function);
|
||||||
|
|
||||||
|
m_ir->CreateCondBr(m_ir->CreateICmpNE(m_ir->getInt32(info.required_pc), m_base_pc), heavy_op, short_op);
|
||||||
|
m_ir->SetInsertPoint(heavy_op);
|
||||||
|
update_pc();
|
||||||
|
call("spu_exec_mfc_cmd", &exec_mfc_cmd<false>, m_thread);
|
||||||
|
m_ir->CreateBr(_final);
|
||||||
|
m_ir->SetInsertPoint(short_op);
|
||||||
|
}
|
||||||
|
|
||||||
m_ir->CreateCondBr(m_ir->CreateAnd(m_ir->CreateICmpEQ(_eal, _raddr), m_ir->CreateIsNotNull(_raddr)), _next, _fail, m_md_likely);
|
m_ir->CreateCondBr(m_ir->CreateAnd(m_ir->CreateICmpEQ(_eal, _raddr), m_ir->CreateIsNotNull(_raddr)), _next, _fail, m_md_likely);
|
||||||
m_ir->SetInsertPoint(_next);
|
m_ir->SetInsertPoint(_next);
|
||||||
|
|
||||||
|
|
@ -1598,7 +1647,11 @@ public:
|
||||||
|
|
||||||
// Create LLVM module
|
// Create LLVM module
|
||||||
std::unique_ptr<Module> _module = std::make_unique<Module>(m_hash + ".obj", m_context);
|
std::unique_ptr<Module> _module = std::make_unique<Module>(m_hash + ".obj", m_context);
|
||||||
|
#if LLVM_VERSION_MAJOR >= 21 && (LLVM_VERSION_MINOR >= 1 || LLVM_VERSION_MAJOR >= 22)
|
||||||
|
_module->setTargetTriple(Triple(jit_compiler::triple2()));
|
||||||
|
#else
|
||||||
_module->setTargetTriple(jit_compiler::triple2());
|
_module->setTargetTriple(jit_compiler::triple2());
|
||||||
|
#endif
|
||||||
_module->setDataLayout(m_jit.get_engine().getTargetMachine()->createDataLayout());
|
_module->setDataLayout(m_jit.get_engine().getTargetMachine()->createDataLayout());
|
||||||
m_module = _module.get();
|
m_module = _module.get();
|
||||||
|
|
||||||
|
|
@ -1632,7 +1685,7 @@ public:
|
||||||
m_ir->SetInsertPoint(label_test);
|
m_ir->SetInsertPoint(label_test);
|
||||||
|
|
||||||
// Set block hash for profiling (if enabled)
|
// Set block hash for profiling (if enabled)
|
||||||
if (g_cfg.core.spu_prof && g_cfg.core.spu_verification)
|
if ((g_cfg.core.spu_prof || g_cfg.core.spu_debug) && g_cfg.core.spu_verification)
|
||||||
m_ir->CreateStore(m_ir->getInt64((m_hash_start & -65536)), spu_ptr(&spu_thread::block_hash));
|
m_ir->CreateStore(m_ir->getInt64((m_hash_start & -65536)), spu_ptr(&spu_thread::block_hash));
|
||||||
|
|
||||||
if (!g_cfg.core.spu_verification)
|
if (!g_cfg.core.spu_verification)
|
||||||
|
|
@ -1989,7 +2042,7 @@ public:
|
||||||
set_function(m_functions[m_entry].chunk);
|
set_function(m_functions[m_entry].chunk);
|
||||||
|
|
||||||
// Set block hash for profiling (if enabled)
|
// Set block hash for profiling (if enabled)
|
||||||
if (g_cfg.core.spu_prof)
|
if (g_cfg.core.spu_prof || g_cfg.core.spu_debug)
|
||||||
m_ir->CreateStore(m_ir->getInt64((m_hash_start & -65536) | (m_entry >> 2)), spu_ptr(&spu_thread::block_hash));
|
m_ir->CreateStore(m_ir->getInt64((m_hash_start & -65536) | (m_entry >> 2)), spu_ptr(&spu_thread::block_hash));
|
||||||
|
|
||||||
m_finfo = &m_functions[m_entry];
|
m_finfo = &m_functions[m_entry];
|
||||||
|
|
@ -2139,12 +2192,12 @@ public:
|
||||||
{
|
{
|
||||||
case inst_attr::putllc0:
|
case inst_attr::putllc0:
|
||||||
{
|
{
|
||||||
putllc0_pattern(func, m_patterns.at(m_pos - start).range);
|
putllc0_pattern(func, m_patterns.at(m_pos - start).info);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case inst_attr::putllc16:
|
case inst_attr::putllc16:
|
||||||
{
|
{
|
||||||
putllc16_pattern(func, m_patterns.at(m_pos - start).range);
|
putllc16_pattern(func, m_patterns.at(m_pos - start).info);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case inst_attr::omit:
|
case inst_attr::omit:
|
||||||
|
|
@ -2227,6 +2280,12 @@ public:
|
||||||
{
|
{
|
||||||
for (auto& [a, b] : m_blocks)
|
for (auto& [a, b] : m_blocks)
|
||||||
{
|
{
|
||||||
|
if (has_gpr_memory_barriers)
|
||||||
|
{
|
||||||
|
// Dive deeper and inspect GPR store barriers
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the store occurs before any barrier in the block
|
// Check if the store occurs before any barrier in the block
|
||||||
if (b.store[i] && b.store[i] != bs && b.store_context_first_id[i] == 1)
|
if (b.store[i] && b.store[i] != bs && b.store_context_first_id[i] == 1)
|
||||||
{
|
{
|
||||||
|
|
@ -2873,7 +2932,11 @@ public:
|
||||||
|
|
||||||
// Create LLVM module
|
// Create LLVM module
|
||||||
std::unique_ptr<Module> _module = std::make_unique<Module>("spu_interpreter.obj", m_context);
|
std::unique_ptr<Module> _module = std::make_unique<Module>("spu_interpreter.obj", m_context);
|
||||||
|
#if LLVM_VERSION_MAJOR >= 21 && (LLVM_VERSION_MINOR >= 1 || LLVM_VERSION_MAJOR >= 22)
|
||||||
|
_module->setTargetTriple(Triple(jit_compiler::triple2()));
|
||||||
|
#else
|
||||||
_module->setTargetTriple(jit_compiler::triple2());
|
_module->setTargetTriple(jit_compiler::triple2());
|
||||||
|
#endif
|
||||||
_module->setDataLayout(m_jit.get_engine().getTargetMachine()->createDataLayout());
|
_module->setDataLayout(m_jit.get_engine().getTargetMachine()->createDataLayout());
|
||||||
m_module = _module.get();
|
m_module = _module.get();
|
||||||
|
|
||||||
|
|
@ -3977,7 +4040,7 @@ public:
|
||||||
|
|
||||||
bool must_use_cpp_functions = !!g_cfg.core.spu_accurate_dma;
|
bool must_use_cpp_functions = !!g_cfg.core.spu_accurate_dma;
|
||||||
|
|
||||||
if (u64 cmdh = ci->getZExtValue() & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_RESULT_MASK); g_cfg.core.rsx_fifo_accuracy || g_cfg.video.strict_rendering_mode || !g_use_rtm)
|
if (u64 cmdh = ci->getZExtValue() & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_RESULT_MASK); g_cfg.core.rsx_fifo_accuracy || g_cfg.video.strict_rendering_mode || /*!g_use_rtm*/ true)
|
||||||
{
|
{
|
||||||
// TODO: don't require TSX (current implementation is TSX-only)
|
// TODO: don't require TSX (current implementation is TSX-only)
|
||||||
if (cmdh == MFC_PUT_CMD || cmdh == MFC_SNDSIG_CMD)
|
if (cmdh == MFC_PUT_CMD || cmdh == MFC_SNDSIG_CMD)
|
||||||
|
|
|
||||||
|
|
@ -397,12 +397,12 @@ protected:
|
||||||
|
|
||||||
struct pattern_info
|
struct pattern_info
|
||||||
{
|
{
|
||||||
utils::address_range32 range;
|
u64 info;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unordered_map<u32, pattern_info> m_patterns;
|
std::unordered_map<u32, pattern_info> m_patterns;
|
||||||
|
|
||||||
void add_pattern(bool fill_all, inst_attr attr, u32 start, u32 end = -1);
|
void add_pattern(bool fill_all, inst_attr attr, u32 start, u64 info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// For private use
|
// For private use
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -901,7 +901,8 @@ public:
|
||||||
|
|
||||||
// Returns true if reservation existed but was just discovered to be lost
|
// Returns true if reservation existed but was just discovered to be lost
|
||||||
// It is safe to use on any address, even if not directly accessed by SPU (so it's slower)
|
// It is safe to use on any address, even if not directly accessed by SPU (so it's slower)
|
||||||
bool reservation_check(u32 addr, const decltype(rdata)& data) const;
|
// Optionally pass a known allocated address for internal optimization (the current Effective-Address of the MFC command)
|
||||||
|
bool reservation_check(u32 addr, const decltype(rdata)& data, u32 current_eal = 0) const;
|
||||||
static bool reservation_check(u32 addr, u32 hash, atomic_t<u64, 64>* range_lock);
|
static bool reservation_check(u32 addr, u32 hash, atomic_t<u64, 64>* range_lock);
|
||||||
usz register_cache_line_waiter(u32 addr);
|
usz register_cache_line_waiter(u32 addr);
|
||||||
void deregister_cache_line_waiter(usz index);
|
void deregister_cache_line_waiter(usz index);
|
||||||
|
|
|
||||||
|
|
@ -1036,7 +1036,6 @@ lv2_file::open_result_t lv2_file::open(std::string_view vpath, s32 flags, s32 mo
|
||||||
error_code sys_fs_open(ppu_thread& ppu, vm::cptr<char> path, s32 flags, vm::ptr<u32> fd, s32 mode, vm::cptr<void> arg, u64 size)
|
error_code sys_fs_open(ppu_thread& ppu, vm::cptr<char> path, s32 flags, vm::ptr<u32> fd, s32 mode, vm::cptr<void> arg, u64 size)
|
||||||
{
|
{
|
||||||
ppu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
lv2_obj::sleep(ppu);
|
|
||||||
|
|
||||||
sys_fs.warning("sys_fs_open(path=%s, flags=%#o, fd=*0x%x, mode=%#o, arg=*0x%x, size=0x%llx)", path, flags, fd, mode, arg, size);
|
sys_fs.warning("sys_fs_open(path=%s, flags=%#o, fd=*0x%x, mode=%#o, arg=*0x%x, size=0x%llx)", path, flags, fd, mode, arg, size);
|
||||||
|
|
||||||
|
|
@ -1085,7 +1084,6 @@ error_code sys_fs_open(ppu_thread& ppu, vm::cptr<char> path, s32 flags, vm::ptr<
|
||||||
error_code sys_fs_read(ppu_thread& ppu, u32 fd, vm::ptr<void> buf, u64 nbytes, vm::ptr<u64> nread)
|
error_code sys_fs_read(ppu_thread& ppu, u32 fd, vm::ptr<void> buf, u64 nbytes, vm::ptr<u64> nread)
|
||||||
{
|
{
|
||||||
ppu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
lv2_obj::sleep(ppu);
|
|
||||||
|
|
||||||
sys_fs.trace("sys_fs_read(fd=%d, buf=*0x%x, nbytes=0x%llx, nread=*0x%x)", fd, buf, nbytes, nread);
|
sys_fs.trace("sys_fs_read(fd=%d, buf=*0x%x, nbytes=0x%llx, nread=*0x%x)", fd, buf, nbytes, nread);
|
||||||
|
|
||||||
|
|
@ -1122,6 +1120,11 @@ error_code sys_fs_read(ppu_thread& ppu, u32 fd, vm::ptr<void> buf, u64 nbytes, v
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nbytes >= 0x100000 && file->type != lv2_file_type::regular)
|
||||||
|
{
|
||||||
|
lv2_obj::sleep(ppu);
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_lock lock(file->mp->mutex);
|
std::unique_lock lock(file->mp->mutex);
|
||||||
|
|
||||||
if (!file->file)
|
if (!file->file)
|
||||||
|
|
@ -1154,7 +1157,6 @@ error_code sys_fs_read(ppu_thread& ppu, u32 fd, vm::ptr<void> buf, u64 nbytes, v
|
||||||
error_code sys_fs_write(ppu_thread& ppu, u32 fd, vm::cptr<void> buf, u64 nbytes, vm::ptr<u64> nwrite)
|
error_code sys_fs_write(ppu_thread& ppu, u32 fd, vm::cptr<void> buf, u64 nbytes, vm::ptr<u64> nwrite)
|
||||||
{
|
{
|
||||||
ppu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
lv2_obj::sleep(ppu);
|
|
||||||
|
|
||||||
sys_fs.trace("sys_fs_write(fd=%d, buf=*0x%x, nbytes=0x%llx, nwrite=*0x%x)", fd, buf, nbytes, nwrite);
|
sys_fs.trace("sys_fs_write(fd=%d, buf=*0x%x, nbytes=0x%llx, nwrite=*0x%x)", fd, buf, nbytes, nwrite);
|
||||||
|
|
||||||
|
|
@ -1237,7 +1239,6 @@ error_code sys_fs_write(ppu_thread& ppu, u32 fd, vm::cptr<void> buf, u64 nbytes,
|
||||||
error_code sys_fs_close(ppu_thread& ppu, u32 fd)
|
error_code sys_fs_close(ppu_thread& ppu, u32 fd)
|
||||||
{
|
{
|
||||||
ppu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
lv2_obj::sleep(ppu);
|
|
||||||
|
|
||||||
const auto file = idm::get_unlocked<lv2_fs_object, lv2_file>(fd);
|
const auto file = idm::get_unlocked<lv2_fs_object, lv2_file>(fd);
|
||||||
|
|
||||||
|
|
@ -1314,7 +1315,6 @@ error_code sys_fs_close(ppu_thread& ppu, u32 fd)
|
||||||
error_code sys_fs_opendir(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<u32> fd)
|
error_code sys_fs_opendir(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<u32> fd)
|
||||||
{
|
{
|
||||||
ppu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
lv2_obj::sleep(ppu);
|
|
||||||
|
|
||||||
sys_fs.warning("sys_fs_opendir(path=%s, fd=*0x%x)", path, fd);
|
sys_fs.warning("sys_fs_opendir(path=%s, fd=*0x%x)", path, fd);
|
||||||
|
|
||||||
|
|
@ -1491,7 +1491,6 @@ error_code sys_fs_readdir(ppu_thread& ppu, u32 fd, vm::ptr<CellFsDirent> dir, vm
|
||||||
error_code sys_fs_closedir(ppu_thread& ppu, u32 fd)
|
error_code sys_fs_closedir(ppu_thread& ppu, u32 fd)
|
||||||
{
|
{
|
||||||
ppu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
lv2_obj::sleep(ppu);
|
|
||||||
|
|
||||||
sys_fs.warning("sys_fs_closedir(fd=%d)", fd);
|
sys_fs.warning("sys_fs_closedir(fd=%d)", fd);
|
||||||
|
|
||||||
|
|
@ -1506,7 +1505,6 @@ error_code sys_fs_closedir(ppu_thread& ppu, u32 fd)
|
||||||
error_code sys_fs_stat(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<CellFsStat> sb)
|
error_code sys_fs_stat(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<CellFsStat> sb)
|
||||||
{
|
{
|
||||||
ppu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
lv2_obj::sleep(ppu);
|
|
||||||
|
|
||||||
sys_fs.warning("sys_fs_stat(path=%s, sb=*0x%x)", path, sb);
|
sys_fs.warning("sys_fs_stat(path=%s, sb=*0x%x)", path, sb);
|
||||||
|
|
||||||
|
|
@ -1610,7 +1608,6 @@ error_code sys_fs_stat(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<CellFsStat>
|
||||||
error_code sys_fs_fstat(ppu_thread& ppu, u32 fd, vm::ptr<CellFsStat> sb)
|
error_code sys_fs_fstat(ppu_thread& ppu, u32 fd, vm::ptr<CellFsStat> sb)
|
||||||
{
|
{
|
||||||
ppu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
lv2_obj::sleep(ppu);
|
|
||||||
|
|
||||||
sys_fs.warning("sys_fs_fstat(fd=%d, sb=*0x%x)", fd, sb);
|
sys_fs.warning("sys_fs_fstat(fd=%d, sb=*0x%x)", fd, sb);
|
||||||
|
|
||||||
|
|
@ -1666,7 +1663,6 @@ error_code sys_fs_link(ppu_thread&, vm::cptr<char> from, vm::cptr<char> to)
|
||||||
error_code sys_fs_mkdir(ppu_thread& ppu, vm::cptr<char> path, s32 mode)
|
error_code sys_fs_mkdir(ppu_thread& ppu, vm::cptr<char> path, s32 mode)
|
||||||
{
|
{
|
||||||
ppu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
lv2_obj::sleep(ppu);
|
|
||||||
|
|
||||||
sys_fs.warning("sys_fs_mkdir(path=%s, mode=%#o)", path, mode);
|
sys_fs.warning("sys_fs_mkdir(path=%s, mode=%#o)", path, mode);
|
||||||
|
|
||||||
|
|
@ -1728,7 +1724,6 @@ error_code sys_fs_mkdir(ppu_thread& ppu, vm::cptr<char> path, s32 mode)
|
||||||
error_code sys_fs_rename(ppu_thread& ppu, vm::cptr<char> from, vm::cptr<char> to)
|
error_code sys_fs_rename(ppu_thread& ppu, vm::cptr<char> from, vm::cptr<char> to)
|
||||||
{
|
{
|
||||||
ppu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
lv2_obj::sleep(ppu);
|
|
||||||
|
|
||||||
sys_fs.warning("sys_fs_rename(from=%s, to=%s)", from, to);
|
sys_fs.warning("sys_fs_rename(from=%s, to=%s)", from, to);
|
||||||
|
|
||||||
|
|
@ -1794,7 +1789,6 @@ error_code sys_fs_rename(ppu_thread& ppu, vm::cptr<char> from, vm::cptr<char> to
|
||||||
error_code sys_fs_rmdir(ppu_thread& ppu, vm::cptr<char> path)
|
error_code sys_fs_rmdir(ppu_thread& ppu, vm::cptr<char> path)
|
||||||
{
|
{
|
||||||
ppu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
lv2_obj::sleep(ppu);
|
|
||||||
|
|
||||||
sys_fs.warning("sys_fs_rmdir(path=%s)", path);
|
sys_fs.warning("sys_fs_rmdir(path=%s)", path);
|
||||||
|
|
||||||
|
|
@ -1850,7 +1844,6 @@ error_code sys_fs_rmdir(ppu_thread& ppu, vm::cptr<char> path)
|
||||||
error_code sys_fs_unlink(ppu_thread& ppu, vm::cptr<char> path)
|
error_code sys_fs_unlink(ppu_thread& ppu, vm::cptr<char> path)
|
||||||
{
|
{
|
||||||
ppu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
lv2_obj::sleep(ppu);
|
|
||||||
|
|
||||||
sys_fs.warning("sys_fs_unlink(path=%s)", path);
|
sys_fs.warning("sys_fs_unlink(path=%s)", path);
|
||||||
|
|
||||||
|
|
@ -1951,8 +1944,6 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr<void> _arg, u32
|
||||||
case 0x8000000a: // cellFsReadWithOffset
|
case 0x8000000a: // cellFsReadWithOffset
|
||||||
case 0x8000000b: // cellFsWriteWithOffset
|
case 0x8000000b: // cellFsWriteWithOffset
|
||||||
{
|
{
|
||||||
lv2_obj::sleep(ppu);
|
|
||||||
|
|
||||||
const auto arg = vm::static_ptr_cast<lv2_file_op_rw>(_arg);
|
const auto arg = vm::static_ptr_cast<lv2_file_op_rw>(_arg);
|
||||||
|
|
||||||
if (_size < arg.size())
|
if (_size < arg.size())
|
||||||
|
|
@ -1992,6 +1983,11 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr<void> _arg, u32
|
||||||
sys_fs.error("%s type: Writing %u bytes to FD=%d (path=%s)", file->type, arg->size, file->name.data());
|
sys_fs.error("%s type: Writing %u bytes to FD=%d (path=%s)", file->type, arg->size, file->name.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (op == 0x8000000a && file->type != lv2_file_type::regular && arg->size >= 0x100000)
|
||||||
|
{
|
||||||
|
lv2_obj::sleep(ppu);
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_lock wlock(file->mp->mutex, std::defer_lock);
|
std::unique_lock wlock(file->mp->mutex, std::defer_lock);
|
||||||
std::shared_lock rlock(file->mp->mutex, std::defer_lock);
|
std::shared_lock rlock(file->mp->mutex, std::defer_lock);
|
||||||
|
|
||||||
|
|
@ -2047,8 +2043,6 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr<void> _arg, u32
|
||||||
|
|
||||||
case 0x80000009: // cellFsSdataOpenByFd
|
case 0x80000009: // cellFsSdataOpenByFd
|
||||||
{
|
{
|
||||||
lv2_obj::sleep(ppu);
|
|
||||||
|
|
||||||
const auto arg = vm::static_ptr_cast<lv2_file_op_09>(_arg);
|
const auto arg = vm::static_ptr_cast<lv2_file_op_09>(_arg);
|
||||||
|
|
||||||
if (_size < arg.size())
|
if (_size < arg.size())
|
||||||
|
|
@ -2102,8 +2096,6 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr<void> _arg, u32
|
||||||
|
|
||||||
case 0xc0000002: // cellFsGetFreeSize (TODO)
|
case 0xc0000002: // cellFsGetFreeSize (TODO)
|
||||||
{
|
{
|
||||||
lv2_obj::sleep(ppu);
|
|
||||||
|
|
||||||
const auto arg = vm::static_ptr_cast<lv2_file_c0000002>(_arg);
|
const auto arg = vm::static_ptr_cast<lv2_file_c0000002>(_arg);
|
||||||
|
|
||||||
const auto& mp = g_fxo->get<lv2_fs_mount_info_map>().lookup("/dev_hdd0");
|
const auto& mp = g_fxo->get<lv2_fs_mount_info_map>().lookup("/dev_hdd0");
|
||||||
|
|
@ -2418,8 +2410,6 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr<void> _arg, u32
|
||||||
|
|
||||||
case 0xe0000012: // cellFsGetDirectoryEntries
|
case 0xe0000012: // cellFsGetDirectoryEntries
|
||||||
{
|
{
|
||||||
lv2_obj::sleep(ppu);
|
|
||||||
|
|
||||||
const auto arg = vm::static_ptr_cast<lv2_file_op_dir::dir_info>(_arg);
|
const auto arg = vm::static_ptr_cast<lv2_file_op_dir::dir_info>(_arg);
|
||||||
|
|
||||||
if (_size < arg.size())
|
if (_size < arg.size())
|
||||||
|
|
@ -2434,8 +2424,6 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr<void> _arg, u32
|
||||||
return CELL_EBADF;
|
return CELL_EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
ppu.check_state();
|
|
||||||
|
|
||||||
u32 read_count = 0;
|
u32 read_count = 0;
|
||||||
|
|
||||||
// NOTE: This function is actually capable of reading only one entry at a time
|
// NOTE: This function is actually capable of reading only one entry at a time
|
||||||
|
|
@ -2593,7 +2581,6 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr<void> _arg, u32
|
||||||
error_code sys_fs_lseek(ppu_thread& ppu, u32 fd, s64 offset, s32 whence, vm::ptr<u64> pos)
|
error_code sys_fs_lseek(ppu_thread& ppu, u32 fd, s64 offset, s32 whence, vm::ptr<u64> pos)
|
||||||
{
|
{
|
||||||
ppu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
lv2_obj::sleep(ppu);
|
|
||||||
|
|
||||||
sys_fs.trace("sys_fs_lseek(fd=%d, offset=0x%llx, whence=0x%x, pos=*0x%x)", fd, offset, whence, pos);
|
sys_fs.trace("sys_fs_lseek(fd=%d, offset=0x%llx, whence=0x%x, pos=*0x%x)", fd, offset, whence, pos);
|
||||||
|
|
||||||
|
|
@ -2639,7 +2626,6 @@ error_code sys_fs_lseek(ppu_thread& ppu, u32 fd, s64 offset, s32 whence, vm::ptr
|
||||||
error_code sys_fs_fdatasync(ppu_thread& ppu, u32 fd)
|
error_code sys_fs_fdatasync(ppu_thread& ppu, u32 fd)
|
||||||
{
|
{
|
||||||
ppu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
lv2_obj::sleep(ppu);
|
|
||||||
|
|
||||||
sys_fs.trace("sys_fs_fdadasync(fd=%d)", fd);
|
sys_fs.trace("sys_fs_fdadasync(fd=%d)", fd);
|
||||||
|
|
||||||
|
|
@ -2650,6 +2636,8 @@ error_code sys_fs_fdatasync(ppu_thread& ppu, u32 fd)
|
||||||
return CELL_EBADF;
|
return CELL_EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lv2_obj::sleep(ppu);
|
||||||
|
|
||||||
std::lock_guard lock(file->mp->mutex);
|
std::lock_guard lock(file->mp->mutex);
|
||||||
|
|
||||||
if (!file->file)
|
if (!file->file)
|
||||||
|
|
@ -2664,7 +2652,6 @@ error_code sys_fs_fdatasync(ppu_thread& ppu, u32 fd)
|
||||||
error_code sys_fs_fsync(ppu_thread& ppu, u32 fd)
|
error_code sys_fs_fsync(ppu_thread& ppu, u32 fd)
|
||||||
{
|
{
|
||||||
ppu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
lv2_obj::sleep(ppu);
|
|
||||||
|
|
||||||
sys_fs.trace("sys_fs_fsync(fd=%d)", fd);
|
sys_fs.trace("sys_fs_fsync(fd=%d)", fd);
|
||||||
|
|
||||||
|
|
@ -2675,6 +2662,8 @@ error_code sys_fs_fsync(ppu_thread& ppu, u32 fd)
|
||||||
return CELL_EBADF;
|
return CELL_EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lv2_obj::sleep(ppu);
|
||||||
|
|
||||||
std::lock_guard lock(file->mp->mutex);
|
std::lock_guard lock(file->mp->mutex);
|
||||||
|
|
||||||
if (!file->file)
|
if (!file->file)
|
||||||
|
|
@ -2763,7 +2752,6 @@ error_code sys_fs_get_block_size(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<u
|
||||||
error_code sys_fs_truncate(ppu_thread& ppu, vm::cptr<char> path, u64 size)
|
error_code sys_fs_truncate(ppu_thread& ppu, vm::cptr<char> path, u64 size)
|
||||||
{
|
{
|
||||||
ppu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
lv2_obj::sleep(ppu);
|
|
||||||
|
|
||||||
sys_fs.warning("sys_fs_truncate(path=%s, size=0x%llx)", path, size);
|
sys_fs.warning("sys_fs_truncate(path=%s, size=0x%llx)", path, size);
|
||||||
|
|
||||||
|
|
@ -2815,7 +2803,6 @@ error_code sys_fs_truncate(ppu_thread& ppu, vm::cptr<char> path, u64 size)
|
||||||
error_code sys_fs_ftruncate(ppu_thread& ppu, u32 fd, u64 size)
|
error_code sys_fs_ftruncate(ppu_thread& ppu, u32 fd, u64 size)
|
||||||
{
|
{
|
||||||
ppu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
lv2_obj::sleep(ppu);
|
|
||||||
|
|
||||||
sys_fs.warning("sys_fs_ftruncate(fd=%d, size=0x%llx)", fd, size);
|
sys_fs.warning("sys_fs_ftruncate(fd=%d, size=0x%llx)", fd, size);
|
||||||
|
|
||||||
|
|
@ -3021,7 +3008,6 @@ error_code sys_fs_disk_free(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<u64> t
|
||||||
error_code sys_fs_utime(ppu_thread& ppu, vm::cptr<char> path, vm::cptr<CellFsUtimbuf> timep)
|
error_code sys_fs_utime(ppu_thread& ppu, vm::cptr<char> path, vm::cptr<CellFsUtimbuf> timep)
|
||||||
{
|
{
|
||||||
ppu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
lv2_obj::sleep(ppu);
|
|
||||||
|
|
||||||
sys_fs.warning("sys_fs_utime(path=%s, timep=*0x%x)", path, timep);
|
sys_fs.warning("sys_fs_utime(path=%s, timep=*0x%x)", path, timep);
|
||||||
sys_fs.warning("** actime=%u, modtime=%u", timep->actime, timep->modtime);
|
sys_fs.warning("** actime=%u, modtime=%u", timep->actime, timep->modtime);
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include "Emu/CPU/CPUThread.h"
|
#include "Emu/CPU/CPUThread.h"
|
||||||
#include "Emu/Cell/ErrorCodes.h"
|
#include "Emu/Cell/ErrorCodes.h"
|
||||||
#include "Emu/Cell/SPUThread.h"
|
#include "Emu/Cell/SPUThread.h"
|
||||||
|
#include "Emu/Cell/PPUThread.h"
|
||||||
#include "Emu/IdManager.h"
|
#include "Emu/IdManager.h"
|
||||||
|
|
||||||
#include "util/asm.hpp"
|
#include "util/asm.hpp"
|
||||||
|
|
@ -213,6 +214,8 @@ error_code sys_memory_allocate_from_container(cpu_thread& cpu, u64 size, u32 cid
|
||||||
|
|
||||||
if (alloc_addr)
|
if (alloc_addr)
|
||||||
{
|
{
|
||||||
|
sys_memory.notice("sys_memory_allocate_from_container(): Allocated 0x%x address (size=0x%x)", addr, size);
|
||||||
|
|
||||||
vm::lock_sudo(addr, static_cast<u32>(size));
|
vm::lock_sudo(addr, static_cast<u32>(size));
|
||||||
cpu.check_state();
|
cpu.check_state();
|
||||||
*alloc_addr = addr;
|
*alloc_addr = addr;
|
||||||
|
|
@ -247,17 +250,37 @@ error_code sys_memory_free(cpu_thread& cpu, u32 addr)
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code sys_memory_get_page_attribute(cpu_thread& cpu, u32 addr, vm::ptr<sys_page_attr_t> attr)
|
error_code sys_memory_get_page_attribute(ppu_thread& ppu, u32 addr, vm::ptr<sys_page_attr_t> attr)
|
||||||
{
|
{
|
||||||
cpu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
|
|
||||||
sys_memory.trace("sys_memory_get_page_attribute(addr=0x%x, attr=*0x%x)", addr, attr);
|
sys_memory.trace("sys_memory_get_page_attribute(addr=0x%x, attr=*0x%x)", addr, attr);
|
||||||
|
|
||||||
vm::writer_lock rlock;
|
if ((addr >> 28) == (ppu.stack_addr >> 28))
|
||||||
|
|
||||||
if (!vm::check_addr(addr) || addr >= SPU_FAKE_BASE_ADDR)
|
|
||||||
{
|
{
|
||||||
return CELL_EINVAL;
|
// Stack address: fast path
|
||||||
|
if (!(addr >= ppu.stack_addr && addr < ppu.stack_addr + ppu.stack_size) && !vm::check_addr(addr))
|
||||||
|
{
|
||||||
|
return { CELL_EINVAL, addr };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vm::check_addr(attr.addr(), vm::page_readable, attr.size()))
|
||||||
|
{
|
||||||
|
return CELL_EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
attr->attribute = 0x40000ull; // SYS_MEMORY_PROT_READ_WRITE
|
||||||
|
attr->access_right = SYS_MEMORY_ACCESS_RIGHT_PPU_THR;
|
||||||
|
attr->page_size = 4096;
|
||||||
|
attr->pad = 0; // Always write 0
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto [ok, vm_flags] = vm::get_addr_flags(addr);
|
||||||
|
|
||||||
|
if (!ok || addr >= SPU_FAKE_BASE_ADDR)
|
||||||
|
{
|
||||||
|
return { CELL_EINVAL, addr };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vm::check_addr(attr.addr(), vm::page_readable, attr.size()))
|
if (!vm::check_addr(attr.addr(), vm::page_readable, attr.size()))
|
||||||
|
|
@ -266,19 +289,20 @@ error_code sys_memory_get_page_attribute(cpu_thread& cpu, u32 addr, vm::ptr<sys_
|
||||||
}
|
}
|
||||||
|
|
||||||
attr->attribute = 0x40000ull; // SYS_MEMORY_PROT_READ_WRITE (TODO)
|
attr->attribute = 0x40000ull; // SYS_MEMORY_PROT_READ_WRITE (TODO)
|
||||||
attr->access_right = addr >> 28 == 0xdu ? SYS_MEMORY_ACCESS_RIGHT_PPU_THR : SYS_MEMORY_ACCESS_RIGHT_ANY;// (TODO)
|
attr->access_right = SYS_MEMORY_ACCESS_RIGHT_ANY; // TODO: Report accurately
|
||||||
|
|
||||||
if (vm::check_addr(addr, vm::page_1m_size))
|
if (vm_flags & vm::page_1m_size)
|
||||||
{
|
{
|
||||||
attr->page_size = 0x100000;
|
attr->page_size = 0x100000;
|
||||||
}
|
}
|
||||||
else if (vm::check_addr(addr, vm::page_64k_size))
|
else if (vm_flags & vm::page_64k_size)
|
||||||
{
|
{
|
||||||
attr->page_size = 0x10000;
|
attr->page_size = 0x10000;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
attr->page_size = 4096;
|
//attr->page_size = 4096;
|
||||||
|
fmt::throw_exception("Unreachable");
|
||||||
}
|
}
|
||||||
|
|
||||||
attr->pad = 0; // Always write 0
|
attr->pad = 0; // Always write 0
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include "Emu/Cell/ErrorCodes.h"
|
#include "Emu/Cell/ErrorCodes.h"
|
||||||
|
|
||||||
class cpu_thread;
|
class cpu_thread;
|
||||||
|
class ppu_thread;
|
||||||
|
|
||||||
enum lv2_mem_container_id : u32
|
enum lv2_mem_container_id : u32
|
||||||
{
|
{
|
||||||
|
|
@ -131,7 +132,7 @@ struct sys_memory_user_memory_stat_t
|
||||||
error_code sys_memory_allocate(cpu_thread& cpu, u64 size, u64 flags, vm::ptr<u32> alloc_addr);
|
error_code sys_memory_allocate(cpu_thread& cpu, u64 size, u64 flags, vm::ptr<u32> alloc_addr);
|
||||||
error_code sys_memory_allocate_from_container(cpu_thread& cpu, u64 size, u32 cid, u64 flags, vm::ptr<u32> alloc_addr);
|
error_code sys_memory_allocate_from_container(cpu_thread& cpu, u64 size, u32 cid, u64 flags, vm::ptr<u32> alloc_addr);
|
||||||
error_code sys_memory_free(cpu_thread& cpu, u32 start_addr);
|
error_code sys_memory_free(cpu_thread& cpu, u32 start_addr);
|
||||||
error_code sys_memory_get_page_attribute(cpu_thread& cpu, u32 addr, vm::ptr<sys_page_attr_t> attr);
|
error_code sys_memory_get_page_attribute(ppu_thread& cpu, u32 addr, vm::ptr<sys_page_attr_t> attr);
|
||||||
error_code sys_memory_get_user_memory_size(cpu_thread& cpu, vm::ptr<sys_memory_info_t> mem_info);
|
error_code sys_memory_get_user_memory_size(cpu_thread& cpu, vm::ptr<sys_memory_info_t> mem_info);
|
||||||
error_code sys_memory_get_user_memory_stat(cpu_thread& cpu, vm::ptr<sys_memory_user_memory_stat_t> mem_stat);
|
error_code sys_memory_get_user_memory_stat(cpu_thread& cpu, vm::ptr<sys_memory_user_memory_stat_t> mem_stat);
|
||||||
error_code sys_memory_container_create(cpu_thread& cpu, vm::ptr<u32> cid, u64 size);
|
error_code sys_memory_container_create(cpu_thread& cpu, vm::ptr<u32> cid, u64 size);
|
||||||
|
|
|
||||||
|
|
@ -468,11 +468,11 @@ error_code sys_ppu_thread_restart(ppu_thread& ppu)
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code _sys_ppu_thread_create(ppu_thread& ppu, vm::ptr<u64> thread_id, vm::ptr<ppu_thread_param_t> param, u64 arg, u64 unk, s32 prio, u32 _stacksz, u64 flags, vm::cptr<char> threadname)
|
error_code _sys_ppu_thread_create(ppu_thread& ppu, vm::ptr<u64> thread_id, vm::ptr<ppu_thread_param_t> param, u64 arg, u64 unk, s32 prio, u64 _stacksz, u64 flags, vm::cptr<char> threadname)
|
||||||
{
|
{
|
||||||
ppu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
|
|
||||||
sys_ppu_thread.warning("_sys_ppu_thread_create(thread_id=*0x%x, param=*0x%x, arg=0x%llx, unk=0x%llx, prio=%d, stacksize=0x%x, flags=0x%llx, threadname=*0x%x)",
|
sys_ppu_thread.warning("_sys_ppu_thread_create(thread_id=*0x%x, param=*0x%x, arg=0x%llx, unk=0x%llx, prio=%d, stacksize=0x%llx, flags=0x%llx, threadname=*0x%x)",
|
||||||
thread_id, param, arg, unk, prio, _stacksz, flags, threadname);
|
thread_id, param, arg, unk, prio, _stacksz, flags, threadname);
|
||||||
|
|
||||||
// thread_id is checked for null in stub -> CELL_ENOMEM
|
// thread_id is checked for null in stub -> CELL_ENOMEM
|
||||||
|
|
@ -497,7 +497,8 @@ error_code _sys_ppu_thread_create(ppu_thread& ppu, vm::ptr<u64> thread_id, vm::p
|
||||||
const u32 tls = param->tls;
|
const u32 tls = param->tls;
|
||||||
|
|
||||||
// Compute actual stack size and allocate
|
// Compute actual stack size and allocate
|
||||||
const u32 stack_size = utils::align<u32>(std::max<u32>(_stacksz, 4096), 4096);
|
// 0 and UINT64_MAX both convert to 4096
|
||||||
|
const u64 stack_size = FN(x ? x : 4096)(utils::align<u64>(_stacksz, 4096));
|
||||||
|
|
||||||
auto& dct = g_fxo->get<lv2_memory_container>();
|
auto& dct = g_fxo->get<lv2_memory_container>();
|
||||||
|
|
||||||
|
|
@ -507,7 +508,7 @@ error_code _sys_ppu_thread_create(ppu_thread& ppu, vm::ptr<u64> thread_id, vm::p
|
||||||
return {CELL_ENOMEM, dct.size - dct.used};
|
return {CELL_ENOMEM, dct.size - dct.used};
|
||||||
}
|
}
|
||||||
|
|
||||||
const vm::addr_t stack_base{vm::alloc(stack_size, vm::stack, 4096)};
|
const vm::addr_t stack_base{vm::alloc(static_cast<u32>(stack_size), vm::stack, 4096)};
|
||||||
|
|
||||||
if (!stack_base)
|
if (!stack_base)
|
||||||
{
|
{
|
||||||
|
|
@ -532,7 +533,7 @@ error_code _sys_ppu_thread_create(ppu_thread& ppu, vm::ptr<u64> thread_id, vm::p
|
||||||
{
|
{
|
||||||
ppu_thread_params p;
|
ppu_thread_params p;
|
||||||
p.stack_addr = stack_base;
|
p.stack_addr = stack_base;
|
||||||
p.stack_size = stack_size;
|
p.stack_size = static_cast<u32>(stack_size);
|
||||||
p.tls_addr = tls;
|
p.tls_addr = tls;
|
||||||
p.entry = entry;
|
p.entry = entry;
|
||||||
p.arg0 = arg;
|
p.arg0 = arg;
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ error_code sys_ppu_thread_get_priority(ppu_thread& ppu, u32 thread_id, vm::ptr<s
|
||||||
error_code sys_ppu_thread_get_stack_information(ppu_thread& ppu, vm::ptr<sys_ppu_thread_stack_t> sp);
|
error_code sys_ppu_thread_get_stack_information(ppu_thread& ppu, vm::ptr<sys_ppu_thread_stack_t> sp);
|
||||||
error_code sys_ppu_thread_stop(ppu_thread& ppu, u32 thread_id);
|
error_code sys_ppu_thread_stop(ppu_thread& ppu, u32 thread_id);
|
||||||
error_code sys_ppu_thread_restart(ppu_thread& ppu);
|
error_code sys_ppu_thread_restart(ppu_thread& ppu);
|
||||||
error_code _sys_ppu_thread_create(ppu_thread& ppu, vm::ptr<u64> thread_id, vm::ptr<ppu_thread_param_t> param, u64 arg, u64 arg4, s32 prio, u32 stacksize, u64 flags, vm::cptr<char> threadname);
|
error_code _sys_ppu_thread_create(ppu_thread& ppu, vm::ptr<u64> thread_id, vm::ptr<ppu_thread_param_t> param, u64 arg, u64 arg4, s32 prio, u64 stacksize, u64 flags, vm::cptr<char> threadname);
|
||||||
error_code sys_ppu_thread_start(ppu_thread& ppu, u32 thread_id);
|
error_code sys_ppu_thread_start(ppu_thread& ppu, u32 thread_id);
|
||||||
error_code sys_ppu_thread_rename(ppu_thread& ppu, u32 thread_id, vm::cptr<char> name);
|
error_code sys_ppu_thread_rename(ppu_thread& ppu, u32 thread_id, vm::cptr<char> name);
|
||||||
error_code sys_ppu_thread_recover_page_fault(ppu_thread& ppu, u32 thread_id);
|
error_code sys_ppu_thread_recover_page_fault(ppu_thread& ppu, u32 thread_id);
|
||||||
|
|
|
||||||
|
|
@ -767,7 +767,12 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr<u32> thread, u32 g
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read thread name
|
// Read thread name
|
||||||
const std::string thread_name(attr_data.name.get_ptr(), std::max<u32>(attr_data.name_len, 1) - 1);
|
std::string thread_name;
|
||||||
|
|
||||||
|
if (attr_data.name_len && !vm::read_string(attr_data.name.addr(), attr_data.name_len - 1, thread_name, true))
|
||||||
|
{
|
||||||
|
return { CELL_EFAULT, attr_data.name.addr() };
|
||||||
|
}
|
||||||
|
|
||||||
const auto group = idm::get_unlocked<lv2_spu_group>(group_id);
|
const auto group = idm::get_unlocked<lv2_spu_group>(group_id);
|
||||||
|
|
||||||
|
|
@ -906,7 +911,7 @@ error_code sys_spu_thread_get_exit_status(ppu_thread& ppu, u32 id, vm::ptr<s32>
|
||||||
return CELL_ESTAT;
|
return CELL_ESTAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code sys_spu_thread_group_create(ppu_thread& ppu, vm::ptr<u32> id, u32 num, s32 prio, vm::ptr<sys_spu_thread_group_attribute> attr)
|
error_code sys_spu_thread_group_create(ppu_thread& ppu, vm::ptr<u32> id, u32 num, s32 prio, vm::ptr<reduced_sys_spu_thread_group_attribute> attr)
|
||||||
{
|
{
|
||||||
ppu.state += cpu_flag::wait;
|
ppu.state += cpu_flag::wait;
|
||||||
|
|
||||||
|
|
@ -914,13 +919,32 @@ error_code sys_spu_thread_group_create(ppu_thread& ppu, vm::ptr<u32> id, u32 num
|
||||||
|
|
||||||
const s32 min_prio = g_ps3_process_info.has_root_perm() ? 0 : 16;
|
const s32 min_prio = g_ps3_process_info.has_root_perm() ? 0 : 16;
|
||||||
|
|
||||||
const sys_spu_thread_group_attribute attr_data = *attr;
|
sys_spu_thread_group_attribute attr_data{};
|
||||||
|
{
|
||||||
|
const reduced_sys_spu_thread_group_attribute attr_reduced = *attr;
|
||||||
|
attr_data.name = attr_reduced.name;
|
||||||
|
attr_data.nsize = attr_reduced.nsize;
|
||||||
|
attr_data.type = attr_reduced.type;
|
||||||
|
|
||||||
|
// Read container-id member at offset 12 bytes conditionally (that's what LV2 does)
|
||||||
|
if (attr_data.type & SYS_SPU_THREAD_GROUP_TYPE_MEMORY_FROM_CONTAINER)
|
||||||
|
{
|
||||||
|
attr_data.ct = vm::unsafe_ptr_cast<sys_spu_thread_group_attribute>(attr)->ct;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (attr_data.nsize > 0x80 || !num)
|
if (attr_data.nsize > 0x80 || !num)
|
||||||
{
|
{
|
||||||
return CELL_EINVAL;
|
return CELL_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string group_name;
|
||||||
|
|
||||||
|
if (attr_data.nsize && !vm::read_string(attr_data.name.addr(), attr_data.nsize - 1, group_name, true))
|
||||||
|
{
|
||||||
|
return { CELL_EFAULT, attr_data.name.addr() };
|
||||||
|
}
|
||||||
|
|
||||||
const s32 type = attr_data.type;
|
const s32 type = attr_data.type;
|
||||||
|
|
||||||
bool use_scheduler = true;
|
bool use_scheduler = true;
|
||||||
|
|
@ -1075,7 +1099,7 @@ error_code sys_spu_thread_group_create(ppu_thread& ppu, vm::ptr<u32> id, u32 num
|
||||||
return CELL_EBUSY;
|
return CELL_EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto group = idm::make_ptr<lv2_spu_group>(std::string(attr_data.name.get_ptr(), std::max<u32>(attr_data.nsize, 1) - 1), num, prio, type, ct, use_scheduler, mem_size);
|
const auto group = idm::make_ptr<lv2_spu_group>(std::move(group_name), num, prio, type, ct, use_scheduler, mem_size);
|
||||||
|
|
||||||
if (!group)
|
if (!group)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -82,11 +82,18 @@ enum spu_stop_syscall : u32
|
||||||
SYS_SPU_THREAD_STOP_SWITCH_SYSTEM_MODULE = 0x0120,
|
SYS_SPU_THREAD_STOP_SWITCH_SYSTEM_MODULE = 0x0120,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sys_spu_thread_group_attribute
|
struct reduced_sys_spu_thread_group_attribute
|
||||||
{
|
{
|
||||||
be_t<u32> nsize; // name length including NULL terminator
|
be_t<u32> nsize; // name length including NULL terminator
|
||||||
vm::bcptr<char> name;
|
vm::bcptr<char> name;
|
||||||
be_t<s32> type;
|
be_t<s32> type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sys_spu_thread_group_attribute
|
||||||
|
{
|
||||||
|
be_t<u32> nsize;
|
||||||
|
vm::bcptr<char> name;
|
||||||
|
be_t<s32> type;
|
||||||
be_t<u32> ct; // memory container id
|
be_t<u32> ct; // memory container id
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -360,7 +367,7 @@ error_code _sys_spu_image_close(ppu_thread&, vm::ptr<sys_spu_image> img);
|
||||||
error_code _sys_spu_image_get_segments(ppu_thread&, vm::ptr<sys_spu_image> img, vm::ptr<sys_spu_segment> segments, s32 nseg);
|
error_code _sys_spu_image_get_segments(ppu_thread&, vm::ptr<sys_spu_image> img, vm::ptr<sys_spu_segment> segments, s32 nseg);
|
||||||
error_code sys_spu_thread_initialize(ppu_thread&, vm::ptr<u32> thread, u32 group, u32 spu_num, vm::ptr<sys_spu_image>, vm::ptr<sys_spu_thread_attribute>, vm::ptr<sys_spu_thread_argument>);
|
error_code sys_spu_thread_initialize(ppu_thread&, vm::ptr<u32> thread, u32 group, u32 spu_num, vm::ptr<sys_spu_image>, vm::ptr<sys_spu_thread_attribute>, vm::ptr<sys_spu_thread_argument>);
|
||||||
error_code sys_spu_thread_set_argument(ppu_thread&, u32 id, vm::ptr<sys_spu_thread_argument> arg);
|
error_code sys_spu_thread_set_argument(ppu_thread&, u32 id, vm::ptr<sys_spu_thread_argument> arg);
|
||||||
error_code sys_spu_thread_group_create(ppu_thread&, vm::ptr<u32> id, u32 num, s32 prio, vm::ptr<sys_spu_thread_group_attribute> attr);
|
error_code sys_spu_thread_group_create(ppu_thread&, vm::ptr<u32> id, u32 num, s32 prio, vm::ptr<reduced_sys_spu_thread_group_attribute> attr);
|
||||||
error_code sys_spu_thread_group_destroy(ppu_thread&, u32 id);
|
error_code sys_spu_thread_group_destroy(ppu_thread&, u32 id);
|
||||||
error_code sys_spu_thread_group_start(ppu_thread&, u32 id);
|
error_code sys_spu_thread_group_start(ppu_thread&, u32 id);
|
||||||
error_code sys_spu_thread_group_suspend(ppu_thread&, u32 id);
|
error_code sys_spu_thread_group_suspend(ppu_thread&, u32 id);
|
||||||
|
|
|
||||||
|
|
@ -210,8 +210,10 @@ error_code sys_ss_get_open_psid(vm::ptr<CellSsOpenPSID> psid)
|
||||||
{
|
{
|
||||||
sys_ss.notice("sys_ss_get_open_psid(psid=*0x%x)", psid);
|
sys_ss.notice("sys_ss_get_open_psid(psid=*0x%x)", psid);
|
||||||
|
|
||||||
psid->high = g_cfg.sys.console_psid_high;
|
const u128 configured_psid = g_cfg.sys.console_psid.get();
|
||||||
psid->low = g_cfg.sys.console_psid_low;
|
|
||||||
|
psid->high = static_cast<u64>(configured_psid >> 64);
|
||||||
|
psid->low = static_cast<u64>(configured_psid);
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
@ -259,8 +261,8 @@ error_code sys_ss_appliance_info_manager(u32 code, vm::ptr<u8> buffer)
|
||||||
case 0x19005:
|
case 0x19005:
|
||||||
{
|
{
|
||||||
// AIM_get_open_ps_id
|
// AIM_get_open_ps_id
|
||||||
be_t<u64> psid[2] = { +g_cfg.sys.console_psid_high, +g_cfg.sys.console_psid_low };
|
const be_t<u128> psid = g_cfg.sys.console_psid.get();
|
||||||
std::memcpy(buffer.get_ptr(), psid, 16);
|
std::memcpy(buffer.get_ptr(), &psid, 16);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x19006:
|
case 0x19006:
|
||||||
|
|
@ -268,7 +270,11 @@ error_code sys_ss_appliance_info_manager(u32 code, vm::ptr<u8> buffer)
|
||||||
// qa values (dex only) ??
|
// qa values (dex only) ??
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
}
|
}
|
||||||
default: sys_ss.todo("sys_ss_appliance_info_manager(code=0x%x, buffer=*0x%x)", code, buffer);
|
default:
|
||||||
|
{
|
||||||
|
sys_ss.todo("sys_ss_appliance_info_manager(code=0x%x, buffer=*0x%x)", code, buffer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
#include "Emu/Io/Skylander.h"
|
#include "Emu/Io/Skylander.h"
|
||||||
#include "Emu/Io/Infinity.h"
|
#include "Emu/Io/Infinity.h"
|
||||||
#include "Emu/Io/Dimensions.h"
|
#include "Emu/Io/Dimensions.h"
|
||||||
|
#include "Emu/Io/KamenRider.h"
|
||||||
#include "Emu/Io/GHLtar.h"
|
#include "Emu/Io/GHLtar.h"
|
||||||
#include "Emu/Io/ghltar_config.h"
|
#include "Emu/Io/ghltar_config.h"
|
||||||
#include "Emu/Io/guncon3_config.h"
|
#include "Emu/Io/guncon3_config.h"
|
||||||
|
|
@ -175,7 +176,7 @@ private:
|
||||||
{0x1430, 0x0150, 0x0150, "Skylanders Portal", &usb_device_skylander::get_num_emu_devices, &usb_device_skylander::make_instance},
|
{0x1430, 0x0150, 0x0150, "Skylanders Portal", &usb_device_skylander::get_num_emu_devices, &usb_device_skylander::make_instance},
|
||||||
{0x0E6F, 0x0129, 0x0129, "Disney Infinity Base", &usb_device_infinity::get_num_emu_devices, &usb_device_infinity::make_instance},
|
{0x0E6F, 0x0129, 0x0129, "Disney Infinity Base", &usb_device_infinity::get_num_emu_devices, &usb_device_infinity::make_instance},
|
||||||
{0x0E6F, 0x0241, 0x0241, "Lego Dimensions Portal", &usb_device_dimensions::get_num_emu_devices, &usb_device_dimensions::make_instance},
|
{0x0E6F, 0x0241, 0x0241, "Lego Dimensions Portal", &usb_device_dimensions::get_num_emu_devices, &usb_device_dimensions::make_instance},
|
||||||
{0x0E6F, 0x200A, 0x200A, "Kamen Rider Summonride Portal", nullptr, nullptr},
|
{0x0E6F, 0x200A, 0x200A, "Kamen Rider Summonride Portal", &usb_device_kamen_rider::get_num_emu_devices, &usb_device_kamen_rider::make_instance},
|
||||||
|
|
||||||
// Cameras
|
// Cameras
|
||||||
// {0x1415, 0x0020, 0x2000, "Sony Playstation Eye", nullptr, nullptr}, // TODO: verifiy
|
// {0x1415, 0x0020, 0x2000, "Sony Playstation Eye", nullptr, nullptr}, // TODO: verifiy
|
||||||
|
|
|
||||||
|
|
@ -544,9 +544,7 @@ std::optional<std::array<u8, 32>> dimensions_toypad::pop_added_removed_response(
|
||||||
std::lock_guard lock(m_dimensions_mutex);
|
std::lock_guard lock(m_dimensions_mutex);
|
||||||
|
|
||||||
if (m_figure_added_removed_responses.empty())
|
if (m_figure_added_removed_responses.empty())
|
||||||
{
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
|
||||||
|
|
||||||
std::array<u8, 32> response = m_figure_added_removed_responses.front();
|
std::array<u8, 32> response = m_figure_added_removed_responses.front();
|
||||||
m_figure_added_removed_responses.pop();
|
m_figure_added_removed_responses.pop();
|
||||||
|
|
@ -597,7 +595,6 @@ void usb_device_dimensions::interrupt_transfer(u32 buf_size, u8* buf, u32 endpoi
|
||||||
{
|
{
|
||||||
// Read Endpoint, if a request has not been sent via the write endpoint, set expected result as
|
// Read Endpoint, if a request has not been sent via the write endpoint, set expected result as
|
||||||
// EHCI_CC_HALTED so the game doesn't report the Toypad as being disconnected.
|
// EHCI_CC_HALTED so the game doesn't report the Toypad as being disconnected.
|
||||||
std::lock_guard lock(m_query_mutex);
|
|
||||||
std::optional<std::array<u8, 32>> response = g_dimensionstoypad.pop_added_removed_response();
|
std::optional<std::array<u8, 32>> response = g_dimensionstoypad.pop_added_removed_response();
|
||||||
if (response)
|
if (response)
|
||||||
{
|
{
|
||||||
|
|
@ -696,7 +693,6 @@ void usb_device_dimensions::interrupt_transfer(u32 buf_size, u8* buf, u32 endpoi
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::lock_guard lock(m_query_mutex);
|
|
||||||
m_queries.push(q_result);
|
m_queries.push(q_result);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,5 @@ public:
|
||||||
void isochronous_transfer(UsbTransfer* transfer) override;
|
void isochronous_transfer(UsbTransfer* transfer) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
shared_mutex m_query_mutex;
|
|
||||||
std::queue<std::array<u8, 32>> m_queries;
|
std::queue<std::array<u8, 32>> m_queries;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -258,13 +258,13 @@ void infinity_base::get_figure_identifier(u8 fig_num, u8 sequence, std::array<u8
|
||||||
reply_buf[11] = generate_checksum(reply_buf, 11);
|
reply_buf[11] = generate_checksum(reply_buf, 11);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool infinity_base::has_figure_been_added_removed() const
|
std::optional<std::array<u8, 32>> infinity_base::pop_added_removed_response()
|
||||||
{
|
{
|
||||||
return !m_figure_added_removed_responses.empty();
|
std::lock_guard lock(infinity_mutex);
|
||||||
}
|
|
||||||
|
if (m_figure_added_removed_responses.empty())
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
std::array<u8, 32> infinity_base::pop_added_removed_response()
|
|
||||||
{
|
|
||||||
std::array<u8, 32> response = m_figure_added_removed_responses.front();
|
std::array<u8, 32> response = m_figure_added_removed_responses.front();
|
||||||
m_figure_added_removed_responses.pop();
|
m_figure_added_removed_responses.pop();
|
||||||
return response;
|
return response;
|
||||||
|
|
@ -399,9 +399,10 @@ void usb_device_infinity::interrupt_transfer(u32 buf_size, u8* buf, u32 endpoint
|
||||||
{
|
{
|
||||||
// Respond after FF command
|
// Respond after FF command
|
||||||
transfer->expected_time = get_timestamp() + 1000;
|
transfer->expected_time = get_timestamp() + 1000;
|
||||||
if (g_infinitybase.has_figure_been_added_removed())
|
std::optional<std::array<u8, 32>> response = g_infinitybase.pop_added_removed_response();
|
||||||
|
if (response)
|
||||||
{
|
{
|
||||||
memcpy(buf, g_infinitybase.pop_added_removed_response().data(), 0x20);
|
memcpy(buf, response.value().data(), 0x20);
|
||||||
}
|
}
|
||||||
else if (!m_queries.empty())
|
else if (!m_queries.empty())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include "Emu/Io/usb_device.h"
|
#include "Emu/Io/usb_device.h"
|
||||||
#include "Utilities/mutex.h"
|
#include "Utilities/mutex.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <optional>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
struct infinity_figure
|
struct infinity_figure
|
||||||
|
|
@ -24,8 +25,7 @@ public:
|
||||||
void query_block(u8 fig_num, u8 block, std::array<u8, 32>& reply_buf, u8 sequence);
|
void query_block(u8 fig_num, u8 block, std::array<u8, 32>& reply_buf, u8 sequence);
|
||||||
void write_block(u8 fig_num, u8 block, const u8* to_write_buf, std::array<u8, 32>& reply_buf, u8 sequence);
|
void write_block(u8 fig_num, u8 block, const u8* to_write_buf, std::array<u8, 32>& reply_buf, u8 sequence);
|
||||||
void get_figure_identifier(u8 fig_num, u8 sequence, std::array<u8, 32>& reply_buf);
|
void get_figure_identifier(u8 fig_num, u8 sequence, std::array<u8, 32>& reply_buf);
|
||||||
bool has_figure_been_added_removed() const;
|
std::optional<std::array<u8, 32>> pop_added_removed_response();
|
||||||
std::array<u8, 32> pop_added_removed_response();
|
|
||||||
|
|
||||||
bool remove_figure(u8 position);
|
bool remove_figure(u8 position);
|
||||||
u32 load_figure(const std::array<u8, 0x14 * 0x10>& buf, fs::file in_file, u8 position);
|
u32 load_figure(const std::array<u8, 0x14 * 0x10>& buf, fs::file in_file, u8 position);
|
||||||
|
|
|
||||||
291
rpcs3/Emu/Io/KamenRider.cpp
Normal file
291
rpcs3/Emu/Io/KamenRider.cpp
Normal file
|
|
@ -0,0 +1,291 @@
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "KamenRider.h"
|
||||||
|
|
||||||
|
LOG_CHANNEL(kamen_rider_log, "kamen_rider");
|
||||||
|
|
||||||
|
rider_gate g_ridergate;
|
||||||
|
|
||||||
|
void kamen_rider_figure::save()
|
||||||
|
{
|
||||||
|
if (!kamen_file)
|
||||||
|
{
|
||||||
|
kamen_rider_log.error("Tried to save kamen rider figure to file but no kamen rider figure is active!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
kamen_file.seek(0, fs::seek_set);
|
||||||
|
kamen_file.write(data.data(), 0x14 * 0x10);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 rider_gate::generate_checksum(const std::array<u8, 64>& data, u32 num_of_bytes) const
|
||||||
|
{
|
||||||
|
ensure(num_of_bytes <= data.size());
|
||||||
|
int checksum = 0;
|
||||||
|
for (u32 i = 0; i < num_of_bytes; i++)
|
||||||
|
{
|
||||||
|
checksum += data[i];
|
||||||
|
}
|
||||||
|
return (checksum & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
kamen_rider_figure& rider_gate::get_figure_by_uid(const std::array<u8, 7> uid)
|
||||||
|
{
|
||||||
|
for (kamen_rider_figure& figure : figures)
|
||||||
|
{
|
||||||
|
if (figure.uid == uid)
|
||||||
|
{
|
||||||
|
return figure;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return figures[7];
|
||||||
|
}
|
||||||
|
|
||||||
|
void rider_gate::get_blank_response(u8 command, u8 sequence, std::array<u8, 64>& reply_buf)
|
||||||
|
{
|
||||||
|
reply_buf = {0x55, 0x02, command, sequence};
|
||||||
|
reply_buf[4] = generate_checksum(reply_buf, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rider_gate::wake_rider_gate(std::array<u8, 64>& reply_buf, u8 command, u8 sequence)
|
||||||
|
{
|
||||||
|
std::lock_guard lock(kamen_mutex);
|
||||||
|
|
||||||
|
m_is_awake = true;
|
||||||
|
reply_buf = {0x55, 0x1a, command, sequence, 0x00, 0x07, 0x00, 0x03, 0x02,
|
||||||
|
0x09, 0x20, 0x03, 0xf5, 0x00, 0x19, 0x42, 0x52, 0xb7,
|
||||||
|
0xb9, 0xa1, 0xae, 0x2b, 0x88, 0x42, 0x05, 0xfe, 0xe0, 0x1c, 0xac};
|
||||||
|
}
|
||||||
|
|
||||||
|
void rider_gate::get_list_tags(std::array<u8, 64>& reply_buf, u8 command, u8 sequence)
|
||||||
|
{
|
||||||
|
std::lock_guard lock(kamen_mutex);
|
||||||
|
|
||||||
|
reply_buf = {0x55, 0x02, command, sequence};
|
||||||
|
u8 index = 4;
|
||||||
|
for (const kamen_rider_figure& figure : figures)
|
||||||
|
{
|
||||||
|
if (figure.present)
|
||||||
|
{
|
||||||
|
reply_buf[index] = 0x09;
|
||||||
|
memcpy(&reply_buf[index + 1], figure.data.data(), 7);
|
||||||
|
index += 8;
|
||||||
|
reply_buf[1] += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reply_buf[index] = generate_checksum(reply_buf, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rider_gate::query_block(std::array<u8, 64>& reply_buf, u8 command, u8 sequence, const u8* uid, u8 sector, u8 block)
|
||||||
|
{
|
||||||
|
std::lock_guard lock(kamen_mutex);
|
||||||
|
|
||||||
|
reply_buf = {0x55, 0x13, command, sequence, 0x00};
|
||||||
|
|
||||||
|
const std::array<u8, 7> uid_array = {uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6]};
|
||||||
|
|
||||||
|
const kamen_rider_figure& figure = get_figure_by_uid(uid_array);
|
||||||
|
if (figure.present)
|
||||||
|
{
|
||||||
|
if (sector < 5 && block < 4)
|
||||||
|
{
|
||||||
|
memcpy(&reply_buf[5], &figure.data[(sector * 4 * 16) + (block * 16)], 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reply_buf[21] = generate_checksum(reply_buf, 21);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rider_gate::write_block(std::array<u8, 64>& replyBuf, u8 command, u8 sequence, const u8* uid, u8 sector, u8 block, const u8* to_write_buf)
|
||||||
|
{
|
||||||
|
std::lock_guard lock(kamen_mutex);
|
||||||
|
|
||||||
|
const std::array<u8, 7> uid_array = {uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6]};
|
||||||
|
|
||||||
|
kamen_rider_figure& figure = get_figure_by_uid(uid_array);
|
||||||
|
if (figure.present)
|
||||||
|
{
|
||||||
|
if (sector < 5 && block < 4)
|
||||||
|
{
|
||||||
|
memcpy(&figure.data[(sector * 4 * 16) + (block * 16)], to_write_buf, 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get_blank_response(command, sequence, replyBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::array<u8, 64>> rider_gate::pop_added_removed_response()
|
||||||
|
{
|
||||||
|
std::lock_guard lock(kamen_mutex);
|
||||||
|
|
||||||
|
if (m_figure_added_removed_responses.empty())
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<u8, 64> response = m_figure_added_removed_responses.front();
|
||||||
|
m_figure_added_removed_responses.pop();
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rider_gate::remove_figure(u8 index)
|
||||||
|
{
|
||||||
|
std::lock_guard lock(kamen_mutex);
|
||||||
|
|
||||||
|
auto& figure = figures[index];
|
||||||
|
|
||||||
|
if (figure.present)
|
||||||
|
{
|
||||||
|
figure.present = false;
|
||||||
|
figure.save();
|
||||||
|
figure.kamen_file.close();
|
||||||
|
if (m_is_awake)
|
||||||
|
{
|
||||||
|
std::array<u8, 64> figure_removed_response = {0x56, 0x09, 0x09, 0x00};
|
||||||
|
memcpy(&figure_removed_response[4], figure.uid.data(), figure.uid.size());
|
||||||
|
figure_removed_response[11] = generate_checksum(figure_removed_response, 11);
|
||||||
|
m_figure_added_removed_responses.push(std::move(figure_removed_response));
|
||||||
|
}
|
||||||
|
figure.uid = {};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 rider_gate::load_figure(const std::array<u8, 0x14 * 0x10>& buf, fs::file in_file)
|
||||||
|
{
|
||||||
|
std::lock_guard lock(kamen_mutex);
|
||||||
|
|
||||||
|
u8 found_slot = 0xFF;
|
||||||
|
|
||||||
|
// mimics spot retaining on the portal
|
||||||
|
for (auto i = 0; i < 7; i++)
|
||||||
|
{
|
||||||
|
if (!figures[i].present)
|
||||||
|
{
|
||||||
|
if (i < found_slot)
|
||||||
|
{
|
||||||
|
found_slot = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found_slot != 0xFF)
|
||||||
|
{
|
||||||
|
auto& figure = figures[found_slot];
|
||||||
|
memcpy(figure.data.data(), buf.data(), buf.size());
|
||||||
|
figure.kamen_file = std::move(in_file);
|
||||||
|
figure.uid = {buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]};
|
||||||
|
figure.present = true;
|
||||||
|
|
||||||
|
if (m_is_awake)
|
||||||
|
{
|
||||||
|
std::array<u8, 64> figure_added_response = {0x56, 0x09, 0x09, 0x01};
|
||||||
|
memcpy(&figure_added_response[4], figure.uid.data(), figure.uid.size());
|
||||||
|
figure_added_response[11] = generate_checksum(figure_added_response, 11);
|
||||||
|
m_figure_added_removed_responses.push(std::move(figure_added_response));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found_slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_device_kamen_rider::usb_device_kamen_rider(const std::array<u8, 7>& location)
|
||||||
|
: usb_device_emulated(location)
|
||||||
|
{
|
||||||
|
device = UsbDescriptorNode(USB_DESCRIPTOR_DEVICE, UsbDeviceDescriptor{0x200, 0x0, 0x0, 0x0, 0x40, 0x0E6F, 0x200A, 0x100, 0x1, 0x2, 0x3, 0x1});
|
||||||
|
auto& config0 = device.add_node(UsbDescriptorNode(USB_DESCRIPTOR_CONFIG, UsbDeviceConfiguration{0x29, 0x1, 0x1, 0x0, 0x80, 0xFA}));
|
||||||
|
config0.add_node(UsbDescriptorNode(USB_DESCRIPTOR_INTERFACE, UsbDeviceInterface{0x0, 0x0, 0x2, 0x3, 0x0, 0x0, 0x0}));
|
||||||
|
config0.add_node(UsbDescriptorNode(USB_DESCRIPTOR_ENDPOINT, UsbDeviceEndpoint{0x81, 0x3, 0x40, 0x1}));
|
||||||
|
config0.add_node(UsbDescriptorNode(USB_DESCRIPTOR_ENDPOINT, UsbDeviceEndpoint{0x1, 0x3, 0x40, 0x1}));
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_device_kamen_rider::~usb_device_kamen_rider()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<usb_device> usb_device_kamen_rider::make_instance(u32, const std::array<u8, 7>& location)
|
||||||
|
{
|
||||||
|
return std::make_shared<usb_device_kamen_rider>(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 usb_device_kamen_rider::get_num_emu_devices()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_device_kamen_rider::control_transfer(u8 bmRequestType, u8 bRequest, u16 wValue, u16 wIndex, u16 wLength, u32 buf_size, u8* buf, UsbTransfer* transfer)
|
||||||
|
{
|
||||||
|
usb_device_emulated::control_transfer(bmRequestType, bRequest, wValue, wIndex, wLength, buf_size, buf, transfer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_device_kamen_rider::interrupt_transfer(u32 buf_size, u8* buf, u32 endpoint, UsbTransfer* transfer)
|
||||||
|
{
|
||||||
|
ensure(buf_size == 0x40);
|
||||||
|
|
||||||
|
transfer->fake = true;
|
||||||
|
transfer->expected_count = buf_size;
|
||||||
|
transfer->expected_result = HC_CC_NOERR;
|
||||||
|
|
||||||
|
if (endpoint == 0x81)
|
||||||
|
{
|
||||||
|
// Respond after FF command
|
||||||
|
transfer->expected_time = get_timestamp() + 1000;
|
||||||
|
std::optional<std::array<u8, 64>> response = g_ridergate.pop_added_removed_response();
|
||||||
|
if (response)
|
||||||
|
{
|
||||||
|
memcpy(buf, response.value().data(), 0x40);
|
||||||
|
}
|
||||||
|
else if (!m_queries.empty())
|
||||||
|
{
|
||||||
|
memcpy(buf, m_queries.front().data(), 0x20);
|
||||||
|
m_queries.pop();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
transfer->expected_count = 0;
|
||||||
|
transfer->expected_result = EHCI_CC_HALTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (endpoint == 0x01)
|
||||||
|
{
|
||||||
|
const u8 command = buf[2];
|
||||||
|
const u8 sequence = buf[3];
|
||||||
|
|
||||||
|
std::array<u8, 64> q_result{};
|
||||||
|
|
||||||
|
switch (command)
|
||||||
|
{
|
||||||
|
case 0xB0: // Wake
|
||||||
|
{
|
||||||
|
g_ridergate.wake_rider_gate(q_result, command, sequence);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0xC0:
|
||||||
|
case 0xC3: // Color Commands
|
||||||
|
{
|
||||||
|
g_ridergate.get_blank_response(command, sequence, q_result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0xD0: // Tag List
|
||||||
|
{
|
||||||
|
// Return list of figure UIDs, separated by an 09
|
||||||
|
g_ridergate.get_list_tags(q_result, command, sequence);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0xD2: // Read
|
||||||
|
{
|
||||||
|
// Read 16 bytes from figure with UID buf[4] - buf[10]
|
||||||
|
g_ridergate.query_block(q_result, command, sequence, &buf[4], buf[11], buf[12]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0xD3:
|
||||||
|
{
|
||||||
|
// Write 16 bytes to figure with UID buf[4] - buf[10]
|
||||||
|
g_ridergate.write_block(q_result, command, sequence, &buf[4], buf[11], buf[12], &buf[13]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
kamen_rider_log.error("Unhandled Query Type: 0x%02X", command);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_queries.push(std::move(q_result));
|
||||||
|
}
|
||||||
|
}
|
||||||
60
rpcs3/Emu/Io/KamenRider.h
Normal file
60
rpcs3/Emu/Io/KamenRider.h
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Emu/Io/usb_device.h"
|
||||||
|
#include "Utilities/mutex.h"
|
||||||
|
#include <array>
|
||||||
|
#include <optional>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
struct kamen_rider_figure
|
||||||
|
{
|
||||||
|
fs::file kamen_file;
|
||||||
|
std::array<u8, 0x14 * 0x10> data{};
|
||||||
|
std::array<u8, 7> uid{};
|
||||||
|
bool present = false;
|
||||||
|
void save();
|
||||||
|
};
|
||||||
|
|
||||||
|
class rider_gate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void get_blank_response(u8 command, u8 sequence, std::array<u8, 64>& reply_buf);
|
||||||
|
void wake_rider_gate(std::array<u8, 64>& replyBuf, u8 command, u8 sequence);
|
||||||
|
void get_list_tags(std::array<u8, 64>& replyBuf, u8 command, u8 sequence);
|
||||||
|
void query_block(std::array<u8, 64>& replyBuf, u8 command, u8 sequence, const u8* uid, u8 sector, u8 block);
|
||||||
|
void write_block(std::array<u8, 64>& replyBuf, u8 command, u8 sequence, const u8* uid, u8 sector, u8 block, const u8* to_write_buf);
|
||||||
|
std::optional<std::array<u8, 64>> pop_added_removed_response();
|
||||||
|
|
||||||
|
bool remove_figure(u8 position);
|
||||||
|
u8 load_figure(const std::array<u8, 0x14 * 0x10>& buf, fs::file in_file);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
shared_mutex kamen_mutex;
|
||||||
|
std::array<kamen_rider_figure, 8> figures{};
|
||||||
|
|
||||||
|
private:
|
||||||
|
u8 generate_checksum(const std::array<u8, 64>& data, u32 num_of_bytes) const;
|
||||||
|
kamen_rider_figure& get_figure_by_uid(const std::array<u8, 7> uid);
|
||||||
|
|
||||||
|
std::queue<std::array<u8, 64>> m_figure_added_removed_responses;
|
||||||
|
|
||||||
|
bool m_is_awake = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern rider_gate g_ridergate;
|
||||||
|
|
||||||
|
class usb_device_kamen_rider : public usb_device_emulated
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
usb_device_kamen_rider(const std::array<u8, 7>& location);
|
||||||
|
~usb_device_kamen_rider();
|
||||||
|
|
||||||
|
static std::shared_ptr<usb_device> make_instance(u32 controller_index, const std::array<u8, 7>& location);
|
||||||
|
static u16 get_num_emu_devices();
|
||||||
|
|
||||||
|
void control_transfer(u8 bmRequestType, u8 bRequest, u16 wValue, u16 wIndex, u16 wLength, u32 buf_size, u8* buf, UsbTransfer* transfer) override;
|
||||||
|
void interrupt_transfer(u32 buf_size, u8* buf, u32 endpoint, UsbTransfer* transfer) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::queue<std::array<u8, 64>> m_queries;
|
||||||
|
};
|
||||||
|
|
@ -170,7 +170,7 @@ u16 PadHandlerBase::ConvertAxis(f32 value)
|
||||||
|
|
||||||
// The DS3, (and i think xbox controllers) give a 'square-ish' type response, so that the corners will give (almost)max x/y instead of the ~30x30 from a perfect circle
|
// The DS3, (and i think xbox controllers) give a 'square-ish' type response, so that the corners will give (almost)max x/y instead of the ~30x30 from a perfect circle
|
||||||
// using a simple scale/sensitivity increase would *work* although it eats a chunk of our usable range in exchange
|
// using a simple scale/sensitivity increase would *work* although it eats a chunk of our usable range in exchange
|
||||||
// this might be the best for now, in practice it seems to push the corners to max of 20x20, with a squircle_factor of 8000
|
// this might be the best for now, in practice it seems to push the corners to max of 20x20, with a squircle_factor of ~4000
|
||||||
// This function assumes inX and inY is already in 0-255
|
// This function assumes inX and inY is already in 0-255
|
||||||
void PadHandlerBase::ConvertToSquirclePoint(u16& inX, u16& inY, u32 squircle_factor)
|
void PadHandlerBase::ConvertToSquirclePoint(u16& inX, u16& inY, u32 squircle_factor)
|
||||||
{
|
{
|
||||||
|
|
@ -208,6 +208,21 @@ void PadHandlerBase::init_configs()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pad_capabilities PadHandlerBase::get_capabilities(const std::string& /*pad_id*/)
|
||||||
|
{
|
||||||
|
return pad_capabilities
|
||||||
|
{
|
||||||
|
.has_led = b_has_rgb,
|
||||||
|
.has_mono_led = b_has_led,
|
||||||
|
.has_player_led = b_has_player_led,
|
||||||
|
.has_battery_led = b_has_battery_led,
|
||||||
|
.has_rumble = b_has_rumble,
|
||||||
|
.has_accel = b_has_motion,
|
||||||
|
.has_gyro = b_has_motion,
|
||||||
|
.has_pressure_sensitivity = b_has_pressure_intensity_button
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
cfg_pad* PadHandlerBase::get_config(const std::string& pad_id)
|
cfg_pad* PadHandlerBase::get_config(const std::string& pad_id)
|
||||||
{
|
{
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
@ -331,12 +346,13 @@ PadHandlerBase::connection PadHandlerBase::get_next_button_press(const std::stri
|
||||||
if (callback)
|
if (callback)
|
||||||
{
|
{
|
||||||
pad_preview_values preview_values = get_preview_values(data);
|
pad_preview_values preview_values = get_preview_values(data);
|
||||||
|
pad_capabilities capabilities = get_capabilities(pad_id);
|
||||||
const u32 battery_level = get_battery_level(pad_id);
|
const u32 battery_level = get_battery_level(pad_id);
|
||||||
|
|
||||||
if (pressed_button.value > 0)
|
if (pressed_button.value > 0)
|
||||||
callback(pressed_button.value, pressed_button.name, pad_id, battery_level, std::move(preview_values));
|
callback(pressed_button.value, pressed_button.name, pad_id, battery_level, std::move(preview_values), std::move(capabilities));
|
||||||
else
|
else
|
||||||
callback(0, "", pad_id, battery_level, std::move(preview_values));
|
callback(0, "", pad_id, battery_level, std::move(preview_values), std::move(capabilities));
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,20 @@ struct pad_list_entry
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct pad_capabilities
|
||||||
|
{
|
||||||
|
bool has_led = false;
|
||||||
|
bool has_mono_led = false;
|
||||||
|
bool has_player_led = false;
|
||||||
|
bool has_battery_led = false;
|
||||||
|
bool has_rumble = false;
|
||||||
|
bool has_accel = false;
|
||||||
|
bool has_gyro = false;
|
||||||
|
bool has_pressure_sensitivity = false;
|
||||||
|
};
|
||||||
|
|
||||||
using pad_preview_values = std::array<int, 6>;
|
using pad_preview_values = std::array<int, 6>;
|
||||||
using pad_callback = std::function<void(u16 /*button_value*/, std::string /*button_name*/, std::string /*pad_name*/, u32 /*battery_level*/, pad_preview_values /*preview_values*/)>;
|
using pad_callback = std::function<void(u16 /*button_value*/, std::string /*button_name*/, std::string /*pad_name*/, u32 /*battery_level*/, pad_preview_values, pad_capabilities)>;
|
||||||
using pad_fail_callback = std::function<void(std::string /*pad_name*/)>;
|
using pad_fail_callback = std::function<void(std::string /*pad_name*/)>;
|
||||||
|
|
||||||
using motion_preview_values = std::array<u16, 4>;
|
using motion_preview_values = std::array<u16, 4>;
|
||||||
|
|
@ -326,6 +338,8 @@ public:
|
||||||
bool has_analog_limiter_button() const { return b_has_analog_limiter_button; }
|
bool has_analog_limiter_button() const { return b_has_analog_limiter_button; }
|
||||||
bool has_orientation() const { return b_has_orientation; }
|
bool has_orientation() const { return b_has_orientation; }
|
||||||
|
|
||||||
|
virtual pad_capabilities get_capabilities(const std::string& /*pad_id*/);
|
||||||
|
|
||||||
u16 NormalizeStickInput(u16 raw_value, s32 threshold, s32 multiplier, bool ignore_threshold = false) const;
|
u16 NormalizeStickInput(u16 raw_value, s32 threshold, s32 multiplier, bool ignore_threshold = false) const;
|
||||||
void convert_stick_values(u16& x_out, u16& y_out, s32 x_in, s32 y_in, u32 deadzone, u32 anti_deadzone, u32 padsquircling) const;
|
void convert_stick_values(u16& x_out, u16& y_out, s32 x_in, s32 y_in, u32 deadzone, u32 anti_deadzone, u32 padsquircling) const;
|
||||||
void set_trigger_recognition_mode(trigger_recognition_mode mode) { m_trigger_recognition_mode = mode; }
|
void set_trigger_recognition_mode(trigger_recognition_mode mode) { m_trigger_recognition_mode = mode; }
|
||||||
|
|
|
||||||
|
|
@ -88,8 +88,8 @@ struct cfg_pad final : cfg::node
|
||||||
cfg::uint<0, 1000000> rstick_anti_deadzone{ this, "Right Stick Anti-Deadzone", 0 };
|
cfg::uint<0, 1000000> rstick_anti_deadzone{ this, "Right Stick Anti-Deadzone", 0 };
|
||||||
cfg::uint<0, 1000000> ltriggerthreshold{ this, "Left Trigger Threshold", 0 };
|
cfg::uint<0, 1000000> ltriggerthreshold{ this, "Left Trigger Threshold", 0 };
|
||||||
cfg::uint<0, 1000000> rtriggerthreshold{ this, "Right Trigger Threshold", 0 };
|
cfg::uint<0, 1000000> rtriggerthreshold{ this, "Right Trigger Threshold", 0 };
|
||||||
cfg::uint<0, 1000000> lpadsquircling{ this, "Left Pad Squircling Factor", 8000 };
|
cfg::uint<0, 1000000> lpadsquircling{ this, "Left Pad Squircling Factor", 4000 };
|
||||||
cfg::uint<0, 1000000> rpadsquircling{ this, "Right Pad Squircling Factor", 8000 };
|
cfg::uint<0, 1000000> rpadsquircling{ this, "Right Pad Squircling Factor", 4000 };
|
||||||
|
|
||||||
cfg::uint<0, 255> colorR{ this, "Color Value R", 0 };
|
cfg::uint<0, 255> colorR{ this, "Color Value R", 0 };
|
||||||
cfg::uint<0, 255> colorG{ this, "Color Value G", 0 };
|
cfg::uint<0, 255> colorG{ this, "Color Value G", 0 };
|
||||||
|
|
|
||||||
|
|
@ -217,6 +217,12 @@ bool Pad::get_analog_limiter_button_active(bool is_toggle_mode, u32 player_id)
|
||||||
|
|
||||||
const Button& analog_limiter_button = m_buttons[m_analog_limiter_button_index];
|
const Button& analog_limiter_button = m_buttons[m_analog_limiter_button_index];
|
||||||
|
|
||||||
|
if (analog_limiter_button.m_key_codes.empty())
|
||||||
|
{
|
||||||
|
// Active by default if no button was assigned
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_toggle_mode)
|
if (is_toggle_mode)
|
||||||
{
|
{
|
||||||
const bool pressed = analog_limiter_button.m_pressed;
|
const bool pressed = analog_limiter_button.m_pressed;
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@ namespace vm
|
||||||
|
|
||||||
void reservation_update(u32 addr)
|
void reservation_update(u32 addr)
|
||||||
{
|
{
|
||||||
u64 old = -1;
|
|
||||||
const auto cpu = get_current_cpu_thread();
|
const auto cpu = get_current_cpu_thread();
|
||||||
|
|
||||||
const bool had_wait = cpu && cpu->state & cpu_flag::wait;
|
const bool had_wait = cpu && cpu->state & cpu_flag::wait;
|
||||||
|
|
@ -126,8 +125,6 @@ namespace vm
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
old = rtime;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -550,6 +547,13 @@ namespace vm
|
||||||
{
|
{
|
||||||
to_clear = for_all_range_locks(to_clear & ~get_range_lock_bits(true), [&](u64 addr2, u32 size2)
|
to_clear = for_all_range_locks(to_clear & ~get_range_lock_bits(true), [&](u64 addr2, u32 size2)
|
||||||
{
|
{
|
||||||
|
constexpr u32 range_size_loc = vm::range_pos - 32;
|
||||||
|
|
||||||
|
if ((size2 >> range_size_loc) == (vm::range_readable >> vm::range_pos))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Split and check every 64K page separately
|
// Split and check every 64K page separately
|
||||||
for (u64 hi = addr2 >> 16, max = (addr2 + size2 - 1) >> 16; hi <= max; hi++)
|
for (u64 hi = addr2 >> 16, max = (addr2 + size2 - 1) >> 16; hi <= max; hi++)
|
||||||
{
|
{
|
||||||
|
|
@ -953,7 +957,7 @@ namespace vm
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 _page_unmap(u32 addr, u32 max_size, u64 bflags, utils::shm* shm, std::vector<std::pair<u64, u64>>& unmap_events)
|
static u32 _page_unmap(u32 addr, u32 max_size, u64 bflags, utils::shm* shm, std::vector<std::pair<u64, u64>>& unmap_events, bool is_block_termination = false)
|
||||||
{
|
{
|
||||||
perf_meter<"PAGE_UNm"_u64> perf0;
|
perf_meter<"PAGE_UNm"_u64> perf0;
|
||||||
|
|
||||||
|
|
@ -1024,7 +1028,11 @@ namespace vm
|
||||||
ppu_remove_hle_instructions(addr, size);
|
ppu_remove_hle_instructions(addr, size);
|
||||||
|
|
||||||
// Actually unmap memory
|
// Actually unmap memory
|
||||||
if (is_noop)
|
if (is_block_termination && (!shm || is_noop))
|
||||||
|
{
|
||||||
|
// We can skip it if the block is freed
|
||||||
|
}
|
||||||
|
else if (is_noop)
|
||||||
{
|
{
|
||||||
std::memset(g_sudo_addr + addr, 0, size);
|
std::memset(g_sudo_addr + addr, 0, size);
|
||||||
}
|
}
|
||||||
|
|
@ -1330,7 +1338,17 @@ namespace vm
|
||||||
const auto size = it->second.first;
|
const auto size = it->second.first;
|
||||||
|
|
||||||
std::vector<std::pair<u64, u64>> event_data;
|
std::vector<std::pair<u64, u64>> event_data;
|
||||||
ensure(size == _page_unmap(it->first, size, this->flags, it->second.second.get(), unmapped ? *unmapped : event_data));
|
ensure(size == _page_unmap(it->first, size, this->flags, it->second.second.get(), unmapped ? *unmapped : event_data, true));
|
||||||
|
|
||||||
|
if (it->second.second && addr < 0xE0000000)
|
||||||
|
{
|
||||||
|
if (it->second.second.use_count() != 1)
|
||||||
|
{
|
||||||
|
fmt::throw_exception("External memory usage at block 0x%x (addr=0x%x, size=0x%x)", this->addr, it->first, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
it->second.second.reset();
|
||||||
|
}
|
||||||
|
|
||||||
it = next;
|
it = next;
|
||||||
}
|
}
|
||||||
|
|
@ -1341,6 +1359,8 @@ namespace vm
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
m_common->unmap_critical(vm::get_super_ptr(addr));
|
m_common->unmap_critical(vm::get_super_ptr(addr));
|
||||||
#endif
|
#endif
|
||||||
|
ensure(m_common.use_count() == 1);
|
||||||
|
m_common.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1352,6 +1372,7 @@ namespace vm
|
||||||
block_t::~block_t()
|
block_t::~block_t()
|
||||||
{
|
{
|
||||||
ensure(!is_valid());
|
ensure(!is_valid());
|
||||||
|
ensure(!m_common || m_common.use_count() == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 block_t::alloc(const u32 orig_size, const std::shared_ptr<utils::shm>* src, u32 align, u64 flags)
|
u32 block_t::alloc(const u32 orig_size, const std::shared_ptr<utils::shm>* src, u32 align, u64 flags)
|
||||||
|
|
@ -2247,7 +2268,11 @@ namespace vm
|
||||||
|
|
||||||
for (auto& block : g_locations)
|
for (auto& block : g_locations)
|
||||||
{
|
{
|
||||||
if (block) _unmap_block(block);
|
if (block)
|
||||||
|
{
|
||||||
|
_unmap_block(block);
|
||||||
|
ensure(block.use_count() == 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_locations.clear();
|
g_locations.clear();
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ namespace vm
|
||||||
bool check_addr(u32 addr, u8 flags, u32 size);
|
bool check_addr(u32 addr, u8 flags, u32 size);
|
||||||
|
|
||||||
template <u32 Size = 1>
|
template <u32 Size = 1>
|
||||||
bool check_addr(u32 addr, u8 flags = page_readable)
|
inline bool check_addr(u32 addr, u8 flags = page_readable)
|
||||||
{
|
{
|
||||||
extern std::array<memory_page, 0x100000000 / 4096> g_pages;
|
extern std::array<memory_page, 0x100000000 / 4096> g_pages;
|
||||||
|
|
||||||
|
|
@ -94,6 +94,16 @@ namespace vm
|
||||||
return !(~g_pages[addr / 4096] & (flags | page_allocated));
|
return !(~g_pages[addr / 4096] & (flags | page_allocated));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Like check_addr but should only be used in lock-free context with care
|
||||||
|
inline std::pair<bool, u8> get_addr_flags(u32 addr) noexcept
|
||||||
|
{
|
||||||
|
extern std::array<memory_page, 0x100000000 / 4096> g_pages;
|
||||||
|
|
||||||
|
const u8 flags = g_pages[addr / 4096].load();
|
||||||
|
|
||||||
|
return std::make_pair(!!(flags & page_allocated), flags);
|
||||||
|
}
|
||||||
|
|
||||||
// Read string in a safe manner (page aware) (bool true = if null-termination)
|
// Read string in a safe manner (page aware) (bool true = if null-termination)
|
||||||
bool read_string(u32 addr, u32 max_size, std::string& out_string, bool check_pages = true) noexcept;
|
bool read_string(u32 addr, u32 max_size, std::string& out_string, bool check_pages = true) noexcept;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,6 @@
|
||||||
#include "util/tsc.hpp"
|
#include "util/tsc.hpp"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
extern bool g_use_rtm;
|
|
||||||
extern u64 g_rtm_tx_limit2;
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
|
|
@ -143,7 +140,7 @@ namespace vm
|
||||||
void reservation_op_internal(u32 addr, std::function<bool()> func);
|
void reservation_op_internal(u32 addr, std::function<bool()> func);
|
||||||
|
|
||||||
template <bool Ack = false, typename CPU, typename T, typename AT = u32, typename F>
|
template <bool Ack = false, typename CPU, typename T, typename AT = u32, typename F>
|
||||||
inline SAFE_BUFFERS(auto) reservation_op(CPU& cpu, _ptr_base<T, AT> ptr, F op)
|
inline SAFE_BUFFERS(auto) reservation_op(CPU& /*cpu*/, _ptr_base<T, AT> ptr, F op)
|
||||||
{
|
{
|
||||||
// Atomic operation will be performed on aligned 128 bytes of data, so the data size and alignment must comply
|
// Atomic operation will be performed on aligned 128 bytes of data, so the data size and alignment must comply
|
||||||
static_assert(sizeof(T) <= 128 && alignof(T) == sizeof(T), "vm::reservation_op: unsupported type");
|
static_assert(sizeof(T) <= 128 && alignof(T) == sizeof(T), "vm::reservation_op: unsupported type");
|
||||||
|
|
@ -162,188 +159,6 @@ namespace vm
|
||||||
auto& res = vm::reservation_acquire(addr);
|
auto& res = vm::reservation_acquire(addr);
|
||||||
//_m_prefetchw(&res);
|
//_m_prefetchw(&res);
|
||||||
|
|
||||||
#if defined(ARCH_X64)
|
|
||||||
if (g_use_rtm)
|
|
||||||
{
|
|
||||||
// Stage 1: single optimistic transaction attempt
|
|
||||||
unsigned status = -1;
|
|
||||||
u64 _old = 0;
|
|
||||||
|
|
||||||
auto stamp0 = utils::get_tsc(), stamp1 = stamp0, stamp2 = stamp0;
|
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
__asm__ goto ("xbegin %l[stage2];" ::: "memory" : stage2);
|
|
||||||
#else
|
|
||||||
status = _xbegin();
|
|
||||||
if (status == umax)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if (res & rsrv_unique_lock)
|
|
||||||
{
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
__asm__ volatile ("xend; mov $-1, %%eax;" ::: "memory");
|
|
||||||
#else
|
|
||||||
_xend();
|
|
||||||
#endif
|
|
||||||
goto stage2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if constexpr (std::is_void_v<std::invoke_result_t<F, T&>>)
|
|
||||||
{
|
|
||||||
std::invoke(op, *sptr);
|
|
||||||
const u64 old_time = res.fetch_add(128);
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
__asm__ volatile ("xend;" ::: "memory");
|
|
||||||
#else
|
|
||||||
_xend();
|
|
||||||
#endif
|
|
||||||
if constexpr (Ack)
|
|
||||||
reservation_notifier_notify(addr, old_time);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (auto result = std::invoke(op, *sptr))
|
|
||||||
{
|
|
||||||
const u64 old_time = res.fetch_add(128);
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
__asm__ volatile ("xend;" ::: "memory");
|
|
||||||
#else
|
|
||||||
_xend();
|
|
||||||
#endif
|
|
||||||
if constexpr (Ack)
|
|
||||||
reservation_notifier_notify(addr, old_time);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
__asm__ volatile ("xend;" ::: "memory");
|
|
||||||
#else
|
|
||||||
_xend();
|
|
||||||
#endif
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stage2:
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
__asm__ volatile ("mov %%eax, %0;" : "=r" (status) :: "memory");
|
|
||||||
#endif
|
|
||||||
stamp1 = utils::get_tsc();
|
|
||||||
|
|
||||||
// Stage 2: try to lock reservation first
|
|
||||||
_old = res.fetch_add(1);
|
|
||||||
|
|
||||||
// Compute stamps excluding memory touch
|
|
||||||
stamp2 = utils::get_tsc() - (stamp1 - stamp0);
|
|
||||||
|
|
||||||
// Start lightened transaction
|
|
||||||
for (; !(_old & vm::rsrv_unique_lock) && stamp2 - stamp0 <= g_rtm_tx_limit2; stamp2 = utils::get_tsc())
|
|
||||||
{
|
|
||||||
if (cpu.has_pause_flag())
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
__asm__ goto ("xbegin %l[retry];" ::: "memory" : retry);
|
|
||||||
#else
|
|
||||||
status = _xbegin();
|
|
||||||
|
|
||||||
if (status != umax) [[unlikely]]
|
|
||||||
{
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if constexpr (std::is_void_v<std::invoke_result_t<F, T&>>)
|
|
||||||
{
|
|
||||||
std::invoke(op, *sptr);
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
__asm__ volatile ("xend;" ::: "memory");
|
|
||||||
#else
|
|
||||||
_xend();
|
|
||||||
#endif
|
|
||||||
res += 127;
|
|
||||||
if (Ack)
|
|
||||||
reservation_notifier_notify(addr, _old);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (auto result = std::invoke(op, *sptr))
|
|
||||||
{
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
__asm__ volatile ("xend;" ::: "memory");
|
|
||||||
#else
|
|
||||||
_xend();
|
|
||||||
#endif
|
|
||||||
res += 127;
|
|
||||||
if (Ack)
|
|
||||||
reservation_notifier_notify(addr, _old);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
__asm__ volatile ("xend;" ::: "memory");
|
|
||||||
#else
|
|
||||||
_xend();
|
|
||||||
#endif
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
retry:
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
__asm__ volatile ("mov %%eax, %0;" : "=r" (status) :: "memory");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!status)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stage 3: all failed, heavyweight fallback (see comments at the bottom)
|
|
||||||
if constexpr (std::is_void_v<std::invoke_result_t<F, T&>>)
|
|
||||||
{
|
|
||||||
vm::reservation_op_internal(addr, [&]
|
|
||||||
{
|
|
||||||
std::invoke(op, *sptr);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
if constexpr (Ack)
|
|
||||||
reservation_notifier_notify(addr, _old);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto result = std::invoke_result_t<F, T&>();
|
|
||||||
|
|
||||||
vm::reservation_op_internal(addr, [&]
|
|
||||||
{
|
|
||||||
if ((result = std::invoke(op, *sptr)))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (Ack && result)
|
|
||||||
reservation_notifier_notify(addr, _old);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static_cast<void>(cpu);
|
|
||||||
#endif /* ARCH_X64 */
|
|
||||||
|
|
||||||
// Lock reservation and perform heavyweight lock
|
// Lock reservation and perform heavyweight lock
|
||||||
reservation_shared_lock_internal(res);
|
reservation_shared_lock_internal(res);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include "Emu/Cell/PPUCallback.h"
|
#include "Emu/Cell/PPUCallback.h"
|
||||||
#include "Emu/IdManager.h"
|
#include "Emu/IdManager.h"
|
||||||
#include "Emu/Cell/Modules/cellSysutil.h"
|
#include "Emu/Cell/Modules/cellSysutil.h"
|
||||||
|
#include "np_helpers.h"
|
||||||
|
|
||||||
LOG_CHANNEL(sceNp2);
|
LOG_CHANNEL(sceNp2);
|
||||||
|
|
||||||
|
|
@ -53,7 +54,7 @@ void generic_async_transaction_context::set_result_and_wake(error_code err)
|
||||||
|
|
||||||
tus_ctx::tus_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase)
|
tus_ctx::tus_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase)
|
||||||
{
|
{
|
||||||
ensure(!communicationId->data[9] && strlen(communicationId->data) == 9);
|
ensure(communicationId && np::validate_communication_id(*communicationId), "tus_ctx::tus_ctx: Invalid SceNpCommunicationId");
|
||||||
memcpy(&this->communicationId, communicationId.get_ptr(), sizeof(SceNpCommunicationId));
|
memcpy(&this->communicationId, communicationId.get_ptr(), sizeof(SceNpCommunicationId));
|
||||||
memcpy(&this->passphrase, passphrase.get_ptr(), sizeof(SceNpCommunicationPassphrase));
|
memcpy(&this->passphrase, passphrase.get_ptr(), sizeof(SceNpCommunicationPassphrase));
|
||||||
}
|
}
|
||||||
|
|
@ -96,7 +97,7 @@ bool destroy_tus_transaction_context(s32 ctx_id)
|
||||||
|
|
||||||
score_ctx::score_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase)
|
score_ctx::score_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase)
|
||||||
{
|
{
|
||||||
ensure(!communicationId->data[9] && strlen(communicationId->data) == 9);
|
ensure(communicationId && np::validate_communication_id(*communicationId), "score_ctx::score_ctx: Invalid SceNpCommunicationId");
|
||||||
memcpy(&this->communicationId, communicationId.get_ptr(), sizeof(SceNpCommunicationId));
|
memcpy(&this->communicationId, communicationId.get_ptr(), sizeof(SceNpCommunicationId));
|
||||||
memcpy(&this->passphrase, passphrase.get_ptr(), sizeof(SceNpCommunicationPassphrase));
|
memcpy(&this->passphrase, passphrase.get_ptr(), sizeof(SceNpCommunicationPassphrase));
|
||||||
}
|
}
|
||||||
|
|
@ -140,7 +141,7 @@ bool destroy_score_transaction_context(s32 ctx_id)
|
||||||
|
|
||||||
match2_ctx::match2_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase, s32 option)
|
match2_ctx::match2_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase, s32 option)
|
||||||
{
|
{
|
||||||
ensure(!communicationId->data[9] && strlen(communicationId->data) == 9);
|
ensure(communicationId && np::validate_communication_id(*communicationId), "match2_ctx::match2_ctx: Invalid SceNpCommunicationId");
|
||||||
memcpy(&this->communicationId, communicationId.get_ptr(), sizeof(SceNpCommunicationId));
|
memcpy(&this->communicationId, communicationId.get_ptr(), sizeof(SceNpCommunicationId));
|
||||||
memcpy(&this->passphrase, passphrase.get_ptr(), sizeof(SceNpCommunicationPassphrase));
|
memcpy(&this->passphrase, passphrase.get_ptr(), sizeof(SceNpCommunicationPassphrase));
|
||||||
|
|
||||||
|
|
@ -149,7 +150,7 @@ match2_ctx::match2_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<
|
||||||
}
|
}
|
||||||
u16 create_match2_context(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase, s32 option)
|
u16 create_match2_context(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase, s32 option)
|
||||||
{
|
{
|
||||||
sceNp2.notice("Creating match2 context with communicationId: <%s>", static_cast<const char*>(communicationId->data));
|
sceNp2.notice("Creating match2 context with communicationId: <%s>", std::string_view(communicationId->data, 9));
|
||||||
return static_cast<u16>(idm::make<match2_ctx>(communicationId, passphrase, option));
|
return static_cast<u16>(idm::make<match2_ctx>(communicationId, passphrase, option));
|
||||||
}
|
}
|
||||||
bool destroy_match2_context(u16 ctx_id)
|
bool destroy_match2_context(u16 ctx_id)
|
||||||
|
|
@ -167,7 +168,7 @@ shared_ptr<match2_ctx> get_match2_context(u16 ctx_id)
|
||||||
|
|
||||||
lookup_title_ctx::lookup_title_ctx(vm::cptr<SceNpCommunicationId> communicationId)
|
lookup_title_ctx::lookup_title_ctx(vm::cptr<SceNpCommunicationId> communicationId)
|
||||||
{
|
{
|
||||||
ensure(!communicationId->data[9] && strlen(communicationId->data) == 9);
|
ensure(communicationId && np::validate_communication_id(*communicationId), "lookup_title_ctx::lookup_title_ctx: Invalid SceNpCommunicationId");
|
||||||
memcpy(&this->communicationId, communicationId.get_ptr(), sizeof(SceNpCommunicationId));
|
memcpy(&this->communicationId, communicationId.get_ptr(), sizeof(SceNpCommunicationId));
|
||||||
}
|
}
|
||||||
s32 create_lookup_title_context(vm::cptr<SceNpCommunicationId> communicationId)
|
s32 create_lookup_title_context(vm::cptr<SceNpCommunicationId> communicationId)
|
||||||
|
|
|
||||||
|
|
@ -646,7 +646,7 @@ namespace np
|
||||||
|
|
||||||
for (; it != end; ++it)
|
for (; it != end; ++it)
|
||||||
{
|
{
|
||||||
strcpy(ifr.ifr_name, it->ifr_name);
|
strcpy_trunc(ifr.ifr_name, it->ifr_name);
|
||||||
if (ioctl(sock, SIOCGIFFLAGS, &ifr) == 0)
|
if (ioctl(sock, SIOCGIFFLAGS, &ifr) == 0)
|
||||||
{
|
{
|
||||||
if (!(ifr.ifr_flags & IFF_LOOPBACK))
|
if (!(ifr.ifr_flags & IFF_LOOPBACK))
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include "Emu/Cell/Modules/sceNp.h"
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "util/types.hpp"
|
#include "util/types.hpp"
|
||||||
#include "Utilities/StrUtil.h"
|
#include "Utilities/StrUtil.h"
|
||||||
|
|
@ -22,9 +23,15 @@ namespace np
|
||||||
return fmt::format("%02X:%02X:%02X:%02X:%02X:%02X", ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]);
|
return fmt::format("%02X:%02X:%02X:%02X:%02X:%02X", ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool validate_communication_id(const SceNpCommunicationId& com_id)
|
||||||
|
{
|
||||||
|
return std::all_of(com_id.data, com_id.data + 9, [](char c) { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z'); }) && com_id.num <= 99;
|
||||||
|
}
|
||||||
|
|
||||||
std::string communication_id_to_string(const SceNpCommunicationId& communicationId)
|
std::string communication_id_to_string(const SceNpCommunicationId& communicationId)
|
||||||
{
|
{
|
||||||
return fmt::format("%s_%02d", communicationId.data, communicationId.num);
|
std::string_view com_id_data(communicationId.data, 9);
|
||||||
|
return fmt::format("%s_%02d", com_id_data, communicationId.num);
|
||||||
}
|
}
|
||||||
|
|
||||||
void strings_to_userinfo(std::string_view npid, std::string_view online_name, std::string_view avatar_url, SceNpUserInfo& user_info)
|
void strings_to_userinfo(std::string_view npid, std::string_view online_name, std::string_view avatar_url, SceNpUserInfo& user_info)
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue