Compare commits
587 Commits
v.0.9.0
...
Pre-releas
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e287564ce | ||
|
|
9e7df6ae54 | ||
|
|
de6c5bbb83 | ||
|
|
65f0b07c34 | ||
|
|
2a5910ed51 | ||
|
|
391d30cbb1 | ||
|
|
d3ad728ac0 | ||
|
|
5183cbe686 | ||
|
|
9e80cde60d | ||
|
|
98fd0689ac | ||
|
|
9db4642f66 | ||
|
|
b135a056ba | ||
|
|
dc6013cf0e | ||
|
|
e5ea55e425 | ||
|
|
c3f7a4301c | ||
|
|
a5f9280841 | ||
|
|
cf866ab294 | ||
|
|
052f3260f3 | ||
|
|
78e301c3db | ||
|
|
a9f8eaf778 | ||
|
|
f9ef57f74b | ||
|
|
1394852791 | ||
|
|
6295c32e5c | ||
|
|
14d71a155a | ||
|
|
2577dfde7e | ||
|
|
8123c44ad1 | ||
|
|
f1a8b7d85e | ||
|
|
f6ae5544fd | ||
|
|
4922d526fe | ||
|
|
56109a1331 | ||
|
|
544a22a431 | ||
|
|
6612a32523 | ||
|
|
3f86c2e94a | ||
|
|
5b699090e6 | ||
|
|
aa5c045555 | ||
|
|
ed14359c87 | ||
|
|
6a9f9abda0 | ||
|
|
2f55636626 | ||
|
|
94d0f2e7ed | ||
|
|
f557c6ac64 | ||
|
|
93c340c6e1 | ||
|
|
25344a3b89 | ||
|
|
bbd985fe4b | ||
|
|
ee2bc97248 | ||
|
|
bebfee58d6 | ||
|
|
5ddabda2b8 | ||
|
|
3ce1ac5e86 | ||
|
|
b4628b80e2 | ||
|
|
2f022a462d | ||
|
|
f5505daaca | ||
|
|
8c1ec863da | ||
|
|
604f8d9398 | ||
|
|
19e974bf21 | ||
|
|
7031f5968e | ||
|
|
ff8869262f | ||
|
|
683e5f3b04 | ||
|
|
08fe66a97f | ||
|
|
bc44865cda | ||
|
|
a42ae46553 | ||
|
|
a4c3c665fe | ||
|
|
caccc05fb2 | ||
|
|
8238ecf88a | ||
|
|
8bbb3956a2 | ||
|
|
f466352dde | ||
|
|
430f2e4700 | ||
|
|
6c7c5eb59c | ||
|
|
493cda07c0 | ||
|
|
eda6be746f | ||
|
|
ed9ffbfb64 | ||
|
|
5cabd6ddd8 | ||
|
|
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 | ||
|
|
f56eecea44 | ||
|
|
41b05ce7ed | ||
|
|
a63db68114 | ||
|
|
4f99f304e6 | ||
|
|
a050c9d65b | ||
|
|
b22da77f9a | ||
|
|
df22c4225e | ||
|
|
48460d1cbe | ||
|
|
7431b30005 | ||
|
|
9eae6b57ce | ||
|
|
efa7093f34 | ||
|
|
0594dac405 | ||
|
|
5789fd881c | ||
|
|
1757dfaf5a | ||
|
|
77117abb31 | ||
|
|
64dfccdf26 | ||
|
|
6bf3c44b9c | ||
|
|
434dcde9f3 | ||
|
|
bdd2419de9 | ||
|
|
7f727340aa | ||
|
|
59dd73492b | ||
|
|
83056712e0 | ||
|
|
fa32537f40 | ||
|
|
09b584b23f | ||
|
|
4bfd8b967b | ||
|
|
52bd92b97d | ||
|
|
8e44a7099f | ||
|
|
0a58ead5f6 | ||
|
|
9f37ede336 | ||
|
|
a49b13fe66 | ||
|
|
6eaec7a004 | ||
|
|
075d6425e2 | ||
|
|
70e4f81655 | ||
|
|
12198f9255 | ||
|
|
4bfa8c9fc7 | ||
|
|
669b19c2f3 | ||
|
|
d9dac05db2 | ||
|
|
802124309d | ||
|
|
5b5096e9ea | ||
|
|
54163ffaa5 | ||
|
|
2d335f436c | ||
|
|
1fc95bf44b | ||
|
|
0bb1ee167f | ||
|
|
a62027d4c2 | ||
|
|
8dcd9cc0f9 | ||
|
|
7b0249d9ca | ||
|
|
551751df3c | ||
|
|
be12305f65 | ||
|
|
e214ca6884 | ||
|
|
43321fb45a | ||
|
|
423254692a | ||
|
|
612f340292 | ||
|
|
6d65ea7314 | ||
|
|
e389d03601 | ||
|
|
33f46202d2 | ||
|
|
8e06b1b2b0 | ||
|
|
1437c5a1de | ||
|
|
20670186ab | ||
|
|
5bc4cc761a | ||
|
|
efa8f6a154 | ||
|
|
9dd35c3a42 | ||
|
|
21d14abaee | ||
|
|
c27f45c8c0 | ||
|
|
d0e2a40cdc | ||
|
|
e2b8ceb6ba | ||
|
|
213ca72fa1 | ||
|
|
de69f2b40b | ||
|
|
3f40a8d46e | ||
|
|
226058d2e9 | ||
|
|
ae6f7b8d5a | ||
|
|
1a27af6951 | ||
|
|
c35141b33f | ||
|
|
a1d6cd15f4 | ||
|
|
34d0d85c15 | ||
|
|
c71dc740e2 | ||
|
|
69a50fa713 | ||
|
|
34a1ffbcda | ||
|
|
3e0ec9ebef | ||
|
|
2741829545 | ||
|
|
dedf6de2ac | ||
|
|
fc4fd0107d | ||
|
|
ca92e72efe | ||
|
|
b49340dff8 | ||
|
|
9981c8df03 | ||
|
|
e0c930f2d8 | ||
|
|
e2b726382e | ||
|
|
0444e590e0 | ||
|
|
64bbedeb82 | ||
|
|
217d32b502 | ||
|
|
a71bfb30a2 | ||
|
|
046cf50412 | ||
|
|
d7051f15f4 | ||
|
|
12f4a8f073 | ||
|
|
c20d02dd40 | ||
|
|
ae2053c487 | ||
|
|
14b082f5ea | ||
|
|
ce42eccc9d | ||
|
|
8ffcfc87bd | ||
|
|
5004e41100 | ||
|
|
a07a6bb9d3 | ||
|
|
f2bbb6847d | ||
|
|
ce84e80f65 | ||
|
|
952cef5a15 | ||
|
|
2bc199a41b | ||
|
|
5d064dd89f | ||
|
|
2857ef34f0 | ||
|
|
5edd9ff54b | ||
|
|
91d29459fb | ||
|
|
fff3bf9917 | ||
|
|
43bf4ed1bc | ||
|
|
3b3026ff1c | ||
|
|
0e9420a7b2 | ||
|
|
93222c6f9f | ||
|
|
285df1b5be | ||
|
|
d4fbeea085 | ||
|
|
4d1a1ce9c2 | ||
|
|
23710f397e | ||
|
|
88f6cb4d41 | ||
|
|
5b6fc788b3 | ||
|
|
8cdd8dd725 | ||
|
|
c09d1c3cff | ||
|
|
ca0f458505 | ||
|
|
bb3f8af81a | ||
|
|
eed99141b3 | ||
|
|
2c78272185 | ||
|
|
1930a2132c | ||
|
|
6bdd83684b | ||
|
|
b1af1334c9 | ||
|
|
bb199865cf | ||
|
|
c09e463b8e | ||
|
|
4019319d92 | ||
|
|
790b54bf29 | ||
|
|
2091bc5651 | ||
|
|
8fffdc3918 | ||
|
|
6cdc52cdde | ||
|
|
aca8e7e9eb | ||
|
|
eb9f66c349 | ||
|
|
7f0503bf8b | ||
|
|
95f04b746d | ||
|
|
e0309a4b01 | ||
|
|
139a253edc | ||
|
|
99ccf56938 | ||
|
|
149898193f | ||
|
|
10d09ac977 | ||
|
|
e5c6c88835 | ||
|
|
d124f40503 | ||
|
|
e518a7062c | ||
|
|
f9bbde9c79 | ||
|
|
37887e8fde |
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).
|
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.
|
Please make an effort to make sure your issue isn't already reported.
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ body:
|
|||||||
required: true
|
required: true
|
||||||
- label: I have disabled all patches and cheats and the issue is still present.
|
- label: I have disabled all patches and cheats and the issue is still present.
|
||||||
required: true
|
required: true
|
||||||
- label: I have all the required [system modules](https://github.com/shadps4-emu/shadps4-game-compatibility?tab=readme-ov-file#informations) 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
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: desc
|
id: desc
|
||||||
|
|||||||
33
.github/linux-appimage-qt.sh
vendored
@@ -1,33 +0,0 @@
|
|||||||
# SPDX-FileCopyrightText: 2024 shadPS4 Emulator Project
|
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
if [[ -z $GITHUB_WORKSPACE ]]; then
|
|
||||||
GITHUB_WORKSPACE="${PWD%/*}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
export Qt6_DIR="/usr/lib/qt6"
|
|
||||||
export PATH="$Qt6_DIR/bin:$PATH"
|
|
||||||
export EXTRA_QT_PLUGINS="waylandcompositor"
|
|
||||||
export EXTRA_PLATFORM_PLUGINS="libqwayland-egl.so;libqwayland-generic.so"
|
|
||||||
|
|
||||||
# Prepare Tools for building the AppImage
|
|
||||||
wget -q https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
|
|
||||||
wget -q https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage
|
|
||||||
wget -q https://github.com/linuxdeploy/linuxdeploy-plugin-checkrt/releases/download/continuous/linuxdeploy-plugin-checkrt-x86_64.sh
|
|
||||||
|
|
||||||
chmod a+x linuxdeploy-x86_64.AppImage
|
|
||||||
chmod a+x linuxdeploy-plugin-qt-x86_64.AppImage
|
|
||||||
chmod a+x linuxdeploy-plugin-checkrt-x86_64.sh
|
|
||||||
|
|
||||||
# Build AppImage
|
|
||||||
./linuxdeploy-x86_64.AppImage --appdir AppDir
|
|
||||||
./linuxdeploy-plugin-checkrt-x86_64.sh --appdir AppDir
|
|
||||||
|
|
||||||
cp -a "$GITHUB_WORKSPACE/build/translations" AppDir/usr/bin
|
|
||||||
|
|
||||||
./linuxdeploy-x86_64.AppImage --appdir AppDir -d "$GITHUB_WORKSPACE"/dist/net.shadps4.shadPS4.desktop -e "$GITHUB_WORKSPACE"/build/shadps4 -i "$GITHUB_WORKSPACE"/src/images/net.shadps4.shadPS4.svg --plugin qt
|
|
||||||
rm AppDir/usr/plugins/multimedia/libgstreamermediaplugin.so
|
|
||||||
./linuxdeploy-x86_64.AppImage --appdir AppDir --output appimage
|
|
||||||
mv shadPS4-x86_64.AppImage Shadps4-qt.AppImage
|
|
||||||
256
.github/workflows/build.yml
vendored
@@ -17,14 +17,14 @@ jobs:
|
|||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
- uses: fsfe/reuse-action@v5
|
- uses: fsfe/reuse-action@v5
|
||||||
|
|
||||||
clang-format:
|
clang-format:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Install
|
- name: Install
|
||||||
@@ -45,7 +45,7 @@ jobs:
|
|||||||
shorthash: ${{ steps.vars.outputs.shorthash }}
|
shorthash: ${{ steps.vars.outputs.shorthash }}
|
||||||
fullhash: ${{ steps.vars.outputs.fullhash }}
|
fullhash: ${{ steps.vars.outputs.fullhash }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
- name: Get date and git hash
|
- name: Get date and git hash
|
||||||
id: vars
|
id: vars
|
||||||
run: |
|
run: |
|
||||||
@@ -60,7 +60,7 @@ jobs:
|
|||||||
runs-on: windows-2025
|
runs-on: windows-2025
|
||||||
needs: get-info
|
needs: get-info
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
@@ -76,18 +76,13 @@ jobs:
|
|||||||
${{ env.cache-name }}-
|
${{ env.cache-name }}-
|
||||||
|
|
||||||
- name: Cache CMake Build
|
- name: Cache CMake Build
|
||||||
uses: hendrikmuhs/ccache-action@v1.2.17
|
uses: hendrikmuhs/ccache-action@v1.2.19
|
||||||
env:
|
env:
|
||||||
cache-name: ${{ runner.os }}-sdl-cache-cmake-build
|
cache-name: ${{ runner.os }}-sdl-cache-cmake-build
|
||||||
with:
|
with:
|
||||||
append-timestamp: false
|
append-timestamp: false
|
||||||
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
||||||
|
|
||||||
- name: Setup VS Environment
|
|
||||||
uses: ilammy/msvc-dev-cmd@v1.13.0
|
|
||||||
with:
|
|
||||||
arch: amd64
|
|
||||||
|
|
||||||
- name: Configure CMake
|
- name: Configure CMake
|
||||||
run: cmake --fresh -G Ninja -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
run: cmake --fresh -G Ninja -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||||
|
|
||||||
@@ -100,72 +95,11 @@ jobs:
|
|||||||
name: shadps4-win64-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}
|
name: shadps4-win64-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}
|
||||||
path: ${{github.workspace}}/build/shadPS4.exe
|
path: ${{github.workspace}}/build/shadPS4.exe
|
||||||
|
|
||||||
windows-qt:
|
|
||||||
runs-on: windows-2025
|
|
||||||
needs: get-info
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
|
|
||||||
- name: Setup Qt
|
|
||||||
uses: jurplel/install-qt-action@v4
|
|
||||||
with:
|
|
||||||
version: 6.9.0
|
|
||||||
host: windows
|
|
||||||
target: desktop
|
|
||||||
arch: win64_msvc2022_64
|
|
||||||
archives: qtbase qttools
|
|
||||||
modules: qtmultimedia
|
|
||||||
|
|
||||||
- name: Cache CMake Configuration
|
|
||||||
uses: actions/cache@v4
|
|
||||||
env:
|
|
||||||
cache-name: ${{ runner.os }}-qt-ninja-cache-cmake-configuration
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
${{github.workspace}}/build
|
|
||||||
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ env.cache-name }}-
|
|
||||||
|
|
||||||
- name: Cache CMake Build
|
|
||||||
uses: hendrikmuhs/ccache-action@v1.2.17
|
|
||||||
env:
|
|
||||||
cache-name: ${{ runner.os }}-qt-cache-cmake-build
|
|
||||||
with:
|
|
||||||
append-timestamp: false
|
|
||||||
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
|
||||||
|
|
||||||
- name: Setup VS Environment
|
|
||||||
uses: ilammy/msvc-dev-cmd@v1.13.0
|
|
||||||
with:
|
|
||||||
arch: amd64
|
|
||||||
|
|
||||||
- name: Configure CMake
|
|
||||||
run: cmake --fresh -G Ninja -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DENABLE_QT_GUI=ON -DENABLE_UPDATER=ON -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $env:NUMBER_OF_PROCESSORS
|
|
||||||
|
|
||||||
- name: Deploy and Package
|
|
||||||
run: |
|
|
||||||
mkdir upload
|
|
||||||
move build/shadPS4.exe upload
|
|
||||||
windeployqt --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
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: shadps4-win64-qt-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}
|
|
||||||
path: upload/
|
|
||||||
|
|
||||||
macos-sdl:
|
macos-sdl:
|
||||||
runs-on: macos-15
|
runs-on: macos-15
|
||||||
needs: get-info
|
needs: get-info
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
@@ -186,7 +120,7 @@ jobs:
|
|||||||
${{ env.cache-name }}-
|
${{ env.cache-name }}-
|
||||||
|
|
||||||
- name: Cache CMake Build
|
- name: Cache CMake Build
|
||||||
uses: hendrikmuhs/ccache-action@v1.2.17
|
uses: hendrikmuhs/ccache-action@v1.2.19
|
||||||
env:
|
env:
|
||||||
cache-name: ${{runner.os}}-sdl-cache-cmake-build
|
cache-name: ${{runner.os}}-sdl-cache-cmake-build
|
||||||
with:
|
with:
|
||||||
@@ -212,72 +146,11 @@ jobs:
|
|||||||
name: shadps4-macos-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}
|
name: shadps4-macos-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}
|
||||||
path: upload/
|
path: upload/
|
||||||
|
|
||||||
macos-qt:
|
|
||||||
runs-on: macos-15
|
|
||||||
needs: get-info
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
|
|
||||||
- name: Setup latest Xcode
|
|
||||||
uses: maxim-lobanov/setup-xcode@v1
|
|
||||||
with:
|
|
||||||
xcode-version: latest
|
|
||||||
|
|
||||||
- name: Setup Qt
|
|
||||||
uses: jurplel/install-qt-action@v4
|
|
||||||
with:
|
|
||||||
version: 6.9.0
|
|
||||||
host: mac
|
|
||||||
target: desktop
|
|
||||||
arch: clang_64
|
|
||||||
archives: qtbase qttools
|
|
||||||
modules: qtmultimedia
|
|
||||||
|
|
||||||
- name: Cache CMake Configuration
|
|
||||||
uses: actions/cache@v4
|
|
||||||
env:
|
|
||||||
cache-name: ${{ runner.os }}-qt-cache-cmake-configuration
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
${{github.workspace}}/build
|
|
||||||
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ env.cache-name }}-
|
|
||||||
|
|
||||||
- name: Cache CMake Build
|
|
||||||
uses: hendrikmuhs/ccache-action@v1.2.17
|
|
||||||
env:
|
|
||||||
cache-name: ${{runner.os}}-qt-cache-cmake-build
|
|
||||||
with:
|
|
||||||
append-timestamp: false
|
|
||||||
create-symlink: true
|
|
||||||
key: ${{env.cache-name}}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
|
||||||
variant: sccache
|
|
||||||
|
|
||||||
- name: Configure CMake
|
|
||||||
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_OSX_ARCHITECTURES=x86_64 -DENABLE_QT_GUI=ON -DENABLE_UPDATER=ON -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(sysctl -n hw.ncpu)
|
|
||||||
|
|
||||||
- name: Package and Upload macOS Qt artifact
|
|
||||||
run: |
|
|
||||||
mkdir upload
|
|
||||||
mv ${{github.workspace}}/build/shadps4.app upload
|
|
||||||
macdeployqt upload/shadps4.app
|
|
||||||
tar cf shadps4-macos-qt.tar.gz -C upload .
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: shadps4-macos-qt-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}
|
|
||||||
path: shadps4-macos-qt.tar.gz
|
|
||||||
|
|
||||||
linux-sdl:
|
linux-sdl:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
needs: get-info
|
needs: get-info
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
@@ -287,7 +160,7 @@ jobs:
|
|||||||
sudo add-apt-repository 'deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main'
|
sudo add-apt-repository 'deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 clang-19 mold build-essential libasound2-dev libpulse-dev libopenal-dev libudev-dev
|
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 clang-19 mold build-essential libasound2-dev libpulse-dev libopenal-dev libudev-dev libxcursor-dev libxi-dev libxss-dev libxtst-dev
|
||||||
|
|
||||||
- name: Cache CMake Configuration
|
- name: Cache CMake Configuration
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
@@ -301,7 +174,7 @@ jobs:
|
|||||||
${{ env.cache-name }}-
|
${{ env.cache-name }}-
|
||||||
|
|
||||||
- name: Cache CMake Build
|
- name: Cache CMake Build
|
||||||
uses: hendrikmuhs/ccache-action@v1.2.17
|
uses: hendrikmuhs/ccache-action@v1.2.19
|
||||||
env:
|
env:
|
||||||
cache-name: ${{ runner.os }}-sdl-cache-cmake-build
|
cache-name: ${{ runner.os }}-sdl-cache-cmake-build
|
||||||
with:
|
with:
|
||||||
@@ -334,68 +207,16 @@ jobs:
|
|||||||
name: shadps4-linux-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}
|
name: shadps4-linux-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}
|
||||||
path: Shadps4-sdl.AppImage
|
path: Shadps4-sdl.AppImage
|
||||||
|
|
||||||
linux-qt:
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
needs: get-info
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
|
|
||||||
- name: Add LLVM repository
|
|
||||||
run: |
|
|
||||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
|
||||||
sudo add-apt-repository 'deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 clang-19 mold build-essential qt6-base-dev qt6-tools-dev qt6-multimedia-dev libasound2-dev libpulse-dev libopenal-dev libudev-dev
|
|
||||||
|
|
||||||
- name: Cache CMake Configuration
|
|
||||||
uses: actions/cache@v4
|
|
||||||
env:
|
|
||||||
cache-name: ${{ runner.os }}-qt-cache-cmake-configuration
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
${{github.workspace}}/build
|
|
||||||
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ env.cache-name }}-
|
|
||||||
|
|
||||||
- name: Cache CMake Build
|
|
||||||
uses: hendrikmuhs/ccache-action@v1.2.17
|
|
||||||
env:
|
|
||||||
cache-name: ${{ runner.os }}-qt-cache-cmake-build
|
|
||||||
with:
|
|
||||||
append-timestamp: false
|
|
||||||
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
|
||||||
|
|
||||||
- name: Configure CMake
|
|
||||||
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=clang-19 -DCMAKE_CXX_COMPILER=clang++-19 -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=mold" -DCMAKE_SHARED_LINKER_FLAGS="-fuse-ld=mold" -DENABLE_QT_GUI=ON -DENABLE_UPDATER=ON -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(nproc)
|
|
||||||
|
|
||||||
- name: Run AppImage packaging script
|
|
||||||
run: ./.github/linux-appimage-qt.sh
|
|
||||||
|
|
||||||
- name: Package and Upload Linux Qt artifact
|
|
||||||
run: |
|
|
||||||
tar cf shadps4-linux-qt.tar.gz -C ${{github.workspace}}/build shadps4
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: shadps4-linux-qt-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}
|
|
||||||
path: Shadps4-qt.AppImage
|
|
||||||
|
|
||||||
linux-sdl-gcc:
|
linux-sdl-gcc:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
needs: get-info
|
needs: get-info
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 gcc-14 mold build-essential libasound2-dev libpulse-dev libopenal-dev libudev-dev
|
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 gcc-14 mold build-essential libasound2-dev libpulse-dev libopenal-dev libudev-dev libxcursor-dev libxi-dev libxss-dev libxtst-dev
|
||||||
|
|
||||||
- name: Cache CMake Configuration
|
- name: Cache CMake Configuration
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
@@ -409,7 +230,7 @@ jobs:
|
|||||||
${{ env.cache-name }}-
|
${{ env.cache-name }}-
|
||||||
|
|
||||||
- name: Cache CMake Build
|
- name: Cache CMake Build
|
||||||
uses: hendrikmuhs/ccache-action@v1.2.17
|
uses: hendrikmuhs/ccache-action@v1.2.19
|
||||||
env:
|
env:
|
||||||
cache-name: ${{ runner.os }}-sdl-gcc-cache-cmake-build
|
cache-name: ${{ runner.os }}-sdl-gcc-cache-cmake-build
|
||||||
with:
|
with:
|
||||||
@@ -422,52 +243,21 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(nproc)
|
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(nproc)
|
||||||
|
|
||||||
linux-qt-gcc:
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
needs: get-info
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 gcc-14 mold build-essential qt6-base-dev qt6-tools-dev qt6-multimedia-dev libasound2-dev libpulse-dev libopenal-dev libudev-dev
|
|
||||||
|
|
||||||
- name: Cache CMake Configuration
|
|
||||||
uses: actions/cache@v4
|
|
||||||
env:
|
|
||||||
cache-name: ${{ runner.os }}-qt-gcc-cache-cmake-configuration
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
${{github.workspace}}/build
|
|
||||||
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ env.cache-name }}-
|
|
||||||
|
|
||||||
- name: Cache CMake Build
|
|
||||||
uses: hendrikmuhs/ccache-action@v1.2.17
|
|
||||||
env:
|
|
||||||
cache-name: ${{ runner.os }}-qt-gcc-cache-cmake-build
|
|
||||||
with:
|
|
||||||
append-timestamp: false
|
|
||||||
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
|
||||||
|
|
||||||
- name: Configure CMake
|
|
||||||
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=mold" -DCMAKE_SHARED_LINKER_FLAGS="-fuse-ld=mold" -DENABLE_QT_GUI=ON -DENABLE_UPDATER=ON -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(nproc)
|
|
||||||
|
|
||||||
pre-release:
|
pre-release:
|
||||||
if: github.ref == 'refs/heads/main' && github.repository == 'shadps4-emu/shadPS4' && github.event_name == 'push'
|
if: github.ref == 'refs/heads/main' && github.repository == 'shadps4-emu/shadPS4' && github.event_name == 'push'
|
||||||
needs: [get-info, windows-sdl, windows-qt, macos-sdl, macos-qt, linux-sdl, linux-qt]
|
needs: [get-info, windows-sdl, macos-sdl, linux-sdl]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Download all artifacts
|
- name: Download all artifacts
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v5
|
||||||
with:
|
with:
|
||||||
path: ./artifacts
|
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)
|
- name: Compress individual directories (without parent directory)
|
||||||
run: |
|
run: |
|
||||||
cd ./artifacts
|
cd ./artifacts
|
||||||
@@ -494,7 +284,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
token: ${{ secrets.SHADPS4_TOKEN_REPO }}
|
token: ${{ secrets.SHADPS4_TOKEN_REPO }}
|
||||||
name: "Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}"
|
name: "Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}"
|
||||||
tag: "Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}"
|
tag: "Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.fullhash }}"
|
||||||
draft: false
|
draft: false
|
||||||
prerelease: true
|
prerelease: true
|
||||||
body: "Full Changelog: [${{ env.last_release_tag }}...${{ needs.get-info.outputs.shorthash }}](https://github.com/shadps4-emu/shadPS4/compare/${{ env.last_release_tag }}...${{ needs.get-info.outputs.fullhash }})"
|
body: "Full Changelog: [${{ env.last_release_tag }}...${{ needs.get-info.outputs.shorthash }}](https://github.com/shadps4-emu/shadPS4/compare/${{ env.last_release_tag }}...${{ needs.get-info.outputs.fullhash }})"
|
||||||
@@ -530,14 +320,14 @@ jobs:
|
|||||||
|
|
||||||
# Check if release already exists and get ID
|
# Check if release already exists and get ID
|
||||||
release_id=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
|
release_id=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
|
||||||
"https://api.github.com/repos/$REPO/releases/tags/Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}" | jq -r '.id')
|
"https://api.github.com/repos/$REPO/releases/tags/Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.fullhash }}" | jq -r '.id')
|
||||||
|
|
||||||
if [[ "$release_id" == "null" ]]; then
|
if [[ "$release_id" == "null" ]]; then
|
||||||
echo "Creating release in $REPO for $filename"
|
echo "Creating release in $REPO for $filename"
|
||||||
release_id=$(curl -s -X POST -H "Authorization: token $GITHUB_TOKEN" \
|
release_id=$(curl -s -X POST -H "Authorization: token $GITHUB_TOKEN" \
|
||||||
-H "Accept: application/vnd.github.v3+json" \
|
-H "Accept: application/vnd.github.v3+json" \
|
||||||
-d '{
|
-d '{
|
||||||
"tag_name": "Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}",
|
"tag_name": "Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.fullhash }}",
|
||||||
"name": "Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}",
|
"name": "Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}",
|
||||||
"draft": false,
|
"draft": false,
|
||||||
"prerelease": true,
|
"prerelease": true,
|
||||||
|
|||||||
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
|
|
||||||
38
.gitmodules
vendored
@@ -91,18 +91,32 @@
|
|||||||
path = externals/libpng
|
path = externals/libpng
|
||||||
url = https://github.com/pnggroup/libpng
|
url = https://github.com/pnggroup/libpng
|
||||||
shallow = true
|
shallow = true
|
||||||
[submodule "externals/MoltenVK/SPIRV-Cross"]
|
[submodule "externals/ext-libusb"]
|
||||||
path = externals/MoltenVK/SPIRV-Cross
|
path = externals/ext-libusb
|
||||||
url = https://github.com/KhronosGroup/SPIRV-Cross
|
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
|
shallow = true
|
||||||
[submodule "externals/MoltenVK/MoltenVK"]
|
[submodule "externals/ext-wepoll"]
|
||||||
path = externals/MoltenVK/MoltenVK
|
path = externals/ext-wepoll
|
||||||
url = https://github.com/KhronosGroup/MoltenVK
|
url = https://github.com/shadps4-emu/ext-wepoll.git
|
||||||
shallow = true
|
shallow = true
|
||||||
[submodule "externals/MoltenVK/cereal"]
|
branch = dist
|
||||||
path = externals/MoltenVK/cereal
|
[submodule "externals/MoltenVK"]
|
||||||
url = https://github.com/USCiLab/cereal
|
path = externals/MoltenVK
|
||||||
|
url = https://github.com/shadPS4-emu/ext-MoltenVK.git
|
||||||
shallow = true
|
shallow = true
|
||||||
[submodule "externals/libusb"]
|
[submodule "externals/json"]
|
||||||
path = externals/libusb
|
path = externals/json
|
||||||
url = https://github.com/libusb/libusb-cmake.git
|
url = https://github.com/nlohmann/json.git
|
||||||
|
[submodule "externals/sdl3_mixer"]
|
||||||
|
path = externals/sdl3_mixer
|
||||||
|
url = https://github.com/libsdl-org/SDL_mixer
|
||||||
|
shallow = true
|
||||||
|
[submodule "externals/miniz"]
|
||||||
|
path = externals/miniz
|
||||||
|
url = https://github.com/richgel999/miniz
|
||||||
|
|||||||
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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
21
CMakeLinuxPresets.json
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"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}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
430
CMakeLists.txt
@@ -31,7 +31,6 @@ if(UNIX AND NOT APPLE)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(ENABLE_QT_GUI "Enable the Qt GUI. If not selected then the emulator uses a minimal SDL-based UI instead" OFF)
|
|
||||||
option(ENABLE_DISCORD_RPC "Enable the Discord RPC integration" ON)
|
option(ENABLE_DISCORD_RPC "Enable the Discord RPC integration" ON)
|
||||||
option(ENABLE_UPDATER "Enables the options to updater" ON)
|
option(ENABLE_UPDATER "Enables the options to updater" ON)
|
||||||
|
|
||||||
@@ -126,7 +125,7 @@ execute_process(
|
|||||||
|
|
||||||
# If there's no upstream set or the command failed, check remote.pushDefault
|
# If there's no upstream set or the command failed, check remote.pushDefault
|
||||||
if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
|
if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
|
||||||
message("check default push")
|
message(STATUS "check default push")
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND git config --get remote.pushDefault
|
COMMAND git config --get remote.pushDefault
|
||||||
OUTPUT_VARIABLE GIT_REMOTE_NAME
|
OUTPUT_VARIABLE GIT_REMOTE_NAME
|
||||||
@@ -134,30 +133,30 @@ if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
|
|||||||
ERROR_QUIET
|
ERROR_QUIET
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
)
|
)
|
||||||
message("got remote: ${GIT_REMOTE_NAME}")
|
message(STATUS "got remote: ${GIT_REMOTE_NAME}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# If running in GitHub Actions and the above fails
|
# If running in GitHub Actions and the above fails
|
||||||
if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
|
if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
|
||||||
message("check github")
|
message(STATUS "check github")
|
||||||
set(GIT_REMOTE_NAME "origin")
|
set(GIT_REMOTE_NAME "origin")
|
||||||
|
|
||||||
# Retrieve environment variables
|
# Retrieve environment variables
|
||||||
if (DEFINED ENV{GITHUB_HEAD_REF} AND NOT "$ENV{GITHUB_HEAD_REF}" STREQUAL "")
|
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}")
|
set(GITHUB_HEAD_REF "$ENV{GITHUB_HEAD_REF}")
|
||||||
else()
|
else()
|
||||||
set(GITHUB_HEAD_REF "")
|
set(GITHUB_HEAD_REF "")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (DEFINED ENV{GITHUB_REF} AND NOT "$ENV{GITHUB_REF}" STREQUAL "")
|
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 REPLACE "^refs/[^/]*/" "" GITHUB_BRANCH "$ENV{GITHUB_REF}")
|
||||||
string(REGEX MATCH "refs/pull/([0-9]+)/merge" MATCHED_REF "$ENV{GITHUB_REF}")
|
string(REGEX MATCH "refs/pull/([0-9]+)/merge" MATCHED_REF "$ENV{GITHUB_REF}")
|
||||||
if (MATCHED_REF)
|
if (MATCHED_REF)
|
||||||
set(PR_NUMBER "${CMAKE_MATCH_1}")
|
set(PR_NUMBER "${CMAKE_MATCH_1}")
|
||||||
set(GITHUB_BRANCH "")
|
set(GITHUB_BRANCH "")
|
||||||
message("PR number: ${PR_NUMBER}")
|
message(STATUS "PR number: ${PR_NUMBER}")
|
||||||
else()
|
else()
|
||||||
set(PR_NUMBER "")
|
set(PR_NUMBER "")
|
||||||
endif()
|
endif()
|
||||||
@@ -179,7 +178,7 @@ if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
|
|||||||
elseif ("${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_REF}" STREQUAL "")
|
elseif ("${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_REF}" STREQUAL "")
|
||||||
set(GIT_BRANCH "${GITHUB_REF}")
|
set(GIT_BRANCH "${GITHUB_REF}")
|
||||||
elseif("${GIT_BRANCH}" STREQUAL "")
|
elseif("${GIT_BRANCH}" STREQUAL "")
|
||||||
message("couldn't find branch")
|
message(STATUS "couldn't find branch")
|
||||||
set(GIT_BRANCH "detached-head")
|
set(GIT_BRANCH "detached-head")
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
@@ -188,13 +187,13 @@ else()
|
|||||||
if (INDEX GREATER -1)
|
if (INDEX GREATER -1)
|
||||||
string(SUBSTRING "${GIT_REMOTE_NAME}" 0 "${INDEX}" GIT_REMOTE_NAME)
|
string(SUBSTRING "${GIT_REMOTE_NAME}" 0 "${INDEX}" GIT_REMOTE_NAME)
|
||||||
elseif("${GIT_REMOTE_NAME}" STREQUAL "")
|
elseif("${GIT_REMOTE_NAME}" STREQUAL "")
|
||||||
message("reset to origin")
|
message(STATUS "reset to origin")
|
||||||
set(GIT_REMOTE_NAME "origin")
|
set(GIT_REMOTE_NAME "origin")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Get remote link
|
# Get remote link
|
||||||
message("getting remote link")
|
message(STATUS "getting remote link")
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND git config --get remote.${GIT_REMOTE_NAME}.url
|
COMMAND git config --get remote.${GIT_REMOTE_NAME}.url
|
||||||
OUTPUT_VARIABLE GIT_REMOTE_URL
|
OUTPUT_VARIABLE GIT_REMOTE_URL
|
||||||
@@ -203,16 +202,22 @@ execute_process(
|
|||||||
|
|
||||||
# Set Version
|
# Set Version
|
||||||
set(EMULATOR_VERSION_MAJOR "0")
|
set(EMULATOR_VERSION_MAJOR "0")
|
||||||
set(EMULATOR_VERSION_MINOR "9")
|
set(EMULATOR_VERSION_MINOR "12")
|
||||||
set(EMULATOR_VERSION_PATCH "0")
|
set(EMULATOR_VERSION_PATCH "6")
|
||||||
|
|
||||||
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}")
|
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}")
|
||||||
|
|
||||||
set(APP_VERSION "${EMULATOR_VERSION_MAJOR}.${EMULATOR_VERSION_MINOR}.${EMULATOR_VERSION_PATCH}")
|
set(APP_VERSION "${EMULATOR_VERSION_MAJOR}.${EMULATOR_VERSION_MINOR}.${EMULATOR_VERSION_PATCH} WIP")
|
||||||
set(APP_IS_RELEASE true)
|
set(APP_IS_RELEASE false)
|
||||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/src/common/scm_rev.cpp" @ONLY)
|
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()
|
||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
find_package(Boost 1.84.0 CONFIG)
|
find_package(Boost 1.84.0 CONFIG)
|
||||||
@@ -223,20 +228,23 @@ find_package(half 1.12.0 MODULE)
|
|||||||
find_package(magic_enum 0.9.7 CONFIG)
|
find_package(magic_enum 0.9.7 CONFIG)
|
||||||
find_package(PNG 1.6 MODULE)
|
find_package(PNG 1.6 MODULE)
|
||||||
find_package(RenderDoc 1.6.0 MODULE)
|
find_package(RenderDoc 1.6.0 MODULE)
|
||||||
find_package(SDL3 3.1.2 CONFIG)
|
find_package(SDL3_mixer 2.8.1 CONFIG)
|
||||||
|
if (SDL3_mixer_FOUND)
|
||||||
|
find_package(SDL3 3.1.2 CONFIG)
|
||||||
|
endif()
|
||||||
find_package(stb MODULE)
|
find_package(stb MODULE)
|
||||||
find_package(toml11 4.2.0 CONFIG)
|
find_package(toml11 4.2.0 CONFIG)
|
||||||
find_package(tsl-robin-map 1.3.0 CONFIG)
|
find_package(tsl-robin-map 1.3.0 CONFIG)
|
||||||
find_package(VulkanHeaders 1.4.309 CONFIG)
|
find_package(VulkanHeaders 1.4.329 CONFIG)
|
||||||
find_package(VulkanMemoryAllocator 3.1.0 CONFIG)
|
find_package(VulkanMemoryAllocator 3.1.0 CONFIG)
|
||||||
find_package(xbyak 7.07 CONFIG)
|
find_package(xbyak 7.07 CONFIG)
|
||||||
find_package(xxHash 0.8.2 MODULE)
|
find_package(xxHash 0.8.2 MODULE)
|
||||||
find_package(ZLIB 1.3 MODULE)
|
find_package(ZLIB 1.3 MODULE)
|
||||||
find_package(Zydis 5.0.0 CONFIG)
|
find_package(Zydis 5.0.0 CONFIG)
|
||||||
find_package(pugixml 1.14 CONFIG)
|
find_package(pugixml 1.14 CONFIG)
|
||||||
find_package(libusb 1.0.27 MODULE)
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
find_package(date 3.0.1 CONFIG)
|
find_package(date 3.0.1 CONFIG)
|
||||||
|
find_package(epoll-shim 3.14 CONFIG)
|
||||||
endif()
|
endif()
|
||||||
list(POP_BACK CMAKE_MODULE_PATH)
|
list(POP_BACK CMAKE_MODULE_PATH)
|
||||||
|
|
||||||
@@ -251,31 +259,6 @@ endif()
|
|||||||
|
|
||||||
add_subdirectory(externals)
|
add_subdirectory(externals)
|
||||||
include_directories(src)
|
include_directories(src)
|
||||||
include_directories(Resources)
|
|
||||||
|
|
||||||
if(ENABLE_QT_GUI)
|
|
||||||
find_package(Qt6 REQUIRED COMPONENTS Widgets Concurrent LinguistTools Network Multimedia)
|
|
||||||
qt_standard_project_setup()
|
|
||||||
set(CMAKE_AUTORCC ON)
|
|
||||||
set(CMAKE_AUTOMOC ON)
|
|
||||||
set(CMAKE_AUTOUIC ON)
|
|
||||||
|
|
||||||
set(QT_TRANSLATIONS "${PROJECT_SOURCE_DIR}/src/qt_gui/translations")
|
|
||||||
file(GLOB_RECURSE TRANSLATIONS_TS ${QT_TRANSLATIONS}/*.ts)
|
|
||||||
|
|
||||||
set_source_files_properties(${TRANSLATIONS_TS} PROPERTIES OUTPUT_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/translations")
|
|
||||||
qt_add_translation(TRANSLATIONS_QM ${TRANSLATIONS_TS})
|
|
||||||
|
|
||||||
set(TRANSLATIONS_QRC ${CMAKE_CURRENT_BINARY_DIR}/translations/translations.qrc)
|
|
||||||
file(WRITE ${TRANSLATIONS_QRC} "<RCC><qresource prefix=\"translations\">\n")
|
|
||||||
foreach (QM ${TRANSLATIONS_QM})
|
|
||||||
get_filename_component(QM_FILE ${QM} NAME)
|
|
||||||
file(APPEND ${TRANSLATIONS_QRC} "<file>${QM_FILE}</file>\n")
|
|
||||||
endforeach (QM)
|
|
||||||
file(APPEND ${TRANSLATIONS_QRC} "</qresource></RCC>")
|
|
||||||
|
|
||||||
qt_add_resources(TRANSLATIONS ${TRANSLATIONS_QRC})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(AJM_LIB src/core/libraries/ajm/ajm.cpp
|
set(AJM_LIB src/core/libraries/ajm/ajm.cpp
|
||||||
src/core/libraries/ajm/ajm.h
|
src/core/libraries/ajm/ajm.h
|
||||||
@@ -296,6 +279,10 @@ set(AJM_LIB src/core/libraries/ajm/ajm.cpp
|
|||||||
|
|
||||||
set(AUDIO_LIB src/core/libraries/audio/audioin.cpp
|
set(AUDIO_LIB src/core/libraries/audio/audioin.cpp
|
||||||
src/core/libraries/audio/audioin.h
|
src/core/libraries/audio/audioin.h
|
||||||
|
src/core/libraries/audio/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
|
src/core/libraries/audio/audioout.cpp
|
||||||
src/core/libraries/audio/audioout.h
|
src/core/libraries/audio/audioout.h
|
||||||
src/core/libraries/audio/audioout_backend.h
|
src/core/libraries/audio/audioout_backend.h
|
||||||
@@ -367,6 +354,10 @@ set(NETWORK_LIBS src/core/libraries/network/http.cpp
|
|||||||
src/core/libraries/network/net_ctl_codes.h
|
src/core/libraries/network/net_ctl_codes.h
|
||||||
src/core/libraries/network/net_util.cpp
|
src/core/libraries/network/net_util.cpp
|
||||||
src/core/libraries/network/net_util.h
|
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_error.h
|
||||||
src/core/libraries/network/net.h
|
src/core/libraries/network/net.h
|
||||||
src/core/libraries/network/ssl.cpp
|
src/core/libraries/network/ssl.cpp
|
||||||
@@ -377,6 +368,7 @@ set(NETWORK_LIBS src/core/libraries/network/http.cpp
|
|||||||
src/core/libraries/network/sys_net.h
|
src/core/libraries/network/sys_net.h
|
||||||
src/core/libraries/network/posix_sockets.cpp
|
src/core/libraries/network/posix_sockets.cpp
|
||||||
src/core/libraries/network/p2p_sockets.cpp
|
src/core/libraries/network/p2p_sockets.cpp
|
||||||
|
src/core/libraries/network/unix_sockets.cpp
|
||||||
src/core/libraries/network/sockets.h
|
src/core/libraries/network/sockets.h
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -472,6 +464,12 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp
|
|||||||
src/core/libraries/mouse/mouse.h
|
src/core/libraries/mouse/mouse.h
|
||||||
src/core/libraries/web_browser_dialog/webbrowserdialog.cpp
|
src/core/libraries/web_browser_dialog/webbrowserdialog.cpp
|
||||||
src/core/libraries/web_browser_dialog/webbrowserdialog.h
|
src/core/libraries/web_browser_dialog/webbrowserdialog.h
|
||||||
|
src/core/libraries/font/font.cpp
|
||||||
|
src/core/libraries/font/font.h
|
||||||
|
src/core/libraries/font/fontft.cpp
|
||||||
|
src/core/libraries/font/fontft.h
|
||||||
|
src/core/libraries/font/font_error.h
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(VIDEOOUT_LIB src/core/libraries/videoout/buffer.h
|
set(VIDEOOUT_LIB src/core/libraries/videoout/buffer.h
|
||||||
@@ -514,6 +512,11 @@ set(PAD_LIB src/core/libraries/pad/pad.cpp
|
|||||||
src/core/libraries/pad/pad_errors.h
|
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
|
set(PNG_LIB src/core/libraries/libpng/pngdec.cpp
|
||||||
src/core/libraries/libpng/pngdec.h
|
src/core/libraries/libpng/pngdec.h
|
||||||
src/core/libraries/libpng/pngdec_error.h
|
src/core/libraries/libpng/pngdec_error.h
|
||||||
@@ -538,6 +541,13 @@ set(RANDOM_LIB src/core/libraries/random/random.cpp
|
|||||||
|
|
||||||
set(USBD_LIB src/core/libraries/usbd/usbd.cpp
|
set(USBD_LIB src/core/libraries/usbd/usbd.cpp
|
||||||
src/core/libraries/usbd/usbd.h
|
src/core/libraries/usbd/usbd.h
|
||||||
|
src/core/libraries/usbd/usb_backend.h
|
||||||
|
src/core/libraries/usbd/emulated/dimensions.cpp
|
||||||
|
src/core/libraries/usbd/emulated/dimensions.h
|
||||||
|
src/core/libraries/usbd/emulated/infinity.cpp
|
||||||
|
src/core/libraries/usbd/emulated/infinity.h
|
||||||
|
src/core/libraries/usbd/emulated/skylander.cpp
|
||||||
|
src/core/libraries/usbd/emulated/skylander.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(FIBER_LIB src/core/libraries/fiber/fiber_context.s
|
set(FIBER_LIB src/core/libraries/fiber/fiber_context.s
|
||||||
@@ -546,6 +556,8 @@ set(FIBER_LIB src/core/libraries/fiber/fiber_context.s
|
|||||||
src/core/libraries/fiber/fiber_error.h
|
src/core/libraries/fiber/fiber_error.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set_source_files_properties(src/core/libraries/fiber/fiber_context.s PROPERTIES COMPILE_OPTIONS -Wno-unused-command-line-argument)
|
||||||
|
|
||||||
set(VDEC_LIB src/core/libraries/videodec/videodec2_impl.cpp
|
set(VDEC_LIB src/core/libraries/videodec/videodec2_impl.cpp
|
||||||
src/core/libraries/videodec/videodec2_impl.h
|
src/core/libraries/videodec/videodec2_impl.h
|
||||||
src/core/libraries/videodec/videodec2.cpp
|
src/core/libraries/videodec/videodec2.cpp
|
||||||
@@ -558,23 +570,29 @@ set(VDEC_LIB src/core/libraries/videodec/videodec2_impl.cpp
|
|||||||
src/core/libraries/videodec/videodec_impl.h
|
src/core/libraries/videodec/videodec_impl.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(NP_LIBS src/core/libraries/np_common/np_common.cpp
|
set(NP_LIBS src/core/libraries/np/np_error.h
|
||||||
src/core/libraries/np_common/np_common.h
|
src/core/libraries/np/np_common.cpp
|
||||||
src/core/libraries/np_manager/np_manager.cpp
|
src/core/libraries/np/np_common.h
|
||||||
src/core/libraries/np_manager/np_manager.h
|
src/core/libraries/np/np_commerce.cpp
|
||||||
src/core/libraries/np_score/np_score.cpp
|
src/core/libraries/np/np_commerce.h
|
||||||
src/core/libraries/np_score/np_score.h
|
src/core/libraries/np/np_manager.cpp
|
||||||
src/core/libraries/np_trophy/np_trophy.cpp
|
src/core/libraries/np/np_manager.h
|
||||||
src/core/libraries/np_trophy/np_trophy.h
|
src/core/libraries/np/np_score.cpp
|
||||||
src/core/libraries/np_trophy/trophy_ui.cpp
|
src/core/libraries/np/np_score.h
|
||||||
src/core/libraries/np_trophy/trophy_ui.h
|
src/core/libraries/np/np_trophy.cpp
|
||||||
src/core/libraries/np_trophy/np_trophy_error.h
|
src/core/libraries/np/np_trophy.h
|
||||||
src/core/libraries/np_web_api/np_web_api.cpp
|
src/core/libraries/np/trophy_ui.cpp
|
||||||
src/core/libraries/np_web_api/np_web_api.h
|
src/core/libraries/np/trophy_ui.h
|
||||||
src/core/libraries/np_party/np_party.cpp
|
src/core/libraries/np/np_web_api.cpp
|
||||||
src/core/libraries/np_party/np_party.h
|
src/core/libraries/np/np_web_api.h
|
||||||
src/core/libraries/np_auth/np_auth.cpp
|
src/core/libraries/np/np_party.cpp
|
||||||
src/core/libraries/np_auth/np_auth.h
|
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
|
set(ZLIB_LIB src/core/libraries/zlib/zlib.cpp
|
||||||
@@ -583,13 +601,20 @@ set(ZLIB_LIB src/core/libraries/zlib/zlib.cpp
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(VR_LIBS src/core/libraries/hmd/hmd.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.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
|
set(MISC_LIBS src/core/libraries/screenshot/screenshot.cpp
|
||||||
src/core/libraries/screenshot/screenshot.h
|
src/core/libraries/screenshot/screenshot.h
|
||||||
src/core/libraries/move/move.cpp
|
src/core/libraries/move/move.cpp
|
||||||
src/core/libraries/move/move.h
|
src/core/libraries/move/move.h
|
||||||
|
src/core/libraries/move/move_error.h
|
||||||
src/core/libraries/ulobjmgr/ulobjmgr.cpp
|
src/core/libraries/ulobjmgr/ulobjmgr.cpp
|
||||||
src/core/libraries/ulobjmgr/ulobjmgr.h
|
src/core/libraries/ulobjmgr/ulobjmgr.h
|
||||||
src/core/libraries/signin_dialog/signindialog.cpp
|
src/core/libraries/signin_dialog/signindialog.cpp
|
||||||
@@ -603,10 +628,13 @@ set(CAMERA_LIBS src/core/libraries/camera/camera.cpp
|
|||||||
|
|
||||||
set(COMPANION_LIBS src/core/libraries/companion/companion_httpd.cpp
|
set(COMPANION_LIBS src/core/libraries/companion/companion_httpd.cpp
|
||||||
src/core/libraries/companion/companion_httpd.h
|
src/core/libraries/companion/companion_httpd.h
|
||||||
|
src/core/libraries/companion/companion_util.cpp
|
||||||
|
src/core/libraries/companion/companion_util.h
|
||||||
src/core/libraries/companion/companion_error.h
|
src/core/libraries/companion/companion_error.h
|
||||||
)
|
)
|
||||||
set(DEV_TOOLS src/core/devtools/layer.cpp
|
set(DEV_TOOLS src/core/devtools/layer.cpp
|
||||||
src/core/devtools/layer.h
|
src/core/devtools/layer.h
|
||||||
|
src/core/devtools/layer_extra.cpp
|
||||||
src/core/devtools/options.cpp
|
src/core/devtools/options.cpp
|
||||||
src/core/devtools/options.h
|
src/core/devtools/options.h
|
||||||
src/core/devtools/gcn/gcn_context_regs.cpp
|
src/core/devtools/gcn/gcn_context_regs.cpp
|
||||||
@@ -622,6 +650,8 @@ set(DEV_TOOLS src/core/devtools/layer.cpp
|
|||||||
src/core/devtools/widget/imgui_memory_editor.h
|
src/core/devtools/widget/imgui_memory_editor.h
|
||||||
src/core/devtools/widget/memory_map.cpp
|
src/core/devtools/widget/memory_map.cpp
|
||||||
src/core/devtools/widget/memory_map.h
|
src/core/devtools/widget/memory_map.h
|
||||||
|
src/core/devtools/widget/module_list.cpp
|
||||||
|
src/core/devtools/widget/module_list.h
|
||||||
src/core/devtools/widget/reg_popup.cpp
|
src/core/devtools/widget/reg_popup.cpp
|
||||||
src/core/devtools/widget/reg_popup.h
|
src/core/devtools/widget/reg_popup.h
|
||||||
src/core/devtools/widget/reg_view.cpp
|
src/core/devtools/widget/reg_view.cpp
|
||||||
@@ -647,6 +677,7 @@ set(COMMON src/common/logging/backend.cpp
|
|||||||
src/common/arch.h
|
src/common/arch.h
|
||||||
src/common/assert.cpp
|
src/common/assert.cpp
|
||||||
src/common/assert.h
|
src/common/assert.h
|
||||||
|
src/common/bit_array.h
|
||||||
src/common/bit_field.h
|
src/common/bit_field.h
|
||||||
src/common/bounded_threadsafe_queue.h
|
src/common/bounded_threadsafe_queue.h
|
||||||
src/common/concepts.h
|
src/common/concepts.h
|
||||||
@@ -661,9 +692,9 @@ set(COMMON src/common/logging/backend.cpp
|
|||||||
src/common/enum.h
|
src/common/enum.h
|
||||||
src/common/io_file.cpp
|
src/common/io_file.cpp
|
||||||
src/common/io_file.h
|
src/common/io_file.h
|
||||||
|
src/common/lru_cache.h
|
||||||
src/common/error.cpp
|
src/common/error.cpp
|
||||||
src/common/error.h
|
src/common/error.h
|
||||||
src/common/scope_exit.h
|
|
||||||
src/common/fixed_value.h
|
src/common/fixed_value.h
|
||||||
src/common/func_traits.h
|
src/common/func_traits.h
|
||||||
src/common/native_clock.cpp
|
src/common/native_clock.cpp
|
||||||
@@ -672,9 +703,15 @@ set(COMMON src/common/logging/backend.cpp
|
|||||||
src/common/path_util.h
|
src/common/path_util.h
|
||||||
src/common/object_pool.h
|
src/common/object_pool.h
|
||||||
src/common/polyfill_thread.h
|
src/common/polyfill_thread.h
|
||||||
|
src/common/range_lock.h
|
||||||
src/common/rdtsc.cpp
|
src/common/rdtsc.cpp
|
||||||
src/common/rdtsc.h
|
src/common/rdtsc.h
|
||||||
|
src/common/recursive_lock.cpp
|
||||||
|
src/common/recursive_lock.h
|
||||||
|
src/common/scope_exit.h
|
||||||
|
src/common/serdes.h
|
||||||
src/common/sha1.h
|
src/common/sha1.h
|
||||||
|
src/common/shared_first_mutex.h
|
||||||
src/common/signal_context.h
|
src/common/signal_context.h
|
||||||
src/common/signal_context.cpp
|
src/common/signal_context.cpp
|
||||||
src/common/singleton.h
|
src/common/singleton.h
|
||||||
@@ -713,22 +750,30 @@ set(CORE src/core/aerolib/stubs.cpp
|
|||||||
src/core/aerolib/aerolib.h
|
src/core/aerolib/aerolib.h
|
||||||
src/core/address_space.cpp
|
src/core/address_space.cpp
|
||||||
src/core/address_space.h
|
src/core/address_space.h
|
||||||
src/core/devices/base_device.cpp
|
src/core/file_sys/devices/base_device.cpp
|
||||||
src/core/devices/base_device.h
|
src/core/file_sys/devices/base_device.h
|
||||||
src/core/devices/ioccom.h
|
src/core/file_sys/devices/ioccom.h
|
||||||
src/core/devices/logger.cpp
|
src/core/file_sys/devices/logger.cpp
|
||||||
src/core/devices/logger.h
|
src/core/file_sys/devices/logger.h
|
||||||
src/core/devices/nop_device.h
|
src/core/file_sys/devices/nop_device.h
|
||||||
src/core/devices/console_device.cpp
|
src/core/file_sys/devices/console_device.cpp
|
||||||
src/core/devices/console_device.h
|
src/core/file_sys/devices/console_device.h
|
||||||
src/core/devices/deci_tty6_device.cpp
|
src/core/file_sys/devices/deci_tty6_device.cpp
|
||||||
src/core/devices/deci_tty6_device.h
|
src/core/file_sys/devices/deci_tty6_device.h
|
||||||
src/core/devices/random_device.cpp
|
src/core/file_sys/devices/random_device.cpp
|
||||||
src/core/devices/random_device.h
|
src/core/file_sys/devices/random_device.h
|
||||||
src/core/devices/urandom_device.cpp
|
src/core/file_sys/devices/rng_device.cpp
|
||||||
src/core/devices/urandom_device.h
|
src/core/file_sys/devices/rng_device.h
|
||||||
src/core/devices/srandom_device.cpp
|
src/core/file_sys/devices/urandom_device.cpp
|
||||||
src/core/devices/srandom_device.h
|
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/pfs.h
|
||||||
src/core/file_format/psf.cpp
|
src/core/file_format/psf.cpp
|
||||||
src/core/file_format/psf.h
|
src/core/file_format/psf.h
|
||||||
@@ -738,6 +783,8 @@ set(CORE src/core/aerolib/stubs.cpp
|
|||||||
src/core/file_format/trp.h
|
src/core/file_format/trp.h
|
||||||
src/core/file_sys/fs.cpp
|
src/core/file_sys/fs.cpp
|
||||||
src/core/file_sys/fs.h
|
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.cpp
|
||||||
src/core/loader/dwarf.h
|
src/core/loader/dwarf.h
|
||||||
src/core/loader/elf.cpp
|
src/core/loader/elf.cpp
|
||||||
@@ -755,6 +802,7 @@ set(CORE src/core/aerolib/stubs.cpp
|
|||||||
${SYSTEM_LIBS}
|
${SYSTEM_LIBS}
|
||||||
${HLE_LIBC_INTERNAL_LIB}
|
${HLE_LIBC_INTERNAL_LIB}
|
||||||
${PAD_LIB}
|
${PAD_LIB}
|
||||||
|
${SYSTEM_GESTURE_LIB}
|
||||||
${VIDEOOUT_LIB}
|
${VIDEOOUT_LIB}
|
||||||
${NP_LIBS}
|
${NP_LIBS}
|
||||||
${PNG_LIB}
|
${PNG_LIB}
|
||||||
@@ -773,6 +821,8 @@ set(CORE src/core/aerolib/stubs.cpp
|
|||||||
${DEV_TOOLS}
|
${DEV_TOOLS}
|
||||||
src/core/debug_state.cpp
|
src/core/debug_state.cpp
|
||||||
src/core/debug_state.h
|
src/core/debug_state.h
|
||||||
|
src/core/debugger.cpp
|
||||||
|
src/core/debugger.h
|
||||||
src/core/linker.cpp
|
src/core/linker.cpp
|
||||||
src/core/linker.h
|
src/core/linker.h
|
||||||
src/core/memory.cpp
|
src/core/memory.cpp
|
||||||
@@ -794,10 +844,10 @@ if (ARCHITECTURE STREQUAL "x86_64")
|
|||||||
src/core/cpu_patches.h)
|
src/core/cpu_patches.h)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(SHADER_RECOMPILER src/shader_recompiler/exception.h
|
set(SHADER_RECOMPILER src/shader_recompiler/profile.h
|
||||||
src/shader_recompiler/profile.h
|
|
||||||
src/shader_recompiler/recompiler.cpp
|
src/shader_recompiler/recompiler.cpp
|
||||||
src/shader_recompiler/recompiler.h
|
src/shader_recompiler/recompiler.h
|
||||||
|
src/shader_recompiler/resource.h
|
||||||
src/shader_recompiler/info.h
|
src/shader_recompiler/info.h
|
||||||
src/shader_recompiler/params.h
|
src/shader_recompiler/params.h
|
||||||
src/shader_recompiler/runtime_info.h
|
src/shader_recompiler/runtime_info.h
|
||||||
@@ -862,13 +912,16 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h
|
|||||||
src/shader_recompiler/ir/passes/ring_access_elimination.cpp
|
src/shader_recompiler/ir/passes/ring_access_elimination.cpp
|
||||||
src/shader_recompiler/ir/passes/shader_info_collection_pass.cpp
|
src/shader_recompiler/ir/passes/shader_info_collection_pass.cpp
|
||||||
src/shader_recompiler/ir/passes/shared_memory_barrier_pass.cpp
|
src/shader_recompiler/ir/passes/shared_memory_barrier_pass.cpp
|
||||||
|
src/shader_recompiler/ir/passes/shared_memory_simplify_pass.cpp
|
||||||
src/shader_recompiler/ir/passes/shared_memory_to_storage_pass.cpp
|
src/shader_recompiler/ir/passes/shared_memory_to_storage_pass.cpp
|
||||||
src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp
|
src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp
|
||||||
|
src/shader_recompiler/ir/abstract_syntax_list.cpp
|
||||||
src/shader_recompiler/ir/abstract_syntax_list.h
|
src/shader_recompiler/ir/abstract_syntax_list.h
|
||||||
src/shader_recompiler/ir/attribute.cpp
|
src/shader_recompiler/ir/attribute.cpp
|
||||||
src/shader_recompiler/ir/attribute.h
|
src/shader_recompiler/ir/attribute.h
|
||||||
src/shader_recompiler/ir/basic_block.cpp
|
src/shader_recompiler/ir/basic_block.cpp
|
||||||
src/shader_recompiler/ir/basic_block.h
|
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/condition.h
|
||||||
src/shader_recompiler/ir/ir_emitter.cpp
|
src/shader_recompiler/ir/ir_emitter.cpp
|
||||||
src/shader_recompiler/ir/ir_emitter.h
|
src/shader_recompiler/ir/ir_emitter.h
|
||||||
@@ -876,8 +929,10 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h
|
|||||||
src/shader_recompiler/ir/opcodes.cpp
|
src/shader_recompiler/ir/opcodes.cpp
|
||||||
src/shader_recompiler/ir/opcodes.h
|
src/shader_recompiler/ir/opcodes.h
|
||||||
src/shader_recompiler/ir/opcodes.inc
|
src/shader_recompiler/ir/opcodes.inc
|
||||||
|
src/shader_recompiler/ir/operand_helper.h
|
||||||
src/shader_recompiler/ir/patch.cpp
|
src/shader_recompiler/ir/patch.cpp
|
||||||
src/shader_recompiler/ir/patch.h
|
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.cpp
|
||||||
src/shader_recompiler/ir/post_order.h
|
src/shader_recompiler/ir/post_order.h
|
||||||
src/shader_recompiler/ir/program.cpp
|
src/shader_recompiler/ir/program.cpp
|
||||||
@@ -890,22 +945,34 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h
|
|||||||
src/shader_recompiler/ir/value.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/liverpool.h
|
||||||
src/video_core/amdgpu/pixel_format.cpp
|
src/video_core/amdgpu/pixel_format.cpp
|
||||||
src/video_core/amdgpu/pixel_format.h
|
src/video_core/amdgpu/pixel_format.h
|
||||||
src/video_core/amdgpu/pm4_cmds.h
|
src/video_core/amdgpu/pm4_cmds.h
|
||||||
src/video_core/amdgpu/pm4_opcodes.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/resource.h
|
||||||
src/video_core/amdgpu/types.h
|
src/video_core/amdgpu/tiling.cpp
|
||||||
src/video_core/amdgpu/default_context.cpp
|
src/video_core/amdgpu/tiling.h
|
||||||
src/video_core/buffer_cache/buffer.cpp
|
src/video_core/buffer_cache/buffer.cpp
|
||||||
src/video_core/buffer_cache/buffer.h
|
src/video_core/buffer_cache/buffer.h
|
||||||
src/video_core/buffer_cache/buffer_cache.cpp
|
src/video_core/buffer_cache/buffer_cache.cpp
|
||||||
src/video_core/buffer_cache/buffer_cache.h
|
src/video_core/buffer_cache/buffer_cache.h
|
||||||
src/video_core/buffer_cache/memory_tracker_base.h
|
src/video_core/buffer_cache/fault_manager.cpp
|
||||||
|
src/video_core/buffer_cache/fault_manager.h
|
||||||
|
src/video_core/buffer_cache/memory_tracker.h
|
||||||
src/video_core/buffer_cache/range_set.h
|
src/video_core/buffer_cache/range_set.h
|
||||||
src/video_core/buffer_cache/word_manager.h
|
src/video_core/buffer_cache/region_definitions.h
|
||||||
|
src/video_core/buffer_cache/region_manager.h
|
||||||
src/video_core/renderer_vulkan/liverpool_to_vk.cpp
|
src/video_core/renderer_vulkan/liverpool_to_vk.cpp
|
||||||
src/video_core/renderer_vulkan/liverpool_to_vk.h
|
src/video_core/renderer_vulkan/liverpool_to_vk.h
|
||||||
src/video_core/renderer_vulkan/vk_common.cpp
|
src/video_core/renderer_vulkan/vk_common.cpp
|
||||||
@@ -922,6 +989,8 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp
|
|||||||
src/video_core/renderer_vulkan/vk_pipeline_cache.h
|
src/video_core/renderer_vulkan/vk_pipeline_cache.h
|
||||||
src/video_core/renderer_vulkan/vk_pipeline_common.cpp
|
src/video_core/renderer_vulkan/vk_pipeline_common.cpp
|
||||||
src/video_core/renderer_vulkan/vk_pipeline_common.h
|
src/video_core/renderer_vulkan/vk_pipeline_common.h
|
||||||
|
src/video_core/renderer_vulkan/vk_pipeline_serialization.cpp
|
||||||
|
src/video_core/renderer_vulkan/vk_pipeline_serialization.h
|
||||||
src/video_core/renderer_vulkan/vk_platform.cpp
|
src/video_core/renderer_vulkan/vk_platform.cpp
|
||||||
src/video_core/renderer_vulkan/vk_platform.h
|
src/video_core/renderer_vulkan/vk_platform.h
|
||||||
src/video_core/renderer_vulkan/vk_presenter.cpp
|
src/video_core/renderer_vulkan/vk_presenter.cpp
|
||||||
@@ -942,6 +1011,10 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp
|
|||||||
src/video_core/renderer_vulkan/host_passes/fsr_pass.h
|
src/video_core/renderer_vulkan/host_passes/fsr_pass.h
|
||||||
src/video_core/renderer_vulkan/host_passes/pp_pass.cpp
|
src/video_core/renderer_vulkan/host_passes/pp_pass.cpp
|
||||||
src/video_core/renderer_vulkan/host_passes/pp_pass.h
|
src/video_core/renderer_vulkan/host_passes/pp_pass.h
|
||||||
|
src/video_core/texture_cache/blit_helper.cpp
|
||||||
|
src/video_core/texture_cache/blit_helper.h
|
||||||
|
src/video_core/texture_cache/host_compatibility.cpp
|
||||||
|
src/video_core/texture_cache/host_compatibility.h
|
||||||
src/video_core/texture_cache/image.cpp
|
src/video_core/texture_cache/image.cpp
|
||||||
src/video_core/texture_cache/image.h
|
src/video_core/texture_cache/image.h
|
||||||
src/video_core/texture_cache/image_info.cpp
|
src/video_core/texture_cache/image_info.cpp
|
||||||
@@ -955,7 +1028,8 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp
|
|||||||
src/video_core/texture_cache/tile_manager.cpp
|
src/video_core/texture_cache/tile_manager.cpp
|
||||||
src/video_core/texture_cache/tile_manager.h
|
src/video_core/texture_cache/tile_manager.h
|
||||||
src/video_core/texture_cache/types.h
|
src/video_core/texture_cache/types.h
|
||||||
src/video_core/texture_cache/host_compatibility.h
|
src/video_core/cache_storage.cpp
|
||||||
|
src/video_core/cache_storage.h
|
||||||
src/video_core/page_manager.cpp
|
src/video_core/page_manager.cpp
|
||||||
src/video_core/page_manager.h
|
src/video_core/page_manager.h
|
||||||
src/video_core/multi_level_page_table.h
|
src/video_core/multi_level_page_table.h
|
||||||
@@ -991,101 +1065,27 @@ set(EMULATOR src/emulator.cpp
|
|||||||
src/sdl_window.cpp
|
src/sdl_window.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# The above is shared in SDL and Qt version (TODO share them all)
|
add_executable(shadps4
|
||||||
|
${AUDIO_CORE}
|
||||||
if(ENABLE_QT_GUI)
|
${IMGUI}
|
||||||
qt_add_resources(RESOURCE_FILES src/shadps4.qrc)
|
${INPUT}
|
||||||
|
${COMMON}
|
||||||
if (ENABLE_UPDATER)
|
${CORE}
|
||||||
set(UPDATER src/qt_gui/check_update.cpp
|
${SHADER_RECOMPILER}
|
||||||
src/qt_gui/check_update.h
|
${VIDEO_CORE}
|
||||||
)
|
${EMULATOR}
|
||||||
endif()
|
src/main.cpp
|
||||||
|
src/emulator.cpp
|
||||||
set(QT_GUI src/qt_gui/about_dialog.cpp
|
src/emulator.h
|
||||||
src/qt_gui/about_dialog.h
|
src/sdl_window.h
|
||||||
src/qt_gui/about_dialog.ui
|
src/sdl_window.cpp
|
||||||
src/qt_gui/background_music_player.cpp
|
|
||||||
src/qt_gui/background_music_player.h
|
|
||||||
src/qt_gui/cheats_patches.cpp
|
|
||||||
src/qt_gui/cheats_patches.h
|
|
||||||
src/qt_gui/compatibility_info.cpp
|
|
||||||
src/qt_gui/compatibility_info.h
|
|
||||||
src/qt_gui/control_settings.cpp
|
|
||||||
src/qt_gui/control_settings.h
|
|
||||||
src/qt_gui/control_settings.ui
|
|
||||||
src/qt_gui/kbm_gui.cpp
|
|
||||||
src/qt_gui/kbm_gui.h
|
|
||||||
src/qt_gui/kbm_gui.ui
|
|
||||||
src/qt_gui/main_window_ui.h
|
|
||||||
src/qt_gui/main_window.cpp
|
|
||||||
src/qt_gui/main_window.h
|
|
||||||
src/qt_gui/gui_context_menus.h
|
|
||||||
src/qt_gui/game_list_utils.h
|
|
||||||
src/qt_gui/game_info.cpp
|
|
||||||
src/qt_gui/game_info.h
|
|
||||||
src/qt_gui/game_list_frame.cpp
|
|
||||||
src/qt_gui/game_list_frame.h
|
|
||||||
src/qt_gui/game_grid_frame.cpp
|
|
||||||
src/qt_gui/game_grid_frame.h
|
|
||||||
src/qt_gui/game_install_dialog.cpp
|
|
||||||
src/qt_gui/game_install_dialog.h
|
|
||||||
src/qt_gui/trophy_viewer.cpp
|
|
||||||
src/qt_gui/trophy_viewer.h
|
|
||||||
src/qt_gui/elf_viewer.cpp
|
|
||||||
src/qt_gui/elf_viewer.h
|
|
||||||
src/qt_gui/kbm_config_dialog.cpp
|
|
||||||
src/qt_gui/kbm_config_dialog.h
|
|
||||||
src/qt_gui/kbm_help_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/settings_dialog.cpp
|
|
||||||
src/qt_gui/settings_dialog.h
|
|
||||||
src/qt_gui/settings_dialog.ui
|
|
||||||
src/qt_gui/main.cpp
|
|
||||||
${EMULATOR}
|
|
||||||
${RESOURCE_FILES}
|
|
||||||
${TRANSLATIONS}
|
|
||||||
${UPDATER}
|
|
||||||
)
|
)
|
||||||
endif()
|
|
||||||
|
|
||||||
if (ENABLE_QT_GUI)
|
|
||||||
qt_add_executable(shadps4
|
|
||||||
${AUDIO_CORE}
|
|
||||||
${IMGUI}
|
|
||||||
${INPUT}
|
|
||||||
${QT_GUI}
|
|
||||||
${COMMON}
|
|
||||||
${CORE}
|
|
||||||
${SHADER_RECOMPILER}
|
|
||||||
${VIDEO_CORE}
|
|
||||||
${EMULATOR}
|
|
||||||
src/images/shadPS4.icns
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
add_executable(shadps4
|
|
||||||
${AUDIO_CORE}
|
|
||||||
${IMGUI}
|
|
||||||
${INPUT}
|
|
||||||
${COMMON}
|
|
||||||
${CORE}
|
|
||||||
${SHADER_RECOMPILER}
|
|
||||||
${VIDEO_CORE}
|
|
||||||
${EMULATOR}
|
|
||||||
src/main.cpp
|
|
||||||
src/emulator.cpp
|
|
||||||
src/emulator.h
|
|
||||||
src/sdl_window.h
|
|
||||||
src/sdl_window.cpp
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
create_target_directory_groups(shadps4)
|
create_target_directory_groups(shadps4)
|
||||||
|
|
||||||
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui gcn half::half ZLIB::ZLIB PNG::PNG)
|
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 SDL3_mixer::SDL3_mixer pugixml::pugixml)
|
||||||
|
target_link_libraries(shadps4 PRIVATE stb::headers libusb::usb lfreist-hwinfo::hwinfo nlohmann_json::nlohmann_json miniz)
|
||||||
|
|
||||||
target_compile_definitions(shadps4 PRIVATE IMGUI_USER_CONFIG="imgui/imgui_config.h")
|
target_compile_definitions(shadps4 PRIVATE IMGUI_USER_CONFIG="imgui/imgui_config.h")
|
||||||
target_compile_definitions(Dear_ImGui PRIVATE IMGUI_USER_CONFIG="${PROJECT_SOURCE_DIR}/src/imgui/imgui_config.h")
|
target_compile_definitions(Dear_ImGui PRIVATE IMGUI_USER_CONFIG="${PROJECT_SOURCE_DIR}/src/imgui/imgui_config.h")
|
||||||
@@ -1105,23 +1105,13 @@ endif()
|
|||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
# Include MoltenVK, along with an ICD file so it can be found by the system Vulkan loader if used for loading layers.
|
# Include MoltenVK, along with an ICD file so it can be found by the system Vulkan loader if used for loading layers.
|
||||||
if (ENABLE_QT_GUI)
|
set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path")
|
||||||
set(MVK_BUNDLE_PATH "Resources/vulkan/icd.d")
|
set(MVK_DST ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path/../${MVK_BUNDLE_PATH}")
|
set(MVK_DYLIB_SRC ${CMAKE_CURRENT_BINARY_DIR}/externals/MoltenVK/MoltenVK/libMoltenVK.dylib)
|
||||||
set(MVK_DST ${CMAKE_CURRENT_BINARY_DIR}/shadps4.app/Contents/${MVK_BUNDLE_PATH})
|
|
||||||
else()
|
|
||||||
set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path")
|
|
||||||
set(MVK_DST ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(MVK_DYLIB_SRC ${CMAKE_CURRENT_BINARY_DIR}/externals/MoltenVK/libMoltenVK.dylib)
|
|
||||||
set(MVK_DYLIB_DST ${MVK_DST}/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)
|
set(MVK_ICD_DST ${MVK_DST}/MoltenVK_icd.json)
|
||||||
|
|
||||||
add_custom_command(
|
|
||||||
OUTPUT ${MVK_DST}
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${MVK_DST})
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${MVK_ICD_DST}
|
OUTPUT ${MVK_ICD_DST}
|
||||||
DEPENDS ${MVK_ICD_SRC} ${MVK_DST}
|
DEPENDS ${MVK_ICD_SRC} ${MVK_DST}
|
||||||
@@ -1136,42 +1126,30 @@ if (APPLE)
|
|||||||
|
|
||||||
if (ARCHITECTURE STREQUAL "x86_64")
|
if (ARCHITECTURE STREQUAL "x86_64")
|
||||||
# Reserve system-managed memory space.
|
# Reserve system-managed memory space.
|
||||||
target_link_options(shadps4 PRIVATE -Wl,-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()
|
endif()
|
||||||
|
|
||||||
# Replacement for std::chrono::time_zone
|
# 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 (NOT ENABLE_QT_GUI)
|
|
||||||
target_link_libraries(shadps4 PRIVATE SDL3::SDL3)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (ENABLE_QT_GUI)
|
|
||||||
target_link_libraries(shadps4 PRIVATE Qt6::Widgets Qt6::Concurrent Qt6::Network Qt6::Multimedia)
|
|
||||||
add_definitions(-DENABLE_QT_GUI)
|
|
||||||
if (ENABLE_UPDATER)
|
|
||||||
add_definitions(-DENABLE_UPDATER)
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
target_link_libraries(shadps4 PRIVATE mincore)
|
target_link_libraries(shadps4 PRIVATE mincore wepoll wbemuuid)
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
# MSVC likes putting opinions on what people can use, disable:
|
# MSVC likes putting opinions on what people can use, disable:
|
||||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS)
|
add_compile_definitions(_CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_DEPRECATE _SCL_SECURE_NO_WARNINGS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN)
|
add_compile_definitions(NOMINMAX WIN32_LEAN_AND_MEAN)
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
# Needed for conflicts with time.h of windows.h
|
# Needed for conflicts with time.h of windows.h
|
||||||
add_definitions(-D_TIMESPEC_DEFINED)
|
add_compile_definitions(_TIMESPEC_DEFINED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Target Windows 10 RS5
|
# Target Windows 10 RS5
|
||||||
add_definitions(-DNTDDI_VERSION=0x0A000006 -D_WIN32_WINNT=0x0A00 -DWINVER=0x0A00)
|
add_compile_definitions(NTDDI_VERSION=0x0A000006 _WIN32_WINNT=0x0A00 WINVER=0x0A00)
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
target_link_libraries(shadps4 PRIVATE clang_rt.builtins-x86_64.lib)
|
target_link_libraries(shadps4 PRIVATE clang_rt.builtins-x86_64.lib)
|
||||||
@@ -1190,13 +1168,20 @@ if (WIN32)
|
|||||||
else()
|
else()
|
||||||
target_link_options(shadps4 PRIVATE -Wl,--stack,2097152)
|
target_link_options(shadps4 PRIVATE -Wl,--stack,2097152)
|
||||||
endif()
|
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()
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
target_sources(shadps4 PRIVATE src/shadps4.rc)
|
target_sources(shadps4 PRIVATE src/shadps4.rc)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_definitions(-DBOOST_ASIO_STANDALONE)
|
add_compile_definitions(BOOST_ASIO_STANDALONE)
|
||||||
|
|
||||||
target_include_directories(shadps4 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
target_include_directories(shadps4 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
@@ -1213,6 +1198,7 @@ include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/CMakeRC.cmake")
|
|||||||
cmrc_add_resource_library(embedded-resources
|
cmrc_add_resource_library(embedded-resources
|
||||||
ALIAS res::embedded
|
ALIAS res::embedded
|
||||||
NAMESPACE res
|
NAMESPACE res
|
||||||
|
src/images/trophy.wav
|
||||||
src/images/bronze.png
|
src/images/bronze.png
|
||||||
src/images/gold.png
|
src/images/gold.png
|
||||||
src/images/platinum.png
|
src/images/platinum.png
|
||||||
@@ -1224,25 +1210,6 @@ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/imgui/renderer)
|
|||||||
add_dependencies(shadps4 ImGui_Resources)
|
add_dependencies(shadps4 ImGui_Resources)
|
||||||
target_include_directories(shadps4 PRIVATE ${IMGUI_RESOURCES_INCLUDE})
|
target_include_directories(shadps4 PRIVATE ${IMGUI_RESOURCES_INCLUDE})
|
||||||
|
|
||||||
if (ENABLE_QT_GUI)
|
|
||||||
set_target_properties(shadps4 PROPERTIES
|
|
||||||
# WIN32_EXECUTABLE ON
|
|
||||||
MACOSX_BUNDLE ON
|
|
||||||
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/dist/MacOSBundleInfo.plist.in"
|
|
||||||
MACOSX_BUNDLE_ICON_FILE "shadPS4.icns"
|
|
||||||
MACOSX_BUNDLE_SHORT_VERSION_STRING "${APP_VERSION}"
|
|
||||||
)
|
|
||||||
|
|
||||||
set_source_files_properties(src/images/shadPS4.icns PROPERTIES
|
|
||||||
MACOSX_PACKAGE_LOCATION Resources)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (UNIX AND NOT APPLE)
|
|
||||||
if (ENABLE_QT_GUI)
|
|
||||||
find_package(OpenSSL REQUIRED)
|
|
||||||
target_link_libraries(shadps4 PRIVATE ${OPENSSL_LIBRARIES})
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Discord RPC
|
# Discord RPC
|
||||||
if (ENABLE_DISCORD_RPC)
|
if (ENABLE_DISCORD_RPC)
|
||||||
@@ -1251,10 +1218,3 @@ endif()
|
|||||||
|
|
||||||
# Install rules
|
# Install rules
|
||||||
install(TARGETS shadps4 BUNDLE DESTINATION .)
|
install(TARGETS shadps4 BUNDLE DESTINATION .)
|
||||||
|
|
||||||
if (ENABLE_QT_GUI AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
|
||||||
install(FILES "dist/net.shadps4.shadPS4.desktop" DESTINATION "share/applications")
|
|
||||||
install(FILES "dist/net.shadps4.shadPS4.metainfo.xml" DESTINATION "share/metainfo")
|
|
||||||
install(FILES ".github/shadps4.png" DESTINATION "share/icons/hicolor/512x512/apps" RENAME "net.shadps4.shadPS4.png")
|
|
||||||
install(FILES "src/images/net.shadps4.shadPS4.svg" DESTINATION "share/icons/hicolor/scalable/apps")
|
|
||||||
endif()
|
|
||||||
|
|||||||
35
CMakePresets.json
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"version": 9,
|
||||||
|
"cmakeMinimumRequired": {
|
||||||
|
"major": 3,
|
||||||
|
"minor": 30,
|
||||||
|
"patch": 0
|
||||||
|
},
|
||||||
|
"include": ["CMake${hostSystemName}Presets.json"],
|
||||||
|
"configurePresets": [
|
||||||
|
{
|
||||||
|
"name": "x64-Clang-Debug",
|
||||||
|
"displayName": "Clang x64 Debug",
|
||||||
|
"inherits": ["x64-Clang-Base"],
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_BUILD_TYPE": "Debug"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x64-Clang-Release",
|
||||||
|
"displayName": "Clang x64 Release",
|
||||||
|
"inherits": ["x64-Clang-Base"],
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_BUILD_TYPE": "Release"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x64-Clang-RelWithDebInfo",
|
||||||
|
"displayName": "Clang x64 RelWithDebInfo",
|
||||||
|
"inherits": ["x64-Clang-Base"],
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
26
CMakeWindowsPresets.json
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"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-cl",
|
||||||
|
"CMAKE_CXX_COMPILER": "clang-cl",
|
||||||
|
"CMAKE_INSTALL_PREFIX": "${sourceDir}/Build/${presetName}"
|
||||||
|
},
|
||||||
|
"vendor": {
|
||||||
|
"microsoft.com/VisualStudioSettings/CMake/1.0": {
|
||||||
|
"intelliSenseMode": "windows-clang-x64"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
68
README.md
@@ -24,40 +24,40 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
|||||||
<img src="https://img.shields.io/github/stars/shadps4-emu/shadPS4" width="120">
|
<img src="https://img.shields.io/github/stars/shadps4-emu/shadPS4" width="120">
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<p align="center">
|
| Bloodborne by From Software | Hatsune Miku Project DIVA Future Tone by SEGA |
|
||||||
<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">
|
| Yakuza 0 by SEGA | DRIVECLUB™ by Evolution Studios |
|
||||||
<img src="https://github.com/shadps4-emu/shadPS4/blob/main/documents/Screenshots/4.png" width="400">
|
| :------------------------------------------------------------------------: | :------------------------------------------------------------------: |
|
||||||
</p>
|
|  |  |
|
||||||
|
|
||||||
# General information
|
# General information
|
||||||
|
|
||||||
**shadPS4** is an early **PlayStation 4** emulator for **Windows**, **Linux** and **macOS** written in C++.
|
**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/blob/main/documents/Quickstart/Quickstart.md).\
|
> [!IMPORTANT]
|
||||||
To verify that a game works, you can look at [**shadPS4 Game Compatibility**](https://github.com/shadps4-emu/shadps4-game-compatibility).\
|
> This is the emulator core, which does not include a GUI. If you just want to use the emulator as an end user, download the [**QtLauncher**](https://github.com/shadps4-emu/shadps4-qtlauncher/releases) instead.
|
||||||
|
|
||||||
|
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-compatibility/shadps4-game-compatibility).\
|
||||||
To discuss shadPS4 development, suggest ideas or to ask for help, join our [**Discord server**](https://discord.gg/bFJxfftGW6).\
|
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/).\
|
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
|
# Status
|
||||||
|
|
||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
> shadPS4 is early in development, don't expect a flawless experience.
|
> 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
|
# 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
|
# Building
|
||||||
|
|
||||||
> [!IMPORTANT]
|
|
||||||
> If you want to use shadPS4 to play your games, you don't have to follow the build instructions, you can simply download the emulator from either the [**release tab**](https://github.com/shadps4-emu/shadPS4/releases) or the [**action tab**](https://github.com/shadps4-emu/shadPS4/actions).
|
|
||||||
|
|
||||||
## Windows
|
## Windows
|
||||||
|
|
||||||
Check the build instructions for [**Windows**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/building-windows.md).
|
Check the build instructions for [**Windows**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/building-windows.md).
|
||||||
@@ -73,6 +73,22 @@ Check the build instructions for [**macOS**](https://github.com/shadps4-emu/shad
|
|||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
> macOS users need at least macOS 15.4 to run shadPS4. Due to GPU issues there are currently heavy bugs on Intel Macs.
|
> macOS users need at least macOS 15.4 to run shadPS4. Due to GPU issues there are currently heavy bugs on Intel Macs.
|
||||||
|
|
||||||
|
# Usage examples
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> For a user-friendly GUI, download the [**QtLauncher**](https://github.com/shadps4-emu/shadps4-qtlauncher/releases).
|
||||||
|
|
||||||
|
To get the list of all available commands and also a more detailed description of what each command does, please refer to the `--help` flag's output.
|
||||||
|
|
||||||
|
Below is a list of commonly used command patterns:
|
||||||
|
```sh
|
||||||
|
shadPS4 CUSA00001 # Searches for a game folder called CUSA00001 in the list of game install folders, and boots it.
|
||||||
|
shadPS4 --fullscreen true --config-clean CUSA00001 # the game argument is always the last one,
|
||||||
|
shadPS4 -g CUSA00001 --fullscreen true --config-clean # ...unless manually specified otherwise.
|
||||||
|
shadPS4 /path/to/game.elf # Boots a PS4 ELF file directly. Useful if you want to boot an executable that is not named eboot.bin.
|
||||||
|
shadPS4 CUSA00001 -- -flag1 -flag2 # Passes '-flag1' and '-flag2' to the game executable in argv.
|
||||||
|
```
|
||||||
|
|
||||||
# Debugging and reporting issues
|
# Debugging and reporting issues
|
||||||
|
|
||||||
For more information on how to test, debug and report issues with the emulator or games, read the [**Debugging documentation**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Debugging/Debugging.md).
|
For more information on how to test, debug and report issues with the emulator or games, read the [**Debugging documentation**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Debugging/Debugging.md).
|
||||||
@@ -124,8 +140,8 @@ Keyboard and mouse inputs can be customized in the settings menu by clicking the
|
|||||||
|
|
||||||
# Firmware files
|
# 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 `user/sys_modules` folder.
|
The following firmware modules are supported and must be placed in shadPS4's `sys_modules` folder.
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
@@ -133,13 +149,12 @@ The following firmware modules are supported and must be placed in shadPS4's `us
|
|||||||
|-------------------------|-------------------------|-------------------------|-------------------------|
|
|-------------------------|-------------------------|-------------------------|-------------------------|
|
||||||
| libSceCesCs.sprx | libSceFont.sprx | libSceFontFt.sprx | libSceFreeTypeOt.sprx |
|
| libSceCesCs.sprx | libSceFont.sprx | libSceFontFt.sprx | libSceFreeTypeOt.sprx |
|
||||||
| libSceJson.sprx | libSceJson2.sprx | libSceLibcInternal.sprx | libSceNgs2.sprx |
|
| libSceJson.sprx | libSceJson2.sprx | libSceLibcInternal.sprx | libSceNgs2.sprx |
|
||||||
| libSceRtc.sprx | libSceUlt.sprx | | |
|
| libSceUlt.sprx | | | |
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
> [!Caution]
|
> [!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.
|
||||||
> **We do not provide any information or support on how to do this**.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -148,7 +163,7 @@ The following firmware modules are supported and must be placed in shadPS4's `us
|
|||||||
- [**georgemoralis**](https://github.com/georgemoralis)
|
- [**georgemoralis**](https://github.com/georgemoralis)
|
||||||
- [**psucien**](https://github.com/psucien)
|
- [**psucien**](https://github.com/psucien)
|
||||||
- [**viniciuslrangel**](https://github.com/viniciuslrangel)
|
- [**viniciuslrangel**](https://github.com/viniciuslrangel)
|
||||||
- [**roamic**](https://github.com/vladmikhalin)
|
- [**roamic**](https://github.com/roamic)
|
||||||
- [**squidbus**](https://github.com/squidbus)
|
- [**squidbus**](https://github.com/squidbus)
|
||||||
- [**frodo**](https://github.com/baggins183)
|
- [**frodo**](https://github.com/baggins183)
|
||||||
- [**Stephen Miller**](https://github.com/StevenMiller123)
|
- [**Stephen Miller**](https://github.com/StevenMiller123)
|
||||||
@@ -158,18 +173,9 @@ Logo is done by [**Xphalnos**](https://github.com/Xphalnos)
|
|||||||
|
|
||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
If you want to contribute, please look the [**CONTRIBUTING.md**](https://github.com/shadps4-emu/shadPS4/blob/main/CONTRIBUTING.md) file.\
|
If you want to contribute, please read the [**CONTRIBUTING.md**](https://github.com/shadps4-emu/shadPS4/blob/main/CONTRIBUTING.md) file.\
|
||||||
Open a PR and we'll check it :)
|
Open a PR and we'll check it :)
|
||||||
|
|
||||||
# Translations
|
|
||||||
|
|
||||||
If you want to translate shadPS4 to your language we use [**Crowdin**](https://crowdin.com/project/shadps4-emulator).
|
|
||||||
# Contributors
|
|
||||||
|
|
||||||
<a href="https://github.com/shadps4-emu/shadPS4/graphs/contributors">
|
|
||||||
<img src="https://contrib.rocks/image?repo=shadps4-emu/shadPS4&max=24">
|
|
||||||
</a>
|
|
||||||
|
|
||||||
|
|
||||||
# Special Thanks
|
# Special Thanks
|
||||||
|
|
||||||
|
|||||||
13
REUSE.toml
@@ -5,10 +5,12 @@ path = [
|
|||||||
"REUSE.toml",
|
"REUSE.toml",
|
||||||
"crowdin.yml",
|
"crowdin.yml",
|
||||||
"CMakeSettings.json",
|
"CMakeSettings.json",
|
||||||
|
"CMakeDarwinPresets.json",
|
||||||
|
"CMakeLinuxPresets.json",
|
||||||
|
"CMakeWindowsPresets.json",
|
||||||
|
"CMakePresets.json",
|
||||||
".github/FUNDING.yml",
|
".github/FUNDING.yml",
|
||||||
".github/shadps4.png",
|
".github/shadps4.png",
|
||||||
".github/workflows/scripts/update_translation.sh",
|
|
||||||
".github/workflows/update_translation.yml",
|
|
||||||
".gitmodules",
|
".gitmodules",
|
||||||
"dist/MacOSBundleInfo.plist.in",
|
"dist/MacOSBundleInfo.plist.in",
|
||||||
"dist/net.shadps4.shadPS4.desktop",
|
"dist/net.shadps4.shadPS4.desktop",
|
||||||
@@ -29,7 +31,7 @@ path = [
|
|||||||
"src/images/discord.png",
|
"src/images/discord.png",
|
||||||
"src/images/dump_icon.png",
|
"src/images/dump_icon.png",
|
||||||
"src/images/exit_icon.png",
|
"src/images/exit_icon.png",
|
||||||
"src/images/file_icon.png",
|
"src/images/favorite_icon.png",
|
||||||
"src/images/trophy_icon.png",
|
"src/images/trophy_icon.png",
|
||||||
"src/images/flag_china.png",
|
"src/images/flag_china.png",
|
||||||
"src/images/flag_eu.png",
|
"src/images/flag_eu.png",
|
||||||
@@ -69,9 +71,10 @@ path = [
|
|||||||
"src/images/shadps4.svg",
|
"src/images/shadps4.svg",
|
||||||
"src/images/website.svg",
|
"src/images/website.svg",
|
||||||
"src/images/youtube.svg",
|
"src/images/youtube.svg",
|
||||||
"src/shadps4.qrc",
|
"src/images/trophy.wav",
|
||||||
|
"src/images/hotkey.png",
|
||||||
|
"src/images/game_settings.png",
|
||||||
"src/shadps4.rc",
|
"src/shadps4.rc",
|
||||||
"src/qt_gui/translations/update_translation.sh",
|
|
||||||
]
|
]
|
||||||
precedence = "aggregate"
|
precedence = "aggregate"
|
||||||
SPDX-FileCopyrightText = "shadPS4 Emulator Project"
|
SPDX-FileCopyrightText = "shadPS4 Emulator Project"
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
files:
|
|
||||||
- source: /src/qt_gui/translations/en_US.ts
|
|
||||||
translation: /%original_path%/%locale_with_underscore%.ts
|
|
||||||
20
dist/net.shadps4.shadPS4.metainfo.xml
vendored
@@ -18,25 +18,37 @@
|
|||||||
<screenshots>
|
<screenshots>
|
||||||
<screenshot type="default">
|
<screenshot type="default">
|
||||||
<image type="source" translate="no" >https://cdn.jsdelivr.net/gh/shadps4-emu/shadps4@main/documents/Screenshots/1.png</image>
|
<image type="source" translate="no" >https://cdn.jsdelivr.net/gh/shadps4-emu/shadps4@main/documents/Screenshots/1.png</image>
|
||||||
<caption>Bloodborne</caption>
|
<caption>Bloodborne by From Software</caption>
|
||||||
</screenshot>
|
</screenshot>
|
||||||
<screenshot>
|
<screenshot>
|
||||||
<image type="source" translate="no">https://cdn.jsdelivr.net/gh/shadps4-emu/shadps4@main/documents/Screenshots/2.png</image>
|
<image type="source" translate="no">https://cdn.jsdelivr.net/gh/shadps4-emu/shadps4@main/documents/Screenshots/2.png</image>
|
||||||
<caption>Hatsune Miku: Project DIVA Future Tone</caption>
|
<caption>Hatsune Miku Project DIVA Future Tone by SEGA</caption>
|
||||||
</screenshot>
|
</screenshot>
|
||||||
<screenshot>
|
<screenshot>
|
||||||
<image type="source" translate="no">https://cdn.jsdelivr.net/gh/shadps4-emu/shadps4@main/documents/Screenshots/3.png</image>
|
<image type="source" translate="no">https://cdn.jsdelivr.net/gh/shadps4-emu/shadps4@main/documents/Screenshots/3.png</image>
|
||||||
<caption>Yakuza 0</caption>
|
<caption>Yakuza 0 by SEGA</caption>
|
||||||
</screenshot>
|
</screenshot>
|
||||||
<screenshot>
|
<screenshot>
|
||||||
<image type="source" translate="no">https://cdn.jsdelivr.net/gh/shadps4-emu/shadps4@main/documents/Screenshots/4.png</image>
|
<image type="source" translate="no">https://cdn.jsdelivr.net/gh/shadps4-emu/shadps4@main/documents/Screenshots/4.png</image>
|
||||||
<caption>Persona 4 Golden</caption>
|
<caption>DRIVECLUB™ by Evolution Studios</caption>
|
||||||
</screenshot>
|
</screenshot>
|
||||||
</screenshots>
|
</screenshots>
|
||||||
<categories>
|
<categories>
|
||||||
<category translate="no">Game</category>
|
<category translate="no">Game</category>
|
||||||
</categories>
|
</categories>
|
||||||
<releases>
|
<releases>
|
||||||
|
<release version="0.12.5" date="2025-11-07">
|
||||||
|
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.12.5</url>
|
||||||
|
</release>
|
||||||
|
<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>
|
||||||
<release version="0.9.0" date="2025-05-22">
|
<release version="0.9.0" date="2025-05-22">
|
||||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.9.0</url>
|
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.9.0</url>
|
||||||
</release>
|
</release>
|
||||||
|
|||||||
@@ -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.
|
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>
|
<details>
|
||||||
<summary>Windows and Visual Studio</summary>
|
<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
|
- 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.
|
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.
|
(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.**\
|
- ⚠ **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 |
@@ -17,27 +17,23 @@ First and foremost, Clang 18 is the **recommended compiler** as it is used for o
|
|||||||
sudo apt install build-essential clang git cmake libasound2-dev \
|
sudo apt install build-essential clang git cmake libasound2-dev \
|
||||||
libpulse-dev libopenal-dev libssl-dev zlib1g-dev libedit-dev \
|
libpulse-dev libopenal-dev libssl-dev zlib1g-dev libedit-dev \
|
||||||
libudev-dev libevdev-dev libsdl2-dev libjack-dev libsndio-dev \
|
libudev-dev libevdev-dev libsdl2-dev libjack-dev libsndio-dev \
|
||||||
qt6-base-dev qt6-tools-dev qt6-multimedia-dev libvulkan-dev \
|
libvulkan-dev vulkan-validationlayers libpng-dev
|
||||||
vulkan-validationlayers libpng-dev
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Fedora
|
#### Fedora
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo dnf install clang git cmake libatomic alsa-lib-devel \
|
sudo dnf install clang git cmake libatomic alsa-lib-devel \
|
||||||
pipewire-jack-audio-connection-kit-devel openal-devel \
|
pipewire-jack-audio-connection-kit-devel openal-soft-devel \
|
||||||
openssl-devel libevdev-devel libudev-devel libXext-devel \
|
openssl-devel libevdev-devel libudev-devel libXext-devel \
|
||||||
qt6-qtbase-devel qt6-qtbase-private-devel \
|
vulkan-devel vulkan-validation-layers libpng-devel libuuid-devel
|
||||||
qt6-qtmultimedia-devel qt6-qtsvg-devel qt6-qttools-devel \
|
|
||||||
vulkan-devel vulkan-validation-layers libpng-devel
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Arch Linux
|
#### Arch Linux
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo pacman -S base-devel clang git cmake sndio jack2 openal \
|
sudo pacman -S base-devel clang git cmake sndio jack2 openal \
|
||||||
qt6-base qt6-declarative qt6-multimedia qt6-tools sdl2 \
|
sdl2 vulkan-validation-layers libpng
|
||||||
vulkan-validation-layers libpng
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note**: The `shadps4-git` AUR package is not maintained by any of the developers, and it uses the default compiler, which is often set to GCC. Use at your own discretion.
|
**Note**: The `shadps4-git` AUR package is not maintained by any of the developers, and it uses the default compiler, which is often set to GCC. Use at your own discretion.
|
||||||
@@ -48,9 +44,7 @@ sudo pacman -S base-devel clang git cmake sndio jack2 openal \
|
|||||||
sudo zypper install clang git cmake libasound2 libpulse-devel \
|
sudo zypper install clang git cmake libasound2 libpulse-devel \
|
||||||
libsndio7 libjack-devel openal-soft-devel libopenssl-devel \
|
libsndio7 libjack-devel openal-soft-devel libopenssl-devel \
|
||||||
zlib-devel libedit-devel systemd-devel libevdev-devel \
|
zlib-devel libedit-devel systemd-devel libevdev-devel \
|
||||||
qt6-base-devel qt6-multimedia-devel qt6-svg-devel \
|
vulkan-devel vulkan-validationlayers libpng-devel
|
||||||
qt6-linguist-devel qt6-gui-private-devel vulkan-devel \
|
|
||||||
vulkan-validationlayers libpng-devel
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### NixOS
|
#### NixOS
|
||||||
@@ -74,6 +68,7 @@ and install the dependencies on that container as cited above.
|
|||||||
This option is **highly recommended** for distributions with immutable/atomic filesystems (example: Fedora Kinoite, SteamOS).
|
This option is **highly recommended** for distributions with immutable/atomic filesystems (example: Fedora Kinoite, SteamOS).
|
||||||
|
|
||||||
### Cloning
|
### Cloning
|
||||||
|
The project uses submodules to manage dependencies, and they need to be initialized before you can build the project. To achieve this, make sure you've cloned the repository with the --recursive flag
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone --recursive https://github.com/shadps4-emu/shadPS4.git
|
git clone --recursive https://github.com/shadps4-emu/shadPS4.git
|
||||||
@@ -89,12 +84,12 @@ There are 3 options you can choose from. Option 1 is **highly recommended**.
|
|||||||
1. Generate the build directory in the shadPS4 directory.
|
1. Generate the build directory in the shadPS4 directory.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cmake -S . -B build/ -DENABLE_QT_GUI=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
cmake -S . -B build/ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
||||||
```
|
```
|
||||||
|
|
||||||
To disable the Qt GUI, remove the `-DENABLE_QT_GUI=ON` flag. To change the build type (for debugging), add `-DCMAKE_BUILD_TYPE=Debug`.
|
To change the build type (for debugging), add `-DCMAKE_BUILD_TYPE=Debug`.
|
||||||
|
|
||||||
2. Use CMake to build the project:
|
1. Use CMake to build the project:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cmake --build ./build --parallel$(nproc)
|
cmake --build ./build --parallel$(nproc)
|
||||||
@@ -102,18 +97,12 @@ cmake --build ./build --parallel$(nproc)
|
|||||||
|
|
||||||
If your computer freezes during this step, this could be caused by excessive system resource usage. In that case, remove `--parallel$(nproc)`.
|
If your computer freezes during this step, this could be caused by excessive system resource usage. In that case, remove `--parallel$(nproc)`.
|
||||||
|
|
||||||
Now run the emulator. If Qt was enabled at configure time:
|
Now run the emulator to get the list of options:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./build/shadps4
|
./build/shadps4
|
||||||
```
|
```
|
||||||
|
|
||||||
Otherwise, specify the path to your game's boot file:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./build/shadps4 /"PATH"/"TO"/"GAME"/"FOLDER"/eboot.bin
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also specify the Game ID as an argument for which game to boot, as long as the folder containing the games is specified in config.toml (example: Bloodborne (US) is CUSA00900).
|
You can also specify the Game ID as an argument for which game to boot, as long as the folder containing the games is specified in config.toml (example: Bloodborne (US) is CUSA00900).
|
||||||
#### Option 2: Configuring with cmake-gui
|
#### Option 2: Configuring with cmake-gui
|
||||||
|
|
||||||
@@ -141,10 +130,6 @@ Go to Settings, filter by `@ext:ms-vscode.cmake-tools configure` and disable thi
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
If you wish to build with the Qt GUI, add `-DENABLE_QT_GUI=ON` to the configure arguments:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
On the CMake tab, change the options as you wish, but make sure that it looks similar to or exactly like this:
|
On the CMake tab, change the options as you wish, but make sure that it looks similar to or exactly like this:
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -24,21 +24,6 @@ eval $(/opt/homebrew/bin/brew shellenv)
|
|||||||
brew install clang-format cmake
|
brew install clang-format cmake
|
||||||
```
|
```
|
||||||
|
|
||||||
Next, install x86_64 Qt. You can skip these steps and move on to **Cloning and compiling** if you do not intend to build the Qt GUI.
|
|
||||||
|
|
||||||
**If you are on an ARM Mac:**
|
|
||||||
```
|
|
||||||
# Installs x86_64 Homebrew to /usr/local
|
|
||||||
arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
|
||||||
# Installs libraries.
|
|
||||||
arch -x86_64 /usr/local/bin/brew install qt@6
|
|
||||||
```
|
|
||||||
|
|
||||||
**If you are on an x86_64 Mac:**
|
|
||||||
```
|
|
||||||
brew install qt@6
|
|
||||||
```
|
|
||||||
|
|
||||||
### Cloning and compiling:
|
### Cloning and compiling:
|
||||||
|
|
||||||
Clone the repository recursively:
|
Clone the repository recursively:
|
||||||
@@ -52,8 +37,6 @@ Generate the build directory in the shadPS4 directory:
|
|||||||
cmake -S . -B build/ -DCMAKE_OSX_ARCHITECTURES=x86_64
|
cmake -S . -B build/ -DCMAKE_OSX_ARCHITECTURES=x86_64
|
||||||
```
|
```
|
||||||
|
|
||||||
If you want to build the Qt GUI, add `-DENABLE_QT_GUI=ON` to the end of this command as well.
|
|
||||||
|
|
||||||
Enter the directory:
|
Enter the directory:
|
||||||
```
|
```
|
||||||
cd build/
|
cd build/
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2024 shadPS4 Emulator Project
|
SPDX-FileCopyrightText: 2025 shadPS4 Emulator Project
|
||||||
SPDX-License-Identifier: GPL-2.0-or-later
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
-->
|
-->
|
||||||
|
|
||||||
# Build shadPS4 for Windows
|
# 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.
|
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.
|
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,26 +19,8 @@ Note: **ARM64 is not supported!** As of writing, it will not build nor run. The
|
|||||||
Once you are within the installer:
|
Once you are within the installer:
|
||||||
|
|
||||||
1. Select `Desktop development with C++`
|
1. Select `Desktop development with C++`
|
||||||
2. Go to "Individual Components" tab
|
2. Go to "Individual Components" tab then search and select both `C++ Clang Compiler for Windows` and `MSBuild support for LLVM`
|
||||||
3. Search and select `C++ Clang Compiler for Windows` and `MSBuild support for LLVM`
|
3. Continue the installation
|
||||||
4. 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`.
|
|
||||||
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.
|
|
||||||
|
|
||||||
2. Download and install [Qt Visual Studio Tools](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2022)
|
|
||||||
|
|
||||||
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`
|
|
||||||
3. Enable the default checkmark on the new version you just created.
|
|
||||||
|
|
||||||
### (Prerequisite) Download [**Git for Windows**](https://git-scm.com/download/win)
|
### (Prerequisite) Download [**Git for Windows**](https://git-scm.com/download/win)
|
||||||
|
|
||||||
@@ -51,22 +35,12 @@ Go through the Git for Windows installation as normal
|
|||||||
### Compiling with Visual Studio GUI
|
### 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`
|
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.
|
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:
|
3. Change the project to build to shadps4.exe
|
||||||
1. Click x64-Clang-Release and select "Manage Configurations"
|
4. Build -> Build All
|
||||||
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
|
|
||||||
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\`
|
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"`
|
|
||||||
(Change Qt path if you've installed it to non-default path)
|
|
||||||
|
|
||||||
## Option 2: MSYS2/MinGW
|
## Option 2: MSYS2/MinGW
|
||||||
|
|
||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
@@ -83,13 +57,10 @@ Normal x86-based computers, follow:
|
|||||||
1. Open "MSYS2 MINGW64" from your new applications
|
1. Open "MSYS2 MINGW64" from your new applications
|
||||||
2. Run `pacman -Syu`, let it complete;
|
2. Run `pacman -Syu`, let it complete;
|
||||||
3. Run `pacman -S --needed git mingw-w64-x86_64-binutils mingw-w64-x86_64-clang mingw-w64-x86_64-cmake mingw-w64-x86_64-rapidjson mingw-w64-x86_64-ninja mingw-w64-x86_64-ffmpeg`
|
3. Run `pacman -S --needed git mingw-w64-x86_64-binutils mingw-w64-x86_64-clang mingw-w64-x86_64-cmake mingw-w64-x86_64-rapidjson mingw-w64-x86_64-ninja mingw-w64-x86_64-ffmpeg`
|
||||||
1. Optional (Qt only): run `pacman -S --needed mingw-w64-x86_64-qt6-base mingw-w64-x86_64-qt6-tools mingw-w64-x86_64-qt6-multimedia`
|
|
||||||
4. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4`
|
4. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4`
|
||||||
5. Run `cd shadPS4`
|
5. Run `cd shadPS4`
|
||||||
6. Run `cmake -S . -B build -DCMAKE_C_COMPILER="clang.exe" -DCMAKE_CXX_COMPILER="clang++.exe" -DCMAKE_CXX_FLAGS="-O2 -march=native"`
|
6. Run `cmake -S . -B build -DCMAKE_C_COMPILER="clang.exe" -DCMAKE_CXX_COMPILER="clang++.exe" -DCMAKE_CXX_FLAGS="-O2 -march=native"`
|
||||||
1. Optional (Qt only): add `-DENABLE_QT_GUI=ON`
|
|
||||||
7. Run `cmake --build build`
|
7. Run `cmake --build build`
|
||||||
1. Optional (Qt only): run `windeployqt6 build/shadps4.exe`
|
|
||||||
8. To run the finished product, run `./build/shadPS4.exe`
|
8. To run the finished product, run `./build/shadPS4.exe`
|
||||||
|
|
||||||
ARM64-based computers, follow:
|
ARM64-based computers, follow:
|
||||||
@@ -97,13 +68,10 @@ ARM64-based computers, follow:
|
|||||||
1. Open "MSYS2 CLANGARM64" from your new applications
|
1. Open "MSYS2 CLANGARM64" from your new applications
|
||||||
2. Run `pacman -Syu`, let it complete;
|
2. Run `pacman -Syu`, let it complete;
|
||||||
3. Run `pacman -S --needed git mingw-w64-clang-aarch64-binutils mingw-w64-clang-aarch64-clang mingw-w64-clang-aarch64-rapidjson mingw-w64-clang-aarch64-cmake mingw-w64-clang-aarch64-ninja mingw-w64-clang-aarch64-ffmpeg`
|
3. Run `pacman -S --needed git mingw-w64-clang-aarch64-binutils mingw-w64-clang-aarch64-clang mingw-w64-clang-aarch64-rapidjson mingw-w64-clang-aarch64-cmake mingw-w64-clang-aarch64-ninja mingw-w64-clang-aarch64-ffmpeg`
|
||||||
1. Optional (Qt only): run `pacman -S --needed mingw-w64-clang-aarch64-qt6-base mingw-w64-clang-aarch64-qt6-tools mingw-w64-clang-aarch64-qt6-multimedia`
|
|
||||||
4. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4`
|
4. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4`
|
||||||
5. Run `cd shadPS4`
|
5. Run `cd shadPS4`
|
||||||
6. Run `cmake -S . -B build -DCMAKE_C_COMPILER="clang.exe" -DCMAKE_CXX_COMPILER="clang++.exe" -DCMAKE_CXX_FLAGS="-O2 -march=native"`
|
6. Run `cmake -S . -B build -DCMAKE_C_COMPILER="clang.exe" -DCMAKE_CXX_COMPILER="clang++.exe" -DCMAKE_CXX_FLAGS="-O2 -march=native"`
|
||||||
1. Optional (Qt only): add `-DENABLE_QT_GUI=ON`
|
|
||||||
7. Run `cmake --build build`
|
7. Run `cmake --build build`
|
||||||
1. Optional (Qt only): run `windeployqt6 build/shadps4.exe`
|
|
||||||
8. To run the finished product, run `./build/shadPS4.exe`
|
8. To run the finished product, run `./build/shadPS4.exe`
|
||||||
|
|
||||||
## Note on MSYS2 builds
|
## Note on MSYS2 builds
|
||||||
|
|||||||
38
externals/CMakeLists.txt
vendored
@@ -63,6 +63,18 @@ if (NOT TARGET SDL3::SDL3)
|
|||||||
add_subdirectory(sdl3)
|
add_subdirectory(sdl3)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# SDL3_mixer
|
||||||
|
if (NOT TARGET SDL3_mixer::SDL3_mixer)
|
||||||
|
set(SDLMIXER_FLAC OFF)
|
||||||
|
set(SDLMIXER_OGG OFF)
|
||||||
|
set(SDLMIXER_MOD OFF)
|
||||||
|
set(SDLMIXER_MIDI OFF)
|
||||||
|
set(SDLMIXER_OPUS OFF)
|
||||||
|
set(SDLMIXER_WAVPACK OFF)
|
||||||
|
set(BUILD_SHARED_LIBS OFF)
|
||||||
|
add_subdirectory(sdl3_mixer)
|
||||||
|
endif()
|
||||||
|
|
||||||
# vulkan-headers
|
# vulkan-headers
|
||||||
if (NOT TARGET Vulkan::Headers)
|
if (NOT TARGET Vulkan::Headers)
|
||||||
set(VULKAN_HEADERS_ENABLE_MODULE OFF)
|
set(VULKAN_HEADERS_ENABLE_MODULE OFF)
|
||||||
@@ -140,7 +152,7 @@ endif()
|
|||||||
# sirit
|
# sirit
|
||||||
add_subdirectory(sirit)
|
add_subdirectory(sirit)
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
target_compile_options(sirit PUBLIC "-Wno-error=unused-command-line-argument")
|
target_compile_options(sirit PRIVATE "-Wno-error=unused-command-line-argument")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# half
|
# half
|
||||||
@@ -197,7 +209,7 @@ endif()
|
|||||||
|
|
||||||
# libusb
|
# libusb
|
||||||
if (NOT TARGET libusb::usb)
|
if (NOT TARGET libusb::usb)
|
||||||
add_subdirectory(libusb)
|
add_subdirectory(ext-libusb)
|
||||||
add_library(libusb::usb ALIAS usb-1.0)
|
add_library(libusb::usb ALIAS usb-1.0)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -216,6 +228,10 @@ if (NOT TARGET stb::headers)
|
|||||||
add_library(stb::headers ALIAS stb)
|
add_library(stb::headers ALIAS stb)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# hwinfo
|
||||||
|
set(HWINFO_STATIC ON)
|
||||||
|
add_subdirectory(hwinfo)
|
||||||
|
|
||||||
# Apple-only dependencies
|
# Apple-only dependencies
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
# date
|
# date
|
||||||
@@ -227,6 +243,24 @@ if (APPLE)
|
|||||||
|
|
||||||
# MoltenVK
|
# MoltenVK
|
||||||
if (NOT TARGET MoltenVK)
|
if (NOT TARGET MoltenVK)
|
||||||
|
set(MVK_EXCLUDE_SPIRV_TOOLS ON)
|
||||||
|
set(MVK_USE_METAL_PRIVATE_API ON)
|
||||||
add_subdirectory(MoltenVK)
|
add_subdirectory(MoltenVK)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (NOT TARGET epoll-shim)
|
||||||
|
add_subdirectory(epoll-shim)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
#windows only
|
||||||
|
if (WIN32)
|
||||||
|
add_subdirectory(ext-wepoll)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#nlohmann json
|
||||||
|
set(JSON_BuildTests OFF CACHE INTERNAL "")
|
||||||
|
add_subdirectory(json)
|
||||||
|
|
||||||
|
# miniz
|
||||||
|
add_subdirectory(miniz)
|
||||||
|
|||||||
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
2
externals/ffmpeg-core
vendored
2
externals/fmt
vendored
1
externals/hwinfo
vendored
Submodule
1
externals/json
vendored
Submodule
1
externals/libusb
vendored
1
externals/miniz
vendored
Submodule
2
externals/sdl3
vendored
1
externals/sdl3_mixer
vendored
Submodule
2
externals/sirit
vendored
2
externals/vulkan-headers
vendored
73
shell.nix
@@ -6,54 +6,47 @@ with import (fetchTarball "https://github.com/nixos/nixpkgs/archive/cfd19cdc5468
|
|||||||
pkgs.mkShell {
|
pkgs.mkShell {
|
||||||
name = "shadps4-build-env";
|
name = "shadps4-build-env";
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = with pkgs; [
|
||||||
pkgs.llvmPackages_18.clang
|
llvmPackages_18.clang
|
||||||
pkgs.cmake
|
cmake
|
||||||
pkgs.pkg-config
|
pkg-config
|
||||||
pkgs.git
|
git
|
||||||
|
util-linux
|
||||||
];
|
];
|
||||||
|
|
||||||
buildInputs = [
|
buildInputs = with pkgs; [
|
||||||
pkgs.alsa-lib
|
alsa-lib
|
||||||
pkgs.libpulseaudio
|
libpulseaudio
|
||||||
pkgs.openal
|
openal
|
||||||
pkgs.openssl
|
zlib
|
||||||
pkgs.zlib
|
libedit
|
||||||
pkgs.libedit
|
udev
|
||||||
pkgs.udev
|
libevdev
|
||||||
pkgs.libevdev
|
SDL2
|
||||||
pkgs.SDL2
|
jack2
|
||||||
pkgs.jack2
|
sndio
|
||||||
pkgs.sndio
|
|
||||||
pkgs.qt6.qtbase
|
|
||||||
pkgs.qt6.qttools
|
|
||||||
pkgs.qt6.qtmultimedia
|
|
||||||
|
|
||||||
pkgs.vulkan-headers
|
vulkan-headers
|
||||||
pkgs.vulkan-utility-libraries
|
vulkan-utility-libraries
|
||||||
pkgs.vulkan-tools
|
vulkan-tools
|
||||||
|
|
||||||
pkgs.ffmpeg
|
ffmpeg
|
||||||
pkgs.fmt
|
fmt
|
||||||
pkgs.glslang
|
glslang
|
||||||
pkgs.libxkbcommon
|
libxkbcommon
|
||||||
pkgs.wayland
|
wayland
|
||||||
pkgs.xorg.libxcb
|
xorg.libxcb
|
||||||
pkgs.xorg.xcbutil
|
xorg.xcbutil
|
||||||
pkgs.xorg.xcbutilkeysyms
|
xorg.xcbutilkeysyms
|
||||||
pkgs.xorg.xcbutilwm
|
xorg.xcbutilwm
|
||||||
pkgs.sdl3
|
sdl3
|
||||||
pkgs.stb
|
stb
|
||||||
pkgs.qt6.qtwayland
|
wayland-protocols
|
||||||
pkgs.wayland-protocols
|
libpng
|
||||||
pkgs.libpng
|
|
||||||
];
|
];
|
||||||
|
|
||||||
shellHook = ''
|
shellHook = ''
|
||||||
echo "Entering shadPS4 dev shell"
|
echo "Entering shadPS4 dev shell"
|
||||||
export QT_QPA_PLATFORM="wayland"
|
|
||||||
export QT_PLUGIN_PATH="${pkgs.qt6.qtwayland}/lib/qt-6/plugins:${pkgs.qt6.qtbase}/lib/qt-6/plugins"
|
|
||||||
export QML2_IMPORT_PATH="${pkgs.qt6.qtbase}/lib/qt-6/qml"
|
|
||||||
export CMAKE_PREFIX_PATH="${pkgs.vulkan-headers}:$CMAKE_PREFIX_PATH"
|
export CMAKE_PREFIX_PATH="${pkgs.vulkan-headers}:$CMAKE_PREFIX_PATH"
|
||||||
|
|
||||||
# OpenGL
|
# OpenGL
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ public:
|
|||||||
void unlock() {
|
void unlock() {
|
||||||
pthread_mutex_unlock(&mutex);
|
pthread_mutex_unlock(&mutex);
|
||||||
}
|
}
|
||||||
|
[[nodiscard]] bool try_lock() {
|
||||||
|
return pthread_mutex_trylock(&mutex) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
pthread_mutex_t mutex = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;
|
pthread_mutex_t mutex = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;
|
||||||
|
|||||||
406
src/common/bit_array.h
Normal file
@@ -0,0 +1,406 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cstddef>
|
||||||
|
#include "common/types.h"
|
||||||
|
|
||||||
|
#ifdef __AVX2__
|
||||||
|
#define BIT_ARRAY_USE_AVX
|
||||||
|
#include <immintrin.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
template <size_t N>
|
||||||
|
class BitArray {
|
||||||
|
static_assert(N % 64 == 0, "BitArray size must be a multiple of 64 bits.");
|
||||||
|
|
||||||
|
static constexpr size_t BITS_PER_WORD = 64;
|
||||||
|
static constexpr size_t WORD_COUNT = N / BITS_PER_WORD;
|
||||||
|
static constexpr size_t WORDS_PER_AVX = 4;
|
||||||
|
static constexpr size_t AVX_WORD_COUNT = WORD_COUNT / WORDS_PER_AVX;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using Range = std::pair<size_t, size_t>;
|
||||||
|
|
||||||
|
class Iterator {
|
||||||
|
public:
|
||||||
|
explicit Iterator(const BitArray& bit_array_, u64 start) : bit_array(bit_array_) {
|
||||||
|
range = bit_array.FirstRangeFrom(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator& operator++() {
|
||||||
|
range = bit_array.FirstRangeFrom(range.second);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Iterator& other) const {
|
||||||
|
return range == other.range;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Iterator& other) const {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Range& operator*() const {
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Range* operator->() const {
|
||||||
|
return ⦥
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const BitArray& bit_array;
|
||||||
|
Range range;
|
||||||
|
};
|
||||||
|
|
||||||
|
using const_iterator = Iterator;
|
||||||
|
using iterator_category = std::forward_iterator_tag;
|
||||||
|
using value_type = Range;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using pointer = const Range*;
|
||||||
|
using reference = const Range&;
|
||||||
|
|
||||||
|
BitArray() = default;
|
||||||
|
BitArray(const BitArray& other) = default;
|
||||||
|
BitArray& operator=(const BitArray& other) = default;
|
||||||
|
BitArray(BitArray&& other) noexcept = default;
|
||||||
|
BitArray& operator=(BitArray&& other) noexcept = default;
|
||||||
|
~BitArray() = default;
|
||||||
|
|
||||||
|
BitArray(const BitArray& other, size_t start, size_t end) {
|
||||||
|
if (start >= end || end > N) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const size_t first_word = start / BITS_PER_WORD;
|
||||||
|
const size_t last_word = (end - 1) / BITS_PER_WORD;
|
||||||
|
const size_t start_bit = start % BITS_PER_WORD;
|
||||||
|
const size_t end_bit = (end - 1) % BITS_PER_WORD;
|
||||||
|
const u64 start_mask = ~((1ULL << start_bit) - 1);
|
||||||
|
const u64 end_mask = end_bit == BITS_PER_WORD - 1 ? ~0ULL : (1ULL << (end_bit + 1)) - 1;
|
||||||
|
if (first_word == last_word) {
|
||||||
|
data[first_word] = other.data[first_word] & (start_mask & end_mask);
|
||||||
|
} else {
|
||||||
|
data[first_word] = other.data[first_word] & start_mask;
|
||||||
|
size_t i = first_word + 1;
|
||||||
|
#ifdef BIT_ARRAY_USE_AVX
|
||||||
|
for (; i + WORDS_PER_AVX <= last_word; i += WORDS_PER_AVX) {
|
||||||
|
const __m256i current =
|
||||||
|
_mm256_loadu_si256(reinterpret_cast<const __m256i*>(&other.data[i]));
|
||||||
|
_mm256_storeu_si256(reinterpret_cast<__m256i*>(&data[i]), current);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
for (; i < last_word; ++i) {
|
||||||
|
data[i] = other.data[i];
|
||||||
|
}
|
||||||
|
data[last_word] = other.data[last_word] & end_mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BitArray(const BitArray& other, const Range& range)
|
||||||
|
: BitArray(other, range.first, range.second) {}
|
||||||
|
|
||||||
|
const_iterator begin() const {
|
||||||
|
return Iterator(*this, 0);
|
||||||
|
}
|
||||||
|
const_iterator end() const {
|
||||||
|
return Iterator(*this, N);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr void Set(size_t idx) {
|
||||||
|
data[idx / BITS_PER_WORD] |= (1ULL << (idx % BITS_PER_WORD));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr void Unset(size_t idx) {
|
||||||
|
data[idx / BITS_PER_WORD] &= ~(1ULL << (idx % BITS_PER_WORD));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr bool Get(size_t idx) const {
|
||||||
|
return (data[idx / BITS_PER_WORD] & (1ULL << (idx % BITS_PER_WORD))) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetRange(size_t start, size_t end) {
|
||||||
|
if (start >= end || end > N) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const size_t first_word = start / BITS_PER_WORD;
|
||||||
|
const size_t last_word = (end - 1) / BITS_PER_WORD;
|
||||||
|
const size_t start_bit = start % BITS_PER_WORD;
|
||||||
|
const size_t end_bit = (end - 1) % BITS_PER_WORD;
|
||||||
|
const u64 start_mask = ~((1ULL << start_bit) - 1);
|
||||||
|
const u64 end_mask = end_bit == BITS_PER_WORD - 1 ? ~0ULL : (1ULL << (end_bit + 1)) - 1;
|
||||||
|
if (first_word == last_word) {
|
||||||
|
data[first_word] |= start_mask & end_mask;
|
||||||
|
} else {
|
||||||
|
data[first_word] |= start_mask;
|
||||||
|
size_t i = first_word + 1;
|
||||||
|
#ifdef BIT_ARRAY_USE_AVX
|
||||||
|
const __m256i value = _mm256_set1_epi64x(-1);
|
||||||
|
for (; i + WORDS_PER_AVX <= last_word; i += WORDS_PER_AVX) {
|
||||||
|
_mm256_storeu_si256(reinterpret_cast<__m256i*>(&data[i]), value);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
for (; i < last_word; ++i) {
|
||||||
|
data[i] = ~0ULL;
|
||||||
|
}
|
||||||
|
data[last_word] |= end_mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void UnsetRange(size_t start, size_t end) {
|
||||||
|
if (start >= end || end > N) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
size_t first_word = start / BITS_PER_WORD;
|
||||||
|
const size_t last_word = (end - 1) / BITS_PER_WORD;
|
||||||
|
const size_t start_bit = start % BITS_PER_WORD;
|
||||||
|
const size_t end_bit = (end - 1) % BITS_PER_WORD;
|
||||||
|
const u64 start_mask = (1ULL << start_bit) - 1;
|
||||||
|
const u64 end_mask = end_bit == BITS_PER_WORD - 1 ? 0ULL : ~((1ULL << (end_bit + 1)) - 1);
|
||||||
|
if (first_word == last_word) {
|
||||||
|
data[first_word] &= start_mask | end_mask;
|
||||||
|
} else {
|
||||||
|
data[first_word] &= start_mask;
|
||||||
|
size_t i = first_word + 1;
|
||||||
|
#ifdef BIT_ARRAY_USE_AVX
|
||||||
|
const __m256i value = _mm256_setzero_si256();
|
||||||
|
for (; i + WORDS_PER_AVX <= last_word; i += WORDS_PER_AVX) {
|
||||||
|
_mm256_storeu_si256(reinterpret_cast<__m256i*>(&data[i]), value);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
for (; i < last_word; ++i) {
|
||||||
|
data[i] = 0ULL;
|
||||||
|
}
|
||||||
|
data[last_word] &= end_mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr void SetRange(const Range& range) {
|
||||||
|
SetRange(range.first, range.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr void UnsetRange(const Range& range) {
|
||||||
|
UnsetRange(range.first, range.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr void Clear() {
|
||||||
|
data.fill(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr void Fill() {
|
||||||
|
data.fill(~0ULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr bool None() const {
|
||||||
|
u64 result = 0;
|
||||||
|
for (const auto& word : data) {
|
||||||
|
result |= word;
|
||||||
|
}
|
||||||
|
return result == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr bool Any() const {
|
||||||
|
return !None();
|
||||||
|
}
|
||||||
|
|
||||||
|
Range FirstRangeFrom(size_t start) const {
|
||||||
|
if (start >= N) {
|
||||||
|
return {N, N};
|
||||||
|
}
|
||||||
|
const auto find_end_bit = [&](size_t word) {
|
||||||
|
#ifdef BIT_ARRAY_USE_AVX
|
||||||
|
const __m256i all_one = _mm256_set1_epi64x(-1);
|
||||||
|
for (; word + WORDS_PER_AVX <= WORD_COUNT; word += WORDS_PER_AVX) {
|
||||||
|
const __m256i current =
|
||||||
|
_mm256_loadu_si256(reinterpret_cast<const __m256i*>(&data[word]));
|
||||||
|
const __m256i cmp = _mm256_cmpeq_epi64(current, all_one);
|
||||||
|
if (_mm256_movemask_epi8(cmp) != 0xFFFFFFFF) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
for (; word < WORD_COUNT; ++word) {
|
||||||
|
if (data[word] != ~0ULL) {
|
||||||
|
return (word * BITS_PER_WORD) + std::countr_one(data[word]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return N;
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto word_bits = [&](size_t index, u64 word) {
|
||||||
|
const int empty_bits = std::countr_zero(word);
|
||||||
|
const int ones_count = std::countr_one(word >> empty_bits);
|
||||||
|
const size_t start_bit = index * BITS_PER_WORD + empty_bits;
|
||||||
|
if (ones_count + empty_bits < BITS_PER_WORD) {
|
||||||
|
return Range{start_bit, start_bit + ones_count};
|
||||||
|
}
|
||||||
|
return Range{start_bit, find_end_bit(index + 1)};
|
||||||
|
};
|
||||||
|
|
||||||
|
const size_t start_word = start / BITS_PER_WORD;
|
||||||
|
const size_t start_bit = start % BITS_PER_WORD;
|
||||||
|
const u64 masked_first = data[start_word] & (~((1ULL << start_bit) - 1));
|
||||||
|
if (masked_first) {
|
||||||
|
return word_bits(start_word, masked_first);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t word = start_word + 1;
|
||||||
|
#ifdef BIT_ARRAY_USE_AVX
|
||||||
|
for (; word + WORDS_PER_AVX <= WORD_COUNT; word += WORDS_PER_AVX) {
|
||||||
|
const __m256i current =
|
||||||
|
_mm256_loadu_si256(reinterpret_cast<const __m256i*>(&data[word]));
|
||||||
|
if (!_mm256_testz_si256(current, current)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
for (; word < WORD_COUNT; ++word) {
|
||||||
|
if (data[word] != 0) {
|
||||||
|
return word_bits(word, data[word]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {N, N};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr Range FirstRange() const {
|
||||||
|
return FirstRangeFrom(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Range LastRangeFrom(size_t end) const {
|
||||||
|
if (end == 0) {
|
||||||
|
return {0, 0};
|
||||||
|
}
|
||||||
|
if (end > N) {
|
||||||
|
end = N;
|
||||||
|
}
|
||||||
|
const auto find_start_bit = [&](size_t word) {
|
||||||
|
#ifdef BIT_ARRAY_USE_AVX
|
||||||
|
const __m256i all_zero = _mm256_setzero_si256();
|
||||||
|
for (; word >= WORDS_PER_AVX; word -= WORDS_PER_AVX) {
|
||||||
|
const __m256i current = _mm256_loadu_si256(
|
||||||
|
reinterpret_cast<const __m256i*>(&data[word - WORDS_PER_AVX]));
|
||||||
|
const __m256i cmp = _mm256_cmpeq_epi64(current, all_zero);
|
||||||
|
if (_mm256_movemask_epi8(cmp) != 0xFFFFFFFF) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
for (; word > 0; --word) {
|
||||||
|
if (data[word - 1] != ~0ULL) {
|
||||||
|
return word * BITS_PER_WORD - std::countl_one(data[word - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return size_t(0);
|
||||||
|
};
|
||||||
|
const auto word_bits = [&](size_t index, u64 word) {
|
||||||
|
const int empty_bits = std::countl_zero(word);
|
||||||
|
const int ones_count = std::countl_one(word << empty_bits);
|
||||||
|
const size_t end_bit = index * BITS_PER_WORD - empty_bits;
|
||||||
|
if (empty_bits + ones_count < BITS_PER_WORD) {
|
||||||
|
return Range{end_bit - ones_count, end_bit};
|
||||||
|
}
|
||||||
|
return Range{find_start_bit(index - 1), end_bit};
|
||||||
|
};
|
||||||
|
const size_t end_word = ((end - 1) / BITS_PER_WORD) + 1;
|
||||||
|
const size_t end_bit = (end - 1) % BITS_PER_WORD;
|
||||||
|
u64 masked_last = data[end_word - 1];
|
||||||
|
if (end_bit < BITS_PER_WORD - 1) {
|
||||||
|
masked_last &= (1ULL << (end_bit + 1)) - 1;
|
||||||
|
}
|
||||||
|
if (masked_last) {
|
||||||
|
return word_bits(end_word, masked_last);
|
||||||
|
}
|
||||||
|
size_t word = end_word - 1;
|
||||||
|
#ifdef BIT_ARRAY_USE_AVX
|
||||||
|
for (; word >= WORDS_PER_AVX; word -= WORDS_PER_AVX) {
|
||||||
|
const __m256i current =
|
||||||
|
_mm256_loadu_si256(reinterpret_cast<const __m256i*>(&data[word - WORDS_PER_AVX]));
|
||||||
|
if (!_mm256_testz_si256(current, current)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
for (; word > 0; --word) {
|
||||||
|
if (data[word - 1] != 0) {
|
||||||
|
return word_bits(word, data[word - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {0, 0};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr Range LastRange() const {
|
||||||
|
return LastRangeFrom(N);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr size_t Size() const {
|
||||||
|
return N;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr BitArray& operator|=(const BitArray& other) {
|
||||||
|
for (size_t i = 0; i < WORD_COUNT; ++i) {
|
||||||
|
data[i] |= other.data[i];
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr BitArray& operator&=(const BitArray& other) {
|
||||||
|
for (size_t i = 0; i < WORD_COUNT; ++i) {
|
||||||
|
data[i] &= other.data[i];
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr BitArray& operator^=(const BitArray& other) {
|
||||||
|
for (size_t i = 0; i < WORD_COUNT; ++i) {
|
||||||
|
data[i] ^= other.data[i];
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr BitArray operator|(const BitArray& other) const {
|
||||||
|
BitArray result = *this;
|
||||||
|
result |= other;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr BitArray operator&(const BitArray& other) const {
|
||||||
|
BitArray result = *this;
|
||||||
|
result &= other;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr BitArray operator^(const BitArray& other) const {
|
||||||
|
BitArray result = *this;
|
||||||
|
result ^= other;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr BitArray operator~() const {
|
||||||
|
BitArray result = *this;
|
||||||
|
for (size_t i = 0; i < WORD_COUNT; ++i) {
|
||||||
|
result.data[i] = ~result.data[i];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr bool operator==(const BitArray& other) const {
|
||||||
|
u64 result = 0;
|
||||||
|
for (size_t i = 0; i < WORD_COUNT; ++i) {
|
||||||
|
result |= data[i] ^ other.data[i];
|
||||||
|
}
|
||||||
|
return result == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr bool operator!=(const BitArray& other) const {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::array<u64, WORD_COUNT> data{};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Common
|
||||||
@@ -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
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -9,177 +9,183 @@
|
|||||||
|
|
||||||
namespace Config {
|
namespace Config {
|
||||||
|
|
||||||
|
enum class ConfigMode {
|
||||||
|
Default,
|
||||||
|
Global,
|
||||||
|
Clean,
|
||||||
|
};
|
||||||
|
void setConfigMode(ConfigMode mode);
|
||||||
|
|
||||||
struct GameInstallDir {
|
struct GameInstallDir {
|
||||||
std::filesystem::path path;
|
std::filesystem::path path;
|
||||||
bool enabled;
|
bool enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum HideCursorState : s16 { Never, Idle, Always };
|
enum HideCursorState : int { Never, Idle, Always };
|
||||||
|
|
||||||
void load(const std::filesystem::path& path);
|
void load(const std::filesystem::path& path, bool is_game_specific = false);
|
||||||
void save(const std::filesystem::path& path);
|
void save(const std::filesystem::path& path, bool is_game_specific = false);
|
||||||
void saveMainWindow(const std::filesystem::path& path);
|
void resetGameSpecificValue(std::string entry);
|
||||||
|
|
||||||
|
bool getGameRunning();
|
||||||
|
void setGameRunning(bool running);
|
||||||
|
int getVolumeSlider();
|
||||||
|
void setVolumeSlider(int volumeValue, bool is_game_specific = false);
|
||||||
std::string getTrophyKey();
|
std::string getTrophyKey();
|
||||||
void setTrophyKey(std::string key);
|
void setTrophyKey(std::string key);
|
||||||
bool GetLoadGameSizeEnabled();
|
|
||||||
std::filesystem::path GetSaveDataPath();
|
|
||||||
void setLoadGameSizeEnabled(bool enable);
|
|
||||||
bool getIsFullscreen();
|
bool getIsFullscreen();
|
||||||
bool getShowLabelsUnderIcons();
|
void setIsFullscreen(bool enable, bool is_game_specific = false);
|
||||||
bool setShowLabelsUnderIcons();
|
|
||||||
std::string getFullscreenMode();
|
std::string getFullscreenMode();
|
||||||
bool isNeoModeConsole();
|
void setFullscreenMode(std::string mode, bool is_game_specific = false);
|
||||||
bool isDevKitConsole();
|
std::string getPresentMode();
|
||||||
bool getPlayBGM();
|
void setPresentMode(std::string mode, bool is_game_specific = false);
|
||||||
int getBGMvolume();
|
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, bool is_game_specific = false);
|
||||||
|
s32 getGpuId();
|
||||||
|
void setGpuId(s32 selectedGpuId, bool is_game_specific = false);
|
||||||
|
bool allowHDR();
|
||||||
|
void setAllowHDR(bool enable, bool is_game_specific = false);
|
||||||
|
bool collectShadersForDebug();
|
||||||
|
void setCollectShaderForDebug(bool enable, bool is_game_specific = false);
|
||||||
|
bool showSplash();
|
||||||
|
void setShowSplash(bool enable, bool is_game_specific = false);
|
||||||
|
std::string sideTrophy();
|
||||||
|
void setSideTrophy(std::string side, bool is_game_specific = false);
|
||||||
|
bool nullGpu();
|
||||||
|
void setNullGpu(bool enable, bool is_game_specific = false);
|
||||||
|
bool copyGPUCmdBuffers();
|
||||||
|
void setCopyGPUCmdBuffers(bool enable, bool is_game_specific = false);
|
||||||
|
bool readbacks();
|
||||||
|
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, bool is_game_specific = false);
|
||||||
|
bool dumpShaders();
|
||||||
|
void setDumpShaders(bool enable, bool is_game_specific = false);
|
||||||
|
u32 vblankFreq();
|
||||||
|
void setVblankFreq(u32 value, bool is_game_specific = false);
|
||||||
bool getisTrophyPopupDisabled();
|
bool getisTrophyPopupDisabled();
|
||||||
bool getEnableDiscordRPC();
|
void setisTrophyPopupDisabled(bool disable, bool is_game_specific = false);
|
||||||
bool getCompatibilityEnabled();
|
|
||||||
bool getCheckCompatibilityOnStartup();
|
|
||||||
int getBackgroundImageOpacity();
|
|
||||||
bool getShowBackgroundImage();
|
|
||||||
|
|
||||||
std::string getLogFilter();
|
|
||||||
std::string getLogType();
|
|
||||||
std::string getUserName();
|
|
||||||
std::string getUpdateChannel();
|
|
||||||
std::string getChooseHomeTab();
|
|
||||||
|
|
||||||
s16 getCursorState();
|
s16 getCursorState();
|
||||||
int getCursorHideTimeout();
|
void setCursorState(s16 cursorState, bool is_game_specific = false);
|
||||||
|
bool vkValidationEnabled();
|
||||||
|
void setVkValidation(bool enable, bool is_game_specific = false);
|
||||||
|
bool vkValidationSyncEnabled();
|
||||||
|
void setVkSyncValidation(bool enable, bool is_game_specific = false);
|
||||||
|
bool vkValidationGpuEnabled();
|
||||||
|
void setVkGpuValidation(bool enable, bool is_game_specific = false);
|
||||||
|
bool vkValidationCoreEnabled();
|
||||||
|
void setVkCoreValidation(bool enable, bool is_game_specific = false);
|
||||||
|
bool getVkCrashDiagnosticEnabled();
|
||||||
|
void setVkCrashDiagnosticEnabled(bool enable, bool is_game_specific = false);
|
||||||
|
bool getVkHostMarkersEnabled();
|
||||||
|
void setVkHostMarkersEnabled(bool enable, bool is_game_specific = false);
|
||||||
|
bool getVkGuestMarkersEnabled();
|
||||||
|
void setVkGuestMarkersEnabled(bool enable, bool is_game_specific = false);
|
||||||
|
bool getEnableDiscordRPC();
|
||||||
|
void setEnableDiscordRPC(bool enable);
|
||||||
|
bool isRdocEnabled();
|
||||||
|
bool isPipelineCacheEnabled();
|
||||||
|
bool isPipelineCacheArchived();
|
||||||
|
void setRdocEnabled(bool enable, bool is_game_specific = false);
|
||||||
|
void setPipelineCacheEnabled(bool enable, bool is_game_specific = false);
|
||||||
|
void setPipelineCacheArchived(bool enable, bool is_game_specific = false);
|
||||||
|
std::string getLogType();
|
||||||
|
void setLogType(const std::string& type, bool is_game_specific = false);
|
||||||
|
std::string getLogFilter();
|
||||||
|
void setLogFilter(const std::string& type, bool is_game_specific = false);
|
||||||
double getTrophyNotificationDuration();
|
double getTrophyNotificationDuration();
|
||||||
std::string getBackButtonBehavior();
|
void setTrophyNotificationDuration(double newTrophyNotificationDuration,
|
||||||
|
bool is_game_specific = false);
|
||||||
|
int getCursorHideTimeout();
|
||||||
|
std::string getMainOutputDevice();
|
||||||
|
void setMainOutputDevice(std::string device, bool is_game_specific = false);
|
||||||
|
std::string getPadSpkOutputDevice();
|
||||||
|
void setPadSpkOutputDevice(std::string device, bool is_game_specific = false);
|
||||||
|
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, bool is_game_specific = false);
|
||||||
|
void setUseSpecialPad(bool use);
|
||||||
bool getUseSpecialPad();
|
bool getUseSpecialPad();
|
||||||
|
void setSpecialPadClass(int type);
|
||||||
int getSpecialPadClass();
|
int getSpecialPadClass();
|
||||||
|
bool getPSNSignedIn();
|
||||||
|
void setPSNSignedIn(bool sign, bool is_game_specific = false);
|
||||||
|
bool patchShaders(); // no set
|
||||||
|
bool fpsColor(); // no set
|
||||||
|
bool getShowFpsCounter();
|
||||||
|
void setShowFpsCounter(bool enable, bool is_game_specific = false);
|
||||||
|
bool isNeoModeConsole();
|
||||||
|
void setNeoMode(bool enable, bool is_game_specific = false);
|
||||||
|
bool isDevKitConsole();
|
||||||
|
void setDevKitConsole(bool enable, bool is_game_specific = false);
|
||||||
|
|
||||||
|
int getExtraDmemInMbytes();
|
||||||
|
void setExtraDmemInMbytes(int value, bool is_game_specific = false);
|
||||||
bool getIsMotionControlsEnabled();
|
bool getIsMotionControlsEnabled();
|
||||||
|
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);
|
||||||
|
std::filesystem::path getSysModulesPath();
|
||||||
|
void setSysModulesPath(const std::filesystem::path& path);
|
||||||
|
bool getLoadAutoPatches();
|
||||||
|
void setLoadAutoPatches(bool enable);
|
||||||
|
|
||||||
|
enum UsbBackendType : int { Real, SkylandersPortal, InfinityBase, DimensionsToypad };
|
||||||
|
int getUsbDeviceBackend();
|
||||||
|
void setUsbDeviceBackend(int value, bool is_game_specific = false);
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
std::filesystem::path GetSaveDataPath();
|
||||||
|
std::string getUserName();
|
||||||
bool GetUseUnifiedInputConfig();
|
bool GetUseUnifiedInputConfig();
|
||||||
void SetUseUnifiedInputConfig(bool use);
|
void SetUseUnifiedInputConfig(bool use);
|
||||||
bool GetOverrideControllerColor();
|
bool GetOverrideControllerColor();
|
||||||
void SetOverrideControllerColor(bool enable);
|
void SetOverrideControllerColor(bool enable);
|
||||||
int* GetControllerCustomColor();
|
int* GetControllerCustomColor();
|
||||||
void SetControllerCustomColor(int r, int b, int g);
|
void SetControllerCustomColor(int r, int b, int g);
|
||||||
|
|
||||||
u32 getScreenWidth();
|
|
||||||
u32 getScreenHeight();
|
|
||||||
s32 getGpuId();
|
|
||||||
bool allowHDR();
|
|
||||||
|
|
||||||
bool debugDump();
|
|
||||||
bool collectShadersForDebug();
|
|
||||||
bool showSplash();
|
|
||||||
bool autoUpdate();
|
|
||||||
bool alwaysShowChangelog();
|
|
||||||
std::string sideTrophy();
|
|
||||||
bool nullGpu();
|
|
||||||
bool copyGPUCmdBuffers();
|
|
||||||
bool dumpShaders();
|
|
||||||
bool patchShaders();
|
|
||||||
bool isRdocEnabled();
|
|
||||||
bool fpsColor();
|
|
||||||
u32 vblankDiv();
|
|
||||||
|
|
||||||
void setDebugDump(bool enable);
|
|
||||||
void setCollectShaderForDebug(bool enable);
|
|
||||||
void setShowSplash(bool enable);
|
|
||||||
void setAutoUpdate(bool enable);
|
|
||||||
void setAlwaysShowChangelog(bool enable);
|
|
||||||
void setSideTrophy(std::string side);
|
|
||||||
void setNullGpu(bool enable);
|
|
||||||
void setAllowHDR(bool enable);
|
|
||||||
void setCopyGPUCmdBuffers(bool enable);
|
|
||||||
void setDumpShaders(bool enable);
|
|
||||||
void setVblankDiv(u32 value);
|
|
||||||
void setGpuId(s32 selectedGpuId);
|
|
||||||
void setScreenWidth(u32 width);
|
|
||||||
void setScreenHeight(u32 height);
|
|
||||||
void setIsFullscreen(bool enable);
|
|
||||||
void setFullscreenMode(std::string mode);
|
|
||||||
void setisTrophyPopupDisabled(bool disable);
|
|
||||||
void setPlayBGM(bool enable);
|
|
||||||
void setBGMvolume(int volume);
|
|
||||||
void setEnableDiscordRPC(bool enable);
|
|
||||||
void setLanguage(u32 language);
|
|
||||||
void setNeoMode(bool enable);
|
|
||||||
void setUserName(const std::string& type);
|
|
||||||
void setUpdateChannel(const std::string& type);
|
|
||||||
void setChooseHomeTab(const std::string& type);
|
|
||||||
void setGameInstallDirs(const std::vector<std::filesystem::path>& dirs_config);
|
void setGameInstallDirs(const std::vector<std::filesystem::path>& dirs_config);
|
||||||
void setAllGameInstallDirs(const std::vector<GameInstallDir>& dirs_config);
|
void setAllGameInstallDirs(const std::vector<GameInstallDir>& dirs_config);
|
||||||
void setSaveDataPath(const std::filesystem::path& path);
|
void setSaveDataPath(const std::filesystem::path& path);
|
||||||
void setCompatibilityEnabled(bool use);
|
|
||||||
void setCheckCompatibilityOnStartup(bool use);
|
|
||||||
void setBackgroundImageOpacity(int opacity);
|
|
||||||
void setShowBackgroundImage(bool show);
|
|
||||||
|
|
||||||
void setCursorState(s16 cursorState);
|
|
||||||
void setCursorHideTimeout(int newcursorHideTimeout);
|
|
||||||
void setTrophyNotificationDuration(double newTrophyNotificationDuration);
|
|
||||||
void setBackButtonBehavior(const std::string& type);
|
|
||||||
void setUseSpecialPad(bool use);
|
|
||||||
void setSpecialPadClass(int type);
|
|
||||||
void setIsMotionControlsEnabled(bool use);
|
|
||||||
|
|
||||||
void setLogType(const std::string& type);
|
|
||||||
void setLogFilter(const std::string& type);
|
|
||||||
void setSeparateLogFilesEnabled(bool enabled);
|
|
||||||
bool getSeparateLogFilesEnabled();
|
|
||||||
void setVkValidation(bool enable);
|
|
||||||
void setVkSyncValidation(bool enable);
|
|
||||||
void setRdocEnabled(bool enable);
|
|
||||||
|
|
||||||
bool vkValidationEnabled();
|
|
||||||
bool vkValidationSyncEnabled();
|
|
||||||
bool vkValidationGpuEnabled();
|
|
||||||
bool getVkCrashDiagnosticEnabled();
|
|
||||||
bool getVkHostMarkersEnabled();
|
|
||||||
bool getVkGuestMarkersEnabled();
|
|
||||||
void setVkCrashDiagnosticEnabled(bool enable);
|
|
||||||
void setVkHostMarkersEnabled(bool enable);
|
|
||||||
void setVkGuestMarkersEnabled(bool enable);
|
|
||||||
|
|
||||||
// Gui
|
// Gui
|
||||||
void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h);
|
|
||||||
bool addGameInstallDir(const std::filesystem::path& dir, bool enabled = true);
|
bool addGameInstallDir(const std::filesystem::path& dir, bool enabled = true);
|
||||||
void removeGameInstallDir(const std::filesystem::path& dir);
|
void removeGameInstallDir(const std::filesystem::path& dir);
|
||||||
void setGameInstallDirEnabled(const std::filesystem::path& dir, bool enabled);
|
void setGameInstallDirEnabled(const std::filesystem::path& dir, bool enabled);
|
||||||
void setAddonInstallDir(const std::filesystem::path& dir);
|
void setAddonInstallDir(const std::filesystem::path& dir);
|
||||||
void setMainWindowTheme(u32 theme);
|
|
||||||
void setIconSize(u32 size);
|
|
||||||
void setIconSizeGrid(u32 size);
|
|
||||||
void setSliderPosition(u32 pos);
|
|
||||||
void setSliderPositionGrid(u32 pos);
|
|
||||||
void setTableMode(u32 mode);
|
|
||||||
void setMainWindowWidth(u32 width);
|
|
||||||
void setMainWindowHeight(u32 height);
|
|
||||||
void setElfViewer(const std::vector<std::string>& elfList);
|
|
||||||
void setRecentFiles(const std::vector<std::string>& recentFiles);
|
|
||||||
void setEmulatorLanguage(std::string language);
|
|
||||||
|
|
||||||
u32 getMainWindowGeometryX();
|
|
||||||
u32 getMainWindowGeometryY();
|
|
||||||
u32 getMainWindowGeometryW();
|
|
||||||
u32 getMainWindowGeometryH();
|
|
||||||
const std::vector<std::filesystem::path> getGameInstallDirs();
|
const std::vector<std::filesystem::path> getGameInstallDirs();
|
||||||
const std::vector<bool> getGameInstallDirsEnabled();
|
const std::vector<bool> getGameInstallDirsEnabled();
|
||||||
std::filesystem::path getAddonInstallDir();
|
std::filesystem::path getAddonInstallDir();
|
||||||
u32 getMainWindowTheme();
|
|
||||||
u32 getIconSize();
|
|
||||||
u32 getIconSizeGrid();
|
|
||||||
u32 getSliderPosition();
|
|
||||||
u32 getSliderPositionGrid();
|
|
||||||
u32 getTableMode();
|
|
||||||
u32 getMainWindowWidth();
|
|
||||||
u32 getMainWindowHeight();
|
|
||||||
std::vector<std::string> getElfViewer();
|
|
||||||
std::vector<std::string> getRecentFiles();
|
|
||||||
std::string getEmulatorLanguage();
|
|
||||||
|
|
||||||
void setDefaultValues();
|
void setDefaultValues(bool is_game_specific = false);
|
||||||
|
|
||||||
// todo: name and function location pending
|
constexpr std::string_view GetDefaultGlobalConfig();
|
||||||
std::filesystem::path GetFoolproofKbmConfigFile(const std::string& game_id = "");
|
std::filesystem::path GetFoolproofInputConfigFile(const std::string& game_id = "");
|
||||||
|
|
||||||
// settings
|
|
||||||
u32 GetLanguage();
|
|
||||||
}; // namespace Config
|
}; // namespace Config
|
||||||
|
|||||||
@@ -68,9 +68,11 @@ class ElfInfo {
|
|||||||
std::string app_ver{};
|
std::string app_ver{};
|
||||||
u32 firmware_ver = 0;
|
u32 firmware_ver = 0;
|
||||||
u32 raw_firmware_ver = 0;
|
u32 raw_firmware_ver = 0;
|
||||||
|
u32 sdk_ver = 0;
|
||||||
PSFAttributes psf_attributes{};
|
PSFAttributes psf_attributes{};
|
||||||
|
|
||||||
std::filesystem::path splash_path{};
|
std::filesystem::path splash_path{};
|
||||||
|
std::filesystem::path game_folder{};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr u32 FW_15 = 0x1500000;
|
static constexpr u32 FW_15 = 0x1500000;
|
||||||
@@ -84,6 +86,7 @@ public:
|
|||||||
static constexpr u32 FW_45 = 0x4500000;
|
static constexpr u32 FW_45 = 0x4500000;
|
||||||
static constexpr u32 FW_50 = 0x5000000;
|
static constexpr u32 FW_50 = 0x5000000;
|
||||||
static constexpr u32 FW_55 = 0x5500000;
|
static constexpr u32 FW_55 = 0x5500000;
|
||||||
|
static constexpr u32 FW_60 = 0x6000000;
|
||||||
static constexpr u32 FW_80 = 0x8000000;
|
static constexpr u32 FW_80 = 0x8000000;
|
||||||
|
|
||||||
static ElfInfo& Instance() {
|
static ElfInfo& Instance() {
|
||||||
@@ -115,6 +118,11 @@ public:
|
|||||||
return raw_firmware_ver;
|
return raw_firmware_ver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] u32 CompiledSdkVer() const {
|
||||||
|
ASSERT(initialized);
|
||||||
|
return sdk_ver;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] const PSFAttributes& GetPSFAttributes() const {
|
[[nodiscard]] const PSFAttributes& GetPSFAttributes() const {
|
||||||
ASSERT(initialized);
|
ASSERT(initialized);
|
||||||
return psf_attributes;
|
return psf_attributes;
|
||||||
@@ -123,6 +131,10 @@ public:
|
|||||||
[[nodiscard]] const std::filesystem::path& GetSplashPath() const {
|
[[nodiscard]] const std::filesystem::path& GetSplashPath() const {
|
||||||
return splash_path;
|
return splash_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const std::filesystem::path& GetGameFolder() const {
|
||||||
|
return game_folder;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
|
|||||||
@@ -40,28 +40,30 @@ namespace {
|
|||||||
switch (mode) {
|
switch (mode) {
|
||||||
case FileAccessMode::Read:
|
case FileAccessMode::Read:
|
||||||
return L"rb";
|
return L"rb";
|
||||||
case FileAccessMode::Write:
|
|
||||||
return L"wb";
|
|
||||||
case FileAccessMode::Append:
|
case FileAccessMode::Append:
|
||||||
return L"ab";
|
return L"ab";
|
||||||
|
case FileAccessMode::Write:
|
||||||
case FileAccessMode::ReadWrite:
|
case FileAccessMode::ReadWrite:
|
||||||
return L"r+b";
|
return L"r+b";
|
||||||
case FileAccessMode::ReadAppend:
|
case FileAccessMode::ReadAppend:
|
||||||
return L"a+b";
|
return L"a+b";
|
||||||
|
case FileAccessMode::Create:
|
||||||
|
return L"wb";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FileType::TextFile:
|
case FileType::TextFile:
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case FileAccessMode::Read:
|
case FileAccessMode::Read:
|
||||||
return L"r";
|
return L"r";
|
||||||
case FileAccessMode::Write:
|
|
||||||
return L"w";
|
|
||||||
case FileAccessMode::Append:
|
case FileAccessMode::Append:
|
||||||
return L"a";
|
return L"a";
|
||||||
|
case FileAccessMode::Write:
|
||||||
case FileAccessMode::ReadWrite:
|
case FileAccessMode::ReadWrite:
|
||||||
return L"r+";
|
return L"r+";
|
||||||
case FileAccessMode::ReadAppend:
|
case FileAccessMode::ReadAppend:
|
||||||
return L"a+";
|
return L"a+";
|
||||||
|
case FileAccessMode::Create:
|
||||||
|
return L"w";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -91,28 +93,30 @@ namespace {
|
|||||||
switch (mode) {
|
switch (mode) {
|
||||||
case FileAccessMode::Read:
|
case FileAccessMode::Read:
|
||||||
return "rb";
|
return "rb";
|
||||||
case FileAccessMode::Write:
|
|
||||||
return "wb";
|
|
||||||
case FileAccessMode::Append:
|
case FileAccessMode::Append:
|
||||||
return "ab";
|
return "ab";
|
||||||
|
case FileAccessMode::Write:
|
||||||
case FileAccessMode::ReadWrite:
|
case FileAccessMode::ReadWrite:
|
||||||
return "r+b";
|
return "r+b";
|
||||||
case FileAccessMode::ReadAppend:
|
case FileAccessMode::ReadAppend:
|
||||||
return "a+b";
|
return "a+b";
|
||||||
|
case FileAccessMode::Create:
|
||||||
|
return "wb";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FileType::TextFile:
|
case FileType::TextFile:
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case FileAccessMode::Read:
|
case FileAccessMode::Read:
|
||||||
return "r";
|
return "r";
|
||||||
case FileAccessMode::Write:
|
|
||||||
return "w";
|
|
||||||
case FileAccessMode::Append:
|
case FileAccessMode::Append:
|
||||||
return "a";
|
return "a";
|
||||||
|
case FileAccessMode::Write:
|
||||||
case FileAccessMode::ReadWrite:
|
case FileAccessMode::ReadWrite:
|
||||||
return "r+";
|
return "r+";
|
||||||
case FileAccessMode::ReadAppend:
|
case FileAccessMode::ReadAppend:
|
||||||
return "a+";
|
return "a+";
|
||||||
|
case FileAccessMode::Create:
|
||||||
|
return "w";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,9 +21,8 @@ enum class FileAccessMode {
|
|||||||
*/
|
*/
|
||||||
Read = 1 << 0,
|
Read = 1 << 0,
|
||||||
/**
|
/**
|
||||||
* If the file at path exists, the existing contents of the file are erased.
|
* If the file at path exists, it opens the file for writing.
|
||||||
* The empty file is then opened for writing.
|
* If the file at path does not exist, it fails to open the file.
|
||||||
* If the file at path does not exist, it creates and opens a new empty file for writing.
|
|
||||||
*/
|
*/
|
||||||
Write = 1 << 1,
|
Write = 1 << 1,
|
||||||
/**
|
/**
|
||||||
@@ -42,6 +41,12 @@ enum class FileAccessMode {
|
|||||||
* reading and appending.
|
* reading and appending.
|
||||||
*/
|
*/
|
||||||
ReadAppend = Read | Append,
|
ReadAppend = Read | Append,
|
||||||
|
/**
|
||||||
|
* If the file at path exists, the existing contents of the file are erased.
|
||||||
|
* The empty file is then opened for writing.
|
||||||
|
* If the file at path does not exist, it creates and opens a new empty file for writing.
|
||||||
|
*/
|
||||||
|
Create = 1 << 3,
|
||||||
};
|
};
|
||||||
DECLARE_ENUM_FLAG_OPERATORS(FileAccessMode);
|
DECLARE_ENUM_FLAG_OPERATORS(FileAccessMode);
|
||||||
|
|
||||||
@@ -102,6 +107,11 @@ public:
|
|||||||
return file != nullptr;
|
return file != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsWriteOnly() const {
|
||||||
|
return file_access_mode == FileAccessMode::Append ||
|
||||||
|
file_access_mode == FileAccessMode::Write;
|
||||||
|
}
|
||||||
|
|
||||||
uintptr_t GetFileMapping();
|
uintptr_t GetFileMapping();
|
||||||
|
|
||||||
int Open(const std::filesystem::path& path, FileAccessMode mode,
|
int Open(const std::filesystem::path& path, FileAccessMode mode,
|
||||||
@@ -186,7 +196,9 @@ public:
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
size_t WriteRaw(const void* data, size_t size) const {
|
size_t WriteRaw(const void* data, size_t size) const {
|
||||||
return std::fwrite(data, sizeof(T), size, file);
|
auto bytes = std::fwrite(data, sizeof(T), size, file);
|
||||||
|
std::fflush(file);
|
||||||
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -208,16 +220,16 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static size_t WriteBytes(const std::filesystem::path path, const auto& data) {
|
static size_t WriteBytes(const std::filesystem::path path, const auto& data) {
|
||||||
IOFile out(path, FileAccessMode::Write);
|
IOFile out(path, FileAccessMode::Create);
|
||||||
return out.Write(data);
|
return out.Write(data);
|
||||||
}
|
}
|
||||||
|
std::FILE* file = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::filesystem::path file_path;
|
std::filesystem::path file_path;
|
||||||
FileAccessMode file_access_mode{};
|
FileAccessMode file_access_mode{};
|
||||||
FileType file_type{};
|
FileType file_type{};
|
||||||
|
|
||||||
std::FILE* file = nullptr;
|
|
||||||
uintptr_t file_mapping = 0;
|
uintptr_t file_mapping = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -61,8 +61,9 @@ private:
|
|||||||
*/
|
*/
|
||||||
class FileBackend {
|
class FileBackend {
|
||||||
public:
|
public:
|
||||||
explicit FileBackend(const std::filesystem::path& filename)
|
explicit FileBackend(const std::filesystem::path& filename, bool should_append = false)
|
||||||
: file{filename, FS::FileAccessMode::Write, FS::FileType::TextFile} {}
|
: file{filename, should_append ? FS::FileAccessMode::Append : FS::FileAccessMode::Create,
|
||||||
|
FS::FileType::TextFile} {}
|
||||||
|
|
||||||
~FileBackend() = default;
|
~FileBackend() = default;
|
||||||
|
|
||||||
@@ -145,6 +146,11 @@ public:
|
|||||||
initialization_in_progress_suppress_logging = false;
|
initialization_in_progress_suppress_logging = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ResetInstance() {
|
||||||
|
initialization_in_progress_suppress_logging = true;
|
||||||
|
instance.reset();
|
||||||
|
}
|
||||||
|
|
||||||
static bool IsActive() {
|
static bool IsActive() {
|
||||||
return instance != nullptr;
|
return instance != nullptr;
|
||||||
}
|
}
|
||||||
@@ -157,6 +163,10 @@ public:
|
|||||||
instance->StopBackendThread();
|
instance->StopBackendThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SetAppend() {
|
||||||
|
should_append = true;
|
||||||
|
}
|
||||||
|
|
||||||
Impl(const Impl&) = delete;
|
Impl(const Impl&) = delete;
|
||||||
Impl& operator=(const Impl&) = delete;
|
Impl& operator=(const Impl&) = delete;
|
||||||
|
|
||||||
@@ -172,7 +182,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num,
|
void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num,
|
||||||
const char* function, std::string message) {
|
const char* function, const char* format, const fmt::format_args& args) {
|
||||||
|
if (!filter.CheckMessage(log_class, log_level) || !Config::getLoggingEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto message = fmt::vformat(format, args);
|
||||||
|
|
||||||
// Propagate important log messages to the profiler
|
// Propagate important log messages to the profiler
|
||||||
if (IsProfilerConnected()) {
|
if (IsProfilerConnected()) {
|
||||||
const auto& msg_str = fmt::format("[{}] {}", GetLogClassName(log_class), message);
|
const auto& msg_str = fmt::format("[{}] {}", GetLogClassName(log_class), message);
|
||||||
@@ -191,10 +207,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!filter.CheckMessage(log_class, log_level)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
using std::chrono::duration_cast;
|
using std::chrono::duration_cast;
|
||||||
using std::chrono::microseconds;
|
using std::chrono::microseconds;
|
||||||
using std::chrono::steady_clock;
|
using std::chrono::steady_clock;
|
||||||
@@ -218,7 +230,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Impl(const std::filesystem::path& file_backend_filename, const Filter& filter_)
|
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;
|
~Impl() = default;
|
||||||
|
|
||||||
@@ -264,6 +276,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline std::unique_ptr<Impl, decltype(&Deleter)> instance{nullptr, Deleter};
|
static inline std::unique_ptr<Impl, decltype(&Deleter)> instance{nullptr, Deleter};
|
||||||
|
static inline bool should_append{false};
|
||||||
|
|
||||||
Filter filter;
|
Filter filter;
|
||||||
DebuggerBackend debugger_backend{};
|
DebuggerBackend debugger_backend{};
|
||||||
@@ -292,6 +305,11 @@ void Stop() {
|
|||||||
Impl::Stop();
|
Impl::Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Denitializer() {
|
||||||
|
Impl::Stop();
|
||||||
|
Impl::ResetInstance();
|
||||||
|
}
|
||||||
|
|
||||||
void SetGlobalFilter(const Filter& filter) {
|
void SetGlobalFilter(const Filter& filter) {
|
||||||
Impl::Instance().SetGlobalFilter(filter);
|
Impl::Instance().SetGlobalFilter(filter);
|
||||||
}
|
}
|
||||||
@@ -300,12 +318,16 @@ void SetColorConsoleBackendEnabled(bool enabled) {
|
|||||||
Impl::Instance().SetColorConsoleBackendEnabled(enabled);
|
Impl::Instance().SetColorConsoleBackendEnabled(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetAppend() {
|
||||||
|
Impl::SetAppend();
|
||||||
|
}
|
||||||
|
|
||||||
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
|
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
|
||||||
unsigned int line_num, const char* function, const char* format,
|
unsigned int line_num, const char* function, const char* format,
|
||||||
const fmt::format_args& args) {
|
const fmt::format_args& args) {
|
||||||
if (!initialization_in_progress_suppress_logging) [[likely]] {
|
if (!initialization_in_progress_suppress_logging) [[likely]] {
|
||||||
Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function,
|
Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function, format,
|
||||||
fmt::vformat(format, args));
|
args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace Common::Log
|
} // namespace Common::Log
|
||||||
|
|||||||
@@ -21,9 +21,14 @@ void Start();
|
|||||||
/// Explictily stops the logger thread and flushes the buffers
|
/// Explictily stops the logger thread and flushes the buffers
|
||||||
void Stop();
|
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.
|
/// The global filter will prevent any messages from even being processed if they are filtered.
|
||||||
void SetGlobalFilter(const Filter& filter);
|
void SetGlobalFilter(const Filter& filter);
|
||||||
|
|
||||||
void SetColorConsoleBackendEnabled(bool enabled);
|
void SetColorConsoleBackendEnabled(bool enabled);
|
||||||
|
|
||||||
|
void SetAppend();
|
||||||
|
|
||||||
} // namespace Common::Log
|
} // namespace Common::Log
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
|||||||
SUB(Lib, LibcInternal) \
|
SUB(Lib, LibcInternal) \
|
||||||
SUB(Lib, Kernel) \
|
SUB(Lib, Kernel) \
|
||||||
SUB(Lib, Pad) \
|
SUB(Lib, Pad) \
|
||||||
|
SUB(Lib, SystemGesture) \
|
||||||
SUB(Lib, GnmDriver) \
|
SUB(Lib, GnmDriver) \
|
||||||
SUB(Lib, SystemService) \
|
SUB(Lib, SystemService) \
|
||||||
SUB(Lib, UserService) \
|
SUB(Lib, UserService) \
|
||||||
@@ -103,10 +104,13 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
|||||||
SUB(Lib, Move) \
|
SUB(Lib, Move) \
|
||||||
SUB(Lib, NpAuth) \
|
SUB(Lib, NpAuth) \
|
||||||
SUB(Lib, NpCommon) \
|
SUB(Lib, NpCommon) \
|
||||||
|
SUB(Lib, NpCommerce) \
|
||||||
SUB(Lib, NpManager) \
|
SUB(Lib, NpManager) \
|
||||||
SUB(Lib, NpScore) \
|
SUB(Lib, NpScore) \
|
||||||
SUB(Lib, NpTrophy) \
|
SUB(Lib, NpTrophy) \
|
||||||
SUB(Lib, NpWebApi) \
|
SUB(Lib, NpWebApi) \
|
||||||
|
SUB(Lib, NpProfileDialog) \
|
||||||
|
SUB(Lib, NpSnsFacebookDialog) \
|
||||||
SUB(Lib, Screenshot) \
|
SUB(Lib, Screenshot) \
|
||||||
SUB(Lib, LibCInternal) \
|
SUB(Lib, LibCInternal) \
|
||||||
SUB(Lib, AppContent) \
|
SUB(Lib, AppContent) \
|
||||||
@@ -137,9 +141,15 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
|||||||
SUB(Lib, NpParty) \
|
SUB(Lib, NpParty) \
|
||||||
SUB(Lib, Zlib) \
|
SUB(Lib, Zlib) \
|
||||||
SUB(Lib, Hmd) \
|
SUB(Lib, Hmd) \
|
||||||
|
SUB(Lib, Font) \
|
||||||
|
SUB(Lib, FontFt) \
|
||||||
|
SUB(Lib, HmdSetupDialog) \
|
||||||
SUB(Lib, SigninDialog) \
|
SUB(Lib, SigninDialog) \
|
||||||
SUB(Lib, Camera) \
|
SUB(Lib, Camera) \
|
||||||
SUB(Lib, CompanionHttpd) \
|
SUB(Lib, CompanionHttpd) \
|
||||||
|
SUB(Lib, CompanionUtil) \
|
||||||
|
SUB(Lib, Voice) \
|
||||||
|
SUB(Lib, VrTracker) \
|
||||||
CLS(Frontend) \
|
CLS(Frontend) \
|
||||||
CLS(Render) \
|
CLS(Render) \
|
||||||
SUB(Render, Vulkan) \
|
SUB(Render, Vulkan) \
|
||||||
|
|||||||
@@ -29,93 +29,103 @@ enum class Level : u8 {
|
|||||||
* filter.cpp.
|
* filter.cpp.
|
||||||
*/
|
*/
|
||||||
enum class Class : u8 {
|
enum class Class : u8 {
|
||||||
Log, ///< Messages about the log system itself
|
Log, ///< Messages about the log system itself
|
||||||
Common, ///< Library routines
|
Common, ///< Library routines
|
||||||
Common_Filesystem, ///< Filesystem interface library
|
Common_Filesystem, ///< Filesystem interface library
|
||||||
Common_Memory, ///< Memory mapping and management functions
|
Common_Memory, ///< Memory mapping and management functions
|
||||||
Core, ///< LLE emulation core
|
Core, ///< LLE emulation core
|
||||||
Core_Linker, ///< The module linker
|
Core_Linker, ///< The module linker
|
||||||
Core_Devices, ///< Devices emulation
|
Core_Devices, ///< Devices emulation
|
||||||
Config, ///< Emulator configuration (including commandline)
|
Config, ///< Emulator configuration (including commandline)
|
||||||
Debug, ///< Debugging tools
|
Debug, ///< Debugging tools
|
||||||
Kernel, ///< The HLE implementation of the PS4 kernel.
|
Kernel, ///< The HLE implementation of the PS4 kernel.
|
||||||
Kernel_Pthread, ///< The pthread implementation of the kernel.
|
Kernel_Pthread, ///< The pthread implementation of the kernel.
|
||||||
Kernel_Fs, ///< The filesystem implementation of the kernel.
|
Kernel_Fs, ///< The filesystem implementation of the kernel.
|
||||||
Kernel_Vmm, ///< The virtual memory implementation of the kernel.
|
Kernel_Vmm, ///< The virtual memory implementation of the kernel.
|
||||||
Kernel_Event, ///< The event management implementation of the kernel.
|
Kernel_Event, ///< The event management implementation of the kernel.
|
||||||
Kernel_Sce, ///< The sony specific interfaces provided by the kernel.
|
Kernel_Sce, ///< The sony specific interfaces provided by the kernel.
|
||||||
Lib, ///< HLE implementation of system library. Each major library
|
Lib, ///< HLE implementation of system library. Each major library
|
||||||
///< should have its own subclass.
|
///< should have its own subclass.
|
||||||
Lib_LibC, ///< The LibC implementation.
|
Lib_LibC, ///< The LibC implementation.
|
||||||
Lib_LibcInternal, ///< The LibcInternal implementation.
|
Lib_LibcInternal, ///< The LibcInternal implementation.
|
||||||
Lib_Kernel, ///< The LibKernel implementation.
|
Lib_Kernel, ///< The LibKernel implementation.
|
||||||
Lib_Pad, ///< The LibScePad implementation.
|
Lib_Pad, ///< The LibScePad implementation.
|
||||||
Lib_GnmDriver, ///< The LibSceGnmDriver implementation.
|
Lib_SystemGesture, ///< The LibSceSystemGesture implementation.
|
||||||
Lib_SystemService, ///< The LibSceSystemService implementation.
|
Lib_GnmDriver, ///< The LibSceGnmDriver implementation.
|
||||||
Lib_UserService, ///< The LibSceUserService implementation.
|
Lib_SystemService, ///< The LibSceSystemService implementation.
|
||||||
Lib_VideoOut, ///< The LibSceVideoOut implementation.
|
Lib_UserService, ///< The LibSceUserService implementation.
|
||||||
Lib_CommonDlg, ///< The LibSceCommonDialog implementation.
|
Lib_VideoOut, ///< The LibSceVideoOut implementation.
|
||||||
Lib_MsgDlg, ///< The LibSceMsgDialog implementation.
|
Lib_CommonDlg, ///< The LibSceCommonDialog implementation.
|
||||||
Lib_AudioOut, ///< The LibSceAudioOut implementation.
|
Lib_MsgDlg, ///< The LibSceMsgDialog implementation.
|
||||||
Lib_AudioIn, ///< The LibSceAudioIn implementation.
|
Lib_AudioOut, ///< The LibSceAudioOut implementation.
|
||||||
Lib_Move, ///< The LibSceMove implementation.
|
Lib_AudioIn, ///< The LibSceAudioIn implementation.
|
||||||
Lib_Net, ///< The LibSceNet implementation.
|
Lib_Move, ///< The LibSceMove implementation.
|
||||||
Lib_NetCtl, ///< The LibSceNetCtl implementation.
|
Lib_Net, ///< The LibSceNet implementation.
|
||||||
Lib_SaveData, ///< The LibSceSaveData implementation.
|
Lib_NetCtl, ///< The LibSceNetCtl implementation.
|
||||||
Lib_SaveDataDialog, ///< The LibSceSaveDataDialog implementation.
|
Lib_SaveData, ///< The LibSceSaveData implementation.
|
||||||
Lib_Ssl, ///< The LibSceSsl implementation.
|
Lib_SaveDataDialog, ///< The LibSceSaveDataDialog implementation.
|
||||||
Lib_Ssl2, ///< The LibSceSsl2 implementation.
|
Lib_Ssl, ///< The LibSceSsl implementation.
|
||||||
Lib_Http, ///< The LibSceHttp implementation.
|
Lib_Ssl2, ///< The LibSceSsl2 implementation.
|
||||||
Lib_Http2, ///< The LibSceHttp2 implementation.
|
Lib_Http, ///< The LibSceHttp implementation.
|
||||||
Lib_SysModule, ///< The LibSceSysModule implementation
|
Lib_Http2, ///< The LibSceHttp2 implementation.
|
||||||
Lib_NpCommon, ///< The LibSceNpCommon implementation
|
Lib_SysModule, ///< The LibSceSysModule implementation
|
||||||
Lib_NpAuth, ///< The LibSceNpAuth implementation
|
Lib_NpCommon, ///< The LibSceNpCommon implementation
|
||||||
Lib_NpManager, ///< The LibSceNpManager implementation
|
Lib_NpCommerce, ///< The LibSceNpCommerce implementation
|
||||||
Lib_NpScore, ///< The LibSceNpScore implementation
|
Lib_NpAuth, ///< The LibSceNpAuth implementation
|
||||||
Lib_NpTrophy, ///< The LibSceNpTrophy implementation
|
Lib_NpManager, ///< The LibSceNpManager implementation
|
||||||
Lib_NpWebApi, ///< The LibSceWebApi implementation
|
Lib_NpScore, ///< The LibSceNpScore implementation
|
||||||
Lib_Screenshot, ///< The LibSceScreenshot implementation
|
Lib_NpTrophy, ///< The LibSceNpTrophy implementation
|
||||||
Lib_LibCInternal, ///< The LibCInternal implementation.
|
Lib_NpWebApi, ///< The LibSceWebApi implementation
|
||||||
Lib_AppContent, ///< The LibSceAppContent implementation.
|
Lib_NpProfileDialog, ///< The LibSceNpProfileDialog implementation
|
||||||
Lib_Rtc, ///< The LibSceRtc implementation.
|
Lib_NpSnsFacebookDialog, ///< The LibSceNpSnsFacebookDialog implementation
|
||||||
Lib_DiscMap, ///< The LibSceDiscMap implementation.
|
Lib_Screenshot, ///< The LibSceScreenshot implementation
|
||||||
Lib_Png, ///< The LibScePng implementation.
|
Lib_LibCInternal, ///< The LibCInternal implementation.
|
||||||
Lib_Jpeg, ///< The LibSceJpeg implementation.
|
Lib_AppContent, ///< The LibSceAppContent implementation.
|
||||||
Lib_PlayGo, ///< The LibScePlayGo implementation.
|
Lib_Rtc, ///< The LibSceRtc implementation.
|
||||||
Lib_PlayGoDialog, ///< The LibScePlayGoDialog implementation.
|
Lib_DiscMap, ///< The LibSceDiscMap implementation.
|
||||||
Lib_Random, ///< The libSceRandom implementation.
|
Lib_Png, ///< The LibScePng implementation.
|
||||||
Lib_Usbd, ///< The LibSceUsbd implementation.
|
Lib_Jpeg, ///< The LibSceJpeg implementation.
|
||||||
Lib_Ajm, ///< The LibSceAjm implementation.
|
Lib_PlayGo, ///< The LibScePlayGo implementation.
|
||||||
Lib_ErrorDialog, ///< The LibSceErrorDialog implementation.
|
Lib_PlayGoDialog, ///< The LibScePlayGoDialog implementation.
|
||||||
Lib_ImeDialog, ///< The LibSceImeDialog implementation.
|
Lib_Random, ///< The LibSceRandom implementation.
|
||||||
Lib_AvPlayer, ///< The LibSceAvPlayer implementation.
|
Lib_Usbd, ///< The LibSceUsbd implementation.
|
||||||
Lib_Ngs2, ///< The LibSceNgs2 implementation.
|
Lib_Ajm, ///< The LibSceAjm implementation.
|
||||||
Lib_Audio3d, ///< The LibSceAudio3d implementation.
|
Lib_ErrorDialog, ///< The LibSceErrorDialog implementation.
|
||||||
Lib_Ime, ///< The LibSceIme implementation
|
Lib_ImeDialog, ///< The LibSceImeDialog implementation.
|
||||||
Lib_GameLiveStreaming, ///< The LibSceGameLiveStreaming implementation
|
Lib_AvPlayer, ///< The LibSceAvPlayer implementation.
|
||||||
Lib_Remoteplay, ///< The LibSceRemotePlay implementation
|
Lib_Ngs2, ///< The LibSceNgs2 implementation.
|
||||||
Lib_SharePlay, ///< The LibSceSharePlay implemenation
|
Lib_Audio3d, ///< The LibSceAudio3d implementation.
|
||||||
Lib_Fiber, ///< The LibSceFiber implementation.
|
Lib_Ime, ///< The LibSceIme implementation
|
||||||
Lib_Vdec2, ///< The LibSceVideodec2 implementation.
|
Lib_GameLiveStreaming, ///< The LibSceGameLiveStreaming implementation
|
||||||
Lib_Videodec, ///< The LibSceVideodec implementation.
|
Lib_Remoteplay, ///< The LibSceRemotePlay implementation
|
||||||
Lib_RazorCpu, ///< The LibRazorCpu implementation.
|
Lib_SharePlay, ///< The LibSceSharePlay implemenation
|
||||||
Lib_Mouse, ///< The LibSceMouse implementation
|
Lib_Fiber, ///< The LibSceFiber implementation.
|
||||||
Lib_WebBrowserDialog, ///< The LibSceWebBrowserDialog implementation
|
Lib_Vdec2, ///< The LibSceVideodec2 implementation.
|
||||||
Lib_NpParty, ///< The LibSceNpParty implementation
|
Lib_Videodec, ///< The LibSceVideodec implementation.
|
||||||
Lib_Zlib, ///< The LibSceZlib implementation.
|
Lib_Voice, ///< The LibSceVoice implementation.
|
||||||
Lib_Hmd, ///< The LibSceHmd implementation.
|
Lib_RazorCpu, ///< The LibRazorCpu implementation.
|
||||||
Lib_SigninDialog, ///< The LibSigninDialog implementation.
|
Lib_Mouse, ///< The LibSceMouse implementation
|
||||||
Lib_Camera, ///< The LibCamera implementation.
|
Lib_WebBrowserDialog, ///< The LibSceWebBrowserDialog implementation
|
||||||
Lib_CompanionHttpd, ///< The LibCompanionHttpd implementation.
|
Lib_NpParty, ///< The LibSceNpParty implementation
|
||||||
Frontend, ///< Emulator UI
|
Lib_Zlib, ///< The LibSceZlib implementation.
|
||||||
Render, ///< Video Core
|
Lib_Hmd, ///< The LibSceHmd implementation.
|
||||||
Render_Vulkan, ///< Vulkan backend
|
Lib_HmdSetupDialog, ///< The LibSceHmdSetupDialog implementation.
|
||||||
Render_Recompiler, ///< Shader recompiler
|
Lib_SigninDialog, ///< The LibSigninDialog implementation.
|
||||||
ImGui, ///< ImGui
|
Lib_Camera, ///< The LibCamera implementation.
|
||||||
Loader, ///< ROM loader
|
Lib_CompanionHttpd, ///< The LibCompanionHttpd implementation.
|
||||||
Input, ///< Input emulation
|
Lib_CompanionUtil, ///< The LibCompanionUtil implementation.
|
||||||
Tty, ///< Debug output from emu
|
Lib_VrTracker, ///< The LibSceVrTracker implementation.
|
||||||
Count ///< Total number of logging classes
|
Lib_Font, ///< The libSceFont implementation.
|
||||||
|
Lib_FontFt, ///< The libSceFontFt 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
|
} // 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
|
||||||
@@ -3,22 +3,16 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <codecvt>
|
#include <codecvt>
|
||||||
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
#include <pugixml.hpp>
|
#include <pugixml.hpp>
|
||||||
#ifdef ENABLE_QT_GUI
|
#include "common/config.h"
|
||||||
#include <QDir>
|
#include "common/elf_info.h"
|
||||||
#include <QFile>
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QJsonDocument>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QListView>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QString>
|
|
||||||
#include <QXmlStreamReader>
|
|
||||||
#endif
|
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/path_util.h"
|
#include "common/path_util.h"
|
||||||
|
#include "core/file_format/psf.h"
|
||||||
#include "memory_patcher.h"
|
#include "memory_patcher.h"
|
||||||
|
|
||||||
namespace MemoryPatcher {
|
namespace MemoryPatcher {
|
||||||
@@ -26,7 +20,8 @@ namespace MemoryPatcher {
|
|||||||
EXPORT uintptr_t g_eboot_address;
|
EXPORT uintptr_t g_eboot_address;
|
||||||
uint64_t g_eboot_image_size;
|
uint64_t g_eboot_image_size;
|
||||||
std::string g_game_serial;
|
std::string g_game_serial;
|
||||||
std::string patchFile;
|
std::string patch_file;
|
||||||
|
bool patches_applied = false;
|
||||||
std::vector<patchInfo> pending_patches;
|
std::vector<patchInfo> pending_patches;
|
||||||
|
|
||||||
std::string toHex(u64 value, size_t byteSize) {
|
std::string toHex(u64 value, size_t byteSize) {
|
||||||
@@ -117,251 +112,129 @@ std::string convertValueToHex(const std::string type, const std::string valueStr
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ApplyPendingPatches();
|
||||||
|
|
||||||
|
void ApplyPatchesFromXML(std::filesystem::path path) {
|
||||||
|
pugi::xml_document doc;
|
||||||
|
pugi::xml_parse_result result = doc.load_file(path.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();
|
||||||
|
it != patchXML.children().end(); ++it) {
|
||||||
|
|
||||||
|
if (std::string(it->name()) == "Metadata") {
|
||||||
|
if (std::string(it->attribute("isEnabled").value()) == "true") {
|
||||||
|
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();
|
||||||
|
if (!versionMatches && type != "mask" && type != "mask_jump32")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG_ERROR(Loader, "Could not parse patch XML: {}", result.description());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void OnGameLoaded() {
|
void OnGameLoaded() {
|
||||||
|
std::filesystem::path patch_dir = Common::FS::GetUserPath(Common::FS::PathType::PatchesDir);
|
||||||
|
if (!patch_file.empty()) {
|
||||||
|
|
||||||
if (!patchFile.empty()) {
|
auto file_path = (patch_dir / patch_file).native();
|
||||||
std::filesystem::path patchDir = Common::FS::GetUserPath(Common::FS::PathType::PatchesDir);
|
if (std::filesystem::exists(patch_file)) {
|
||||||
|
ApplyPatchesFromXML(patch_file);
|
||||||
auto filePath = (patchDir / patchFile).native();
|
|
||||||
|
|
||||||
pugi::xml_document doc;
|
|
||||||
pugi::xml_parse_result result = doc.load_file(filePath.c_str());
|
|
||||||
|
|
||||||
if (result) {
|
|
||||||
auto patchXML = doc.child("Patch");
|
|
||||||
for (pugi::xml_node_iterator it = patchXML.children().begin();
|
|
||||||
it != patchXML.children().end(); ++it) {
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
LOG_ERROR(Loader, "couldnt patch parse xml : {}", result.description());
|
|
||||||
|
|
||||||
ApplyPendingPatches();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ENABLE_QT_GUI
|
|
||||||
// We use the QT headers for the xml and json parsing, this define is only true on QT builds
|
|
||||||
QString patchDir;
|
|
||||||
Common::FS::PathToQString(patchDir, Common::FS::GetUserPath(Common::FS::PathType::PatchesDir));
|
|
||||||
QDir dir(patchDir);
|
|
||||||
QStringList folders = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
|
|
||||||
|
|
||||||
for (const QString& folder : folders) {
|
|
||||||
QString filesJsonPath = patchDir + "/" + folder + "/files.json";
|
|
||||||
|
|
||||||
QFile jsonFile(filesJsonPath);
|
|
||||||
if (!jsonFile.open(QIODevice::ReadOnly)) {
|
|
||||||
LOG_ERROR(Loader, "Unable to open files.json for reading in repository {}",
|
|
||||||
folder.toStdString());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray jsonData = jsonFile.readAll();
|
|
||||||
jsonFile.close();
|
|
||||||
|
|
||||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData);
|
|
||||||
QJsonObject jsonObject = jsonDoc.object();
|
|
||||||
|
|
||||||
QString selectedFileName;
|
|
||||||
QString serial = QString::fromStdString(g_game_serial);
|
|
||||||
|
|
||||||
for (auto it = jsonObject.constBegin(); it != jsonObject.constEnd(); ++it) {
|
|
||||||
QString filePath = it.key();
|
|
||||||
QJsonArray idsArray = it.value().toArray();
|
|
||||||
|
|
||||||
if (idsArray.contains(QJsonValue(serial))) {
|
|
||||||
selectedFileName = filePath;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selectedFileName.isEmpty()) {
|
|
||||||
LOG_ERROR(Loader, "No patch file found for the current serial in repository {}",
|
|
||||||
folder.toStdString());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString filePath = patchDir + "/" + folder + "/" + selectedFileName;
|
|
||||||
QFile file(filePath);
|
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
||||||
LOG_ERROR(Loader, "Unable to open the file for reading.");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray xmlData = file.readAll();
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
QString newXmlData;
|
|
||||||
|
|
||||||
QXmlStreamReader xmlReader(xmlData);
|
|
||||||
bool insideMetadata = false;
|
|
||||||
|
|
||||||
bool isEnabled = false;
|
|
||||||
std::string currentPatchName;
|
|
||||||
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();
|
|
||||||
|
|
||||||
// Check and update the isEnabled attribute
|
|
||||||
for (const QXmlStreamAttribute& attr : xmlReader.attributes()) {
|
|
||||||
if (attr.name() == QStringLiteral("isEnabled")) {
|
|
||||||
if (attr.value().toString() == "true") {
|
|
||||||
isEnabled = true;
|
|
||||||
} else
|
|
||||||
isEnabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (xmlReader.name() == QStringLiteral("PatchList")) {
|
|
||||||
QJsonArray linesArray;
|
|
||||||
while (!xmlReader.atEnd() &&
|
|
||||||
!(xmlReader.tokenType() == QXmlStreamReader::EndElement &&
|
|
||||||
xmlReader.name() == QStringLiteral("PatchList"))) {
|
|
||||||
xmlReader.readNext();
|
|
||||||
if (xmlReader.tokenType() == QXmlStreamReader::StartElement &&
|
|
||||||
xmlReader.name() == QStringLiteral("Line")) {
|
|
||||||
QXmlStreamAttributes attributes = xmlReader.attributes();
|
|
||||||
QJsonObject lineObject;
|
|
||||||
lineObject["Type"] = attributes.value("Type").toString();
|
|
||||||
lineObject["Address"] = attributes.value("Address").toString();
|
|
||||||
lineObject["Value"] = attributes.value("Value").toString();
|
|
||||||
lineObject["Offset"] = attributes.value("Offset").toString();
|
|
||||||
if (lineObject["Type"].toString() == "mask_jump32") {
|
|
||||||
lineObject["Target"] = attributes.value("Target").toString();
|
|
||||||
lineObject["Size"] = attributes.value("Size").toString();
|
|
||||||
}
|
|
||||||
linesArray.append(lineObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
patchLines = linesArray;
|
|
||||||
if (isEnabled) {
|
|
||||||
foreach (const QJsonValue& value, patchLines) {
|
|
||||||
QJsonObject lineObject = value.toObject();
|
|
||||||
QString type = lineObject["Type"].toString();
|
|
||||||
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();
|
|
||||||
} else {
|
|
||||||
patchValue = QString::fromStdString(convertValueToHex(
|
|
||||||
type.toStdString(), patchValue.toStdString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
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.toStdString().empty()) {
|
|
||||||
maskOffsetValue = std::stoi(maskOffsetStr.toStdString(), 0, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryPatcher::PatchMemory(
|
|
||||||
currentPatchName, address.toStdString(), patchValue.toStdString(),
|
|
||||||
targetStr.toStdString(), sizeStr.toStdString(), false, littleEndian,
|
|
||||||
patchMask, maskOffsetValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xmlReader.hasError()) {
|
|
||||||
LOG_ERROR(Loader, "Failed to parse XML for {}", g_game_serial);
|
|
||||||
} else {
|
} else {
|
||||||
LOG_INFO(Loader, "Patches loaded successfully");
|
ApplyPatchesFromXML(file_path);
|
||||||
|
}
|
||||||
|
} else if (Config::getLoadAutoPatches()) {
|
||||||
|
for (auto const& repo : std::filesystem::directory_iterator(patch_dir)) {
|
||||||
|
if (!repo.is_directory()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::ifstream json_file{repo.path() / "files.json"};
|
||||||
|
nlohmann::json available_patches = nlohmann::json::parse(json_file);
|
||||||
|
std::filesystem::path game_patch_file;
|
||||||
|
for (auto const& [filename, serials] : available_patches.items()) {
|
||||||
|
if (std::find(serials.begin(), serials.end(), g_game_serial) != serials.end()) {
|
||||||
|
game_patch_file = repo.path() / filename;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (std::filesystem::exists(game_patch_file)) {
|
||||||
|
ApplyPatchesFromXML(game_patch_file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ApplyPendingPatches();
|
|
||||||
}
|
}
|
||||||
#endif
|
ApplyPendingPatches();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddPatchToQueue(patchInfo patchToAdd) {
|
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);
|
pending_patches.push_back(patchToAdd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplyPendingPatches() {
|
void ApplyPendingPatches() {
|
||||||
|
patches_applied = true;
|
||||||
for (size_t i = 0; i < pending_patches.size(); ++i) {
|
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;
|
continue;
|
||||||
|
|
||||||
PatchMemory(currentPatch.modNameStr, currentPatch.offsetStr, currentPatch.valueStr, "", "",
|
PatchMemory(currentPatch.modNameStr, currentPatch.offsetStr, currentPatch.valueStr,
|
||||||
currentPatch.isOffset, currentPatch.littleEndian, currentPatch.patchMask,
|
currentPatch.targetStr, currentPatch.sizeStr, currentPatch.isOffset,
|
||||||
currentPatch.maskOffset);
|
currentPatch.littleEndian, currentPatch.patchMask, currentPatch.maskOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
pending_patches.clear();
|
pending_patches.clear();
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace MemoryPatcher {
|
|||||||
extern EXPORT uintptr_t g_eboot_address;
|
extern EXPORT uintptr_t g_eboot_address;
|
||||||
extern uint64_t g_eboot_image_size;
|
extern uint64_t g_eboot_image_size;
|
||||||
extern std::string g_game_serial;
|
extern std::string g_game_serial;
|
||||||
extern std::string patchFile;
|
extern std::string patch_file;
|
||||||
|
|
||||||
enum PatchMask : uint8_t {
|
enum PatchMask : uint8_t {
|
||||||
None,
|
None,
|
||||||
@@ -30,19 +30,18 @@ struct patchInfo {
|
|||||||
std::string modNameStr;
|
std::string modNameStr;
|
||||||
std::string offsetStr;
|
std::string offsetStr;
|
||||||
std::string valueStr;
|
std::string valueStr;
|
||||||
|
std::string targetStr;
|
||||||
|
std::string sizeStr;
|
||||||
bool isOffset;
|
bool isOffset;
|
||||||
bool littleEndian;
|
bool littleEndian;
|
||||||
PatchMask patchMask;
|
PatchMask patchMask;
|
||||||
int maskOffset;
|
int maskOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern std::vector<patchInfo> pending_patches;
|
|
||||||
|
|
||||||
std::string convertValueToHex(const std::string type, const std::string valueStr);
|
std::string convertValueToHex(const std::string type, const std::string valueStr);
|
||||||
|
|
||||||
void OnGameLoaded();
|
void OnGameLoaded();
|
||||||
void AddPatchToQueue(patchInfo patchToAdd);
|
void AddPatchToQueue(patchInfo patchToAdd);
|
||||||
void ApplyPendingPatches();
|
|
||||||
|
|
||||||
void PatchMemory(std::string modNameStr, std::string offsetStr, std::string valueStr,
|
void PatchMemory(std::string modNameStr, std::string offsetStr, std::string valueStr,
|
||||||
std::string targetStr, std::string sizeStr, bool isOffset, bool littleEndian,
|
std::string targetStr, std::string sizeStr, bool isOffset, bool littleEndian,
|
||||||
|
|||||||
@@ -1,20 +1,14 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <half.hpp>
|
#include <half.hpp>
|
||||||
|
|
||||||
#include "common/number_utils.h"
|
#include "common/number_utils.h"
|
||||||
#include "video_core/amdgpu/pixel_format.h"
|
|
||||||
#include "video_core/amdgpu/types.h"
|
|
||||||
|
|
||||||
#define UF11_EXPONENT_SHIFT 6
|
constexpr u32 UF11_EXPONENT_SHIFT = 6;
|
||||||
#define UF10_EXPONENT_SHIFT 5
|
constexpr u32 UF10_EXPONENT_SHIFT = 5;
|
||||||
|
constexpr u32 RGB9E5_MANTISSA_BITS = 9;
|
||||||
#define RGB9E5_MANTISSA_BITS 9
|
constexpr u32 RGB9E5_EXP_BIAS = 1;
|
||||||
#define RGB9E5_EXP_BIAS 1
|
constexpr u32 F32_INFINITY = 0x7f800000;
|
||||||
|
|
||||||
#define F32_INFINITY 0x7f800000
|
|
||||||
|
|
||||||
namespace NumberUtils {
|
namespace NumberUtils {
|
||||||
|
|
||||||
|
|||||||
@@ -25,10 +25,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_QT_GUI
|
|
||||||
#include <QString>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Common::FS {
|
namespace Common::FS {
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
@@ -88,13 +84,6 @@ static std::optional<std::filesystem::path> GetBundleParentDirectory() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static auto UserPaths = [] {
|
static auto UserPaths = [] {
|
||||||
#if defined(__APPLE__) && defined(ENABLE_QT_GUI)
|
|
||||||
// Set the current path to the directory containing the app bundle.
|
|
||||||
if (const auto bundle_dir = GetBundleParentDirectory()) {
|
|
||||||
std::filesystem::current_path(*bundle_dir);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Try the portable user directory first.
|
// Try the portable user directory first.
|
||||||
auto user_dir = std::filesystem::current_path() / PORTABLE_DIR;
|
auto user_dir = std::filesystem::current_path() / PORTABLE_DIR;
|
||||||
if (!std::filesystem::exists(user_dir)) {
|
if (!std::filesystem::exists(user_dir)) {
|
||||||
@@ -137,6 +126,8 @@ static auto UserPaths = [] {
|
|||||||
create_path(PathType::PatchesDir, user_dir / PATCHES_DIR);
|
create_path(PathType::PatchesDir, user_dir / PATCHES_DIR);
|
||||||
create_path(PathType::MetaDataDir, user_dir / METADATA_DIR);
|
create_path(PathType::MetaDataDir, user_dir / METADATA_DIR);
|
||||||
create_path(PathType::CustomTrophy, user_dir / CUSTOM_TROPHY);
|
create_path(PathType::CustomTrophy, user_dir / CUSTOM_TROPHY);
|
||||||
|
create_path(PathType::CustomConfigs, user_dir / CUSTOM_CONFIGS);
|
||||||
|
create_path(PathType::CacheDir, user_dir / CACHE_DIR);
|
||||||
|
|
||||||
std::ofstream notice_file(user_dir / CUSTOM_TROPHY / "Notice.txt");
|
std::ofstream notice_file(user_dir / CUSTOM_TROPHY / "Notice.txt");
|
||||||
if (notice_file.is_open()) {
|
if (notice_file.is_open()) {
|
||||||
@@ -228,22 +219,4 @@ std::optional<fs::path> FindGameByID(const fs::path& dir, const std::string& gam
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_QT_GUI
|
|
||||||
void PathToQString(QString& result, const std::filesystem::path& path) {
|
|
||||||
#ifdef _WIN32
|
|
||||||
result = QString::fromStdWString(path.wstring());
|
|
||||||
#else
|
|
||||||
result = QString::fromStdString(path.string());
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
std::filesystem::path PathFromQString(const QString& path) {
|
|
||||||
#ifdef _WIN32
|
|
||||||
return std::filesystem::path(path.toStdWString());
|
|
||||||
#else
|
|
||||||
return std::filesystem::path(path.toStdString());
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace Common::FS
|
} // namespace Common::FS
|
||||||
|
|||||||
@@ -7,10 +7,6 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#ifdef ENABLE_QT_GUI
|
|
||||||
class QString; // to avoid including <QString> in this header
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Common::FS {
|
namespace Common::FS {
|
||||||
|
|
||||||
enum class PathType {
|
enum class PathType {
|
||||||
@@ -27,6 +23,8 @@ enum class PathType {
|
|||||||
PatchesDir, // Where patches are stored.
|
PatchesDir, // Where patches are stored.
|
||||||
MetaDataDir, // Where game metadata (e.g. trophies and menu backgrounds) is stored.
|
MetaDataDir, // Where game metadata (e.g. trophies and menu backgrounds) is stored.
|
||||||
CustomTrophy, // Where custom files for trophies are stored.
|
CustomTrophy, // Where custom files for trophies are stored.
|
||||||
|
CustomConfigs, // Where custom files for different games are stored.
|
||||||
|
CacheDir, // Where pipeline and shader cache is stored.
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr auto PORTABLE_DIR = "user";
|
constexpr auto PORTABLE_DIR = "user";
|
||||||
@@ -44,6 +42,8 @@ constexpr auto CHEATS_DIR = "cheats";
|
|||||||
constexpr auto PATCHES_DIR = "patches";
|
constexpr auto PATCHES_DIR = "patches";
|
||||||
constexpr auto METADATA_DIR = "game_data";
|
constexpr auto METADATA_DIR = "game_data";
|
||||||
constexpr auto CUSTOM_TROPHY = "custom_trophy";
|
constexpr auto CUSTOM_TROPHY = "custom_trophy";
|
||||||
|
constexpr auto CUSTOM_CONFIGS = "custom_configs";
|
||||||
|
constexpr auto CACHE_DIR = "cache";
|
||||||
|
|
||||||
// Filenames
|
// Filenames
|
||||||
constexpr auto LOG_FILE = "shad_log.txt";
|
constexpr auto LOG_FILE = "shad_log.txt";
|
||||||
@@ -97,25 +97,6 @@ constexpr auto LOG_FILE = "shad_log.txt";
|
|||||||
*/
|
*/
|
||||||
void SetUserPath(PathType user_path, const std::filesystem::path& new_path);
|
void SetUserPath(PathType user_path, const std::filesystem::path& new_path);
|
||||||
|
|
||||||
#ifdef ENABLE_QT_GUI
|
|
||||||
/**
|
|
||||||
* Converts an std::filesystem::path to a QString.
|
|
||||||
* The native underlying string of a path is wstring on Windows and string on POSIX.
|
|
||||||
*
|
|
||||||
* @param result The resulting QString
|
|
||||||
* @param path The path to convert
|
|
||||||
*/
|
|
||||||
void PathToQString(QString& result, const std::filesystem::path& path);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a QString to an std::filesystem::path.
|
|
||||||
* The native underlying string of a path is wstring on Windows and string on POSIX.
|
|
||||||
*
|
|
||||||
* @param path The path to convert
|
|
||||||
*/
|
|
||||||
[[nodiscard]] std::filesystem::path PathFromQString(const QString& path);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively searches for a game directory by its ID.
|
* Recursively searches for a game directory by its ID.
|
||||||
* Limits search depth to prevent excessive filesystem traversal.
|
* Limits search depth to prevent excessive filesystem traversal.
|
||||||
|
|||||||
101
src/common/range_lock.h
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
// From boost thread locking
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
struct RangeLockGuard {
|
||||||
|
Iterator begin;
|
||||||
|
Iterator end;
|
||||||
|
|
||||||
|
RangeLockGuard(Iterator begin_, Iterator end_) : begin(begin_), end(end_) {
|
||||||
|
LockRange(begin, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
void release() {
|
||||||
|
begin = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
~RangeLockGuard() {
|
||||||
|
for (; begin != end; ++begin) {
|
||||||
|
begin->unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
Iterator TryLockRange(Iterator begin, Iterator end) {
|
||||||
|
using LockType = typename std::iterator_traits<Iterator>::value_type;
|
||||||
|
|
||||||
|
if (begin == end) {
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_lock<LockType> guard(*begin, std::try_to_lock);
|
||||||
|
if (!guard.owns_lock()) {
|
||||||
|
return begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator failed = TryLockRange(++begin, end);
|
||||||
|
if (failed == end) {
|
||||||
|
guard.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
void LockRange(Iterator begin, Iterator end) {
|
||||||
|
using LockType = typename std::iterator_traits<Iterator>::value_type;
|
||||||
|
|
||||||
|
if (begin == end) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool start_with_begin = true;
|
||||||
|
Iterator second = begin;
|
||||||
|
++second;
|
||||||
|
Iterator next = second;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
std::unique_lock<LockType> begin_lock(*begin, std::defer_lock);
|
||||||
|
if (start_with_begin) {
|
||||||
|
begin_lock.lock();
|
||||||
|
|
||||||
|
const Iterator failed_lock = TryLockRange(next, end);
|
||||||
|
if (failed_lock == end) {
|
||||||
|
begin_lock.release();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
start_with_begin = false;
|
||||||
|
next = failed_lock;
|
||||||
|
} else {
|
||||||
|
RangeLockGuard<Iterator> guard(next, end);
|
||||||
|
|
||||||
|
if (begin_lock.try_lock()) {
|
||||||
|
const Iterator failed_lock = TryLockRange(second, next);
|
||||||
|
if (failed_lock == next) {
|
||||||
|
begin_lock.release();
|
||||||
|
guard.release();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
start_with_begin = false;
|
||||||
|
next = failed_lock;
|
||||||
|
} else {
|
||||||
|
start_with_begin = true;
|
||||||
|
next = second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Common
|
||||||
37
src/common/recursive_lock.cpp
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "common/recursive_lock.h"
|
||||||
|
|
||||||
|
namespace Common::Detail {
|
||||||
|
|
||||||
|
struct RecursiveLockState {
|
||||||
|
RecursiveLockType type;
|
||||||
|
int count;
|
||||||
|
};
|
||||||
|
|
||||||
|
thread_local std::unordered_map<void*, RecursiveLockState> g_recursive_locks;
|
||||||
|
|
||||||
|
bool IncrementRecursiveLock(void* mutex, RecursiveLockType type) {
|
||||||
|
auto& state = g_recursive_locks[mutex];
|
||||||
|
if (state.count == 0) {
|
||||||
|
ASSERT(state.type == RecursiveLockType::None);
|
||||||
|
state.type = type;
|
||||||
|
}
|
||||||
|
ASSERT(state.type == type);
|
||||||
|
return state.count++ == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DecrementRecursiveLock(void* mutex, RecursiveLockType type) {
|
||||||
|
auto& state = g_recursive_locks[mutex];
|
||||||
|
ASSERT(state.type == type && state.count > 0);
|
||||||
|
if (--state.count == 0) {
|
||||||
|
g_recursive_locks.erase(mutex);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Common::Detail
|
||||||
67
src/common/recursive_lock.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <optional>
|
||||||
|
#include <shared_mutex>
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
namespace Detail {
|
||||||
|
|
||||||
|
enum class RecursiveLockType { None, Shared, Exclusive };
|
||||||
|
|
||||||
|
bool IncrementRecursiveLock(void* mutex, RecursiveLockType type);
|
||||||
|
bool DecrementRecursiveLock(void* mutex, RecursiveLockType type);
|
||||||
|
|
||||||
|
} // namespace Detail
|
||||||
|
|
||||||
|
template <typename MutexType>
|
||||||
|
class RecursiveScopedLock {
|
||||||
|
public:
|
||||||
|
explicit RecursiveScopedLock(MutexType& mutex) : m_mutex(mutex), m_locked(false) {
|
||||||
|
if (Detail::IncrementRecursiveLock(&m_mutex, Detail::RecursiveLockType::Exclusive)) {
|
||||||
|
m_locked = true;
|
||||||
|
m_lock.emplace(m_mutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~RecursiveScopedLock() {
|
||||||
|
Detail::DecrementRecursiveLock(&m_mutex, Detail::RecursiveLockType::Exclusive);
|
||||||
|
if (m_locked) {
|
||||||
|
m_lock.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
MutexType& m_mutex;
|
||||||
|
std::optional<std::unique_lock<MutexType>> m_lock;
|
||||||
|
bool m_locked = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename MutexType>
|
||||||
|
class RecursiveSharedLock {
|
||||||
|
public:
|
||||||
|
explicit RecursiveSharedLock(MutexType& mutex) : m_mutex(mutex), m_locked(false) {
|
||||||
|
if (Detail::IncrementRecursiveLock(&m_mutex, Detail::RecursiveLockType::Shared)) {
|
||||||
|
m_locked = true;
|
||||||
|
m_lock.emplace(m_mutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~RecursiveSharedLock() {
|
||||||
|
Detail::DecrementRecursiveLock(&m_mutex, Detail::RecursiveLockType::Shared);
|
||||||
|
if (m_locked) {
|
||||||
|
m_lock.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
MutexType& m_mutex;
|
||||||
|
std::optional<std::shared_lock<MutexType>> m_lock;
|
||||||
|
bool m_locked = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Common
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "common/scm_rev.h"
|
#include "common/scm_rev.h"
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
@@ -15,5 +17,26 @@ constexpr char g_scm_remote_name[] = "@GIT_REMOTE_NAME@";
|
|||||||
constexpr char g_scm_remote_url[] = "@GIT_REMOTE_URL@";
|
constexpr char g_scm_remote_url[] = "@GIT_REMOTE_URL@";
|
||||||
constexpr char g_scm_date[] = "@BUILD_DATE@";
|
constexpr char g_scm_date[] = "@BUILD_DATE@";
|
||||||
|
|
||||||
|
const std::string GetRemoteNameFromLink() {
|
||||||
|
std::string remote_url(Common::g_scm_remote_url);
|
||||||
|
std::string remote_host;
|
||||||
|
try {
|
||||||
|
if (remote_url.starts_with("http")) {
|
||||||
|
if (*remote_url.rbegin() == '/') {
|
||||||
|
remote_url.pop_back();
|
||||||
|
}
|
||||||
|
remote_host = remote_url.substr(19, remote_url.rfind('/') - 19);
|
||||||
|
} else if (remote_url.starts_with("git@")) {
|
||||||
|
auto after_comma_pos = remote_url.find(':') + 1, slash_pos = remote_url.find('/');
|
||||||
|
remote_host = remote_url.substr(after_comma_pos, slash_pos - after_comma_pos);
|
||||||
|
} else {
|
||||||
|
remote_host = "unknown";
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
remote_host = "unknown";
|
||||||
|
}
|
||||||
|
return remote_host;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
extern const char g_version[];
|
extern const char g_version[];
|
||||||
@@ -15,4 +17,6 @@ extern const char g_scm_remote_name[];
|
|||||||
extern const char g_scm_remote_url[];
|
extern const char g_scm_remote_url[];
|
||||||
extern const char g_scm_date[];
|
extern const char g_scm_date[];
|
||||||
|
|
||||||
|
const std::string GetRemoteNameFromLink();
|
||||||
|
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
|
|||||||
140
src/common/serdes.h
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "common/types.h"
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace Serialization {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept Container = requires(T t) {
|
||||||
|
typename T::iterator;
|
||||||
|
{ t.begin() } -> std::same_as<typename T::iterator>;
|
||||||
|
{ t.end() } -> std::same_as<typename T::iterator>;
|
||||||
|
{ t.size() } -> std::convertible_to<std::size_t>;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Archive {
|
||||||
|
void Alloc(size_t size) {
|
||||||
|
container.resize(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Grow(size_t size) {
|
||||||
|
container.resize(container.size() + size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Merge(const Archive& ar) {
|
||||||
|
container.insert(container.end(), ar.container.cbegin(), ar.container.cend());
|
||||||
|
offset = container.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] size_t SizeBytes() const {
|
||||||
|
return container.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
u8* CurrPtr() {
|
||||||
|
return container.data() + offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Advance(size_t size) {
|
||||||
|
ASSERT(offset + size <= container.size());
|
||||||
|
offset += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<u8>&& TakeOff() {
|
||||||
|
offset = 0;
|
||||||
|
return std::move(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsEoS() const {
|
||||||
|
return offset >= container.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
Archive() = default;
|
||||||
|
explicit Archive(std::vector<u8>&& v) : container{v} {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
u32 offset{};
|
||||||
|
std::vector<u8> container{};
|
||||||
|
|
||||||
|
friend struct Writer;
|
||||||
|
friend struct Reader;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Writer {
|
||||||
|
template <typename T>
|
||||||
|
void Write(const T* ptr, size_t size) {
|
||||||
|
if (ar.offset + size >= ar.container.size()) {
|
||||||
|
ar.Grow(size);
|
||||||
|
}
|
||||||
|
std::memcpy(ar.CurrPtr(), reinterpret_cast<const void*>(ptr), size);
|
||||||
|
ar.Advance(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
requires(!Container<T>)
|
||||||
|
void Write(const T& value) {
|
||||||
|
const auto size = sizeof(value);
|
||||||
|
Write(&value, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Write(const auto& v) {
|
||||||
|
Write(v.size());
|
||||||
|
for (const auto& elem : v) {
|
||||||
|
Write(elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Write(const std::string& s) {
|
||||||
|
Write(s.size());
|
||||||
|
Write(s.c_str(), s.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
Writer() = delete;
|
||||||
|
explicit Writer(Archive& ar_) : ar{ar_} {}
|
||||||
|
|
||||||
|
Archive& ar;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Reader {
|
||||||
|
template <typename T>
|
||||||
|
void Read(T* ptr, size_t size) {
|
||||||
|
ASSERT(ar.offset + size <= ar.container.size());
|
||||||
|
std::memcpy(reinterpret_cast<void*>(ptr), ar.CurrPtr(), size);
|
||||||
|
ar.Advance(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
requires(!Container<T>)
|
||||||
|
void Read(T& value) {
|
||||||
|
const auto size = sizeof(value);
|
||||||
|
Read(&value, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Read(auto& v) {
|
||||||
|
size_t num_elements{};
|
||||||
|
Read(num_elements);
|
||||||
|
for (int i = 0; i < num_elements; ++i) {
|
||||||
|
v.emplace_back();
|
||||||
|
Read(v.back());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Read(std::string& s) {
|
||||||
|
size_t length{};
|
||||||
|
Read(length);
|
||||||
|
s.resize(length);
|
||||||
|
Read(s.data(), length);
|
||||||
|
}
|
||||||
|
|
||||||
|
Reader() = delete;
|
||||||
|
explicit Reader(Archive& ar_) : ar{ar_} {}
|
||||||
|
|
||||||
|
Archive& ar;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Serialization
|
||||||
46
src/common/shared_first_mutex.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
// Like std::shared_mutex, but reader has priority over writer.
|
||||||
|
class SharedFirstMutex {
|
||||||
|
public:
|
||||||
|
void lock() {
|
||||||
|
std::unique_lock<std::mutex> lock(mtx);
|
||||||
|
cv.wait(lock, [this]() { return !writer_active && readers == 0; });
|
||||||
|
writer_active = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlock() {
|
||||||
|
std::lock_guard<std::mutex> lock(mtx);
|
||||||
|
writer_active = false;
|
||||||
|
cv.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
void lock_shared() {
|
||||||
|
std::unique_lock<std::mutex> lock(mtx);
|
||||||
|
cv.wait(lock, [this]() { return !writer_active; });
|
||||||
|
++readers;
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlock_shared() {
|
||||||
|
std::lock_guard<std::mutex> lock(mtx);
|
||||||
|
if (--readers == 0) {
|
||||||
|
cv.notify_all();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::mutex mtx;
|
||||||
|
std::condition_variable cv;
|
||||||
|
int readers = 0;
|
||||||
|
bool writer_active = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Common
|
||||||
@@ -14,6 +14,9 @@ namespace Common {
|
|||||||
struct SlotId {
|
struct SlotId {
|
||||||
static constexpr u32 INVALID_INDEX = std::numeric_limits<u32>::max();
|
static constexpr u32 INVALID_INDEX = std::numeric_limits<u32>::max();
|
||||||
|
|
||||||
|
SlotId() noexcept = default;
|
||||||
|
constexpr SlotId(u32 index) noexcept : index(index) {}
|
||||||
|
|
||||||
constexpr auto operator<=>(const SlotId&) const noexcept = default;
|
constexpr auto operator<=>(const SlotId&) const noexcept = default;
|
||||||
|
|
||||||
constexpr explicit operator bool() const noexcept {
|
constexpr explicit operator bool() const noexcept {
|
||||||
@@ -28,6 +31,63 @@ class SlotVector {
|
|||||||
constexpr static std::size_t InitialCapacity = 2048;
|
constexpr static std::size_t InitialCapacity = 2048;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
template <typename ValueType, typename Pointer, typename Reference>
|
||||||
|
class Iterator {
|
||||||
|
public:
|
||||||
|
using iterator_category = std::forward_iterator_tag;
|
||||||
|
using value_type = ValueType;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using pointer = Pointer;
|
||||||
|
using reference = Reference;
|
||||||
|
|
||||||
|
Iterator(SlotVector& vector_, SlotId index_) : vector(vector_), slot(index_) {
|
||||||
|
AdvanceToValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
reference operator*() const {
|
||||||
|
return vector[slot];
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer operator->() const {
|
||||||
|
return &vector[slot];
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator& operator++() {
|
||||||
|
++slot.index;
|
||||||
|
AdvanceToValid();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator operator++(int) {
|
||||||
|
Iterator temp = *this;
|
||||||
|
++(*this);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Iterator& other) const {
|
||||||
|
return slot == other.slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Iterator& other) const {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void AdvanceToValid() {
|
||||||
|
while (slot < vector.values_capacity && !vector.ReadStorageBit(slot.index)) {
|
||||||
|
++slot.index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SlotVector& vector;
|
||||||
|
SlotId slot;
|
||||||
|
};
|
||||||
|
|
||||||
|
using iterator = Iterator<T, T*, T&>;
|
||||||
|
using const_iterator = Iterator<const T, const T*, const T&>;
|
||||||
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||||
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||||
|
|
||||||
SlotVector() {
|
SlotVector() {
|
||||||
Reserve(InitialCapacity);
|
Reserve(InitialCapacity);
|
||||||
}
|
}
|
||||||
@@ -60,7 +120,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
[[nodiscard]] SlotId insert(Args&&... args) noexcept {
|
SlotId insert(Args&&... args) noexcept {
|
||||||
const u32 index = FreeValueIndex();
|
const u32 index = FreeValueIndex();
|
||||||
new (&values[index].object) T(std::forward<Args>(args)...);
|
new (&values[index].object) T(std::forward<Args>(args)...);
|
||||||
SetStorageBit(index);
|
SetStorageBit(index);
|
||||||
@@ -78,6 +138,54 @@ public:
|
|||||||
return values_capacity - free_list.size();
|
return values_capacity - free_list.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iterator begin() noexcept {
|
||||||
|
return iterator(*this, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator begin() const noexcept {
|
||||||
|
return const_iterator(*this, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator cbegin() const noexcept {
|
||||||
|
return begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator end() noexcept {
|
||||||
|
return iterator(*this, values_capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator end() const noexcept {
|
||||||
|
return const_iterator(*this, values_capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator cend() const noexcept {
|
||||||
|
return end();
|
||||||
|
}
|
||||||
|
|
||||||
|
reverse_iterator rbegin() noexcept {
|
||||||
|
return reverse_iterator(end());
|
||||||
|
}
|
||||||
|
|
||||||
|
const_reverse_iterator rbegin() const noexcept {
|
||||||
|
return const_reverse_iterator(end());
|
||||||
|
}
|
||||||
|
|
||||||
|
const_reverse_iterator crbegin() const noexcept {
|
||||||
|
return rbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
reverse_iterator rend() noexcept {
|
||||||
|
return reverse_iterator(begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
const_reverse_iterator rend() const noexcept {
|
||||||
|
return const_reverse_iterator(begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
const_reverse_iterator crend() const noexcept {
|
||||||
|
return rend();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct NonTrivialDummy {
|
struct NonTrivialDummy {
|
||||||
NonTrivialDummy() noexcept {}
|
NonTrivialDummy() noexcept {}
|
||||||
|
|||||||
@@ -2,10 +2,11 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <boost/icl/separate_interval_set.hpp>
|
|
||||||
#include "common/alignment.h"
|
#include "common/alignment.h"
|
||||||
#include "common/arch.h"
|
#include "common/arch.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
#include "common/config.h"
|
||||||
|
#include "common/elf_info.h"
|
||||||
#include "common/error.h"
|
#include "common/error.h"
|
||||||
#include "core/address_space.h"
|
#include "core/address_space.h"
|
||||||
#include "core/libraries/kernel/memory.h"
|
#include "core/libraries/kernel/memory.h"
|
||||||
@@ -23,22 +24,70 @@
|
|||||||
// Reserve space for the system address space using a zerofill section.
|
// Reserve space for the system address space using a zerofill section.
|
||||||
asm(".zerofill SYSTEM_MANAGED,SYSTEM_MANAGED,__SYSTEM_MANAGED,0x7FFBFC000");
|
asm(".zerofill SYSTEM_MANAGED,SYSTEM_MANAGED,__SYSTEM_MANAGED,0x7FFBFC000");
|
||||||
asm(".zerofill SYSTEM_RESERVED,SYSTEM_RESERVED,__SYSTEM_RESERVED,0x7C0004000");
|
asm(".zerofill SYSTEM_RESERVED,SYSTEM_RESERVED,__SYSTEM_RESERVED,0x7C0004000");
|
||||||
|
asm(".zerofill USER_AREA,USER_AREA,__USER_AREA,0x5F9000000000");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Core {
|
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
|
#ifdef _WIN32
|
||||||
|
|
||||||
[[nodiscard]] constexpr u64 ToWindowsProt(Core::MemoryProt prot) {
|
[[nodiscard]] constexpr u64 ToWindowsProt(Core::MemoryProt prot) {
|
||||||
if (True(prot & Core::MemoryProt::CpuReadWrite) ||
|
const bool read =
|
||||||
True(prot & Core::MemoryProt::GpuReadWrite)) {
|
True(prot & Core::MemoryProt::CpuRead) || True(prot & Core::MemoryProt::GpuRead);
|
||||||
return PAGE_READWRITE;
|
const bool write =
|
||||||
} else if (True(prot & Core::MemoryProt::CpuRead) || True(prot & Core::MemoryProt::GpuRead)) {
|
True(prot & Core::MemoryProt::CpuWrite) || True(prot & Core::MemoryProt::GpuWrite);
|
||||||
return PAGE_READONLY;
|
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 {
|
} else {
|
||||||
return PAGE_NOACCESS;
|
if (write) {
|
||||||
|
return PAGE_READWRITE;
|
||||||
|
} else if (read && !write) {
|
||||||
|
return PAGE_READONLY;
|
||||||
|
} else {
|
||||||
|
return PAGE_NOACCESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,70 +99,108 @@ struct MemoryRegion {
|
|||||||
|
|
||||||
struct AddressSpace::Impl {
|
struct AddressSpace::Impl {
|
||||||
Impl() : process{GetCurrentProcess()} {
|
Impl() : process{GetCurrentProcess()} {
|
||||||
// Allocate virtual address placeholder for our address space.
|
// Determine the system's page alignment
|
||||||
MEM_ADDRESS_REQUIREMENTS req{};
|
SYSTEM_INFO sys_info{};
|
||||||
MEM_EXTENDED_PARAMETER param{};
|
GetSystemInfo(&sys_info);
|
||||||
req.LowestStartingAddress = reinterpret_cast<PVOID>(SYSTEM_MANAGED_MIN);
|
u64 alignment = sys_info.dwAllocationGranularity;
|
||||||
// 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;
|
|
||||||
|
|
||||||
// Typically, lower parts of system managed area is already reserved in windows.
|
// Older Windows builds have a severe performance issue with VirtualAlloc2.
|
||||||
// If reservation fails attempt again by reducing the area size a little bit.
|
// We need to get the host's Windows version, then determine if it needs a workaround.
|
||||||
// System managed is about 31GB in size so also cap the number of times we can reduce it
|
auto ntdll_handle = GetModuleHandleW(L"ntdll.dll");
|
||||||
// to a reasonable amount.
|
ASSERT_MSG(ntdll_handle, "Failed to retrieve ntdll handle");
|
||||||
static constexpr size_t ReductionOnFail = 1_GB;
|
|
||||||
static constexpr size_t MaxReductions = 10;
|
|
||||||
|
|
||||||
size_t virtual_size = SystemManagedSize + SystemReservedSize + UserSize;
|
// Get the RtlGetVersion function
|
||||||
for (u32 i = 0; i < MaxReductions; i++) {
|
s64(WINAPI * RtlGetVersion)(LPOSVERSIONINFOW);
|
||||||
virtual_base = static_cast<u8*>(VirtualAlloc2(process, NULL, virtual_size,
|
*(FARPROC*)&RtlGetVersion = GetProcAddress(ntdll_handle, "RtlGetVersion");
|
||||||
MEM_RESERVE | MEM_RESERVE_PLACEHOLDER,
|
ASSERT_MSG(RtlGetVersion, "failed to retrieve function pointer for RtlGetVersion");
|
||||||
PAGE_NOACCESS, ¶m, 1));
|
|
||||||
if (virtual_base) {
|
// Call RtlGetVersion
|
||||||
break;
|
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;
|
||||||
|
|
||||||
|
// Higher PS4 firmware versions prevent higher address mappings too.
|
||||||
|
s32 sdk_ver = Common::ElfInfo::Instance().CompiledSdkVer();
|
||||||
|
if (os_version_info.dwBuildNumber <= AffectedBuildNumber ||
|
||||||
|
sdk_ver >= Common::ElfInfo::FW_30) {
|
||||||
|
supported_user_max = 0x10000000000ULL;
|
||||||
|
// Only log the message if we're restricting the user max due to operating system.
|
||||||
|
// Since higher compiled SDK versions also get reduced max, we don't need to log there.
|
||||||
|
if (sdk_ver < Common::ElfInfo::FW_30) {
|
||||||
|
LOG_WARNING(
|
||||||
|
Core,
|
||||||
|
"Older Windows version detected, reducing user max to {:#x} to avoid problems",
|
||||||
|
supported_user_max);
|
||||||
}
|
}
|
||||||
virtual_size -= ReductionOnFail;
|
|
||||||
}
|
}
|
||||||
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_base = reinterpret_cast<u8*>(SYSTEM_RESERVED_MIN);
|
||||||
system_reserved_size = SystemReservedSize;
|
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_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: {} - {}",
|
// Increase BackingSize to account for config options.
|
||||||
fmt::ptr(system_managed_base),
|
BackingSize += Config::getExtraDmemInMbytes() * 1_MB;
|
||||||
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});
|
|
||||||
|
|
||||||
// Allocate backing file that represents the total physical memory.
|
// Allocate backing file that represents the total physical memory.
|
||||||
backing_handle =
|
backing_handle = CreateFileMapping2(INVALID_HANDLE_VALUE, nullptr, FILE_MAP_ALL_ACCESS,
|
||||||
CreateFileMapping2(INVALID_HANDLE_VALUE, nullptr, FILE_MAP_WRITE | FILE_MAP_READ,
|
PAGE_EXECUTE_READWRITE, SEC_COMMIT, BackingSize,
|
||||||
PAGE_READWRITE, SEC_COMMIT, BackingSize, nullptr, nullptr, 0);
|
nullptr, nullptr, 0);
|
||||||
|
|
||||||
ASSERT_MSG(backing_handle, "{}", Common::GetLastErrorMsg());
|
ASSERT_MSG(backing_handle, "{}", Common::GetLastErrorMsg());
|
||||||
// Allocate a virtual memory for the backing file map as placeholder
|
// Allocate a virtual memory for the backing file map as placeholder
|
||||||
backing_base = static_cast<u8*>(VirtualAlloc2(process, nullptr, BackingSize,
|
backing_base = static_cast<u8*>(VirtualAlloc2(process, nullptr, BackingSize,
|
||||||
MEM_RESERVE | MEM_RESERVE_PLACEHOLDER,
|
MEM_RESERVE | MEM_RESERVE_PLACEHOLDER,
|
||||||
PAGE_NOACCESS, nullptr, 0));
|
PAGE_NOACCESS, nullptr, 0));
|
||||||
|
ASSERT_MSG(backing_base, "{}", Common::GetLastErrorMsg());
|
||||||
|
|
||||||
// Map backing placeholder. This will commit the pages
|
// Map backing placeholder. This will commit the pages
|
||||||
void* const ret = MapViewOfFile3(backing_handle, process, backing_base, 0, BackingSize,
|
void* const ret =
|
||||||
MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, nullptr, 0);
|
MapViewOfFile3(backing_handle, process, backing_base, 0, BackingSize,
|
||||||
|
MEM_REPLACE_PLACEHOLDER, PAGE_EXECUTE_READWRITE, nullptr, 0);
|
||||||
ASSERT_MSG(ret == backing_base, "{}", Common::GetLastErrorMsg());
|
ASSERT_MSG(ret == backing_base, "{}", Common::GetLastErrorMsg());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +241,12 @@ struct AddressSpace::Impl {
|
|||||||
ASSERT_MSG(ret, "VirtualProtect failed. {}", Common::GetLastErrorMsg());
|
ASSERT_MSG(ret, "VirtualProtect failed. {}", Common::GetLastErrorMsg());
|
||||||
} else {
|
} else {
|
||||||
ptr = MapViewOfFile3(backing, process, reinterpret_cast<PVOID>(virtual_addr),
|
ptr = MapViewOfFile3(backing, process, reinterpret_cast<PVOID>(virtual_addr),
|
||||||
phys_addr, 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 {
|
} else {
|
||||||
ptr =
|
ptr =
|
||||||
@@ -296,20 +388,37 @@ struct AddressSpace::Impl {
|
|||||||
void Protect(VAddr virtual_addr, size_t size, bool read, bool write, bool execute) {
|
void Protect(VAddr virtual_addr, size_t size, bool read, bool write, bool execute) {
|
||||||
DWORD new_flags{};
|
DWORD new_flags{};
|
||||||
|
|
||||||
if (read && write && execute) {
|
if (write && !read) {
|
||||||
new_flags = PAGE_EXECUTE_READWRITE;
|
// While write-only CPU protection isn't possible, write-only GPU protection is.
|
||||||
} else if (read && write) {
|
LOG_WARNING(Core, "Converting write-only protection to read-write");
|
||||||
new_flags = PAGE_READWRITE;
|
}
|
||||||
} else if (read && !write) {
|
|
||||||
new_flags = PAGE_READONLY;
|
// All cases involving execute permissions have separate permissions.
|
||||||
} else if (execute && !read && not write) {
|
if (execute) {
|
||||||
new_flags = PAGE_EXECUTE;
|
// If there's some form of write protection requested, provide read-write permissions.
|
||||||
} else if (!read && !write && !execute) {
|
if (write) {
|
||||||
new_flags = PAGE_NOACCESS;
|
new_flags = PAGE_EXECUTE_READWRITE;
|
||||||
|
} else if (read && !write) {
|
||||||
|
new_flags = PAGE_EXECUTE_READ;
|
||||||
|
} else {
|
||||||
|
new_flags = PAGE_EXECUTE;
|
||||||
|
}
|
||||||
} else {
|
} 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,
|
LOG_CRITICAL(Common_Memory,
|
||||||
"Unsupported protection flag combination for address {:#x}, size {}",
|
"Unsupported protection flag combination for address {:#x}, size {}, "
|
||||||
virtual_addr, size);
|
"read={}, write={}, execute={}",
|
||||||
|
virtual_addr, size, read, write, execute);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,12 +434,20 @@ struct AddressSpace::Impl {
|
|||||||
DWORD old_flags{};
|
DWORD old_flags{};
|
||||||
if (!VirtualProtectEx(process, LPVOID(range_addr), range_size, new_flags, &old_flags)) {
|
if (!VirtualProtectEx(process, LPVOID(range_addr), range_size, new_flags, &old_flags)) {
|
||||||
UNREACHABLE_MSG(
|
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);
|
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 process{};
|
||||||
HANDLE backing_handle{};
|
HANDLE backing_handle{};
|
||||||
u8* backing_base{};
|
u8* backing_base{};
|
||||||
@@ -355,54 +472,73 @@ enum PosixPageProtection {
|
|||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] constexpr PosixPageProtection ToPosixProt(Core::MemoryProt prot) {
|
[[nodiscard]] constexpr PosixPageProtection ToPosixProt(Core::MemoryProt prot) {
|
||||||
if (True(prot & Core::MemoryProt::CpuReadWrite) ||
|
const bool read =
|
||||||
True(prot & Core::MemoryProt::GpuReadWrite)) {
|
True(prot & Core::MemoryProt::CpuRead) || True(prot & Core::MemoryProt::GpuRead);
|
||||||
return PAGE_READWRITE;
|
const bool write =
|
||||||
} else if (True(prot & Core::MemoryProt::CpuRead) || True(prot & Core::MemoryProt::GpuRead)) {
|
True(prot & Core::MemoryProt::CpuWrite) || True(prot & Core::MemoryProt::GpuWrite);
|
||||||
return PAGE_READONLY;
|
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 {
|
} else {
|
||||||
return PAGE_NOACCESS;
|
if (write) {
|
||||||
|
return PAGE_READWRITE;
|
||||||
|
} else if (read && !write) {
|
||||||
|
return PAGE_READONLY;
|
||||||
|
} else {
|
||||||
|
return PAGE_NOACCESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AddressSpace::Impl {
|
struct AddressSpace::Impl {
|
||||||
Impl() {
|
Impl() {
|
||||||
|
BackingSize += Config::getExtraDmemInMbytes() * 1_MB;
|
||||||
// Allocate virtual address placeholder for our address space.
|
// Allocate virtual address placeholder for our address space.
|
||||||
system_managed_size = SystemManagedSize;
|
system_managed_size = SystemManagedSize;
|
||||||
system_reserved_size = SystemReservedSize;
|
system_reserved_size = SystemReservedSize;
|
||||||
user_size = UserSize;
|
user_size = UserSize;
|
||||||
|
|
||||||
constexpr int protection_flags = PROT_READ | PROT_WRITE;
|
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)
|
#if defined(__APPLE__) && defined(ARCH_X86_64)
|
||||||
// On ARM64 Macs under Rosetta 2, we run into limitations due to the commpage from
|
// On ARM64 Macs, we run into limitations due to the commpage from 0xFC0000000 - 0xFFFFFFFFF
|
||||||
// 0xFC0000000 - 0xFFFFFFFFF and the GPU carveout region from 0x1000000000 - 0x6FFFFFFFFF.
|
// and the GPU carveout region from 0x1000000000 - 0x6FFFFFFFFF. Because this creates gaps
|
||||||
// We can allocate the system managed region, as well as system reserved if reduced in size
|
// in the available virtual memory region, we map memory space using three distinct parts.
|
||||||
// slightly, but we cannot map the user region where we want, so we must let the OS put it
|
system_managed_base =
|
||||||
// wherever possible and hope the game won't rely on its location.
|
reinterpret_cast<u8*>(mmap(reinterpret_cast<void*>(SYSTEM_MANAGED_MIN),
|
||||||
system_managed_base = reinterpret_cast<u8*>(
|
system_managed_size, protection_flags, map_flags, -1, 0));
|
||||||
mmap(reinterpret_cast<void*>(SYSTEM_MANAGED_MIN), system_managed_size, protection_flags,
|
system_reserved_base =
|
||||||
base_map_flags | MAP_FIXED, -1, 0));
|
reinterpret_cast<u8*>(mmap(reinterpret_cast<void*>(SYSTEM_RESERVED_MIN),
|
||||||
system_reserved_base = reinterpret_cast<u8*>(
|
system_reserved_size, protection_flags, map_flags, -1, 0));
|
||||||
mmap(reinterpret_cast<void*>(SYSTEM_RESERVED_MIN), system_reserved_size,
|
user_base = reinterpret_cast<u8*>(
|
||||||
protection_flags, base_map_flags | MAP_FIXED, -1, 0));
|
mmap(reinterpret_cast<void*>(USER_MIN), user_size, protection_flags, map_flags, -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));
|
|
||||||
#else
|
#else
|
||||||
const auto virtual_size = system_managed_size + system_reserved_size + user_size;
|
const auto virtual_size = system_managed_size + system_reserved_size + user_size;
|
||||||
#if defined(ARCH_X86_64)
|
#if defined(ARCH_X86_64)
|
||||||
const auto virtual_base =
|
const auto virtual_base =
|
||||||
reinterpret_cast<u8*>(mmap(reinterpret_cast<void*>(SYSTEM_MANAGED_MIN), virtual_size,
|
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_managed_base = virtual_base;
|
||||||
system_reserved_base = reinterpret_cast<u8*>(SYSTEM_RESERVED_MIN);
|
system_reserved_base = reinterpret_cast<u8*>(SYSTEM_RESERVED_MIN);
|
||||||
user_base = reinterpret_cast<u8*>(USER_MIN);
|
user_base = reinterpret_cast<u8*>(USER_MIN);
|
||||||
#else
|
#else
|
||||||
// Map memory wherever possible and instruction translation can handle offsetting to the
|
// Map memory wherever possible and instruction translation can handle offsetting to the
|
||||||
// base.
|
// base.
|
||||||
const auto virtual_base = reinterpret_cast<u8*>(
|
const auto virtual_base =
|
||||||
mmap(nullptr, virtual_size, protection_flags, base_map_flags, -1, 0));
|
reinterpret_cast<u8*>(mmap(nullptr, virtual_size, protection_flags, map_flags, -1, 0));
|
||||||
system_managed_base = virtual_base;
|
system_managed_base = virtual_base;
|
||||||
system_reserved_base = virtual_base + SYSTEM_RESERVED_MIN - SYSTEM_MANAGED_MIN;
|
system_reserved_base = virtual_base + SYSTEM_RESERVED_MIN - SYSTEM_MANAGED_MIN;
|
||||||
user_base = virtual_base + USER_MIN - SYSTEM_MANAGED_MIN;
|
user_base = virtual_base + USER_MIN - SYSTEM_MANAGED_MIN;
|
||||||
@@ -570,9 +706,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.
|
// the entire allocation and remap the portions outside of the requested unmapping range.
|
||||||
impl->Unmap(virtual_addr, size, has_backing && !readonly_file);
|
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),
|
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) {
|
if (start_in_vma != 0) {
|
||||||
Map(virtual_addr, start_in_vma, 0, phys_base, is_exec);
|
Map(virtual_addr, start_in_vma, 0, phys_base, is_exec);
|
||||||
@@ -593,4 +729,22 @@ void AddressSpace::Protect(VAddr virtual_addr, size_t size, MemoryPermission per
|
|||||||
return impl->Protect(virtual_addr, size, read, write, execute);
|
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
|
} // namespace Core
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <boost/icl/separate_interval_set.hpp>
|
||||||
#include "common/arch.h"
|
#include "common/arch.h"
|
||||||
#include "common/enum.h"
|
#include "common/enum.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
@@ -11,6 +12,7 @@
|
|||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
enum class MemoryPermission : u32 {
|
enum class MemoryPermission : u32 {
|
||||||
|
None = 0,
|
||||||
Read = 1 << 0,
|
Read = 1 << 0,
|
||||||
Write = 1 << 1,
|
Write = 1 << 1,
|
||||||
ReadWrite = Read | Write,
|
ReadWrite = Read | Write,
|
||||||
@@ -19,22 +21,6 @@ enum class MemoryPermission : u32 {
|
|||||||
};
|
};
|
||||||
DECLARE_ENUM_FLAG_OPERATORS(MemoryPermission)
|
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
|
* Represents the user virtual address space backed by a dmem memory block
|
||||||
*/
|
*/
|
||||||
@@ -99,6 +85,9 @@ public:
|
|||||||
|
|
||||||
void Protect(VAddr virtual_addr, size_t size, MemoryPermission perms);
|
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:
|
private:
|
||||||
struct Impl;
|
struct Impl;
|
||||||
std::unique_ptr<Impl> impl;
|
std::unique_ptr<Impl> impl;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
#include <Zydis/Zydis.h>
|
#include <Zydis/Zydis.h>
|
||||||
#include <xbyak/xbyak.h>
|
#include <xbyak/xbyak.h>
|
||||||
#include <xbyak/xbyak_util.h>
|
#include <xbyak/xbyak_util.h>
|
||||||
@@ -88,7 +89,8 @@ static bool FilterTcbAccess(const ZydisDecodedOperand* operands) {
|
|||||||
dst_op.reg.value <= ZYDIS_REGISTER_R15;
|
dst_op.reg.value <= ZYDIS_REGISTER_R15;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GenerateTcbAccess(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
static void GenerateTcbAccess(void* /* address */, const ZydisDecodedOperand* operands,
|
||||||
|
Xbyak::CodeGenerator& c) {
|
||||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
@@ -121,12 +123,37 @@ static void GenerateTcbAccess(const ZydisDecodedOperand* operands, Xbyak::CodeGe
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool FilterStackCheck(const ZydisDecodedOperand* operands) {
|
||||||
|
const auto& dst_op = operands[0];
|
||||||
|
const auto& src_op = operands[1];
|
||||||
|
|
||||||
|
// Some compilers emit stack checks by starting a function with
|
||||||
|
// 'mov (64-bit register), fs:[0x28]', then checking with `xor (64-bit register), fs:[0x28]`
|
||||||
|
return src_op.type == ZYDIS_OPERAND_TYPE_MEMORY && src_op.mem.segment == ZYDIS_REGISTER_FS &&
|
||||||
|
src_op.mem.base == ZYDIS_REGISTER_NONE && src_op.mem.index == ZYDIS_REGISTER_NONE &&
|
||||||
|
src_op.mem.disp.value == 0x28 && dst_op.reg.value >= ZYDIS_REGISTER_RAX &&
|
||||||
|
dst_op.reg.value <= ZYDIS_REGISTER_R15;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GenerateStackCheck(void* /* address */, const ZydisDecodedOperand* operands,
|
||||||
|
Xbyak::CodeGenerator& c) {
|
||||||
|
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||||
|
c.xor_(dst, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GenerateStackCanary(void* /* address */, const ZydisDecodedOperand* operands,
|
||||||
|
Xbyak::CodeGenerator& c) {
|
||||||
|
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||||
|
c.mov(dst, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static bool FilterNoSSE4a(const ZydisDecodedOperand*) {
|
static bool FilterNoSSE4a(const ZydisDecodedOperand*) {
|
||||||
Cpu cpu;
|
Cpu cpu;
|
||||||
return !cpu.has(Cpu::tSSE4a);
|
return !cpu.has(Cpu::tSSE4a);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GenerateEXTRQ(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
static void GenerateEXTRQ(void* /* address */, const ZydisDecodedOperand* operands,
|
||||||
|
Xbyak::CodeGenerator& c) {
|
||||||
bool immediateForm = operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
|
bool immediateForm = operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
|
||||||
operands[2].type == ZYDIS_OPERAND_TYPE_IMMEDIATE;
|
operands[2].type == ZYDIS_OPERAND_TYPE_IMMEDIATE;
|
||||||
|
|
||||||
@@ -161,7 +188,9 @@ static void GenerateEXTRQ(const ZydisDecodedOperand* operands, Xbyak::CodeGenera
|
|||||||
mask = (1ULL << length) - 1;
|
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
|
// Get lower qword from xmm register
|
||||||
c.vmovq(scratch1, xmm_dst);
|
c.vmovq(scratch1, xmm_dst);
|
||||||
@@ -175,8 +204,8 @@ static void GenerateEXTRQ(const ZydisDecodedOperand* operands, Xbyak::CodeGenera
|
|||||||
c.mov(scratch2, mask);
|
c.mov(scratch2, mask);
|
||||||
c.and_(scratch1, scratch2);
|
c.and_(scratch1, scratch2);
|
||||||
|
|
||||||
// Writeback to xmm register, extrq instruction says top 64-bits are undefined so we don't
|
// Writeback to xmm register, extrq instruction says top 64-bits are undefined but zeroed on
|
||||||
// care to preserve them
|
// AMD CPUs
|
||||||
c.vmovq(xmm_dst, scratch1);
|
c.vmovq(xmm_dst, scratch1);
|
||||||
|
|
||||||
c.pop(scratch2);
|
c.pop(scratch2);
|
||||||
@@ -245,7 +274,8 @@ static void GenerateEXTRQ(const ZydisDecodedOperand* operands, Xbyak::CodeGenera
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GenerateINSERTQ(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
static void GenerateINSERTQ(void* /* address */, const ZydisDecodedOperand* operands,
|
||||||
|
Xbyak::CodeGenerator& c) {
|
||||||
bool immediateForm = operands[2].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
|
bool immediateForm = operands[2].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
|
||||||
operands[3].type == ZYDIS_OPERAND_TYPE_IMMEDIATE;
|
operands[3].type == ZYDIS_OPERAND_TYPE_IMMEDIATE;
|
||||||
|
|
||||||
@@ -284,7 +314,9 @@ static void GenerateINSERTQ(const ZydisDecodedOperand* operands, Xbyak::CodeGene
|
|||||||
mask_value = (1ULL << length) - 1;
|
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(scratch1, xmm_src);
|
||||||
c.vmovq(scratch2, xmm_dst);
|
c.vmovq(scratch2, xmm_dst);
|
||||||
@@ -304,8 +336,9 @@ static void GenerateINSERTQ(const ZydisDecodedOperand* operands, Xbyak::CodeGene
|
|||||||
// dst |= src
|
// dst |= src
|
||||||
c.or_(scratch2, scratch1);
|
c.or_(scratch2, scratch1);
|
||||||
|
|
||||||
// Insert scratch2 into low 64 bits of dst, upper 64 bits are unaffected
|
// Insert scratch2 into low 64 bits of dst, upper 64 bits are undefined but zeroed on AMD
|
||||||
c.vpinsrq(xmm_dst, xmm_dst, scratch2, 0);
|
// CPUs
|
||||||
|
c.vmovq(xmm_dst, scratch2);
|
||||||
|
|
||||||
c.pop(mask);
|
c.pop(mask);
|
||||||
c.pop(scratch2);
|
c.pop(scratch2);
|
||||||
@@ -371,7 +404,7 @@ static void GenerateINSERTQ(const ZydisDecodedOperand* operands, Xbyak::CodeGene
|
|||||||
c.and_(scratch2, mask);
|
c.and_(scratch2, mask);
|
||||||
c.or_(scratch2, scratch1);
|
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.vmovq(xmm_dst, scratch2);
|
||||||
|
|
||||||
c.pop(mask);
|
c.pop(mask);
|
||||||
@@ -383,8 +416,44 @@ static void GenerateINSERTQ(const ZydisDecodedOperand* operands, Xbyak::CodeGene
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ReplaceMOVNT(void* address, u8 rep_prefix) {
|
||||||
|
// Find the opcode byte
|
||||||
|
// There can be any amount of prefixes but the instruction can't be more than 15 bytes
|
||||||
|
// And we know for sure this is a MOVNTSS/MOVNTSD
|
||||||
|
bool found = false;
|
||||||
|
bool rep_prefix_found = false;
|
||||||
|
int index = 0;
|
||||||
|
u8* ptr = reinterpret_cast<u8*>(address);
|
||||||
|
for (int i = 0; i < 15; i++) {
|
||||||
|
if (ptr[i] == rep_prefix) {
|
||||||
|
rep_prefix_found = true;
|
||||||
|
} else if (ptr[i] == 0x2B) {
|
||||||
|
index = i;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some sanity checks
|
||||||
|
ASSERT(found);
|
||||||
|
ASSERT(index >= 2);
|
||||||
|
ASSERT(ptr[index - 1] == 0x0F);
|
||||||
|
ASSERT(rep_prefix_found);
|
||||||
|
|
||||||
|
// This turns the MOVNTSS/MOVNTSD to a MOVSS/MOVSD m, xmm
|
||||||
|
ptr[index] = 0x11;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ReplaceMOVNTSS(void* address, const ZydisDecodedOperand*, Xbyak::CodeGenerator&) {
|
||||||
|
ReplaceMOVNT(address, 0xF3);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ReplaceMOVNTSD(void* address, const ZydisDecodedOperand*, Xbyak::CodeGenerator&) {
|
||||||
|
ReplaceMOVNT(address, 0xF2);
|
||||||
|
}
|
||||||
|
|
||||||
using PatchFilter = bool (*)(const ZydisDecodedOperand*);
|
using PatchFilter = bool (*)(const ZydisDecodedOperand*);
|
||||||
using InstructionGenerator = void (*)(const ZydisDecodedOperand*, Xbyak::CodeGenerator&);
|
using InstructionGenerator = void (*)(void*, const ZydisDecodedOperand*, Xbyak::CodeGenerator&);
|
||||||
struct PatchInfo {
|
struct PatchInfo {
|
||||||
/// Filter for more granular patch conditions past just the instruction mnemonic.
|
/// Filter for more granular patch conditions past just the instruction mnemonic.
|
||||||
PatchFilter filter;
|
PatchFilter filter;
|
||||||
@@ -396,16 +465,26 @@ struct PatchInfo {
|
|||||||
bool trampoline;
|
bool trampoline;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::unordered_map<ZydisMnemonic, PatchInfo> Patches = {
|
static const std::unordered_map<ZydisMnemonic, std::vector<PatchInfo>> Patches = {
|
||||||
// SSE4a
|
// SSE4a
|
||||||
{ZYDIS_MNEMONIC_EXTRQ, {FilterNoSSE4a, GenerateEXTRQ, true}},
|
{ZYDIS_MNEMONIC_EXTRQ, {{FilterNoSSE4a, GenerateEXTRQ, true}}},
|
||||||
{ZYDIS_MNEMONIC_INSERTQ, {FilterNoSSE4a, GenerateINSERTQ, true}},
|
{ZYDIS_MNEMONIC_INSERTQ, {{FilterNoSSE4a, GenerateINSERTQ, true}}},
|
||||||
|
{ZYDIS_MNEMONIC_MOVNTSS, {{FilterNoSSE4a, ReplaceMOVNTSS, false}}},
|
||||||
|
{ZYDIS_MNEMONIC_MOVNTSD, {{FilterNoSSE4a, ReplaceMOVNTSD, false}}},
|
||||||
|
|
||||||
|
#if !defined(__APPLE__)
|
||||||
|
// FS segment patches
|
||||||
|
// These first two patches are for accesses to the stack canary, fs:[0x28]
|
||||||
|
{ZYDIS_MNEMONIC_XOR, {{FilterStackCheck, GenerateStackCheck, false}}},
|
||||||
|
{ZYDIS_MNEMONIC_MOV,
|
||||||
|
{{FilterStackCheck, GenerateStackCanary, false},
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
// Windows needs a trampoline.
|
// Windows needs a trampoline for Tcb accesses.
|
||||||
{ZYDIS_MNEMONIC_MOV, {FilterTcbAccess, GenerateTcbAccess, true}},
|
{FilterTcbAccess, GenerateTcbAccess, true}
|
||||||
#elif !defined(__APPLE__)
|
#else
|
||||||
{ZYDIS_MNEMONIC_MOV, {FilterTcbAccess, GenerateTcbAccess, false}},
|
{FilterTcbAccess, GenerateTcbAccess, false}
|
||||||
|
#endif
|
||||||
|
}},
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -457,51 +536,53 @@ static std::pair<bool, u64> TryPatch(u8* code, PatchModule* module) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Patches.contains(instruction.mnemonic)) {
|
if (Patches.contains(instruction.mnemonic)) {
|
||||||
const auto& patch_info = Patches.at(instruction.mnemonic);
|
const auto& patches = Patches.at(instruction.mnemonic);
|
||||||
bool needs_trampoline = patch_info.trampoline;
|
for (const auto& patch_info : patches) {
|
||||||
if (patch_info.filter(operands)) {
|
bool needs_trampoline = patch_info.trampoline;
|
||||||
auto& patch_gen = module->patch_gen;
|
if (patch_info.filter(operands)) {
|
||||||
|
auto& patch_gen = module->patch_gen;
|
||||||
|
|
||||||
if (needs_trampoline && instruction.length < 5) {
|
if (needs_trampoline && instruction.length < 5) {
|
||||||
// Trampoline is needed but instruction is too short to patch.
|
// Trampoline is needed but instruction is too short to patch.
|
||||||
// Return false and length to signal to AOT compilation that this instruction
|
// Return false and length to signal to AOT compilation that this instruction
|
||||||
// should be skipped and handled at runtime.
|
// should be skipped and handled at runtime.
|
||||||
return std::make_pair(false, instruction.length);
|
return std::make_pair(false, instruction.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset state and move to current code position.
|
// Reset state and move to current code position.
|
||||||
patch_gen.reset();
|
patch_gen.reset();
|
||||||
patch_gen.setSize(code - patch_gen.getCode());
|
patch_gen.setSize(code - patch_gen.getCode());
|
||||||
|
|
||||||
if (needs_trampoline) {
|
if (needs_trampoline) {
|
||||||
auto& trampoline_gen = module->trampoline_gen;
|
auto& trampoline_gen = module->trampoline_gen;
|
||||||
const auto trampoline_ptr = trampoline_gen.getCurr();
|
const auto trampoline_ptr = trampoline_gen.getCurr();
|
||||||
|
|
||||||
patch_info.generator(operands, trampoline_gen);
|
patch_info.generator(code, operands, trampoline_gen);
|
||||||
|
|
||||||
// Return to the following instruction at the end of the trampoline.
|
// Return to the following instruction at the end of the trampoline.
|
||||||
trampoline_gen.jmp(code + instruction.length);
|
trampoline_gen.jmp(code + instruction.length);
|
||||||
|
|
||||||
// Replace instruction with near jump to the trampoline.
|
// Replace instruction with near jump to the trampoline.
|
||||||
patch_gen.jmp(trampoline_ptr, Xbyak::CodeGenerator::LabelType::T_NEAR);
|
patch_gen.jmp(trampoline_ptr, Xbyak::CodeGenerator::LabelType::T_NEAR);
|
||||||
} else {
|
} else {
|
||||||
patch_info.generator(operands, patch_gen);
|
patch_info.generator(code, operands, patch_gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto patch_size = patch_gen.getCurr() - code;
|
const auto patch_size = patch_gen.getCurr() - code;
|
||||||
if (patch_size > 0) {
|
if (patch_size > 0) {
|
||||||
ASSERT_MSG(instruction.length >= patch_size,
|
ASSERT_MSG(instruction.length >= patch_size,
|
||||||
"Instruction {} with length {} is too short to replace at: {}",
|
"Instruction {} with length {} is too short to replace at: {}",
|
||||||
ZydisMnemonicGetString(instruction.mnemonic), instruction.length,
|
ZydisMnemonicGetString(instruction.mnemonic), instruction.length,
|
||||||
fmt::ptr(code));
|
fmt::ptr(code));
|
||||||
|
|
||||||
// Fill remaining space with nops.
|
// Fill remaining space with nops.
|
||||||
patch_gen.nop(instruction.length - patch_size);
|
patch_gen.nop(instruction.length - patch_size);
|
||||||
|
|
||||||
module->patched.insert(code);
|
module->patched.insert(code);
|
||||||
LOG_DEBUG(Core, "Patched instruction '{}' at: {}",
|
LOG_DEBUG(Core, "Patched instruction '{}' at: {}",
|
||||||
ZydisMnemonicGetString(instruction.mnemonic), fmt::ptr(code));
|
ZydisMnemonicGetString(instruction.mnemonic), fmt::ptr(code));
|
||||||
return std::make_pair(true, instruction.length);
|
return std::make_pair(true, instruction.length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -594,6 +675,7 @@ static bool TryExecuteIllegalInstruction(void* ctx, void* code_address) {
|
|||||||
lowQWordDst >>= index;
|
lowQWordDst >>= index;
|
||||||
lowQWordDst &= mask;
|
lowQWordDst &= mask;
|
||||||
|
|
||||||
|
memset((u8*)dst + sizeof(u64), 0, sizeof(u64));
|
||||||
memcpy(dst, &lowQWordDst, sizeof(lowQWordDst));
|
memcpy(dst, &lowQWordDst, sizeof(lowQWordDst));
|
||||||
|
|
||||||
Common::IncrementRip(ctx, 4);
|
Common::IncrementRip(ctx, 4);
|
||||||
@@ -634,6 +716,7 @@ static bool TryExecuteIllegalInstruction(void* ctx, void* code_address) {
|
|||||||
lowQWordDst &= ~(mask << index);
|
lowQWordDst &= ~(mask << index);
|
||||||
lowQWordDst |= lowQWordSrc << index;
|
lowQWordDst |= lowQWordSrc << index;
|
||||||
|
|
||||||
|
memset((u8*)dst + sizeof(u64), 0, sizeof(u64));
|
||||||
memcpy(dst, &lowQWordDst, sizeof(lowQWordDst));
|
memcpy(dst, &lowQWordDst, sizeof(lowQWordDst));
|
||||||
|
|
||||||
Common::IncrementRip(ctx, 4);
|
Common::IncrementRip(ctx, 4);
|
||||||
@@ -705,9 +788,14 @@ static bool PatchesIllegalInstructionHandler(void* context) {
|
|||||||
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
|
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
|
||||||
const auto status =
|
const auto status =
|
||||||
Common::Decoder::Instance()->decodeInstruction(instruction, operands, code_address);
|
Common::Decoder::Instance()->decodeInstruction(instruction, operands, code_address);
|
||||||
LOG_ERROR(Core, "Failed to patch address {:x} -- mnemonic: {}", (u64)code_address,
|
if (ZYAN_SUCCESS(status) && instruction.mnemonic == ZydisMnemonic::ZYDIS_MNEMONIC_UD2)
|
||||||
ZYAN_SUCCESS(status) ? ZydisMnemonicGetString(instruction.mnemonic)
|
[[unlikely]] {
|
||||||
: "Failed to decode");
|
UNREACHABLE_MSG("ud2 at code address {:#x}", reinterpret_cast<u64>(code_address));
|
||||||
|
}
|
||||||
|
UNREACHABLE_MSG("Failed to patch address {:x} -- mnemonic: {}",
|
||||||
|
reinterpret_cast<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,
|
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};
|
std::scoped_lock lock{frame_dump_list_mutex};
|
||||||
|
|
||||||
auto dump = GetRegDump(base_addr, header_addr);
|
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++) {
|
for (int i = 0; i < RegDump::MaxShaderStages; i++) {
|
||||||
if ((*dump)->regs.stage_enable.IsStageEnabled(i)) {
|
if ((*dump)->regs.stage_enable.IsStageEnabled(i)) {
|
||||||
auto stage = (*dump)->regs.ProgramForStage(i);
|
auto stage = (*dump)->regs.ProgramForStage(i);
|
||||||
if (stage->address_lo != 0) {
|
if (stage->address) {
|
||||||
const auto& info = AmdGpu::Liverpool::SearchBinaryInfo(stage->Address<u32*>());
|
const auto params = AmdGpu::GetParams(*stage);
|
||||||
auto code = stage->Code();
|
|
||||||
(*dump)->stages[i] = PipelineShaderProgramDump{
|
(*dump)->stages[i] = PipelineShaderProgramDump{
|
||||||
.name = Vulkan::PipelineCache::GetShaderName(Shader::StageFromIndex(i),
|
.name = Vulkan::PipelineCache::GetShaderName(Shader::StageFromIndex(i),
|
||||||
info.shader_hash),
|
params.hash),
|
||||||
.hash = info.shader_hash,
|
.hash = params.hash,
|
||||||
.user_data = *stage,
|
.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;
|
auto& cs = (*dump)->regs.cs_program;
|
||||||
cs = cs_state;
|
cs = cs_state;
|
||||||
|
|
||||||
const auto& info = AmdGpu::Liverpool::SearchBinaryInfo(cs.Address<u32*>());
|
const auto params = AmdGpu::GetParams(cs);
|
||||||
(*dump)->cs_data = PipelineComputerProgramDump{
|
(*dump)->cs_data = PipelineComputerProgramDump{
|
||||||
.name = Vulkan::PipelineCache::GetShaderName(Shader::Stage::Compute, info.shader_hash),
|
.name = Vulkan::PipelineCache::GetShaderName(Shader::Stage::Compute, params.hash),
|
||||||
.hash = info.shader_hash,
|
.hash = params.hash,
|
||||||
.cs_program = cs,
|
.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 <queue>
|
||||||
|
|
||||||
#include "common/types.h"
|
#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
|
#ifdef _WIN32
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
@@ -54,21 +56,21 @@ struct QueueDump {
|
|||||||
struct PipelineShaderProgramDump {
|
struct PipelineShaderProgramDump {
|
||||||
std::string name;
|
std::string name;
|
||||||
u64 hash;
|
u64 hash;
|
||||||
Vulkan::Liverpool::ShaderProgram user_data{};
|
AmdGpu::ShaderProgram user_data{};
|
||||||
std::vector<u32> code{};
|
std::vector<u32> code{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PipelineComputerProgramDump {
|
struct PipelineComputerProgramDump {
|
||||||
std::string name;
|
std::string name;
|
||||||
u64 hash;
|
u64 hash;
|
||||||
Vulkan::Liverpool::ComputeProgram cs_program{};
|
AmdGpu::ComputeProgram cs_program{};
|
||||||
std::vector<u32> code{};
|
std::vector<u32> code{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RegDump {
|
struct RegDump {
|
||||||
bool is_compute{false};
|
bool is_compute{false};
|
||||||
static constexpr size_t MaxShaderStages = 5;
|
static constexpr size_t MaxShaderStages = 5;
|
||||||
Vulkan::Liverpool::Regs regs{};
|
AmdGpu::Regs regs;
|
||||||
std::array<PipelineShaderProgramDump, MaxShaderStages> stages{};
|
std::array<PipelineShaderProgramDump, MaxShaderStages> stages{};
|
||||||
PipelineComputerProgramDump cs_data{};
|
PipelineComputerProgramDump cs_data{};
|
||||||
};
|
};
|
||||||
@@ -219,9 +221,8 @@ public:
|
|||||||
|
|
||||||
void PushQueueDump(QueueDump dump);
|
void PushQueueDump(QueueDump dump);
|
||||||
|
|
||||||
void PushRegsDump(uintptr_t base_addr, uintptr_t header_addr,
|
void PushRegsDump(uintptr_t base_addr, uintptr_t header_addr, const AmdGpu::Regs& regs);
|
||||||
const AmdGpu::Liverpool::Regs& regs);
|
using CsState = AmdGpu::ComputeProgram;
|
||||||
using CsState = AmdGpu::Liverpool::ComputeProgram;
|
|
||||||
void PushRegsDumpCompute(uintptr_t base_addr, uintptr_t header_addr, const CsState& cs_state);
|
void PushRegsDumpCompute(uintptr_t base_addr, uintptr_t header_addr, const CsState& cs_state);
|
||||||
|
|
||||||
void CollectShader(const std::string& name, Shader::LogicalStage l_stage,
|
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
|
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "layer.h"
|
#include "layer.h"
|
||||||
|
|
||||||
|
#include <SDL3/SDL_events.h>
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
#include "SDL3/SDL_log.h"
|
#include "SDL3/SDL_log.h"
|
||||||
@@ -17,6 +18,7 @@
|
|||||||
#include "widget/frame_dump.h"
|
#include "widget/frame_dump.h"
|
||||||
#include "widget/frame_graph.h"
|
#include "widget/frame_graph.h"
|
||||||
#include "widget/memory_map.h"
|
#include "widget/memory_map.h"
|
||||||
|
#include "widget/module_list.h"
|
||||||
#include "widget/shader_list.h"
|
#include "widget/shader_list.h"
|
||||||
|
|
||||||
extern std::unique_ptr<Vulkan::Presenter> presenter;
|
extern std::unique_ptr<Vulkan::Presenter> presenter;
|
||||||
@@ -27,6 +29,7 @@ using L = ::Core::Devtools::Layer;
|
|||||||
|
|
||||||
static bool show_simple_fps = false;
|
static bool show_simple_fps = false;
|
||||||
static bool visibility_toggled = false;
|
static bool visibility_toggled = false;
|
||||||
|
static bool show_quit_window = false;
|
||||||
|
|
||||||
static float fps_scale = 1.0f;
|
static float fps_scale = 1.0f;
|
||||||
static int dump_frame_count = 1;
|
static int dump_frame_count = 1;
|
||||||
@@ -40,6 +43,7 @@ static bool just_opened_options = false;
|
|||||||
|
|
||||||
static Widget::MemoryMapViewer memory_map;
|
static Widget::MemoryMapViewer memory_map;
|
||||||
static Widget::ShaderList shader_list;
|
static Widget::ShaderList shader_list;
|
||||||
|
static Widget::ModuleList module_list;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static std::string help_text =
|
static std::string help_text =
|
||||||
@@ -100,6 +104,16 @@ void L::DrawMenuBar() {
|
|||||||
EndDisabled();
|
EndDisabled();
|
||||||
}
|
}
|
||||||
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();
|
||||||
}
|
}
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
@@ -108,6 +122,9 @@ void L::DrawMenuBar() {
|
|||||||
if (MenuItem("Memory map")) {
|
if (MenuItem("Memory map")) {
|
||||||
memory_map.open = true;
|
memory_map.open = true;
|
||||||
}
|
}
|
||||||
|
if (MenuItem("Module list")) {
|
||||||
|
module_list.open = true;
|
||||||
|
}
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,15 +150,8 @@ void L::DrawAdvanced() {
|
|||||||
const auto& ctx = *GImGui;
|
const auto& ctx = *GImGui;
|
||||||
const auto& io = ctx.IO;
|
const auto& io = ctx.IO;
|
||||||
|
|
||||||
auto isSystemPaused = DebugState.IsGuestThreadsPaused();
|
|
||||||
|
|
||||||
frame_graph.Draw();
|
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()) {
|
if (DebugState.should_show_frame_dump && DebugState.waiting_reg_dumps.empty()) {
|
||||||
DebugState.should_show_frame_dump = false;
|
DebugState.should_show_frame_dump = false;
|
||||||
std::unique_lock lock{DebugState.frame_dump_list_mutex};
|
std::unique_lock lock{DebugState.frame_dump_list_mutex};
|
||||||
@@ -256,6 +266,9 @@ void L::DrawAdvanced() {
|
|||||||
if (shader_list.open) {
|
if (shader_list.open) {
|
||||||
shader_list.Draw();
|
shader_list.Draw();
|
||||||
}
|
}
|
||||||
|
if (module_list.open) {
|
||||||
|
module_list.Draw();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void L::DrawSimple() {
|
void L::DrawSimple() {
|
||||||
@@ -298,6 +311,7 @@ static void LoadSettings(const char* line) {
|
|||||||
|
|
||||||
void L::SetupSettings() {
|
void L::SetupSettings() {
|
||||||
frame_graph.is_open = true;
|
frame_graph.is_open = true;
|
||||||
|
show_simple_fps = Config::getShowFpsCounter();
|
||||||
|
|
||||||
using SettingLoader = void (*)(const char*);
|
using SettingLoader = void (*)(const char*);
|
||||||
|
|
||||||
@@ -360,8 +374,6 @@ void L::Draw() {
|
|||||||
if (IsKeyPressed(ImGuiKey_F10, false)) {
|
if (IsKeyPressed(ImGuiKey_F10, false)) {
|
||||||
if (io.KeyCtrl) {
|
if (io.KeyCtrl) {
|
||||||
DebugState.IsShowingDebugMenuBar() ^= true;
|
DebugState.IsShowingDebugMenuBar() ^= true;
|
||||||
} else {
|
|
||||||
show_simple_fps = !show_simple_fps;
|
|
||||||
}
|
}
|
||||||
visibility_toggled = true;
|
visibility_toggled = true;
|
||||||
}
|
}
|
||||||
@@ -371,25 +383,13 @@ void L::Draw() {
|
|||||||
if (!DebugState.ShouldPauseInSubmit()) {
|
if (!DebugState.ShouldPauseInSubmit()) {
|
||||||
DebugState.RequestFrameDump(dump_frame_count);
|
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);
|
ImVec2 pos = ImVec2(10, 10);
|
||||||
ImU32 color = IM_COL32(255, 255, 255, 255);
|
ImU32 color = IM_COL32(255, 255, 255, 255);
|
||||||
|
ImGui::GetForegroundDrawList()->AddText(pos, color, "Emulation Paused");
|
||||||
ImGui::GetForegroundDrawList()->AddText(pos, color, "Game Paused Press F9 to Resume");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (show_simple_fps) {
|
if (show_simple_fps) {
|
||||||
@@ -428,5 +428,61 @@ void L::Draw() {
|
|||||||
PopFont();
|
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();
|
PopID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void L::TextCentered(const std::string& text) {
|
||||||
|
float window_width = GetWindowSize().x;
|
||||||
|
float text_width = CalcTextSize(text.c_str()).x;
|
||||||
|
float text_indentation = (window_width - text_width) * 0.5f;
|
||||||
|
|
||||||
|
SameLine(text_indentation);
|
||||||
|
Text("%s", text.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Overlay {
|
||||||
|
|
||||||
|
void ToggleSimpleFps() {
|
||||||
|
show_simple_fps = !show_simple_fps;
|
||||||
|
visibility_toggled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSimpleFps(bool enabled) {
|
||||||
|
show_simple_fps = enabled;
|
||||||
|
visibility_toggled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ToggleQuitWindow() {
|
||||||
|
show_quit_window = !show_quit_window;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Overlay
|
||||||
|
|||||||
@@ -1,25 +1,36 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "imgui/imgui_layer.h"
|
#include "imgui/imgui_layer.h"
|
||||||
|
|
||||||
namespace Core::Devtools {
|
namespace Core::Devtools {
|
||||||
|
|
||||||
class Layer final : public ImGui::Layer {
|
class Layer final : public ImGui::Layer {
|
||||||
|
|
||||||
static void DrawMenuBar();
|
|
||||||
|
|
||||||
static void DrawAdvanced();
|
|
||||||
|
|
||||||
static void DrawSimple();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void SetupSettings();
|
static void SetupSettings();
|
||||||
|
|
||||||
void Draw() override;
|
void Draw() override;
|
||||||
bool show_pause_status = false;
|
|
||||||
|
// Must be inside a window
|
||||||
|
static void DrawNullGpuNotice();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void DrawMenuBar();
|
||||||
|
static void DrawAdvanced();
|
||||||
|
static void DrawSimple();
|
||||||
|
|
||||||
|
static void TextCentered(const std::string& text);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Core::Devtools
|
} // namespace Core::Devtools
|
||||||
|
|
||||||
|
namespace Overlay {
|
||||||
|
|
||||||
|
void ToggleSimpleFps();
|
||||||
|
void SetSimpleFps(bool enabled);
|
||||||
|
void ToggleQuitWindow();
|
||||||
|
|
||||||
|
} // namespace Overlay
|
||||||
|
|||||||
95
src/core/devtools/layer_extra.cpp
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "layer.h"
|
||||||
|
|
||||||
|
#include "imgui/imgui_std.h"
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
#include <imgui_internal.h>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <numbers>
|
||||||
|
|
||||||
|
namespace Core::Devtools {
|
||||||
|
|
||||||
|
void Layer::DrawNullGpuNotice() {
|
||||||
|
|
||||||
|
auto* window = ImGui::GetCurrentWindow();
|
||||||
|
if (window->SkipItems) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr std::string_view mainNotice = "Null GPU is enabled";
|
||||||
|
constexpr std::string_view detailsNotice =
|
||||||
|
"Disable the nullGpu config to show the game display";
|
||||||
|
|
||||||
|
auto displaySize = window->Size;
|
||||||
|
|
||||||
|
ImVec2 targetSize = displaySize * 0.7f;
|
||||||
|
|
||||||
|
float minFontSize = 1.0f;
|
||||||
|
float maxFontSize = 200.0f;
|
||||||
|
float optimalFontSize = minFontSize;
|
||||||
|
|
||||||
|
static auto lastSize = ImVec2(-1, -1);
|
||||||
|
static float lastFontSize = -1.0f;
|
||||||
|
|
||||||
|
auto* font = ImGui::GetIO().Fonts->Fonts[IMGUI_FONT_TEXT_BIG];
|
||||||
|
|
||||||
|
if (lastSize != targetSize) {
|
||||||
|
while (maxFontSize - minFontSize > 0.1f) {
|
||||||
|
float testFontSize = (minFontSize + maxFontSize) / 2.0f;
|
||||||
|
|
||||||
|
ImVec2 textSize = font->CalcTextSizeA(testFontSize, FLT_MAX, 0.0f, &mainNotice.front(),
|
||||||
|
&mainNotice.back() + 1);
|
||||||
|
|
||||||
|
if (textSize.x <= targetSize.x && textSize.y <= targetSize.y) {
|
||||||
|
optimalFontSize = testFontSize;
|
||||||
|
minFontSize = testFontSize;
|
||||||
|
} else {
|
||||||
|
maxFontSize = testFontSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastSize = targetSize;
|
||||||
|
lastFontSize = optimalFontSize;
|
||||||
|
} else {
|
||||||
|
optimalFontSize = lastFontSize;
|
||||||
|
}
|
||||||
|
ImVec2 textSize = font->CalcTextSizeA(optimalFontSize, FLT_MAX, 0.0f, &mainNotice.front(),
|
||||||
|
&mainNotice.back() + 1);
|
||||||
|
|
||||||
|
ImVec2 textPos = (displaySize - textSize) * 0.5f + window->Pos;
|
||||||
|
|
||||||
|
const float scale = optimalFontSize / font->FontSize;
|
||||||
|
double timeAnim = -std::numbers::pi * ImGui::GetTime();
|
||||||
|
int i = 0;
|
||||||
|
for (auto ch : mainNotice) {
|
||||||
|
double colorTime = sin(timeAnim + i * std::numbers::pi / 6.0) / 2.0 + 0.5;
|
||||||
|
int color = (int)(200 * colorTime) + 55;
|
||||||
|
|
||||||
|
double posTime = sin(timeAnim + i * std::numbers::pi / 15.0) / 2.0 + 0.5;
|
||||||
|
|
||||||
|
auto pos = textPos;
|
||||||
|
pos.y += 10.0 * (posTime < 0.5 ? std::pow(2.0, 20.0 * posTime - 10.0) / 2.0
|
||||||
|
: (2.0 - std::pow(2.0, -20.0 * posTime + 10.0)) / 2.0);
|
||||||
|
|
||||||
|
window->DrawList->AddText(font, optimalFontSize, pos, IM_COL32(color, color, color, 255),
|
||||||
|
&ch, &ch + 1);
|
||||||
|
textPos.x += font->FindGlyph(ch)->AdvanceX * scale;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
font = ImGui::GetIO().Fonts->Fonts[IMGUI_FONT_TEXT];
|
||||||
|
|
||||||
|
textPos.y += textSize.y + 1.0;
|
||||||
|
|
||||||
|
optimalFontSize *= 0.2;
|
||||||
|
textSize = font->CalcTextSizeA(optimalFontSize, FLT_MAX, 0.0f, &detailsNotice.front(),
|
||||||
|
&detailsNotice.back() + 1);
|
||||||
|
textPos.x = window->Pos.x + (window->Size.x - textSize.x) * 0.5f;
|
||||||
|
window->DrawList->AddText(font, optimalFontSize, textPos, IM_COL32(200, 200, 200, 255),
|
||||||
|
&detailsNotice.front(), &detailsNotice.back() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Core::Devtools
|
||||||
@@ -30,26 +30,12 @@ void LoadOptionsConfig(const char* line) {
|
|||||||
Options.frame_dump_render_on_collapse = i != 0;
|
Options.frame_dump_render_on_collapse = i != 0;
|
||||||
return;
|
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) {
|
void SerializeOptionsConfig(ImGuiTextBuffer* buf) {
|
||||||
buf->appendf("disassembler_cli_isa=%s\n", Options.disassembler_cli_isa.c_str());
|
buf->appendf("disassembler_cli_isa=%s\n", Options.disassembler_cli_isa.c_str());
|
||||||
buf->appendf("disassembler_cli_spv=%s\n", Options.disassembler_cli_spv.c_str());
|
buf->appendf("disassembler_cli_spv=%s\n", Options.disassembler_cli_spv.c_str());
|
||||||
buf->appendf("frame_dump_render_on_collapse=%d\n", Options.frame_dump_render_on_collapse);
|
buf->appendf("frame_dump_render_on_collapse=%d\n", Options.frame_dump_render_on_collapse);
|
||||||
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
|
} // namespace Core::Devtools
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ static HdrType GetNext(HdrType this_pm4, uint32_t n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ParsePolygonControl(u32 value, bool begin_table) {
|
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 ||
|
if (!begin_table ||
|
||||||
BeginTable("PA_SU_SC_MODE_CNTL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
BeginTable("PA_SU_SC_MODE_CNTL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||||
@@ -73,80 +73,80 @@ void ParsePolygonControl(u32 value, bool begin_table) {
|
|||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("CULL_FRONT");
|
Text("CULL_FRONT");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.cull_front.Value());
|
Text("%X", reg.cull_front);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("CULL_BACK");
|
Text("CULL_BACK");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.cull_back.Value());
|
Text("%X", reg.cull_back);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("FACE");
|
Text("FACE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%s", enum_name(reg.front_face.Value()).data());
|
Text("%s", enum_name(reg.front_face).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("POLY_MODE");
|
Text("POLY_MODE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.enable_polygon_mode.Value());
|
Text("%X", reg.enable_polygon_mode);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("POLYMODE_FRONT_PTYPE");
|
Text("POLYMODE_FRONT_PTYPE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%s", enum_name(reg.polygon_mode_front.Value()).data());
|
Text("%s", enum_name(reg.polygon_mode_front).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("POLYMODE_BACK_PTYPE");
|
Text("POLYMODE_BACK_PTYPE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%s", enum_name(reg.polygon_mode_back.Value()).data());
|
Text("%s", enum_name(reg.polygon_mode_back).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("POLY_OFFSET_FRONT_ENABLE");
|
Text("POLY_OFFSET_FRONT_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.enable_polygon_offset_front.Value());
|
Text("%X", reg.enable_polygon_offset_front);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("POLY_OFFSET_BACK_ENABLE");
|
Text("POLY_OFFSET_BACK_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.enable_polygon_offset_back.Value());
|
Text("%X", reg.enable_polygon_offset_back);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("POLY_OFFSET_PARA_ENABLE");
|
Text("POLY_OFFSET_PARA_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.enable_polygon_offset_para.Value());
|
Text("%X", reg.enable_polygon_offset_para);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("VTX_WINDOW_OFFSET_ENABLE");
|
Text("VTX_WINDOW_OFFSET_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.enable_window_offset.Value());
|
Text("%X", reg.enable_window_offset);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("PROVOKING_VTX_LAST");
|
Text("PROVOKING_VTX_LAST");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X (%s)", (u32)reg.provoking_vtx_last.Value(),
|
Text("%X (%s)", static_cast<u32>(reg.provoking_vtx_last),
|
||||||
enum_name(reg.provoking_vtx_last.Value()).data());
|
enum_name(reg.provoking_vtx_last).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("PERSP_CORR_DIS");
|
Text("PERSP_CORR_DIS");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.persp_corr_dis.Value());
|
Text("%X", reg.persp_corr_dis);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("MULTI_PRIM_IB_ENA");
|
Text("MULTI_PRIM_IB_ENA");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.multi_prim_ib_ena.Value());
|
Text("%X", reg.multi_prim_ib_ena);
|
||||||
|
|
||||||
if (begin_table) {
|
if (begin_table) {
|
||||||
EndTable();
|
EndTable();
|
||||||
@@ -155,7 +155,7 @@ void ParsePolygonControl(u32 value, bool begin_table) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ParseAaConfig(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 ||
|
if (!begin_table ||
|
||||||
BeginTable("PA_SC_AA_CONFIG", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
BeginTable("PA_SC_AA_CONFIG", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||||
@@ -163,31 +163,31 @@ void ParseAaConfig(u32 value, bool begin_table) {
|
|||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("MSAA_NUM_SAMPLES");
|
Text("MSAA_NUM_SAMPLES");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.msaa_num_samples.Value());
|
Text("%X", reg.msaa_num_samples);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("AA_MASK_CENTROID_DTMN");
|
Text("AA_MASK_CENTROID_DTMN");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.aa_mask_centroid_dtmn.Value());
|
Text("%X", reg.aa_mask_centroid_dtmn);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("MAX_SAMPLE_DIST");
|
Text("MAX_SAMPLE_DIST");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.max_sample_dst.Value());
|
Text("%X", reg.max_sample_dst);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("MSAA_EXPOSED_SAMPLES");
|
Text("MSAA_EXPOSED_SAMPLES");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.msaa_exposed_samples.Value());
|
Text("%X", reg.msaa_exposed_samples);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DETAIL_TO_EXPOSED_MODE");
|
Text("DETAIL_TO_EXPOSED_MODE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.detail_to_exposed_mode.Value());
|
Text("%X", reg.detail_to_exposed_mode);
|
||||||
|
|
||||||
if (begin_table) {
|
if (begin_table) {
|
||||||
EndTable();
|
EndTable();
|
||||||
@@ -196,7 +196,7 @@ void ParseAaConfig(u32 value, bool begin_table) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ParseViewportControl(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 ||
|
if (!begin_table ||
|
||||||
BeginTable("PA_CL_VTE_CNTL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
BeginTable("PA_CL_VTE_CNTL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||||
@@ -204,61 +204,61 @@ void ParseViewportControl(u32 value, bool begin_table) {
|
|||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("VPORT_X_SCALE_ENA");
|
Text("VPORT_X_SCALE_ENA");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.xscale_enable.Value());
|
Text("%X", reg.xscale_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("VPORT_X_OFFSET_ENA");
|
Text("VPORT_X_OFFSET_ENA");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.yoffset_enable.Value());
|
Text("%X", reg.yoffset_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("VPORT_Y_SCALE_ENA");
|
Text("VPORT_Y_SCALE_ENA");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.yscale_enable.Value());
|
Text("%X", reg.yscale_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("VPORT_Y_OFFSET_ENA");
|
Text("VPORT_Y_OFFSET_ENA");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.yoffset_enable.Value());
|
Text("%X", reg.yoffset_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("VPORT_Z_SCALE_ENA");
|
Text("VPORT_Z_SCALE_ENA");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.zscale_enable.Value());
|
Text("%X", reg.zscale_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("VPORT_Z_OFFSET_ENA");
|
Text("VPORT_Z_OFFSET_ENA");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.zoffset_enable.Value());
|
Text("%X", reg.zoffset_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("VTX_XY_FMT");
|
Text("VTX_XY_FMT");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.xy_transformed.Value());
|
Text("%X", reg.xy_transformed);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("VTX_Z_FMT");
|
Text("VTX_Z_FMT");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.z_transformed.Value());
|
Text("%X", reg.z_transformed);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("VTX_W0_FMT");
|
Text("VTX_W0_FMT");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.w_transformed.Value());
|
Text("%X", reg.w_transformed);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("PERFCOUNTER_REF");
|
Text("PERFCOUNTER_REF");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.perfcounter_ref.Value());
|
Text("%X", reg.perfcounter_ref);
|
||||||
|
|
||||||
if (begin_table) {
|
if (begin_table) {
|
||||||
EndTable();
|
EndTable();
|
||||||
@@ -267,7 +267,7 @@ void ParseViewportControl(u32 value, bool begin_table) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ParseColorControl(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 ||
|
if (!begin_table ||
|
||||||
BeginTable("CB_COLOR_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
BeginTable("CB_COLOR_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||||
@@ -275,25 +275,25 @@ void ParseColorControl(u32 value, bool begin_table) {
|
|||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DISABLE_DUAL_QUAD__VI");
|
Text("DISABLE_DUAL_QUAD__VI");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.disable_dual_quad.Value());
|
Text("%X", reg.disable_dual_quad);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DEGAMMA_ENABLE");
|
Text("DEGAMMA_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.degamma_enable.Value());
|
Text("%X", reg.degamma_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("MODE");
|
Text("MODE");
|
||||||
TableSetColumnIndex(1);
|
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();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ROP3");
|
Text("ROP3");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.rop3.Value());
|
Text("%X", static_cast<u32>(reg.rop3));
|
||||||
|
|
||||||
if (begin_table) {
|
if (begin_table) {
|
||||||
EndTable();
|
EndTable();
|
||||||
@@ -302,7 +302,7 @@ void ParseColorControl(u32 value, bool begin_table) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ParseColor0Info(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 ||
|
if (!begin_table ||
|
||||||
BeginTable("CB_COLOR_INFO", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
BeginTable("CB_COLOR_INFO", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||||
@@ -310,109 +310,109 @@ void ParseColor0Info(u32 value, bool begin_table) {
|
|||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ENDIAN");
|
Text("ENDIAN");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%s", enum_name(reg.endian.Value()).data());
|
Text("%s", enum_name(reg.endian).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("FORMAT");
|
Text("FORMAT");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%s", enum_name(reg.format.Value()).data());
|
Text("%s", enum_name(AmdGpu::DataFormat(reg.format)).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("LINEAR_GENERAL");
|
Text("LINEAR_GENERAL");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.linear_general.Value());
|
Text("%X", reg.linear_general);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("NUMBER_TYPE");
|
Text("NUMBER_TYPE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%s", enum_name(reg.number_type.Value()).data());
|
Text("%s", enum_name(AmdGpu::NumberFormat(reg.number_type)).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("COMP_SWAP");
|
Text("COMP_SWAP");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%s", enum_name(reg.comp_swap.Value()).data());
|
Text("%s", enum_name(reg.comp_swap).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("FAST_CLEAR");
|
Text("FAST_CLEAR");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.fast_clear.Value());
|
Text("%X", reg.fast_clear);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("COMPRESSION");
|
Text("COMPRESSION");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.compression.Value());
|
Text("%X", reg.compression);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("BLEND_CLAMP");
|
Text("BLEND_CLAMP");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.blend_clamp.Value());
|
Text("%X", reg.blend_clamp);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("BLEND_BYPASS");
|
Text("BLEND_BYPASS");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.blend_bypass.Value());
|
Text("%X", reg.blend_bypass);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("SIMPLE_FLOAT");
|
Text("SIMPLE_FLOAT");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.simple_float.Value());
|
Text("%X", reg.simple_float);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ROUND_MODE");
|
Text("ROUND_MODE");
|
||||||
TableSetColumnIndex(1);
|
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();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("CMASK_IS_LINEAR");
|
Text("CMASK_IS_LINEAR");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.cmask_is_linear.Value());
|
Text("%X", reg.cmask_is_linear);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("BLEND_OPT_DONT_RD_DST");
|
Text("BLEND_OPT_DONT_RD_DST");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.blend_opt_dont_rd_dst.Value());
|
Text("%X", reg.blend_opt_dont_rd_dst);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("BLEND_OPT_DISCARD_PIXEL");
|
Text("BLEND_OPT_DISCARD_PIXEL");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.blend_opt_discard_pixel.Value());
|
Text("%X", reg.blend_opt_discard_pixel);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("FMASK_COMPRESSION_DISABLE__CI__VI");
|
Text("FMASK_COMPRESSION_DISABLE__CI__VI");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.fmask_compression_disable_ci.Value());
|
Text("%X", reg.fmask_compression_disable_ci);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("FMASK_COMPRESS_1FRAG_ONLY__VI");
|
Text("FMASK_COMPRESS_1FRAG_ONLY__VI");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.fmask_compress_1frag_only.Value());
|
Text("%X", reg.fmask_compress_1frag_only);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DCC_ENABLE__VI");
|
Text("DCC_ENABLE__VI");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.dcc_enable.Value());
|
Text("%X", reg.dcc_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("CMASK_ADDR_TYPE__VI");
|
Text("CMASK_ADDR_TYPE__VI");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.cmask_addr_type.Value());
|
Text("%X", reg.cmask_addr_type);
|
||||||
|
|
||||||
if (begin_table) {
|
if (begin_table) {
|
||||||
EndTable();
|
EndTable();
|
||||||
@@ -421,7 +421,7 @@ void ParseColor0Info(u32 value, bool begin_table) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ParseColor0Attrib(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 ||
|
if (!begin_table ||
|
||||||
BeginTable("CB_COLOR_ATTRIB", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
BeginTable("CB_COLOR_ATTRIB", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||||
@@ -429,37 +429,37 @@ void ParseColor0Attrib(u32 value, bool begin_table) {
|
|||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("TILE_MODE_INDEX");
|
Text("TILE_MODE_INDEX");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%s", enum_name(reg.tile_mode_index.Value()).data());
|
Text("%s", enum_name(reg.tile_mode_index).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("FMASK_TILE_MODE_INDEX");
|
Text("FMASK_TILE_MODE_INDEX");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.fmask_tile_mode_index.Value());
|
Text("%X", reg.fmask_tile_mode_index);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("FMASK_BANK_HEIGHT");
|
Text("FMASK_BANK_HEIGHT");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.fmask_bank_height.Value());
|
Text("%X", reg.fmask_bank_height);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("NUM_SAMPLES");
|
Text("NUM_SAMPLES");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.num_samples_log2.Value());
|
Text("%X", reg.num_samples_log2);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("NUM_FRAGMENTS");
|
Text("NUM_FRAGMENTS");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.num_fragments_log2.Value());
|
Text("%X", reg.num_fragments_log2);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("FORCE_DST_ALPHA_1");
|
Text("FORCE_DST_ALPHA_1");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.force_dst_alpha_1.Value());
|
Text("%X", reg.force_dst_alpha_1);
|
||||||
|
|
||||||
if (begin_table) {
|
if (begin_table) {
|
||||||
EndTable();
|
EndTable();
|
||||||
@@ -468,7 +468,7 @@ void ParseColor0Attrib(u32 value, bool begin_table) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ParseBlendControl(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 ||
|
if (!begin_table ||
|
||||||
BeginTable("CB_BLEND_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
BeginTable("CB_BLEND_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||||
@@ -476,59 +476,59 @@ void ParseBlendControl(u32 value, bool begin_table) {
|
|||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("COLOR_SRCBLEND");
|
Text("COLOR_SRCBLEND");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X (%s)", (u32)reg.color_src_factor.Value(),
|
Text("%X (%s)", static_cast<u32>(reg.color_src_factor),
|
||||||
enum_name(reg.color_src_factor.Value()).data());
|
enum_name(reg.color_src_factor).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("COLOR_COMB_FCN");
|
Text("COLOR_COMB_FCN");
|
||||||
TableSetColumnIndex(1);
|
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();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("COLOR_DESTBLEND");
|
Text("COLOR_DESTBLEND");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X (%s)", (u32)reg.color_dst_factor.Value(),
|
Text("%X (%s)", static_cast<u32>(reg.color_dst_factor),
|
||||||
enum_name(reg.color_dst_factor.Value()).data());
|
enum_name(reg.color_dst_factor).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ALPHA_SRCBLEND");
|
Text("ALPHA_SRCBLEND");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X (%s)", (u32)reg.alpha_src_factor.Value(),
|
Text("%X (%s)", static_cast<u32>(reg.alpha_src_factor),
|
||||||
enum_name(reg.alpha_src_factor.Value()).data());
|
enum_name(reg.alpha_src_factor).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ALPHA_COMB_FCN");
|
Text("ALPHA_COMB_FCN");
|
||||||
TableSetColumnIndex(1);
|
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();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ALPHA_DESTBLEND");
|
Text("ALPHA_DESTBLEND");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X (%s)", (u32)reg.alpha_dst_factor.Value(),
|
Text("%X (%s)", static_cast<u32>(reg.alpha_dst_factor),
|
||||||
enum_name(reg.alpha_dst_factor.Value()).data());
|
enum_name(reg.alpha_dst_factor).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("SEPARATE_ALPHA_BLEND");
|
Text("SEPARATE_ALPHA_BLEND");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.separate_alpha_blend.Value());
|
Text("%X", reg.separate_alpha_blend);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ENABLE");
|
Text("ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.enable.Value());
|
Text("%X", reg.enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DISABLE_ROP3");
|
Text("DISABLE_ROP3");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.disable_rop3.Value());
|
Text("%X", reg.disable_rop3);
|
||||||
|
|
||||||
if (begin_table) {
|
if (begin_table) {
|
||||||
EndTable();
|
EndTable();
|
||||||
@@ -537,7 +537,7 @@ void ParseBlendControl(u32 value, bool begin_table) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ParseDepthRenderControl(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 ||
|
if (!begin_table ||
|
||||||
BeginTable("DB_RENDER_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
BeginTable("DB_RENDER_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||||
@@ -545,61 +545,61 @@ void ParseDepthRenderControl(u32 value, bool begin_table) {
|
|||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DEPTH_CLEAR_ENABLE");
|
Text("DEPTH_CLEAR_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.depth_clear_enable.Value());
|
Text("%X", reg.depth_clear_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("STENCIL_CLEAR_ENABLE");
|
Text("STENCIL_CLEAR_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.stencil_clear_enable.Value());
|
Text("%X", reg.stencil_clear_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DEPTH_COPY");
|
Text("DEPTH_COPY");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.depth_clear_enable.Value());
|
Text("%X", reg.depth_clear_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("STENCIL_COPY");
|
Text("STENCIL_COPY");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.stencil_copy.Value());
|
Text("%X", reg.stencil_copy);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("RESUMMARIZE_ENABLE");
|
Text("RESUMMARIZE_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.resummarize_enable.Value());
|
Text("%X", reg.resummarize_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("STENCIL_COMPRESS_DISABLE");
|
Text("STENCIL_COMPRESS_DISABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.stencil_compress_disable.Value());
|
Text("%X", reg.stencil_compress_disable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DEPTH_COMPRESS_DISABLE");
|
Text("DEPTH_COMPRESS_DISABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.depth_compress_disable.Value());
|
Text("%X", reg.depth_compress_disable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("COPY_CENTROID");
|
Text("COPY_CENTROID");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.copy_centroid.Value());
|
Text("%X", reg.copy_centroid);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("COPY_SAMPLE");
|
Text("COPY_SAMPLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.copy_sample.Value());
|
Text("%X", reg.copy_sample);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DECOMPRESS_ENABLE__VI");
|
Text("DECOMPRESS_ENABLE__VI");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.decompress_enable.Value());
|
Text("%X", reg.decompress_enable);
|
||||||
|
|
||||||
if (begin_table) {
|
if (begin_table) {
|
||||||
EndTable();
|
EndTable();
|
||||||
@@ -608,7 +608,7 @@ void ParseDepthRenderControl(u32 value, bool begin_table) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ParseDepthControl(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 ||
|
if (!begin_table ||
|
||||||
BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||||
@@ -616,63 +616,63 @@ void ParseDepthControl(u32 value, bool begin_table) {
|
|||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("STENCIL_ENABLE");
|
Text("STENCIL_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.stencil_enable.Value());
|
Text("%X", reg.stencil_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("Z_ENABLE");
|
Text("Z_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.depth_enable.Value());
|
Text("%X", reg.depth_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("Z_WRITE_ENABLE");
|
Text("Z_WRITE_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.depth_write_enable.Value());
|
Text("%X", reg.depth_write_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DEPTH_BOUNDS_ENABLE");
|
Text("DEPTH_BOUNDS_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.depth_bounds_enable.Value());
|
Text("%X", reg.depth_bounds_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ZFUNC");
|
Text("ZFUNC");
|
||||||
TableSetColumnIndex(1);
|
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();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("BACKFACE_ENABLE");
|
Text("BACKFACE_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.backface_enable.Value());
|
Text("%X", reg.backface_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("STENCILFUNC");
|
Text("STENCILFUNC");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X (%s)", (u32)reg.stencil_ref_func.Value(),
|
Text("%X (%s)", static_cast<u32>(reg.stencil_ref_func),
|
||||||
enum_name(reg.stencil_ref_func.Value()).data());
|
enum_name(reg.stencil_ref_func).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("STENCILFUNC_BF");
|
Text("STENCILFUNC_BF");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X (%s)", (u32)reg.stencil_bf_func.Value(),
|
Text("%X (%s)", static_cast<u32>(reg.stencil_bf_func),
|
||||||
enum_name(reg.stencil_bf_func.Value()).data());
|
enum_name(reg.stencil_bf_func).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ENABLE_COLOR_WRITES_ON_DEPTH_FAIL");
|
Text("ENABLE_COLOR_WRITES_ON_DEPTH_FAIL");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.enable_color_writes_on_depth_fail.Value());
|
Text("%X", reg.enable_color_writes_on_depth_fail);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DISABLE_COLOR_WRITES_ON_DEPTH_PASS");
|
Text("DISABLE_COLOR_WRITES_ON_DEPTH_PASS");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.disable_color_writes_on_depth_pass.Value());
|
Text("%X", reg.disable_color_writes_on_depth_pass);
|
||||||
|
|
||||||
if (begin_table) {
|
if (begin_table) {
|
||||||
EndTable();
|
EndTable();
|
||||||
@@ -681,7 +681,7 @@ void ParseDepthControl(u32 value, bool begin_table) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ParseEqaa(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 ||
|
if (!begin_table ||
|
||||||
BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||||
@@ -689,73 +689,73 @@ void ParseEqaa(u32 value, bool begin_table) {
|
|||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("MAX_ANCHOR_SAMPLES");
|
Text("MAX_ANCHOR_SAMPLES");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.max_anchor_samples.Value());
|
Text("%X", reg.max_anchor_samples);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("PS_ITER_SAMPLES");
|
Text("PS_ITER_SAMPLES");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.ps_iter_samples.Value());
|
Text("%X", reg.ps_iter_samples);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("MASK_EXPORT_NUM_SAMPLES");
|
Text("MASK_EXPORT_NUM_SAMPLES");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.mask_export_num_samples.Value());
|
Text("%X", reg.mask_export_num_samples);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ALPHA_TO_MASK_NUM_SAMPLES");
|
Text("ALPHA_TO_MASK_NUM_SAMPLES");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.alpha_to_mask_num_samples.Value());
|
Text("%X", reg.alpha_to_mask_num_samples);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("HIGH_QUALITY_INTERSECTIONS");
|
Text("HIGH_QUALITY_INTERSECTIONS");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.high_quality_intersections.Value());
|
Text("%X", reg.high_quality_intersections);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("INCOHERENT_EQAA_READS");
|
Text("INCOHERENT_EQAA_READS");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.incoherent_eqaa_reads.Value());
|
Text("%X", reg.incoherent_eqaa_reads);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("INTERPOLATE_COMP_Z");
|
Text("INTERPOLATE_COMP_Z");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.interpolate_comp_z.Value());
|
Text("%X", reg.interpolate_comp_z);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("INTERPOLATE_SRC_Z");
|
Text("INTERPOLATE_SRC_Z");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.interpolate_src_z.Value());
|
Text("%X", reg.interpolate_src_z);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("STATIC_ANCHOR_ASSOCIATIONS");
|
Text("STATIC_ANCHOR_ASSOCIATIONS");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.static_anchor_associations.Value());
|
Text("%X", reg.static_anchor_associations);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ALPHA_TO_MASK_EQAA_DISABLE");
|
Text("ALPHA_TO_MASK_EQAA_DISABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.alpha_to_mask_eqaa_disable.Value());
|
Text("%X", reg.alpha_to_mask_eqaa_disable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("OVERRASTERIZATION_AMOUNT");
|
Text("OVERRASTERIZATION_AMOUNT");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.overrasterization_amount.Value());
|
Text("%X", reg.overrasterization_amount);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ENABLE_POSTZ_OVERRASTERIZATION");
|
Text("ENABLE_POSTZ_OVERRASTERIZATION");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.enable_postz_overrasterization.Value());
|
Text("%X", reg.enable_postz_overrasterization);
|
||||||
|
|
||||||
if (begin_table) {
|
if (begin_table) {
|
||||||
EndTable();
|
EndTable();
|
||||||
@@ -764,7 +764,7 @@ void ParseEqaa(u32 value, bool begin_table) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ParseZInfo(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 ||
|
if (!begin_table ||
|
||||||
BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||||
@@ -772,61 +772,61 @@ void ParseZInfo(u32 value, bool begin_table) {
|
|||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("FORMAT");
|
Text("FORMAT");
|
||||||
TableSetColumnIndex(1);
|
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();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("NUM_SAMPLES");
|
Text("NUM_SAMPLES");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.num_samples.Value());
|
Text("%X", reg.num_samples);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("TILE_SPLIT__CI__VI");
|
Text("TILE_SPLIT__CI__VI");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.tile_split.Value());
|
Text("%X", reg.tile_split);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("TILE_MODE_INDEX");
|
Text("TILE_MODE_INDEX");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.tile_mode_index.Value());
|
Text("%X", static_cast<u32>(reg.tile_mode_index));
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DECOMPRESS_ON_N_ZPLANES__VI");
|
Text("DECOMPRESS_ON_N_ZPLANES__VI");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.decompress_on_n_zplanes.Value());
|
Text("%X", reg.decompress_on_n_zplanes);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ALLOW_EXPCLEAR");
|
Text("ALLOW_EXPCLEAR");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.allow_expclear.Value());
|
Text("%X", reg.allow_expclear);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("READ_SIZE");
|
Text("READ_SIZE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.read_size.Value());
|
Text("%X", reg.read_size);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("TILE_SURFACE_ENABLE");
|
Text("TILE_SURFACE_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.tile_surface_en.Value());
|
Text("%X", reg.tile_surface_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("CLEAR_DISALLOWED__VI");
|
Text("CLEAR_DISALLOWED__VI");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.clear_disallowed.Value());
|
Text("%X", reg.clear_disallowed);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ZRANGE_PRECISION");
|
Text("ZRANGE_PRECISION");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.zrange_precision.Value());
|
Text("%X", reg.zrange_precision);
|
||||||
|
|
||||||
if (begin_table) {
|
if (begin_table) {
|
||||||
EndTable();
|
EndTable();
|
||||||
|
|||||||
@@ -5,14 +5,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
#include "imgui_memory_editor.h"
|
#include "core/devtools/widget/imgui_memory_editor.h"
|
||||||
#include "reg_view.h"
|
#include "core/devtools/widget/reg_view.h"
|
||||||
|
|
||||||
namespace AmdGpu {
|
namespace AmdGpu {
|
||||||
union PM4Type3Header;
|
union PM4Type3Header;
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ inline std::string RunDisassembler(const std::string& disassembler_cli, const T&
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cli.replace(pos, src_arg.size(), "\"" + bin_path.string() + "\"");
|
cli.replace(pos, src_arg.size(), "\"" + bin_path.string() + "\"");
|
||||||
Common::FS::IOFile file(bin_path, Common::FS::FileAccessMode::Write);
|
Common::FS::IOFile file(bin_path, Common::FS::FileAccessMode::Create);
|
||||||
file.Write(shader_code);
|
file.Write(shader_code);
|
||||||
file.Close();
|
file.Close();
|
||||||
|
|
||||||
|
|||||||
@@ -118,11 +118,12 @@ void FrameDumpViewer::Draw() {
|
|||||||
SameLine();
|
SameLine();
|
||||||
BeginDisabled(selected_cmd == -1);
|
BeginDisabled(selected_cmd == -1);
|
||||||
if (SmallButton("Dump cmd")) {
|
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,
|
const auto fname = fmt::format("{:%F %H-%M-%S} {}_{}_{}.bin", now_time,
|
||||||
magic_enum::enum_name(selected_queue_type),
|
magic_enum::enum_name(selected_queue_type),
|
||||||
selected_submit_num, selected_queue_num2);
|
selected_submit_num, selected_queue_num2);
|
||||||
Common::FS::IOFile file(fname, Common::FS::FileAccessMode::Write);
|
Common::FS::IOFile file(fname, Common::FS::FileAccessMode::Create);
|
||||||
const auto& data = frame_dump->queues[selected_cmd].data;
|
const auto& data = frame_dump->queues[selected_cmd].data;
|
||||||
if (file.IsOpen()) {
|
if (file.IsOpen()) {
|
||||||
DebugState.ShowDebugMessage(fmt::format("Dumping cmd as {}", fname));
|
DebugState.ShowDebugMessage(fmt::format("Dumping cmd as {}", fname));
|
||||||
|
|||||||
@@ -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
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "frame_graph.h"
|
#include "frame_graph.h"
|
||||||
@@ -13,7 +13,6 @@ using namespace ImGui;
|
|||||||
|
|
||||||
namespace Core::Devtools::Widget {
|
namespace Core::Devtools::Widget {
|
||||||
|
|
||||||
constexpr float TARGET_FPS = 60.0f;
|
|
||||||
constexpr float BAR_WIDTH_MULT = 1.4f;
|
constexpr float BAR_WIDTH_MULT = 1.4f;
|
||||||
constexpr float BAR_HEIGHT_MULT = 1.25f;
|
constexpr float BAR_HEIGHT_MULT = 1.25f;
|
||||||
constexpr float FRAME_GRAPH_PADDING_Y = 3.0f;
|
constexpr float FRAME_GRAPH_PADDING_Y = 3.0f;
|
||||||
@@ -30,7 +29,7 @@ void FrameGraph::DrawFrameGraph() {
|
|||||||
return;
|
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;
|
float cur_pos_x = pos.x + full_width;
|
||||||
pos.y += FRAME_GRAPH_PADDING_Y;
|
pos.y += FRAME_GRAPH_PADDING_Y;
|
||||||
const float final_pos_y = pos.y + FRAME_GRAPH_HEIGHT;
|
const float final_pos_y = pos.y + FRAME_GRAPH_HEIGHT;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ bool MemoryMapViewer::Iterator::DrawLine() {
|
|||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
Text("%" PRIXPTR, m.base);
|
Text("%" PRIXPTR, m.base);
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
Text("%zX", m.size);
|
Text("%" PRIX64, m.size);
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
Text("%s", magic_enum::enum_name(m.type).data());
|
Text("%s", magic_enum::enum_name(m.type).data());
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
@@ -44,19 +44,19 @@ bool MemoryMapViewer::Iterator::DrawLine() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto m = dmem.it->second;
|
auto m = dmem.it->second;
|
||||||
if (m.is_free) {
|
if (m.dma_type == DMAType::Free) {
|
||||||
++dmem.it;
|
++dmem.it;
|
||||||
return DrawLine();
|
return DrawLine();
|
||||||
}
|
}
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
Text("%" PRIXPTR, m.base);
|
Text("%" PRIXPTR, m.base);
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
Text("%zX", m.size);
|
Text("%" PRIX64, m.size);
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
auto type = static_cast<::Libraries::Kernel::MemoryTypes>(m.memory_type);
|
auto type = static_cast<::Libraries::Kernel::MemoryTypes>(m.memory_type);
|
||||||
Text("%s", magic_enum::enum_name(type).data());
|
Text("%s", magic_enum::enum_name(type).data());
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
Text("%d", m.is_pooled);
|
Text("%d", m.dma_type == DMAType::Pooled || m.dma_type == DMAType::Committed);
|
||||||
++dmem.it;
|
++dmem.it;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
55
src/core/devtools/widget/module_list.cpp
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "module_list.h"
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "core/debug_state.h"
|
||||||
|
#include "imgui/imgui_std.h"
|
||||||
|
|
||||||
|
using namespace ImGui;
|
||||||
|
|
||||||
|
namespace Core::Devtools::Widget {
|
||||||
|
void ModuleList::Draw() {
|
||||||
|
SetNextWindowSize({550.0f, 600.0f}, ImGuiCond_FirstUseEver);
|
||||||
|
if (!Begin("Module List", &open)) {
|
||||||
|
End();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BeginTable("ModuleTable", 3,
|
||||||
|
ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable |
|
||||||
|
ImGuiTableFlags_RowBg)) {
|
||||||
|
TableSetupColumn("Modulname", ImGuiTableColumnFlags_WidthStretch);
|
||||||
|
TableHeadersRow();
|
||||||
|
|
||||||
|
std::scoped_lock lock(modules_mutex);
|
||||||
|
for (const auto& module : modules) {
|
||||||
|
TableNextRow();
|
||||||
|
|
||||||
|
TableSetColumnIndex(0);
|
||||||
|
TextUnformatted(module.name.c_str());
|
||||||
|
|
||||||
|
TableSetColumnIndex(1);
|
||||||
|
if (module.is_sys_module) {
|
||||||
|
TextColored({0.2f, 0.6f, 0.8f, 1.0f}, "System Module");
|
||||||
|
} else {
|
||||||
|
TextColored({0.8f, 0.4f, 0.2f, 1.0f}, "Game Module");
|
||||||
|
}
|
||||||
|
|
||||||
|
TableSetColumnIndex(2);
|
||||||
|
if (module.is_lle) {
|
||||||
|
TextColored({0.4f, 0.7f, 0.4f, 1.0f}, "LLE");
|
||||||
|
} else {
|
||||||
|
TextColored({0.7f, 0.4f, 0.5f, 1.0f}, "HLE");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EndTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
End();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Core::Devtools::Widget
|
||||||
83
src/core/devtools/widget/module_list.h
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "common/config.h"
|
||||||
|
#include "common/elf_info.h"
|
||||||
|
#include "common/path_util.h"
|
||||||
|
|
||||||
|
namespace Core::Devtools::Widget {
|
||||||
|
|
||||||
|
class ModuleList {
|
||||||
|
public:
|
||||||
|
ModuleList() = default;
|
||||||
|
~ModuleList() = default;
|
||||||
|
|
||||||
|
void Draw();
|
||||||
|
bool open = false;
|
||||||
|
|
||||||
|
static bool IsSystemModule(const std::filesystem::path& path) {
|
||||||
|
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();
|
||||||
|
|
||||||
|
const auto path_str = abs_path.string();
|
||||||
|
const auto sys_path_str = abs_sys_path.string();
|
||||||
|
|
||||||
|
return path_str.starts_with(sys_path_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsSystemModule(const std::string& name) {
|
||||||
|
const auto game_modules_path = Common::ElfInfo::Instance().GetGameFolder() / "sce_module";
|
||||||
|
const auto prx_path = game_modules_path / name;
|
||||||
|
|
||||||
|
if (!std::filesystem::exists(prx_path)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AddModule(const std::string& name, std::filesystem::path path) {
|
||||||
|
if (name == "eboot.bin") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::scoped_lock lock(modules_mutex);
|
||||||
|
modules.push_back({name, IsSystemModule(path), true});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AddModule(std::string name) {
|
||||||
|
name = name + ".prx";
|
||||||
|
std::scoped_lock lock(modules_mutex);
|
||||||
|
|
||||||
|
bool is_sys_module = IsSystemModule(name);
|
||||||
|
bool is_lle = false;
|
||||||
|
auto it = std::find_if(modules.begin(), modules.end(),
|
||||||
|
[&name, is_sys_module, is_lle](const ModuleInfo& entry) {
|
||||||
|
return entry.name == name && !entry.is_lle;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (it == modules.end()) {
|
||||||
|
modules.push_back({name, is_sys_module, is_lle});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct ModuleInfo {
|
||||||
|
std::string name;
|
||||||
|
bool is_sys_module;
|
||||||
|
bool is_lle;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline std::mutex modules_mutex;
|
||||||
|
|
||||||
|
static inline std::vector<ModuleInfo> modules;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Core::Devtools::Widget
|
||||||
@@ -16,7 +16,7 @@ using magic_enum::enum_name;
|
|||||||
|
|
||||||
namespace Core::Devtools::Widget {
|
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)) {
|
if (BeginTable("COLOR_BUFFER", 2, ImGuiTableFlags_Borders)) {
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ void RegPopup::DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer) {
|
|||||||
if (TreeNode("Color0Info")) {
|
if (TreeNode("Color0Info")) {
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
ParseColor0Info(buffer.info.u32all, false);
|
ParseColor0Info(buffer.info.raw, false);
|
||||||
TreePop();
|
TreePop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ void RegPopup::DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer) {
|
|||||||
if (TreeNode("Color0Attrib")) {
|
if (TreeNode("Color0Attrib")) {
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
ParseColor0Attrib(buffer.attrib.u32all, false);
|
ParseColor0Attrib(buffer.attrib.raw, false);
|
||||||
TreePop();
|
TreePop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ void RegPopup::DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer) {
|
|||||||
"NumSamples()", buffer.NumSamples(),
|
"NumSamples()", buffer.NumSamples(),
|
||||||
"NumSlices()", buffer.NumSlices(),
|
"NumSlices()", buffer.NumSlices(),
|
||||||
"GetColorSliceSize()", buffer.GetColorSliceSize(),
|
"GetColorSliceSize()", buffer.GetColorSliceSize(),
|
||||||
"GetTilingMode()", buffer.GetTilingMode(),
|
"GetTileMode()", buffer.GetTileMode(),
|
||||||
"IsTiled()", buffer.IsTiled(),
|
"IsTiled()", buffer.IsTiled(),
|
||||||
"NumFormat()", buffer.GetNumberFmt()
|
"NumFormat()", buffer.GetNumberFmt()
|
||||||
);
|
);
|
||||||
@@ -75,9 +75,8 @@ void RegPopup::DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegPopup::DrawDepthBuffer(const DepthBuffer& depth_data) {
|
void RegPopup::DrawDepthBuffer(const AmdGpu::DepthBuffer& buffer,
|
||||||
const auto& [depth_buffer, depth_control] = depth_data;
|
const AmdGpu::DepthControl control) {
|
||||||
|
|
||||||
SeparatorText("Depth buffer");
|
SeparatorText("Depth buffer");
|
||||||
|
|
||||||
if (BeginTable("DEPTH_BUFFER", 2, ImGuiTableFlags_Borders)) {
|
if (BeginTable("DEPTH_BUFFER", 2, ImGuiTableFlags_Borders)) {
|
||||||
@@ -85,31 +84,31 @@ void RegPopup::DrawDepthBuffer(const DepthBuffer& depth_data) {
|
|||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
DrawValueRowList(
|
DrawValueRowList(
|
||||||
"Z_INFO.FORMAT", depth_buffer.z_info.format,
|
"Z_INFO.FORMAT", buffer.z_info.format,
|
||||||
"Z_INFO.NUM_SAMPLES", depth_buffer.z_info.num_samples,
|
"Z_INFO.NUM_SAMPLES", buffer.z_info.num_samples,
|
||||||
"Z_INFO.TILE_SPLIT", depth_buffer.z_info.tile_split,
|
"Z_INFO.TILE_SPLIT", buffer.z_info.tile_split,
|
||||||
"Z_INFO.TILE_MODE_INDEX", depth_buffer.z_info.tile_mode_index,
|
"Z_INFO.TILE_MODE_INDEX", buffer.z_info.tile_mode_index,
|
||||||
"Z_INFO.DECOMPRESS_ON_N_ZPLANES", depth_buffer.z_info.decompress_on_n_zplanes,
|
"Z_INFO.DECOMPRESS_ON_N_ZPLANES", buffer.z_info.decompress_on_n_zplanes,
|
||||||
"Z_INFO.ALLOW_EXPCLEAR", depth_buffer.z_info.allow_expclear,
|
"Z_INFO.ALLOW_EXPCLEAR", buffer.z_info.allow_expclear,
|
||||||
"Z_INFO.READ_SIZE", depth_buffer.z_info.read_size,
|
"Z_INFO.READ_SIZE", buffer.z_info.read_size,
|
||||||
"Z_INFO.TILE_SURFACE_EN", depth_buffer.z_info.tile_surface_en,
|
"Z_INFO.TILE_SURFACE_ENABLE", buffer.z_info.tile_surface_enable,
|
||||||
"Z_INFO.CLEAR_DISALLOWED", depth_buffer.z_info.clear_disallowed,
|
"Z_INFO.CLEAR_DISALLOWED", buffer.z_info.clear_disallowed,
|
||||||
"Z_INFO.ZRANGE_PRECISION", depth_buffer.z_info.zrange_precision,
|
"Z_INFO.ZRANGE_PRECISION", buffer.z_info.zrange_precision,
|
||||||
"STENCIL_INFO.FORMAT", depth_buffer.stencil_info.format,
|
"STENCIL_INFO.FORMAT", buffer.stencil_info.format,
|
||||||
"Z_READ_BASE", depth_buffer.z_read_base,
|
"Z_READ_BASE", buffer.z_read_base,
|
||||||
"STENCIL_READ_BASE", depth_buffer.stencil_read_base,
|
"STENCIL_READ_BASE", buffer.stencil_read_base,
|
||||||
"Z_WRITE_BASE", depth_buffer.z_write_base,
|
"Z_WRITE_BASE", buffer.z_write_base,
|
||||||
"STENCIL_WRITE_BASE", depth_buffer.stencil_write_base,
|
"STENCIL_WRITE_BASE", buffer.stencil_write_base,
|
||||||
"DEPTH_SIZE.PITCH_TILE_MAX", depth_buffer.depth_size.pitch_tile_max,
|
"DEPTH_SIZE.PITCH_TILE_MAX", buffer.depth_size.pitch_tile_max,
|
||||||
"DEPTH_SIZE.HEIGHT_TILE_MAX", depth_buffer.depth_size.height_tile_max,
|
"DEPTH_SIZE.HEIGHT_TILE_MAX", buffer.depth_size.height_tile_max,
|
||||||
"DEPTH_SLICE.TILE_MAX", depth_buffer.depth_slice.tile_max,
|
"DEPTH_SLICE.TILE_MAX", buffer.depth_slice.tile_max,
|
||||||
"Pitch()", depth_buffer.Pitch(),
|
"Pitch()", buffer.Pitch(),
|
||||||
"Height()", depth_buffer.Height(),
|
"Height()", buffer.Height(),
|
||||||
"DepthAddress()", depth_buffer.DepthAddress(),
|
"DepthAddress()", buffer.DepthAddress(),
|
||||||
"StencilAddress()", depth_buffer.StencilAddress(),
|
"StencilAddress()", buffer.StencilAddress(),
|
||||||
"NumSamples()", depth_buffer.NumSamples(),
|
"NumSamples()", buffer.NumSamples(),
|
||||||
"NumBits()", depth_buffer.NumBits(),
|
"NumBits()", buffer.NumBits(),
|
||||||
"GetDepthSliceSize()", depth_buffer.GetDepthSliceSize()
|
"GetDepthSliceSize()", buffer.GetDepthSliceSize()
|
||||||
);
|
);
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
@@ -121,16 +120,16 @@ void RegPopup::DrawDepthBuffer(const DepthBuffer& depth_data) {
|
|||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
DrawValueRowList(
|
DrawValueRowList(
|
||||||
"STENCIL_ENABLE", depth_control.stencil_enable,
|
"STENCIL_ENABLE", control.stencil_enable,
|
||||||
"DEPTH_ENABLE", depth_control.depth_enable,
|
"DEPTH_ENABLE", control.depth_enable,
|
||||||
"DEPTH_WRITE_ENABLE", depth_control.depth_write_enable,
|
"DEPTH_WRITE_ENABLE", control.depth_write_enable,
|
||||||
"DEPTH_BOUNDS_ENABLE", depth_control.depth_bounds_enable,
|
"DEPTH_BOUNDS_ENABLE", control.depth_bounds_enable,
|
||||||
"DEPTH_FUNC", depth_control.depth_func,
|
"DEPTH_FUNC", control.depth_func,
|
||||||
"BACKFACE_ENABLE", depth_control.backface_enable,
|
"BACKFACE_ENABLE", control.backface_enable,
|
||||||
"STENCIL_FUNC", depth_control.stencil_ref_func,
|
"STENCIL_FUNC", control.stencil_ref_func,
|
||||||
"STENCIL_FUNC_BF", depth_control.stencil_bf_func,
|
"STENCIL_FUNC_BF", control.stencil_bf_func,
|
||||||
"ENABLE_COLOR_WRITES_ON_DEPTH_FAIL", depth_control.enable_color_writes_on_depth_fail,
|
"ENABLE_COLOR_WRITES_ON_DEPTH_FAIL", control.enable_color_writes_on_depth_fail,
|
||||||
"DISABLE_COLOR_WRITES_ON_DEPTH_PASS", depth_control.disable_color_writes_on_depth_pass
|
"DISABLE_COLOR_WRITES_ON_DEPTH_PASS", control.disable_color_writes_on_depth_pass
|
||||||
);
|
);
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
@@ -143,15 +142,17 @@ RegPopup::RegPopup() {
|
|||||||
id = unique_id++;
|
id = unique_id++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegPopup::SetData(const std::string& base_title, AmdGpu::Liverpool::ColorBuffer color_buffer,
|
void RegPopup::SetData(const std::string& base_title, AmdGpu::ColorBuffer color_buffer, u32 cb_id) {
|
||||||
u32 cb_id) {
|
this->type = DataType::Color;
|
||||||
this->data = color_buffer;
|
this->color = color_buffer;
|
||||||
this->title = fmt::format("{}/CB #{}", base_title, cb_id);
|
this->title = fmt::format("{}/CB #{}", base_title, cb_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegPopup::SetData(const std::string& base_title, AmdGpu::Liverpool::DepthBuffer depth_buffer,
|
void RegPopup::SetData(const std::string& base_title, AmdGpu::DepthBuffer depth_buffer,
|
||||||
AmdGpu::Liverpool::DepthControl depth_control) {
|
AmdGpu::DepthControl depth_control) {
|
||||||
this->data = std::make_tuple(depth_buffer, depth_control);
|
this->type = DataType::Depth;
|
||||||
|
this->depth.buffer = depth_buffer;
|
||||||
|
this->depth.control = depth_control;
|
||||||
this->title = fmt::format("{}/Depth", base_title);
|
this->title = fmt::format("{}/Depth", base_title);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,10 +162,10 @@ void RegPopup::SetPos(ImVec2 pos, bool auto_resize) {
|
|||||||
Begin(name, &open, flags);
|
Begin(name, &open, flags);
|
||||||
SetWindowPos(pos);
|
SetWindowPos(pos);
|
||||||
if (auto_resize) {
|
if (auto_resize) {
|
||||||
if (std::holds_alternative<AmdGpu::Liverpool::ColorBuffer>(data)) {
|
if (type == DataType::Color) {
|
||||||
SetWindowSize({365.0f, 520.0f});
|
SetWindowSize({365.0f, 520.0f});
|
||||||
KeepWindowInside();
|
KeepWindowInside();
|
||||||
} else if (std::holds_alternative<DepthBuffer>(data)) {
|
} else if (type == DataType::Depth) {
|
||||||
SetWindowSize({404.0f, 543.0f});
|
SetWindowSize({404.0f, 543.0f});
|
||||||
KeepWindowInside();
|
KeepWindowInside();
|
||||||
}
|
}
|
||||||
@@ -182,10 +183,10 @@ void RegPopup::Draw() {
|
|||||||
moved = true;
|
moved = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const auto* buffer = std::get_if<AmdGpu::Liverpool::ColorBuffer>(&data)) {
|
if (type == DataType::Color) {
|
||||||
DrawColorBuffer(*buffer);
|
DrawColorBuffer(color);
|
||||||
} else if (const auto* depth_data = std::get_if<DepthBuffer>(&data)) {
|
} else if (type == DataType::Depth) {
|
||||||
DrawDepthBuffer(*depth_data);
|
DrawDepthBuffer(depth.buffer, depth.control);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
End();
|
End();
|
||||||
|
|||||||