Compare commits
368 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f06e126330 | ||
|
|
715eb512c9 | ||
|
|
87e09b613b | ||
|
|
6c08c6983b | ||
|
|
6bd74ef769 | ||
|
|
bf34665a8f | ||
|
|
2d17ab8e4b | ||
|
|
db9921baf2 | ||
|
|
17fab7fdf1 | ||
|
|
0cd6248eee | ||
|
|
a1973438db | ||
|
|
a7376dd41f | ||
|
|
6b6294a750 | ||
|
|
999960a6e6 | ||
|
|
6805baffb2 | ||
|
|
109b239ddf | ||
|
|
1714647343 | ||
|
|
794d593a02 | ||
|
|
b34556702e | ||
|
|
a0e7f7fb65 | ||
|
|
8f37cfb739 | ||
|
|
d17a4fb8cc | ||
|
|
4fa435490c | ||
|
|
11229c1dc0 | ||
|
|
455cd37aae | ||
|
|
e7194af881 | ||
|
|
08878385e1 | ||
|
|
81098da509 | ||
|
|
5fedf9daea | ||
|
|
23d0fc6493 | ||
|
|
5c7f802233 | ||
|
|
54b5520c1a | ||
|
|
02f9aef34a | ||
|
|
8de385a4f1 | ||
|
|
110a735a04 | ||
|
|
74c0ea8432 | ||
|
|
af147debc6 | ||
|
|
1020c3150f | ||
|
|
0134b8c3a8 | ||
|
|
6fb64a8054 | ||
|
|
6d0b179d24 | ||
|
|
68fca2552f | ||
|
|
0e6dea1059 | ||
|
|
8a8ee395c5 | ||
|
|
a8f4a20b24 | ||
|
|
505e80e756 | ||
|
|
ad99bda08d | ||
|
|
a35c9f3586 | ||
|
|
cad027845f | ||
|
|
6c5a84dc99 | ||
|
|
937d50cb00 | ||
|
|
905c536ef4 | ||
|
|
528a060709 | ||
|
|
6e27842562 | ||
|
|
71f343d2d6 | ||
|
|
a6f5e4c7dc | ||
|
|
98ceb6e43e | ||
|
|
eeee6ad0ee | ||
|
|
5d8027f0c0 | ||
|
|
1eead6a5ee | ||
|
|
419ea140ab | ||
|
|
976d12f4e6 | ||
|
|
50a3081084 | ||
|
|
525d24a7fc | ||
|
|
51c96b8ee6 | ||
|
|
2b1c0b4f82 | ||
|
|
eb18382396 | ||
|
|
fa489c023e | ||
|
|
f01b6295dd | ||
|
|
be80276ec3 | ||
|
|
71e81c836c | ||
|
|
ddb59edd3e | ||
|
|
7bd3eb485f | ||
|
|
0eff74223a | ||
|
|
1e949c5813 | ||
|
|
1c0ec3be2a | ||
|
|
cf1f0f25c1 | ||
|
|
932bb25a4c | ||
|
|
99a398bd41 | ||
|
|
cf9b5a2942 | ||
|
|
0d09c32df9 | ||
|
|
7101caa80b | ||
|
|
6ab7aa3b18 | ||
|
|
775d27c0cd | ||
|
|
0e8d350f8e | ||
|
|
58fc05a127 | ||
|
|
d555241e51 | ||
|
|
c106a98bd6 | ||
|
|
fb090dc90f | ||
|
|
c42d0cff2e | ||
|
|
fd9f372a86 | ||
|
|
260e0438a7 | ||
|
|
21a1888857 | ||
|
|
c51abe4e8b | ||
|
|
e402ea3de4 | ||
|
|
321fa34892 | ||
|
|
70d33be7b7 | ||
|
|
0bfde1fcde | ||
|
|
c885b522db | ||
|
|
fa543d3cc8 | ||
|
|
9cdb6b1097 | ||
|
|
698458061e | ||
|
|
dc6bfbeb12 | ||
|
|
374c2194d4 | ||
|
|
de7652384d | ||
|
|
f3e344dfcf | ||
|
|
b132739014 | ||
|
|
eb8a454089 | ||
|
|
d4d179610d | ||
|
|
c13502d618 | ||
|
|
99d0f85739 | ||
|
|
4b0069b296 | ||
|
|
35d3d4f763 | ||
|
|
2c4f573d3a | ||
|
|
98abb4e372 | ||
|
|
319db3bebe | ||
|
|
4abc6b3010 | ||
|
|
c05695fde5 | ||
|
|
e885d52ad0 | ||
|
|
ac318b56ac | ||
|
|
f4531fd927 | ||
|
|
707fe9faff | ||
|
|
e38876b5b2 | ||
|
|
b5e2503418 | ||
|
|
133f4b9187 | ||
|
|
eb9a7e8fbd | ||
|
|
f6219e0382 | ||
|
|
ce6681b991 | ||
|
|
582daef658 | ||
|
|
0ee348622d | ||
|
|
d8e52c599b | ||
|
|
b5d8426db7 | ||
|
|
d34ae8ce08 | ||
|
|
38e6dd49b1 | ||
|
|
081d52e615 | ||
|
|
5e3ffeafbe | ||
|
|
0e7e100a7e | ||
|
|
6f5036f8dc | ||
|
|
72e00e5d91 | ||
|
|
40f6c27a50 | ||
|
|
90f6bf0516 | ||
|
|
17568353a9 | ||
|
|
c06a923b66 | ||
|
|
7db456299e | ||
|
|
53181b005c | ||
|
|
ced900f98e | ||
|
|
50683a3b87 | ||
|
|
43b72b59a2 | ||
|
|
3af5a6b1bf | ||
|
|
781f51afe7 | ||
|
|
acd8dd7074 | ||
|
|
73d6771b16 | ||
|
|
5f0b13ac57 | ||
|
|
b2269f628a | ||
|
|
e0a697f1b7 | ||
|
|
4478b47666 | ||
|
|
35933d61fc | ||
|
|
487bcaae85 | ||
|
|
e06667d307 | ||
|
|
bcbe07e6b1 | ||
|
|
e8abbd4305 | ||
|
|
df52585086 | ||
|
|
59eea3b49e | ||
|
|
59f00dc051 | ||
|
|
77b1d11796 | ||
|
|
d9b4618085 | ||
|
|
c43ab1217d | ||
|
|
9246b4277b | ||
|
|
f09c0e5a28 | ||
|
|
b4a82bfcdd | ||
|
|
47e0d488d8 | ||
|
|
3de73371c1 | ||
|
|
bcea7a02c3 | ||
|
|
be8c35eef1 | ||
|
|
af9947a862 | ||
|
|
ba65408608 | ||
|
|
e6f0ee7ed2 | ||
|
|
52d2c4ddc1 | ||
|
|
31aa7539d3 | ||
|
|
c26f56ab02 | ||
|
|
ed3f9ee626 | ||
|
|
507bd777f9 | ||
|
|
af322c3a2f | ||
|
|
673b2afaa8 | ||
|
|
32244c097c | ||
|
|
bfa5c508ce | ||
|
|
62ddc0664b | ||
|
|
56626111ab | ||
|
|
6f26f66d77 | ||
|
|
ae89a492ea | ||
|
|
90757d6d09 | ||
|
|
412355aab4 | ||
|
|
8ae45559fc | ||
|
|
d4a2ca01bf | ||
|
|
e85308c011 | ||
|
|
8ed6572393 | ||
|
|
1d459474a2 | ||
|
|
10afc6b3c6 | ||
|
|
adcf4d9749 | ||
|
|
e172323dd0 | ||
|
|
dcb256c930 | ||
|
|
1b2ac916f1 | ||
|
|
56599bcba4 | ||
|
|
25d1defb5b | ||
|
|
875724a982 | ||
|
|
c90781d3e2 | ||
|
|
6d98a5ab60 | ||
|
|
6590f07772 | ||
|
|
6dd2b3090c | ||
|
|
d42f4fcc4f | ||
|
|
babe19dcd4 | ||
|
|
7165772e9b | ||
|
|
788228c0f3 | ||
|
|
975166e5e1 | ||
|
|
709a9ac0c8 | ||
|
|
630fba2822 | ||
|
|
165f3e1e78 | ||
|
|
8a84f1b778 | ||
|
|
2d98adef17 | ||
|
|
8e8f359b56 | ||
|
|
a166e0c2e9 | ||
|
|
defd826a73 | ||
|
|
07bae57a16 | ||
|
|
68e35d57d2 | ||
|
|
0b02364f97 | ||
|
|
2d53d1a1e2 | ||
|
|
670067c001 | ||
|
|
72db53a257 | ||
|
|
3a929515e7 | ||
|
|
e93fd00dc7 | ||
|
|
8deefa63b0 | ||
|
|
1c0a5c60ea | ||
|
|
51559033ef | ||
|
|
a285543134 | ||
|
|
2c906dc280 | ||
|
|
882dd889df | ||
|
|
1b621e4b1d | ||
|
|
d6b2845dcc | ||
|
|
ff6ab9444a | ||
|
|
54de156e1e | ||
|
|
d1f9594b9d | ||
|
|
c5aed0873f | ||
|
|
4ff9d371f6 | ||
|
|
adef2ff231 | ||
|
|
e7b97580b7 | ||
|
|
d9108cd39a | ||
|
|
befc5ec17b | ||
|
|
f9ab6c48e3 | ||
|
|
f83619e313 | ||
|
|
5b46216bae | ||
|
|
841aa9e43d | ||
|
|
2f701311f2 | ||
|
|
074dfe2571 | ||
|
|
7dd64f889f | ||
|
|
7ec3a38b89 | ||
|
|
afb9e220aa | ||
|
|
0044a27c1f | ||
|
|
77410fd228 | ||
|
|
b53bda852d | ||
|
|
339081d08f | ||
|
|
7f4183eb27 | ||
|
|
42e3ce9465 | ||
|
|
012b01d81f | ||
|
|
e56232134f | ||
|
|
c7f1c66b82 | ||
|
|
a362f20dae | ||
|
|
1e7c4bb69c | ||
|
|
1b195c9613 | ||
|
|
ecc924791d | ||
|
|
78936f31fc | ||
|
|
6c34b86add | ||
|
|
f685233401 | ||
|
|
c924c20575 | ||
|
|
35132d9fdc | ||
|
|
26a92d97fa | ||
|
|
93767ae31b | ||
|
|
d286631798 | ||
|
|
968cfe1180 | ||
|
|
116554e425 | ||
|
|
df85efde7c | ||
|
|
e3fe6e2809 | ||
|
|
ee3816ffd6 | ||
|
|
2e237051e3 | ||
|
|
c863b350b2 | ||
|
|
446426224e | ||
|
|
d62d65af62 | ||
|
|
90705cbe51 | ||
|
|
8b1b0fa0dc | ||
|
|
923c5f3ef5 | ||
|
|
d46792da94 | ||
|
|
61ce393673 | ||
|
|
4c22137255 | ||
|
|
2cd42aaba9 | ||
|
|
6a476fdb42 | ||
|
|
7ef0cc0698 | ||
|
|
539b1b91a8 | ||
|
|
fb5ac912cd | ||
|
|
88161535cf | ||
|
|
93b06ba2da | ||
|
|
824d332d0f | ||
|
|
19c3d05ac1 | ||
|
|
8dc50ffc79 | ||
|
|
ea37ea11fc | ||
|
|
4d3578edbe | ||
|
|
800b332f60 | ||
|
|
b4ec1bd371 | ||
|
|
0ad7fcb341 | ||
|
|
16a6469b75 | ||
|
|
7502739425 | ||
|
|
de11de43f2 | ||
|
|
14ef56d148 | ||
|
|
9e2af5f619 | ||
|
|
637e503685 | ||
|
|
1fc9eedbab | ||
|
|
bad9cd097a | ||
|
|
a4c5fa4b5c | ||
|
|
95a386308a | ||
|
|
0706223aaf | ||
|
|
fd03fe2b5a | ||
|
|
f0cd981548 | ||
|
|
bd0102c8d0 | ||
|
|
0b72a795eb | ||
|
|
2ae7037c08 | ||
|
|
af67473de3 | ||
|
|
b56039b15a | ||
|
|
3019bfb978 | ||
|
|
76f003d388 | ||
|
|
fafd3fb564 | ||
|
|
e914099ae2 | ||
|
|
1689cdb1a2 | ||
|
|
fddded8d20 | ||
|
|
161aa49f37 | ||
|
|
68b147488e | ||
|
|
aeab525a7f | ||
|
|
499451bb80 | ||
|
|
cf8a6efd37 | ||
|
|
6e350a5085 | ||
|
|
a82698d601 | ||
|
|
83475ac828 | ||
|
|
6d6068e0e2 | ||
|
|
4407ebdd9b | ||
|
|
87f6cce7b1 | ||
|
|
bf623d4f85 | ||
|
|
97daee836a | ||
|
|
b68ca43166 | ||
|
|
00f4eeddaf | ||
|
|
399a725343 | ||
|
|
b403e1be33 | ||
|
|
8bc30270c8 | ||
|
|
88abb93669 | ||
|
|
ee97c5c110 | ||
|
|
27cbd6647f | ||
|
|
dc6ef99dc7 | ||
|
|
7d4b875ee3 | ||
|
|
f5336358ea | ||
|
|
df4314f831 | ||
|
|
e5f899aae3 | ||
|
|
2d1a2982df | ||
|
|
ddede4a52d | ||
|
|
80f7ec2681 | ||
|
|
7fedbd52e0 | ||
|
|
d6163a6edb | ||
|
|
4eaa992aff | ||
|
|
70eef0de90 | ||
|
|
146e81a56a | ||
|
|
5eef2fd28a | ||
|
|
d1f5a7e8fb | ||
|
|
78cb5334cf |
4
.github/ISSUE_TEMPLATE/game-bug-report.yaml
vendored
@@ -17,7 +17,7 @@ body:
|
||||
|
||||
This repository does not provide support for game patches. If you are having issues with patches please refer to [Cheats and Patches Repository](https://github.com/shadps4-emu/ps4_cheats).
|
||||
|
||||
Before submitting an issue please check [Game Compatibility Repository](https://github.com/shadps4-emu/shadps4-game-compatibility) for the information about the status of the game.
|
||||
Before submitting an issue please check [Game Compatibility Repository](https://github.com/shadps4-compatibility/shadps4-game-compatibility) for the information about the status of the game.
|
||||
|
||||
Please make an effort to make sure your issue isn't already reported.
|
||||
|
||||
@@ -35,7 +35,7 @@ body:
|
||||
required: true
|
||||
- label: I have disabled all patches and cheats and the issue is still present.
|
||||
required: true
|
||||
- label: I have all the required [system modules](https://github.com/shadps4-emu/shadPS4/wiki/I.-Quick-start-%5BUsers%5D#4-adding-modules) installed.
|
||||
- label: I have all the required [system modules](https://github.com/shadps4-emu/shadPS4/wiki/I.-Quick-start-%5BUsers%5D#4-dumping-firmware-modules) installed.
|
||||
required: true
|
||||
- type: textarea
|
||||
id: desc
|
||||
|
||||
56
.github/workflows/build.yml
vendored
@@ -17,14 +17,14 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- uses: fsfe/reuse-action@v5
|
||||
|
||||
clang-format:
|
||||
runs-on: ubuntu-24.04
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Install
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
shorthash: ${{ steps.vars.outputs.shorthash }}
|
||||
fullhash: ${{ steps.vars.outputs.fullhash }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- name: Get date and git hash
|
||||
id: vars
|
||||
run: |
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
runs-on: windows-2025
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
@@ -76,7 +76,7 @@ jobs:
|
||||
${{ env.cache-name }}-
|
||||
|
||||
- name: Cache CMake Build
|
||||
uses: hendrikmuhs/ccache-action@v1.2.18
|
||||
uses: hendrikmuhs/ccache-action@v1.2.19
|
||||
env:
|
||||
cache-name: ${{ runner.os }}-sdl-cache-cmake-build
|
||||
with:
|
||||
@@ -99,14 +99,14 @@ jobs:
|
||||
runs-on: windows-2025
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup Qt
|
||||
uses: jurplel/install-qt-action@v4
|
||||
with:
|
||||
version: 6.9.1
|
||||
version: 6.9.3
|
||||
host: windows
|
||||
target: desktop
|
||||
arch: win64_msvc2022_64
|
||||
@@ -125,7 +125,7 @@ jobs:
|
||||
${{ env.cache-name }}-
|
||||
|
||||
- name: Cache CMake Build
|
||||
uses: hendrikmuhs/ccache-action@v1.2.18
|
||||
uses: hendrikmuhs/ccache-action@v1.2.19
|
||||
env:
|
||||
cache-name: ${{ runner.os }}-qt-cache-cmake-build
|
||||
with:
|
||||
@@ -141,8 +141,10 @@ jobs:
|
||||
- name: Deploy and Package
|
||||
run: |
|
||||
mkdir upload
|
||||
mkdir upload/qtplugins
|
||||
move build/shadPS4.exe upload
|
||||
windeployqt --no-compiler-runtime --no-system-d3d-compiler --no-system-dxc-compiler --dir upload upload/shadPS4.exe
|
||||
cp dist/qt.conf upload/qt.conf
|
||||
windeployqt --plugindir upload/qtplugins --no-compiler-runtime --no-system-d3d-compiler --no-system-dxc-compiler --dir upload upload/shadPS4.exe
|
||||
Compress-Archive -Path upload/* -DestinationPath shadps4-win64-qt-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}.zip
|
||||
|
||||
- name: Upload Windows Qt artifact
|
||||
@@ -155,7 +157,7 @@ jobs:
|
||||
runs-on: macos-15
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
@@ -176,7 +178,7 @@ jobs:
|
||||
${{ env.cache-name }}-
|
||||
|
||||
- name: Cache CMake Build
|
||||
uses: hendrikmuhs/ccache-action@v1.2.18
|
||||
uses: hendrikmuhs/ccache-action@v1.2.19
|
||||
env:
|
||||
cache-name: ${{runner.os}}-sdl-cache-cmake-build
|
||||
with:
|
||||
@@ -206,7 +208,7 @@ jobs:
|
||||
runs-on: macos-15
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
@@ -218,16 +220,13 @@ jobs:
|
||||
- name: Setup Qt
|
||||
uses: jurplel/install-qt-action@v4
|
||||
with:
|
||||
version: 6.9.1
|
||||
version: 6.9.3
|
||||
host: mac
|
||||
target: desktop
|
||||
arch: clang_64
|
||||
archives: qtbase qttools
|
||||
modules: qtmultimedia
|
||||
|
||||
- name: Workaround Qt <=6.9.1 issue
|
||||
run: sed -i '' '/target_link_libraries(WrapOpenGL::WrapOpenGL INTERFACE ${__opengl_agl_fw_path})/d' ${{env.QT_ROOT_DIR}}/lib/cmake/Qt6/FindWrapOpenGL.cmake
|
||||
|
||||
- name: Cache CMake Configuration
|
||||
uses: actions/cache@v4
|
||||
env:
|
||||
@@ -240,7 +239,7 @@ jobs:
|
||||
${{ env.cache-name }}-
|
||||
|
||||
- name: Cache CMake Build
|
||||
uses: hendrikmuhs/ccache-action@v1.2.18
|
||||
uses: hendrikmuhs/ccache-action@v1.2.19
|
||||
env:
|
||||
cache-name: ${{runner.os}}-qt-cache-cmake-build
|
||||
with:
|
||||
@@ -270,7 +269,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
@@ -294,7 +293,7 @@ jobs:
|
||||
${{ env.cache-name }}-
|
||||
|
||||
- name: Cache CMake Build
|
||||
uses: hendrikmuhs/ccache-action@v1.2.18
|
||||
uses: hendrikmuhs/ccache-action@v1.2.19
|
||||
env:
|
||||
cache-name: ${{ runner.os }}-sdl-cache-cmake-build
|
||||
with:
|
||||
@@ -331,7 +330,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
@@ -355,7 +354,7 @@ jobs:
|
||||
${{ env.cache-name }}-
|
||||
|
||||
- name: Cache CMake Build
|
||||
uses: hendrikmuhs/ccache-action@v1.2.18
|
||||
uses: hendrikmuhs/ccache-action@v1.2.19
|
||||
env:
|
||||
cache-name: ${{ runner.os }}-qt-cache-cmake-build
|
||||
with:
|
||||
@@ -383,7 +382,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
@@ -402,7 +401,7 @@ jobs:
|
||||
${{ env.cache-name }}-
|
||||
|
||||
- name: Cache CMake Build
|
||||
uses: hendrikmuhs/ccache-action@v1.2.18
|
||||
uses: hendrikmuhs/ccache-action@v1.2.19
|
||||
env:
|
||||
cache-name: ${{ runner.os }}-sdl-gcc-cache-cmake-build
|
||||
with:
|
||||
@@ -419,7 +418,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
@@ -438,7 +437,7 @@ jobs:
|
||||
${{ env.cache-name }}-
|
||||
|
||||
- name: Cache CMake Build
|
||||
uses: hendrikmuhs/ccache-action@v1.2.18
|
||||
uses: hendrikmuhs/ccache-action@v1.2.19
|
||||
env:
|
||||
cache-name: ${{ runner.os }}-qt-gcc-cache-cmake-build
|
||||
with:
|
||||
@@ -457,9 +456,14 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
path: ./artifacts
|
||||
|
||||
- name: Make SDL artifacts executable
|
||||
run: |
|
||||
chmod -R a+x ./artifacts/shadps4-linux-sdl-*
|
||||
chmod -R a+x ./artifacts/shadps4-macos-sdl-*
|
||||
|
||||
- name: Compress individual directories (without parent directory)
|
||||
run: |
|
||||
|
||||
11
.github/workflows/scripts/update_translation.sh
vendored
@@ -1,11 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
sudo apt-get -y install qt6-l10n-tools python3
|
||||
|
||||
SCRIPT_PATH="src/qt_gui/translations/update_translation.sh"
|
||||
|
||||
chmod +x "$SCRIPT_PATH"
|
||||
|
||||
PATH=/usr/lib/qt6/bin:$PATH "$SCRIPT_PATH"
|
||||
30
.github/workflows/update_translation.yml
vendored
@@ -1,30 +0,0 @@
|
||||
name: Update Translation
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *" # Every day at 12am UTC.
|
||||
workflow_dispatch: # As well as manually.
|
||||
|
||||
jobs:
|
||||
update:
|
||||
if: github.repository == 'shadps4-emu/shadPS4'
|
||||
name: "Update Translation"
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set execution permissions for the script
|
||||
run: chmod +x ./.github/workflows/scripts/update_translation.sh
|
||||
|
||||
- name: Update Base Translation
|
||||
run: ./.github/workflows/scripts/update_translation.sh
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
token: ${{ secrets.SHADPS4_TOKEN_REPO }}
|
||||
title: "Qt GUI: Update Translation"
|
||||
commit-message: "[ci skip] Qt GUI: Update Translation."
|
||||
body: "Daily update of translation sources."
|
||||
branch: update-translation
|
||||
delete-branch: true
|
||||
28
.gitmodules
vendored
@@ -91,18 +91,22 @@
|
||||
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
|
||||
[submodule "externals/ext-libusb"]
|
||||
path = externals/ext-libusb
|
||||
url = https://github.com/shadps4-emu/ext-libusb.git
|
||||
[submodule "externals/epoll-shim"]
|
||||
path = externals/epoll-shim
|
||||
url = https://github.com/jiixyj/epoll-shim.git
|
||||
[submodule "externals/hwinfo"]
|
||||
path = externals/hwinfo
|
||||
url = https://github.com/shadps4-emu/ext-hwinfo
|
||||
shallow = true
|
||||
[submodule "externals/MoltenVK/MoltenVK"]
|
||||
path = externals/MoltenVK/MoltenVK
|
||||
url = https://github.com/KhronosGroup/MoltenVK
|
||||
[submodule "externals/ext-wepoll"]
|
||||
path = externals/ext-wepoll
|
||||
url = https://github.com/shadps4-emu/ext-wepoll.git
|
||||
shallow = true
|
||||
[submodule "externals/MoltenVK/cereal"]
|
||||
path = externals/MoltenVK/cereal
|
||||
url = https://github.com/USCiLab/cereal
|
||||
branch = dist
|
||||
[submodule "externals/MoltenVK"]
|
||||
path = externals/MoltenVK
|
||||
url = https://github.com/KhronosGroup/MoltenVK.git
|
||||
shallow = true
|
||||
[submodule "externals/libusb"]
|
||||
path = externals/libusb
|
||||
url = https://github.com/libusb/libusb-cmake.git
|
||||
|
||||
22
CMakeDarwinPresets.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"version": 9,
|
||||
"cmakeMinimumRequired": {
|
||||
"major": 3,
|
||||
"minor": 30,
|
||||
"patch": 0
|
||||
},
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "x64-Clang-Base",
|
||||
"hidden": true,
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/Build/${presetName}",
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "clang",
|
||||
"CMAKE_CXX_COMPILER": "clang++",
|
||||
"CMAKE_INSTALL_PREFIX": "${sourceDir}/Build/${presetName}",
|
||||
"CMAKE_OSX_ARCHITECTURES": "x86_64"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
183
CMakeLists.txt
@@ -126,7 +126,7 @@ execute_process(
|
||||
|
||||
# If there's no upstream set or the command failed, check remote.pushDefault
|
||||
if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
|
||||
message("check default push")
|
||||
message(STATUS "check default push")
|
||||
execute_process(
|
||||
COMMAND git config --get remote.pushDefault
|
||||
OUTPUT_VARIABLE GIT_REMOTE_NAME
|
||||
@@ -134,30 +134,30 @@ if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
message("got remote: ${GIT_REMOTE_NAME}")
|
||||
message(STATUS "got remote: ${GIT_REMOTE_NAME}")
|
||||
endif()
|
||||
|
||||
# If running in GitHub Actions and the above fails
|
||||
if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
|
||||
message("check github")
|
||||
message(STATUS "check github")
|
||||
set(GIT_REMOTE_NAME "origin")
|
||||
|
||||
# Retrieve environment variables
|
||||
if (DEFINED ENV{GITHUB_HEAD_REF} AND NOT "$ENV{GITHUB_HEAD_REF}" STREQUAL "")
|
||||
message("github head ref: $ENV{GITHUB_HEAD_REF}")
|
||||
message(STATUS "github head ref: $ENV{GITHUB_HEAD_REF}")
|
||||
set(GITHUB_HEAD_REF "$ENV{GITHUB_HEAD_REF}")
|
||||
else()
|
||||
set(GITHUB_HEAD_REF "")
|
||||
endif()
|
||||
|
||||
if (DEFINED ENV{GITHUB_REF} AND NOT "$ENV{GITHUB_REF}" STREQUAL "")
|
||||
message("github ref: $ENV{GITHUB_REF}")
|
||||
message(STATUS "github ref: $ENV{GITHUB_REF}")
|
||||
string(REGEX REPLACE "^refs/[^/]*/" "" GITHUB_BRANCH "$ENV{GITHUB_REF}")
|
||||
string(REGEX MATCH "refs/pull/([0-9]+)/merge" MATCHED_REF "$ENV{GITHUB_REF}")
|
||||
if (MATCHED_REF)
|
||||
set(PR_NUMBER "${CMAKE_MATCH_1}")
|
||||
set(GITHUB_BRANCH "")
|
||||
message("PR number: ${PR_NUMBER}")
|
||||
message(STATUS "PR number: ${PR_NUMBER}")
|
||||
else()
|
||||
set(PR_NUMBER "")
|
||||
endif()
|
||||
@@ -179,7 +179,7 @@ if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
|
||||
elseif ("${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_REF}" STREQUAL "")
|
||||
set(GIT_BRANCH "${GITHUB_REF}")
|
||||
elseif("${GIT_BRANCH}" STREQUAL "")
|
||||
message("couldn't find branch")
|
||||
message(STATUS "couldn't find branch")
|
||||
set(GIT_BRANCH "detached-head")
|
||||
endif()
|
||||
else()
|
||||
@@ -188,13 +188,13 @@ else()
|
||||
if (INDEX GREATER -1)
|
||||
string(SUBSTRING "${GIT_REMOTE_NAME}" 0 "${INDEX}" GIT_REMOTE_NAME)
|
||||
elseif("${GIT_REMOTE_NAME}" STREQUAL "")
|
||||
message("reset to origin")
|
||||
message(STATUS "reset to origin")
|
||||
set(GIT_REMOTE_NAME "origin")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Get remote link
|
||||
message("getting remote link")
|
||||
message(STATUS "getting remote link")
|
||||
execute_process(
|
||||
COMMAND git config --get remote.${GIT_REMOTE_NAME}.url
|
||||
OUTPUT_VARIABLE GIT_REMOTE_URL
|
||||
@@ -203,7 +203,7 @@ execute_process(
|
||||
|
||||
# Set Version
|
||||
set(EMULATOR_VERSION_MAJOR "0")
|
||||
set(EMULATOR_VERSION_MINOR "10")
|
||||
set(EMULATOR_VERSION_MINOR "12")
|
||||
set(EMULATOR_VERSION_PATCH "0")
|
||||
|
||||
set_source_files_properties(src/shadps4.rc PROPERTIES COMPILE_DEFINITIONS "EMULATOR_VERSION_MAJOR=${EMULATOR_VERSION_MAJOR};EMULATOR_VERSION_MINOR=${EMULATOR_VERSION_MINOR};EMULATOR_VERSION_PATCH=${EMULATOR_VERSION_PATCH}")
|
||||
@@ -212,7 +212,13 @@ set(APP_VERSION "${EMULATOR_VERSION_MAJOR}.${EMULATOR_VERSION_MINOR}.${EMULATOR_
|
||||
set(APP_IS_RELEASE true)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/src/common/scm_rev.cpp" @ONLY)
|
||||
|
||||
message("end git things, remote: ${GIT_REMOTE_NAME}, branch: ${GIT_BRANCH}")
|
||||
message("-- end git things, remote: ${GIT_REMOTE_NAME}, branch: ${GIT_BRANCH}, link: ${GIT_REMOTE_URL}")
|
||||
|
||||
string(TOLOWER "${GIT_REMOTE_URL}" GIT_REMOTE_URL_LOWER)
|
||||
if(NOT (GIT_REMOTE_URL_LOWER MATCHES "shadps4-emu/shadps4" AND (GIT_BRANCH STREQUAL "main" OR "$ENV{GITHUB_REF}" MATCHES "refs/tags/")))
|
||||
message(STATUS "not main, disabling auto update")
|
||||
set(ENABLE_UPDATER OFF)
|
||||
endif()
|
||||
|
||||
if(WIN32 AND ENABLE_QT_GUI AND NOT CMAKE_PREFIX_PATH)
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/DetectQtInstallation.cmake")
|
||||
@@ -231,16 +237,16 @@ find_package(SDL3 3.1.2 CONFIG)
|
||||
find_package(stb MODULE)
|
||||
find_package(toml11 4.2.0 CONFIG)
|
||||
find_package(tsl-robin-map 1.3.0 CONFIG)
|
||||
find_package(VulkanHeaders 1.4.314 CONFIG)
|
||||
find_package(VulkanHeaders 1.4.329 CONFIG)
|
||||
find_package(VulkanMemoryAllocator 3.1.0 CONFIG)
|
||||
find_package(xbyak 7.07 CONFIG)
|
||||
find_package(xxHash 0.8.2 MODULE)
|
||||
find_package(ZLIB 1.3 MODULE)
|
||||
find_package(Zydis 5.0.0 CONFIG)
|
||||
find_package(pugixml 1.14 CONFIG)
|
||||
find_package(libusb 1.0.27 MODULE)
|
||||
if (APPLE)
|
||||
find_package(date 3.0.1 CONFIG)
|
||||
find_package(epoll-shim 3.14 CONFIG)
|
||||
endif()
|
||||
list(POP_BACK CMAKE_MODULE_PATH)
|
||||
|
||||
@@ -255,7 +261,6 @@ endif()
|
||||
|
||||
add_subdirectory(externals)
|
||||
include_directories(src)
|
||||
include_directories(Resources)
|
||||
|
||||
if(ENABLE_QT_GUI)
|
||||
find_package(Qt6 REQUIRED COMPONENTS Widgets Concurrent LinguistTools Network Multimedia)
|
||||
@@ -300,6 +305,8 @@ set(AJM_LIB src/core/libraries/ajm/ajm.cpp
|
||||
|
||||
set(AUDIO_LIB src/core/libraries/audio/audioin.cpp
|
||||
src/core/libraries/audio/audioin.h
|
||||
src/core/libraries/audio/sdl_in.h
|
||||
src/core/libraries/audio/sdl_in.cpp
|
||||
src/core/libraries/voice/voice.cpp
|
||||
src/core/libraries/voice/voice.h
|
||||
src/core/libraries/audio/audioout.cpp
|
||||
@@ -373,6 +380,10 @@ set(NETWORK_LIBS src/core/libraries/network/http.cpp
|
||||
src/core/libraries/network/net_ctl_codes.h
|
||||
src/core/libraries/network/net_util.cpp
|
||||
src/core/libraries/network/net_util.h
|
||||
src/core/libraries/network/net_epoll.cpp
|
||||
src/core/libraries/network/net_epoll.h
|
||||
src/core/libraries/network/net_resolver.cpp
|
||||
src/core/libraries/network/net_resolver.h
|
||||
src/core/libraries/network/net_error.h
|
||||
src/core/libraries/network/net.h
|
||||
src/core/libraries/network/ssl.cpp
|
||||
@@ -383,6 +394,7 @@ set(NETWORK_LIBS src/core/libraries/network/http.cpp
|
||||
src/core/libraries/network/sys_net.h
|
||||
src/core/libraries/network/posix_sockets.cpp
|
||||
src/core/libraries/network/p2p_sockets.cpp
|
||||
src/core/libraries/network/unix_sockets.cpp
|
||||
src/core/libraries/network/sockets.h
|
||||
)
|
||||
|
||||
@@ -520,6 +532,11 @@ set(PAD_LIB src/core/libraries/pad/pad.cpp
|
||||
src/core/libraries/pad/pad_errors.h
|
||||
)
|
||||
|
||||
set(SYSTEM_GESTURE_LIB
|
||||
src/core/libraries/system_gesture/system_gesture.cpp
|
||||
src/core/libraries/system_gesture/system_gesture.h
|
||||
)
|
||||
|
||||
set(PNG_LIB src/core/libraries/libpng/pngdec.cpp
|
||||
src/core/libraries/libpng/pngdec.h
|
||||
src/core/libraries/libpng/pngdec_error.h
|
||||
@@ -564,23 +581,27 @@ set(VDEC_LIB src/core/libraries/videodec/videodec2_impl.cpp
|
||||
src/core/libraries/videodec/videodec_impl.h
|
||||
)
|
||||
|
||||
set(NP_LIBS src/core/libraries/np_common/np_common.cpp
|
||||
src/core/libraries/np_common/np_common.h
|
||||
src/core/libraries/np_manager/np_manager.cpp
|
||||
src/core/libraries/np_manager/np_manager.h
|
||||
src/core/libraries/np_score/np_score.cpp
|
||||
src/core/libraries/np_score/np_score.h
|
||||
src/core/libraries/np_trophy/np_trophy.cpp
|
||||
src/core/libraries/np_trophy/np_trophy.h
|
||||
src/core/libraries/np_trophy/trophy_ui.cpp
|
||||
src/core/libraries/np_trophy/trophy_ui.h
|
||||
src/core/libraries/np_trophy/np_trophy_error.h
|
||||
src/core/libraries/np_web_api/np_web_api.cpp
|
||||
src/core/libraries/np_web_api/np_web_api.h
|
||||
src/core/libraries/np_party/np_party.cpp
|
||||
src/core/libraries/np_party/np_party.h
|
||||
src/core/libraries/np_auth/np_auth.cpp
|
||||
src/core/libraries/np_auth/np_auth.h
|
||||
set(NP_LIBS src/core/libraries/np/np_error.h
|
||||
src/core/libraries/np/np_common.cpp
|
||||
src/core/libraries/np/np_common.h
|
||||
src/core/libraries/np/np_manager.cpp
|
||||
src/core/libraries/np/np_manager.h
|
||||
src/core/libraries/np/np_score.cpp
|
||||
src/core/libraries/np/np_score.h
|
||||
src/core/libraries/np/np_trophy.cpp
|
||||
src/core/libraries/np/np_trophy.h
|
||||
src/core/libraries/np/trophy_ui.cpp
|
||||
src/core/libraries/np/trophy_ui.h
|
||||
src/core/libraries/np/np_web_api.cpp
|
||||
src/core/libraries/np/np_web_api.h
|
||||
src/core/libraries/np/np_party.cpp
|
||||
src/core/libraries/np/np_party.h
|
||||
src/core/libraries/np/np_auth.cpp
|
||||
src/core/libraries/np/np_auth.h
|
||||
src/core/libraries/np/np_profile_dialog.cpp
|
||||
src/core/libraries/np/np_profile_dialog.h
|
||||
src/core/libraries/np/np_sns_facebook_dialog.cpp
|
||||
src/core/libraries/np/np_sns_facebook_dialog.h
|
||||
)
|
||||
|
||||
set(ZLIB_LIB src/core/libraries/zlib/zlib.cpp
|
||||
@@ -589,13 +610,20 @@ set(ZLIB_LIB src/core/libraries/zlib/zlib.cpp
|
||||
)
|
||||
|
||||
set(VR_LIBS src/core/libraries/hmd/hmd.cpp
|
||||
src/core/libraries/hmd/hmd_reprojection.cpp
|
||||
src/core/libraries/hmd/hmd_distortion.cpp
|
||||
src/core/libraries/hmd/hmd.h
|
||||
src/core/libraries/hmd/hmd_setup_dialog.cpp
|
||||
src/core/libraries/hmd/hmd_setup_dialog.h
|
||||
src/core/libraries/vr_tracker/vr_tracker.cpp
|
||||
src/core/libraries/vr_tracker/vr_tracker.h
|
||||
)
|
||||
|
||||
set(MISC_LIBS src/core/libraries/screenshot/screenshot.cpp
|
||||
src/core/libraries/screenshot/screenshot.h
|
||||
src/core/libraries/move/move.cpp
|
||||
src/core/libraries/move/move.h
|
||||
src/core/libraries/move/move_error.h
|
||||
src/core/libraries/ulobjmgr/ulobjmgr.cpp
|
||||
src/core/libraries/ulobjmgr/ulobjmgr.h
|
||||
src/core/libraries/signin_dialog/signindialog.cpp
|
||||
@@ -672,6 +700,7 @@ set(COMMON src/common/logging/backend.cpp
|
||||
src/common/enum.h
|
||||
src/common/io_file.cpp
|
||||
src/common/io_file.h
|
||||
src/common/lru_cache.h
|
||||
src/common/error.cpp
|
||||
src/common/error.h
|
||||
src/common/scope_exit.h
|
||||
@@ -728,22 +757,30 @@ set(CORE src/core/aerolib/stubs.cpp
|
||||
src/core/aerolib/aerolib.h
|
||||
src/core/address_space.cpp
|
||||
src/core/address_space.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/devices/console_device.cpp
|
||||
src/core/devices/console_device.h
|
||||
src/core/devices/deci_tty6_device.cpp
|
||||
src/core/devices/deci_tty6_device.h
|
||||
src/core/devices/random_device.cpp
|
||||
src/core/devices/random_device.h
|
||||
src/core/devices/urandom_device.cpp
|
||||
src/core/devices/urandom_device.h
|
||||
src/core/devices/srandom_device.cpp
|
||||
src/core/devices/srandom_device.h
|
||||
src/core/file_sys/devices/base_device.cpp
|
||||
src/core/file_sys/devices/base_device.h
|
||||
src/core/file_sys/devices/ioccom.h
|
||||
src/core/file_sys/devices/logger.cpp
|
||||
src/core/file_sys/devices/logger.h
|
||||
src/core/file_sys/devices/nop_device.h
|
||||
src/core/file_sys/devices/console_device.cpp
|
||||
src/core/file_sys/devices/console_device.h
|
||||
src/core/file_sys/devices/deci_tty6_device.cpp
|
||||
src/core/file_sys/devices/deci_tty6_device.h
|
||||
src/core/file_sys/devices/random_device.cpp
|
||||
src/core/file_sys/devices/random_device.h
|
||||
src/core/file_sys/devices/rng_device.cpp
|
||||
src/core/file_sys/devices/rng_device.h
|
||||
src/core/file_sys/devices/urandom_device.cpp
|
||||
src/core/file_sys/devices/urandom_device.h
|
||||
src/core/file_sys/devices/srandom_device.cpp
|
||||
src/core/file_sys/devices/srandom_device.h
|
||||
src/core/file_sys/directories/base_directory.cpp
|
||||
src/core/file_sys/directories/base_directory.h
|
||||
src/core/file_sys/directories/normal_directory.cpp
|
||||
src/core/file_sys/directories/normal_directory.h
|
||||
src/core/file_sys/directories/pfs_directory.cpp
|
||||
src/core/file_sys/directories/pfs_directory.h
|
||||
src/core/file_format/pfs.h
|
||||
src/core/file_format/psf.cpp
|
||||
src/core/file_format/psf.h
|
||||
@@ -753,6 +790,8 @@ set(CORE src/core/aerolib/stubs.cpp
|
||||
src/core/file_format/trp.h
|
||||
src/core/file_sys/fs.cpp
|
||||
src/core/file_sys/fs.h
|
||||
src/core/ipc/ipc.cpp
|
||||
src/core/ipc/ipc.h
|
||||
src/core/loader/dwarf.cpp
|
||||
src/core/loader/dwarf.h
|
||||
src/core/loader/elf.cpp
|
||||
@@ -770,6 +809,7 @@ set(CORE src/core/aerolib/stubs.cpp
|
||||
${SYSTEM_LIBS}
|
||||
${HLE_LIBC_INTERNAL_LIB}
|
||||
${PAD_LIB}
|
||||
${SYSTEM_GESTURE_LIB}
|
||||
${VIDEOOUT_LIB}
|
||||
${NP_LIBS}
|
||||
${PNG_LIB}
|
||||
@@ -788,6 +828,8 @@ set(CORE src/core/aerolib/stubs.cpp
|
||||
${DEV_TOOLS}
|
||||
src/core/debug_state.cpp
|
||||
src/core/debug_state.h
|
||||
src/core/debugger.cpp
|
||||
src/core/debugger.h
|
||||
src/core/linker.cpp
|
||||
src/core/linker.h
|
||||
src/core/memory.cpp
|
||||
@@ -809,10 +851,10 @@ if (ARCHITECTURE STREQUAL "x86_64")
|
||||
src/core/cpu_patches.h)
|
||||
endif()
|
||||
|
||||
set(SHADER_RECOMPILER src/shader_recompiler/exception.h
|
||||
src/shader_recompiler/profile.h
|
||||
set(SHADER_RECOMPILER src/shader_recompiler/profile.h
|
||||
src/shader_recompiler/recompiler.cpp
|
||||
src/shader_recompiler/recompiler.h
|
||||
src/shader_recompiler/resource.h
|
||||
src/shader_recompiler/info.h
|
||||
src/shader_recompiler/params.h
|
||||
src/shader_recompiler/runtime_info.h
|
||||
@@ -886,6 +928,7 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h
|
||||
src/shader_recompiler/ir/attribute.h
|
||||
src/shader_recompiler/ir/basic_block.cpp
|
||||
src/shader_recompiler/ir/basic_block.h
|
||||
src/shader_recompiler/ir/breadth_first_search.h
|
||||
src/shader_recompiler/ir/condition.h
|
||||
src/shader_recompiler/ir/ir_emitter.cpp
|
||||
src/shader_recompiler/ir/ir_emitter.h
|
||||
@@ -893,8 +936,10 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h
|
||||
src/shader_recompiler/ir/opcodes.cpp
|
||||
src/shader_recompiler/ir/opcodes.h
|
||||
src/shader_recompiler/ir/opcodes.inc
|
||||
src/shader_recompiler/ir/operand_helper.h
|
||||
src/shader_recompiler/ir/patch.cpp
|
||||
src/shader_recompiler/ir/patch.h
|
||||
src/shader_recompiler/ir/position.h
|
||||
src/shader_recompiler/ir/post_order.cpp
|
||||
src/shader_recompiler/ir/post_order.h
|
||||
src/shader_recompiler/ir/program.cpp
|
||||
@@ -907,15 +952,24 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h
|
||||
src/shader_recompiler/ir/value.h
|
||||
)
|
||||
|
||||
set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp
|
||||
set(VIDEO_CORE src/video_core/amdgpu/cb_db_extent.h
|
||||
src/video_core/amdgpu/liverpool.cpp
|
||||
src/video_core/amdgpu/liverpool.h
|
||||
src/video_core/amdgpu/pixel_format.cpp
|
||||
src/video_core/amdgpu/pixel_format.h
|
||||
src/video_core/amdgpu/pm4_cmds.h
|
||||
src/video_core/amdgpu/pm4_opcodes.h
|
||||
src/video_core/amdgpu/regs_color.h
|
||||
src/video_core/amdgpu/regs_depth.h
|
||||
src/video_core/amdgpu/regs.cpp
|
||||
src/video_core/amdgpu/regs.h
|
||||
src/video_core/amdgpu/regs_primitive.h
|
||||
src/video_core/amdgpu/regs_shader.h
|
||||
src/video_core/amdgpu/regs_texture.h
|
||||
src/video_core/amdgpu/regs_vertex.h
|
||||
src/video_core/amdgpu/resource.h
|
||||
src/video_core/amdgpu/types.h
|
||||
src/video_core/amdgpu/default_context.cpp
|
||||
src/video_core/amdgpu/tiling.cpp
|
||||
src/video_core/amdgpu/tiling.h
|
||||
src/video_core/buffer_cache/buffer.cpp
|
||||
src/video_core/buffer_cache/buffer.h
|
||||
src/video_core/buffer_cache/buffer_cache.cpp
|
||||
@@ -1061,6 +1115,8 @@ set(QT_GUI src/qt_gui/about_dialog.cpp
|
||||
src/qt_gui/kbm_help_dialog.h
|
||||
src/qt_gui/main_window_themes.cpp
|
||||
src/qt_gui/main_window_themes.h
|
||||
src/qt_gui/log_presets_dialog.cpp
|
||||
src/qt_gui/log_presets_dialog.h
|
||||
src/qt_gui/settings_dialog.cpp
|
||||
src/qt_gui/settings_dialog.h
|
||||
src/qt_gui/settings_dialog.ui
|
||||
@@ -1071,6 +1127,9 @@ set(QT_GUI src/qt_gui/about_dialog.cpp
|
||||
src/qt_gui/settings.h
|
||||
src/qt_gui/sdl_event_wrapper.cpp
|
||||
src/qt_gui/sdl_event_wrapper.h
|
||||
src/qt_gui/hotkeys.h
|
||||
src/qt_gui/hotkeys.cpp
|
||||
src/qt_gui/hotkeys.ui
|
||||
${EMULATOR}
|
||||
${RESOURCE_FILES}
|
||||
${TRANSLATIONS}
|
||||
@@ -1112,7 +1171,7 @@ endif()
|
||||
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 ZLIB::ZLIB PNG::PNG)
|
||||
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 libusb::usb)
|
||||
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 libusb::usb lfreist-hwinfo::hwinfo)
|
||||
|
||||
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")
|
||||
@@ -1145,9 +1204,9 @@ if (APPLE)
|
||||
set(MVK_DST ${CMAKE_CURRENT_BINARY_DIR})
|
||||
endif()
|
||||
|
||||
set(MVK_DYLIB_SRC ${CMAKE_CURRENT_BINARY_DIR}/externals/MoltenVK/libMoltenVK.dylib)
|
||||
set(MVK_DYLIB_SRC ${CMAKE_CURRENT_BINARY_DIR}/externals/MoltenVK/MoltenVK/libMoltenVK.dylib)
|
||||
set(MVK_DYLIB_DST ${MVK_DST}/libMoltenVK.dylib)
|
||||
set(MVK_ICD_SRC ${CMAKE_CURRENT_SOURCE_DIR}/externals/MoltenVK/MoltenVK/MoltenVK/icd/MoltenVK_icd.json)
|
||||
set(MVK_ICD_SRC ${CMAKE_CURRENT_SOURCE_DIR}/externals/MoltenVK/MoltenVK/icd/MoltenVK_icd.json)
|
||||
set(MVK_ICD_DST ${MVK_DST}/MoltenVK_icd.json)
|
||||
|
||||
add_custom_command(
|
||||
@@ -1164,11 +1223,11 @@ if (APPLE)
|
||||
|
||||
if (ARCHITECTURE STREQUAL "x86_64")
|
||||
# Reserve system-managed memory space.
|
||||
target_link_options(shadps4 PRIVATE -Wl,-ld_classic,-no_pie,-no_fixup_chains,-no_huge,-pagezero_size,0x4000,-segaddr,TCB_SPACE,0x4000,-segaddr,SYSTEM_MANAGED,0x400000,-segaddr,SYSTEM_RESERVED,0x7FFFFC000,-image_base,0x20000000000)
|
||||
target_link_options(shadps4 PRIVATE -Wl,-ld_classic,-no_pie,-no_fixup_chains,-no_huge,-pagezero_size,0x4000,-segaddr,TCB_SPACE,0x4000,-segaddr,SYSTEM_MANAGED,0x400000,-segaddr,SYSTEM_RESERVED,0x7FFFFC000,-segaddr,USER_AREA,0x7000000000,-image_base,0x700000000000)
|
||||
endif()
|
||||
|
||||
# Replacement for std::chrono::time_zone
|
||||
target_link_libraries(shadps4 PRIVATE date::date-tz)
|
||||
target_link_libraries(shadps4 PRIVATE date::date-tz epoll-shim)
|
||||
endif()
|
||||
|
||||
if (ENABLE_QT_GUI)
|
||||
@@ -1180,7 +1239,7 @@ if (ENABLE_QT_GUI)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(shadps4 PRIVATE mincore)
|
||||
target_link_libraries(shadps4 PRIVATE mincore wepoll)
|
||||
|
||||
if (MSVC)
|
||||
# MSVC likes putting opinions on what people can use, disable:
|
||||
@@ -1214,6 +1273,13 @@ if (WIN32)
|
||||
else()
|
||||
target_link_options(shadps4 PRIVATE -Wl,--stack,2097152)
|
||||
endif()
|
||||
|
||||
# Change base image address
|
||||
if (MSVC)
|
||||
target_link_options(shadps4 PRIVATE /BASE:0x700000000000)
|
||||
else()
|
||||
target_link_options(shadps4 PRIVATE -Wl,--image-base=0x700000000000)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
@@ -1237,6 +1303,7 @@ include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/CMakeRC.cmake")
|
||||
cmrc_add_resource_library(embedded-resources
|
||||
ALIAS res::embedded
|
||||
NAMESPACE res
|
||||
src/images/trophy.wav
|
||||
src/images/bronze.png
|
||||
src/images/gold.png
|
||||
src/images/platinum.png
|
||||
|
||||
28
README.md
@@ -24,34 +24,34 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||
<img src="https://img.shields.io/github/stars/shadps4-emu/shadPS4" width="120">
|
||||
</h1>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://shadps4.net/">
|
||||
<img src="https://github.com/shadps4-emu/shadPS4/blob/main/documents/Screenshots/1.png" width="400">
|
||||
<img src="https://github.com/shadps4-emu/shadPS4/blob/main/documents/Screenshots/2.png" width="400">
|
||||
<img src="https://github.com/shadps4-emu/shadPS4/blob/main/documents/Screenshots/3.png" width="400">
|
||||
<img src="https://github.com/shadps4-emu/shadPS4/blob/main/documents/Screenshots/4.png" width="400">
|
||||
</p>
|
||||
| Bloodborne by From Software | Hatsune Miku Project DIVA Future Tone by SEGA |
|
||||
| :-----------------------------------------------------------: | :--------------------------------------------------------------------------------------------: |
|
||||
|  |  |
|
||||
|
||||
| Yakuza 0 by SEGA | DRIVECLUB™ by Evolution Studios |
|
||||
| :------------------------------------------------------------------------: | :------------------------------------------------------------------: |
|
||||
|  |  |
|
||||
|
||||
# General information
|
||||
|
||||
**shadPS4** is an early **PlayStation 4** emulator for **Windows**, **Linux** and **macOS** written in C++.
|
||||
|
||||
If you encounter problems or have doubts, do not hesitate to look at the [**Quickstart**](https://github.com/shadps4-emu/shadPS4/wiki/I.-Quick-start-%5BUsers%5D).\
|
||||
To verify that a game works, you can look at [**shadPS4 Game Compatibility**](https://github.com/shadps4-emu/shadps4-game-compatibility).\
|
||||
To verify that a game works, you can look at [**shadPS4 Game Compatibility**](https://github.com/shadps4-compatibility/shadps4-game-compatibility).\
|
||||
To discuss shadPS4 development, suggest ideas or to ask for help, join our [**Discord server**](https://discord.gg/bFJxfftGW6).\
|
||||
To get the latest news, go to our [**X (Twitter)**](https://x.com/shadps4) or our [**website**](https://shadps4.net/).\
|
||||
For those who'd like to donate to the project, we now have a [**Kofi page**](https://ko-fi.com/shadps4)!
|
||||
You can donate to the project via our [**Kofi page**](https://ko-fi.com/shadps4).
|
||||
|
||||
# Status
|
||||
|
||||
> [!IMPORTANT]
|
||||
> shadPS4 is early in development, don't expect a flawless experience.
|
||||
|
||||
Currently, the emulator can successfully run games like [**Bloodborne**](https://www.youtube.com/watch?v=wC6s0avpQRE), [**Dark Souls Remastered**](https://www.youtube.com/watch?v=-3PA-Xwszts), [**Red Dead Redemption**](https://www.youtube.com/watch?v=Al7yz_5nLag) and many other games.
|
||||
Currently, the emulator can successfully run games like [**Bloodborne**](https://www.youtube.com/watch?v=5sZgWyVflFM), [**Dark Souls Remastered**](https://www.youtube.com/watch?v=-3PA-Xwszts), [**Red Dead Redemption**](https://www.youtube.com/watch?v=Al7yz_5nLag), and many other games.
|
||||
|
||||
# Why
|
||||
|
||||
This project began as a fun project. Given our limited free time, it may take some time before shadPS4 can run more complex games, but we're committed to making small, regular updates.
|
||||
This project began for fun. Given our limited free time, it may take some time before shadPS4 can run more complex games, but we're committed to making small, regular updates.
|
||||
|
||||
# Building
|
||||
|
||||
@@ -124,7 +124,7 @@ Keyboard and mouse inputs can be customized in the settings menu by clicking the
|
||||
|
||||
# Firmware files
|
||||
|
||||
shadPS4 can load some PlayStation 4 firmware files, these must be dumped from your legally owned PlayStation 4 console.
|
||||
shadPS4 can load some PlayStation 4 firmware files.
|
||||
The following firmware modules are supported and must be placed in shadPS4's `sys_modules` folder.
|
||||
|
||||
<div align="center">
|
||||
@@ -133,12 +133,12 @@ The following firmware modules are supported and must be placed in shadPS4's `sy
|
||||
|-------------------------|-------------------------|-------------------------|-------------------------|
|
||||
| libSceCesCs.sprx | libSceFont.sprx | libSceFontFt.sprx | libSceFreeTypeOt.sprx |
|
||||
| libSceJson.sprx | libSceJson2.sprx | libSceLibcInternal.sprx | libSceNgs2.sprx |
|
||||
| libSceRtc.sprx | libSceUlt.sprx | | |
|
||||
| libSceUlt.sprx | | | |
|
||||
|
||||
</div>
|
||||
|
||||
> [!Caution]
|
||||
> The above modules are required to run the games properly and must be extracted from your PlayStation 4.
|
||||
> The above modules are required to run the games properly and must be dumped from your legally owned PlayStation 4 console.
|
||||
|
||||
|
||||
|
||||
|
||||
13
REUSE.toml
@@ -5,13 +5,12 @@ path = [
|
||||
"REUSE.toml",
|
||||
"crowdin.yml",
|
||||
"CMakeSettings.json",
|
||||
"CMakeDarwinPresets.json",
|
||||
"CMakeLinuxPresets.json",
|
||||
"CMakeWindowsPresets.json",
|
||||
"CMakePresets.json",
|
||||
".github/FUNDING.yml",
|
||||
".github/shadps4.png",
|
||||
".github/workflows/scripts/update_translation.sh",
|
||||
".github/workflows/update_translation.yml",
|
||||
".gitmodules",
|
||||
"dist/MacOSBundleInfo.plist.in",
|
||||
"dist/net.shadps4.shadPS4.desktop",
|
||||
@@ -33,7 +32,6 @@ path = [
|
||||
"src/images/dump_icon.png",
|
||||
"src/images/exit_icon.png",
|
||||
"src/images/favorite_icon.png",
|
||||
"src/images/file_icon.png",
|
||||
"src/images/trophy_icon.png",
|
||||
"src/images/flag_china.png",
|
||||
"src/images/flag_eu.png",
|
||||
@@ -73,9 +71,11 @@ path = [
|
||||
"src/images/shadps4.svg",
|
||||
"src/images/website.svg",
|
||||
"src/images/youtube.svg",
|
||||
"src/images/trophy.wav",
|
||||
"src/images/hotkey.png",
|
||||
"src/images/game_settings.png",
|
||||
"src/shadps4.qrc",
|
||||
"src/shadps4.rc",
|
||||
"src/qt_gui/translations/update_translation.sh",
|
||||
]
|
||||
precedence = "aggregate"
|
||||
SPDX-FileCopyrightText = "shadPS4 Emulator Project"
|
||||
@@ -131,3 +131,8 @@ SPDX-License-Identifier = "MIT"
|
||||
path = "src/video_core/host_shaders/fsr/*"
|
||||
SPDX-FileCopyrightText = "Copyright (c) 2021 Advanced Micro Devices, Inc. All rights reserved."
|
||||
SPDX-License-Identifier = "MIT"
|
||||
|
||||
[[annotations]]
|
||||
path = "dist/qt.conf"
|
||||
SPDX-FileCopyrightText = "shadPS4 Emulator Project"
|
||||
SPDX-License-Identifier = "GPL-2.0-or-later"
|
||||
|
||||
@@ -1,14 +1,28 @@
|
||||
# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
file(GLOB QT_KITS LIST_DIRECTORIES true "C:/Qt/*/msvc*_64")
|
||||
list(SORT QT_KITS COMPARE NATURAL)
|
||||
list(REVERSE QT_KITS)
|
||||
if(QT_KITS)
|
||||
list(GET QT_KITS 0 QT_PREFIX)
|
||||
set(CMAKE_PREFIX_PATH "${QT_PREFIX}" CACHE PATH "Qt prefix auto‑detected" FORCE)
|
||||
message(STATUS "Auto-detected Qt prefix: ${QT_PREFIX}")
|
||||
else()
|
||||
message(STATUS "findQt.cmake: no Qt‑Directory found in C:/Qt – please set CMAKE_PREFIX_PATH manually")
|
||||
endif()
|
||||
set(highest_version "0")
|
||||
set(CANDIDATE_DRIVES A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)
|
||||
|
||||
foreach(drive ${CANDIDATE_DRIVES})
|
||||
file(GLOB kits LIST_DIRECTORIES true CONFIGURE_DEPENDS "${drive}:/Qt/*/msvc*_64")
|
||||
foreach(kit IN LISTS kits)
|
||||
get_filename_component(version_dir "${kit}" DIRECTORY)
|
||||
get_filename_component(kit_version "${version_dir}" NAME)
|
||||
|
||||
message(STATUS "DetectQtInstallation.cmake: Detected Qt: ${kit}")
|
||||
|
||||
if (kit_version VERSION_GREATER highest_version)
|
||||
set(highest_version "${kit_version}")
|
||||
set(QT_PREFIX "${kit}")
|
||||
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
if(QT_PREFIX)
|
||||
set(CMAKE_PREFIX_PATH "${QT_PREFIX}" CACHE PATH "Qt prefix auto‑detected" FORCE)
|
||||
message(STATUS "DetectQtInstallation.cmake: Choose newest Qt: ${QT_PREFIX}")
|
||||
else()
|
||||
message(STATUS "DetectQtInstallation.cmake: No Qt‑Directory found in <drive>:/Qt – please set CMAKE_PREFIX_PATH manually")
|
||||
endif()
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
files:
|
||||
- source: /src/qt_gui/translations/en_US.ts
|
||||
translation: /%original_path%/%locale_with_underscore%.ts
|
||||
6
dist/net.shadps4.shadPS4.metainfo.xml
vendored
@@ -37,6 +37,12 @@
|
||||
<category translate="no">Game</category>
|
||||
</categories>
|
||||
<releases>
|
||||
<release version="0.12.0" date="2025-10-31">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.12.0</url>
|
||||
</release>
|
||||
<release version="0.11.0" date="2025-09-18">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.11.0</url>
|
||||
</release>
|
||||
<release version="0.10.0" date="2025-07-06">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.10.0</url>
|
||||
</release>
|
||||
|
||||
2
dist/qt.conf
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
[Paths]
|
||||
plugins = "./qtplugins"
|
||||
@@ -11,6 +11,13 @@ This document covers information about debugging, troubleshooting and reporting
|
||||
|
||||
This section will guide you through setting up tools for debugging the emulator. This list will likely expand as more tools and platforms receive consistent setups.
|
||||
|
||||
<details>
|
||||
<summary>Linux</summary>
|
||||
|
||||
RenderDoc doesn't work with Wayland, so to use it you have to run the emulator with `SDL_VIDEODRIVER=x11` set.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Windows and Visual Studio</summary>
|
||||
|
||||
@@ -147,7 +154,7 @@ Accurately identifying games will help other developers that own that game recog
|
||||
- If your issue is small or you aren't sure whether you have properly identified something, [join the Discord server](https://discord.gg/MyZRaBngxA) and use the #development channel
|
||||
to concisely explain the issue, as well as any findings you currently have.
|
||||
|
||||
- It is recommended that you check the [game compatibility issue tracker](https://github.com/shadps4-emu/shadps4-game-compatibility/issues) and post very short summaries of progress changes there,
|
||||
- It is recommended that you check the [game compatibility issue tracker](https://github.com/shadps4-compatibility/shadps4-game-compatibility/issues) and post very short summaries of progress changes there,
|
||||
(such as the game now booting into the menu or getting in-game) for organizational and status update purposes.
|
||||
|
||||
- ⚠ **Do not post theoretical, unproven game-specific issues in the emulator issue tracker that you cannot verify and locate in the emulator source code as being a bug.**\
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2024 shadPS4 Emulator Project
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
-->
|
||||
|
||||
# shadPS4 Quickstart
|
||||
|
||||
## Summary
|
||||
|
||||
- [**PC Requirements**](#minimum-pc-requirements)
|
||||
- [**CPU**](#cpu)
|
||||
- [**GPU**](#gpu)
|
||||
- [**RAM**](#ram)
|
||||
- [**OS**](#os)
|
||||
- [**Have the latest WIP version**](#how-to-run-the-latest-work-in-progress-builds-of-shadps4)
|
||||
- [**Configure the emulator**](#configure-the-emulator)
|
||||
|
||||
## Minimum PC requirements
|
||||
|
||||
### CPU
|
||||
|
||||
- A processor with at least 4 cores and 6 threads
|
||||
- Above 2.5 GHz frequency
|
||||
- A CPU supporting the x86-64-v3 baseline.
|
||||
- **Intel**: Haswell generation or newer
|
||||
- **AMD**: Excavator generation or newer
|
||||
- **Apple**: Rosetta 2 on macOS 15.4 or newer
|
||||
|
||||
### GPU
|
||||
|
||||
- A graphics card with at least 1GB of VRAM
|
||||
- Up-to-date graphics drivers
|
||||
- Vulkan 1.3 with the `VK_KHR_swapchain` and `VK_KHR_push_descriptor` extensions
|
||||
|
||||
### RAM
|
||||
|
||||
- 8GB of RAM or more
|
||||
|
||||
### OS
|
||||
|
||||
- Windows 10 or Ubuntu 22.04
|
||||
|
||||
## How to run the latest Work-in-Progress builds of shadPS4
|
||||
|
||||
1. Go to <https://github.com/shadps4-emu/shadPS4/releases> In the release identified as 'pre-release' click on the down arrow(Assets), select your operating system of choice (the "**qt**" versions have a user interface, which is probably the one you want. The others are SDL versions, which can only be run via command line).
|
||||

|
||||
|
||||
2. Once downloaded, extract to its own folder, and run shadPS4's executable from the extracted folder.
|
||||
|
||||
3. Upon first launch, shadPS4 will prompt you to select a folder to store your installed games in. Select "Browse" and then select a folder that contains your dumped games.
|
||||
|
||||
## Configure the emulator
|
||||
|
||||
To configure the emulator, you can go through the interface and go to "settings".
|
||||
|
||||
You can also configure the emulator by editing the `config.toml` file located in the `user` folder created after the application is started (Mostly useful if you are using the SDL version).
|
||||
Some settings may be related to more technical development and debugging.\
|
||||
For more information on this, see [**Debugging**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Debugging/Debugging.md#configuration).
|
||||
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.6 MiB |
|
Before Width: | Height: | Size: 2.3 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1010 KiB |
|
Before Width: | Height: | Size: 1.8 MiB After Width: | Height: | Size: 1.9 MiB |
@@ -1,12 +1,14 @@
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2024 shadPS4 Emulator Project
|
||||
SPDX-FileCopyrightText: 2025 shadPS4 Emulator Project
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
-->
|
||||
|
||||
# Build shadPS4 for Windows
|
||||
|
||||
This tutorial reads as if you have none of the prerequisites already installed. If you do, just ignore the steps regarding installation.
|
||||
If you are building to contribute to the project, please omit `--depth 1` from the git invocations.
|
||||
> [!WARNING]
|
||||
> If you are trying to compile older builds for testing, do not provide the `--depth 1` flag in `git clone`.
|
||||
> This flag omits the commit history from your clone, saving storage space while preventing you from testing older commits.
|
||||
|
||||
Note: **ARM64 is not supported!** As of writing, it will not build nor run. The instructions with respect to ARM64 are for developers only.
|
||||
|
||||
@@ -17,15 +19,14 @@ Note: **ARM64 is not supported!** As of writing, it will not build nor run. The
|
||||
Once you are within the installer:
|
||||
|
||||
1. Select `Desktop development with C++`
|
||||
2. Go to "Individual Components" tab
|
||||
3. Search and select `C++ Clang Compiler for Windows` and `MSBuild support for LLVM`
|
||||
4. Continue the installation
|
||||
2. Go to "Individual Components" tab then search and select both `C++ Clang Compiler for Windows` and `MSBuild support for LLVM`
|
||||
3. Continue the installation
|
||||
|
||||
### (Prerequisite) Download [**Qt**](https://doc.qt.io/qt-6/get-and-install-qt.html)
|
||||
|
||||
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.8.2), select the option `MSVC 2022 64-bit` or similar, as well as `QT Multimedia`.
|
||||
1. Under the current, non beta version of Qt, select the option `MSVC 2022 64-bit` or similar, as well as `QT Multimedia`.
|
||||
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.
|
||||
@@ -35,7 +36,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:
|
||||
|
||||
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.8.2\msvc2022_64`
|
||||
2. Add a new Qt version and navigate it to the correct folder. Should look like so: `C:\Qt\<QtVersion>\msvc2022_64`
|
||||
3. Enable the default checkmark on the new version you just created.
|
||||
|
||||
### (Prerequisite) Download [**Git for Windows**](https://git-scm.com/download/win)
|
||||
@@ -51,20 +52,15 @@ Go through the Git for Windows installation as normal
|
||||
### Compiling with Visual Studio GUI
|
||||
|
||||
1. Open up Visual Studio, select `Open a local folder` and select the folder with the shadPS4 source code. The folder should contain `CMakeLists.txt`
|
||||
2. Change x64-Clang-Debug to x64-Clang-Release if you want a regular, non-debug build.
|
||||
3. If you want to build shadPS4 with the Qt Gui:
|
||||
1. Click x64-Clang-Release and select "Manage Configurations"
|
||||
2. Look for "CMake command arguments" and add to the text field
|
||||
`-DENABLE_QT_GUI=ON -DCMAKE_PREFIX_PATH=C:\Qt\6.8.2\msvc2022_64`
|
||||
(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
|
||||
2. Change Clang x64 Debug to Clang x64 Release if you want a regular, non-debug build.
|
||||
3. If you want to build shadPS4 with the Qt Gui, simply select Clang x64 Release with Qt instead.
|
||||
4. Change the project to build to shadps4.exe
|
||||
5. Build -> Build All
|
||||
|
||||
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:
|
||||
`C:\Qt\6.8.2\msvc2022_64\bin\windeployqt6.exe "C:\path\to\shadps4.exe"`
|
||||
`C:\Qt\<QtVersion>\msvc2022_64\bin\windeployqt6.exe "C:\path\to\shadps4.exe"`
|
||||
(Change Qt path if you've installed it to non-default path)
|
||||
|
||||
## Option 2: MSYS2/MinGW
|
||||
|
||||
17
externals/CMakeLists.txt
vendored
@@ -197,7 +197,7 @@ endif()
|
||||
|
||||
# libusb
|
||||
if (NOT TARGET libusb::usb)
|
||||
add_subdirectory(libusb)
|
||||
add_subdirectory(ext-libusb)
|
||||
add_library(libusb::usb ALIAS usb-1.0)
|
||||
endif()
|
||||
|
||||
@@ -216,6 +216,10 @@ if (NOT TARGET stb::headers)
|
||||
add_library(stb::headers ALIAS stb)
|
||||
endif()
|
||||
|
||||
# hwinfo
|
||||
set(HWINFO_STATIC ON)
|
||||
add_subdirectory(hwinfo)
|
||||
|
||||
# Apple-only dependencies
|
||||
if (APPLE)
|
||||
# date
|
||||
@@ -227,6 +231,17 @@ if (APPLE)
|
||||
|
||||
# MoltenVK
|
||||
if (NOT TARGET MoltenVK)
|
||||
set(MVK_EXCLUDE_SPIRV_TOOLS ON)
|
||||
set(MVK_USE_METAL_PRIVATE_API ON)
|
||||
add_subdirectory(MoltenVK)
|
||||
endif()
|
||||
|
||||
if (NOT TARGET epoll-shim)
|
||||
add_subdirectory(epoll-shim)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#windows only
|
||||
if (WIN32)
|
||||
add_subdirectory(ext-wepoll)
|
||||
endif()
|
||||
|
||||
1
externals/MoltenVK
vendored
Submodule
93
externals/MoltenVK/CMakeLists.txt
vendored
@@ -1,93 +0,0 @@
|
||||
# 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
1
externals/MoltenVK/SPIRV-Cross
vendored
1
externals/MoltenVK/cereal
vendored
1
externals/epoll-shim
vendored
Submodule
1
externals/ext-libusb
vendored
Submodule
1
externals/ext-wepoll
vendored
Submodule
1
externals/hwinfo
vendored
Submodule
1
externals/libusb
vendored
2
externals/sdl3
vendored
2
externals/sirit
vendored
2
externals/vulkan-headers
vendored
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
@@ -9,6 +9,13 @@
|
||||
|
||||
namespace Config {
|
||||
|
||||
enum class ConfigMode {
|
||||
Default,
|
||||
Global,
|
||||
Clean,
|
||||
};
|
||||
void setConfigMode(ConfigMode mode);
|
||||
|
||||
struct GameInstallDir {
|
||||
std::filesystem::path path;
|
||||
bool enabled;
|
||||
@@ -16,87 +23,129 @@ struct GameInstallDir {
|
||||
|
||||
enum HideCursorState : int { Never, Idle, Always };
|
||||
|
||||
void load(const std::filesystem::path& path);
|
||||
void save(const std::filesystem::path& path);
|
||||
void load(const std::filesystem::path& path, bool is_game_specific = false);
|
||||
void save(const std::filesystem::path& path, bool is_game_specific = false);
|
||||
void resetGameSpecificValue(std::string entry);
|
||||
|
||||
int getVolumeSlider();
|
||||
void setVolumeSlider(int volumeValue, bool is_game_specific = false);
|
||||
std::string getTrophyKey();
|
||||
void setTrophyKey(std::string key);
|
||||
bool getIsFullscreen();
|
||||
void setIsFullscreen(bool enable);
|
||||
void setIsFullscreen(bool enable, bool is_game_specific = false);
|
||||
std::string getFullscreenMode();
|
||||
void setFullscreenMode(std::string mode);
|
||||
u32 getScreenWidth();
|
||||
u32 getScreenHeight();
|
||||
void setScreenWidth(u32 width);
|
||||
void setScreenHeight(u32 height);
|
||||
void setFullscreenMode(std::string mode, bool is_game_specific = false);
|
||||
std::string getPresentMode();
|
||||
void setPresentMode(std::string mode, bool is_game_specific = false);
|
||||
u32 getWindowWidth();
|
||||
u32 getWindowHeight();
|
||||
void setWindowWidth(u32 width, bool is_game_specific = false);
|
||||
void setWindowHeight(u32 height, bool is_game_specific = false);
|
||||
u32 getInternalScreenWidth();
|
||||
u32 getInternalScreenHeight();
|
||||
void setInternalScreenWidth(u32 width);
|
||||
void setInternalScreenHeight(u32 height);
|
||||
bool debugDump();
|
||||
void setDebugDump(bool enable);
|
||||
void setDebugDump(bool enable, bool is_game_specific = false);
|
||||
s32 getGpuId();
|
||||
void setGpuId(s32 selectedGpuId);
|
||||
void setGpuId(s32 selectedGpuId, bool is_game_specific = false);
|
||||
bool allowHDR();
|
||||
void setAllowHDR(bool enable);
|
||||
void setAllowHDR(bool enable, bool is_game_specific = false);
|
||||
bool collectShadersForDebug();
|
||||
void setCollectShaderForDebug(bool enable);
|
||||
void setCollectShaderForDebug(bool enable, bool is_game_specific = false);
|
||||
bool showSplash();
|
||||
void setShowSplash(bool enable);
|
||||
void setShowSplash(bool enable, bool is_game_specific = false);
|
||||
std::string sideTrophy();
|
||||
void setSideTrophy(std::string side);
|
||||
void setSideTrophy(std::string side, bool is_game_specific = false);
|
||||
bool nullGpu();
|
||||
void setNullGpu(bool enable);
|
||||
void setNullGpu(bool enable, bool is_game_specific = false);
|
||||
bool copyGPUCmdBuffers();
|
||||
void setCopyGPUCmdBuffers(bool enable);
|
||||
void setCopyGPUCmdBuffers(bool enable, bool is_game_specific = false);
|
||||
bool readbacks();
|
||||
void setReadbacks(bool enable);
|
||||
void setReadbacks(bool enable, bool is_game_specific = false);
|
||||
bool readbackLinearImages();
|
||||
void setReadbackLinearImages(bool enable, bool is_game_specific = false);
|
||||
bool directMemoryAccess();
|
||||
void setDirectMemoryAccess(bool enable);
|
||||
void setDirectMemoryAccess(bool enable, bool is_game_specific = false);
|
||||
bool dumpShaders();
|
||||
void setDumpShaders(bool enable);
|
||||
u32 vblankDiv();
|
||||
void setVblankDiv(u32 value);
|
||||
void setDumpShaders(bool enable, bool is_game_specific = false);
|
||||
u32 vblankFreq();
|
||||
void setVblankFreq(u32 value, bool is_game_specific = false);
|
||||
bool getisTrophyPopupDisabled();
|
||||
void setisTrophyPopupDisabled(bool disable);
|
||||
void setisTrophyPopupDisabled(bool disable, bool is_game_specific = false);
|
||||
s16 getCursorState();
|
||||
void setCursorState(s16 cursorState);
|
||||
void setCursorState(s16 cursorState, bool is_game_specific = false);
|
||||
bool vkValidationEnabled();
|
||||
void setVkValidation(bool enable);
|
||||
void setVkValidation(bool enable, bool is_game_specific = false);
|
||||
bool vkValidationSyncEnabled();
|
||||
void setVkSyncValidation(bool enable);
|
||||
void setVkSyncValidation(bool enable, bool is_game_specific = false);
|
||||
bool getVkCrashDiagnosticEnabled();
|
||||
void setVkCrashDiagnosticEnabled(bool enable);
|
||||
void setVkCrashDiagnosticEnabled(bool enable, bool is_game_specific = false);
|
||||
bool getVkHostMarkersEnabled();
|
||||
void setVkHostMarkersEnabled(bool enable);
|
||||
void setVkHostMarkersEnabled(bool enable, bool is_game_specific = false);
|
||||
bool getVkGuestMarkersEnabled();
|
||||
void setVkGuestMarkersEnabled(bool enable);
|
||||
void setVkGuestMarkersEnabled(bool enable, bool is_game_specific = false);
|
||||
bool getEnableDiscordRPC();
|
||||
void setEnableDiscordRPC(bool enable);
|
||||
bool isRdocEnabled();
|
||||
void setRdocEnabled(bool enable);
|
||||
void setRdocEnabled(bool enable, bool is_game_specific = false);
|
||||
std::string getLogType();
|
||||
void setLogType(const std::string& type);
|
||||
void setLogType(const std::string& type, bool is_game_specific = false);
|
||||
std::string getLogFilter();
|
||||
void setLogFilter(const std::string& type);
|
||||
void setLogFilter(const std::string& type, bool is_game_specific = false);
|
||||
double getTrophyNotificationDuration();
|
||||
void setTrophyNotificationDuration(double newTrophyNotificationDuration);
|
||||
void setTrophyNotificationDuration(double newTrophyNotificationDuration,
|
||||
bool is_game_specific = false);
|
||||
int getCursorHideTimeout();
|
||||
void setCursorHideTimeout(int newcursorHideTimeout);
|
||||
void setSeparateLogFilesEnabled(bool enabled);
|
||||
std::string getMainOutputDevice();
|
||||
void setMainOutputDevice(std::string device);
|
||||
std::string getPadSpkOutputDevice();
|
||||
void setPadSpkOutputDevice(std::string device);
|
||||
std::string getMicDevice();
|
||||
void setCursorHideTimeout(int newcursorHideTimeout, bool is_game_specific = false);
|
||||
void setMicDevice(std::string device, bool is_game_specific = false);
|
||||
void setSeparateLogFilesEnabled(bool enabled, bool is_game_specific = false);
|
||||
bool getSeparateLogFilesEnabled();
|
||||
u32 GetLanguage();
|
||||
void setLanguage(u32 language);
|
||||
void setLanguage(u32 language, bool is_game_specific = false);
|
||||
void setUseSpecialPad(bool use);
|
||||
bool getUseSpecialPad();
|
||||
void setSpecialPadClass(int type);
|
||||
int getSpecialPadClass();
|
||||
bool getPSNSignedIn();
|
||||
void setPSNSignedIn(bool sign); // no ui setting
|
||||
bool patchShaders(); // no set
|
||||
bool fpsColor(); // no set
|
||||
void setPSNSignedIn(bool sign, bool is_game_specific = false);
|
||||
bool patchShaders(); // no set
|
||||
bool fpsColor(); // no set
|
||||
bool isNeoModeConsole();
|
||||
void setNeoMode(bool enable); // no ui setting
|
||||
bool isDevKitConsole(); // no set
|
||||
bool vkValidationGpuEnabled(); // no set
|
||||
void setNeoMode(bool enable, bool is_game_specific = false);
|
||||
bool isDevKitConsole();
|
||||
void setDevKitConsole(bool enable, bool is_game_specific = false);
|
||||
|
||||
bool vkValidationCoreEnabled(); // no set
|
||||
bool vkValidationGpuEnabled(); // no set
|
||||
int getExtraDmemInMbytes();
|
||||
void setExtraDmemInMbytes(int value);
|
||||
bool getIsMotionControlsEnabled();
|
||||
void setIsMotionControlsEnabled(bool use);
|
||||
void setIsMotionControlsEnabled(bool use, bool is_game_specific = false);
|
||||
std::string getDefaultControllerID();
|
||||
void setDefaultControllerID(std::string id);
|
||||
bool getBackgroundControllerInput();
|
||||
void setBackgroundControllerInput(bool enable, bool is_game_specific = false);
|
||||
bool getLoggingEnabled();
|
||||
void setLoggingEnabled(bool enable, bool is_game_specific = false);
|
||||
bool getFsrEnabled();
|
||||
void setFsrEnabled(bool enable, bool is_game_specific = false);
|
||||
bool getRcasEnabled();
|
||||
void setRcasEnabled(bool enable, bool is_game_specific = false);
|
||||
int getRcasAttenuation();
|
||||
void setRcasAttenuation(int value, bool is_game_specific = false);
|
||||
bool getIsConnectedToNetwork();
|
||||
void setConnectedToNetwork(bool enable, bool is_game_specific = false);
|
||||
void setUserName(const std::string& name, bool is_game_specific = false);
|
||||
void setChooseHomeTab(const std::string& type, bool is_game_specific = false);
|
||||
std::filesystem::path getSysModulesPath();
|
||||
void setSysModulesPath(const std::filesystem::path& path);
|
||||
|
||||
// TODO
|
||||
bool GetLoadGameSizeEnabled();
|
||||
@@ -112,8 +161,6 @@ bool GetOverrideControllerColor();
|
||||
void SetOverrideControllerColor(bool enable);
|
||||
int* GetControllerCustomColor();
|
||||
void SetControllerCustomColor(int r, int b, int g);
|
||||
void setUserName(const std::string& type);
|
||||
void setChooseHomeTab(const std::string& type);
|
||||
void setGameInstallDirs(const std::vector<std::filesystem::path>& dirs_config);
|
||||
void setAllGameInstallDirs(const std::vector<GameInstallDir>& dirs_config);
|
||||
void setSaveDataPath(const std::filesystem::path& path);
|
||||
@@ -129,9 +176,9 @@ const std::vector<std::filesystem::path> getGameInstallDirs();
|
||||
const std::vector<bool> getGameInstallDirsEnabled();
|
||||
std::filesystem::path getAddonInstallDir();
|
||||
|
||||
void setDefaultValues();
|
||||
void setDefaultValues(bool is_game_specific = false);
|
||||
|
||||
// todo: name and function location pending
|
||||
std::filesystem::path GetFoolproofKbmConfigFile(const std::string& game_id = "");
|
||||
constexpr std::string_view GetDefaultGlobalConfig();
|
||||
std::filesystem::path GetFoolproofInputConfigFile(const std::string& game_id = "");
|
||||
|
||||
}; // namespace Config
|
||||
|
||||
@@ -85,6 +85,7 @@ public:
|
||||
static constexpr u32 FW_45 = 0x4500000;
|
||||
static constexpr u32 FW_50 = 0x5000000;
|
||||
static constexpr u32 FW_55 = 0x5500000;
|
||||
static constexpr u32 FW_60 = 0x6000000;
|
||||
static constexpr u32 FW_80 = 0x8000000;
|
||||
|
||||
static ElfInfo& Instance() {
|
||||
|
||||
@@ -213,13 +213,13 @@ public:
|
||||
IOFile out(path, FileAccessMode::Write);
|
||||
return out.Write(data);
|
||||
}
|
||||
std::FILE* file = nullptr;
|
||||
|
||||
private:
|
||||
std::filesystem::path file_path;
|
||||
FileAccessMode file_access_mode{};
|
||||
FileType file_type{};
|
||||
|
||||
std::FILE* file = nullptr;
|
||||
uintptr_t file_mapping = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -61,8 +61,9 @@ private:
|
||||
*/
|
||||
class FileBackend {
|
||||
public:
|
||||
explicit FileBackend(const std::filesystem::path& filename)
|
||||
: file{filename, FS::FileAccessMode::Write, FS::FileType::TextFile} {}
|
||||
explicit FileBackend(const std::filesystem::path& filename, bool should_append = false)
|
||||
: file{filename, should_append ? FS::FileAccessMode::Append : FS::FileAccessMode::Write,
|
||||
FS::FileType::TextFile} {}
|
||||
|
||||
~FileBackend() = default;
|
||||
|
||||
@@ -145,6 +146,11 @@ public:
|
||||
initialization_in_progress_suppress_logging = false;
|
||||
}
|
||||
|
||||
static void ResetInstance() {
|
||||
initialization_in_progress_suppress_logging = true;
|
||||
instance.reset();
|
||||
}
|
||||
|
||||
static bool IsActive() {
|
||||
return instance != nullptr;
|
||||
}
|
||||
@@ -157,6 +163,10 @@ public:
|
||||
instance->StopBackendThread();
|
||||
}
|
||||
|
||||
static void SetAppend() {
|
||||
should_append = true;
|
||||
}
|
||||
|
||||
Impl(const Impl&) = delete;
|
||||
Impl& operator=(const Impl&) = delete;
|
||||
|
||||
@@ -191,7 +201,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
if (!filter.CheckMessage(log_class, log_level)) {
|
||||
if (!filter.CheckMessage(log_class, log_level) || !Config::getLoggingEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -218,7 +228,7 @@ public:
|
||||
|
||||
private:
|
||||
Impl(const std::filesystem::path& file_backend_filename, const Filter& filter_)
|
||||
: filter{filter_}, file_backend{file_backend_filename} {}
|
||||
: filter{filter_}, file_backend{file_backend_filename, should_append} {}
|
||||
|
||||
~Impl() = default;
|
||||
|
||||
@@ -264,6 +274,7 @@ private:
|
||||
}
|
||||
|
||||
static inline std::unique_ptr<Impl, decltype(&Deleter)> instance{nullptr, Deleter};
|
||||
static inline bool should_append{false};
|
||||
|
||||
Filter filter;
|
||||
DebuggerBackend debugger_backend{};
|
||||
@@ -292,6 +303,11 @@ void Stop() {
|
||||
Impl::Stop();
|
||||
}
|
||||
|
||||
void Denitializer() {
|
||||
Impl::Stop();
|
||||
Impl::ResetInstance();
|
||||
}
|
||||
|
||||
void SetGlobalFilter(const Filter& filter) {
|
||||
Impl::Instance().SetGlobalFilter(filter);
|
||||
}
|
||||
@@ -300,6 +316,10 @@ void SetColorConsoleBackendEnabled(bool enabled) {
|
||||
Impl::Instance().SetColorConsoleBackendEnabled(enabled);
|
||||
}
|
||||
|
||||
void SetAppend() {
|
||||
Impl::SetAppend();
|
||||
}
|
||||
|
||||
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
|
||||
unsigned int line_num, const char* function, const char* format,
|
||||
const fmt::format_args& args) {
|
||||
|
||||
@@ -21,9 +21,14 @@ void Start();
|
||||
/// Explictily stops the logger thread and flushes the buffers
|
||||
void Stop();
|
||||
|
||||
/// Closes log files and stops the logger
|
||||
void Denitializer();
|
||||
|
||||
/// The global filter will prevent any messages from even being processed if they are filtered.
|
||||
void SetGlobalFilter(const Filter& filter);
|
||||
|
||||
void SetColorConsoleBackendEnabled(bool enabled);
|
||||
|
||||
void SetAppend();
|
||||
|
||||
} // namespace Common::Log
|
||||
|
||||
@@ -83,6 +83,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
||||
SUB(Lib, LibcInternal) \
|
||||
SUB(Lib, Kernel) \
|
||||
SUB(Lib, Pad) \
|
||||
SUB(Lib, SystemGesture) \
|
||||
SUB(Lib, GnmDriver) \
|
||||
SUB(Lib, SystemService) \
|
||||
SUB(Lib, UserService) \
|
||||
@@ -107,6 +108,8 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
||||
SUB(Lib, NpScore) \
|
||||
SUB(Lib, NpTrophy) \
|
||||
SUB(Lib, NpWebApi) \
|
||||
SUB(Lib, NpProfileDialog) \
|
||||
SUB(Lib, NpSnsFacebookDialog) \
|
||||
SUB(Lib, Screenshot) \
|
||||
SUB(Lib, LibCInternal) \
|
||||
SUB(Lib, AppContent) \
|
||||
@@ -137,11 +140,13 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
||||
SUB(Lib, NpParty) \
|
||||
SUB(Lib, Zlib) \
|
||||
SUB(Lib, Hmd) \
|
||||
SUB(Lib, HmdSetupDialog) \
|
||||
SUB(Lib, SigninDialog) \
|
||||
SUB(Lib, Camera) \
|
||||
SUB(Lib, CompanionHttpd) \
|
||||
SUB(Lib, CompanionUtil) \
|
||||
SUB(Lib, Voice) \
|
||||
SUB(Lib, VrTracker) \
|
||||
CLS(Frontend) \
|
||||
CLS(Render) \
|
||||
SUB(Render, Vulkan) \
|
||||
|
||||
@@ -29,95 +29,100 @@ enum class Level : u8 {
|
||||
* filter.cpp.
|
||||
*/
|
||||
enum class Class : u8 {
|
||||
Log, ///< Messages about the log system itself
|
||||
Common, ///< Library routines
|
||||
Common_Filesystem, ///< Filesystem interface library
|
||||
Common_Memory, ///< Memory mapping and management functions
|
||||
Core, ///< LLE emulation core
|
||||
Core_Linker, ///< The module linker
|
||||
Core_Devices, ///< Devices emulation
|
||||
Config, ///< Emulator configuration (including commandline)
|
||||
Debug, ///< Debugging tools
|
||||
Kernel, ///< The HLE implementation of the PS4 kernel.
|
||||
Kernel_Pthread, ///< The pthread implementation of the kernel.
|
||||
Kernel_Fs, ///< The filesystem implementation of the kernel.
|
||||
Kernel_Vmm, ///< The virtual memory implementation of the kernel.
|
||||
Kernel_Event, ///< The event management implementation of the kernel.
|
||||
Kernel_Sce, ///< The sony specific interfaces provided by the kernel.
|
||||
Lib, ///< HLE implementation of system library. Each major library
|
||||
///< should have its own subclass.
|
||||
Lib_LibC, ///< The LibC implementation.
|
||||
Lib_LibcInternal, ///< The LibcInternal implementation.
|
||||
Lib_Kernel, ///< The LibKernel implementation.
|
||||
Lib_Pad, ///< The LibScePad implementation.
|
||||
Lib_GnmDriver, ///< The LibSceGnmDriver implementation.
|
||||
Lib_SystemService, ///< The LibSceSystemService implementation.
|
||||
Lib_UserService, ///< The LibSceUserService implementation.
|
||||
Lib_VideoOut, ///< The LibSceVideoOut implementation.
|
||||
Lib_CommonDlg, ///< The LibSceCommonDialog implementation.
|
||||
Lib_MsgDlg, ///< The LibSceMsgDialog implementation.
|
||||
Lib_AudioOut, ///< The LibSceAudioOut implementation.
|
||||
Lib_AudioIn, ///< The LibSceAudioIn implementation.
|
||||
Lib_Move, ///< The LibSceMove implementation.
|
||||
Lib_Net, ///< The LibSceNet implementation.
|
||||
Lib_NetCtl, ///< The LibSceNetCtl implementation.
|
||||
Lib_SaveData, ///< The LibSceSaveData implementation.
|
||||
Lib_SaveDataDialog, ///< The LibSceSaveDataDialog implementation.
|
||||
Lib_Ssl, ///< The LibSceSsl implementation.
|
||||
Lib_Ssl2, ///< The LibSceSsl2 implementation.
|
||||
Lib_Http, ///< The LibSceHttp implementation.
|
||||
Lib_Http2, ///< The LibSceHttp2 implementation.
|
||||
Lib_SysModule, ///< The LibSceSysModule implementation
|
||||
Lib_NpCommon, ///< The LibSceNpCommon implementation
|
||||
Lib_NpAuth, ///< The LibSceNpAuth implementation
|
||||
Lib_NpManager, ///< The LibSceNpManager implementation
|
||||
Lib_NpScore, ///< The LibSceNpScore implementation
|
||||
Lib_NpTrophy, ///< The LibSceNpTrophy implementation
|
||||
Lib_NpWebApi, ///< The LibSceWebApi implementation
|
||||
Lib_Screenshot, ///< The LibSceScreenshot implementation
|
||||
Lib_LibCInternal, ///< The LibCInternal implementation.
|
||||
Lib_AppContent, ///< The LibSceAppContent implementation.
|
||||
Lib_Rtc, ///< The LibSceRtc implementation.
|
||||
Lib_DiscMap, ///< The LibSceDiscMap implementation.
|
||||
Lib_Png, ///< The LibScePng implementation.
|
||||
Lib_Jpeg, ///< The LibSceJpeg implementation.
|
||||
Lib_PlayGo, ///< The LibScePlayGo implementation.
|
||||
Lib_PlayGoDialog, ///< The LibScePlayGoDialog implementation.
|
||||
Lib_Random, ///< The libSceRandom implementation.
|
||||
Lib_Usbd, ///< The LibSceUsbd implementation.
|
||||
Lib_Ajm, ///< The LibSceAjm implementation.
|
||||
Lib_ErrorDialog, ///< The LibSceErrorDialog implementation.
|
||||
Lib_ImeDialog, ///< The LibSceImeDialog implementation.
|
||||
Lib_AvPlayer, ///< The LibSceAvPlayer implementation.
|
||||
Lib_Ngs2, ///< The LibSceNgs2 implementation.
|
||||
Lib_Audio3d, ///< The LibSceAudio3d implementation.
|
||||
Lib_Ime, ///< The LibSceIme implementation
|
||||
Lib_GameLiveStreaming, ///< The LibSceGameLiveStreaming implementation
|
||||
Lib_Remoteplay, ///< The LibSceRemotePlay implementation
|
||||
Lib_SharePlay, ///< The LibSceSharePlay implemenation
|
||||
Lib_Fiber, ///< The LibSceFiber implementation.
|
||||
Lib_Vdec2, ///< The LibSceVideodec2 implementation.
|
||||
Lib_Videodec, ///< The LibSceVideodec implementation.
|
||||
Lib_Voice, ///< The LibSceVoice implementation.
|
||||
Lib_RazorCpu, ///< The LibRazorCpu implementation.
|
||||
Lib_Mouse, ///< The LibSceMouse implementation
|
||||
Lib_WebBrowserDialog, ///< The LibSceWebBrowserDialog implementation
|
||||
Lib_NpParty, ///< The LibSceNpParty implementation
|
||||
Lib_Zlib, ///< The LibSceZlib implementation.
|
||||
Lib_Hmd, ///< The LibSceHmd implementation.
|
||||
Lib_SigninDialog, ///< The LibSigninDialog implementation.
|
||||
Lib_Camera, ///< The LibCamera implementation.
|
||||
Lib_CompanionHttpd, ///< The LibCompanionHttpd implementation.
|
||||
Lib_CompanionUtil, ///< The LibCompanionUtil implementation.
|
||||
Frontend, ///< Emulator UI
|
||||
Render, ///< Video Core
|
||||
Render_Vulkan, ///< Vulkan backend
|
||||
Render_Recompiler, ///< Shader recompiler
|
||||
ImGui, ///< ImGui
|
||||
Loader, ///< ROM loader
|
||||
Input, ///< Input emulation
|
||||
Tty, ///< Debug output from emu
|
||||
Count ///< Total number of logging classes
|
||||
Log, ///< Messages about the log system itself
|
||||
Common, ///< Library routines
|
||||
Common_Filesystem, ///< Filesystem interface library
|
||||
Common_Memory, ///< Memory mapping and management functions
|
||||
Core, ///< LLE emulation core
|
||||
Core_Linker, ///< The module linker
|
||||
Core_Devices, ///< Devices emulation
|
||||
Config, ///< Emulator configuration (including commandline)
|
||||
Debug, ///< Debugging tools
|
||||
Kernel, ///< The HLE implementation of the PS4 kernel.
|
||||
Kernel_Pthread, ///< The pthread implementation of the kernel.
|
||||
Kernel_Fs, ///< The filesystem implementation of the kernel.
|
||||
Kernel_Vmm, ///< The virtual memory implementation of the kernel.
|
||||
Kernel_Event, ///< The event management implementation of the kernel.
|
||||
Kernel_Sce, ///< The sony specific interfaces provided by the kernel.
|
||||
Lib, ///< HLE implementation of system library. Each major library
|
||||
///< should have its own subclass.
|
||||
Lib_LibC, ///< The LibC implementation.
|
||||
Lib_LibcInternal, ///< The LibcInternal implementation.
|
||||
Lib_Kernel, ///< The LibKernel implementation.
|
||||
Lib_Pad, ///< The LibScePad implementation.
|
||||
Lib_SystemGesture, ///< The LibSceSystemGesture implementation.
|
||||
Lib_GnmDriver, ///< The LibSceGnmDriver implementation.
|
||||
Lib_SystemService, ///< The LibSceSystemService implementation.
|
||||
Lib_UserService, ///< The LibSceUserService implementation.
|
||||
Lib_VideoOut, ///< The LibSceVideoOut implementation.
|
||||
Lib_CommonDlg, ///< The LibSceCommonDialog implementation.
|
||||
Lib_MsgDlg, ///< The LibSceMsgDialog implementation.
|
||||
Lib_AudioOut, ///< The LibSceAudioOut implementation.
|
||||
Lib_AudioIn, ///< The LibSceAudioIn implementation.
|
||||
Lib_Move, ///< The LibSceMove implementation.
|
||||
Lib_Net, ///< The LibSceNet implementation.
|
||||
Lib_NetCtl, ///< The LibSceNetCtl implementation.
|
||||
Lib_SaveData, ///< The LibSceSaveData implementation.
|
||||
Lib_SaveDataDialog, ///< The LibSceSaveDataDialog implementation.
|
||||
Lib_Ssl, ///< The LibSceSsl implementation.
|
||||
Lib_Ssl2, ///< The LibSceSsl2 implementation.
|
||||
Lib_Http, ///< The LibSceHttp implementation.
|
||||
Lib_Http2, ///< The LibSceHttp2 implementation.
|
||||
Lib_SysModule, ///< The LibSceSysModule implementation
|
||||
Lib_NpCommon, ///< The LibSceNpCommon implementation
|
||||
Lib_NpAuth, ///< The LibSceNpAuth implementation
|
||||
Lib_NpManager, ///< The LibSceNpManager implementation
|
||||
Lib_NpScore, ///< The LibSceNpScore implementation
|
||||
Lib_NpTrophy, ///< The LibSceNpTrophy implementation
|
||||
Lib_NpWebApi, ///< The LibSceWebApi implementation
|
||||
Lib_NpProfileDialog, ///< The LibSceNpProfileDialog implementation
|
||||
Lib_NpSnsFacebookDialog, ///< The LibSceNpSnsFacebookDialog implementation
|
||||
Lib_Screenshot, ///< The LibSceScreenshot implementation
|
||||
Lib_LibCInternal, ///< The LibCInternal implementation.
|
||||
Lib_AppContent, ///< The LibSceAppContent implementation.
|
||||
Lib_Rtc, ///< The LibSceRtc implementation.
|
||||
Lib_DiscMap, ///< The LibSceDiscMap implementation.
|
||||
Lib_Png, ///< The LibScePng implementation.
|
||||
Lib_Jpeg, ///< The LibSceJpeg implementation.
|
||||
Lib_PlayGo, ///< The LibScePlayGo implementation.
|
||||
Lib_PlayGoDialog, ///< The LibScePlayGoDialog implementation.
|
||||
Lib_Random, ///< The LibSceRandom implementation.
|
||||
Lib_Usbd, ///< The LibSceUsbd implementation.
|
||||
Lib_Ajm, ///< The LibSceAjm implementation.
|
||||
Lib_ErrorDialog, ///< The LibSceErrorDialog implementation.
|
||||
Lib_ImeDialog, ///< The LibSceImeDialog implementation.
|
||||
Lib_AvPlayer, ///< The LibSceAvPlayer implementation.
|
||||
Lib_Ngs2, ///< The LibSceNgs2 implementation.
|
||||
Lib_Audio3d, ///< The LibSceAudio3d implementation.
|
||||
Lib_Ime, ///< The LibSceIme implementation
|
||||
Lib_GameLiveStreaming, ///< The LibSceGameLiveStreaming implementation
|
||||
Lib_Remoteplay, ///< The LibSceRemotePlay implementation
|
||||
Lib_SharePlay, ///< The LibSceSharePlay implemenation
|
||||
Lib_Fiber, ///< The LibSceFiber implementation.
|
||||
Lib_Vdec2, ///< The LibSceVideodec2 implementation.
|
||||
Lib_Videodec, ///< The LibSceVideodec implementation.
|
||||
Lib_Voice, ///< The LibSceVoice implementation.
|
||||
Lib_RazorCpu, ///< The LibRazorCpu implementation.
|
||||
Lib_Mouse, ///< The LibSceMouse implementation
|
||||
Lib_WebBrowserDialog, ///< The LibSceWebBrowserDialog implementation
|
||||
Lib_NpParty, ///< The LibSceNpParty implementation
|
||||
Lib_Zlib, ///< The LibSceZlib implementation.
|
||||
Lib_Hmd, ///< The LibSceHmd implementation.
|
||||
Lib_HmdSetupDialog, ///< The LibSceHmdSetupDialog implementation.
|
||||
Lib_SigninDialog, ///< The LibSigninDialog implementation.
|
||||
Lib_Camera, ///< The LibCamera implementation.
|
||||
Lib_CompanionHttpd, ///< The LibCompanionHttpd implementation.
|
||||
Lib_CompanionUtil, ///< The LibCompanionUtil implementation.
|
||||
Lib_VrTracker, ///< The LibSceVrTracker implementation.
|
||||
Frontend, ///< Emulator UI
|
||||
Render, ///< Video Core
|
||||
Render_Vulkan, ///< Vulkan backend
|
||||
Render_Recompiler, ///< Shader recompiler
|
||||
ImGui, ///< ImGui
|
||||
Loader, ///< ROM loader
|
||||
Input, ///< Input emulation
|
||||
Tty, ///< Debug output from emu
|
||||
Count ///< Total number of logging classes
|
||||
};
|
||||
|
||||
} // namespace Common::Log
|
||||
|
||||
135
src/common/lru_cache.h
Normal file
@@ -0,0 +1,135 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
#include <type_traits>
|
||||
|
||||
#include "common/types.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
template <typename ObjectType, typename TickType>
|
||||
class LeastRecentlyUsedCache {
|
||||
struct Item {
|
||||
ObjectType obj;
|
||||
TickType tick;
|
||||
Item* next{};
|
||||
Item* prev{};
|
||||
};
|
||||
|
||||
public:
|
||||
LeastRecentlyUsedCache() : first_item{}, last_item{} {}
|
||||
~LeastRecentlyUsedCache() = default;
|
||||
|
||||
size_t Insert(ObjectType obj, TickType tick) {
|
||||
const auto new_id = Build();
|
||||
auto& item = item_pool[new_id];
|
||||
item.obj = obj;
|
||||
item.tick = tick;
|
||||
Attach(item);
|
||||
return new_id;
|
||||
}
|
||||
|
||||
void Touch(size_t id, TickType tick) {
|
||||
auto& item = item_pool[id];
|
||||
if (item.tick >= tick) {
|
||||
return;
|
||||
}
|
||||
item.tick = tick;
|
||||
if (&item == last_item) {
|
||||
return;
|
||||
}
|
||||
Detach(item);
|
||||
Attach(item);
|
||||
}
|
||||
|
||||
void Free(size_t id) {
|
||||
auto& item = item_pool[id];
|
||||
Detach(item);
|
||||
item.prev = nullptr;
|
||||
item.next = nullptr;
|
||||
free_items.push_back(id);
|
||||
}
|
||||
|
||||
template <typename Func>
|
||||
void ForEachItemBelow(TickType tick, Func&& func) {
|
||||
static constexpr bool RETURNS_BOOL =
|
||||
std::is_same_v<std::invoke_result<Func, ObjectType>, bool>;
|
||||
Item* iterator = first_item;
|
||||
while (iterator) {
|
||||
if (static_cast<s64>(tick) - static_cast<s64>(iterator->tick) < 0) {
|
||||
return;
|
||||
}
|
||||
Item* next = iterator->next;
|
||||
if constexpr (RETURNS_BOOL) {
|
||||
if (func(iterator->obj)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
func(iterator->obj);
|
||||
}
|
||||
iterator = next;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
size_t Build() {
|
||||
if (free_items.empty()) {
|
||||
const size_t item_id = item_pool.size();
|
||||
auto& item = item_pool.emplace_back();
|
||||
item.next = nullptr;
|
||||
item.prev = nullptr;
|
||||
return item_id;
|
||||
}
|
||||
const size_t item_id = free_items.front();
|
||||
free_items.pop_front();
|
||||
auto& item = item_pool[item_id];
|
||||
item.next = nullptr;
|
||||
item.prev = nullptr;
|
||||
return item_id;
|
||||
}
|
||||
|
||||
void Attach(Item& item) {
|
||||
if (!first_item) {
|
||||
first_item = &item;
|
||||
}
|
||||
if (!last_item) {
|
||||
last_item = &item;
|
||||
} else {
|
||||
item.prev = last_item;
|
||||
last_item->next = &item;
|
||||
item.next = nullptr;
|
||||
last_item = &item;
|
||||
}
|
||||
}
|
||||
|
||||
void Detach(Item& item) {
|
||||
if (item.prev) {
|
||||
item.prev->next = item.next;
|
||||
}
|
||||
if (item.next) {
|
||||
item.next->prev = item.prev;
|
||||
}
|
||||
if (&item == first_item) {
|
||||
first_item = item.next;
|
||||
if (first_item) {
|
||||
first_item->prev = nullptr;
|
||||
}
|
||||
}
|
||||
if (&item == last_item) {
|
||||
last_item = item.prev;
|
||||
if (last_item) {
|
||||
last_item->next = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::deque<Item> item_pool;
|
||||
std::deque<size_t> free_items;
|
||||
Item* first_item{};
|
||||
Item* last_item{};
|
||||
};
|
||||
|
||||
} // namespace Common
|
||||
@@ -17,8 +17,10 @@
|
||||
#include <QString>
|
||||
#include <QXmlStreamReader>
|
||||
#endif
|
||||
#include "common/elf_info.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/path_util.h"
|
||||
#include "core/file_format/psf.h"
|
||||
#include "memory_patcher.h"
|
||||
|
||||
namespace MemoryPatcher {
|
||||
@@ -27,6 +29,7 @@ EXPORT uintptr_t g_eboot_address;
|
||||
uint64_t g_eboot_image_size;
|
||||
std::string g_game_serial;
|
||||
std::string patchFile;
|
||||
bool patches_applied = false;
|
||||
std::vector<patchInfo> pending_patches;
|
||||
|
||||
std::string toHex(u64 value, size_t byteSize) {
|
||||
@@ -117,8 +120,9 @@ std::string convertValueToHex(const std::string type, const std::string valueStr
|
||||
return result;
|
||||
}
|
||||
|
||||
void OnGameLoaded() {
|
||||
void ApplyPendingPatches();
|
||||
|
||||
void OnGameLoaded() {
|
||||
if (!patchFile.empty()) {
|
||||
std::filesystem::path patchDir = Common::FS::GetUserPath(Common::FS::PathType::PatchesDir);
|
||||
|
||||
@@ -127,6 +131,9 @@ void OnGameLoaded() {
|
||||
pugi::xml_document doc;
|
||||
pugi::xml_parse_result result = doc.load_file(filePath.c_str());
|
||||
|
||||
auto* param_sfo = Common::Singleton<PSF>::Instance();
|
||||
auto app_version = param_sfo->GetString("APP_VER").value_or("Unknown version");
|
||||
|
||||
if (result) {
|
||||
auto patchXML = doc.child("Patch");
|
||||
for (pugi::xml_node_iterator it = patchXML.children().begin();
|
||||
@@ -134,59 +141,70 @@ void OnGameLoaded() {
|
||||
|
||||
if (std::string(it->name()) == "Metadata") {
|
||||
if (std::string(it->attribute("isEnabled").value()) == "true") {
|
||||
auto patchList = it->first_child();
|
||||
|
||||
std::string currentPatchName = it->attribute("Name").value();
|
||||
std::string metadataAppVer = it->attribute("AppVer").value();
|
||||
bool versionMatches = metadataAppVer == app_version;
|
||||
|
||||
auto patchList = it->first_child();
|
||||
for (pugi::xml_node_iterator patchLineIt = patchList.children().begin();
|
||||
patchLineIt != patchList.children().end(); ++patchLineIt) {
|
||||
|
||||
std::string type = patchLineIt->attribute("Type").value();
|
||||
std::string address = patchLineIt->attribute("Address").value();
|
||||
std::string patchValue = patchLineIt->attribute("Value").value();
|
||||
std::string maskOffsetStr = patchLineIt->attribute("Offset").value();
|
||||
std::string targetStr = "";
|
||||
std::string sizeStr = "";
|
||||
if (type == "mask_jump32") {
|
||||
targetStr = patchLineIt->attribute("Target").value();
|
||||
sizeStr = patchLineIt->attribute("Size").value();
|
||||
} else {
|
||||
patchValue = convertValueToHex(type, patchValue);
|
||||
if (!versionMatches && type != "mask" && type != "mask_jump32")
|
||||
continue;
|
||||
|
||||
std::string currentPatchName = it->attribute("Name").value();
|
||||
|
||||
for (pugi::xml_node_iterator patchLineIt = patchList.children().begin();
|
||||
patchLineIt != patchList.children().end(); ++patchLineIt) {
|
||||
|
||||
std::string type = patchLineIt->attribute("Type").value();
|
||||
std::string address = patchLineIt->attribute("Address").value();
|
||||
std::string patchValue = patchLineIt->attribute("Value").value();
|
||||
std::string maskOffsetStr =
|
||||
patchLineIt->attribute("Offset").value();
|
||||
std::string targetStr = "";
|
||||
std::string sizeStr = "";
|
||||
if (type == "mask_jump32") {
|
||||
targetStr = patchLineIt->attribute("Target").value();
|
||||
sizeStr = patchLineIt->attribute("Size").value();
|
||||
} else {
|
||||
patchValue = convertValueToHex(type, patchValue);
|
||||
}
|
||||
|
||||
bool littleEndian = false;
|
||||
|
||||
if (type == "bytes16" || type == "bytes32" || type == "bytes64") {
|
||||
littleEndian = true;
|
||||
}
|
||||
|
||||
MemoryPatcher::PatchMask patchMask = MemoryPatcher::PatchMask::None;
|
||||
int maskOffsetValue = 0;
|
||||
|
||||
if (type == "mask")
|
||||
patchMask = MemoryPatcher::PatchMask::Mask;
|
||||
|
||||
if (type == "mask_jump32")
|
||||
patchMask = MemoryPatcher::PatchMask::Mask_Jump32;
|
||||
|
||||
if ((type == "mask" || type == "mask_jump32") &&
|
||||
!maskOffsetStr.empty()) {
|
||||
maskOffsetValue = std::stoi(maskOffsetStr, 0, 10);
|
||||
}
|
||||
|
||||
MemoryPatcher::PatchMemory(currentPatchName, address, patchValue,
|
||||
targetStr, sizeStr, false, littleEndian,
|
||||
patchMask, maskOffsetValue);
|
||||
}
|
||||
|
||||
bool littleEndian = false;
|
||||
|
||||
if (type == "bytes16" || type == "bytes32" || type == "bytes64") {
|
||||
littleEndian = true;
|
||||
}
|
||||
|
||||
MemoryPatcher::PatchMask patchMask = MemoryPatcher::PatchMask::None;
|
||||
int maskOffsetValue = 0;
|
||||
|
||||
if (type == "mask")
|
||||
patchMask = MemoryPatcher::PatchMask::Mask;
|
||||
|
||||
if (type == "mask_jump32")
|
||||
patchMask = MemoryPatcher::PatchMask::Mask_Jump32;
|
||||
|
||||
if ((type == "mask" || type == "mask_jump32") &&
|
||||
!maskOffsetStr.empty()) {
|
||||
maskOffsetValue = std::stoi(maskOffsetStr, 0, 10);
|
||||
}
|
||||
|
||||
MemoryPatcher::PatchMemory(currentPatchName, address, patchValue,
|
||||
targetStr, sizeStr, false, littleEndian,
|
||||
patchMask, maskOffsetValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
LOG_ERROR(Loader, "couldnt patch parse xml : {}", result.description());
|
||||
|
||||
ApplyPendingPatches();
|
||||
return;
|
||||
}
|
||||
}
|
||||
ApplyPendingPatches();
|
||||
|
||||
#ifdef ENABLE_QT_GUI
|
||||
// We use the QT headers for the xml and json parsing, this define is only true on QT builds
|
||||
@@ -243,30 +261,34 @@ void OnGameLoaded() {
|
||||
QString newXmlData;
|
||||
|
||||
QXmlStreamReader xmlReader(xmlData);
|
||||
bool insideMetadata = false;
|
||||
|
||||
bool isEnabled = false;
|
||||
std::string currentPatchName;
|
||||
|
||||
auto* param_sfo = Common::Singleton<PSF>::Instance();
|
||||
auto app_version = param_sfo->GetString("APP_VER").value_or("Unknown version");
|
||||
bool versionMatches = true;
|
||||
|
||||
while (!xmlReader.atEnd()) {
|
||||
xmlReader.readNext();
|
||||
|
||||
if (xmlReader.isStartElement()) {
|
||||
QJsonArray patchLines;
|
||||
if (xmlReader.name() == QStringLiteral("Metadata")) {
|
||||
insideMetadata = true;
|
||||
|
||||
QString name = xmlReader.attributes().value("Name").toString();
|
||||
currentPatchName = name.toStdString();
|
||||
|
||||
QString appVer = xmlReader.attributes().value("AppVer").toString();
|
||||
|
||||
// Check and update the isEnabled attribute
|
||||
isEnabled = false;
|
||||
for (const QXmlStreamAttribute& attr : xmlReader.attributes()) {
|
||||
if (attr.name() == QStringLiteral("isEnabled")) {
|
||||
if (attr.value().toString() == "true") {
|
||||
isEnabled = true;
|
||||
} else
|
||||
isEnabled = false;
|
||||
isEnabled = (attr.value().toString() == "true");
|
||||
}
|
||||
}
|
||||
versionMatches = (appVer.toStdString() == app_version);
|
||||
|
||||
} else if (xmlReader.name() == QStringLiteral("PatchList")) {
|
||||
QJsonArray linesArray;
|
||||
while (!xmlReader.atEnd() &&
|
||||
@@ -294,12 +316,17 @@ void OnGameLoaded() {
|
||||
foreach (const QJsonValue& value, patchLines) {
|
||||
QJsonObject lineObject = value.toObject();
|
||||
QString type = lineObject["Type"].toString();
|
||||
|
||||
if ((type != "mask" && type != "mask_jump32") && !versionMatches)
|
||||
continue;
|
||||
|
||||
QString address = lineObject["Address"].toString();
|
||||
QString patchValue = lineObject["Value"].toString();
|
||||
QString maskOffsetStr = lineObject["Offset"].toString();
|
||||
|
||||
QString targetStr;
|
||||
QString sizeStr;
|
||||
|
||||
if (type == "mask_jump32") {
|
||||
targetStr = lineObject["Target"].toString();
|
||||
sizeStr = lineObject["Size"].toString();
|
||||
@@ -322,8 +349,8 @@ void OnGameLoaded() {
|
||||
if (type == "mask_jump32")
|
||||
patchMask = MemoryPatcher::PatchMask::Mask_Jump32;
|
||||
|
||||
if (type == "mask" ||
|
||||
type == "mask_jump32" && !maskOffsetStr.toStdString().empty()) {
|
||||
if ((type == "mask" || type == "mask_jump32") &&
|
||||
!maskOffsetStr.toStdString().empty()) {
|
||||
maskOffsetValue = std::stoi(maskOffsetStr.toStdString(), 0, 10);
|
||||
}
|
||||
|
||||
@@ -340,7 +367,7 @@ void OnGameLoaded() {
|
||||
if (xmlReader.hasError()) {
|
||||
LOG_ERROR(Loader, "Failed to parse XML for {}", g_game_serial);
|
||||
} else {
|
||||
LOG_INFO(Loader, "Patches loaded successfully");
|
||||
LOG_INFO(Loader, "Patches loaded successfully, repository: {}", folder.toStdString());
|
||||
}
|
||||
ApplyPendingPatches();
|
||||
}
|
||||
@@ -348,20 +375,26 @@ void OnGameLoaded() {
|
||||
}
|
||||
|
||||
void AddPatchToQueue(patchInfo patchToAdd) {
|
||||
if (patches_applied) {
|
||||
PatchMemory(patchToAdd.modNameStr, patchToAdd.offsetStr, patchToAdd.valueStr,
|
||||
patchToAdd.targetStr, patchToAdd.sizeStr, patchToAdd.isOffset,
|
||||
patchToAdd.littleEndian, patchToAdd.patchMask, patchToAdd.maskOffset);
|
||||
return;
|
||||
}
|
||||
pending_patches.push_back(patchToAdd);
|
||||
}
|
||||
|
||||
void ApplyPendingPatches() {
|
||||
|
||||
patches_applied = true;
|
||||
for (size_t i = 0; i < pending_patches.size(); ++i) {
|
||||
patchInfo currentPatch = pending_patches[i];
|
||||
const patchInfo& currentPatch = pending_patches[i];
|
||||
|
||||
if (currentPatch.gameSerial != g_game_serial)
|
||||
if (currentPatch.gameSerial != "*" && currentPatch.gameSerial != g_game_serial)
|
||||
continue;
|
||||
|
||||
PatchMemory(currentPatch.modNameStr, currentPatch.offsetStr, currentPatch.valueStr, "", "",
|
||||
currentPatch.isOffset, currentPatch.littleEndian, currentPatch.patchMask,
|
||||
currentPatch.maskOffset);
|
||||
PatchMemory(currentPatch.modNameStr, currentPatch.offsetStr, currentPatch.valueStr,
|
||||
currentPatch.targetStr, currentPatch.sizeStr, currentPatch.isOffset,
|
||||
currentPatch.littleEndian, currentPatch.patchMask, currentPatch.maskOffset);
|
||||
}
|
||||
|
||||
pending_patches.clear();
|
||||
|
||||
@@ -30,19 +30,18 @@ struct patchInfo {
|
||||
std::string modNameStr;
|
||||
std::string offsetStr;
|
||||
std::string valueStr;
|
||||
std::string targetStr;
|
||||
std::string sizeStr;
|
||||
bool isOffset;
|
||||
bool littleEndian;
|
||||
PatchMask patchMask;
|
||||
int maskOffset;
|
||||
};
|
||||
|
||||
extern std::vector<patchInfo> pending_patches;
|
||||
|
||||
std::string convertValueToHex(const std::string type, const std::string valueStr);
|
||||
|
||||
void OnGameLoaded();
|
||||
void AddPatchToQueue(patchInfo patchToAdd);
|
||||
void ApplyPendingPatches();
|
||||
|
||||
void PatchMemory(std::string modNameStr, std::string offsetStr, std::string valueStr,
|
||||
std::string targetStr, std::string sizeStr, bool isOffset, bool littleEndian,
|
||||
|
||||
@@ -1,20 +1,14 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <array>
|
||||
#include <half.hpp>
|
||||
|
||||
#include "common/number_utils.h"
|
||||
#include "video_core/amdgpu/pixel_format.h"
|
||||
#include "video_core/amdgpu/types.h"
|
||||
|
||||
#define UF11_EXPONENT_SHIFT 6
|
||||
#define UF10_EXPONENT_SHIFT 5
|
||||
|
||||
#define RGB9E5_MANTISSA_BITS 9
|
||||
#define RGB9E5_EXP_BIAS 1
|
||||
|
||||
#define F32_INFINITY 0x7f800000
|
||||
constexpr u32 UF11_EXPONENT_SHIFT = 6;
|
||||
constexpr u32 UF10_EXPONENT_SHIFT = 5;
|
||||
constexpr u32 RGB9E5_MANTISSA_BITS = 9;
|
||||
constexpr u32 RGB9E5_EXP_BIAS = 1;
|
||||
constexpr u32 F32_INFINITY = 0x7f800000;
|
||||
|
||||
namespace NumberUtils {
|
||||
|
||||
@@ -158,4 +152,4 @@ float S16ToSnorm(s16 val) {
|
||||
return float(val * c);
|
||||
}
|
||||
|
||||
} // namespace NumberUtils
|
||||
} // namespace NumberUtils
|
||||
|
||||
@@ -137,6 +137,7 @@ static auto UserPaths = [] {
|
||||
create_path(PathType::PatchesDir, user_dir / PATCHES_DIR);
|
||||
create_path(PathType::MetaDataDir, user_dir / METADATA_DIR);
|
||||
create_path(PathType::CustomTrophy, user_dir / CUSTOM_TROPHY);
|
||||
create_path(PathType::CustomConfigs, user_dir / CUSTOM_CONFIGS);
|
||||
|
||||
std::ofstream notice_file(user_dir / CUSTOM_TROPHY / "Notice.txt");
|
||||
if (notice_file.is_open()) {
|
||||
|
||||
@@ -27,6 +27,7 @@ enum class PathType {
|
||||
PatchesDir, // Where patches are stored.
|
||||
MetaDataDir, // Where game metadata (e.g. trophies and menu backgrounds) is stored.
|
||||
CustomTrophy, // Where custom files for trophies are stored.
|
||||
CustomConfigs, // Where custom files for different games are stored.
|
||||
};
|
||||
|
||||
constexpr auto PORTABLE_DIR = "user";
|
||||
@@ -44,6 +45,7 @@ constexpr auto CHEATS_DIR = "cheats";
|
||||
constexpr auto PATCHES_DIR = "patches";
|
||||
constexpr auto METADATA_DIR = "game_data";
|
||||
constexpr auto CUSTOM_TROPHY = "custom_trophy";
|
||||
constexpr auto CUSTOM_CONFIGS = "custom_configs";
|
||||
|
||||
// Filenames
|
||||
constexpr auto LOG_FILE = "shad_log.txt";
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <map>
|
||||
#include <boost/icl/separate_interval_set.hpp>
|
||||
#include "common/alignment.h"
|
||||
#include "common/arch.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/config.h"
|
||||
#include "common/error.h"
|
||||
#include "core/address_space.h"
|
||||
#include "core/libraries/kernel/memory.h"
|
||||
@@ -23,22 +23,70 @@
|
||||
// Reserve space for the system address space using a zerofill section.
|
||||
asm(".zerofill SYSTEM_MANAGED,SYSTEM_MANAGED,__SYSTEM_MANAGED,0x7FFBFC000");
|
||||
asm(".zerofill SYSTEM_RESERVED,SYSTEM_RESERVED,__SYSTEM_RESERVED,0x7C0004000");
|
||||
asm(".zerofill USER_AREA,USER_AREA,__USER_AREA,0x5F9000000000");
|
||||
#endif
|
||||
|
||||
namespace Core {
|
||||
|
||||
static constexpr size_t BackingSize = SCE_KERNEL_TOTAL_MEM_PRO;
|
||||
// Constants used for mapping address space.
|
||||
constexpr VAddr SYSTEM_MANAGED_MIN = 0x400000ULL;
|
||||
constexpr VAddr SYSTEM_MANAGED_MAX = 0x7FFFFBFFFULL;
|
||||
constexpr VAddr SYSTEM_RESERVED_MIN = 0x7FFFFC000ULL;
|
||||
#if defined(__APPLE__) && defined(ARCH_X86_64)
|
||||
// Commpage ranges from 0xFC0000000 - 0xFFFFFFFFF, so decrease the system reserved maximum.
|
||||
constexpr VAddr SYSTEM_RESERVED_MAX = 0xFBFFFFFFFULL;
|
||||
// GPU-reserved memory ranges from 0x1000000000 - 0x6FFFFFFFFF, so increase the user minimum.
|
||||
constexpr VAddr USER_MIN = 0x7000000000ULL;
|
||||
#else
|
||||
constexpr VAddr SYSTEM_RESERVED_MAX = 0xFFFFFFFFFULL;
|
||||
constexpr VAddr USER_MIN = 0x1000000000ULL;
|
||||
#endif
|
||||
#if defined(__linux__)
|
||||
// Linux maps the shadPS4 executable around here, so limit the user maximum
|
||||
constexpr VAddr USER_MAX = 0x54FFFFFFFFFFULL;
|
||||
#else
|
||||
constexpr VAddr USER_MAX = 0x5FFFFFFFFFFFULL;
|
||||
#endif
|
||||
|
||||
// Constants for the sizes of the ranges in address space.
|
||||
static constexpr u64 SystemManagedSize = SYSTEM_MANAGED_MAX - SYSTEM_MANAGED_MIN + 1;
|
||||
static constexpr u64 SystemReservedSize = SYSTEM_RESERVED_MAX - SYSTEM_RESERVED_MIN + 1;
|
||||
static constexpr u64 UserSize = USER_MAX - USER_MIN + 1;
|
||||
|
||||
// Required backing file size for mapping physical address space.
|
||||
static u64 BackingSize = ORBIS_KERNEL_TOTAL_MEM_DEV_PRO;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
[[nodiscard]] constexpr u64 ToWindowsProt(Core::MemoryProt prot) {
|
||||
if (True(prot & Core::MemoryProt::CpuReadWrite) ||
|
||||
True(prot & Core::MemoryProt::GpuReadWrite)) {
|
||||
return PAGE_READWRITE;
|
||||
} else if (True(prot & Core::MemoryProt::CpuRead) || True(prot & Core::MemoryProt::GpuRead)) {
|
||||
return PAGE_READONLY;
|
||||
const bool read =
|
||||
True(prot & Core::MemoryProt::CpuRead) || True(prot & Core::MemoryProt::GpuRead);
|
||||
const bool write =
|
||||
True(prot & Core::MemoryProt::CpuWrite) || True(prot & Core::MemoryProt::GpuWrite);
|
||||
const bool execute = True(prot & Core::MemoryProt::CpuExec);
|
||||
|
||||
if (write && !read) {
|
||||
// While write-only CPU mappings aren't possible, write-only GPU mappings are.
|
||||
LOG_WARNING(Core, "Converting write-only mapping to read-write");
|
||||
}
|
||||
|
||||
// All cases involving execute permissions have separate permissions.
|
||||
if (execute) {
|
||||
if (write) {
|
||||
return PAGE_EXECUTE_READWRITE;
|
||||
} else if (read && !write) {
|
||||
return PAGE_EXECUTE_READ;
|
||||
} else {
|
||||
return PAGE_EXECUTE;
|
||||
}
|
||||
} else {
|
||||
return PAGE_NOACCESS;
|
||||
if (write) {
|
||||
return PAGE_READWRITE;
|
||||
} else if (read && !write) {
|
||||
return PAGE_READONLY;
|
||||
} else {
|
||||
return PAGE_NOACCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,70 +98,100 @@ struct MemoryRegion {
|
||||
|
||||
struct AddressSpace::Impl {
|
||||
Impl() : process{GetCurrentProcess()} {
|
||||
// Allocate virtual address placeholder for our address space.
|
||||
MEM_ADDRESS_REQUIREMENTS req{};
|
||||
MEM_EXTENDED_PARAMETER param{};
|
||||
req.LowestStartingAddress = reinterpret_cast<PVOID>(SYSTEM_MANAGED_MIN);
|
||||
// The ending address must align to page boundary - 1
|
||||
// https://stackoverflow.com/questions/54223343/virtualalloc2-with-memextendedparameteraddressrequirements-always-produces-error
|
||||
req.HighestEndingAddress = reinterpret_cast<PVOID>(USER_MIN + UserSize - 1);
|
||||
req.Alignment = 0;
|
||||
param.Type = MemExtendedParameterAddressRequirements;
|
||||
param.Pointer = &req;
|
||||
// Determine the system's page alignment
|
||||
SYSTEM_INFO sys_info{};
|
||||
GetSystemInfo(&sys_info);
|
||||
u64 alignment = sys_info.dwAllocationGranularity;
|
||||
|
||||
// Typically, lower parts of system managed area is already reserved in windows.
|
||||
// If reservation fails attempt again by reducing the area size a little bit.
|
||||
// System managed is about 31GB in size so also cap the number of times we can reduce it
|
||||
// to a reasonable amount.
|
||||
static constexpr size_t ReductionOnFail = 1_GB;
|
||||
static constexpr size_t MaxReductions = 10;
|
||||
// Determine the host OS build number
|
||||
// Retrieve module handle for ntdll
|
||||
auto ntdll_handle = GetModuleHandleW(L"ntdll.dll");
|
||||
ASSERT_MSG(ntdll_handle, "Failed to retrieve ntdll handle");
|
||||
|
||||
size_t virtual_size = SystemManagedSize + SystemReservedSize + UserSize;
|
||||
for (u32 i = 0; i < MaxReductions; i++) {
|
||||
virtual_base = static_cast<u8*>(VirtualAlloc2(process, NULL, virtual_size,
|
||||
MEM_RESERVE | MEM_RESERVE_PLACEHOLDER,
|
||||
PAGE_NOACCESS, ¶m, 1));
|
||||
if (virtual_base) {
|
||||
break;
|
||||
}
|
||||
virtual_size -= ReductionOnFail;
|
||||
// Get the RtlGetVersion function
|
||||
s64(WINAPI * RtlGetVersion)(LPOSVERSIONINFOW);
|
||||
*(FARPROC*)&RtlGetVersion = GetProcAddress(ntdll_handle, "RtlGetVersion");
|
||||
ASSERT_MSG(RtlGetVersion, "failed to retrieve function pointer for RtlGetVersion");
|
||||
|
||||
// Call RtlGetVersion
|
||||
RTL_OSVERSIONINFOW os_version_info{};
|
||||
RtlGetVersion(&os_version_info);
|
||||
|
||||
u64 supported_user_max = USER_MAX;
|
||||
// This is the build number for Windows 11 22H2
|
||||
static constexpr s32 AffectedBuildNumber = 22621;
|
||||
if (os_version_info.dwBuildNumber <= AffectedBuildNumber) {
|
||||
// Older Windows builds have an issue with VirtualAlloc2 on higher addresses.
|
||||
// To prevent regressions, limit the maximum address we reserve for this platform.
|
||||
supported_user_max = 0x11000000000ULL;
|
||||
LOG_WARNING(Core, "Windows 10 detected, reducing user max to {:#x} to avoid problems",
|
||||
supported_user_max);
|
||||
}
|
||||
ASSERT_MSG(virtual_base, "Unable to reserve virtual address space: {}",
|
||||
Common::GetLastErrorMsg());
|
||||
|
||||
// Determine the free address ranges we can access.
|
||||
VAddr next_addr = SYSTEM_MANAGED_MIN;
|
||||
MEMORY_BASIC_INFORMATION info{};
|
||||
while (next_addr <= supported_user_max) {
|
||||
ASSERT_MSG(VirtualQuery(reinterpret_cast<PVOID>(next_addr), &info, sizeof(info)),
|
||||
"Failed to query memory information for address {:#x}", next_addr);
|
||||
|
||||
// Ensure logic uses values aligned to bage boundaries.
|
||||
next_addr = reinterpret_cast<VAddr>(info.BaseAddress) + info.RegionSize;
|
||||
next_addr = Common::AlignUp(next_addr, alignment);
|
||||
|
||||
// Prevent size from going past supported_user_max
|
||||
u64 size = info.RegionSize;
|
||||
if (next_addr > supported_user_max) {
|
||||
size -= (next_addr - supported_user_max);
|
||||
}
|
||||
size = Common::AlignDown(size, alignment);
|
||||
|
||||
// Check for free memory areas
|
||||
// Restrict region size to avoid overly fragmenting the virtual memory space.
|
||||
if (info.State == MEM_FREE && info.RegionSize > 0x1000000) {
|
||||
VAddr addr = Common::AlignUp(reinterpret_cast<VAddr>(info.BaseAddress), alignment);
|
||||
regions.emplace(addr, MemoryRegion{addr, size, false});
|
||||
}
|
||||
}
|
||||
|
||||
// Reserve all detected free regions.
|
||||
for (auto region : regions) {
|
||||
auto addr = static_cast<u8*>(VirtualAlloc2(
|
||||
process, reinterpret_cast<PVOID>(region.second.base), region.second.size,
|
||||
MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, PAGE_NOACCESS, NULL, 0));
|
||||
// All marked regions should reserve fine since they're free.
|
||||
ASSERT_MSG(addr, "Unable to reserve virtual address space: {}",
|
||||
Common::GetLastErrorMsg());
|
||||
}
|
||||
|
||||
// Set these constants to ensure code relying on them works.
|
||||
// These do not fully encapsulate the state of the address space.
|
||||
system_managed_base = reinterpret_cast<u8*>(regions.begin()->first);
|
||||
system_managed_size = SystemManagedSize - (regions.begin()->first - SYSTEM_MANAGED_MIN);
|
||||
system_reserved_base = reinterpret_cast<u8*>(SYSTEM_RESERVED_MIN);
|
||||
system_reserved_size = SystemReservedSize;
|
||||
system_managed_base = virtual_base;
|
||||
system_managed_size = system_reserved_base - virtual_base;
|
||||
user_base = reinterpret_cast<u8*>(USER_MIN);
|
||||
user_size = virtual_base + virtual_size - user_base;
|
||||
user_size = supported_user_max - USER_MIN - 1;
|
||||
|
||||
LOG_INFO(Kernel_Vmm, "System managed virtual memory region: {} - {}",
|
||||
fmt::ptr(system_managed_base),
|
||||
fmt::ptr(system_managed_base + system_managed_size - 1));
|
||||
LOG_INFO(Kernel_Vmm, "System reserved virtual memory region: {} - {}",
|
||||
fmt::ptr(system_reserved_base),
|
||||
fmt::ptr(system_reserved_base + system_reserved_size - 1));
|
||||
LOG_INFO(Kernel_Vmm, "User virtual memory region: {} - {}", fmt::ptr(user_base),
|
||||
fmt::ptr(user_base + user_size - 1));
|
||||
|
||||
// Initializer placeholder tracker
|
||||
const uintptr_t system_managed_addr = reinterpret_cast<uintptr_t>(system_managed_base);
|
||||
regions.emplace(system_managed_addr,
|
||||
MemoryRegion{system_managed_addr, virtual_size, false});
|
||||
// Increase BackingSize to account for config options.
|
||||
BackingSize += Config::getExtraDmemInMbytes() * 1_MB;
|
||||
|
||||
// Allocate backing file that represents the total physical memory.
|
||||
backing_handle =
|
||||
CreateFileMapping2(INVALID_HANDLE_VALUE, nullptr, FILE_MAP_WRITE | FILE_MAP_READ,
|
||||
PAGE_READWRITE, SEC_COMMIT, BackingSize, nullptr, nullptr, 0);
|
||||
backing_handle = CreateFileMapping2(INVALID_HANDLE_VALUE, nullptr, FILE_MAP_ALL_ACCESS,
|
||||
PAGE_EXECUTE_READWRITE, SEC_COMMIT, BackingSize,
|
||||
nullptr, nullptr, 0);
|
||||
|
||||
ASSERT_MSG(backing_handle, "{}", Common::GetLastErrorMsg());
|
||||
// Allocate a virtual memory for the backing file map as placeholder
|
||||
backing_base = static_cast<u8*>(VirtualAlloc2(process, nullptr, BackingSize,
|
||||
MEM_RESERVE | MEM_RESERVE_PLACEHOLDER,
|
||||
PAGE_NOACCESS, nullptr, 0));
|
||||
ASSERT_MSG(backing_base, "{}", Common::GetLastErrorMsg());
|
||||
|
||||
// Map backing placeholder. This will commit the pages
|
||||
void* const ret = MapViewOfFile3(backing_handle, process, backing_base, 0, BackingSize,
|
||||
MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, nullptr, 0);
|
||||
void* const ret =
|
||||
MapViewOfFile3(backing_handle, process, backing_base, 0, BackingSize,
|
||||
MEM_REPLACE_PLACEHOLDER, PAGE_EXECUTE_READWRITE, nullptr, 0);
|
||||
ASSERT_MSG(ret == backing_base, "{}", Common::GetLastErrorMsg());
|
||||
}
|
||||
|
||||
@@ -154,7 +232,12 @@ struct AddressSpace::Impl {
|
||||
ASSERT_MSG(ret, "VirtualProtect failed. {}", Common::GetLastErrorMsg());
|
||||
} else {
|
||||
ptr = MapViewOfFile3(backing, process, reinterpret_cast<PVOID>(virtual_addr),
|
||||
phys_addr, size, MEM_REPLACE_PLACEHOLDER, prot, nullptr, 0);
|
||||
phys_addr, size, MEM_REPLACE_PLACEHOLDER,
|
||||
PAGE_EXECUTE_READWRITE, nullptr, 0);
|
||||
ASSERT_MSG(ptr, "MapViewOfFile3 failed. {}", Common::GetLastErrorMsg());
|
||||
DWORD resultvar;
|
||||
bool ret = VirtualProtect(ptr, size, prot, &resultvar);
|
||||
ASSERT_MSG(ret, "VirtualProtect failed. {}", Common::GetLastErrorMsg());
|
||||
}
|
||||
} else {
|
||||
ptr =
|
||||
@@ -296,17 +379,33 @@ struct AddressSpace::Impl {
|
||||
void Protect(VAddr virtual_addr, size_t size, bool read, bool write, bool execute) {
|
||||
DWORD new_flags{};
|
||||
|
||||
if (read && write && execute) {
|
||||
new_flags = PAGE_EXECUTE_READWRITE;
|
||||
} else if (read && write) {
|
||||
new_flags = PAGE_READWRITE;
|
||||
} else if (read && !write) {
|
||||
new_flags = PAGE_READONLY;
|
||||
} else if (execute && !read && !write) {
|
||||
new_flags = PAGE_EXECUTE;
|
||||
} else if (!read && !write && !execute) {
|
||||
new_flags = PAGE_NOACCESS;
|
||||
if (write && !read) {
|
||||
// While write-only CPU protection isn't possible, write-only GPU protection is.
|
||||
LOG_WARNING(Core, "Converting write-only protection to read-write");
|
||||
}
|
||||
|
||||
// All cases involving execute permissions have separate permissions.
|
||||
if (execute) {
|
||||
// If there's some form of write protection requested, provide read-write permissions.
|
||||
if (write) {
|
||||
new_flags = PAGE_EXECUTE_READWRITE;
|
||||
} else if (read && !write) {
|
||||
new_flags = PAGE_EXECUTE_READ;
|
||||
} else {
|
||||
new_flags = PAGE_EXECUTE;
|
||||
}
|
||||
} else {
|
||||
if (write) {
|
||||
new_flags = PAGE_READWRITE;
|
||||
} else if (read && !write) {
|
||||
new_flags = PAGE_READONLY;
|
||||
} else {
|
||||
new_flags = PAGE_NOACCESS;
|
||||
}
|
||||
}
|
||||
|
||||
// If no flags are assigned, then something's gone wrong.
|
||||
if (new_flags == 0) {
|
||||
LOG_CRITICAL(Common_Memory,
|
||||
"Unsupported protection flag combination for address {:#x}, size {}, "
|
||||
"read={}, write={}, execute={}",
|
||||
@@ -326,12 +425,20 @@ struct AddressSpace::Impl {
|
||||
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 {}",
|
||||
"Failed to change virtual memory protection for address {:#x}, size {:#x}",
|
||||
range_addr, range_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boost::icl::interval_set<VAddr> GetUsableRegions() {
|
||||
boost::icl::interval_set<VAddr> reserved_regions;
|
||||
for (auto region : regions) {
|
||||
reserved_regions.insert({region.second.base, region.second.base + region.second.size});
|
||||
}
|
||||
return reserved_regions;
|
||||
}
|
||||
|
||||
HANDLE process{};
|
||||
HANDLE backing_handle{};
|
||||
u8* backing_base{};
|
||||
@@ -356,54 +463,73 @@ enum PosixPageProtection {
|
||||
};
|
||||
|
||||
[[nodiscard]] constexpr PosixPageProtection ToPosixProt(Core::MemoryProt prot) {
|
||||
if (True(prot & Core::MemoryProt::CpuReadWrite) ||
|
||||
True(prot & Core::MemoryProt::GpuReadWrite)) {
|
||||
return PAGE_READWRITE;
|
||||
} else if (True(prot & Core::MemoryProt::CpuRead) || True(prot & Core::MemoryProt::GpuRead)) {
|
||||
return PAGE_READONLY;
|
||||
const bool read =
|
||||
True(prot & Core::MemoryProt::CpuRead) || True(prot & Core::MemoryProt::GpuRead);
|
||||
const bool write =
|
||||
True(prot & Core::MemoryProt::CpuWrite) || True(prot & Core::MemoryProt::GpuWrite);
|
||||
const bool execute = True(prot & Core::MemoryProt::CpuExec);
|
||||
|
||||
if (write && !read) {
|
||||
// While write-only CPU mappings aren't possible, write-only GPU mappings are.
|
||||
LOG_WARNING(Core, "Converting write-only mapping to read-write");
|
||||
}
|
||||
|
||||
// All cases involving execute permissions have separate permissions.
|
||||
if (execute) {
|
||||
if (write) {
|
||||
return PAGE_EXECUTE_READWRITE;
|
||||
} else if (read && !write) {
|
||||
return PAGE_EXECUTE_READ;
|
||||
} else {
|
||||
return PAGE_EXECUTE;
|
||||
}
|
||||
} else {
|
||||
return PAGE_NOACCESS;
|
||||
if (write) {
|
||||
return PAGE_READWRITE;
|
||||
} else if (read && !write) {
|
||||
return PAGE_READONLY;
|
||||
} else {
|
||||
return PAGE_NOACCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct AddressSpace::Impl {
|
||||
Impl() {
|
||||
BackingSize += Config::getExtraDmemInMbytes() * 1_MB;
|
||||
// Allocate virtual address placeholder for our address space.
|
||||
system_managed_size = SystemManagedSize;
|
||||
system_reserved_size = SystemReservedSize;
|
||||
user_size = UserSize;
|
||||
|
||||
constexpr int protection_flags = PROT_READ | PROT_WRITE;
|
||||
constexpr int base_map_flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE;
|
||||
constexpr int map_flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED;
|
||||
#if defined(__APPLE__) && defined(ARCH_X86_64)
|
||||
// On ARM64 Macs under Rosetta 2, we run into limitations due to the commpage from
|
||||
// 0xFC0000000 - 0xFFFFFFFFF and the GPU carveout region from 0x1000000000 - 0x6FFFFFFFFF.
|
||||
// We can allocate the system managed region, as well as system reserved if reduced in size
|
||||
// slightly, but we cannot map the user region where we want, so we must let the OS put it
|
||||
// wherever possible and hope the game won't rely on its location.
|
||||
system_managed_base = reinterpret_cast<u8*>(
|
||||
mmap(reinterpret_cast<void*>(SYSTEM_MANAGED_MIN), system_managed_size, protection_flags,
|
||||
base_map_flags | MAP_FIXED, -1, 0));
|
||||
system_reserved_base = reinterpret_cast<u8*>(
|
||||
mmap(reinterpret_cast<void*>(SYSTEM_RESERVED_MIN), system_reserved_size,
|
||||
protection_flags, base_map_flags | MAP_FIXED, -1, 0));
|
||||
// Cannot guarantee enough space for these areas at the desired addresses, so not MAP_FIXED.
|
||||
user_base = reinterpret_cast<u8*>(mmap(reinterpret_cast<void*>(USER_MIN), user_size,
|
||||
protection_flags, base_map_flags, -1, 0));
|
||||
// On ARM64 Macs, we run into limitations due to the commpage from 0xFC0000000 - 0xFFFFFFFFF
|
||||
// and the GPU carveout region from 0x1000000000 - 0x6FFFFFFFFF. Because this creates gaps
|
||||
// in the available virtual memory region, we map memory space using three distinct parts.
|
||||
system_managed_base =
|
||||
reinterpret_cast<u8*>(mmap(reinterpret_cast<void*>(SYSTEM_MANAGED_MIN),
|
||||
system_managed_size, protection_flags, map_flags, -1, 0));
|
||||
system_reserved_base =
|
||||
reinterpret_cast<u8*>(mmap(reinterpret_cast<void*>(SYSTEM_RESERVED_MIN),
|
||||
system_reserved_size, protection_flags, map_flags, -1, 0));
|
||||
user_base = reinterpret_cast<u8*>(
|
||||
mmap(reinterpret_cast<void*>(USER_MIN), user_size, protection_flags, map_flags, -1, 0));
|
||||
#else
|
||||
const auto virtual_size = system_managed_size + system_reserved_size + user_size;
|
||||
#if defined(ARCH_X86_64)
|
||||
const auto virtual_base =
|
||||
reinterpret_cast<u8*>(mmap(reinterpret_cast<void*>(SYSTEM_MANAGED_MIN), virtual_size,
|
||||
protection_flags, base_map_flags | MAP_FIXED, -1, 0));
|
||||
protection_flags, map_flags, -1, 0));
|
||||
system_managed_base = virtual_base;
|
||||
system_reserved_base = reinterpret_cast<u8*>(SYSTEM_RESERVED_MIN);
|
||||
user_base = reinterpret_cast<u8*>(USER_MIN);
|
||||
#else
|
||||
// Map memory wherever possible and instruction translation can handle offsetting to the
|
||||
// base.
|
||||
const auto virtual_base = reinterpret_cast<u8*>(
|
||||
mmap(nullptr, virtual_size, protection_flags, base_map_flags, -1, 0));
|
||||
const auto virtual_base =
|
||||
reinterpret_cast<u8*>(mmap(nullptr, virtual_size, protection_flags, map_flags, -1, 0));
|
||||
system_managed_base = virtual_base;
|
||||
system_reserved_base = virtual_base + SYSTEM_RESERVED_MIN - SYSTEM_MANAGED_MIN;
|
||||
user_base = virtual_base + USER_MIN - SYSTEM_MANAGED_MIN;
|
||||
@@ -571,9 +697,9 @@ void AddressSpace::Unmap(VAddr virtual_addr, size_t size, VAddr start_in_vma, VA
|
||||
// the entire allocation and remap the portions outside of the requested unmapping range.
|
||||
impl->Unmap(virtual_addr, size, has_backing && !readonly_file);
|
||||
|
||||
// TODO: Determine if any titles require partial unmapping support for flexible allocations.
|
||||
// TODO: Determine if any titles require partial unmapping support for un-backed allocations.
|
||||
ASSERT_MSG(has_backing || (start_in_vma == 0 && end_in_vma == size),
|
||||
"Partial unmapping of flexible allocations is not supported");
|
||||
"Partial unmapping of un-backed allocations is not supported");
|
||||
|
||||
if (start_in_vma != 0) {
|
||||
Map(virtual_addr, start_in_vma, 0, phys_base, is_exec);
|
||||
@@ -594,4 +720,22 @@ void AddressSpace::Protect(VAddr virtual_addr, size_t size, MemoryPermission per
|
||||
return impl->Protect(virtual_addr, size, read, write, execute);
|
||||
}
|
||||
|
||||
boost::icl::interval_set<VAddr> AddressSpace::GetUsableRegions() {
|
||||
#ifdef _WIN32
|
||||
// On Windows, we need to obtain the accessible intervals from the implementation's regions.
|
||||
return impl->GetUsableRegions();
|
||||
#else
|
||||
// On Linux and Mac, the memory space is fully represented by the three major regions
|
||||
boost::icl::interval_set<VAddr> reserved_regions;
|
||||
VAddr system_managed_addr = reinterpret_cast<VAddr>(system_managed_base);
|
||||
VAddr system_reserved_addr = reinterpret_cast<VAddr>(system_reserved_base);
|
||||
VAddr user_addr = reinterpret_cast<VAddr>(user_base);
|
||||
|
||||
reserved_regions.insert({system_managed_addr, system_managed_addr + system_managed_size});
|
||||
reserved_regions.insert({system_reserved_addr, system_reserved_addr + system_reserved_size});
|
||||
reserved_regions.insert({user_addr, user_addr + user_size});
|
||||
return reserved_regions;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <boost/icl/separate_interval_set.hpp>
|
||||
#include "common/arch.h"
|
||||
#include "common/enum.h"
|
||||
#include "common/types.h"
|
||||
@@ -20,22 +21,6 @@ enum class MemoryPermission : u32 {
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(MemoryPermission)
|
||||
|
||||
constexpr VAddr SYSTEM_MANAGED_MIN = 0x00000400000ULL;
|
||||
constexpr VAddr SYSTEM_MANAGED_MAX = 0x07FFFFBFFFULL;
|
||||
constexpr VAddr SYSTEM_RESERVED_MIN = 0x07FFFFC000ULL;
|
||||
#if defined(__APPLE__) && defined(ARCH_X86_64)
|
||||
// Can only comfortably reserve the first 0x7C0000000 of system reserved space.
|
||||
constexpr VAddr SYSTEM_RESERVED_MAX = 0xFBFFFFFFFULL;
|
||||
#else
|
||||
constexpr VAddr SYSTEM_RESERVED_MAX = 0xFFFFFFFFFULL;
|
||||
#endif
|
||||
constexpr VAddr USER_MIN = 0x1000000000ULL;
|
||||
constexpr VAddr USER_MAX = 0xFBFFFFFFFFULL;
|
||||
|
||||
static constexpr size_t SystemManagedSize = SYSTEM_MANAGED_MAX - SYSTEM_MANAGED_MIN + 1;
|
||||
static constexpr size_t SystemReservedSize = SYSTEM_RESERVED_MAX - SYSTEM_RESERVED_MIN + 1;
|
||||
static constexpr size_t UserSize = 1ULL << 40;
|
||||
|
||||
/**
|
||||
* Represents the user virtual address space backed by a dmem memory block
|
||||
*/
|
||||
@@ -100,6 +85,9 @@ public:
|
||||
|
||||
void Protect(VAddr virtual_addr, size_t size, MemoryPermission perms);
|
||||
|
||||
// Returns an interval set containing all usable regions.
|
||||
boost::icl::interval_set<VAddr> GetUsableRegions();
|
||||
|
||||
private:
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
|
||||
@@ -163,7 +163,9 @@ static void GenerateEXTRQ(void* /* address */, const ZydisDecodedOperand* operan
|
||||
mask = (1ULL << length) - 1;
|
||||
}
|
||||
|
||||
ASSERT_MSG(length + index <= 64, "length + index must be less than or equal to 64.");
|
||||
if (length + index > 64) {
|
||||
mask = 0xFFFF'FFFF'FFFF'FFFF;
|
||||
}
|
||||
|
||||
// Get lower qword from xmm register
|
||||
c.vmovq(scratch1, xmm_dst);
|
||||
@@ -177,8 +179,8 @@ static void GenerateEXTRQ(void* /* address */, const ZydisDecodedOperand* operan
|
||||
c.mov(scratch2, mask);
|
||||
c.and_(scratch1, scratch2);
|
||||
|
||||
// Writeback to xmm register, extrq instruction says top 64-bits are undefined so we don't
|
||||
// care to preserve them
|
||||
// Writeback to xmm register, extrq instruction says top 64-bits are undefined but zeroed on
|
||||
// AMD CPUs
|
||||
c.vmovq(xmm_dst, scratch1);
|
||||
|
||||
c.pop(scratch2);
|
||||
@@ -287,7 +289,9 @@ static void GenerateINSERTQ(void* /* address */, const ZydisDecodedOperand* oper
|
||||
mask_value = (1ULL << length) - 1;
|
||||
}
|
||||
|
||||
ASSERT_MSG(length + index <= 64, "length + index must be less than or equal to 64.");
|
||||
if (length + index > 64) {
|
||||
mask_value = 0xFFFF'FFFF'FFFF'FFFF;
|
||||
}
|
||||
|
||||
c.vmovq(scratch1, xmm_src);
|
||||
c.vmovq(scratch2, xmm_dst);
|
||||
@@ -307,8 +311,9 @@ static void GenerateINSERTQ(void* /* address */, const ZydisDecodedOperand* oper
|
||||
// dst |= src
|
||||
c.or_(scratch2, scratch1);
|
||||
|
||||
// Insert scratch2 into low 64 bits of dst, upper 64 bits are unaffected
|
||||
c.vpinsrq(xmm_dst, xmm_dst, scratch2, 0);
|
||||
// Insert scratch2 into low 64 bits of dst, upper 64 bits are undefined but zeroed on AMD
|
||||
// CPUs
|
||||
c.vmovq(xmm_dst, scratch2);
|
||||
|
||||
c.pop(mask);
|
||||
c.pop(scratch2);
|
||||
@@ -374,7 +379,7 @@ static void GenerateINSERTQ(void* /* address */, const ZydisDecodedOperand* oper
|
||||
c.and_(scratch2, mask);
|
||||
c.or_(scratch2, scratch1);
|
||||
|
||||
// Upper 64 bits are undefined in insertq
|
||||
// Upper 64 bits are undefined in insertq but AMD CPUs zero them
|
||||
c.vmovq(xmm_dst, scratch2);
|
||||
|
||||
c.pop(mask);
|
||||
@@ -635,6 +640,7 @@ static bool TryExecuteIllegalInstruction(void* ctx, void* code_address) {
|
||||
lowQWordDst >>= index;
|
||||
lowQWordDst &= mask;
|
||||
|
||||
memset((u8*)dst + sizeof(u64), 0, sizeof(u64));
|
||||
memcpy(dst, &lowQWordDst, sizeof(lowQWordDst));
|
||||
|
||||
Common::IncrementRip(ctx, 4);
|
||||
@@ -675,6 +681,7 @@ static bool TryExecuteIllegalInstruction(void* ctx, void* code_address) {
|
||||
lowQWordDst &= ~(mask << index);
|
||||
lowQWordDst |= lowQWordSrc << index;
|
||||
|
||||
memset((u8*)dst + sizeof(u64), 0, sizeof(u64));
|
||||
memcpy(dst, &lowQWordDst, sizeof(lowQWordDst));
|
||||
|
||||
Common::IncrementRip(ctx, 4);
|
||||
@@ -746,6 +753,10 @@ static bool PatchesIllegalInstructionHandler(void* context) {
|
||||
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
|
||||
const auto status =
|
||||
Common::Decoder::Instance()->decodeInstruction(instruction, operands, code_address);
|
||||
if (ZYAN_SUCCESS(status) && instruction.mnemonic == ZydisMnemonic::ZYDIS_MNEMONIC_UD2)
|
||||
[[unlikely]] {
|
||||
UNREACHABLE_MSG("ud2 at code address {:#x}", (u64)code_address);
|
||||
}
|
||||
LOG_ERROR(Core, "Failed to patch address {:x} -- mnemonic: {}", (u64)code_address,
|
||||
ZYAN_SUCCESS(status) ? ZydisMnemonicGetString(instruction.mnemonic)
|
||||
: "Failed to decode");
|
||||
|
||||
@@ -157,7 +157,7 @@ std::optional<RegDump*> DebugStateImpl::GetRegDump(uintptr_t base_addr, uintptr_
|
||||
}
|
||||
|
||||
void DebugStateImpl::PushRegsDump(uintptr_t base_addr, uintptr_t header_addr,
|
||||
const AmdGpu::Liverpool::Regs& regs) {
|
||||
const AmdGpu::Regs& regs) {
|
||||
std::scoped_lock lock{frame_dump_list_mutex};
|
||||
|
||||
auto dump = GetRegDump(base_addr, header_addr);
|
||||
@@ -170,15 +170,14 @@ void DebugStateImpl::PushRegsDump(uintptr_t base_addr, uintptr_t header_addr,
|
||||
for (int i = 0; i < RegDump::MaxShaderStages; i++) {
|
||||
if ((*dump)->regs.stage_enable.IsStageEnabled(i)) {
|
||||
auto stage = (*dump)->regs.ProgramForStage(i);
|
||||
if (stage->address_lo != 0) {
|
||||
const auto& info = AmdGpu::Liverpool::SearchBinaryInfo(stage->Address<u32*>());
|
||||
auto code = stage->Code();
|
||||
if (stage->address) {
|
||||
const auto params = AmdGpu::GetParams(*stage);
|
||||
(*dump)->stages[i] = PipelineShaderProgramDump{
|
||||
.name = Vulkan::PipelineCache::GetShaderName(Shader::StageFromIndex(i),
|
||||
info.shader_hash),
|
||||
.hash = info.shader_hash,
|
||||
params.hash),
|
||||
.hash = params.hash,
|
||||
.user_data = *stage,
|
||||
.code = std::vector<u32>{code.begin(), code.end()},
|
||||
.code = std::vector<u32>{params.code.begin(), params.code.end()},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -198,12 +197,12 @@ void DebugStateImpl::PushRegsDumpCompute(uintptr_t base_addr, uintptr_t header_a
|
||||
auto& cs = (*dump)->regs.cs_program;
|
||||
cs = cs_state;
|
||||
|
||||
const auto& info = AmdGpu::Liverpool::SearchBinaryInfo(cs.Address<u32*>());
|
||||
const auto params = AmdGpu::GetParams(cs);
|
||||
(*dump)->cs_data = PipelineComputerProgramDump{
|
||||
.name = Vulkan::PipelineCache::GetShaderName(Shader::Stage::Compute, info.shader_hash),
|
||||
.hash = info.shader_hash,
|
||||
.name = Vulkan::PipelineCache::GetShaderName(Shader::Stage::Compute, params.hash),
|
||||
.hash = params.hash,
|
||||
.cs_program = cs,
|
||||
.code = std::vector<u32>{cs.Code().begin(), cs.Code().end()},
|
||||
.code = std::vector<u32>{params.code.begin(), params.code.end()},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
#include <queue>
|
||||
|
||||
#include "common/types.h"
|
||||
#include "video_core/renderer_vulkan/vk_graphics_pipeline.h"
|
||||
#include "shader_recompiler/runtime_info.h"
|
||||
#include "video_core/amdgpu/regs.h"
|
||||
#include "video_core/renderer_vulkan/vk_common.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
@@ -54,21 +56,21 @@ struct QueueDump {
|
||||
struct PipelineShaderProgramDump {
|
||||
std::string name;
|
||||
u64 hash;
|
||||
Vulkan::Liverpool::ShaderProgram user_data{};
|
||||
AmdGpu::ShaderProgram user_data{};
|
||||
std::vector<u32> code{};
|
||||
};
|
||||
|
||||
struct PipelineComputerProgramDump {
|
||||
std::string name;
|
||||
u64 hash;
|
||||
Vulkan::Liverpool::ComputeProgram cs_program{};
|
||||
AmdGpu::ComputeProgram cs_program{};
|
||||
std::vector<u32> code{};
|
||||
};
|
||||
|
||||
struct RegDump {
|
||||
bool is_compute{false};
|
||||
static constexpr size_t MaxShaderStages = 5;
|
||||
Vulkan::Liverpool::Regs regs{};
|
||||
AmdGpu::Regs regs;
|
||||
std::array<PipelineShaderProgramDump, MaxShaderStages> stages{};
|
||||
PipelineComputerProgramDump cs_data{};
|
||||
};
|
||||
@@ -219,9 +221,8 @@ public:
|
||||
|
||||
void PushQueueDump(QueueDump dump);
|
||||
|
||||
void PushRegsDump(uintptr_t base_addr, uintptr_t header_addr,
|
||||
const AmdGpu::Liverpool::Regs& regs);
|
||||
using CsState = AmdGpu::Liverpool::ComputeProgram;
|
||||
void PushRegsDump(uintptr_t base_addr, uintptr_t header_addr, const AmdGpu::Regs& regs);
|
||||
using CsState = AmdGpu::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,
|
||||
|
||||
99
src/core/debugger.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "debugger.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <Windows.h>
|
||||
#include <debugapi.h>
|
||||
#elif defined(__linux__)
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#elif defined(__APPLE__)
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
bool Core::Debugger::IsDebuggerAttached() {
|
||||
#if defined(_WIN32)
|
||||
return IsDebuggerPresent();
|
||||
#elif defined(__linux__)
|
||||
std::ifstream status_file("/proc/self/status");
|
||||
std::string line;
|
||||
while (std::getline(status_file, line)) {
|
||||
if (line.starts_with("TracerPid:")) {
|
||||
std::string tracer_pid = line.substr(10);
|
||||
tracer_pid.erase(0, tracer_pid.find_first_not_of(" \t"));
|
||||
return tracer_pid != "0";
|
||||
}
|
||||
}
|
||||
return false;
|
||||
#elif defined(__APPLE__)
|
||||
int mib[4];
|
||||
struct kinfo_proc info;
|
||||
size_t size = sizeof(info);
|
||||
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_PROC;
|
||||
mib[2] = KERN_PROC_PID;
|
||||
mib[3] = getpid();
|
||||
|
||||
if (sysctl(mib, 4, &info, &size, nullptr, 0) == 0) {
|
||||
return (info.kp_proc.p_flag & P_TRACED) != 0;
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
#error "Unsupported platform"
|
||||
#endif
|
||||
}
|
||||
|
||||
void Core::Debugger::WaitForDebuggerAttach() {
|
||||
int count = 0;
|
||||
while (!IsDebuggerAttached()) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
if (--count <= 0) {
|
||||
count = 10;
|
||||
std::cerr << "Waiting for debugger to attach..." << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
int Core::Debugger::GetCurrentPid() {
|
||||
#if defined(_WIN32)
|
||||
return GetCurrentProcessId();
|
||||
#elif defined(__APPLE__) || defined(__linux__)
|
||||
return getpid();
|
||||
#else
|
||||
#error "Unsupported platform"
|
||||
#endif
|
||||
}
|
||||
|
||||
void Core::Debugger::WaitForPid(int pid) {
|
||||
#if defined(_WIN32)
|
||||
HANDLE process_handle = OpenProcess(SYNCHRONIZE, FALSE, pid);
|
||||
if (process_handle != nullptr) {
|
||||
std::cerr << "Waiting for process " << pid << " to exit..." << std::endl;
|
||||
WaitForSingleObject(process_handle, INFINITE);
|
||||
CloseHandle(process_handle);
|
||||
}
|
||||
#elif defined(__linux__)
|
||||
std::string proc_path = "/proc/" + std::to_string(pid);
|
||||
|
||||
while (std::filesystem::exists(proc_path)) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
std::cerr << "Waiting for process " << pid << " to exit..." << std::endl;
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
while (kill(pid, 0) == 0) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
std::cerr << "Waiting for process " << pid << " to exit..." << std::endl;
|
||||
}
|
||||
#else
|
||||
#error "Unsupported platform"
|
||||
#endif
|
||||
}
|
||||
16
src/core/debugger.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Core::Debugger {
|
||||
|
||||
bool IsDebuggerAttached();
|
||||
|
||||
void WaitForDebuggerAttach();
|
||||
|
||||
int GetCurrentPid();
|
||||
|
||||
void WaitForPid(int pid);
|
||||
|
||||
} // namespace Core::Debugger
|
||||
@@ -1,74 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "console_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
std::shared_ptr<BaseDevice> ConsoleDevice::Create(u32 handle, const char*, int, u16) {
|
||||
return std::shared_ptr<BaseDevice>(
|
||||
reinterpret_cast<Devices::BaseDevice*>(new ConsoleDevice(handle)));
|
||||
}
|
||||
|
||||
int ConsoleDevice::ioctl(u64 cmd, Common::VaCtx* args) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 ConsoleDevice::write(const void* buf, size_t nbytes) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t ConsoleDevice::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t ConsoleDevice::readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 ConsoleDevice::preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 ConsoleDevice::lseek(s64 offset, int whence) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 ConsoleDevice::read(void* buf, size_t nbytes) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ConsoleDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 ConsoleDevice::fsync() {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ConsoleDevice::ftruncate(s64 length) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ConsoleDevice::getdents(void* buf, u32 nbytes, s64* basep) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 ConsoleDevice::pwrite(const void* buf, size_t nbytes, u64 offset) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace Core::Devices
|
||||
@@ -1,33 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "base_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
class ConsoleDevice final : BaseDevice {
|
||||
u32 handle;
|
||||
|
||||
public:
|
||||
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, int, u16);
|
||||
explicit ConsoleDevice(u32 handle) : handle(handle) {}
|
||||
|
||||
~ConsoleDevice() override = default;
|
||||
|
||||
int ioctl(u64 cmd, Common::VaCtx* args) override;
|
||||
s64 write(const void* buf, size_t nbytes) override;
|
||||
size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
|
||||
size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
|
||||
s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) override;
|
||||
s64 lseek(s64 offset, int whence) override;
|
||||
s64 read(void* buf, size_t nbytes) override;
|
||||
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
|
||||
s32 fsync() override;
|
||||
int ftruncate(s64 length) override;
|
||||
int getdents(void* buf, u32 nbytes, s64* basep) override;
|
||||
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override;
|
||||
};
|
||||
|
||||
} // namespace Core::Devices
|
||||
@@ -1,74 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "deci_tty6_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
std::shared_ptr<BaseDevice> DeciTty6Device::Create(u32 handle, const char*, int, u16) {
|
||||
return std::shared_ptr<BaseDevice>(
|
||||
reinterpret_cast<Devices::BaseDevice*>(new DeciTty6Device(handle)));
|
||||
}
|
||||
|
||||
int DeciTty6Device::ioctl(u64 cmd, Common::VaCtx* args) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 DeciTty6Device::write(const void* buf, size_t nbytes) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t DeciTty6Device::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t DeciTty6Device::readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 DeciTty6Device::preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 DeciTty6Device::lseek(s64 offset, int whence) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 DeciTty6Device::read(void* buf, size_t nbytes) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DeciTty6Device::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 DeciTty6Device::fsync() {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DeciTty6Device::ftruncate(s64 length) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DeciTty6Device::getdents(void* buf, u32 nbytes, s64* basep) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 DeciTty6Device::pwrite(const void* buf, size_t nbytes, u64 offset) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace Core::Devices
|
||||
@@ -1,33 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "base_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
class DeciTty6Device final : BaseDevice {
|
||||
u32 handle;
|
||||
|
||||
public:
|
||||
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, int, u16);
|
||||
explicit DeciTty6Device(u32 handle) : handle(handle) {}
|
||||
|
||||
~DeciTty6Device() override = default;
|
||||
|
||||
int ioctl(u64 cmd, Common::VaCtx* args) override;
|
||||
s64 write(const void* buf, size_t nbytes) override;
|
||||
size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
|
||||
size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
|
||||
s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) override;
|
||||
s64 lseek(s64 offset, int whence) override;
|
||||
s64 read(void* buf, size_t nbytes) override;
|
||||
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
|
||||
s32 fsync() override;
|
||||
int ftruncate(s64 length) override;
|
||||
int getdents(void* buf, u32 nbytes, s64* basep) override;
|
||||
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override;
|
||||
};
|
||||
|
||||
} // namespace Core::Devices
|
||||
@@ -1,66 +0,0 @@
|
||||
// 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
|
||||
@@ -1,79 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include "common/logging/log.h"
|
||||
#include "random_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
std::shared_ptr<BaseDevice> RandomDevice::Create(u32 handle, const char*, int, u16) {
|
||||
std::srand(std::time(nullptr));
|
||||
return std::shared_ptr<BaseDevice>(
|
||||
reinterpret_cast<Devices::BaseDevice*>(new RandomDevice(handle)));
|
||||
}
|
||||
|
||||
int RandomDevice::ioctl(u64 cmd, Common::VaCtx* args) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 RandomDevice::write(const void* buf, size_t nbytes) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t RandomDevice::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t RandomDevice::readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 RandomDevice::preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 RandomDevice::lseek(s64 offset, int whence) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 RandomDevice::read(void* buf, size_t nbytes) {
|
||||
auto rbuf = static_cast<char*>(buf);
|
||||
for (size_t i = 0; i < nbytes; i++) {
|
||||
rbuf[i] = std::rand() & 0xFF;
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
int RandomDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 RandomDevice::fsync() {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RandomDevice::ftruncate(s64 length) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RandomDevice::getdents(void* buf, u32 nbytes, s64* basep) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 RandomDevice::pwrite(const void* buf, size_t nbytes, u64 offset) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace Core::Devices
|
||||
@@ -1,33 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "base_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
class RandomDevice final : BaseDevice {
|
||||
u32 handle;
|
||||
|
||||
public:
|
||||
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, int, u16);
|
||||
explicit RandomDevice(u32 handle) : handle(handle) {}
|
||||
|
||||
~RandomDevice() override = default;
|
||||
|
||||
int ioctl(u64 cmd, Common::VaCtx* args) override;
|
||||
s64 write(const void* buf, size_t nbytes) override;
|
||||
size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
|
||||
size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
|
||||
s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) override;
|
||||
s64 lseek(s64 offset, int whence) override;
|
||||
s64 read(void* buf, size_t nbytes) override;
|
||||
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
|
||||
s32 fsync() override;
|
||||
int ftruncate(s64 length) override;
|
||||
int getdents(void* buf, u32 nbytes, s64* basep) override;
|
||||
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override;
|
||||
};
|
||||
|
||||
} // namespace Core::Devices
|
||||
@@ -1,80 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include "common/logging/log.h"
|
||||
#include "srandom_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
std::shared_ptr<BaseDevice> SRandomDevice::Create(u32 handle, const char*, int, u16) {
|
||||
std::srand(std::time(nullptr));
|
||||
return std::shared_ptr<BaseDevice>(
|
||||
reinterpret_cast<Devices::BaseDevice*>(new SRandomDevice(handle)));
|
||||
}
|
||||
|
||||
int SRandomDevice::ioctl(u64 cmd, Common::VaCtx* args) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 SRandomDevice::write(const void* buf, size_t nbytes) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t SRandomDevice::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t SRandomDevice::readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 SRandomDevice::preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 SRandomDevice::lseek(s64 offset, int whence) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 SRandomDevice::read(void* buf, size_t nbytes) {
|
||||
auto rbuf = static_cast<char*>(buf);
|
||||
for (size_t i = 0; i < nbytes; i++) {
|
||||
rbuf[i] = std::rand();
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
int SRandomDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 SRandomDevice::fsync() {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return s32();
|
||||
}
|
||||
|
||||
int SRandomDevice::ftruncate(s64 length) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SRandomDevice::getdents(void* buf, u32 nbytes, s64* basep) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 SRandomDevice::pwrite(const void* buf, size_t nbytes, u64 offset) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace Core::Devices
|
||||
@@ -1,33 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "base_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
class SRandomDevice final : BaseDevice {
|
||||
u32 handle;
|
||||
|
||||
public:
|
||||
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, int, u16);
|
||||
explicit SRandomDevice(u32 handle) : handle(handle) {}
|
||||
|
||||
~SRandomDevice() override = default;
|
||||
|
||||
int ioctl(u64 cmd, Common::VaCtx* args) override;
|
||||
s64 write(const void* buf, size_t nbytes) override;
|
||||
size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
|
||||
size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
|
||||
s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) override;
|
||||
s64 lseek(s64 offset, int whence) override;
|
||||
s64 read(void* buf, size_t nbytes) override;
|
||||
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
|
||||
s32 fsync() override;
|
||||
int ftruncate(s64 length) override;
|
||||
int getdents(void* buf, u32 nbytes, s64* basep) override;
|
||||
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override;
|
||||
};
|
||||
|
||||
} // namespace Core::Devices
|
||||
@@ -1,80 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include "common/logging/log.h"
|
||||
#include "urandom_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
std::shared_ptr<BaseDevice> URandomDevice::Create(u32 handle, const char*, int, u16) {
|
||||
std::srand(std::time(nullptr));
|
||||
return std::shared_ptr<BaseDevice>(
|
||||
reinterpret_cast<Devices::BaseDevice*>(new URandomDevice(handle)));
|
||||
}
|
||||
|
||||
int URandomDevice::ioctl(u64 cmd, Common::VaCtx* args) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 URandomDevice::write(const void* buf, size_t nbytes) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t URandomDevice::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t URandomDevice::readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 URandomDevice::preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 URandomDevice::lseek(s64 offset, int whence) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 URandomDevice::read(void* buf, size_t nbytes) {
|
||||
auto rbuf = static_cast<char*>(buf);
|
||||
for (size_t i = 0; i < nbytes; i++) {
|
||||
rbuf[i] = std::rand() & 0xFF;
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
int URandomDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 URandomDevice::fsync() {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int URandomDevice::ftruncate(s64 length) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int URandomDevice::getdents(void* buf, u32 nbytes, s64* basep) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 URandomDevice::pwrite(const void* buf, size_t nbytes, u64 offset) {
|
||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace Core::Devices
|
||||
@@ -1,33 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "base_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
class URandomDevice final : BaseDevice {
|
||||
u32 handle;
|
||||
|
||||
public:
|
||||
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, int, u16);
|
||||
explicit URandomDevice(u32 handle) : handle(handle) {}
|
||||
|
||||
~URandomDevice() override = default;
|
||||
|
||||
int ioctl(u64 cmd, Common::VaCtx* args) override;
|
||||
s64 write(const void* buf, size_t nbytes) override;
|
||||
size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
|
||||
size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
|
||||
s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) override;
|
||||
s64 lseek(s64 offset, int whence) override;
|
||||
s64 read(void* buf, size_t nbytes) override;
|
||||
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
|
||||
s32 fsync() override;
|
||||
int ftruncate(s64 length) override;
|
||||
int getdents(void* buf, u32 nbytes, s64* basep) override;
|
||||
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override;
|
||||
};
|
||||
|
||||
} // namespace Core::Devices
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "layer.h"
|
||||
|
||||
#include <SDL3/SDL_events.h>
|
||||
#include <imgui.h>
|
||||
|
||||
#include "SDL3/SDL_log.h"
|
||||
@@ -28,6 +29,7 @@ using L = ::Core::Devtools::Layer;
|
||||
|
||||
static bool show_simple_fps = false;
|
||||
static bool visibility_toggled = false;
|
||||
static bool show_quit_window = false;
|
||||
|
||||
static float fps_scale = 1.0f;
|
||||
static int dump_frame_count = 1;
|
||||
@@ -102,6 +104,16 @@ void L::DrawMenuBar() {
|
||||
EndDisabled();
|
||||
}
|
||||
EndDisabled();
|
||||
|
||||
if (Button("Save")) {
|
||||
Config::setFsrEnabled(fsr.enable);
|
||||
Config::setRcasEnabled(fsr.use_rcas);
|
||||
Config::setRcasAttenuation(static_cast<int>(fsr.rcas_attenuation * 1000));
|
||||
Config::save(Common::FS::GetUserPath(Common::FS::PathType::UserDir) /
|
||||
"config.toml");
|
||||
CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
@@ -138,15 +150,8 @@ void L::DrawAdvanced() {
|
||||
const auto& ctx = *GImGui;
|
||||
const auto& io = ctx.IO;
|
||||
|
||||
auto isSystemPaused = DebugState.IsGuestThreadsPaused();
|
||||
|
||||
frame_graph.Draw();
|
||||
|
||||
if (isSystemPaused) {
|
||||
GetForegroundDrawList(GetMainViewport())
|
||||
->AddText({10.0f, io.DisplaySize.y - 40.0f}, IM_COL32_WHITE, "Emulator paused");
|
||||
}
|
||||
|
||||
if (DebugState.should_show_frame_dump && DebugState.waiting_reg_dumps.empty()) {
|
||||
DebugState.should_show_frame_dump = false;
|
||||
std::unique_lock lock{DebugState.frame_dump_list_mutex};
|
||||
@@ -368,8 +373,6 @@ void L::Draw() {
|
||||
if (IsKeyPressed(ImGuiKey_F10, false)) {
|
||||
if (io.KeyCtrl) {
|
||||
DebugState.IsShowingDebugMenuBar() ^= true;
|
||||
} else {
|
||||
show_simple_fps = !show_simple_fps;
|
||||
}
|
||||
visibility_toggled = true;
|
||||
}
|
||||
@@ -379,25 +382,13 @@ void L::Draw() {
|
||||
if (!DebugState.ShouldPauseInSubmit()) {
|
||||
DebugState.RequestFrameDump(dump_frame_count);
|
||||
}
|
||||
} else {
|
||||
if (DebugState.IsGuestThreadsPaused()) {
|
||||
DebugState.ResumeGuestThreads();
|
||||
SDL_Log("Game resumed from Keyboard");
|
||||
show_pause_status = false;
|
||||
} else {
|
||||
DebugState.PauseGuestThreads();
|
||||
SDL_Log("Game paused from Keyboard");
|
||||
show_pause_status = true;
|
||||
}
|
||||
visibility_toggled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (show_pause_status) {
|
||||
if (DebugState.IsGuestThreadsPaused()) {
|
||||
ImVec2 pos = ImVec2(10, 10);
|
||||
ImU32 color = IM_COL32(255, 255, 255, 255);
|
||||
|
||||
ImGui::GetForegroundDrawList()->AddText(pos, color, "Game Paused Press F9 to Resume");
|
||||
ImGui::GetForegroundDrawList()->AddText(pos, color, "Emulation Paused");
|
||||
}
|
||||
|
||||
if (show_simple_fps) {
|
||||
@@ -436,5 +427,56 @@ void L::Draw() {
|
||||
PopFont();
|
||||
}
|
||||
|
||||
if (show_quit_window) {
|
||||
ImVec2 center = ImGui::GetMainViewport()->GetCenter();
|
||||
ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
|
||||
|
||||
if (Begin("Quit Notification", nullptr,
|
||||
ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoDecoration |
|
||||
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDocking)) {
|
||||
SetWindowFontScale(1.5f);
|
||||
TextCentered("Are you sure you want to quit?");
|
||||
NewLine();
|
||||
Text("Press Escape or Circle/B button to cancel");
|
||||
Text("Press Enter or Cross/A button to quit");
|
||||
|
||||
if (IsKeyPressed(ImGuiKey_Escape, false) ||
|
||||
(IsKeyPressed(ImGuiKey_GamepadFaceRight, false))) {
|
||||
show_quit_window = false;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(ImGuiKey_Enter, false) ||
|
||||
(IsKeyPressed(ImGuiKey_GamepadFaceDown, false))) {
|
||||
SDL_Event event;
|
||||
SDL_memset(&event, 0, sizeof(event));
|
||||
event.type = SDL_EVENT_QUIT;
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
End();
|
||||
}
|
||||
|
||||
PopID();
|
||||
}
|
||||
|
||||
void L::TextCentered(const std::string& text) {
|
||||
float window_width = ImGui::GetWindowSize().x;
|
||||
float text_width = ImGui::CalcTextSize(text.c_str()).x;
|
||||
float text_indentation = (window_width - text_width) * 0.5f;
|
||||
|
||||
ImGui::SameLine(text_indentation);
|
||||
ImGui::Text("%s", text.c_str());
|
||||
}
|
||||
|
||||
namespace Overlay {
|
||||
|
||||
void ToggleSimpleFps() {
|
||||
show_simple_fps = !show_simple_fps;
|
||||
visibility_toggled = true;
|
||||
}
|
||||
|
||||
void ToggleQuitWindow() {
|
||||
show_quit_window = !show_quit_window;
|
||||
}
|
||||
|
||||
} // namespace Overlay
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
#include "imgui/imgui_layer.h"
|
||||
|
||||
@@ -19,7 +20,14 @@ public:
|
||||
static void SetupSettings();
|
||||
|
||||
void Draw() override;
|
||||
bool show_pause_status = false;
|
||||
void TextCentered(const std::string& text);
|
||||
};
|
||||
|
||||
} // namespace Core::Devtools
|
||||
|
||||
namespace Overlay {
|
||||
|
||||
void ToggleSimpleFps();
|
||||
void ToggleQuitWindow();
|
||||
|
||||
} // namespace Overlay
|
||||
|
||||
@@ -30,26 +30,12 @@ void LoadOptionsConfig(const char* line) {
|
||||
Options.frame_dump_render_on_collapse = i != 0;
|
||||
return;
|
||||
}
|
||||
if (sscanf(line, "fsr_enabled=%d", &i) == 1) {
|
||||
presenter->GetFsrSettingsRef().enable = i != 0;
|
||||
return;
|
||||
}
|
||||
if (sscanf(line, "fsr_rcas_enabled=%d", &i) == 1) {
|
||||
presenter->GetFsrSettingsRef().use_rcas = i != 0;
|
||||
return;
|
||||
}
|
||||
if (sscanf(line, "fsr_rcas_attenuation=%f", &f) == 1) {
|
||||
presenter->GetFsrSettingsRef().rcas_attenuation = f;
|
||||
}
|
||||
}
|
||||
|
||||
void SerializeOptionsConfig(ImGuiTextBuffer* buf) {
|
||||
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("fsr_enabled=%d\n", presenter->GetFsrSettingsRef().enable);
|
||||
buf->appendf("fsr_rcas_enabled=%d\n", presenter->GetFsrSettingsRef().use_rcas);
|
||||
buf->appendf("fsr_rcas_attenuation=%f\n", presenter->GetFsrSettingsRef().rcas_attenuation);
|
||||
}
|
||||
|
||||
} // namespace Core::Devtools
|
||||
|
||||
@@ -65,7 +65,7 @@ static HdrType GetNext(HdrType this_pm4, uint32_t n) {
|
||||
}
|
||||
|
||||
void ParsePolygonControl(u32 value, bool begin_table) {
|
||||
auto const reg = reinterpret_cast<AmdGpu::Liverpool::PolygonControl const&>(value);
|
||||
auto const reg = reinterpret_cast<AmdGpu::PolygonControl const&>(value);
|
||||
|
||||
if (!begin_table ||
|
||||
BeginTable("PA_SU_SC_MODE_CNTL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||
@@ -73,80 +73,80 @@ void ParsePolygonControl(u32 value, bool begin_table) {
|
||||
TableSetColumnIndex(0);
|
||||
Text("CULL_FRONT");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.cull_front.Value());
|
||||
Text("%X", reg.cull_front);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("CULL_BACK");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.cull_back.Value());
|
||||
Text("%X", reg.cull_back);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("FACE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%s", enum_name(reg.front_face.Value()).data());
|
||||
Text("%s", enum_name(reg.front_face).data());
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("POLY_MODE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.enable_polygon_mode.Value());
|
||||
Text("%X", reg.enable_polygon_mode);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("POLYMODE_FRONT_PTYPE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%s", enum_name(reg.polygon_mode_front.Value()).data());
|
||||
Text("%s", enum_name(reg.polygon_mode_front).data());
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("POLYMODE_BACK_PTYPE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%s", enum_name(reg.polygon_mode_back.Value()).data());
|
||||
Text("%s", enum_name(reg.polygon_mode_back).data());
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("POLY_OFFSET_FRONT_ENABLE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.enable_polygon_offset_front.Value());
|
||||
Text("%X", reg.enable_polygon_offset_front);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("POLY_OFFSET_BACK_ENABLE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.enable_polygon_offset_back.Value());
|
||||
Text("%X", reg.enable_polygon_offset_back);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("POLY_OFFSET_PARA_ENABLE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.enable_polygon_offset_para.Value());
|
||||
Text("%X", reg.enable_polygon_offset_para);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("VTX_WINDOW_OFFSET_ENABLE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.enable_window_offset.Value());
|
||||
Text("%X", reg.enable_window_offset);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("PROVOKING_VTX_LAST");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X (%s)", (u32)reg.provoking_vtx_last.Value(),
|
||||
enum_name(reg.provoking_vtx_last.Value()).data());
|
||||
Text("%X (%s)", static_cast<u32>(reg.provoking_vtx_last),
|
||||
enum_name(reg.provoking_vtx_last).data());
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("PERSP_CORR_DIS");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.persp_corr_dis.Value());
|
||||
Text("%X", reg.persp_corr_dis);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("MULTI_PRIM_IB_ENA");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.multi_prim_ib_ena.Value());
|
||||
Text("%X", reg.multi_prim_ib_ena);
|
||||
|
||||
if (begin_table) {
|
||||
EndTable();
|
||||
@@ -155,7 +155,7 @@ void ParsePolygonControl(u32 value, bool begin_table) {
|
||||
}
|
||||
|
||||
void ParseAaConfig(u32 value, bool begin_table) {
|
||||
auto const reg = reinterpret_cast<Liverpool::AaConfig const&>(value);
|
||||
auto const reg = reinterpret_cast<AmdGpu::AaConfig const&>(value);
|
||||
|
||||
if (!begin_table ||
|
||||
BeginTable("PA_SC_AA_CONFIG", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||
@@ -163,31 +163,31 @@ void ParseAaConfig(u32 value, bool begin_table) {
|
||||
TableSetColumnIndex(0);
|
||||
Text("MSAA_NUM_SAMPLES");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.msaa_num_samples.Value());
|
||||
Text("%X", reg.msaa_num_samples);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("AA_MASK_CENTROID_DTMN");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.aa_mask_centroid_dtmn.Value());
|
||||
Text("%X", reg.aa_mask_centroid_dtmn);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("MAX_SAMPLE_DIST");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.max_sample_dst.Value());
|
||||
Text("%X", reg.max_sample_dst);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("MSAA_EXPOSED_SAMPLES");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.msaa_exposed_samples.Value());
|
||||
Text("%X", reg.msaa_exposed_samples);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("DETAIL_TO_EXPOSED_MODE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.detail_to_exposed_mode.Value());
|
||||
Text("%X", reg.detail_to_exposed_mode);
|
||||
|
||||
if (begin_table) {
|
||||
EndTable();
|
||||
@@ -196,7 +196,7 @@ void ParseAaConfig(u32 value, bool begin_table) {
|
||||
}
|
||||
|
||||
void ParseViewportControl(u32 value, bool begin_table) {
|
||||
auto const reg = reinterpret_cast<Liverpool::ViewportControl const&>(value);
|
||||
auto const reg = reinterpret_cast<AmdGpu::ViewportControl const&>(value);
|
||||
|
||||
if (!begin_table ||
|
||||
BeginTable("PA_CL_VTE_CNTL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||
@@ -204,61 +204,61 @@ void ParseViewportControl(u32 value, bool begin_table) {
|
||||
TableSetColumnIndex(0);
|
||||
Text("VPORT_X_SCALE_ENA");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.xscale_enable.Value());
|
||||
Text("%X", reg.xscale_enable);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("VPORT_X_OFFSET_ENA");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.yoffset_enable.Value());
|
||||
Text("%X", reg.yoffset_enable);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("VPORT_Y_SCALE_ENA");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.yscale_enable.Value());
|
||||
Text("%X", reg.yscale_enable);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("VPORT_Y_OFFSET_ENA");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.yoffset_enable.Value());
|
||||
Text("%X", reg.yoffset_enable);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("VPORT_Z_SCALE_ENA");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.zscale_enable.Value());
|
||||
Text("%X", reg.zscale_enable);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("VPORT_Z_OFFSET_ENA");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.zoffset_enable.Value());
|
||||
Text("%X", reg.zoffset_enable);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("VTX_XY_FMT");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.xy_transformed.Value());
|
||||
Text("%X", reg.xy_transformed);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("VTX_Z_FMT");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.z_transformed.Value());
|
||||
Text("%X", reg.z_transformed);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("VTX_W0_FMT");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.w_transformed.Value());
|
||||
Text("%X", reg.w_transformed);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("PERFCOUNTER_REF");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.perfcounter_ref.Value());
|
||||
Text("%X", reg.perfcounter_ref);
|
||||
|
||||
if (begin_table) {
|
||||
EndTable();
|
||||
@@ -267,7 +267,7 @@ void ParseViewportControl(u32 value, bool begin_table) {
|
||||
}
|
||||
|
||||
void ParseColorControl(u32 value, bool begin_table) {
|
||||
auto const reg = reinterpret_cast<Liverpool::ColorControl const&>(value);
|
||||
auto const reg = reinterpret_cast<AmdGpu::ColorControl const&>(value);
|
||||
|
||||
if (!begin_table ||
|
||||
BeginTable("CB_COLOR_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||
@@ -275,25 +275,25 @@ void ParseColorControl(u32 value, bool begin_table) {
|
||||
TableSetColumnIndex(0);
|
||||
Text("DISABLE_DUAL_QUAD__VI");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.disable_dual_quad.Value());
|
||||
Text("%X", reg.disable_dual_quad);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("DEGAMMA_ENABLE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.degamma_enable.Value());
|
||||
Text("%X", reg.degamma_enable);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("MODE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X (%s)", (u32)reg.mode.Value(), enum_name(reg.mode.Value()).data());
|
||||
Text("%X (%s)", static_cast<u32>(reg.mode), enum_name(reg.mode).data());
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("ROP3");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.rop3.Value());
|
||||
Text("%X", static_cast<u32>(reg.rop3));
|
||||
|
||||
if (begin_table) {
|
||||
EndTable();
|
||||
@@ -302,7 +302,7 @@ void ParseColorControl(u32 value, bool begin_table) {
|
||||
}
|
||||
|
||||
void ParseColor0Info(u32 value, bool begin_table) {
|
||||
auto const reg = reinterpret_cast<Liverpool::ColorBuffer::Color0Info const&>(value);
|
||||
auto const reg = reinterpret_cast<AmdGpu::ColorBuffer::Color0Info const&>(value);
|
||||
|
||||
if (!begin_table ||
|
||||
BeginTable("CB_COLOR_INFO", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||
@@ -310,109 +310,109 @@ void ParseColor0Info(u32 value, bool begin_table) {
|
||||
TableSetColumnIndex(0);
|
||||
Text("ENDIAN");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%s", enum_name(reg.endian.Value()).data());
|
||||
Text("%s", enum_name(reg.endian).data());
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("FORMAT");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%s", enum_name(reg.format.Value()).data());
|
||||
Text("%s", enum_name(AmdGpu::DataFormat(reg.format)).data());
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("LINEAR_GENERAL");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.linear_general.Value());
|
||||
Text("%X", reg.linear_general);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("NUMBER_TYPE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%s", enum_name(reg.number_type.Value()).data());
|
||||
Text("%s", enum_name(AmdGpu::NumberFormat(reg.number_type)).data());
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("COMP_SWAP");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%s", enum_name(reg.comp_swap.Value()).data());
|
||||
Text("%s", enum_name(reg.comp_swap).data());
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("FAST_CLEAR");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.fast_clear.Value());
|
||||
Text("%X", reg.fast_clear);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("COMPRESSION");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.compression.Value());
|
||||
Text("%X", reg.compression);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("BLEND_CLAMP");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.blend_clamp.Value());
|
||||
Text("%X", reg.blend_clamp);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("BLEND_BYPASS");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.blend_bypass.Value());
|
||||
Text("%X", reg.blend_bypass);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("SIMPLE_FLOAT");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.simple_float.Value());
|
||||
Text("%X", reg.simple_float);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("ROUND_MODE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X (%s)", (u32)reg.round_mode.Value(), enum_name(reg.round_mode.Value()).data());
|
||||
Text("%X (%s)", static_cast<u32>(reg.round_mode), enum_name(reg.round_mode).data());
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("CMASK_IS_LINEAR");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.cmask_is_linear.Value());
|
||||
Text("%X", reg.cmask_is_linear);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("BLEND_OPT_DONT_RD_DST");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.blend_opt_dont_rd_dst.Value());
|
||||
Text("%X", reg.blend_opt_dont_rd_dst);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("BLEND_OPT_DISCARD_PIXEL");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.blend_opt_discard_pixel.Value());
|
||||
Text("%X", reg.blend_opt_discard_pixel);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("FMASK_COMPRESSION_DISABLE__CI__VI");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.fmask_compression_disable_ci.Value());
|
||||
Text("%X", reg.fmask_compression_disable_ci);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("FMASK_COMPRESS_1FRAG_ONLY__VI");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.fmask_compress_1frag_only.Value());
|
||||
Text("%X", reg.fmask_compress_1frag_only);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("DCC_ENABLE__VI");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.dcc_enable.Value());
|
||||
Text("%X", reg.dcc_enable);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("CMASK_ADDR_TYPE__VI");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.cmask_addr_type.Value());
|
||||
Text("%X", reg.cmask_addr_type);
|
||||
|
||||
if (begin_table) {
|
||||
EndTable();
|
||||
@@ -421,7 +421,7 @@ void ParseColor0Info(u32 value, bool begin_table) {
|
||||
}
|
||||
|
||||
void ParseColor0Attrib(u32 value, bool begin_table) {
|
||||
auto const reg = reinterpret_cast<Liverpool::ColorBuffer::Color0Attrib const&>(value);
|
||||
auto const reg = reinterpret_cast<AmdGpu::ColorBuffer::Color0Attrib const&>(value);
|
||||
|
||||
if (!begin_table ||
|
||||
BeginTable("CB_COLOR_ATTRIB", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||
@@ -429,37 +429,37 @@ void ParseColor0Attrib(u32 value, bool begin_table) {
|
||||
TableSetColumnIndex(0);
|
||||
Text("TILE_MODE_INDEX");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%s", enum_name(reg.tile_mode_index.Value()).data());
|
||||
Text("%s", enum_name(reg.tile_mode_index).data());
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("FMASK_TILE_MODE_INDEX");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.fmask_tile_mode_index.Value());
|
||||
Text("%X", reg.fmask_tile_mode_index);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("FMASK_BANK_HEIGHT");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.fmask_bank_height.Value());
|
||||
Text("%X", reg.fmask_bank_height);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("NUM_SAMPLES");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.num_samples_log2.Value());
|
||||
Text("%X", reg.num_samples_log2);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("NUM_FRAGMENTS");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.num_fragments_log2.Value());
|
||||
Text("%X", reg.num_fragments_log2);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("FORCE_DST_ALPHA_1");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.force_dst_alpha_1.Value());
|
||||
Text("%X", reg.force_dst_alpha_1);
|
||||
|
||||
if (begin_table) {
|
||||
EndTable();
|
||||
@@ -468,7 +468,7 @@ void ParseColor0Attrib(u32 value, bool begin_table) {
|
||||
}
|
||||
|
||||
void ParseBlendControl(u32 value, bool begin_table) {
|
||||
auto const reg = reinterpret_cast<Liverpool::BlendControl const&>(value);
|
||||
auto const reg = reinterpret_cast<AmdGpu::BlendControl const&>(value);
|
||||
|
||||
if (!begin_table ||
|
||||
BeginTable("CB_BLEND_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||
@@ -476,59 +476,59 @@ void ParseBlendControl(u32 value, bool begin_table) {
|
||||
TableSetColumnIndex(0);
|
||||
Text("COLOR_SRCBLEND");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X (%s)", (u32)reg.color_src_factor.Value(),
|
||||
enum_name(reg.color_src_factor.Value()).data());
|
||||
Text("%X (%s)", static_cast<u32>(reg.color_src_factor),
|
||||
enum_name(reg.color_src_factor).data());
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("COLOR_COMB_FCN");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X (%s)", (u32)reg.color_func.Value(), enum_name(reg.color_func.Value()).data());
|
||||
Text("%X (%s)", static_cast<u32>(reg.color_func), enum_name(reg.color_func).data());
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("COLOR_DESTBLEND");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X (%s)", (u32)reg.color_dst_factor.Value(),
|
||||
enum_name(reg.color_dst_factor.Value()).data());
|
||||
Text("%X (%s)", static_cast<u32>(reg.color_dst_factor),
|
||||
enum_name(reg.color_dst_factor).data());
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("ALPHA_SRCBLEND");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X (%s)", (u32)reg.alpha_src_factor.Value(),
|
||||
enum_name(reg.alpha_src_factor.Value()).data());
|
||||
Text("%X (%s)", static_cast<u32>(reg.alpha_src_factor),
|
||||
enum_name(reg.alpha_src_factor).data());
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("ALPHA_COMB_FCN");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X (%s)", (u32)reg.alpha_func.Value(), enum_name(reg.alpha_func.Value()).data());
|
||||
Text("%X (%s)", static_cast<u32>(reg.alpha_func), enum_name(reg.alpha_func).data());
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("ALPHA_DESTBLEND");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X (%s)", (u32)reg.alpha_dst_factor.Value(),
|
||||
enum_name(reg.alpha_dst_factor.Value()).data());
|
||||
Text("%X (%s)", static_cast<u32>(reg.alpha_dst_factor),
|
||||
enum_name(reg.alpha_dst_factor).data());
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("SEPARATE_ALPHA_BLEND");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.separate_alpha_blend.Value());
|
||||
Text("%X", reg.separate_alpha_blend);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("ENABLE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.enable.Value());
|
||||
Text("%X", reg.enable);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("DISABLE_ROP3");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.disable_rop3.Value());
|
||||
Text("%X", reg.disable_rop3);
|
||||
|
||||
if (begin_table) {
|
||||
EndTable();
|
||||
@@ -537,7 +537,7 @@ void ParseBlendControl(u32 value, bool begin_table) {
|
||||
}
|
||||
|
||||
void ParseDepthRenderControl(u32 value, bool begin_table) {
|
||||
auto const reg = reinterpret_cast<Liverpool::DepthRenderControl const&>(value);
|
||||
auto const reg = reinterpret_cast<AmdGpu::DepthRenderControl const&>(value);
|
||||
|
||||
if (!begin_table ||
|
||||
BeginTable("DB_RENDER_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||
@@ -545,61 +545,61 @@ void ParseDepthRenderControl(u32 value, bool begin_table) {
|
||||
TableSetColumnIndex(0);
|
||||
Text("DEPTH_CLEAR_ENABLE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.depth_clear_enable.Value());
|
||||
Text("%X", reg.depth_clear_enable);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("STENCIL_CLEAR_ENABLE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.stencil_clear_enable.Value());
|
||||
Text("%X", reg.stencil_clear_enable);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("DEPTH_COPY");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.depth_clear_enable.Value());
|
||||
Text("%X", reg.depth_clear_enable);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("STENCIL_COPY");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.stencil_copy.Value());
|
||||
Text("%X", reg.stencil_copy);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("RESUMMARIZE_ENABLE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.resummarize_enable.Value());
|
||||
Text("%X", reg.resummarize_enable);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("STENCIL_COMPRESS_DISABLE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.stencil_compress_disable.Value());
|
||||
Text("%X", reg.stencil_compress_disable);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("DEPTH_COMPRESS_DISABLE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.depth_compress_disable.Value());
|
||||
Text("%X", reg.depth_compress_disable);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("COPY_CENTROID");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.copy_centroid.Value());
|
||||
Text("%X", reg.copy_centroid);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("COPY_SAMPLE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.copy_sample.Value());
|
||||
Text("%X", reg.copy_sample);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("DECOMPRESS_ENABLE__VI");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.decompress_enable.Value());
|
||||
Text("%X", reg.decompress_enable);
|
||||
|
||||
if (begin_table) {
|
||||
EndTable();
|
||||
@@ -608,7 +608,7 @@ void ParseDepthRenderControl(u32 value, bool begin_table) {
|
||||
}
|
||||
|
||||
void ParseDepthControl(u32 value, bool begin_table) {
|
||||
auto const reg = reinterpret_cast<Liverpool::DepthControl const&>(value);
|
||||
auto const reg = reinterpret_cast<AmdGpu::DepthControl const&>(value);
|
||||
|
||||
if (!begin_table ||
|
||||
BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||
@@ -616,63 +616,63 @@ void ParseDepthControl(u32 value, bool begin_table) {
|
||||
TableSetColumnIndex(0);
|
||||
Text("STENCIL_ENABLE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.stencil_enable.Value());
|
||||
Text("%X", reg.stencil_enable);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("Z_ENABLE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.depth_enable.Value());
|
||||
Text("%X", reg.depth_enable);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("Z_WRITE_ENABLE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.depth_write_enable.Value());
|
||||
Text("%X", reg.depth_write_enable);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("DEPTH_BOUNDS_ENABLE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.depth_bounds_enable.Value());
|
||||
Text("%X", reg.depth_bounds_enable);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("ZFUNC");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X (%s)", (u32)reg.depth_func.Value(), enum_name(reg.depth_func.Value()).data());
|
||||
Text("%X (%s)", static_cast<u32>(reg.depth_func), enum_name(reg.depth_func).data());
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("BACKFACE_ENABLE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.backface_enable.Value());
|
||||
Text("%X", reg.backface_enable);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("STENCILFUNC");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X (%s)", (u32)reg.stencil_ref_func.Value(),
|
||||
enum_name(reg.stencil_ref_func.Value()).data());
|
||||
Text("%X (%s)", static_cast<u32>(reg.stencil_ref_func),
|
||||
enum_name(reg.stencil_ref_func).data());
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("STENCILFUNC_BF");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X (%s)", (u32)reg.stencil_bf_func.Value(),
|
||||
enum_name(reg.stencil_bf_func.Value()).data());
|
||||
Text("%X (%s)", static_cast<u32>(reg.stencil_bf_func),
|
||||
enum_name(reg.stencil_bf_func).data());
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("ENABLE_COLOR_WRITES_ON_DEPTH_FAIL");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.enable_color_writes_on_depth_fail.Value());
|
||||
Text("%X", reg.enable_color_writes_on_depth_fail);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("DISABLE_COLOR_WRITES_ON_DEPTH_PASS");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.disable_color_writes_on_depth_pass.Value());
|
||||
Text("%X", reg.disable_color_writes_on_depth_pass);
|
||||
|
||||
if (begin_table) {
|
||||
EndTable();
|
||||
@@ -681,7 +681,7 @@ void ParseDepthControl(u32 value, bool begin_table) {
|
||||
}
|
||||
|
||||
void ParseEqaa(u32 value, bool begin_table) {
|
||||
auto const reg = reinterpret_cast<Liverpool::Eqaa const&>(value);
|
||||
auto const reg = reinterpret_cast<AmdGpu::Eqaa const&>(value);
|
||||
|
||||
if (!begin_table ||
|
||||
BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||
@@ -689,73 +689,73 @@ void ParseEqaa(u32 value, bool begin_table) {
|
||||
TableSetColumnIndex(0);
|
||||
Text("MAX_ANCHOR_SAMPLES");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.max_anchor_samples.Value());
|
||||
Text("%X", reg.max_anchor_samples);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("PS_ITER_SAMPLES");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.ps_iter_samples.Value());
|
||||
Text("%X", reg.ps_iter_samples);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("MASK_EXPORT_NUM_SAMPLES");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.mask_export_num_samples.Value());
|
||||
Text("%X", reg.mask_export_num_samples);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("ALPHA_TO_MASK_NUM_SAMPLES");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.alpha_to_mask_num_samples.Value());
|
||||
Text("%X", reg.alpha_to_mask_num_samples);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("HIGH_QUALITY_INTERSECTIONS");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.high_quality_intersections.Value());
|
||||
Text("%X", reg.high_quality_intersections);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("INCOHERENT_EQAA_READS");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.incoherent_eqaa_reads.Value());
|
||||
Text("%X", reg.incoherent_eqaa_reads);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("INTERPOLATE_COMP_Z");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.interpolate_comp_z.Value());
|
||||
Text("%X", reg.interpolate_comp_z);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("INTERPOLATE_SRC_Z");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.interpolate_src_z.Value());
|
||||
Text("%X", reg.interpolate_src_z);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("STATIC_ANCHOR_ASSOCIATIONS");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.static_anchor_associations.Value());
|
||||
Text("%X", reg.static_anchor_associations);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("ALPHA_TO_MASK_EQAA_DISABLE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.alpha_to_mask_eqaa_disable.Value());
|
||||
Text("%X", reg.alpha_to_mask_eqaa_disable);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("OVERRASTERIZATION_AMOUNT");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.overrasterization_amount.Value());
|
||||
Text("%X", reg.overrasterization_amount);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("ENABLE_POSTZ_OVERRASTERIZATION");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.enable_postz_overrasterization.Value());
|
||||
Text("%X", reg.enable_postz_overrasterization);
|
||||
|
||||
if (begin_table) {
|
||||
EndTable();
|
||||
@@ -764,7 +764,7 @@ void ParseEqaa(u32 value, bool begin_table) {
|
||||
}
|
||||
|
||||
void ParseZInfo(u32 value, bool begin_table) {
|
||||
auto const reg = reinterpret_cast<Liverpool::DepthBuffer::ZInfo const&>(value);
|
||||
auto const reg = reinterpret_cast<AmdGpu::DepthBuffer::ZInfo const&>(value);
|
||||
|
||||
if (!begin_table ||
|
||||
BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||
@@ -772,61 +772,61 @@ void ParseZInfo(u32 value, bool begin_table) {
|
||||
TableSetColumnIndex(0);
|
||||
Text("FORMAT");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X (%s)", (u32)reg.format.Value(), enum_name(reg.format.Value()).data());
|
||||
Text("%X (%s)", static_cast<u32>(reg.format), enum_name(reg.format).data());
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("NUM_SAMPLES");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.num_samples.Value());
|
||||
Text("%X", reg.num_samples);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("TILE_SPLIT__CI__VI");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.tile_split.Value());
|
||||
Text("%X", reg.tile_split);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("TILE_MODE_INDEX");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.tile_mode_index.Value());
|
||||
Text("%X", static_cast<u32>(reg.tile_mode_index));
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("DECOMPRESS_ON_N_ZPLANES__VI");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.decompress_on_n_zplanes.Value());
|
||||
Text("%X", reg.decompress_on_n_zplanes);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("ALLOW_EXPCLEAR");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.allow_expclear.Value());
|
||||
Text("%X", reg.allow_expclear);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("READ_SIZE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.read_size.Value());
|
||||
Text("%X", reg.read_size);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("TILE_SURFACE_ENABLE");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.tile_surface_en.Value());
|
||||
Text("%X", reg.tile_surface_enable);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("CLEAR_DISALLOWED__VI");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.clear_disallowed.Value());
|
||||
Text("%X", reg.clear_disallowed);
|
||||
|
||||
TableNextRow();
|
||||
TableSetColumnIndex(0);
|
||||
Text("ZRANGE_PRECISION");
|
||||
TableSetColumnIndex(1);
|
||||
Text("%X", reg.zrange_precision.Value());
|
||||
Text("%X", reg.zrange_precision);
|
||||
|
||||
if (begin_table) {
|
||||
EndTable();
|
||||
@@ -1515,4 +1515,4 @@ void CmdListViewer::Draw(bool only_batches_view, CmdListFilter& filter) {
|
||||
PopID();
|
||||
}
|
||||
|
||||
} // namespace Core::Devtools::Widget
|
||||
} // namespace Core::Devtools::Widget
|
||||
|
||||
@@ -5,14 +5,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <imgui.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "common/types.h"
|
||||
#include "imgui_memory_editor.h"
|
||||
#include "reg_view.h"
|
||||
#include "core/devtools/widget/imgui_memory_editor.h"
|
||||
#include "core/devtools/widget/reg_view.h"
|
||||
|
||||
namespace AmdGpu {
|
||||
union PM4Type3Header;
|
||||
|
||||
@@ -118,7 +118,8 @@ void FrameDumpViewer::Draw() {
|
||||
SameLine();
|
||||
BeginDisabled(selected_cmd == -1);
|
||||
if (SmallButton("Dump cmd")) {
|
||||
auto now_time = fmt::localtime(std::time(nullptr));
|
||||
auto time = std::time(nullptr);
|
||||
auto now_time = *std::localtime(&time);
|
||||
const auto fname = fmt::format("{:%F %H-%M-%S} {}_{}_{}.bin", now_time,
|
||||
magic_enum::enum_name(selected_queue_type),
|
||||
selected_submit_num, selected_queue_num2);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "frame_graph.h"
|
||||
@@ -13,7 +13,6 @@ using namespace ImGui;
|
||||
|
||||
namespace Core::Devtools::Widget {
|
||||
|
||||
constexpr float TARGET_FPS = 60.0f;
|
||||
constexpr float BAR_WIDTH_MULT = 1.4f;
|
||||
constexpr float BAR_HEIGHT_MULT = 1.25f;
|
||||
constexpr float FRAME_GRAPH_PADDING_Y = 3.0f;
|
||||
@@ -30,7 +29,7 @@ void FrameGraph::DrawFrameGraph() {
|
||||
return;
|
||||
}
|
||||
|
||||
float target_dt = 1.0f / (TARGET_FPS * (float)Config::vblankDiv());
|
||||
float target_dt = 1.0f / (float)Config::vblankFreq();
|
||||
float cur_pos_x = pos.x + full_width;
|
||||
pos.y += FRAME_GRAPH_PADDING_Y;
|
||||
const float final_pos_y = pos.y + FRAME_GRAPH_HEIGHT;
|
||||
|
||||
@@ -26,7 +26,7 @@ bool MemoryMapViewer::Iterator::DrawLine() {
|
||||
TableNextColumn();
|
||||
Text("%" PRIXPTR, m.base);
|
||||
TableNextColumn();
|
||||
Text("%zX", m.size);
|
||||
Text("%" PRIX64, m.size);
|
||||
TableNextColumn();
|
||||
Text("%s", magic_enum::enum_name(m.type).data());
|
||||
TableNextColumn();
|
||||
@@ -44,19 +44,19 @@ bool MemoryMapViewer::Iterator::DrawLine() {
|
||||
return false;
|
||||
}
|
||||
auto m = dmem.it->second;
|
||||
if (m.is_free) {
|
||||
if (m.dma_type == DMAType::Free) {
|
||||
++dmem.it;
|
||||
return DrawLine();
|
||||
}
|
||||
TableNextColumn();
|
||||
Text("%" PRIXPTR, m.base);
|
||||
TableNextColumn();
|
||||
Text("%zX", m.size);
|
||||
Text("%" PRIX64, 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);
|
||||
Text("%d", m.dma_type == DMAType::Pooled || m.dma_type == DMAType::Committed);
|
||||
++dmem.it;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "common/config.h"
|
||||
#include "common/elf_info.h"
|
||||
#include "common/path_util.h"
|
||||
|
||||
@@ -22,7 +23,7 @@ public:
|
||||
bool open = false;
|
||||
|
||||
static bool IsSystemModule(const std::filesystem::path& path) {
|
||||
const auto sys_modules_path = Common::FS::GetUserPath(Common::FS::PathType::SysModuleDir);
|
||||
const auto sys_modules_path = Config::getSysModulesPath();
|
||||
|
||||
const auto abs_path = std::filesystem::absolute(path).lexically_normal();
|
||||
const auto abs_sys_path = std::filesystem::absolute(sys_modules_path).lexically_normal();
|
||||
|
||||
@@ -16,7 +16,7 @@ using magic_enum::enum_name;
|
||||
|
||||
namespace Core::Devtools::Widget {
|
||||
|
||||
void RegPopup::DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer) {
|
||||
void RegPopup::DrawColorBuffer(const AmdGpu::ColorBuffer& buffer) {
|
||||
if (BeginTable("COLOR_BUFFER", 2, ImGuiTableFlags_Borders)) {
|
||||
TableNextRow();
|
||||
|
||||
@@ -36,7 +36,7 @@ void RegPopup::DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer) {
|
||||
if (TreeNode("Color0Info")) {
|
||||
TableNextRow();
|
||||
TableNextColumn();
|
||||
ParseColor0Info(buffer.info.u32all, false);
|
||||
ParseColor0Info(buffer.info.raw, false);
|
||||
TreePop();
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ void RegPopup::DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer) {
|
||||
if (TreeNode("Color0Attrib")) {
|
||||
TableNextRow();
|
||||
TableNextColumn();
|
||||
ParseColor0Attrib(buffer.attrib.u32all, false);
|
||||
ParseColor0Attrib(buffer.attrib.raw, false);
|
||||
TreePop();
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ void RegPopup::DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer) {
|
||||
"NumSamples()", buffer.NumSamples(),
|
||||
"NumSlices()", buffer.NumSlices(),
|
||||
"GetColorSliceSize()", buffer.GetColorSliceSize(),
|
||||
"GetTilingMode()", buffer.GetTilingMode(),
|
||||
"GetTileMode()", buffer.GetTileMode(),
|
||||
"IsTiled()", buffer.IsTiled(),
|
||||
"NumFormat()", buffer.GetNumberFmt()
|
||||
);
|
||||
@@ -75,9 +75,8 @@ void RegPopup::DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer) {
|
||||
}
|
||||
}
|
||||
|
||||
void RegPopup::DrawDepthBuffer(const DepthBuffer& depth_data) {
|
||||
const auto& [depth_buffer, depth_control] = depth_data;
|
||||
|
||||
void RegPopup::DrawDepthBuffer(const AmdGpu::DepthBuffer& buffer,
|
||||
const AmdGpu::DepthControl control) {
|
||||
SeparatorText("Depth buffer");
|
||||
|
||||
if (BeginTable("DEPTH_BUFFER", 2, ImGuiTableFlags_Borders)) {
|
||||
@@ -85,31 +84,31 @@ void RegPopup::DrawDepthBuffer(const DepthBuffer& depth_data) {
|
||||
|
||||
// clang-format off
|
||||
DrawValueRowList(
|
||||
"Z_INFO.FORMAT", depth_buffer.z_info.format,
|
||||
"Z_INFO.NUM_SAMPLES", depth_buffer.z_info.num_samples,
|
||||
"Z_INFO.TILE_SPLIT", depth_buffer.z_info.tile_split,
|
||||
"Z_INFO.TILE_MODE_INDEX", depth_buffer.z_info.tile_mode_index,
|
||||
"Z_INFO.DECOMPRESS_ON_N_ZPLANES", depth_buffer.z_info.decompress_on_n_zplanes,
|
||||
"Z_INFO.ALLOW_EXPCLEAR", depth_buffer.z_info.allow_expclear,
|
||||
"Z_INFO.READ_SIZE", depth_buffer.z_info.read_size,
|
||||
"Z_INFO.TILE_SURFACE_EN", depth_buffer.z_info.tile_surface_en,
|
||||
"Z_INFO.CLEAR_DISALLOWED", depth_buffer.z_info.clear_disallowed,
|
||||
"Z_INFO.ZRANGE_PRECISION", depth_buffer.z_info.zrange_precision,
|
||||
"STENCIL_INFO.FORMAT", depth_buffer.stencil_info.format,
|
||||
"Z_READ_BASE", depth_buffer.z_read_base,
|
||||
"STENCIL_READ_BASE", depth_buffer.stencil_read_base,
|
||||
"Z_WRITE_BASE", depth_buffer.z_write_base,
|
||||
"STENCIL_WRITE_BASE", depth_buffer.stencil_write_base,
|
||||
"DEPTH_SIZE.PITCH_TILE_MAX", depth_buffer.depth_size.pitch_tile_max,
|
||||
"DEPTH_SIZE.HEIGHT_TILE_MAX", depth_buffer.depth_size.height_tile_max,
|
||||
"DEPTH_SLICE.TILE_MAX", depth_buffer.depth_slice.tile_max,
|
||||
"Pitch()", depth_buffer.Pitch(),
|
||||
"Height()", depth_buffer.Height(),
|
||||
"DepthAddress()", depth_buffer.DepthAddress(),
|
||||
"StencilAddress()", depth_buffer.StencilAddress(),
|
||||
"NumSamples()", depth_buffer.NumSamples(),
|
||||
"NumBits()", depth_buffer.NumBits(),
|
||||
"GetDepthSliceSize()", depth_buffer.GetDepthSliceSize()
|
||||
"Z_INFO.FORMAT", buffer.z_info.format,
|
||||
"Z_INFO.NUM_SAMPLES", buffer.z_info.num_samples,
|
||||
"Z_INFO.TILE_SPLIT", buffer.z_info.tile_split,
|
||||
"Z_INFO.TILE_MODE_INDEX", buffer.z_info.tile_mode_index,
|
||||
"Z_INFO.DECOMPRESS_ON_N_ZPLANES", buffer.z_info.decompress_on_n_zplanes,
|
||||
"Z_INFO.ALLOW_EXPCLEAR", buffer.z_info.allow_expclear,
|
||||
"Z_INFO.READ_SIZE", buffer.z_info.read_size,
|
||||
"Z_INFO.TILE_SURFACE_ENABLE", buffer.z_info.tile_surface_enable,
|
||||
"Z_INFO.CLEAR_DISALLOWED", buffer.z_info.clear_disallowed,
|
||||
"Z_INFO.ZRANGE_PRECISION", buffer.z_info.zrange_precision,
|
||||
"STENCIL_INFO.FORMAT", buffer.stencil_info.format,
|
||||
"Z_READ_BASE", buffer.z_read_base,
|
||||
"STENCIL_READ_BASE", buffer.stencil_read_base,
|
||||
"Z_WRITE_BASE", buffer.z_write_base,
|
||||
"STENCIL_WRITE_BASE", buffer.stencil_write_base,
|
||||
"DEPTH_SIZE.PITCH_TILE_MAX", buffer.depth_size.pitch_tile_max,
|
||||
"DEPTH_SIZE.HEIGHT_TILE_MAX", buffer.depth_size.height_tile_max,
|
||||
"DEPTH_SLICE.TILE_MAX", buffer.depth_slice.tile_max,
|
||||
"Pitch()", buffer.Pitch(),
|
||||
"Height()", buffer.Height(),
|
||||
"DepthAddress()", buffer.DepthAddress(),
|
||||
"StencilAddress()", buffer.StencilAddress(),
|
||||
"NumSamples()", buffer.NumSamples(),
|
||||
"NumBits()", buffer.NumBits(),
|
||||
"GetDepthSliceSize()", buffer.GetDepthSliceSize()
|
||||
);
|
||||
// clang-format on
|
||||
|
||||
@@ -121,16 +120,16 @@ void RegPopup::DrawDepthBuffer(const DepthBuffer& depth_data) {
|
||||
|
||||
// clang-format off
|
||||
DrawValueRowList(
|
||||
"STENCIL_ENABLE", depth_control.stencil_enable,
|
||||
"DEPTH_ENABLE", depth_control.depth_enable,
|
||||
"DEPTH_WRITE_ENABLE", depth_control.depth_write_enable,
|
||||
"DEPTH_BOUNDS_ENABLE", depth_control.depth_bounds_enable,
|
||||
"DEPTH_FUNC", depth_control.depth_func,
|
||||
"BACKFACE_ENABLE", depth_control.backface_enable,
|
||||
"STENCIL_FUNC", depth_control.stencil_ref_func,
|
||||
"STENCIL_FUNC_BF", depth_control.stencil_bf_func,
|
||||
"ENABLE_COLOR_WRITES_ON_DEPTH_FAIL", depth_control.enable_color_writes_on_depth_fail,
|
||||
"DISABLE_COLOR_WRITES_ON_DEPTH_PASS", depth_control.disable_color_writes_on_depth_pass
|
||||
"STENCIL_ENABLE", control.stencil_enable,
|
||||
"DEPTH_ENABLE", control.depth_enable,
|
||||
"DEPTH_WRITE_ENABLE", control.depth_write_enable,
|
||||
"DEPTH_BOUNDS_ENABLE", control.depth_bounds_enable,
|
||||
"DEPTH_FUNC", control.depth_func,
|
||||
"BACKFACE_ENABLE", control.backface_enable,
|
||||
"STENCIL_FUNC", control.stencil_ref_func,
|
||||
"STENCIL_FUNC_BF", control.stencil_bf_func,
|
||||
"ENABLE_COLOR_WRITES_ON_DEPTH_FAIL", control.enable_color_writes_on_depth_fail,
|
||||
"DISABLE_COLOR_WRITES_ON_DEPTH_PASS", control.disable_color_writes_on_depth_pass
|
||||
);
|
||||
// clang-format on
|
||||
|
||||
@@ -143,15 +142,17 @@ RegPopup::RegPopup() {
|
||||
id = unique_id++;
|
||||
}
|
||||
|
||||
void RegPopup::SetData(const std::string& base_title, AmdGpu::Liverpool::ColorBuffer color_buffer,
|
||||
u32 cb_id) {
|
||||
this->data = color_buffer;
|
||||
void RegPopup::SetData(const std::string& base_title, AmdGpu::ColorBuffer color_buffer, u32 cb_id) {
|
||||
this->type = DataType::Color;
|
||||
this->color = color_buffer;
|
||||
this->title = fmt::format("{}/CB #{}", base_title, cb_id);
|
||||
}
|
||||
|
||||
void RegPopup::SetData(const std::string& base_title, AmdGpu::Liverpool::DepthBuffer depth_buffer,
|
||||
AmdGpu::Liverpool::DepthControl depth_control) {
|
||||
this->data = std::make_tuple(depth_buffer, depth_control);
|
||||
void RegPopup::SetData(const std::string& base_title, AmdGpu::DepthBuffer depth_buffer,
|
||||
AmdGpu::DepthControl depth_control) {
|
||||
this->type = DataType::Depth;
|
||||
this->depth.buffer = depth_buffer;
|
||||
this->depth.control = depth_control;
|
||||
this->title = fmt::format("{}/Depth", base_title);
|
||||
}
|
||||
|
||||
@@ -161,10 +162,10 @@ void RegPopup::SetPos(ImVec2 pos, bool auto_resize) {
|
||||
Begin(name, &open, flags);
|
||||
SetWindowPos(pos);
|
||||
if (auto_resize) {
|
||||
if (std::holds_alternative<AmdGpu::Liverpool::ColorBuffer>(data)) {
|
||||
if (type == DataType::Color) {
|
||||
SetWindowSize({365.0f, 520.0f});
|
||||
KeepWindowInside();
|
||||
} else if (std::holds_alternative<DepthBuffer>(data)) {
|
||||
} else if (type == DataType::Depth) {
|
||||
SetWindowSize({404.0f, 543.0f});
|
||||
KeepWindowInside();
|
||||
}
|
||||
@@ -182,10 +183,10 @@ void RegPopup::Draw() {
|
||||
moved = true;
|
||||
}
|
||||
|
||||
if (const auto* buffer = std::get_if<AmdGpu::Liverpool::ColorBuffer>(&data)) {
|
||||
DrawColorBuffer(*buffer);
|
||||
} else if (const auto* depth_data = std::get_if<DepthBuffer>(&data)) {
|
||||
DrawDepthBuffer(*depth_data);
|
||||
if (type == DataType::Color) {
|
||||
DrawColorBuffer(color);
|
||||
} else if (type == DataType::Depth) {
|
||||
DrawDepthBuffer(depth.buffer, depth.control);
|
||||
}
|
||||
}
|
||||
End();
|
||||
|
||||
@@ -3,12 +3,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <variant>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include "common/types.h"
|
||||
#include "video_core/renderer_vulkan/liverpool_to_vk.h"
|
||||
#include "video_core/amdgpu/regs_color.h"
|
||||
#include "video_core/amdgpu/regs_depth.h"
|
||||
|
||||
namespace Core::Devtools::Widget {
|
||||
|
||||
@@ -16,15 +14,24 @@ class RegPopup {
|
||||
int id;
|
||||
ImGuiWindowFlags flags{ImGuiWindowFlags_NoSavedSettings};
|
||||
|
||||
using DepthBuffer = std::tuple<AmdGpu::Liverpool::DepthBuffer, AmdGpu::Liverpool::DepthControl>;
|
||||
|
||||
ImVec2 last_pos;
|
||||
std::variant<AmdGpu::Liverpool::ColorBuffer, DepthBuffer> data;
|
||||
AmdGpu::ColorBuffer color;
|
||||
struct {
|
||||
AmdGpu::DepthBuffer buffer;
|
||||
AmdGpu::DepthControl control;
|
||||
} depth;
|
||||
enum class DataType {
|
||||
None = 0,
|
||||
Color = 1,
|
||||
Depth = 2,
|
||||
};
|
||||
DataType type{};
|
||||
std::string title{};
|
||||
|
||||
static void DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer);
|
||||
static void DrawColorBuffer(const AmdGpu::ColorBuffer& buffer);
|
||||
|
||||
static void DrawDepthBuffer(const DepthBuffer& depth_data);
|
||||
static void DrawDepthBuffer(const AmdGpu::DepthBuffer& buffer,
|
||||
const AmdGpu::DepthControl control);
|
||||
|
||||
public:
|
||||
bool open = false;
|
||||
@@ -32,11 +39,10 @@ public:
|
||||
|
||||
RegPopup();
|
||||
|
||||
void SetData(const std::string& base_title, AmdGpu::Liverpool::ColorBuffer color_buffer,
|
||||
u32 cb_id);
|
||||
void SetData(const std::string& base_title, AmdGpu::ColorBuffer color_buffer, u32 cb_id);
|
||||
|
||||
void SetData(const std::string& base_title, AmdGpu::Liverpool::DepthBuffer depth_buffer,
|
||||
AmdGpu::Liverpool::DepthControl depth_control);
|
||||
void SetData(const std::string& base_title, AmdGpu::DepthBuffer depth_buffer,
|
||||
AmdGpu::DepthControl depth_control);
|
||||
|
||||
void SetPos(ImVec2 pos, bool auto_resize = false);
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Core::Devtools::Widget {
|
||||
|
||||
void RegView::ProcessShader(int shader_id) {
|
||||
std::vector<u32> shader_code;
|
||||
Vulkan::Liverpool::UserData user_data;
|
||||
AmdGpu::UserData user_data;
|
||||
if (data.is_compute) {
|
||||
shader_code = data.cs_data.code;
|
||||
user_data = data.cs_data.cs_program.user_data;
|
||||
@@ -129,7 +129,7 @@ void RegView::DrawGraphicsRegs() {
|
||||
}
|
||||
};
|
||||
|
||||
for (int cb = 0; cb < AmdGpu::Liverpool::NumColorBuffers; ++cb) {
|
||||
for (int cb = 0; cb < AmdGpu::NUM_COLOR_BUFFERS; ++cb) {
|
||||
PushID(cb);
|
||||
|
||||
TableNextRow();
|
||||
@@ -246,8 +246,7 @@ void RegView::SetData(DebugStateType::RegDump _data, const std::string& base_tit
|
||||
default_reg_popup.SetData(title, regs.depth_buffer, regs.depth_control);
|
||||
default_reg_popup.open = true;
|
||||
}
|
||||
} else if (last_selected_cb >= 0 &&
|
||||
last_selected_cb < AmdGpu::Liverpool::NumColorBuffers) {
|
||||
} else if (last_selected_cb >= 0 && last_selected_cb < AmdGpu::NUM_COLOR_BUFFERS) {
|
||||
const auto& buffer = regs.color_buffers[last_selected_cb];
|
||||
const bool has_cb = buffer && regs.color_target_mask.GetMask(last_selected_cb);
|
||||
if (has_cb) {
|
||||
@@ -348,7 +347,7 @@ void RegView::Draw() {
|
||||
} else {
|
||||
shader->hex_view.DrawContents(shader->user_data.data(),
|
||||
shader->user_data.size() *
|
||||
sizeof(Vulkan::Liverpool::UserData::value_type));
|
||||
sizeof(AmdGpu::UserData::value_type));
|
||||
}
|
||||
}
|
||||
End();
|
||||
@@ -392,4 +391,4 @@ void RegView::Draw() {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Core::Devtools::Widget
|
||||
} // namespace Core::Devtools::Widget
|
||||
|
||||
@@ -2,17 +2,18 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/debug_state.h"
|
||||
#include "imgui_memory_editor.h"
|
||||
#include "reg_popup.h"
|
||||
#include "text_editor.h"
|
||||
#include "core/devtools/widget/imgui_memory_editor.h"
|
||||
#include "core/devtools/widget/reg_popup.h"
|
||||
#include "core/devtools/widget/text_editor.h"
|
||||
|
||||
namespace Core::Devtools::Widget {
|
||||
|
||||
struct ShaderCache {
|
||||
MemoryEditor hex_view;
|
||||
TextEditor dis_view;
|
||||
Vulkan::Liverpool::UserData user_data;
|
||||
AmdGpu::UserData user_data;
|
||||
};
|
||||
|
||||
class RegView {
|
||||
@@ -54,4 +55,4 @@ public:
|
||||
void Draw();
|
||||
};
|
||||
|
||||
} // namespace Core::Devtools::Widget
|
||||
} // namespace Core::Devtools::Widget
|
||||
|
||||
@@ -65,7 +65,7 @@ bool TRP::Extract(const std::filesystem::path& trophyPath, const std::string tit
|
||||
|
||||
const auto user_key_str = Config::getTrophyKey();
|
||||
if (user_key_str.size() != 32) {
|
||||
LOG_CRITICAL(Common_Filesystem, "Trophy decryption key is not specified");
|
||||
LOG_INFO(Common_Filesystem, "Trophy decryption key is not specified");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ bool TRP::Extract(const std::filesystem::path& trophyPath, const std::string tit
|
||||
TrpEntry entry;
|
||||
file.Read(entry);
|
||||
std::string_view name(entry.entry_name);
|
||||
if (entry.flag == 0 && name.find("TROP") != std::string::npos) { // PNG
|
||||
if (entry.flag == 0) { // PNG
|
||||
if (!file.Seek(entry.entry_pos)) {
|
||||
LOG_CRITICAL(Common_Filesystem, "Failed to seek to TRP entry offset");
|
||||
return false;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "base_device.h"
|
||||
#include "core/file_sys/devices/base_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 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"
|
||||
#include "core/libraries/kernel/orbis_error.h"
|
||||
|
||||
namespace Libraries::Kernel {
|
||||
struct OrbisKernelStat;
|
||||
struct SceKernelIovec;
|
||||
struct OrbisKernelIovec;
|
||||
} // namespace Libraries::Kernel
|
||||
|
||||
namespace Core::Devices {
|
||||
@@ -20,27 +20,27 @@ public:
|
||||
|
||||
virtual ~BaseDevice() = 0;
|
||||
|
||||
virtual int ioctl(u64 cmd, Common::VaCtx* args) {
|
||||
virtual s32 ioctl(u64 cmd, Common::VaCtx* args) {
|
||||
return ORBIS_KERNEL_ERROR_ENOTTY;
|
||||
}
|
||||
|
||||
virtual s64 write(const void* buf, size_t nbytes) {
|
||||
virtual s64 write(const void* buf, u64 nbytes) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
|
||||
virtual s64 readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
|
||||
virtual s64 writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) {
|
||||
virtual s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual size_t pwritev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) {
|
||||
virtual s64 pwritev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
@@ -48,11 +48,11 @@ public:
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual s64 read(void* buf, size_t nbytes) {
|
||||
virtual s64 read(void* buf, u64 nbytes) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual int fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
||||
virtual s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
@@ -60,15 +60,15 @@ public:
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual int ftruncate(s64 length) {
|
||||
virtual s32 ftruncate(s64 length) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual int getdents(void* buf, u32 nbytes, s64* basep) {
|
||||
virtual s64 getdents(void* buf, u32 nbytes, s64* basep) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual s64 pwrite(const void* buf, size_t nbytes, u64 offset) {
|
||||
virtual s64 pwrite(const void* buf, u64 nbytes, s64 offset) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
};
|
||||
73
src/core/file_sys/devices/console_device.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/file_sys/devices/console_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
std::shared_ptr<BaseDevice> ConsoleDevice::Create(u32 handle, const char*, s32, u16) {
|
||||
return std::static_pointer_cast<BaseDevice>(std::make_shared<ConsoleDevice>(handle));
|
||||
}
|
||||
|
||||
s32 ConsoleDevice::ioctl(u64 cmd, Common::VaCtx* args) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called, cmd = {:#x}", cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 ConsoleDevice::write(const void* buf, u64 nbytes) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 ConsoleDevice::writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 ConsoleDevice::readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 ConsoleDevice::preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 ConsoleDevice::lseek(s64 offset, s32 whence) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 ConsoleDevice::read(void* buf, u64 nbytes) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 ConsoleDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 ConsoleDevice::fsync() {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 ConsoleDevice::ftruncate(s64 length) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 ConsoleDevice::getdents(void* buf, u32 nbytes, s64* basep) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 ConsoleDevice::pwrite(const void* buf, u64 nbytes, s64 offset) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace Core::Devices
|
||||
33
src/core/file_sys/devices/console_device.h
Normal file
@@ -0,0 +1,33 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "core/file_sys/devices/base_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
class ConsoleDevice final : public BaseDevice {
|
||||
u32 handle;
|
||||
|
||||
public:
|
||||
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, s32, u16);
|
||||
explicit ConsoleDevice(u32 handle) : handle(handle) {}
|
||||
|
||||
~ConsoleDevice() override = default;
|
||||
|
||||
s32 ioctl(u64 cmd, Common::VaCtx* args) override;
|
||||
s64 write(const void* buf, u64 nbytes) override;
|
||||
s64 readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||
s64 writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||
s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) override;
|
||||
s64 lseek(s64 offset, s32 whence) override;
|
||||
s64 read(void* buf, u64 nbytes) override;
|
||||
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
|
||||
s32 fsync() override;
|
||||
s32 ftruncate(s64 length) override;
|
||||
s64 getdents(void* buf, u32 nbytes, s64* basep) override;
|
||||
s64 pwrite(const void* buf, u64 nbytes, s64 offset) override;
|
||||
};
|
||||
|
||||
} // namespace Core::Devices
|
||||
73
src/core/file_sys/devices/deci_tty6_device.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/file_sys/devices/deci_tty6_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
std::shared_ptr<BaseDevice> DeciTty6Device::Create(u32 handle, const char*, s32, u16) {
|
||||
return std::static_pointer_cast<BaseDevice>(std::make_shared<DeciTty6Device>(handle));
|
||||
}
|
||||
|
||||
s32 DeciTty6Device::ioctl(u64 cmd, Common::VaCtx* args) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called, cmd = {:#x}", cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 DeciTty6Device::write(const void* buf, u64 nbytes) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 DeciTty6Device::writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 DeciTty6Device::readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 DeciTty6Device::preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 DeciTty6Device::lseek(s64 offset, s32 whence) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 DeciTty6Device::read(void* buf, u64 nbytes) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 DeciTty6Device::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 DeciTty6Device::fsync() {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 DeciTty6Device::ftruncate(s64 length) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 DeciTty6Device::getdents(void* buf, u32 nbytes, s64* basep) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 DeciTty6Device::pwrite(const void* buf, u64 nbytes, s64 offset) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace Core::Devices
|
||||
33
src/core/file_sys/devices/deci_tty6_device.h
Normal file
@@ -0,0 +1,33 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "core/file_sys/devices/base_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
class DeciTty6Device final : public BaseDevice {
|
||||
u32 handle;
|
||||
|
||||
public:
|
||||
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, s32, u16);
|
||||
explicit DeciTty6Device(u32 handle) : handle(handle) {}
|
||||
|
||||
~DeciTty6Device() override = default;
|
||||
|
||||
s32 ioctl(u64 cmd, Common::VaCtx* args) override;
|
||||
s64 write(const void* buf, u64 nbytes) override;
|
||||
s64 readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||
s64 writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||
s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) override;
|
||||
s64 lseek(s64 offset, s32 whence) override;
|
||||
s64 read(void* buf, u64 nbytes) override;
|
||||
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
|
||||
s32 fsync() override;
|
||||
s32 ftruncate(s64 length) override;
|
||||
s64 getdents(void* buf, u32 nbytes, s64* basep) override;
|
||||
s64 pwrite(const void* buf, u64 nbytes, s64 offset) override;
|
||||
};
|
||||
|
||||
} // namespace Core::Devices
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
@@ -1,9 +1,9 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/file_sys/devices/logger.h"
|
||||
#include "core/libraries/kernel/file_system.h"
|
||||
#include "logger.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
@@ -11,13 +11,13 @@ Logger::Logger(std::string prefix, bool is_err) : prefix(std::move(prefix)), is_
|
||||
|
||||
Logger::~Logger() = default;
|
||||
|
||||
s64 Logger::write(const void* buf, size_t nbytes) {
|
||||
s64 Logger::write(const void* buf, u64 nbytes) {
|
||||
log(static_cast<const char*>(buf), nbytes);
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
size_t Logger::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
|
||||
size_t total_written = 0;
|
||||
s64 Logger::writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||
u64 total_written = 0;
|
||||
for (int i = 0; i < iovcnt; i++) {
|
||||
log(static_cast<const char*>(iov[i].iov_base), iov[i].iov_len);
|
||||
total_written += iov[i].iov_len;
|
||||
@@ -25,7 +25,7 @@ size_t Logger::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt)
|
||||
return total_written;
|
||||
}
|
||||
|
||||
s64 Logger::pwrite(const void* buf, size_t nbytes, u64 offset) {
|
||||
s64 Logger::pwrite(const void* buf, u64 nbytes, s64 offset) {
|
||||
log(static_cast<const char*>(buf), nbytes);
|
||||
return nbytes;
|
||||
}
|
||||
@@ -35,7 +35,7 @@ s32 Logger::fsync() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Logger::log(const char* buf, size_t nbytes) {
|
||||
void Logger::log(const char* buf, u64 nbytes) {
|
||||
std::scoped_lock lock{mtx};
|
||||
const char* end = buf + nbytes;
|
||||
for (const char* it = buf; it < end; ++it) {
|
||||
@@ -1,9 +1,9 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base_device.h"
|
||||
#include "core/file_sys/devices/base_device.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
@@ -23,14 +23,14 @@ public:
|
||||
|
||||
~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;
|
||||
s64 write(const void* buf, u64 nbytes) override;
|
||||
s64 writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||
s64 pwrite(const void* buf, u64 nbytes, s64 offset) override;
|
||||
|
||||
s32 fsync() override;
|
||||
|
||||
private:
|
||||
void log(const char* buf, size_t nbytes);
|
||||
void log(const char* buf, u64 nbytes);
|
||||
void log_flush();
|
||||
};
|
||||
|
||||
66
src/core/file_sys/devices/nop_device.h
Normal file
@@ -0,0 +1,66 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
#include "core/file_sys/devices/base_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
class NopDevice final : BaseDevice {
|
||||
u32 handle;
|
||||
|
||||
public:
|
||||
explicit NopDevice(u32 handle) : handle(handle) {}
|
||||
|
||||
~NopDevice() override = default;
|
||||
|
||||
s32 ioctl(u64 cmd, Common::VaCtx* args) override {
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 write(const void* buf, u64 nbytes) override {
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override {
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override {
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) override {
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 lseek(s64 offset, s32 whence) override {
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 read(void* buf, u64 nbytes) override {
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override {
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 fsync() override {
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 ftruncate(s64 length) override {
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 getdents(void* buf, u32 nbytes, s64* basep) override {
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 pwrite(const void* buf, u64 nbytes, s64 offset) override {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Core::Devices
|
||||
79
src/core/file_sys/devices/random_device.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include "common/logging/log.h"
|
||||
#include "core/file_sys/devices/random_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
std::shared_ptr<BaseDevice> RandomDevice::Create(u32 handle, const char*, s32, u16) {
|
||||
std::srand(std::time(nullptr));
|
||||
return std::static_pointer_cast<BaseDevice>(std::make_shared<RandomDevice>(handle));
|
||||
}
|
||||
|
||||
s32 RandomDevice::ioctl(u64 cmd, Common::VaCtx* args) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called, cmd = {:#x}", cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 RandomDevice::write(const void* buf, u64 nbytes) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 RandomDevice::writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 RandomDevice::readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 RandomDevice::preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 RandomDevice::lseek(s64 offset, s32 whence) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 RandomDevice::read(void* buf, u64 nbytes) {
|
||||
auto rbuf = static_cast<s8*>(buf);
|
||||
for (u64 i = 0; i < nbytes; i++) {
|
||||
rbuf[i] = std::rand() & 0xFF;
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
s32 RandomDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 RandomDevice::fsync() {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 RandomDevice::ftruncate(s64 length) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 RandomDevice::getdents(void* buf, u32 nbytes, s64* basep) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 RandomDevice::pwrite(const void* buf, u64 nbytes, s64 offset) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace Core::Devices
|
||||
33
src/core/file_sys/devices/random_device.h
Normal file
@@ -0,0 +1,33 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "core/file_sys/devices/base_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
class RandomDevice final : public BaseDevice {
|
||||
u32 handle;
|
||||
|
||||
public:
|
||||
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, s32, u16);
|
||||
explicit RandomDevice(u32 handle) : handle(handle) {}
|
||||
|
||||
~RandomDevice() override = default;
|
||||
|
||||
s32 ioctl(u64 cmd, Common::VaCtx* args) override;
|
||||
s64 write(const void* buf, u64 nbytes) override;
|
||||
s64 readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||
s64 writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||
s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) override;
|
||||
s64 lseek(s64 offset, s32 whence) override;
|
||||
s64 read(void* buf, u64 nbytes) override;
|
||||
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
|
||||
s32 fsync() override;
|
||||
s32 ftruncate(s64 length) override;
|
||||
s64 getdents(void* buf, u32 nbytes, s64* basep) override;
|
||||
s64 pwrite(const void* buf, u64 nbytes, s64 offset) override;
|
||||
};
|
||||
|
||||
} // namespace Core::Devices
|
||||
87
src/core/file_sys/devices/rng_device.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include "common/logging/log.h"
|
||||
#include "core/file_sys/devices/rng_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
std::shared_ptr<BaseDevice> RngDevice::Create(u32 handle, const char*, s32, u16) {
|
||||
std::srand(std::time(nullptr));
|
||||
return std::static_pointer_cast<BaseDevice>(std::make_shared<RngDevice>(handle));
|
||||
}
|
||||
|
||||
s32 RngDevice::ioctl(u64 cmd, Common::VaCtx* args) {
|
||||
LOG_INFO(Kernel_Pthread, "called, cmd = {:#x}", cmd);
|
||||
// Both commands are for generating a random number
|
||||
if (cmd == 0x40445301 || cmd == 0x40445302) {
|
||||
auto& data = *vaArgPtr<GetRandomArgs>(&args->va_list);
|
||||
data.result = 0;
|
||||
for (u64 i = 0; i < 64; i++) {
|
||||
data.buf[i] = std::rand();
|
||||
}
|
||||
} else {
|
||||
// ENOIOCTL
|
||||
return -3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 RngDevice::write(const void* buf, u64 nbytes) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 RngDevice::writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 RngDevice::readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 RngDevice::preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 RngDevice::lseek(s64 offset, s32 whence) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 RngDevice::read(void* buf, u64 nbytes) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 RngDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 RngDevice::fsync() {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 RngDevice::ftruncate(s64 length) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 RngDevice::getdents(void* buf, u32 nbytes, s64* basep) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 RngDevice::pwrite(const void* buf, u64 nbytes, s64 offset) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace Core::Devices
|
||||
39
src/core/file_sys/devices/rng_device.h
Normal file
@@ -0,0 +1,39 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "core/file_sys/devices/base_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
class RngDevice final : public BaseDevice {
|
||||
u32 handle;
|
||||
|
||||
public:
|
||||
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, s32, u16);
|
||||
explicit RngDevice(u32 handle) : handle(handle) {}
|
||||
|
||||
~RngDevice() override = default;
|
||||
|
||||
s32 ioctl(u64 cmd, Common::VaCtx* args) override;
|
||||
s64 write(const void* buf, u64 nbytes) override;
|
||||
s64 readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||
s64 writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||
s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) override;
|
||||
s64 lseek(s64 offset, s32 whence) override;
|
||||
s64 read(void* buf, u64 nbytes) override;
|
||||
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
|
||||
s32 fsync() override;
|
||||
s32 ftruncate(s64 length) override;
|
||||
s64 getdents(void* buf, u32 nbytes, s64* basep) override;
|
||||
s64 pwrite(const void* buf, u64 nbytes, s64 offset) override;
|
||||
|
||||
private:
|
||||
struct GetRandomArgs {
|
||||
s32 result;
|
||||
s8 buf[64];
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace Core::Devices
|
||||
79
src/core/file_sys/devices/srandom_device.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include "common/logging/log.h"
|
||||
#include "core/file_sys/devices/srandom_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
std::shared_ptr<BaseDevice> SRandomDevice::Create(u32 handle, const char*, s32, u16) {
|
||||
std::srand(std::time(nullptr));
|
||||
return std::static_pointer_cast<BaseDevice>(std::make_shared<SRandomDevice>(handle));
|
||||
}
|
||||
|
||||
s32 SRandomDevice::ioctl(u64 cmd, Common::VaCtx* args) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called, cmd = {:#x}", cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 SRandomDevice::write(const void* buf, u64 nbytes) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 SRandomDevice::writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 SRandomDevice::readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 SRandomDevice::preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 SRandomDevice::lseek(s64 offset, s32 whence) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 SRandomDevice::read(void* buf, u64 nbytes) {
|
||||
auto rbuf = static_cast<s8*>(buf);
|
||||
for (u64 i = 0; i < nbytes; i++) {
|
||||
rbuf[i] = std::rand();
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
s32 SRandomDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 SRandomDevice::fsync() {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 SRandomDevice::ftruncate(s64 length) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 SRandomDevice::getdents(void* buf, u32 nbytes, s64* basep) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 SRandomDevice::pwrite(const void* buf, u64 nbytes, s64 offset) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace Core::Devices
|
||||
33
src/core/file_sys/devices/srandom_device.h
Normal file
@@ -0,0 +1,33 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "core/file_sys/devices/base_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
class SRandomDevice final : public BaseDevice {
|
||||
u32 handle;
|
||||
|
||||
public:
|
||||
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, s32, u16);
|
||||
explicit SRandomDevice(u32 handle) : handle(handle) {}
|
||||
|
||||
~SRandomDevice() override = default;
|
||||
|
||||
s32 ioctl(u64 cmd, Common::VaCtx* args) override;
|
||||
s64 write(const void* buf, u64 nbytes) override;
|
||||
s64 readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||
s64 writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||
s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) override;
|
||||
s64 lseek(s64 offset, s32 whence) override;
|
||||
s64 read(void* buf, u64 nbytes) override;
|
||||
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
|
||||
s32 fsync() override;
|
||||
s32 ftruncate(s64 length) override;
|
||||
s64 getdents(void* buf, u32 nbytes, s64* basep) override;
|
||||
s64 pwrite(const void* buf, u64 nbytes, s64 offset) override;
|
||||
};
|
||||
|
||||
} // namespace Core::Devices
|
||||
79
src/core/file_sys/devices/urandom_device.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include "common/logging/log.h"
|
||||
#include "core/file_sys/devices/urandom_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
std::shared_ptr<BaseDevice> URandomDevice::Create(u32 handle, const char*, s32, u16) {
|
||||
std::srand(std::time(nullptr));
|
||||
return std::static_pointer_cast<BaseDevice>(std::make_shared<URandomDevice>(handle));
|
||||
}
|
||||
|
||||
s32 URandomDevice::ioctl(u64 cmd, Common::VaCtx* args) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called, cmd = {:#x}", cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 URandomDevice::write(const void* buf, u64 nbytes) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 URandomDevice::writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 URandomDevice::readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 URandomDevice::preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 URandomDevice::lseek(s64 offset, s32 whence) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 URandomDevice::read(void* buf, u64 nbytes) {
|
||||
auto rbuf = static_cast<s8*>(buf);
|
||||
for (u64 i = 0; i < nbytes; i++) {
|
||||
rbuf[i] = std::rand() & 0xFF;
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
s32 URandomDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 URandomDevice::fsync() {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 URandomDevice::ftruncate(s64 length) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 URandomDevice::getdents(void* buf, u32 nbytes, s64* basep) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s64 URandomDevice::pwrite(const void* buf, u64 nbytes, s64 offset) {
|
||||
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace Core::Devices
|
||||
33
src/core/file_sys/devices/urandom_device.h
Normal file
@@ -0,0 +1,33 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "core/file_sys/devices/base_device.h"
|
||||
|
||||
namespace Core::Devices {
|
||||
|
||||
class URandomDevice final : public BaseDevice {
|
||||
u32 handle;
|
||||
|
||||
public:
|
||||
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, s32, u16);
|
||||
explicit URandomDevice(u32 handle) : handle(handle) {}
|
||||
|
||||
~URandomDevice() override = default;
|
||||
|
||||
s32 ioctl(u64 cmd, Common::VaCtx* args) override;
|
||||
s64 write(const void* buf, u64 nbytes) override;
|
||||
s64 readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||
s64 writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||
s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) override;
|
||||
s64 lseek(s64 offset, s32 whence) override;
|
||||
s64 read(void* buf, u64 nbytes) override;
|
||||
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
|
||||
s32 fsync() override;
|
||||
s32 ftruncate(s64 length) override;
|
||||
s64 getdents(void* buf, u32 nbytes, s64* basep) override;
|
||||
s64 pwrite(const void* buf, u64 nbytes, s64 offset) override;
|
||||
};
|
||||
|
||||
} // namespace Core::Devices
|
||||
15
src/core/file_sys/directories/base_directory.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "common/singleton.h"
|
||||
#include "core/file_sys/directories/base_directory.h"
|
||||
#include "core/file_sys/fs.h"
|
||||
|
||||
namespace Core::Directories {
|
||||
|
||||
BaseDirectory::BaseDirectory() = default;
|
||||
|
||||
BaseDirectory::~BaseDirectory() = default;
|
||||
|
||||
} // namespace Core::Directories
|
||||
52
src/core/file_sys/directories/base_directory.h
Normal file
@@ -0,0 +1,52 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include "common/types.h"
|
||||
#include "common/va_ctx.h"
|
||||
#include "core/libraries/kernel/file_system.h"
|
||||
#include "core/libraries/kernel/orbis_error.h"
|
||||
|
||||
namespace Libraries::Kernel {
|
||||
struct OrbisKernelStat;
|
||||
struct OrbisKernelIovec;
|
||||
struct OrbisKernelDirent;
|
||||
} // namespace Libraries::Kernel
|
||||
|
||||
namespace Core::Directories {
|
||||
|
||||
class BaseDirectory {
|
||||
public:
|
||||
explicit BaseDirectory();
|
||||
|
||||
virtual ~BaseDirectory() = 0;
|
||||
|
||||
virtual s64 read(void* buf, u64 nbytes) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual s64 readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual s64 lseek(s64 offset, s32 whence) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual s32 fstat(Libraries::Kernel::OrbisKernelStat* stat) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual s64 getdents(void* buf, u64 nbytes, s64* basep) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Core::Directories
|
||||