mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-04-28 21:38:03 +03:00
Compare commits
657 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
beb9c86749 | ||
![]() |
81fa9b7fff | ||
![]() |
385c5a4507 | ||
![]() |
59d060bc16 | ||
![]() |
83fd0683fa | ||
![]() |
81ad31ce31 | ||
![]() |
ff984d3cde | ||
![]() |
b505829e16 | ||
![]() |
254375ef0c | ||
![]() |
cef795b80b | ||
![]() |
410313ca87 | ||
![]() |
c09fff2da6 | ||
![]() |
e816bc4b99 | ||
![]() |
632ed99ee7 | ||
![]() |
15d6a45dcd | ||
![]() |
d370ea32f4 | ||
![]() |
c01590175a | ||
![]() |
a12d447bd6 | ||
![]() |
ce3aded3e5 | ||
![]() |
4ecdcf77d1 | ||
![]() |
3f4249084c | ||
![]() |
aeee7706ee | ||
![]() |
5db162cbcd | ||
![]() |
354a2e6946 | ||
![]() |
53ca64f6ff | ||
![]() |
ee7fe305c9 | ||
![]() |
b1ebb2fec5 | ||
![]() |
96bee58d0f | ||
![]() |
0297aee3f4 | ||
![]() |
5b0205bc59 | ||
![]() |
cda421434b | ||
![]() |
0c86c54d48 | ||
![]() |
5be726ca3b | ||
![]() |
69777e2ffa | ||
![]() |
111ff2bedd | ||
![]() |
d188510e59 | ||
![]() |
d0dbb737d9 | ||
![]() |
e11ffe242b | ||
![]() |
6e963a7f71 | ||
![]() |
81ada41baa | ||
![]() |
0feb2e7211 | ||
![]() |
23c616c647 | ||
![]() |
20b11f2d63 | ||
![]() |
df89241eb8 | ||
![]() |
703620c7cd | ||
![]() |
b1b7538afd | ||
![]() |
ddc05e8a5f | ||
![]() |
62a4182aca | ||
![]() |
aa8dab5371 | ||
![]() |
ddf3df7f56 | ||
![]() |
243ee04b1c | ||
![]() |
04e4ce0775 | ||
![]() |
52ab1ed04b | ||
![]() |
3bc876ca78 | ||
![]() |
247e935353 | ||
![]() |
4bea00135d | ||
![]() |
683a223c1b | ||
![]() |
2b633fd3c5 | ||
![]() |
cd8e2c4e79 | ||
![]() |
7d32efbd31 | ||
![]() |
b8884d9591 | ||
![]() |
bec1b9056f | ||
![]() |
657073b9e2 | ||
![]() |
fb146f2a20 | ||
![]() |
ec515ad113 | ||
![]() |
d188d14e19 | ||
![]() |
14fad28a9b | ||
![]() |
aec6e330dc | ||
![]() |
6c2574364b | ||
![]() |
8ed82712a0 | ||
![]() |
b0fe1532f7 | ||
![]() |
6ebed7ce69 | ||
![]() |
37d4cd091c | ||
![]() |
5abec2a291 | ||
![]() |
e3b1c041d0 | ||
![]() |
2965656325 | ||
![]() |
03b1fef331 | ||
![]() |
08731303d8 | ||
![]() |
7fee289b66 | ||
![]() |
040fd79ef7 | ||
![]() |
473b66649f | ||
![]() |
b8f6ef1c0b | ||
![]() |
9d2175180e | ||
![]() |
0c6f2b470f | ||
![]() |
54b4d7fc78 | ||
![]() |
1ee2016902 | ||
![]() |
7bb49d85d3 | ||
![]() |
806b2ddc89 | ||
![]() |
afd0251dd2 | ||
![]() |
eb300d0aa7 | ||
![]() |
f6cc245e40 | ||
![]() |
9ee5d066a2 | ||
![]() |
01243fb8e5 | ||
![]() |
a2a1ecde0a | ||
![]() |
a5958bf7f0 | ||
![]() |
7533206d89 | ||
![]() |
b0a12c02e1 | ||
![]() |
374b66ad8e | ||
![]() |
f85d8df71e | ||
![]() |
a707d31a4c | ||
![]() |
f1e0a096d5 | ||
![]() |
3f33d218b3 | ||
![]() |
99b90cbd5c | ||
![]() |
bad82e7204 | ||
![]() |
faae1218fa | ||
![]() |
064c3161c3 | ||
![]() |
8122f8ecbf | ||
![]() |
9dbc79dc96 | ||
![]() |
df9151481c | ||
![]() |
be7d646e83 | ||
![]() |
78c8bca2bb | ||
![]() |
751a23af0f | ||
![]() |
501f46e515 | ||
![]() |
31e1d4f839 | ||
![]() |
be22674f8c | ||
![]() |
d339b3f7d6 | ||
![]() |
602de0c370 | ||
![]() |
c96853816a | ||
![]() |
437af93201 | ||
![]() |
ae2c9a745e | ||
![]() |
5caab76a45 | ||
![]() |
9c37aa039b | ||
![]() |
3abe5b0d57 | ||
![]() |
90b949b8ce | ||
![]() |
69cb4d5787 | ||
![]() |
d8204641fa | ||
![]() |
7d0631cf26 | ||
![]() |
a1ec8b0a88 | ||
![]() |
5c72030fb8 | ||
![]() |
1908d26093 | ||
![]() |
16a68d78eb | ||
![]() |
4f8e5dfd7c | ||
![]() |
10bf3d383c | ||
![]() |
99332e4ec2 | ||
![]() |
6f944ab117 | ||
![]() |
1f9ac53c28 | ||
![]() |
a80c4a7f48 | ||
![]() |
0fa1220eca | ||
![]() |
d7b947dd79 | ||
![]() |
3b2c012723 | ||
![]() |
2e54afb295 | ||
![]() |
c19b692a66 | ||
![]() |
b1885badda | ||
![]() |
2a05af22e1 | ||
![]() |
4eb6304076 | ||
![]() |
9298b074fc | ||
![]() |
b520994960 | ||
![]() |
171f755c13 | ||
![]() |
5691046dcc | ||
![]() |
36927a7bbd | ||
![]() |
4d0c03fd4a | ||
![]() |
f663176a5d | ||
![]() |
ba1eb298de | ||
![]() |
8bcdd9c068 | ||
![]() |
46b1bafa17 | ||
![]() |
a711f4d86e | ||
![]() |
20ea0ee190 | ||
![]() |
74c2c6c74f | ||
![]() |
aa22d80c3f | ||
![]() |
0e315cbd8f | ||
![]() |
6b3746f3a6 | ||
![]() |
bfb8b46d7d | ||
![]() |
b5029ab940 | ||
![]() |
8b7eed3ffc | ||
![]() |
eaa18d4e3c | ||
![]() |
f4dc8dca8d | ||
![]() |
0efe9a4d0f | ||
![]() |
f1aea5176d | ||
![]() |
96560ed3ca | ||
![]() |
dc52cfb9bc | ||
![]() |
f62884ffda | ||
![]() |
f4bf53402f | ||
![]() |
ba109a4c53 | ||
![]() |
3a9633f553 | ||
![]() |
7bef4a5c70 | ||
![]() |
e82c8d2f70 | ||
![]() |
367f08c1b5 | ||
![]() |
a4b35f275c | ||
![]() |
c2adaf41c0 | ||
![]() |
517d7f04c6 | ||
![]() |
c59d5eef45 | ||
![]() |
951128389d | ||
![]() |
a583a9abe0 | ||
![]() |
7a4244ac8b | ||
![]() |
d59536a71c | ||
![]() |
f4110c43a7 | ||
![]() |
76483f9c7b | ||
![]() |
4c7c703ea2 | ||
![]() |
9061028ce5 | ||
![]() |
0bdd21b4e4 | ||
![]() |
636a90386b | ||
![]() |
db868ea400 | ||
![]() |
99c7fc4049 | ||
![]() |
75db253370 | ||
![]() |
6331eb1d8a | ||
![]() |
169cbe90a5 | ||
![]() |
f5c75a5f55 | ||
![]() |
3b5d9459f3 | ||
![]() |
bf995d659b | ||
![]() |
5e5ca2138e | ||
![]() |
63b50ff92c | ||
![]() |
927f398658 | ||
![]() |
f0cc8c0d54 | ||
![]() |
be6840f6a9 | ||
![]() |
15d10e47ea | ||
![]() |
eac1daa5f7 | ||
![]() |
b8aac357cb | ||
![]() |
fd3bfdae80 | ||
![]() |
0a23072938 | ||
![]() |
76b4da6212 | ||
![]() |
0885d8fce7 | ||
![]() |
f975c0603c | ||
![]() |
ad68318515 | ||
![]() |
c9ba8e989e | ||
![]() |
47ac8b6c03 | ||
![]() |
bc0b42ee53 | ||
![]() |
07baf17c2a | ||
![]() |
229740f557 | ||
![]() |
42dd79a32d | ||
![]() |
c38e1635ea | ||
![]() |
84a614dddc | ||
![]() |
f1c70ce53c | ||
![]() |
02f9d03f57 | ||
![]() |
bc85357235 | ||
![]() |
e1e697a3ff | ||
![]() |
10486db091 | ||
![]() |
e1ae052185 | ||
![]() |
22ca57b1f2 | ||
![]() |
4f1baece33 | ||
![]() |
0aaeea4837 | ||
![]() |
8a793f64bf | ||
![]() |
9424047214 | ||
![]() |
6860bb7349 | ||
![]() |
5b3e156197 | ||
![]() |
745cdd89fd | ||
![]() |
6f5dfc576f | ||
![]() |
54a1694a2b | ||
![]() |
14717b8ecb | ||
![]() |
3ed1c31678 | ||
![]() |
b6baf78812 | ||
![]() |
2af20b0d83 | ||
![]() |
cc583b6189 | ||
![]() |
da0ab005c7 | ||
![]() |
50aa0f5564 | ||
![]() |
f686b1df98 | ||
![]() |
48c621532c | ||
![]() |
7d756e79ae | ||
![]() |
8447412c77 | ||
![]() |
e67263cc0e | ||
![]() |
41496e035a | ||
![]() |
e40451a3f7 | ||
![]() |
154473d3b3 | ||
![]() |
fd3d3c4158 | ||
![]() |
b06790dfe5 | ||
![]() |
195b94c1f1 | ||
![]() |
90c01f8d92 | ||
![]() |
679f8f1f36 | ||
![]() |
e9b44af469 | ||
![]() |
0425bd0fd6 | ||
![]() |
e13fb2e366 | ||
![]() |
26bb3d40d9 | ||
![]() |
7af9de353b | ||
![]() |
b0169de7c4 | ||
![]() |
e042710eaa | ||
![]() |
2b9a8e5605 | ||
![]() |
bdf4a5249d | ||
![]() |
82cacec8eb | ||
![]() |
290e127a4f | ||
![]() |
32763b7af6 | ||
![]() |
1781fcb9ef | ||
![]() |
16451b01e8 | ||
![]() |
bb6cca3056 | ||
![]() |
b48975f116 | ||
![]() |
1cc9e0d37f | ||
![]() |
ad43ba5ec7 | ||
![]() |
57bdb6cac2 | ||
![]() |
1dca54c165 | ||
![]() |
67a74a9357 | ||
![]() |
7db30d12cb | ||
![]() |
0f8bd509b2 | ||
![]() |
d1e88c40d8 | ||
![]() |
46ef678f55 | ||
![]() |
d76210d24f | ||
![]() |
4dfe05db24 | ||
![]() |
3634026436 | ||
![]() |
455b23c6f1 | ||
![]() |
b2fb004414 | ||
![]() |
1e7f651b1b | ||
![]() |
c94cd531f0 | ||
![]() |
40cd5c57c5 | ||
![]() |
753a3072ee | ||
![]() |
43191ff426 | ||
![]() |
7728db0dd3 | ||
![]() |
6e12642151 | ||
![]() |
ebe2aadb4c | ||
![]() |
c9d425dc08 | ||
![]() |
5f2467b453 | ||
![]() |
3b1840b7a9 | ||
![]() |
50b27bebd8 | ||
![]() |
7624e9482c | ||
![]() |
642c0bc367 | ||
![]() |
98eb8cb741 | ||
![]() |
2188895b40 | ||
![]() |
40eef6a066 | ||
![]() |
b51c767296 | ||
![]() |
843cd01308 | ||
![]() |
22357f70c2 | ||
![]() |
04fe3a79b9 | ||
![]() |
34a4f6e60e | ||
![]() |
15b520f4a2 | ||
![]() |
5d4812d1a6 | ||
![]() |
f3afbfbcec | ||
![]() |
0e238c87cb | ||
![]() |
89d349ae1c | ||
![]() |
95d5343eb4 | ||
![]() |
214eab2c52 | ||
![]() |
8f2883a388 | ||
![]() |
fb0871dbc8 | ||
![]() |
9dc3e39fc2 | ||
![]() |
a7a8ebcd77 | ||
![]() |
d98face501 | ||
![]() |
cb14431ee5 | ||
![]() |
3c5cb093de | ||
![]() |
cfe249debe | ||
![]() |
78b4f10cc6 | ||
![]() |
46cbee1585 | ||
![]() |
78ea536c95 | ||
![]() |
1a00b1af24 | ||
![]() |
1eb0affdea | ||
![]() |
0d498f12b9 | ||
![]() |
f111395044 | ||
![]() |
0c3260b1b4 | ||
![]() |
e1f0cd65af | ||
![]() |
e972a8805d | ||
![]() |
f5d64239cb | ||
![]() |
00465d5e41 | ||
![]() |
126cb824ea | ||
![]() |
ecfc940381 | ||
![]() |
e757063d31 | ||
![]() |
131b6f90e0 | ||
![]() |
b879dd59c6 | ||
![]() |
b6ad512e34 | ||
![]() |
363604c6f0 | ||
![]() |
e4598e8821 | ||
![]() |
fffd373652 | ||
![]() |
f8f732e78c | ||
![]() |
e0d85a7e58 | ||
![]() |
97441b62d1 | ||
![]() |
8ad650582a | ||
![]() |
02ad2b78fa | ||
![]() |
cef7edaea9 | ||
![]() |
83abaafdfa | ||
![]() |
a55acae5ee | ||
![]() |
8d4261efba | ||
![]() |
56b2f6c4cf | ||
![]() |
0d65ef6f6e | ||
![]() |
c5cd4bc5cf | ||
![]() |
460c266e04 | ||
![]() |
831903799b | ||
![]() |
1d8c607c15 | ||
![]() |
83671ebf76 | ||
![]() |
84c27eea2a | ||
![]() |
e1550c9091 | ||
![]() |
259d5ef60b | ||
![]() |
9aa6c5b951 | ||
![]() |
c4bfaa6031 | ||
![]() |
f3810cebea | ||
![]() |
fda8f1afa3 | ||
![]() |
eed4de1da9 | ||
![]() |
8aea0fc7ee | ||
![]() |
ec0cf25097 | ||
![]() |
49fc210833 | ||
![]() |
f3c33b29dd | ||
![]() |
8057ed408c | ||
![]() |
ec7a541263 | ||
![]() |
a55cec1954 | ||
![]() |
6e58c6c513 | ||
![]() |
647694d1b9 | ||
![]() |
7ae1d73781 | ||
![]() |
be74f65864 | ||
![]() |
b5d63a31cc | ||
![]() |
c77f62a738 | ||
![]() |
52df7f6fe5 | ||
![]() |
ad5bd91a13 | ||
![]() |
e805b97520 | ||
![]() |
c89c7e8fed | ||
![]() |
19bbbf994c | ||
![]() |
3a163002d7 | ||
![]() |
132a9d7d35 | ||
![]() |
d8b4114296 | ||
![]() |
0b50e2e270 | ||
![]() |
0358271b93 | ||
![]() |
929e15260d | ||
![]() |
4bb578f9fb | ||
![]() |
aa847de043 | ||
![]() |
9bad66b24d | ||
![]() |
78a0a755c5 | ||
![]() |
0575853be1 | ||
![]() |
a78f8afe58 | ||
![]() |
2cdd873681 | ||
![]() |
4b93b8b574 | ||
![]() |
8379922f8a | ||
![]() |
d2127b38de | ||
![]() |
2837d848ed | ||
![]() |
665261efc5 | ||
![]() |
191e64bfa1 | ||
![]() |
6f04ea18e4 | ||
![]() |
7d1631f9f4 | ||
![]() |
46b5437fdf | ||
![]() |
461148c227 | ||
![]() |
3960283a67 | ||
![]() |
f1bc3b4f3d | ||
![]() |
a5a1253185 | ||
![]() |
564dbc7b94 | ||
![]() |
e433f3116d | ||
![]() |
73b7d34460 | ||
![]() |
7072dfc99f | ||
![]() |
361532418c | ||
![]() |
a51c8c17e0 | ||
![]() |
56f4b8a2b8 | ||
![]() |
b3c573f798 | ||
![]() |
a4eba8e827 | ||
![]() |
4f426b723f | ||
![]() |
4d12de8149 | ||
![]() |
9dcf40e261 | ||
![]() |
0f69697acb | ||
![]() |
481f420a89 | ||
![]() |
d1b9a5adcc | ||
![]() |
74710116f6 | ||
![]() |
91444a0545 | ||
![]() |
a8a779c79b | ||
![]() |
e652369f22 | ||
![]() |
cc4ddd28c3 | ||
![]() |
0ebe817a28 | ||
![]() |
cdca420a2e | ||
![]() |
2e6c9b8f98 | ||
![]() |
fb738bc247 | ||
![]() |
cef92fbcaa | ||
![]() |
cc2e13873f | ||
![]() |
81e7e4b216 | ||
![]() |
1fcfb07421 | ||
![]() |
d7c2cb17f3 | ||
![]() |
c015ac1344 | ||
![]() |
e584444aa3 | ||
![]() |
b3bce086b3 | ||
![]() |
2968cf5a99 | ||
![]() |
adbff4056f | ||
![]() |
78ae9613c5 | ||
![]() |
2a4798cfa6 | ||
![]() |
5c62a00134 | ||
![]() |
41b3942833 | ||
![]() |
84a341dce5 | ||
![]() |
3563b88d8c | ||
![]() |
95a30b2b3e | ||
![]() |
a3967ccdb4 | ||
![]() |
e1132db197 | ||
![]() |
0f93edb377 | ||
![]() |
4fa501c8d5 | ||
![]() |
d14e57f6a8 | ||
![]() |
80092b6367 | ||
![]() |
201f2817ca | ||
![]() |
17ac63d23a | ||
![]() |
c8bbecda26 | ||
![]() |
a7d45231b7 | ||
![]() |
ec0dfb32b5 | ||
![]() |
746f2e091d | ||
![]() |
269ce12614 | ||
![]() |
388548ba47 | ||
![]() |
3b92cd1c1a | ||
![]() |
1ea5f8f092 | ||
![]() |
c80151adde | ||
![]() |
d361579618 | ||
![]() |
12364b197a | ||
![]() |
81ad575b22 | ||
![]() |
9a956f5ed0 | ||
![]() |
40385e13e7 | ||
![]() |
90b04e8cc0 | ||
![]() |
7b8177f48e | ||
![]() |
a5440e0e43 | ||
![]() |
e134fc5f1e | ||
![]() |
99a04357d1 | ||
![]() |
4e8c178aec | ||
![]() |
0cee59cbe6 | ||
![]() |
9e5b50c866 | ||
![]() |
1d3427780a | ||
![]() |
1e5b316ac4 | ||
![]() |
c13b29662e | ||
![]() |
3b474a12f9 | ||
![]() |
eb49193309 | ||
![]() |
8695383d35 | ||
![]() |
56a6c95730 | ||
![]() |
440a693fae | ||
![]() |
4695aaa830 | ||
![]() |
34a5f2319c | ||
![]() |
da2b58f66e | ||
![]() |
b3739bea92 | ||
![]() |
1c3048ccc2 | ||
![]() |
5a7d45fdfa | ||
![]() |
53d0a309cc | ||
![]() |
c10f9b8269 | ||
![]() |
5040be1640 | ||
![]() |
d94abffd9a | ||
![]() |
4719d32295 | ||
![]() |
4f2f9494b0 | ||
![]() |
c6ab149c56 | ||
![]() |
394331f206 | ||
![]() |
8a309c30a9 | ||
![]() |
466e071c97 | ||
![]() |
82cb298c5c | ||
![]() |
5810c88c00 | ||
![]() |
62bbad62fc | ||
![]() |
5ac7e70e4b | ||
![]() |
5c845d4ecc | ||
![]() |
6ec68f66a9 | ||
![]() |
cfaea1ea6d | ||
![]() |
4a21d94871 | ||
![]() |
e656093d85 | ||
![]() |
562ed2a025 | ||
![]() |
4563b6379d | ||
![]() |
725814ce01 | ||
![]() |
93402620de | ||
![]() |
65f9bbbfed | ||
![]() |
0eee36cbc7 | ||
![]() |
fc50567fc2 | ||
![]() |
e791ff4c5c | ||
![]() |
8f5bcb0f1c | ||
![]() |
af8c748e9c | ||
![]() |
3e5d4bb69c | ||
![]() |
c055c80c6f | ||
![]() |
a4c18b1434 | ||
![]() |
4df0d9c035 | ||
![]() |
32fc983ef8 | ||
![]() |
b0d7feb292 | ||
![]() |
c3ecf599ad | ||
![]() |
86038e6a71 | ||
![]() |
7bf467c653 | ||
![]() |
869bf85e9a | ||
![]() |
c08fc85b72 | ||
![]() |
39b511070a | ||
![]() |
5559f35905 | ||
![]() |
6f3c767b99 | ||
![]() |
121328eced | ||
![]() |
fb67d948b6 | ||
![]() |
7cdeb51670 | ||
![]() |
8879380427 | ||
![]() |
e5f638b378 | ||
![]() |
4dcd7f0271 | ||
![]() |
c0f57df4e6 | ||
![]() |
8f33dfe4f1 | ||
![]() |
79663789bd | ||
![]() |
9d3143231c | ||
![]() |
7459d9c333 | ||
![]() |
f2f24bb2cd | ||
![]() |
f42b8acf47 | ||
![]() |
78a32a3c0f | ||
![]() |
ddc658f8c8 | ||
![]() |
7153bc8d8f | ||
![]() |
8e8671323a | ||
![]() |
c2be12f009 | ||
![]() |
9434cae458 | ||
![]() |
2951788afc | ||
![]() |
345d55669e | ||
![]() |
4e1733222f | ||
![]() |
dcc662ff1a | ||
![]() |
67c531298a | ||
![]() |
77d2172441 | ||
![]() |
f7a8e2409c | ||
![]() |
55ccec4a38 | ||
![]() |
c977011d2f | ||
![]() |
b87bca2e46 | ||
![]() |
55b50171f8 | ||
![]() |
596f4cdf0e | ||
![]() |
c25447097e | ||
![]() |
6862c9aad7 | ||
![]() |
099e685bff | ||
![]() |
1926900945 | ||
![]() |
33afc00c3a | ||
![]() |
3109bd245f | ||
![]() |
8b66e9f78d | ||
![]() |
4e0757ed55 | ||
![]() |
46720e756b | ||
![]() |
40211642ca | ||
![]() |
444016df7e | ||
![]() |
15c9bb0e83 | ||
![]() |
5631a31640 | ||
![]() |
a76e8f0211 | ||
![]() |
283442b42f | ||
![]() |
d69341fd31 | ||
![]() |
65cd3be4ca | ||
![]() |
174b5c0f95 | ||
![]() |
48c51bd9ef | ||
![]() |
927dc6d95c | ||
![]() |
f41829707d | ||
![]() |
052473e048 | ||
![]() |
e1cf1f500d | ||
![]() |
41d64a200d | ||
![]() |
284f473a52 | ||
![]() |
62780e4e43 | ||
![]() |
9091223396 | ||
![]() |
dd3f24614b | ||
![]() |
ac2e8c2602 | ||
![]() |
38f1cc2652 | ||
![]() |
1bc27135e3 | ||
![]() |
ee72d99947 | ||
![]() |
f09a95453e | ||
![]() |
e952013fe0 | ||
![]() |
f8177902a5 | ||
![]() |
4b2db61120 | ||
![]() |
248220fef3 | ||
![]() |
62c47cb1b7 | ||
![]() |
da9e45b582 | ||
![]() |
202c1046a1 | ||
![]() |
468d7ea80e | ||
![]() |
ab7e794f23 | ||
![]() |
ee974414d2 | ||
![]() |
851995d444 | ||
![]() |
e8b0fdd6cc | ||
![]() |
a8b4e14bf5 | ||
![]() |
8447d6ea1c | ||
![]() |
63d2d1ebe8 | ||
![]() |
668d5f65dc | ||
![]() |
99e1e028c0 | ||
![]() |
f0352d2f7d | ||
![]() |
c8b704e4a3 | ||
![]() |
fc2fd9fd3c | ||
![]() |
817a62468e | ||
![]() |
55f78a0b94 | ||
![]() |
9aabe98e4e | ||
![]() |
04933ac863 | ||
![]() |
122fe22a32 | ||
![]() |
49ffb7b120 | ||
![]() |
3218c36b22 | ||
![]() |
abe85fd3e0 | ||
![]() |
f4c1d827d5 | ||
![]() |
115aa61d04 | ||
![]() |
333f35ef25 | ||
![]() |
f95803664b | ||
![]() |
e40ede5db2 | ||
![]() |
ff4d37cbc8 | ||
![]() |
0351b864d0 | ||
![]() |
a86ee7e7f5 | ||
![]() |
b1f74660df | ||
![]() |
1c5947d93b | ||
![]() |
cf84c46a49 | ||
![]() |
0677d7a214 | ||
![]() |
9b8de8d320 | ||
![]() |
4e8b8887df | ||
![]() |
5dd1e7c32e | ||
![]() |
edc027a8bc | ||
![]() |
0bb1c05aff | ||
![]() |
cbb13fa39b | ||
![]() |
91d4044162 | ||
![]() |
e885088632 | ||
![]() |
ba9273d1cc | ||
![]() |
5f9abd1db4 | ||
![]() |
0939082aca | ||
![]() |
3a1a3fc75e |
561 changed files with 115078 additions and 56549 deletions
|
@ -10,7 +10,7 @@ if grep -nrI '\s$' src *.yml *.txt *.md Doxyfile .gitignore .gitmodules .ci* dis
|
|||
fi
|
||||
|
||||
# Default clang-format points to default 3.5 version one
|
||||
CLANG_FORMAT=clang-format-18
|
||||
CLANG_FORMAT=clang-format-19
|
||||
$CLANG_FORMAT --version
|
||||
|
||||
if [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then
|
||||
|
|
76
.github/ISSUE_TEMPLATE/app-bug-report.yaml
vendored
Normal file
76
.github/ISSUE_TEMPLATE/app-bug-report.yaml
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Docs - https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
|
||||
name: Application Bug Report
|
||||
description: Problem with the application itself (ie. bad file path handling, UX issue)
|
||||
title: "[APP BUG]: "
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Important: Read First
|
||||
|
||||
**Please do not make support requests on GitHub. Our issue tracker is for tracking bugs and feature requests only.
|
||||
If you have a support request or are unsure about the nature of your issue please contact us on [discord](https://discord.gg/bFJxfftGW6).**
|
||||
|
||||
Please make an effort to make sure your issue isn't already reported.
|
||||
|
||||
Do not create issues involving software piracy, our rules specifically prohibit this. Otherwise your issue will be closed and you will be banned in this repository.
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Checklist
|
||||
options:
|
||||
- label: I have searched for a similar issue in this repository and did not find one.
|
||||
required: true
|
||||
- label: I am using an official build obtained from [releases](https://github.com/shadps4-emu/shadPS4/releases) or updated one of those builds using its in-app updater.
|
||||
required: true
|
||||
- type: textarea
|
||||
id: desc
|
||||
attributes:
|
||||
label: Describe the Bug
|
||||
description: "A clear and concise description of what the bug is"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: repro
|
||||
attributes:
|
||||
label: Reproduction Steps
|
||||
description: "Detailed steps to reproduce the behavior"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: "A clear and concise description of what you expected to happen"
|
||||
validations:
|
||||
required: false
|
||||
- type: input
|
||||
id: os
|
||||
attributes:
|
||||
label: Specify OS Version
|
||||
placeholder: "Example: Windows 11, Arch Linux, MacOS 15"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: cpu
|
||||
attributes:
|
||||
label: CPU
|
||||
placeholder: "Example: Intel Core i7-8700"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: gpu
|
||||
attributes:
|
||||
label: GPU
|
||||
placeholder: "Example: nVidia GTX 1650"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: ram
|
||||
attributes:
|
||||
label: Amount of RAM in GB
|
||||
placeholder: "Example: 16 GB"
|
||||
validations:
|
||||
required: true
|
10
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
10
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Discord
|
||||
url: https://discord.gg/bFJxfftGW6
|
||||
about: Get direct support and hang out with us
|
||||
- name: Wiki
|
||||
url: https://github.com/shadps4-emu/shadPS4/wiki
|
||||
about: Information, guides, etc.
|
54
.github/ISSUE_TEMPLATE/feature-request.yaml
vendored
Normal file
54
.github/ISSUE_TEMPLATE/feature-request.yaml
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Docs - https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
|
||||
name: Feature Request
|
||||
description: Suggest a new feature or improve an existing one
|
||||
title: "[Feature Request]: "
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Important: Read First
|
||||
|
||||
Please make an effort to make sure your issue isn't already reported.
|
||||
|
||||
Do not create issues involving software piracy, our rules specifically prohibit this. Otherwise your issue will be closed and you will be banned in this repository.
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Checklist
|
||||
options:
|
||||
- label: I have searched for a similar issue in this repository and did not find one.
|
||||
required: true
|
||||
- type: textarea
|
||||
id: desc
|
||||
attributes:
|
||||
label: Description
|
||||
description: |
|
||||
A concise description of the feature you want
|
||||
|
||||
Include step by step examples of how the feature should work under various circumstances
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: reason
|
||||
attributes:
|
||||
label: Reason
|
||||
description: |
|
||||
Give a reason why you want this feature
|
||||
- How will it make things easier for you?
|
||||
- How does this feature help your enjoyment of the emulator?
|
||||
- What does it provide that isn't being provided currently?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: examples
|
||||
attributes:
|
||||
label: Examples
|
||||
description: |
|
||||
Provide examples of the feature as implemented by other software
|
||||
|
||||
Include screenshots or video if you like to help demonstrate how you'd like this feature to work
|
||||
validations:
|
||||
required: false
|
95
.github/ISSUE_TEMPLATE/game-bug-report.yaml
vendored
Normal file
95
.github/ISSUE_TEMPLATE/game-bug-report.yaml
vendored
Normal file
|
@ -0,0 +1,95 @@
|
|||
# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Docs - https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
|
||||
name: Game Emulation Bug Report
|
||||
description: Problem in a game (ie. graphical artifacts, crashes, etc.)
|
||||
title: "[GAME BUG]: "
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## Important: Read First
|
||||
|
||||
**Please do not make support requests on GitHub. Our issue tracker is for tracking bugs and feature requests only.
|
||||
If you have a support request or are unsure about the nature of your issue please contact us on [discord](https://discord.gg/bFJxfftGW6).**
|
||||
|
||||
This repository does not provide support for modded games. You should perform and test a clean game installation before submitting an issue.
|
||||
|
||||
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.
|
||||
|
||||
Please make an effort to make sure your issue isn't already reported.
|
||||
|
||||
Do not create issues involving software piracy, our rules specifically prohibit this. Otherwise your issue will be closed and you will be banned in this repository.
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Checklist (we expect you to perform these steps before opening the issue)
|
||||
options:
|
||||
- label: I have searched for a similar issue in this repository and did not find one.
|
||||
required: true
|
||||
- label: I am using an official build obtained from [releases](https://github.com/shadps4-emu/shadPS4/releases) or updated one of those builds using its in-app updater.
|
||||
required: true
|
||||
- label: I have re-dumped the game and performed a clean install without mods and the issue is still present.
|
||||
required: true
|
||||
- label: I have disabled all patches and cheats and the issue is still present.
|
||||
required: true
|
||||
- label: I have all the required [system modules](https://github.com/shadps4-emu/shadps4-game-compatibility?tab=readme-ov-file#informations) installed.
|
||||
required: true
|
||||
- type: textarea
|
||||
id: desc
|
||||
attributes:
|
||||
label: Describe the Bug
|
||||
description: "A clear and concise description of what the bug is"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: repro
|
||||
attributes:
|
||||
label: Reproduction Steps
|
||||
description: "Detailed steps to reproduce the behavior"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: os
|
||||
attributes:
|
||||
label: Specify OS Version
|
||||
placeholder: "Example: Windows 11, Arch Linux, MacOS 15"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: cpu
|
||||
attributes:
|
||||
label: CPU
|
||||
placeholder: "Example: Intel Core i7-8700"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: gpu
|
||||
attributes:
|
||||
label: GPU
|
||||
placeholder: "Example: nVidia GTX 1650"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: ram
|
||||
attributes:
|
||||
label: Amount of RAM in GB
|
||||
placeholder: "Example: 16 GB"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: vram
|
||||
attributes:
|
||||
label: Amount of VRAM in GB
|
||||
placeholder: "Example: 8 GB"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: "Log File"
|
||||
description: Drag and drop the log file here. It can be found by right clicking on a game name -> Open Folder... -> Open Log Folder. Make sure that the log type is set to `sync`.
|
||||
validations:
|
||||
required: true
|
128
.github/workflows/build.yml
vendored
128
.github/workflows/build.yml
vendored
|
@ -14,14 +14,14 @@ env:
|
|||
|
||||
jobs:
|
||||
reuse:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: fsfe/reuse-action@v5
|
||||
|
||||
clang-format:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
@ -30,16 +30,16 @@ jobs:
|
|||
- name: Install
|
||||
run: |
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo add-apt-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-18 main'
|
||||
sudo add-apt-repository 'deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main'
|
||||
sudo apt update
|
||||
sudo apt install clang-format-18
|
||||
sudo apt install clang-format-19
|
||||
- name: Build
|
||||
env:
|
||||
COMMIT_RANGE: ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}
|
||||
run: ./.ci/clang-format.sh
|
||||
|
||||
get-info:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
date: ${{ steps.vars.outputs.date }}
|
||||
shorthash: ${{ steps.vars.outputs.shorthash }}
|
||||
|
@ -57,7 +57,7 @@ jobs:
|
|||
echo "fullhash=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
|
||||
|
||||
windows-sdl:
|
||||
runs-on: windows-latest
|
||||
runs-on: windows-2025
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
@ -76,7 +76,7 @@ jobs:
|
|||
${{ env.cache-name }}-
|
||||
|
||||
- name: Cache CMake Build
|
||||
uses: hendrikmuhs/ccache-action@v1.2.14
|
||||
uses: hendrikmuhs/ccache-action@v1.2.17
|
||||
env:
|
||||
cache-name: ${{ runner.os }}-sdl-cache-cmake-build
|
||||
with:
|
||||
|
@ -101,7 +101,7 @@ jobs:
|
|||
path: ${{github.workspace}}/build/shadPS4.exe
|
||||
|
||||
windows-qt:
|
||||
runs-on: windows-latest
|
||||
runs-on: windows-2025
|
||||
needs: get-info
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
@ -111,10 +111,10 @@ jobs:
|
|||
- name: Setup Qt
|
||||
uses: jurplel/install-qt-action@v4
|
||||
with:
|
||||
version: 6.7.3
|
||||
version: 6.9.0
|
||||
host: windows
|
||||
target: desktop
|
||||
arch: win64_msvc2019_64
|
||||
arch: win64_msvc2022_64
|
||||
archives: qtbase qttools
|
||||
modules: qtmultimedia
|
||||
|
||||
|
@ -130,7 +130,7 @@ jobs:
|
|||
${{ env.cache-name }}-
|
||||
|
||||
- name: Cache CMake Build
|
||||
uses: hendrikmuhs/ccache-action@v1.2.14
|
||||
uses: hendrikmuhs/ccache-action@v1.2.17
|
||||
env:
|
||||
cache-name: ${{ runner.os }}-qt-cache-cmake-build
|
||||
with:
|
||||
|
@ -186,7 +186,7 @@ jobs:
|
|||
${{ env.cache-name }}-
|
||||
|
||||
- name: Cache CMake Build
|
||||
uses: hendrikmuhs/ccache-action@v1.2.14
|
||||
uses: hendrikmuhs/ccache-action@v1.2.17
|
||||
env:
|
||||
cache-name: ${{runner.os}}-sdl-cache-cmake-build
|
||||
with:
|
||||
|
@ -205,12 +205,12 @@ jobs:
|
|||
run: |
|
||||
mkdir upload
|
||||
mv ${{github.workspace}}/build/shadps4 upload
|
||||
cp ${{github.workspace}}/build/externals/MoltenVK/libMoltenVK.dylib upload
|
||||
tar cf shadps4-macos-sdl.tar.gz -C upload .
|
||||
mv ${{github.workspace}}/build/MoltenVK_icd.json upload
|
||||
mv ${{github.workspace}}/build/libMoltenVK.dylib upload
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: shadps4-macos-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}
|
||||
path: shadps4-macos-sdl.tar.gz
|
||||
path: upload/
|
||||
|
||||
macos-qt:
|
||||
runs-on: macos-15
|
||||
|
@ -228,7 +228,7 @@ jobs:
|
|||
- name: Setup Qt
|
||||
uses: jurplel/install-qt-action@v4
|
||||
with:
|
||||
version: 6.7.3
|
||||
version: 6.9.0
|
||||
host: mac
|
||||
target: desktop
|
||||
arch: clang_64
|
||||
|
@ -247,7 +247,7 @@ jobs:
|
|||
${{ env.cache-name }}-
|
||||
|
||||
- name: Cache CMake Build
|
||||
uses: hendrikmuhs/ccache-action@v1.2.14
|
||||
uses: hendrikmuhs/ccache-action@v1.2.17
|
||||
env:
|
||||
cache-name: ${{runner.os}}-qt-cache-cmake-build
|
||||
with:
|
||||
|
@ -281,8 +281,13 @@ jobs:
|
|||
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 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
|
||||
|
||||
- name: Cache CMake Configuration
|
||||
uses: actions/cache@v4
|
||||
|
@ -296,7 +301,7 @@ jobs:
|
|||
${{ env.cache-name }}-
|
||||
|
||||
- name: Cache CMake Build
|
||||
uses: hendrikmuhs/ccache-action@v1.2.14
|
||||
uses: hendrikmuhs/ccache-action@v1.2.17
|
||||
env:
|
||||
cache-name: ${{ runner.os }}-sdl-cache-cmake-build
|
||||
with:
|
||||
|
@ -304,7 +309,7 @@ jobs:
|
|||
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 -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=clang-19 -DCMAKE_CXX_COMPILER=clang++-19 -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=mold" -DCMAKE_SHARED_LINKER_FLAGS="-fuse-ld=mold" -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
|
||||
- name: Build
|
||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(nproc)
|
||||
|
@ -337,8 +342,13 @@ jobs:
|
|||
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 build-essential qt6-base-dev qt6-tools-dev qt6-multimedia-dev 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 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
|
||||
|
@ -352,7 +362,7 @@ jobs:
|
|||
${{ env.cache-name }}-
|
||||
|
||||
- name: Cache CMake Build
|
||||
uses: hendrikmuhs/ccache-action@v1.2.14
|
||||
uses: hendrikmuhs/ccache-action@v1.2.17
|
||||
env:
|
||||
cache-name: ${{ runner.os }}-qt-cache-cmake-build
|
||||
with:
|
||||
|
@ -360,7 +370,7 @@ jobs:
|
|||
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 -DCMAKE_CXX_COMPILER=clang++ -DENABLE_QT_GUI=ON -DENABLE_UPDATER=ON -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=clang-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)
|
||||
|
@ -376,6 +386,78 @@ jobs:
|
|||
name: shadps4-linux-qt-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}
|
||||
path: Shadps4-qt.AppImage
|
||||
|
||||
linux-sdl-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 libasound2-dev libpulse-dev libopenal-dev libudev-dev
|
||||
|
||||
- name: Cache CMake Configuration
|
||||
uses: actions/cache@v4
|
||||
env:
|
||||
cache-name: ${{ runner.os }}-sdl-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 }}-sdl-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" -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
|
||||
- name: Build
|
||||
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:
|
||||
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]
|
||||
|
|
11
.github/workflows/scripts/update_translation.sh
vendored
Executable file
11
.github/workflows/scripts/update_translation.sh
vendored
Executable file
|
@ -0,0 +1,11 @@
|
|||
#!/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
Normal file
30
.github/workflows/update_translation.yml
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
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
|
15
.gitmodules
vendored
15
.gitmodules
vendored
|
@ -1,15 +1,3 @@
|
|||
[submodule "externals/cryptopp-cmake"]
|
||||
path = externals/cryptopp-cmake
|
||||
url = https://github.com/shadps4-emu/ext-cryptopp-cmake.git
|
||||
shallow = true
|
||||
[submodule "externals/cryptopp"]
|
||||
path = externals/cryptopp
|
||||
url = https://github.com/shadps4-emu/ext-cryptopp.git
|
||||
shallow = true
|
||||
[submodule "externals/cryptoppwin"]
|
||||
path = externals/cryptoppwin
|
||||
url = https://github.com/shadps4-emu/ext-cryptoppwin.git
|
||||
shallow = true
|
||||
[submodule "externals/zlib-ng"]
|
||||
path = externals/zlib-ng
|
||||
url = https://github.com/shadps4-emu/ext-zlib-ng.git
|
||||
|
@ -119,3 +107,6 @@
|
|||
path = externals/MoltenVK/cereal
|
||||
url = https://github.com/USCiLab/cereal
|
||||
shallow = true
|
||||
[submodule "externals/libusb"]
|
||||
path = externals/libusb
|
||||
url = https://github.com/libusb/libusb-cmake.git
|
||||
|
|
331
CMakeLists.txt
331
CMakeLists.txt
|
@ -8,15 +8,16 @@ set(CMAKE_CXX_STANDARD 23)
|
|||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
if(APPLE)
|
||||
enable_language(OBJC)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 14)
|
||||
list(APPEND ADDITIONAL_LANGUAGES OBJC)
|
||||
# Starting with 15.4, Rosetta 2 has support for all the necessary instruction sets.
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 15.4 CACHE STRING "")
|
||||
endif()
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
endif()
|
||||
|
||||
project(shadPS4 CXX C ASM)
|
||||
project(shadPS4 CXX C ASM ${ADDITIONAL_LANGUAGES})
|
||||
|
||||
# Forcing PIE makes sure that the base address is high enough so that it doesn't clash with the PS4 memory.
|
||||
if(UNIX AND NOT APPLE)
|
||||
|
@ -37,8 +38,10 @@ option(ENABLE_UPDATER "Enables the options to updater" ON)
|
|||
# First, determine whether to use CMAKE_OSX_ARCHITECTURES or CMAKE_SYSTEM_PROCESSOR.
|
||||
if (APPLE AND CMAKE_OSX_ARCHITECTURES)
|
||||
set(BASE_ARCHITECTURE "${CMAKE_OSX_ARCHITECTURES}")
|
||||
else()
|
||||
elseif (CMAKE_SYSTEM_PROCESSOR)
|
||||
set(BASE_ARCHITECTURE "${CMAKE_SYSTEM_PROCESSOR}")
|
||||
else()
|
||||
set(BASE_ARCHITECTURE "${CMAKE_HOST_SYSTEM_PROCESSOR}")
|
||||
endif()
|
||||
|
||||
# Next, match common architecture strings down to a known common value.
|
||||
|
@ -50,7 +53,13 @@ else()
|
|||
message(FATAL_ERROR "Unsupported CPU architecture: ${BASE_ARCHITECTURE}")
|
||||
endif()
|
||||
|
||||
if (APPLE AND ARCHITECTURE STREQUAL "x86_64" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
|
||||
if (ARCHITECTURE STREQUAL "x86_64")
|
||||
# Target the same CPU architecture as the PS4, to maintain the same level of compatibility.
|
||||
# Exclude SSE4a as it is only available on AMD CPUs.
|
||||
add_compile_options(-march=btver2 -mtune=generic -mno-sse4a)
|
||||
endif()
|
||||
|
||||
if (APPLE AND ARCHITECTURE STREQUAL "x86_64" AND CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "arm64")
|
||||
# Exclude ARM homebrew path to avoid conflicts when cross compiling.
|
||||
list(APPEND CMAKE_IGNORE_PREFIX_PATH "/opt/homebrew")
|
||||
|
||||
|
@ -96,18 +105,115 @@ if (CLANG_FORMAT)
|
|||
unset(CCOMMENT)
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
# generate git revision information
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules/")
|
||||
include(GetGitRevisionDescription)
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules/GetGitRevisionDescription.cmake")
|
||||
get_git_head_revision(GIT_REF_SPEC GIT_REV)
|
||||
git_describe(GIT_DESC --always --long --dirty)
|
||||
git_branch_name(GIT_BRANCH)
|
||||
string(TIMESTAMP BUILD_DATE "%Y-%m-%d %H:%M:%S")
|
||||
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp" @ONLY)
|
||||
message("start git things")
|
||||
|
||||
# Try to get the upstream remote and branch
|
||||
message("check for remote and branch")
|
||||
execute_process(
|
||||
COMMAND git rev-parse --abbrev-ref --symbolic-full-name @{u}
|
||||
OUTPUT_VARIABLE GIT_REMOTE_NAME
|
||||
RESULT_VARIABLE GIT_REMOTE_RESULT
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
# If there's no upstream set or the command failed, check remote.pushDefault
|
||||
if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
|
||||
message("check default push")
|
||||
execute_process(
|
||||
COMMAND git config --get remote.pushDefault
|
||||
OUTPUT_VARIABLE GIT_REMOTE_NAME
|
||||
RESULT_VARIABLE GIT_REMOTE_RESULT
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
endif()
|
||||
|
||||
# If running in GitHub Actions and the above fails
|
||||
if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
|
||||
message("check github")
|
||||
set(GIT_REMOTE_NAME "origin")
|
||||
|
||||
# Retrieve environment variables
|
||||
if (DEFINED ENV{GITHUB_HEAD_REF} AND NOT "$ENV{GITHUB_HEAD_REF}" STREQUAL "")
|
||||
message("github head ref: $ENV{GITHUB_HEAD_REF}")
|
||||
set(GITHUB_HEAD_REF "$ENV{GITHUB_HEAD_REF}")
|
||||
else()
|
||||
set(GITHUB_HEAD_REF "")
|
||||
endif()
|
||||
|
||||
if (DEFINED ENV{GITHUB_REF} AND NOT "$ENV{GITHUB_REF}" STREQUAL "")
|
||||
message("github ref: $ENV{GITHUB_REF}")
|
||||
string(REGEX REPLACE "^refs/[^/]*/" "" GITHUB_BRANCH "$ENV{GITHUB_REF}")
|
||||
string(REGEX MATCH "refs/pull/([0-9]+)/merge" MATCHED_REF "$ENV{GITHUB_REF}")
|
||||
if (MATCHED_REF)
|
||||
set(PR_NUMBER "${CMAKE_MATCH_1}")
|
||||
set(GITHUB_BRANCH "")
|
||||
message("PR number: ${PR_NUMBER}")
|
||||
else()
|
||||
set(PR_NUMBER "")
|
||||
endif()
|
||||
else()
|
||||
set(GITHUB_BRANCH "")
|
||||
set(PR_NUMBER "")
|
||||
endif()
|
||||
|
||||
if (NOT "${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_HEAD_REF}" STREQUAL "")
|
||||
set(GIT_BRANCH "pr-${PR_NUMBER}-${GITHUB_HEAD_REF}")
|
||||
elseif (NOT "${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_BRANCH}" STREQUAL "")
|
||||
set(GIT_BRANCH "pr-${PR_NUMBER}-${GITHUB_BRANCH}")
|
||||
elseif (NOT "${PR_NUMBER}" STREQUAL "")
|
||||
set(GIT_BRANCH "pr-${PR_NUMBER}")
|
||||
elseif ("${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_HEAD_REF}" STREQUAL "")
|
||||
set(GIT_BRANCH "${GITHUB_HEAD_REF}")
|
||||
elseif ("${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_BRANCH}" STREQUAL "")
|
||||
set(GIT_BRANCH "${GITHUB_BRANCH}")
|
||||
elseif ("${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_REF}" STREQUAL "")
|
||||
set(GIT_BRANCH "${GITHUB_REF}")
|
||||
else()
|
||||
message("couldn't find branch")
|
||||
set(GIT_BRANCH "detached-head")
|
||||
endif()
|
||||
else()
|
||||
# Extract remote name if the output contains a remote/branch format
|
||||
string(FIND "${GIT_REMOTE_NAME}" "/" INDEX)
|
||||
if (INDEX GREATER -1)
|
||||
string(SUBSTRING "${GIT_REMOTE_NAME}" 0 "${INDEX}" GIT_REMOTE_NAME)
|
||||
else()
|
||||
# If no remote is present (only a branch name), default to origin
|
||||
set(GIT_REMOTE_NAME "origin")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Get remote link
|
||||
message("getting remote link")
|
||||
execute_process(
|
||||
COMMAND git config --get remote.${GIT_REMOTE_NAME}.url
|
||||
OUTPUT_VARIABLE GIT_REMOTE_URL
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
# Set Version
|
||||
set(EMULATOR_VERSION_MAJOR "0")
|
||||
set(EMULATOR_VERSION_MINOR "8")
|
||||
set(EMULATOR_VERSION_PATCH "1")
|
||||
|
||||
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} WIP")
|
||||
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)
|
||||
|
||||
message("end git things, remote: ${GIT_REMOTE_NAME}, branch: ${GIT_BRANCH}")
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
find_package(Boost 1.84.0 CONFIG)
|
||||
find_package(FFmpeg 5.1.2 MODULE)
|
||||
find_package(fmt 10.2.0 CONFIG)
|
||||
|
@ -120,21 +226,18 @@ find_package(SDL3 3.1.2 CONFIG)
|
|||
find_package(stb MODULE)
|
||||
find_package(toml11 4.2.0 CONFIG)
|
||||
find_package(tsl-robin-map 1.3.0 CONFIG)
|
||||
find_package(VulkanHeaders 1.4.303 CONFIG)
|
||||
find_package(VulkanHeaders 1.4.309 CONFIG)
|
||||
find_package(VulkanMemoryAllocator 3.1.0 CONFIG)
|
||||
find_package(xbyak 7.07 CONFIG)
|
||||
find_package(xxHash 0.8.2 MODULE)
|
||||
find_package(ZLIB 1.3 MODULE)
|
||||
find_package(Zydis 5.0.0 CONFIG)
|
||||
find_package(pugixml 1.14 CONFIG)
|
||||
|
||||
if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR NOT MSVC)
|
||||
find_package(cryptopp 8.9.0 MODULE)
|
||||
endif()
|
||||
|
||||
find_package(libusb 1.0.27 MODULE)
|
||||
if (APPLE)
|
||||
find_package(date 3.0.1 CONFIG)
|
||||
endif()
|
||||
list(POP_BACK CMAKE_MODULE_PATH)
|
||||
|
||||
# Note: Windows always has these functions through winpthreads
|
||||
include(CheckSymbolExists)
|
||||
|
@ -154,6 +257,7 @@ endif()
|
|||
|
||||
add_subdirectory(externals)
|
||||
include_directories(src)
|
||||
include_directories(Resources)
|
||||
|
||||
if(ENABLE_QT_GUI)
|
||||
find_package(Qt6 REQUIRED COMPONENTS Widgets Concurrent LinguistTools Network Multimedia)
|
||||
|
@ -188,6 +292,8 @@ set(AJM_LIB src/core/libraries/ajm/ajm.cpp
|
|||
src/core/libraries/ajm/ajm_context.cpp
|
||||
src/core/libraries/ajm/ajm_context.h
|
||||
src/core/libraries/ajm/ajm_error.h
|
||||
src/core/libraries/ajm/ajm_instance_statistics.cpp
|
||||
src/core/libraries/ajm/ajm_instance_statistics.h
|
||||
src/core/libraries/ajm/ajm_instance.cpp
|
||||
src/core/libraries/ajm/ajm_instance.h
|
||||
src/core/libraries/ajm/ajm_mp3.cpp
|
||||
|
@ -198,15 +304,16 @@ set(AUDIO_LIB src/core/libraries/audio/audioin.cpp
|
|||
src/core/libraries/audio/audioin.h
|
||||
src/core/libraries/audio/audioout.cpp
|
||||
src/core/libraries/audio/audioout.h
|
||||
src/core/libraries/audio/sdl_audio.cpp
|
||||
src/core/libraries/audio/sdl_audio.h
|
||||
src/core/libraries/audio/audioout_backend.h
|
||||
src/core/libraries/audio/audioout_error.h
|
||||
src/core/libraries/audio/sdl_audio.cpp
|
||||
src/core/libraries/ngs2/ngs2.cpp
|
||||
src/core/libraries/ngs2/ngs2.h
|
||||
)
|
||||
|
||||
set(GNM_LIB src/core/libraries/gnmdriver/gnmdriver.cpp
|
||||
src/core/libraries/gnmdriver/gnmdriver.h
|
||||
src/core/libraries/gnmdriver/gnmdriver_init.h
|
||||
src/core/libraries/gnmdriver/gnm_error.h
|
||||
)
|
||||
|
||||
|
@ -233,6 +340,8 @@ set(KERNEL_LIB src/core/libraries/kernel/sync/mutex.cpp
|
|||
src/core/libraries/kernel/threads/thread_state.h
|
||||
src/core/libraries/kernel/process.cpp
|
||||
src/core/libraries/kernel/process.h
|
||||
src/core/libraries/kernel/debug.cpp
|
||||
src/core/libraries/kernel/debug.h
|
||||
src/core/libraries/kernel/equeue.cpp
|
||||
src/core/libraries/kernel/equeue.h
|
||||
src/core/libraries/kernel/file_system.cpp
|
||||
|
@ -247,10 +356,15 @@ set(KERNEL_LIB src/core/libraries/kernel/sync/mutex.cpp
|
|||
src/core/libraries/kernel/time.h
|
||||
src/core/libraries/kernel/orbis_error.h
|
||||
src/core/libraries/kernel/posix_error.h
|
||||
src/core/libraries/kernel/aio.cpp
|
||||
src/core/libraries/kernel/aio.h
|
||||
)
|
||||
|
||||
set(NETWORK_LIBS src/core/libraries/network/http.cpp
|
||||
src/core/libraries/network/http.h
|
||||
src/core/libraries/network/http_error.h
|
||||
src/core/libraries/network/http2.cpp
|
||||
src/core/libraries/network/http2.h
|
||||
src/core/libraries/network/net.cpp
|
||||
src/core/libraries/network/netctl.cpp
|
||||
src/core/libraries/network/netctl.h
|
||||
|
@ -260,6 +374,8 @@ set(NETWORK_LIBS src/core/libraries/network/http.cpp
|
|||
src/core/libraries/network/net.h
|
||||
src/core/libraries/network/ssl.cpp
|
||||
src/core/libraries/network/ssl.h
|
||||
src/core/libraries/network/ssl2.cpp
|
||||
src/core/libraries/network/ssl2.h
|
||||
)
|
||||
|
||||
set(AVPLAYER_LIB src/core/libraries/avplayer/avplayer_common.cpp
|
||||
|
@ -319,12 +435,28 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp
|
|||
src/core/libraries/ngs2/ngs2_error.h
|
||||
src/core/libraries/ngs2/ngs2_impl.cpp
|
||||
src/core/libraries/ngs2/ngs2_impl.h
|
||||
src/core/libraries/ngs2/ngs2_custom.cpp
|
||||
src/core/libraries/ngs2/ngs2_custom.h
|
||||
src/core/libraries/ngs2/ngs2_reverb.cpp
|
||||
src/core/libraries/ngs2/ngs2_reverb.h
|
||||
src/core/libraries/ngs2/ngs2_geom.cpp
|
||||
src/core/libraries/ngs2/ngs2_geom.h
|
||||
src/core/libraries/ngs2/ngs2_pan.cpp
|
||||
src/core/libraries/ngs2/ngs2_pan.h
|
||||
src/core/libraries/ngs2/ngs2_report.cpp
|
||||
src/core/libraries/ngs2/ngs2_report.h
|
||||
src/core/libraries/ngs2/ngs2_eq.cpp
|
||||
src/core/libraries/ngs2/ngs2_eq.h
|
||||
src/core/libraries/ngs2/ngs2_mastering.cpp
|
||||
src/core/libraries/ngs2/ngs2_mastering.h
|
||||
src/core/libraries/ngs2/ngs2_sampler.cpp
|
||||
src/core/libraries/ngs2/ngs2_sampler.h
|
||||
src/core/libraries/ngs2/ngs2_submixer.cpp
|
||||
src/core/libraries/ngs2/ngs2_submixer.h
|
||||
src/core/libraries/ajm/ajm_error.h
|
||||
src/core/libraries/audio3d/audio3d.cpp
|
||||
src/core/libraries/audio3d/audio3d.h
|
||||
src/core/libraries/audio3d/audio3d_error.h
|
||||
src/core/libraries/audio3d/audio3d_impl.cpp
|
||||
src/core/libraries/audio3d/audio3d_impl.h
|
||||
src/core/libraries/game_live_streaming/gamelivestreaming.cpp
|
||||
src/core/libraries/game_live_streaming/gamelivestreaming.h
|
||||
src/core/libraries/remote_play/remoteplay.cpp
|
||||
|
@ -333,6 +465,10 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp
|
|||
src/core/libraries/share_play/shareplay.h
|
||||
src/core/libraries/razor_cpu/razor_cpu.cpp
|
||||
src/core/libraries/razor_cpu/razor_cpu.h
|
||||
src/core/libraries/mouse/mouse.cpp
|
||||
src/core/libraries/mouse/mouse.h
|
||||
src/core/libraries/web_browser_dialog/webbrowserdialog.cpp
|
||||
src/core/libraries/web_browser_dialog/webbrowserdialog.h
|
||||
)
|
||||
|
||||
set(VIDEOOUT_LIB src/core/libraries/videoout/buffer.h
|
||||
|
@ -343,8 +479,17 @@ set(VIDEOOUT_LIB src/core/libraries/videoout/buffer.h
|
|||
src/core/libraries/videoout/videoout_error.h
|
||||
)
|
||||
|
||||
set(LIBC_SOURCES src/core/libraries/libc_internal/libc_internal.cpp
|
||||
set(HLE_LIBC_INTERNAL_LIB src/core/libraries/libc_internal/libc_internal.cpp
|
||||
src/core/libraries/libc_internal/libc_internal.h
|
||||
src/core/libraries/libc_internal/libc_internal_io.cpp
|
||||
src/core/libraries/libc_internal/libc_internal_io.h
|
||||
src/core/libraries/libc_internal/libc_internal_memory.cpp
|
||||
src/core/libraries/libc_internal/libc_internal_memory.h
|
||||
src/core/libraries/libc_internal/libc_internal_str.cpp
|
||||
src/core/libraries/libc_internal/libc_internal_str.h
|
||||
src/core/libraries/libc_internal/libc_internal_math.cpp
|
||||
src/core/libraries/libc_internal/libc_internal_math.h
|
||||
src/core/libraries/libc_internal/printf.h
|
||||
)
|
||||
|
||||
set(IME_LIB src/core/libraries/ime/error_dialog.cpp
|
||||
|
@ -410,7 +555,9 @@ set(VDEC_LIB src/core/libraries/videodec/videodec2_impl.cpp
|
|||
src/core/libraries/videodec/videodec_impl.h
|
||||
)
|
||||
|
||||
set(NP_LIBS src/core/libraries/np_manager/np_manager.cpp
|
||||
set(NP_LIBS src/core/libraries/np_common/np_common.cpp
|
||||
src/core/libraries/np_common/np_common.h
|
||||
src/core/libraries/np_manager/np_manager.cpp
|
||||
src/core/libraries/np_manager/np_manager.h
|
||||
src/core/libraries/np_score/np_score.cpp
|
||||
src/core/libraries/np_score/np_score.h
|
||||
|
@ -419,10 +566,29 @@ set(NP_LIBS src/core/libraries/np_manager/np_manager.cpp
|
|||
src/core/libraries/np_trophy/trophy_ui.cpp
|
||||
src/core/libraries/np_trophy/trophy_ui.h
|
||||
src/core/libraries/np_trophy/np_trophy_error.h
|
||||
src/core/libraries/np_web_api/np_web_api.cpp
|
||||
src/core/libraries/np_web_api/np_web_api.h
|
||||
src/core/libraries/np_party/np_party.cpp
|
||||
src/core/libraries/np_party/np_party.h
|
||||
src/core/libraries/np_auth/np_auth.cpp
|
||||
src/core/libraries/np_auth/np_auth.h
|
||||
)
|
||||
|
||||
set(ZLIB_LIB src/core/libraries/zlib/zlib.cpp
|
||||
src/core/libraries/zlib/zlib_sce.h
|
||||
src/core/libraries/zlib/zlib_error.h
|
||||
)
|
||||
|
||||
set(VR_LIBS src/core/libraries/hmd/hmd.cpp
|
||||
src/core/libraries/hmd/hmd.h
|
||||
)
|
||||
|
||||
set(MISC_LIBS src/core/libraries/screenshot/screenshot.cpp
|
||||
src/core/libraries/screenshot/screenshot.h
|
||||
src/core/libraries/move/move.cpp
|
||||
src/core/libraries/move/move.h
|
||||
src/core/libraries/ulobjmgr/ulobjmgr.cpp
|
||||
src/core/libraries/ulobjmgr/ulobjmgr.h
|
||||
)
|
||||
|
||||
set(DEV_TOOLS src/core/devtools/layer.cpp
|
||||
|
@ -462,6 +628,7 @@ set(COMMON src/common/logging/backend.cpp
|
|||
src/common/logging/text_formatter.cpp
|
||||
src/common/logging/text_formatter.h
|
||||
src/common/logging/types.h
|
||||
src/common/aes.h
|
||||
src/common/alignment.h
|
||||
src/common/arch.h
|
||||
src/common/assert.cpp
|
||||
|
@ -493,6 +660,7 @@ set(COMMON src/common/logging/backend.cpp
|
|||
src/common/polyfill_thread.h
|
||||
src/common/rdtsc.cpp
|
||||
src/common/rdtsc.h
|
||||
src/common/sha1.h
|
||||
src/common/signal_context.h
|
||||
src/common/signal_context.cpp
|
||||
src/common/singleton.h
|
||||
|
@ -502,6 +670,7 @@ set(COMMON src/common/logging/backend.cpp
|
|||
src/common/spin_lock.h
|
||||
src/common/stb.cpp
|
||||
src/common/stb.h
|
||||
src/common/string_literal.h
|
||||
src/common/string_util.cpp
|
||||
src/common/string_util.h
|
||||
src/common/thread.cpp
|
||||
|
@ -510,14 +679,13 @@ set(COMMON src/common/logging/backend.cpp
|
|||
src/common/uint128.h
|
||||
src/common/unique_function.h
|
||||
src/common/va_ctx.h
|
||||
src/common/version.h
|
||||
src/common/ntapi.h
|
||||
src/common/ntapi.cpp
|
||||
src/common/number_utils.h
|
||||
src/common/number_utils.cpp
|
||||
src/common/memory_patcher.h
|
||||
src/common/memory_patcher.cpp
|
||||
src/common/scm_rev.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/src/common/scm_rev.cpp
|
||||
src/common/scm_rev.h
|
||||
)
|
||||
|
||||
|
@ -531,32 +699,31 @@ set(CORE src/core/aerolib/stubs.cpp
|
|||
src/core/aerolib/aerolib.h
|
||||
src/core/address_space.cpp
|
||||
src/core/address_space.h
|
||||
src/core/crypto/crypto.cpp
|
||||
src/core/crypto/crypto.h
|
||||
src/core/crypto/keys.h
|
||||
src/core/devices/base_device.cpp
|
||||
src/core/devices/base_device.h
|
||||
src/core/devices/ioccom.h
|
||||
src/core/devices/logger.cpp
|
||||
src/core/devices/logger.h
|
||||
src/core/devices/nop_device.h
|
||||
src/core/devices/console_device.cpp
|
||||
src/core/devices/console_device.h
|
||||
src/core/devices/deci_tty6_device.cpp
|
||||
src/core/devices/deci_tty6_device.h
|
||||
src/core/devices/random_device.cpp
|
||||
src/core/devices/random_device.h
|
||||
src/core/devices/urandom_device.cpp
|
||||
src/core/devices/urandom_device.h
|
||||
src/core/devices/srandom_device.cpp
|
||||
src/core/devices/srandom_device.h
|
||||
src/core/file_format/pfs.h
|
||||
src/core/file_format/pkg.cpp
|
||||
src/core/file_format/pkg.h
|
||||
src/core/file_format/pkg_type.cpp
|
||||
src/core/file_format/pkg_type.h
|
||||
src/core/file_format/psf.cpp
|
||||
src/core/file_format/psf.h
|
||||
src/core/file_format/playgo_chunk.cpp
|
||||
src/core/file_format/playgo_chunk.h
|
||||
src/core/file_format/trp.cpp
|
||||
src/core/file_format/trp.h
|
||||
src/core/file_format/splash.h
|
||||
src/core/file_format/splash.cpp
|
||||
src/core/file_sys/fs.cpp
|
||||
src/core/file_sys/fs.h
|
||||
src/core/loader.cpp
|
||||
src/core/loader.h
|
||||
src/core/loader/dwarf.cpp
|
||||
src/core/loader/dwarf.h
|
||||
src/core/loader/elf.cpp
|
||||
|
@ -572,7 +739,7 @@ set(CORE src/core/aerolib/stubs.cpp
|
|||
${KERNEL_LIB}
|
||||
${NETWORK_LIBS}
|
||||
${SYSTEM_LIBS}
|
||||
${LIBC_SOURCES}
|
||||
${HLE_LIBC_INTERNAL_LIB}
|
||||
${PAD_LIB}
|
||||
${VIDEOOUT_LIB}
|
||||
${NP_LIBS}
|
||||
|
@ -581,10 +748,12 @@ set(CORE src/core/aerolib/stubs.cpp
|
|||
${PLAYGO_LIB}
|
||||
${RANDOM_LIB}
|
||||
${USBD_LIB}
|
||||
${ZLIB_LIB}
|
||||
${MISC_LIBS}
|
||||
${IME_LIB}
|
||||
${FIBER_LIB}
|
||||
${VDEC_LIB}
|
||||
${VR_LIBS}
|
||||
${DEV_TOOLS}
|
||||
src/core/debug_state.cpp
|
||||
src/core/debug_state.h
|
||||
|
@ -670,11 +839,14 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h
|
|||
src/shader_recompiler/ir/passes/hull_shader_transform.cpp
|
||||
src/shader_recompiler/ir/passes/identity_removal_pass.cpp
|
||||
src/shader_recompiler/ir/passes/ir_passes.h
|
||||
src/shader_recompiler/ir/passes/lower_shared_mem_to_registers.cpp
|
||||
src/shader_recompiler/ir/passes/lower_buffer_format_to_raw.cpp
|
||||
src/shader_recompiler/ir/passes/lower_fp64_to_fp32.cpp
|
||||
src/shader_recompiler/ir/passes/readlane_elimination_pass.cpp
|
||||
src/shader_recompiler/ir/passes/resource_tracking_pass.cpp
|
||||
src/shader_recompiler/ir/passes/ring_access_elimination.cpp
|
||||
src/shader_recompiler/ir/passes/shader_info_collection_pass.cpp
|
||||
src/shader_recompiler/ir/passes/shared_memory_barrier_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/abstract_syntax_list.h
|
||||
src/shader_recompiler/ir/attribute.cpp
|
||||
|
@ -694,6 +866,7 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h
|
|||
src/shader_recompiler/ir/post_order.h
|
||||
src/shader_recompiler/ir/program.cpp
|
||||
src/shader_recompiler/ir/program.h
|
||||
src/shader_recompiler/ir/reinterpret.h
|
||||
src/shader_recompiler/ir/reg.h
|
||||
src/shader_recompiler/ir/type.cpp
|
||||
src/shader_recompiler/ir/type.h
|
||||
|
@ -723,8 +896,6 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp
|
|||
src/video_core/renderer_vulkan/vk_common.h
|
||||
src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
|
||||
src/video_core/renderer_vulkan/vk_compute_pipeline.h
|
||||
src/video_core/renderer_vulkan/vk_descriptor_update_queue.cpp
|
||||
src/video_core/renderer_vulkan/vk_descriptor_update_queue.h
|
||||
src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
|
||||
src/video_core/renderer_vulkan/vk_graphics_pipeline.h
|
||||
src/video_core/renderer_vulkan/vk_instance.cpp
|
||||
|
@ -751,6 +922,10 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp
|
|||
src/video_core/renderer_vulkan/vk_shader_util.h
|
||||
src/video_core/renderer_vulkan/vk_swapchain.cpp
|
||||
src/video_core/renderer_vulkan/vk_swapchain.h
|
||||
src/video_core/renderer_vulkan/host_passes/fsr_pass.cpp
|
||||
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.h
|
||||
src/video_core/texture_cache/image.cpp
|
||||
src/video_core/texture_cache/image.h
|
||||
src/video_core/texture_cache/image_info.cpp
|
||||
|
@ -788,6 +963,10 @@ set(IMGUI src/imgui/imgui_config.h
|
|||
|
||||
set(INPUT src/input/controller.cpp
|
||||
src/input/controller.h
|
||||
src/input/input_handler.cpp
|
||||
src/input/input_handler.h
|
||||
src/input/input_mouse.cpp
|
||||
src/input/input_mouse.h
|
||||
)
|
||||
|
||||
set(EMULATOR src/emulator.cpp
|
||||
|
@ -816,6 +995,12 @@ set(QT_GUI src/qt_gui/about_dialog.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
|
||||
|
@ -829,14 +1014,14 @@ set(QT_GUI src/qt_gui/about_dialog.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/install_dir_select.cpp
|
||||
src/qt_gui/install_dir_select.h
|
||||
src/qt_gui/pkg_viewer.cpp
|
||||
src/qt_gui/pkg_viewer.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
|
||||
|
@ -884,7 +1069,7 @@ endif()
|
|||
create_target_directory_groups(shadps4)
|
||||
|
||||
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui gcn half::half ZLIB::ZLIB PNG::PNG)
|
||||
target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator LibAtrac9 sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::glslang SDL3::SDL3 pugixml::pugixml stb::headers)
|
||||
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_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")
|
||||
|
@ -899,22 +1084,39 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND ENABLE_USERFAULTFD)
|
|||
endif()
|
||||
|
||||
if (APPLE)
|
||||
# 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)
|
||||
# Include MoltenVK in the app bundle, along with an ICD file so it can be found by the system Vulkan loader if used for loading layers.
|
||||
target_sources(shadps4 PRIVATE externals/MoltenVK/MoltenVK_icd.json)
|
||||
set_source_files_properties(externals/MoltenVK/MoltenVK_icd.json
|
||||
PROPERTIES MACOSX_PACKAGE_LOCATION Resources/vulkan/icd.d)
|
||||
add_custom_command(TARGET shadps4 POST_BUILD
|
||||
COMMAND cmake -E copy $<TARGET_LINKER_FILE:MoltenVK> $<TARGET_BUNDLE_DIR:shadps4>/Contents/Frameworks/libMoltenVK.dylib)
|
||||
set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path/../Frameworks")
|
||||
set(MVK_BUNDLE_PATH "Resources/vulkan/icd.d")
|
||||
set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path/../${MVK_BUNDLE_PATH}")
|
||||
set(MVK_DST ${CMAKE_CURRENT_BINARY_DIR}/shadps4.app/Contents/${MVK_BUNDLE_PATH})
|
||||
else()
|
||||
# For non-bundled SDL build, just do a normal library link.
|
||||
target_link_libraries(shadps4 PRIVATE MoltenVK)
|
||||
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_ICD_SRC ${CMAKE_CURRENT_SOURCE_DIR}/externals/MoltenVK/MoltenVK/MoltenVK/icd/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(
|
||||
OUTPUT ${MVK_ICD_DST}
|
||||
DEPENDS ${MVK_ICD_SRC} ${MVK_DST}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${MVK_ICD_SRC} ${MVK_ICD_DST})
|
||||
add_custom_command(
|
||||
OUTPUT ${MVK_DYLIB_DST}
|
||||
DEPENDS ${MVK_DYLIB_SRC} ${MVK_DST}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${MVK_DYLIB_SRC} ${MVK_DYLIB_DST})
|
||||
add_custom_target(CopyMoltenVK DEPENDS ${MVK_ICD_DST} ${MVK_DYLIB_DST})
|
||||
add_dependencies(CopyMoltenVK MoltenVK)
|
||||
add_dependencies(shadps4 CopyMoltenVK)
|
||||
|
||||
if (ARCHITECTURE STREQUAL "x86_64")
|
||||
# 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,GUEST_SYSTEM,0x400000,-image_base,0x20000000000)
|
||||
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)
|
||||
endif()
|
||||
|
||||
# Replacement for std::chrono::time_zone
|
||||
|
@ -925,12 +1127,6 @@ if (NOT ENABLE_QT_GUI)
|
|||
target_link_libraries(shadps4 PRIVATE SDL3::SDL3)
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND MSVC)
|
||||
target_link_libraries(shadps4 PRIVATE cryptoppwin)
|
||||
else()
|
||||
target_link_libraries(shadps4 PRIVATE cryptopp::cryptopp)
|
||||
endif()
|
||||
|
||||
if (ENABLE_QT_GUI)
|
||||
target_link_libraries(shadps4 PRIVATE Qt6::Widgets Qt6::Concurrent Qt6::Network Qt6::Multimedia)
|
||||
add_definitions(-DENABLE_QT_GUI)
|
||||
|
@ -991,6 +1187,18 @@ add_subdirectory(${HOST_SHADERS_INCLUDE})
|
|||
add_dependencies(shadps4 host_shaders)
|
||||
target_include_directories(shadps4 PRIVATE ${HOST_SHADERS_INCLUDE})
|
||||
|
||||
# embed resources
|
||||
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/CMakeRC.cmake")
|
||||
cmrc_add_resource_library(embedded-resources
|
||||
ALIAS res::embedded
|
||||
NAMESPACE res
|
||||
src/images/bronze.png
|
||||
src/images/gold.png
|
||||
src/images/platinum.png
|
||||
src/images/silver.png)
|
||||
target_link_libraries(shadps4 PRIVATE res::embedded)
|
||||
|
||||
# ImGui resources
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/imgui/renderer)
|
||||
add_dependencies(shadps4 ImGui_Resources)
|
||||
|
@ -1002,7 +1210,7 @@ if (ENABLE_QT_GUI)
|
|||
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 "0.4.1"
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING "${APP_VERSION}"
|
||||
)
|
||||
|
||||
set_source_files_properties(src/images/shadPS4.icns PROPERTIES
|
||||
|
@ -1026,7 +1234,6 @@ 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.releases.xml" DESTINATION "share/metainfo/releases")
|
||||
install(FILES "dist/net.shadps4.shadPS4.metainfo.xml" DESTINATION "share/metainfo")
|
||||
install(FILES ".github/shadps4.png" DESTINATION "share/icons/hicolor/512x512/apps" RENAME "net.shadps4.shadPS4.png")
|
||||
install(FILES "src/images/net.shadps4.shadPS4.svg" DESTINATION "share/icons/hicolor/scalable/apps")
|
||||
|
|
105
README.md
105
README.md
|
@ -13,7 +13,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
|||
|
||||
<h1 align="center">
|
||||
<a href="https://discord.gg/bFJxfftGW6">
|
||||
<img src="https://img.shields.io/discord/1080089157554155590?color=5865F2&label=shadPS4 Discord&logo=Discord&logoColor=white" width="240">
|
||||
<img src="https://img.shields.io/discord/1080089157554155590?color=5865F2&label=shadPS4%20Discord&logo=Discord&logoColor=white" width="275">
|
||||
<a href="https://github.com/shadps4-emu/shadPS4/releases/latest">
|
||||
<img src="https://img.shields.io/github/downloads/shadps4-emu/shadPS4/total.svg" width="140">
|
||||
<a href="https://shadps4.net/">
|
||||
|
@ -55,6 +55,9 @@ This project began as a fun project. Given our limited free time, it may take so
|
|||
|
||||
# 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
|
||||
|
||||
Check the build instructions for [**Windows**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/building-windows.md).
|
||||
|
@ -68,13 +71,16 @@ Check the build instructions for [**Linux**](https://github.com/shadps4-emu/shad
|
|||
Check the build instructions for [**macOS**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/building-macos.md).
|
||||
|
||||
> [!IMPORTANT]
|
||||
> macOS users need at least macOS 15 on Apple Silicon-based Mac devices and at least macOS 14 on Intel-based Mac devices.
|
||||
> macOS users need at least macOS 15.4 to run shadPS4. Due to GPU issues there are currently heavy bugs on Intel Macs.
|
||||
|
||||
# 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).
|
||||
|
||||
# Keyboard mapping
|
||||
# Keyboard and Mouse Mappings
|
||||
|
||||
> [!NOTE]
|
||||
> Some keyboards may also require you to hold the Fn key to use the F\* keys. Mac users should use the Command key instead of Control, and need to use Command+F11 for full screen to avoid conflicting with system key bindings.
|
||||
|
||||
| Button | Function |
|
||||
|-------------|-------------|
|
||||
|
@ -86,41 +92,67 @@ F12 | Trigger RenderDoc Capture
|
|||
> [!NOTE]
|
||||
> Xbox and DualShock controllers work out of the box.
|
||||
|
||||
| Controller button | Keyboard equivelant | Mac alternative |
|
||||
|-------------|-------------|--------------|
|
||||
LEFT AXIS UP | W | |
|
||||
LEFT AXIS DOWN | S | |
|
||||
LEFT AXIS LEFT | A | |
|
||||
LEFT AXIS RIGHT | D | |
|
||||
RIGHT AXIS UP | I | |
|
||||
RIGHT AXIS DOWN | K | |
|
||||
RIGHT AXIS LEFT | J | |
|
||||
RIGHT AXIS RIGHT | L | |
|
||||
TRIANGLE | Numpad 8 | C |
|
||||
CIRCLE | Numpad 6 | B |
|
||||
CROSS | Numpad 2 | N |
|
||||
SQUARE | Numpad 4 | V |
|
||||
PAD UP | UP | |
|
||||
PAD DOWN | DOWN | |
|
||||
PAD LEFT | LEFT | |
|
||||
PAD RIGHT | RIGHT | |
|
||||
OPTIONS | RETURN | |
|
||||
BACK BUTTON / TOUCH PAD | SPACE | |
|
||||
L1 | Q | |
|
||||
R1 | U | |
|
||||
L2 | E | |
|
||||
R2 | O | |
|
||||
L3 | X | |
|
||||
R3 | M | |
|
||||
| Controller button | Keyboard equivalent |
|
||||
|-------------|-------------|
|
||||
LEFT AXIS UP | W |
|
||||
LEFT AXIS DOWN | S |
|
||||
LEFT AXIS LEFT | A |
|
||||
LEFT AXIS RIGHT | D |
|
||||
RIGHT AXIS UP | I |
|
||||
RIGHT AXIS DOWN | K |
|
||||
RIGHT AXIS LEFT | J |
|
||||
RIGHT AXIS RIGHT | L |
|
||||
TRIANGLE | Numpad 8 or C |
|
||||
CIRCLE | Numpad 6 or B |
|
||||
CROSS | Numpad 2 or N |
|
||||
SQUARE | Numpad 4 or V |
|
||||
PAD UP | UP |
|
||||
PAD DOWN | DOWN |
|
||||
PAD LEFT | LEFT |
|
||||
PAD RIGHT | RIGHT |
|
||||
OPTIONS | RETURN |
|
||||
BACK BUTTON / TOUCH PAD | SPACE |
|
||||
L1 | Q |
|
||||
R1 | U |
|
||||
L2 | E |
|
||||
R2 | O |
|
||||
L3 | X |
|
||||
R3 | M |
|
||||
|
||||
Keyboard and mouse inputs can be customized in the settings menu by clicking the Controller button, and further details and help on controls are also found there. Custom bindings are saved per-game. Inputs support up to three keys per binding, mouse buttons, mouse movement mapped to joystick input, and more.
|
||||
|
||||
|
||||
# Firmware files
|
||||
|
||||
shadPS4 can load some PlayStation 4 firmware files, these must be dumped from your legally owned PlayStation 4 console.\
|
||||
The following firmware modules are supported and must be placed in shadPS4's `user/sys_modules` folder.
|
||||
|
||||
<div align="center">
|
||||
|
||||
| Modules | Modules | Modules | Modules |
|
||||
|-------------------------|-------------------------|-------------------------|-------------------------|
|
||||
| libSceCesCs.sprx | libSceFont.sprx | libSceFontFt.sprx | libSceFreeTypeOt.sprx |
|
||||
| libSceJson.sprx | libSceJson2.sprx | libSceLibcInternal.sprx | libSceNgs2.sprx |
|
||||
| libSceRtc.sprx | libSceUlt.sprx | | |
|
||||
|
||||
</div>
|
||||
|
||||
> [!Caution]
|
||||
> The above modules are required to run the games properly and must be extracted from your PlayStation 4.\
|
||||
> **We do not provide any information or support on how to do this**.
|
||||
|
||||
|
||||
|
||||
# Main team
|
||||
|
||||
- [**georgemoralis**](https://github.com/georgemoralis)
|
||||
- [**raphaelthegreat**](https://github.com/raphaelthegreat)
|
||||
- [**psucien**](https://github.com/psucien)
|
||||
- [**skmp**](https://github.com/skmp)
|
||||
- [**wheremyfoodat**](https://github.com/wheremyfoodat)
|
||||
- [**raziel1000**](https://github.com/raziel1000)
|
||||
- [**viniciuslrangel**](https://github.com/viniciuslrangel)
|
||||
- [**roamic**](https://github.com/vladmikhalin)
|
||||
- [**squidbus**](https://github.com/squidbus)
|
||||
- [**frodo**](https://github.com/baggins183)
|
||||
- [**Stephen Miller**](https://github.com/StevenMiller123)
|
||||
- [**kalaposfos13**](https://github.com/kalaposfos13)
|
||||
|
||||
Logo is done by [**Xphalnos**](https://github.com/Xphalnos)
|
||||
|
||||
|
@ -129,10 +161,13 @@ Logo is done by [**Xphalnos**](https://github.com/Xphalnos)
|
|||
If you want to contribute, please look the [**CONTRIBUTING.md**](https://github.com/shadps4-emu/shadPS4/blob/main/CONTRIBUTING.md) file.\
|
||||
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=15">
|
||||
<img src="https://contrib.rocks/image?repo=shadps4-emu/shadPS4&max=24">
|
||||
</a>
|
||||
|
||||
|
||||
|
@ -146,7 +181,7 @@ A few noteworthy teams/projects who've helped us along the way are:
|
|||
|
||||
- **yuzu**: Our shader compiler has been designed with yuzu's Hades compiler as a blueprint. This allowed us to focus on the challenges of emulating a modern AMD GPU while having a high-quality optimizing shader compiler implementation as a base.
|
||||
|
||||
- [**hydra**](https://github.com/hydra-emu/hydra): A multisystem, multiplatform emulator (chip-8, GB, NES, N64) from Paris.
|
||||
- [**felix86**](https://github.com/OFFTKP/felix86): A new x86-64 → RISC-V Linux userspace emulator
|
||||
|
||||
# License
|
||||
|
||||
|
|
34
REUSE.toml
34
REUSE.toml
|
@ -3,26 +3,34 @@ version = 1
|
|||
[[annotations]]
|
||||
path = [
|
||||
"REUSE.toml",
|
||||
"crowdin.yml",
|
||||
"CMakeSettings.json",
|
||||
".github/FUNDING.yml",
|
||||
".github/shadps4.png",
|
||||
".github/workflows/scripts/update_translation.sh",
|
||||
".github/workflows/update_translation.yml",
|
||||
".gitmodules",
|
||||
"dist/MacOSBundleInfo.plist.in",
|
||||
"dist/net.shadps4.shadPS4.desktop",
|
||||
"dist/net.shadps4.shadPS4_metadata.pot",
|
||||
"dist/net.shadps4.shadPS4.metainfo.xml",
|
||||
"dist/net.shadps4.shadPS4.releases.xml",
|
||||
"documents/changelog.md",
|
||||
"documents/Quickstart/2.png",
|
||||
"documents/Screenshots/*",
|
||||
"documents/Screenshots/Linux/*",
|
||||
"externals/MoltenVK/MoltenVK_icd.json",
|
||||
"scripts/ps4_names.txt",
|
||||
"src/images/bronze.png",
|
||||
"src/images/gold.png",
|
||||
"src/images/platinum.png",
|
||||
"src/images/silver.png",
|
||||
"src/images/about_icon.png",
|
||||
"src/images/controller_icon.png",
|
||||
"src/images/discord.png",
|
||||
"src/images/dump_icon.png",
|
||||
"src/images/exit_icon.png",
|
||||
"src/images/file_icon.png",
|
||||
"src/images/trophy_icon.png",
|
||||
"src/images/flag_china.png",
|
||||
"src/images/flag_eu.png",
|
||||
"src/images/flag_jp.png",
|
||||
|
@ -32,25 +40,38 @@ path = [
|
|||
"src/images/folder_icon.png",
|
||||
"src/images/github.png",
|
||||
"src/images/grid_icon.png",
|
||||
"src/images/keyboard_icon.png",
|
||||
"src/images/iconsize_icon.png",
|
||||
"src/images/KBM.png",
|
||||
"src/images/ko-fi.png",
|
||||
"src/images/list_icon.png",
|
||||
"src/images/list_mode_icon.png",
|
||||
"src/images/pause_icon.png",
|
||||
"src/images/play_icon.png",
|
||||
"src/images/refresh_icon.png",
|
||||
"src/images/ps4_controller.png",
|
||||
"src/images/restart_game_icon.png",
|
||||
"src/images/refreshlist_icon.png",
|
||||
"src/images/settings_icon.png",
|
||||
"src/images/fullscreen_icon.png",
|
||||
"src/images/stop_icon.png",
|
||||
"src/images/utils_icon.png",
|
||||
"src/images/shadPS4.icns",
|
||||
"src/images/shadps4.ico",
|
||||
"src/images/shadps4.png",
|
||||
"src/images/net.shadps4.shadPS4.svg",
|
||||
"src/images/themes_icon.png",
|
||||
"src/images/update_icon.png",
|
||||
"src/images/youtube.png",
|
||||
"src/images/website.png",
|
||||
"src/images/discord.svg",
|
||||
"src/images/github.svg",
|
||||
"src/images/ko-fi.svg",
|
||||
"src/images/shadps4.svg",
|
||||
"src/images/website.svg",
|
||||
"src/images/youtube.svg",
|
||||
"src/shadps4.qrc",
|
||||
"src/shadps4.rc",
|
||||
"src/qt_gui/translations/update_translation.sh",
|
||||
]
|
||||
precedence = "aggregate"
|
||||
SPDX-FileCopyrightText = "shadPS4 Emulator Project"
|
||||
|
@ -97,3 +118,12 @@ path = "externals/gcn/include/**"
|
|||
SPDX-FileCopyrightText = "NONE"
|
||||
SPDX-License-Identifier = "CC0-1.0"
|
||||
|
||||
[[annotations]]
|
||||
path = "cmake/CMakeRC.cmake"
|
||||
SPDX-FileCopyrightText = "Copyright (c) 2017 vector-of-bool <vectorofbool@gmail.com>"
|
||||
SPDX-License-Identifier = "MIT"
|
||||
|
||||
[[annotations]]
|
||||
path = "src/video_core/host_shaders/fsr/*"
|
||||
SPDX-FileCopyrightText = "Copyright (c) 2021 Advanced Micro Devices, Inc. All rights reserved."
|
||||
SPDX-License-Identifier = "MIT"
|
||||
|
|
666
cmake/CMakeRC.cmake
Normal file
666
cmake/CMakeRC.cmake
Normal file
|
@ -0,0 +1,666 @@
|
|||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2017 vector-of-bool <vectorofbool@gmail.com>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
# This block is executed when generating an intermediate resource file, not when
|
||||
# running in CMake configure mode
|
||||
if(_CMRC_GENERATE_MODE)
|
||||
# Read in the digits
|
||||
file(READ "${INPUT_FILE}" bytes HEX)
|
||||
# Format each pair into a character literal. Heuristics seem to favor doing
|
||||
# the conversion in groups of five for fastest conversion
|
||||
string(REGEX REPLACE "(..)(..)(..)(..)(..)" "'\\\\x\\1','\\\\x\\2','\\\\x\\3','\\\\x\\4','\\\\x\\5'," chars "${bytes}")
|
||||
# Since we did this in groups, we have some leftovers to clean up
|
||||
string(LENGTH "${bytes}" n_bytes2)
|
||||
math(EXPR n_bytes "${n_bytes2} / 2")
|
||||
math(EXPR remainder "${n_bytes} % 5") # <-- '5' is the grouping count from above
|
||||
set(cleanup_re "$")
|
||||
set(cleanup_sub )
|
||||
while(remainder)
|
||||
set(cleanup_re "(..)${cleanup_re}")
|
||||
set(cleanup_sub "'\\\\x\\${remainder}',${cleanup_sub}")
|
||||
math(EXPR remainder "${remainder} - 1")
|
||||
endwhile()
|
||||
if(NOT cleanup_re STREQUAL "$")
|
||||
string(REGEX REPLACE "${cleanup_re}" "${cleanup_sub}" chars "${chars}")
|
||||
endif()
|
||||
string(CONFIGURE [[
|
||||
namespace { const char file_array[] = { @chars@ 0 }; }
|
||||
namespace cmrc { namespace @NAMESPACE@ { namespace res_chars {
|
||||
extern const char* const @SYMBOL@_begin = file_array;
|
||||
extern const char* const @SYMBOL@_end = file_array + @n_bytes@;
|
||||
}}}
|
||||
]] code)
|
||||
file(WRITE "${OUTPUT_FILE}" "${code}")
|
||||
# Exit from the script. Nothing else needs to be processed
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(_version 2.0.0)
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
include(CMakeParseArguments)
|
||||
|
||||
if(COMMAND cmrc_add_resource_library)
|
||||
if(NOT DEFINED _CMRC_VERSION OR NOT (_version STREQUAL _CMRC_VERSION))
|
||||
message(WARNING "More than one CMakeRC version has been included in this project.")
|
||||
endif()
|
||||
# CMakeRC has already been included! Don't do anything
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(_CMRC_VERSION "${_version}" CACHE INTERNAL "CMakeRC version. Used for checking for conflicts")
|
||||
|
||||
set(_CMRC_SCRIPT "${CMAKE_CURRENT_LIST_FILE}" CACHE INTERNAL "Path to CMakeRC script")
|
||||
|
||||
function(_cmrc_normalize_path var)
|
||||
set(path "${${var}}")
|
||||
file(TO_CMAKE_PATH "${path}" path)
|
||||
while(path MATCHES "//")
|
||||
string(REPLACE "//" "/" path "${path}")
|
||||
endwhile()
|
||||
string(REGEX REPLACE "/+$" "" path "${path}")
|
||||
set("${var}" "${path}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
get_filename_component(_inc_dir "${CMAKE_BINARY_DIR}/_cmrc/include" ABSOLUTE)
|
||||
set(CMRC_INCLUDE_DIR "${_inc_dir}" CACHE INTERNAL "Directory for CMakeRC include files")
|
||||
# Let's generate the primary include file
|
||||
file(MAKE_DIRECTORY "${CMRC_INCLUDE_DIR}/cmrc")
|
||||
set(hpp_content [==[
|
||||
#ifndef CMRC_CMRC_HPP_INCLUDED
|
||||
#define CMRC_CMRC_HPP_INCLUDED
|
||||
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
#include <type_traits>
|
||||
|
||||
#if !(defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) || defined(CMRC_NO_EXCEPTIONS))
|
||||
#define CMRC_NO_EXCEPTIONS 1
|
||||
#endif
|
||||
|
||||
namespace cmrc { namespace detail { struct dummy; } }
|
||||
|
||||
#define CMRC_DECLARE(libid) \
|
||||
namespace cmrc { namespace detail { \
|
||||
struct dummy; \
|
||||
static_assert(std::is_same<dummy, ::cmrc::detail::dummy>::value, "CMRC_DECLARE() must only appear at the global namespace"); \
|
||||
} } \
|
||||
namespace cmrc { namespace libid { \
|
||||
cmrc::embedded_filesystem get_filesystem(); \
|
||||
} } static_assert(true, "")
|
||||
|
||||
namespace cmrc {
|
||||
|
||||
class file {
|
||||
const char* _begin = nullptr;
|
||||
const char* _end = nullptr;
|
||||
|
||||
public:
|
||||
using iterator = const char*;
|
||||
using const_iterator = iterator;
|
||||
iterator begin() const noexcept { return _begin; }
|
||||
iterator cbegin() const noexcept { return _begin; }
|
||||
iterator end() const noexcept { return _end; }
|
||||
iterator cend() const noexcept { return _end; }
|
||||
std::size_t size() const { return static_cast<std::size_t>(std::distance(begin(), end())); }
|
||||
|
||||
file() = default;
|
||||
file(iterator beg, iterator end) noexcept : _begin(beg), _end(end) {}
|
||||
};
|
||||
|
||||
class directory_entry;
|
||||
|
||||
namespace detail {
|
||||
|
||||
class directory;
|
||||
class file_data;
|
||||
|
||||
class file_or_directory {
|
||||
union _data_t {
|
||||
class file_data* file_data;
|
||||
class directory* directory;
|
||||
} _data;
|
||||
bool _is_file = true;
|
||||
|
||||
public:
|
||||
explicit file_or_directory(file_data& f) {
|
||||
_data.file_data = &f;
|
||||
}
|
||||
explicit file_or_directory(directory& d) {
|
||||
_data.directory = &d;
|
||||
_is_file = false;
|
||||
}
|
||||
bool is_file() const noexcept {
|
||||
return _is_file;
|
||||
}
|
||||
bool is_directory() const noexcept {
|
||||
return !is_file();
|
||||
}
|
||||
const directory& as_directory() const noexcept {
|
||||
assert(!is_file());
|
||||
return *_data.directory;
|
||||
}
|
||||
const file_data& as_file() const noexcept {
|
||||
assert(is_file());
|
||||
return *_data.file_data;
|
||||
}
|
||||
};
|
||||
|
||||
class file_data {
|
||||
public:
|
||||
const char* begin_ptr;
|
||||
const char* end_ptr;
|
||||
file_data(const file_data&) = delete;
|
||||
file_data(const char* b, const char* e) : begin_ptr(b), end_ptr(e) {}
|
||||
};
|
||||
|
||||
inline std::pair<std::string, std::string> split_path(const std::string& path) {
|
||||
auto first_sep = path.find("/");
|
||||
if (first_sep == path.npos) {
|
||||
return std::make_pair(path, "");
|
||||
} else {
|
||||
return std::make_pair(path.substr(0, first_sep), path.substr(first_sep + 1));
|
||||
}
|
||||
}
|
||||
|
||||
struct created_subdirectory {
|
||||
class directory& directory;
|
||||
class file_or_directory& index_entry;
|
||||
};
|
||||
|
||||
class directory {
|
||||
std::list<file_data> _files;
|
||||
std::list<directory> _dirs;
|
||||
std::map<std::string, file_or_directory> _index;
|
||||
|
||||
using base_iterator = std::map<std::string, file_or_directory>::const_iterator;
|
||||
|
||||
public:
|
||||
|
||||
directory() = default;
|
||||
directory(const directory&) = delete;
|
||||
|
||||
created_subdirectory add_subdir(std::string name) & {
|
||||
_dirs.emplace_back();
|
||||
auto& back = _dirs.back();
|
||||
auto& fod = _index.emplace(name, file_or_directory{back}).first->second;
|
||||
return created_subdirectory{back, fod};
|
||||
}
|
||||
|
||||
file_or_directory* add_file(std::string name, const char* begin, const char* end) & {
|
||||
assert(_index.find(name) == _index.end());
|
||||
_files.emplace_back(begin, end);
|
||||
return &_index.emplace(name, file_or_directory{_files.back()}).first->second;
|
||||
}
|
||||
|
||||
const file_or_directory* get(const std::string& path) const {
|
||||
auto pair = split_path(path);
|
||||
auto child = _index.find(pair.first);
|
||||
if (child == _index.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
auto& entry = child->second;
|
||||
if (pair.second.empty()) {
|
||||
// We're at the end of the path
|
||||
return &entry;
|
||||
}
|
||||
|
||||
if (entry.is_file()) {
|
||||
// We can't traverse into a file. Stop.
|
||||
return nullptr;
|
||||
}
|
||||
// Keep going down
|
||||
return entry.as_directory().get(pair.second);
|
||||
}
|
||||
|
||||
class iterator {
|
||||
base_iterator _base_iter;
|
||||
base_iterator _end_iter;
|
||||
public:
|
||||
using value_type = directory_entry;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = const value_type*;
|
||||
using reference = const value_type&;
|
||||
using iterator_category = std::input_iterator_tag;
|
||||
|
||||
iterator() = default;
|
||||
explicit iterator(base_iterator iter, base_iterator end) : _base_iter(iter), _end_iter(end) {}
|
||||
|
||||
iterator begin() const noexcept {
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator end() const noexcept {
|
||||
return iterator(_end_iter, _end_iter);
|
||||
}
|
||||
|
||||
inline value_type operator*() const noexcept;
|
||||
|
||||
bool operator==(const iterator& rhs) const noexcept {
|
||||
return _base_iter == rhs._base_iter;
|
||||
}
|
||||
|
||||
bool operator!=(const iterator& rhs) const noexcept {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
iterator& operator++() noexcept {
|
||||
++_base_iter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator operator++(int) noexcept {
|
||||
auto cp = *this;
|
||||
++_base_iter;
|
||||
return cp;
|
||||
}
|
||||
};
|
||||
|
||||
using const_iterator = iterator;
|
||||
|
||||
iterator begin() const noexcept {
|
||||
return iterator(_index.begin(), _index.end());
|
||||
}
|
||||
|
||||
iterator end() const noexcept {
|
||||
return iterator();
|
||||
}
|
||||
};
|
||||
|
||||
inline std::string normalize_path(std::string path) {
|
||||
while (path.find("/") == 0) {
|
||||
path.erase(path.begin());
|
||||
}
|
||||
while (!path.empty() && (path.rfind("/") == path.size() - 1)) {
|
||||
path.pop_back();
|
||||
}
|
||||
auto off = path.npos;
|
||||
while ((off = path.find("//")) != path.npos) {
|
||||
path.erase(path.begin() + static_cast<std::string::difference_type>(off));
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
using index_type = std::map<std::string, const cmrc::detail::file_or_directory*>;
|
||||
|
||||
} // detail
|
||||
|
||||
class directory_entry {
|
||||
std::string _fname;
|
||||
const detail::file_or_directory* _item;
|
||||
|
||||
public:
|
||||
directory_entry() = delete;
|
||||
explicit directory_entry(std::string filename, const detail::file_or_directory& item)
|
||||
: _fname(filename)
|
||||
, _item(&item)
|
||||
{}
|
||||
|
||||
const std::string& filename() const & {
|
||||
return _fname;
|
||||
}
|
||||
std::string filename() const && {
|
||||
return std::move(_fname);
|
||||
}
|
||||
|
||||
bool is_file() const {
|
||||
return _item->is_file();
|
||||
}
|
||||
|
||||
bool is_directory() const {
|
||||
return _item->is_directory();
|
||||
}
|
||||
};
|
||||
|
||||
directory_entry detail::directory::iterator::operator*() const noexcept {
|
||||
assert(begin() != end());
|
||||
return directory_entry(_base_iter->first, _base_iter->second);
|
||||
}
|
||||
|
||||
using directory_iterator = detail::directory::iterator;
|
||||
|
||||
class embedded_filesystem {
|
||||
// Never-null:
|
||||
const cmrc::detail::index_type* _index;
|
||||
const detail::file_or_directory* _get(std::string path) const {
|
||||
path = detail::normalize_path(path);
|
||||
auto found = _index->find(path);
|
||||
if (found == _index->end()) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return found->second;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
explicit embedded_filesystem(const detail::index_type& index)
|
||||
: _index(&index)
|
||||
{}
|
||||
|
||||
file open(const std::string& path) const {
|
||||
auto entry_ptr = _get(path);
|
||||
if (!entry_ptr || !entry_ptr->is_file()) {
|
||||
#ifdef CMRC_NO_EXCEPTIONS
|
||||
fprintf(stderr, "Error no such file or directory: %s\n", path.c_str());
|
||||
abort();
|
||||
#else
|
||||
throw std::system_error(make_error_code(std::errc::no_such_file_or_directory), path);
|
||||
#endif
|
||||
}
|
||||
auto& dat = entry_ptr->as_file();
|
||||
return file{dat.begin_ptr, dat.end_ptr};
|
||||
}
|
||||
|
||||
bool is_file(const std::string& path) const noexcept {
|
||||
auto entry_ptr = _get(path);
|
||||
return entry_ptr && entry_ptr->is_file();
|
||||
}
|
||||
|
||||
bool is_directory(const std::string& path) const noexcept {
|
||||
auto entry_ptr = _get(path);
|
||||
return entry_ptr && entry_ptr->is_directory();
|
||||
}
|
||||
|
||||
bool exists(const std::string& path) const noexcept {
|
||||
return !!_get(path);
|
||||
}
|
||||
|
||||
directory_iterator iterate_directory(const std::string& path) const {
|
||||
auto entry_ptr = _get(path);
|
||||
if (!entry_ptr) {
|
||||
#ifdef CMRC_NO_EXCEPTIONS
|
||||
fprintf(stderr, "Error no such file or directory: %s\n", path.c_str());
|
||||
abort();
|
||||
#else
|
||||
throw std::system_error(make_error_code(std::errc::no_such_file_or_directory), path);
|
||||
#endif
|
||||
}
|
||||
if (!entry_ptr->is_directory()) {
|
||||
#ifdef CMRC_NO_EXCEPTIONS
|
||||
fprintf(stderr, "Error not a directory: %s\n", path.c_str());
|
||||
abort();
|
||||
#else
|
||||
throw std::system_error(make_error_code(std::errc::not_a_directory), path);
|
||||
#endif
|
||||
}
|
||||
return entry_ptr->as_directory().begin();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // CMRC_CMRC_HPP_INCLUDED
|
||||
]==])
|
||||
|
||||
set(cmrc_hpp "${CMRC_INCLUDE_DIR}/cmrc/cmrc.hpp" CACHE INTERNAL "")
|
||||
set(_generate 1)
|
||||
if(EXISTS "${cmrc_hpp}")
|
||||
file(READ "${cmrc_hpp}" _current)
|
||||
if(_current STREQUAL hpp_content)
|
||||
set(_generate 0)
|
||||
endif()
|
||||
endif()
|
||||
file(GENERATE OUTPUT "${cmrc_hpp}" CONTENT "${hpp_content}" CONDITION ${_generate})
|
||||
|
||||
add_library(cmrc-base INTERFACE)
|
||||
target_include_directories(cmrc-base INTERFACE $<BUILD_INTERFACE:${CMRC_INCLUDE_DIR}>)
|
||||
# Signal a basic C++11 feature to require C++11.
|
||||
target_compile_features(cmrc-base INTERFACE cxx_nullptr)
|
||||
set_property(TARGET cmrc-base PROPERTY INTERFACE_CXX_EXTENSIONS OFF)
|
||||
add_library(cmrc::base ALIAS cmrc-base)
|
||||
|
||||
function(cmrc_add_resource_library name)
|
||||
set(args ALIAS NAMESPACE TYPE)
|
||||
cmake_parse_arguments(ARG "" "${args}" "" "${ARGN}")
|
||||
# Generate the identifier for the resource library's namespace
|
||||
set(ns_re "[a-zA-Z_][a-zA-Z0-9_]*")
|
||||
if(NOT DEFINED ARG_NAMESPACE)
|
||||
# Check that the library name is also a valid namespace
|
||||
if(NOT name MATCHES "${ns_re}")
|
||||
message(SEND_ERROR "Library name is not a valid namespace. Specify the NAMESPACE argument")
|
||||
endif()
|
||||
set(ARG_NAMESPACE "${name}")
|
||||
else()
|
||||
if(NOT ARG_NAMESPACE MATCHES "${ns_re}")
|
||||
message(SEND_ERROR "NAMESPACE for ${name} is not a valid C++ namespace identifier (${ARG_NAMESPACE})")
|
||||
endif()
|
||||
endif()
|
||||
set(libname "${name}")
|
||||
# Check that type is either "STATIC" or "OBJECT", or default to "STATIC" if
|
||||
# not set
|
||||
if(NOT DEFINED ARG_TYPE)
|
||||
set(ARG_TYPE STATIC)
|
||||
elseif(NOT "${ARG_TYPE}" MATCHES "^(STATIC|OBJECT)$")
|
||||
message(SEND_ERROR "${ARG_TYPE} is not a valid TYPE (STATIC and OBJECT are acceptable)")
|
||||
set(ARG_TYPE STATIC)
|
||||
endif()
|
||||
# Generate a library with the compiled in character arrays.
|
||||
string(CONFIGURE [=[
|
||||
#include <cmrc/cmrc.hpp>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
namespace cmrc {
|
||||
namespace @ARG_NAMESPACE@ {
|
||||
|
||||
namespace res_chars {
|
||||
// These are the files which are available in this resource library
|
||||
$<JOIN:$<TARGET_PROPERTY:@libname@,CMRC_EXTERN_DECLS>,
|
||||
>
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
const cmrc::detail::index_type&
|
||||
get_root_index() {
|
||||
static cmrc::detail::directory root_directory_;
|
||||
static cmrc::detail::file_or_directory root_directory_fod{root_directory_};
|
||||
static cmrc::detail::index_type root_index;
|
||||
root_index.emplace("", &root_directory_fod);
|
||||
struct dir_inl {
|
||||
class cmrc::detail::directory& directory;
|
||||
};
|
||||
dir_inl root_directory_dir{root_directory_};
|
||||
(void)root_directory_dir;
|
||||
$<JOIN:$<TARGET_PROPERTY:@libname@,CMRC_MAKE_DIRS>,
|
||||
>
|
||||
$<JOIN:$<TARGET_PROPERTY:@libname@,CMRC_MAKE_FILES>,
|
||||
>
|
||||
return root_index;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cmrc::embedded_filesystem get_filesystem() {
|
||||
static auto& index = get_root_index();
|
||||
return cmrc::embedded_filesystem{index};
|
||||
}
|
||||
|
||||
} // @ARG_NAMESPACE@
|
||||
} // cmrc
|
||||
]=] cpp_content @ONLY)
|
||||
get_filename_component(libdir "${CMAKE_CURRENT_BINARY_DIR}/__cmrc_${name}" ABSOLUTE)
|
||||
get_filename_component(lib_tmp_cpp "${libdir}/lib_.cpp" ABSOLUTE)
|
||||
string(REPLACE "\n " "\n" cpp_content "${cpp_content}")
|
||||
file(GENERATE OUTPUT "${lib_tmp_cpp}" CONTENT "${cpp_content}")
|
||||
get_filename_component(libcpp "${libdir}/lib.cpp" ABSOLUTE)
|
||||
add_custom_command(OUTPUT "${libcpp}"
|
||||
DEPENDS "${lib_tmp_cpp}" "${cmrc_hpp}"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${lib_tmp_cpp}" "${libcpp}"
|
||||
COMMENT "Generating ${name} resource loader"
|
||||
)
|
||||
# Generate the actual static library. Each source file is just a single file
|
||||
# with a character array compiled in containing the contents of the
|
||||
# corresponding resource file.
|
||||
add_library(${name} ${ARG_TYPE} ${libcpp})
|
||||
set_property(TARGET ${name} PROPERTY CMRC_LIBDIR "${libdir}")
|
||||
set_property(TARGET ${name} PROPERTY CMRC_NAMESPACE "${ARG_NAMESPACE}")
|
||||
target_link_libraries(${name} PUBLIC cmrc::base)
|
||||
set_property(TARGET ${name} PROPERTY CMRC_IS_RESOURCE_LIBRARY TRUE)
|
||||
if(ARG_ALIAS)
|
||||
add_library("${ARG_ALIAS}" ALIAS ${name})
|
||||
endif()
|
||||
cmrc_add_resources(${name} ${ARG_UNPARSED_ARGUMENTS})
|
||||
endfunction()
|
||||
|
||||
function(_cmrc_register_dirs name dirpath)
|
||||
if(dirpath STREQUAL "")
|
||||
return()
|
||||
endif()
|
||||
# Skip this dir if we have already registered it
|
||||
get_target_property(registered "${name}" _CMRC_REGISTERED_DIRS)
|
||||
if(dirpath IN_LIST registered)
|
||||
return()
|
||||
endif()
|
||||
# Register the parent directory first
|
||||
get_filename_component(parent "${dirpath}" DIRECTORY)
|
||||
if(NOT parent STREQUAL "")
|
||||
_cmrc_register_dirs("${name}" "${parent}")
|
||||
endif()
|
||||
# Now generate the registration
|
||||
set_property(TARGET "${name}" APPEND PROPERTY _CMRC_REGISTERED_DIRS "${dirpath}")
|
||||
_cm_encode_fpath(sym "${dirpath}")
|
||||
if(parent STREQUAL "")
|
||||
set(parent_sym root_directory)
|
||||
else()
|
||||
_cm_encode_fpath(parent_sym "${parent}")
|
||||
endif()
|
||||
get_filename_component(leaf "${dirpath}" NAME)
|
||||
set_property(
|
||||
TARGET "${name}"
|
||||
APPEND PROPERTY CMRC_MAKE_DIRS
|
||||
"static auto ${sym}_dir = ${parent_sym}_dir.directory.add_subdir(\"${leaf}\")\;"
|
||||
"root_index.emplace(\"${dirpath}\", &${sym}_dir.index_entry)\;"
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(cmrc_add_resources name)
|
||||
get_target_property(is_reslib ${name} CMRC_IS_RESOURCE_LIBRARY)
|
||||
if(NOT TARGET ${name} OR NOT is_reslib)
|
||||
message(SEND_ERROR "cmrc_add_resources called on target '${name}' which is not an existing resource library")
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(options)
|
||||
set(args WHENCE PREFIX)
|
||||
set(list_args)
|
||||
cmake_parse_arguments(ARG "${options}" "${args}" "${list_args}" "${ARGN}")
|
||||
|
||||
if(NOT ARG_WHENCE)
|
||||
set(ARG_WHENCE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
endif()
|
||||
_cmrc_normalize_path(ARG_WHENCE)
|
||||
get_filename_component(ARG_WHENCE "${ARG_WHENCE}" ABSOLUTE)
|
||||
|
||||
# Generate the identifier for the resource library's namespace
|
||||
get_target_property(lib_ns "${name}" CMRC_NAMESPACE)
|
||||
|
||||
get_target_property(libdir ${name} CMRC_LIBDIR)
|
||||
get_target_property(target_dir ${name} SOURCE_DIR)
|
||||
file(RELATIVE_PATH reldir "${target_dir}" "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
if(reldir MATCHES "^\\.\\.")
|
||||
message(SEND_ERROR "Cannot call cmrc_add_resources in a parent directory from the resource library target")
|
||||
return()
|
||||
endif()
|
||||
|
||||
foreach(input IN LISTS ARG_UNPARSED_ARGUMENTS)
|
||||
_cmrc_normalize_path(input)
|
||||
get_filename_component(abs_in "${input}" ABSOLUTE)
|
||||
# Generate a filename based on the input filename that we can put in
|
||||
# the intermediate directory.
|
||||
file(RELATIVE_PATH relpath "${ARG_WHENCE}" "${abs_in}")
|
||||
if(relpath MATCHES "^\\.\\.")
|
||||
# For now we just error on files that exist outside of the soure dir.
|
||||
message(SEND_ERROR "Cannot add file '${input}': File must be in a subdirectory of ${ARG_WHENCE}")
|
||||
continue()
|
||||
endif()
|
||||
if(DEFINED ARG_PREFIX)
|
||||
_cmrc_normalize_path(ARG_PREFIX)
|
||||
endif()
|
||||
if(ARG_PREFIX AND NOT ARG_PREFIX MATCHES "/$")
|
||||
set(ARG_PREFIX "${ARG_PREFIX}/")
|
||||
endif()
|
||||
get_filename_component(dirpath "${ARG_PREFIX}${relpath}" DIRECTORY)
|
||||
_cmrc_register_dirs("${name}" "${dirpath}")
|
||||
get_filename_component(abs_out "${libdir}/intermediate/${ARG_PREFIX}${relpath}.cpp" ABSOLUTE)
|
||||
# Generate a symbol name relpath the file's character array
|
||||
_cm_encode_fpath(sym "${relpath}")
|
||||
# Get the symbol name for the parent directory
|
||||
if(dirpath STREQUAL "")
|
||||
set(parent_sym root_directory)
|
||||
else()
|
||||
_cm_encode_fpath(parent_sym "${dirpath}")
|
||||
endif()
|
||||
# Generate the rule for the intermediate source file
|
||||
_cmrc_generate_intermediate_cpp(${lib_ns} ${sym} "${abs_out}" "${abs_in}")
|
||||
target_sources(${name} PRIVATE "${abs_out}")
|
||||
set_property(TARGET ${name} APPEND PROPERTY CMRC_EXTERN_DECLS
|
||||
"// Pointers to ${input}"
|
||||
"extern const char* const ${sym}_begin\;"
|
||||
"extern const char* const ${sym}_end\;"
|
||||
)
|
||||
get_filename_component(leaf "${relpath}" NAME)
|
||||
set_property(
|
||||
TARGET ${name}
|
||||
APPEND PROPERTY CMRC_MAKE_FILES
|
||||
"root_index.emplace("
|
||||
" \"${ARG_PREFIX}${relpath}\","
|
||||
" ${parent_sym}_dir.directory.add_file("
|
||||
" \"${leaf}\","
|
||||
" res_chars::${sym}_begin,"
|
||||
" res_chars::${sym}_end"
|
||||
" )"
|
||||
")\;"
|
||||
)
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
function(_cmrc_generate_intermediate_cpp lib_ns symbol outfile infile)
|
||||
add_custom_command(
|
||||
# This is the file we will generate
|
||||
OUTPUT "${outfile}"
|
||||
# These are the primary files that affect the output
|
||||
DEPENDS "${infile}" "${_CMRC_SCRIPT}"
|
||||
COMMAND
|
||||
"${CMAKE_COMMAND}"
|
||||
-D_CMRC_GENERATE_MODE=TRUE
|
||||
-DNAMESPACE=${lib_ns}
|
||||
-DSYMBOL=${symbol}
|
||||
"-DINPUT_FILE=${infile}"
|
||||
"-DOUTPUT_FILE=${outfile}"
|
||||
-P "${_CMRC_SCRIPT}"
|
||||
COMMENT "Generating intermediate file for ${infile}"
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(_cm_encode_fpath var fpath)
|
||||
string(MAKE_C_IDENTIFIER "${fpath}" ident)
|
||||
string(MD5 hash "${fpath}")
|
||||
string(SUBSTRING "${hash}" 0 4 hash)
|
||||
set(${var} f_${hash}_${ident} PARENT_SCOPE)
|
||||
endfunction()
|
|
@ -1,15 +0,0 @@
|
|||
# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(CRYPTOPP QUIET IMPORTED_TARGET libcryptopp)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(cryptopp
|
||||
REQUIRED_VARS CRYPTOPP_LINK_LIBRARIES
|
||||
VERSION_VAR CRYPTOPP_VERSION
|
||||
)
|
||||
|
||||
if (cryptopp_FOUND AND NOT TARGET cryptopp::cryptopp)
|
||||
add_library(cryptopp::cryptopp ALIAS PkgConfig::CRYPTOPP)
|
||||
endif()
|
15
cmake/Findlibusb.cmake
Normal file
15
cmake/Findlibusb.cmake
Normal file
|
@ -0,0 +1,15 @@
|
|||
# SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(LIBUSB QUIET IMPORTED_TARGET libusb-1.0)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(libusb
|
||||
REQUIRED_VARS LIBUSB_LINK_LIBRARIES
|
||||
VERSION_VAR LIBUSB_VERSION
|
||||
)
|
||||
|
||||
if (libusb_FOUND AND NOT TARGET libusb::usb)
|
||||
add_library(libusb::usb ALIAS PkgConfig::LIBUSB)
|
||||
endif()
|
3
crowdin.yml
Normal file
3
crowdin.yml
Normal file
|
@ -0,0 +1,3 @@
|
|||
files:
|
||||
- source: /src/qt_gui/translations/en_US.ts
|
||||
translation: /%original_path%/%locale_with_underscore%.ts
|
2
dist/net.shadps4.shadPS4.desktop
vendored
2
dist/net.shadps4.shadPS4.desktop
vendored
|
@ -5,5 +5,5 @@ Terminal=false
|
|||
Type=Application
|
||||
Icon=net.shadps4.shadPS4
|
||||
Comment=PlayStation 4 emulator
|
||||
Categories=Game;
|
||||
Categories=Game;Emulator;
|
||||
StartupWMClass=shadps4;
|
||||
|
|
38
dist/net.shadps4.shadPS4.metainfo.xml
vendored
38
dist/net.shadps4.shadPS4.metainfo.xml
vendored
|
@ -26,7 +26,7 @@
|
|||
</screenshot>
|
||||
<screenshot>
|
||||
<image type="source" translate="no">https://cdn.jsdelivr.net/gh/shadps4-emu/shadps4@main/documents/Screenshots/3.png</image>
|
||||
<caption>Yakuza Kiwami</caption>
|
||||
<caption>Yakuza 0</caption>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image type="source" translate="no">https://cdn.jsdelivr.net/gh/shadps4-emu/shadps4@main/documents/Screenshots/4.png</image>
|
||||
|
@ -36,9 +36,39 @@
|
|||
<categories>
|
||||
<category translate="no">Game</category>
|
||||
</categories>
|
||||
<releases type="external" url="https://cdn.jsdelivr.net/gh/fpiesche/flatpak-builds/apps/net.shadps4.shadPS4/net.shadps4.shadPS4.releases.xml">
|
||||
<release version="v.0.4.0" date="2024-11-03">
|
||||
<description></description>
|
||||
<releases>
|
||||
<release version="0.8.0" date="2025-05-23">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.8.0</url>
|
||||
</release>
|
||||
<release version="0.7.0" date="2025-03-23">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.7.0</url>
|
||||
</release>
|
||||
<release version="0.6.0" date="2025-01-31">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.6.0</url>
|
||||
</release>
|
||||
<release version="0.5.0" date="2024-12-25">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.5.0</url>
|
||||
</release>
|
||||
<release version="0.4.0" date="2024-10-31">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.4.0</url>
|
||||
</release>
|
||||
<release version="0.3.0" date="2024-09-23">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.3.0</url>
|
||||
</release>
|
||||
<release version="0.2.0" date="2024-08-15">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.2.0</url>
|
||||
</release>
|
||||
<release version="0.1.0" date="2024-07-01">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/0.1.0</url>
|
||||
</release>
|
||||
<release version="0.0.3" date="2024-03-23">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v0.0.3</url>
|
||||
</release>
|
||||
<release version="0.0.2" date="2023-10-21">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v0.0.2</url>
|
||||
</release>
|
||||
<release version="0.0.1" date="2024-09-29">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v0.0.1</url>
|
||||
</release>
|
||||
</releases>
|
||||
<content_rating type="oars-1.1"/>
|
||||
|
|
23
dist/net.shadps4.shadPS4.releases.xml
vendored
23
dist/net.shadps4.shadPS4.releases.xml
vendored
|
@ -1,23 +0,0 @@
|
|||
<releases>
|
||||
<release version="0.4.0" date="2024-10-31">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.4.0</url>
|
||||
</release>
|
||||
<release version="0.3.0" date="2024-09-23">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.3.0</url>
|
||||
</release>
|
||||
<release version="0.2.0" date="2024-08-15">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.2.0</url>
|
||||
</release>
|
||||
<release version="0.1.0" date="2024-07-01">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/0.1.0</url>
|
||||
</release>
|
||||
<release version="0.0.3" date="2024-03-23">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v0.0.3</url>
|
||||
</release>
|
||||
<release version="0.0.2" date="2023-10-21">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v0.0.2</url>
|
||||
</release>
|
||||
<release version="0.0.1" date="2024-09-29">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v0.0.1</url>
|
||||
</release>
|
||||
</releases>
|
Binary file not shown.
Before Width: | Height: | Size: 658 KiB |
|
@ -13,7 +13,6 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
|||
- [**RAM**](#ram)
|
||||
- [**OS**](#os)
|
||||
- [**Have the latest WIP version**](#how-to-run-the-latest-work-in-progress-builds-of-shadps4)
|
||||
- [**Install PKG files (Games and Updates)**](#install-pkg-files)
|
||||
- [**Configure the emulator**](#configure-the-emulator)
|
||||
|
||||
## Minimum PC requirements
|
||||
|
@ -22,13 +21,16 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
|||
|
||||
- A processor with at least 4 cores and 6 threads
|
||||
- Above 2.5 GHz frequency
|
||||
- required support AVX2 extension or Rosetta 2 on ARM
|
||||
- A CPU supporting the following instruction sets: MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, F16C, CLMUL, AES, BMI1, MOVBE, XSAVE, ABM
|
||||
- **Intel**: Haswell generation or newer
|
||||
- **AMD**: Jaguar generation or newer
|
||||
- **Apple**: Rosetta 2 on macOS 15.4 or newer
|
||||
|
||||
### GPU
|
||||
|
||||
- A graphics card with at least 1GB of VRAM
|
||||
- Keep your graphics drivers up to date
|
||||
- Vulkan 1.3 support (required)
|
||||
- Up-to-date graphics drivers
|
||||
- Vulkan 1.3 with the `VK_KHR_swapchain` and `VK_KHR_push_descriptor` extensions
|
||||
|
||||
### RAM
|
||||
|
||||
|
@ -45,13 +47,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
|||
|
||||
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 shadPS4 can use to install your PKG files to.
|
||||
|
||||
## Install PKG files
|
||||
|
||||
To install PKG files (game and updates), you will need the Qt application (with UI). You will have to go to "File" then to "Install Packages (PKG)", a window will open then you will have to select the files. You can install multiple PKG files at once. Once finished, the game should appear in the application.
|
||||
|
||||
<img src="https://github.com/shadps4-emu/shadPS4/blob/main/documents/Quickstart/2.png" width="800">
|
||||
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
|
||||
|
||||
|
|
BIN
documents/Screenshots/Linux/1.png
Normal file
BIN
documents/Screenshots/Linux/1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
documents/Screenshots/Linux/2.png
Normal file
BIN
documents/Screenshots/Linux/2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
BIN
documents/Screenshots/Linux/3.png
Normal file
BIN
documents/Screenshots/Linux/3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
BIN
documents/Screenshots/Linux/4.png
Normal file
BIN
documents/Screenshots/Linux/4.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
BIN
documents/Screenshots/Linux/5.png
Normal file
BIN
documents/Screenshots/Linux/5.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
|
@ -5,57 +5,154 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
|||
|
||||
## Build shadPS4 for Linux
|
||||
|
||||
### Install the necessary tools to build shadPS4:
|
||||
First and foremost, Clang 18 is the **recommended compiler** as it is used for official builds and CI. If you build with GCC, you might encounter issues — please report any you find. Additionally, if you choose to use GCC, please build shadPS4 with Clang at least once before creating an `[APP BUG]` issue or submitting a pull request.
|
||||
|
||||
## Preparatory steps
|
||||
|
||||
### Installing dependencies
|
||||
|
||||
#### Debian & Ubuntu
|
||||
```
|
||||
sudo apt install build-essential clang git cmake libasound2-dev libpulse-dev libopenal-dev libssl-dev zlib1g-dev libedit-dev libudev-dev libevdev-dev libsdl2-dev libjack-dev libsndio-dev qt6-base-dev qt6-tools-dev qt6-multimedia-dev libvulkan-dev vulkan-validationlayers
|
||||
|
||||
```bash
|
||||
sudo apt install build-essential clang git cmake libasound2-dev \
|
||||
libpulse-dev libopenal-dev libssl-dev zlib1g-dev libedit-dev \
|
||||
libudev-dev libevdev-dev libsdl2-dev libjack-dev libsndio-dev \
|
||||
qt6-base-dev qt6-tools-dev qt6-multimedia-dev libvulkan-dev \
|
||||
vulkan-validationlayers libpng-dev
|
||||
```
|
||||
|
||||
#### Fedora
|
||||
```
|
||||
sudo dnf install clang git cmake libatomic alsa-lib-devel pipewire-jack-audio-connection-kit-devel openal-devel openssl-devel libevdev-devel libudev-devel libXext-devel qt6-qtbase-devel qt6-qtbase-private-devel qt6-qtmultimedia-devel qt6-qtsvg-devel qt6-qttools-devel vulkan-devel vulkan-validation-layers
|
||||
|
||||
```bash
|
||||
sudo dnf install clang git cmake libatomic alsa-lib-devel \
|
||||
pipewire-jack-audio-connection-kit-devel openal-devel \
|
||||
openssl-devel libevdev-devel libudev-devel libXext-devel \
|
||||
qt6-qtbase-devel qt6-qtbase-private-devel \
|
||||
qt6-qtmultimedia-devel qt6-qtsvg-devel qt6-qttools-devel \
|
||||
vulkan-devel vulkan-validation-layers libpng-devel
|
||||
```
|
||||
|
||||
#### Arch Linux
|
||||
|
||||
```bash
|
||||
sudo pacman -S base-devel clang git cmake sndio jack2 openal \
|
||||
qt6-base qt6-declarative qt6-multimedia qt6-tools sdl2 \
|
||||
vulkan-validation-layers libpng
|
||||
```
|
||||
sudo pacman -S base-devel clang git cmake sndio jack2 openal qt6-base qt6-declarative qt6-multimedia sdl2 vulkan-validation-layers
|
||||
```
|
||||
|
||||
**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.
|
||||
|
||||
#### OpenSUSE
|
||||
```
|
||||
sudo zypper install clang git cmake libasound2 libpulse-devel libsndio7 libjack-devel openal-soft-devel libopenssl-devel zlib-devel libedit-devel systemd-devel libevdev-devel qt6-base-devel qt6-multimedia-devel qt6-svg-devel qt6-linguist-devel qt6-gui-private-devel vulkan-devel vulkan-validationlayers
|
||||
```
|
||||
### Cloning and compiling:
|
||||
|
||||
Clone the repository recursively:
|
||||
```bash
|
||||
sudo zypper install clang git cmake libasound2 libpulse-devel \
|
||||
libsndio7 libjack-devel openal-soft-devel libopenssl-devel \
|
||||
zlib-devel libedit-devel systemd-devel libevdev-devel \
|
||||
qt6-base-devel qt6-multimedia-devel qt6-svg-devel \
|
||||
qt6-linguist-devel qt6-gui-private-devel vulkan-devel \
|
||||
vulkan-validationlayers libpng-devel
|
||||
```
|
||||
|
||||
#### NixOS
|
||||
|
||||
```bash
|
||||
nix-shell shell.nix
|
||||
```
|
||||
|
||||
#### Other Linux distributions
|
||||
|
||||
You can try one of two methods:
|
||||
|
||||
- Search the packages by name and install them with your package manager, or
|
||||
- Install [distrobox](https://distrobox.it/), create a container using any of the distributions cited above as a base, for Arch Linux you'd do:
|
||||
|
||||
```bash
|
||||
distrobox create --name archlinux --init --image archlinux:latest
|
||||
```
|
||||
|
||||
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).
|
||||
|
||||
### Cloning
|
||||
|
||||
```bash
|
||||
git clone --recursive https://github.com/shadps4-emu/shadPS4.git
|
||||
cd shadPS4
|
||||
```
|
||||
|
||||
Generate the build directory in the shadPS4 directory. To disable the QT GUI, remove the ```-DENABLE_QT_GUI=ON``` flag:
|
||||
## Building
|
||||
|
||||
**Note**: Clang is the compiler used for official builds and CI. If you build with GCC, you might encounter issues—please report any you find. If you choose to use GCC, we recommend building with Clang at least once before submitting a pull request.
|
||||
```
|
||||
There are 3 options you can choose from. Option 1 is **highly recommended**.
|
||||
|
||||
#### Option 1: Terminal-only
|
||||
|
||||
1. Generate the build directory in the shadPS4 directory.
|
||||
|
||||
```bash
|
||||
cmake -S . -B build/ -DENABLE_QT_GUI=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
||||
```
|
||||
|
||||
Enter the directory:
|
||||
```
|
||||
cd build/
|
||||
To disable the Qt GUI, remove the `-DENABLE_QT_GUI=ON` flag. To change the build type (for debugging), add `-DCMAKE_BUILD_TYPE=Debug`.
|
||||
|
||||
2. Use CMake to build the project:
|
||||
|
||||
```bash
|
||||
cmake --build ./build --parallel$(nproc)
|
||||
```
|
||||
|
||||
Use make to build the project:
|
||||
```
|
||||
cmake --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)`.
|
||||
|
||||
Now run the emulator. If Qt was enabled at configure time:
|
||||
|
||||
```bash
|
||||
./build/shadps4
|
||||
```
|
||||
|
||||
Now run the emulator. If QT is enabled:
|
||||
```
|
||||
./shadps4
|
||||
```
|
||||
Otherwise, specify the path to your PKG's boot file:
|
||||
```
|
||||
./shadps4 /"PATH"/"TO"/"GAME"/"FOLDER"/eboot.bin
|
||||
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).
|
||||
#### Option 2: Configuring with cmake-gui
|
||||
|
||||
`cmake-gui` should be installed by default alongside `cmake`, if not search for the package in your package manager and install it.
|
||||
|
||||
Open `cmake-gui` and specify the source code and build directories. If you cloned the source code to your Home directory, it would be `/home/user/shadPS4` and `/home/user/shadPS4/build`.
|
||||
|
||||
Click on Configure, select "Unix Makefiles", select "Specify native compilers", click Next and choose `clang` and `clang++` as the C and CXX compilers. Usually they are located in `/bin/clang` and `/bin/clang++`. Click on Finish and let it configure the project.
|
||||
|
||||
Now every option should be displayed in red. Change anything you want, then click on Generate to make the changes permanent, then open a terminal window and do step 2 of Option 1.
|
||||
|
||||
#### Option 3: Visual Studio Code
|
||||
|
||||
This option is pretty convoluted and should only be used if you have VSCode as your default IDE, or just prefer building and debugging projects through it. This also assumes that you're using an Arch Linux environment, as the naming for some options might differ from other distros.
|
||||
|
||||
[Download Visual Studio Code for your platform](https://code.visualstudio.com/download), or use [Code - OSS](https://github.com/microsoft/vscode) if you'd like. Code - OSS is available on most Linux distributions' package repositories (on Arch Linux it is simply named `code`).
|
||||
|
||||
Once set up, go to Extensions and install "CMake Tools":
|
||||
|
||||

|
||||
|
||||
You can also install other CMake and Clang related extensions if you'd like, but this one is what enables you to configure and build CMake projects directly within VSCode.
|
||||
|
||||
Go to Settings, filter by `@ext:ms-vscode.cmake-tools configure` and disable this option:
|
||||
|
||||

|
||||
|
||||
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:
|
||||
|
||||

|
||||
|
||||
When hovering over Project Status > Configure, there should be an icon titled "Configure". Click on it and let it configure the project, then do the same for Project Status > Build.
|
||||
|
||||
If you want to debug it, change the build type under Project Status > Configure to Debug (it should be the default) and compile it, then click on the icon in Project Status > Debug. If you simply want to launch the shadPS4 executable from within VSCode, click on the icon in Project Status > Launch.
|
||||
|
||||
Don't forget to change the launch target for both options to the shadPS4 executable inside shadPS4/build:
|
||||
|
||||

|
||||
|
|
|
@ -25,7 +25,7 @@ Once you are within the installer:
|
|||
|
||||
Beware, this requires you to create a Qt account. If you do not want to do this, please follow the MSYS2/MinGW compilation method instead.
|
||||
|
||||
1. Under the current, non beta version of Qt (at the time of writing 6.7.3), select the option `MSVC 2022 64-bit` or similar.
|
||||
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.
|
||||
|
@ -35,7 +35,7 @@ Beware, this requires you to create a Qt account. If you do not want to do this,
|
|||
Once you are finished, you will have to configure Qt within Visual Studio:
|
||||
|
||||
1. Tools -> Options -> Qt -> Versions
|
||||
2. Add a new Qt version and navigate it to the correct folder. Should look like so: `C:\Qt\6.7.3\msvc2022_64`
|
||||
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)
|
||||
|
@ -55,7 +55,7 @@ Go through the Git for Windows installation as normal
|
|||
3. If you want to build shadPS4 with the Qt Gui:
|
||||
1. Click x64-Clang-Release and select "Manage Configurations"
|
||||
2. Look for "CMake command arguments" and add to the text field
|
||||
`-DENABLE_QT_GUI=ON -DCMAKE_PREFIX_PATH=C:\Qt\6.7.3\msvc2022_64`
|
||||
`-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
|
||||
|
@ -64,11 +64,14 @@ Go through the Git for Windows installation as normal
|
|||
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.7.3\msvc2022_64\bin\windeployqt.exe "C:\path\to\shadps4.exe"`
|
||||
`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
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Building with MSYS2 is broken as of right now, the only way to build on Windows is to use [Option 1: Visual Studio 2022](https://github.com/shadps4-emu/shadPS4/blob/main/documents/building-windows.md#option-1-visual-studio-2022).
|
||||
|
||||
### (Prerequisite) Download [**MSYS2**](https://www.msys2.org/)
|
||||
|
||||
Go through the MSYS2 installation as normal
|
||||
|
|
38
externals/CMakeLists.txt
vendored
38
externals/CMakeLists.txt
vendored
|
@ -18,8 +18,6 @@ endif()
|
|||
|
||||
# Boost
|
||||
if (NOT TARGET Boost::headers)
|
||||
set(BOOST_ROOT "${CMAKE_SOURCE_DIR}/externals/ext-boost" CACHE STRING "")
|
||||
set(Boost_NO_SYSTEM_PATHS ON CACHE BOOL "")
|
||||
add_subdirectory(ext-boost)
|
||||
endif()
|
||||
|
||||
|
@ -28,24 +26,7 @@ if (NOT TARGET fmt::fmt)
|
|||
add_subdirectory(fmt)
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND MSVC)
|
||||
# If it is clang and MSVC we will add a static lib
|
||||
# CryptoPP
|
||||
add_subdirectory(cryptoppwin)
|
||||
target_include_directories(cryptoppwin INTERFACE cryptoppwin/include)
|
||||
else()
|
||||
# CryptoPP
|
||||
if (NOT TARGET cryptopp::cryptopp)
|
||||
set(CRYPTOPP_INSTALL OFF)
|
||||
set(CRYPTOPP_BUILD_TESTING OFF)
|
||||
set(CRYPTOPP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/cryptopp)
|
||||
add_subdirectory(cryptopp-cmake)
|
||||
file(COPY cryptopp DESTINATION cryptopp FILES_MATCHING PATTERN "*.h")
|
||||
# remove externals/cryptopp from include directories because it contains a conflicting zlib.h file
|
||||
set_target_properties(cryptopp PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/cryptopp")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# FFmpeg
|
||||
if (NOT TARGET FFmpeg::ffmpeg)
|
||||
add_subdirectory(ffmpeg-core)
|
||||
add_library(FFmpeg::ffmpeg ALIAS ffmpeg)
|
||||
|
@ -77,6 +58,7 @@ endif()
|
|||
|
||||
# SDL3
|
||||
if (NOT TARGET SDL3::SDL3)
|
||||
set(SDL_TEST_LIBRARY OFF)
|
||||
set(SDL_PIPEWIRE OFF)
|
||||
add_subdirectory(sdl3)
|
||||
endif()
|
||||
|
@ -131,6 +113,14 @@ endif()
|
|||
# Toml11
|
||||
if (NOT TARGET toml11::toml11)
|
||||
add_subdirectory(toml11)
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
|
||||
get_target_property(_toml11_compile_options toml11 INTERFACE_COMPILE_OPTIONS)
|
||||
list(REMOVE_ITEM _toml11_compile_options "/Zc:preprocessor")
|
||||
set_target_properties(toml11 PROPERTIES INTERFACE_COMPILE_OPTIONS ${_toml11_compile_options})
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# xxHash
|
||||
|
@ -211,11 +201,15 @@ if (NOT TARGET pugixml::pugixml)
|
|||
add_subdirectory(pugixml)
|
||||
endif()
|
||||
|
||||
# libusb
|
||||
if (NOT TARGET libusb::usb)
|
||||
add_subdirectory(libusb)
|
||||
add_library(libusb::usb ALIAS usb-1.0)
|
||||
endif()
|
||||
|
||||
# Discord RPC
|
||||
if (ENABLE_DISCORD_RPC)
|
||||
set(BUILD_EXAMPLES OFF)
|
||||
add_subdirectory(discord-rpc)
|
||||
target_include_directories(discord-rpc INTERFACE discord-rpc/include)
|
||||
endif()
|
||||
|
||||
# GCN Headers
|
||||
|
|
2
externals/LibAtrac9
vendored
2
externals/LibAtrac9
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 9640129dc6f2afbca6ceeca3019856e8653a5fb2
|
||||
Subproject commit ec8899dadf393f655f2871a94e0fe4b3d6220c9a
|
2
externals/MoltenVK/MoltenVK
vendored
2
externals/MoltenVK/MoltenVK
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 5ad3ee5d2f84342950c3fe93dec97719574d1932
|
||||
Subproject commit 87a8e8b13d4ad8835367fea1ebad1896d0460946
|
8
externals/MoltenVK/MoltenVK_icd.json
vendored
8
externals/MoltenVK/MoltenVK_icd.json
vendored
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"file_format_version": "1.0.0",
|
||||
"ICD": {
|
||||
"library_path": "../../../Frameworks/libMoltenVK.dylib",
|
||||
"api_version": "1.2.0",
|
||||
"is_portability_driver": true
|
||||
}
|
||||
}
|
2
externals/MoltenVK/SPIRV-Cross
vendored
2
externals/MoltenVK/SPIRV-Cross
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 6173e24b31f09a0c3217103a130e74c4ddec14a6
|
||||
Subproject commit 7918775748c5e2f5c40d9918ce68825035b5a1e1
|
2
externals/MoltenVK/cereal
vendored
2
externals/MoltenVK/cereal
vendored
|
@ -1 +1 @@
|
|||
Subproject commit d1fcec807b372f04e4c1041b3058e11c12853e6e
|
||||
Subproject commit a56bad8bbb770ee266e930c95d37fff2a5be7fea
|
1
externals/cryptopp
vendored
1
externals/cryptopp
vendored
|
@ -1 +0,0 @@
|
|||
Subproject commit 60f81a77e0c9a0e7ffc1ca1bc438ddfa2e43b78e
|
1
externals/cryptopp-cmake
vendored
1
externals/cryptopp-cmake
vendored
|
@ -1 +0,0 @@
|
|||
Subproject commit 2c384c28265a93358a2455e610e76393358794df
|
1
externals/cryptoppwin
vendored
1
externals/cryptoppwin
vendored
|
@ -1 +0,0 @@
|
|||
Subproject commit bc3441dd2d6a9728e747dc0180bc8b9065a2923c
|
2
externals/date
vendored
2
externals/date
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 28b7b232521ace2c8ef3f2ad4126daec3569c14f
|
||||
Subproject commit a45ea7c17b4a7f320e199b71436074bd624c9e15
|
2
externals/dear_imgui
vendored
2
externals/dear_imgui
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 636cd4a7d623a2bc9bf59bb3acbb4ca075befba3
|
||||
Subproject commit f4d9359095eff3eb03f685921edc1cf0e37b1687
|
2
externals/discord-rpc
vendored
2
externals/discord-rpc
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 4ec218155d73bcb8022f8f7ca72305d801f84beb
|
||||
Subproject commit 19f66e6dcabb2268965f453db9e5774ede43238f
|
2
externals/ffmpeg-core
vendored
2
externals/ffmpeg-core
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 27de97c826b6b40c255891c37ac046a25836a575
|
||||
Subproject commit b0de1dcca26c0ebfb8011b8e59dd17fc399db0ff
|
2
externals/fmt
vendored
2
externals/fmt
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 8ee89546ffcf046309d1f0d38c0393f02fde56c8
|
||||
Subproject commit 64db979e38ec644b1798e41610b28c8d2c8a2739
|
6
externals/gcn/CMakeLists.txt
vendored
6
externals/gcn/CMakeLists.txt
vendored
|
@ -3,6 +3,10 @@
|
|||
|
||||
project(gcn LANGUAGES CXX)
|
||||
|
||||
add_library(gcn dummy.cpp)
|
||||
add_library(gcn INTERFACE)
|
||||
target_sources(gcn PRIVATE
|
||||
"include/gcn/si_ci_vi_merged_offset.h"
|
||||
"include/gcn/si_ci_vi_merged_pm4_it_opcodes.h"
|
||||
)
|
||||
|
||||
target_include_directories(gcn INTERFACE include)
|
||||
|
|
2
externals/gcn/dummy.cpp
vendored
2
externals/gcn/dummy.cpp
vendored
|
@ -1,2 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
2
externals/glslang
vendored
2
externals/glslang
vendored
|
@ -1 +1 @@
|
|||
Subproject commit a0995c49ebcaca2c6d3b03efbabf74f3843decdb
|
||||
Subproject commit ba1640446f3826a518721d1f083f3a8cca1120c3
|
1
externals/libusb
vendored
Submodule
1
externals/libusb
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit a63a7e43e0950a595cf4b98a0eaf4051749ace5f
|
2
externals/magic_enum
vendored
2
externals/magic_enum
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 1a1824df7ac798177a521eed952720681b0bf482
|
||||
Subproject commit a413fcc9c46a020a746907136a384c227f3cd095
|
2
externals/pugixml
vendored
2
externals/pugixml
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 4bc14418d12d289dd9978fdce9490a45deeb653e
|
||||
Subproject commit caade5a28aad86b92a4b5337a9dc70c4ba73c5eb
|
2
externals/robin-map
vendored
2
externals/robin-map
vendored
|
@ -1 +1 @@
|
|||
Subproject commit fe845fd7852ef541c5479ae23b3d36b57f8608ee
|
||||
Subproject commit 4ec1bf19c6a96125ea22062f38c2cf5b958e448e
|
2
externals/sdl3
vendored
2
externals/sdl3
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 3a1d76d298db023f6cf37fb08ee766f20a4e12ab
|
||||
Subproject commit 4093e4a193971ef1d4928158e0a1832be42e4599
|
2
externals/sirit
vendored
2
externals/sirit
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 1e74f4ef8d2a0e3221a4de51977663f342b53c35
|
||||
Subproject commit 427a42c9ed99b38204d9107bc3dc14e92458acf1
|
2
externals/toml11
vendored
2
externals/toml11
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 7f6c574ff5aa1053534e7e19c0a4f22bf4c6aaca
|
||||
Subproject commit a01fe3b4c14c6d7b99ee3f07c9e80058c6403097
|
2
externals/vma
vendored
2
externals/vma
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 5a53a198945ba8260fbc58fadb788745ce6aa263
|
||||
Subproject commit f378e7b3f18f6e2b06b957f6ba7b1c7207d2a536
|
2
externals/vulkan-headers
vendored
2
externals/vulkan-headers
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 6a74a7d65cafa19e38ec116651436cce6efd5b2e
|
||||
Subproject commit 5ceb9ed481e58e705d0d9b5326537daedd06b97d
|
2
externals/winpthreads
vendored
2
externals/winpthreads
vendored
|
@ -1 +1 @@
|
|||
Subproject commit f00c973a6ab2a23573708568b8ef4acc20a9d36b
|
||||
Subproject commit f35b0948d36a736e6a2d052ae295a3ffde09703f
|
2
externals/xbyak
vendored
2
externals/xbyak
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 4e44f4614ddbf038f2a6296f5b906d5c72691e0f
|
||||
Subproject commit 44a72f369268f7d552650891b296693e91db86bb
|
2
externals/xxhash
vendored
2
externals/xxhash
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 2bf8313b934633b2a5b7e8fd239645b85e10c852
|
||||
Subproject commit 953a09abc39096da9e216b6eb0002c681cdc1199
|
2
externals/zlib-ng
vendored
2
externals/zlib-ng
vendored
|
@ -1 +1 @@
|
|||
Subproject commit d54e3769be0c522015b784eca2af258b1c026107
|
||||
Subproject commit fd0d263cedab1a136f40d65199987e3eaeecfcbd
|
2
externals/zydis
vendored
2
externals/zydis
vendored
|
@ -1 +1 @@
|
|||
Subproject commit bffbb610cfea643b98e87658b9058382f7522807
|
||||
Subproject commit 120e0e705f8e3b507dc49377ac2879979f0d545c
|
71
shell.nix
Normal file
71
shell.nix
Normal file
|
@ -0,0 +1,71 @@
|
|||
# SPDX-FileCopyrightText: 2024 shadPS4 Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
with import (fetchTarball "https://github.com/nixos/nixpkgs/archive/cfd19cdc54680956dc1816ac577abba6b58b901c.tar.gz") { };
|
||||
|
||||
pkgs.mkShell {
|
||||
name = "shadps4-build-env";
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkgs.llvmPackages_18.clang
|
||||
pkgs.cmake
|
||||
pkgs.pkg-config
|
||||
pkgs.git
|
||||
];
|
||||
|
||||
buildInputs = [
|
||||
pkgs.alsa-lib
|
||||
pkgs.libpulseaudio
|
||||
pkgs.openal
|
||||
pkgs.openssl
|
||||
pkgs.zlib
|
||||
pkgs.libedit
|
||||
pkgs.udev
|
||||
pkgs.libevdev
|
||||
pkgs.SDL2
|
||||
pkgs.jack2
|
||||
pkgs.sndio
|
||||
pkgs.qt6.qtbase
|
||||
pkgs.qt6.qttools
|
||||
pkgs.qt6.qtmultimedia
|
||||
|
||||
pkgs.vulkan-headers
|
||||
pkgs.vulkan-utility-libraries
|
||||
pkgs.vulkan-tools
|
||||
|
||||
pkgs.ffmpeg
|
||||
pkgs.fmt
|
||||
pkgs.glslang
|
||||
pkgs.libxkbcommon
|
||||
pkgs.wayland
|
||||
pkgs.xorg.libxcb
|
||||
pkgs.xorg.xcbutil
|
||||
pkgs.xorg.xcbutilkeysyms
|
||||
pkgs.xorg.xcbutilwm
|
||||
pkgs.sdl3
|
||||
pkgs.stb
|
||||
pkgs.qt6.qtwayland
|
||||
pkgs.wayland-protocols
|
||||
pkgs.libpng
|
||||
];
|
||||
|
||||
shellHook = ''
|
||||
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"
|
||||
|
||||
# OpenGL
|
||||
export LD_LIBRARY_PATH="${
|
||||
pkgs.lib.makeLibraryPath [
|
||||
pkgs.libglvnd
|
||||
pkgs.vulkan-tools
|
||||
]
|
||||
}:$LD_LIBRARY_PATH"
|
||||
|
||||
export LDFLAGS="-L${pkgs.llvmPackages_18.libcxx}/lib -lc++"
|
||||
export LC_ALL="C.UTF-8"
|
||||
export XAUTHORITY=${builtins.getEnv "XAUTHORITY"}
|
||||
'';
|
||||
}
|
27
src/common/adaptive_mutex.h
Normal file
27
src/common/adaptive_mutex.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __linux__
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
namespace Common {
|
||||
|
||||
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
|
||||
class AdaptiveMutex {
|
||||
public:
|
||||
void lock() {
|
||||
pthread_mutex_lock(&mutex);
|
||||
}
|
||||
void unlock() {
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
private:
|
||||
pthread_mutex_t mutex = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;
|
||||
};
|
||||
#endif // PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
|
||||
|
||||
} // namespace Common
|
1195
src/common/aes.h
Normal file
1195
src/common/aes.h
Normal file
File diff suppressed because it is too large
Load diff
|
@ -7,10 +7,10 @@
|
|||
#include <fmt/xchar.h> // for wstring support
|
||||
#include <toml.hpp>
|
||||
|
||||
#include "common/config.h"
|
||||
#include "common/logging/formatter.h"
|
||||
#include "common/path_util.h"
|
||||
#include "config.h"
|
||||
#include "logging/formatter.h"
|
||||
#include "version.h"
|
||||
#include "common/scm_rev.h"
|
||||
|
||||
namespace toml {
|
||||
template <typename TC, typename K>
|
||||
|
@ -32,7 +32,7 @@ std::filesystem::path find_fs_path_or(const basic_value<TC>& v, const K& ky,
|
|||
namespace Config {
|
||||
|
||||
static bool isNeo = false;
|
||||
static bool isFullscreen = false;
|
||||
static bool isDevKit = false;
|
||||
static bool playBGM = false;
|
||||
static bool isTrophyPopupDisabled = false;
|
||||
static int BGMvolume = 50;
|
||||
|
@ -41,16 +41,20 @@ static u32 screenWidth = 1280;
|
|||
static u32 screenHeight = 720;
|
||||
static s32 gpuId = -1; // Vulkan physical device index. Set to negative for auto select
|
||||
static std::string logFilter;
|
||||
static std::string logType = "async";
|
||||
static std::string logType = "sync";
|
||||
static std::string userName = "shadPS4";
|
||||
static std::string updateChannel;
|
||||
static std::string chooseHomeTab;
|
||||
static std::string backButtonBehavior = "left";
|
||||
static bool useSpecialPad = false;
|
||||
static int specialPadClass = 1;
|
||||
static bool isMotionControlsEnabled = true;
|
||||
static bool isDebugDump = false;
|
||||
static bool isShaderDebug = false;
|
||||
static bool isShowSplash = false;
|
||||
static bool isAutoUpdate = false;
|
||||
static bool isAlwaysShowChangelog = false;
|
||||
static std::string isSideTrophy = "right";
|
||||
static bool isNullGpu = false;
|
||||
static bool shouldCopyGPUBuffers = false;
|
||||
static bool shouldDumpShaders = false;
|
||||
|
@ -59,18 +63,28 @@ static u32 vblankDivider = 1;
|
|||
static bool vkValidation = false;
|
||||
static bool vkValidationSync = false;
|
||||
static bool vkValidationGpu = false;
|
||||
static bool rdocEnable = false;
|
||||
static bool vkMarkers = false;
|
||||
static bool vkCrashDiagnostic = false;
|
||||
static bool vkHostMarkers = false;
|
||||
static bool vkGuestMarkers = false;
|
||||
static bool rdocEnable = false;
|
||||
static bool isFpsColor = true;
|
||||
static bool isSeparateLogFilesEnabled = false;
|
||||
static s16 cursorState = HideCursorState::Idle;
|
||||
static int cursorHideTimeout = 5; // 5 seconds (default)
|
||||
static bool separateupdatefolder = false;
|
||||
static double trophyNotificationDuration = 6.0;
|
||||
static bool useUnifiedInputConfig = true;
|
||||
static bool overrideControllerColor = false;
|
||||
static int controllerCustomColorRGB[3] = {0, 0, 255};
|
||||
static bool compatibilityData = false;
|
||||
static bool checkCompatibilityOnStartup = false;
|
||||
static std::string trophyKey;
|
||||
|
||||
// Gui
|
||||
std::vector<std::filesystem::path> settings_install_dirs = {};
|
||||
static bool load_game_size = true;
|
||||
static std::vector<GameInstallDir> settings_install_dirs = {};
|
||||
std::vector<bool> install_dirs_enabled = {};
|
||||
std::filesystem::path settings_addon_install_dir = {};
|
||||
std::filesystem::path save_data_path = {};
|
||||
u32 main_window_geometry_x = 400;
|
||||
u32 main_window_geometry_y = 400;
|
||||
u32 main_window_geometry_w = 1280;
|
||||
|
@ -83,22 +97,96 @@ u32 m_slider_pos_grid = 0;
|
|||
u32 m_table_mode = 0;
|
||||
u32 m_window_size_W = 1280;
|
||||
u32 m_window_size_H = 720;
|
||||
std::vector<std::string> m_pkg_viewer;
|
||||
std::vector<std::string> m_elf_viewer;
|
||||
std::vector<std::string> m_recent_files;
|
||||
std::string emulator_language = "en";
|
||||
std::string emulator_language = "en_US";
|
||||
static int backgroundImageOpacity = 50;
|
||||
static bool showBackgroundImage = true;
|
||||
static bool isFullscreen = false;
|
||||
static std::string fullscreenMode = "Windowed";
|
||||
static bool isHDRAllowed = false;
|
||||
static bool showLabelsUnderIcons = true;
|
||||
|
||||
// Language
|
||||
u32 m_language = 1; // english
|
||||
|
||||
bool isNeoMode() {
|
||||
bool allowHDR() {
|
||||
return isHDRAllowed;
|
||||
}
|
||||
|
||||
bool GetUseUnifiedInputConfig() {
|
||||
return useUnifiedInputConfig;
|
||||
}
|
||||
|
||||
void SetUseUnifiedInputConfig(bool use) {
|
||||
useUnifiedInputConfig = use;
|
||||
}
|
||||
|
||||
bool GetOverrideControllerColor() {
|
||||
return overrideControllerColor;
|
||||
}
|
||||
|
||||
void SetOverrideControllerColor(bool enable) {
|
||||
overrideControllerColor = enable;
|
||||
}
|
||||
|
||||
int* GetControllerCustomColor() {
|
||||
return controllerCustomColorRGB;
|
||||
}
|
||||
|
||||
void SetControllerCustomColor(int r, int b, int g) {
|
||||
controllerCustomColorRGB[0] = r;
|
||||
controllerCustomColorRGB[1] = b;
|
||||
controllerCustomColorRGB[2] = g;
|
||||
}
|
||||
|
||||
std::string getTrophyKey() {
|
||||
return trophyKey;
|
||||
}
|
||||
|
||||
void setTrophyKey(std::string key) {
|
||||
trophyKey = key;
|
||||
}
|
||||
|
||||
bool GetLoadGameSizeEnabled() {
|
||||
return load_game_size;
|
||||
}
|
||||
|
||||
std::filesystem::path GetSaveDataPath() {
|
||||
if (save_data_path.empty()) {
|
||||
return Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir);
|
||||
}
|
||||
return save_data_path;
|
||||
}
|
||||
|
||||
void setLoadGameSizeEnabled(bool enable) {
|
||||
load_game_size = enable;
|
||||
}
|
||||
|
||||
bool isNeoModeConsole() {
|
||||
return isNeo;
|
||||
}
|
||||
|
||||
bool isFullscreenMode() {
|
||||
bool isDevKitConsole() {
|
||||
return isDevKit;
|
||||
}
|
||||
|
||||
bool getIsFullscreen() {
|
||||
return isFullscreen;
|
||||
}
|
||||
|
||||
bool getShowLabelsUnderIcons() {
|
||||
return showLabelsUnderIcons;
|
||||
}
|
||||
|
||||
bool setShowLabelsUnderIcons() {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string getFullscreenMode() {
|
||||
return fullscreenMode;
|
||||
}
|
||||
|
||||
bool getisTrophyPopupDisabled() {
|
||||
return isTrophyPopupDisabled;
|
||||
}
|
||||
|
@ -123,6 +211,10 @@ int getCursorHideTimeout() {
|
|||
return cursorHideTimeout;
|
||||
}
|
||||
|
||||
double getTrophyNotificationDuration() {
|
||||
return trophyNotificationDuration;
|
||||
}
|
||||
|
||||
u32 getScreenWidth() {
|
||||
return screenWidth;
|
||||
}
|
||||
|
@ -151,6 +243,10 @@ std::string getUpdateChannel() {
|
|||
return updateChannel;
|
||||
}
|
||||
|
||||
std::string getChooseHomeTab() {
|
||||
return chooseHomeTab;
|
||||
}
|
||||
|
||||
std::string getBackButtonBehavior() {
|
||||
return backButtonBehavior;
|
||||
}
|
||||
|
@ -163,6 +259,10 @@ int getSpecialPadClass() {
|
|||
return specialPadClass;
|
||||
}
|
||||
|
||||
bool getIsMotionControlsEnabled() {
|
||||
return isMotionControlsEnabled;
|
||||
}
|
||||
|
||||
bool debugDump() {
|
||||
return isDebugDump;
|
||||
}
|
||||
|
@ -179,6 +279,14 @@ bool autoUpdate() {
|
|||
return isAutoUpdate;
|
||||
}
|
||||
|
||||
bool alwaysShowChangelog() {
|
||||
return isAlwaysShowChangelog;
|
||||
}
|
||||
|
||||
std::string sideTrophy() {
|
||||
return isSideTrophy;
|
||||
}
|
||||
|
||||
bool nullGpu() {
|
||||
return isNullGpu;
|
||||
}
|
||||
|
@ -199,8 +307,8 @@ bool isRdocEnabled() {
|
|||
return rdocEnable;
|
||||
}
|
||||
|
||||
bool isMarkersEnabled() {
|
||||
return vkMarkers;
|
||||
bool fpsColor() {
|
||||
return isFpsColor;
|
||||
}
|
||||
|
||||
u32 vblankDiv() {
|
||||
|
@ -219,16 +327,28 @@ bool vkValidationGpuEnabled() {
|
|||
return vkValidationGpu;
|
||||
}
|
||||
|
||||
bool vkMarkersEnabled() {
|
||||
return vkMarkers || vkCrashDiagnostic; // Crash diagnostic forces markers on
|
||||
}
|
||||
|
||||
bool vkCrashDiagnosticEnabled() {
|
||||
bool getVkCrashDiagnosticEnabled() {
|
||||
return vkCrashDiagnostic;
|
||||
}
|
||||
|
||||
bool getSeparateUpdateEnabled() {
|
||||
return separateupdatefolder;
|
||||
bool getVkHostMarkersEnabled() {
|
||||
return vkHostMarkers;
|
||||
}
|
||||
|
||||
bool getVkGuestMarkersEnabled() {
|
||||
return vkGuestMarkers;
|
||||
}
|
||||
|
||||
void setVkCrashDiagnosticEnabled(bool enable) {
|
||||
vkCrashDiagnostic = enable;
|
||||
}
|
||||
|
||||
void setVkHostMarkersEnabled(bool enable) {
|
||||
vkHostMarkers = enable;
|
||||
}
|
||||
|
||||
void setVkGuestMarkersEnabled(bool enable) {
|
||||
vkGuestMarkers = enable;
|
||||
}
|
||||
|
||||
bool getCompatibilityEnabled() {
|
||||
|
@ -267,10 +387,22 @@ void setAutoUpdate(bool enable) {
|
|||
isAutoUpdate = enable;
|
||||
}
|
||||
|
||||
void setAlwaysShowChangelog(bool enable) {
|
||||
isAlwaysShowChangelog = enable;
|
||||
}
|
||||
|
||||
void setSideTrophy(std::string side) {
|
||||
isSideTrophy = side;
|
||||
}
|
||||
|
||||
void setNullGpu(bool enable) {
|
||||
isNullGpu = enable;
|
||||
}
|
||||
|
||||
void setAllowHDR(bool enable) {
|
||||
isHDRAllowed = enable;
|
||||
}
|
||||
|
||||
void setCopyGPUCmdBuffers(bool enable) {
|
||||
shouldCopyGPUBuffers = enable;
|
||||
}
|
||||
|
@ -295,9 +427,16 @@ void setVblankDiv(u32 value) {
|
|||
vblankDivider = value;
|
||||
}
|
||||
|
||||
void setFullscreenMode(bool enable) {
|
||||
void setIsFullscreen(bool enable) {
|
||||
isFullscreen = enable;
|
||||
}
|
||||
static void setShowLabelsUnderIcons(bool enable) {
|
||||
showLabelsUnderIcons = enable;
|
||||
}
|
||||
|
||||
void setFullscreenMode(std::string mode) {
|
||||
fullscreenMode = mode;
|
||||
}
|
||||
|
||||
void setisTrophyPopupDisabled(bool disable) {
|
||||
isTrophyPopupDisabled = disable;
|
||||
|
@ -322,6 +461,9 @@ void setCursorState(s16 newCursorState) {
|
|||
void setCursorHideTimeout(int newcursorHideTimeout) {
|
||||
cursorHideTimeout = newcursorHideTimeout;
|
||||
}
|
||||
void setTrophyNotificationDuration(double newTrophyNotificationDuration) {
|
||||
trophyNotificationDuration = newTrophyNotificationDuration;
|
||||
}
|
||||
|
||||
void setLanguage(u32 language) {
|
||||
m_language = language;
|
||||
|
@ -339,6 +481,10 @@ void setLogFilter(const std::string& type) {
|
|||
logFilter = type;
|
||||
}
|
||||
|
||||
void setSeparateLogFilesEnabled(bool enabled) {
|
||||
isSeparateLogFilesEnabled = enabled;
|
||||
}
|
||||
|
||||
void setUserName(const std::string& type) {
|
||||
userName = type;
|
||||
}
|
||||
|
@ -346,6 +492,9 @@ void setUserName(const std::string& type) {
|
|||
void setUpdateChannel(const std::string& type) {
|
||||
updateChannel = type;
|
||||
}
|
||||
void setChooseHomeTab(const std::string& type) {
|
||||
chooseHomeTab = type;
|
||||
}
|
||||
|
||||
void setBackButtonBehavior(const std::string& type) {
|
||||
backButtonBehavior = type;
|
||||
|
@ -359,8 +508,8 @@ void setSpecialPadClass(int type) {
|
|||
specialPadClass = type;
|
||||
}
|
||||
|
||||
void setSeparateUpdateEnabled(bool use) {
|
||||
separateupdatefolder = use;
|
||||
void setIsMotionControlsEnabled(bool use) {
|
||||
isMotionControlsEnabled = use;
|
||||
}
|
||||
|
||||
void setCompatibilityEnabled(bool use) {
|
||||
|
@ -378,22 +527,34 @@ void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h) {
|
|||
main_window_geometry_h = h;
|
||||
}
|
||||
|
||||
bool addGameInstallDir(const std::filesystem::path& dir) {
|
||||
if (std::find(settings_install_dirs.begin(), settings_install_dirs.end(), dir) ==
|
||||
settings_install_dirs.end()) {
|
||||
settings_install_dirs.push_back(dir);
|
||||
return true;
|
||||
}
|
||||
bool addGameInstallDir(const std::filesystem::path& dir, bool enabled) {
|
||||
for (const auto& install_dir : settings_install_dirs) {
|
||||
if (install_dir.path == dir) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
settings_install_dirs.push_back({dir, enabled});
|
||||
return true;
|
||||
}
|
||||
|
||||
void removeGameInstallDir(const std::filesystem::path& dir) {
|
||||
auto iterator = std::find(settings_install_dirs.begin(), settings_install_dirs.end(), dir);
|
||||
auto iterator =
|
||||
std::find_if(settings_install_dirs.begin(), settings_install_dirs.end(),
|
||||
[&dir](const GameInstallDir& install_dir) { return install_dir.path == dir; });
|
||||
if (iterator != settings_install_dirs.end()) {
|
||||
settings_install_dirs.erase(iterator);
|
||||
}
|
||||
}
|
||||
|
||||
void setGameInstallDirEnabled(const std::filesystem::path& dir, bool enabled) {
|
||||
auto iterator =
|
||||
std::find_if(settings_install_dirs.begin(), settings_install_dirs.end(),
|
||||
[&dir](const GameInstallDir& install_dir) { return install_dir.path == dir; });
|
||||
if (iterator != settings_install_dirs.end()) {
|
||||
iterator->enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
void setAddonInstallDir(const std::filesystem::path& dir) {
|
||||
settings_addon_install_dir = dir;
|
||||
}
|
||||
|
@ -430,11 +591,6 @@ void setMainWindowHeight(u32 height) {
|
|||
m_window_size_H = height;
|
||||
}
|
||||
|
||||
void setPkgViewer(const std::vector<std::string>& pkgList) {
|
||||
m_pkg_viewer.resize(pkgList.size());
|
||||
m_pkg_viewer = pkgList;
|
||||
}
|
||||
|
||||
void setElfViewer(const std::vector<std::string>& elfList) {
|
||||
m_elf_viewer.resize(elfList.size());
|
||||
m_elf_viewer = elfList;
|
||||
|
@ -449,8 +605,19 @@ void setEmulatorLanguage(std::string language) {
|
|||
emulator_language = language;
|
||||
}
|
||||
|
||||
void setGameInstallDirs(const std::vector<std::filesystem::path>& settings_install_dirs_config) {
|
||||
settings_install_dirs = settings_install_dirs_config;
|
||||
void setGameInstallDirs(const std::vector<std::filesystem::path>& dirs_config) {
|
||||
settings_install_dirs.clear();
|
||||
for (const auto& dir : dirs_config) {
|
||||
settings_install_dirs.push_back({dir, true});
|
||||
}
|
||||
}
|
||||
|
||||
void setAllGameInstallDirs(const std::vector<GameInstallDir>& dirs_config) {
|
||||
settings_install_dirs = dirs_config;
|
||||
}
|
||||
|
||||
void setSaveDataPath(const std::filesystem::path& path) {
|
||||
save_data_path = path;
|
||||
}
|
||||
|
||||
u32 getMainWindowGeometryX() {
|
||||
|
@ -469,8 +636,22 @@ u32 getMainWindowGeometryH() {
|
|||
return main_window_geometry_h;
|
||||
}
|
||||
|
||||
const std::vector<std::filesystem::path>& getGameInstallDirs() {
|
||||
return settings_install_dirs;
|
||||
const std::vector<std::filesystem::path> getGameInstallDirs() {
|
||||
std::vector<std::filesystem::path> enabled_dirs;
|
||||
for (const auto& dir : settings_install_dirs) {
|
||||
if (dir.enabled) {
|
||||
enabled_dirs.push_back(dir.path);
|
||||
}
|
||||
}
|
||||
return enabled_dirs;
|
||||
}
|
||||
|
||||
const std::vector<bool> getGameInstallDirsEnabled() {
|
||||
std::vector<bool> enabled_dirs;
|
||||
for (const auto& dir : settings_install_dirs) {
|
||||
enabled_dirs.push_back(dir.enabled);
|
||||
}
|
||||
return enabled_dirs;
|
||||
}
|
||||
|
||||
std::filesystem::path getAddonInstallDir() {
|
||||
|
@ -513,10 +694,6 @@ u32 getMainWindowHeight() {
|
|||
return m_window_size_H;
|
||||
}
|
||||
|
||||
std::vector<std::string> getPkgViewer() {
|
||||
return m_pkg_viewer;
|
||||
}
|
||||
|
||||
std::vector<std::string> getElfViewer() {
|
||||
return m_elf_viewer;
|
||||
}
|
||||
|
@ -533,6 +710,26 @@ u32 GetLanguage() {
|
|||
return m_language;
|
||||
}
|
||||
|
||||
bool getSeparateLogFilesEnabled() {
|
||||
return isSeparateLogFilesEnabled;
|
||||
}
|
||||
|
||||
int getBackgroundImageOpacity() {
|
||||
return backgroundImageOpacity;
|
||||
}
|
||||
|
||||
void setBackgroundImageOpacity(int opacity) {
|
||||
backgroundImageOpacity = std::clamp(opacity, 0, 100);
|
||||
}
|
||||
|
||||
bool getShowBackgroundImage() {
|
||||
return showBackgroundImage;
|
||||
}
|
||||
|
||||
void setShowBackgroundImage(bool show) {
|
||||
showBackgroundImage = show;
|
||||
}
|
||||
|
||||
void load(const std::filesystem::path& path) {
|
||||
// If the configuration file does not exist, create it and return
|
||||
std::error_code error;
|
||||
|
@ -556,25 +753,29 @@ void load(const std::filesystem::path& path) {
|
|||
const toml::value& general = data.at("General");
|
||||
|
||||
isNeo = toml::find_or<bool>(general, "isPS4Pro", false);
|
||||
isFullscreen = toml::find_or<bool>(general, "Fullscreen", false);
|
||||
isDevKit = toml::find_or<bool>(general, "isDevKit", false);
|
||||
playBGM = toml::find_or<bool>(general, "playBGM", false);
|
||||
isTrophyPopupDisabled = toml::find_or<bool>(general, "isTrophyPopupDisabled", false);
|
||||
trophyNotificationDuration =
|
||||
toml::find_or<double>(general, "trophyNotificationDuration", 5.0);
|
||||
BGMvolume = toml::find_or<int>(general, "BGMvolume", 50);
|
||||
enableDiscordRPC = toml::find_or<bool>(general, "enableDiscordRPC", true);
|
||||
logFilter = toml::find_or<std::string>(general, "logFilter", "");
|
||||
logType = toml::find_or<std::string>(general, "logType", "sync");
|
||||
userName = toml::find_or<std::string>(general, "userName", "shadPS4");
|
||||
if (Common::isRelease) {
|
||||
if (Common::g_is_release) {
|
||||
updateChannel = toml::find_or<std::string>(general, "updateChannel", "Release");
|
||||
} else {
|
||||
updateChannel = toml::find_or<std::string>(general, "updateChannel", "Nightly");
|
||||
}
|
||||
isShowSplash = toml::find_or<bool>(general, "showSplash", true);
|
||||
isAutoUpdate = toml::find_or<bool>(general, "autoUpdate", false);
|
||||
separateupdatefolder = toml::find_or<bool>(general, "separateUpdateEnabled", false);
|
||||
isAlwaysShowChangelog = toml::find_or<bool>(general, "alwaysShowChangelog", false);
|
||||
isSideTrophy = toml::find_or<std::string>(general, "sideTrophy", "right");
|
||||
compatibilityData = toml::find_or<bool>(general, "compatibilityEnabled", false);
|
||||
checkCompatibilityOnStartup =
|
||||
toml::find_or<bool>(general, "checkCompatibilityOnStartup", false);
|
||||
chooseHomeTab = toml::find_or<std::string>(general, "chooseHomeTab", "Release");
|
||||
}
|
||||
|
||||
if (data.contains("Input")) {
|
||||
|
@ -585,6 +786,8 @@ void load(const std::filesystem::path& path) {
|
|||
backButtonBehavior = toml::find_or<std::string>(input, "backButtonBehavior", "left");
|
||||
useSpecialPad = toml::find_or<bool>(input, "useSpecialPad", false);
|
||||
specialPadClass = toml::find_or<int>(input, "specialPadClass", 1);
|
||||
isMotionControlsEnabled = toml::find_or<bool>(input, "isMotionControlsEnabled", true);
|
||||
useUnifiedInputConfig = toml::find_or<bool>(input, "useUnifiedInputConfig", true);
|
||||
}
|
||||
|
||||
if (data.contains("GPU")) {
|
||||
|
@ -597,6 +800,9 @@ void load(const std::filesystem::path& path) {
|
|||
shouldDumpShaders = toml::find_or<bool>(gpu, "dumpShaders", false);
|
||||
shouldPatchShaders = toml::find_or<bool>(gpu, "patchShaders", true);
|
||||
vblankDivider = toml::find_or<int>(gpu, "vblankDivider", 1);
|
||||
isFullscreen = toml::find_or<bool>(gpu, "Fullscreen", false);
|
||||
fullscreenMode = toml::find_or<std::string>(gpu, "FullscreenMode", "Windowed");
|
||||
isHDRAllowed = toml::find_or<bool>(gpu, "allowHDR", false);
|
||||
}
|
||||
|
||||
if (data.contains("Vulkan")) {
|
||||
|
@ -606,21 +812,25 @@ void load(const std::filesystem::path& path) {
|
|||
vkValidation = toml::find_or<bool>(vk, "validation", false);
|
||||
vkValidationSync = toml::find_or<bool>(vk, "validation_sync", false);
|
||||
vkValidationGpu = toml::find_or<bool>(vk, "validation_gpu", true);
|
||||
rdocEnable = toml::find_or<bool>(vk, "rdocEnable", false);
|
||||
vkMarkers = toml::find_or<bool>(vk, "rdocMarkersEnable", false);
|
||||
vkCrashDiagnostic = toml::find_or<bool>(vk, "crashDiagnostic", false);
|
||||
vkHostMarkers = toml::find_or<bool>(vk, "hostMarkers", false);
|
||||
vkGuestMarkers = toml::find_or<bool>(vk, "guestMarkers", false);
|
||||
rdocEnable = toml::find_or<bool>(vk, "rdocEnable", false);
|
||||
}
|
||||
|
||||
if (data.contains("Debug")) {
|
||||
const toml::value& debug = data.at("Debug");
|
||||
|
||||
isDebugDump = toml::find_or<bool>(debug, "DebugDump", false);
|
||||
isSeparateLogFilesEnabled = toml::find_or<bool>(debug, "isSeparateLogFilesEnabled", false);
|
||||
isShaderDebug = toml::find_or<bool>(debug, "CollectShader", false);
|
||||
isFpsColor = toml::find_or<bool>(debug, "FPSColor", true);
|
||||
}
|
||||
|
||||
if (data.contains("GUI")) {
|
||||
const toml::value& gui = data.at("GUI");
|
||||
|
||||
load_game_size = toml::find_or<bool>(gui, "loadGameSizeEnabled", true);
|
||||
m_icon_size = toml::find_or<int>(gui, "iconSize", 0);
|
||||
m_icon_size_grid = toml::find_or<int>(gui, "iconSizeGrid", 0);
|
||||
m_slider_pos = toml::find_or<int>(gui, "sliderPos", 0);
|
||||
|
@ -630,21 +840,38 @@ void load(const std::filesystem::path& path) {
|
|||
m_window_size_H = toml::find_or<int>(gui, "mw_height", 0);
|
||||
|
||||
const auto install_dir_array =
|
||||
toml::find_or<std::vector<std::string>>(gui, "installDirs", {});
|
||||
for (const auto& dir : install_dir_array) {
|
||||
addGameInstallDir(std::filesystem::path{dir});
|
||||
toml::find_or<std::vector<std::u8string>>(gui, "installDirs", {});
|
||||
|
||||
try {
|
||||
install_dirs_enabled = toml::find<std::vector<bool>>(gui, "installDirsEnabled");
|
||||
} catch (...) {
|
||||
// If it does not exist, assume that all are enabled.
|
||||
install_dirs_enabled.resize(install_dir_array.size(), true);
|
||||
}
|
||||
|
||||
if (install_dirs_enabled.size() < install_dir_array.size()) {
|
||||
install_dirs_enabled.resize(install_dir_array.size(), true);
|
||||
}
|
||||
|
||||
settings_install_dirs.clear();
|
||||
for (size_t i = 0; i < install_dir_array.size(); i++) {
|
||||
settings_install_dirs.push_back(
|
||||
{std::filesystem::path{install_dir_array[i]}, install_dirs_enabled[i]});
|
||||
}
|
||||
|
||||
save_data_path = toml::find_fs_path_or(gui, "saveDataPath", {});
|
||||
|
||||
settings_addon_install_dir = toml::find_fs_path_or(gui, "addonInstallDir", {});
|
||||
main_window_geometry_x = toml::find_or<int>(gui, "geometry_x", 0);
|
||||
main_window_geometry_y = toml::find_or<int>(gui, "geometry_y", 0);
|
||||
main_window_geometry_w = toml::find_or<int>(gui, "geometry_w", 0);
|
||||
main_window_geometry_h = toml::find_or<int>(gui, "geometry_h", 0);
|
||||
m_pkg_viewer = toml::find_or<std::vector<std::string>>(gui, "pkgDirs", {});
|
||||
m_elf_viewer = toml::find_or<std::vector<std::string>>(gui, "elfDirs", {});
|
||||
m_recent_files = toml::find_or<std::vector<std::string>>(gui, "recentFiles", {});
|
||||
m_table_mode = toml::find_or<int>(gui, "gameTableMode", 0);
|
||||
emulator_language = toml::find_or<std::string>(gui, "emulatorLanguage", "en");
|
||||
emulator_language = toml::find_or<std::string>(gui, "emulatorLanguage", "en_US");
|
||||
backgroundImageOpacity = toml::find_or<int>(gui, "backgroundImageOpacity", 50);
|
||||
showBackgroundImage = toml::find_or<bool>(gui, "showBackgroundImage", true);
|
||||
}
|
||||
|
||||
if (data.contains("Settings")) {
|
||||
|
@ -652,10 +879,58 @@ void load(const std::filesystem::path& path) {
|
|||
|
||||
m_language = toml::find_or<int>(settings, "consoleLanguage", 1);
|
||||
}
|
||||
|
||||
if (data.contains("Keys")) {
|
||||
const toml::value& keys = data.at("Keys");
|
||||
trophyKey = toml::find_or<std::string>(keys, "TrophyKey", "");
|
||||
}
|
||||
|
||||
// Check if the loaded language is in the allowed list
|
||||
const std::vector<std::string> allowed_languages = {
|
||||
"ar_SA", "da_DK", "de_DE", "el_GR", "en_US", "es_ES", "fa_IR", "fi_FI", "fr_FR", "hu_HU",
|
||||
"id_ID", "it_IT", "ja_JP", "ko_KR", "lt_LT", "nb_NO", "nl_NL", "pl_PL", "pt_BR", "pt_PT",
|
||||
"ro_RO", "ru_RU", "sq_AL", "sv_SE", "tr_TR", "uk_UA", "vi_VN", "zh_CN", "zh_TW"};
|
||||
|
||||
if (std::find(allowed_languages.begin(), allowed_languages.end(), emulator_language) ==
|
||||
allowed_languages.end()) {
|
||||
emulator_language = "en_US"; // Default to en_US if not in the list
|
||||
save(path);
|
||||
}
|
||||
}
|
||||
|
||||
void sortTomlSections(toml::ordered_value& data) {
|
||||
toml::ordered_value ordered_data;
|
||||
std::vector<std::string> section_order = {"General", "Input", "GPU", "Vulkan",
|
||||
"Debug", "Keys", "GUI", "Settings"};
|
||||
|
||||
for (const auto& section : section_order) {
|
||||
if (data.contains(section)) {
|
||||
std::vector<std::string> keys;
|
||||
for (const auto& item : data.at(section).as_table()) {
|
||||
keys.push_back(item.first);
|
||||
}
|
||||
|
||||
std::sort(keys.begin(), keys.end(), [](const std::string& a, const std::string& b) {
|
||||
return std::lexicographical_compare(
|
||||
a.begin(), a.end(), b.begin(), b.end(), [](char a_char, char b_char) {
|
||||
return std::tolower(a_char) < std::tolower(b_char);
|
||||
});
|
||||
});
|
||||
|
||||
toml::ordered_value ordered_section;
|
||||
for (const auto& key : keys) {
|
||||
ordered_section[key] = data.at(section).at(key);
|
||||
}
|
||||
|
||||
ordered_data[section] = ordered_section;
|
||||
}
|
||||
}
|
||||
|
||||
data = ordered_data;
|
||||
}
|
||||
|
||||
void save(const std::filesystem::path& path) {
|
||||
toml::value data;
|
||||
toml::ordered_value data;
|
||||
|
||||
std::error_code error;
|
||||
if (std::filesystem::exists(path, error)) {
|
||||
|
@ -663,7 +938,8 @@ void save(const std::filesystem::path& path) {
|
|||
std::ifstream ifs;
|
||||
ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
ifs.open(path, std::ios_base::binary);
|
||||
data = toml::parse(ifs, std::string{fmt::UTF(path.filename().u8string()).data});
|
||||
data = toml::parse<toml::ordered_type_config>(
|
||||
ifs, std::string{fmt::UTF(path.filename().u8string()).data});
|
||||
} catch (const std::exception& ex) {
|
||||
fmt::print("Exception trying to parse config file. Exception: {}\n", ex.what());
|
||||
return;
|
||||
|
@ -676,8 +952,9 @@ void save(const std::filesystem::path& path) {
|
|||
}
|
||||
|
||||
data["General"]["isPS4Pro"] = isNeo;
|
||||
data["General"]["Fullscreen"] = isFullscreen;
|
||||
data["General"]["isDevKit"] = isDevKit;
|
||||
data["General"]["isTrophyPopupDisabled"] = isTrophyPopupDisabled;
|
||||
data["General"]["trophyNotificationDuration"] = trophyNotificationDuration;
|
||||
data["General"]["playBGM"] = playBGM;
|
||||
data["General"]["BGMvolume"] = BGMvolume;
|
||||
data["General"]["enableDiscordRPC"] = enableDiscordRPC;
|
||||
|
@ -685,9 +962,11 @@ void save(const std::filesystem::path& path) {
|
|||
data["General"]["logType"] = logType;
|
||||
data["General"]["userName"] = userName;
|
||||
data["General"]["updateChannel"] = updateChannel;
|
||||
data["General"]["chooseHomeTab"] = chooseHomeTab;
|
||||
data["General"]["showSplash"] = isShowSplash;
|
||||
data["General"]["autoUpdate"] = isAutoUpdate;
|
||||
data["General"]["separateUpdateEnabled"] = separateupdatefolder;
|
||||
data["General"]["alwaysShowChangelog"] = isAlwaysShowChangelog;
|
||||
data["General"]["sideTrophy"] = isSideTrophy;
|
||||
data["General"]["compatibilityEnabled"] = compatibilityData;
|
||||
data["General"]["checkCompatibilityOnStartup"] = checkCompatibilityOnStartup;
|
||||
data["Input"]["cursorState"] = cursorState;
|
||||
|
@ -695,6 +974,8 @@ void save(const std::filesystem::path& path) {
|
|||
data["Input"]["backButtonBehavior"] = backButtonBehavior;
|
||||
data["Input"]["useSpecialPad"] = useSpecialPad;
|
||||
data["Input"]["specialPadClass"] = specialPadClass;
|
||||
data["Input"]["isMotionControlsEnabled"] = isMotionControlsEnabled;
|
||||
data["Input"]["useUnifiedInputConfig"] = useUnifiedInputConfig;
|
||||
data["GPU"]["screenWidth"] = screenWidth;
|
||||
data["GPU"]["screenHeight"] = screenHeight;
|
||||
data["GPU"]["nullGpu"] = isNullGpu;
|
||||
|
@ -702,35 +983,74 @@ void save(const std::filesystem::path& path) {
|
|||
data["GPU"]["dumpShaders"] = shouldDumpShaders;
|
||||
data["GPU"]["patchShaders"] = shouldPatchShaders;
|
||||
data["GPU"]["vblankDivider"] = vblankDivider;
|
||||
data["GPU"]["Fullscreen"] = isFullscreen;
|
||||
data["GPU"]["FullscreenMode"] = fullscreenMode;
|
||||
data["GPU"]["allowHDR"] = isHDRAllowed;
|
||||
data["Vulkan"]["gpuId"] = gpuId;
|
||||
data["Vulkan"]["validation"] = vkValidation;
|
||||
data["Vulkan"]["validation_sync"] = vkValidationSync;
|
||||
data["Vulkan"]["validation_gpu"] = vkValidationGpu;
|
||||
data["Vulkan"]["rdocEnable"] = rdocEnable;
|
||||
data["Vulkan"]["rdocMarkersEnable"] = vkMarkers;
|
||||
data["Vulkan"]["crashDiagnostic"] = vkCrashDiagnostic;
|
||||
data["Vulkan"]["hostMarkers"] = vkHostMarkers;
|
||||
data["Vulkan"]["guestMarkers"] = vkGuestMarkers;
|
||||
data["Vulkan"]["rdocEnable"] = rdocEnable;
|
||||
data["Debug"]["DebugDump"] = isDebugDump;
|
||||
data["Debug"]["CollectShader"] = isShaderDebug;
|
||||
data["Debug"]["isSeparateLogFilesEnabled"] = isSeparateLogFilesEnabled;
|
||||
data["Debug"]["FPSColor"] = isFpsColor;
|
||||
data["Keys"]["TrophyKey"] = trophyKey;
|
||||
|
||||
std::vector<std::string> install_dirs;
|
||||
for (const auto& dirString : settings_install_dirs) {
|
||||
install_dirs.emplace_back(std::string{fmt::UTF(dirString.u8string()).data});
|
||||
std::vector<bool> install_dirs_enabled;
|
||||
|
||||
// temporary structure for ordering
|
||||
struct DirEntry {
|
||||
std::string path_str;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
std::vector<DirEntry> sorted_dirs;
|
||||
for (const auto& dirInfo : settings_install_dirs) {
|
||||
sorted_dirs.push_back(
|
||||
{std::string{fmt::UTF(dirInfo.path.u8string()).data}, dirInfo.enabled});
|
||||
}
|
||||
|
||||
// Sort directories alphabetically
|
||||
std::sort(sorted_dirs.begin(), sorted_dirs.end(), [](const DirEntry& a, const DirEntry& b) {
|
||||
return std::lexicographical_compare(
|
||||
a.path_str.begin(), a.path_str.end(), b.path_str.begin(), b.path_str.end(),
|
||||
[](char a_char, char b_char) { return std::tolower(a_char) < std::tolower(b_char); });
|
||||
});
|
||||
|
||||
for (const auto& entry : sorted_dirs) {
|
||||
install_dirs.push_back(entry.path_str);
|
||||
install_dirs_enabled.push_back(entry.enabled);
|
||||
}
|
||||
|
||||
data["GUI"]["installDirs"] = install_dirs;
|
||||
data["GUI"]["installDirsEnabled"] = install_dirs_enabled;
|
||||
data["GUI"]["saveDataPath"] = std::string{fmt::UTF(save_data_path.u8string()).data};
|
||||
data["GUI"]["loadGameSizeEnabled"] = load_game_size;
|
||||
|
||||
data["GUI"]["addonInstallDir"] =
|
||||
std::string{fmt::UTF(settings_addon_install_dir.u8string()).data};
|
||||
data["GUI"]["emulatorLanguage"] = emulator_language;
|
||||
data["GUI"]["backgroundImageOpacity"] = backgroundImageOpacity;
|
||||
data["GUI"]["showBackgroundImage"] = showBackgroundImage;
|
||||
data["Settings"]["consoleLanguage"] = m_language;
|
||||
|
||||
// Sorting of TOML sections
|
||||
sortTomlSections(data);
|
||||
|
||||
std::ofstream file(path, std::ios::binary);
|
||||
file << data;
|
||||
file.close();
|
||||
|
||||
saveMainWindow(path);
|
||||
}
|
||||
|
||||
void saveMainWindow(const std::filesystem::path& path) {
|
||||
toml::value data;
|
||||
toml::ordered_value data;
|
||||
|
||||
std::error_code error;
|
||||
if (std::filesystem::exists(path, error)) {
|
||||
|
@ -738,7 +1058,8 @@ void saveMainWindow(const std::filesystem::path& path) {
|
|||
std::ifstream ifs;
|
||||
ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
ifs.open(path, std::ios_base::binary);
|
||||
data = toml::parse(ifs, std::string{fmt::UTF(path.filename().u8string()).data});
|
||||
data = toml::parse<toml::ordered_type_config>(
|
||||
ifs, std::string{fmt::UTF(path.filename().u8string()).data});
|
||||
} catch (const std::exception& ex) {
|
||||
fmt::print("Exception trying to parse config file. Exception: {}\n", ex.what());
|
||||
return;
|
||||
|
@ -762,17 +1083,21 @@ void saveMainWindow(const std::filesystem::path& path) {
|
|||
data["GUI"]["geometry_y"] = main_window_geometry_y;
|
||||
data["GUI"]["geometry_w"] = main_window_geometry_w;
|
||||
data["GUI"]["geometry_h"] = main_window_geometry_h;
|
||||
data["GUI"]["pkgDirs"] = m_pkg_viewer;
|
||||
data["GUI"]["elfDirs"] = m_elf_viewer;
|
||||
data["GUI"]["recentFiles"] = m_recent_files;
|
||||
|
||||
// Sorting of TOML sections
|
||||
sortTomlSections(data);
|
||||
|
||||
std::ofstream file(path, std::ios::binary);
|
||||
file << data;
|
||||
file.close();
|
||||
}
|
||||
|
||||
void setDefaultValues() {
|
||||
isHDRAllowed = false;
|
||||
isNeo = false;
|
||||
isDevKit = false;
|
||||
isFullscreen = false;
|
||||
isTrophyPopupDisabled = false;
|
||||
playBGM = false;
|
||||
|
@ -781,15 +1106,17 @@ void setDefaultValues() {
|
|||
screenWidth = 1280;
|
||||
screenHeight = 720;
|
||||
logFilter = "";
|
||||
logType = "async";
|
||||
logType = "sync";
|
||||
userName = "shadPS4";
|
||||
if (Common::isRelease) {
|
||||
if (Common::g_is_release) {
|
||||
updateChannel = "Release";
|
||||
} else {
|
||||
updateChannel = "Nightly";
|
||||
}
|
||||
chooseHomeTab = "General";
|
||||
cursorState = HideCursorState::Idle;
|
||||
cursorHideTimeout = 5;
|
||||
trophyNotificationDuration = 6.0;
|
||||
backButtonBehavior = "left";
|
||||
useSpecialPad = false;
|
||||
specialPadClass = 1;
|
||||
|
@ -797,21 +1124,135 @@ void setDefaultValues() {
|
|||
isShaderDebug = false;
|
||||
isShowSplash = false;
|
||||
isAutoUpdate = false;
|
||||
isAlwaysShowChangelog = false;
|
||||
isSideTrophy = "right";
|
||||
isNullGpu = false;
|
||||
shouldDumpShaders = false;
|
||||
vblankDivider = 1;
|
||||
vkValidation = false;
|
||||
vkValidationSync = false;
|
||||
vkValidationGpu = false;
|
||||
rdocEnable = false;
|
||||
vkMarkers = false;
|
||||
vkCrashDiagnostic = false;
|
||||
emulator_language = "en";
|
||||
vkHostMarkers = false;
|
||||
vkGuestMarkers = false;
|
||||
rdocEnable = false;
|
||||
emulator_language = "en_US";
|
||||
m_language = 1;
|
||||
gpuId = -1;
|
||||
separateupdatefolder = false;
|
||||
compatibilityData = false;
|
||||
checkCompatibilityOnStartup = false;
|
||||
backgroundImageOpacity = 50;
|
||||
showBackgroundImage = true;
|
||||
}
|
||||
|
||||
constexpr std::string_view GetDefaultKeyboardConfig() {
|
||||
return R"(#Feeling lost? Check out the Help section!
|
||||
|
||||
# Keyboard bindings
|
||||
|
||||
triangle = kp8
|
||||
circle = kp6
|
||||
cross = kp2
|
||||
square = kp4
|
||||
# Alternatives for users without a keypad
|
||||
triangle = c
|
||||
circle = b
|
||||
cross = n
|
||||
square = v
|
||||
|
||||
l1 = q
|
||||
r1 = u
|
||||
l2 = e
|
||||
r2 = o
|
||||
l3 = x
|
||||
r3 = m
|
||||
|
||||
options = enter
|
||||
touchpad = space
|
||||
|
||||
pad_up = up
|
||||
pad_down = down
|
||||
pad_left = left
|
||||
pad_right = right
|
||||
|
||||
axis_left_x_minus = a
|
||||
axis_left_x_plus = d
|
||||
axis_left_y_minus = w
|
||||
axis_left_y_plus = s
|
||||
|
||||
axis_right_x_minus = j
|
||||
axis_right_x_plus = l
|
||||
axis_right_y_minus = i
|
||||
axis_right_y_plus = k
|
||||
|
||||
# Controller bindings
|
||||
|
||||
triangle = triangle
|
||||
cross = cross
|
||||
square = square
|
||||
circle = circle
|
||||
|
||||
l1 = l1
|
||||
l2 = l2
|
||||
l3 = l3
|
||||
r1 = r1
|
||||
r2 = r2
|
||||
r3 = r3
|
||||
|
||||
options = options
|
||||
touchpad = back
|
||||
|
||||
pad_up = pad_up
|
||||
pad_down = pad_down
|
||||
pad_left = pad_left
|
||||
pad_right = pad_right
|
||||
|
||||
axis_left_x = axis_left_x
|
||||
axis_left_y = axis_left_y
|
||||
axis_right_x = axis_right_x
|
||||
axis_right_y = axis_right_y
|
||||
|
||||
# Range of deadzones: 1 (almost none) to 127 (max)
|
||||
analog_deadzone = leftjoystick, 2, 127
|
||||
analog_deadzone = rightjoystick, 2, 127
|
||||
|
||||
override_controller_color = false, 0, 0, 255
|
||||
)";
|
||||
}
|
||||
std::filesystem::path GetFoolproofKbmConfigFile(const std::string& game_id) {
|
||||
// Read configuration file of the game, and if it doesn't exist, generate it from default
|
||||
// If that doesn't exist either, generate that from getDefaultConfig() and try again
|
||||
// If even the folder is missing, we start with that.
|
||||
|
||||
const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "input_config";
|
||||
const auto config_file = config_dir / (game_id + ".ini");
|
||||
const auto default_config_file = config_dir / "default.ini";
|
||||
|
||||
// Ensure the config directory exists
|
||||
if (!std::filesystem::exists(config_dir)) {
|
||||
std::filesystem::create_directories(config_dir);
|
||||
}
|
||||
|
||||
// Check if the default config exists
|
||||
if (!std::filesystem::exists(default_config_file)) {
|
||||
// If the default config is also missing, create it from getDefaultConfig()
|
||||
const auto default_config = GetDefaultKeyboardConfig();
|
||||
std::ofstream default_config_stream(default_config_file);
|
||||
if (default_config_stream) {
|
||||
default_config_stream << default_config;
|
||||
}
|
||||
}
|
||||
|
||||
// if empty, we only need to execute the function up until this point
|
||||
if (game_id.empty()) {
|
||||
return default_config_file;
|
||||
}
|
||||
|
||||
// If game-specific config doesn't exist, create it from the default config
|
||||
if (!std::filesystem::exists(config_file)) {
|
||||
std::filesystem::copy(default_config_file, config_file);
|
||||
}
|
||||
return config_file;
|
||||
}
|
||||
|
||||
} // namespace Config
|
||||
|
|
|
@ -9,60 +9,92 @@
|
|||
|
||||
namespace Config {
|
||||
|
||||
struct GameInstallDir {
|
||||
std::filesystem::path path;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
enum HideCursorState : s16 { Never, Idle, Always };
|
||||
|
||||
void load(const std::filesystem::path& path);
|
||||
void save(const std::filesystem::path& path);
|
||||
void saveMainWindow(const std::filesystem::path& path);
|
||||
|
||||
bool isNeoMode();
|
||||
bool isFullscreenMode();
|
||||
std::string getTrophyKey();
|
||||
void setTrophyKey(std::string key);
|
||||
bool GetLoadGameSizeEnabled();
|
||||
std::filesystem::path GetSaveDataPath();
|
||||
void setLoadGameSizeEnabled(bool enable);
|
||||
bool getIsFullscreen();
|
||||
bool getShowLabelsUnderIcons();
|
||||
bool setShowLabelsUnderIcons();
|
||||
std::string getFullscreenMode();
|
||||
bool isNeoModeConsole();
|
||||
bool isDevKitConsole();
|
||||
bool getPlayBGM();
|
||||
int getBGMvolume();
|
||||
bool getisTrophyPopupDisabled();
|
||||
bool getEnableDiscordRPC();
|
||||
bool getSeparateUpdateEnabled();
|
||||
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();
|
||||
int getCursorHideTimeout();
|
||||
double getTrophyNotificationDuration();
|
||||
std::string getBackButtonBehavior();
|
||||
bool getUseSpecialPad();
|
||||
int getSpecialPadClass();
|
||||
bool getIsMotionControlsEnabled();
|
||||
bool GetUseUnifiedInputConfig();
|
||||
void SetUseUnifiedInputConfig(bool use);
|
||||
bool GetOverrideControllerColor();
|
||||
void SetOverrideControllerColor(bool enable);
|
||||
int* GetControllerCustomColor();
|
||||
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 setFullscreenMode(bool enable);
|
||||
void setIsFullscreen(bool enable);
|
||||
void setFullscreenMode(std::string mode);
|
||||
void setisTrophyPopupDisabled(bool disable);
|
||||
void setPlayBGM(bool enable);
|
||||
void setBGMvolume(int volume);
|
||||
|
@ -71,20 +103,27 @@ void setLanguage(u32 language);
|
|||
void setNeoMode(bool enable);
|
||||
void setUserName(const std::string& type);
|
||||
void setUpdateChannel(const std::string& type);
|
||||
void setSeparateUpdateEnabled(bool use);
|
||||
void setGameInstallDirs(const std::vector<std::filesystem::path>& settings_install_dirs_config);
|
||||
void setChooseHomeTab(const std::string& type);
|
||||
void setGameInstallDirs(const std::vector<std::filesystem::path>& dirs_config);
|
||||
void setAllGameInstallDirs(const std::vector<GameInstallDir>& dirs_config);
|
||||
void setSaveDataPath(const std::filesystem::path& path);
|
||||
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);
|
||||
|
@ -92,13 +131,18 @@ void setRdocEnabled(bool enable);
|
|||
bool vkValidationEnabled();
|
||||
bool vkValidationSyncEnabled();
|
||||
bool vkValidationGpuEnabled();
|
||||
bool vkMarkersEnabled();
|
||||
bool vkCrashDiagnosticEnabled();
|
||||
bool getVkCrashDiagnosticEnabled();
|
||||
bool getVkHostMarkersEnabled();
|
||||
bool getVkGuestMarkersEnabled();
|
||||
void setVkCrashDiagnosticEnabled(bool enable);
|
||||
void setVkHostMarkersEnabled(bool enable);
|
||||
void setVkGuestMarkersEnabled(bool enable);
|
||||
|
||||
// Gui
|
||||
void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h);
|
||||
bool addGameInstallDir(const std::filesystem::path& dir);
|
||||
bool addGameInstallDir(const std::filesystem::path& dir, bool enabled = true);
|
||||
void removeGameInstallDir(const std::filesystem::path& dir);
|
||||
void setGameInstallDirEnabled(const std::filesystem::path& dir, bool enabled);
|
||||
void setAddonInstallDir(const std::filesystem::path& dir);
|
||||
void setMainWindowTheme(u32 theme);
|
||||
void setIconSize(u32 size);
|
||||
|
@ -108,7 +152,6 @@ void setSliderPositionGrid(u32 pos);
|
|||
void setTableMode(u32 mode);
|
||||
void setMainWindowWidth(u32 width);
|
||||
void setMainWindowHeight(u32 height);
|
||||
void setPkgViewer(const std::vector<std::string>& pkgList);
|
||||
void setElfViewer(const std::vector<std::string>& elfList);
|
||||
void setRecentFiles(const std::vector<std::string>& recentFiles);
|
||||
void setEmulatorLanguage(std::string language);
|
||||
|
@ -117,7 +160,8 @@ 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();
|
||||
std::filesystem::path getAddonInstallDir();
|
||||
u32 getMainWindowTheme();
|
||||
u32 getIconSize();
|
||||
|
@ -127,13 +171,15 @@ u32 getSliderPositionGrid();
|
|||
u32 getTableMode();
|
||||
u32 getMainWindowWidth();
|
||||
u32 getMainWindowHeight();
|
||||
std::vector<std::string> getPkgViewer();
|
||||
std::vector<std::string> getElfViewer();
|
||||
std::vector<std::string> getRecentFiles();
|
||||
std::string getEmulatorLanguage();
|
||||
|
||||
void setDefaultValues();
|
||||
|
||||
// todo: name and function location pending
|
||||
std::filesystem::path GetFoolproofKbmConfigFile(const std::string& game_id = "");
|
||||
|
||||
// settings
|
||||
u32 GetLanguage();
|
||||
}; // namespace Config
|
|
@ -3,10 +3,12 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "assert.h"
|
||||
#include "bit_field.h"
|
||||
#include "singleton.h"
|
||||
#include "types.h"
|
||||
|
||||
|
@ -16,6 +18,46 @@ class Emulator;
|
|||
|
||||
namespace Common {
|
||||
|
||||
union PSFAttributes {
|
||||
/// Supports initial user's logout
|
||||
BitField<0, 1, u32> support_initial_user_logout;
|
||||
/// Enter button for the common dialog is cross.
|
||||
BitField<1, 1, u32> enter_button_cross;
|
||||
/// Warning dialog for PS Move is displayed in the options menu.
|
||||
BitField<2, 1, u32> ps_move_warning;
|
||||
/// Supports stereoscopic 3D.
|
||||
BitField<3, 1, u32> support_stereoscopic_3d;
|
||||
/// Suspends when PS button is pressed.
|
||||
BitField<4, 1, u32> ps_button_suspend;
|
||||
/// Enter button for the common dialog is assigned by the system software.
|
||||
BitField<5, 1, u32> enter_button_system;
|
||||
/// Overrides share menu behavior.
|
||||
BitField<6, 1, u32> override_share_menu;
|
||||
/// Suspends when PS button is pressed and special output resolution is set.
|
||||
BitField<8, 1, u32> special_res_ps_button_suspend;
|
||||
/// Enable HDCP.
|
||||
BitField<9, 1, u32> enable_hdcp;
|
||||
/// Disable HDCP for non-game.
|
||||
BitField<10, 1, u32> disable_hdcp_non_game;
|
||||
/// Supports PS VR.
|
||||
BitField<14, 1, u32> support_ps_vr;
|
||||
/// CPU mode (6 CPU)
|
||||
BitField<15, 1, u32> six_cpu_mode;
|
||||
/// CPU mode (7 CPU)
|
||||
BitField<16, 1, u32> seven_cpu_mode;
|
||||
/// Supports PS4 Pro (Neo) mode.
|
||||
BitField<23, 1, u32> support_neo_mode;
|
||||
/// Requires PS VR.
|
||||
BitField<26, 1, u32> require_ps_vr;
|
||||
/// Supports HDR.
|
||||
BitField<29, 1, u32> support_hdr;
|
||||
/// Display location.
|
||||
BitField<31, 1, u32> display_location;
|
||||
|
||||
u32 raw{};
|
||||
};
|
||||
static_assert(sizeof(PSFAttributes) == 4);
|
||||
|
||||
class ElfInfo {
|
||||
friend class Core::Emulator;
|
||||
|
||||
|
@ -26,6 +68,9 @@ class ElfInfo {
|
|||
std::string app_ver{};
|
||||
u32 firmware_ver = 0;
|
||||
u32 raw_firmware_ver = 0;
|
||||
PSFAttributes psf_attributes{};
|
||||
|
||||
std::filesystem::path splash_path{};
|
||||
|
||||
public:
|
||||
static constexpr u32 FW_15 = 0x1500000;
|
||||
|
@ -34,9 +79,11 @@ public:
|
|||
static constexpr u32 FW_20 = 0x2000000;
|
||||
static constexpr u32 FW_25 = 0x2500000;
|
||||
static constexpr u32 FW_30 = 0x3000000;
|
||||
static constexpr u32 FW_35 = 0x3500000;
|
||||
static constexpr u32 FW_40 = 0x4000000;
|
||||
static constexpr u32 FW_45 = 0x4500000;
|
||||
static constexpr u32 FW_50 = 0x5000000;
|
||||
static constexpr u32 FW_55 = 0x5500000;
|
||||
static constexpr u32 FW_80 = 0x8000000;
|
||||
|
||||
static ElfInfo& Instance() {
|
||||
|
@ -67,6 +114,15 @@ public:
|
|||
ASSERT(initialized);
|
||||
return raw_firmware_ver;
|
||||
}
|
||||
|
||||
[[nodiscard]] const PSFAttributes& GetPSFAttributes() const {
|
||||
ASSERT(initialized);
|
||||
return psf_attributes;
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::filesystem::path& GetSplashPath() const {
|
||||
return splash_path;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Common
|
||||
|
|
|
@ -125,12 +125,15 @@ namespace {
|
|||
[[nodiscard]] constexpr int ToSeekOrigin(SeekOrigin origin) {
|
||||
switch (origin) {
|
||||
case SeekOrigin::SetOrigin:
|
||||
default:
|
||||
return SEEK_SET;
|
||||
case SeekOrigin::CurrentPosition:
|
||||
return SEEK_CUR;
|
||||
case SeekOrigin::End:
|
||||
return SEEK_END;
|
||||
default:
|
||||
LOG_ERROR(Common_Filesystem, "Unsupported origin {}, defaulting to SEEK_SET",
|
||||
static_cast<u32>(origin));
|
||||
return SEEK_SET;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -377,20 +380,6 @@ bool IOFile::Seek(s64 offset, SeekOrigin origin) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (False(file_access_mode & (FileAccessMode::Write | FileAccessMode::Append))) {
|
||||
u64 size = GetSize();
|
||||
if (origin == SeekOrigin::CurrentPosition && Tell() + offset > size) {
|
||||
LOG_ERROR(Common_Filesystem, "Seeking past the end of the file");
|
||||
return false;
|
||||
} else if (origin == SeekOrigin::SetOrigin && (u64)offset > size) {
|
||||
LOG_ERROR(Common_Filesystem, "Seeking past the end of the file");
|
||||
return false;
|
||||
} else if (origin == SeekOrigin::End && offset > 0) {
|
||||
LOG_ERROR(Common_Filesystem, "Seeking past the end of the file");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
|
||||
const auto seek_result = fseeko(file, offset, ToSeekOrigin(origin)) == 0;
|
||||
|
|
|
@ -61,6 +61,8 @@ enum class SeekOrigin : u32 {
|
|||
SetOrigin, // Seeks from the start of the file.
|
||||
CurrentPosition, // Seeks from the current file pointer position.
|
||||
End, // Seeks from the end of the file.
|
||||
SeekHole, // Seeks from the start of the next hole in the file.
|
||||
SeekData, // Seeks from the start of the next non-hole region in the file.
|
||||
};
|
||||
|
||||
class IOFile final {
|
||||
|
|
|
@ -139,8 +139,9 @@ public:
|
|||
std::filesystem::create_directory(log_dir);
|
||||
Filter filter;
|
||||
filter.ParseFilterString(Config::getLogFilter());
|
||||
instance = std::unique_ptr<Impl, decltype(&Deleter)>(new Impl(log_dir / LOG_FILE, filter),
|
||||
Deleter);
|
||||
const auto& log_file_path = log_file.empty() ? LOG_FILE : log_file;
|
||||
instance = std::unique_ptr<Impl, decltype(&Deleter)>(
|
||||
new Impl(log_dir / log_file_path, filter), Deleter);
|
||||
initialization_in_progress_suppress_logging = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -80,6 +80,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
|||
SUB(Kernel, Sce) \
|
||||
CLS(Lib) \
|
||||
SUB(Lib, LibC) \
|
||||
SUB(Lib, LibcInternal) \
|
||||
SUB(Lib, Kernel) \
|
||||
SUB(Lib, Pad) \
|
||||
SUB(Lib, GnmDriver) \
|
||||
|
@ -95,11 +96,17 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
|||
SUB(Lib, SaveData) \
|
||||
SUB(Lib, SaveDataDialog) \
|
||||
SUB(Lib, Http) \
|
||||
SUB(Lib, Http2) \
|
||||
SUB(Lib, Ssl) \
|
||||
SUB(Lib, Ssl2) \
|
||||
SUB(Lib, SysModule) \
|
||||
SUB(Lib, Move) \
|
||||
SUB(Lib, NpAuth) \
|
||||
SUB(Lib, NpCommon) \
|
||||
SUB(Lib, NpManager) \
|
||||
SUB(Lib, NpScore) \
|
||||
SUB(Lib, NpTrophy) \
|
||||
SUB(Lib, NpWebApi) \
|
||||
SUB(Lib, Screenshot) \
|
||||
SUB(Lib, LibCInternal) \
|
||||
SUB(Lib, AppContent) \
|
||||
|
@ -125,6 +132,11 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
|||
SUB(Lib, Vdec2) \
|
||||
SUB(Lib, Videodec) \
|
||||
SUB(Lib, RazorCpu) \
|
||||
SUB(Lib, Mouse) \
|
||||
SUB(Lib, WebBrowserDialog) \
|
||||
SUB(Lib, NpParty) \
|
||||
SUB(Lib, Zlib) \
|
||||
SUB(Lib, Hmd) \
|
||||
CLS(Frontend) \
|
||||
CLS(Render) \
|
||||
SUB(Render, Vulkan) \
|
||||
|
|
|
@ -23,8 +23,8 @@ std::string FormatLogMessage(const Entry& entry) {
|
|||
const char* class_name = GetLogClassName(entry.log_class);
|
||||
const char* level_name = GetLevelName(entry.log_level);
|
||||
|
||||
return fmt::format("[{}] <{}> {}:{}:{}: {}", class_name, level_name, entry.filename,
|
||||
entry.function, entry.line_num, entry.message);
|
||||
return fmt::format("[{}] <{}> {}:{} {}: {}", class_name, level_name, entry.filename,
|
||||
entry.line_num, entry.function, entry.message);
|
||||
}
|
||||
|
||||
void PrintMessage(const Entry& entry) {
|
||||
|
|
|
@ -47,6 +47,7 @@ enum class Class : u8 {
|
|||
Lib, ///< HLE implementation of system library. Each major library
|
||||
///< should have its own subclass.
|
||||
Lib_LibC, ///< The LibC implementation.
|
||||
Lib_LibcInternal, ///< The LibcInternal implementation.
|
||||
Lib_Kernel, ///< The LibKernel implementation.
|
||||
Lib_Pad, ///< The LibScePad implementation.
|
||||
Lib_GnmDriver, ///< The LibSceGnmDriver implementation.
|
||||
|
@ -57,16 +58,22 @@ enum class Class : u8 {
|
|||
Lib_MsgDlg, ///< The LibSceMsgDialog implementation.
|
||||
Lib_AudioOut, ///< The LibSceAudioOut implementation.
|
||||
Lib_AudioIn, ///< The LibSceAudioIn implementation.
|
||||
Lib_Move, ///< The LibSceMove implementation.
|
||||
Lib_Net, ///< The LibSceNet implementation.
|
||||
Lib_NetCtl, ///< The LibSecNetCtl implementation.
|
||||
Lib_NetCtl, ///< The LibSceNetCtl implementation.
|
||||
Lib_SaveData, ///< The LibSceSaveData implementation.
|
||||
Lib_SaveDataDialog, ///< The LibSceSaveDataDialog implementation.
|
||||
Lib_Ssl, ///< The LibSceSsl implementation.
|
||||
Lib_Ssl2, ///< The LibSceSsl2 implementation.
|
||||
Lib_Http, ///< The LibSceHttp implementation.
|
||||
Lib_Http2, ///< The LibSceHttp2 implementation.
|
||||
Lib_SysModule, ///< The LibSceSysModule implementation
|
||||
Lib_NpCommon, ///< The LibSceNpCommon implementation
|
||||
Lib_NpAuth, ///< The LibSceNpAuth implementation
|
||||
Lib_NpManager, ///< The LibSceNpManager implementation
|
||||
Lib_NpScore, ///< The LibSceNpScore implementation
|
||||
Lib_NpTrophy, ///< The LibSceNpTrophy implementation
|
||||
Lib_NpWebApi, ///< The LibSceWebApi implementation
|
||||
Lib_Screenshot, ///< The LibSceScreenshot implementation
|
||||
Lib_LibCInternal, ///< The LibCInternal implementation.
|
||||
Lib_AppContent, ///< The LibSceAppContent implementation.
|
||||
|
@ -92,6 +99,11 @@ enum class Class : u8 {
|
|||
Lib_Vdec2, ///< The LibSceVideodec2 implementation.
|
||||
Lib_Videodec, ///< The LibSceVideodec implementation.
|
||||
Lib_RazorCpu, ///< The LibRazorCpu implementation.
|
||||
Lib_Mouse, ///< The LibSceMouse implementation
|
||||
Lib_WebBrowserDialog, ///< The LibSceWebBrowserDialog implementation
|
||||
Lib_NpParty, ///< The LibSceNpParty implementation
|
||||
Lib_Zlib, ///< The LibSceZlib implementation.
|
||||
Lib_Hmd, ///< The LibSceHmd implementation.
|
||||
Frontend, ///< Emulator UI
|
||||
Render, ///< Video Core
|
||||
Render_Vulkan, ///< Vulkan backend
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <string>
|
||||
#include <pugixml.hpp>
|
||||
#ifdef ENABLE_QT_GUI
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
|
@ -143,37 +144,39 @@ void OnGameLoaded() {
|
|||
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("type").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") {
|
||||
littleEndian = true;
|
||||
} else if (type == "bytes32") {
|
||||
littleEndian = true;
|
||||
} else if (type == "bytes64") {
|
||||
if (type == "bytes16" || type == "bytes32" || type == "bytes64") {
|
||||
littleEndian = true;
|
||||
}
|
||||
|
||||
MemoryPatcher::PatchMask patchMask = MemoryPatcher::PatchMask::None;
|
||||
int maskOffsetValue = 0;
|
||||
|
||||
if (type == "mask") {
|
||||
if (type == "mask")
|
||||
patchMask = MemoryPatcher::PatchMask::Mask;
|
||||
|
||||
// im not sure if this works, there is no games to test the mask
|
||||
// offset on yet
|
||||
if (!maskOffsetStr.empty())
|
||||
maskOffsetValue = std::stoi(maskOffsetStr, 0, 10);
|
||||
}
|
||||
|
||||
if (type == "mask_jump32")
|
||||
patchMask = MemoryPatcher::PatchMask::Mask_Jump32;
|
||||
|
||||
MemoryPatcher::PatchMemory(currentPatchName, address, patchValue, false,
|
||||
littleEndian, patchMask);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -189,14 +192,16 @@ void OnGameLoaded() {
|
|||
// 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));
|
||||
QString repositories[] = {"GoldHEN", "shadPS4"};
|
||||
QDir dir(patchDir);
|
||||
QStringList folders = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
|
||||
for (const QString& repository : repositories) {
|
||||
QString filesJsonPath = patchDir + "/" + repository + "/files.json";
|
||||
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.");
|
||||
LOG_ERROR(Loader, "Unable to open files.json for reading in repository {}",
|
||||
folder.toStdString());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -220,11 +225,12 @@ void OnGameLoaded() {
|
|||
}
|
||||
|
||||
if (selectedFileName.isEmpty()) {
|
||||
LOG_ERROR(Loader, "No patch file found for the current serial.");
|
||||
LOG_ERROR(Loader, "No patch file found for the current serial in repository {}",
|
||||
folder.toStdString());
|
||||
continue;
|
||||
}
|
||||
|
||||
QString filePath = patchDir + "/" + repository + "/" + selectedFileName;
|
||||
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.");
|
||||
|
@ -274,6 +280,11 @@ void OnGameLoaded() {
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
@ -287,37 +298,39 @@ void OnGameLoaded() {
|
|||
QString patchValue = lineObject["Value"].toString();
|
||||
QString maskOffsetStr = lineObject["Offset"].toString();
|
||||
|
||||
patchValue = QString::fromStdString(
|
||||
convertValueToHex(type.toStdString(), patchValue.toStdString()));
|
||||
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") {
|
||||
if (type == "bytes16" || type == "bytes32" || type == "bytes64")
|
||||
littleEndian = true;
|
||||
} else if (type == "bytes32") {
|
||||
littleEndian = true;
|
||||
} else if (type == "bytes64") {
|
||||
littleEndian = true;
|
||||
}
|
||||
|
||||
MemoryPatcher::PatchMask patchMask = MemoryPatcher::PatchMask::None;
|
||||
int maskOffsetValue = 0;
|
||||
|
||||
if (type == "mask") {
|
||||
if (type == "mask")
|
||||
patchMask = MemoryPatcher::PatchMask::Mask;
|
||||
|
||||
// im not sure if this works, there is no games to test the mask
|
||||
// offset on yet
|
||||
if (!maskOffsetStr.toStdString().empty())
|
||||
maskOffsetValue = std::stoi(maskOffsetStr.toStdString(), 0, 10);
|
||||
}
|
||||
|
||||
if (type == "mask_jump32")
|
||||
patchMask = MemoryPatcher::PatchMask::Mask_Jump32;
|
||||
|
||||
MemoryPatcher::PatchMemory(currentPatchName, address.toStdString(),
|
||||
patchValue.toStdString(), false,
|
||||
littleEndian, patchMask);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -346,7 +359,7 @@ void ApplyPendingPatches() {
|
|||
if (currentPatch.gameSerial != g_game_serial)
|
||||
continue;
|
||||
|
||||
PatchMemory(currentPatch.modNameStr, currentPatch.offsetStr, currentPatch.valueStr,
|
||||
PatchMemory(currentPatch.modNameStr, currentPatch.offsetStr, currentPatch.valueStr, "", "",
|
||||
currentPatch.isOffset, currentPatch.littleEndian, currentPatch.patchMask,
|
||||
currentPatch.maskOffset);
|
||||
}
|
||||
|
@ -354,8 +367,9 @@ void ApplyPendingPatches() {
|
|||
pending_patches.clear();
|
||||
}
|
||||
|
||||
void PatchMemory(std::string modNameStr, std::string offsetStr, std::string valueStr, bool isOffset,
|
||||
bool littleEndian, PatchMask patchMask, int maskOffset) {
|
||||
void PatchMemory(std::string modNameStr, std::string offsetStr, std::string valueStr,
|
||||
std::string targetStr, std::string sizeStr, bool isOffset, bool littleEndian,
|
||||
PatchMask patchMask, int maskOffset) {
|
||||
// Send a request to modify the process memory.
|
||||
void* cheatAddress = nullptr;
|
||||
|
||||
|
@ -372,7 +386,83 @@ void PatchMemory(std::string modNameStr, std::string offsetStr, std::string valu
|
|||
cheatAddress = reinterpret_cast<void*>(PatternScan(offsetStr) + maskOffset);
|
||||
}
|
||||
|
||||
// TODO: implement mask_jump32
|
||||
if (patchMask == PatchMask::Mask_Jump32) {
|
||||
int jumpSize = std::stoi(sizeStr);
|
||||
|
||||
constexpr int MAX_PATTERN_LENGTH = 256;
|
||||
if (jumpSize < 5) {
|
||||
LOG_ERROR(Loader, "Jump size must be at least 5 bytes");
|
||||
return;
|
||||
}
|
||||
if (jumpSize > MAX_PATTERN_LENGTH) {
|
||||
LOG_ERROR(Loader, "Jump size must be no more than {} bytes.", MAX_PATTERN_LENGTH);
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the base address using "Address"
|
||||
uintptr_t baseAddress = PatternScan(offsetStr);
|
||||
if (baseAddress == 0) {
|
||||
LOG_ERROR(Loader, "PatternScan failed for mask_jump32 with pattern: {}", offsetStr);
|
||||
return;
|
||||
}
|
||||
uintptr_t patchAddress = baseAddress + maskOffset;
|
||||
|
||||
// Fills the original region (jumpSize bytes) with NOPs
|
||||
std::vector<u8> nopBytes(jumpSize, 0x90);
|
||||
std::memcpy(reinterpret_cast<void*>(patchAddress), nopBytes.data(), nopBytes.size());
|
||||
|
||||
// Use "Target" to locate the start of the code cave
|
||||
uintptr_t jump_target = PatternScan(targetStr);
|
||||
if (jump_target == 0) {
|
||||
LOG_ERROR(Loader, "PatternScan failed to Target with pattern: {}", targetStr);
|
||||
return;
|
||||
}
|
||||
|
||||
// Converts the Value attribute to a byte array (payload)
|
||||
std::vector<u8> payload;
|
||||
for (size_t i = 0; i < valueStr.length(); i += 2) {
|
||||
|
||||
std::string tempStr = valueStr.substr(i, 2);
|
||||
const char* byteStr = tempStr.c_str();
|
||||
char* endPtr;
|
||||
unsigned int byteVal = std::strtoul(byteStr, &endPtr, 16);
|
||||
|
||||
if (endPtr != byteStr + 2) {
|
||||
LOG_ERROR(Loader, "Invalid byte in Value: {}", valueStr.substr(i, 2));
|
||||
return;
|
||||
}
|
||||
payload.push_back(static_cast<u8>(byteVal));
|
||||
}
|
||||
|
||||
// Calculates the end of the code cave (where the return jump will be inserted)
|
||||
uintptr_t code_cave_end = jump_target + payload.size();
|
||||
|
||||
// Write the payload to the code cave, from jump_target
|
||||
std::memcpy(reinterpret_cast<void*>(jump_target), payload.data(), payload.size());
|
||||
|
||||
// Inserts the initial jump in the original region to divert to the code cave
|
||||
u8 jumpInstruction[5];
|
||||
jumpInstruction[0] = 0xE9;
|
||||
s32 relJump = static_cast<s32>(jump_target - patchAddress - 5);
|
||||
std::memcpy(&jumpInstruction[1], &relJump, sizeof(relJump));
|
||||
std::memcpy(reinterpret_cast<void*>(patchAddress), jumpInstruction,
|
||||
sizeof(jumpInstruction));
|
||||
|
||||
// Inserts jump back at the end of the code cave to resume execution after patching
|
||||
u8 jumpBack[5];
|
||||
jumpBack[0] = 0xE9;
|
||||
// Calculates the relative offset to return to the instruction immediately following the
|
||||
// overwritten region
|
||||
s32 target_return = static_cast<s32>((patchAddress + jumpSize) - (code_cave_end + 5));
|
||||
std::memcpy(&jumpBack[1], &target_return, sizeof(target_return));
|
||||
std::memcpy(reinterpret_cast<void*>(code_cave_end), jumpBack, sizeof(jumpBack));
|
||||
|
||||
LOG_INFO(Loader,
|
||||
"Applied Patch mask_jump32: {}, PatchAddress: {:#x}, JumpTarget: {:#x}, "
|
||||
"CodeCaveEnd: {:#x}, JumpSize: {}",
|
||||
modNameStr, patchAddress, jump_target, code_cave_end, jumpSize);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cheatAddress == nullptr) {
|
||||
LOG_ERROR(Loader, "Failed to get address for patch {}", modNameStr);
|
||||
|
|
|
@ -38,8 +38,9 @@ void OnGameLoaded();
|
|||
void AddPatchToQueue(patchInfo patchToAdd);
|
||||
void ApplyPendingPatches();
|
||||
|
||||
void PatchMemory(std::string modNameStr, std::string offsetStr, std::string valueStr, bool isOffset,
|
||||
bool littleEndian, PatchMask patchMask = PatchMask::None, int maskOffset = 0);
|
||||
void PatchMemory(std::string modNameStr, std::string offsetStr, std::string valueStr,
|
||||
std::string targetStr, std::string sizeStr, bool isOffset, bool littleEndian,
|
||||
PatchMask patchMask = PatchMask::None, int maskOffset = 0);
|
||||
|
||||
static std::vector<int32_t> PatternToByte(const std::string& pattern);
|
||||
uintptr_t PatternScan(const std::string& signature);
|
||||
|
|
|
@ -4,11 +4,6 @@
|
|||
#include "common/native_clock.h"
|
||||
#include "common/rdtsc.h"
|
||||
#include "common/uint128.h"
|
||||
#ifdef _WIN64
|
||||
#include <pthread_time.h>
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
namespace Common {
|
||||
|
||||
|
@ -34,10 +29,4 @@ u64 NativeClock::GetUptime() const {
|
|||
return FencedRDTSC();
|
||||
}
|
||||
|
||||
u64 NativeClock::GetProcessTimeUS() const {
|
||||
timespec ret;
|
||||
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ret);
|
||||
return ret.tv_nsec / 1000 + ret.tv_sec * 1000000;
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
|
|
|
@ -20,7 +20,6 @@ public:
|
|||
u64 GetTimeUS(u64 base_ptc = 0) const;
|
||||
u64 GetTimeMS(u64 base_ptc = 0) const;
|
||||
u64 GetUptime() const;
|
||||
u64 GetProcessTimeUS() const;
|
||||
|
||||
private:
|
||||
u64 rdtsc_frequency;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <fstream>
|
||||
#include <unordered_map>
|
||||
#include "common/logging/log.h"
|
||||
#include "common/path_util.h"
|
||||
|
@ -16,6 +17,8 @@
|
|||
#ifdef _WIN32
|
||||
// This is the maximum number of UTF-16 code units permissible in Windows file paths
|
||||
#define MAX_PATH 260
|
||||
#include <Shlobj.h>
|
||||
#include <windows.h>
|
||||
#else
|
||||
// This is the maximum number of UTF-8 code units permissible in all other OSes' file paths
|
||||
#define MAX_PATH 1024
|
||||
|
@ -57,7 +60,7 @@ static CFURLRef UntranslocateBundlePath(const CFURLRef bundle_path) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static std::filesystem::path GetBundleParentDirectory() {
|
||||
static std::optional<std::filesystem::path> GetBundleParentDirectory() {
|
||||
if (CFBundleRef bundle_ref = CFBundleGetMainBundle()) {
|
||||
if (CFURLRef bundle_url_ref = CFBundleCopyBundleURL(bundle_ref)) {
|
||||
SCOPE_EXIT {
|
||||
|
@ -80,14 +83,16 @@ static std::filesystem::path GetBundleParentDirectory() {
|
|||
}
|
||||
}
|
||||
}
|
||||
return std::filesystem::current_path();
|
||||
return std::nullopt;
|
||||
}
|
||||
#endif
|
||||
|
||||
static auto UserPaths = [] {
|
||||
#ifdef __APPLE__
|
||||
#if defined(__APPLE__) && defined(ENABLE_QT_GUI)
|
||||
// Set the current path to the directory containing the app bundle.
|
||||
std::filesystem::current_path(GetBundleParentDirectory());
|
||||
if (const auto bundle_dir = GetBundleParentDirectory()) {
|
||||
std::filesystem::current_path(*bundle_dir);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Try the portable user directory first.
|
||||
|
@ -105,6 +110,10 @@ static auto UserPaths = [] {
|
|||
} else {
|
||||
user_dir = std::filesystem::path(getenv("HOME")) / ".local" / "share" / "shadPS4";
|
||||
}
|
||||
#elif _WIN32
|
||||
TCHAR appdata[MAX_PATH] = {0};
|
||||
SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, appdata);
|
||||
user_dir = std::filesystem::path(appdata) / "shadPS4";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -128,6 +137,22 @@ static auto UserPaths = [] {
|
|||
create_path(PathType::CheatsDir, user_dir / CHEATS_DIR);
|
||||
create_path(PathType::PatchesDir, user_dir / PATCHES_DIR);
|
||||
create_path(PathType::MetaDataDir, user_dir / METADATA_DIR);
|
||||
create_path(PathType::CustomTrophy, user_dir / CUSTOM_TROPHY);
|
||||
|
||||
std::ofstream notice_file(user_dir / CUSTOM_TROPHY / "Notice.txt");
|
||||
if (notice_file.is_open()) {
|
||||
notice_file
|
||||
<< "++++++++++++++++++++++++++++++++\n+ Custom Trophy Images / Sound "
|
||||
"+\n++++++++++++++++++++++++++++++++\n\nYou can add custom images to the "
|
||||
"trophies.\n*We recommend a square resolution image, for example 200x200, 500x500, "
|
||||
"the same size as the height and width.\nIn this folder ('user\\custom_trophy'), "
|
||||
"add the files with the following "
|
||||
"names:\n\nbronze.png\nsilver.png\ngold.png\nplatinum.png\n\nYou can add a custom "
|
||||
"sound for trophy notifications.\n*By default, no audio is played unless it is in "
|
||||
"this folder and you are using the QT version.\nIn this folder "
|
||||
"('user\\custom_trophy'), add the files with the following names:\n\ntrophy.mp3";
|
||||
notice_file.close();
|
||||
}
|
||||
|
||||
return paths;
|
||||
}();
|
||||
|
@ -176,6 +201,34 @@ void SetUserPath(PathType shad_path, const fs::path& new_path) {
|
|||
UserPaths.insert_or_assign(shad_path, new_path);
|
||||
}
|
||||
|
||||
std::optional<fs::path> FindGameByID(const fs::path& dir, const std::string& game_id,
|
||||
int max_depth) {
|
||||
if (max_depth < 0) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Check if this is the game we're looking for
|
||||
if (dir.filename() == game_id && fs::exists(dir / "sce_sys" / "param.sfo")) {
|
||||
auto eboot_path = dir / "eboot.bin";
|
||||
if (fs::exists(eboot_path)) {
|
||||
return eboot_path;
|
||||
}
|
||||
}
|
||||
|
||||
// Recursively search subdirectories
|
||||
std::error_code ec;
|
||||
for (const auto& entry : fs::directory_iterator(dir, ec)) {
|
||||
if (!entry.is_directory()) {
|
||||
continue;
|
||||
}
|
||||
if (auto found = FindGameByID(entry.path(), game_id, max_depth - 1)) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_QT_GUI
|
||||
void PathToQString(QString& result, const std::filesystem::path& path) {
|
||||
#ifdef _WIN32
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#ifdef ENABLE_QT_GUI
|
||||
|
@ -26,6 +27,7 @@ enum class PathType {
|
|||
CheatsDir, // Where cheats are stored.
|
||||
PatchesDir, // Where patches are stored.
|
||||
MetaDataDir, // Where game metadata (e.g. trophies and menu backgrounds) is stored.
|
||||
CustomTrophy, // Where custom files for trophies are stored.
|
||||
};
|
||||
|
||||
constexpr auto PORTABLE_DIR = "user";
|
||||
|
@ -43,6 +45,7 @@ constexpr auto CAPTURES_DIR = "captures";
|
|||
constexpr auto CHEATS_DIR = "cheats";
|
||||
constexpr auto PATCHES_DIR = "patches";
|
||||
constexpr auto METADATA_DIR = "game_data";
|
||||
constexpr auto CUSTOM_TROPHY = "custom_trophy";
|
||||
|
||||
// Filenames
|
||||
constexpr auto LOG_FILE = "shad_log.txt";
|
||||
|
@ -115,4 +118,18 @@ void PathToQString(QString& result, const std::filesystem::path& path);
|
|||
[[nodiscard]] std::filesystem::path PathFromQString(const QString& path);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Recursively searches for a game directory by its ID.
|
||||
* Limits search depth to prevent excessive filesystem traversal.
|
||||
*
|
||||
* @param dir Base directory to start the search from
|
||||
* @param game_id The game ID to search for
|
||||
* @param max_depth Maximum directory depth to search
|
||||
*
|
||||
* @returns Path to eboot.bin if found, std::nullopt otherwise
|
||||
*/
|
||||
[[nodiscard]] std::optional<std::filesystem::path> FindGameByID(const std::filesystem::path& dir,
|
||||
const std::string& game_id,
|
||||
int max_depth);
|
||||
|
||||
} // namespace Common::FS
|
||||
|
|
|
@ -339,7 +339,9 @@ void CondvarWait(Condvar& cv, std::unique_lock<Lock>& lk, std::stop_token token,
|
|||
}
|
||||
|
||||
std::stop_callback callback(token, [&] {
|
||||
{ std::scoped_lock lk2{*lk.mutex()}; }
|
||||
{
|
||||
std::scoped_lock lk2{*lk.mutex()};
|
||||
}
|
||||
cv.notify_all();
|
||||
});
|
||||
|
||||
|
|
|
@ -3,17 +3,17 @@
|
|||
|
||||
#include "common/scm_rev.h"
|
||||
|
||||
#define GIT_REV "@GIT_REV@"
|
||||
#define GIT_BRANCH "@GIT_BRANCH@"
|
||||
#define GIT_DESC "@GIT_DESC@"
|
||||
#define BUILD_DATE "@BUILD_DATE@"
|
||||
|
||||
namespace Common {
|
||||
|
||||
const char g_scm_rev[] = GIT_REV;
|
||||
const char g_scm_branch[] = GIT_BRANCH;
|
||||
const char g_scm_desc[] = GIT_DESC;
|
||||
const char g_scm_date[] = BUILD_DATE;
|
||||
constexpr char g_version[] = "@APP_VERSION@";
|
||||
constexpr bool g_is_release = @APP_IS_RELEASE@;
|
||||
|
||||
constexpr char g_scm_rev[] = "@GIT_REV@";
|
||||
constexpr char g_scm_branch[] = "@GIT_BRANCH@";
|
||||
constexpr char g_scm_desc[] = "@GIT_DESC@";
|
||||
constexpr char g_scm_remote_name[] = "@GIT_REMOTE_NAME@";
|
||||
constexpr char g_scm_remote_url[] = "@GIT_REMOTE_URL@";
|
||||
constexpr char g_scm_date[] = "@BUILD_DATE@";
|
||||
|
||||
} // namespace
|
||||
|
||||
|
|
|
@ -5,9 +5,14 @@
|
|||
|
||||
namespace Common {
|
||||
|
||||
extern const char g_version[];
|
||||
extern const bool g_is_release;
|
||||
|
||||
extern const char g_scm_rev[];
|
||||
extern const char g_scm_branch[];
|
||||
extern const char g_scm_desc[];
|
||||
extern const char g_scm_remote_name[];
|
||||
extern const char g_scm_remote_url[];
|
||||
extern const char g_scm_date[];
|
||||
|
||||
} // namespace Common
|
||||
|
|
180
src/common/sha1.h
Normal file
180
src/common/sha1.h
Normal file
|
@ -0,0 +1,180 @@
|
|||
// SPDX-FileCopyrightText: 2012 SAURAV MOHAPATRA <mohaps@gmail.com>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
namespace sha1 {
|
||||
class SHA1 {
|
||||
public:
|
||||
typedef uint32_t digest32_t[5];
|
||||
typedef uint8_t digest8_t[20];
|
||||
inline static uint32_t LeftRotate(uint32_t value, size_t count) {
|
||||
return (value << count) ^ (value >> (32 - count));
|
||||
}
|
||||
SHA1() {
|
||||
reset();
|
||||
}
|
||||
virtual ~SHA1() {}
|
||||
SHA1(const SHA1& s) {
|
||||
*this = s;
|
||||
}
|
||||
const SHA1& operator=(const SHA1& s) {
|
||||
memcpy(m_digest, s.m_digest, 5 * sizeof(uint32_t));
|
||||
memcpy(m_block, s.m_block, 64);
|
||||
m_blockByteIndex = s.m_blockByteIndex;
|
||||
m_byteCount = s.m_byteCount;
|
||||
return *this;
|
||||
}
|
||||
SHA1& reset() {
|
||||
m_digest[0] = 0x67452301;
|
||||
m_digest[1] = 0xEFCDAB89;
|
||||
m_digest[2] = 0x98BADCFE;
|
||||
m_digest[3] = 0x10325476;
|
||||
m_digest[4] = 0xC3D2E1F0;
|
||||
m_blockByteIndex = 0;
|
||||
m_byteCount = 0;
|
||||
return *this;
|
||||
}
|
||||
SHA1& processByte(uint8_t octet) {
|
||||
this->m_block[this->m_blockByteIndex++] = octet;
|
||||
++this->m_byteCount;
|
||||
if (m_blockByteIndex == 64) {
|
||||
this->m_blockByteIndex = 0;
|
||||
processBlock();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
SHA1& processBlock(const void* const start, const void* const end) {
|
||||
const uint8_t* begin = static_cast<const uint8_t*>(start);
|
||||
const uint8_t* finish = static_cast<const uint8_t*>(end);
|
||||
while (begin != finish) {
|
||||
processByte(*begin);
|
||||
begin++;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
SHA1& processBytes(const void* const data, size_t len) {
|
||||
const uint8_t* block = static_cast<const uint8_t*>(data);
|
||||
processBlock(block, block + len);
|
||||
return *this;
|
||||
}
|
||||
const uint32_t* getDigest(digest32_t digest) {
|
||||
size_t bitCount = this->m_byteCount * 8;
|
||||
processByte(0x80);
|
||||
if (this->m_blockByteIndex > 56) {
|
||||
while (m_blockByteIndex != 0) {
|
||||
processByte(0);
|
||||
}
|
||||
while (m_blockByteIndex < 56) {
|
||||
processByte(0);
|
||||
}
|
||||
} else {
|
||||
while (m_blockByteIndex < 56) {
|
||||
processByte(0);
|
||||
}
|
||||
}
|
||||
processByte(0);
|
||||
processByte(0);
|
||||
processByte(0);
|
||||
processByte(0);
|
||||
processByte(static_cast<unsigned char>((bitCount >> 24) & 0xFF));
|
||||
processByte(static_cast<unsigned char>((bitCount >> 16) & 0xFF));
|
||||
processByte(static_cast<unsigned char>((bitCount >> 8) & 0xFF));
|
||||
processByte(static_cast<unsigned char>((bitCount) & 0xFF));
|
||||
|
||||
memcpy(digest, m_digest, 5 * sizeof(uint32_t));
|
||||
return digest;
|
||||
}
|
||||
const uint8_t* getDigestBytes(digest8_t digest) {
|
||||
digest32_t d32;
|
||||
getDigest(d32);
|
||||
size_t di = 0;
|
||||
digest[di++] = ((d32[0] >> 24) & 0xFF);
|
||||
digest[di++] = ((d32[0] >> 16) & 0xFF);
|
||||
digest[di++] = ((d32[0] >> 8) & 0xFF);
|
||||
digest[di++] = ((d32[0]) & 0xFF);
|
||||
|
||||
digest[di++] = ((d32[1] >> 24) & 0xFF);
|
||||
digest[di++] = ((d32[1] >> 16) & 0xFF);
|
||||
digest[di++] = ((d32[1] >> 8) & 0xFF);
|
||||
digest[di++] = ((d32[1]) & 0xFF);
|
||||
|
||||
digest[di++] = ((d32[2] >> 24) & 0xFF);
|
||||
digest[di++] = ((d32[2] >> 16) & 0xFF);
|
||||
digest[di++] = ((d32[2] >> 8) & 0xFF);
|
||||
digest[di++] = ((d32[2]) & 0xFF);
|
||||
|
||||
digest[di++] = ((d32[3] >> 24) & 0xFF);
|
||||
digest[di++] = ((d32[3] >> 16) & 0xFF);
|
||||
digest[di++] = ((d32[3] >> 8) & 0xFF);
|
||||
digest[di++] = ((d32[3]) & 0xFF);
|
||||
|
||||
digest[di++] = ((d32[4] >> 24) & 0xFF);
|
||||
digest[di++] = ((d32[4] >> 16) & 0xFF);
|
||||
digest[di++] = ((d32[4] >> 8) & 0xFF);
|
||||
digest[di++] = ((d32[4]) & 0xFF);
|
||||
return digest;
|
||||
}
|
||||
|
||||
protected:
|
||||
void processBlock() {
|
||||
uint32_t w[80];
|
||||
for (size_t i = 0; i < 16; i++) {
|
||||
w[i] = (m_block[i * 4 + 0] << 24);
|
||||
w[i] |= (m_block[i * 4 + 1] << 16);
|
||||
w[i] |= (m_block[i * 4 + 2] << 8);
|
||||
w[i] |= (m_block[i * 4 + 3]);
|
||||
}
|
||||
for (size_t i = 16; i < 80; i++) {
|
||||
w[i] = LeftRotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1);
|
||||
}
|
||||
|
||||
uint32_t a = m_digest[0];
|
||||
uint32_t b = m_digest[1];
|
||||
uint32_t c = m_digest[2];
|
||||
uint32_t d = m_digest[3];
|
||||
uint32_t e = m_digest[4];
|
||||
|
||||
for (std::size_t i = 0; i < 80; ++i) {
|
||||
uint32_t f = 0;
|
||||
uint32_t k = 0;
|
||||
|
||||
if (i < 20) {
|
||||
f = (b & c) | (~b & d);
|
||||
k = 0x5A827999;
|
||||
} else if (i < 40) {
|
||||
f = b ^ c ^ d;
|
||||
k = 0x6ED9EBA1;
|
||||
} else if (i < 60) {
|
||||
f = (b & c) | (b & d) | (c & d);
|
||||
k = 0x8F1BBCDC;
|
||||
} else {
|
||||
f = b ^ c ^ d;
|
||||
k = 0xCA62C1D6;
|
||||
}
|
||||
uint32_t temp = LeftRotate(a, 5) + f + e + k + w[i];
|
||||
e = d;
|
||||
d = c;
|
||||
c = LeftRotate(b, 30);
|
||||
b = a;
|
||||
a = temp;
|
||||
}
|
||||
|
||||
m_digest[0] += a;
|
||||
m_digest[1] += b;
|
||||
m_digest[2] += c;
|
||||
m_digest[3] += d;
|
||||
m_digest[4] += e;
|
||||
}
|
||||
|
||||
private:
|
||||
digest32_t m_digest;
|
||||
uint8_t m_block[64];
|
||||
size_t m_blockByteIndex;
|
||||
size_t m_byteCount;
|
||||
};
|
||||
} // namespace sha1
|
15
src/common/string_literal.h
Normal file
15
src/common/string_literal.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
template <size_t N, typename C = char>
|
||||
struct StringLiteral {
|
||||
static constexpr size_t len = N;
|
||||
|
||||
constexpr StringLiteral(const C (&str)[N]) {
|
||||
std::copy_n(str, N, value);
|
||||
}
|
||||
|
||||
C value[N]{};
|
||||
};
|
|
@ -41,7 +41,7 @@ void SetCurrentThreadRealtime(const std::chrono::nanoseconds period_ns) {
|
|||
const std::chrono::nanoseconds computation_ns = period_ns / 2;
|
||||
|
||||
// Determine the timebase for converting time to ticks.
|
||||
struct mach_timebase_info timebase {};
|
||||
struct mach_timebase_info timebase{};
|
||||
mach_timebase_info(&timebase);
|
||||
const auto ticks_per_ns =
|
||||
static_cast<double>(timebase.denom) / static_cast<double>(timebase.numer);
|
||||
|
|
|
@ -37,6 +37,10 @@ public:
|
|||
void Start();
|
||||
|
||||
void End();
|
||||
|
||||
std::chrono::nanoseconds GetTotalWait() const {
|
||||
return total_wait;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Common
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace Common {
|
||||
|
||||
constexpr char VERSION[] = "0.5.0";
|
||||
constexpr bool isRelease = true;
|
||||
|
||||
} // namespace Common
|
|
@ -21,12 +21,13 @@
|
|||
|
||||
#if defined(__APPLE__) && defined(ARCH_X86_64)
|
||||
// Reserve space for the system address space using a zerofill section.
|
||||
asm(".zerofill GUEST_SYSTEM,GUEST_SYSTEM,__guest_system,0xFBFC00000");
|
||||
asm(".zerofill SYSTEM_MANAGED,SYSTEM_MANAGED,__SYSTEM_MANAGED,0x7FFBFC000");
|
||||
asm(".zerofill SYSTEM_RESERVED,SYSTEM_RESERVED,__SYSTEM_RESERVED,0x7C0004000");
|
||||
#endif
|
||||
|
||||
namespace Core {
|
||||
|
||||
static constexpr size_t BackingSize = SCE_KERNEL_MAIN_DMEM_SIZE_PRO;
|
||||
static constexpr size_t BackingSize = SCE_KERNEL_TOTAL_MEM_PRO;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
@ -67,28 +68,25 @@ struct AddressSpace::Impl {
|
|||
static constexpr size_t ReductionOnFail = 1_GB;
|
||||
static constexpr size_t MaxReductions = 10;
|
||||
|
||||
size_t reduction = 0;
|
||||
size_t virtual_size = SystemManagedSize + SystemReservedSize + UserSize;
|
||||
for (u32 i = 0; i < MaxReductions; i++) {
|
||||
virtual_base = static_cast<u8*>(VirtualAlloc2(process, NULL, virtual_size - reduction,
|
||||
virtual_base = static_cast<u8*>(VirtualAlloc2(process, NULL, virtual_size,
|
||||
MEM_RESERVE | MEM_RESERVE_PLACEHOLDER,
|
||||
PAGE_NOACCESS, ¶m, 1));
|
||||
if (virtual_base) {
|
||||
break;
|
||||
}
|
||||
reduction += ReductionOnFail;
|
||||
virtual_size -= ReductionOnFail;
|
||||
}
|
||||
ASSERT_MSG(virtual_base, "Unable to reserve virtual address space: {}",
|
||||
Common::GetLastErrorMsg());
|
||||
|
||||
// Take the reduction off of the system managed area, and leave the others unchanged.
|
||||
reduction = size_t(virtual_base - SYSTEM_MANAGED_MIN);
|
||||
system_managed_base = virtual_base;
|
||||
system_managed_size = SystemManagedSize - reduction;
|
||||
system_reserved_base = reinterpret_cast<u8*>(SYSTEM_RESERVED_MIN);
|
||||
system_reserved_size = SystemReservedSize;
|
||||
system_managed_base = virtual_base;
|
||||
system_managed_size = system_reserved_base - virtual_base;
|
||||
user_base = reinterpret_cast<u8*>(USER_MIN);
|
||||
user_size = UserSize;
|
||||
user_size = virtual_base + virtual_size - user_base;
|
||||
|
||||
LOG_INFO(Kernel_Vmm, "System managed virtual memory region: {} - {}",
|
||||
fmt::ptr(system_managed_base),
|
||||
|
@ -101,10 +99,8 @@ struct AddressSpace::Impl {
|
|||
|
||||
// Initializer placeholder tracker
|
||||
const uintptr_t system_managed_addr = reinterpret_cast<uintptr_t>(system_managed_base);
|
||||
const uintptr_t system_reserved_addr = reinterpret_cast<uintptr_t>(system_reserved_base);
|
||||
const uintptr_t user_addr = reinterpret_cast<uintptr_t>(user_base);
|
||||
regions.emplace(system_managed_addr,
|
||||
MemoryRegion{system_managed_addr, virtual_size - reduction, false});
|
||||
MemoryRegion{system_managed_addr, virtual_size, false});
|
||||
|
||||
// Allocate backing file that represents the total physical memory.
|
||||
backing_handle =
|
||||
|
|
|
@ -22,24 +22,10 @@
|
|||
#include <windows.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#ifdef __APPLE__
|
||||
#include <half.hpp>
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
using namespace Xbyak::util;
|
||||
|
||||
#define MAYBE_AVX(OPCODE, ...) \
|
||||
[&] { \
|
||||
Cpu cpu; \
|
||||
if (cpu.has(Cpu::tAVX)) { \
|
||||
c.v##OPCODE(__VA_ARGS__); \
|
||||
} else { \
|
||||
c.OPCODE(__VA_ARGS__); \
|
||||
} \
|
||||
}()
|
||||
|
||||
namespace Core {
|
||||
|
||||
static Xbyak::Reg ZydisToXbyakRegister(const ZydisRegister reg) {
|
||||
|
@ -91,469 +77,6 @@ static Xbyak::Address ZydisToXbyakMemoryOperand(const ZydisDecodedOperand& opera
|
|||
return ptr[expression];
|
||||
}
|
||||
|
||||
static u64 ZydisToXbyakImmediateOperand(const ZydisDecodedOperand& operand) {
|
||||
ASSERT_MSG(operand.type == ZYDIS_OPERAND_TYPE_IMMEDIATE,
|
||||
"Expected immediate operand, got type: {}", static_cast<u32>(operand.type));
|
||||
return operand.imm.value.u;
|
||||
}
|
||||
|
||||
static std::unique_ptr<Xbyak::Operand> ZydisToXbyakOperand(const ZydisDecodedOperand& operand) {
|
||||
switch (operand.type) {
|
||||
case ZYDIS_OPERAND_TYPE_REGISTER: {
|
||||
return std::make_unique<Xbyak::Reg>(ZydisToXbyakRegisterOperand(operand));
|
||||
}
|
||||
case ZYDIS_OPERAND_TYPE_MEMORY: {
|
||||
return std::make_unique<Xbyak::Address>(ZydisToXbyakMemoryOperand(operand));
|
||||
}
|
||||
default:
|
||||
UNREACHABLE_MSG("Unsupported operand type: {}", static_cast<u32>(operand.type));
|
||||
}
|
||||
}
|
||||
|
||||
static bool OperandUsesRegister(const Xbyak::Operand* operand, int index) {
|
||||
if (operand->isREG()) {
|
||||
return operand->getIdx() == index;
|
||||
}
|
||||
if (operand->isMEM()) {
|
||||
const Xbyak::RegExp& reg_exp = operand->getAddress().getRegExp();
|
||||
return reg_exp.getBase().getIdx() == index || reg_exp.getIndex().getIdx() == index;
|
||||
}
|
||||
UNREACHABLE_MSG("Unsupported operand kind: {}", static_cast<u32>(operand->getKind()));
|
||||
}
|
||||
|
||||
static bool IsRegisterAllocated(
|
||||
const std::initializer_list<const Xbyak::Operand*>& allocated_registers, const int index) {
|
||||
return std::ranges::find_if(allocated_registers.begin(), allocated_registers.end(),
|
||||
[index](const Xbyak::Operand* operand) {
|
||||
return OperandUsesRegister(operand, index);
|
||||
}) != allocated_registers.end();
|
||||
}
|
||||
|
||||
static Xbyak::Reg AllocateScratchRegister(
|
||||
const std::initializer_list<const Xbyak::Operand*> allocated_registers, const u32 bits) {
|
||||
for (int index = Xbyak::Operand::R8; index <= Xbyak::Operand::R15; index++) {
|
||||
if (!IsRegisterAllocated(allocated_registers, index)) {
|
||||
return Xbyak::Reg32e(index, static_cast<int>(bits));
|
||||
}
|
||||
}
|
||||
UNREACHABLE_MSG("Out of scratch registers!");
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
static pthread_key_t stack_pointer_slot;
|
||||
static pthread_key_t patch_stack_slot;
|
||||
static std::once_flag patch_context_slots_init_flag;
|
||||
static constexpr u32 patch_stack_size = 0x1000;
|
||||
|
||||
static_assert(sizeof(void*) == sizeof(u64),
|
||||
"Cannot fit a register inside a thread local storage slot.");
|
||||
|
||||
static void FreePatchStack(void* patch_stack) {
|
||||
// Subtract back to the bottom of the stack for free.
|
||||
std::free(static_cast<u8*>(patch_stack) - patch_stack_size);
|
||||
}
|
||||
|
||||
static void InitializePatchContextSlots() {
|
||||
ASSERT_MSG(pthread_key_create(&stack_pointer_slot, nullptr) == 0,
|
||||
"Unable to allocate thread-local register for stack pointer.");
|
||||
ASSERT_MSG(pthread_key_create(&patch_stack_slot, FreePatchStack) == 0,
|
||||
"Unable to allocate thread-local register for patch stack.");
|
||||
}
|
||||
|
||||
void InitializeThreadPatchStack() {
|
||||
std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots);
|
||||
|
||||
pthread_setspecific(patch_stack_slot,
|
||||
static_cast<u8*>(std::malloc(patch_stack_size)) + patch_stack_size);
|
||||
}
|
||||
|
||||
/// Saves the stack pointer to thread local storage and loads the patch stack.
|
||||
static void SaveStack(Xbyak::CodeGenerator& c) {
|
||||
std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots);
|
||||
|
||||
// Save original stack pointer and load patch stack.
|
||||
c.putSeg(gs);
|
||||
c.mov(qword[reinterpret_cast<void*>(stack_pointer_slot * sizeof(void*))], rsp);
|
||||
c.putSeg(gs);
|
||||
c.mov(rsp, qword[reinterpret_cast<void*>(patch_stack_slot * sizeof(void*))]);
|
||||
}
|
||||
|
||||
/// Restores the stack pointer from thread local storage.
|
||||
static void RestoreStack(Xbyak::CodeGenerator& c) {
|
||||
std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots);
|
||||
|
||||
// Save patch stack pointer and load original stack.
|
||||
c.putSeg(gs);
|
||||
c.mov(qword[reinterpret_cast<void*>(patch_stack_slot * sizeof(void*))], rsp);
|
||||
c.putSeg(gs);
|
||||
c.mov(rsp, qword[reinterpret_cast<void*>(stack_pointer_slot * sizeof(void*))]);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// These utilities are not implemented as we can't save anything to thread local storage without
|
||||
// temporary registers.
|
||||
void InitializeThreadPatchStack() {
|
||||
// No-op
|
||||
}
|
||||
|
||||
/// Saves the stack pointer to thread local storage and loads the patch stack.
|
||||
static void SaveStack(Xbyak::CodeGenerator& c) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
/// Restores the stack pointer from thread local storage.
|
||||
static void RestoreStack(Xbyak::CodeGenerator& c) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/// Switches to the patch stack, saves registers, and restores the original stack.
|
||||
static void SaveRegisters(Xbyak::CodeGenerator& c, const std::initializer_list<Xbyak::Reg> regs) {
|
||||
SaveStack(c);
|
||||
for (const auto& reg : regs) {
|
||||
c.push(reg.cvt64());
|
||||
}
|
||||
RestoreStack(c);
|
||||
}
|
||||
|
||||
/// Switches to the patch stack, restores registers, and restores the original stack.
|
||||
static void RestoreRegisters(Xbyak::CodeGenerator& c,
|
||||
const std::initializer_list<Xbyak::Reg> regs) {
|
||||
SaveStack(c);
|
||||
for (const auto& reg : regs) {
|
||||
c.pop(reg.cvt64());
|
||||
}
|
||||
RestoreStack(c);
|
||||
}
|
||||
|
||||
/// Switches to the patch stack and stores all registers.
|
||||
static void SaveContext(Xbyak::CodeGenerator& c, bool save_flags = false) {
|
||||
SaveStack(c);
|
||||
for (int reg = Xbyak::Operand::RAX; reg <= Xbyak::Operand::R15; reg++) {
|
||||
c.push(Xbyak::Reg64(reg));
|
||||
}
|
||||
for (int reg = 0; reg <= 7; reg++) {
|
||||
c.lea(rsp, ptr[rsp - 32]);
|
||||
c.vmovdqu(ptr[rsp], Xbyak::Ymm(reg));
|
||||
}
|
||||
if (save_flags) {
|
||||
c.pushfq();
|
||||
}
|
||||
}
|
||||
|
||||
/// Restores all registers and restores the original stack.
|
||||
/// If the destination is a register, it is not restored to preserve the output.
|
||||
static void RestoreContext(Xbyak::CodeGenerator& c, const Xbyak::Operand& dst,
|
||||
bool restore_flags = false) {
|
||||
if (restore_flags) {
|
||||
c.popfq();
|
||||
}
|
||||
for (int reg = 7; reg >= 0; reg--) {
|
||||
if ((!dst.isXMM() && !dst.isYMM()) || dst.getIdx() != reg) {
|
||||
c.vmovdqu(Xbyak::Ymm(reg), ptr[rsp]);
|
||||
}
|
||||
c.lea(rsp, ptr[rsp + 32]);
|
||||
}
|
||||
for (int reg = Xbyak::Operand::R15; reg >= Xbyak::Operand::RAX; reg--) {
|
||||
if (!dst.isREG() || dst.getIdx() != reg) {
|
||||
c.pop(Xbyak::Reg64(reg));
|
||||
} else {
|
||||
c.lea(rsp, ptr[rsp + 8]);
|
||||
}
|
||||
}
|
||||
RestoreStack(c);
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
static void GenerateANDN(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||
const auto src1 = ZydisToXbyakRegisterOperand(operands[1]);
|
||||
const auto src2 = ZydisToXbyakOperand(operands[2]);
|
||||
|
||||
const auto scratch = AllocateScratchRegister({&dst, &src1, src2.get()}, dst.getBit());
|
||||
|
||||
SaveRegisters(c, {scratch});
|
||||
|
||||
c.mov(scratch, src1);
|
||||
c.not_(scratch);
|
||||
c.and_(scratch, *src2);
|
||||
c.mov(dst, scratch);
|
||||
|
||||
RestoreRegisters(c, {scratch});
|
||||
}
|
||||
|
||||
static void GenerateBEXTR(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||
const auto src = ZydisToXbyakOperand(operands[1]);
|
||||
const auto start_len = ZydisToXbyakRegisterOperand(operands[2]);
|
||||
|
||||
const Xbyak::Reg32e shift(Xbyak::Operand::RCX, static_cast<int>(start_len.getBit()));
|
||||
const auto scratch1 =
|
||||
AllocateScratchRegister({&dst, src.get(), &start_len, &shift}, dst.getBit());
|
||||
const auto scratch2 =
|
||||
AllocateScratchRegister({&dst, src.get(), &start_len, &shift, &scratch1}, dst.getBit());
|
||||
|
||||
if (dst.getIdx() == shift.getIdx()) {
|
||||
SaveRegisters(c, {scratch1, scratch2});
|
||||
} else {
|
||||
SaveRegisters(c, {scratch1, scratch2, shift});
|
||||
}
|
||||
|
||||
c.mov(scratch1, *src);
|
||||
if (shift.getIdx() != start_len.getIdx()) {
|
||||
c.mov(shift, start_len);
|
||||
}
|
||||
|
||||
c.shr(scratch1, shift.cvt8());
|
||||
c.shr(shift, 8);
|
||||
c.mov(scratch2, 1);
|
||||
c.shl(scratch2, shift.cvt8());
|
||||
c.dec(scratch2);
|
||||
|
||||
c.mov(dst, scratch1);
|
||||
c.and_(dst, scratch2);
|
||||
|
||||
if (dst.getIdx() == shift.getIdx()) {
|
||||
RestoreRegisters(c, {scratch2, scratch1});
|
||||
} else {
|
||||
RestoreRegisters(c, {shift, scratch2, scratch1});
|
||||
}
|
||||
}
|
||||
|
||||
static void GenerateBLSI(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||
const auto src = ZydisToXbyakOperand(operands[1]);
|
||||
|
||||
const auto scratch = AllocateScratchRegister({&dst, src.get()}, dst.getBit());
|
||||
|
||||
SaveRegisters(c, {scratch});
|
||||
|
||||
// BLSI sets CF to zero if source is zero, otherwise it sets CF to one.
|
||||
Xbyak::Label clear_carry, end;
|
||||
|
||||
c.mov(scratch, *src);
|
||||
c.neg(scratch); // NEG, like BLSI, clears CF if the source is zero and sets it otherwise
|
||||
c.jnc(clear_carry);
|
||||
|
||||
c.and_(scratch, *src);
|
||||
c.stc(); // setting/clearing carry needs to happen after the AND because that clears CF
|
||||
c.jmp(end);
|
||||
|
||||
c.L(clear_carry);
|
||||
c.and_(scratch, *src);
|
||||
// We don't need to clear carry here since AND does that for us
|
||||
|
||||
c.L(end);
|
||||
c.mov(dst, scratch);
|
||||
|
||||
RestoreRegisters(c, {scratch});
|
||||
}
|
||||
|
||||
static void GenerateBLSMSK(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||
const auto src = ZydisToXbyakOperand(operands[1]);
|
||||
|
||||
const auto scratch = AllocateScratchRegister({&dst, src.get()}, dst.getBit());
|
||||
|
||||
SaveRegisters(c, {scratch});
|
||||
|
||||
Xbyak::Label clear_carry, end;
|
||||
|
||||
// BLSMSK sets CF to zero if source is NOT zero, otherwise it sets CF to one.
|
||||
c.mov(scratch, *src);
|
||||
c.test(scratch, scratch);
|
||||
c.jnz(clear_carry);
|
||||
|
||||
c.dec(scratch);
|
||||
c.xor_(scratch, *src);
|
||||
c.stc();
|
||||
c.jmp(end);
|
||||
|
||||
c.L(clear_carry);
|
||||
c.dec(scratch);
|
||||
c.xor_(scratch, *src);
|
||||
// We don't need to clear carry here since XOR does that for us
|
||||
|
||||
c.L(end);
|
||||
c.mov(dst, scratch);
|
||||
|
||||
RestoreRegisters(c, {scratch});
|
||||
}
|
||||
|
||||
static void GenerateBLSR(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||
const auto src = ZydisToXbyakOperand(operands[1]);
|
||||
|
||||
const auto scratch = AllocateScratchRegister({&dst, src.get()}, dst.getBit());
|
||||
|
||||
SaveRegisters(c, {scratch});
|
||||
|
||||
Xbyak::Label clear_carry, end;
|
||||
|
||||
// BLSR sets CF to zero if source is NOT zero, otherwise it sets CF to one.
|
||||
c.mov(scratch, *src);
|
||||
c.test(scratch, scratch);
|
||||
c.jnz(clear_carry);
|
||||
|
||||
c.dec(scratch);
|
||||
c.and_(scratch, *src);
|
||||
c.stc();
|
||||
c.jmp(end);
|
||||
|
||||
c.L(clear_carry);
|
||||
c.dec(scratch);
|
||||
c.and_(scratch, *src);
|
||||
// We don't need to clear carry here since AND does that for us
|
||||
|
||||
c.L(end);
|
||||
c.mov(dst, scratch);
|
||||
|
||||
RestoreRegisters(c, {scratch});
|
||||
}
|
||||
|
||||
static __attribute__((sysv_abi)) void PerformVCVTPH2PS(float* out, const half_float::half* in,
|
||||
const u32 count) {
|
||||
for (u32 i = 0; i < count; i++) {
|
||||
out[i] = half_float::half_cast<float>(in[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void GenerateVCVTPH2PS(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||
const auto src = ZydisToXbyakOperand(operands[1]);
|
||||
|
||||
const auto float_count = dst.getBit() / 32;
|
||||
const auto byte_count = float_count * 4;
|
||||
|
||||
SaveContext(c, true);
|
||||
|
||||
// Allocate stack space for outputs and load into first parameter.
|
||||
c.sub(rsp, byte_count);
|
||||
c.mov(rdi, rsp);
|
||||
|
||||
if (src->isXMM()) {
|
||||
// Allocate stack space for inputs and load into second parameter.
|
||||
c.sub(rsp, byte_count);
|
||||
c.mov(rsi, rsp);
|
||||
|
||||
// Move input to the allocated space.
|
||||
c.movdqu(ptr[rsp], *reinterpret_cast<Xbyak::Xmm*>(src.get()));
|
||||
} else {
|
||||
c.lea(rsi, src->getAddress());
|
||||
}
|
||||
|
||||
// Load float count into third parameter.
|
||||
c.mov(rdx, float_count);
|
||||
|
||||
c.mov(rax, reinterpret_cast<u64>(PerformVCVTPH2PS));
|
||||
c.call(rax);
|
||||
|
||||
if (src->isXMM()) {
|
||||
// Clean up after inputs space.
|
||||
c.add(rsp, byte_count);
|
||||
}
|
||||
|
||||
// Load outputs into destination register and clean up space.
|
||||
if (dst.isYMM()) {
|
||||
c.vmovdqu(*reinterpret_cast<const Xbyak::Ymm*>(&dst), ptr[rsp]);
|
||||
} else {
|
||||
c.movdqu(*reinterpret_cast<const Xbyak::Xmm*>(&dst), ptr[rsp]);
|
||||
}
|
||||
c.add(rsp, byte_count);
|
||||
|
||||
RestoreContext(c, dst, true);
|
||||
}
|
||||
|
||||
using SingleToHalfFloatConverter = half_float::half (*)(float);
|
||||
static const SingleToHalfFloatConverter SingleToHalfFloatConverters[4] = {
|
||||
half_float::half_cast<half_float::half, std::round_to_nearest, float>,
|
||||
half_float::half_cast<half_float::half, std::round_toward_neg_infinity, float>,
|
||||
half_float::half_cast<half_float::half, std::round_toward_infinity, float>,
|
||||
half_float::half_cast<half_float::half, std::round_toward_zero, float>,
|
||||
};
|
||||
|
||||
static __attribute__((sysv_abi)) void PerformVCVTPS2PH(half_float::half* out, const float* in,
|
||||
const u32 count, const u8 rounding_mode) {
|
||||
const auto conversion_func = SingleToHalfFloatConverters[rounding_mode];
|
||||
|
||||
for (u32 i = 0; i < count; i++) {
|
||||
out[i] = conversion_func(in[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void GenerateVCVTPS2PH(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakOperand(operands[0]);
|
||||
const auto src = ZydisToXbyakRegisterOperand(operands[1]);
|
||||
const auto ctrl = ZydisToXbyakImmediateOperand(operands[2]);
|
||||
|
||||
const auto float_count = src.getBit() / 32;
|
||||
const auto byte_count = float_count * 4;
|
||||
|
||||
SaveContext(c, true);
|
||||
|
||||
if (dst->isXMM()) {
|
||||
// Allocate stack space for outputs and load into first parameter.
|
||||
c.sub(rsp, byte_count);
|
||||
c.mov(rdi, rsp);
|
||||
} else {
|
||||
c.lea(rdi, dst->getAddress());
|
||||
}
|
||||
|
||||
// Allocate stack space for inputs and load into second parameter.
|
||||
c.sub(rsp, byte_count);
|
||||
c.mov(rsi, rsp);
|
||||
|
||||
// Move input to the allocated space.
|
||||
if (src.isYMM()) {
|
||||
c.vmovdqu(ptr[rsp], *reinterpret_cast<const Xbyak::Ymm*>(&src));
|
||||
} else {
|
||||
c.movdqu(ptr[rsp], *reinterpret_cast<const Xbyak::Xmm*>(&src));
|
||||
}
|
||||
|
||||
// Load float count into third parameter.
|
||||
c.mov(rdx, float_count);
|
||||
|
||||
// Load rounding mode into fourth parameter.
|
||||
if (ctrl & 4) {
|
||||
// Load from MXCSR.RC.
|
||||
c.stmxcsr(ptr[rsp - 4]);
|
||||
c.mov(rcx, ptr[rsp - 4]);
|
||||
c.shr(rcx, 13);
|
||||
c.and_(rcx, 3);
|
||||
} else {
|
||||
c.mov(rcx, ctrl & 3);
|
||||
}
|
||||
|
||||
c.mov(rax, reinterpret_cast<u64>(PerformVCVTPS2PH));
|
||||
c.call(rax);
|
||||
|
||||
// Clean up after inputs space.
|
||||
c.add(rsp, byte_count);
|
||||
|
||||
if (dst->isXMM()) {
|
||||
// Load outputs into destination register and clean up space.
|
||||
c.movdqu(*reinterpret_cast<Xbyak::Xmm*>(dst.get()), ptr[rsp]);
|
||||
c.add(rsp, byte_count);
|
||||
}
|
||||
|
||||
RestoreContext(c, *dst, true);
|
||||
}
|
||||
|
||||
static bool FilterRosetta2Only(const ZydisDecodedOperand*) {
|
||||
int ret = 0;
|
||||
size_t size = sizeof(ret);
|
||||
if (sysctlbyname("sysctl.proc_translated", &ret, &size, nullptr, 0) != 0) {
|
||||
return false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else // __APPLE__
|
||||
|
||||
static bool FilterTcbAccess(const ZydisDecodedOperand* operands) {
|
||||
const auto& dst_op = operands[0];
|
||||
const auto& src_op = operands[1];
|
||||
|
@ -598,8 +121,6 @@ static void GenerateTcbAccess(const ZydisDecodedOperand* operands, Xbyak::CodeGe
|
|||
#endif
|
||||
}
|
||||
|
||||
#endif // __APPLE__
|
||||
|
||||
static bool FilterNoSSE4a(const ZydisDecodedOperand*) {
|
||||
Cpu cpu;
|
||||
return !cpu.has(Cpu::tSSE4a);
|
||||
|
@ -643,7 +164,7 @@ static void GenerateEXTRQ(const ZydisDecodedOperand* operands, Xbyak::CodeGenera
|
|||
ASSERT_MSG(length + index <= 64, "length + index must be less than or equal to 64.");
|
||||
|
||||
// Get lower qword from xmm register
|
||||
MAYBE_AVX(movq, scratch1, xmm_dst);
|
||||
c.vmovq(scratch1, xmm_dst);
|
||||
|
||||
if (index != 0) {
|
||||
c.shr(scratch1, index);
|
||||
|
@ -656,7 +177,7 @@ static void GenerateEXTRQ(const ZydisDecodedOperand* operands, Xbyak::CodeGenera
|
|||
|
||||
// Writeback to xmm register, extrq instruction says top 64-bits are undefined so we don't
|
||||
// care to preserve them
|
||||
MAYBE_AVX(movq, xmm_dst, scratch1);
|
||||
c.vmovq(xmm_dst, scratch1);
|
||||
|
||||
c.pop(scratch2);
|
||||
c.pop(scratch1);
|
||||
|
@ -690,7 +211,7 @@ static void GenerateEXTRQ(const ZydisDecodedOperand* operands, Xbyak::CodeGenera
|
|||
c.push(mask);
|
||||
|
||||
// Construct the mask out of the length that resides in bottom 6 bits of source xmm
|
||||
MAYBE_AVX(movq, scratch1, xmm_src);
|
||||
c.vmovq(scratch1, xmm_src);
|
||||
c.mov(scratch2, scratch1);
|
||||
c.and_(scratch2, 0x3F);
|
||||
c.jz(length_zero);
|
||||
|
@ -711,10 +232,10 @@ static void GenerateEXTRQ(const ZydisDecodedOperand* operands, Xbyak::CodeGenera
|
|||
c.and_(scratch1, 0x3F);
|
||||
c.mov(scratch2, scratch1); // cl now contains the shift amount
|
||||
|
||||
MAYBE_AVX(movq, scratch1, xmm_dst);
|
||||
c.vmovq(scratch1, xmm_dst);
|
||||
c.shr(scratch1, cl);
|
||||
c.and_(scratch1, mask);
|
||||
MAYBE_AVX(movq, xmm_dst, scratch1);
|
||||
c.vmovq(xmm_dst, scratch1);
|
||||
|
||||
c.pop(mask);
|
||||
c.pop(scratch2);
|
||||
|
@ -765,8 +286,8 @@ static void GenerateINSERTQ(const ZydisDecodedOperand* operands, Xbyak::CodeGene
|
|||
|
||||
ASSERT_MSG(length + index <= 64, "length + index must be less than or equal to 64.");
|
||||
|
||||
MAYBE_AVX(movq, scratch1, xmm_src);
|
||||
MAYBE_AVX(movq, scratch2, xmm_dst);
|
||||
c.vmovq(scratch1, xmm_src);
|
||||
c.vmovq(scratch2, xmm_dst);
|
||||
c.mov(mask, mask_value);
|
||||
|
||||
// src &= mask
|
||||
|
@ -784,12 +305,7 @@ static void GenerateINSERTQ(const ZydisDecodedOperand* operands, Xbyak::CodeGene
|
|||
c.or_(scratch2, scratch1);
|
||||
|
||||
// Insert scratch2 into low 64 bits of dst, upper 64 bits are unaffected
|
||||
Cpu cpu;
|
||||
if (cpu.has(Cpu::tAVX)) {
|
||||
c.vpinsrq(xmm_dst, xmm_dst, scratch2, 0);
|
||||
} else {
|
||||
c.pinsrq(xmm_dst, scratch2, 0);
|
||||
}
|
||||
|
||||
c.pop(mask);
|
||||
c.pop(scratch2);
|
||||
|
@ -816,7 +332,7 @@ static void GenerateINSERTQ(const ZydisDecodedOperand* operands, Xbyak::CodeGene
|
|||
c.push(mask);
|
||||
|
||||
// Get upper 64 bits of src and copy it to mask and index
|
||||
MAYBE_AVX(pextrq, index, xmm_src, 1);
|
||||
c.vpextrq(index, xmm_src, 1);
|
||||
c.mov(mask, index);
|
||||
|
||||
// When length is 0, set it to 64
|
||||
|
@ -839,7 +355,7 @@ static void GenerateINSERTQ(const ZydisDecodedOperand* operands, Xbyak::CodeGene
|
|||
c.and_(index, 0x3F);
|
||||
|
||||
// src &= mask
|
||||
MAYBE_AVX(movq, scratch1, xmm_src);
|
||||
c.vmovq(scratch1, xmm_src);
|
||||
c.and_(scratch1, mask);
|
||||
|
||||
// mask = ~(mask << index)
|
||||
|
@ -851,12 +367,12 @@ static void GenerateINSERTQ(const ZydisDecodedOperand* operands, Xbyak::CodeGene
|
|||
c.shl(scratch1, cl);
|
||||
|
||||
// dst = (dst & mask) | src
|
||||
MAYBE_AVX(movq, scratch2, xmm_dst);
|
||||
c.vmovq(scratch2, xmm_dst);
|
||||
c.and_(scratch2, mask);
|
||||
c.or_(scratch2, scratch1);
|
||||
|
||||
// Upper 64 bits are undefined in insertq
|
||||
MAYBE_AVX(movq, xmm_dst, scratch2);
|
||||
c.vmovq(xmm_dst, scratch2);
|
||||
|
||||
c.pop(mask);
|
||||
c.pop(index);
|
||||
|
@ -881,28 +397,16 @@ struct PatchInfo {
|
|||
};
|
||||
|
||||
static const std::unordered_map<ZydisMnemonic, PatchInfo> Patches = {
|
||||
// SSE4a
|
||||
{ZYDIS_MNEMONIC_EXTRQ, {FilterNoSSE4a, GenerateEXTRQ, true}},
|
||||
{ZYDIS_MNEMONIC_INSERTQ, {FilterNoSSE4a, GenerateINSERTQ, true}},
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Windows needs a trampoline.
|
||||
{ZYDIS_MNEMONIC_MOV, {FilterTcbAccess, GenerateTcbAccess, true}},
|
||||
#elif !defined(__APPLE__)
|
||||
{ZYDIS_MNEMONIC_MOV, {FilterTcbAccess, GenerateTcbAccess, false}},
|
||||
#endif
|
||||
|
||||
{ZYDIS_MNEMONIC_EXTRQ, {FilterNoSSE4a, GenerateEXTRQ, true}},
|
||||
{ZYDIS_MNEMONIC_INSERTQ, {FilterNoSSE4a, GenerateINSERTQ, true}},
|
||||
|
||||
#ifdef __APPLE__
|
||||
// Patches for instruction sets not supported by Rosetta 2.
|
||||
// BMI1
|
||||
{ZYDIS_MNEMONIC_ANDN, {FilterRosetta2Only, GenerateANDN, true}},
|
||||
{ZYDIS_MNEMONIC_BEXTR, {FilterRosetta2Only, GenerateBEXTR, true}},
|
||||
{ZYDIS_MNEMONIC_BLSI, {FilterRosetta2Only, GenerateBLSI, true}},
|
||||
{ZYDIS_MNEMONIC_BLSMSK, {FilterRosetta2Only, GenerateBLSMSK, true}},
|
||||
{ZYDIS_MNEMONIC_BLSR, {FilterRosetta2Only, GenerateBLSR, true}},
|
||||
// F16C
|
||||
{ZYDIS_MNEMONIC_VCVTPH2PS, {FilterRosetta2Only, GenerateVCVTPH2PS, true}},
|
||||
{ZYDIS_MNEMONIC_VCVTPS2PH, {FilterRosetta2Only, GenerateVCVTPS2PH, true}},
|
||||
#endif
|
||||
};
|
||||
|
||||
static std::once_flag init_flag;
|
||||
|
@ -1056,7 +560,7 @@ static bool TryExecuteIllegalInstruction(void* ctx, void* code_address) {
|
|||
if (length + index > 64) {
|
||||
// Undefined behavior if length + index is bigger than 64 according to the spec,
|
||||
// we'll warn and continue execution.
|
||||
LOG_WARNING(Core,
|
||||
LOG_TRACE(Core,
|
||||
"extrq at {} with length {} and index {} is bigger than 64, "
|
||||
"undefined behavior",
|
||||
fmt::ptr(code_address), length, index);
|
||||
|
@ -1116,7 +620,7 @@ static bool TryExecuteIllegalInstruction(void* ctx, void* code_address) {
|
|||
if (length + index > 64) {
|
||||
// Undefined behavior if length + index is bigger than 64 according to the spec,
|
||||
// we'll warn and continue execution.
|
||||
LOG_WARNING(Core,
|
||||
LOG_TRACE(Core,
|
||||
"insertq at {} with length {} and index {} is bigger than 64, "
|
||||
"undefined behavior",
|
||||
fmt::ptr(code_address), length, index);
|
||||
|
@ -1219,18 +723,7 @@ void RegisterPatchModule(void* module_ptr, u64 module_size, void* trampoline_are
|
|||
}
|
||||
|
||||
void PrePatchInstructions(u64 segment_addr, u64 segment_size) {
|
||||
#if defined(__APPLE__)
|
||||
// HACK: For some reason patching in the signal handler at the start of a page does not work
|
||||
// under Rosetta 2. Patch any instructions at the start of a page ahead of time.
|
||||
if (!Patches.empty()) {
|
||||
auto* code_page = reinterpret_cast<u8*>(Common::AlignUp(segment_addr, 0x1000));
|
||||
const auto* end_page = code_page + Common::AlignUp(segment_size, 0x1000);
|
||||
while (code_page < end_page) {
|
||||
TryPatchJit(code_page);
|
||||
code_page += 0x1000;
|
||||
}
|
||||
}
|
||||
#elif !defined(_WIN32)
|
||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
// Linux and others have an FS segment pointing to valid memory, so continue to do full
|
||||
// ahead-of-time patching for now until a better solution is worked out.
|
||||
if (!Patches.empty()) {
|
||||
|
|
|
@ -7,12 +7,6 @@
|
|||
|
||||
namespace Core {
|
||||
|
||||
/// Initializes a stack for the current thread for use by patch implementations.
|
||||
void InitializeThreadPatchStack();
|
||||
|
||||
/// Cleans up the patch stack for the current thread.
|
||||
void CleanupThreadPatchStack();
|
||||
|
||||
/// Registers a module for patching, providing an area to generate trampoline code.
|
||||
void RegisterPatchModule(void* module_ptr, u64 module_size, void* trampoline_area_ptr,
|
||||
u64 trampoline_area_size);
|
||||
|
|
|
@ -1,214 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <array>
|
||||
#include "crypto.h"
|
||||
|
||||
CryptoPP::RSA::PrivateKey Crypto::key_pkg_derived_key3_keyset_init() {
|
||||
CryptoPP::InvertibleRSAFunction params;
|
||||
params.SetPrime1(CryptoPP::Integer(PkgDerivedKey3Keyset::Prime1, 0x80));
|
||||
params.SetPrime2(CryptoPP::Integer(PkgDerivedKey3Keyset::Prime2, 0x80));
|
||||
|
||||
params.SetPublicExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::PublicExponent, 4));
|
||||
params.SetPrivateExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::PrivateExponent, 0x100));
|
||||
|
||||
params.SetModPrime1PrivateExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::Exponent1, 0x80));
|
||||
params.SetModPrime2PrivateExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::Exponent2, 0x80));
|
||||
|
||||
params.SetModulus(CryptoPP::Integer(PkgDerivedKey3Keyset::Modulus, 0x100));
|
||||
params.SetMultiplicativeInverseOfPrime2ModPrime1(
|
||||
CryptoPP::Integer(PkgDerivedKey3Keyset::Coefficient, 0x80));
|
||||
|
||||
CryptoPP::RSA::PrivateKey privateKey(params);
|
||||
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
CryptoPP::RSA::PrivateKey Crypto::FakeKeyset_keyset_init() {
|
||||
CryptoPP::InvertibleRSAFunction params;
|
||||
params.SetPrime1(CryptoPP::Integer(FakeKeyset::Prime1, 0x80));
|
||||
params.SetPrime2(CryptoPP::Integer(FakeKeyset::Prime2, 0x80));
|
||||
|
||||
params.SetPublicExponent(CryptoPP::Integer(FakeKeyset::PublicExponent, 4));
|
||||
params.SetPrivateExponent(CryptoPP::Integer(FakeKeyset::PrivateExponent, 0x100));
|
||||
|
||||
params.SetModPrime1PrivateExponent(CryptoPP::Integer(FakeKeyset::Exponent1, 0x80));
|
||||
params.SetModPrime2PrivateExponent(CryptoPP::Integer(FakeKeyset::Exponent2, 0x80));
|
||||
|
||||
params.SetModulus(CryptoPP::Integer(FakeKeyset::Modulus, 0x100));
|
||||
params.SetMultiplicativeInverseOfPrime2ModPrime1(
|
||||
CryptoPP::Integer(FakeKeyset::Coefficient, 0x80));
|
||||
|
||||
CryptoPP::RSA::PrivateKey privateKey(params);
|
||||
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
CryptoPP::RSA::PrivateKey Crypto::DebugRifKeyset_init() {
|
||||
CryptoPP::InvertibleRSAFunction params;
|
||||
params.SetPrime1(CryptoPP::Integer(DebugRifKeyset::Prime1, sizeof(DebugRifKeyset::Prime1)));
|
||||
params.SetPrime2(CryptoPP::Integer(DebugRifKeyset::Prime2, sizeof(DebugRifKeyset::Prime2)));
|
||||
|
||||
params.SetPublicExponent(
|
||||
CryptoPP::Integer(DebugRifKeyset::PublicExponent, sizeof(DebugRifKeyset::PublicExponent)));
|
||||
params.SetPrivateExponent(CryptoPP::Integer(DebugRifKeyset::PrivateExponent,
|
||||
sizeof(DebugRifKeyset::PrivateExponent)));
|
||||
|
||||
params.SetModPrime1PrivateExponent(
|
||||
CryptoPP::Integer(DebugRifKeyset::Exponent1, sizeof(DebugRifKeyset::Exponent1)));
|
||||
params.SetModPrime2PrivateExponent(
|
||||
CryptoPP::Integer(DebugRifKeyset::Exponent2, sizeof(DebugRifKeyset::Exponent2)));
|
||||
|
||||
params.SetModulus(CryptoPP::Integer(DebugRifKeyset::Modulus, sizeof(DebugRifKeyset::Modulus)));
|
||||
params.SetMultiplicativeInverseOfPrime2ModPrime1(
|
||||
CryptoPP::Integer(DebugRifKeyset::Coefficient, sizeof(DebugRifKeyset::Coefficient)));
|
||||
|
||||
CryptoPP::RSA::PrivateKey privateKey(params);
|
||||
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
void Crypto::RSA2048Decrypt(std::span<CryptoPP::byte, 32> dec_key,
|
||||
std::span<const CryptoPP::byte, 256> ciphertext,
|
||||
bool is_dk3) { // RSAES_PKCS1v15_
|
||||
// Create an RSA decryptor
|
||||
CryptoPP::RSA::PrivateKey privateKey;
|
||||
if (is_dk3) {
|
||||
privateKey = key_pkg_derived_key3_keyset_init();
|
||||
} else {
|
||||
privateKey = FakeKeyset_keyset_init();
|
||||
}
|
||||
|
||||
CryptoPP::RSAES_PKCS1v15_Decryptor rsaDecryptor(privateKey);
|
||||
|
||||
// Allocate memory for the decrypted data
|
||||
std::array<CryptoPP::byte, 256> decrypted;
|
||||
|
||||
// Perform the decryption
|
||||
CryptoPP::AutoSeededRandomPool rng;
|
||||
CryptoPP::DecodingResult result =
|
||||
rsaDecryptor.Decrypt(rng, ciphertext.data(), decrypted.size(), decrypted.data());
|
||||
std::copy(decrypted.begin(), decrypted.begin() + dec_key.size(), dec_key.begin());
|
||||
}
|
||||
|
||||
void Crypto::ivKeyHASH256(std::span<const CryptoPP::byte, 64> cipher_input,
|
||||
std::span<CryptoPP::byte, 32> ivkey_result) {
|
||||
CryptoPP::SHA256 sha256;
|
||||
std::array<CryptoPP::byte, CryptoPP::SHA256::DIGESTSIZE> hashResult;
|
||||
auto array_sink = new CryptoPP::ArraySink(hashResult.data(), CryptoPP::SHA256::DIGESTSIZE);
|
||||
auto filter = new CryptoPP::HashFilter(sha256, array_sink);
|
||||
CryptoPP::ArraySource r(cipher_input.data(), cipher_input.size(), true, filter);
|
||||
std::copy(hashResult.begin(), hashResult.begin() + ivkey_result.size(), ivkey_result.begin());
|
||||
}
|
||||
|
||||
void Crypto::aesCbcCfb128Decrypt(std::span<const CryptoPP::byte, 32> ivkey,
|
||||
std::span<const CryptoPP::byte, 256> ciphertext,
|
||||
std::span<CryptoPP::byte, 256> decrypted) {
|
||||
std::array<CryptoPP::byte, CryptoPP::AES::DEFAULT_KEYLENGTH> key;
|
||||
std::array<CryptoPP::byte, CryptoPP::AES::DEFAULT_KEYLENGTH> iv;
|
||||
|
||||
std::copy(ivkey.begin() + 16, ivkey.begin() + 16 + key.size(), key.begin());
|
||||
std::copy(ivkey.begin(), ivkey.begin() + iv.size(), iv.begin());
|
||||
|
||||
CryptoPP::AES::Decryption aesDecryption(key.data(), CryptoPP::AES::DEFAULT_KEYLENGTH);
|
||||
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv.data());
|
||||
|
||||
for (size_t i = 0; i < decrypted.size(); i += CryptoPP::AES::BLOCKSIZE) {
|
||||
cbcDecryption.ProcessData(decrypted.data() + i, ciphertext.data() + i,
|
||||
CryptoPP::AES::BLOCKSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
void Crypto::aesCbcCfb128DecryptEntry(std::span<const CryptoPP::byte, 32> ivkey,
|
||||
std::span<CryptoPP::byte> ciphertext,
|
||||
std::span<CryptoPP::byte> decrypted) {
|
||||
std::array<CryptoPP::byte, CryptoPP::AES::DEFAULT_KEYLENGTH> key;
|
||||
std::array<CryptoPP::byte, CryptoPP::AES::DEFAULT_KEYLENGTH> iv;
|
||||
|
||||
std::copy(ivkey.begin() + 16, ivkey.begin() + 16 + key.size(), key.begin());
|
||||
std::copy(ivkey.begin(), ivkey.begin() + iv.size(), iv.begin());
|
||||
|
||||
CryptoPP::AES::Decryption aesDecryption(key.data(), CryptoPP::AES::DEFAULT_KEYLENGTH);
|
||||
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv.data());
|
||||
|
||||
for (size_t i = 0; i < decrypted.size(); i += CryptoPP::AES::BLOCKSIZE) {
|
||||
cbcDecryption.ProcessData(decrypted.data() + i, ciphertext.data() + i,
|
||||
CryptoPP::AES::BLOCKSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
void Crypto::decryptEFSM(std::span<CryptoPP::byte, 16> NPcommID,
|
||||
std::span<CryptoPP::byte, 16> efsmIv, std::span<CryptoPP::byte> ciphertext,
|
||||
std::span<CryptoPP::byte> decrypted) {
|
||||
|
||||
std::vector<CryptoPP::byte> TrophyKey = {0x21, 0xF4, 0x1A, 0x6B, 0xAD, 0x8A, 0x1D, 0x3E,
|
||||
0xCA, 0x7A, 0xD5, 0x86, 0xC1, 0x01, 0xB7, 0xA9};
|
||||
std::vector<CryptoPP::byte> TrophyIV = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
// step 1: Encrypt NPcommID
|
||||
CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption encrypt;
|
||||
encrypt.SetKeyWithIV(TrophyKey.data(), TrophyKey.size(), TrophyIV.data());
|
||||
|
||||
std::vector<CryptoPP::byte> trpKey(16);
|
||||
|
||||
encrypt.ProcessData(trpKey.data(), NPcommID.data(), 16);
|
||||
// step 2: decrypt efsm.
|
||||
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption decrypt;
|
||||
decrypt.SetKeyWithIV(trpKey.data(), trpKey.size(), efsmIv.data());
|
||||
|
||||
for (size_t i = 0; i < decrypted.size(); i += CryptoPP::AES::BLOCKSIZE) {
|
||||
decrypt.ProcessData(decrypted.data() + i, ciphertext.data() + i, CryptoPP::AES::BLOCKSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
void Crypto::PfsGenCryptoKey(std::span<const CryptoPP::byte, 32> ekpfs,
|
||||
std::span<const CryptoPP::byte, 16> seed,
|
||||
std::span<CryptoPP::byte, 16> dataKey,
|
||||
std::span<CryptoPP::byte, 16> tweakKey) {
|
||||
CryptoPP::HMAC<CryptoPP::SHA256> hmac(ekpfs.data(), ekpfs.size());
|
||||
|
||||
CryptoPP::SecByteBlock d(20); // Use Crypto++ SecByteBlock for better memory management
|
||||
|
||||
// Copy the bytes of 'index' to the 'd' array
|
||||
uint32_t index = 1;
|
||||
std::memcpy(d, &index, sizeof(uint32_t));
|
||||
|
||||
// Copy the bytes of 'seed' to the 'd' array starting from index 4
|
||||
std::memcpy(d + sizeof(uint32_t), seed.data(), seed.size());
|
||||
|
||||
// Allocate memory for 'u64' using new
|
||||
std::vector<CryptoPP::byte> data_tweak_key(hmac.DigestSize());
|
||||
|
||||
// Calculate the HMAC
|
||||
hmac.CalculateDigest(data_tweak_key.data(), d, d.size());
|
||||
std::copy(data_tweak_key.begin(), data_tweak_key.begin() + dataKey.size(), tweakKey.begin());
|
||||
std::copy(data_tweak_key.begin() + tweakKey.size(),
|
||||
data_tweak_key.begin() + tweakKey.size() + dataKey.size(), dataKey.begin());
|
||||
}
|
||||
|
||||
void Crypto::decryptPFS(std::span<const CryptoPP::byte, 16> dataKey,
|
||||
std::span<const CryptoPP::byte, 16> tweakKey, std::span<const u8> src_image,
|
||||
std::span<CryptoPP::byte> dst_image, u64 sector) {
|
||||
// Start at 0x10000 to keep the header when decrypting the whole pfs_image.
|
||||
for (int i = 0; i < src_image.size(); i += 0x1000) {
|
||||
const u64 current_sector = sector + (i / 0x1000);
|
||||
CryptoPP::ECB_Mode<CryptoPP::AES>::Encryption encrypt(tweakKey.data(), tweakKey.size());
|
||||
CryptoPP::ECB_Mode<CryptoPP::AES>::Decryption decrypt(dataKey.data(), dataKey.size());
|
||||
|
||||
std::array<CryptoPP::byte, 16> tweak{};
|
||||
std::array<CryptoPP::byte, 16> encryptedTweak;
|
||||
std::array<CryptoPP::byte, 16> xorBuffer;
|
||||
std::memcpy(tweak.data(), ¤t_sector, sizeof(u64));
|
||||
|
||||
// Encrypt the tweak for each sector.
|
||||
encrypt.ProcessData(encryptedTweak.data(), tweak.data(), 16);
|
||||
|
||||
for (int plaintextOffset = 0; plaintextOffset < 0x1000; plaintextOffset += 16) {
|
||||
xtsXorBlock(xorBuffer.data(), src_image.data() + i + plaintextOffset,
|
||||
encryptedTweak.data()); // x, c, t
|
||||
decrypt.ProcessData(xorBuffer.data(), xorBuffer.data(), 16); // x, x
|
||||
xtsXorBlock(dst_image.data() + i + plaintextOffset, xorBuffer.data(),
|
||||
encryptedTweak.data()); //(p) c, x , t
|
||||
xtsMult(encryptedTweak);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <span>
|
||||
#include <cryptopp/aes.h>
|
||||
#include <cryptopp/filters.h>
|
||||
#include <cryptopp/modes.h>
|
||||
#include <cryptopp/oaep.h>
|
||||
#include <cryptopp/osrng.h>
|
||||
#include <cryptopp/rsa.h>
|
||||
#include <cryptopp/sha.h>
|
||||
|
||||
#include "common/types.h"
|
||||
#include "keys.h"
|
||||
|
||||
class Crypto {
|
||||
public:
|
||||
CryptoPP::RSA::PrivateKey key_pkg_derived_key3_keyset_init();
|
||||
CryptoPP::RSA::PrivateKey FakeKeyset_keyset_init();
|
||||
CryptoPP::RSA::PrivateKey DebugRifKeyset_init();
|
||||
|
||||
void RSA2048Decrypt(std::span<CryptoPP::byte, 32> dk3,
|
||||
std::span<const CryptoPP::byte, 256> ciphertext,
|
||||
bool is_dk3); // RSAES_PKCS1v15_
|
||||
void ivKeyHASH256(std::span<const CryptoPP::byte, 64> cipher_input,
|
||||
std::span<CryptoPP::byte, 32> ivkey_result);
|
||||
void aesCbcCfb128Decrypt(std::span<const CryptoPP::byte, 32> ivkey,
|
||||
std::span<const CryptoPP::byte, 256> ciphertext,
|
||||
std::span<CryptoPP::byte, 256> decrypted);
|
||||
void aesCbcCfb128DecryptEntry(std::span<const CryptoPP::byte, 32> ivkey,
|
||||
std::span<CryptoPP::byte> ciphertext,
|
||||
std::span<CryptoPP::byte> decrypted);
|
||||
void decryptEFSM(std::span<CryptoPP::byte, 16>, std::span<CryptoPP::byte, 16> efsmIv,
|
||||
std::span<CryptoPP::byte> ciphertext, std::span<CryptoPP::byte> decrypted);
|
||||
void PfsGenCryptoKey(std::span<const CryptoPP::byte, 32> ekpfs,
|
||||
std::span<const CryptoPP::byte, 16> seed,
|
||||
std::span<CryptoPP::byte, 16> dataKey,
|
||||
std::span<CryptoPP::byte, 16> tweakKey);
|
||||
void decryptPFS(std::span<const CryptoPP::byte, 16> dataKey,
|
||||
std::span<const CryptoPP::byte, 16> tweakKey, std::span<const u8> src_image,
|
||||
std::span<CryptoPP::byte> dst_image, u64 sector);
|
||||
|
||||
void xtsXorBlock(CryptoPP::byte* x, const CryptoPP::byte* a, const CryptoPP::byte* b) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
x[i] = a[i] ^ b[i];
|
||||
}
|
||||
}
|
||||
|
||||
void xtsMult(std::span<CryptoPP::byte, 16> encryptedTweak) {
|
||||
int feedback = 0;
|
||||
for (int k = 0; k < encryptedTweak.size(); k++) {
|
||||
const auto tmp = (encryptedTweak[k] >> 7) & 1;
|
||||
encryptedTweak[k] = ((encryptedTweak[k] << 1) + feedback) & 0xFF;
|
||||
feedback = tmp;
|
||||
}
|
||||
if (feedback != 0) {
|
||||
encryptedTweak[0] ^= 0x87;
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,305 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
#include <cryptopp/rsa.h>
|
||||
|
||||
class FakeKeyset {
|
||||
public:
|
||||
// Constructor
|
||||
static constexpr CryptoPP::byte Exponent1[] = {
|
||||
0x6D, 0x48, 0xE0, 0x54, 0x40, 0x25, 0xC8, 0x41, 0x29, 0x52, 0x42, 0x27, 0xEB, 0xD2, 0xC7,
|
||||
0xAB, 0x6B, 0x9C, 0x27, 0x0A, 0xB4, 0x1F, 0x94, 0x4E, 0xFA, 0x42, 0x1D, 0xB7, 0xBC, 0xB9,
|
||||
0xAE, 0xBC, 0x04, 0x6F, 0x75, 0x8F, 0x10, 0x5F, 0x89, 0xAC, 0xAB, 0x9C, 0xD2, 0xFA, 0xE6,
|
||||
0xA4, 0x13, 0x83, 0x68, 0xD4, 0x56, 0x38, 0xFE, 0xE5, 0x2B, 0x78, 0x44, 0x9C, 0x34, 0xE6,
|
||||
0x5A, 0xA0, 0xBE, 0x05, 0x70, 0xAD, 0x15, 0xC3, 0x2D, 0x31, 0xAC, 0x97, 0x5D, 0x88, 0xFC,
|
||||
0xC1, 0x62, 0x3D, 0xE2, 0xED, 0x11, 0xDB, 0xB6, 0x9E, 0xFC, 0x5A, 0x5A, 0x03, 0xF6, 0xCF,
|
||||
0x08, 0xD4, 0x5D, 0x90, 0xC9, 0x2A, 0xB9, 0x9B, 0xCF, 0xC8, 0x1A, 0x65, 0xF3, 0x5B, 0xE8,
|
||||
0x7F, 0xCF, 0xA5, 0xA6, 0x4C, 0x5C, 0x2A, 0x12, 0x0F, 0x92, 0xA5, 0xE3, 0xF0, 0x17, 0x1E,
|
||||
0x9A, 0x97, 0x45, 0x86, 0xFD, 0xDB, 0x54, 0x25};
|
||||
// exponent2 = d mod (q - 1)
|
||||
static constexpr CryptoPP::byte Exponent2[] = {
|
||||
0x2A, 0x51, 0xCE, 0x02, 0x44, 0x28, 0x50, 0xE8, 0x30, 0x20, 0x7C, 0x9C, 0x55, 0xBF, 0x60,
|
||||
0x39, 0xBC, 0xD1, 0xF0, 0xE7, 0x68, 0xF8, 0x08, 0x5B, 0x61, 0x1F, 0xA7, 0xBF, 0xD0, 0xE8,
|
||||
0x8B, 0xB5, 0xB1, 0xD5, 0xD9, 0x16, 0xAC, 0x75, 0x0C, 0x6D, 0xF2, 0xE0, 0xB5, 0x97, 0x75,
|
||||
0xD2, 0x68, 0x16, 0x1F, 0x00, 0x7D, 0x8B, 0x17, 0xE8, 0x78, 0x48, 0x41, 0x71, 0x2B, 0x18,
|
||||
0x96, 0x80, 0x11, 0xDB, 0x68, 0x39, 0x9C, 0xD6, 0xE0, 0x72, 0x42, 0x86, 0xF0, 0x1B, 0x16,
|
||||
0x0D, 0x3E, 0x12, 0x94, 0x3D, 0x25, 0xA8, 0xA9, 0x30, 0x9E, 0x54, 0x5A, 0xD6, 0x36, 0x6C,
|
||||
0xD6, 0x8C, 0x20, 0x62, 0x8F, 0xA1, 0x6B, 0x1F, 0x7C, 0x6D, 0xB2, 0xB1, 0xC1, 0x2E, 0xAD,
|
||||
0x36, 0x02, 0x9C, 0x3A, 0xCA, 0x2F, 0x09, 0xD2, 0x45, 0x9E, 0xEB, 0xF2, 0xBC, 0x6C, 0xAA,
|
||||
0x3B, 0x3E, 0x90, 0xBC, 0x38, 0x67, 0x35, 0x4D};
|
||||
// e
|
||||
static constexpr CryptoPP::byte PublicExponent[] = {0, 1, 0, 1};
|
||||
// (InverseQ)(q) = 1 mod p
|
||||
static constexpr CryptoPP::byte Coefficient[] = {
|
||||
0x0B, 0x67, 0x1C, 0x0D, 0x6C, 0x57, 0xD3, 0xE7, 0x05, 0x65, 0x94, 0x31, 0x56, 0x55, 0xFD,
|
||||
0x28, 0x08, 0xFA, 0x05, 0x8A, 0xCC, 0x55, 0x39, 0x61, 0x97, 0x63, 0xA0, 0x16, 0x27, 0x3D,
|
||||
0xED, 0xC1, 0x16, 0x40, 0x2A, 0x12, 0xEA, 0x6F, 0xD9, 0xD8, 0x58, 0x56, 0xA8, 0x56, 0x8B,
|
||||
0x0D, 0x38, 0x5E, 0x1E, 0x80, 0x3B, 0x5F, 0x40, 0x80, 0x6F, 0x62, 0x4F, 0x28, 0xA2, 0x69,
|
||||
0xF3, 0xD3, 0xF7, 0xFD, 0xB2, 0xC3, 0x52, 0x43, 0x20, 0x92, 0x9D, 0x97, 0x8D, 0xA0, 0x15,
|
||||
0x07, 0x15, 0x6E, 0xA4, 0x0D, 0x56, 0xD3, 0x37, 0x1A, 0xC4, 0x9E, 0xDF, 0x02, 0x49, 0xB8,
|
||||
0x0A, 0x84, 0x62, 0xF5, 0xFA, 0xB9, 0x3F, 0xA4, 0x09, 0x76, 0xCC, 0xAA, 0xB9, 0x9B, 0xA6,
|
||||
0x4F, 0xC1, 0x6A, 0x64, 0xCE, 0xD8, 0x77, 0xAB, 0x4B, 0xF9, 0xA0, 0xAE, 0xDA, 0xF1, 0x67,
|
||||
0x87, 0x7C, 0x98, 0x5C, 0x7E, 0xB8, 0x73, 0xF5};
|
||||
// n = p * q
|
||||
static constexpr CryptoPP::byte Modulus[] = {
|
||||
0xC6, 0xCF, 0x71, 0xE7, 0xE5, 0x9A, 0xF0, 0xD1, 0x2A, 0x2C, 0x45, 0x8B, 0xF9, 0x2A, 0x0E,
|
||||
0xC1, 0x43, 0x05, 0x8B, 0xC3, 0x71, 0x17, 0x80, 0x1D, 0xCD, 0x49, 0x7D, 0xDE, 0x35, 0x9D,
|
||||
0x25, 0x9B, 0xA0, 0xD7, 0xA0, 0xF2, 0x7D, 0x6C, 0x08, 0x7E, 0xAA, 0x55, 0x02, 0x68, 0x2B,
|
||||
0x23, 0xC6, 0x44, 0xB8, 0x44, 0x18, 0xEB, 0x56, 0xCF, 0x16, 0xA2, 0x48, 0x03, 0xC9, 0xE7,
|
||||
0x4F, 0x87, 0xEB, 0x3D, 0x30, 0xC3, 0x15, 0x88, 0xBF, 0x20, 0xE7, 0x9D, 0xFF, 0x77, 0x0C,
|
||||
0xDE, 0x1D, 0x24, 0x1E, 0x63, 0xA9, 0x4F, 0x8A, 0xBF, 0x5B, 0xBE, 0x60, 0x19, 0x68, 0x33,
|
||||
0x3B, 0xFC, 0xED, 0x9F, 0x47, 0x4E, 0x5F, 0xF8, 0xEA, 0xCB, 0x3D, 0x00, 0xBD, 0x67, 0x01,
|
||||
0xF9, 0x2C, 0x6D, 0xC6, 0xAC, 0x13, 0x64, 0xE7, 0x67, 0x14, 0xF3, 0xDC, 0x52, 0x69, 0x6A,
|
||||
0xB9, 0x83, 0x2C, 0x42, 0x30, 0x13, 0x1B, 0xB2, 0xD8, 0xA5, 0x02, 0x0D, 0x79, 0xED, 0x96,
|
||||
0xB1, 0x0D, 0xF8, 0xCC, 0x0C, 0xDF, 0x81, 0x95, 0x4F, 0x03, 0x58, 0x09, 0x57, 0x0E, 0x80,
|
||||
0x69, 0x2E, 0xFE, 0xFF, 0x52, 0x77, 0xEA, 0x75, 0x28, 0xA8, 0xFB, 0xC9, 0xBE, 0xBF, 0x9F,
|
||||
0xBB, 0xB7, 0x79, 0x8E, 0x18, 0x05, 0xE1, 0x80, 0xBD, 0x50, 0x34, 0x94, 0x81, 0xD3, 0x53,
|
||||
0xC2, 0x69, 0xA2, 0xD2, 0x4C, 0xCF, 0x6C, 0xF4, 0x57, 0x2C, 0x10, 0x4A, 0x3F, 0xFB, 0x22,
|
||||
0xFD, 0x8B, 0x97, 0xE2, 0xC9, 0x5B, 0xA6, 0x2B, 0xCD, 0xD6, 0x1B, 0x6B, 0xDB, 0x68, 0x7F,
|
||||
0x4B, 0xC2, 0xA0, 0x50, 0x34, 0xC0, 0x05, 0xE5, 0x8D, 0xEF, 0x24, 0x67, 0xFF, 0x93, 0x40,
|
||||
0xCF, 0x2D, 0x62, 0xA2, 0xA0, 0x50, 0xB1, 0xF1, 0x3A, 0xA8, 0x3D, 0xFD, 0x80, 0xD1, 0xF9,
|
||||
0xB8, 0x05, 0x22, 0xAF, 0xC8, 0x35, 0x45, 0x90, 0x58, 0x8E, 0xE3, 0x3A, 0x7C, 0xBD, 0x3E,
|
||||
0x27};
|
||||
// p
|
||||
static constexpr CryptoPP::byte Prime1[] = {
|
||||
0xFE, 0xF6, 0xBF, 0x1D, 0x69, 0xAB, 0x16, 0x25, 0x08, 0x47, 0x55, 0x6B, 0x86, 0xE4, 0x35,
|
||||
0x88, 0x72, 0x2A, 0xB1, 0x3D, 0xF8, 0xB6, 0x44, 0xCA, 0xB3, 0xAB, 0x19, 0xD1, 0x04, 0x24,
|
||||
0x28, 0x0A, 0x74, 0x55, 0xB8, 0x15, 0x45, 0x09, 0xCC, 0x13, 0x1C, 0xF2, 0xBA, 0x37, 0xA9,
|
||||
0x03, 0x90, 0x8F, 0x02, 0x10, 0xFF, 0x25, 0x79, 0x86, 0xCC, 0x18, 0x50, 0x9A, 0x10, 0x5F,
|
||||
0x5B, 0x4C, 0x1C, 0x4E, 0xB0, 0xA7, 0xE3, 0x59, 0xB1, 0x2D, 0xA0, 0xC6, 0xB0, 0x20, 0x2C,
|
||||
0x21, 0x33, 0x12, 0xB3, 0xAF, 0x72, 0x34, 0x83, 0xCD, 0x52, 0x2F, 0xAF, 0x0F, 0x20, 0x5A,
|
||||
0x1B, 0xC0, 0xE2, 0xA3, 0x76, 0x34, 0x0F, 0xD7, 0xFC, 0xC1, 0x41, 0xC9, 0xF9, 0x79, 0x40,
|
||||
0x17, 0x42, 0x21, 0x3E, 0x9D, 0xFD, 0xC7, 0xC1, 0x50, 0xDE, 0x44, 0x5A, 0xC9, 0x31, 0x89,
|
||||
0x6A, 0x78, 0x05, 0xBE, 0x65, 0xB4, 0xE8, 0x2D};
|
||||
// q
|
||||
static constexpr CryptoPP::byte Prime2[] = {
|
||||
0xC7, 0x9E, 0x47, 0x58, 0x00, 0x7D, 0x62, 0x82, 0xB0, 0xD2, 0x22, 0x81, 0xD4, 0xA8, 0x97,
|
||||
0x1B, 0x79, 0x0C, 0x3A, 0xB0, 0xD7, 0xC9, 0x30, 0xE3, 0xC3, 0x53, 0x8E, 0x57, 0xEF, 0xF0,
|
||||
0x9B, 0x9F, 0xB3, 0x90, 0x52, 0xC6, 0x94, 0x22, 0x36, 0xAA, 0xE6, 0x4A, 0x5F, 0x72, 0x1D,
|
||||
0x70, 0xE8, 0x76, 0x58, 0xC8, 0xB2, 0x91, 0xCE, 0x9C, 0xC3, 0xE9, 0x09, 0x7F, 0x2E, 0x47,
|
||||
0x97, 0xCC, 0x90, 0x39, 0x15, 0x35, 0x31, 0xDE, 0x1F, 0x0C, 0x8C, 0x0D, 0xC1, 0xC2, 0x92,
|
||||
0xBE, 0x97, 0xBF, 0x2F, 0x91, 0xA1, 0x8C, 0x7D, 0x50, 0xA8, 0x21, 0x2F, 0xD7, 0xA2, 0x9A,
|
||||
0x7E, 0xB5, 0xA7, 0x2A, 0x90, 0x02, 0xD9, 0xF3, 0x3D, 0xD1, 0xEB, 0xB8, 0xE0, 0x5A, 0x79,
|
||||
0x9E, 0x7D, 0x8D, 0xCA, 0x18, 0x6D, 0xBD, 0x9E, 0xA1, 0x80, 0x28, 0x6B, 0x2A, 0xFE, 0x51,
|
||||
0x24, 0x9B, 0x6F, 0x4D, 0x84, 0x77, 0x80, 0x23};
|
||||
static constexpr CryptoPP::byte PrivateExponent[] = {
|
||||
0x7F, 0x76, 0xCD, 0x0E, 0xE2, 0xD4, 0xDE, 0x05, 0x1C, 0xC6, 0xD9, 0xA8, 0x0E, 0x8D, 0xFA,
|
||||
0x7B, 0xCA, 0x1E, 0xAA, 0x27, 0x1A, 0x40, 0xF8, 0xF1, 0x22, 0x87, 0x35, 0xDD, 0xDB, 0xFD,
|
||||
0xEE, 0xF8, 0xC2, 0xBC, 0xBD, 0x01, 0xFB, 0x8B, 0xE2, 0x3E, 0x63, 0xB2, 0xB1, 0x22, 0x5C,
|
||||
0x56, 0x49, 0x6E, 0x11, 0xBE, 0x07, 0x44, 0x0B, 0x9A, 0x26, 0x66, 0xD1, 0x49, 0x2C, 0x8F,
|
||||
0xD3, 0x1B, 0xCF, 0xA4, 0xA1, 0xB8, 0xD1, 0xFB, 0xA4, 0x9E, 0xD2, 0x21, 0x28, 0x83, 0x09,
|
||||
0x8A, 0xF6, 0xA0, 0x0B, 0xA3, 0xD6, 0x0F, 0x9B, 0x63, 0x68, 0xCC, 0xBC, 0x0C, 0x4E, 0x14,
|
||||
0x5B, 0x27, 0xA4, 0xA9, 0xF4, 0x2B, 0xB9, 0xB8, 0x7B, 0xC0, 0xE6, 0x51, 0xAD, 0x1D, 0x77,
|
||||
0xD4, 0x6B, 0xB9, 0xCE, 0x20, 0xD1, 0x26, 0x66, 0x7E, 0x5E, 0x9E, 0xA2, 0xE9, 0x6B, 0x90,
|
||||
0xF3, 0x73, 0xB8, 0x52, 0x8F, 0x44, 0x11, 0x03, 0x0C, 0x13, 0x97, 0x39, 0x3D, 0x13, 0x22,
|
||||
0x58, 0xD5, 0x43, 0x82, 0x49, 0xDA, 0x6E, 0x7C, 0xA1, 0xC5, 0x8C, 0xA5, 0xB0, 0x09, 0xE0,
|
||||
0xCE, 0x3D, 0xDF, 0xF4, 0x9D, 0x3C, 0x97, 0x15, 0xE2, 0x6A, 0xC7, 0x2B, 0x3C, 0x50, 0x93,
|
||||
0x23, 0xDB, 0xBA, 0x4A, 0x22, 0x66, 0x44, 0xAC, 0x78, 0xBB, 0x0E, 0x1A, 0x27, 0x43, 0xB5,
|
||||
0x71, 0x67, 0xAF, 0xF4, 0xAB, 0x48, 0x46, 0x93, 0x73, 0xD0, 0x42, 0xAB, 0x93, 0x63, 0xE5,
|
||||
0x6C, 0x9A, 0xDE, 0x50, 0x24, 0xC0, 0x23, 0x7D, 0x99, 0x79, 0x3F, 0x22, 0x07, 0xE0, 0xC1,
|
||||
0x48, 0x56, 0x1B, 0xDF, 0x83, 0x09, 0x12, 0xB4, 0x2D, 0x45, 0x6B, 0xC9, 0xC0, 0x68, 0x85,
|
||||
0x99, 0x90, 0x79, 0x96, 0x1A, 0xD7, 0xF5, 0x4D, 0x1F, 0x37, 0x83, 0x40, 0x4A, 0xEC, 0x39,
|
||||
0x37, 0xA6, 0x80, 0x92, 0x7D, 0xC5, 0x80, 0xC7, 0xD6, 0x6F, 0xFE, 0x8A, 0x79, 0x89, 0xC6,
|
||||
0xB1};
|
||||
};
|
||||
|
||||
class DebugRifKeyset {
|
||||
public:
|
||||
// std::uint8_t* PrivateExponent;
|
||||
static constexpr CryptoPP::byte Exponent1[] = {
|
||||
0xCD, 0x9A, 0x61, 0xB0, 0xB8, 0xD5, 0xB4, 0xE4, 0xE4, 0xF6, 0xAB, 0xF7, 0x27, 0xB7, 0x56,
|
||||
0x59, 0x6B, 0xB9, 0x11, 0xE7, 0xF4, 0x83, 0xAF, 0xB9, 0x73, 0x99, 0x7F, 0x49, 0xA2, 0x9C,
|
||||
0xF0, 0xB5, 0x6D, 0x37, 0x82, 0x14, 0x15, 0xF1, 0x04, 0x8A, 0xD4, 0x8E, 0xEB, 0x2E, 0x1F,
|
||||
0xE2, 0x81, 0xA9, 0x62, 0x6E, 0xB1, 0x68, 0x75, 0x62, 0xF3, 0x0F, 0xFE, 0xD4, 0x91, 0x87,
|
||||
0x98, 0x78, 0xBF, 0x26, 0xB5, 0x07, 0x58, 0xD0, 0xEE, 0x3F, 0x21, 0xE8, 0xC8, 0x0F, 0x5F,
|
||||
0xFA, 0x1C, 0x64, 0x74, 0x49, 0x52, 0xEB, 0xE7, 0xEE, 0xDE, 0xBA, 0x23, 0x26, 0x4A, 0xF6,
|
||||
0x9C, 0x1A, 0x09, 0x3F, 0xB9, 0x0B, 0x36, 0x26, 0x1A, 0xBE, 0xA9, 0x76, 0xE6, 0xF2, 0x69,
|
||||
0xDE, 0xFF, 0xAF, 0xCC, 0x0C, 0x9A, 0x66, 0x03, 0x86, 0x0A, 0x1F, 0x49, 0xA4, 0x10, 0xB6,
|
||||
0xBC, 0xC3, 0x7C, 0x88, 0xE8, 0xCE, 0x4B, 0xD9};
|
||||
// exponent2 = d mod (q - 1)
|
||||
static constexpr CryptoPP::byte Exponent2[] = {
|
||||
0xB3, 0x73, 0xA3, 0x59, 0xE6, 0x97, 0xC0, 0xAB, 0x3B, 0x68, 0xFC, 0x39, 0xAC, 0xDB, 0x44,
|
||||
0xB1, 0xB4, 0x9E, 0x35, 0x4D, 0xBE, 0xC5, 0x36, 0x69, 0x6C, 0x3D, 0xC5, 0xFC, 0xFE, 0x4B,
|
||||
0x2F, 0xDC, 0x86, 0x80, 0x46, 0x96, 0x40, 0x1A, 0x0D, 0x6E, 0xFA, 0x8C, 0xE0, 0x47, 0x91,
|
||||
0xAC, 0xAD, 0x95, 0x2B, 0x8E, 0x1F, 0xF2, 0x0A, 0x45, 0xF8, 0x29, 0x95, 0x70, 0xC6, 0x88,
|
||||
0x5F, 0x71, 0x03, 0x99, 0x79, 0xBC, 0x84, 0x71, 0xBD, 0xE8, 0x84, 0x8C, 0x0E, 0xD4, 0x7B,
|
||||
0x30, 0x74, 0x57, 0x1A, 0x95, 0xE7, 0x90, 0x19, 0x8D, 0xAD, 0x8B, 0x4C, 0x4E, 0xC3, 0xE7,
|
||||
0x6B, 0x23, 0x86, 0x01, 0xEE, 0x9B, 0xE0, 0x2F, 0x15, 0xA2, 0x2C, 0x4C, 0x39, 0xD3, 0xDF,
|
||||
0x9C, 0x39, 0x01, 0xF1, 0x8C, 0x44, 0x4A, 0x15, 0x44, 0xDC, 0x51, 0xF7, 0x22, 0xD7, 0x7F,
|
||||
0x41, 0x7F, 0x68, 0xFA, 0xEE, 0x56, 0xE8, 0x05};
|
||||
// e
|
||||
static constexpr CryptoPP::byte PublicExponent[] = {0x00, 0x01, 0x00, 0x01};
|
||||
// (InverseQ)(q) = 1 mod p
|
||||
static constexpr CryptoPP::byte Coefficient[] = {
|
||||
0xC0, 0x32, 0x43, 0xD3, 0x8C, 0x3D, 0xB4, 0xD2, 0x48, 0x8C, 0x42, 0x41, 0x24, 0x94, 0x6C,
|
||||
0x80, 0xC9, 0xC1, 0x79, 0x36, 0x7F, 0xAC, 0xC3, 0xFF, 0x6A, 0x25, 0xEB, 0x2C, 0xFB, 0xD4,
|
||||
0x2B, 0xA0, 0xEB, 0xFE, 0x25, 0xE9, 0xC6, 0x77, 0xCE, 0xFE, 0x2D, 0x23, 0xFE, 0xD0, 0xF4,
|
||||
0x0F, 0xD9, 0x7E, 0xD5, 0xA5, 0x7D, 0x1F, 0xC0, 0xE8, 0xE8, 0xEC, 0x80, 0x5B, 0xC7, 0xFD,
|
||||
0xE2, 0xBD, 0x94, 0xA6, 0x2B, 0xDD, 0x6A, 0x60, 0x45, 0x54, 0xAB, 0xCA, 0x42, 0x9C, 0x6A,
|
||||
0x6C, 0xBF, 0x3C, 0x84, 0xF9, 0xA5, 0x0E, 0x63, 0x0C, 0x51, 0x58, 0x62, 0x6D, 0x5A, 0xB7,
|
||||
0x3C, 0x3F, 0x49, 0x1A, 0xD0, 0x93, 0xB8, 0x4F, 0x1A, 0x6C, 0x5F, 0xC5, 0xE5, 0xA9, 0x75,
|
||||
0xD4, 0x86, 0x9E, 0xDF, 0x87, 0x0F, 0x27, 0xB0, 0x26, 0x78, 0x4E, 0xFB, 0xC1, 0x8A, 0x4A,
|
||||
0x24, 0x3F, 0x7F, 0x8F, 0x9A, 0x12, 0x51, 0xCB};
|
||||
// n = p * q
|
||||
static constexpr CryptoPP::byte Modulus[] = {
|
||||
0xC2, 0xD2, 0x44, 0xBC, 0xDD, 0x84, 0x3F, 0xD9, 0xC5, 0x22, 0xAF, 0xF7, 0xFC, 0x88, 0x8A,
|
||||
0x33, 0x80, 0xED, 0x8E, 0xE2, 0xCC, 0x81, 0xF7, 0xEC, 0xF8, 0x1C, 0x79, 0xBF, 0x02, 0xBB,
|
||||
0x12, 0x8E, 0x61, 0x68, 0x29, 0x1B, 0x15, 0xB6, 0x5E, 0xC6, 0xF8, 0xBF, 0x5A, 0xE0, 0x3B,
|
||||
0x6A, 0x6C, 0xD9, 0xD6, 0xF5, 0x75, 0xAB, 0xA0, 0x6F, 0x34, 0x81, 0x34, 0x9A, 0x5B, 0xAD,
|
||||
0xED, 0x31, 0xE3, 0xC6, 0xEA, 0x1A, 0xD1, 0x13, 0x22, 0xBB, 0xB3, 0xDA, 0xB3, 0xB2, 0x53,
|
||||
0xBD, 0x45, 0x79, 0x87, 0xAD, 0x0A, 0x01, 0x72, 0x18, 0x10, 0x29, 0x49, 0xF4, 0x41, 0x7F,
|
||||
0xD6, 0x47, 0x0C, 0x72, 0x92, 0x9E, 0xE9, 0xBB, 0x95, 0xA9, 0x5D, 0x79, 0xEB, 0xE4, 0x30,
|
||||
0x76, 0x90, 0x45, 0x4B, 0x9D, 0x9C, 0xCF, 0x92, 0x03, 0x60, 0x8C, 0x4B, 0x6C, 0xB3, 0x7A,
|
||||
0x3A, 0x05, 0x39, 0xA0, 0x66, 0xA9, 0x35, 0xCF, 0xB9, 0xFA, 0xAD, 0x9C, 0xAB, 0xEB, 0xE4,
|
||||
0x6A, 0x8C, 0xE9, 0x3B, 0xCC, 0x72, 0x12, 0x62, 0x63, 0xBD, 0x80, 0xC4, 0xEE, 0x37, 0x2B,
|
||||
0x32, 0x03, 0xA3, 0x09, 0xF7, 0xA0, 0x61, 0x57, 0xAD, 0x0D, 0xCF, 0x15, 0x98, 0x9E, 0x4E,
|
||||
0x49, 0xF8, 0xB5, 0xA3, 0x5C, 0x27, 0xEE, 0x45, 0x04, 0xEA, 0xE4, 0x4B, 0xBC, 0x8F, 0x87,
|
||||
0xED, 0x19, 0x1E, 0x46, 0x75, 0x63, 0xC4, 0x5B, 0xD5, 0xBC, 0x09, 0x2F, 0x02, 0x73, 0x19,
|
||||
0x3C, 0x58, 0x55, 0x49, 0x66, 0x4C, 0x11, 0xEC, 0x0F, 0x09, 0xFA, 0xA5, 0x56, 0x0A, 0x5A,
|
||||
0x63, 0x56, 0xAD, 0xA0, 0x0D, 0x86, 0x08, 0xC1, 0xE6, 0xB6, 0x13, 0x22, 0x49, 0x2F, 0x7C,
|
||||
0xDB, 0x4C, 0x56, 0x97, 0x0E, 0xC2, 0xD9, 0x2E, 0x87, 0xBC, 0x0E, 0x67, 0xC0, 0x1B, 0x58,
|
||||
0xBC, 0x64, 0x2B, 0xC2, 0x6E, 0xE2, 0x93, 0x2E, 0xB5, 0x6B, 0x70, 0xA4, 0x42, 0x9F, 0x64,
|
||||
0xC1};
|
||||
// p
|
||||
static constexpr CryptoPP::byte Prime1[] = {
|
||||
0xE5, 0x62, 0xE1, 0x7F, 0x9F, 0x86, 0x08, 0xE2, 0x61, 0xD3, 0xD0, 0x42, 0xE2, 0xC4, 0xB6,
|
||||
0xA8, 0x51, 0x09, 0x19, 0x14, 0xA4, 0x3A, 0x11, 0x4C, 0x33, 0xA5, 0x9C, 0x01, 0x5E, 0x34,
|
||||
0xB6, 0x3F, 0x02, 0x1A, 0xCA, 0x47, 0xF1, 0x4F, 0x3B, 0x35, 0x2A, 0x07, 0x20, 0xEC, 0xD8,
|
||||
0xC1, 0x15, 0xD9, 0xCA, 0x03, 0x4F, 0xB8, 0xE8, 0x09, 0x73, 0x3F, 0x85, 0xB7, 0x41, 0xD5,
|
||||
0x51, 0x3E, 0x7B, 0xE3, 0x53, 0x2B, 0x48, 0x8B, 0x8E, 0xCB, 0xBA, 0xF7, 0xE0, 0x60, 0xF5,
|
||||
0x35, 0x0E, 0x6F, 0xB0, 0xD9, 0x2A, 0x99, 0xD0, 0xFF, 0x60, 0x14, 0xED, 0x40, 0xEA, 0xF8,
|
||||
0xD7, 0x0B, 0xC3, 0x8D, 0x8C, 0xE8, 0x81, 0xB3, 0x75, 0x93, 0x15, 0xB3, 0x7D, 0xF6, 0x39,
|
||||
0x60, 0x1A, 0x00, 0xE7, 0xC3, 0x27, 0xAD, 0xA4, 0x33, 0xD5, 0x3E, 0xA4, 0x35, 0x48, 0x6F,
|
||||
0x22, 0xEF, 0x5D, 0xDD, 0x7D, 0x7B, 0x61, 0x05};
|
||||
// q
|
||||
static constexpr CryptoPP::byte Prime2[] = {
|
||||
0xD9, 0x6C, 0xC2, 0x0C, 0xF7, 0xAE, 0xD1, 0xF3, 0x3B, 0x3B, 0x49, 0x1E, 0x9F, 0x12, 0x9C,
|
||||
0xA1, 0x78, 0x1F, 0x35, 0x1D, 0x98, 0x26, 0x13, 0x71, 0xF9, 0x09, 0xFD, 0xF0, 0xAD, 0x38,
|
||||
0x55, 0xB7, 0xEE, 0x61, 0x04, 0x72, 0x51, 0x87, 0x2E, 0x05, 0x84, 0xB1, 0x1D, 0x0C, 0x0D,
|
||||
0xDB, 0xD4, 0x25, 0x3E, 0x26, 0xED, 0xEA, 0xB8, 0xF7, 0x49, 0xFE, 0xA2, 0x94, 0xE6, 0xF2,
|
||||
0x08, 0x92, 0xA7, 0x85, 0xF5, 0x30, 0xB9, 0x84, 0x22, 0xBF, 0xCA, 0xF0, 0x5F, 0xCB, 0x31,
|
||||
0x20, 0x34, 0x49, 0x16, 0x76, 0x34, 0xCC, 0x7A, 0xCB, 0x96, 0xFE, 0x78, 0x7A, 0x41, 0xFE,
|
||||
0x9A, 0xA2, 0x23, 0xF7, 0x68, 0x80, 0xD6, 0xCE, 0x4A, 0x78, 0xA5, 0xB7, 0x05, 0x77, 0x81,
|
||||
0x1F, 0xDE, 0x5E, 0xA8, 0x6E, 0x3E, 0x87, 0xEC, 0x44, 0xD2, 0x69, 0xC6, 0x54, 0x91, 0x6B,
|
||||
0x5E, 0x13, 0x8A, 0x03, 0x87, 0x05, 0x31, 0x8D};
|
||||
static constexpr CryptoPP::byte PrivateExponent[] = {
|
||||
0x01, 0x61, 0xAD, 0xD8, 0x9C, 0x06, 0x89, 0xD0, 0x60, 0xC8, 0x41, 0xF0, 0xB3, 0x83, 0x01,
|
||||
0x5D, 0xE3, 0xA2, 0x6B, 0xA2, 0xBA, 0x9A, 0x0A, 0x58, 0xCD, 0x1A, 0xA0, 0x97, 0x64, 0xEC,
|
||||
0xD0, 0x31, 0x1F, 0xCA, 0x36, 0x0E, 0x69, 0xDD, 0x40, 0xF7, 0x4E, 0xC0, 0xC6, 0xA3, 0x73,
|
||||
0xF0, 0x69, 0x84, 0xB2, 0xF4, 0x4B, 0x29, 0x14, 0x2A, 0x6D, 0xB8, 0x23, 0xD8, 0x1B, 0x61,
|
||||
0xD4, 0x9E, 0x87, 0xB3, 0xBB, 0xA9, 0xC4, 0x85, 0x4A, 0xF8, 0x03, 0x4A, 0xBF, 0xFE, 0xF9,
|
||||
0xFE, 0x8B, 0xDD, 0x54, 0x83, 0xBA, 0xE0, 0x2F, 0x3F, 0xB1, 0xEF, 0xA5, 0x05, 0x5D, 0x28,
|
||||
0x8B, 0xAB, 0xB5, 0xD0, 0x23, 0x2F, 0x8A, 0xCF, 0x48, 0x7C, 0xAA, 0xBB, 0xC8, 0x5B, 0x36,
|
||||
0x27, 0xC5, 0x16, 0xA4, 0xB6, 0x61, 0xAC, 0x0C, 0x28, 0x47, 0x79, 0x3F, 0x38, 0xAE, 0x5E,
|
||||
0x25, 0xC6, 0xAF, 0x35, 0xAE, 0xBC, 0xB0, 0xF3, 0xBC, 0xBD, 0xFD, 0xA4, 0x87, 0x0D, 0x14,
|
||||
0x3D, 0x90, 0xE4, 0xDE, 0x5D, 0x1D, 0x46, 0x81, 0xF1, 0x28, 0x6D, 0x2F, 0x2C, 0x5E, 0x97,
|
||||
0x2D, 0x89, 0x2A, 0x51, 0x72, 0x3C, 0x20, 0x02, 0x59, 0xB1, 0x98, 0x93, 0x05, 0x1E, 0x3F,
|
||||
0xA1, 0x8A, 0x69, 0x30, 0x0E, 0x70, 0x84, 0x8B, 0xAE, 0x97, 0xA1, 0x08, 0x95, 0x63, 0x4C,
|
||||
0xC7, 0xE8, 0x5D, 0x59, 0xCA, 0x78, 0x2A, 0x23, 0x87, 0xAC, 0x6F, 0x04, 0x33, 0xB1, 0x61,
|
||||
0xB9, 0xF0, 0x95, 0xDA, 0x33, 0xCC, 0xE0, 0x4C, 0x82, 0x68, 0x82, 0x14, 0x51, 0xBE, 0x49,
|
||||
0x1C, 0x58, 0xA2, 0x8B, 0x05, 0x4E, 0x98, 0x37, 0xEB, 0x94, 0x0B, 0x01, 0x22, 0xDC, 0xB3,
|
||||
0x19, 0xCA, 0x77, 0xA6, 0x6E, 0x97, 0xFF, 0x8A, 0x53, 0x5A, 0xC5, 0x24, 0xE4, 0xAF, 0x6E,
|
||||
0xA8, 0x2B, 0x53, 0xA4, 0xBE, 0x96, 0xA5, 0x7B, 0xCE, 0x22, 0x56, 0xA3, 0xF1, 0xCF, 0x14,
|
||||
0xA5};
|
||||
};
|
||||
|
||||
class PkgDerivedKey3Keyset {
|
||||
public:
|
||||
// std::uint8_t* PrivateExponent;
|
||||
static constexpr CryptoPP::byte Exponent1[] = {
|
||||
0x52, 0xCC, 0x2D, 0xA0, 0x9C, 0x9E, 0x75, 0xE7, 0x28, 0xEE, 0x3D, 0xDE, 0xE3, 0x45, 0xD1,
|
||||
0x4F, 0x94, 0x1C, 0xCC, 0xC8, 0x87, 0x29, 0x45, 0x3B, 0x8D, 0x6E, 0xAB, 0x6E, 0x2A, 0xA7,
|
||||
0xC7, 0x15, 0x43, 0xA3, 0x04, 0x8F, 0x90, 0x5F, 0xEB, 0xF3, 0x38, 0x4A, 0x77, 0xFA, 0x36,
|
||||
0xB7, 0x15, 0x76, 0xB6, 0x01, 0x1A, 0x8E, 0x25, 0x87, 0x82, 0xF1, 0x55, 0xD8, 0xC6, 0x43,
|
||||
0x2A, 0xC0, 0xE5, 0x98, 0xC9, 0x32, 0xD1, 0x94, 0x6F, 0xD9, 0x01, 0xBA, 0x06, 0x81, 0xE0,
|
||||
0x6D, 0x88, 0xF2, 0x24, 0x2A, 0x25, 0x01, 0x64, 0x5C, 0xBF, 0xF2, 0xD9, 0x99, 0x67, 0x3E,
|
||||
0xF6, 0x72, 0xEE, 0xE4, 0xE2, 0x33, 0x5C, 0xF8, 0x00, 0x40, 0xE3, 0x2A, 0x9A, 0xF4, 0x3D,
|
||||
0x22, 0x86, 0x44, 0x3C, 0xFB, 0x0A, 0xA5, 0x7C, 0x3F, 0xCC, 0xF5, 0xF1, 0x16, 0xC4, 0xAC,
|
||||
0x88, 0xB4, 0xDE, 0x62, 0x94, 0x92, 0x6A, 0x13};
|
||||
// exponent2 = d mod (q - 1)
|
||||
static constexpr CryptoPP::byte Exponent2[] = {
|
||||
0x7C, 0x9D, 0xAD, 0x39, 0xE0, 0xD5, 0x60, 0x14, 0x94, 0x48, 0x19, 0x7F, 0x88, 0x95, 0xD5,
|
||||
0x8B, 0x80, 0xAD, 0x85, 0x8A, 0x4B, 0x77, 0x37, 0x85, 0xD0, 0x77, 0xBB, 0xBF, 0x89, 0x71,
|
||||
0x4A, 0x72, 0xCB, 0x72, 0x68, 0x38, 0xEC, 0x02, 0xC6, 0x7D, 0xC6, 0x44, 0x06, 0x33, 0x51,
|
||||
0x1C, 0xC0, 0xFF, 0x95, 0x8F, 0x0D, 0x75, 0xDC, 0x25, 0xBB, 0x0B, 0x73, 0x91, 0xA9, 0x6D,
|
||||
0x42, 0xD8, 0x03, 0xB7, 0x68, 0xD4, 0x1E, 0x75, 0x62, 0xA3, 0x70, 0x35, 0x79, 0x78, 0x00,
|
||||
0xC8, 0xF5, 0xEF, 0x15, 0xB9, 0xFC, 0x4E, 0x47, 0x5A, 0xC8, 0x70, 0x70, 0x5B, 0x52, 0x98,
|
||||
0xC0, 0xC2, 0x58, 0x4A, 0x70, 0x96, 0xCC, 0xB8, 0x10, 0xE1, 0x2F, 0x78, 0x8B, 0x2B, 0xA1,
|
||||
0x7F, 0xF9, 0xAC, 0xDE, 0xF0, 0xBB, 0x2B, 0xE2, 0x66, 0xE3, 0x22, 0x92, 0x31, 0x21, 0x57,
|
||||
0x92, 0xC4, 0xB8, 0xF2, 0x3E, 0x76, 0x20, 0x37};
|
||||
// e
|
||||
static constexpr CryptoPP::byte PublicExponent[] = {0, 1, 0, 1};
|
||||
// (InverseQ)(q) = 1 mod p
|
||||
static constexpr CryptoPP::byte Coefficient[] = {
|
||||
0x45, 0x97, 0x55, 0xD4, 0x22, 0x08, 0x5E, 0xF3, 0x5C, 0xB4, 0x05, 0x7A, 0xFD, 0xAA, 0x42,
|
||||
0x42, 0xAD, 0x9A, 0x8C, 0xA0, 0x6C, 0xBB, 0x1D, 0x68, 0x54, 0x54, 0x6E, 0x3E, 0x32, 0xE3,
|
||||
0x53, 0x73, 0x76, 0xF1, 0x3E, 0x01, 0xEA, 0xD3, 0xCF, 0xEB, 0xEB, 0x23, 0x3E, 0xC0, 0xBE,
|
||||
0xCE, 0xEC, 0x2C, 0x89, 0x5F, 0xA8, 0x27, 0x3A, 0x4C, 0xB7, 0xE6, 0x74, 0xBC, 0x45, 0x4C,
|
||||
0x26, 0xC8, 0x25, 0xFF, 0x34, 0x63, 0x25, 0x37, 0xE1, 0x48, 0x10, 0xC1, 0x93, 0xA6, 0xAF,
|
||||
0xEB, 0xBA, 0xE3, 0xA2, 0xF1, 0x3D, 0xEF, 0x63, 0xD8, 0xF4, 0xFD, 0xD3, 0xEE, 0xE2, 0x5D,
|
||||
0xE9, 0x33, 0xCC, 0xAD, 0xBA, 0x75, 0x5C, 0x85, 0xAF, 0xCE, 0xA9, 0x3D, 0xD1, 0xA2, 0x17,
|
||||
0xF3, 0xF6, 0x98, 0xB3, 0x50, 0x8E, 0x5E, 0xF6, 0xEB, 0x02, 0x8E, 0xA1, 0x62, 0xA7, 0xD6,
|
||||
0x2C, 0xEC, 0x91, 0xFF, 0x15, 0x40, 0xD2, 0xE3};
|
||||
// n = p * q
|
||||
static constexpr CryptoPP::byte Modulus[] = {
|
||||
0xd2, 0x12, 0xfc, 0x33, 0x5f, 0x6d, 0xdb, 0x83, 0x16, 0x09, 0x62, 0x8b, 0x03, 0x56, 0x27,
|
||||
0x37, 0x82, 0xd4, 0x77, 0x85, 0x35, 0x29, 0x39, 0x2d, 0x52, 0x6b, 0x8c, 0x4c, 0x8c, 0xfb,
|
||||
0x06, 0xc1, 0x84, 0x5b, 0xe7, 0xd4, 0xf7, 0xbc, 0xd2, 0x4e, 0x62, 0x45, 0xcd, 0x2a, 0xbb,
|
||||
0xd7, 0x77, 0x76, 0x45, 0x36, 0x55, 0x27, 0x3f, 0xb3, 0xf5, 0xf9, 0x8e, 0xda, 0x4b, 0xef,
|
||||
0xaa, 0x59, 0xae, 0xb3, 0x9b, 0xea, 0x54, 0x98, 0xd2, 0x06, 0x32, 0x6a, 0x58, 0x31, 0x2a,
|
||||
0xe0, 0xd4, 0x4f, 0x90, 0xb5, 0x0a, 0x7d, 0xec, 0xf4, 0x3a, 0x9c, 0x52, 0x67, 0x2d, 0x99,
|
||||
0x31, 0x8e, 0x0c, 0x43, 0xe6, 0x82, 0xfe, 0x07, 0x46, 0xe1, 0x2e, 0x50, 0xd4, 0x1f, 0x2d,
|
||||
0x2f, 0x7e, 0xd9, 0x08, 0xba, 0x06, 0xb3, 0xbf, 0x2e, 0x20, 0x3f, 0x4e, 0x3f, 0xfe, 0x44,
|
||||
0xff, 0xaa, 0x50, 0x43, 0x57, 0x91, 0x69, 0x94, 0x49, 0x15, 0x82, 0x82, 0xe4, 0x0f, 0x4c,
|
||||
0x8d, 0x9d, 0x2c, 0xc9, 0x5b, 0x1d, 0x64, 0xbf, 0x88, 0x8b, 0xd4, 0xc5, 0x94, 0xe7, 0x65,
|
||||
0x47, 0x84, 0x1e, 0xe5, 0x79, 0x10, 0xfb, 0x98, 0x93, 0x47, 0xb9, 0x7d, 0x85, 0x12, 0xa6,
|
||||
0x40, 0x98, 0x2c, 0xf7, 0x92, 0xbc, 0x95, 0x19, 0x32, 0xed, 0xe8, 0x90, 0x56, 0x0d, 0x65,
|
||||
0xc1, 0xaa, 0x78, 0xc6, 0x2e, 0x54, 0xfd, 0x5f, 0x54, 0xa1, 0xf6, 0x7e, 0xe5, 0xe0, 0x5f,
|
||||
0x61, 0xc1, 0x20, 0xb4, 0xb9, 0xb4, 0x33, 0x08, 0x70, 0xe4, 0xdf, 0x89, 0x56, 0xed, 0x01,
|
||||
0x29, 0x46, 0x77, 0x5f, 0x8c, 0xb8, 0xa9, 0xf5, 0x1e, 0x2e, 0xb3, 0xb9, 0xbf, 0xe0, 0x09,
|
||||
0xb7, 0x8d, 0x28, 0xd4, 0xa6, 0xc3, 0xb8, 0x1e, 0x1f, 0x07, 0xeb, 0xb4, 0x12, 0x0b, 0x95,
|
||||
0xb8, 0x85, 0x30, 0xfd, 0xdc, 0x39, 0x13, 0xd0, 0x7c, 0xdc, 0x8f, 0xed, 0xf9, 0xc9, 0xa3,
|
||||
0xc1};
|
||||
// p
|
||||
static constexpr CryptoPP::byte Prime1[] = {
|
||||
0xF9, 0x67, 0xAD, 0x99, 0x12, 0x31, 0x0C, 0x56, 0xA2, 0x2E, 0x16, 0x1C, 0x46, 0xB3, 0x4D,
|
||||
0x5B, 0x43, 0xBE, 0x42, 0xA2, 0xF6, 0x86, 0x96, 0x80, 0x42, 0xC3, 0xC7, 0x3F, 0xC3, 0x42,
|
||||
0xF5, 0x87, 0x49, 0x33, 0x9F, 0x07, 0x5D, 0x6E, 0x2C, 0x04, 0xFD, 0xE3, 0xE1, 0xB2, 0xAE,
|
||||
0x0A, 0x0C, 0xF0, 0xC7, 0xA6, 0x1C, 0xA1, 0x63, 0x50, 0xC8, 0x09, 0x9C, 0x51, 0x24, 0x52,
|
||||
0x6C, 0x5E, 0x5E, 0xBD, 0x1E, 0x27, 0x06, 0xBB, 0xBC, 0x9E, 0x94, 0xE1, 0x35, 0xD4, 0x6D,
|
||||
0xB3, 0xCB, 0x3C, 0x68, 0xDD, 0x68, 0xB3, 0xFE, 0x6C, 0xCB, 0x8D, 0x82, 0x20, 0x76, 0x23,
|
||||
0x63, 0xB7, 0xE9, 0x68, 0x10, 0x01, 0x4E, 0xDC, 0xBA, 0x27, 0x5D, 0x01, 0xC1, 0x2D, 0x80,
|
||||
0x5E, 0x2B, 0xAF, 0x82, 0x6B, 0xD8, 0x84, 0xB6, 0x10, 0x52, 0x86, 0xA7, 0x89, 0x8E, 0xAE,
|
||||
0x9A, 0xE2, 0x89, 0xC6, 0xF7, 0xD5, 0x87, 0xFB};
|
||||
// q
|
||||
static constexpr CryptoPP::byte Prime2[] = {
|
||||
0xD7, 0xA1, 0x0F, 0x9A, 0x8B, 0xF2, 0xC9, 0x11, 0x95, 0x32, 0x9A, 0x8C, 0xF0, 0xD9, 0x40,
|
||||
0x47, 0xF5, 0x68, 0xA0, 0x0D, 0xBD, 0xC1, 0xFC, 0x43, 0x2F, 0x65, 0xF9, 0xC3, 0x61, 0x0F,
|
||||
0x25, 0x77, 0x54, 0xAD, 0xD7, 0x58, 0xAC, 0x84, 0x40, 0x60, 0x8D, 0x3F, 0xF3, 0x65, 0x89,
|
||||
0x75, 0xB5, 0xC6, 0x2C, 0x51, 0x1A, 0x2F, 0x1F, 0x22, 0xE4, 0x43, 0x11, 0x54, 0xBE, 0xC9,
|
||||
0xB4, 0xC7, 0xB5, 0x1B, 0x05, 0x0B, 0xBC, 0x56, 0x9A, 0xCD, 0x4A, 0xD9, 0x73, 0x68, 0x5E,
|
||||
0x5C, 0xFB, 0x92, 0xB7, 0x8B, 0x0D, 0xFF, 0xF5, 0x07, 0xCA, 0xB4, 0xC8, 0x9B, 0x96, 0x3C,
|
||||
0x07, 0x9E, 0x3E, 0x6B, 0x2A, 0x11, 0xF2, 0x8A, 0xB1, 0x8A, 0xD7, 0x2E, 0x1B, 0xA5, 0x53,
|
||||
0x24, 0x06, 0xED, 0x50, 0xB8, 0x90, 0x67, 0xB1, 0xE2, 0x41, 0xC6, 0x92, 0x01, 0xEE, 0x10,
|
||||
0xF0, 0x61, 0xBB, 0xFB, 0xB2, 0x7D, 0x4A, 0x73};
|
||||
static constexpr CryptoPP::byte PrivateExponent[] = {
|
||||
0x32, 0xD9, 0x03, 0x90, 0x8F, 0xBD, 0xB0, 0x8F, 0x57, 0x2B, 0x28, 0x5E, 0x0B, 0x8D, 0xB3,
|
||||
0xEA, 0x5C, 0xD1, 0x7E, 0xA8, 0x90, 0x88, 0x8C, 0xDD, 0x6A, 0x80, 0xBB, 0xB1, 0xDF, 0xC1,
|
||||
0xF7, 0x0D, 0xAA, 0x32, 0xF0, 0xB7, 0x7C, 0xCB, 0x88, 0x80, 0x0E, 0x8B, 0x64, 0xB0, 0xBE,
|
||||
0x4C, 0xD6, 0x0E, 0x9B, 0x8C, 0x1E, 0x2A, 0x64, 0xE1, 0xF3, 0x5C, 0xD7, 0x76, 0x01, 0x41,
|
||||
0x5E, 0x93, 0x5C, 0x94, 0xFE, 0xDD, 0x46, 0x62, 0xC3, 0x1B, 0x5A, 0xE2, 0xA0, 0xBC, 0x2D,
|
||||
0xEB, 0xC3, 0x98, 0x0A, 0xA7, 0xB7, 0x85, 0x69, 0x70, 0x68, 0x2B, 0x64, 0x4A, 0xB3, 0x1F,
|
||||
0xCC, 0x7D, 0xDC, 0x7C, 0x26, 0xF4, 0x77, 0xF6, 0x5C, 0xF2, 0xAE, 0x5A, 0x44, 0x2D, 0xD3,
|
||||
0xAB, 0x16, 0x62, 0x04, 0x19, 0xBA, 0xFB, 0x90, 0xFF, 0xE2, 0x30, 0x50, 0x89, 0x6E, 0xCB,
|
||||
0x56, 0xB2, 0xEB, 0xC0, 0x91, 0x16, 0x92, 0x5E, 0x30, 0x8E, 0xAE, 0xC7, 0x94, 0x5D, 0xFD,
|
||||
0x35, 0xE1, 0x20, 0xF8, 0xAD, 0x3E, 0xBC, 0x08, 0xBF, 0xC0, 0x36, 0x74, 0x9F, 0xD5, 0xBB,
|
||||
0x52, 0x08, 0xFD, 0x06, 0x66, 0xF3, 0x7A, 0xB3, 0x04, 0xF4, 0x75, 0x29, 0x5D, 0xE9, 0x5F,
|
||||
0xAA, 0x10, 0x30, 0xB2, 0x0F, 0x5A, 0x1A, 0xC1, 0x2A, 0xB3, 0xFE, 0xCB, 0x21, 0xAD, 0x80,
|
||||
0xEC, 0x8F, 0x20, 0x09, 0x1C, 0xDB, 0xC5, 0x58, 0x94, 0xC2, 0x9C, 0xC6, 0xCE, 0x82, 0x65,
|
||||
0x3E, 0x57, 0x90, 0xBC, 0xA9, 0x8B, 0x06, 0xB4, 0xF0, 0x72, 0xF6, 0x77, 0xDF, 0x98, 0x64,
|
||||
0xF1, 0xEC, 0xFE, 0x37, 0x2D, 0xBC, 0xAE, 0x8C, 0x08, 0x81, 0x1F, 0xC3, 0xC9, 0x89, 0x1A,
|
||||
0xC7, 0x42, 0x82, 0x4B, 0x2E, 0xDC, 0x8E, 0x8D, 0x73, 0xCE, 0xB1, 0xCC, 0x01, 0xD9, 0x08,
|
||||
0x70, 0x87, 0x3C, 0x44, 0x08, 0xEC, 0x49, 0x8F, 0x81, 0x5A, 0xE2, 0x40, 0xFF, 0x77, 0xFC,
|
||||
0x0D};
|
||||
};
|
|
@ -11,11 +11,14 @@
|
|||
#include "libraries/kernel/time.h"
|
||||
#include "libraries/system/msgdialog.h"
|
||||
#include "video_core/amdgpu/pm4_cmds.h"
|
||||
#include "video_core/renderer_vulkan/vk_pipeline_cache.h"
|
||||
|
||||
using namespace DebugStateType;
|
||||
|
||||
DebugStateImpl& DebugState = *Common::Singleton<DebugStateImpl>::Instance();
|
||||
|
||||
bool DebugStateType::showing_debug_menu_bar = false;
|
||||
|
||||
static ThreadID ThisThreadID() {
|
||||
#ifdef _WIN32
|
||||
return GetCurrentThreadId();
|
||||
|
@ -168,8 +171,12 @@ void DebugStateImpl::PushRegsDump(uintptr_t base_addr, uintptr_t header_addr,
|
|||
if ((*dump)->regs.stage_enable.IsStageEnabled(i)) {
|
||||
auto stage = (*dump)->regs.ProgramForStage(i);
|
||||
if (stage->address_lo != 0) {
|
||||
const auto& info = AmdGpu::Liverpool::SearchBinaryInfo(stage->Address<u32*>());
|
||||
auto code = stage->Code();
|
||||
(*dump)->stages[i] = PipelineShaderProgramDump{
|
||||
.name = Vulkan::PipelineCache::GetShaderName(Shader::StageFromIndex(i),
|
||||
info.shader_hash),
|
||||
.hash = info.shader_hash,
|
||||
.user_data = *stage,
|
||||
.code = std::vector<u32>{code.begin(), code.end()},
|
||||
};
|
||||
|
@ -191,7 +198,10 @@ void DebugStateImpl::PushRegsDumpCompute(uintptr_t base_addr, uintptr_t header_a
|
|||
auto& cs = (*dump)->regs.cs_program;
|
||||
cs = cs_state;
|
||||
|
||||
const auto& info = AmdGpu::Liverpool::SearchBinaryInfo(cs.Address<u32*>());
|
||||
(*dump)->cs_data = PipelineComputerProgramDump{
|
||||
.name = Vulkan::PipelineCache::GetShaderName(Shader::Stage::Compute, info.shader_hash),
|
||||
.hash = info.shader_hash,
|
||||
.cs_program = cs,
|
||||
.code = std::vector<u32>{cs.Code().begin(), cs.Code().end()},
|
||||
};
|
||||
|
|
|
@ -35,6 +35,8 @@ class ShaderList;
|
|||
|
||||
namespace DebugStateType {
|
||||
|
||||
extern bool showing_debug_menu_bar;
|
||||
|
||||
enum class QueueType {
|
||||
dcb = 0,
|
||||
ccb = 1,
|
||||
|
@ -50,11 +52,15 @@ struct QueueDump {
|
|||
};
|
||||
|
||||
struct PipelineShaderProgramDump {
|
||||
std::string name;
|
||||
u64 hash;
|
||||
Vulkan::Liverpool::ShaderProgram user_data{};
|
||||
std::vector<u32> code{};
|
||||
};
|
||||
|
||||
struct PipelineComputerProgramDump {
|
||||
std::string name;
|
||||
u64 hash;
|
||||
Vulkan::Liverpool::ComputeProgram cs_program{};
|
||||
std::vector<u32> code{};
|
||||
};
|
||||
|
@ -149,6 +155,13 @@ class DebugStateImpl {
|
|||
std::vector<ShaderDump> shader_dump_list{};
|
||||
|
||||
public:
|
||||
float Framerate = 1.0f / 60.0f;
|
||||
float FrameDeltaTime;
|
||||
|
||||
std::pair<u32, u32> game_resolution{};
|
||||
std::pair<u32, u32> output_resolution{};
|
||||
bool is_using_fsr{};
|
||||
|
||||
void ShowDebugMessage(std::string message) {
|
||||
if (message.empty()) {
|
||||
return;
|
||||
|
@ -156,6 +169,10 @@ public:
|
|||
debug_message_popup.push(std::move(message));
|
||||
}
|
||||
|
||||
bool& IsShowingDebugMenuBar() {
|
||||
return showing_debug_menu_bar;
|
||||
}
|
||||
|
||||
void AddCurrentThreadToGuestList();
|
||||
|
||||
void RemoveCurrentThreadFromGuestList();
|
||||
|
|
74
src/core/devices/console_device.cpp
Normal file
74
src/core/devices/console_device.cpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
// 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
|
33
src/core/devices/console_device.h
Normal file
33
src/core/devices/console_device.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
#include <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
|
74
src/core/devices/deci_tty6_device.cpp
Normal file
74
src/core/devices/deci_tty6_device.cpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
// 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
|
33
src/core/devices/deci_tty6_device.h
Normal file
33
src/core/devices/deci_tty6_device.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
#include <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
|
|
@ -17,10 +17,12 @@ s64 Logger::write(const void* buf, size_t nbytes) {
|
|||
}
|
||||
|
||||
size_t Logger::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
|
||||
size_t total_written = 0;
|
||||
for (int i = 0; i < iovcnt; i++) {
|
||||
log(static_cast<const char*>(iov[i].iov_base), iov[i].iov_len);
|
||||
total_written += iov[i].iov_len;
|
||||
}
|
||||
return iovcnt;
|
||||
return total_written;
|
||||
}
|
||||
|
||||
s64 Logger::pwrite(const void* buf, size_t nbytes, u64 offset) {
|
||||
|
|
|
@ -17,36 +17,47 @@ public:
|
|||
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;
|
||||
}
|
||||
|
|
78
src/core/devices/random_device.cpp
Normal file
78
src/core/devices/random_device.cpp
Normal file
|
@ -0,0 +1,78 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <cstdlib>
|
||||
#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
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue