mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-12-14 07:38:49 +00:00
Compare commits
260 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1a98966ee | ||
|
|
195929953b | ||
|
|
3d0d1a26df | ||
|
|
3ab118837a | ||
|
|
3c111202e1 | ||
|
|
db43c601fc | ||
|
|
d55e41a19e | ||
|
|
a89c29c2ca | ||
|
|
95638d5ca5 | ||
|
|
6d728ec7ed | ||
|
|
7b24b42711 | ||
|
|
8f7eb2d0e9 | ||
|
|
c284cf72e1 | ||
|
|
2c0f986c52 | ||
|
|
0a4453b912 | ||
|
|
092d42e981 | ||
|
|
c2e9c877dd | ||
|
|
400da1aa8d | ||
|
|
94f861588d | ||
|
|
dfdd819e3e | ||
|
|
43fd8fa44a | ||
|
|
2dc5755799 | ||
|
|
8abc43a03d | ||
|
|
7fe4df85ab | ||
|
|
8a409d86d4 | ||
|
|
ab5240d8d2 | ||
|
|
14dc136832 | ||
|
|
aba2b29074 | ||
|
|
433d9459e0 | ||
|
|
5eebb04de9 | ||
|
|
fac21a5362 | ||
|
|
0931802151 | ||
|
|
fb2c035c05 | ||
|
|
7e890def48 | ||
|
|
08182f814f | ||
|
|
8d8bb05055 | ||
|
|
39fed1f469 | ||
|
|
953fb14638 | ||
|
|
f2a989b9da | ||
|
|
b0b74243af | ||
|
|
188eebb92a | ||
|
|
adf4b635f7 | ||
|
|
1e08099036 | ||
|
|
32435674f2 | ||
|
|
b1b4c8c487 | ||
|
|
be4c38bf1c | ||
|
|
ccfb1bbfa8 | ||
|
|
87773a417b | ||
|
|
aa5c1c10df | ||
|
|
3c8e25e8e4 | ||
|
|
5585e42677 | ||
|
|
8a4e03228a | ||
|
|
e7c4ffe032 | ||
|
|
3001b007f6 | ||
|
|
9aa1c13c7e | ||
|
|
d2ac92481b | ||
|
|
0fd1ab674b | ||
|
|
af26c945b1 | ||
|
|
876445faf1 | ||
|
|
f93677b953 | ||
|
|
8b88344679 | ||
|
|
e9ede8d627 | ||
|
|
27447537c3 | ||
|
|
e752f04cde | ||
|
|
cafd40f2c2 | ||
|
|
3c0c921ef5 | ||
|
|
3e22622508 | ||
|
|
8caca4df32 | ||
|
|
40e8a40ada | ||
|
|
a57ccf9112 | ||
|
|
32556ad0d8 | ||
|
|
8bb1e8fcdb | ||
|
|
715ac8a279 | ||
|
|
f1c23d514b | ||
|
|
722a0e36be | ||
|
|
028be3ba5d | ||
|
|
306279901f | ||
|
|
cfbd869126 | ||
|
|
8acefd25e7 | ||
|
|
bab00dbca8 | ||
|
|
f587931ed3 | ||
|
|
91d57e830b | ||
|
|
5be807fc8a | ||
|
|
3f1061de56 | ||
|
|
2a19d915e8 | ||
|
|
1e3d034f96 | ||
|
|
ec8e5d5ef1 | ||
|
|
7aa868562c | ||
|
|
3d1e332c6f | ||
|
|
5789d1a5fb | ||
|
|
7f4265834a | ||
|
|
714605c6a7 | ||
|
|
0a9c437ec8 | ||
|
|
b82993c568 | ||
|
|
0211b7e38e | ||
|
|
14f7dc3527 | ||
|
|
e612e881ac | ||
|
|
8db1beaec6 | ||
|
|
2a953391ef | ||
|
|
51bf98a7b5 | ||
|
|
14c2be8c67 | ||
|
|
e36c4d5f75 | ||
|
|
b8a443c728 | ||
|
|
ea8ad35947 | ||
|
|
00543fe640 | ||
|
|
e5e1aba241 | ||
|
|
41fd1c84cf | ||
|
|
bf41ab6c40 | ||
|
|
aa5293e3ad | ||
|
|
cd9fc5d0e9 | ||
|
|
f1b23c616e | ||
|
|
f623613d12 | ||
|
|
07f451650f | ||
|
|
0b59ebb22f | ||
|
|
f347d3df18 | ||
|
|
f938829f12 | ||
|
|
fea2593ab4 | ||
|
|
1793fd4df0 | ||
|
|
a88850fec6 | ||
|
|
0b672a08ac | ||
|
|
4fb2247196 | ||
|
|
71a82199ed | ||
|
|
7d546f32d8 | ||
|
|
1940ac0fec | ||
|
|
dad5953e8c | ||
|
|
8ee672fe32 | ||
|
|
cde84e4bac | ||
|
|
119e03cb58 | ||
|
|
c076ba69e8 | ||
|
|
57e762468f | ||
|
|
2266622dcf | ||
|
|
941a668f78 | ||
|
|
9524f94749 | ||
|
|
6f543b5bd9 | ||
|
|
8eacb88a86 | ||
|
|
e1ecfb8dd1 | ||
|
|
7ffa581d4b | ||
|
|
357b7829c3 | ||
|
|
6acfdd5e33 | ||
|
|
9e618c0e0c | ||
|
|
d05846a327 | ||
|
|
17abbcd74d | ||
|
|
77da8bac00 | ||
|
|
22a2741ea0 | ||
|
|
874508f8c2 | ||
|
|
642dedea8c | ||
|
|
7fbe15de28 | ||
|
|
37f4bad2b7 | ||
|
|
15ae7a094d | ||
|
|
98f0cb65d7 | ||
|
|
2380f2f9c9 | ||
|
|
c019b54fec | ||
|
|
920acb8d8b | ||
|
|
74b091fd08 | ||
|
|
6bf93071cf | ||
|
|
c66db95378 | ||
|
|
f0b75289c8 | ||
|
|
eb844b9b63 | ||
|
|
fda4f06518 | ||
|
|
3dc0f6d831 | ||
|
|
0835dc71b3 | ||
|
|
f658fc58d1 | ||
|
|
4a5850628e | ||
|
|
b00a321b5e | ||
|
|
394a14626b | ||
|
|
4ebb90c774 | ||
|
|
5f4d03172f | ||
|
|
b0860d6e8c | ||
|
|
5b6e0ab238 | ||
|
|
3d0aacd43d | ||
|
|
7153838c4e | ||
|
|
2002e37ce9 | ||
|
|
07f4a0305b | ||
|
|
c0d43a1a5f | ||
|
|
36044043bc | ||
|
|
99ac10a417 | ||
|
|
7bf168e47f | ||
|
|
7e525a59e4 | ||
|
|
b1a024efbd | ||
|
|
7b68004a40 | ||
|
|
6c215e672d | ||
|
|
086c5802f4 | ||
|
|
9f6261524b | ||
|
|
d6d1ec4f22 | ||
|
|
57a3c0132d | ||
|
|
bd3371bdfb | ||
|
|
286a288bfd | ||
|
|
471ebdb4f0 | ||
|
|
18a36c5daa | ||
|
|
3f1be5a4ce | ||
|
|
cd4f48cb8d | ||
|
|
cea6d87472 | ||
|
|
2226175d9b | ||
|
|
ff18b89e66 | ||
|
|
20b4cd2a32 | ||
|
|
001b94e802 | ||
|
|
23bb5f09fd | ||
|
|
82bd780a6b | ||
|
|
3d95ad0e3a | ||
|
|
16e1d679dc | ||
|
|
fde1726af5 | ||
|
|
add6eeeb8a | ||
|
|
d7d28aa8da | ||
|
|
5976300788 | ||
|
|
df8284c5f8 | ||
|
|
15d6b095f7 | ||
|
|
c71385ec90 | ||
|
|
9ed07f6f6e | ||
|
|
8c9d7d1a08 | ||
|
|
8f2d71d458 | ||
|
|
f9ae945a55 | ||
|
|
c4506da0ae | ||
|
|
6904764aab | ||
|
|
e968b1c23f | ||
|
|
2a0629477b | ||
|
|
5054827441 | ||
|
|
c55d7fbb6a | ||
|
|
c83ac654ce | ||
|
|
3d04765a3f | ||
|
|
e98fab4b58 | ||
|
|
e585330744 | ||
|
|
b41664ac61 | ||
|
|
96cd79f272 | ||
|
|
da00235eaf | ||
|
|
9f42a12baf | ||
|
|
17c47bcd96 | ||
|
|
c45af9a2ca | ||
|
|
8fbd9187f8 | ||
|
|
e1fecda74f | ||
|
|
ce158290fb | ||
|
|
7be35c3997 | ||
|
|
bf239ebc04 | ||
|
|
8e281575b5 | ||
|
|
6ae92c0aac | ||
|
|
0c52d02043 | ||
|
|
85f45d2788 | ||
|
|
8a15d68a8d | ||
|
|
f5618e0342 | ||
|
|
b64dcd2f56 | ||
|
|
7ab851592b | ||
|
|
4fd7f67459 | ||
|
|
f7b458c85a | ||
|
|
75d2181489 | ||
|
|
176d222519 | ||
|
|
ed0a9c0e4e | ||
|
|
a547b2774f | ||
|
|
f45cad6bc9 | ||
|
|
46ac48c311 | ||
|
|
f98b9f7726 | ||
|
|
204bba9be8 | ||
|
|
aa4c6c0178 | ||
|
|
fe389e560a | ||
|
|
f068f13e4a | ||
|
|
76f440889b | ||
|
|
29183354cc | ||
|
|
0b015daff7 | ||
|
|
9ec75c3feb | ||
|
|
7b16085c59 | ||
|
|
b7fe08519f | ||
|
|
72440a4996 |
@@ -10,7 +10,7 @@ if grep -nrI '\s$' src *.yml *.txt *.md Doxyfile .gitignore .gitmodules .ci* dis
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Default clang-format points to default 3.5 version one
|
# Default clang-format points to default 3.5 version one
|
||||||
CLANG_FORMAT=clang-format-17
|
CLANG_FORMAT=clang-format-18
|
||||||
$CLANG_FORMAT --version
|
$CLANG_FORMAT --version
|
||||||
|
|
||||||
if [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then
|
if [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then
|
||||||
|
|||||||
4
.github/linux-appimage-qt.sh
vendored
4
.github/linux-appimage-qt.sh
vendored
@@ -27,7 +27,7 @@ chmod a+x linuxdeploy-plugin-checkrt-x86_64.sh
|
|||||||
|
|
||||||
cp -a "$GITHUB_WORKSPACE/build/translations" AppDir/usr/bin
|
cp -a "$GITHUB_WORKSPACE/build/translations" AppDir/usr/bin
|
||||||
|
|
||||||
./linuxdeploy-x86_64.AppImage --appdir AppDir -d "$GITHUB_WORKSPACE"/.github/shadps4.desktop -e "$GITHUB_WORKSPACE"/build/shadps4 -i "$GITHUB_WORKSPACE"/.github/shadps4.png --plugin qt
|
./linuxdeploy-x86_64.AppImage --appdir AppDir -d "$GITHUB_WORKSPACE"/dist/net.shadps4.shadPS4.desktop -e "$GITHUB_WORKSPACE"/build/shadps4 -i "$GITHUB_WORKSPACE"/src/images/net.shadps4.shadPS4.svg --plugin qt
|
||||||
rm AppDir/usr/plugins/multimedia/libgstreamermediaplugin.so
|
rm AppDir/usr/plugins/multimedia/libgstreamermediaplugin.so
|
||||||
./linuxdeploy-x86_64.AppImage --appdir AppDir --output appimage
|
./linuxdeploy-x86_64.AppImage --appdir AppDir --output appimage
|
||||||
mv Shadps4-x86_64.AppImage Shadps4-qt.AppImage
|
mv shadPS4-x86_64.AppImage Shadps4-qt.AppImage
|
||||||
|
|||||||
4
.github/linux-appimage-sdl.sh
vendored
4
.github/linux-appimage-sdl.sh
vendored
@@ -17,5 +17,5 @@ chmod a+x linuxdeploy-plugin-checkrt-x86_64.sh
|
|||||||
# Build AppImage
|
# Build AppImage
|
||||||
./linuxdeploy-x86_64.AppImage --appdir AppDir
|
./linuxdeploy-x86_64.AppImage --appdir AppDir
|
||||||
./linuxdeploy-plugin-checkrt-x86_64.sh --appdir AppDir
|
./linuxdeploy-plugin-checkrt-x86_64.sh --appdir AppDir
|
||||||
./linuxdeploy-x86_64.AppImage --appdir AppDir -d "$GITHUB_WORKSPACE"/.github/shadps4.desktop -e "$GITHUB_WORKSPACE"/build/shadps4 -i "$GITHUB_WORKSPACE"/.github/shadps4.png --output appimage
|
./linuxdeploy-x86_64.AppImage --appdir AppDir -d "$GITHUB_WORKSPACE"/dist/net.shadps4.shadPS4.desktop -e "$GITHUB_WORKSPACE"/build/shadps4 -i "$GITHUB_WORKSPACE"/src/images/net.shadps4.shadPS4.svg --output appimage
|
||||||
mv Shadps4-x86_64.AppImage Shadps4-sdl.AppImage
|
mv shadPS4-x86_64.AppImage Shadps4-sdl.AppImage
|
||||||
|
|||||||
44
.github/workflows/build.yml
vendored
44
.github/workflows/build.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
|||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: fsfe/reuse-action@v4
|
- uses: fsfe/reuse-action@v5
|
||||||
|
|
||||||
clang-format:
|
clang-format:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -30,9 +30,9 @@ jobs:
|
|||||||
- name: Install
|
- name: Install
|
||||||
run: |
|
run: |
|
||||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||||
sudo add-apt-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-17 main'
|
sudo add-apt-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-18 main'
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install clang-format-17
|
sudo apt install clang-format-18
|
||||||
- name: Build
|
- name: Build
|
||||||
env:
|
env:
|
||||||
COMMIT_RANGE: ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}
|
COMMIT_RANGE: ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}
|
||||||
@@ -89,10 +89,10 @@ jobs:
|
|||||||
arch: amd64
|
arch: amd64
|
||||||
|
|
||||||
- name: Configure CMake
|
- name: Configure CMake
|
||||||
run: cmake --fresh -G Ninja -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
run: cmake --fresh -G Ninja -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel
|
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $env:NUMBER_OF_PROCESSORS
|
||||||
|
|
||||||
- name: Upload Windows SDL artifact
|
- name: Upload Windows SDL artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
@@ -143,10 +143,10 @@ jobs:
|
|||||||
arch: amd64
|
arch: amd64
|
||||||
|
|
||||||
- name: Configure CMake
|
- name: Configure CMake
|
||||||
run: cmake --fresh -G Ninja -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DENABLE_QT_GUI=ON -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
run: cmake --fresh -G Ninja -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DENABLE_QT_GUI=ON -DENABLE_UPDATER=ON -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel
|
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $env:NUMBER_OF_PROCESSORS
|
||||||
|
|
||||||
- name: Deploy and Package
|
- name: Deploy and Package
|
||||||
run: |
|
run: |
|
||||||
@@ -162,7 +162,7 @@ jobs:
|
|||||||
path: upload/
|
path: upload/
|
||||||
|
|
||||||
macos-sdl:
|
macos-sdl:
|
||||||
runs-on: macos-latest
|
runs-on: macos-15
|
||||||
needs: get-info
|
needs: get-info
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -174,11 +174,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
xcode-version: latest
|
xcode-version: latest
|
||||||
|
|
||||||
- name: Install MoltenVK
|
|
||||||
run: |
|
|
||||||
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 molten-vk
|
|
||||||
|
|
||||||
- name: Cache CMake Configuration
|
- name: Cache CMake Configuration
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
env:
|
env:
|
||||||
@@ -201,7 +196,7 @@ jobs:
|
|||||||
variant: sccache
|
variant: sccache
|
||||||
|
|
||||||
- name: Configure CMake
|
- name: Configure CMake
|
||||||
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache
|
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(sysctl -n hw.ncpu)
|
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(sysctl -n hw.ncpu)
|
||||||
@@ -210,7 +205,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir upload
|
mkdir upload
|
||||||
mv ${{github.workspace}}/build/shadps4 upload
|
mv ${{github.workspace}}/build/shadps4 upload
|
||||||
cp $(arch -x86_64 /usr/local/bin/brew --prefix)/opt/molten-vk/lib/libMoltenVK.dylib upload
|
cp ${{github.workspace}}/build/externals/MoltenVK/libMoltenVK.dylib upload
|
||||||
tar cf shadps4-macos-sdl.tar.gz -C upload .
|
tar cf shadps4-macos-sdl.tar.gz -C upload .
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
@@ -218,7 +213,7 @@ jobs:
|
|||||||
path: shadps4-macos-sdl.tar.gz
|
path: shadps4-macos-sdl.tar.gz
|
||||||
|
|
||||||
macos-qt:
|
macos-qt:
|
||||||
runs-on: macos-latest
|
runs-on: macos-15
|
||||||
needs: get-info
|
needs: get-info
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -230,11 +225,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
xcode-version: latest
|
xcode-version: latest
|
||||||
|
|
||||||
- name: Install MoltenVK and Setup Qt
|
- name: Setup Qt
|
||||||
run: |
|
uses: jurplel/install-qt-action@v4
|
||||||
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 molten-vk
|
|
||||||
- uses: jurplel/install-qt-action@v4
|
|
||||||
with:
|
with:
|
||||||
version: 6.7.3
|
version: 6.7.3
|
||||||
host: mac
|
host: mac
|
||||||
@@ -265,7 +257,7 @@ jobs:
|
|||||||
variant: sccache
|
variant: sccache
|
||||||
|
|
||||||
- name: Configure CMake
|
- name: Configure CMake
|
||||||
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_OSX_ARCHITECTURES=x86_64 -DENABLE_QT_GUI=ON -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache
|
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_OSX_ARCHITECTURES=x86_64 -DENABLE_QT_GUI=ON -DENABLE_UPDATER=ON -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(sysctl -n hw.ncpu)
|
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(sysctl -n hw.ncpu)
|
||||||
@@ -312,10 +304,10 @@ jobs:
|
|||||||
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
||||||
|
|
||||||
- name: Configure CMake
|
- name: Configure CMake
|
||||||
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel
|
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(nproc)
|
||||||
|
|
||||||
- name: Package and Upload Linux(ubuntu64) SDL artifact
|
- name: Package and Upload Linux(ubuntu64) SDL artifact
|
||||||
run: |
|
run: |
|
||||||
@@ -368,10 +360,10 @@ jobs:
|
|||||||
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
||||||
|
|
||||||
- name: Configure CMake
|
- name: Configure CMake
|
||||||
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DENABLE_QT_GUI=ON -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DENABLE_QT_GUI=ON -DENABLE_UPDATER=ON -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel3
|
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(nproc)
|
||||||
|
|
||||||
- name: Run AppImage packaging script
|
- name: Run AppImage packaging script
|
||||||
run: ./.github/linux-appimage-qt.sh
|
run: ./.github/linux-appimage-qt.sh
|
||||||
|
|||||||
12
.gitignore
vendored
12
.gitignore
vendored
@@ -382,10 +382,10 @@ FodyWeavers.xsd
|
|||||||
|
|
||||||
# VS Code files for those working on multiple tools
|
# VS Code files for those working on multiple tools
|
||||||
.vscode/*
|
.vscode/*
|
||||||
!.vscode/settings.json
|
.vscode/settings.json
|
||||||
!.vscode/tasks.json
|
.vscode/tasks.json
|
||||||
!.vscode/launch.json
|
.vscode/launch.json
|
||||||
!.vscode/extensions.json
|
.vscode/extensions.json
|
||||||
*.code-workspace
|
*.code-workspace
|
||||||
/CMakeUserPresets.json
|
/CMakeUserPresets.json
|
||||||
/compile_commands.json
|
/compile_commands.json
|
||||||
@@ -414,3 +414,7 @@ FodyWeavers.xsd
|
|||||||
|
|
||||||
# for macOS
|
# for macOS
|
||||||
**/.DS_Store
|
**/.DS_Store
|
||||||
|
|
||||||
|
# JetBrains
|
||||||
|
.idea
|
||||||
|
cmake-build-*
|
||||||
|
|||||||
20
.gitmodules
vendored
20
.gitmodules
vendored
@@ -99,3 +99,23 @@
|
|||||||
path = externals/discord-rpc
|
path = externals/discord-rpc
|
||||||
url = https://github.com/shadps4-emu/ext-discord-rpc.git
|
url = https://github.com/shadps4-emu/ext-discord-rpc.git
|
||||||
shallow = true
|
shallow = true
|
||||||
|
[submodule "externals/LibAtrac9"]
|
||||||
|
path = externals/LibAtrac9
|
||||||
|
url = https://github.com/shadps4-emu/ext-LibAtrac9.git
|
||||||
|
shallow = true
|
||||||
|
[submodule "externals/libpng"]
|
||||||
|
path = externals/libpng
|
||||||
|
url = https://github.com/pnggroup/libpng
|
||||||
|
shallow = true
|
||||||
|
[submodule "externals/MoltenVK/SPIRV-Cross"]
|
||||||
|
path = externals/MoltenVK/SPIRV-Cross
|
||||||
|
url = https://github.com/KhronosGroup/SPIRV-Cross
|
||||||
|
shallow = true
|
||||||
|
[submodule "externals/MoltenVK/MoltenVK"]
|
||||||
|
path = externals/MoltenVK/MoltenVK
|
||||||
|
url = https://github.com/KhronosGroup/MoltenVK
|
||||||
|
shallow = true
|
||||||
|
[submodule "externals/MoltenVK/cereal"]
|
||||||
|
path = externals/MoltenVK/cereal
|
||||||
|
url = https://github.com/USCiLab/cereal
|
||||||
|
shallow = true
|
||||||
|
|||||||
244
CMakeLists.txt
244
CMakeLists.txt
@@ -1,7 +1,8 @@
|
|||||||
# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.16.3)
|
# Version 3.24 needed for FetchContent OVERRIDE_FIND_PACKAGE
|
||||||
|
cmake_minimum_required(VERSION 3.24)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 23)
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
@@ -15,7 +16,7 @@ if (NOT CMAKE_BUILD_TYPE)
|
|||||||
set(CMAKE_BUILD_TYPE Release)
|
set(CMAKE_BUILD_TYPE Release)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
project(shadPS4)
|
project(shadPS4 CXX C ASM)
|
||||||
|
|
||||||
# Forcing PIE makes sure that the base address is high enough so that it doesn't clash with the PS4 memory.
|
# Forcing PIE makes sure that the base address is high enough so that it doesn't clash with the PS4 memory.
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
@@ -31,6 +32,7 @@ endif()
|
|||||||
|
|
||||||
option(ENABLE_QT_GUI "Enable the Qt GUI. If not selected then the emulator uses a minimal SDL-based UI instead" OFF)
|
option(ENABLE_QT_GUI "Enable the Qt GUI. If not selected then the emulator uses a minimal SDL-based UI instead" OFF)
|
||||||
option(ENABLE_DISCORD_RPC "Enable the Discord RPC integration" ON)
|
option(ENABLE_DISCORD_RPC "Enable the Discord RPC integration" ON)
|
||||||
|
option(ENABLE_UPDATER "Enables the options to updater" ON)
|
||||||
|
|
||||||
# First, determine whether to use CMAKE_OSX_ARCHITECTURES or CMAKE_SYSTEM_PROCESSOR.
|
# First, determine whether to use CMAKE_OSX_ARCHITECTURES or CMAKE_SYSTEM_PROCESSOR.
|
||||||
if (APPLE AND CMAKE_OSX_ARCHITECTURES)
|
if (APPLE AND CMAKE_OSX_ARCHITECTURES)
|
||||||
@@ -109,18 +111,20 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_
|
|||||||
find_package(Boost 1.84.0 CONFIG)
|
find_package(Boost 1.84.0 CONFIG)
|
||||||
find_package(FFmpeg 5.1.2 MODULE)
|
find_package(FFmpeg 5.1.2 MODULE)
|
||||||
find_package(fmt 10.2.0 CONFIG)
|
find_package(fmt 10.2.0 CONFIG)
|
||||||
find_package(glslang 14.2.0 CONFIG)
|
find_package(glslang 15 CONFIG)
|
||||||
find_package(half 1.12.0 MODULE)
|
find_package(half 1.12.0 MODULE)
|
||||||
find_package(magic_enum 0.9.6 CONFIG)
|
find_package(magic_enum 0.9.7 CONFIG)
|
||||||
|
find_package(PNG 1.6 MODULE)
|
||||||
find_package(RenderDoc 1.6.0 MODULE)
|
find_package(RenderDoc 1.6.0 MODULE)
|
||||||
find_package(SDL3 3.1.2 CONFIG)
|
find_package(SDL3 3.1.2 CONFIG)
|
||||||
|
find_package(stb MODULE)
|
||||||
find_package(toml11 4.2.0 CONFIG)
|
find_package(toml11 4.2.0 CONFIG)
|
||||||
find_package(tsl-robin-map 1.3.0 CONFIG)
|
find_package(tsl-robin-map 1.3.0 CONFIG)
|
||||||
find_package(VulkanHeaders 1.3.289 CONFIG)
|
find_package(VulkanHeaders 1.4.303 CONFIG)
|
||||||
find_package(VulkanMemoryAllocator 3.1.0 CONFIG)
|
find_package(VulkanMemoryAllocator 3.1.0 CONFIG)
|
||||||
find_package(xbyak 7.07 CONFIG)
|
find_package(xbyak 7.07 CONFIG)
|
||||||
find_package(xxHash 0.8.2 MODULE)
|
find_package(xxHash 0.8.2 MODULE)
|
||||||
find_package(zlib-ng 2.1.7 MODULE)
|
find_package(ZLIB 1.3 MODULE)
|
||||||
find_package(Zydis 5.0.0 CONFIG)
|
find_package(Zydis 5.0.0 CONFIG)
|
||||||
find_package(pugixml 1.14 CONFIG)
|
find_package(pugixml 1.14 CONFIG)
|
||||||
|
|
||||||
@@ -175,16 +179,28 @@ if(ENABLE_QT_GUI)
|
|||||||
qt_add_resources(TRANSLATIONS ${TRANSLATIONS_QRC})
|
qt_add_resources(TRANSLATIONS ${TRANSLATIONS_QRC})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(AUDIO_CORE src/audio_core/sdl_audio.cpp
|
set(AJM_LIB src/core/libraries/ajm/ajm.cpp
|
||||||
src/audio_core/sdl_audio.h
|
src/core/libraries/ajm/ajm.h
|
||||||
|
src/core/libraries/ajm/ajm_at9.cpp
|
||||||
|
src/core/libraries/ajm/ajm_at9.h
|
||||||
|
src/core/libraries/ajm/ajm_batch.cpp
|
||||||
|
src/core/libraries/ajm/ajm_batch.h
|
||||||
|
src/core/libraries/ajm/ajm_context.cpp
|
||||||
|
src/core/libraries/ajm/ajm_context.h
|
||||||
|
src/core/libraries/ajm/ajm_error.h
|
||||||
|
src/core/libraries/ajm/ajm_instance.cpp
|
||||||
|
src/core/libraries/ajm/ajm_instance.h
|
||||||
|
src/core/libraries/ajm/ajm_mp3.cpp
|
||||||
|
src/core/libraries/ajm/ajm_mp3.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(AUDIO_LIB src/core/libraries/audio/audioin.cpp
|
set(AUDIO_LIB src/core/libraries/audio/audioin.cpp
|
||||||
src/core/libraries/audio/audioin.h
|
src/core/libraries/audio/audioin.h
|
||||||
src/core/libraries/audio/audioout.cpp
|
src/core/libraries/audio/audioout.cpp
|
||||||
src/core/libraries/audio/audioout.h
|
src/core/libraries/audio/audioout.h
|
||||||
src/core/libraries/ajm/ajm.cpp
|
src/core/libraries/audio/sdl_audio.cpp
|
||||||
src/core/libraries/ajm/ajm.h
|
src/core/libraries/audio/sdl_audio.h
|
||||||
|
src/core/libraries/audio/audioout_error.h
|
||||||
src/core/libraries/ngs2/ngs2.cpp
|
src/core/libraries/ngs2/ngs2.cpp
|
||||||
src/core/libraries/ngs2/ngs2.h
|
src/core/libraries/ngs2/ngs2.h
|
||||||
)
|
)
|
||||||
@@ -194,31 +210,43 @@ set(GNM_LIB src/core/libraries/gnmdriver/gnmdriver.cpp
|
|||||||
src/core/libraries/gnmdriver/gnm_error.h
|
src/core/libraries/gnmdriver/gnm_error.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(KERNEL_LIB
|
set(KERNEL_LIB src/core/libraries/kernel/sync/mutex.cpp
|
||||||
src/core/libraries/kernel/event_flag/event_flag.cpp
|
src/core/libraries/kernel/sync/mutex.h
|
||||||
src/core/libraries/kernel/event_flag/event_flag.h
|
src/core/libraries/kernel/sync/semaphore.h
|
||||||
src/core/libraries/kernel/event_flag/event_flag_obj.cpp
|
src/core/libraries/kernel/threads/condvar.cpp
|
||||||
src/core/libraries/kernel/event_flag/event_flag_obj.h
|
src/core/libraries/kernel/threads/event_flag.cpp
|
||||||
|
src/core/libraries/kernel/threads/exception.cpp
|
||||||
|
src/core/libraries/kernel/threads/exception.h
|
||||||
|
src/core/libraries/kernel/threads/mutex.cpp
|
||||||
|
src/core/libraries/kernel/threads/pthread_attr.cpp
|
||||||
|
src/core/libraries/kernel/threads/pthread_clean.cpp
|
||||||
|
src/core/libraries/kernel/threads/pthread.cpp
|
||||||
|
src/core/libraries/kernel/threads/pthread_spec.cpp
|
||||||
src/core/libraries/kernel/threads/rwlock.cpp
|
src/core/libraries/kernel/threads/rwlock.cpp
|
||||||
src/core/libraries/kernel/threads/semaphore.cpp
|
src/core/libraries/kernel/threads/semaphore.cpp
|
||||||
src/core/libraries/kernel/threads/keys.cpp
|
src/core/libraries/kernel/threads/sleepq.cpp
|
||||||
src/core/libraries/kernel/threads/threads.h
|
src/core/libraries/kernel/threads/sleepq.h
|
||||||
src/core/libraries/kernel/cpu_management.cpp
|
src/core/libraries/kernel/threads/stack.cpp
|
||||||
src/core/libraries/kernel/cpu_management.h
|
src/core/libraries/kernel/threads/tcb.cpp
|
||||||
src/core/libraries/kernel/event_queue.cpp
|
src/core/libraries/kernel/threads/pthread.h
|
||||||
src/core/libraries/kernel/event_queue.h
|
src/core/libraries/kernel/threads/thread_state.cpp
|
||||||
src/core/libraries/kernel/event_queues.cpp
|
src/core/libraries/kernel/threads/thread_state.h
|
||||||
src/core/libraries/kernel/event_queues.h
|
src/core/libraries/kernel/process.cpp
|
||||||
|
src/core/libraries/kernel/process.h
|
||||||
|
src/core/libraries/kernel/equeue.cpp
|
||||||
|
src/core/libraries/kernel/equeue.h
|
||||||
src/core/libraries/kernel/file_system.cpp
|
src/core/libraries/kernel/file_system.cpp
|
||||||
src/core/libraries/kernel/file_system.h
|
src/core/libraries/kernel/file_system.h
|
||||||
src/core/libraries/kernel/libkernel.cpp
|
src/core/libraries/kernel/kernel.cpp
|
||||||
src/core/libraries/kernel/libkernel.h
|
src/core/libraries/kernel/kernel.h
|
||||||
src/core/libraries/kernel/memory_management.cpp
|
src/core/libraries/kernel/memory.cpp
|
||||||
src/core/libraries/kernel/memory_management.h
|
src/core/libraries/kernel/memory.h
|
||||||
src/core/libraries/kernel/thread_management.cpp
|
src/core/libraries/kernel/threads.cpp
|
||||||
src/core/libraries/kernel/thread_management.h
|
src/core/libraries/kernel/threads.h
|
||||||
src/core/libraries/kernel/time_management.cpp
|
src/core/libraries/kernel/time.cpp
|
||||||
src/core/libraries/kernel/time_management.h
|
src/core/libraries/kernel/time.h
|
||||||
|
src/core/libraries/kernel/orbis_error.h
|
||||||
|
src/core/libraries/kernel/posix_error.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(NETWORK_LIBS src/core/libraries/network/http.cpp
|
set(NETWORK_LIBS src/core/libraries/network/http.cpp
|
||||||
@@ -234,6 +262,21 @@ set(NETWORK_LIBS src/core/libraries/network/http.cpp
|
|||||||
src/core/libraries/network/ssl.h
|
src/core/libraries/network/ssl.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(AVPLAYER_LIB src/core/libraries/avplayer/avplayer_common.cpp
|
||||||
|
src/core/libraries/avplayer/avplayer_common.h
|
||||||
|
src/core/libraries/avplayer/avplayer_file_streamer.cpp
|
||||||
|
src/core/libraries/avplayer/avplayer_file_streamer.h
|
||||||
|
src/core/libraries/avplayer/avplayer_impl.cpp
|
||||||
|
src/core/libraries/avplayer/avplayer_impl.h
|
||||||
|
src/core/libraries/avplayer/avplayer_source.cpp
|
||||||
|
src/core/libraries/avplayer/avplayer_source.h
|
||||||
|
src/core/libraries/avplayer/avplayer_state.cpp
|
||||||
|
src/core/libraries/avplayer/avplayer_state.h
|
||||||
|
src/core/libraries/avplayer/avplayer.cpp
|
||||||
|
src/core/libraries/avplayer/avplayer.h
|
||||||
|
src/core/libraries/avplayer/avplayer_error.h
|
||||||
|
)
|
||||||
|
|
||||||
set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp
|
set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp
|
||||||
src/core/libraries/system/commondialog.h
|
src/core/libraries/system/commondialog.h
|
||||||
src/core/libraries/system/msgdialog.cpp
|
src/core/libraries/system/msgdialog.cpp
|
||||||
@@ -255,30 +298,22 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp
|
|||||||
src/core/libraries/save_data/dialog/savedatadialog_ui.h
|
src/core/libraries/save_data/dialog/savedatadialog_ui.h
|
||||||
src/core/libraries/system/sysmodule.cpp
|
src/core/libraries/system/sysmodule.cpp
|
||||||
src/core/libraries/system/sysmodule.h
|
src/core/libraries/system/sysmodule.h
|
||||||
|
src/core/libraries/system/system_error.h
|
||||||
src/core/libraries/system/systemservice.cpp
|
src/core/libraries/system/systemservice.cpp
|
||||||
src/core/libraries/system/systemservice.h
|
src/core/libraries/system/systemservice.h
|
||||||
|
src/core/libraries/system/systemservice_error.h
|
||||||
src/core/libraries/system/userservice.cpp
|
src/core/libraries/system/userservice.cpp
|
||||||
src/core/libraries/system/userservice.h
|
src/core/libraries/system/userservice.h
|
||||||
|
src/core/libraries/system/userservice_error.h
|
||||||
src/core/libraries/app_content/app_content.cpp
|
src/core/libraries/app_content/app_content.cpp
|
||||||
src/core/libraries/app_content/app_content.h
|
src/core/libraries/app_content/app_content.h
|
||||||
|
src/core/libraries/app_content/app_content_error.h
|
||||||
src/core/libraries/rtc/rtc.cpp
|
src/core/libraries/rtc/rtc.cpp
|
||||||
src/core/libraries/rtc/rtc.h
|
src/core/libraries/rtc/rtc.h
|
||||||
src/core/libraries/rtc/rtc_error.h
|
src/core/libraries/rtc/rtc_error.h
|
||||||
src/core/libraries/disc_map/disc_map.cpp
|
src/core/libraries/disc_map/disc_map.cpp
|
||||||
src/core/libraries/disc_map/disc_map.h
|
src/core/libraries/disc_map/disc_map.h
|
||||||
src/core/libraries/disc_map/disc_map_codes.h
|
src/core/libraries/disc_map/disc_map_codes.h
|
||||||
src/core/libraries/avplayer/avplayer_common.cpp
|
|
||||||
src/core/libraries/avplayer/avplayer_common.h
|
|
||||||
src/core/libraries/avplayer/avplayer_file_streamer.cpp
|
|
||||||
src/core/libraries/avplayer/avplayer_file_streamer.h
|
|
||||||
src/core/libraries/avplayer/avplayer_impl.cpp
|
|
||||||
src/core/libraries/avplayer/avplayer_impl.h
|
|
||||||
src/core/libraries/avplayer/avplayer_source.cpp
|
|
||||||
src/core/libraries/avplayer/avplayer_source.h
|
|
||||||
src/core/libraries/avplayer/avplayer_state.cpp
|
|
||||||
src/core/libraries/avplayer/avplayer_state.h
|
|
||||||
src/core/libraries/avplayer/avplayer.cpp
|
|
||||||
src/core/libraries/avplayer/avplayer.h
|
|
||||||
src/core/libraries/ngs2/ngs2.cpp
|
src/core/libraries/ngs2/ngs2.cpp
|
||||||
src/core/libraries/ngs2/ngs2.h
|
src/core/libraries/ngs2/ngs2.h
|
||||||
src/core/libraries/ngs2/ngs2_error.h
|
src/core/libraries/ngs2/ngs2_error.h
|
||||||
@@ -296,6 +331,8 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp
|
|||||||
src/core/libraries/remote_play/remoteplay.h
|
src/core/libraries/remote_play/remoteplay.h
|
||||||
src/core/libraries/share_play/shareplay.cpp
|
src/core/libraries/share_play/shareplay.cpp
|
||||||
src/core/libraries/share_play/shareplay.h
|
src/core/libraries/share_play/shareplay.h
|
||||||
|
src/core/libraries/razor_cpu/razor_cpu.cpp
|
||||||
|
src/core/libraries/razor_cpu/razor_cpu.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(VIDEOOUT_LIB src/core/libraries/videoout/buffer.h
|
set(VIDEOOUT_LIB src/core/libraries/videoout/buffer.h
|
||||||
@@ -303,6 +340,7 @@ set(VIDEOOUT_LIB src/core/libraries/videoout/buffer.h
|
|||||||
src/core/libraries/videoout/driver.h
|
src/core/libraries/videoout/driver.h
|
||||||
src/core/libraries/videoout/video_out.cpp
|
src/core/libraries/videoout/video_out.cpp
|
||||||
src/core/libraries/videoout/video_out.h
|
src/core/libraries/videoout/video_out.h
|
||||||
|
src/core/libraries/videoout/videoout_error.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LIBC_SOURCES src/core/libraries/libc_internal/libc_internal.cpp
|
set(LIBC_SOURCES src/core/libraries/libc_internal/libc_internal.cpp
|
||||||
@@ -320,18 +358,28 @@ set(IME_LIB src/core/libraries/ime/error_dialog.cpp
|
|||||||
src/core/libraries/ime/ime_ui.h
|
src/core/libraries/ime/ime_ui.h
|
||||||
src/core/libraries/ime/ime.cpp
|
src/core/libraries/ime/ime.cpp
|
||||||
src/core/libraries/ime/ime.h
|
src/core/libraries/ime/ime.h
|
||||||
|
src/core/libraries/ime/ime_error.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(PAD_LIB src/core/libraries/pad/pad.cpp
|
set(PAD_LIB src/core/libraries/pad/pad.cpp
|
||||||
src/core/libraries/pad/pad.h
|
src/core/libraries/pad/pad.h
|
||||||
|
src/core/libraries/pad/pad_errors.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(PNG_LIB src/core/libraries/libpng/pngdec.cpp
|
set(PNG_LIB src/core/libraries/libpng/pngdec.cpp
|
||||||
src/core/libraries/libpng/pngdec.h
|
src/core/libraries/libpng/pngdec.h
|
||||||
|
src/core/libraries/libpng/pngdec_error.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set(JPEG_LIB src/core/libraries/jpeg/jpeg_error.h
|
||||||
|
src/core/libraries/jpeg/jpegenc.cpp
|
||||||
|
src/core/libraries/jpeg/jpegenc.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(PLAYGO_LIB src/core/libraries/playgo/playgo.cpp
|
set(PLAYGO_LIB src/core/libraries/playgo/playgo.cpp
|
||||||
src/core/libraries/playgo/playgo.h
|
src/core/libraries/playgo/playgo.h
|
||||||
|
src/core/libraries/playgo/playgo_dialog.cpp
|
||||||
|
src/core/libraries/playgo/playgo_dialog.h
|
||||||
src/core/libraries/playgo/playgo_types.h
|
src/core/libraries/playgo/playgo_types.h
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -344,8 +392,10 @@ set(USBD_LIB src/core/libraries/usbd/usbd.cpp
|
|||||||
src/core/libraries/usbd/usbd.h
|
src/core/libraries/usbd/usbd.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(FIBER_LIB src/core/libraries/fiber/fiber.cpp
|
set(FIBER_LIB src/core/libraries/fiber/fiber_context.s
|
||||||
|
src/core/libraries/fiber/fiber.cpp
|
||||||
src/core/libraries/fiber/fiber.h
|
src/core/libraries/fiber/fiber.h
|
||||||
|
src/core/libraries/fiber/fiber_error.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(VDEC_LIB src/core/libraries/videodec/videodec2_impl.cpp
|
set(VDEC_LIB src/core/libraries/videodec/videodec2_impl.cpp
|
||||||
@@ -353,6 +403,11 @@ set(VDEC_LIB src/core/libraries/videodec/videodec2_impl.cpp
|
|||||||
src/core/libraries/videodec/videodec2.cpp
|
src/core/libraries/videodec/videodec2.cpp
|
||||||
src/core/libraries/videodec/videodec2.h
|
src/core/libraries/videodec/videodec2.h
|
||||||
src/core/libraries/videodec/videodec2_avc.h
|
src/core/libraries/videodec/videodec2_avc.h
|
||||||
|
src/core/libraries/videodec/videodec.cpp
|
||||||
|
src/core/libraries/videodec/videodec.h
|
||||||
|
src/core/libraries/videodec/videodec_error.h
|
||||||
|
src/core/libraries/videodec/videodec_impl.cpp
|
||||||
|
src/core/libraries/videodec/videodec_impl.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(NP_LIBS src/core/libraries/np_manager/np_manager.cpp
|
set(NP_LIBS src/core/libraries/np_manager/np_manager.cpp
|
||||||
@@ -363,6 +418,7 @@ set(NP_LIBS src/core/libraries/np_manager/np_manager.cpp
|
|||||||
src/core/libraries/np_trophy/np_trophy.h
|
src/core/libraries/np_trophy/np_trophy.h
|
||||||
src/core/libraries/np_trophy/trophy_ui.cpp
|
src/core/libraries/np_trophy/trophy_ui.cpp
|
||||||
src/core/libraries/np_trophy/trophy_ui.h
|
src/core/libraries/np_trophy/trophy_ui.h
|
||||||
|
src/core/libraries/np_trophy/np_trophy_error.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(MISC_LIBS src/core/libraries/screenshot/screenshot.cpp
|
set(MISC_LIBS src/core/libraries/screenshot/screenshot.cpp
|
||||||
@@ -384,10 +440,14 @@ set(DEV_TOOLS src/core/devtools/layer.cpp
|
|||||||
src/core/devtools/widget/frame_graph.cpp
|
src/core/devtools/widget/frame_graph.cpp
|
||||||
src/core/devtools/widget/frame_graph.h
|
src/core/devtools/widget/frame_graph.h
|
||||||
src/core/devtools/widget/imgui_memory_editor.h
|
src/core/devtools/widget/imgui_memory_editor.h
|
||||||
|
src/core/devtools/widget/memory_map.cpp
|
||||||
|
src/core/devtools/widget/memory_map.h
|
||||||
src/core/devtools/widget/reg_popup.cpp
|
src/core/devtools/widget/reg_popup.cpp
|
||||||
src/core/devtools/widget/reg_popup.h
|
src/core/devtools/widget/reg_popup.h
|
||||||
src/core/devtools/widget/reg_view.cpp
|
src/core/devtools/widget/reg_view.cpp
|
||||||
src/core/devtools/widget/reg_view.h
|
src/core/devtools/widget/reg_view.h
|
||||||
|
src/core/devtools/widget/shader_list.cpp
|
||||||
|
src/core/devtools/widget/shader_list.h
|
||||||
src/core/devtools/widget/text_editor.cpp
|
src/core/devtools/widget/text_editor.cpp
|
||||||
src/core/devtools/widget/text_editor.h
|
src/core/devtools/widget/text_editor.h
|
||||||
)
|
)
|
||||||
@@ -436,7 +496,12 @@ set(COMMON src/common/logging/backend.cpp
|
|||||||
src/common/signal_context.h
|
src/common/signal_context.h
|
||||||
src/common/signal_context.cpp
|
src/common/signal_context.cpp
|
||||||
src/common/singleton.h
|
src/common/singleton.h
|
||||||
|
src/common/slab_heap.h
|
||||||
src/common/slot_vector.h
|
src/common/slot_vector.h
|
||||||
|
src/common/spin_lock.cpp
|
||||||
|
src/common/spin_lock.h
|
||||||
|
src/common/stb.cpp
|
||||||
|
src/common/stb.h
|
||||||
src/common/string_util.cpp
|
src/common/string_util.cpp
|
||||||
src/common/string_util.h
|
src/common/string_util.h
|
||||||
src/common/thread.cpp
|
src/common/thread.cpp
|
||||||
@@ -444,6 +509,7 @@ set(COMMON src/common/logging/backend.cpp
|
|||||||
src/common/types.h
|
src/common/types.h
|
||||||
src/common/uint128.h
|
src/common/uint128.h
|
||||||
src/common/unique_function.h
|
src/common/unique_function.h
|
||||||
|
src/common/va_ctx.h
|
||||||
src/common/version.h
|
src/common/version.h
|
||||||
src/common/ntapi.h
|
src/common/ntapi.h
|
||||||
src/common/ntapi.cpp
|
src/common/ntapi.cpp
|
||||||
@@ -468,6 +534,12 @@ set(CORE src/core/aerolib/stubs.cpp
|
|||||||
src/core/crypto/crypto.cpp
|
src/core/crypto/crypto.cpp
|
||||||
src/core/crypto/crypto.h
|
src/core/crypto/crypto.h
|
||||||
src/core/crypto/keys.h
|
src/core/crypto/keys.h
|
||||||
|
src/core/devices/base_device.cpp
|
||||||
|
src/core/devices/base_device.h
|
||||||
|
src/core/devices/ioccom.h
|
||||||
|
src/core/devices/logger.cpp
|
||||||
|
src/core/devices/logger.h
|
||||||
|
src/core/devices/nop_device.h
|
||||||
src/core/file_format/pfs.h
|
src/core/file_format/pfs.h
|
||||||
src/core/file_format/pkg.cpp
|
src/core/file_format/pkg.cpp
|
||||||
src/core/file_format/pkg.h
|
src/core/file_format/pkg.h
|
||||||
@@ -491,9 +563,10 @@ set(CORE src/core/aerolib/stubs.cpp
|
|||||||
src/core/loader/elf.h
|
src/core/loader/elf.h
|
||||||
src/core/loader/symbols_resolver.h
|
src/core/loader/symbols_resolver.h
|
||||||
src/core/loader/symbols_resolver.cpp
|
src/core/loader/symbols_resolver.cpp
|
||||||
src/core/libraries/error_codes.h
|
|
||||||
src/core/libraries/libs.h
|
src/core/libraries/libs.h
|
||||||
src/core/libraries/libs.cpp
|
src/core/libraries/libs.cpp
|
||||||
|
${AJM_LIB}
|
||||||
|
${AVPLAYER_LIB}
|
||||||
${AUDIO_LIB}
|
${AUDIO_LIB}
|
||||||
${GNM_LIB}
|
${GNM_LIB}
|
||||||
${KERNEL_LIB}
|
${KERNEL_LIB}
|
||||||
@@ -504,6 +577,7 @@ set(CORE src/core/aerolib/stubs.cpp
|
|||||||
${VIDEOOUT_LIB}
|
${VIDEOOUT_LIB}
|
||||||
${NP_LIBS}
|
${NP_LIBS}
|
||||||
${PNG_LIB}
|
${PNG_LIB}
|
||||||
|
${JPEG_LIB}
|
||||||
${PLAYGO_LIB}
|
${PLAYGO_LIB}
|
||||||
${RANDOM_LIB}
|
${RANDOM_LIB}
|
||||||
${USBD_LIB}
|
${USBD_LIB}
|
||||||
@@ -523,10 +597,10 @@ set(CORE src/core/aerolib/stubs.cpp
|
|||||||
src/core/platform.h
|
src/core/platform.h
|
||||||
src/core/signals.cpp
|
src/core/signals.cpp
|
||||||
src/core/signals.h
|
src/core/signals.h
|
||||||
|
src/core/thread.cpp
|
||||||
|
src/core/thread.h
|
||||||
src/core/tls.cpp
|
src/core/tls.cpp
|
||||||
src/core/tls.h
|
src/core/tls.h
|
||||||
src/core/virtual_memory.cpp
|
|
||||||
src/core/virtual_memory.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if (ARCHITECTURE STREQUAL "x86_64")
|
if (ARCHITECTURE STREQUAL "x86_64")
|
||||||
@@ -557,6 +631,8 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h
|
|||||||
src/shader_recompiler/backend/spirv/emit_spirv_instructions.h
|
src/shader_recompiler/backend/spirv/emit_spirv_instructions.h
|
||||||
src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
|
src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
|
||||||
src/shader_recompiler/backend/spirv/emit_spirv_logical.cpp
|
src/shader_recompiler/backend/spirv/emit_spirv_logical.cpp
|
||||||
|
src/shader_recompiler/backend/spirv/emit_spirv_quad_rect.cpp
|
||||||
|
src/shader_recompiler/backend/spirv/emit_spirv_quad_rect.h
|
||||||
src/shader_recompiler/backend/spirv/emit_spirv_select.cpp
|
src/shader_recompiler/backend/spirv/emit_spirv_select.cpp
|
||||||
src/shader_recompiler/backend/spirv/emit_spirv_shared_memory.cpp
|
src/shader_recompiler/backend/spirv/emit_spirv_shared_memory.cpp
|
||||||
src/shader_recompiler/backend/spirv/emit_spirv_special.cpp
|
src/shader_recompiler/backend/spirv/emit_spirv_special.cpp
|
||||||
@@ -590,12 +666,15 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h
|
|||||||
src/shader_recompiler/frontend/structured_control_flow.h
|
src/shader_recompiler/frontend/structured_control_flow.h
|
||||||
src/shader_recompiler/ir/passes/constant_propagation_pass.cpp
|
src/shader_recompiler/ir/passes/constant_propagation_pass.cpp
|
||||||
src/shader_recompiler/ir/passes/dead_code_elimination_pass.cpp
|
src/shader_recompiler/ir/passes/dead_code_elimination_pass.cpp
|
||||||
|
src/shader_recompiler/ir/passes/flatten_extended_userdata_pass.cpp
|
||||||
|
src/shader_recompiler/ir/passes/hull_shader_transform.cpp
|
||||||
src/shader_recompiler/ir/passes/identity_removal_pass.cpp
|
src/shader_recompiler/ir/passes/identity_removal_pass.cpp
|
||||||
src/shader_recompiler/ir/passes/ir_passes.h
|
src/shader_recompiler/ir/passes/ir_passes.h
|
||||||
src/shader_recompiler/ir/passes/lower_shared_mem_to_registers.cpp
|
src/shader_recompiler/ir/passes/lower_shared_mem_to_registers.cpp
|
||||||
src/shader_recompiler/ir/passes/resource_tracking_pass.cpp
|
src/shader_recompiler/ir/passes/resource_tracking_pass.cpp
|
||||||
src/shader_recompiler/ir/passes/ring_access_elimination.cpp
|
src/shader_recompiler/ir/passes/ring_access_elimination.cpp
|
||||||
src/shader_recompiler/ir/passes/shader_info_collection_pass.cpp
|
src/shader_recompiler/ir/passes/shader_info_collection_pass.cpp
|
||||||
|
src/shader_recompiler/ir/passes/shared_memory_barrier_pass.cpp
|
||||||
src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp
|
src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp
|
||||||
src/shader_recompiler/ir/abstract_syntax_list.h
|
src/shader_recompiler/ir/abstract_syntax_list.h
|
||||||
src/shader_recompiler/ir/attribute.cpp
|
src/shader_recompiler/ir/attribute.cpp
|
||||||
@@ -609,6 +688,8 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h
|
|||||||
src/shader_recompiler/ir/opcodes.cpp
|
src/shader_recompiler/ir/opcodes.cpp
|
||||||
src/shader_recompiler/ir/opcodes.h
|
src/shader_recompiler/ir/opcodes.h
|
||||||
src/shader_recompiler/ir/opcodes.inc
|
src/shader_recompiler/ir/opcodes.inc
|
||||||
|
src/shader_recompiler/ir/patch.cpp
|
||||||
|
src/shader_recompiler/ir/patch.h
|
||||||
src/shader_recompiler/ir/post_order.cpp
|
src/shader_recompiler/ir/post_order.cpp
|
||||||
src/shader_recompiler/ir/post_order.h
|
src/shader_recompiler/ir/post_order.h
|
||||||
src/shader_recompiler/ir/program.cpp
|
src/shader_recompiler/ir/program.cpp
|
||||||
@@ -638,8 +719,6 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp
|
|||||||
src/video_core/buffer_cache/word_manager.h
|
src/video_core/buffer_cache/word_manager.h
|
||||||
src/video_core/renderer_vulkan/liverpool_to_vk.cpp
|
src/video_core/renderer_vulkan/liverpool_to_vk.cpp
|
||||||
src/video_core/renderer_vulkan/liverpool_to_vk.h
|
src/video_core/renderer_vulkan/liverpool_to_vk.h
|
||||||
src/video_core/renderer_vulkan/renderer_vulkan.cpp
|
|
||||||
src/video_core/renderer_vulkan/renderer_vulkan.h
|
|
||||||
src/video_core/renderer_vulkan/vk_common.cpp
|
src/video_core/renderer_vulkan/vk_common.cpp
|
||||||
src/video_core/renderer_vulkan/vk_common.h
|
src/video_core/renderer_vulkan/vk_common.h
|
||||||
src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
|
src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
|
||||||
@@ -658,12 +737,16 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp
|
|||||||
src/video_core/renderer_vulkan/vk_pipeline_common.h
|
src/video_core/renderer_vulkan/vk_pipeline_common.h
|
||||||
src/video_core/renderer_vulkan/vk_platform.cpp
|
src/video_core/renderer_vulkan/vk_platform.cpp
|
||||||
src/video_core/renderer_vulkan/vk_platform.h
|
src/video_core/renderer_vulkan/vk_platform.h
|
||||||
|
src/video_core/renderer_vulkan/vk_presenter.cpp
|
||||||
|
src/video_core/renderer_vulkan/vk_presenter.h
|
||||||
src/video_core/renderer_vulkan/vk_rasterizer.cpp
|
src/video_core/renderer_vulkan/vk_rasterizer.cpp
|
||||||
src/video_core/renderer_vulkan/vk_rasterizer.h
|
src/video_core/renderer_vulkan/vk_rasterizer.h
|
||||||
src/video_core/renderer_vulkan/vk_resource_pool.cpp
|
src/video_core/renderer_vulkan/vk_resource_pool.cpp
|
||||||
src/video_core/renderer_vulkan/vk_resource_pool.h
|
src/video_core/renderer_vulkan/vk_resource_pool.h
|
||||||
src/video_core/renderer_vulkan/vk_scheduler.cpp
|
src/video_core/renderer_vulkan/vk_scheduler.cpp
|
||||||
src/video_core/renderer_vulkan/vk_scheduler.h
|
src/video_core/renderer_vulkan/vk_scheduler.h
|
||||||
|
src/video_core/renderer_vulkan/vk_shader_hle.cpp
|
||||||
|
src/video_core/renderer_vulkan/vk_shader_hle.h
|
||||||
src/video_core/renderer_vulkan/vk_shader_util.cpp
|
src/video_core/renderer_vulkan/vk_shader_util.cpp
|
||||||
src/video_core/renderer_vulkan/vk_shader_util.h
|
src/video_core/renderer_vulkan/vk_shader_util.h
|
||||||
src/video_core/renderer_vulkan/vk_swapchain.cpp
|
src/video_core/renderer_vulkan/vk_swapchain.cpp
|
||||||
@@ -718,6 +801,12 @@ set(EMULATOR src/emulator.cpp
|
|||||||
if(ENABLE_QT_GUI)
|
if(ENABLE_QT_GUI)
|
||||||
qt_add_resources(RESOURCE_FILES src/shadps4.qrc)
|
qt_add_resources(RESOURCE_FILES src/shadps4.qrc)
|
||||||
|
|
||||||
|
if (ENABLE_UPDATER)
|
||||||
|
set(UPDATER src/qt_gui/check_update.cpp
|
||||||
|
src/qt_gui/check_update.h
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(QT_GUI src/qt_gui/about_dialog.cpp
|
set(QT_GUI src/qt_gui/about_dialog.cpp
|
||||||
src/qt_gui/about_dialog.h
|
src/qt_gui/about_dialog.h
|
||||||
src/qt_gui/about_dialog.ui
|
src/qt_gui/about_dialog.ui
|
||||||
@@ -725,8 +814,8 @@ set(QT_GUI src/qt_gui/about_dialog.cpp
|
|||||||
src/qt_gui/background_music_player.h
|
src/qt_gui/background_music_player.h
|
||||||
src/qt_gui/cheats_patches.cpp
|
src/qt_gui/cheats_patches.cpp
|
||||||
src/qt_gui/cheats_patches.h
|
src/qt_gui/cheats_patches.h
|
||||||
src/qt_gui/check_update.cpp
|
src/qt_gui/compatibility_info.cpp
|
||||||
src/qt_gui/check_update.h
|
src/qt_gui/compatibility_info.h
|
||||||
src/qt_gui/main_window_ui.h
|
src/qt_gui/main_window_ui.h
|
||||||
src/qt_gui/main_window.cpp
|
src/qt_gui/main_window.cpp
|
||||||
src/qt_gui/main_window.h
|
src/qt_gui/main_window.h
|
||||||
@@ -757,6 +846,7 @@ set(QT_GUI src/qt_gui/about_dialog.cpp
|
|||||||
${EMULATOR}
|
${EMULATOR}
|
||||||
${RESOURCE_FILES}
|
${RESOURCE_FILES}
|
||||||
${TRANSLATIONS}
|
${TRANSLATIONS}
|
||||||
|
${UPDATER}
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -793,20 +883,33 @@ endif()
|
|||||||
|
|
||||||
create_target_directory_groups(shadps4)
|
create_target_directory_groups(shadps4)
|
||||||
|
|
||||||
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui gcn half::half)
|
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui gcn half::half ZLIB::ZLIB PNG::PNG)
|
||||||
target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::SPIRV glslang::glslang SDL3::SDL3 pugixml::pugixml)
|
target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator LibAtrac9 sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::glslang SDL3::SDL3 pugixml::pugixml stb::headers)
|
||||||
|
|
||||||
target_compile_definitions(shadps4 PRIVATE IMGUI_USER_CONFIG="imgui/imgui_config.h")
|
target_compile_definitions(shadps4 PRIVATE IMGUI_USER_CONFIG="imgui/imgui_config.h")
|
||||||
target_compile_definitions(Dear_ImGui PRIVATE IMGUI_USER_CONFIG="${PROJECT_SOURCE_DIR}/src/imgui/imgui_config.h")
|
target_compile_definitions(Dear_ImGui PRIVATE IMGUI_USER_CONFIG="${PROJECT_SOURCE_DIR}/src/imgui/imgui_config.h")
|
||||||
|
|
||||||
|
if (ENABLE_DISCORD_RPC)
|
||||||
|
target_compile_definitions(shadps4 PRIVATE ENABLE_DISCORD_RPC)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Optional due to https://github.com/shadps4-emu/shadPS4/issues/1704
|
||||||
|
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND ENABLE_USERFAULTFD)
|
||||||
|
target_compile_definitions(shadps4 PRIVATE ENABLE_USERFAULTFD)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
option(USE_SYSTEM_VULKAN_LOADER "Enables using the system Vulkan loader instead of directly linking with MoltenVK. Useful for loading validation layers." OFF)
|
if (ENABLE_QT_GUI)
|
||||||
if (USE_SYSTEM_VULKAN_LOADER)
|
# Include MoltenVK in the app bundle, along with an ICD file so it can be found by the system Vulkan loader if used for loading layers.
|
||||||
target_compile_definitions(shadps4 PRIVATE USE_SYSTEM_VULKAN_LOADER=1)
|
target_sources(shadps4 PRIVATE externals/MoltenVK/MoltenVK_icd.json)
|
||||||
|
set_source_files_properties(externals/MoltenVK/MoltenVK_icd.json
|
||||||
|
PROPERTIES MACOSX_PACKAGE_LOCATION Resources/vulkan/icd.d)
|
||||||
|
add_custom_command(TARGET shadps4 POST_BUILD
|
||||||
|
COMMAND cmake -E copy $<TARGET_LINKER_FILE:MoltenVK> $<TARGET_BUNDLE_DIR:shadps4>/Contents/Frameworks/libMoltenVK.dylib)
|
||||||
|
set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path/../Frameworks")
|
||||||
else()
|
else()
|
||||||
# Link MoltenVK for Vulkan support
|
# For non-bundled SDL build, just do a normal library link.
|
||||||
find_library(MOLTENVK MoltenVK REQUIRED)
|
target_link_libraries(shadps4 PRIVATE MoltenVK)
|
||||||
target_link_libraries(shadps4 PRIVATE ${MOLTENVK})
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (ARCHITECTURE STREQUAL "x86_64")
|
if (ARCHITECTURE STREQUAL "x86_64")
|
||||||
@@ -823,14 +926,17 @@ if (NOT ENABLE_QT_GUI)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND MSVC)
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND MSVC)
|
||||||
target_link_libraries(shadps4 PRIVATE cryptoppwin zlib-ng::zlib)
|
target_link_libraries(shadps4 PRIVATE cryptoppwin)
|
||||||
else()
|
else()
|
||||||
target_link_libraries(shadps4 PRIVATE cryptopp::cryptopp zlib-ng::zlib)
|
target_link_libraries(shadps4 PRIVATE cryptopp::cryptopp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (ENABLE_QT_GUI)
|
if (ENABLE_QT_GUI)
|
||||||
target_link_libraries(shadps4 PRIVATE Qt6::Widgets Qt6::Concurrent Qt6::Network Qt6::Multimedia)
|
target_link_libraries(shadps4 PRIVATE Qt6::Widgets Qt6::Concurrent Qt6::Network Qt6::Multimedia)
|
||||||
add_definitions(-DENABLE_QT_GUI)
|
add_definitions(-DENABLE_QT_GUI)
|
||||||
|
if (ENABLE_UPDATER)
|
||||||
|
add_definitions(-DENABLE_UPDATER)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
@@ -894,7 +1000,10 @@ if (ENABLE_QT_GUI)
|
|||||||
set_target_properties(shadps4 PROPERTIES
|
set_target_properties(shadps4 PROPERTIES
|
||||||
# WIN32_EXECUTABLE ON
|
# WIN32_EXECUTABLE ON
|
||||||
MACOSX_BUNDLE ON
|
MACOSX_BUNDLE ON
|
||||||
MACOSX_BUNDLE_ICON_FILE shadPS4.icns)
|
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/dist/MacOSBundleInfo.plist.in"
|
||||||
|
MACOSX_BUNDLE_ICON_FILE "shadPS4.icns"
|
||||||
|
MACOSX_BUNDLE_SHORT_VERSION_STRING "0.4.1"
|
||||||
|
)
|
||||||
|
|
||||||
set_source_files_properties(src/images/shadPS4.icns PROPERTIES
|
set_source_files_properties(src/images/shadPS4.icns PROPERTIES
|
||||||
MACOSX_PACKAGE_LOCATION Resources)
|
MACOSX_PACKAGE_LOCATION Resources)
|
||||||
@@ -916,6 +1025,9 @@ endif()
|
|||||||
install(TARGETS shadps4 BUNDLE DESTINATION .)
|
install(TARGETS shadps4 BUNDLE DESTINATION .)
|
||||||
|
|
||||||
if (ENABLE_QT_GUI AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
if (ENABLE_QT_GUI AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
install(FILES ".github/shadps4.desktop" DESTINATION "share/applications")
|
install(FILES "dist/net.shadps4.shadPS4.desktop" DESTINATION "share/applications")
|
||||||
install(FILES ".github/shadps4.png" DESTINATION "share/icons/hicolor/512x512/apps")
|
install(FILES "dist/net.shadps4.shadPS4.releases.xml" DESTINATION "share/metainfo/releases")
|
||||||
|
install(FILES "dist/net.shadps4.shadPS4.metainfo.xml" DESTINATION "share/metainfo")
|
||||||
|
install(FILES ".github/shadps4.png" DESTINATION "share/icons/hicolor/512x512/apps" RENAME "net.shadps4.shadPS4.png")
|
||||||
|
install(FILES "src/images/net.shadps4.shadPS4.svg" DESTINATION "share/icons/hicolor/scalable/apps")
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
59
README.md
59
README.md
@@ -76,35 +76,42 @@ For more information on how to test, debug and report issues with the emulator o
|
|||||||
|
|
||||||
# Keyboard mapping
|
# Keyboard mapping
|
||||||
|
|
||||||
|
| Button | Function |
|
||||||
|
|-------------|-------------|
|
||||||
|
F10 | FPS Counter
|
||||||
|
Ctrl+F10 | Video Debug Info
|
||||||
|
F11 | Fullscreen
|
||||||
|
F12 | Trigger RenderDoc Capture
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> Xbox and DualShock controllers work out of the box.
|
> Xbox and DualShock controllers work out of the box.
|
||||||
|
|
||||||
| Controller button | Keyboard equivelant |
|
| Controller button | Keyboard equivelant | Mac alternative |
|
||||||
|-------------|-------------|
|
|-------------|-------------|--------------|
|
||||||
LEFT AXIS UP | W |
|
LEFT AXIS UP | W | |
|
||||||
LEFT AXIS DOWN | S |
|
LEFT AXIS DOWN | S | |
|
||||||
LEFT AXIS LEFT | A |
|
LEFT AXIS LEFT | A | |
|
||||||
LEFT AXIS RIGHT | D |
|
LEFT AXIS RIGHT | D | |
|
||||||
RIGHT AXIS UP | I |
|
RIGHT AXIS UP | I | |
|
||||||
RIGHT AXIS DOWN | K |
|
RIGHT AXIS DOWN | K | |
|
||||||
RIGHT AXIS LEFT | J |
|
RIGHT AXIS LEFT | J | |
|
||||||
RIGHT AXIS RIGHT | L |
|
RIGHT AXIS RIGHT | L | |
|
||||||
TRIANGLE | Numpad 8 |
|
TRIANGLE | Numpad 8 | C |
|
||||||
CIRCLE | Numpad 6 |
|
CIRCLE | Numpad 6 | B |
|
||||||
CROSS | Numpad 2 |
|
CROSS | Numpad 2 | N |
|
||||||
SQUARE | Numpad 4 |
|
SQUARE | Numpad 4 | V |
|
||||||
PAD UP | UP |
|
PAD UP | UP | |
|
||||||
PAD DOWN | DOWN |
|
PAD DOWN | DOWN | |
|
||||||
PAD LEFT | LEFT |
|
PAD LEFT | LEFT | |
|
||||||
PAD RIGHT | RIGHT |
|
PAD RIGHT | RIGHT | |
|
||||||
OPTIONS | RETURN |
|
OPTIONS | RETURN | |
|
||||||
BACK BUTTON / TOUCH PAD | SPACE |
|
BACK BUTTON / TOUCH PAD | SPACE | |
|
||||||
L1 | Q |
|
L1 | Q | |
|
||||||
R1 | U |
|
R1 | U | |
|
||||||
L2 | E |
|
L2 | E | |
|
||||||
R2 | O |
|
R2 | O | |
|
||||||
L3 | X |
|
L3 | X | |
|
||||||
R3 | M |
|
R3 | M | |
|
||||||
|
|
||||||
# Main team
|
# Main team
|
||||||
|
|
||||||
|
|||||||
18
REUSE.toml
18
REUSE.toml
@@ -5,15 +5,21 @@ path = [
|
|||||||
"REUSE.toml",
|
"REUSE.toml",
|
||||||
"CMakeSettings.json",
|
"CMakeSettings.json",
|
||||||
".github/FUNDING.yml",
|
".github/FUNDING.yml",
|
||||||
".github/shadps4.desktop",
|
|
||||||
".github/shadps4.png",
|
".github/shadps4.png",
|
||||||
".gitmodules",
|
".gitmodules",
|
||||||
"documents/changelog.txt",
|
"dist/MacOSBundleInfo.plist.in",
|
||||||
|
"dist/net.shadps4.shadPS4.desktop",
|
||||||
|
"dist/net.shadps4.shadPS4_metadata.pot",
|
||||||
|
"dist/net.shadps4.shadPS4.metainfo.xml",
|
||||||
|
"dist/net.shadps4.shadPS4.releases.xml",
|
||||||
|
"documents/changelog.md",
|
||||||
"documents/Quickstart/2.png",
|
"documents/Quickstart/2.png",
|
||||||
"documents/Screenshots/*",
|
"documents/Screenshots/*",
|
||||||
|
"externals/MoltenVK/MoltenVK_icd.json",
|
||||||
"scripts/ps4_names.txt",
|
"scripts/ps4_names.txt",
|
||||||
"src/images/about_icon.png",
|
"src/images/about_icon.png",
|
||||||
"src/images/controller_icon.png",
|
"src/images/controller_icon.png",
|
||||||
|
"src/images/discord.png",
|
||||||
"src/images/dump_icon.png",
|
"src/images/dump_icon.png",
|
||||||
"src/images/exit_icon.png",
|
"src/images/exit_icon.png",
|
||||||
"src/images/file_icon.png",
|
"src/images/file_icon.png",
|
||||||
@@ -24,8 +30,10 @@ path = [
|
|||||||
"src/images/flag_us.png",
|
"src/images/flag_us.png",
|
||||||
"src/images/flag_world.png",
|
"src/images/flag_world.png",
|
||||||
"src/images/folder_icon.png",
|
"src/images/folder_icon.png",
|
||||||
|
"src/images/github.png",
|
||||||
"src/images/grid_icon.png",
|
"src/images/grid_icon.png",
|
||||||
"src/images/iconsize_icon.png",
|
"src/images/iconsize_icon.png",
|
||||||
|
"src/images/ko-fi.png",
|
||||||
"src/images/list_icon.png",
|
"src/images/list_icon.png",
|
||||||
"src/images/list_mode_icon.png",
|
"src/images/list_mode_icon.png",
|
||||||
"src/images/pause_icon.png",
|
"src/images/pause_icon.png",
|
||||||
@@ -33,10 +41,14 @@ path = [
|
|||||||
"src/images/refresh_icon.png",
|
"src/images/refresh_icon.png",
|
||||||
"src/images/settings_icon.png",
|
"src/images/settings_icon.png",
|
||||||
"src/images/stop_icon.png",
|
"src/images/stop_icon.png",
|
||||||
|
"src/images/utils_icon.png",
|
||||||
"src/images/shadPS4.icns",
|
"src/images/shadPS4.icns",
|
||||||
"src/images/shadps4.ico",
|
"src/images/shadps4.ico",
|
||||||
|
"src/images/net.shadps4.shadPS4.svg",
|
||||||
"src/images/themes_icon.png",
|
"src/images/themes_icon.png",
|
||||||
"src/images/update_icon.png",
|
"src/images/update_icon.png",
|
||||||
|
"src/images/youtube.png",
|
||||||
|
"src/images/website.png",
|
||||||
"src/shadps4.qrc",
|
"src/shadps4.qrc",
|
||||||
"src/shadps4.rc",
|
"src/shadps4.rc",
|
||||||
]
|
]
|
||||||
@@ -57,7 +69,7 @@ SPDX-FileCopyrightText = "2019-2024 Baldur Karlsson"
|
|||||||
SPDX-License-Identifier = "MIT"
|
SPDX-License-Identifier = "MIT"
|
||||||
|
|
||||||
[[annotations]]
|
[[annotations]]
|
||||||
path = "externals/stb_image.h"
|
path = "externals/stb/**"
|
||||||
precedence = "aggregate"
|
precedence = "aggregate"
|
||||||
SPDX-FileCopyrightText = "2017 Sean Barrett"
|
SPDX-FileCopyrightText = "2017 Sean Barrett"
|
||||||
SPDX-License-Identifier = "MIT"
|
SPDX-License-Identifier = "MIT"
|
||||||
|
|||||||
19
cmake/Findstb.cmake
Normal file
19
cmake/Findstb.cmake
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
find_path(stb_image_INCLUDE_DIR stb_image.h PATH_SUFFIXES stb)
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(stb
|
||||||
|
REQUIRED_VARS stb_image_INCLUDE_DIR
|
||||||
|
)
|
||||||
|
|
||||||
|
if (stb_FOUND AND NOT TARGET stb::headers)
|
||||||
|
add_library(stb::headers INTERFACE IMPORTED)
|
||||||
|
set_property(TARGET stb::headers PROPERTY
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES
|
||||||
|
"${stb_image_INCLUDE_DIR}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
mark_as_advanced(stb_image_INCLUDE_DIR)
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
find_package(PkgConfig QUIET)
|
|
||||||
pkg_search_module(ZLIB_NG QUIET IMPORTED_TARGET zlib-ng)
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
find_package_handle_standard_args(zlib-ng
|
|
||||||
REQUIRED_VARS ZLIB_NG_LINK_LIBRARIES
|
|
||||||
VERSION_VAR ZLIB_NG_VERSION
|
|
||||||
)
|
|
||||||
|
|
||||||
if (zlib-ng_FOUND AND NOT TARGET zlib-ng::zlib)
|
|
||||||
add_library(zlib-ng::zlib ALIAS PkgConfig::ZLIB_NG)
|
|
||||||
endif()
|
|
||||||
46
dist/MacOSBundleInfo.plist.in
vendored
Normal file
46
dist/MacOSBundleInfo.plist.in
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>shadps4</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>com.shadps4-emu.shadps4</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>shadps4</string>
|
||||||
|
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1.0.0</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
|
||||||
|
|
||||||
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
<string>${CMAKE_OSX_DEPLOYMENT_TARGET}</string>
|
||||||
|
<key>LSApplicationCategoryType</key>
|
||||||
|
<string>public.app-category.games</string>
|
||||||
|
<key>GCSupportsGameMode</key>
|
||||||
|
<true/>
|
||||||
|
|
||||||
|
<key>NSHumanReadableCopyright</key>
|
||||||
|
<string></string>
|
||||||
|
|
||||||
|
<key>CFBundleIconFile</key>
|
||||||
|
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
|
||||||
|
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleAllowMixedLocalizations</key>
|
||||||
|
<true/>
|
||||||
|
|
||||||
|
<key>NSPrincipalClass</key>
|
||||||
|
<string>NSApplication</string>
|
||||||
|
|
||||||
|
<key>NSSupportsAutomaticGraphicsSwitching</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Name=Shadps4
|
Name=shadPS4
|
||||||
Exec=shadps4
|
Exec=shadps4
|
||||||
Terminal=false
|
Terminal=false
|
||||||
Type=Application
|
Type=Application
|
||||||
Icon=shadps4
|
Icon=net.shadps4.shadPS4
|
||||||
Comment=shadps4 emulator
|
Comment=PlayStation 4 emulator
|
||||||
Categories=Game;
|
Categories=Game;
|
||||||
StartupWMClass=shadps4;
|
StartupWMClass=shadps4;
|
||||||
63
dist/net.shadps4.shadPS4.metainfo.xml
vendored
Normal file
63
dist/net.shadps4.shadPS4.metainfo.xml
vendored
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<component type="desktop-application">
|
||||||
|
<id translate="no">net.shadps4.shadPS4</id>
|
||||||
|
<name translate="no">shadPS4</name>
|
||||||
|
<developer id="net.shadps4.shadPS4">
|
||||||
|
<name>shadPS4 Contributors</name>
|
||||||
|
<url translate="no">https://github.com/shadps4-emu/shadps4/graphs/contributors</url>
|
||||||
|
</developer>
|
||||||
|
<summary>PS4 Emulator</summary>
|
||||||
|
<metadata_license translate="no">CC0-1.0</metadata_license>
|
||||||
|
<project_license translate="no">GPL-2.0</project_license>
|
||||||
|
<launchable type="desktop-id" translate="no">net.shadps4.shadPS4.desktop</launchable>
|
||||||
|
<url type="homepage" translate="no">https://shadps4.net/</url>
|
||||||
|
<description>
|
||||||
|
<p>shadPS4 is an early PlayStation 4 emulator for Windows, Linux and macOS written in C++.</p>
|
||||||
|
<p>The emulator is still early in development, so don't expect a flawless experience. Nonetheless, the emulator can already run a number of commercial games.</p>
|
||||||
|
</description>
|
||||||
|
<screenshots>
|
||||||
|
<screenshot type="default">
|
||||||
|
<image type="source" translate="no" >https://cdn.jsdelivr.net/gh/shadps4-emu/shadps4@main/documents/Screenshots/1.png</image>
|
||||||
|
<caption>Bloodborne</caption>
|
||||||
|
</screenshot>
|
||||||
|
<screenshot>
|
||||||
|
<image type="source" translate="no">https://cdn.jsdelivr.net/gh/shadps4-emu/shadps4@main/documents/Screenshots/2.png</image>
|
||||||
|
<caption>Hatsune Miku: Project DIVA Future Tone</caption>
|
||||||
|
</screenshot>
|
||||||
|
<screenshot>
|
||||||
|
<image type="source" translate="no">https://cdn.jsdelivr.net/gh/shadps4-emu/shadps4@main/documents/Screenshots/3.png</image>
|
||||||
|
<caption>Yakuza Kiwami</caption>
|
||||||
|
</screenshot>
|
||||||
|
<screenshot>
|
||||||
|
<image type="source" translate="no">https://cdn.jsdelivr.net/gh/shadps4-emu/shadps4@main/documents/Screenshots/4.png</image>
|
||||||
|
<caption>Persona 4 Golden</caption>
|
||||||
|
</screenshot>
|
||||||
|
</screenshots>
|
||||||
|
<categories>
|
||||||
|
<category translate="no">Game</category>
|
||||||
|
</categories>
|
||||||
|
<releases type="external" url="https://cdn.jsdelivr.net/gh/fpiesche/flatpak-builds/apps/net.shadps4.shadPS4/net.shadps4.shadPS4.releases.xml">
|
||||||
|
<release version="v.0.4.0" date="2024-11-03">
|
||||||
|
<description></description>
|
||||||
|
</release>
|
||||||
|
</releases>
|
||||||
|
<content_rating type="oars-1.1"/>
|
||||||
|
<supports>
|
||||||
|
<control translate="no">keyboard</control>
|
||||||
|
</supports>
|
||||||
|
<recommends>
|
||||||
|
<control translate="no">gamepad</control>
|
||||||
|
</recommends>
|
||||||
|
<requires>
|
||||||
|
<internet translate="no">offline-only</internet>
|
||||||
|
</requires>
|
||||||
|
<provides>
|
||||||
|
<binary translate="no">shadps4</binary>
|
||||||
|
</provides>
|
||||||
|
<keywords>
|
||||||
|
<keyword>emulator</keyword>
|
||||||
|
<keyword>emulation</keyword>
|
||||||
|
<keyword translate="no">playstation</keyword>
|
||||||
|
<keyword translate="no">ps4</keyword>
|
||||||
|
</keywords>
|
||||||
|
</component>
|
||||||
23
dist/net.shadps4.shadPS4.releases.xml
vendored
Normal file
23
dist/net.shadps4.shadPS4.releases.xml
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<releases>
|
||||||
|
<release version="0.4.0" date="2024-10-31">
|
||||||
|
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.4.0</url>
|
||||||
|
</release>
|
||||||
|
<release version="0.3.0" date="2024-09-23">
|
||||||
|
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.3.0</url>
|
||||||
|
</release>
|
||||||
|
<release version="0.2.0" date="2024-08-15">
|
||||||
|
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.2.0</url>
|
||||||
|
</release>
|
||||||
|
<release version="0.1.0" date="2024-07-01">
|
||||||
|
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/0.1.0</url>
|
||||||
|
</release>
|
||||||
|
<release version="0.0.3" date="2024-03-23">
|
||||||
|
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v0.0.3</url>
|
||||||
|
</release>
|
||||||
|
<release version="0.0.2" date="2023-10-21">
|
||||||
|
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v0.0.2</url>
|
||||||
|
</release>
|
||||||
|
<release version="0.0.1" date="2024-09-29">
|
||||||
|
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v0.0.1</url>
|
||||||
|
</release>
|
||||||
|
</releases>
|
||||||
65
dist/net.shadps4.shadPS4_metadata.pot
vendored
Normal file
65
dist/net.shadps4.shadPS4_metadata.pot
vendored
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"POT-Creation-Date: 2024-11-08 09:07+0000\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#. (itstool) path: component/name
|
||||||
|
#: ./net.shadps4.shadPS4.metainfo.xml:4
|
||||||
|
msgid "shadPS4"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. (itstool) path: developer/name
|
||||||
|
#: ./net.shadps4.shadPS4.metainfo.xml:6
|
||||||
|
msgid "shadPS4 Contributors"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. (itstool) path: component/summary
|
||||||
|
#: ./net.shadps4.shadPS4.metainfo.xml:9
|
||||||
|
msgid "PS4 Emulator"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. (itstool) path: description/p
|
||||||
|
#: ./net.shadps4.shadPS4.metainfo.xml:16
|
||||||
|
msgid "shadPS4 is an early PlayStation 4 emulator for Windows, Linux and macOS written in C++."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. (itstool) path: description/p
|
||||||
|
#: ./net.shadps4.shadPS4.metainfo.xml:17
|
||||||
|
msgid "The emulator is still early in development, so don't expect a flawless experience. Nonetheless, the emulator can already run a number of commercial games."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. (itstool) path: screenshot/caption
|
||||||
|
#: ./net.shadps4.shadPS4.metainfo.xml:22
|
||||||
|
msgid "Bloodborne"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. (itstool) path: screenshot/caption
|
||||||
|
#: ./net.shadps4.shadPS4.metainfo.xml:26
|
||||||
|
msgid "Hatsune Miku: Project DIVA Future Tone"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. (itstool) path: screenshot/caption
|
||||||
|
#: ./net.shadps4.shadPS4.metainfo.xml:30
|
||||||
|
msgid "Yakuza Kiwami"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. (itstool) path: screenshot/caption
|
||||||
|
#: ./net.shadps4.shadPS4.metainfo.xml:34
|
||||||
|
msgid "Persona 4 Golden"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. (itstool) path: keywords/keyword
|
||||||
|
#: ./net.shadps4.shadPS4.metainfo.xml:59
|
||||||
|
msgid "emulator"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. (itstool) path: keywords/keyword
|
||||||
|
#: ./net.shadps4.shadPS4.metainfo.xml:60
|
||||||
|
msgid "emulation"
|
||||||
|
msgstr ""
|
||||||
@@ -24,23 +24,21 @@ eval $(/opt/homebrew/bin/brew shellenv)
|
|||||||
brew install clang-format cmake
|
brew install clang-format cmake
|
||||||
```
|
```
|
||||||
|
|
||||||
Next, install x86_64 Homebrew and libraries.
|
Next, install x86_64 Qt. You can skip these steps and move on to **Cloning and compiling** if you do not intend to build the Qt GUI.
|
||||||
|
|
||||||
**If you are on an ARM Mac:**
|
**If you are on an ARM Mac:**
|
||||||
```
|
```
|
||||||
# Installs x86_64 Homebrew to /usr/local
|
# Installs x86_64 Homebrew to /usr/local
|
||||||
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)"
|
||||||
# Installs libraries.
|
# Installs libraries.
|
||||||
arch -x86_64 /usr/local/bin/brew install molten-vk qt@6
|
arch -x86_64 /usr/local/bin/brew install qt@6
|
||||||
```
|
```
|
||||||
|
|
||||||
**If you are on an x86_64 Mac:**
|
**If you are on an x86_64 Mac:**
|
||||||
```
|
```
|
||||||
brew install molten-vk qt@6
|
brew install qt@6
|
||||||
```
|
```
|
||||||
|
|
||||||
If you don't need the Qt GUI you can remove `qt@6` from the last command.
|
|
||||||
|
|
||||||
### Cloning and compiling:
|
### Cloning and compiling:
|
||||||
|
|
||||||
Clone the repository recursively:
|
Clone the repository recursively:
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ Once you are within the installer:
|
|||||||
|
|
||||||
Beware, this requires you to create a Qt account. If you do not want to do this, please follow the MSYS2/MinGW compilation method instead.
|
Beware, this requires you to create a Qt account. If you do not want to do this, please follow the MSYS2/MinGW compilation method instead.
|
||||||
|
|
||||||
1. Under the current, non beta version of Qt (at the time of writing 6.7.2), select the option `MSVC 2019 64-bit` or similar.
|
1. Under the current, non beta version of Qt (at the time of writing 6.7.3), select the option `MSVC 2022 64-bit` or similar.
|
||||||
If you are on Windows on ARM / Qualcomm Snapdragon Elite X, select `MSVC 2019 ARM64` instead.
|
If you are on Windows on ARM / Qualcomm Snapdragon Elite X, select `MSVC 2022 ARM64` instead.
|
||||||
|
|
||||||
Go through the installation normally. If you know what you are doing, you may unselect individual components that eat up too much disk space.
|
Go through the installation normally. If you know what you are doing, you may unselect individual components that eat up too much disk space.
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ Beware, this requires you to create a Qt account. If you do not want to do this,
|
|||||||
Once you are finished, you will have to configure Qt within Visual Studio:
|
Once you are finished, you will have to configure Qt within Visual Studio:
|
||||||
|
|
||||||
1. Tools -> Options -> Qt -> Versions
|
1. Tools -> Options -> Qt -> Versions
|
||||||
2. Add a new Qt version and navigate it to the correct folder. Should look like so: `C:\Qt\6.7.2\msvc2019_64`
|
2. Add a new Qt version and navigate it to the correct folder. Should look like so: `C:\Qt\6.7.3\msvc2022_64`
|
||||||
3. Enable the default checkmark on the new version you just created.
|
3. Enable the default checkmark on the new version you just created.
|
||||||
|
|
||||||
### (Prerequisite) Download [**Git for Windows**](https://git-scm.com/download/win)
|
### (Prerequisite) Download [**Git for Windows**](https://git-scm.com/download/win)
|
||||||
@@ -55,16 +55,16 @@ Go through the Git for Windows installation as normal
|
|||||||
3. If you want to build shadPS4 with the Qt Gui:
|
3. If you want to build shadPS4 with the Qt Gui:
|
||||||
1. Click x64-Clang-Release and select "Manage Configurations"
|
1. Click x64-Clang-Release and select "Manage Configurations"
|
||||||
2. Look for "CMake command arguments" and add to the text field
|
2. Look for "CMake command arguments" and add to the text field
|
||||||
`-DENABLE_QT_GUI=ON -DCMAKE_PREFIX_PATH=C:\Qt\6.7.2\msvc2019_64`
|
`-DENABLE_QT_GUI=ON -DCMAKE_PREFIX_PATH=C:\Qt\6.7.3\msvc2022_64`
|
||||||
(Change Qt path if you've installed it to non-default path)
|
(Change Qt path if you've installed it to non-default path)
|
||||||
3. Press CTRL+S to save and wait a moment for CMake generation
|
3. Press CTRL+S to save and wait a moment for CMake generation
|
||||||
4. Change the project to build to shadps4.exe
|
4. Change the project to build to shadps4.exe
|
||||||
5. Build -> Build All
|
5. Build -> Build All
|
||||||
|
|
||||||
Your shadps4.exe will be in `c:\path\to\source\Build\x64-Clang-Release\`
|
Your shadps4.exe will be in `C:\path\to\source\Build\x64-Clang-Release\`
|
||||||
|
|
||||||
To automatically populate the necessary files to run shadPS4.exe, run in a command prompt or terminal:
|
To automatically populate the necessary files to run shadPS4.exe, run in a command prompt or terminal:
|
||||||
`C:\Qt\6.7.2\msvc2019_64\bin\windeployqt.exe "c:\path\to\shadps4.exe"`
|
`C:\Qt\6.7.3\msvc2022_64\bin\windeployqt.exe "C:\path\to\shadps4.exe"`
|
||||||
(Change Qt path if you've installed it to non-default path)
|
(Change Qt path if you've installed it to non-default path)
|
||||||
|
|
||||||
## Option 2: MSYS2/MinGW
|
## Option 2: MSYS2/MinGW
|
||||||
@@ -79,7 +79,7 @@ Normal x86-based computers, follow:
|
|||||||
|
|
||||||
1. Open "MSYS2 MINGW64" from your new applications
|
1. Open "MSYS2 MINGW64" from your new applications
|
||||||
2. Run `pacman -Syu`, let it complete;
|
2. Run `pacman -Syu`, let it complete;
|
||||||
3. Run `pacman -S --needed git mingw-w64-x86_64-binutils mingw-w64-x86_64-clang mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-ffmpeg`
|
3. Run `pacman -S --needed git mingw-w64-x86_64-binutils mingw-w64-x86_64-clang mingw-w64-x86_64-cmake mingw-w64-x86_64-rapidjson mingw-w64-x86_64-ninja mingw-w64-x86_64-ffmpeg`
|
||||||
1. Optional (Qt only): run `pacman -S --needed mingw-w64-x86_64-qt6-base mingw-w64-x86_64-qt6-tools mingw-w64-x86_64-qt6-multimedia`
|
1. Optional (Qt only): run `pacman -S --needed mingw-w64-x86_64-qt6-base mingw-w64-x86_64-qt6-tools mingw-w64-x86_64-qt6-multimedia`
|
||||||
4. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4`
|
4. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4`
|
||||||
5. Run `cd shadPS4`
|
5. Run `cd shadPS4`
|
||||||
@@ -93,7 +93,7 @@ ARM64-based computers, follow:
|
|||||||
|
|
||||||
1. Open "MSYS2 CLANGARM64" from your new applications
|
1. Open "MSYS2 CLANGARM64" from your new applications
|
||||||
2. Run `pacman -Syu`, let it complete;
|
2. Run `pacman -Syu`, let it complete;
|
||||||
3. Run `pacman -S --needed git mingw-w64-clang-aarch64-binutils mingw-w64-clang-aarch64-clang mingw-w64-clang-aarch64-cmake mingw-w64-clang-aarch64-ninja mingw-w64-clang-aarch64-ffmpeg`
|
3. Run `pacman -S --needed git mingw-w64-clang-aarch64-binutils mingw-w64-clang-aarch64-clang mingw-w64-clang-aarch64-rapidjson mingw-w64-clang-aarch64-cmake mingw-w64-clang-aarch64-ninja mingw-w64-clang-aarch64-ffmpeg`
|
||||||
1. Optional (Qt only): run `pacman -S --needed mingw-w64-clang-aarch64-qt6-base mingw-w64-clang-aarch64-qt6-tools mingw-w64-clang-aarch64-qt6-multimedia`
|
1. Optional (Qt only): run `pacman -S --needed mingw-w64-clang-aarch64-qt6-base mingw-w64-clang-aarch64-qt6-tools mingw-w64-clang-aarch64-qt6-multimedia`
|
||||||
4. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4`
|
4. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4`
|
||||||
5. Run `cd shadPS4`
|
5. Run `cd shadPS4`
|
||||||
|
|||||||
@@ -1,3 +1,47 @@
|
|||||||
|
v0.4.0 31/10/2024 - codename divicius
|
||||||
|
=================
|
||||||
|
|
||||||
|
- Shader recompiler fixes
|
||||||
|
- Emulated support for cpus that doesn't have SSE4.2a (intel cpus)
|
||||||
|
- Frame graph + Precise 60 fps timing
|
||||||
|
- Save data: fix nullptr & concurrent file write
|
||||||
|
- Auto Update
|
||||||
|
- Error dialog implementation
|
||||||
|
- Swapchain recreation and window resizing
|
||||||
|
- Add playback of background/title music in game list
|
||||||
|
- Kernel: Quiet sceKernelWaitEventFlag error log on timeout
|
||||||
|
- Improve keyboard navigation in game list
|
||||||
|
- core/memory: Pooled memory implementation
|
||||||
|
- Fix PKG loading
|
||||||
|
- replace trophy xml assert with error
|
||||||
|
- Refactor audio handling with range checks, buffer threshold, and lock
|
||||||
|
- audio_core: Fix return value types and shift some error handling to library
|
||||||
|
- Devtools: PM4 Explorer
|
||||||
|
- Initial support of Geometry shaders
|
||||||
|
- Working touchpad support
|
||||||
|
- net: Stub sceNetErrnoLoc
|
||||||
|
- Add support to click touchpad using back button on non PS4/5 controllers
|
||||||
|
- Multiple Install Folders
|
||||||
|
- Using a more standard data directory for linux
|
||||||
|
- video_core: Implement sceGnmInsertPushColorMarker
|
||||||
|
- ime_dialog: Initial implementation
|
||||||
|
- Network libs fixes
|
||||||
|
- Use GetSystemTimePreciseAsFileTime to fix fps timing issues
|
||||||
|
- Added adaptive mutex initializer
|
||||||
|
- Small Np + trophy fixes
|
||||||
|
- Separate Updates from Game Folder
|
||||||
|
- Minor Fixes for Separate Update Folder
|
||||||
|
- AvPlayer: Do not align w/h to 16 with vdec2
|
||||||
|
- Improve sceSystemServiceReceiveEvent stub
|
||||||
|
- renderer_vulkan: Commize and adjust buffer bindings
|
||||||
|
- Add poll interval to libScePad
|
||||||
|
- Add more surface format mappings.
|
||||||
|
- vulkan: Report only missing format feature flags.
|
||||||
|
- IME implementation
|
||||||
|
- Videodec2 implementation
|
||||||
|
- path_util: Make sure macOS has current directory set and clean up path code.
|
||||||
|
- Load LLE modules from sys_modules/GAMEID folder
|
||||||
|
|
||||||
v0.3.0 23/09/2024 - codename broamic
|
v0.3.0 23/09/2024 - codename broamic
|
||||||
=================
|
=================
|
||||||
|
|
||||||
19
documents/patching-shader.md
Normal file
19
documents/patching-shader.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<!--
|
||||||
|
SPDX-FileCopyrightText: 2024 shadPS4 Emulator Project
|
||||||
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
-->
|
||||||
|
|
||||||
|
### Install Vulkan SDK and \*ensure `spirv-cross` and `glslc` are in PATH\*.
|
||||||
|
|
||||||
|
1. Enable `dumpShaders` in config.toml
|
||||||
|
|
||||||
|
2. Run `spirv-cross -V fs_0x000000.spv --output fs_0x000000.glsl` to decompile the SPIR-V IR to GLSL.
|
||||||
|
|
||||||
|
3. Edit the GLSL file as you wish
|
||||||
|
|
||||||
|
4. To compile back to SPIR-V, run (change the _**-fshader-stage**_ to correct stage):
|
||||||
|
`glslc --target-env=vulkan1.3 --target-spv=spv1.6 -fshader-stage=frag fs_0x000000.glsl -o fs_0x000000.spv`
|
||||||
|
|
||||||
|
5. Put the updated .spv file to `shader/patch` folder with the same name as the original shader
|
||||||
|
|
||||||
|
6. Enable `patchShaders` in config.toml
|
||||||
80
externals/CMakeLists.txt
vendored
80
externals/CMakeLists.txt
vendored
@@ -8,6 +8,9 @@ set_directory_properties(PROPERTIES
|
|||||||
SYSTEM ON
|
SYSTEM ON
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Set CMP0069 policy to "NEW" in order to ensure consistent behavior when building external targets with LTO enabled
|
||||||
|
set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
# Silence "deprecation" warnings
|
# Silence "deprecation" warnings
|
||||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS)
|
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS)
|
||||||
@@ -35,10 +38,11 @@ else()
|
|||||||
if (NOT TARGET cryptopp::cryptopp)
|
if (NOT TARGET cryptopp::cryptopp)
|
||||||
set(CRYPTOPP_INSTALL OFF)
|
set(CRYPTOPP_INSTALL OFF)
|
||||||
set(CRYPTOPP_BUILD_TESTING OFF)
|
set(CRYPTOPP_BUILD_TESTING OFF)
|
||||||
set(CRYPTOPP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/cryptopp/)
|
set(CRYPTOPP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/cryptopp)
|
||||||
add_subdirectory(cryptopp-cmake)
|
add_subdirectory(cryptopp-cmake)
|
||||||
file(COPY cryptopp DESTINATION cryptopp FILES_MATCHING PATTERN "*.h")
|
file(COPY cryptopp DESTINATION cryptopp FILES_MATCHING PATTERN "*.h")
|
||||||
target_include_directories(cryptopp INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/cryptopp")
|
# remove externals/cryptopp from include directories because it contains a conflicting zlib.h file
|
||||||
|
set_target_properties(cryptopp PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/cryptopp")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -47,14 +51,28 @@ if (NOT TARGET FFmpeg::ffmpeg)
|
|||||||
add_library(FFmpeg::ffmpeg ALIAS ffmpeg)
|
add_library(FFmpeg::ffmpeg ALIAS ffmpeg)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Zlib-Ng
|
# LibAtrac9
|
||||||
if (NOT TARGET zlib-ng::zlib)
|
file(GLOB LIBATRAC9_SOURCES LibAtrac9/C/src/*.c)
|
||||||
|
add_library(LibAtrac9 STATIC ${LIBATRAC9_SOURCES})
|
||||||
|
target_include_directories(LibAtrac9 INTERFACE LibAtrac9/C/src)
|
||||||
|
|
||||||
|
# zlib
|
||||||
|
if (NOT TARGET ZLIB::ZLIB)
|
||||||
set(ZLIB_ENABLE_TESTS OFF)
|
set(ZLIB_ENABLE_TESTS OFF)
|
||||||
set(WITH_GTEST OFF)
|
set(WITH_GTEST OFF)
|
||||||
set(WITH_NEW_STRATEGIES ON)
|
set(WITH_NEW_STRATEGIES ON)
|
||||||
set(WITH_NATIVE_INSTRUCTIONS ON)
|
set(WITH_NATIVE_INSTRUCTIONS ON)
|
||||||
add_subdirectory(zlib-ng)
|
set(ZLIB_COMPAT ON CACHE BOOL "" FORCE)
|
||||||
add_library(zlib-ng::zlib ALIAS zlib)
|
include(FetchContent)
|
||||||
|
FetchContent_Declare(
|
||||||
|
ZLIB
|
||||||
|
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/zlib-ng"
|
||||||
|
OVERRIDE_FIND_PACKAGE
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(ZLIB)
|
||||||
|
add_library(ZLIB::ZLIB ALIAS zlib)
|
||||||
|
# libpng expects this variable to exist after its find_package(ZLIB)
|
||||||
|
set(ZLIB_INCLUDE_DIRS "${FETCHCONTENT_BASE_DIR}/zlib-build")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# SDL3
|
# SDL3
|
||||||
@@ -92,7 +110,7 @@ if (NOT TARGET glslang::glslang)
|
|||||||
set(ENABLE_OPT OFF CACHE BOOL "")
|
set(ENABLE_OPT OFF CACHE BOOL "")
|
||||||
add_subdirectory(glslang)
|
add_subdirectory(glslang)
|
||||||
file(COPY glslang/SPIRV DESTINATION glslang/glslang FILES_MATCHING PATTERN "*.h")
|
file(COPY glslang/SPIRV DESTINATION glslang/glslang FILES_MATCHING PATTERN "*.h")
|
||||||
target_include_directories(SPIRV INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/glslang")
|
target_include_directories(glslang INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/glslang")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Robin-map
|
# Robin-map
|
||||||
@@ -148,13 +166,15 @@ if (NOT TARGET half::half)
|
|||||||
add_library(half::half ALIAS half)
|
add_library(half::half ALIAS half)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (APPLE)
|
# libpng
|
||||||
# date
|
if (NOT TARGET PNG::PNG)
|
||||||
if (NOT TARGET date::date-tz)
|
set(PNG_SHARED OFF CACHE BOOL "" FORCE)
|
||||||
option(BUILD_TZ_LIB "" ON)
|
set(PNG_STATIC ON CACHE BOOL "" FORCE)
|
||||||
option(USE_SYSTEM_TZ_DB "" ON)
|
set(PNG_TESTS OFF CACHE BOOL "" FORCE)
|
||||||
add_subdirectory(date)
|
set(PNG_TOOLS OFF CACHE BOOL "" FORCE)
|
||||||
endif()
|
set(SKIP_INSTALL_ALL OFF CACHE BOOL "" FORCE)
|
||||||
|
add_subdirectory(libpng)
|
||||||
|
add_library(PNG::PNG ALIAS png_static)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Dear ImGui
|
# Dear ImGui
|
||||||
@@ -169,11 +189,15 @@ add_library(Dear_ImGui
|
|||||||
target_include_directories(Dear_ImGui INTERFACE dear_imgui/)
|
target_include_directories(Dear_ImGui INTERFACE dear_imgui/)
|
||||||
|
|
||||||
# Tracy
|
# Tracy
|
||||||
option(TRACY_ENABLE "" ON)
|
if (CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||||
|
option(TRACY_ENABLE "" OFF)
|
||||||
|
else()
|
||||||
|
option(TRACY_ENABLE "" ON)
|
||||||
|
endif()
|
||||||
option(TRACY_NO_CRASH_HANDLER "" ON) # Otherwise texture cache exceptions will be treaten as a crash
|
option(TRACY_NO_CRASH_HANDLER "" ON) # Otherwise texture cache exceptions will be treaten as a crash
|
||||||
option(TRACY_ON_DEMAND "" ON)
|
option(TRACY_ON_DEMAND "" ON)
|
||||||
option(TRACY_NO_FRAME_IMAGE "" ON)
|
option(TRACY_NO_FRAME_IMAGE "" ON)
|
||||||
option(TRACY_FIBERS "" ON) # For AmdGpu frontend profiling
|
option(TRACY_FIBERS "" OFF) # For AmdGpu frontend profiling, disabled due to instability
|
||||||
option(TRACY_NO_SYSTEM_TRACING "" ON)
|
option(TRACY_NO_SYSTEM_TRACING "" ON)
|
||||||
option(TRACY_NO_CALLSTACK "" ON)
|
option(TRACY_NO_CALLSTACK "" ON)
|
||||||
option(TRACY_NO_CODE_TRANSFER "" ON)
|
option(TRACY_NO_CODE_TRANSFER "" ON)
|
||||||
@@ -190,9 +214,31 @@ endif()
|
|||||||
# Discord RPC
|
# Discord RPC
|
||||||
if (ENABLE_DISCORD_RPC)
|
if (ENABLE_DISCORD_RPC)
|
||||||
set(BUILD_EXAMPLES OFF)
|
set(BUILD_EXAMPLES OFF)
|
||||||
add_subdirectory(discord-rpc/)
|
add_subdirectory(discord-rpc)
|
||||||
target_include_directories(discord-rpc INTERFACE discord-rpc/include)
|
target_include_directories(discord-rpc INTERFACE discord-rpc/include)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# GCN Headers
|
# GCN Headers
|
||||||
add_subdirectory(gcn)
|
add_subdirectory(gcn)
|
||||||
|
|
||||||
|
# stb
|
||||||
|
if (NOT TARGET stb::headers)
|
||||||
|
add_library(stb INTERFACE)
|
||||||
|
target_include_directories(stb INTERFACE stb)
|
||||||
|
add_library(stb::headers ALIAS stb)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Apple-only dependencies
|
||||||
|
if (APPLE)
|
||||||
|
# date
|
||||||
|
if (NOT TARGET date::date-tz)
|
||||||
|
option(BUILD_TZ_LIB "" ON)
|
||||||
|
option(USE_SYSTEM_TZ_DB "" ON)
|
||||||
|
add_subdirectory(date)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# MoltenVK
|
||||||
|
if (NOT TARGET MoltenVK)
|
||||||
|
add_subdirectory(MoltenVK)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|||||||
1
externals/LibAtrac9
vendored
Submodule
1
externals/LibAtrac9
vendored
Submodule
Submodule externals/LibAtrac9 added at 9640129dc6
93
externals/MoltenVK/CMakeLists.txt
vendored
Normal file
93
externals/MoltenVK/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
# Prepare MoltenVK Git revision
|
||||||
|
find_package(Git)
|
||||||
|
if(GIT_FOUND)
|
||||||
|
execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD
|
||||||
|
OUTPUT_VARIABLE MVK_GIT_REV
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK
|
||||||
|
ERROR_QUIET
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
endif()
|
||||||
|
set(MVK_GENERATED_INCLUDES ${CMAKE_CURRENT_BINARY_DIR}/Generated)
|
||||||
|
file(WRITE ${MVK_GENERATED_INCLUDES}/mvkGitRevDerived.h "static const char* mvkRevString = \"${MVK_GIT_REV}\";")
|
||||||
|
message(STATUS "MoltenVK revision: ${MVK_GIT_REV}")
|
||||||
|
|
||||||
|
# Prepare MoltenVK version
|
||||||
|
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK/MoltenVK/MoltenVK/API/mvk_private_api.h MVK_PRIVATE_API)
|
||||||
|
string(REGEX MATCH "#define MVK_VERSION_MAJOR [0-9]+" MVK_VERSION_MAJOR_LINE "${MVK_PRIVATE_API}")
|
||||||
|
string(REGEX MATCH "[0-9]+" MVK_VERSION_MAJOR "${MVK_VERSION_MAJOR_LINE}")
|
||||||
|
string(REGEX MATCH "#define MVK_VERSION_MINOR [0-9]+" MVK_VERSION_MINOR_LINE "${MVK_PRIVATE_API}")
|
||||||
|
string(REGEX MATCH "[0-9]+" MVK_VERSION_MINOR "${MVK_VERSION_MINOR_LINE}")
|
||||||
|
string(REGEX MATCH "#define MVK_VERSION_PATCH [0-9]+" MVK_VERSION_PATCH_LINE "${MVK_PRIVATE_API}")
|
||||||
|
string(REGEX MATCH "[0-9]+" MVK_VERSION_PATCH "${MVK_VERSION_PATCH_LINE}")
|
||||||
|
set(MVK_VERSION "${MVK_VERSION_MAJOR}.${MVK_VERSION_MINOR}.${MVK_VERSION_PATCH}")
|
||||||
|
message(STATUS "MoltenVK version: ${MVK_VERSION}")
|
||||||
|
|
||||||
|
# Find required system libraries
|
||||||
|
find_library(APPKIT_LIBRARY AppKit REQUIRED)
|
||||||
|
find_library(FOUNDATION_LIBRARY Foundation REQUIRED)
|
||||||
|
find_library(IOKIT_LIBRARY IOKit REQUIRED)
|
||||||
|
find_library(IOSURFACE_LIBRARY IOSurface REQUIRED)
|
||||||
|
find_library(METAL_LIBRARY Metal REQUIRED)
|
||||||
|
find_library(QUARTZCORE_LIBRARY QuartzCore REQUIRED)
|
||||||
|
|
||||||
|
# cereal
|
||||||
|
option(SKIP_PORTABILITY_TEST "" ON)
|
||||||
|
option(BUILD_DOC "" OFF)
|
||||||
|
option(BUILD_SANDBOX "" OFF)
|
||||||
|
option(SKIP_PERFORMANCE_COMPARISON "" ON)
|
||||||
|
option(SPIRV_CROSS_SKIP_INSTALL "" ON)
|
||||||
|
add_subdirectory(cereal)
|
||||||
|
|
||||||
|
# SPIRV-Cross
|
||||||
|
option(SPIRV_CROSS_CLI "" OFF)
|
||||||
|
option(SPIRV_CROSS_ENABLE_TESTS "" OFF)
|
||||||
|
option(SPIRV_CROSS_ENABLE_HLSL "" OFF)
|
||||||
|
option(SPIRV_CROSS_ENABLE_CPP "" OFF)
|
||||||
|
option(SPIRV_CROSS_SKIP_INSTALL "" ON)
|
||||||
|
add_subdirectory(SPIRV-Cross)
|
||||||
|
|
||||||
|
# Common
|
||||||
|
set(MVK_COMMON_DIR ${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK/Common)
|
||||||
|
file(GLOB_RECURSE MVK_COMMON_SOURCES CONFIGURE_DEPENDS
|
||||||
|
${MVK_COMMON_DIR}/*.cpp
|
||||||
|
${MVK_COMMON_DIR}/*.m
|
||||||
|
${MVK_COMMON_DIR}/*.mm)
|
||||||
|
set(MVK_COMMON_INCLUDES ${MVK_COMMON_DIR})
|
||||||
|
|
||||||
|
add_library(MoltenVKCommon STATIC ${MVK_COMMON_SOURCES})
|
||||||
|
target_include_directories(MoltenVKCommon PUBLIC ${MVK_COMMON_INCLUDES})
|
||||||
|
target_compile_options(MoltenVKCommon PRIVATE -w)
|
||||||
|
|
||||||
|
# MoltenVKShaderConverter
|
||||||
|
set(MVK_SHADER_CONVERTER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK/MoltenVKShaderConverter)
|
||||||
|
file(GLOB_RECURSE MVK_SHADER_CONVERTER_SOURCES CONFIGURE_DEPENDS
|
||||||
|
${MVK_SHADER_CONVERTER_DIR}/MoltenVKShaderConverter/*.cpp
|
||||||
|
${MVK_SHADER_CONVERTER_DIR}/MoltenVKShaderConverter/*.m
|
||||||
|
${MVK_SHADER_CONVERTER_DIR}/MoltenVKShaderConverter/*.mm)
|
||||||
|
set(MVK_SHADER_CONVERTER_INCLUDES ${MVK_SHADER_CONVERTER_DIR} ${MVK_SHADER_CONVERTER_DIR}/include)
|
||||||
|
|
||||||
|
add_library(MoltenVKShaderConverter STATIC ${MVK_SHADER_CONVERTER_SOURCES})
|
||||||
|
target_include_directories(MoltenVKShaderConverter PUBLIC ${MVK_SHADER_CONVERTER_INCLUDES})
|
||||||
|
target_compile_options(MoltenVKShaderConverter PRIVATE -w)
|
||||||
|
target_link_libraries(MoltenVKShaderConverter PRIVATE spirv-cross-msl spirv-cross-reflect MoltenVKCommon)
|
||||||
|
target_compile_definitions(MoltenVKShaderConverter PRIVATE MVK_EXCLUDE_SPIRV_TOOLS=1)
|
||||||
|
|
||||||
|
# MoltenVK
|
||||||
|
set(MVK_DIR ${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK/MoltenVK)
|
||||||
|
file(GLOB_RECURSE MVK_SOURCES CONFIGURE_DEPENDS
|
||||||
|
${MVK_DIR}/MoltenVK/*.cpp
|
||||||
|
${MVK_DIR}/MoltenVK/*.m
|
||||||
|
${MVK_DIR}/MoltenVK/*.mm)
|
||||||
|
file(GLOB MVK_SRC_INCLUDES LIST_DIRECTORIES ON ${MVK_DIR}/MoltenVK/*)
|
||||||
|
set(MVK_INCLUDES ${MVK_SRC_INCLUDES} ${MVK_GENERATED_INCLUDES} ${MVK_DIR}/include)
|
||||||
|
|
||||||
|
add_library(MoltenVK SHARED ${MVK_SOURCES})
|
||||||
|
target_include_directories(MoltenVK PRIVATE ${MVK_INCLUDES})
|
||||||
|
target_compile_options(MoltenVK PRIVATE -w)
|
||||||
|
target_link_libraries(MoltenVK PRIVATE
|
||||||
|
${APPKIT_LIBRARY} ${FOUNDATION_LIBRARY} ${IOKIT_LIBRARY} ${IOSURFACE_LIBRARY} ${METAL_LIBRARY} ${QUARTZCORE_LIBRARY}
|
||||||
|
Vulkan::Headers cereal::cereal spirv-cross-msl MoltenVKCommon MoltenVKShaderConverter)
|
||||||
|
target_compile_definitions(MoltenVK PRIVATE MVK_FRAMEWORK_VERSION=${MVK_VERSION} MVK_USE_METAL_PRIVATE_API=1)
|
||||||
1
externals/MoltenVK/MoltenVK
vendored
Submodule
1
externals/MoltenVK/MoltenVK
vendored
Submodule
Submodule externals/MoltenVK/MoltenVK added at 5ad3ee5d2f
8
externals/MoltenVK/MoltenVK_icd.json
vendored
Normal file
8
externals/MoltenVK/MoltenVK_icd.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"file_format_version": "1.0.0",
|
||||||
|
"ICD": {
|
||||||
|
"library_path": "../../../Frameworks/libMoltenVK.dylib",
|
||||||
|
"api_version": "1.2.0",
|
||||||
|
"is_portability_driver": true
|
||||||
|
}
|
||||||
|
}
|
||||||
1
externals/MoltenVK/SPIRV-Cross
vendored
Submodule
1
externals/MoltenVK/SPIRV-Cross
vendored
Submodule
Submodule externals/MoltenVK/SPIRV-Cross added at 6173e24b31
1
externals/MoltenVK/cereal
vendored
Submodule
1
externals/MoltenVK/cereal
vendored
Submodule
Submodule externals/MoltenVK/cereal added at d1fcec807b
2
externals/date
vendored
2
externals/date
vendored
Submodule externals/date updated: dd8affc6de...28b7b23252
2
externals/ext-boost
vendored
2
externals/ext-boost
vendored
Submodule externals/ext-boost updated: f2474e1b58...ca6f230e67
2
externals/ffmpeg-core
vendored
2
externals/ffmpeg-core
vendored
Submodule externals/ffmpeg-core updated: e30b7d7fe2...27de97c826
2
externals/glslang
vendored
2
externals/glslang
vendored
Submodule externals/glslang updated: e61d7bb300...a0995c49eb
1
externals/libpng
vendored
Submodule
1
externals/libpng
vendored
Submodule
Submodule externals/libpng added at c1cc0f3f4c
2
externals/magic_enum
vendored
2
externals/magic_enum
vendored
Submodule externals/magic_enum updated: 126539e13c...1a1824df7a
2
externals/pugixml
vendored
2
externals/pugixml
vendored
Submodule externals/pugixml updated: 3b17184379...4bc14418d1
2
externals/sdl3
vendored
2
externals/sdl3
vendored
Submodule externals/sdl3 updated: 54e622c2e6...3a1d76d298
2
externals/sirit
vendored
2
externals/sirit
vendored
Submodule externals/sirit updated: 6cecb95d67...1e74f4ef8d
2
externals/toml11
vendored
2
externals/toml11
vendored
Submodule externals/toml11 updated: f925e7f287...7f6c574ff5
2
externals/tracy
vendored
2
externals/tracy
vendored
Submodule externals/tracy updated: b8061982ca...143a53d198
2
externals/vma
vendored
2
externals/vma
vendored
Submodule externals/vma updated: 1c35ba99ce...5a53a19894
2
externals/vulkan-headers
vendored
2
externals/vulkan-headers
vendored
Submodule externals/vulkan-headers updated: d91597a82f...6a74a7d65c
2
externals/xbyak
vendored
2
externals/xbyak
vendored
Submodule externals/xbyak updated: d067f0d3f5...4e44f4614d
2
externals/xxhash
vendored
2
externals/xxhash
vendored
Submodule externals/xxhash updated: d4ad85e4af...2bf8313b93
2
externals/zydis
vendored
2
externals/zydis
vendored
Submodule externals/zydis updated: 9d298eb806...bffbb610cf
@@ -1,166 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "sdl_audio.h"
|
|
||||||
|
|
||||||
#include "common/assert.h"
|
|
||||||
#include "core/libraries/error_codes.h"
|
|
||||||
|
|
||||||
#include <SDL3/SDL_audio.h>
|
|
||||||
#include <SDL3/SDL_init.h>
|
|
||||||
#include <SDL3/SDL_timer.h>
|
|
||||||
|
|
||||||
#include <mutex> // std::unique_lock
|
|
||||||
|
|
||||||
namespace Audio {
|
|
||||||
|
|
||||||
constexpr int AUDIO_STREAM_BUFFER_THRESHOLD = 65536; // Define constant for buffer threshold
|
|
||||||
|
|
||||||
s32 SDLAudio::AudioOutOpen(int type, u32 samples_num, u32 freq,
|
|
||||||
Libraries::AudioOut::OrbisAudioOutParamFormat format) {
|
|
||||||
using Libraries::AudioOut::OrbisAudioOutParamFormat;
|
|
||||||
std::unique_lock lock{m_mutex};
|
|
||||||
for (int id = 0; id < portsOut.size(); id++) {
|
|
||||||
auto& port = portsOut[id];
|
|
||||||
if (!port.isOpen) {
|
|
||||||
port.isOpen = true;
|
|
||||||
port.type = type;
|
|
||||||
port.samples_num = samples_num;
|
|
||||||
port.freq = freq;
|
|
||||||
port.format = format;
|
|
||||||
SDL_AudioFormat sampleFormat;
|
|
||||||
switch (format) {
|
|
||||||
case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_MONO:
|
|
||||||
sampleFormat = SDL_AUDIO_S16;
|
|
||||||
port.channels_num = 1;
|
|
||||||
port.sample_size = 2;
|
|
||||||
break;
|
|
||||||
case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_MONO:
|
|
||||||
sampleFormat = SDL_AUDIO_F32;
|
|
||||||
port.channels_num = 1;
|
|
||||||
port.sample_size = 4;
|
|
||||||
break;
|
|
||||||
case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_STEREO:
|
|
||||||
sampleFormat = SDL_AUDIO_S16;
|
|
||||||
port.channels_num = 2;
|
|
||||||
port.sample_size = 2;
|
|
||||||
break;
|
|
||||||
case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_STEREO:
|
|
||||||
sampleFormat = SDL_AUDIO_F32;
|
|
||||||
port.channels_num = 2;
|
|
||||||
port.sample_size = 4;
|
|
||||||
break;
|
|
||||||
case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH:
|
|
||||||
sampleFormat = SDL_AUDIO_S16;
|
|
||||||
port.channels_num = 8;
|
|
||||||
port.sample_size = 2;
|
|
||||||
break;
|
|
||||||
case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH:
|
|
||||||
sampleFormat = SDL_AUDIO_F32;
|
|
||||||
port.channels_num = 8;
|
|
||||||
port.sample_size = 4;
|
|
||||||
break;
|
|
||||||
case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH_STD:
|
|
||||||
sampleFormat = SDL_AUDIO_S16;
|
|
||||||
port.channels_num = 8;
|
|
||||||
port.sample_size = 2;
|
|
||||||
break;
|
|
||||||
case OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH_STD:
|
|
||||||
sampleFormat = SDL_AUDIO_F32;
|
|
||||||
port.channels_num = 8;
|
|
||||||
port.sample_size = 4;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
UNREACHABLE_MSG("Unknown format");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < port.channels_num; i++) {
|
|
||||||
port.volume[i] = Libraries::AudioOut::SCE_AUDIO_OUT_VOLUME_0DB;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_AudioSpec fmt;
|
|
||||||
SDL_zero(fmt);
|
|
||||||
fmt.format = sampleFormat;
|
|
||||||
fmt.channels = port.channels_num;
|
|
||||||
fmt.freq = freq; // Set frequency from the argument
|
|
||||||
port.stream =
|
|
||||||
SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &fmt, NULL, NULL);
|
|
||||||
SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(port.stream));
|
|
||||||
return id + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_ERROR(Lib_AudioOut, "Audio ports are full");
|
|
||||||
return ORBIS_AUDIO_OUT_ERROR_PORT_FULL; // all ports are used
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 SDLAudio::AudioOutOutput(s32 handle, const void* ptr) {
|
|
||||||
std::shared_lock lock{m_mutex};
|
|
||||||
auto& port = portsOut[handle - 1];
|
|
||||||
if (!port.isOpen) {
|
|
||||||
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_t data_size = port.samples_num * port.sample_size * port.channels_num;
|
|
||||||
|
|
||||||
bool result = SDL_PutAudioStreamData(port.stream, ptr, data_size);
|
|
||||||
|
|
||||||
lock.unlock(); // Unlock only after necessary operations
|
|
||||||
|
|
||||||
while (SDL_GetAudioStreamAvailable(port.stream) > AUDIO_STREAM_BUFFER_THRESHOLD) {
|
|
||||||
SDL_Delay(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result ? ORBIS_OK : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 SDLAudio::AudioOutSetVolume(s32 handle, s32 bitflag, s32* volume) {
|
|
||||||
using Libraries::AudioOut::OrbisAudioOutParamFormat;
|
|
||||||
std::shared_lock lock{m_mutex};
|
|
||||||
auto& port = portsOut[handle - 1];
|
|
||||||
if (!port.isOpen) {
|
|
||||||
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < port.channels_num; i++, bitflag >>= 1u) {
|
|
||||||
auto bit = bitflag & 0x1u;
|
|
||||||
|
|
||||||
if (bit == 1) {
|
|
||||||
int src_index = i;
|
|
||||||
if (port.format ==
|
|
||||||
OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH_STD ||
|
|
||||||
port.format == OrbisAudioOutParamFormat::ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH_STD) {
|
|
||||||
switch (i) {
|
|
||||||
case 4:
|
|
||||||
src_index = 6;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
src_index = 7;
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
src_index = 4;
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
src_index = 5;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
port.volume[i] = volume[src_index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 SDLAudio::AudioOutGetStatus(s32 handle, int* type, int* channels_num) {
|
|
||||||
std::shared_lock lock{m_mutex};
|
|
||||||
auto& port = portsOut[handle - 1];
|
|
||||||
*type = port.type;
|
|
||||||
*channels_num = port.channels_num;
|
|
||||||
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Audio
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <shared_mutex>
|
|
||||||
#include <SDL3/SDL_audio.h>
|
|
||||||
#include "core/libraries/audio/audioout.h"
|
|
||||||
|
|
||||||
namespace Audio {
|
|
||||||
|
|
||||||
class SDLAudio {
|
|
||||||
public:
|
|
||||||
SDLAudio() = default;
|
|
||||||
virtual ~SDLAudio() = default;
|
|
||||||
|
|
||||||
s32 AudioOutOpen(int type, u32 samples_num, u32 freq,
|
|
||||||
Libraries::AudioOut::OrbisAudioOutParamFormat format);
|
|
||||||
s32 AudioOutOutput(s32 handle, const void* ptr);
|
|
||||||
s32 AudioOutSetVolume(s32 handle, s32 bitflag, s32* volume);
|
|
||||||
s32 AudioOutGetStatus(s32 handle, int* type, int* channels_num);
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct PortOut {
|
|
||||||
SDL_AudioStream* stream = nullptr;
|
|
||||||
u32 samples_num = 0;
|
|
||||||
u32 freq = 0;
|
|
||||||
u32 format = -1;
|
|
||||||
int type = 0;
|
|
||||||
int channels_num = 0;
|
|
||||||
int volume[8] = {};
|
|
||||||
u8 sample_size = 0;
|
|
||||||
bool isOpen = false;
|
|
||||||
};
|
|
||||||
std::shared_mutex m_mutex;
|
|
||||||
std::array<PortOut, Libraries::AudioOut::SCE_AUDIO_OUT_NUM_PORTS> portsOut;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Audio
|
|
||||||
@@ -22,6 +22,12 @@ template <typename T>
|
|||||||
return static_cast<T>(value - value % size);
|
return static_cast<T>(value - value % size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
requires std::is_integral_v<T>
|
||||||
|
[[nodiscard]] constexpr bool IsAligned(T value, std::size_t alignment) {
|
||||||
|
return (value & (alignment - 1)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
requires std::is_integral_v<T>
|
requires std::is_integral_v<T>
|
||||||
[[nodiscard]] constexpr bool Is16KBAligned(T value) {
|
[[nodiscard]] constexpr bool Is16KBAligned(T value) {
|
||||||
|
|||||||
@@ -3,13 +3,14 @@
|
|||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <common/version.h>
|
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
#include <fmt/xchar.h> // for wstring support
|
#include <fmt/xchar.h> // for wstring support
|
||||||
#include <toml.hpp>
|
#include <toml.hpp>
|
||||||
#include "common/logging/formatter.h"
|
|
||||||
#include "common/path_util.h"
|
#include "common/path_util.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "logging/formatter.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
namespace toml {
|
namespace toml {
|
||||||
template <typename TC, typename K>
|
template <typename TC, typename K>
|
||||||
@@ -33,6 +34,7 @@ namespace Config {
|
|||||||
static bool isNeo = false;
|
static bool isNeo = false;
|
||||||
static bool isFullscreen = false;
|
static bool isFullscreen = false;
|
||||||
static bool playBGM = false;
|
static bool playBGM = false;
|
||||||
|
static bool isTrophyPopupDisabled = false;
|
||||||
static int BGMvolume = 50;
|
static int BGMvolume = 50;
|
||||||
static bool enableDiscordRPC = false;
|
static bool enableDiscordRPC = false;
|
||||||
static u32 screenWidth = 1280;
|
static u32 screenWidth = 1280;
|
||||||
@@ -46,11 +48,13 @@ static std::string backButtonBehavior = "left";
|
|||||||
static bool useSpecialPad = false;
|
static bool useSpecialPad = false;
|
||||||
static int specialPadClass = 1;
|
static int specialPadClass = 1;
|
||||||
static bool isDebugDump = false;
|
static bool isDebugDump = false;
|
||||||
|
static bool isShaderDebug = false;
|
||||||
static bool isShowSplash = false;
|
static bool isShowSplash = false;
|
||||||
static bool isAutoUpdate = false;
|
static bool isAutoUpdate = false;
|
||||||
static bool isNullGpu = false;
|
static bool isNullGpu = false;
|
||||||
static bool shouldCopyGPUBuffers = false;
|
static bool shouldCopyGPUBuffers = false;
|
||||||
static bool shouldDumpShaders = false;
|
static bool shouldDumpShaders = false;
|
||||||
|
static bool shouldPatchShaders = true;
|
||||||
static u32 vblankDivider = 1;
|
static u32 vblankDivider = 1;
|
||||||
static bool vkValidation = false;
|
static bool vkValidation = false;
|
||||||
static bool vkValidationSync = false;
|
static bool vkValidationSync = false;
|
||||||
@@ -61,6 +65,8 @@ static bool vkCrashDiagnostic = false;
|
|||||||
static s16 cursorState = HideCursorState::Idle;
|
static s16 cursorState = HideCursorState::Idle;
|
||||||
static int cursorHideTimeout = 5; // 5 seconds (default)
|
static int cursorHideTimeout = 5; // 5 seconds (default)
|
||||||
static bool separateupdatefolder = false;
|
static bool separateupdatefolder = false;
|
||||||
|
static bool compatibilityData = false;
|
||||||
|
static bool checkCompatibilityOnStartup = false;
|
||||||
|
|
||||||
// Gui
|
// Gui
|
||||||
std::vector<std::filesystem::path> settings_install_dirs = {};
|
std::vector<std::filesystem::path> settings_install_dirs = {};
|
||||||
@@ -81,7 +87,8 @@ std::vector<std::string> m_pkg_viewer;
|
|||||||
std::vector<std::string> m_elf_viewer;
|
std::vector<std::string> m_elf_viewer;
|
||||||
std::vector<std::string> m_recent_files;
|
std::vector<std::string> m_recent_files;
|
||||||
std::string emulator_language = "en";
|
std::string emulator_language = "en";
|
||||||
// Settings
|
|
||||||
|
// Language
|
||||||
u32 m_language = 1; // english
|
u32 m_language = 1; // english
|
||||||
|
|
||||||
bool isNeoMode() {
|
bool isNeoMode() {
|
||||||
@@ -92,6 +99,10 @@ bool isFullscreenMode() {
|
|||||||
return isFullscreen;
|
return isFullscreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool getisTrophyPopupDisabled() {
|
||||||
|
return isTrophyPopupDisabled;
|
||||||
|
}
|
||||||
|
|
||||||
bool getPlayBGM() {
|
bool getPlayBGM() {
|
||||||
return playBGM;
|
return playBGM;
|
||||||
}
|
}
|
||||||
@@ -156,6 +167,10 @@ bool debugDump() {
|
|||||||
return isDebugDump;
|
return isDebugDump;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool collectShadersForDebug() {
|
||||||
|
return isShaderDebug;
|
||||||
|
}
|
||||||
|
|
||||||
bool showSplash() {
|
bool showSplash() {
|
||||||
return isShowSplash;
|
return isShowSplash;
|
||||||
}
|
}
|
||||||
@@ -176,6 +191,10 @@ bool dumpShaders() {
|
|||||||
return shouldDumpShaders;
|
return shouldDumpShaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool patchShaders() {
|
||||||
|
return shouldPatchShaders;
|
||||||
|
}
|
||||||
|
|
||||||
bool isRdocEnabled() {
|
bool isRdocEnabled() {
|
||||||
return rdocEnable;
|
return rdocEnable;
|
||||||
}
|
}
|
||||||
@@ -212,6 +231,14 @@ bool getSeparateUpdateEnabled() {
|
|||||||
return separateupdatefolder;
|
return separateupdatefolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool getCompatibilityEnabled() {
|
||||||
|
return compatibilityData;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getCheckCompatibilityOnStartup() {
|
||||||
|
return checkCompatibilityOnStartup;
|
||||||
|
}
|
||||||
|
|
||||||
void setGpuId(s32 selectedGpuId) {
|
void setGpuId(s32 selectedGpuId) {
|
||||||
gpuId = selectedGpuId;
|
gpuId = selectedGpuId;
|
||||||
}
|
}
|
||||||
@@ -228,6 +255,10 @@ void setDebugDump(bool enable) {
|
|||||||
isDebugDump = enable;
|
isDebugDump = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setCollectShaderForDebug(bool enable) {
|
||||||
|
isShaderDebug = enable;
|
||||||
|
}
|
||||||
|
|
||||||
void setShowSplash(bool enable) {
|
void setShowSplash(bool enable) {
|
||||||
isShowSplash = enable;
|
isShowSplash = enable;
|
||||||
}
|
}
|
||||||
@@ -268,6 +299,10 @@ void setFullscreenMode(bool enable) {
|
|||||||
isFullscreen = enable;
|
isFullscreen = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setisTrophyPopupDisabled(bool disable) {
|
||||||
|
isTrophyPopupDisabled = disable;
|
||||||
|
}
|
||||||
|
|
||||||
void setPlayBGM(bool enable) {
|
void setPlayBGM(bool enable) {
|
||||||
playBGM = enable;
|
playBGM = enable;
|
||||||
}
|
}
|
||||||
@@ -328,12 +363,21 @@ void setSeparateUpdateEnabled(bool use) {
|
|||||||
separateupdatefolder = use;
|
separateupdatefolder = use;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setCompatibilityEnabled(bool use) {
|
||||||
|
compatibilityData = use;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setCheckCompatibilityOnStartup(bool use) {
|
||||||
|
checkCompatibilityOnStartup = use;
|
||||||
|
}
|
||||||
|
|
||||||
void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h) {
|
void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h) {
|
||||||
main_window_geometry_x = x;
|
main_window_geometry_x = x;
|
||||||
main_window_geometry_y = y;
|
main_window_geometry_y = y;
|
||||||
main_window_geometry_w = w;
|
main_window_geometry_w = w;
|
||||||
main_window_geometry_h = h;
|
main_window_geometry_h = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool addGameInstallDir(const std::filesystem::path& dir) {
|
bool addGameInstallDir(const std::filesystem::path& dir) {
|
||||||
if (std::find(settings_install_dirs.begin(), settings_install_dirs.end(), dir) ==
|
if (std::find(settings_install_dirs.begin(), settings_install_dirs.end(), dir) ==
|
||||||
settings_install_dirs.end()) {
|
settings_install_dirs.end()) {
|
||||||
@@ -342,47 +386,60 @@ bool addGameInstallDir(const std::filesystem::path& dir) {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeGameInstallDir(const std::filesystem::path& dir) {
|
void removeGameInstallDir(const std::filesystem::path& dir) {
|
||||||
auto iterator = std::find(settings_install_dirs.begin(), settings_install_dirs.end(), dir);
|
auto iterator = std::find(settings_install_dirs.begin(), settings_install_dirs.end(), dir);
|
||||||
if (iterator != settings_install_dirs.end()) {
|
if (iterator != settings_install_dirs.end()) {
|
||||||
settings_install_dirs.erase(iterator);
|
settings_install_dirs.erase(iterator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setAddonInstallDir(const std::filesystem::path& dir) {
|
void setAddonInstallDir(const std::filesystem::path& dir) {
|
||||||
settings_addon_install_dir = dir;
|
settings_addon_install_dir = dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMainWindowTheme(u32 theme) {
|
void setMainWindowTheme(u32 theme) {
|
||||||
mw_themes = theme;
|
mw_themes = theme;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setIconSize(u32 size) {
|
void setIconSize(u32 size) {
|
||||||
m_icon_size = size;
|
m_icon_size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setIconSizeGrid(u32 size) {
|
void setIconSizeGrid(u32 size) {
|
||||||
m_icon_size_grid = size;
|
m_icon_size_grid = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSliderPosition(u32 pos) {
|
void setSliderPosition(u32 pos) {
|
||||||
m_slider_pos = pos;
|
m_slider_pos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSliderPositionGrid(u32 pos) {
|
void setSliderPositionGrid(u32 pos) {
|
||||||
m_slider_pos_grid = pos;
|
m_slider_pos_grid = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTableMode(u32 mode) {
|
void setTableMode(u32 mode) {
|
||||||
m_table_mode = mode;
|
m_table_mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMainWindowWidth(u32 width) {
|
void setMainWindowWidth(u32 width) {
|
||||||
m_window_size_W = width;
|
m_window_size_W = width;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMainWindowHeight(u32 height) {
|
void setMainWindowHeight(u32 height) {
|
||||||
m_window_size_H = height;
|
m_window_size_H = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPkgViewer(const std::vector<std::string>& pkgList) {
|
void setPkgViewer(const std::vector<std::string>& pkgList) {
|
||||||
m_pkg_viewer.resize(pkgList.size());
|
m_pkg_viewer.resize(pkgList.size());
|
||||||
m_pkg_viewer = pkgList;
|
m_pkg_viewer = pkgList;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setElfViewer(const std::vector<std::string>& elfList) {
|
void setElfViewer(const std::vector<std::string>& elfList) {
|
||||||
m_elf_viewer.resize(elfList.size());
|
m_elf_viewer.resize(elfList.size());
|
||||||
m_elf_viewer = elfList;
|
m_elf_viewer = elfList;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRecentFiles(const std::vector<std::string>& recentFiles) {
|
void setRecentFiles(const std::vector<std::string>& recentFiles) {
|
||||||
m_recent_files.resize(recentFiles.size());
|
m_recent_files.resize(recentFiles.size());
|
||||||
m_recent_files = recentFiles;
|
m_recent_files = recentFiles;
|
||||||
@@ -392,21 +449,30 @@ void setEmulatorLanguage(std::string language) {
|
|||||||
emulator_language = language;
|
emulator_language = language;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setGameInstallDirs(const std::vector<std::filesystem::path>& settings_install_dirs_config) {
|
||||||
|
settings_install_dirs = settings_install_dirs_config;
|
||||||
|
}
|
||||||
|
|
||||||
u32 getMainWindowGeometryX() {
|
u32 getMainWindowGeometryX() {
|
||||||
return main_window_geometry_x;
|
return main_window_geometry_x;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 getMainWindowGeometryY() {
|
u32 getMainWindowGeometryY() {
|
||||||
return main_window_geometry_y;
|
return main_window_geometry_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 getMainWindowGeometryW() {
|
u32 getMainWindowGeometryW() {
|
||||||
return main_window_geometry_w;
|
return main_window_geometry_w;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 getMainWindowGeometryH() {
|
u32 getMainWindowGeometryH() {
|
||||||
return main_window_geometry_h;
|
return main_window_geometry_h;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::filesystem::path>& getGameInstallDirs() {
|
const std::vector<std::filesystem::path>& getGameInstallDirs() {
|
||||||
return settings_install_dirs;
|
return settings_install_dirs;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path getAddonInstallDir() {
|
std::filesystem::path getAddonInstallDir() {
|
||||||
if (settings_addon_install_dir.empty()) {
|
if (settings_addon_install_dir.empty()) {
|
||||||
// Default for users without a config file or a config file from before this option existed
|
// Default for users without a config file or a config file from before this option existed
|
||||||
@@ -414,36 +480,47 @@ std::filesystem::path getAddonInstallDir() {
|
|||||||
}
|
}
|
||||||
return settings_addon_install_dir;
|
return settings_addon_install_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 getMainWindowTheme() {
|
u32 getMainWindowTheme() {
|
||||||
return mw_themes;
|
return mw_themes;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 getIconSize() {
|
u32 getIconSize() {
|
||||||
return m_icon_size;
|
return m_icon_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 getIconSizeGrid() {
|
u32 getIconSizeGrid() {
|
||||||
return m_icon_size_grid;
|
return m_icon_size_grid;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 getSliderPosition() {
|
u32 getSliderPosition() {
|
||||||
return m_slider_pos;
|
return m_slider_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 getSliderPositionGrid() {
|
u32 getSliderPositionGrid() {
|
||||||
return m_slider_pos_grid;
|
return m_slider_pos_grid;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 getTableMode() {
|
u32 getTableMode() {
|
||||||
return m_table_mode;
|
return m_table_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 getMainWindowWidth() {
|
u32 getMainWindowWidth() {
|
||||||
return m_window_size_W;
|
return m_window_size_W;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 getMainWindowHeight() {
|
u32 getMainWindowHeight() {
|
||||||
return m_window_size_H;
|
return m_window_size_H;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> getPkgViewer() {
|
std::vector<std::string> getPkgViewer() {
|
||||||
return m_pkg_viewer;
|
return m_pkg_viewer;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> getElfViewer() {
|
std::vector<std::string> getElfViewer() {
|
||||||
return m_elf_viewer;
|
return m_elf_viewer;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> getRecentFiles() {
|
std::vector<std::string> getRecentFiles() {
|
||||||
return m_recent_files;
|
return m_recent_files;
|
||||||
}
|
}
|
||||||
@@ -455,6 +532,7 @@ std::string getEmulatorLanguage() {
|
|||||||
u32 GetLanguage() {
|
u32 GetLanguage() {
|
||||||
return m_language;
|
return m_language;
|
||||||
}
|
}
|
||||||
|
|
||||||
void load(const std::filesystem::path& path) {
|
void load(const std::filesystem::path& path) {
|
||||||
// If the configuration file does not exist, create it and return
|
// If the configuration file does not exist, create it and return
|
||||||
std::error_code error;
|
std::error_code error;
|
||||||
@@ -480,6 +558,7 @@ void load(const std::filesystem::path& path) {
|
|||||||
isNeo = toml::find_or<bool>(general, "isPS4Pro", false);
|
isNeo = toml::find_or<bool>(general, "isPS4Pro", false);
|
||||||
isFullscreen = toml::find_or<bool>(general, "Fullscreen", false);
|
isFullscreen = toml::find_or<bool>(general, "Fullscreen", false);
|
||||||
playBGM = toml::find_or<bool>(general, "playBGM", false);
|
playBGM = toml::find_or<bool>(general, "playBGM", false);
|
||||||
|
isTrophyPopupDisabled = toml::find_or<bool>(general, "isTrophyPopupDisabled", false);
|
||||||
BGMvolume = toml::find_or<int>(general, "BGMvolume", 50);
|
BGMvolume = toml::find_or<int>(general, "BGMvolume", 50);
|
||||||
enableDiscordRPC = toml::find_or<bool>(general, "enableDiscordRPC", true);
|
enableDiscordRPC = toml::find_or<bool>(general, "enableDiscordRPC", true);
|
||||||
logFilter = toml::find_or<std::string>(general, "logFilter", "");
|
logFilter = toml::find_or<std::string>(general, "logFilter", "");
|
||||||
@@ -493,6 +572,9 @@ void load(const std::filesystem::path& path) {
|
|||||||
isShowSplash = toml::find_or<bool>(general, "showSplash", true);
|
isShowSplash = toml::find_or<bool>(general, "showSplash", true);
|
||||||
isAutoUpdate = toml::find_or<bool>(general, "autoUpdate", false);
|
isAutoUpdate = toml::find_or<bool>(general, "autoUpdate", false);
|
||||||
separateupdatefolder = toml::find_or<bool>(general, "separateUpdateEnabled", false);
|
separateupdatefolder = toml::find_or<bool>(general, "separateUpdateEnabled", false);
|
||||||
|
compatibilityData = toml::find_or<bool>(general, "compatibilityEnabled", false);
|
||||||
|
checkCompatibilityOnStartup =
|
||||||
|
toml::find_or<bool>(general, "checkCompatibilityOnStartup", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.contains("Input")) {
|
if (data.contains("Input")) {
|
||||||
@@ -513,6 +595,7 @@ void load(const std::filesystem::path& path) {
|
|||||||
isNullGpu = toml::find_or<bool>(gpu, "nullGpu", false);
|
isNullGpu = toml::find_or<bool>(gpu, "nullGpu", false);
|
||||||
shouldCopyGPUBuffers = toml::find_or<bool>(gpu, "copyGPUBuffers", false);
|
shouldCopyGPUBuffers = toml::find_or<bool>(gpu, "copyGPUBuffers", false);
|
||||||
shouldDumpShaders = toml::find_or<bool>(gpu, "dumpShaders", false);
|
shouldDumpShaders = toml::find_or<bool>(gpu, "dumpShaders", false);
|
||||||
|
shouldPatchShaders = toml::find_or<bool>(gpu, "patchShaders", true);
|
||||||
vblankDivider = toml::find_or<int>(gpu, "vblankDivider", 1);
|
vblankDivider = toml::find_or<int>(gpu, "vblankDivider", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -532,6 +615,7 @@ void load(const std::filesystem::path& path) {
|
|||||||
const toml::value& debug = data.at("Debug");
|
const toml::value& debug = data.at("Debug");
|
||||||
|
|
||||||
isDebugDump = toml::find_or<bool>(debug, "DebugDump", false);
|
isDebugDump = toml::find_or<bool>(debug, "DebugDump", false);
|
||||||
|
isShaderDebug = toml::find_or<bool>(debug, "CollectShader", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.contains("GUI")) {
|
if (data.contains("GUI")) {
|
||||||
@@ -545,16 +629,10 @@ void load(const std::filesystem::path& path) {
|
|||||||
m_window_size_W = toml::find_or<int>(gui, "mw_width", 0);
|
m_window_size_W = toml::find_or<int>(gui, "mw_width", 0);
|
||||||
m_window_size_H = toml::find_or<int>(gui, "mw_height", 0);
|
m_window_size_H = toml::find_or<int>(gui, "mw_height", 0);
|
||||||
|
|
||||||
// TODO Migration code, after a major release this should be removed.
|
const auto install_dir_array =
|
||||||
auto old_game_install_dir = toml::find_fs_path_or(gui, "installDir", {});
|
toml::find_or<std::vector<std::string>>(gui, "installDirs", {});
|
||||||
if (!old_game_install_dir.empty()) {
|
for (const auto& dir : install_dir_array) {
|
||||||
addGameInstallDir(std::filesystem::path{old_game_install_dir});
|
addGameInstallDir(std::filesystem::path{dir});
|
||||||
} else {
|
|
||||||
const auto install_dir_array =
|
|
||||||
toml::find_or<std::vector<std::string>>(gui, "installDirs", {});
|
|
||||||
for (const auto& dir : install_dir_array) {
|
|
||||||
addGameInstallDir(std::filesystem::path{dir});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
settings_addon_install_dir = toml::find_fs_path_or(gui, "addonInstallDir", {});
|
settings_addon_install_dir = toml::find_fs_path_or(gui, "addonInstallDir", {});
|
||||||
@@ -575,6 +653,7 @@ void load(const std::filesystem::path& path) {
|
|||||||
m_language = toml::find_or<int>(settings, "consoleLanguage", 1);
|
m_language = toml::find_or<int>(settings, "consoleLanguage", 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void save(const std::filesystem::path& path) {
|
void save(const std::filesystem::path& path) {
|
||||||
toml::value data;
|
toml::value data;
|
||||||
|
|
||||||
@@ -598,6 +677,7 @@ void save(const std::filesystem::path& path) {
|
|||||||
|
|
||||||
data["General"]["isPS4Pro"] = isNeo;
|
data["General"]["isPS4Pro"] = isNeo;
|
||||||
data["General"]["Fullscreen"] = isFullscreen;
|
data["General"]["Fullscreen"] = isFullscreen;
|
||||||
|
data["General"]["isTrophyPopupDisabled"] = isTrophyPopupDisabled;
|
||||||
data["General"]["playBGM"] = playBGM;
|
data["General"]["playBGM"] = playBGM;
|
||||||
data["General"]["BGMvolume"] = BGMvolume;
|
data["General"]["BGMvolume"] = BGMvolume;
|
||||||
data["General"]["enableDiscordRPC"] = enableDiscordRPC;
|
data["General"]["enableDiscordRPC"] = enableDiscordRPC;
|
||||||
@@ -608,6 +688,8 @@ void save(const std::filesystem::path& path) {
|
|||||||
data["General"]["showSplash"] = isShowSplash;
|
data["General"]["showSplash"] = isShowSplash;
|
||||||
data["General"]["autoUpdate"] = isAutoUpdate;
|
data["General"]["autoUpdate"] = isAutoUpdate;
|
||||||
data["General"]["separateUpdateEnabled"] = separateupdatefolder;
|
data["General"]["separateUpdateEnabled"] = separateupdatefolder;
|
||||||
|
data["General"]["compatibilityEnabled"] = compatibilityData;
|
||||||
|
data["General"]["checkCompatibilityOnStartup"] = checkCompatibilityOnStartup;
|
||||||
data["Input"]["cursorState"] = cursorState;
|
data["Input"]["cursorState"] = cursorState;
|
||||||
data["Input"]["cursorHideTimeout"] = cursorHideTimeout;
|
data["Input"]["cursorHideTimeout"] = cursorHideTimeout;
|
||||||
data["Input"]["backButtonBehavior"] = backButtonBehavior;
|
data["Input"]["backButtonBehavior"] = backButtonBehavior;
|
||||||
@@ -618,6 +700,7 @@ void save(const std::filesystem::path& path) {
|
|||||||
data["GPU"]["nullGpu"] = isNullGpu;
|
data["GPU"]["nullGpu"] = isNullGpu;
|
||||||
data["GPU"]["copyGPUBuffers"] = shouldCopyGPUBuffers;
|
data["GPU"]["copyGPUBuffers"] = shouldCopyGPUBuffers;
|
||||||
data["GPU"]["dumpShaders"] = shouldDumpShaders;
|
data["GPU"]["dumpShaders"] = shouldDumpShaders;
|
||||||
|
data["GPU"]["patchShaders"] = shouldPatchShaders;
|
||||||
data["GPU"]["vblankDivider"] = vblankDivider;
|
data["GPU"]["vblankDivider"] = vblankDivider;
|
||||||
data["Vulkan"]["gpuId"] = gpuId;
|
data["Vulkan"]["gpuId"] = gpuId;
|
||||||
data["Vulkan"]["validation"] = vkValidation;
|
data["Vulkan"]["validation"] = vkValidation;
|
||||||
@@ -627,14 +710,7 @@ void save(const std::filesystem::path& path) {
|
|||||||
data["Vulkan"]["rdocMarkersEnable"] = vkMarkers;
|
data["Vulkan"]["rdocMarkersEnable"] = vkMarkers;
|
||||||
data["Vulkan"]["crashDiagnostic"] = vkCrashDiagnostic;
|
data["Vulkan"]["crashDiagnostic"] = vkCrashDiagnostic;
|
||||||
data["Debug"]["DebugDump"] = isDebugDump;
|
data["Debug"]["DebugDump"] = isDebugDump;
|
||||||
data["GUI"]["theme"] = mw_themes;
|
data["Debug"]["CollectShader"] = isShaderDebug;
|
||||||
data["GUI"]["iconSize"] = m_icon_size;
|
|
||||||
data["GUI"]["sliderPos"] = m_slider_pos;
|
|
||||||
data["GUI"]["iconSizeGrid"] = m_icon_size_grid;
|
|
||||||
data["GUI"]["sliderPosGrid"] = m_slider_pos_grid;
|
|
||||||
data["GUI"]["gameTableMode"] = m_table_mode;
|
|
||||||
data["GUI"]["mw_width"] = m_window_size_W;
|
|
||||||
data["GUI"]["mw_height"] = m_window_size_H;
|
|
||||||
|
|
||||||
std::vector<std::string> install_dirs;
|
std::vector<std::string> install_dirs;
|
||||||
for (const auto& dirString : settings_install_dirs) {
|
for (const auto& dirString : settings_install_dirs) {
|
||||||
@@ -644,6 +720,44 @@ void save(const std::filesystem::path& path) {
|
|||||||
|
|
||||||
data["GUI"]["addonInstallDir"] =
|
data["GUI"]["addonInstallDir"] =
|
||||||
std::string{fmt::UTF(settings_addon_install_dir.u8string()).data};
|
std::string{fmt::UTF(settings_addon_install_dir.u8string()).data};
|
||||||
|
data["GUI"]["emulatorLanguage"] = emulator_language;
|
||||||
|
data["Settings"]["consoleLanguage"] = m_language;
|
||||||
|
|
||||||
|
std::ofstream file(path, std::ios::binary);
|
||||||
|
file << data;
|
||||||
|
file.close();
|
||||||
|
saveMainWindow(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveMainWindow(const std::filesystem::path& path) {
|
||||||
|
toml::value data;
|
||||||
|
|
||||||
|
std::error_code error;
|
||||||
|
if (std::filesystem::exists(path, error)) {
|
||||||
|
try {
|
||||||
|
std::ifstream ifs;
|
||||||
|
ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||||
|
ifs.open(path, std::ios_base::binary);
|
||||||
|
data = toml::parse(ifs, std::string{fmt::UTF(path.filename().u8string()).data});
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
fmt::print("Exception trying to parse config file. Exception: {}\n", ex.what());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (error) {
|
||||||
|
fmt::print("Filesystem error: {}\n", error.message());
|
||||||
|
}
|
||||||
|
fmt::print("Saving new configuration file {}\n", fmt::UTF(path.u8string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
data["GUI"]["mw_width"] = m_window_size_W;
|
||||||
|
data["GUI"]["mw_height"] = m_window_size_H;
|
||||||
|
data["GUI"]["theme"] = mw_themes;
|
||||||
|
data["GUI"]["iconSize"] = m_icon_size;
|
||||||
|
data["GUI"]["sliderPos"] = m_slider_pos;
|
||||||
|
data["GUI"]["iconSizeGrid"] = m_icon_size_grid;
|
||||||
|
data["GUI"]["sliderPosGrid"] = m_slider_pos_grid;
|
||||||
|
data["GUI"]["gameTableMode"] = m_table_mode;
|
||||||
data["GUI"]["geometry_x"] = main_window_geometry_x;
|
data["GUI"]["geometry_x"] = main_window_geometry_x;
|
||||||
data["GUI"]["geometry_y"] = main_window_geometry_y;
|
data["GUI"]["geometry_y"] = main_window_geometry_y;
|
||||||
data["GUI"]["geometry_w"] = main_window_geometry_w;
|
data["GUI"]["geometry_w"] = main_window_geometry_w;
|
||||||
@@ -651,14 +765,8 @@ void save(const std::filesystem::path& path) {
|
|||||||
data["GUI"]["pkgDirs"] = m_pkg_viewer;
|
data["GUI"]["pkgDirs"] = m_pkg_viewer;
|
||||||
data["GUI"]["elfDirs"] = m_elf_viewer;
|
data["GUI"]["elfDirs"] = m_elf_viewer;
|
||||||
data["GUI"]["recentFiles"] = m_recent_files;
|
data["GUI"]["recentFiles"] = m_recent_files;
|
||||||
data["GUI"]["emulatorLanguage"] = emulator_language;
|
|
||||||
|
|
||||||
data["Settings"]["consoleLanguage"] = m_language;
|
std::ofstream file(path, std::ios::binary);
|
||||||
|
|
||||||
// TODO Migration code, after a major release this should be removed.
|
|
||||||
data.at("GUI").as_table().erase("installDir");
|
|
||||||
|
|
||||||
std::ofstream file(path, std::ios::out);
|
|
||||||
file << data;
|
file << data;
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
@@ -666,6 +774,7 @@ void save(const std::filesystem::path& path) {
|
|||||||
void setDefaultValues() {
|
void setDefaultValues() {
|
||||||
isNeo = false;
|
isNeo = false;
|
||||||
isFullscreen = false;
|
isFullscreen = false;
|
||||||
|
isTrophyPopupDisabled = false;
|
||||||
playBGM = false;
|
playBGM = false;
|
||||||
BGMvolume = 50;
|
BGMvolume = 50;
|
||||||
enableDiscordRPC = true;
|
enableDiscordRPC = true;
|
||||||
@@ -685,6 +794,7 @@ void setDefaultValues() {
|
|||||||
useSpecialPad = false;
|
useSpecialPad = false;
|
||||||
specialPadClass = 1;
|
specialPadClass = 1;
|
||||||
isDebugDump = false;
|
isDebugDump = false;
|
||||||
|
isShaderDebug = false;
|
||||||
isShowSplash = false;
|
isShowSplash = false;
|
||||||
isAutoUpdate = false;
|
isAutoUpdate = false;
|
||||||
isNullGpu = false;
|
isNullGpu = false;
|
||||||
@@ -699,6 +809,9 @@ void setDefaultValues() {
|
|||||||
emulator_language = "en";
|
emulator_language = "en";
|
||||||
m_language = 1;
|
m_language = 1;
|
||||||
gpuId = -1;
|
gpuId = -1;
|
||||||
|
separateupdatefolder = false;
|
||||||
|
compatibilityData = false;
|
||||||
|
checkCompatibilityOnStartup = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Config
|
} // namespace Config
|
||||||
|
|||||||
@@ -13,13 +13,17 @@ enum HideCursorState : s16 { Never, Idle, Always };
|
|||||||
|
|
||||||
void load(const std::filesystem::path& path);
|
void load(const std::filesystem::path& path);
|
||||||
void save(const std::filesystem::path& path);
|
void save(const std::filesystem::path& path);
|
||||||
|
void saveMainWindow(const std::filesystem::path& path);
|
||||||
|
|
||||||
bool isNeoMode();
|
bool isNeoMode();
|
||||||
bool isFullscreenMode();
|
bool isFullscreenMode();
|
||||||
bool getPlayBGM();
|
bool getPlayBGM();
|
||||||
int getBGMvolume();
|
int getBGMvolume();
|
||||||
|
bool getisTrophyPopupDisabled();
|
||||||
bool getEnableDiscordRPC();
|
bool getEnableDiscordRPC();
|
||||||
bool getSeparateUpdateEnabled();
|
bool getSeparateUpdateEnabled();
|
||||||
|
bool getCompatibilityEnabled();
|
||||||
|
bool getCheckCompatibilityOnStartup();
|
||||||
|
|
||||||
std::string getLogFilter();
|
std::string getLogFilter();
|
||||||
std::string getLogType();
|
std::string getLogType();
|
||||||
@@ -37,15 +41,18 @@ u32 getScreenHeight();
|
|||||||
s32 getGpuId();
|
s32 getGpuId();
|
||||||
|
|
||||||
bool debugDump();
|
bool debugDump();
|
||||||
|
bool collectShadersForDebug();
|
||||||
bool showSplash();
|
bool showSplash();
|
||||||
bool autoUpdate();
|
bool autoUpdate();
|
||||||
bool nullGpu();
|
bool nullGpu();
|
||||||
bool copyGPUCmdBuffers();
|
bool copyGPUCmdBuffers();
|
||||||
bool dumpShaders();
|
bool dumpShaders();
|
||||||
|
bool patchShaders();
|
||||||
bool isRdocEnabled();
|
bool isRdocEnabled();
|
||||||
u32 vblankDiv();
|
u32 vblankDiv();
|
||||||
|
|
||||||
void setDebugDump(bool enable);
|
void setDebugDump(bool enable);
|
||||||
|
void setCollectShaderForDebug(bool enable);
|
||||||
void setShowSplash(bool enable);
|
void setShowSplash(bool enable);
|
||||||
void setAutoUpdate(bool enable);
|
void setAutoUpdate(bool enable);
|
||||||
void setNullGpu(bool enable);
|
void setNullGpu(bool enable);
|
||||||
@@ -56,6 +63,7 @@ void setGpuId(s32 selectedGpuId);
|
|||||||
void setScreenWidth(u32 width);
|
void setScreenWidth(u32 width);
|
||||||
void setScreenHeight(u32 height);
|
void setScreenHeight(u32 height);
|
||||||
void setFullscreenMode(bool enable);
|
void setFullscreenMode(bool enable);
|
||||||
|
void setisTrophyPopupDisabled(bool disable);
|
||||||
void setPlayBGM(bool enable);
|
void setPlayBGM(bool enable);
|
||||||
void setBGMvolume(int volume);
|
void setBGMvolume(int volume);
|
||||||
void setEnableDiscordRPC(bool enable);
|
void setEnableDiscordRPC(bool enable);
|
||||||
@@ -64,6 +72,9 @@ void setNeoMode(bool enable);
|
|||||||
void setUserName(const std::string& type);
|
void setUserName(const std::string& type);
|
||||||
void setUpdateChannel(const std::string& type);
|
void setUpdateChannel(const std::string& type);
|
||||||
void setSeparateUpdateEnabled(bool use);
|
void setSeparateUpdateEnabled(bool use);
|
||||||
|
void setGameInstallDirs(const std::vector<std::filesystem::path>& settings_install_dirs_config);
|
||||||
|
void setCompatibilityEnabled(bool use);
|
||||||
|
void setCheckCompatibilityOnStartup(bool use);
|
||||||
|
|
||||||
void setCursorState(s16 cursorState);
|
void setCursorState(s16 cursorState);
|
||||||
void setCursorHideTimeout(int newcursorHideTimeout);
|
void setCursorHideTimeout(int newcursorHideTimeout);
|
||||||
|
|||||||
@@ -14,9 +14,15 @@
|
|||||||
#include <tracy/Tracy.hpp>
|
#include <tracy/Tracy.hpp>
|
||||||
|
|
||||||
static inline bool IsProfilerConnected() {
|
static inline bool IsProfilerConnected() {
|
||||||
|
#if TRACY_ENABLE
|
||||||
return tracy::GetProfiler().IsConnected();
|
return tracy::GetProfiler().IsConnected();
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define TRACY_GPU_ENABLED 0
|
||||||
|
|
||||||
#define CUSTOM_LOCK(type, varname) \
|
#define CUSTOM_LOCK(type, varname) \
|
||||||
tracy::LockableCtx varname { \
|
tracy::LockableCtx varname { \
|
||||||
[]() -> const tracy::SourceLocationData* { \
|
[]() -> const tracy::SourceLocationData* { \
|
||||||
@@ -41,7 +47,7 @@ enum MarkersPalette : int {
|
|||||||
#define RENDERER_TRACE ZoneScopedC(RendererMarkerColor)
|
#define RENDERER_TRACE ZoneScopedC(RendererMarkerColor)
|
||||||
#define HLE_TRACE ZoneScopedC(HleMarkerColor)
|
#define HLE_TRACE ZoneScopedC(HleMarkerColor)
|
||||||
|
|
||||||
#define TRACE_HINT(str) ZoneText(str.c_str(), str.size())
|
#define TRACE_HINT(str) ZoneText(str.data(), str.size())
|
||||||
|
|
||||||
#define TRACE_WARN(msg) \
|
#define TRACE_WARN(msg) \
|
||||||
[](const auto& msg) { TracyMessageC(msg.c_str(), msg.size(), tracy::Color::DarkOrange); }(msg);
|
[](const auto& msg) { TracyMessageC(msg.c_str(), msg.size(), tracy::Color::DarkOrange); }(msg);
|
||||||
@@ -57,3 +63,11 @@ enum MarkersPalette : int {
|
|||||||
tracy::SourceLocationData{nullptr, name, TracyFile, (uint32_t)TracyLine, 0};
|
tracy::SourceLocationData{nullptr, name, TracyFile, (uint32_t)TracyLine, 0};
|
||||||
|
|
||||||
#define FRAME_END FrameMark
|
#define FRAME_END FrameMark
|
||||||
|
|
||||||
|
#ifdef TRACY_FIBERS
|
||||||
|
#define FIBER_ENTER(name) TracyFiberEnter(name)
|
||||||
|
#define FIBER_EXIT TracyFiberLeave
|
||||||
|
#else
|
||||||
|
#define FIBER_ENTER(name)
|
||||||
|
#define FIBER_EXIT
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -13,6 +13,15 @@ DecoderImpl::DecoderImpl() {
|
|||||||
|
|
||||||
DecoderImpl::~DecoderImpl() = default;
|
DecoderImpl::~DecoderImpl() = default;
|
||||||
|
|
||||||
|
std::string DecoderImpl::disassembleInst(ZydisDecodedInstruction& inst,
|
||||||
|
ZydisDecodedOperand* operands, u64 address) {
|
||||||
|
const int bufLen = 256;
|
||||||
|
char szBuffer[bufLen];
|
||||||
|
ZydisFormatterFormatInstruction(&m_formatter, &inst, operands, inst.operand_count_visible,
|
||||||
|
szBuffer, sizeof(szBuffer), address, ZYAN_NULL);
|
||||||
|
return szBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
void DecoderImpl::printInstruction(void* code, u64 address) {
|
void DecoderImpl::printInstruction(void* code, u64 address) {
|
||||||
ZydisDecodedInstruction instruction;
|
ZydisDecodedInstruction instruction;
|
||||||
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT_VISIBLE];
|
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT_VISIBLE];
|
||||||
@@ -27,11 +36,8 @@ void DecoderImpl::printInstruction(void* code, u64 address) {
|
|||||||
|
|
||||||
void DecoderImpl::printInst(ZydisDecodedInstruction& inst, ZydisDecodedOperand* operands,
|
void DecoderImpl::printInst(ZydisDecodedInstruction& inst, ZydisDecodedOperand* operands,
|
||||||
u64 address) {
|
u64 address) {
|
||||||
const int bufLen = 256;
|
std::string s = disassembleInst(inst, operands, address);
|
||||||
char szBuffer[bufLen];
|
fmt::print("instruction: {}\n", s);
|
||||||
ZydisFormatterFormatInstruction(&m_formatter, &inst, operands, inst.operand_count_visible,
|
|
||||||
szBuffer, sizeof(szBuffer), address, ZYAN_NULL);
|
|
||||||
fmt::print("instruction: {}\n", szBuffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ZyanStatus DecoderImpl::decodeInstruction(ZydisDecodedInstruction& inst,
|
ZyanStatus DecoderImpl::decodeInstruction(ZydisDecodedInstruction& inst,
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ public:
|
|||||||
DecoderImpl();
|
DecoderImpl();
|
||||||
~DecoderImpl();
|
~DecoderImpl();
|
||||||
|
|
||||||
|
std::string disassembleInst(ZydisDecodedInstruction& inst, ZydisDecodedOperand* operands,
|
||||||
|
u64 address);
|
||||||
void printInst(ZydisDecodedInstruction& inst, ZydisDecodedOperand* operands, u64 address);
|
void printInst(ZydisDecodedInstruction& inst, ZydisDecodedOperand* operands, u64 address);
|
||||||
void printInstruction(void* code, u64 address);
|
void printInstruction(void* code, u64 address);
|
||||||
ZyanStatus decodeInstruction(ZydisDecodedInstruction& inst, ZydisDecodedOperand* operands,
|
ZyanStatus decodeInstruction(ZydisDecodedInstruction& inst, ZydisDecodedOperand* operands,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include "src/common/discord_rpc_handler.h"
|
#include "discord_rpc_handler.h"
|
||||||
|
|
||||||
namespace DiscordRPCHandler {
|
namespace DiscordRPCHandler {
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ void RPC::init() {
|
|||||||
|
|
||||||
void RPC::setStatusIdling() {
|
void RPC::setStatusIdling() {
|
||||||
DiscordRichPresence rpc{};
|
DiscordRichPresence rpc{};
|
||||||
rpc.largeImageKey = "https://github.com/shadps4-emu/shadPS4/raw/main/.github/shadps4.png";
|
rpc.largeImageKey = "https://cdn.jsdelivr.net/gh/shadps4-emu/shadPS4@main/.github/shadps4.png";
|
||||||
rpc.largeImageText = "shadPS4 is a PS4 emulator";
|
rpc.largeImageText = "shadPS4 is a PS4 emulator";
|
||||||
rpc.startTimestamp = startTimestamp;
|
rpc.startTimestamp = startTimestamp;
|
||||||
rpc.details = "Idle";
|
rpc.details = "Idle";
|
||||||
|
|||||||
14
src/common/hash.h
Normal file
14
src/common/hash.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/types.h"
|
||||||
|
|
||||||
|
[[nodiscard]] inline u64 HashCombine(const u64 seed, const u64 hash) {
|
||||||
|
return seed ^ (hash + 0x9e3779b9 + (seed << 12) + (seed >> 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline u32 HashCombine(const u32 seed, const u32 hash) {
|
||||||
|
return seed ^ (hash + 0x9e3779b9 + (seed << 6) + (seed >> 2));
|
||||||
|
}
|
||||||
@@ -377,16 +377,18 @@ bool IOFile::Seek(s64 offset, SeekOrigin origin) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 size = GetSize();
|
if (False(file_access_mode & (FileAccessMode::Write | FileAccessMode::Append))) {
|
||||||
if (origin == SeekOrigin::CurrentPosition && Tell() + offset > size) {
|
u64 size = GetSize();
|
||||||
LOG_ERROR(Common_Filesystem, "Seeking past the end of the file");
|
if (origin == SeekOrigin::CurrentPosition && Tell() + offset > size) {
|
||||||
return false;
|
LOG_ERROR(Common_Filesystem, "Seeking past the end of the file");
|
||||||
} else if (origin == SeekOrigin::SetOrigin && (u64)offset > size) {
|
return false;
|
||||||
LOG_ERROR(Common_Filesystem, "Seeking past the end of the file");
|
} else if (origin == SeekOrigin::SetOrigin && (u64)offset > size) {
|
||||||
return false;
|
LOG_ERROR(Common_Filesystem, "Seeking past the end of the file");
|
||||||
} else if (origin == SeekOrigin::End && offset > 0) {
|
return false;
|
||||||
LOG_ERROR(Common_Filesystem, "Seeking past the end of the file");
|
} else if (origin == SeekOrigin::End && offset > 0) {
|
||||||
return false;
|
LOG_ERROR(Common_Filesystem, "Seeking past the end of the file");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include "common/concepts.h"
|
#include "common/concepts.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
|
#include "enum.h"
|
||||||
|
|
||||||
namespace Common::FS {
|
namespace Common::FS {
|
||||||
|
|
||||||
@@ -42,6 +43,7 @@ enum class FileAccessMode {
|
|||||||
*/
|
*/
|
||||||
ReadAppend = Read | Append,
|
ReadAppend = Read | Append,
|
||||||
};
|
};
|
||||||
|
DECLARE_ENUM_FLAG_OPERATORS(FileAccessMode);
|
||||||
|
|
||||||
enum class FileType {
|
enum class FileType {
|
||||||
BinaryFile,
|
BinaryFile,
|
||||||
@@ -205,7 +207,7 @@ public:
|
|||||||
return WriteSpan(string);
|
return WriteSpan(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t WriteBytes(const std::filesystem::path path, std::span<const u8> data) {
|
static size_t WriteBytes(const std::filesystem::path path, const auto& data) {
|
||||||
IOFile out(path, FileAccessMode::Write);
|
IOFile out(path, FileAccessMode::Write);
|
||||||
return out.Write(data);
|
return out.Write(data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
|||||||
SUB(Common, Memory) \
|
SUB(Common, Memory) \
|
||||||
CLS(Core) \
|
CLS(Core) \
|
||||||
SUB(Core, Linker) \
|
SUB(Core, Linker) \
|
||||||
|
SUB(Core, Devices) \
|
||||||
CLS(Config) \
|
CLS(Config) \
|
||||||
CLS(Debug) \
|
CLS(Debug) \
|
||||||
CLS(Kernel) \
|
CLS(Kernel) \
|
||||||
@@ -105,7 +106,9 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
|||||||
SUB(Lib, Rtc) \
|
SUB(Lib, Rtc) \
|
||||||
SUB(Lib, DiscMap) \
|
SUB(Lib, DiscMap) \
|
||||||
SUB(Lib, Png) \
|
SUB(Lib, Png) \
|
||||||
|
SUB(Lib, Jpeg) \
|
||||||
SUB(Lib, PlayGo) \
|
SUB(Lib, PlayGo) \
|
||||||
|
SUB(Lib, PlayGoDialog) \
|
||||||
SUB(Lib, Random) \
|
SUB(Lib, Random) \
|
||||||
SUB(Lib, Usbd) \
|
SUB(Lib, Usbd) \
|
||||||
SUB(Lib, Ajm) \
|
SUB(Lib, Ajm) \
|
||||||
@@ -120,6 +123,8 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
|||||||
SUB(Lib, SharePlay) \
|
SUB(Lib, SharePlay) \
|
||||||
SUB(Lib, Fiber) \
|
SUB(Lib, Fiber) \
|
||||||
SUB(Lib, Vdec2) \
|
SUB(Lib, Vdec2) \
|
||||||
|
SUB(Lib, Videodec) \
|
||||||
|
SUB(Lib, RazorCpu) \
|
||||||
CLS(Frontend) \
|
CLS(Frontend) \
|
||||||
CLS(Render) \
|
CLS(Render) \
|
||||||
SUB(Render, Vulkan) \
|
SUB(Render, Vulkan) \
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ enum class Class : u8 {
|
|||||||
Common_Memory, ///< Memory mapping and management functions
|
Common_Memory, ///< Memory mapping and management functions
|
||||||
Core, ///< LLE emulation core
|
Core, ///< LLE emulation core
|
||||||
Core_Linker, ///< The module linker
|
Core_Linker, ///< The module linker
|
||||||
|
Core_Devices, ///< Devices emulation
|
||||||
Config, ///< Emulator configuration (including commandline)
|
Config, ///< Emulator configuration (including commandline)
|
||||||
Debug, ///< Debugging tools
|
Debug, ///< Debugging tools
|
||||||
Kernel, ///< The HLE implementation of the PS4 kernel.
|
Kernel, ///< The HLE implementation of the PS4 kernel.
|
||||||
@@ -72,7 +73,9 @@ enum class Class : u8 {
|
|||||||
Lib_Rtc, ///< The LibSceRtc implementation.
|
Lib_Rtc, ///< The LibSceRtc implementation.
|
||||||
Lib_DiscMap, ///< The LibSceDiscMap implementation.
|
Lib_DiscMap, ///< The LibSceDiscMap implementation.
|
||||||
Lib_Png, ///< The LibScePng implementation.
|
Lib_Png, ///< The LibScePng implementation.
|
||||||
|
Lib_Jpeg, ///< The LibSceJpeg implementation.
|
||||||
Lib_PlayGo, ///< The LibScePlayGo implementation.
|
Lib_PlayGo, ///< The LibScePlayGo implementation.
|
||||||
|
Lib_PlayGoDialog, ///< The LibScePlayGoDialog implementation.
|
||||||
Lib_Random, ///< The libSceRandom implementation.
|
Lib_Random, ///< The libSceRandom implementation.
|
||||||
Lib_Usbd, ///< The LibSceUsbd implementation.
|
Lib_Usbd, ///< The LibSceUsbd implementation.
|
||||||
Lib_Ajm, ///< The LibSceAjm implementation.
|
Lib_Ajm, ///< The LibSceAjm implementation.
|
||||||
@@ -87,6 +90,8 @@ enum class Class : u8 {
|
|||||||
Lib_SharePlay, ///< The LibSceSharePlay implemenation
|
Lib_SharePlay, ///< The LibSceSharePlay implemenation
|
||||||
Lib_Fiber, ///< The LibSceFiber implementation.
|
Lib_Fiber, ///< The LibSceFiber implementation.
|
||||||
Lib_Vdec2, ///< The LibSceVideodec2 implementation.
|
Lib_Vdec2, ///< The LibSceVideodec2 implementation.
|
||||||
|
Lib_Videodec, ///< The LibSceVideodec implementation.
|
||||||
|
Lib_RazorCpu, ///< The LibRazorCpu implementation.
|
||||||
Frontend, ///< Emulator UI
|
Frontend, ///< Emulator UI
|
||||||
Render, ///< Video Core
|
Render, ///< Video Core
|
||||||
Render_Vulkan, ///< Vulkan backend
|
Render_Vulkan, ///< Vulkan backend
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ std::string g_game_serial;
|
|||||||
std::string patchFile;
|
std::string patchFile;
|
||||||
std::vector<patchInfo> pending_patches;
|
std::vector<patchInfo> pending_patches;
|
||||||
|
|
||||||
std::string toHex(unsigned long long value, size_t byteSize) {
|
std::string toHex(u64 value, size_t byteSize) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << std::hex << std::setfill('0') << std::setw(byteSize * 2) << value;
|
ss << std::hex << std::setfill('0') << std::setw(byteSize * 2) << value;
|
||||||
return ss.str();
|
return ss.str();
|
||||||
@@ -38,16 +38,16 @@ std::string convertValueToHex(const std::string type, const std::string valueStr
|
|||||||
std::string result;
|
std::string result;
|
||||||
|
|
||||||
if (type == "byte") {
|
if (type == "byte") {
|
||||||
unsigned int value = std::stoul(valueStr, nullptr, 16);
|
const u32 value = std::stoul(valueStr, nullptr, 16);
|
||||||
result = toHex(value, 1);
|
result = toHex(value, 1);
|
||||||
} else if (type == "bytes16") {
|
} else if (type == "bytes16") {
|
||||||
unsigned int value = std::stoul(valueStr, nullptr, 16);
|
const u32 value = std::stoul(valueStr, nullptr, 16);
|
||||||
result = toHex(value, 2);
|
result = toHex(value, 2);
|
||||||
} else if (type == "bytes32") {
|
} else if (type == "bytes32") {
|
||||||
unsigned long value = std::stoul(valueStr, nullptr, 16);
|
const u32 value = std::stoul(valueStr, nullptr, 16);
|
||||||
result = toHex(value, 4);
|
result = toHex(value, 4);
|
||||||
} else if (type == "bytes64") {
|
} else if (type == "bytes64") {
|
||||||
unsigned long long value = std::stoull(valueStr, nullptr, 16);
|
const u64 value = std::stoull(valueStr, nullptr, 16);
|
||||||
result = toHex(value, 8);
|
result = toHex(value, 8);
|
||||||
} else if (type == "float32") {
|
} else if (type == "float32") {
|
||||||
union {
|
union {
|
||||||
|
|||||||
@@ -5,8 +5,11 @@
|
|||||||
|
|
||||||
#include "ntapi.h"
|
#include "ntapi.h"
|
||||||
|
|
||||||
NtDelayExecution_t NtDelayExecution = nullptr;
|
NtClose_t NtClose = nullptr;
|
||||||
NtSetInformationFile_t NtSetInformationFile = nullptr;
|
NtSetInformationFile_t NtSetInformationFile = nullptr;
|
||||||
|
NtCreateThread_t NtCreateThread = nullptr;
|
||||||
|
NtTerminateThread_t NtTerminateThread = nullptr;
|
||||||
|
NtQueueApcThreadEx_t NtQueueApcThreadEx = nullptr;
|
||||||
|
|
||||||
namespace Common::NtApi {
|
namespace Common::NtApi {
|
||||||
|
|
||||||
@@ -14,9 +17,12 @@ void Initialize() {
|
|||||||
HMODULE nt_handle = GetModuleHandleA("ntdll.dll");
|
HMODULE nt_handle = GetModuleHandleA("ntdll.dll");
|
||||||
|
|
||||||
// http://stackoverflow.com/a/31411628/4725495
|
// http://stackoverflow.com/a/31411628/4725495
|
||||||
NtDelayExecution = (NtDelayExecution_t)GetProcAddress(nt_handle, "NtDelayExecution");
|
NtClose = (NtClose_t)GetProcAddress(nt_handle, "NtClose");
|
||||||
NtSetInformationFile =
|
NtSetInformationFile =
|
||||||
(NtSetInformationFile_t)GetProcAddress(nt_handle, "NtSetInformationFile");
|
(NtSetInformationFile_t)GetProcAddress(nt_handle, "NtSetInformationFile");
|
||||||
|
NtCreateThread = (NtCreateThread_t)GetProcAddress(nt_handle, "NtCreateThread");
|
||||||
|
NtTerminateThread = (NtTerminateThread_t)GetProcAddress(nt_handle, "NtTerminateThread");
|
||||||
|
NtQueueApcThreadEx = (NtQueueApcThreadEx_t)GetProcAddress(nt_handle, "NtQueueApcThreadEx");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Common::NtApi
|
} // namespace Common::NtApi
|
||||||
|
|||||||
@@ -108,14 +108,444 @@ typedef struct _FILE_DISPOSITION_INFORMATION {
|
|||||||
BOOLEAN DeleteFile;
|
BOOLEAN DeleteFile;
|
||||||
} FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION;
|
} FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION;
|
||||||
|
|
||||||
typedef u32(__stdcall* NtDelayExecution_t)(BOOL Alertable, PLARGE_INTEGER DelayInterval);
|
typedef struct _UNICODE_STRING {
|
||||||
|
USHORT Length;
|
||||||
|
USHORT MaximumLength;
|
||||||
|
PWCH Buffer;
|
||||||
|
} UNICODE_STRING, *PUNICODE_STRING;
|
||||||
|
|
||||||
typedef u32(__stdcall* NtSetInformationFile_t)(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock,
|
typedef const UNICODE_STRING* PCUNICODE_STRING;
|
||||||
|
|
||||||
|
typedef struct _OBJECT_ATTRIBUTES {
|
||||||
|
ULONG Length;
|
||||||
|
HANDLE RootDirectory;
|
||||||
|
PCUNICODE_STRING ObjectName;
|
||||||
|
ULONG Attributes;
|
||||||
|
PVOID SecurityDescriptor; // PSECURITY_DESCRIPTOR;
|
||||||
|
PVOID SecurityQualityOfService; // PSECURITY_QUALITY_OF_SERVICE
|
||||||
|
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
|
||||||
|
|
||||||
|
typedef const OBJECT_ATTRIBUTES* PCOBJECT_ATTRIBUTES;
|
||||||
|
|
||||||
|
typedef struct _CLIENT_ID {
|
||||||
|
HANDLE UniqueProcess;
|
||||||
|
HANDLE UniqueThread;
|
||||||
|
} CLIENT_ID, *PCLIENT_ID;
|
||||||
|
|
||||||
|
typedef struct _INITIAL_TEB {
|
||||||
|
struct {
|
||||||
|
PVOID OldStackBase;
|
||||||
|
PVOID OldStackLimit;
|
||||||
|
} OldInitialTeb;
|
||||||
|
PVOID StackBase;
|
||||||
|
PVOID StackLimit;
|
||||||
|
PVOID StackAllocationBase;
|
||||||
|
} INITIAL_TEB, *PINITIAL_TEB;
|
||||||
|
|
||||||
|
typedef struct _PEB_LDR_DATA {
|
||||||
|
ULONG Length;
|
||||||
|
BOOLEAN Initialized;
|
||||||
|
PVOID SsHandle;
|
||||||
|
LIST_ENTRY InLoadOrderModuleList;
|
||||||
|
LIST_ENTRY InMemoryOrderModuleList;
|
||||||
|
LIST_ENTRY InInitializationOrderModuleList;
|
||||||
|
PVOID EntryInProgress;
|
||||||
|
BOOLEAN ShutdownInProgress;
|
||||||
|
HANDLE ShutdownThreadId;
|
||||||
|
} PEB_LDR_DATA, *PPEB_LDR_DATA;
|
||||||
|
|
||||||
|
typedef struct _CURDIR {
|
||||||
|
UNICODE_STRING DosPath;
|
||||||
|
PVOID Handle;
|
||||||
|
} CURDIR, *PCURDIR;
|
||||||
|
|
||||||
|
typedef struct RTL_DRIVE_LETTER_CURDIR {
|
||||||
|
USHORT Flags;
|
||||||
|
USHORT Length;
|
||||||
|
ULONG TimeStamp;
|
||||||
|
UNICODE_STRING DosPath;
|
||||||
|
} RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR;
|
||||||
|
|
||||||
|
typedef struct _RTL_USER_PROCESS_PARAMETERS {
|
||||||
|
ULONG AllocationSize;
|
||||||
|
ULONG Size;
|
||||||
|
ULONG Flags;
|
||||||
|
ULONG DebugFlags;
|
||||||
|
HANDLE ConsoleHandle;
|
||||||
|
ULONG ConsoleFlags;
|
||||||
|
HANDLE hStdInput;
|
||||||
|
HANDLE hStdOutput;
|
||||||
|
HANDLE hStdError;
|
||||||
|
CURDIR CurrentDirectory;
|
||||||
|
UNICODE_STRING DllPath;
|
||||||
|
UNICODE_STRING ImagePathName;
|
||||||
|
UNICODE_STRING CommandLine;
|
||||||
|
PWSTR Environment;
|
||||||
|
ULONG dwX;
|
||||||
|
ULONG dwY;
|
||||||
|
ULONG dwXSize;
|
||||||
|
ULONG dwYSize;
|
||||||
|
ULONG dwXCountChars;
|
||||||
|
ULONG dwYCountChars;
|
||||||
|
ULONG dwFillAttribute;
|
||||||
|
ULONG dwFlags;
|
||||||
|
ULONG wShowWindow;
|
||||||
|
UNICODE_STRING WindowTitle;
|
||||||
|
UNICODE_STRING Desktop;
|
||||||
|
UNICODE_STRING ShellInfo;
|
||||||
|
UNICODE_STRING RuntimeInfo;
|
||||||
|
RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20];
|
||||||
|
ULONG_PTR EnvironmentSize;
|
||||||
|
ULONG_PTR EnvironmentVersion;
|
||||||
|
PVOID PackageDependencyData;
|
||||||
|
ULONG ProcessGroupId;
|
||||||
|
ULONG LoaderThreads;
|
||||||
|
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
|
||||||
|
|
||||||
|
typedef struct tagRTL_BITMAP {
|
||||||
|
ULONG SizeOfBitMap;
|
||||||
|
PULONG Buffer;
|
||||||
|
} RTL_BITMAP, *PRTL_BITMAP;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT next;
|
||||||
|
UINT id;
|
||||||
|
ULONGLONG addr;
|
||||||
|
ULONGLONG size;
|
||||||
|
UINT args[4];
|
||||||
|
} CROSS_PROCESS_WORK_ENTRY;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
struct {
|
||||||
|
UINT first;
|
||||||
|
UINT counter;
|
||||||
|
};
|
||||||
|
volatile LONGLONG hdr;
|
||||||
|
} CROSS_PROCESS_WORK_HDR;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
CROSS_PROCESS_WORK_HDR free_list;
|
||||||
|
CROSS_PROCESS_WORK_HDR work_list;
|
||||||
|
ULONGLONG unknown[4];
|
||||||
|
CROSS_PROCESS_WORK_ENTRY entries[1];
|
||||||
|
} CROSS_PROCESS_WORK_LIST;
|
||||||
|
|
||||||
|
typedef struct _CHPEV2_PROCESS_INFO {
|
||||||
|
ULONG Wow64ExecuteFlags; /* 000 */
|
||||||
|
USHORT NativeMachineType; /* 004 */
|
||||||
|
USHORT EmulatedMachineType; /* 006 */
|
||||||
|
HANDLE SectionHandle; /* 008 */
|
||||||
|
CROSS_PROCESS_WORK_LIST* CrossProcessWorkList; /* 010 */
|
||||||
|
void* unknown; /* 018 */
|
||||||
|
} CHPEV2_PROCESS_INFO, *PCHPEV2_PROCESS_INFO;
|
||||||
|
|
||||||
|
typedef u64(__stdcall* KERNEL_CALLBACK_PROC)(void*, ULONG);
|
||||||
|
|
||||||
|
typedef struct _PEB { /* win32/win64 */
|
||||||
|
BOOLEAN InheritedAddressSpace; /* 000/000 */
|
||||||
|
BOOLEAN ReadImageFileExecOptions; /* 001/001 */
|
||||||
|
BOOLEAN BeingDebugged; /* 002/002 */
|
||||||
|
UCHAR ImageUsedLargePages : 1; /* 003/003 */
|
||||||
|
UCHAR IsProtectedProcess : 1;
|
||||||
|
UCHAR IsImageDynamicallyRelocated : 1;
|
||||||
|
UCHAR SkipPatchingUser32Forwarders : 1;
|
||||||
|
UCHAR IsPackagedProcess : 1;
|
||||||
|
UCHAR IsAppContainer : 1;
|
||||||
|
UCHAR IsProtectedProcessLight : 1;
|
||||||
|
UCHAR IsLongPathAwareProcess : 1;
|
||||||
|
HANDLE Mutant; /* 004/008 */
|
||||||
|
HMODULE ImageBaseAddress; /* 008/010 */
|
||||||
|
PPEB_LDR_DATA LdrData; /* 00c/018 */
|
||||||
|
RTL_USER_PROCESS_PARAMETERS* ProcessParameters; /* 010/020 */
|
||||||
|
PVOID SubSystemData; /* 014/028 */
|
||||||
|
HANDLE ProcessHeap; /* 018/030 */
|
||||||
|
PRTL_CRITICAL_SECTION FastPebLock; /* 01c/038 */
|
||||||
|
PVOID AtlThunkSListPtr; /* 020/040 */
|
||||||
|
PVOID IFEOKey; /* 024/048 */
|
||||||
|
ULONG ProcessInJob : 1; /* 028/050 */
|
||||||
|
ULONG ProcessInitializing : 1;
|
||||||
|
ULONG ProcessUsingVEH : 1;
|
||||||
|
ULONG ProcessUsingVCH : 1;
|
||||||
|
ULONG ProcessUsingFTH : 1;
|
||||||
|
ULONG ProcessPreviouslyThrottled : 1;
|
||||||
|
ULONG ProcessCurrentlyThrottled : 1;
|
||||||
|
ULONG ProcessImagesHotPatched : 1;
|
||||||
|
ULONG ReservedBits0 : 24;
|
||||||
|
KERNEL_CALLBACK_PROC* KernelCallbackTable; /* 02c/058 */
|
||||||
|
ULONG Reserved; /* 030/060 */
|
||||||
|
ULONG AtlThunkSListPtr32; /* 034/064 */
|
||||||
|
PVOID ApiSetMap; /* 038/068 */
|
||||||
|
ULONG TlsExpansionCounter; /* 03c/070 */
|
||||||
|
PRTL_BITMAP TlsBitmap; /* 040/078 */
|
||||||
|
ULONG TlsBitmapBits[2]; /* 044/080 */
|
||||||
|
PVOID ReadOnlySharedMemoryBase; /* 04c/088 */
|
||||||
|
PVOID SharedData; /* 050/090 */
|
||||||
|
PVOID* ReadOnlyStaticServerData; /* 054/098 */
|
||||||
|
PVOID AnsiCodePageData; /* 058/0a0 */
|
||||||
|
PVOID OemCodePageData; /* 05c/0a8 */
|
||||||
|
PVOID UnicodeCaseTableData; /* 060/0b0 */
|
||||||
|
ULONG NumberOfProcessors; /* 064/0b8 */
|
||||||
|
ULONG NtGlobalFlag; /* 068/0bc */
|
||||||
|
LARGE_INTEGER CriticalSectionTimeout; /* 070/0c0 */
|
||||||
|
SIZE_T HeapSegmentReserve; /* 078/0c8 */
|
||||||
|
SIZE_T HeapSegmentCommit; /* 07c/0d0 */
|
||||||
|
SIZE_T HeapDeCommitTotalFreeThreshold; /* 080/0d8 */
|
||||||
|
SIZE_T HeapDeCommitFreeBlockThreshold; /* 084/0e0 */
|
||||||
|
ULONG NumberOfHeaps; /* 088/0e8 */
|
||||||
|
ULONG MaximumNumberOfHeaps; /* 08c/0ec */
|
||||||
|
PVOID* ProcessHeaps; /* 090/0f0 */
|
||||||
|
PVOID GdiSharedHandleTable; /* 094/0f8 */
|
||||||
|
PVOID ProcessStarterHelper; /* 098/100 */
|
||||||
|
PVOID GdiDCAttributeList; /* 09c/108 */
|
||||||
|
PVOID LoaderLock; /* 0a0/110 */
|
||||||
|
ULONG OSMajorVersion; /* 0a4/118 */
|
||||||
|
ULONG OSMinorVersion; /* 0a8/11c */
|
||||||
|
ULONG OSBuildNumber; /* 0ac/120 */
|
||||||
|
ULONG OSPlatformId; /* 0b0/124 */
|
||||||
|
ULONG ImageSubSystem; /* 0b4/128 */
|
||||||
|
ULONG ImageSubSystemMajorVersion; /* 0b8/12c */
|
||||||
|
ULONG ImageSubSystemMinorVersion; /* 0bc/130 */
|
||||||
|
KAFFINITY ActiveProcessAffinityMask; /* 0c0/138 */
|
||||||
|
#ifdef _WIN64
|
||||||
|
ULONG GdiHandleBuffer[60]; /* /140 */
|
||||||
|
#else
|
||||||
|
ULONG GdiHandleBuffer[34]; /* 0c4/ */
|
||||||
|
#endif
|
||||||
|
PVOID PostProcessInitRoutine; /* 14c/230 */
|
||||||
|
PRTL_BITMAP TlsExpansionBitmap; /* 150/238 */
|
||||||
|
ULONG TlsExpansionBitmapBits[32]; /* 154/240 */
|
||||||
|
ULONG SessionId; /* 1d4/2c0 */
|
||||||
|
ULARGE_INTEGER AppCompatFlags; /* 1d8/2c8 */
|
||||||
|
ULARGE_INTEGER AppCompatFlagsUser; /* 1e0/2d0 */
|
||||||
|
PVOID ShimData; /* 1e8/2d8 */
|
||||||
|
PVOID AppCompatInfo; /* 1ec/2e0 */
|
||||||
|
UNICODE_STRING CSDVersion; /* 1f0/2e8 */
|
||||||
|
PVOID ActivationContextData; /* 1f8/2f8 */
|
||||||
|
PVOID ProcessAssemblyStorageMap; /* 1fc/300 */
|
||||||
|
PVOID SystemDefaultActivationData; /* 200/308 */
|
||||||
|
PVOID SystemAssemblyStorageMap; /* 204/310 */
|
||||||
|
SIZE_T MinimumStackCommit; /* 208/318 */
|
||||||
|
PVOID* FlsCallback; /* 20c/320 */
|
||||||
|
LIST_ENTRY FlsListHead; /* 210/328 */
|
||||||
|
union {
|
||||||
|
PRTL_BITMAP FlsBitmap; /* 218/338 */
|
||||||
|
#ifdef _WIN64
|
||||||
|
CHPEV2_PROCESS_INFO* ChpeV2ProcessInfo; /* /338 */
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
ULONG FlsBitmapBits[4]; /* 21c/340 */
|
||||||
|
ULONG FlsHighIndex; /* 22c/350 */
|
||||||
|
PVOID WerRegistrationData; /* 230/358 */
|
||||||
|
PVOID WerShipAssertPtr; /* 234/360 */
|
||||||
|
PVOID EcCodeBitMap; /* 238/368 */
|
||||||
|
PVOID pImageHeaderHash; /* 23c/370 */
|
||||||
|
ULONG HeapTracingEnabled : 1; /* 240/378 */
|
||||||
|
ULONG CritSecTracingEnabled : 1;
|
||||||
|
ULONG LibLoaderTracingEnabled : 1;
|
||||||
|
ULONG SpareTracingBits : 29;
|
||||||
|
ULONGLONG CsrServerReadOnlySharedMemoryBase; /* 248/380 */
|
||||||
|
ULONG TppWorkerpListLock; /* 250/388 */
|
||||||
|
LIST_ENTRY TppWorkerpList; /* 254/390 */
|
||||||
|
PVOID WaitOnAddressHashTable[0x80]; /* 25c/3a0 */
|
||||||
|
PVOID TelemetryCoverageHeader; /* 45c/7a0 */
|
||||||
|
ULONG CloudFileFlags; /* 460/7a8 */
|
||||||
|
ULONG CloudFileDiagFlags; /* 464/7ac */
|
||||||
|
CHAR PlaceholderCompatibilityMode; /* 468/7b0 */
|
||||||
|
CHAR PlaceholderCompatibilityModeReserved[7]; /* 469/7b1 */
|
||||||
|
PVOID LeapSecondData; /* 470/7b8 */
|
||||||
|
ULONG LeapSecondFlags; /* 474/7c0 */
|
||||||
|
ULONG NtGlobalFlag2; /* 478/7c4 */
|
||||||
|
} PEB, *PPEB;
|
||||||
|
|
||||||
|
typedef struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME {
|
||||||
|
struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME* Previous;
|
||||||
|
struct _ACTIVATION_CONTEXT* ActivationContext;
|
||||||
|
ULONG Flags;
|
||||||
|
} RTL_ACTIVATION_CONTEXT_STACK_FRAME, *PRTL_ACTIVATION_CONTEXT_STACK_FRAME;
|
||||||
|
|
||||||
|
typedef struct _ACTIVATION_CONTEXT_STACK {
|
||||||
|
RTL_ACTIVATION_CONTEXT_STACK_FRAME* ActiveFrame;
|
||||||
|
LIST_ENTRY FrameListCache;
|
||||||
|
ULONG Flags;
|
||||||
|
ULONG NextCookieSequenceNumber;
|
||||||
|
ULONG_PTR StackId;
|
||||||
|
} ACTIVATION_CONTEXT_STACK, *PACTIVATION_CONTEXT_STACK;
|
||||||
|
|
||||||
|
typedef struct _GDI_TEB_BATCH {
|
||||||
|
ULONG Offset;
|
||||||
|
HANDLE HDC;
|
||||||
|
ULONG Buffer[0x136];
|
||||||
|
} GDI_TEB_BATCH;
|
||||||
|
|
||||||
|
typedef struct _TEB_ACTIVE_FRAME_CONTEXT {
|
||||||
|
ULONG Flags;
|
||||||
|
const char* FrameName;
|
||||||
|
} TEB_ACTIVE_FRAME_CONTEXT, *PTEB_ACTIVE_FRAME_CONTEXT;
|
||||||
|
|
||||||
|
typedef struct _TEB_ACTIVE_FRAME {
|
||||||
|
ULONG Flags;
|
||||||
|
struct _TEB_ACTIVE_FRAME* Previous;
|
||||||
|
TEB_ACTIVE_FRAME_CONTEXT* Context;
|
||||||
|
} TEB_ACTIVE_FRAME, *PTEB_ACTIVE_FRAME;
|
||||||
|
|
||||||
|
typedef struct _TEB { /* win32/win64 */
|
||||||
|
NT_TIB Tib; /* 000/0000 */
|
||||||
|
PVOID EnvironmentPointer; /* 01c/0038 */
|
||||||
|
CLIENT_ID ClientId; /* 020/0040 */
|
||||||
|
PVOID ActiveRpcHandle; /* 028/0050 */
|
||||||
|
PVOID ThreadLocalStoragePointer; /* 02c/0058 */
|
||||||
|
PPEB Peb; /* 030/0060 */
|
||||||
|
ULONG LastErrorValue; /* 034/0068 */
|
||||||
|
ULONG CountOfOwnedCriticalSections; /* 038/006c */
|
||||||
|
PVOID CsrClientThread; /* 03c/0070 */
|
||||||
|
PVOID Win32ThreadInfo; /* 040/0078 */
|
||||||
|
ULONG User32Reserved[26]; /* 044/0080 */
|
||||||
|
ULONG UserReserved[5]; /* 0ac/00e8 */
|
||||||
|
PVOID WOW32Reserved; /* 0c0/0100 */
|
||||||
|
ULONG CurrentLocale; /* 0c4/0108 */
|
||||||
|
ULONG FpSoftwareStatusRegister; /* 0c8/010c */
|
||||||
|
PVOID ReservedForDebuggerInstrumentation[16]; /* 0cc/0110 */
|
||||||
|
#ifdef _WIN64
|
||||||
|
PVOID SystemReserved1[30]; /* /0190 */
|
||||||
|
#else
|
||||||
|
PVOID SystemReserved1[26]; /* 10c/ */
|
||||||
|
#endif
|
||||||
|
char PlaceholderCompatibilityMode; /* 174/0280 */
|
||||||
|
BOOLEAN PlaceholderHydrationAlwaysExplicit; /* 175/0281 */
|
||||||
|
char PlaceholderReserved[10]; /* 176/0282 */
|
||||||
|
DWORD ProxiedProcessId; /* 180/028c */
|
||||||
|
ACTIVATION_CONTEXT_STACK ActivationContextStack; /* 184/0290 */
|
||||||
|
UCHAR WorkingOnBehalfOfTicket[8]; /* 19c/02b8 */
|
||||||
|
LONG ExceptionCode; /* 1a4/02c0 */
|
||||||
|
ACTIVATION_CONTEXT_STACK* ActivationContextStackPointer; /* 1a8/02c8 */
|
||||||
|
ULONG_PTR InstrumentationCallbackSp; /* 1ac/02d0 */
|
||||||
|
ULONG_PTR InstrumentationCallbackPreviousPc; /* 1b0/02d8 */
|
||||||
|
ULONG_PTR InstrumentationCallbackPreviousSp; /* 1b4/02e0 */
|
||||||
|
#ifdef _WIN64
|
||||||
|
ULONG TxFsContext; /* /02e8 */
|
||||||
|
BOOLEAN InstrumentationCallbackDisabled; /* /02ec */
|
||||||
|
BOOLEAN UnalignedLoadStoreExceptions; /* /02ed */
|
||||||
|
#else
|
||||||
|
BOOLEAN InstrumentationCallbackDisabled; /* 1b8/ */
|
||||||
|
BYTE SpareBytes1[23]; /* 1b9/ */
|
||||||
|
ULONG TxFsContext; /* 1d0/ */
|
||||||
|
#endif
|
||||||
|
GDI_TEB_BATCH GdiTebBatch; /* 1d4/02f0 */
|
||||||
|
CLIENT_ID RealClientId; /* 6b4/07d8 */
|
||||||
|
HANDLE GdiCachedProcessHandle; /* 6bc/07e8 */
|
||||||
|
ULONG GdiClientPID; /* 6c0/07f0 */
|
||||||
|
ULONG GdiClientTID; /* 6c4/07f4 */
|
||||||
|
PVOID GdiThreadLocaleInfo; /* 6c8/07f8 */
|
||||||
|
ULONG_PTR Win32ClientInfo[62]; /* 6cc/0800 */
|
||||||
|
PVOID glDispatchTable[233]; /* 7c4/09f0 */
|
||||||
|
PVOID glReserved1[29]; /* b68/1138 */
|
||||||
|
PVOID glReserved2; /* bdc/1220 */
|
||||||
|
PVOID glSectionInfo; /* be0/1228 */
|
||||||
|
PVOID glSection; /* be4/1230 */
|
||||||
|
PVOID glTable; /* be8/1238 */
|
||||||
|
PVOID glCurrentRC; /* bec/1240 */
|
||||||
|
PVOID glContext; /* bf0/1248 */
|
||||||
|
ULONG LastStatusValue; /* bf4/1250 */
|
||||||
|
UNICODE_STRING StaticUnicodeString; /* bf8/1258 */
|
||||||
|
WCHAR StaticUnicodeBuffer[261]; /* c00/1268 */
|
||||||
|
PVOID DeallocationStack; /* e0c/1478 */
|
||||||
|
PVOID TlsSlots[64]; /* e10/1480 */
|
||||||
|
LIST_ENTRY TlsLinks; /* f10/1680 */
|
||||||
|
PVOID Vdm; /* f18/1690 */
|
||||||
|
PVOID ReservedForNtRpc; /* f1c/1698 */
|
||||||
|
PVOID DbgSsReserved[2]; /* f20/16a0 */
|
||||||
|
ULONG HardErrorMode; /* f28/16b0 */
|
||||||
|
#ifdef _WIN64
|
||||||
|
PVOID Instrumentation[11]; /* /16b8 */
|
||||||
|
#else
|
||||||
|
PVOID Instrumentation[9]; /* f2c/ */
|
||||||
|
#endif
|
||||||
|
GUID ActivityId; /* f50/1710 */
|
||||||
|
PVOID SubProcessTag; /* f60/1720 */
|
||||||
|
PVOID PerflibData; /* f64/1728 */
|
||||||
|
PVOID EtwTraceData; /* f68/1730 */
|
||||||
|
PVOID WinSockData; /* f6c/1738 */
|
||||||
|
ULONG GdiBatchCount; /* f70/1740 */
|
||||||
|
ULONG IdealProcessorValue; /* f74/1744 */
|
||||||
|
ULONG GuaranteedStackBytes; /* f78/1748 */
|
||||||
|
PVOID ReservedForPerf; /* f7c/1750 */
|
||||||
|
PVOID ReservedForOle; /* f80/1758 */
|
||||||
|
ULONG WaitingOnLoaderLock; /* f84/1760 */
|
||||||
|
PVOID SavedPriorityState; /* f88/1768 */
|
||||||
|
ULONG_PTR ReservedForCodeCoverage; /* f8c/1770 */
|
||||||
|
PVOID ThreadPoolData; /* f90/1778 */
|
||||||
|
PVOID* TlsExpansionSlots; /* f94/1780 */
|
||||||
|
#ifdef _WIN64
|
||||||
|
union {
|
||||||
|
PVOID DeallocationBStore; /* /1788 */
|
||||||
|
PVOID* ChpeV2CpuAreaInfo; /* /1788 */
|
||||||
|
} DUMMYUNIONNAME;
|
||||||
|
PVOID BStoreLimit; /* /1790 */
|
||||||
|
#endif
|
||||||
|
ULONG MuiGeneration; /* f98/1798 */
|
||||||
|
ULONG IsImpersonating; /* f9c/179c */
|
||||||
|
PVOID NlsCache; /* fa0/17a0 */
|
||||||
|
PVOID ShimData; /* fa4/17a8 */
|
||||||
|
ULONG HeapVirtualAffinity; /* fa8/17b0 */
|
||||||
|
PVOID CurrentTransactionHandle; /* fac/17b8 */
|
||||||
|
TEB_ACTIVE_FRAME* ActiveFrame; /* fb0/17c0 */
|
||||||
|
PVOID* FlsSlots; /* fb4/17c8 */
|
||||||
|
PVOID PreferredLanguages; /* fb8/17d0 */
|
||||||
|
PVOID UserPrefLanguages; /* fbc/17d8 */
|
||||||
|
PVOID MergedPrefLanguages; /* fc0/17e0 */
|
||||||
|
ULONG MuiImpersonation; /* fc4/17e8 */
|
||||||
|
USHORT CrossTebFlags; /* fc8/17ec */
|
||||||
|
USHORT SameTebFlags; /* fca/17ee */
|
||||||
|
PVOID TxnScopeEnterCallback; /* fcc/17f0 */
|
||||||
|
PVOID TxnScopeExitCallback; /* fd0/17f8 */
|
||||||
|
PVOID TxnScopeContext; /* fd4/1800 */
|
||||||
|
ULONG LockCount; /* fd8/1808 */
|
||||||
|
LONG WowTebOffset; /* fdc/180c */
|
||||||
|
PVOID ResourceRetValue; /* fe0/1810 */
|
||||||
|
PVOID ReservedForWdf; /* fe4/1818 */
|
||||||
|
ULONGLONG ReservedForCrt; /* fe8/1820 */
|
||||||
|
GUID EffectiveContainerId; /* ff0/1828 */
|
||||||
|
} TEB, *PTEB;
|
||||||
|
static_assert(offsetof(TEB, DeallocationStack) ==
|
||||||
|
0x1478); /* The only member we care about at the moment */
|
||||||
|
|
||||||
|
typedef enum _QUEUE_USER_APC_FLAGS {
|
||||||
|
QueueUserApcFlagsNone,
|
||||||
|
QueueUserApcFlagsSpecialUserApc,
|
||||||
|
QueueUserApcFlagsMaxValue
|
||||||
|
} QUEUE_USER_APC_FLAGS;
|
||||||
|
|
||||||
|
typedef union _USER_APC_OPTION {
|
||||||
|
ULONG_PTR UserApcFlags;
|
||||||
|
HANDLE MemoryReserveHandle;
|
||||||
|
} USER_APC_OPTION, *PUSER_APC_OPTION;
|
||||||
|
|
||||||
|
using PPS_APC_ROUTINE = void (*)(PVOID ApcArgument1, PVOID ApcArgument2, PVOID ApcArgument3,
|
||||||
|
PCONTEXT Context);
|
||||||
|
|
||||||
|
typedef u64(__stdcall* NtClose_t)(HANDLE Handle);
|
||||||
|
|
||||||
|
typedef u64(__stdcall* NtSetInformationFile_t)(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock,
|
||||||
PVOID FileInformation, ULONG Length,
|
PVOID FileInformation, ULONG Length,
|
||||||
FILE_INFORMATION_CLASS FileInformationClass);
|
FILE_INFORMATION_CLASS FileInformationClass);
|
||||||
|
|
||||||
extern NtDelayExecution_t NtDelayExecution;
|
typedef u64(__stdcall* NtCreateThread_t)(PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess,
|
||||||
|
PCOBJECT_ATTRIBUTES ObjectAttributes, HANDLE ProcessHandle,
|
||||||
|
PCLIENT_ID ClientId, PCONTEXT ThreadContext,
|
||||||
|
PINITIAL_TEB InitialTeb, BOOLEAN CreateSuspended);
|
||||||
|
|
||||||
|
typedef u64(__stdcall* NtTerminateThread_t)(HANDLE ThreadHandle, u64 ExitStatus);
|
||||||
|
|
||||||
|
typedef u64(__stdcall* NtQueueApcThreadEx_t)(HANDLE ThreadHandle,
|
||||||
|
USER_APC_OPTION UserApcReserveHandle,
|
||||||
|
PPS_APC_ROUTINE ApcRoutine, PVOID ApcArgument1,
|
||||||
|
PVOID ApcArgument2, PVOID ApcArgument3);
|
||||||
|
|
||||||
|
extern NtClose_t NtClose;
|
||||||
extern NtSetInformationFile_t NtSetInformationFile;
|
extern NtSetInformationFile_t NtSetInformationFile;
|
||||||
|
extern NtCreateThread_t NtCreateThread;
|
||||||
|
extern NtTerminateThread_t NtTerminateThread;
|
||||||
|
extern NtQueueApcThreadEx_t NtQueueApcThreadEx;
|
||||||
|
|
||||||
namespace Common::NtApi {
|
namespace Common::NtApi {
|
||||||
void Initialize();
|
void Initialize();
|
||||||
|
|||||||
163
src/common/slab_heap.h
Normal file
163
src/common/slab_heap.h
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "common/spin_lock.h"
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
class SlabHeapImpl {
|
||||||
|
public:
|
||||||
|
struct Node {
|
||||||
|
Node* next{};
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr SlabHeapImpl() = default;
|
||||||
|
|
||||||
|
void Initialize() {
|
||||||
|
ASSERT(m_head == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* GetHead() const {
|
||||||
|
return m_head;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* Allocate() {
|
||||||
|
m_lock.lock();
|
||||||
|
|
||||||
|
Node* ret = m_head;
|
||||||
|
if (ret != nullptr) {
|
||||||
|
m_head = ret->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lock.unlock();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Free(void* obj) {
|
||||||
|
m_lock.lock();
|
||||||
|
|
||||||
|
Node* node = static_cast<Node*>(obj);
|
||||||
|
node->next = m_head;
|
||||||
|
m_head = node;
|
||||||
|
|
||||||
|
m_lock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::atomic<Node*> m_head{};
|
||||||
|
Common::SpinLock m_lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SlabHeapBase : protected SlabHeapImpl {
|
||||||
|
private:
|
||||||
|
size_t m_obj_size{};
|
||||||
|
uintptr_t m_peak{};
|
||||||
|
uintptr_t m_start{};
|
||||||
|
uintptr_t m_end{};
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr SlabHeapBase() = default;
|
||||||
|
|
||||||
|
bool Contains(uintptr_t address) const {
|
||||||
|
return m_start <= address && address < m_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Initialize(size_t obj_size, void* memory, size_t memory_size) {
|
||||||
|
// Ensure we don't initialize a slab using null memory.
|
||||||
|
ASSERT(memory != nullptr);
|
||||||
|
|
||||||
|
// Set our object size.
|
||||||
|
m_obj_size = obj_size;
|
||||||
|
|
||||||
|
// Initialize the base allocator.
|
||||||
|
SlabHeapImpl::Initialize();
|
||||||
|
|
||||||
|
// Set our tracking variables.
|
||||||
|
const size_t num_obj = (memory_size / obj_size);
|
||||||
|
m_start = reinterpret_cast<uintptr_t>(memory);
|
||||||
|
m_end = m_start + num_obj * obj_size;
|
||||||
|
m_peak = m_start;
|
||||||
|
|
||||||
|
// Free the objects.
|
||||||
|
u8* cur = reinterpret_cast<u8*>(m_end);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < num_obj; i++) {
|
||||||
|
cur -= obj_size;
|
||||||
|
SlabHeapImpl::Free(cur);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetSlabHeapSize() const {
|
||||||
|
return (m_end - m_start) / this->GetObjectSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetObjectSize() const {
|
||||||
|
return m_obj_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* Allocate() {
|
||||||
|
void* obj = SlabHeapImpl::Allocate();
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Free(void* obj) {
|
||||||
|
// Don't allow freeing an object that wasn't allocated from this heap.
|
||||||
|
const bool contained = this->Contains(reinterpret_cast<uintptr_t>(obj));
|
||||||
|
ASSERT(contained);
|
||||||
|
SlabHeapImpl::Free(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetObjectIndex(const void* obj) const {
|
||||||
|
return (reinterpret_cast<uintptr_t>(obj) - m_start) / this->GetObjectSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetPeakIndex() const {
|
||||||
|
return this->GetObjectIndex(reinterpret_cast<const void*>(m_peak));
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t GetSlabHeapAddress() const {
|
||||||
|
return m_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetNumRemaining() const {
|
||||||
|
// Only calculate the number of remaining objects under debug configuration.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class SlabHeap final : public SlabHeapBase {
|
||||||
|
private:
|
||||||
|
using BaseHeap = SlabHeapBase;
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr SlabHeap() = default;
|
||||||
|
|
||||||
|
void Initialize(void* memory, size_t memory_size) {
|
||||||
|
BaseHeap::Initialize(sizeof(T), memory, memory_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
T* Allocate() {
|
||||||
|
T* obj = static_cast<T*>(BaseHeap::Allocate());
|
||||||
|
|
||||||
|
if (obj != nullptr) [[likely]] {
|
||||||
|
std::construct_at(obj);
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Free(T* obj) {
|
||||||
|
BaseHeap::Free(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetObjectIndex(const T* obj) const {
|
||||||
|
return BaseHeap::GetObjectIndex(obj);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Common
|
||||||
63
src/common/slot_array.h
Normal file
63
src/common/slot_array.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
// #include <boost/icl/interval_set.hpp>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <optional>
|
||||||
|
#include <shared_mutex>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
template <class IndexType, class ResourceType,
|
||||||
|
IndexType MaxIndex = std::numeric_limits<IndexType>::max(), IndexType MinIndex = 0>
|
||||||
|
class SlotArray {
|
||||||
|
public:
|
||||||
|
SlotArray() {
|
||||||
|
std::iota(m_free_indices.begin(), m_free_indices.end(), MinIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Types>
|
||||||
|
std::optional<IndexType> Create(Types&&... args) {
|
||||||
|
if (!HasFreeSlots()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
const auto index = m_free_indices[m_curr_cursor];
|
||||||
|
m_resources[index - MinIndex] = ResourceType(std::forward<Types>(args)...);
|
||||||
|
m_curr_cursor += 1;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Destroy(IndexType index) {
|
||||||
|
if (!m_resources[index - MinIndex].has_value()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_curr_cursor -= 1;
|
||||||
|
m_free_indices[m_curr_cursor] = index;
|
||||||
|
m_resources[index - MinIndex] = std::nullopt;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceType* Get(IndexType index) {
|
||||||
|
auto& resource = m_resources[index - MinIndex];
|
||||||
|
if (!resource.has_value()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return &resource.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasFreeSlots() {
|
||||||
|
return m_curr_cursor < m_free_indices.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t m_curr_cursor = 0;
|
||||||
|
std::array<IndexType, MaxIndex - MinIndex> m_free_indices;
|
||||||
|
std::array<std::optional<ResourceType>, MaxIndex - MinIndex> m_resources;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Common
|
||||||
@@ -3,10 +3,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <bit>
|
|
||||||
#include <compare>
|
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
|||||||
53
src/common/spin_lock.cpp
Executable file
53
src/common/spin_lock.cpp
Executable file
@@ -0,0 +1,53 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/spin_lock.h"
|
||||||
|
|
||||||
|
#if _MSC_VER
|
||||||
|
#include <intrin.h>
|
||||||
|
#if _M_AMD64
|
||||||
|
#define __x86_64__ 1
|
||||||
|
#endif
|
||||||
|
#if _M_ARM64
|
||||||
|
#define __aarch64__ 1
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#if __x86_64__
|
||||||
|
#include <xmmintrin.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void ThreadPause() {
|
||||||
|
#if __x86_64__
|
||||||
|
_mm_pause();
|
||||||
|
#elif __aarch64__ && _MSC_VER
|
||||||
|
__yield();
|
||||||
|
#elif __aarch64__
|
||||||
|
asm("yield");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
void SpinLock::lock() {
|
||||||
|
while (lck.test_and_set(std::memory_order_acquire)) {
|
||||||
|
ThreadPause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpinLock::unlock() {
|
||||||
|
lck.clear(std::memory_order_release);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SpinLock::try_lock() {
|
||||||
|
if (lck.test_and_set(std::memory_order_acquire)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Common
|
||||||
33
src/common/spin_lock.h
Executable file
33
src/common/spin_lock.h
Executable file
@@ -0,0 +1,33 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SpinLock class
|
||||||
|
* a lock similar to mutex that forces a thread to spin wait instead calling the
|
||||||
|
* supervisor. Should be used on short sequences of code.
|
||||||
|
*/
|
||||||
|
class SpinLock {
|
||||||
|
public:
|
||||||
|
SpinLock() = default;
|
||||||
|
|
||||||
|
SpinLock(const SpinLock&) = delete;
|
||||||
|
SpinLock& operator=(const SpinLock&) = delete;
|
||||||
|
|
||||||
|
SpinLock(SpinLock&&) = delete;
|
||||||
|
SpinLock& operator=(SpinLock&&) = delete;
|
||||||
|
|
||||||
|
void lock();
|
||||||
|
void unlock();
|
||||||
|
[[nodiscard]] bool try_lock();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::atomic_flag lck = ATOMIC_FLAG_INIT;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Common
|
||||||
7
src/common/stb.cpp
Normal file
7
src/common/stb.cpp
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#define STBI_ONLY_PNG
|
||||||
|
#define STBI_NO_STDIO
|
||||||
|
#include "common/stb.h"
|
||||||
6
src/common/stb.h
Normal file
6
src/common/stb.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stb_image.h>
|
||||||
@@ -37,6 +37,10 @@ std::vector<std::string> SplitString(const std::string& str, char delimiter) {
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string_view U8stringToString(std::u8string_view u8str) {
|
||||||
|
return std::string_view{reinterpret_cast<const char*>(u8str.data()), u8str.size()};
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static std::wstring CPToUTF16(u32 code_page, std::string_view input) {
|
static std::wstring CPToUTF16(u32 code_page, std::string_view input) {
|
||||||
const auto size =
|
const auto size =
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ void ToLowerInPlace(std::string& str);
|
|||||||
|
|
||||||
std::vector<std::string> SplitString(const std::string& str, char delimiter);
|
std::vector<std::string> SplitString(const std::string& str, char delimiter);
|
||||||
|
|
||||||
|
std::string_view U8stringToString(std::u8string_view u8str);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
[[nodiscard]] std::string UTF16ToUTF8(std::wstring_view input);
|
[[nodiscard]] std::string UTF16ToUTF8(std::wstring_view input);
|
||||||
[[nodiscard]] std::wstring UTF8ToUTF16W(std::string_view str);
|
[[nodiscard]] std::wstring UTF8ToUTF16W(std::string_view str);
|
||||||
|
|||||||
17
src/common/support/avdec.h
Normal file
17
src/common/support/avdec.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// support header file for libav
|
||||||
|
|
||||||
|
// The av_err2str macro in libavutil/error.h does not play nice with C++
|
||||||
|
#ifdef av_err2str
|
||||||
|
#undef av_err2str
|
||||||
|
#include <string>
|
||||||
|
av_always_inline std::string av_err2string(int errnum) {
|
||||||
|
char errbuf[AV_ERROR_MAX_STRING_SIZE];
|
||||||
|
return av_make_error_string(errbuf, AV_ERROR_MAX_STRING_SIZE, errnum);
|
||||||
|
}
|
||||||
|
#define av_err2str(err) av_err2string(err).c_str()
|
||||||
|
#endif // av_err2str
|
||||||
@@ -147,6 +147,10 @@ void SetCurrentThreadName(const char* name) {
|
|||||||
SetThreadDescription(GetCurrentThread(), UTF8ToUTF16W(name).data());
|
SetThreadDescription(GetCurrentThread(), UTF8ToUTF16W(name).data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetThreadName(void* thread, const char* name) {
|
||||||
|
SetThreadDescription(thread, UTF8ToUTF16W(name).data());
|
||||||
|
}
|
||||||
|
|
||||||
#else // !MSVC_VER, so must be POSIX threads
|
#else // !MSVC_VER, so must be POSIX threads
|
||||||
|
|
||||||
// MinGW with the POSIX threading model does not support pthread_setname_np
|
// MinGW with the POSIX threading model does not support pthread_setname_np
|
||||||
@@ -170,11 +174,19 @@ void SetCurrentThreadName(const char* name) {
|
|||||||
pthread_setname_np(pthread_self(), name);
|
pthread_setname_np(pthread_self(), name);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetThreadName(void* thread, const char* name) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
void SetCurrentThreadName(const char*) {
|
void SetCurrentThreadName(const char*) {
|
||||||
// Do Nothing on MingW
|
// Do Nothing on MinGW
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetThreadName(void* thread, const char* name) {
|
||||||
|
// Do Nothing on MinGW
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ void SetCurrentThreadPriority(ThreadPriority new_priority);
|
|||||||
|
|
||||||
void SetCurrentThreadName(const char* name);
|
void SetCurrentThreadName(const char* name);
|
||||||
|
|
||||||
|
void SetThreadName(void* thread, const char* name);
|
||||||
|
|
||||||
class AccurateTimer {
|
class AccurateTimer {
|
||||||
std::chrono::nanoseconds target_interval{};
|
std::chrono::nanoseconds target_interval{};
|
||||||
std::chrono::nanoseconds total_wait{};
|
std::chrono::nanoseconds total_wait{};
|
||||||
|
|||||||
111
src/common/va_ctx.h
Normal file
111
src/common/va_ctx.h
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <xmmintrin.h>
|
||||||
|
#include "common/types.h"
|
||||||
|
|
||||||
|
#define VA_ARGS \
|
||||||
|
uint64_t rdi, uint64_t rsi, uint64_t rdx, uint64_t rcx, uint64_t r8, uint64_t r9, \
|
||||||
|
uint64_t overflow_arg_area, __m128 xmm0, __m128 xmm1, __m128 xmm2, __m128 xmm3, \
|
||||||
|
__m128 xmm4, __m128 xmm5, __m128 xmm6, __m128 xmm7, ...
|
||||||
|
|
||||||
|
#define VA_CTX(ctx) \
|
||||||
|
alignas(16)::Common::VaCtx ctx{}; \
|
||||||
|
(ctx).reg_save_area.gp[0] = rdi; \
|
||||||
|
(ctx).reg_save_area.gp[1] = rsi; \
|
||||||
|
(ctx).reg_save_area.gp[2] = rdx; \
|
||||||
|
(ctx).reg_save_area.gp[3] = rcx; \
|
||||||
|
(ctx).reg_save_area.gp[4] = r8; \
|
||||||
|
(ctx).reg_save_area.gp[5] = r9; \
|
||||||
|
(ctx).reg_save_area.fp[0] = xmm0; \
|
||||||
|
(ctx).reg_save_area.fp[1] = xmm1; \
|
||||||
|
(ctx).reg_save_area.fp[2] = xmm2; \
|
||||||
|
(ctx).reg_save_area.fp[3] = xmm3; \
|
||||||
|
(ctx).reg_save_area.fp[4] = xmm4; \
|
||||||
|
(ctx).reg_save_area.fp[5] = xmm5; \
|
||||||
|
(ctx).reg_save_area.fp[6] = xmm6; \
|
||||||
|
(ctx).reg_save_area.fp[7] = xmm7; \
|
||||||
|
(ctx).va_list.reg_save_area = &(ctx).reg_save_area; \
|
||||||
|
(ctx).va_list.gp_offset = offsetof(::Common::VaRegSave, gp); \
|
||||||
|
(ctx).va_list.fp_offset = offsetof(::Common::VaRegSave, fp); \
|
||||||
|
(ctx).va_list.overflow_arg_area = &overflow_arg_area;
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
// https://stackoverflow.com/questions/4958384/what-is-the-format-of-the-x86-64-va-list-structure
|
||||||
|
|
||||||
|
struct VaList {
|
||||||
|
u32 gp_offset;
|
||||||
|
u32 fp_offset;
|
||||||
|
void* overflow_arg_area;
|
||||||
|
void* reg_save_area;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VaRegSave {
|
||||||
|
u64 gp[6];
|
||||||
|
__m128 fp[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VaCtx {
|
||||||
|
VaRegSave reg_save_area;
|
||||||
|
VaList va_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, uint32_t Size>
|
||||||
|
T vaArgRegSaveAreaGp(VaList* l) {
|
||||||
|
auto* addr = reinterpret_cast<T*>(static_cast<u8*>(l->reg_save_area) + l->gp_offset);
|
||||||
|
l->gp_offset += Size;
|
||||||
|
return *addr;
|
||||||
|
}
|
||||||
|
template <class T, u64 Align, u64 Size>
|
||||||
|
T vaArgOverflowArgArea(VaList* l) {
|
||||||
|
auto ptr = ((reinterpret_cast<u64>(l->overflow_arg_area) + (Align - 1)) & ~(Align - 1));
|
||||||
|
auto* addr = reinterpret_cast<T*>(ptr);
|
||||||
|
l->overflow_arg_area = reinterpret_cast<void*>(ptr + Size);
|
||||||
|
return *addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, uint32_t Size>
|
||||||
|
T vaArgRegSaveAreaFp(VaList* l) {
|
||||||
|
auto* addr = reinterpret_cast<T*>(static_cast<u8*>(l->reg_save_area) + l->fp_offset);
|
||||||
|
l->fp_offset += Size;
|
||||||
|
return *addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int vaArgInteger(VaList* l) {
|
||||||
|
if (l->gp_offset <= 40) {
|
||||||
|
return vaArgRegSaveAreaGp<int, 8>(l);
|
||||||
|
}
|
||||||
|
return vaArgOverflowArgArea<int, 1, 8>(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline long long vaArgLongLong(VaList* l) {
|
||||||
|
if (l->gp_offset <= 40) {
|
||||||
|
return vaArgRegSaveAreaGp<long long, 8>(l);
|
||||||
|
}
|
||||||
|
return vaArgOverflowArgArea<long long, 1, 8>(l);
|
||||||
|
}
|
||||||
|
inline long vaArgLong(VaList* l) {
|
||||||
|
if (l->gp_offset <= 40) {
|
||||||
|
return vaArgRegSaveAreaGp<long, 8>(l);
|
||||||
|
}
|
||||||
|
return vaArgOverflowArgArea<long, 1, 8>(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double vaArgDouble(VaList* l) {
|
||||||
|
if (l->fp_offset <= 160) {
|
||||||
|
return vaArgRegSaveAreaFp<double, 16>(l);
|
||||||
|
}
|
||||||
|
return vaArgOverflowArgArea<double, 1, 8>(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
T* vaArgPtr(VaList* l) {
|
||||||
|
if (l->gp_offset <= 40) {
|
||||||
|
return vaArgRegSaveAreaGp<T*, 8>(l);
|
||||||
|
}
|
||||||
|
return vaArgOverflowArgArea<T*, 1, 8>(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Common
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
constexpr char VERSION[] = "0.4.0";
|
constexpr char VERSION[] = "0.5.0";
|
||||||
constexpr bool isRelease = true;
|
constexpr bool isRelease = true;
|
||||||
|
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <map>
|
||||||
#include <boost/icl/separate_interval_set.hpp>
|
#include <boost/icl/separate_interval_set.hpp>
|
||||||
#include "common/alignment.h"
|
#include "common/alignment.h"
|
||||||
#include "common/arch.h"
|
#include "common/arch.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/error.h"
|
#include "common/error.h"
|
||||||
#include "core/address_space.h"
|
#include "core/address_space.h"
|
||||||
#include "core/libraries/kernel/memory_management.h"
|
#include "core/libraries/kernel/memory.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
#include "libraries/error_codes.h"
|
#include "libraries/error_codes.h"
|
||||||
|
|
||||||
@@ -40,6 +41,12 @@ static constexpr size_t BackingSize = SCE_KERNEL_MAIN_DMEM_SIZE_PRO;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct MemoryRegion {
|
||||||
|
VAddr base;
|
||||||
|
size_t size;
|
||||||
|
bool is_mapped;
|
||||||
|
};
|
||||||
|
|
||||||
struct AddressSpace::Impl {
|
struct AddressSpace::Impl {
|
||||||
Impl() : process{GetCurrentProcess()} {
|
Impl() : process{GetCurrentProcess()} {
|
||||||
// Allocate virtual address placeholder for our address space.
|
// Allocate virtual address placeholder for our address space.
|
||||||
@@ -75,6 +82,7 @@ struct AddressSpace::Impl {
|
|||||||
Common::GetLastErrorMsg());
|
Common::GetLastErrorMsg());
|
||||||
|
|
||||||
// Take the reduction off of the system managed area, and leave the others unchanged.
|
// Take the reduction off of the system managed area, and leave the others unchanged.
|
||||||
|
reduction = size_t(virtual_base - SYSTEM_MANAGED_MIN);
|
||||||
system_managed_base = virtual_base;
|
system_managed_base = virtual_base;
|
||||||
system_managed_size = SystemManagedSize - reduction;
|
system_managed_size = SystemManagedSize - reduction;
|
||||||
system_reserved_base = reinterpret_cast<u8*>(SYSTEM_RESERVED_MIN);
|
system_reserved_base = reinterpret_cast<u8*>(SYSTEM_RESERVED_MIN);
|
||||||
@@ -95,7 +103,8 @@ struct AddressSpace::Impl {
|
|||||||
const uintptr_t system_managed_addr = reinterpret_cast<uintptr_t>(system_managed_base);
|
const uintptr_t system_managed_addr = reinterpret_cast<uintptr_t>(system_managed_base);
|
||||||
const uintptr_t system_reserved_addr = reinterpret_cast<uintptr_t>(system_reserved_base);
|
const uintptr_t system_reserved_addr = reinterpret_cast<uintptr_t>(system_reserved_base);
|
||||||
const uintptr_t user_addr = reinterpret_cast<uintptr_t>(user_base);
|
const uintptr_t user_addr = reinterpret_cast<uintptr_t>(user_base);
|
||||||
placeholders.insert({system_managed_addr, virtual_size - reduction});
|
regions.emplace(system_managed_addr,
|
||||||
|
MemoryRegion{system_managed_addr, virtual_size - reduction, false});
|
||||||
|
|
||||||
// Allocate backing file that represents the total physical memory.
|
// Allocate backing file that represents the total physical memory.
|
||||||
backing_handle =
|
backing_handle =
|
||||||
@@ -132,42 +141,15 @@ struct AddressSpace::Impl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void* Map(VAddr virtual_addr, PAddr phys_addr, size_t size, ULONG prot, uintptr_t fd = 0) {
|
void* Map(VAddr virtual_addr, PAddr phys_addr, size_t size, ULONG prot, uintptr_t fd = 0) {
|
||||||
const size_t aligned_size = Common::AlignUp(size, 16_KB);
|
// Before mapping we must carve a placeholder with the exact properties of our mapping.
|
||||||
const auto it = placeholders.find(virtual_addr);
|
auto* region = EnsureSplitRegionForMapping(virtual_addr, size);
|
||||||
ASSERT_MSG(it != placeholders.end(), "Cannot map already mapped region");
|
region->is_mapped = true;
|
||||||
ASSERT_MSG(virtual_addr >= it->lower() && virtual_addr + aligned_size <= it->upper(),
|
|
||||||
"Map range must be fully contained in a placeholder");
|
|
||||||
|
|
||||||
// Windows only allows splitting a placeholder into two.
|
|
||||||
// This means that if the map range is fully
|
|
||||||
// contained the the placeholder we need to perform two split operations,
|
|
||||||
// one at the start and at the end.
|
|
||||||
const VAddr placeholder_start = it->lower();
|
|
||||||
const VAddr placeholder_end = it->upper();
|
|
||||||
const VAddr virtual_end = virtual_addr + aligned_size;
|
|
||||||
|
|
||||||
// If the placeholder doesn't exactly start at virtual_addr, split it at the start.
|
|
||||||
if (placeholder_start != virtual_addr) {
|
|
||||||
VirtualFreeEx(process, reinterpret_cast<LPVOID>(placeholder_start),
|
|
||||||
virtual_addr - placeholder_start, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the placeholder doesn't exactly end at virtual_end, split it at the end.
|
|
||||||
if (placeholder_end != virtual_end) {
|
|
||||||
VirtualFreeEx(process, reinterpret_cast<LPVOID>(virtual_end),
|
|
||||||
placeholder_end - virtual_end, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the placeholder.
|
|
||||||
placeholders.erase({virtual_addr, virtual_end});
|
|
||||||
|
|
||||||
// Perform the map.
|
|
||||||
void* ptr = nullptr;
|
void* ptr = nullptr;
|
||||||
if (phys_addr != -1) {
|
if (phys_addr != -1) {
|
||||||
HANDLE backing = fd ? reinterpret_cast<HANDLE>(fd) : backing_handle;
|
HANDLE backing = fd ? reinterpret_cast<HANDLE>(fd) : backing_handle;
|
||||||
if (fd && prot == PAGE_READONLY) {
|
if (fd && prot == PAGE_READONLY) {
|
||||||
DWORD resultvar;
|
DWORD resultvar;
|
||||||
ptr = VirtualAlloc2(process, reinterpret_cast<PVOID>(virtual_addr), aligned_size,
|
ptr = VirtualAlloc2(process, reinterpret_cast<PVOID>(virtual_addr), size,
|
||||||
MEM_RESERVE | MEM_COMMIT | MEM_REPLACE_PLACEHOLDER,
|
MEM_RESERVE | MEM_COMMIT | MEM_REPLACE_PLACEHOLDER,
|
||||||
PAGE_READWRITE, nullptr, 0);
|
PAGE_READWRITE, nullptr, 0);
|
||||||
bool ret = ReadFile(backing, ptr, size, &resultvar, NULL);
|
bool ret = ReadFile(backing, ptr, size, &resultvar, NULL);
|
||||||
@@ -176,12 +158,11 @@ struct AddressSpace::Impl {
|
|||||||
ASSERT_MSG(ret, "VirtualProtect failed. {}", Common::GetLastErrorMsg());
|
ASSERT_MSG(ret, "VirtualProtect failed. {}", Common::GetLastErrorMsg());
|
||||||
} else {
|
} else {
|
||||||
ptr = MapViewOfFile3(backing, process, reinterpret_cast<PVOID>(virtual_addr),
|
ptr = MapViewOfFile3(backing, process, reinterpret_cast<PVOID>(virtual_addr),
|
||||||
phys_addr, aligned_size, MEM_REPLACE_PLACEHOLDER, prot,
|
phys_addr, size, MEM_REPLACE_PLACEHOLDER, prot, nullptr, 0);
|
||||||
nullptr, 0);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ptr =
|
ptr =
|
||||||
VirtualAlloc2(process, reinterpret_cast<PVOID>(virtual_addr), aligned_size,
|
VirtualAlloc2(process, reinterpret_cast<PVOID>(virtual_addr), size,
|
||||||
MEM_RESERVE | MEM_COMMIT | MEM_REPLACE_PLACEHOLDER, prot, nullptr, 0);
|
MEM_RESERVE | MEM_COMMIT | MEM_REPLACE_PLACEHOLDER, prot, nullptr, 0);
|
||||||
}
|
}
|
||||||
ASSERT_MSG(ptr, "{}", Common::GetLastErrorMsg());
|
ASSERT_MSG(ptr, "{}", Common::GetLastErrorMsg());
|
||||||
@@ -202,33 +183,118 @@ struct AddressSpace::Impl {
|
|||||||
|
|
||||||
// The unmap call will create a new placeholder region. We need to see if we can coalesce it
|
// The unmap call will create a new placeholder region. We need to see if we can coalesce it
|
||||||
// with neighbors.
|
// with neighbors.
|
||||||
VAddr placeholder_start = virtual_addr;
|
JoinRegionsAfterUnmap(virtual_addr, size);
|
||||||
VAddr placeholder_end = virtual_addr + size;
|
}
|
||||||
|
|
||||||
|
// The following code is inspired from Dolphin's MemArena
|
||||||
|
// https://github.com/dolphin-emu/dolphin/blob/deee3ee4/Source/Core/Common/MemArenaWin.cpp#L212
|
||||||
|
MemoryRegion* EnsureSplitRegionForMapping(VAddr address, size_t size) {
|
||||||
|
// Find closest region that is <= the given address by using upper bound and decrementing
|
||||||
|
auto it = regions.upper_bound(address);
|
||||||
|
ASSERT_MSG(it != regions.begin(), "Invalid address {:#x}", address);
|
||||||
|
--it;
|
||||||
|
ASSERT_MSG(!it->second.is_mapped,
|
||||||
|
"Attempt to map {:#x} with size {:#x} which overlaps with {:#x} mapping",
|
||||||
|
address, size, it->second.base);
|
||||||
|
auto& [base, region] = *it;
|
||||||
|
|
||||||
|
const VAddr mapping_address = region.base;
|
||||||
|
const size_t region_size = region.size;
|
||||||
|
if (mapping_address == address) {
|
||||||
|
// If this region is already split up correctly we don't have to do anything
|
||||||
|
if (region_size == size) {
|
||||||
|
return ®ion;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_MSG(region_size >= size,
|
||||||
|
"Region with address {:#x} and size {:#x} can't fit {:#x}", mapping_address,
|
||||||
|
region_size, size);
|
||||||
|
|
||||||
|
// Split the placeholder.
|
||||||
|
if (!VirtualFreeEx(process, LPVOID(address), size,
|
||||||
|
MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER)) {
|
||||||
|
UNREACHABLE_MSG("Region splitting failed: {}", Common::GetLastErrorMsg());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update tracked mappings and return the first of the two
|
||||||
|
region.size = size;
|
||||||
|
const VAddr new_mapping_start = address + size;
|
||||||
|
regions.emplace_hint(std::next(it), new_mapping_start,
|
||||||
|
MemoryRegion(new_mapping_start, region_size - size, false));
|
||||||
|
return ®ion;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(mapping_address < address);
|
||||||
|
|
||||||
|
// Is there enough space to map this?
|
||||||
|
const size_t offset_in_region = address - mapping_address;
|
||||||
|
const size_t minimum_size = size + offset_in_region;
|
||||||
|
ASSERT(region_size >= minimum_size);
|
||||||
|
|
||||||
|
// Split the placeholder.
|
||||||
|
if (!VirtualFreeEx(process, LPVOID(address), size,
|
||||||
|
MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER)) {
|
||||||
|
UNREACHABLE_MSG("Region splitting failed: {}", Common::GetLastErrorMsg());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do we now have two regions or three regions?
|
||||||
|
if (region_size == minimum_size) {
|
||||||
|
// Split into two; update tracked mappings and return the second one
|
||||||
|
region.size = offset_in_region;
|
||||||
|
it = regions.emplace_hint(std::next(it), address, MemoryRegion(address, size, false));
|
||||||
|
return &it->second;
|
||||||
|
} else {
|
||||||
|
// Split into three; update tracked mappings and return the middle one
|
||||||
|
region.size = offset_in_region;
|
||||||
|
const VAddr middle_mapping_start = address;
|
||||||
|
const size_t middle_mapping_size = size;
|
||||||
|
const VAddr after_mapping_start = address + size;
|
||||||
|
const size_t after_mapping_size = region_size - minimum_size;
|
||||||
|
it = regions.emplace_hint(std::next(it), after_mapping_start,
|
||||||
|
MemoryRegion(after_mapping_start, after_mapping_size, false));
|
||||||
|
it = regions.emplace_hint(
|
||||||
|
it, middle_mapping_start,
|
||||||
|
MemoryRegion(middle_mapping_start, middle_mapping_size, false));
|
||||||
|
return &it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JoinRegionsAfterUnmap(VAddr address, size_t size) {
|
||||||
|
// There should be a mapping that matches the request exactly, find it
|
||||||
|
auto it = regions.find(address);
|
||||||
|
ASSERT_MSG(it != regions.end() && it->second.size == size,
|
||||||
|
"Invalid address/size given to unmap.");
|
||||||
|
auto& [base, region] = *it;
|
||||||
|
region.is_mapped = false;
|
||||||
|
|
||||||
// Check if a placeholder exists right before us.
|
// Check if a placeholder exists right before us.
|
||||||
const auto left_it = placeholders.find(virtual_addr - 1);
|
auto it_prev = it != regions.begin() ? std::prev(it) : regions.end();
|
||||||
if (left_it != placeholders.end()) {
|
if (it_prev != regions.end() && !it_prev->second.is_mapped) {
|
||||||
ASSERT_MSG(left_it->upper() == virtual_addr,
|
const size_t total_size = it_prev->second.size + size;
|
||||||
"Left placeholder does not end at virtual_addr!");
|
if (!VirtualFreeEx(process, LPVOID(it_prev->first), total_size,
|
||||||
placeholder_start = left_it->lower();
|
MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS)) {
|
||||||
VirtualFreeEx(process, reinterpret_cast<LPVOID>(placeholder_start),
|
UNREACHABLE_MSG("Region coalescing failed: {}", Common::GetLastErrorMsg());
|
||||||
placeholder_end - placeholder_start,
|
}
|
||||||
MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS);
|
|
||||||
|
it_prev->second.size = total_size;
|
||||||
|
regions.erase(it);
|
||||||
|
it = it_prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if a placeholder exists right after us.
|
// Check if a placeholder exists right after us.
|
||||||
const auto right_it = placeholders.find(placeholder_end + 1);
|
auto it_next = std::next(it);
|
||||||
if (right_it != placeholders.end()) {
|
if (it_next != regions.end() && !it_next->second.is_mapped) {
|
||||||
ASSERT_MSG(right_it->lower() == placeholder_end,
|
const size_t total_size = it->second.size + it_next->second.size;
|
||||||
"Right placeholder does not start at virtual_end!");
|
if (!VirtualFreeEx(process, LPVOID(it->first), total_size,
|
||||||
placeholder_end = right_it->upper();
|
MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS)) {
|
||||||
VirtualFreeEx(process, reinterpret_cast<LPVOID>(placeholder_start),
|
UNREACHABLE_MSG("Region coalescing failed: {}", Common::GetLastErrorMsg());
|
||||||
placeholder_end - placeholder_start,
|
}
|
||||||
MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert the new placeholder.
|
it->second.size = total_size;
|
||||||
placeholders.insert({placeholder_start, placeholder_end});
|
regions.erase(it_next);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Protect(VAddr virtual_addr, size_t size, bool read, bool write, bool execute) {
|
void Protect(VAddr virtual_addr, size_t size, bool read, bool write, bool execute) {
|
||||||
@@ -251,18 +317,22 @@ struct AddressSpace::Impl {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD old_flags{};
|
const VAddr virtual_end = virtual_addr + size;
|
||||||
bool success =
|
auto it = --regions.upper_bound(virtual_addr);
|
||||||
VirtualProtect(reinterpret_cast<void*>(virtual_addr), size, new_flags, &old_flags);
|
for (; it->first < virtual_end; it++) {
|
||||||
|
if (!it->second.is_mapped) {
|
||||||
if (!success) {
|
continue;
|
||||||
LOG_ERROR(Common_Memory,
|
}
|
||||||
"Failed to change virtual memory protection for address {:#x}, size {}",
|
const auto& region = it->second;
|
||||||
virtual_addr, size);
|
const size_t range_addr = std::max(region.base, virtual_addr);
|
||||||
|
const size_t range_size = std::min(region.base + region.size, virtual_end) - range_addr;
|
||||||
|
DWORD old_flags{};
|
||||||
|
if (!VirtualProtectEx(process, LPVOID(range_addr), range_size, new_flags, &old_flags)) {
|
||||||
|
UNREACHABLE_MSG(
|
||||||
|
"Failed to change virtual memory protection for address {:#x}, size {}",
|
||||||
|
range_addr, range_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use assert to ensure success in debug builds
|
|
||||||
DEBUG_ASSERT(success && "Failed to change virtual memory protection");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE process{};
|
HANDLE process{};
|
||||||
@@ -275,7 +345,7 @@ struct AddressSpace::Impl {
|
|||||||
size_t system_reserved_size{};
|
size_t system_reserved_size{};
|
||||||
u8* user_base{};
|
u8* user_base{};
|
||||||
size_t user_size{};
|
size_t user_size{};
|
||||||
boost::icl::separate_interval_set<uintptr_t> placeholders;
|
std::map<VAddr, MemoryRegion> regions;
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/types.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
/// Initializes a stack for the current thread for use by patch implementations.
|
/// Initializes a stack for the current thread for use by patch implementations.
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#include "common/singleton.h"
|
#include "common/singleton.h"
|
||||||
#include "debug_state.h"
|
#include "debug_state.h"
|
||||||
#include "devtools/widget/common.h"
|
#include "devtools/widget/common.h"
|
||||||
#include "libraries/kernel/time_management.h"
|
#include "libraries/kernel/time.h"
|
||||||
#include "libraries/system/msgdialog.h"
|
#include "libraries/system/msgdialog.h"
|
||||||
#include "video_core/amdgpu/pm4_cmds.h"
|
#include "video_core/amdgpu/pm4_cmds.h"
|
||||||
|
|
||||||
@@ -142,37 +142,66 @@ void DebugStateImpl::PushQueueDump(QueueDump dump) {
|
|||||||
frame.queues.push_back(std::move(dump));
|
frame.queues.push_back(std::move(dump));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugStateImpl::PushRegsDump(uintptr_t base_addr, uintptr_t header_addr,
|
std::optional<RegDump*> DebugStateImpl::GetRegDump(uintptr_t base_addr, uintptr_t header_addr) {
|
||||||
const AmdGpu::Liverpool::Regs& regs, bool is_compute) {
|
|
||||||
std::scoped_lock lock{frame_dump_list_mutex};
|
|
||||||
const auto it = waiting_reg_dumps.find(header_addr);
|
const auto it = waiting_reg_dumps.find(header_addr);
|
||||||
if (it == waiting_reg_dumps.end()) {
|
if (it == waiting_reg_dumps.end()) {
|
||||||
return;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
auto& frame = *it->second;
|
auto& frame = *it->second;
|
||||||
waiting_reg_dumps.erase(it);
|
waiting_reg_dumps.erase(it);
|
||||||
waiting_reg_dumps_dbg.erase(waiting_reg_dumps_dbg.find(header_addr));
|
waiting_reg_dumps_dbg.erase(waiting_reg_dumps_dbg.find(header_addr));
|
||||||
auto& dump = frame.regs[header_addr - base_addr];
|
return &frame.regs[header_addr - base_addr];
|
||||||
dump.regs = regs;
|
}
|
||||||
if (is_compute) {
|
|
||||||
dump.is_compute = true;
|
void DebugStateImpl::PushRegsDump(uintptr_t base_addr, uintptr_t header_addr,
|
||||||
const auto& cs = dump.regs.cs_program;
|
const AmdGpu::Liverpool::Regs& regs) {
|
||||||
dump.cs_data = ComputerShaderDump{
|
std::scoped_lock lock{frame_dump_list_mutex};
|
||||||
.cs_program = cs,
|
|
||||||
.code = std::vector<u32>{cs.Code().begin(), cs.Code().end()},
|
auto dump = GetRegDump(base_addr, header_addr);
|
||||||
};
|
if (!dump) {
|
||||||
} else {
|
return;
|
||||||
for (int i = 0; i < RegDump::MaxShaderStages; i++) {
|
}
|
||||||
if (regs.stage_enable.IsStageEnabled(i)) {
|
|
||||||
auto stage = regs.ProgramForStage(i);
|
(*dump)->regs = regs;
|
||||||
if (stage->address_lo != 0) {
|
|
||||||
auto code = stage->Code();
|
for (int i = 0; i < RegDump::MaxShaderStages; i++) {
|
||||||
dump.stages[i] = ShaderDump{
|
if ((*dump)->regs.stage_enable.IsStageEnabled(i)) {
|
||||||
.user_data = *stage,
|
auto stage = (*dump)->regs.ProgramForStage(i);
|
||||||
.code = std::vector<u32>{code.begin(), code.end()},
|
if (stage->address_lo != 0) {
|
||||||
};
|
auto code = stage->Code();
|
||||||
}
|
(*dump)->stages[i] = PipelineShaderProgramDump{
|
||||||
|
.user_data = *stage,
|
||||||
|
.code = std::vector<u32>{code.begin(), code.end()},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DebugStateImpl::PushRegsDumpCompute(uintptr_t base_addr, uintptr_t header_addr,
|
||||||
|
const CsState& cs_state) {
|
||||||
|
std::scoped_lock lock{frame_dump_list_mutex};
|
||||||
|
|
||||||
|
auto dump = GetRegDump(base_addr, header_addr);
|
||||||
|
if (!dump) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*dump)->is_compute = true;
|
||||||
|
auto& cs = (*dump)->regs.cs_program;
|
||||||
|
cs = cs_state;
|
||||||
|
|
||||||
|
(*dump)->cs_data = PipelineComputerProgramDump{
|
||||||
|
.cs_program = cs,
|
||||||
|
.code = std::vector<u32>{cs.Code().begin(), cs.Code().end()},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugStateImpl::CollectShader(const std::string& name, Shader::LogicalStage l_stage,
|
||||||
|
vk::ShaderModule module, std::span<const u32> spv,
|
||||||
|
std::span<const u32> raw_code, std::span<const u32> patch_spv,
|
||||||
|
bool is_patched) {
|
||||||
|
shader_dump_list.emplace_back(name, l_stage, module, std::vector<u32>{spv.begin(), spv.end()},
|
||||||
|
std::vector<u32>{raw_code.begin(), raw_code.end()},
|
||||||
|
std::vector<u32>{patch_spv.begin(), patch_spv.end()}, is_patched);
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,8 +11,7 @@
|
|||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
#include "video_core/amdgpu/liverpool.h"
|
#include "video_core/renderer_vulkan/vk_graphics_pipeline.h"
|
||||||
#include "video_core/renderer_vulkan/vk_pipeline_cache.h"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
@@ -30,7 +29,8 @@ namespace Core::Devtools {
|
|||||||
class Layer;
|
class Layer;
|
||||||
namespace Widget {
|
namespace Widget {
|
||||||
class FrameGraph;
|
class FrameGraph;
|
||||||
}
|
class ShaderList;
|
||||||
|
} // namespace Widget
|
||||||
} // namespace Core::Devtools
|
} // namespace Core::Devtools
|
||||||
|
|
||||||
namespace DebugStateType {
|
namespace DebugStateType {
|
||||||
@@ -49,12 +49,12 @@ struct QueueDump {
|
|||||||
uintptr_t base_addr;
|
uintptr_t base_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ShaderDump {
|
struct PipelineShaderProgramDump {
|
||||||
Vulkan::Liverpool::ShaderProgram user_data{};
|
Vulkan::Liverpool::ShaderProgram user_data{};
|
||||||
std::vector<u32> code{};
|
std::vector<u32> code{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ComputerShaderDump {
|
struct PipelineComputerProgramDump {
|
||||||
Vulkan::Liverpool::ComputeProgram cs_program{};
|
Vulkan::Liverpool::ComputeProgram cs_program{};
|
||||||
std::vector<u32> code{};
|
std::vector<u32> code{};
|
||||||
};
|
};
|
||||||
@@ -63,8 +63,8 @@ struct RegDump {
|
|||||||
bool is_compute{false};
|
bool is_compute{false};
|
||||||
static constexpr size_t MaxShaderStages = 5;
|
static constexpr size_t MaxShaderStages = 5;
|
||||||
Vulkan::Liverpool::Regs regs{};
|
Vulkan::Liverpool::Regs regs{};
|
||||||
std::array<ShaderDump, MaxShaderStages> stages{};
|
std::array<PipelineShaderProgramDump, MaxShaderStages> stages{};
|
||||||
ComputerShaderDump cs_data{};
|
PipelineComputerProgramDump cs_data{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FrameDump {
|
struct FrameDump {
|
||||||
@@ -73,9 +73,61 @@ struct FrameDump {
|
|||||||
std::unordered_map<uintptr_t, RegDump> regs; // address -> reg dump
|
std::unordered_map<uintptr_t, RegDump> regs; // address -> reg dump
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ShaderDump {
|
||||||
|
std::string name;
|
||||||
|
Shader::LogicalStage l_stage;
|
||||||
|
vk::ShaderModule module;
|
||||||
|
|
||||||
|
std::vector<u32> spv;
|
||||||
|
std::vector<u32> isa;
|
||||||
|
|
||||||
|
std::vector<u32> patch_spv;
|
||||||
|
std::string patch_source{};
|
||||||
|
|
||||||
|
bool loaded_data = false;
|
||||||
|
bool is_patched = false;
|
||||||
|
std::string cache_spv_disasm{};
|
||||||
|
std::string cache_isa_disasm{};
|
||||||
|
std::string cache_patch_disasm{};
|
||||||
|
|
||||||
|
ShaderDump(std::string name, Shader::LogicalStage l_stage, vk::ShaderModule module,
|
||||||
|
std::vector<u32> spv, std::vector<u32> isa, std::vector<u32> patch_spv,
|
||||||
|
bool is_patched)
|
||||||
|
: name(std::move(name)), l_stage(l_stage), module(module), spv(std::move(spv)),
|
||||||
|
isa(std::move(isa)), patch_spv(std::move(patch_spv)), is_patched(is_patched) {}
|
||||||
|
|
||||||
|
ShaderDump(const ShaderDump& other) = delete;
|
||||||
|
ShaderDump(ShaderDump&& other) noexcept
|
||||||
|
: name{std::move(other.name)}, l_stage(other.l_stage), module{std::move(other.module)},
|
||||||
|
spv{std::move(other.spv)}, isa{std::move(other.isa)},
|
||||||
|
patch_spv{std::move(other.patch_spv)}, patch_source{std::move(other.patch_source)},
|
||||||
|
cache_spv_disasm{std::move(other.cache_spv_disasm)},
|
||||||
|
cache_isa_disasm{std::move(other.cache_isa_disasm)},
|
||||||
|
cache_patch_disasm{std::move(other.cache_patch_disasm)} {}
|
||||||
|
ShaderDump& operator=(const ShaderDump& other) = delete;
|
||||||
|
ShaderDump& operator=(ShaderDump&& other) noexcept {
|
||||||
|
if (this == &other)
|
||||||
|
return *this;
|
||||||
|
name = std::move(other.name);
|
||||||
|
l_stage = other.l_stage;
|
||||||
|
module = std::move(other.module);
|
||||||
|
spv = std::move(other.spv);
|
||||||
|
isa = std::move(other.isa);
|
||||||
|
patch_spv = std::move(other.patch_spv);
|
||||||
|
patch_source = std::move(other.patch_source);
|
||||||
|
cache_spv_disasm = std::move(other.cache_spv_disasm);
|
||||||
|
cache_isa_disasm = std::move(other.cache_isa_disasm);
|
||||||
|
cache_patch_disasm = std::move(other.cache_patch_disasm);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class DebugStateImpl {
|
class DebugStateImpl {
|
||||||
friend class Core::Devtools::Layer;
|
friend class Core::Devtools::Layer;
|
||||||
friend class Core::Devtools::Widget::FrameGraph;
|
friend class Core::Devtools::Widget::FrameGraph;
|
||||||
|
friend class Core::Devtools::Widget::ShaderList;
|
||||||
|
|
||||||
|
std::queue<std::string> debug_message_popup;
|
||||||
|
|
||||||
std::mutex guest_threads_mutex{};
|
std::mutex guest_threads_mutex{};
|
||||||
std::vector<ThreadID> guest_threads{};
|
std::vector<ThreadID> guest_threads{};
|
||||||
@@ -94,7 +146,7 @@ class DebugStateImpl {
|
|||||||
std::shared_mutex frame_dump_list_mutex;
|
std::shared_mutex frame_dump_list_mutex;
|
||||||
std::vector<FrameDump> frame_dump_list{};
|
std::vector<FrameDump> frame_dump_list{};
|
||||||
|
|
||||||
std::queue<std::string> debug_message_popup;
|
std::vector<ShaderDump> shader_dump_list{};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void ShowDebugMessage(std::string message) {
|
void ShowDebugMessage(std::string message) {
|
||||||
@@ -151,7 +203,17 @@ public:
|
|||||||
void PushQueueDump(QueueDump dump);
|
void PushQueueDump(QueueDump dump);
|
||||||
|
|
||||||
void PushRegsDump(uintptr_t base_addr, uintptr_t header_addr,
|
void PushRegsDump(uintptr_t base_addr, uintptr_t header_addr,
|
||||||
const AmdGpu::Liverpool::Regs& regs, bool is_compute = false);
|
const AmdGpu::Liverpool::Regs& regs);
|
||||||
|
using CsState = AmdGpu::Liverpool::ComputeProgram;
|
||||||
|
void PushRegsDumpCompute(uintptr_t base_addr, uintptr_t header_addr, const CsState& cs_state);
|
||||||
|
|
||||||
|
void CollectShader(const std::string& name, Shader::LogicalStage l_stage,
|
||||||
|
vk::ShaderModule module, std::span<const u32> spv,
|
||||||
|
std::span<const u32> raw_code, std::span<const u32> patch_spv,
|
||||||
|
bool is_patched);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::optional<RegDump*> GetRegDump(uintptr_t base_addr, uintptr_t header_addr);
|
||||||
};
|
};
|
||||||
} // namespace DebugStateType
|
} // namespace DebugStateType
|
||||||
|
|
||||||
|
|||||||
12
src/core/devices/base_device.cpp
Normal file
12
src/core/devices/base_device.cpp
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "base_device.h"
|
||||||
|
|
||||||
|
namespace Core::Devices {
|
||||||
|
|
||||||
|
BaseDevice::BaseDevice() = default;
|
||||||
|
|
||||||
|
BaseDevice::~BaseDevice() = default;
|
||||||
|
|
||||||
|
} // namespace Core::Devices
|
||||||
72
src/core/devices/base_device.h
Normal file
72
src/core/devices/base_device.h
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <core/libraries/kernel/orbis_error.h>
|
||||||
|
#include "common/types.h"
|
||||||
|
#include "common/va_ctx.h"
|
||||||
|
|
||||||
|
namespace Libraries::Kernel {
|
||||||
|
struct OrbisKernelStat;
|
||||||
|
struct SceKernelIovec;
|
||||||
|
} // namespace Libraries::Kernel
|
||||||
|
|
||||||
|
namespace Core::Devices {
|
||||||
|
|
||||||
|
class BaseDevice {
|
||||||
|
public:
|
||||||
|
explicit BaseDevice();
|
||||||
|
|
||||||
|
virtual ~BaseDevice() = 0;
|
||||||
|
|
||||||
|
virtual int ioctl(u64 cmd, Common::VaCtx* args) {
|
||||||
|
return ORBIS_KERNEL_ERROR_ENOTTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual s64 write(const void* buf, size_t nbytes) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual s64 lseek(s64 offset, int whence) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual s64 read(void* buf, size_t nbytes) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual s32 fsync() {
|
||||||
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int ftruncate(s64 length) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int getdents(void* buf, u32 nbytes, s64* basep) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual s64 pwrite(const void* buf, size_t nbytes, u64 offset) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Core::Devices
|
||||||
67
src/core/devices/ioccom.h
Normal file
67
src/core/devices/ioccom.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1982, 1986, 1990, 1993, 1994
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)ioccom.h 8.2 (Berkeley) 3/28/94
|
||||||
|
* $FreeBSD$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define IOCPARM_SHIFT 13 /* number of bits for ioctl size */
|
||||||
|
#define IOCPARM_MASK ((1 << IOCPARM_SHIFT) - 1) /* parameter length mask */
|
||||||
|
#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
|
||||||
|
#define IOCBASECMD(x) ((x) & ~(IOCPARM_MASK << 16))
|
||||||
|
#define IOCGROUP(x) (((x) >> 8) & 0xff)
|
||||||
|
|
||||||
|
#define IOCPARM_MAX (1 << IOCPARM_SHIFT) /* max size of ioctl */
|
||||||
|
#define IOC_VOID 0x20000000 /* no parameters */
|
||||||
|
#define IOC_OUT 0x40000000 /* copy out parameters */
|
||||||
|
#define IOC_IN 0x80000000 /* copy in parameters */
|
||||||
|
#define IOC_INOUT (IOC_IN | IOC_OUT)
|
||||||
|
#define IOC_DIRMASK (IOC_VOID | IOC_OUT | IOC_IN)
|
||||||
|
|
||||||
|
#define _IOC(inout, group, num, len) \
|
||||||
|
((unsigned long)((inout) | (((len) & IOCPARM_MASK) << 16) | ((group) << 8) | (num)))
|
||||||
|
#define _IO(g, n) _IOC(IOC_VOID, (g), (n), 0)
|
||||||
|
#define _IOWINT(g, n) _IOC(IOC_VOID, (g), (n), sizeof(int))
|
||||||
|
#define _IOR(g, n, t) _IOC(IOC_OUT, (g), (n), sizeof(t))
|
||||||
|
#define _IOW(g, n, t) _IOC(IOC_IN, (g), (n), sizeof(t))
|
||||||
|
/* this should be _IORW, but stdio got there first */
|
||||||
|
#define _IOWR(g, n, t) _IOC(IOC_INOUT, (g), (n), sizeof(t))
|
||||||
|
|
||||||
|
/*
|
||||||
|
# Simple parse of ioctl cmd
|
||||||
|
def parse(v):
|
||||||
|
print('inout', (v >> 24 & 0xFF))
|
||||||
|
print('len', hex(v >> 16 & 0xFF))
|
||||||
|
print('group', chr(v >> 8 & 0xFF))
|
||||||
|
print('num', hex(v & 0xFF))
|
||||||
|
*/
|
||||||
65
src/core/devices/logger.cpp
Normal file
65
src/core/devices/logger.cpp
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/libraries/kernel/file_system.h"
|
||||||
|
#include "logger.h"
|
||||||
|
|
||||||
|
namespace Core::Devices {
|
||||||
|
|
||||||
|
Logger::Logger(std::string prefix, bool is_err) : prefix(std::move(prefix)), is_err(is_err) {}
|
||||||
|
|
||||||
|
Logger::~Logger() = default;
|
||||||
|
|
||||||
|
s64 Logger::write(const void* buf, size_t nbytes) {
|
||||||
|
log(static_cast<const char*>(buf), nbytes);
|
||||||
|
return nbytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Logger::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
|
||||||
|
for (int i = 0; i < iovcnt; i++) {
|
||||||
|
log(static_cast<const char*>(iov[i].iov_base), iov[i].iov_len);
|
||||||
|
}
|
||||||
|
return iovcnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
s64 Logger::pwrite(const void* buf, size_t nbytes, u64 offset) {
|
||||||
|
log(static_cast<const char*>(buf), nbytes);
|
||||||
|
return nbytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 Logger::fsync() {
|
||||||
|
log_flush();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::log(const char* buf, size_t nbytes) {
|
||||||
|
std::scoped_lock lock{mtx};
|
||||||
|
const char* end = buf + nbytes;
|
||||||
|
for (const char* it = buf; it < end; ++it) {
|
||||||
|
char c = *it;
|
||||||
|
if (c == '\r') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c == '\n') {
|
||||||
|
log_flush();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
buffer.push_back(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::log_flush() {
|
||||||
|
std::scoped_lock lock{mtx};
|
||||||
|
if (buffer.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (is_err) {
|
||||||
|
LOG_ERROR(Tty, "[{}] {}", prefix, std::string_view{buffer});
|
||||||
|
} else {
|
||||||
|
LOG_INFO(Tty, "[{}] {}", prefix, std::string_view{buffer});
|
||||||
|
}
|
||||||
|
buffer.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Core::Devices
|
||||||
37
src/core/devices/logger.h
Normal file
37
src/core/devices/logger.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "base_device.h"
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Core::Devices {
|
||||||
|
|
||||||
|
class Logger final : BaseDevice {
|
||||||
|
std::string prefix;
|
||||||
|
bool is_err;
|
||||||
|
|
||||||
|
std::recursive_mutex mtx;
|
||||||
|
std::vector<char> buffer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Logger(std::string prefix, bool is_err);
|
||||||
|
|
||||||
|
~Logger() override;
|
||||||
|
|
||||||
|
s64 write(const void* buf, size_t nbytes) override;
|
||||||
|
size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
|
||||||
|
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override;
|
||||||
|
|
||||||
|
s32 fsync() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void log(const char* buf, size_t nbytes);
|
||||||
|
void log_flush();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Core::Devices
|
||||||
55
src/core/devices/nop_device.h
Normal file
55
src/core/devices/nop_device.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "base_device.h"
|
||||||
|
|
||||||
|
namespace Core::Devices {
|
||||||
|
|
||||||
|
class NopDevice final : BaseDevice {
|
||||||
|
u32 handle;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit NopDevice(u32 handle) : handle(handle) {}
|
||||||
|
|
||||||
|
~NopDevice() override = default;
|
||||||
|
|
||||||
|
int ioctl(u64 cmd, Common::VaCtx* args) override {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
s64 write(const void* buf, size_t nbytes) override {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) override {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
s64 lseek(s64 offset, int whence) override {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
s64 read(void* buf, size_t nbytes) override {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
s32 fsync() override {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int ftruncate(s64 length) override {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int getdents(void* buf, u32 nbytes, s64* basep) override {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Core::Devices
|
||||||
@@ -289,6 +289,16 @@ const char* GetContextRegName(u32 reg_offset) {
|
|||||||
return "mmSPI_PS_INPUT_CNTL_2";
|
return "mmSPI_PS_INPUT_CNTL_2";
|
||||||
case mmSPI_PS_INPUT_CNTL_3:
|
case mmSPI_PS_INPUT_CNTL_3:
|
||||||
return "mmSPI_PS_INPUT_CNTL_3";
|
return "mmSPI_PS_INPUT_CNTL_3";
|
||||||
|
case mmPA_SU_POLY_OFFSET_FRONT_SCALE:
|
||||||
|
return "mmPA_SU_POLY_OFFSET_FRONT_SCALE";
|
||||||
|
case mmPA_SU_POLY_OFFSET_FRONT_OFFSET:
|
||||||
|
return "mmPA_SU_POLY_OFFSET_FRONT_OFFSET";
|
||||||
|
case mmPA_SU_POLY_OFFSET_BACK_SCALE:
|
||||||
|
return "mmPA_SU_POLY_OFFSET_BACK_SCALE";
|
||||||
|
case mmPA_SU_POLY_OFFSET_BACK_OFFSET:
|
||||||
|
return "mmPA_SU_POLY_OFFSET_BACK_OFFSET";
|
||||||
|
case mmPA_SU_POLY_OFFSET_CLAMP:
|
||||||
|
return "mmPA_SU_POLY_OFFSET_CLAMP";
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "layer.h"
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
#include "common/config.h"
|
#include "common/config.h"
|
||||||
@@ -9,10 +11,14 @@
|
|||||||
#include "core/debug_state.h"
|
#include "core/debug_state.h"
|
||||||
#include "imgui/imgui_std.h"
|
#include "imgui/imgui_std.h"
|
||||||
#include "imgui_internal.h"
|
#include "imgui_internal.h"
|
||||||
#include "layer.h"
|
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_presenter.h"
|
||||||
#include "widget/frame_dump.h"
|
#include "widget/frame_dump.h"
|
||||||
#include "widget/frame_graph.h"
|
#include "widget/frame_graph.h"
|
||||||
|
#include "widget/memory_map.h"
|
||||||
|
#include "widget/shader_list.h"
|
||||||
|
|
||||||
|
extern std::unique_ptr<Vulkan::Presenter> presenter;
|
||||||
|
|
||||||
using namespace ImGui;
|
using namespace ImGui;
|
||||||
using namespace Core::Devtools;
|
using namespace Core::Devtools;
|
||||||
@@ -32,6 +38,9 @@ static float debug_popup_timing = 3.0f;
|
|||||||
|
|
||||||
static bool just_opened_options = false;
|
static bool just_opened_options = false;
|
||||||
|
|
||||||
|
static Widget::MemoryMapViewer memory_map;
|
||||||
|
static Widget::ShaderList shader_list;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static std::string help_text =
|
static std::string help_text =
|
||||||
#include "help.txt"
|
#include "help.txt"
|
||||||
@@ -60,6 +69,7 @@ void L::DrawMenuBar() {
|
|||||||
}
|
}
|
||||||
if (BeginMenu("GPU Tools")) {
|
if (BeginMenu("GPU Tools")) {
|
||||||
MenuItem("Show frame info", nullptr, &frame_graph.is_open);
|
MenuItem("Show frame info", nullptr, &frame_graph.is_open);
|
||||||
|
MenuItem("Show loaded shaders", nullptr, &shader_list.open);
|
||||||
if (BeginMenu("Dump frames")) {
|
if (BeginMenu("Dump frames")) {
|
||||||
SliderInt("Count", &dump_frame_count, 1, 5);
|
SliderInt("Count", &dump_frame_count, 1, 5);
|
||||||
if (MenuItem("Dump", "Ctrl+Alt+F9", nullptr, !DebugState.DumpingCurrentFrame())) {
|
if (MenuItem("Dump", "Ctrl+Alt+F9", nullptr, !DebugState.DumpingCurrentFrame())) {
|
||||||
@@ -71,6 +81,19 @@ void L::DrawMenuBar() {
|
|||||||
open_popup_help = MenuItem("Help & Tips");
|
open_popup_help = MenuItem("Help & Tips");
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
if (BeginMenu("Display")) {
|
||||||
|
if (BeginMenu("Brightness")) {
|
||||||
|
SliderFloat("Gamma", &presenter->GetGammaRef(), 0.1f, 2.0f);
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
if (BeginMenu("Debug")) {
|
||||||
|
if (MenuItem("Memory map")) {
|
||||||
|
memory_map.open = true;
|
||||||
|
}
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
EndMainMenuBar();
|
EndMainMenuBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,19 +188,29 @@ void L::DrawAdvanced() {
|
|||||||
bool close_popup_options = true;
|
bool close_popup_options = true;
|
||||||
if (BeginPopupModal("GPU Tools Options", &close_popup_options,
|
if (BeginPopupModal("GPU Tools Options", &close_popup_options,
|
||||||
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings)) {
|
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings)) {
|
||||||
static char disassembly_cli[512];
|
static char disassembler_cli_isa[512];
|
||||||
|
static char disassembler_cli_spv[512];
|
||||||
static bool frame_dump_render_on_collapse;
|
static bool frame_dump_render_on_collapse;
|
||||||
|
|
||||||
if (just_opened_options) {
|
if (just_opened_options) {
|
||||||
just_opened_options = false;
|
just_opened_options = false;
|
||||||
auto s = Options.disassembly_cli.copy(disassembly_cli, sizeof(disassembly_cli) - 1);
|
auto s = Options.disassembler_cli_isa.copy(disassembler_cli_isa,
|
||||||
disassembly_cli[s] = '\0';
|
sizeof(disassembler_cli_isa) - 1);
|
||||||
|
disassembler_cli_isa[s] = '\0';
|
||||||
|
s = Options.disassembler_cli_spv.copy(disassembler_cli_spv,
|
||||||
|
sizeof(disassembler_cli_spv) - 1);
|
||||||
|
disassembler_cli_spv[s] = '\0';
|
||||||
frame_dump_render_on_collapse = Options.frame_dump_render_on_collapse;
|
frame_dump_render_on_collapse = Options.frame_dump_render_on_collapse;
|
||||||
}
|
}
|
||||||
|
|
||||||
InputText("Shader disassembler: ", disassembly_cli, sizeof(disassembly_cli));
|
InputText("Shader isa disassembler: ", disassembler_cli_isa, sizeof(disassembler_cli_isa));
|
||||||
if (IsItemHovered()) {
|
if (IsItemHovered()) {
|
||||||
SetTooltip(R"(Command to disassemble shaders. Example "dis.exe" --raw "{src}")");
|
SetTooltip(R"(Command to disassemble shaders. Example: dis.exe --raw "{src}")");
|
||||||
|
}
|
||||||
|
InputText("Shader SPIRV disassembler: ", disassembler_cli_spv,
|
||||||
|
sizeof(disassembler_cli_spv));
|
||||||
|
if (IsItemHovered()) {
|
||||||
|
SetTooltip(R"(Command to disassemble shaders. Example: spirv-cross -V "{src}")");
|
||||||
}
|
}
|
||||||
Checkbox("Show frame dump popups even when collapsed", &frame_dump_render_on_collapse);
|
Checkbox("Show frame dump popups even when collapsed", &frame_dump_render_on_collapse);
|
||||||
if (IsItemHovered()) {
|
if (IsItemHovered()) {
|
||||||
@@ -186,7 +219,8 @@ void L::DrawAdvanced() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Button("Save")) {
|
if (Button("Save")) {
|
||||||
Options.disassembly_cli = disassembly_cli;
|
Options.disassembler_cli_isa = disassembler_cli_isa;
|
||||||
|
Options.disassembler_cli_spv = disassembler_cli_spv;
|
||||||
Options.frame_dump_render_on_collapse = frame_dump_render_on_collapse;
|
Options.frame_dump_render_on_collapse = frame_dump_render_on_collapse;
|
||||||
SaveIniSettingsToDisk(io.IniFilename);
|
SaveIniSettingsToDisk(io.IniFilename);
|
||||||
CloseCurrentPopup();
|
CloseCurrentPopup();
|
||||||
@@ -209,11 +243,18 @@ void L::DrawAdvanced() {
|
|||||||
|
|
||||||
EndPopup();
|
EndPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (memory_map.open) {
|
||||||
|
memory_map.Draw();
|
||||||
|
}
|
||||||
|
if (shader_list.open) {
|
||||||
|
shader_list.Draw();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void L::DrawSimple() {
|
void L::DrawSimple() {
|
||||||
const auto io = GetIO();
|
const auto io = GetIO();
|
||||||
Text("Frame time: %.3f ms (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
Text("%.1f FPS (%.2f ms)", io.Framerate, 1000.0f / io.Framerate);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LoadSettings(const char* line) {
|
static void LoadSettings(const char* line) {
|
||||||
@@ -297,6 +338,7 @@ void L::Draw() {
|
|||||||
const auto fn = DebugState.flip_frame_count.load();
|
const auto fn = DebugState.flip_frame_count.load();
|
||||||
frame_graph.AddFrame(fn, io.DeltaTime);
|
frame_graph.AddFrame(fn, io.DeltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsKeyPressed(ImGuiKey_F10, false)) {
|
if (IsKeyPressed(ImGuiKey_F10, false)) {
|
||||||
if (io.KeyCtrl) {
|
if (io.KeyCtrl) {
|
||||||
show_advanced_debug = !show_advanced_debug;
|
show_advanced_debug = !show_advanced_debug;
|
||||||
|
|||||||
@@ -12,8 +12,12 @@ TOptions Options;
|
|||||||
void LoadOptionsConfig(const char* line) {
|
void LoadOptionsConfig(const char* line) {
|
||||||
char str[512];
|
char str[512];
|
||||||
int i;
|
int i;
|
||||||
if (sscanf(line, "disassembly_cli=%511[^\n]", str) == 1) {
|
if (sscanf(line, "disassembler_cli_isa=%511[^\n]", str) == 1) {
|
||||||
Options.disassembly_cli = str;
|
Options.disassembler_cli_isa = str;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (sscanf(line, "disassembler_cli_spv=%511[^\n]", str) == 1) {
|
||||||
|
Options.disassembler_cli_spv = str;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (sscanf(line, "frame_dump_render_on_collapse=%d", &i) == 1) {
|
if (sscanf(line, "frame_dump_render_on_collapse=%d", &i) == 1) {
|
||||||
@@ -23,7 +27,8 @@ void LoadOptionsConfig(const char* line) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SerializeOptionsConfig(ImGuiTextBuffer* buf) {
|
void SerializeOptionsConfig(ImGuiTextBuffer* buf) {
|
||||||
buf->appendf("disassembly_cli=%s\n", Options.disassembly_cli.c_str());
|
buf->appendf("disassembler_cli_isa=%s\n", Options.disassembler_cli_isa.c_str());
|
||||||
|
buf->appendf("disassembler_cli_spv=%s\n", Options.disassembler_cli_spv.c_str());
|
||||||
buf->appendf("frame_dump_render_on_collapse=%d\n", Options.frame_dump_render_on_collapse);
|
buf->appendf("frame_dump_render_on_collapse=%d\n", Options.frame_dump_render_on_collapse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ struct ImGuiTextBuffer;
|
|||||||
namespace Core::Devtools {
|
namespace Core::Devtools {
|
||||||
|
|
||||||
struct TOptions {
|
struct TOptions {
|
||||||
std::string disassembly_cli{};
|
std::string disassembler_cli_isa{"clrxdisasm --raw {src}"};
|
||||||
|
std::string disassembler_cli_spv{"spirv-cross -V {src}"};
|
||||||
bool frame_dump_render_on_collapse{false};
|
bool frame_dump_render_on_collapse{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
// Credits to https://github.com/psucien/tlg-emu-tools/
|
// Credits to https://github.com/psucien/tlg-emu-tools/
|
||||||
|
|
||||||
|
#include <cinttypes>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <gcn/si_ci_vi_merged_offset.h>
|
#include <gcn/si_ci_vi_merged_offset.h>
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
@@ -1224,12 +1225,12 @@ void CmdListViewer::Draw(bool only_batches_view) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Text("queue : %s", queue_name);
|
Text("queue : %s", queue_name);
|
||||||
Text("base addr: %08llX", cmdb_addr);
|
Text("base addr: %08" PRIXPTR, cmdb_addr);
|
||||||
SameLine();
|
SameLine();
|
||||||
if (SmallButton("Memory >")) {
|
if (SmallButton("Memory >")) {
|
||||||
cmdb_view.Open ^= true;
|
cmdb_view.Open ^= true;
|
||||||
}
|
}
|
||||||
Text("size : %04llX", cmdb_size);
|
Text("size : %04zX", cmdb_size);
|
||||||
Separator();
|
Separator();
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -1292,12 +1293,12 @@ void CmdListViewer::Draw(bool only_batches_view) {
|
|||||||
if (batch.type == static_cast<AmdGpu::PM4ItOpcode>(0xFF)) {
|
if (batch.type == static_cast<AmdGpu::PM4ItOpcode>(0xFF)) {
|
||||||
ignore_header = true;
|
ignore_header = true;
|
||||||
} else if (!batch.marker.empty()) {
|
} else if (!batch.marker.empty()) {
|
||||||
snprintf(batch_hdr, sizeof(batch_hdr), "%08llX: batch-%03d %s | %s",
|
snprintf(batch_hdr, sizeof(batch_hdr), "%08" PRIXPTR ": batch-%03d %s | %s",
|
||||||
cmdb_addr + batch.start_addr, batch.id,
|
cmdb_addr + batch.start_addr, batch.id,
|
||||||
Gcn::GetOpCodeName(static_cast<u32>(batch.type)),
|
Gcn::GetOpCodeName(static_cast<u32>(batch.type)),
|
||||||
batch.marker.c_str());
|
batch.marker.c_str());
|
||||||
} else {
|
} else {
|
||||||
snprintf(batch_hdr, sizeof(batch_hdr), "%08llX: batch-%03d %s",
|
snprintf(batch_hdr, sizeof(batch_hdr), "%08" PRIXPTR ": batch-%03d %s",
|
||||||
cmdb_addr + batch.start_addr, batch.id,
|
cmdb_addr + batch.start_addr, batch.id,
|
||||||
Gcn::GetOpCodeName(static_cast<u32>(batch.type)));
|
Gcn::GetOpCodeName(static_cast<u32>(batch.type)));
|
||||||
}
|
}
|
||||||
@@ -1305,7 +1306,7 @@ void CmdListViewer::Draw(bool only_batches_view) {
|
|||||||
if (batch.id == batch_bp) { // highlight batch at breakpoint
|
if (batch.id == batch_bp) { // highlight batch at breakpoint
|
||||||
PushStyleColor(ImGuiCol_Header, ImVec4{1.0f, 0.5f, 0.5f, 0.5f});
|
PushStyleColor(ImGuiCol_Header, ImVec4{1.0f, 0.5f, 0.5f, 0.5f});
|
||||||
}
|
}
|
||||||
if (batch.id == highlight_batch) {
|
if (batch.id == highlight_batch && !group_batches) {
|
||||||
PushStyleColor(ImGuiCol_Text, ImVec4{1.0f, 0.7f, 0.7f, 1.0f});
|
PushStyleColor(ImGuiCol_Text, ImVec4{1.0f, 0.7f, 0.7f, 1.0f});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1348,7 +1349,7 @@ void CmdListViewer::Draw(bool only_batches_view) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (show_batch_content) {
|
if (show_batch_content) {
|
||||||
auto processed_size = 0ull;
|
size_t processed_size = 0;
|
||||||
auto bb = ctx.LastItemData.Rect;
|
auto bb = ctx.LastItemData.Rect;
|
||||||
if (group_batches && !ignore_header) {
|
if (group_batches && !ignore_header) {
|
||||||
Indent();
|
Indent();
|
||||||
@@ -1364,9 +1365,9 @@ void CmdListViewer::Draw(bool only_batches_view) {
|
|||||||
op = pm4_t3->opcode;
|
op = pm4_t3->opcode;
|
||||||
|
|
||||||
char header_name[128];
|
char header_name[128];
|
||||||
sprintf(header_name, "%08llX: %s",
|
snprintf(header_name, sizeof(header_name), "%08" PRIXPTR ": %s",
|
||||||
cmdb_addr + batch.start_addr + processed_size,
|
cmdb_addr + batch.start_addr + processed_size,
|
||||||
Gcn::GetOpCodeName((u32)op));
|
Gcn::GetOpCodeName(static_cast<u32>(op)));
|
||||||
|
|
||||||
bool open_pm4 = TreeNode(header_name);
|
bool open_pm4 = TreeNode(header_name);
|
||||||
if (!group_batches) {
|
if (!group_batches) {
|
||||||
@@ -1458,7 +1459,7 @@ void CmdListViewer::Draw(bool only_batches_view) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (batch.id == highlight_batch) {
|
if (batch.id == highlight_batch && !group_batches) {
|
||||||
PopStyleColor();
|
PopStyleColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,16 +3,24 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
#include <magic_enum.hpp>
|
#include <magic_enum/magic_enum.hpp>
|
||||||
|
|
||||||
#include "common/bit_field.h"
|
#include "common/bit_field.h"
|
||||||
|
#include "common/io_file.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
|
#include "core/debug_state.h"
|
||||||
#include "video_core/amdgpu/pm4_opcodes.h"
|
#include "video_core/amdgpu/pm4_opcodes.h"
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#define popen _popen
|
||||||
|
#define pclose _pclose
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Core::Devtools::Widget {
|
namespace Core::Devtools::Widget {
|
||||||
/*
|
/*
|
||||||
* Generic PM4 header
|
* Generic PM4 header
|
||||||
@@ -106,4 +114,66 @@ static bool IsDrawCall(AmdGpu::PM4ItOpcode opcode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline std::optional<std::string> exec_cli(const char* cli) {
|
||||||
|
std::array<char, 64> buffer{};
|
||||||
|
std::string output;
|
||||||
|
const auto f = popen(cli, "rt");
|
||||||
|
if (!f) {
|
||||||
|
pclose(f);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
while (fgets(buffer.data(), buffer.size(), f)) {
|
||||||
|
output += buffer.data();
|
||||||
|
}
|
||||||
|
pclose(f);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline std::string RunDisassembler(const std::string& disassembler_cli, const T& shader_code,
|
||||||
|
bool* success = nullptr) {
|
||||||
|
std::string shader_dis;
|
||||||
|
|
||||||
|
if (disassembler_cli.empty()) {
|
||||||
|
shader_dis = "No disassembler set";
|
||||||
|
if (success) {
|
||||||
|
*success = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto bin_path = std::filesystem::temp_directory_path() / "shadps4_tmp_shader.bin";
|
||||||
|
|
||||||
|
constexpr std::string_view src_arg = "{src}";
|
||||||
|
std::string cli = disassembler_cli + " 2>&1";
|
||||||
|
const auto pos = cli.find(src_arg);
|
||||||
|
if (pos == std::string::npos) {
|
||||||
|
shader_dis = "Disassembler CLI does not contain {src} argument";
|
||||||
|
if (success) {
|
||||||
|
*success = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cli.replace(pos, src_arg.size(), "\"" + bin_path.string() + "\"");
|
||||||
|
Common::FS::IOFile file(bin_path, Common::FS::FileAccessMode::Write);
|
||||||
|
file.Write(shader_code);
|
||||||
|
file.Close();
|
||||||
|
|
||||||
|
auto result = exec_cli(cli.c_str());
|
||||||
|
if (result) {
|
||||||
|
shader_dis = result.value();
|
||||||
|
if (success) {
|
||||||
|
*success = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (success) {
|
||||||
|
*success = false;
|
||||||
|
}
|
||||||
|
shader_dis = "Could not disassemble shader";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::filesystem::remove(bin_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return shader_dis;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Core::Devtools::Widget
|
} // namespace Core::Devtools::Widget
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <fmt/chrono.h>
|
#include <fmt/chrono.h>
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <magic_enum.hpp>
|
#include <magic_enum/magic_enum.hpp>
|
||||||
|
|
||||||
#include "common/io_file.h"
|
#include "common/io_file.h"
|
||||||
#include "core/devtools/options.h"
|
#include "core/devtools/options.h"
|
||||||
|
|||||||
@@ -458,7 +458,7 @@ struct MemoryEditor {
|
|||||||
data_write = data_next = true;
|
data_write = data_next = true;
|
||||||
if (data_editing_addr_next != (size_t)-1)
|
if (data_editing_addr_next != (size_t)-1)
|
||||||
data_write = data_next = false;
|
data_write = data_next = false;
|
||||||
unsigned int data_input_value = 0;
|
u32 data_input_value = 0;
|
||||||
if (!ReadOnly && data_write &&
|
if (!ReadOnly && data_write &&
|
||||||
sscanf(DataInputBuf, "%X", &data_input_value) == 1) {
|
sscanf(DataInputBuf, "%X", &data_input_value) == 1) {
|
||||||
if (WriteFn)
|
if (WriteFn)
|
||||||
@@ -929,7 +929,7 @@ struct MemoryEditor {
|
|||||||
default:
|
default:
|
||||||
case ImGuiDataType_COUNT:
|
case ImGuiDataType_COUNT:
|
||||||
break;
|
break;
|
||||||
} // Switch
|
} // Switch
|
||||||
IM_ASSERT(0); // Shouldn't reach
|
IM_ASSERT(0); // Shouldn't reach
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
135
src/core/devtools/widget/memory_map.cpp
Normal file
135
src/core/devtools/widget/memory_map.cpp
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <cinttypes>
|
||||||
|
#include <imgui.h>
|
||||||
|
#include <magic_enum/magic_enum.hpp>
|
||||||
|
|
||||||
|
#include "core/debug_state.h"
|
||||||
|
#include "core/memory.h"
|
||||||
|
#include "memory_map.h"
|
||||||
|
|
||||||
|
using namespace ImGui;
|
||||||
|
|
||||||
|
namespace Core::Devtools::Widget {
|
||||||
|
|
||||||
|
bool MemoryMapViewer::Iterator::DrawLine() {
|
||||||
|
if (is_vma) {
|
||||||
|
if (vma.it == vma.end) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto m = vma.it->second;
|
||||||
|
if (m.type == VMAType::Free) {
|
||||||
|
++vma.it;
|
||||||
|
return DrawLine();
|
||||||
|
}
|
||||||
|
TableNextColumn();
|
||||||
|
Text("%" PRIXPTR, m.base);
|
||||||
|
TableNextColumn();
|
||||||
|
Text("%zX", m.size);
|
||||||
|
TableNextColumn();
|
||||||
|
Text("%s", magic_enum::enum_name(m.type).data());
|
||||||
|
TableNextColumn();
|
||||||
|
Text("%s", magic_enum::enum_name(m.prot).data());
|
||||||
|
TableNextColumn();
|
||||||
|
if (m.is_exec) {
|
||||||
|
Text("X");
|
||||||
|
}
|
||||||
|
TableNextColumn();
|
||||||
|
Text("%s", m.name.c_str());
|
||||||
|
++vma.it;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (dmem.it == dmem.end) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto m = dmem.it->second;
|
||||||
|
if (m.is_free) {
|
||||||
|
++dmem.it;
|
||||||
|
return DrawLine();
|
||||||
|
}
|
||||||
|
TableNextColumn();
|
||||||
|
Text("%" PRIXPTR, m.base);
|
||||||
|
TableNextColumn();
|
||||||
|
Text("%zX", m.size);
|
||||||
|
TableNextColumn();
|
||||||
|
auto type = static_cast<::Libraries::Kernel::MemoryTypes>(m.memory_type);
|
||||||
|
Text("%s", magic_enum::enum_name(type).data());
|
||||||
|
TableNextColumn();
|
||||||
|
Text("%d", m.is_pooled);
|
||||||
|
++dmem.it;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryMapViewer::Draw() {
|
||||||
|
SetNextWindowSize({600.0f, 500.0f}, ImGuiCond_FirstUseEver);
|
||||||
|
if (!Begin("Memory map", &open)) {
|
||||||
|
End();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto mem = Memory::Instance();
|
||||||
|
std::scoped_lock lck{mem->mutex};
|
||||||
|
|
||||||
|
{
|
||||||
|
bool next_showing_vma = showing_vma;
|
||||||
|
if (showing_vma) {
|
||||||
|
PushStyleColor(ImGuiCol_Button, ImVec4{1.0f, 0.7f, 0.7f, 1.0f});
|
||||||
|
}
|
||||||
|
if (Button("VMem")) {
|
||||||
|
next_showing_vma = true;
|
||||||
|
}
|
||||||
|
if (showing_vma) {
|
||||||
|
PopStyleColor();
|
||||||
|
}
|
||||||
|
SameLine();
|
||||||
|
if (!showing_vma) {
|
||||||
|
PushStyleColor(ImGuiCol_Button, ImVec4{1.0f, 0.7f, 0.7f, 1.0f});
|
||||||
|
}
|
||||||
|
if (Button("DMem")) {
|
||||||
|
next_showing_vma = false;
|
||||||
|
}
|
||||||
|
if (!showing_vma) {
|
||||||
|
PopStyleColor();
|
||||||
|
}
|
||||||
|
showing_vma = next_showing_vma;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator it{};
|
||||||
|
if (showing_vma) {
|
||||||
|
it.is_vma = true;
|
||||||
|
it.vma.it = mem->vma_map.begin();
|
||||||
|
it.vma.end = mem->vma_map.end();
|
||||||
|
} else {
|
||||||
|
it.is_vma = false;
|
||||||
|
it.dmem.it = mem->dmem_map.begin();
|
||||||
|
it.dmem.end = mem->dmem_map.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BeginTable("memory_view_table", showing_vma ? 6 : 4,
|
||||||
|
ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_RowBg |
|
||||||
|
ImGuiTableFlags_SizingFixedFit)) {
|
||||||
|
if (showing_vma) {
|
||||||
|
TableSetupColumn("Address");
|
||||||
|
TableSetupColumn("Size");
|
||||||
|
TableSetupColumn("Type");
|
||||||
|
TableSetupColumn("Prot");
|
||||||
|
TableSetupColumn("Is Exec");
|
||||||
|
TableSetupColumn("Name");
|
||||||
|
} else {
|
||||||
|
TableSetupColumn("Address");
|
||||||
|
TableSetupColumn("Size");
|
||||||
|
TableSetupColumn("Type");
|
||||||
|
TableSetupColumn("Pooled");
|
||||||
|
}
|
||||||
|
TableHeadersRow();
|
||||||
|
|
||||||
|
while (it.DrawLine())
|
||||||
|
;
|
||||||
|
EndTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
End();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Core::Devtools::Widget
|
||||||
33
src/core/devtools/widget/memory_map.h
Normal file
33
src/core/devtools/widget/memory_map.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/memory.h"
|
||||||
|
|
||||||
|
namespace Core::Devtools::Widget {
|
||||||
|
|
||||||
|
class MemoryMapViewer {
|
||||||
|
struct Iterator {
|
||||||
|
bool is_vma;
|
||||||
|
struct {
|
||||||
|
MemoryManager::DMemMap::iterator it;
|
||||||
|
MemoryManager::DMemMap::iterator end;
|
||||||
|
} dmem;
|
||||||
|
struct {
|
||||||
|
MemoryManager::VMAMap::iterator it;
|
||||||
|
MemoryManager::VMAMap::iterator end;
|
||||||
|
} vma;
|
||||||
|
|
||||||
|
bool DrawLine();
|
||||||
|
};
|
||||||
|
|
||||||
|
bool showing_vma = true;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool open = false;
|
||||||
|
|
||||||
|
void Draw();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Core::Devtools::Widget
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <magic_enum.hpp>
|
#include <magic_enum/magic_enum.hpp>
|
||||||
|
|
||||||
#include "cmd_list.h"
|
#include "cmd_list.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <magic_enum.hpp>
|
#include <magic_enum/magic_enum.hpp>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
@@ -25,21 +25,6 @@ using magic_enum::enum_name;
|
|||||||
|
|
||||||
constexpr auto depth_id = 0xF3;
|
constexpr auto depth_id = 0xF3;
|
||||||
|
|
||||||
static std::optional<std::string> exec_cli(const char* cli) {
|
|
||||||
std::array<char, 64> buffer{};
|
|
||||||
std::string output;
|
|
||||||
const auto f = popen(cli, "r");
|
|
||||||
if (!f) {
|
|
||||||
pclose(f);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
while (fgets(buffer.data(), buffer.size(), f)) {
|
|
||||||
output += buffer.data();
|
|
||||||
}
|
|
||||||
pclose(f);
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Core::Devtools::Widget {
|
namespace Core::Devtools::Widget {
|
||||||
|
|
||||||
void RegView::ProcessShader(int shader_id) {
|
void RegView::ProcessShader(int shader_id) {
|
||||||
@@ -54,38 +39,12 @@ void RegView::ProcessShader(int shader_id) {
|
|||||||
user_data = s.user_data.user_data;
|
user_data = s.user_data.user_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string shader_dis;
|
std::string shader_dis = RunDisassembler(Options.disassembler_cli_isa, shader_code);
|
||||||
|
|
||||||
if (Options.disassembly_cli.empty()) {
|
|
||||||
shader_dis = "No disassembler set";
|
|
||||||
} else {
|
|
||||||
auto bin_path = std::filesystem::temp_directory_path() / "shadps4_tmp_shader.bin";
|
|
||||||
|
|
||||||
constexpr std::string_view src_arg = "{src}";
|
|
||||||
std::string cli = Options.disassembly_cli;
|
|
||||||
const auto pos = cli.find(src_arg);
|
|
||||||
if (pos == std::string::npos) {
|
|
||||||
DebugState.ShowDebugMessage("Disassembler CLI does not contain {src} argument");
|
|
||||||
} else {
|
|
||||||
cli.replace(pos, src_arg.size(), "\"" + bin_path.string() + "\"");
|
|
||||||
Common::FS::IOFile file(bin_path, Common::FS::FileAccessMode::Write);
|
|
||||||
file.Write(shader_code);
|
|
||||||
file.Close();
|
|
||||||
|
|
||||||
auto result = exec_cli(cli.c_str());
|
|
||||||
shader_dis = result.value_or("Could not disassemble shader");
|
|
||||||
if (shader_dis.empty()) {
|
|
||||||
shader_dis = "Disassembly empty or failed";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::filesystem::remove(bin_path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryEditor hex_view;
|
MemoryEditor hex_view;
|
||||||
hex_view.Open = true;
|
hex_view.Open = true;
|
||||||
hex_view.ReadOnly = true;
|
hex_view.ReadOnly = true;
|
||||||
hex_view.Cols = 8;
|
hex_view.Cols = 16;
|
||||||
hex_view.OptShowAscii = false;
|
hex_view.OptShowAscii = false;
|
||||||
hex_view.OptShowOptions = false;
|
hex_view.OptShowOptions = false;
|
||||||
|
|
||||||
@@ -376,7 +335,9 @@ void RegView::Draw() {
|
|||||||
if (!shader) {
|
if (!shader) {
|
||||||
Text("Stage not selected");
|
Text("Stage not selected");
|
||||||
} else {
|
} else {
|
||||||
shader->hex_view.DrawContents(shader->user_data.data(), shader->user_data.size());
|
shader->hex_view.DrawContents(shader->user_data.data(),
|
||||||
|
shader->user_data.size() *
|
||||||
|
sizeof(Vulkan::Liverpool::UserData::value_type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
End();
|
End();
|
||||||
|
|||||||
252
src/core/devtools/widget/shader_list.cpp
Normal file
252
src/core/devtools/widget/shader_list.cpp
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include "shader_list.h"
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "common/config.h"
|
||||||
|
#include "common/path_util.h"
|
||||||
|
#include "common/string_util.h"
|
||||||
|
#include "core/debug_state.h"
|
||||||
|
#include "core/devtools/options.h"
|
||||||
|
#include "imgui/imgui_std.h"
|
||||||
|
#include "sdl_window.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_presenter.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_rasterizer.h"
|
||||||
|
|
||||||
|
extern std::unique_ptr<Vulkan::Presenter> presenter;
|
||||||
|
|
||||||
|
using namespace ImGui;
|
||||||
|
|
||||||
|
namespace Core::Devtools::Widget {
|
||||||
|
|
||||||
|
ShaderList::Selection::Selection(int index) : index(index) {
|
||||||
|
isa_editor.SetPalette(TextEditor::GetDarkPalette());
|
||||||
|
isa_editor.SetReadOnly(true);
|
||||||
|
glsl_editor.SetPalette(TextEditor::GetDarkPalette());
|
||||||
|
glsl_editor.SetLanguageDefinition(TextEditor::LanguageDefinition::GLSL());
|
||||||
|
presenter->GetWindow().RequestKeyboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderList::Selection::~Selection() {
|
||||||
|
presenter->GetWindow().ReleaseKeyboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderList::Selection::ReloadShader(DebugStateType::ShaderDump& value) {
|
||||||
|
auto& spv = value.is_patched ? value.patch_spv : value.spv;
|
||||||
|
if (spv.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto& cache = presenter->GetRasterizer().GetPipelineCache();
|
||||||
|
if (const auto m = cache.ReplaceShader(value.module, spv); m) {
|
||||||
|
value.module = *m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShaderList::Selection::DrawShader(DebugStateType::ShaderDump& value) {
|
||||||
|
if (!value.loaded_data) {
|
||||||
|
value.loaded_data = true;
|
||||||
|
if (value.cache_isa_disasm.empty()) {
|
||||||
|
value.cache_isa_disasm = RunDisassembler(Options.disassembler_cli_isa, value.isa);
|
||||||
|
}
|
||||||
|
if (value.cache_spv_disasm.empty()) {
|
||||||
|
value.cache_spv_disasm = RunDisassembler(Options.disassembler_cli_spv, value.spv);
|
||||||
|
}
|
||||||
|
if (!value.patch_spv.empty() && value.cache_patch_disasm.empty()) {
|
||||||
|
value.cache_patch_disasm = RunDisassembler("spirv-dis {src}", value.patch_spv);
|
||||||
|
}
|
||||||
|
patch_path =
|
||||||
|
Common::FS::GetUserPath(Common::FS::PathType::ShaderDir) / "patch" / value.name;
|
||||||
|
patch_bin_path = patch_path;
|
||||||
|
patch_bin_path += ".spv";
|
||||||
|
patch_path += ".glsl";
|
||||||
|
if (std::filesystem::exists(patch_path)) {
|
||||||
|
std::ifstream file{patch_path};
|
||||||
|
value.patch_source =
|
||||||
|
std::string{std::istreambuf_iterator{file}, std::istreambuf_iterator<char>{}};
|
||||||
|
}
|
||||||
|
|
||||||
|
value.is_patched = !value.patch_spv.empty();
|
||||||
|
if (!value.is_patched) { // No patch
|
||||||
|
isa_editor.SetText(value.cache_isa_disasm);
|
||||||
|
glsl_editor.SetText(value.cache_spv_disasm);
|
||||||
|
} else {
|
||||||
|
isa_editor.SetText(value.cache_patch_disasm);
|
||||||
|
isa_editor.SetLanguageDefinition(TextEditor::LanguageDefinition::SPIRV());
|
||||||
|
glsl_editor.SetText(value.patch_source);
|
||||||
|
glsl_editor.SetReadOnly(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char name[64];
|
||||||
|
snprintf(name, sizeof(name), "Shader %s", value.name.c_str());
|
||||||
|
SetNextWindowSize({450.0f, 600.0f}, ImGuiCond_FirstUseEver);
|
||||||
|
if (!Begin(name, &open, ImGuiWindowFlags_NoNav)) {
|
||||||
|
End();
|
||||||
|
return open;
|
||||||
|
}
|
||||||
|
|
||||||
|
Text("%s", value.name.c_str());
|
||||||
|
SameLine(0.0f, 7.0f);
|
||||||
|
if (Checkbox("Enable patch", &value.is_patched)) {
|
||||||
|
if (value.is_patched) {
|
||||||
|
if (value.patch_source.empty()) {
|
||||||
|
value.patch_source = value.cache_spv_disasm;
|
||||||
|
}
|
||||||
|
isa_editor.SetText(value.cache_patch_disasm);
|
||||||
|
isa_editor.SetLanguageDefinition(TextEditor::LanguageDefinition::SPIRV());
|
||||||
|
glsl_editor.SetText(value.patch_source);
|
||||||
|
glsl_editor.SetReadOnly(false);
|
||||||
|
if (!value.patch_spv.empty()) {
|
||||||
|
ReloadShader(value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isa_editor.SetText(value.cache_isa_disasm);
|
||||||
|
isa_editor.SetLanguageDefinition(TextEditor::LanguageDefinition());
|
||||||
|
glsl_editor.SetText(value.cache_spv_disasm);
|
||||||
|
glsl_editor.SetReadOnly(true);
|
||||||
|
ReloadShader(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.is_patched) {
|
||||||
|
if (BeginCombo("Shader type", showing_bin ? "SPIRV" : "GLSL",
|
||||||
|
ImGuiComboFlags_WidthFitPreview)) {
|
||||||
|
if (Selectable("GLSL")) {
|
||||||
|
showing_bin = false;
|
||||||
|
}
|
||||||
|
if (Selectable("SPIRV")) {
|
||||||
|
showing_bin = true;
|
||||||
|
}
|
||||||
|
EndCombo();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (BeginCombo("Shader type", showing_bin ? "ISA" : "GLSL",
|
||||||
|
ImGuiComboFlags_WidthFitPreview)) {
|
||||||
|
if (Selectable("GLSL")) {
|
||||||
|
showing_bin = false;
|
||||||
|
}
|
||||||
|
if (Selectable("ISA")) {
|
||||||
|
showing_bin = true;
|
||||||
|
}
|
||||||
|
EndCombo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.is_patched) {
|
||||||
|
bool save = false;
|
||||||
|
bool compile = false;
|
||||||
|
SameLine(0.0f, 3.0f);
|
||||||
|
if (Button("Save")) {
|
||||||
|
save = true;
|
||||||
|
}
|
||||||
|
SameLine();
|
||||||
|
if (Button("Save & Compile")) {
|
||||||
|
save = true;
|
||||||
|
compile = true;
|
||||||
|
}
|
||||||
|
if (save) {
|
||||||
|
value.patch_source = glsl_editor.GetText();
|
||||||
|
std::ofstream file{patch_path, std::ios::binary | std::ios::trunc};
|
||||||
|
file << value.patch_source;
|
||||||
|
std::string msg = "Patch saved to ";
|
||||||
|
msg += Common::U8stringToString(patch_path.u8string());
|
||||||
|
DebugState.ShowDebugMessage(msg);
|
||||||
|
}
|
||||||
|
if (compile) {
|
||||||
|
static std::map<Shader::LogicalStage, std::string> stage_arg = {
|
||||||
|
{Shader::LogicalStage::Vertex, "vert"},
|
||||||
|
{Shader::LogicalStage::TessellationControl, "tesc"},
|
||||||
|
{Shader::LogicalStage::TessellationEval, "tese"},
|
||||||
|
{Shader::LogicalStage::Geometry, "geom"},
|
||||||
|
{Shader::LogicalStage::Fragment, "frag"},
|
||||||
|
{Shader::LogicalStage::Compute, "comp"},
|
||||||
|
};
|
||||||
|
auto stage = stage_arg.find(value.l_stage);
|
||||||
|
if (stage == stage_arg.end()) {
|
||||||
|
DebugState.ShowDebugMessage(std::string{"Invalid shader stage"});
|
||||||
|
} else {
|
||||||
|
std::string cmd =
|
||||||
|
fmt::format("glslc --target-env=vulkan1.3 --target-spv=spv1.6 "
|
||||||
|
"-fshader-stage={} {{src}} -o \"{}\"",
|
||||||
|
stage->second, Common::U8stringToString(patch_bin_path.u8string()));
|
||||||
|
bool success = false;
|
||||||
|
auto res = RunDisassembler(cmd, value.patch_source, &success);
|
||||||
|
if (!res.empty() || !success) {
|
||||||
|
DebugState.ShowDebugMessage("Compilation failed:\n" + res);
|
||||||
|
} else {
|
||||||
|
Common::FS::IOFile file{patch_bin_path, Common::FS::FileAccessMode::Read};
|
||||||
|
value.patch_spv.resize(file.GetSize() / sizeof(u32));
|
||||||
|
file.Read(value.patch_spv);
|
||||||
|
value.cache_patch_disasm =
|
||||||
|
RunDisassembler("spirv-dis {src}", value.patch_spv, &success);
|
||||||
|
if (!success) {
|
||||||
|
DebugState.ShowDebugMessage("Decompilation failed (Compile was ok):\n" +
|
||||||
|
res);
|
||||||
|
} else {
|
||||||
|
isa_editor.SetText(value.cache_patch_disasm);
|
||||||
|
ReloadShader(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showing_bin) {
|
||||||
|
isa_editor.Render(value.is_patched ? "SPIRV" : "ISA", GetContentRegionAvail());
|
||||||
|
} else {
|
||||||
|
glsl_editor.Render("GLSL", GetContentRegionAvail());
|
||||||
|
}
|
||||||
|
|
||||||
|
End();
|
||||||
|
return open;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderList::Draw() {
|
||||||
|
for (auto it = open_shaders.begin(); it != open_shaders.end();) {
|
||||||
|
auto& selection = *it;
|
||||||
|
auto& shader = DebugState.shader_dump_list[selection.index];
|
||||||
|
if (!selection.DrawShader(shader)) {
|
||||||
|
it = open_shaders.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetNextWindowSize({500.0f, 600.0f}, ImGuiCond_FirstUseEver);
|
||||||
|
if (!Begin("Shader list", &open)) {
|
||||||
|
End();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Config::collectShadersForDebug()) {
|
||||||
|
DrawCenteredText("Enable 'CollectShader' in config to see shaders");
|
||||||
|
End();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto width = GetContentRegionAvail().x;
|
||||||
|
int i = 0;
|
||||||
|
for (const auto& shader : DebugState.shader_dump_list) {
|
||||||
|
char name[128];
|
||||||
|
if (shader.is_patched) {
|
||||||
|
snprintf(name, sizeof(name), "%s (PATCH ON)", shader.name.c_str());
|
||||||
|
} else if (!shader.patch_spv.empty()) {
|
||||||
|
snprintf(name, sizeof(name), "%s (PATCH OFF)", shader.name.c_str());
|
||||||
|
} else {
|
||||||
|
snprintf(name, sizeof(name), "%s", shader.name.c_str());
|
||||||
|
}
|
||||||
|
if (ButtonEx(name, {width, 20.0f}, ImGuiButtonFlags_NoHoveredOnFocus)) {
|
||||||
|
open_shaders.emplace_back(i);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
End();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Core::Devtools::Widget
|
||||||
40
src/core/devtools/widget/shader_list.h
Normal file
40
src/core/devtools/widget/shader_list.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/debug_state.h"
|
||||||
|
#include "text_editor.h"
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
namespace Core::Devtools::Widget {
|
||||||
|
|
||||||
|
class ShaderList {
|
||||||
|
struct Selection {
|
||||||
|
explicit Selection(int index);
|
||||||
|
~Selection();
|
||||||
|
|
||||||
|
void ReloadShader(DebugStateType::ShaderDump& value);
|
||||||
|
|
||||||
|
bool DrawShader(DebugStateType::ShaderDump& value);
|
||||||
|
|
||||||
|
int index;
|
||||||
|
TextEditor isa_editor{};
|
||||||
|
TextEditor glsl_editor{};
|
||||||
|
bool open = true;
|
||||||
|
bool showing_bin = false;
|
||||||
|
|
||||||
|
std::filesystem::path patch_path;
|
||||||
|
std::filesystem::path patch_bin_path;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<Selection> open_shaders{};
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool open = false;
|
||||||
|
|
||||||
|
void Draw();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Core::Devtools::Widget
|
||||||
@@ -131,7 +131,7 @@ static int UTF8CharLength(TextEditor::Char c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// "Borrowed" from ImGui source
|
// "Borrowed" from ImGui source
|
||||||
static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c) {
|
static inline int ImTextCharToUtf8(char* buf, int buf_size, u32 c) {
|
||||||
if (c < 0x80) {
|
if (c < 0x80) {
|
||||||
buf[0] = (char)c;
|
buf[0] = (char)c;
|
||||||
return 1;
|
return 1;
|
||||||
@@ -1059,7 +1059,8 @@ void TextEditor::Render(const char* aTitle, const ImVec2& aSize, bool aBorder) {
|
|||||||
if (!mIgnoreImGuiChild)
|
if (!mIgnoreImGuiChild)
|
||||||
ImGui::BeginChild(aTitle, aSize, aBorder,
|
ImGui::BeginChild(aTitle, aSize, aBorder,
|
||||||
ImGuiWindowFlags_HorizontalScrollbar |
|
ImGuiWindowFlags_HorizontalScrollbar |
|
||||||
ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NoMove);
|
ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NoMove |
|
||||||
|
ImGuiWindowFlags_NoNav);
|
||||||
|
|
||||||
if (mHandleKeyboardInputs) {
|
if (mHandleKeyboardInputs) {
|
||||||
HandleKeyboardInputs();
|
HandleKeyboardInputs();
|
||||||
@@ -2331,4 +2332,50 @@ const TextEditor::LanguageDefinition& TextEditor::LanguageDefinition::GLSL() {
|
|||||||
return langDef;
|
return langDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Source: https://github.com/dfranx/ImGuiColorTextEdit/blob/master/TextEditor.cpp
|
||||||
|
const TextEditor::LanguageDefinition& TextEditor::LanguageDefinition::SPIRV() {
|
||||||
|
static bool inited = false;
|
||||||
|
static LanguageDefinition langDef;
|
||||||
|
if (!inited) {
|
||||||
|
/*
|
||||||
|
langDef.mTokenRegexStrings.push_back(std::make_pair<std::string, PaletteIndex>("[ \\t]*#[
|
||||||
|
\\t]*[a-zA-Z_]+", PaletteIndex::Preprocessor));
|
||||||
|
langDef.mTokenRegexStrings.push_back(std::make_pair<std::string,
|
||||||
|
PaletteIndex>("\\'\\\\?[^\\']\\'", PaletteIndex::CharLiteral));
|
||||||
|
langDef.mTokenRegexStrings.push_back(std::make_pair<std::string,
|
||||||
|
PaletteIndex>("[a-zA-Z_][a-zA-Z0-9_]*", PaletteIndex::Identifier));
|
||||||
|
langDef.mTokenRegexStrings.push_back(std::make_pair<std::string,
|
||||||
|
PaletteIndex>("[\\[\\]\\{\\}\\!\\%\\^\\&\\*\\(\\)\\-\\+\\=\\~\\|\\<\\>\\?\\/\\;\\,\\.]",
|
||||||
|
PaletteIndex::Punctuation));
|
||||||
|
*/
|
||||||
|
|
||||||
|
langDef.mTokenRegexStrings.push_back(std::make_pair<std::string, PaletteIndex>(
|
||||||
|
"L?\\\"(\\\\.|[^\\\"])*\\\"", PaletteIndex::String));
|
||||||
|
langDef.mTokenRegexStrings.push_back(
|
||||||
|
std::make_pair<std::string, PaletteIndex>("[ =\\t]Op[a-zA-Z]*", PaletteIndex::Keyword));
|
||||||
|
langDef.mTokenRegexStrings.push_back(
|
||||||
|
std::make_pair<std::string, PaletteIndex>("%[_a-zA-Z0-9]*", PaletteIndex::Identifier));
|
||||||
|
langDef.mTokenRegexStrings.push_back(std::make_pair<std::string, PaletteIndex>(
|
||||||
|
"[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)([eE][+-]?[0-9]+)?[fF]?", PaletteIndex::Number));
|
||||||
|
langDef.mTokenRegexStrings.push_back(std::make_pair<std::string, PaletteIndex>(
|
||||||
|
"[+-]?[0-9]+[Uu]?[lL]?[lL]?", PaletteIndex::Number));
|
||||||
|
langDef.mTokenRegexStrings.push_back(std::make_pair<std::string, PaletteIndex>(
|
||||||
|
"0[0-7]+[Uu]?[lL]?[lL]?", PaletteIndex::Number));
|
||||||
|
langDef.mTokenRegexStrings.push_back(std::make_pair<std::string, PaletteIndex>(
|
||||||
|
"0[xX][0-9a-fA-F]+[uU]?[lL]?[lL]?", PaletteIndex::Number));
|
||||||
|
|
||||||
|
langDef.mCommentStart = "/*";
|
||||||
|
langDef.mCommentEnd = "*/";
|
||||||
|
langDef.mSingleLineComment = ";";
|
||||||
|
|
||||||
|
langDef.mCaseSensitive = true;
|
||||||
|
langDef.mAutoIndentation = false;
|
||||||
|
|
||||||
|
langDef.mName = "SPIR-V";
|
||||||
|
|
||||||
|
inited = true;
|
||||||
|
}
|
||||||
|
return langDef;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Core::Devtools::Widget
|
} // namespace Core::Devtools::Widget
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user