Compare commits
796 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4dcca90ef4 | ||
|
|
ca2d228c9d | ||
|
|
c21dc36cda | ||
|
|
95b804ff05 | ||
|
|
448856695a | ||
|
|
fce33adcf1 | ||
|
|
e891ff9a0c | ||
|
|
8357908099 | ||
|
|
503ebe9b96 | ||
|
|
22e825a3bc | ||
|
|
c281173df6 | ||
|
|
1aa75b1081 | ||
|
|
59d0d34dce | ||
|
|
84e9f9f395 | ||
|
|
662feb8c1c | ||
|
|
aa6fe3f1aa | ||
|
|
49eff536d0 | ||
|
|
4a8fe67964 | ||
|
|
0361aa1915 | ||
|
|
fa1d625eed | ||
|
|
1e84d22275 | ||
|
|
002d9508a0 | ||
|
|
67e7186d79 | ||
|
|
fc205a1bc5 | ||
|
|
2cdda8c564 | ||
|
|
dba112e510 | ||
|
|
c083ea7d78 | ||
|
|
6fc485a607 | ||
|
|
64facb403e | ||
|
|
08c638f249 | ||
|
|
dfa2e336ba | ||
|
|
6af8ff24c9 | ||
|
|
85a4222a8c | ||
|
|
ca7618684c | ||
|
|
735c003a70 | ||
|
|
ef7f6eb67d | ||
|
|
a6a350ddc3 | ||
|
|
887d5288ef | ||
|
|
ac204754d4 | ||
|
|
6669b359a3 | ||
|
|
042256c6bb | ||
|
|
6ac3eb4d87 | ||
|
|
f9df2c6bcd | ||
|
|
cd0e28c9ec | ||
|
|
a33870996b | ||
|
|
42f1874965 | ||
|
|
1bd95a314f | ||
|
|
b1498d2c54 | ||
|
|
62437943a7 | ||
|
|
2eeea90713 | ||
|
|
3ce66776ec | ||
|
|
35bb9239ca | ||
|
|
98c8948b23 | ||
|
|
15cadc3948 | ||
|
|
a5bfc0d045 | ||
|
|
a42a6e1a2c | ||
|
|
4f8d152b18 | ||
|
|
231601763c | ||
|
|
bf1a1d989f | ||
|
|
13afd0e5b0 | ||
|
|
d8f5c45051 | ||
|
|
b727d99441 | ||
|
|
3c22bd92d8 | ||
|
|
9e46953580 | ||
|
|
46a1888e02 | ||
|
|
37536d7a49 | ||
|
|
40a2c57df5 | ||
|
|
b910a83a47 | ||
|
|
b01dd7d1c8 | ||
|
|
f7ec078592 | ||
|
|
758ad3f75d | ||
|
|
9b08698a0c | ||
|
|
69ad6279e4 | ||
|
|
6530144ccb | ||
|
|
ba6f390448 | ||
|
|
7f52efdf61 | ||
|
|
dacf83ac02 | ||
|
|
9e74e6988b | ||
|
|
eed789d0d1 | ||
|
|
b92dfcd7f2 | ||
|
|
1c4bf9cbfa | ||
|
|
5ccb07933a | ||
|
|
17a7fa751b | ||
|
|
9677db03da | ||
|
|
1bc0da3dea | ||
|
|
7d9a5e9e30 | ||
|
|
07a954e67f | ||
|
|
1eee891f6e | ||
|
|
e8125af8dd | ||
|
|
d3e433a380 | ||
|
|
7c16b3551b | ||
|
|
0914c70b7f | ||
|
|
2392b548be | ||
|
|
f92236976b | ||
|
|
04d1134191 | ||
|
|
d5ab0358b6 | ||
|
|
2a662fea36 | ||
|
|
e1a16a52fa | ||
|
|
0f343d32c4 | ||
|
|
42708c762e | ||
|
|
915d73f3b8 | ||
|
|
a0321b984f | ||
|
|
f646321dd0 | ||
|
|
c8f5f54a44 | ||
|
|
925521da5f | ||
|
|
d2d5554296 | ||
|
|
b95f064b51 | ||
|
|
1698143a1d | ||
|
|
96ac3d518a | ||
|
|
e38ed26b98 | ||
|
|
c7db1ef565 | ||
|
|
1326e326f5 | ||
|
|
5056d23d0d | ||
|
|
6c0c2dfabc | ||
|
|
1c385362f5 | ||
|
|
7ee6065178 | ||
|
|
969357af1a | ||
|
|
ebbfe73557 | ||
|
|
e1efab1f51 | ||
|
|
db2f547434 | ||
|
|
a17214baea | ||
|
|
aef159354c | ||
|
|
0aaa69e4d7 | ||
|
|
f3d4d4eaa8 | ||
|
|
1f57f679a4 | ||
|
|
01a05b48b7 | ||
|
|
795893a9a5 | ||
|
|
c6f78a4a6d | ||
|
|
e25297536f | ||
|
|
14877b8f35 | ||
|
|
b2a38cce4e | ||
|
|
667f026c95 | ||
|
|
2e16c23784 | ||
|
|
dc672ca4b3 | ||
|
|
add2c38b73 | ||
|
|
0c82b00dfd | ||
|
|
571451bdfe | ||
|
|
45ac1c62c6 | ||
|
|
00e3eab9c1 | ||
|
|
466ce715e4 | ||
|
|
3c648e3e2d | ||
|
|
78ab2e0474 | ||
|
|
e22ad52cdb | ||
|
|
1e9213632a | ||
|
|
1dda77d392 | ||
|
|
e2dd59e341 | ||
|
|
2b4cdb73b6 | ||
|
|
754aac331f | ||
|
|
3ef5f2017d | ||
|
|
1989e1b9ac | ||
|
|
3d0a2375ca | ||
|
|
a1bf353780 | ||
|
|
b9472eae44 | ||
|
|
d219a96cc8 | ||
|
|
ea956c823e | ||
|
|
5c90d22f3d | ||
|
|
179bafa7cb | ||
|
|
0728dfef84 | ||
|
|
d4da52bbd9 | ||
|
|
f5cf67140b | ||
|
|
19bce3685a | ||
|
|
27d57e0c4a | ||
|
|
7dc488a375 | ||
|
|
4a6a1aeab4 | ||
|
|
ef27b4b7b5 | ||
|
|
6b2719c0bb | ||
|
|
dc7ebc2d01 | ||
|
|
10d8afb302 | ||
|
|
1956a34ee5 | ||
|
|
c0c4da27d9 | ||
|
|
fe8e5d8ae4 | ||
|
|
ecf275887b | ||
|
|
fbbad95845 | ||
|
|
2342c0d50e | ||
|
|
bf0c929d4c | ||
|
|
d65fa7d65c | ||
|
|
d31156931d | ||
|
|
b2bc7682b4 | ||
|
|
c8261a1a57 | ||
|
|
fd4c5463e8 | ||
|
|
88cb05e6e7 | ||
|
|
e61c7e9310 | ||
|
|
47106ab152 | ||
|
|
1b6308727c | ||
|
|
a2c2c5768f | ||
|
|
a8508f2bc0 | ||
|
|
556f3a6e9a | ||
|
|
e545c2322c | ||
|
|
2ef8af93aa | ||
|
|
ad4e5c15fb | ||
|
|
f6f0762e81 | ||
|
|
7f6c686d55 | ||
|
|
ec206f7f95 | ||
|
|
eaf60ca5d8 | ||
|
|
93acfbd3a5 | ||
|
|
9295966d26 | ||
|
|
9fc42fffd9 | ||
|
|
493f0ad904 | ||
|
|
ba84f0988f | ||
|
|
9e42025e5b | ||
|
|
76b55c3624 | ||
|
|
23c4cc80e2 | ||
|
|
293d4d553a | ||
|
|
72d4c6fee0 | ||
|
|
7f380f4ffa | ||
|
|
13b02a1414 | ||
|
|
26006cbd2c | ||
|
|
af29e9d98e | ||
|
|
6a0220b2e1 | ||
|
|
1caf3f11c8 | ||
|
|
bfda5ff3f6 | ||
|
|
fd62bdf377 | ||
|
|
5257a83ebe | ||
|
|
6c0eb6026b | ||
|
|
7fadc9c180 | ||
|
|
619f64d7f4 | ||
|
|
0f70f68fb3 | ||
|
|
14c2a4a2ec | ||
|
|
6910ade146 | ||
|
|
91aa58e410 | ||
|
|
6d3a046caa | ||
|
|
54a00ee4cf | ||
|
|
cc0694559f | ||
|
|
bcd348f238 | ||
|
|
c31382ced5 | ||
|
|
73d2d3342d | ||
|
|
aae8c180cb | ||
|
|
ef9920e164 | ||
|
|
fe1238be7a | ||
|
|
2b58652f08 | ||
|
|
f552d553ba | ||
|
|
c3d0a0d627 | ||
|
|
63a59b9935 | ||
|
|
4501bd8ca9 | ||
|
|
829d8c0d6b | ||
|
|
20dc2e3622 | ||
|
|
22f58cca5e | ||
|
|
27e19f87c6 | ||
|
|
74feed372c | ||
|
|
3217400dd1 | ||
|
|
3563af2364 | ||
|
|
336a4f8e99 | ||
|
|
cbea8c74de | ||
|
|
2bc949628d | ||
|
|
d6ed31b9fa | ||
|
|
8b9a56033a | ||
|
|
0d85b6bfe1 | ||
|
|
be269e21a5 | ||
|
|
9f2c703137 | ||
|
|
8f8dda2d5b | ||
|
|
2506f7b3a1 | ||
|
|
f00a54f508 | ||
|
|
eefd97e80d | ||
|
|
b80c348b09 | ||
|
|
1e6f8aba04 | ||
|
|
d23d504d77 | ||
|
|
926ea5a16d | ||
|
|
c5aefe42aa | ||
|
|
37f1cf8cbd | ||
|
|
68043dd233 | ||
|
|
8e9a4944db | ||
|
|
0cb3bcfbb7 | ||
|
|
84ea9c2b42 | ||
|
|
21c3f48279 | ||
|
|
fcf3425b1b | ||
|
|
a952fbc5b3 | ||
|
|
e210835dd0 | ||
|
|
6536cc9741 | ||
|
|
7b07e521ca | ||
|
|
b5c13ee0eb | ||
|
|
7cacb08cdf | ||
|
|
90bda66028 | ||
|
|
90df4b8e2b | ||
|
|
aa3f9b9606 | ||
|
|
09d766d357 | ||
|
|
1b01c3036d | ||
|
|
ba53543da6 | ||
|
|
7a547b9342 | ||
|
|
3a0c1e79f8 | ||
|
|
77da74e17a | ||
|
|
84e895cdd6 | ||
|
|
3557fa25d0 | ||
|
|
be5fcffb89 | ||
|
|
2245c24e21 | ||
|
|
9751ccc5e0 | ||
|
|
bf9a822b87 | ||
|
|
8bb9eef97b | ||
|
|
c81c361e82 | ||
|
|
a0b4be4262 | ||
|
|
0eb36c90f4 | ||
|
|
08c508b1c4 | ||
|
|
7da52673d0 | ||
|
|
bf21aacc74 | ||
|
|
5733287822 | ||
|
|
c31ec00d67 | ||
|
|
2cd51fc9fd | ||
|
|
c7678c3044 | ||
|
|
83f8090273 | ||
|
|
5c61e0ba39 | ||
|
|
fb9c9ddcc9 | ||
|
|
9bb6ab77f4 | ||
|
|
881408445a | ||
|
|
36524465a6 | ||
|
|
4aa9c9632d | ||
|
|
157eb375a5 | ||
|
|
4eed744277 | ||
|
|
223a89a19f | ||
|
|
b5bbe7e752 | ||
|
|
729ca120e3 | ||
|
|
017474c3f8 | ||
|
|
2916c1bc25 | ||
|
|
69a6796de1 | ||
|
|
c18f9898d9 | ||
|
|
6b5b01b29f | ||
|
|
1948fc0858 | ||
|
|
91b0a3f799 | ||
|
|
472319e573 | ||
|
|
2de2bb980e | ||
|
|
16e7b7b83d | ||
|
|
51927bc9dc | ||
|
|
985d0f35e5 | ||
|
|
8a7cdfc3ff | ||
|
|
c593e45dbd | ||
|
|
b69321650e | ||
|
|
d027850f33 | ||
|
|
a7beabb68f | ||
|
|
2db7adc42a | ||
|
|
252415a163 | ||
|
|
c29584a090 | ||
|
|
f92cbc5501 | ||
|
|
8299f1ceef | ||
|
|
788d57d723 | ||
|
|
e651e54b85 | ||
|
|
9f0162e4b5 | ||
|
|
270177f38a | ||
|
|
b35449c85d | ||
|
|
b11aeced18 | ||
|
|
91f79225e7 | ||
|
|
8d6b4e836c | ||
|
|
6e87111f91 | ||
|
|
4bc4fdf5ff | ||
|
|
c457e47297 | ||
|
|
8178fe8960 | ||
|
|
283f3253bc | ||
|
|
bea6327d74 | ||
|
|
abae795986 | ||
|
|
acfb0b4852 | ||
|
|
2d1984c20c | ||
|
|
137a8aa55c | ||
|
|
e3fc3459c8 | ||
|
|
f55f6ff9bb | ||
|
|
d17dfa6104 | ||
|
|
de4b01f75d | ||
|
|
a1630ab53e | ||
|
|
e4a1ead897 | ||
|
|
450341b397 | ||
|
|
f68bb4f55e | ||
|
|
d95d4ac843 | ||
|
|
4d6a86b03f | ||
|
|
bb8eb15d39 | ||
|
|
d26e74f0a3 | ||
|
|
9a2cdf8520 | ||
|
|
531f25a037 | ||
|
|
96638f57c9 | ||
|
|
2a822f3378 | ||
|
|
05df4a8c94 | ||
|
|
2b1d66eda3 | ||
|
|
845a5dbca9 | ||
|
|
dfd998216c | ||
|
|
806f569143 | ||
|
|
3919b7b8a9 | ||
|
|
37b8504faa | ||
|
|
7c530e0666 | ||
|
|
3c34678627 | ||
|
|
2b02f29a2d | ||
|
|
037ea431ce | ||
|
|
f4603d23c5 | ||
|
|
603c861532 | ||
|
|
64496f2456 | ||
|
|
b97608ca64 | ||
|
|
dc5cfa8d28 | ||
|
|
74aa7de5e3 | ||
|
|
1e4b6bef6f | ||
|
|
c921e496eb | ||
|
|
ab89ced244 | ||
|
|
a104b985a8 | ||
|
|
f64adcfc37 | ||
|
|
1690f1adba | ||
|
|
deb97f6a8e | ||
|
|
e3cad7d49e | ||
|
|
d0e4f1c6f4 | ||
|
|
a31ed02ae4 | ||
|
|
d01eb12f36 | ||
|
|
bbd85a495a | ||
|
|
0fe11746fc | ||
|
|
ac3690f205 | ||
|
|
a167da4278 | ||
|
|
9c6b5cae68 | ||
|
|
ed76c71319 | ||
|
|
5a7eecc3ad | ||
|
|
89b326e396 | ||
|
|
d8e0d839bd | ||
|
|
c7055f3670 | ||
|
|
9a22b6dced | ||
|
|
3ce28342a2 | ||
|
|
79e0991d9b | ||
|
|
a665581684 | ||
|
|
bc55c05947 | ||
|
|
7113236b30 | ||
|
|
4ea073c286 | ||
|
|
4043ba5222 | ||
|
|
69b44392a7 | ||
|
|
5a077c95ce | ||
|
|
690732bc0d | ||
|
|
8b9f433d95 | ||
|
|
f5dfe68a94 | ||
|
|
41373d212e | ||
|
|
c610a8ac5a | ||
|
|
265fe40451 | ||
|
|
9ac33c2620 | ||
|
|
b2c976ad0e | ||
|
|
4e9331f45d | ||
|
|
999e3f89b9 | ||
|
|
f98cd210ab | ||
|
|
51c8aea979 | ||
|
|
94c41ab1d1 | ||
|
|
d110a371bb | ||
|
|
94915d4ea1 | ||
|
|
e972016456 | ||
|
|
278264b9e5 | ||
|
|
56672b8c98 | ||
|
|
55103da066 | ||
|
|
7e94e544f4 | ||
|
|
9bf4850f74 | ||
|
|
15163edaaa | ||
|
|
3cce5056ff | ||
|
|
4512a6bbfc | ||
|
|
09b1d762d7 | ||
|
|
f34e519da3 | ||
|
|
530a761e7a | ||
|
|
dd74fd014b | ||
|
|
48863afb65 | ||
|
|
657b3a366e | ||
|
|
fe5356d223 | ||
|
|
38e789c761 | ||
|
|
e041f33569 | ||
|
|
f09cd52980 | ||
|
|
63ba41a26d | ||
|
|
0caab54b5d | ||
|
|
82e1285c1e | ||
|
|
30faf6a964 | ||
|
|
d23869811d | ||
|
|
a43ac8c79e | ||
|
|
9e874898f5 | ||
|
|
b429095b61 | ||
|
|
c375d735e6 | ||
|
|
7af56dfa76 | ||
|
|
06d30fbcca | ||
|
|
635deb70d4 | ||
|
|
231d9c10f3 | ||
|
|
66a1c777c9 | ||
|
|
cdb00546f0 | ||
|
|
2d09467f6f | ||
|
|
02624c35ec | ||
|
|
64cd46579b | ||
|
|
81e9e229fa | ||
|
|
a1eee1749e | ||
|
|
a83e28b237 | ||
|
|
f10ea944e0 | ||
|
|
4cd5ad90f3 | ||
|
|
15a6840e7a | ||
|
|
55f95e7f26 | ||
|
|
15788ffcde | ||
|
|
6985eea519 | ||
|
|
e749f17257 | ||
|
|
09e17fbb0f | ||
|
|
2b2712fa95 | ||
|
|
da3049aa74 | ||
|
|
83be9fc96d | ||
|
|
6726e8b784 | ||
|
|
43fc793439 | ||
|
|
c76ffa5019 | ||
|
|
b1138e5ea1 | ||
|
|
3d46709b7f | ||
|
|
13021b534c | ||
|
|
e2a2a556b9 | ||
|
|
ae7fd01e38 | ||
|
|
908e085d02 | ||
|
|
82a64da077 | ||
|
|
80436c1330 | ||
|
|
319c4d2108 | ||
|
|
6888d776ff | ||
|
|
2effdeb924 | ||
|
|
dc96a59fa0 | ||
|
|
b392a5986e | ||
|
|
3142f1b597 | ||
|
|
9c548146ca | ||
|
|
5be00cba15 | ||
|
|
ee9b4a7f9a | ||
|
|
5aeff9aff5 | ||
|
|
322d6a0311 | ||
|
|
5b01f80a12 | ||
|
|
ceb851b590 | ||
|
|
85bb6a6f08 | ||
|
|
984563b773 | ||
|
|
8306703a7d | ||
|
|
09908207fb | ||
|
|
89fc75d769 | ||
|
|
56e450a3f7 | ||
|
|
6fe51f398f | ||
|
|
be5c149d37 | ||
|
|
cd0a7dfdbc | ||
|
|
361285add9 | ||
|
|
a4e840181c | ||
|
|
fab2607c6b | ||
|
|
4414640285 | ||
|
|
78f977c980 | ||
|
|
3dd6b55851 | ||
|
|
5135b74179 | ||
|
|
a1667a7b46 | ||
|
|
64c5631579 | ||
|
|
6e347d8d1b | ||
|
|
624a0f7f3f | ||
|
|
2fa9a96309 | ||
|
|
90f9c830ca | ||
|
|
351e3fb72e | ||
|
|
4a566b9828 | ||
|
|
c332c66eb2 | ||
|
|
0d6d8129c4 | ||
|
|
ae0e481677 | ||
|
|
1fe7df4517 | ||
|
|
0986caa8d8 | ||
|
|
028b2718ed | ||
|
|
b3371ed09e | ||
|
|
7bd447355f | ||
|
|
4cbb363d3f | ||
|
|
287d5921cf | ||
|
|
cb9dd01ffd | ||
|
|
f2c61bbe13 | ||
|
|
f846e3d6d0 | ||
|
|
8a76f816a4 | ||
|
|
5b989f189f | ||
|
|
3813af2f3c | ||
|
|
c83bf7cd1e | ||
|
|
a5bb1ac6e3 | ||
|
|
5619d24377 | ||
|
|
4af569ee47 | ||
|
|
b9e3f5eb36 | ||
|
|
4a3026b16b | ||
|
|
5770418fb3 | ||
|
|
91d35559e5 | ||
|
|
e976d0e924 | ||
|
|
1e76655f83 | ||
|
|
0f3ac9cfeb | ||
|
|
3dc585d011 | ||
|
|
218ee18417 | ||
|
|
a3916588b6 | ||
|
|
51c9e98677 | ||
|
|
aea978e037 | ||
|
|
27efcc15e9 | ||
|
|
16dcfacbfc | ||
|
|
1e16023d60 | ||
|
|
486c6a5316 | ||
|
|
af93909c9c | ||
|
|
38d3a48873 | ||
|
|
cf27b59493 | ||
|
|
7be65c6a68 | ||
|
|
6d55b14cc0 | ||
|
|
e41da22c8d | ||
|
|
ec983a2451 | ||
|
|
6ddffa010a | ||
|
|
54747d60bc | ||
|
|
2a63b3bdb9 | ||
|
|
de918ebeb0 | ||
|
|
485c21eac3 | ||
|
|
1eb4a95d2b | ||
|
|
253aa52351 | ||
|
|
f4a25f854c | ||
|
|
abb33d4aec | ||
|
|
d53cf05513 | ||
|
|
da0aa4da6b | ||
|
|
ae8d4b6c0c | ||
|
|
a7d6bd1ef1 | ||
|
|
c053269017 | ||
|
|
15a753b9a5 | ||
|
|
e438079b50 | ||
|
|
8b26b4228b | ||
|
|
8825b88a45 | ||
|
|
8a23c32cf0 | ||
|
|
67b8ecc73e | ||
|
|
b52297767e | ||
|
|
65b1b05e05 | ||
|
|
e09c1fbc1f | ||
|
|
844e4a297b | ||
|
|
a87c85eba2 | ||
|
|
3d2c44848b | ||
|
|
3d9fff82c0 | ||
|
|
eac075692b | ||
|
|
0471eb6dc7 | ||
|
|
3d51153611 | ||
|
|
ccda77c8c4 | ||
|
|
035ec7d9de | ||
|
|
285705b5f4 | ||
|
|
2b650543c6 | ||
|
|
e3ea583893 | ||
|
|
f27b21077d | ||
|
|
8db8631d81 | ||
|
|
15513f0801 | ||
|
|
f845df8651 | ||
|
|
2df9a2dcaf | ||
|
|
6d0d79109b | ||
|
|
8fc49a83b6 | ||
|
|
c0ee0aa1a8 | ||
|
|
af89723fa3 | ||
|
|
84a158c977 | ||
|
|
271a3264f3 | ||
|
|
900b2e5cae | ||
|
|
1d2ba3cc97 | ||
|
|
1a66cde175 | ||
|
|
e9faa1617c | ||
|
|
22c6b9fab2 | ||
|
|
30e365e4fc | ||
|
|
f564eaebed | ||
|
|
48e16c4c49 | ||
|
|
34f8881d3e | ||
|
|
c8db7d1399 | ||
|
|
7ffb672f61 | ||
|
|
425a254fa2 | ||
|
|
6edadef96d | ||
|
|
233ed96a5c | ||
|
|
d30cf51d7d | ||
|
|
0b5b93053d | ||
|
|
ecbfa416f0 | ||
|
|
9ad6327fbd | ||
|
|
6233b1db08 | ||
|
|
f2458106e6 | ||
|
|
19ce0d4f1a | ||
|
|
faf5ae6a50 | ||
|
|
116a940dbb | ||
|
|
7ea362e134 | ||
|
|
e54699565a | ||
|
|
f73e569ba8 | ||
|
|
c3e43c7e81 | ||
|
|
67b8265bd6 | ||
|
|
f632d00eb1 | ||
|
|
36651f215a | ||
|
|
707bf41c6f | ||
|
|
d2b50c5ebd | ||
|
|
4bbb22a477 | ||
|
|
d49ed4a421 | ||
|
|
74f515e8b6 | ||
|
|
e36814d6d5 | ||
|
|
ef2b6733d0 | ||
|
|
dc70a36b44 | ||
|
|
40cd4df584 | ||
|
|
2f79cc3ef5 | ||
|
|
2883cc1658 | ||
|
|
560cfbc21a | ||
|
|
be9f80ef56 | ||
|
|
526e533e90 | ||
|
|
3c1b6b5723 | ||
|
|
5c7253f8d3 | ||
|
|
930b7c18a6 | ||
|
|
b2c7636710 | ||
|
|
ff64c3951a | ||
|
|
fb6cf12a17 | ||
|
|
c34da106ed | ||
|
|
e6a0a30334 | ||
|
|
dee7844443 | ||
|
|
3a44faff11 | ||
|
|
75cc501d52 | ||
|
|
056f049b26 | ||
|
|
4589582eaf | ||
|
|
c3d3b173d3 | ||
|
|
e3ee017e91 | ||
|
|
fe65045dcb | ||
|
|
e0242a4654 | ||
|
|
c47fc3301d | ||
|
|
913d0bb269 | ||
|
|
aed6d8bef5 | ||
|
|
40ec1c22ce | ||
|
|
9403979c22 | ||
|
|
930e311526 | ||
|
|
9341ca7979 | ||
|
|
d66ab2b8aa | ||
|
|
ba3c55ab7b | ||
|
|
a3149536e2 | ||
|
|
e7e939104b | ||
|
|
50a518be69 | ||
|
|
e4c381b885 | ||
|
|
b05bfc6036 | ||
|
|
89ef3ef575 | ||
|
|
849581075a | ||
|
|
b2165c6b35 | ||
|
|
3f08e8d8d4 | ||
|
|
536fc7f0ea | ||
|
|
fc7d0a17b6 | ||
|
|
e58748fd80 | ||
|
|
323680e5ad | ||
|
|
4c2ed2706e | ||
|
|
6df6caaf5f | ||
|
|
ec0ce96c56 | ||
|
|
31daaa7911 | ||
|
|
59484442a0 | ||
|
|
ef4446cb11 | ||
|
|
f6b9b7910e | ||
|
|
410d44ce05 | ||
|
|
6d23b045a0 | ||
|
|
8652313af2 | ||
|
|
2899c93818 | ||
|
|
50c7539108 | ||
|
|
33a6b45a6c | ||
|
|
9046d4a548 | ||
|
|
b03242067d | ||
|
|
74fff717aa | ||
|
|
b7031b2b9d | ||
|
|
7298dcc016 | ||
|
|
ec8bfe94a7 | ||
|
|
e81e0036b4 | ||
|
|
63248f4edd | ||
|
|
6eaf7ab55f | ||
|
|
9ec84fc592 | ||
|
|
6a3fc5d2ff | ||
|
|
4ed183ee42 | ||
|
|
6e4d46908a | ||
|
|
49e0a30dbd | ||
|
|
9a60d8a430 | ||
|
|
dc2e83fa31 | ||
|
|
e3d7334be9 | ||
|
|
919ac2c4d3 | ||
|
|
894ad74b87 | ||
|
|
e35b9597ef | ||
|
|
36d9b409fc | ||
|
|
f936b86c7c | ||
|
|
180417c514 | ||
|
|
c8a48aacc0 | ||
|
|
0f23359a44 | ||
|
|
287ae2b9e8 | ||
|
|
dbeb523879 | ||
|
|
4f5d8e4342 | ||
|
|
dc9961f341 | ||
|
|
32c1bc6a67 | ||
|
|
bedc903c65 | ||
|
|
eedb048585 | ||
|
|
d7953b8ee5 | ||
|
|
46bb609981 | ||
|
|
2ab41ceff4 | ||
|
|
2d16507f9f | ||
|
|
73aaf365e7 | ||
|
|
cc81c0ce64 | ||
|
|
c52f37f259 | ||
|
|
24f4198cee | ||
|
|
bc10714dcf | ||
|
|
b0819e2ffb | ||
|
|
f9d7a6bec6 | ||
|
|
c8473f399e | ||
|
|
60993513af | ||
|
|
67a8bd1e70 | ||
|
|
7d16b2d2dd | ||
|
|
8ed0d92e32 | ||
|
|
3026aec9bd | ||
|
|
2ac834c722 | ||
|
|
a8295d2c53 | ||
|
|
3e0e4f146b | ||
|
|
14581e4a59 | ||
|
|
4681381a34 | ||
|
|
80eacdf89b | ||
|
|
bb31df62bb | ||
|
|
f2e34efcbb | ||
|
|
2c4c2b5eee | ||
|
|
48a1687f51 | ||
|
|
790a482bb4 | ||
|
|
c6bc13d0aa | ||
|
|
cd0f5dfc17 | ||
|
|
f3d1b370aa | ||
|
|
95137a04e1 | ||
|
|
7990220df7 | ||
|
|
e21b6ff79d | ||
|
|
47a6bb2d5b | ||
|
|
f11b87ebf1 | ||
|
|
75dec14f21 | ||
|
|
23878bf360 | ||
|
|
86a1eb7789 | ||
|
|
12dc918937 | ||
|
|
86c397dd6e | ||
|
|
ef060ed40c | ||
|
|
581d2e36e5 | ||
|
|
27ab99490e | ||
|
|
19a0abc19b | ||
|
|
96d677bef0 | ||
|
|
e9d2fad984 | ||
|
|
f1facaeaef | ||
|
|
e2ea0c3e11 | ||
|
|
028b1a34a9 | ||
|
|
f019817f8f | ||
|
|
3c95e49c42 |
@@ -1,39 +0,0 @@
|
||||
# Set-up Visual Studio Command Prompt environment for PowerShell
|
||||
pushd "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\"
|
||||
cmd /c "VsDevCmd.bat -arch=x64 & set" | foreach {
|
||||
if ($_ -match "=") {
|
||||
$v = $_.split("="); Set-Item -Force -Path "ENV:\$($v[0])" -Value "$($v[1])"
|
||||
}
|
||||
}
|
||||
popd
|
||||
|
||||
function Which ($search_path, $name) {
|
||||
($search_path).Split(";") | Get-ChildItem -Filter $name | Select -First 1 -Exp FullName
|
||||
}
|
||||
|
||||
function GetDeps ($search_path, $binary) {
|
||||
((dumpbin /dependents $binary).Where({ $_ -match "dependencies:"}, "SkipUntil") | Select-String "[^ ]*\.dll").Matches | foreach {
|
||||
Which $search_path $_.Value
|
||||
}
|
||||
}
|
||||
|
||||
function RecursivelyGetDeps ($search_path, $binary) {
|
||||
$final_deps = @()
|
||||
$deps_to_process = GetDeps $search_path $binary
|
||||
while ($deps_to_process.Count -gt 0) {
|
||||
$current, $deps_to_process = $deps_to_process
|
||||
if ($final_deps -contains $current) { continue }
|
||||
|
||||
# Is this a system dll file?
|
||||
# We use the same algorithm that cmake uses to determine this.
|
||||
if ($current -match "$([regex]::Escape($env:SystemRoot))\\sys") { continue }
|
||||
if ($current -match "$([regex]::Escape($env:WinDir))\\sys") { continue }
|
||||
if ($current -match "\\msvc[^\\]+dll") { continue }
|
||||
if ($current -match "\\api-ms-win-[^\\]+dll") { continue }
|
||||
|
||||
$final_deps += $current
|
||||
$new_deps = GetDeps $search_path $current
|
||||
$deps_to_process += ($new_deps | ?{-not ($final_deps -contains $_)})
|
||||
}
|
||||
return $final_deps
|
||||
}
|
||||
@@ -5,7 +5,7 @@ cd /yuzu
|
||||
ccache -s
|
||||
|
||||
mkdir build || true && cd build
|
||||
cmake .. -G Ninja -DDISPLAY_VERSION=$1 -DYUZU_USE_BUNDLED_UNICORN=ON -DYUZU_USE_QT_WEB_ENGINE=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON
|
||||
cmake .. -G Ninja -DDISPLAY_VERSION=$1 -DYUZU_USE_BUNDLED_UNICORN=ON -DYUZU_USE_QT_WEB_ENGINE=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_VULKAN=No
|
||||
|
||||
ninja
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ echo '' >> /bin/cmd
|
||||
chmod +x /bin/cmd
|
||||
|
||||
mkdir build || true && cd build
|
||||
cmake .. -G Ninja -DDISPLAY_VERSION=$1 -DCMAKE_TOOLCHAIN_FILE="$(pwd)/../CMakeModules/MinGWCross.cmake" -DUSE_CCACHE=ON -DYUZU_USE_BUNDLED_UNICORN=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DCMAKE_BUILD_TYPE=Release
|
||||
cmake .. -G Ninja -DDISPLAY_VERSION=$1 -DCMAKE_TOOLCHAIN_FILE="$(pwd)/../CMakeModules/MinGWCross.cmake" -DUSE_CCACHE=ON -DYUZU_USE_BUNDLED_UNICORN=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_VULKAN=No
|
||||
ninja
|
||||
|
||||
# Clean up the dirty hacks
|
||||
|
||||
@@ -39,6 +39,7 @@ mkdir "artifacts"
|
||||
# Build a tar.xz for the source of the release
|
||||
Copy-Item .\license.txt -Destination $MSVC_SOURCE
|
||||
Copy-Item .\README.md -Destination $MSVC_SOURCE
|
||||
Copy-Item .\CMakeLists.txt -Destination $MSVC_SOURCE
|
||||
Copy-Item .\src -Recurse -Destination $MSVC_SOURCE
|
||||
Copy-Item .\externals -Recurse -Destination $MSVC_SOURCE
|
||||
Copy-Item .\dist -Recurse -Destination $MSVC_SOURCE
|
||||
@@ -60,4 +61,4 @@ Get-ChildItem "$BUILD_DIR" -Recurse -Filter "QtWebEngineProcess*.exe" | Copy-Ite
|
||||
|
||||
Get-ChildItem . -Filter "*.zip" | Copy-Item -destination "artifacts"
|
||||
Get-ChildItem . -Filter "*.7z" | Copy-Item -destination "artifacts"
|
||||
Get-ChildItem . -Filter "*.tar.xz" | Copy-Item -destination "artifacts"
|
||||
Get-ChildItem . -Filter "*.tar.xz" | Copy-Item -destination "artifacts"
|
||||
|
||||
@@ -10,6 +10,7 @@ stages:
|
||||
jobs:
|
||||
- job: format
|
||||
displayName: 'clang'
|
||||
continueOnError: true
|
||||
pool:
|
||||
vmImage: ubuntu-latest
|
||||
steps:
|
||||
|
||||
@@ -29,7 +29,7 @@ option(ENABLE_VULKAN "Enables Vulkan backend" ON)
|
||||
|
||||
option(USE_DISCORD_PRESENCE "Enables Discord Rich Presence" OFF)
|
||||
|
||||
if(NOT EXISTS ${PROJECT_SOURCE_DIR}/.git/hooks/pre-commit)
|
||||
if(EXISTS ${PROJECT_SOURCE_DIR}/hooks/pre-commit AND NOT EXISTS ${PROJECT_SOURCE_DIR}/.git/hooks/pre-commit)
|
||||
message(STATUS "Copying pre-commit hook")
|
||||
file(COPY hooks/pre-commit
|
||||
DESTINATION ${PROJECT_SOURCE_DIR}/.git/hooks)
|
||||
@@ -49,7 +49,10 @@ function(check_submodules_present)
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
check_submodules_present()
|
||||
|
||||
if(EXISTS ${PROJECT_SOURCE_DIR}/.gitmodules)
|
||||
check_submodules_present()
|
||||
endif()
|
||||
|
||||
configure_file(${PROJECT_SOURCE_DIR}/dist/compatibility_list/compatibility_list.qrc
|
||||
${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.qrc
|
||||
@@ -148,15 +151,22 @@ if (ENABLE_SDL2)
|
||||
set(SDL2_INCLUDE_DIR "${SDL2_PREFIX}/include" CACHE PATH "Path to SDL2 headers")
|
||||
set(SDL2_LIBRARY "${SDL2_PREFIX}/lib/x64/SDL2.lib" CACHE PATH "Path to SDL2 library")
|
||||
set(SDL2_DLL_DIR "${SDL2_PREFIX}/lib/x64/" CACHE PATH "Path to SDL2.dll")
|
||||
else()
|
||||
find_package(SDL2 REQUIRED)
|
||||
endif()
|
||||
|
||||
if (SDL2_FOUND)
|
||||
# TODO(yuriks): Make FindSDL2.cmake export an IMPORTED library instead
|
||||
add_library(SDL2 INTERFACE)
|
||||
target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARY}")
|
||||
target_include_directories(SDL2 INTERFACE "${SDL2_INCLUDE_DIR}")
|
||||
else()
|
||||
find_package(SDL2 REQUIRED)
|
||||
|
||||
# Some installations don't set SDL2_LIBRARIES
|
||||
if("${SDL2_LIBRARIES}" STREQUAL "")
|
||||
message(WARNING "SDL2_LIBRARIES wasn't set, manually setting to SDL2::SDL2")
|
||||
set(SDL2_LIBRARIES "SDL2::SDL2")
|
||||
endif()
|
||||
|
||||
include_directories(${SDL2_INCLUDE_DIRS})
|
||||
add_library(SDL2 INTERFACE)
|
||||
target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARIES}")
|
||||
endif()
|
||||
else()
|
||||
set(SDL2_FOUND NO)
|
||||
@@ -347,6 +357,13 @@ function(create_target_directory_groups target_name)
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# Prevent boost from linking against libs when building
|
||||
add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY
|
||||
-DBOOST_SYSTEM_NO_LIB
|
||||
-DBOOST_DATE_TIME_NO_LIB
|
||||
-DBOOST_REGEX_NO_LIB
|
||||
)
|
||||
|
||||
enable_testing()
|
||||
add_subdirectory(externals)
|
||||
add_subdirectory(src)
|
||||
|
||||
@@ -5,6 +5,10 @@ function(get_timestamp _var)
|
||||
endfunction()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${SRC_DIR}/externals/cmake-modules")
|
||||
|
||||
# Find the package here with the known path so that the GetGit commands can find it as well
|
||||
find_package(Git QUIET PATHS "${GIT_EXECUTABLE}")
|
||||
|
||||
# generate git/build information
|
||||
include(GetGitRevisionDescription)
|
||||
get_git_head_revision(GIT_REF_SPEC GIT_REV)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
yuzu emulator
|
||||
=============
|
||||
[](https://travis-ci.org/yuzu-emu/yuzu)
|
||||
[](https://travis-ci.com/yuzu-emu/yuzu)
|
||||
[](https://dev.azure.com/yuzu-emu/yuzu/)
|
||||
|
||||
yuzu is an experimental open-source emulator for the Nintendo Switch from the creators of [Citra](https://citra-emu.org/).
|
||||
@@ -21,7 +21,7 @@ For development discussion, please join us on [Discord](https://discord.gg/XQV6d
|
||||
|
||||
Most of the development happens on GitHub. It's also where [our central repository](https://github.com/yuzu-emu/yuzu) is hosted.
|
||||
|
||||
If you want to contribute please take a look at the [Contributor's Guide](CONTRIBUTING.md) and [Developer Information](https://github.com/yuzu-emu/yuzu/wiki/Developer-Information). You should as well contact any of the developers on Discord in order to know about the current state of the emulator.
|
||||
If you want to contribute please take a look at the [Contributor's Guide](CONTRIBUTING.md) and [Developer Information](https://github.com/yuzu-emu/yuzu/wiki/Developer-Information). You should also contact any of the developers on Discord in order to know about the current state of the emulator.
|
||||
|
||||
### Building
|
||||
|
||||
|
||||
178
appveyor.yml
178
appveyor.yml
@@ -1,178 +0,0 @@
|
||||
# shallow clone
|
||||
clone_depth: 10
|
||||
|
||||
cache:
|
||||
- C:\ProgramData\chocolatey\bin -> appveyor.yml
|
||||
- C:\ProgramData\chocolatey\lib -> appveyor.yml
|
||||
|
||||
os: Visual Studio 2017
|
||||
|
||||
environment:
|
||||
# Tell msys2 to add mingw64 to the path
|
||||
MSYSTEM: MINGW64
|
||||
# Tell msys2 to inherit the current directory when starting the shell
|
||||
CHERE_INVOKING: 1
|
||||
matrix:
|
||||
- BUILD_TYPE: msvc
|
||||
- BUILD_TYPE: mingw
|
||||
|
||||
platform:
|
||||
- x64
|
||||
|
||||
configuration:
|
||||
- Release
|
||||
|
||||
install:
|
||||
- git submodule update --init --recursive
|
||||
- ps: |
|
||||
if ($env:BUILD_TYPE -eq 'mingw') {
|
||||
$dependencies = "mingw64/mingw-w64-x86_64-cmake",
|
||||
"mingw64/mingw-w64-x86_64-qt5",
|
||||
"mingw64/mingw-w64-x86_64-SDL2"
|
||||
# redirect err to null to prevent warnings from becoming errors
|
||||
# workaround to prevent pacman from failing due to cyclical dependencies
|
||||
C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw64/mingw-w64-x86_64-freetype mingw64/mingw-w64-x86_64-fontconfig" 2> $null
|
||||
C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S $dependencies" 2> $null
|
||||
}
|
||||
|
||||
before_build:
|
||||
- mkdir %BUILD_TYPE%_build
|
||||
- cd %BUILD_TYPE%_build
|
||||
- ps: |
|
||||
$COMPAT = if ($env:ENABLE_COMPATIBILITY_REPORTING -eq $null) {0} else {$env:ENABLE_COMPATIBILITY_REPORTING}
|
||||
if ($env:BUILD_TYPE -eq 'msvc') {
|
||||
# redirect stderr and change the exit code to prevent powershell from cancelling the build if cmake prints a warning
|
||||
cmd /C 'cmake -G "Visual Studio 15 2017 Win64" -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_BUNDLED_UNICORN=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DUSE_DISCORD_PRESENCE=ON .. 2>&1 && exit 0'
|
||||
} else {
|
||||
C:\msys64\usr\bin\bash.exe -lc "cmake -G 'MSYS Makefiles' -DYUZU_BUILD_UNICORN=1 -DCMAKE_BUILD_TYPE=Release -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DUSE_DISCORD_PRESENCE=ON .. 2>&1"
|
||||
}
|
||||
- cd ..
|
||||
|
||||
build_script:
|
||||
- ps: |
|
||||
if ($env:BUILD_TYPE -eq 'msvc') {
|
||||
# https://www.appveyor.com/docs/build-phase
|
||||
msbuild msvc_build/yuzu.sln /maxcpucount /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
|
||||
} else {
|
||||
C:\msys64\usr\bin\bash.exe -lc 'mingw32-make -C mingw_build/ 2>&1'
|
||||
}
|
||||
|
||||
after_build:
|
||||
- ps: |
|
||||
$GITDATE = $(git show -s --date=short --format='%ad') -replace "-",""
|
||||
$GITREV = $(git show -s --format='%h')
|
||||
|
||||
# Find out which kind of release we are producing by tag name
|
||||
if ($env:APPVEYOR_REPO_TAG_NAME) {
|
||||
$RELEASE_DIST, $RELEASE_VERSION = $env:APPVEYOR_REPO_TAG_NAME.split('-')
|
||||
} else {
|
||||
# There is no repo tag - make assumptions
|
||||
$RELEASE_DIST = "head"
|
||||
}
|
||||
|
||||
if ($env:BUILD_TYPE -eq 'msvc') {
|
||||
# Where are these spaces coming from? Regardless, let's remove them
|
||||
$MSVC_BUILD_ZIP = "yuzu-windows-msvc-$GITDATE-$GITREV.zip" -replace " ", ""
|
||||
$MSVC_BUILD_PDB = "yuzu-windows-msvc-$GITDATE-$GITREV-debugsymbols.zip" -replace " ", ""
|
||||
$MSVC_SEVENZIP = "yuzu-windows-msvc-$GITDATE-$GITREV.7z" -replace " ", ""
|
||||
|
||||
# set the build names as env vars so the artifacts can upload them
|
||||
$env:BUILD_ZIP = $MSVC_BUILD_ZIP
|
||||
$env:BUILD_SYMBOLS = $MSVC_BUILD_PDB
|
||||
$env:BUILD_UPDATE = $MSVC_SEVENZIP
|
||||
|
||||
$BUILD_DIR = ".\msvc_build\bin\Release"
|
||||
|
||||
# Make a debug symbol upload
|
||||
mkdir pdb
|
||||
Get-ChildItem "$BUILD_DIR\" -Recurse -Filter "*.pdb" | Copy-Item -destination .\pdb
|
||||
7z a -tzip $MSVC_BUILD_PDB .\pdb\*.pdb
|
||||
rm "$BUILD_DIR\*.pdb"
|
||||
|
||||
mkdir $RELEASE_DIST
|
||||
# get rid of extra exes by copying everything over, then deleting all the exes, then copying just the exes we want
|
||||
Copy-Item "$BUILD_DIR\*" -Destination $RELEASE_DIST -Recurse
|
||||
rm "$RELEASE_DIST\*.exe"
|
||||
Get-ChildItem "$BUILD_DIR" -Recurse -Filter "yuzu*.exe" | Copy-Item -destination $RELEASE_DIST
|
||||
Get-ChildItem "$BUILD_DIR" -Recurse -Filter "QtWebEngineProcess*.exe" | Copy-Item -destination $RELEASE_DIST
|
||||
Copy-Item .\license.txt -Destination $RELEASE_DIST
|
||||
Copy-Item .\README.md -Destination $RELEASE_DIST
|
||||
7z a -tzip $MSVC_BUILD_ZIP $RELEASE_DIST\*
|
||||
7z a $MSVC_SEVENZIP $RELEASE_DIST
|
||||
} else {
|
||||
$MINGW_BUILD_ZIP = "yuzu-windows-mingw-$GITDATE-$GITREV.zip" -replace " ", ""
|
||||
$MINGW_SEVENZIP = "yuzu-windows-mingw-$GITDATE-$GITREV.7z" -replace " ", ""
|
||||
# not going to bother adding separate debug symbols for mingw, so just upload a README for it
|
||||
# if someone wants to add them, change mingw to compile with -g and use objdump and strip to separate the symbols from the binary
|
||||
$MINGW_NO_DEBUG_SYMBOLS = "README_No_Debug_Symbols.txt"
|
||||
Set-Content -Path $MINGW_NO_DEBUG_SYMBOLS -Value "This is a workaround for Appveyor since msvc has debug symbols but mingw doesnt" -Force
|
||||
|
||||
# store the build information in env vars so we can use them as artifacts
|
||||
$env:BUILD_ZIP = $MINGW_BUILD_ZIP
|
||||
$env:BUILD_SYMBOLS = $MINGW_NO_DEBUG_SYMBOLS
|
||||
$env:BUILD_UPDATE = $MINGW_SEVENZIP
|
||||
|
||||
$CMAKE_SOURCE_DIR = "$env:APPVEYOR_BUILD_FOLDER"
|
||||
$CMAKE_BINARY_DIR = "$CMAKE_SOURCE_DIR/mingw_build/bin"
|
||||
$RELEASE_DIST = $RELEASE_DIST + "-mingw"
|
||||
|
||||
mkdir $RELEASE_DIST
|
||||
mkdir $RELEASE_DIST/platforms
|
||||
mkdir $RELEASE_DIST/styles
|
||||
mkdir $RELEASE_DIST/imageformats
|
||||
|
||||
# copy the compiled binaries and other release files to the release folder
|
||||
Get-ChildItem "$CMAKE_BINARY_DIR" -Filter "yuzu*.exe" | Copy-Item -destination $RELEASE_DIST
|
||||
Copy-Item -path "$CMAKE_SOURCE_DIR/license.txt" -destination $RELEASE_DIST
|
||||
Copy-Item -path "$CMAKE_SOURCE_DIR/README.md" -destination $RELEASE_DIST
|
||||
|
||||
# copy the qt windows plugin dll to platforms
|
||||
Copy-Item -path "C:/msys64/mingw64/share/qt5/plugins/platforms/qwindows.dll" -force -destination "$RELEASE_DIST/platforms"
|
||||
|
||||
# copy the qt windows vista style dll to platforms
|
||||
Copy-Item -path "C:/msys64/mingw64/share/qt5/plugins/styles/qwindowsvistastyle.dll" -force -destination "$RELEASE_DIST/styles"
|
||||
|
||||
# copy the qt jpeg imageformat dll to platforms
|
||||
Copy-Item -path "C:/msys64/mingw64/share/qt5/plugins/imageformats/qjpeg.dll" -force -destination "$RELEASE_DIST/imageformats"
|
||||
|
||||
# copy all the dll dependencies to the release folder
|
||||
. "./.appveyor/UtilityFunctions.ps1"
|
||||
$DLLSearchPath = "C:\msys64\mingw64\bin;$env:PATH"
|
||||
$MingwDLLs = RecursivelyGetDeps $DLLSearchPath "$RELEASE_DIST\yuzu.exe"
|
||||
$MingwDLLs += RecursivelyGetDeps $DLLSearchPath "$RELEASE_DIST\yuzu_cmd.exe"
|
||||
$MingwDLLs += RecursivelyGetDeps $DLLSearchPath "$RELEASE_DIST\imageformats\qjpeg.dll"
|
||||
Write-Host "Detected the following dependencies:"
|
||||
Write-Host $MingwDLLs
|
||||
foreach ($file in $MingwDLLs) {
|
||||
Copy-Item -path "$file" -force -destination "$RELEASE_DIST"
|
||||
}
|
||||
|
||||
7z a -tzip $MINGW_BUILD_ZIP $RELEASE_DIST\*
|
||||
7z a $MINGW_SEVENZIP $RELEASE_DIST
|
||||
}
|
||||
|
||||
test_script:
|
||||
- cd %BUILD_TYPE%_build
|
||||
- ps: |
|
||||
if ($env:BUILD_TYPE -eq 'msvc') {
|
||||
ctest -VV -C Release
|
||||
} else {
|
||||
C:\msys64\usr\bin\bash.exe -lc "ctest -VV -C Release"
|
||||
}
|
||||
- cd ..
|
||||
|
||||
artifacts:
|
||||
- path: $(BUILD_ZIP)
|
||||
name: build
|
||||
type: zip
|
||||
|
||||
deploy:
|
||||
provider: GitHub
|
||||
release: $(appveyor_repo_tag_name)
|
||||
auth_token:
|
||||
secure: QqePPnXbkzmXct5c8hZ2X5AbsthbI6cS1Sr+VBzcD8oUOIjfWJJKXVAQGUbQAbb0
|
||||
artifact: update,build
|
||||
draft: false
|
||||
prerelease: false
|
||||
on:
|
||||
appveyor_repo_tag: true
|
||||
2
dist/qt_themes/colorful/style.qrc
vendored
2
dist/qt_themes/colorful/style.qrc
vendored
@@ -10,6 +10,6 @@
|
||||
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="colorful">
|
||||
<file>style.qss</file>
|
||||
<file alias="style.qss">../default/style.qss</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
4
dist/qt_themes/colorful/style.qss
vendored
4
dist/qt_themes/colorful/style.qss
vendored
@@ -1,4 +0,0 @@
|
||||
/*
|
||||
This file is intentionally left blank.
|
||||
We do not want to apply any stylesheet for colorful, only icons.
|
||||
*/
|
||||
13
dist/qt_themes/default/default.qrc
vendored
13
dist/qt_themes/default/default.qrc
vendored
@@ -1,25 +1,18 @@
|
||||
<RCC>
|
||||
<qresource prefix="icons/default">
|
||||
<file alias="index.theme">icons/index.theme</file>
|
||||
|
||||
<file alias="16x16/checked.png">icons/16x16/checked.png</file>
|
||||
|
||||
<file alias="16x16/failed.png">icons/16x16/failed.png</file>
|
||||
|
||||
<file alias="16x16/lock.png">icons/16x16/lock.png</file>
|
||||
|
||||
<file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file>
|
||||
|
||||
<file alias="48x48/chip.png">icons/48x48/chip.png</file>
|
||||
|
||||
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
||||
|
||||
<file alias="48x48/plus.png">icons/48x48/plus.png</file>
|
||||
|
||||
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
||||
|
||||
<file alias="256x256/yuzu.png">icons/256x256/yuzu.png</file>
|
||||
|
||||
<file alias="256x256/plus_folder.png">icons/256x256/plus_folder.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="default">
|
||||
<file>style.qss</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
35
dist/qt_themes/default/style.qss
vendored
Normal file
35
dist/qt_themes/default/style.qss
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
QPushButton#TogglableStatusBarButton {
|
||||
color: #959595;
|
||||
border: 1px solid transparent;
|
||||
background-color: transparent;
|
||||
padding: 0px 3px 0px 3px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
QPushButton#TogglableStatusBarButton:checked {
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
QPushButton#TogglableStatusBarButton:hover {
|
||||
border: 1px solid #76797C;
|
||||
}
|
||||
|
||||
QPushButton#RendererStatusBarButton {
|
||||
color: #656565;
|
||||
border: 1px solid transparent;
|
||||
background-color: transparent;
|
||||
padding: 0px 3px 0px 3px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
QPushButton#RendererStatusBarButton:hover {
|
||||
border: 1px solid #76797C;
|
||||
}
|
||||
|
||||
QPushButton#RendererStatusBarButton:checked {
|
||||
color: #e85c00;
|
||||
}
|
||||
|
||||
QPushButton#RendererStatusBarButton:!checked{
|
||||
color: #0066ff;
|
||||
}
|
||||
283
dist/qt_themes/qdarkstyle/style.qss
vendored
283
dist/qt_themes/qdarkstyle/style.qss
vendored
@@ -2,7 +2,8 @@ QToolTip {
|
||||
border: 1px solid #76797C;
|
||||
background-color: #5A7566;
|
||||
color: white;
|
||||
padding: 0px; /*remove padding, for fix combobox tooltip.*/
|
||||
/*remove padding, for fix combobox tooltip.*/
|
||||
padding: 0;
|
||||
opacity: 200;
|
||||
}
|
||||
|
||||
@@ -13,7 +14,7 @@ QWidget {
|
||||
selection-color: #eff0f1;
|
||||
background-clip: border;
|
||||
border-image: none;
|
||||
border: 0px transparent black;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
@@ -27,10 +28,10 @@ QWidget:item:selected {
|
||||
}
|
||||
|
||||
QCheckBox {
|
||||
spacing: 5px;
|
||||
spacing: 6px;
|
||||
outline: none;
|
||||
color: #eff0f1;
|
||||
margin-bottom: 2px;
|
||||
margin: 0 2px 1px 0;
|
||||
}
|
||||
|
||||
QCheckBox:disabled {
|
||||
@@ -163,7 +164,7 @@ QMenuBar::item:selected {
|
||||
}
|
||||
|
||||
QMenuBar::item:pressed {
|
||||
border: 1px solid #76797C;
|
||||
border: 1px solid #18465d;
|
||||
background-color: #3daee9;
|
||||
color: #eff0f1;
|
||||
margin-bottom: -1px;
|
||||
@@ -171,9 +172,9 @@ QMenuBar::item:pressed {
|
||||
}
|
||||
|
||||
QMenu {
|
||||
border: 1px solid #76797C;
|
||||
border: 1px solid #434242;
|
||||
padding: 2px;
|
||||
color: #eff0f1;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
QMenu::icon {
|
||||
@@ -181,7 +182,7 @@ QMenu::icon {
|
||||
}
|
||||
|
||||
QMenu::item {
|
||||
padding: 5px 30px 5px 30px;
|
||||
padding: 5px 16px 5px 40px;
|
||||
border: 1px solid transparent;
|
||||
/* reserve space for selection border */
|
||||
}
|
||||
@@ -190,22 +191,30 @@ QMenu::item:selected {
|
||||
color: #eff0f1;
|
||||
}
|
||||
|
||||
QMenu::separator {
|
||||
height: 2px;
|
||||
background: lightblue;
|
||||
margin-left: 10px;
|
||||
margin-right: 5px;
|
||||
QMenu::item:disabled {
|
||||
color: #54575B;
|
||||
}
|
||||
|
||||
QMenu::item:disabled:hover,
|
||||
QMenu::item:disabled:selected {
|
||||
background-color: #393e43;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
QMenu::separator,
|
||||
QMenuBar::separator {
|
||||
height: 1px;
|
||||
background-color: #54575B;
|
||||
margin: 2px 4px 2px 40px;
|
||||
}
|
||||
|
||||
QMenu::indicator {
|
||||
margin: 0 -26px 0 8px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
|
||||
/* non-exclusive indicator = check box style indicator
|
||||
(see QActionGroup::setExclusive) */
|
||||
|
||||
/* non-exclusive indicator = check box style indicator (see QActionGroup::setExclusive) */
|
||||
QMenu::indicator:non-exclusive:unchecked {
|
||||
image: url(:/qss_icons/rc/checkbox_unchecked.png);
|
||||
}
|
||||
@@ -222,9 +231,7 @@ QMenu::indicator:non-exclusive:checked:selected {
|
||||
image: url(:/qss_icons/rc/checkbox_checked_disabled.png);
|
||||
}
|
||||
|
||||
|
||||
/* exclusive indicator = radio button style indicator (see QActionGroup::setExclusive) */
|
||||
|
||||
QMenu::indicator:exclusive:unchecked {
|
||||
image: url(:/qss_icons/rc/radio_unchecked.png);
|
||||
}
|
||||
@@ -242,39 +249,46 @@ QMenu::indicator:exclusive:checked:selected {
|
||||
}
|
||||
|
||||
QMenu::right-arrow {
|
||||
margin: 5px;
|
||||
margin-right: 10px;
|
||||
image: url(:/qss_icons/rc/right_arrow.png)
|
||||
}
|
||||
|
||||
QWidget:disabled {
|
||||
color: #454545;
|
||||
color: #4f515b;
|
||||
background-color: #31363b;
|
||||
}
|
||||
|
||||
QAbstractItemView {
|
||||
alternate-background-color: #31363b;
|
||||
alternate-background-color: #2c2f32;
|
||||
color: #eff0f1;
|
||||
border: 1px solid #3A3939;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
QWidget:focus,
|
||||
QMenuBar:focus {
|
||||
QAbstractItemView:disabled,
|
||||
QAbstractItemView:read-only {
|
||||
alternate-background-color: #232629;
|
||||
}
|
||||
|
||||
QWidget:focus {
|
||||
border: 1px solid #3daee9;
|
||||
}
|
||||
|
||||
QTabWidget:focus,
|
||||
QCheckBox:focus,
|
||||
QRadioButton:focus,
|
||||
QSlider:focus {
|
||||
QSlider:focus,
|
||||
QTreeView:focus,
|
||||
QMenu:focus,
|
||||
QMenuBar:focus,
|
||||
QTabBar:focus {
|
||||
border: none;
|
||||
}
|
||||
|
||||
QLineEdit {
|
||||
background-color: #232629;
|
||||
padding: 5px;
|
||||
border-style: solid;
|
||||
border: 1px solid #76797C;
|
||||
border: 1px solid #54575B;
|
||||
border-radius: 2px;
|
||||
color: #eff0f1;
|
||||
}
|
||||
@@ -284,9 +298,10 @@ QAbstractItemView QLineEdit {
|
||||
}
|
||||
|
||||
QGroupBox {
|
||||
border: 1px solid #76797C;
|
||||
border: 1px solid #54575B;
|
||||
border-radius: 2px;
|
||||
margin-top: 20px;
|
||||
margin-top: 12px;
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
QGroupBox::title {
|
||||
@@ -294,12 +309,12 @@ QGroupBox::title {
|
||||
subcontrol-position: top center;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
padding-top: 10px;
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
QAbstractScrollArea {
|
||||
border-radius: 2px;
|
||||
border: 1px solid #76797C;
|
||||
border: 1px solid #54575B;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
@@ -318,7 +333,7 @@ QScrollBar::handle:horizontal {
|
||||
}
|
||||
|
||||
QScrollBar::add-line:horizontal {
|
||||
margin: 0px 3px 0px 3px;
|
||||
margin: 0 3px;
|
||||
border-image: url(:/qss_icons/rc/right_arrow_disabled.png);
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
@@ -327,7 +342,7 @@ QScrollBar::add-line:horizontal {
|
||||
}
|
||||
|
||||
QScrollBar::sub-line:horizontal {
|
||||
margin: 0px 3px 0px 3px;
|
||||
margin: 0 3px;
|
||||
border-image: url(:/qss_icons/rc/left_arrow_disabled.png);
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
@@ -378,7 +393,7 @@ QScrollBar::handle:vertical {
|
||||
}
|
||||
|
||||
QScrollBar::sub-line:vertical {
|
||||
margin: 3px 0px 3px 0px;
|
||||
margin: 3px 0;
|
||||
border-image: url(:/qss_icons/rc/up_arrow_disabled.png);
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
@@ -387,7 +402,7 @@ QScrollBar::sub-line:vertical {
|
||||
}
|
||||
|
||||
QScrollBar::add-line:vertical {
|
||||
margin: 3px 0px 3px 0px;
|
||||
margin: 3px 0;
|
||||
border-image: url(:/qss_icons/rc/down_arrow_disabled.png);
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
@@ -426,15 +441,14 @@ QScrollBar::sub-page:vertical {
|
||||
QTextEdit {
|
||||
background-color: #232629;
|
||||
color: #eff0f1;
|
||||
border: 1px solid #76797C;
|
||||
border: 1px solid #54575B;
|
||||
}
|
||||
|
||||
QPlainTextEdit {
|
||||
background-color: #232629;
|
||||
;
|
||||
color: #eff0f1;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #76797C;
|
||||
border: 1px solid #54575B;
|
||||
}
|
||||
|
||||
QHeaderView::section {
|
||||
@@ -466,15 +480,6 @@ QMainWindow::separator:hover {
|
||||
spacing: 2px;
|
||||
}
|
||||
|
||||
QMenu::separator {
|
||||
height: 1px;
|
||||
background-color: #76797C;
|
||||
color: white;
|
||||
padding-left: 4px;
|
||||
margin-left: 10px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
QFrame {
|
||||
border-radius: 2px;
|
||||
border: 1px solid #76797C;
|
||||
@@ -517,25 +522,19 @@ QToolButton#qt_toolbar_ext_button {
|
||||
|
||||
QPushButton {
|
||||
color: #eff0f1;
|
||||
background-color: #31363b;
|
||||
border-width: 1px;
|
||||
border-color: #76797C;
|
||||
border-color: #54575B;
|
||||
border-style: solid;
|
||||
padding: 5px;
|
||||
padding: 6px 4px;
|
||||
border-radius: 2px;
|
||||
outline: none;
|
||||
min-width: 100px;
|
||||
background-color: #232629;
|
||||
}
|
||||
|
||||
QPushButton:disabled {
|
||||
background-color: #31363b;
|
||||
border-width: 1px;
|
||||
border-color: #454545;
|
||||
border-style: solid;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
border-radius: 2px;
|
||||
color: #454545;
|
||||
}
|
||||
|
||||
@@ -552,11 +551,11 @@ QPushButton:pressed {
|
||||
|
||||
QComboBox {
|
||||
selection-background-color: #3daee9;
|
||||
border-style: solid;
|
||||
border: 1px solid #76797C;
|
||||
border: 1px solid #54575B;
|
||||
border-radius: 2px;
|
||||
padding: 5px;
|
||||
padding: 4px 6px;
|
||||
min-width: 75px;
|
||||
background-color: #232629;
|
||||
}
|
||||
|
||||
QPushButton:checked {
|
||||
@@ -570,15 +569,12 @@ QAbstractSpinBox:hover,
|
||||
QLineEdit:hover,
|
||||
QTextEdit:hover,
|
||||
QPlainTextEdit:hover,
|
||||
QAbstractView:hover,
|
||||
QTreeView:hover {
|
||||
QAbstractView:hover {
|
||||
border: 1px solid #3daee9;
|
||||
color: #eff0f1;
|
||||
}
|
||||
|
||||
QComboBox:on {
|
||||
padding-top: 3px;
|
||||
padding-left: 4px;
|
||||
selection-background-color: #4a4a4a;
|
||||
}
|
||||
|
||||
@@ -592,6 +588,7 @@ QComboBox QAbstractItemView {
|
||||
QComboBox::drop-down {
|
||||
subcontrol-origin: padding;
|
||||
subcontrol-position: top right;
|
||||
left: -6px;
|
||||
width: 15px;
|
||||
border-left-width: 0px;
|
||||
border-left-color: darkgray;
|
||||
@@ -611,8 +608,8 @@ QComboBox::down-arrow:focus {
|
||||
}
|
||||
|
||||
QAbstractSpinBox {
|
||||
padding: 5px;
|
||||
border: 1px solid #76797C;
|
||||
padding: 4px 6px;
|
||||
border: 1px solid #54575B;
|
||||
background-color: #232629;
|
||||
color: #eff0f1;
|
||||
border-radius: 2px;
|
||||
@@ -623,12 +620,14 @@ QAbstractSpinBox:up-button {
|
||||
background-color: transparent;
|
||||
subcontrol-origin: border;
|
||||
subcontrol-position: center right;
|
||||
left: -6px;
|
||||
}
|
||||
|
||||
QAbstractSpinBox:down-button {
|
||||
background-color: transparent;
|
||||
subcontrol-origin: border;
|
||||
subcontrol-position: center left;
|
||||
right: -6px;
|
||||
}
|
||||
|
||||
QAbstractSpinBox::up-arrow,
|
||||
@@ -655,22 +654,27 @@ QAbstractSpinBox::down-arrow:hover {
|
||||
image: url(:/qss_icons/rc/down_arrow.png);
|
||||
}
|
||||
|
||||
QLabel {
|
||||
border: 0px solid black;
|
||||
QLabel,
|
||||
QTabWidget {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
QTabWidget {
|
||||
border: 0px transparent black;
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
QTabWidget::pane {
|
||||
border: 1px solid #76797C;
|
||||
padding: 5px;
|
||||
margin: 0px;
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
border-top-right-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
border-bottom-left-radius: 2px;
|
||||
}
|
||||
|
||||
QTabWidget::tab-bar {
|
||||
/* left: 5px; move to the right by 5px */
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
QTabBar {
|
||||
@@ -678,10 +682,6 @@ QTabBar {
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
QTabBar:focus {
|
||||
border: 0px transparent black;
|
||||
}
|
||||
|
||||
QTabBar::close-button {
|
||||
image: url(:/qss_icons/rc/close.png);
|
||||
background: transparent;
|
||||
@@ -697,36 +697,33 @@ QTabBar::close-button:pressed {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
|
||||
/* TOP TABS */
|
||||
|
||||
QTabBar::tab:top {
|
||||
color: #eff0f1;
|
||||
border: 1px solid #76797C;
|
||||
border-bottom: 1px transparent black;
|
||||
background-color: #31363b;
|
||||
padding: 5px;
|
||||
min-width: 50px;
|
||||
border: 1px solid #54575B;
|
||||
background-color: #2a2f33;
|
||||
padding: 4px 16px 5px;
|
||||
min-width: 36px;
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 2px;
|
||||
}
|
||||
|
||||
QTabBar::tab:top:selected {
|
||||
color: #eff0f1;
|
||||
background-color: #54575B;
|
||||
border: 1px solid #76797C;
|
||||
border-bottom: 2px solid #3daee9;
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 2px;
|
||||
border-color: #76797C;
|
||||
background-color: #31363b;
|
||||
border-bottom-color: #31363b;
|
||||
}
|
||||
|
||||
QTabBar::tab:top:!selected {
|
||||
margin-top: 1px;
|
||||
border-bottom-color: #76797C;
|
||||
}
|
||||
|
||||
QTabBar::tab:top:!selected:hover {
|
||||
background-color: #3daee9;
|
||||
}
|
||||
|
||||
|
||||
/* BOTTOM TABS */
|
||||
|
||||
QTabBar::tab:bottom {
|
||||
color: #eff0f1;
|
||||
border: 1px solid #76797C;
|
||||
@@ -751,9 +748,7 @@ QTabBar::tab:bottom:!selected:hover {
|
||||
background-color: #3daee9;
|
||||
}
|
||||
|
||||
|
||||
/* LEFT TABS */
|
||||
|
||||
QTabBar::tab:left {
|
||||
color: #eff0f1;
|
||||
border: 1px solid #76797C;
|
||||
@@ -778,9 +773,7 @@ QTabBar::tab:left:!selected:hover {
|
||||
background-color: #3daee9;
|
||||
}
|
||||
|
||||
|
||||
/* RIGHT TABS */
|
||||
|
||||
QTabBar::tab:right {
|
||||
color: #eff0f1;
|
||||
border: 1px solid #76797C;
|
||||
@@ -848,7 +841,7 @@ QDockWidget::float-button:pressed {
|
||||
|
||||
QTreeView,
|
||||
QListView {
|
||||
border: 1px solid #76797C;
|
||||
border: 1px solid #54575B;
|
||||
background-color: #232629;
|
||||
}
|
||||
|
||||
@@ -979,8 +972,8 @@ QSlider::handle:vertical {
|
||||
}
|
||||
|
||||
QToolButton {
|
||||
background-color: transparent;
|
||||
border: 1px transparent #76797C;
|
||||
background-color: #232629;
|
||||
border: 1px solid #54575B;
|
||||
border-radius: 2px;
|
||||
margin: 3px;
|
||||
padding: 5px;
|
||||
@@ -989,7 +982,6 @@ QToolButton {
|
||||
QToolButton[popupMode="1"] {
|
||||
/* only for MenuButtonPopup */
|
||||
padding-right: 20px;
|
||||
/* make way for the popup button */
|
||||
border: 1px #76797C;
|
||||
border-radius: 5px;
|
||||
}
|
||||
@@ -997,7 +989,6 @@ QToolButton[popupMode="1"] {
|
||||
QToolButton[popupMode="2"] {
|
||||
/* only for InstantPopup */
|
||||
padding-right: 10px;
|
||||
/* make way for the popup button */
|
||||
border: 1px #76797C;
|
||||
}
|
||||
|
||||
@@ -1016,19 +1007,14 @@ QToolButton::menu-button:pressed {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
|
||||
/* the subcontrol below is used only in the InstantPopup or DelayedPopup mode */
|
||||
|
||||
QToolButton::menu-indicator {
|
||||
image: url(:/qss_icons/rc/down_arrow.png);
|
||||
top: -7px;
|
||||
left: -2px;
|
||||
/* shift it a bit */
|
||||
}
|
||||
|
||||
|
||||
/* the subcontrols below are used only in the MenuButtonPopup mode */
|
||||
|
||||
QToolButton::menu-button {
|
||||
border: 1px transparent #76797C;
|
||||
border-top-right-radius: 6px;
|
||||
@@ -1053,14 +1039,22 @@ QPushButton::menu-indicator {
|
||||
}
|
||||
|
||||
QTableView {
|
||||
border: 1px solid #76797C;
|
||||
border: 1px solid #54575B;
|
||||
gridline-color: #31363b;
|
||||
background-color: #232629;
|
||||
}
|
||||
|
||||
QTreeView:disabled {
|
||||
background-color: #1f2225;
|
||||
}
|
||||
|
||||
QTableView,
|
||||
QHeaderView {
|
||||
border-radius: 0px;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
QListView:focus {
|
||||
border-color: #54575B;
|
||||
}
|
||||
|
||||
QTableView::item:pressed,
|
||||
@@ -1078,7 +1072,7 @@ QListView::item:selected:active {
|
||||
}
|
||||
|
||||
QHeaderView {
|
||||
background-color: #31363b;
|
||||
background-color: #403F3F;
|
||||
border: 1px transparent;
|
||||
border-radius: 0px;
|
||||
margin: 0px;
|
||||
@@ -1086,30 +1080,32 @@ QHeaderView {
|
||||
}
|
||||
|
||||
QHeaderView::section {
|
||||
background-color: #31363b;
|
||||
background-color: #232629;
|
||||
color: #eff0f1;
|
||||
padding: 5px;
|
||||
border: 1px solid #76797C;
|
||||
padding: 0 5px;
|
||||
border: 1px solid #434242;
|
||||
border-bottom: 0;
|
||||
border-radius: 0px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
QHeaderView::section::vertical::first,
|
||||
QHeaderView::section::vertical::only-one {
|
||||
border-top: 1px solid #76797C;
|
||||
border-top: 1px solid #31363b;
|
||||
}
|
||||
|
||||
QHeaderView::section::vertical {
|
||||
border-top: transparent;
|
||||
}
|
||||
|
||||
QHeaderView::section::horizontal,
|
||||
QHeaderView::section::horizontal::first,
|
||||
QHeaderView::section::horizontal::only-one {
|
||||
border-left: 1px solid #76797C;
|
||||
border-left: transparent;
|
||||
}
|
||||
|
||||
QHeaderView::section::horizontal {
|
||||
border-left: transparent;
|
||||
QHeaderView::section::horizontal::last {
|
||||
border-right: transparent;
|
||||
}
|
||||
|
||||
QHeaderView::section:checked {
|
||||
@@ -1117,9 +1113,7 @@ QHeaderView::section:checked {
|
||||
background-color: #334e5e;
|
||||
}
|
||||
|
||||
|
||||
/* style the sort indicator */
|
||||
|
||||
/* sort indicator */
|
||||
QHeaderView::down-arrow {
|
||||
image: url(:/qss_icons/rc/down_arrow.png);
|
||||
}
|
||||
@@ -1149,14 +1143,13 @@ QToolBox::tab {
|
||||
}
|
||||
|
||||
QToolBox::tab:selected {
|
||||
/* italicize selected tabs */
|
||||
font: italic;
|
||||
background-color: #31363b;
|
||||
border-color: #3daee9;
|
||||
}
|
||||
|
||||
QStatusBar::item {
|
||||
border: 0px transparent dark;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
QFrame[height="3"],
|
||||
@@ -1193,7 +1186,6 @@ QProgressBar::chunk {
|
||||
|
||||
QDateEdit {
|
||||
selection-background-color: #3daee9;
|
||||
border-style: solid;
|
||||
border: 1px solid #3375A3;
|
||||
border-radius: 2px;
|
||||
padding: 1px;
|
||||
@@ -1217,7 +1209,7 @@ QDateEdit::drop-down {
|
||||
subcontrol-origin: padding;
|
||||
subcontrol-position: top right;
|
||||
width: 15px;
|
||||
border-left-width: 0px;
|
||||
border-left-width: 0;
|
||||
border-left-color: darkgray;
|
||||
border-left-style: solid;
|
||||
border-top-right-radius: 3px;
|
||||
@@ -1233,3 +1225,52 @@ QDateEdit::down-arrow:hover,
|
||||
QDateEdit::down-arrow:focus {
|
||||
image: url(:/qss_icons/rc/down_arrow.png);
|
||||
}
|
||||
|
||||
QComboBox:disabled,
|
||||
QPushButton:disabled,
|
||||
QAbstractSpinBox:disabled,
|
||||
QDateEdit:disabled,
|
||||
QLineEdit:disabled,
|
||||
QTextEdit:disabled,
|
||||
QToolButton:disabled,
|
||||
QPlainTextEdit:disabled {
|
||||
background-color: #2b2e31;
|
||||
}
|
||||
|
||||
QPushButton#TogglableStatusBarButton {
|
||||
min-width: 0px;
|
||||
color: #656565;
|
||||
border: 1px solid transparent;
|
||||
background-color: transparent;
|
||||
padding: 0px 3px 0px 3px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
QPushButton#TogglableStatusBarButton:checked {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
QPushButton#TogglableStatusBarButton:hover {
|
||||
border: 1px solid #76797C;
|
||||
}
|
||||
|
||||
QPushButton#RendererStatusBarButton {
|
||||
min-width: 0px;
|
||||
color: #656565;
|
||||
border: 1px solid transparent;
|
||||
background-color: transparent;
|
||||
padding: 0px 3px 0px 3px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
QPushButton#RendererStatusBarButton:hover {
|
||||
border: 1px solid #76797C;
|
||||
}
|
||||
|
||||
QPushButton#RendererStatusBarButton:checked {
|
||||
color: #e85c00;
|
||||
}
|
||||
|
||||
QPushButton#RendererStatusBarButton:!checked{
|
||||
color: #00ccdd;
|
||||
}
|
||||
2
externals/Vulkan-Headers
vendored
2
externals/Vulkan-Headers
vendored
Submodule externals/Vulkan-Headers updated: fd568d51ed...d42d0747ee
2
externals/boost
vendored
2
externals/boost
vendored
Submodule externals/boost updated: 0b920df1c9...5e8300b76a
239
externals/cmake-modules/FindSDL2.cmake
vendored
239
externals/cmake-modules/FindSDL2.cmake
vendored
@@ -1,239 +0,0 @@
|
||||
|
||||
# This module defines
|
||||
# SDL2_LIBRARY, the name of the library to link against
|
||||
# SDL2_FOUND, if false, do not try to link to SDL2
|
||||
# SDL2_INCLUDE_DIR, where to find SDL.h
|
||||
# SDL2_DLL_DIR, where to find SDL2.dll if it exists
|
||||
#
|
||||
# This module responds to the the flag:
|
||||
# SDL2_BUILDING_LIBRARY
|
||||
# If this is defined, then no SDL2main will be linked in because
|
||||
# only applications need main().
|
||||
# Otherwise, it is assumed you are building an application and this
|
||||
# module will attempt to locate and set the the proper link flags
|
||||
# as part of the returned SDL2_LIBRARY variable.
|
||||
#
|
||||
# Don't forget to include SDLmain.h and SDLmain.m your project for the
|
||||
# OS X framework based version. (Other versions link to -lSDL2main which
|
||||
# this module will try to find on your behalf.) Also for OS X, this
|
||||
# module will automatically add the -framework Cocoa on your behalf.
|
||||
#
|
||||
#
|
||||
# Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your configuration
|
||||
# and no SDL2_LIBRARY, it means CMake did not find your SDL2 library
|
||||
# (SDL2.dll, libsdl2.so, SDL2.framework, etc).
|
||||
# Set SDL2_LIBRARY_TEMP to point to your SDL2 library, and configure again.
|
||||
# Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this value
|
||||
# as appropriate. These values are used to generate the final SDL2_LIBRARY
|
||||
# variable, but when these values are unset, SDL2_LIBRARY does not get created.
|
||||
#
|
||||
#
|
||||
# $SDL2DIR is an environment variable that would
|
||||
# correspond to the ./configure --prefix=$SDL2DIR
|
||||
# used in building SDL2.
|
||||
# l.e.galup 9-20-02
|
||||
#
|
||||
# Modified by Eric Wing.
|
||||
# Added code to assist with automated building by using environmental variables
|
||||
# and providing a more controlled/consistent search behavior.
|
||||
# Added new modifications to recognize OS X frameworks and
|
||||
# additional Unix paths (FreeBSD, etc).
|
||||
# Also corrected the header search path to follow "proper" SDL guidelines.
|
||||
# Added a search for SDL2main which is needed by some platforms.
|
||||
# Added a search for threads which is needed by some platforms.
|
||||
# Added needed compile switches for MinGW.
|
||||
#
|
||||
# On OSX, this will prefer the Framework version (if found) over others.
|
||||
# People will have to manually change the cache values of
|
||||
# SDL2_LIBRARY to override this selection or set the CMake environment
|
||||
# CMAKE_INCLUDE_PATH to modify the search paths.
|
||||
#
|
||||
# Note that the header path has changed from SDL2/SDL.h to just SDL.h
|
||||
# This needed to change because "proper" SDL convention
|
||||
# is #include "SDL.h", not <SDL2/SDL.h>. This is done for portability
|
||||
# reasons because not all systems place things in SDL2/ (see FreeBSD).
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2003-2009 Kitware, Inc.
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License").
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
# CMake - Cross Platform Makefile Generator
|
||||
# Copyright 2000-2016 Kitware, Inc.
|
||||
# Copyright 2000-2011 Insight Software Consortium
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# * Neither the names of Kitware, Inc., the Insight Software Consortium,
|
||||
# nor the names of their contributors may be used to endorse or promote
|
||||
# products derived from this software without specific prior written
|
||||
# permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
#
|
||||
# The above copyright and license notice applies to distributions of
|
||||
# CMake in source and binary form. Some source files contain additional
|
||||
# notices of original copyright by their contributors; see each source
|
||||
# for details. Third-party software packages supplied with CMake under
|
||||
# compatible licenses provide their own copyright notices documented in
|
||||
# corresponding subdirectories.
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
#
|
||||
# CMake was initially developed by Kitware with the following sponsorship:
|
||||
#
|
||||
# * National Library of Medicine at the National Institutes of Health
|
||||
# as part of the Insight Segmentation and Registration Toolkit (ITK).
|
||||
#
|
||||
# * US National Labs (Los Alamos, Livermore, Sandia) ASC Parallel
|
||||
# Visualization Initiative.
|
||||
#
|
||||
# * National Alliance for Medical Image Computing (NAMIC) is funded by the
|
||||
# National Institutes of Health through the NIH Roadmap for Medical Research,
|
||||
# Grant U54 EB005149.
|
||||
#
|
||||
# * Kitware, Inc.
|
||||
#
|
||||
|
||||
message("<FindSDL2.cmake>")
|
||||
|
||||
SET(SDL2_SEARCH_PATHS
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/usr/local
|
||||
/usr
|
||||
/sw # Fink
|
||||
/opt/local # DarwinPorts
|
||||
/opt/csw # Blastwave
|
||||
/opt
|
||||
${SDL2_PATH}
|
||||
)
|
||||
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(VC_LIB_PATH_SUFFIX lib/x64)
|
||||
else()
|
||||
set(VC_LIB_PATH_SUFFIX lib/x86)
|
||||
endif()
|
||||
|
||||
FIND_LIBRARY(SDL2_LIBRARY_TEMP
|
||||
NAMES SDL2
|
||||
HINTS
|
||||
$ENV{SDL2DIR}
|
||||
PATH_SUFFIXES lib64 lib ${VC_LIB_PATH_SUFFIX}
|
||||
PATHS ${SDL2_SEARCH_PATHS}
|
||||
)
|
||||
|
||||
IF(SDL2_LIBRARY_TEMP)
|
||||
if(MSVC)
|
||||
get_filename_component(SDL2_DLL_DIR_TEMP ${SDL2_LIBRARY_TEMP} DIRECTORY)
|
||||
if(EXISTS ${SDL2_DLL_DIR_TEMP}/SDL2.dll)
|
||||
set(SDL2_DLL_DIR ${SDL2_DLL_DIR_TEMP})
|
||||
unset(SDL2_DLL_DIR_TEMP)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
FIND_PATH(SDL2_INCLUDE_DIR SDL.h
|
||||
HINTS
|
||||
$ENV{SDL2DIR}
|
||||
PATH_SUFFIXES include/SDL2 include
|
||||
PATHS ${SDL2_SEARCH_PATHS}
|
||||
)
|
||||
|
||||
IF(NOT SDL2_BUILDING_LIBRARY)
|
||||
IF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
|
||||
# Non-OS X framework versions expect you to also dynamically link to
|
||||
# SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms
|
||||
# seem to provide SDL2main for compatibility even though they don't
|
||||
# necessarily need it.
|
||||
FIND_LIBRARY(SDL2MAIN_LIBRARY
|
||||
NAMES SDL2main
|
||||
HINTS
|
||||
$ENV{SDL2DIR}
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATHS ${SDL2_SEARCH_PATHS}
|
||||
)
|
||||
ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
|
||||
ENDIF(NOT SDL2_BUILDING_LIBRARY)
|
||||
|
||||
# SDL2 may require threads on your system.
|
||||
# The Apple build may not need an explicit flag because one of the
|
||||
# frameworks may already provide it.
|
||||
# But for non-OSX systems, I will use the CMake Threads package.
|
||||
IF(NOT APPLE)
|
||||
FIND_PACKAGE(Threads)
|
||||
ENDIF(NOT APPLE)
|
||||
|
||||
# MinGW needs an additional library, mwindows
|
||||
# It's total link flags should look like -lmingw32 -lSDL2main -lSDL2 -lmwindows
|
||||
# (Actually on second look, I think it only needs one of the m* libraries.)
|
||||
IF(MINGW)
|
||||
SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW")
|
||||
ENDIF(MINGW)
|
||||
|
||||
# For SDL2main
|
||||
IF(NOT SDL2_BUILDING_LIBRARY)
|
||||
IF(SDL2MAIN_LIBRARY)
|
||||
SET(SDL2_LIBRARY_TEMP ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY_TEMP})
|
||||
ENDIF(SDL2MAIN_LIBRARY)
|
||||
ENDIF(NOT SDL2_BUILDING_LIBRARY)
|
||||
|
||||
# For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa.
|
||||
# CMake doesn't display the -framework Cocoa string in the UI even
|
||||
# though it actually is there if I modify a pre-used variable.
|
||||
# I think it has something to do with the CACHE STRING.
|
||||
# So I use a temporary variable until the end so I can set the
|
||||
# "real" variable in one-shot.
|
||||
IF(APPLE)
|
||||
SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa")
|
||||
ENDIF(APPLE)
|
||||
|
||||
# For threads, as mentioned Apple doesn't need this.
|
||||
# In fact, there seems to be a problem if I used the Threads package
|
||||
# and try using this line, so I'm just skipping it entirely for OS X.
|
||||
IF(NOT APPLE)
|
||||
SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT})
|
||||
ENDIF(NOT APPLE)
|
||||
|
||||
# For MinGW library
|
||||
IF(MINGW)
|
||||
SET(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP})
|
||||
ENDIF(MINGW)
|
||||
|
||||
# Set the final string here so the GUI reflects the final state.
|
||||
SET(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL2 Library can be found")
|
||||
|
||||
# Unset the temp variable to INTERNAL so it is not seen in the CMake GUI
|
||||
UNSET(SDL2_LIBRARY_TEMP)
|
||||
ENDIF(SDL2_LIBRARY_TEMP)
|
||||
|
||||
message("</FindSDL2.cmake>")
|
||||
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR)
|
||||
2
externals/dynarmic
vendored
2
externals/dynarmic
vendored
Submodule externals/dynarmic updated: 087a74417a...f6ae9e1c33
2
externals/httplib/README.md
vendored
2
externals/httplib/README.md
vendored
@@ -1,4 +1,4 @@
|
||||
From https://github.com/yhirose/cpp-httplib/commit/d9479bc0b12e8a1e8bce2d34da4feeef488581f3
|
||||
From https://github.com/yhirose/cpp-httplib/tree/fce8e6fefdab4ad48bc5b25c98e5ebfda4f3cf53
|
||||
|
||||
MIT License
|
||||
|
||||
|
||||
6216
externals/httplib/httplib.h
vendored
6216
externals/httplib/httplib.h
vendored
File diff suppressed because it is too large
Load Diff
1
externals/microprofile/microprofile.h
vendored
1
externals/microprofile/microprofile.h
vendored
@@ -243,6 +243,7 @@ typedef uint32_t ThreadIdType;
|
||||
#define MICROPROFILE_DEFINE_GPU(var, name, color) MicroProfileToken g_mp_##var = MicroProfileGetToken("GPU", name, color, MicroProfileTokenTypeGpu)
|
||||
#define MICROPROFILE_TOKEN_PASTE0(a, b) a ## b
|
||||
#define MICROPROFILE_TOKEN_PASTE(a, b) MICROPROFILE_TOKEN_PASTE0(a,b)
|
||||
#define MICROPROFILE_TOKEN(var) g_mp_##var
|
||||
#define MICROPROFILE_SCOPE(var) MicroProfileScopeHandler MICROPROFILE_TOKEN_PASTE(foo, __LINE__)(g_mp_##var)
|
||||
#define MICROPROFILE_SCOPE_TOKEN(token) MicroProfileScopeHandler MICROPROFILE_TOKEN_PASTE(foo, __LINE__)(token)
|
||||
#define MICROPROFILE_SCOPEI(group, name, color) static MicroProfileToken MICROPROFILE_TOKEN_PASTE(g_mp,__LINE__) = MicroProfileGetToken(group, name, color, MicroProfileTokenTypeCpu); MicroProfileScopeHandler MICROPROFILE_TOKEN_PASTE(foo,__LINE__)( MICROPROFILE_TOKEN_PASTE(g_mp,__LINE__))
|
||||
|
||||
2
externals/sirit
vendored
2
externals/sirit
vendored
Submodule externals/sirit updated: f7c4b07a7e...a712959f1e
@@ -77,6 +77,15 @@ else()
|
||||
add_compile_options("-static")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR MINGW)
|
||||
# GNU ar: Create thin archive files.
|
||||
# Requires binutils-2.19 or later.
|
||||
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> qcTP <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
set(CMAKE_C_ARCHIVE_APPEND "<CMAKE_AR> qTP <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> qcTP <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
set(CMAKE_CXX_ARCHIVE_APPEND "<CMAKE_AR> qTP <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_subdirectory(common)
|
||||
|
||||
@@ -5,21 +5,141 @@
|
||||
#define _USE_MATH_DEFINES
|
||||
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
#include "audio_core/algorithm/interpolate.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
|
||||
namespace AudioCore {
|
||||
|
||||
/// The Lanczos kernel
|
||||
static double Lanczos(std::size_t a, double x) {
|
||||
if (x == 0.0)
|
||||
return 1.0;
|
||||
const double px = M_PI * x;
|
||||
return a * std::sin(px) * std::sin(px / a) / (px * px);
|
||||
}
|
||||
constexpr std::array<s16, 512> curve_lut0{
|
||||
6600, 19426, 6722, 3, 6479, 19424, 6845, 9, 6359, 19419, 6968, 15, 6239,
|
||||
19412, 7093, 22, 6121, 19403, 7219, 28, 6004, 19391, 7345, 34, 5888, 19377,
|
||||
7472, 41, 5773, 19361, 7600, 48, 5659, 19342, 7728, 55, 5546, 19321, 7857,
|
||||
62, 5434, 19298, 7987, 69, 5323, 19273, 8118, 77, 5213, 19245, 8249, 84,
|
||||
5104, 19215, 8381, 92, 4997, 19183, 8513, 101, 4890, 19148, 8646, 109, 4785,
|
||||
19112, 8780, 118, 4681, 19073, 8914, 127, 4579, 19031, 9048, 137, 4477, 18988,
|
||||
9183, 147, 4377, 18942, 9318, 157, 4277, 18895, 9454, 168, 4179, 18845, 9590,
|
||||
179, 4083, 18793, 9726, 190, 3987, 18738, 9863, 202, 3893, 18682, 10000, 215,
|
||||
3800, 18624, 10137, 228, 3709, 18563, 10274, 241, 3618, 18500, 10411, 255, 3529,
|
||||
18436, 10549, 270, 3441, 18369, 10687, 285, 3355, 18300, 10824, 300, 3269, 18230,
|
||||
10962, 317, 3186, 18157, 11100, 334, 3103, 18082, 11238, 351, 3022, 18006, 11375,
|
||||
369, 2942, 17927, 11513, 388, 2863, 17847, 11650, 408, 2785, 17765, 11788, 428,
|
||||
2709, 17681, 11925, 449, 2635, 17595, 12062, 471, 2561, 17507, 12198, 494, 2489,
|
||||
17418, 12334, 517, 2418, 17327, 12470, 541, 2348, 17234, 12606, 566, 2280, 17140,
|
||||
12741, 592, 2213, 17044, 12876, 619, 2147, 16946, 13010, 647, 2083, 16846, 13144,
|
||||
675, 2020, 16745, 13277, 704, 1958, 16643, 13409, 735, 1897, 16539, 13541, 766,
|
||||
1838, 16434, 13673, 798, 1780, 16327, 13803, 832, 1723, 16218, 13933, 866, 1667,
|
||||
16109, 14062, 901, 1613, 15998, 14191, 937, 1560, 15885, 14318, 975, 1508, 15772,
|
||||
14445, 1013, 1457, 15657, 14571, 1052, 1407, 15540, 14695, 1093, 1359, 15423, 14819,
|
||||
1134, 1312, 15304, 14942, 1177, 1266, 15185, 15064, 1221, 1221, 15064, 15185, 1266,
|
||||
1177, 14942, 15304, 1312, 1134, 14819, 15423, 1359, 1093, 14695, 15540, 1407, 1052,
|
||||
14571, 15657, 1457, 1013, 14445, 15772, 1508, 975, 14318, 15885, 1560, 937, 14191,
|
||||
15998, 1613, 901, 14062, 16109, 1667, 866, 13933, 16218, 1723, 832, 13803, 16327,
|
||||
1780, 798, 13673, 16434, 1838, 766, 13541, 16539, 1897, 735, 13409, 16643, 1958,
|
||||
704, 13277, 16745, 2020, 675, 13144, 16846, 2083, 647, 13010, 16946, 2147, 619,
|
||||
12876, 17044, 2213, 592, 12741, 17140, 2280, 566, 12606, 17234, 2348, 541, 12470,
|
||||
17327, 2418, 517, 12334, 17418, 2489, 494, 12198, 17507, 2561, 471, 12062, 17595,
|
||||
2635, 449, 11925, 17681, 2709, 428, 11788, 17765, 2785, 408, 11650, 17847, 2863,
|
||||
388, 11513, 17927, 2942, 369, 11375, 18006, 3022, 351, 11238, 18082, 3103, 334,
|
||||
11100, 18157, 3186, 317, 10962, 18230, 3269, 300, 10824, 18300, 3355, 285, 10687,
|
||||
18369, 3441, 270, 10549, 18436, 3529, 255, 10411, 18500, 3618, 241, 10274, 18563,
|
||||
3709, 228, 10137, 18624, 3800, 215, 10000, 18682, 3893, 202, 9863, 18738, 3987,
|
||||
190, 9726, 18793, 4083, 179, 9590, 18845, 4179, 168, 9454, 18895, 4277, 157,
|
||||
9318, 18942, 4377, 147, 9183, 18988, 4477, 137, 9048, 19031, 4579, 127, 8914,
|
||||
19073, 4681, 118, 8780, 19112, 4785, 109, 8646, 19148, 4890, 101, 8513, 19183,
|
||||
4997, 92, 8381, 19215, 5104, 84, 8249, 19245, 5213, 77, 8118, 19273, 5323,
|
||||
69, 7987, 19298, 5434, 62, 7857, 19321, 5546, 55, 7728, 19342, 5659, 48,
|
||||
7600, 19361, 5773, 41, 7472, 19377, 5888, 34, 7345, 19391, 6004, 28, 7219,
|
||||
19403, 6121, 22, 7093, 19412, 6239, 15, 6968, 19419, 6359, 9, 6845, 19424,
|
||||
6479, 3, 6722, 19426, 6600};
|
||||
|
||||
constexpr std::array<s16, 512> curve_lut1{
|
||||
-68, 32639, 69, -5, -200, 32630, 212, -15, -328, 32613, 359, -26, -450,
|
||||
32586, 512, -36, -568, 32551, 669, -47, -680, 32507, 832, -58, -788, 32454,
|
||||
1000, -69, -891, 32393, 1174, -80, -990, 32323, 1352, -92, -1084, 32244, 1536,
|
||||
-103, -1173, 32157, 1724, -115, -1258, 32061, 1919, -128, -1338, 31956, 2118, -140,
|
||||
-1414, 31844, 2322, -153, -1486, 31723, 2532, -167, -1554, 31593, 2747, -180, -1617,
|
||||
31456, 2967, -194, -1676, 31310, 3192, -209, -1732, 31157, 3422, -224, -1783, 30995,
|
||||
3657, -240, -1830, 30826, 3897, -256, -1874, 30649, 4143, -272, -1914, 30464, 4393,
|
||||
-289, -1951, 30272, 4648, -307, -1984, 30072, 4908, -325, -2014, 29866, 5172, -343,
|
||||
-2040, 29652, 5442, -362, -2063, 29431, 5716, -382, -2083, 29203, 5994, -403, -2100,
|
||||
28968, 6277, -424, -2114, 28727, 6565, -445, -2125, 28480, 6857, -468, -2133, 28226,
|
||||
7153, -490, -2139, 27966, 7453, -514, -2142, 27700, 7758, -538, -2142, 27428, 8066,
|
||||
-563, -2141, 27151, 8378, -588, -2136, 26867, 8694, -614, -2130, 26579, 9013, -641,
|
||||
-2121, 26285, 9336, -668, -2111, 25987, 9663, -696, -2098, 25683, 9993, -724, -2084,
|
||||
25375, 10326, -753, -2067, 25063, 10662, -783, -2049, 24746, 11000, -813, -2030, 24425,
|
||||
11342, -844, -2009, 24100, 11686, -875, -1986, 23771, 12033, -907, -1962, 23438, 12382,
|
||||
-939, -1937, 23103, 12733, -972, -1911, 22764, 13086, -1005, -1883, 22422, 13441, -1039,
|
||||
-1855, 22077, 13798, -1072, -1825, 21729, 14156, -1107, -1795, 21380, 14516, -1141, -1764,
|
||||
21027, 14877, -1176, -1732, 20673, 15239, -1211, -1700, 20317, 15602, -1246, -1667, 19959,
|
||||
15965, -1282, -1633, 19600, 16329, -1317, -1599, 19239, 16694, -1353, -1564, 18878, 17058,
|
||||
-1388, -1530, 18515, 17423, -1424, -1495, 18151, 17787, -1459, -1459, 17787, 18151, -1495,
|
||||
-1424, 17423, 18515, -1530, -1388, 17058, 18878, -1564, -1353, 16694, 19239, -1599, -1317,
|
||||
16329, 19600, -1633, -1282, 15965, 19959, -1667, -1246, 15602, 20317, -1700, -1211, 15239,
|
||||
20673, -1732, -1176, 14877, 21027, -1764, -1141, 14516, 21380, -1795, -1107, 14156, 21729,
|
||||
-1825, -1072, 13798, 22077, -1855, -1039, 13441, 22422, -1883, -1005, 13086, 22764, -1911,
|
||||
-972, 12733, 23103, -1937, -939, 12382, 23438, -1962, -907, 12033, 23771, -1986, -875,
|
||||
11686, 24100, -2009, -844, 11342, 24425, -2030, -813, 11000, 24746, -2049, -783, 10662,
|
||||
25063, -2067, -753, 10326, 25375, -2084, -724, 9993, 25683, -2098, -696, 9663, 25987,
|
||||
-2111, -668, 9336, 26285, -2121, -641, 9013, 26579, -2130, -614, 8694, 26867, -2136,
|
||||
-588, 8378, 27151, -2141, -563, 8066, 27428, -2142, -538, 7758, 27700, -2142, -514,
|
||||
7453, 27966, -2139, -490, 7153, 28226, -2133, -468, 6857, 28480, -2125, -445, 6565,
|
||||
28727, -2114, -424, 6277, 28968, -2100, -403, 5994, 29203, -2083, -382, 5716, 29431,
|
||||
-2063, -362, 5442, 29652, -2040, -343, 5172, 29866, -2014, -325, 4908, 30072, -1984,
|
||||
-307, 4648, 30272, -1951, -289, 4393, 30464, -1914, -272, 4143, 30649, -1874, -256,
|
||||
3897, 30826, -1830, -240, 3657, 30995, -1783, -224, 3422, 31157, -1732, -209, 3192,
|
||||
31310, -1676, -194, 2967, 31456, -1617, -180, 2747, 31593, -1554, -167, 2532, 31723,
|
||||
-1486, -153, 2322, 31844, -1414, -140, 2118, 31956, -1338, -128, 1919, 32061, -1258,
|
||||
-115, 1724, 32157, -1173, -103, 1536, 32244, -1084, -92, 1352, 32323, -990, -80,
|
||||
1174, 32393, -891, -69, 1000, 32454, -788, -58, 832, 32507, -680, -47, 669,
|
||||
32551, -568, -36, 512, 32586, -450, -26, 359, 32613, -328, -15, 212, 32630,
|
||||
-200, -5, 69, 32639, -68};
|
||||
|
||||
constexpr std::array<s16, 512> curve_lut2{
|
||||
3195, 26287, 3329, -32, 3064, 26281, 3467, -34, 2936, 26270, 3608, -38, 2811,
|
||||
26253, 3751, -42, 2688, 26230, 3897, -46, 2568, 26202, 4046, -50, 2451, 26169,
|
||||
4199, -54, 2338, 26130, 4354, -58, 2227, 26085, 4512, -63, 2120, 26035, 4673,
|
||||
-67, 2015, 25980, 4837, -72, 1912, 25919, 5004, -76, 1813, 25852, 5174, -81,
|
||||
1716, 25780, 5347, -87, 1622, 25704, 5522, -92, 1531, 25621, 5701, -98, 1442,
|
||||
25533, 5882, -103, 1357, 25440, 6066, -109, 1274, 25342, 6253, -115, 1193, 25239,
|
||||
6442, -121, 1115, 25131, 6635, -127, 1040, 25018, 6830, -133, 967, 24899, 7027,
|
||||
-140, 897, 24776, 7227, -146, 829, 24648, 7430, -153, 764, 24516, 7635, -159,
|
||||
701, 24379, 7842, -166, 641, 24237, 8052, -174, 583, 24091, 8264, -181, 526,
|
||||
23940, 8478, -187, 472, 23785, 8695, -194, 420, 23626, 8914, -202, 371, 23462,
|
||||
9135, -209, 324, 23295, 9358, -215, 279, 23123, 9583, -222, 236, 22948, 9809,
|
||||
-230, 194, 22769, 10038, -237, 154, 22586, 10269, -243, 117, 22399, 10501, -250,
|
||||
81, 22208, 10735, -258, 47, 22015, 10970, -265, 15, 21818, 11206, -271, -16,
|
||||
21618, 11444, -277, -44, 21415, 11684, -283, -71, 21208, 11924, -290, -97, 20999,
|
||||
12166, -296, -121, 20786, 12409, -302, -143, 20571, 12653, -306, -163, 20354, 12898,
|
||||
-311, -183, 20134, 13143, -316, -201, 19911, 13389, -321, -218, 19686, 13635, -325,
|
||||
-234, 19459, 13882, -328, -248, 19230, 14130, -332, -261, 18998, 14377, -335, -273,
|
||||
18765, 14625, -337, -284, 18531, 14873, -339, -294, 18295, 15121, -341, -302, 18057,
|
||||
15369, -341, -310, 17817, 15617, -341, -317, 17577, 15864, -340, -323, 17335, 16111,
|
||||
-340, -328, 17092, 16357, -338, -332, 16848, 16603, -336, -336, 16603, 16848, -332,
|
||||
-338, 16357, 17092, -328, -340, 16111, 17335, -323, -340, 15864, 17577, -317, -341,
|
||||
15617, 17817, -310, -341, 15369, 18057, -302, -341, 15121, 18295, -294, -339, 14873,
|
||||
18531, -284, -337, 14625, 18765, -273, -335, 14377, 18998, -261, -332, 14130, 19230,
|
||||
-248, -328, 13882, 19459, -234, -325, 13635, 19686, -218, -321, 13389, 19911, -201,
|
||||
-316, 13143, 20134, -183, -311, 12898, 20354, -163, -306, 12653, 20571, -143, -302,
|
||||
12409, 20786, -121, -296, 12166, 20999, -97, -290, 11924, 21208, -71, -283, 11684,
|
||||
21415, -44, -277, 11444, 21618, -16, -271, 11206, 21818, 15, -265, 10970, 22015,
|
||||
47, -258, 10735, 22208, 81, -250, 10501, 22399, 117, -243, 10269, 22586, 154,
|
||||
-237, 10038, 22769, 194, -230, 9809, 22948, 236, -222, 9583, 23123, 279, -215,
|
||||
9358, 23295, 324, -209, 9135, 23462, 371, -202, 8914, 23626, 420, -194, 8695,
|
||||
23785, 472, -187, 8478, 23940, 526, -181, 8264, 24091, 583, -174, 8052, 24237,
|
||||
641, -166, 7842, 24379, 701, -159, 7635, 24516, 764, -153, 7430, 24648, 829,
|
||||
-146, 7227, 24776, 897, -140, 7027, 24899, 967, -133, 6830, 25018, 1040, -127,
|
||||
6635, 25131, 1115, -121, 6442, 25239, 1193, -115, 6253, 25342, 1274, -109, 6066,
|
||||
25440, 1357, -103, 5882, 25533, 1442, -98, 5701, 25621, 1531, -92, 5522, 25704,
|
||||
1622, -87, 5347, 25780, 1716, -81, 5174, 25852, 1813, -76, 5004, 25919, 1912,
|
||||
-72, 4837, 25980, 2015, -67, 4673, 26035, 2120, -63, 4512, 26085, 2227, -58,
|
||||
4354, 26130, 2338, -54, 4199, 26169, 2451, -50, 4046, 26202, 2568, -46, 3897,
|
||||
26230, 2688, -42, 3751, 26253, 2811, -38, 3608, 26270, 2936, -34, 3467, 26281,
|
||||
3064, -32, 3329, 26287, 3195};
|
||||
|
||||
std::vector<s16> Interpolate(InterpolationState& state, std::vector<s16> input, double ratio) {
|
||||
if (input.size() < 2)
|
||||
@@ -27,43 +147,51 @@ std::vector<s16> Interpolate(InterpolationState& state, std::vector<s16> input,
|
||||
|
||||
if (ratio <= 0) {
|
||||
LOG_CRITICAL(Audio, "Nonsensical interpolation ratio {}", ratio);
|
||||
ratio = 1.0;
|
||||
return input;
|
||||
}
|
||||
|
||||
if (ratio != state.current_ratio) {
|
||||
const double cutoff_frequency = std::min(0.5 / ratio, 0.5 * ratio);
|
||||
state.nyquist = CascadingFilter::LowPass(std::clamp(cutoff_frequency, 0.0, 0.4), 3);
|
||||
state.current_ratio = ratio;
|
||||
}
|
||||
state.nyquist.Process(input);
|
||||
const s32 step{static_cast<s32>(ratio * 0x8000)};
|
||||
const std::array<s16, 512>& lut = [step] {
|
||||
if (step > 0xaaaa) {
|
||||
return curve_lut0;
|
||||
}
|
||||
if (step <= 0x8000) {
|
||||
return curve_lut1;
|
||||
}
|
||||
return curve_lut2;
|
||||
}();
|
||||
|
||||
constexpr std::size_t taps = InterpolationState::lanczos_taps;
|
||||
const std::size_t num_frames = input.size() / 2;
|
||||
const std::size_t num_frames{input.size() / 2};
|
||||
|
||||
std::vector<s16> output;
|
||||
output.reserve(static_cast<std::size_t>(input.size() / ratio + 4));
|
||||
output.reserve(static_cast<std::size_t>(input.size() / ratio + InterpolationState::taps));
|
||||
|
||||
double& pos = state.position;
|
||||
auto& h = state.history;
|
||||
for (std::size_t i = 0; i < num_frames; ++i) {
|
||||
std::rotate(h.begin(), h.end() - 1, h.end());
|
||||
h[0][0] = input[i * 2 + 0];
|
||||
h[0][1] = input[i * 2 + 1];
|
||||
for (std::size_t frame{}; frame < num_frames; ++frame) {
|
||||
const std::size_t lut_index{(state.fraction >> 8) * InterpolationState::taps};
|
||||
|
||||
while (pos <= 1.0) {
|
||||
double l = 0.0;
|
||||
double r = 0.0;
|
||||
for (std::size_t j = 0; j < h.size(); j++) {
|
||||
const double lanczos_calc = Lanczos(taps, pos + j - taps + 1);
|
||||
l += lanczos_calc * h[j][0];
|
||||
r += lanczos_calc * h[j][1];
|
||||
}
|
||||
output.emplace_back(static_cast<s16>(std::clamp(l, -32768.0, 32767.0)));
|
||||
output.emplace_back(static_cast<s16>(std::clamp(r, -32768.0, 32767.0)));
|
||||
std::rotate(state.history.begin(), state.history.end() - 1, state.history.end());
|
||||
state.history[0][0] = input[frame * 2 + 0];
|
||||
state.history[0][1] = input[frame * 2 + 1];
|
||||
|
||||
pos += ratio;
|
||||
while (state.position <= 1.0) {
|
||||
const s32 left{state.history[0][0] * lut[lut_index + 0] +
|
||||
state.history[1][0] * lut[lut_index + 1] +
|
||||
state.history[2][0] * lut[lut_index + 2] +
|
||||
state.history[3][0] * lut[lut_index + 3]};
|
||||
const s32 right{state.history[0][1] * lut[lut_index + 0] +
|
||||
state.history[1][1] * lut[lut_index + 1] +
|
||||
state.history[2][1] * lut[lut_index + 2] +
|
||||
state.history[3][1] * lut[lut_index + 3]};
|
||||
const s32 new_offset{state.fraction + step};
|
||||
|
||||
state.fraction = new_offset & 0x7fff;
|
||||
|
||||
output.emplace_back(static_cast<s16>(std::clamp(left >> 15, SHRT_MIN, SHRT_MAX)));
|
||||
output.emplace_back(static_cast<s16>(std::clamp(right >> 15, SHRT_MIN, SHRT_MAX)));
|
||||
|
||||
state.position += ratio;
|
||||
}
|
||||
pos -= 1.0;
|
||||
state.position -= 1.0;
|
||||
}
|
||||
|
||||
return output;
|
||||
|
||||
@@ -6,19 +6,17 @@
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include "audio_core/algorithm/filter.h"
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace AudioCore {
|
||||
|
||||
struct InterpolationState {
|
||||
static constexpr std::size_t lanczos_taps = 4;
|
||||
static constexpr std::size_t history_size = lanczos_taps * 2 - 1;
|
||||
|
||||
double current_ratio = 0.0;
|
||||
CascadingFilter nyquist;
|
||||
std::array<std::array<s16, 2>, history_size> history = {};
|
||||
double position = 0;
|
||||
static constexpr std::size_t taps{4};
|
||||
static constexpr std::size_t history_size{taps * 2 - 1};
|
||||
std::array<std::array<s16, 2>, history_size> history{};
|
||||
double position{};
|
||||
s32 fraction{};
|
||||
};
|
||||
|
||||
/// Interpolates input signal to produce output signal.
|
||||
|
||||
@@ -36,9 +36,9 @@ public:
|
||||
}
|
||||
|
||||
void SetWaveIndex(std::size_t index);
|
||||
std::vector<s16> DequeueSamples(std::size_t sample_count);
|
||||
std::vector<s16> DequeueSamples(std::size_t sample_count, Memory::Memory& memory);
|
||||
void UpdateState();
|
||||
void RefreshBuffer();
|
||||
void RefreshBuffer(Memory::Memory& memory);
|
||||
|
||||
private:
|
||||
bool is_in_use{};
|
||||
@@ -66,17 +66,18 @@ public:
|
||||
return info;
|
||||
}
|
||||
|
||||
void UpdateState();
|
||||
void UpdateState(Memory::Memory& memory);
|
||||
|
||||
private:
|
||||
EffectOutStatus out_status{};
|
||||
EffectInStatus info{};
|
||||
};
|
||||
AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing, AudioRendererParameter params,
|
||||
Kernel::SharedPtr<Kernel::WritableEvent> buffer_event,
|
||||
AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing, Memory::Memory& memory_,
|
||||
AudioRendererParameter params,
|
||||
std::shared_ptr<Kernel::WritableEvent> buffer_event,
|
||||
std::size_t instance_number)
|
||||
: worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count),
|
||||
effects(params.effect_count) {
|
||||
effects(params.effect_count), memory{memory_} {
|
||||
|
||||
audio_out = std::make_unique<AudioCore::AudioOut>();
|
||||
stream = audio_out->OpenStream(core_timing, STREAM_SAMPLE_RATE, STREAM_NUM_CHANNELS,
|
||||
@@ -162,7 +163,7 @@ std::vector<u8> AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_
|
||||
}
|
||||
|
||||
for (auto& effect : effects) {
|
||||
effect.UpdateState();
|
||||
effect.UpdateState(memory);
|
||||
}
|
||||
|
||||
// Release previous buffers and queue next ones for playback
|
||||
@@ -206,13 +207,14 @@ void AudioRenderer::VoiceState::SetWaveIndex(std::size_t index) {
|
||||
is_refresh_pending = true;
|
||||
}
|
||||
|
||||
std::vector<s16> AudioRenderer::VoiceState::DequeueSamples(std::size_t sample_count) {
|
||||
std::vector<s16> AudioRenderer::VoiceState::DequeueSamples(std::size_t sample_count,
|
||||
Memory::Memory& memory) {
|
||||
if (!IsPlaying()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (is_refresh_pending) {
|
||||
RefreshBuffer();
|
||||
RefreshBuffer(memory);
|
||||
}
|
||||
|
||||
const std::size_t max_size{samples.size() - offset};
|
||||
@@ -256,10 +258,11 @@ void AudioRenderer::VoiceState::UpdateState() {
|
||||
is_in_use = info.is_in_use;
|
||||
}
|
||||
|
||||
void AudioRenderer::VoiceState::RefreshBuffer() {
|
||||
std::vector<s16> new_samples(info.wave_buffer[wave_index].buffer_sz / sizeof(s16));
|
||||
Memory::ReadBlock(info.wave_buffer[wave_index].buffer_addr, new_samples.data(),
|
||||
info.wave_buffer[wave_index].buffer_sz);
|
||||
void AudioRenderer::VoiceState::RefreshBuffer(Memory::Memory& memory) {
|
||||
const auto wave_buffer_address = info.wave_buffer[wave_index].buffer_addr;
|
||||
const auto wave_buffer_size = info.wave_buffer[wave_index].buffer_sz;
|
||||
std::vector<s16> new_samples(wave_buffer_size / sizeof(s16));
|
||||
memory.ReadBlock(wave_buffer_address, new_samples.data(), wave_buffer_size);
|
||||
|
||||
switch (static_cast<Codec::PcmFormat>(info.sample_format)) {
|
||||
case Codec::PcmFormat::Int16: {
|
||||
@@ -269,7 +272,7 @@ void AudioRenderer::VoiceState::RefreshBuffer() {
|
||||
case Codec::PcmFormat::Adpcm: {
|
||||
// Decode ADPCM to PCM16
|
||||
Codec::ADPCM_Coeff coeffs;
|
||||
Memory::ReadBlock(info.additional_params_addr, coeffs.data(), sizeof(Codec::ADPCM_Coeff));
|
||||
memory.ReadBlock(info.additional_params_addr, coeffs.data(), sizeof(Codec::ADPCM_Coeff));
|
||||
new_samples = Codec::DecodeADPCM(reinterpret_cast<u8*>(new_samples.data()),
|
||||
new_samples.size() * sizeof(s16), coeffs, adpcm_state);
|
||||
break;
|
||||
@@ -307,18 +310,18 @@ void AudioRenderer::VoiceState::RefreshBuffer() {
|
||||
is_refresh_pending = false;
|
||||
}
|
||||
|
||||
void AudioRenderer::EffectState::UpdateState() {
|
||||
void AudioRenderer::EffectState::UpdateState(Memory::Memory& memory) {
|
||||
if (info.is_new) {
|
||||
out_status.state = EffectStatus::New;
|
||||
} else {
|
||||
if (info.type == Effect::Aux) {
|
||||
ASSERT_MSG(Memory::Read32(info.aux_info.return_buffer_info) == 0,
|
||||
ASSERT_MSG(memory.Read32(info.aux_info.return_buffer_info) == 0,
|
||||
"Aux buffers tried to update");
|
||||
ASSERT_MSG(Memory::Read32(info.aux_info.send_buffer_info) == 0,
|
||||
ASSERT_MSG(memory.Read32(info.aux_info.send_buffer_info) == 0,
|
||||
"Aux buffers tried to update");
|
||||
ASSERT_MSG(Memory::Read32(info.aux_info.return_buffer_base) == 0,
|
||||
ASSERT_MSG(memory.Read32(info.aux_info.return_buffer_base) == 0,
|
||||
"Aux buffers tried to update");
|
||||
ASSERT_MSG(Memory::Read32(info.aux_info.send_buffer_base) == 0,
|
||||
ASSERT_MSG(memory.Read32(info.aux_info.send_buffer_base) == 0,
|
||||
"Aux buffers tried to update");
|
||||
}
|
||||
}
|
||||
@@ -340,7 +343,7 @@ void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) {
|
||||
std::size_t offset{};
|
||||
s64 samples_remaining{BUFFER_SIZE};
|
||||
while (samples_remaining > 0) {
|
||||
const std::vector<s16> samples{voice.DequeueSamples(samples_remaining)};
|
||||
const std::vector<s16> samples{voice.DequeueSamples(samples_remaining, memory)};
|
||||
|
||||
if (samples.empty()) {
|
||||
break;
|
||||
|
||||
@@ -22,6 +22,10 @@ namespace Kernel {
|
||||
class WritableEvent;
|
||||
}
|
||||
|
||||
namespace Memory {
|
||||
class Memory;
|
||||
}
|
||||
|
||||
namespace AudioCore {
|
||||
|
||||
class AudioOut;
|
||||
@@ -217,9 +221,9 @@ static_assert(sizeof(UpdateDataHeader) == 0x40, "UpdateDataHeader has wrong size
|
||||
|
||||
class AudioRenderer {
|
||||
public:
|
||||
AudioRenderer(Core::Timing::CoreTiming& core_timing, AudioRendererParameter params,
|
||||
Kernel::SharedPtr<Kernel::WritableEvent> buffer_event,
|
||||
std::size_t instance_number);
|
||||
AudioRenderer(Core::Timing::CoreTiming& core_timing, Memory::Memory& memory_,
|
||||
AudioRendererParameter params,
|
||||
std::shared_ptr<Kernel::WritableEvent> buffer_event, std::size_t instance_number);
|
||||
~AudioRenderer();
|
||||
|
||||
std::vector<u8> UpdateAudioRenderer(const std::vector<u8>& input_params);
|
||||
@@ -235,11 +239,12 @@ private:
|
||||
class VoiceState;
|
||||
|
||||
AudioRendererParameter worker_params;
|
||||
Kernel::SharedPtr<Kernel::WritableEvent> buffer_event;
|
||||
std::shared_ptr<Kernel::WritableEvent> buffer_event;
|
||||
std::vector<VoiceState> voices;
|
||||
std::vector<EffectState> effects;
|
||||
std::unique_ptr<AudioOut> audio_out;
|
||||
AudioCore::StreamPtr stream;
|
||||
StreamPtr stream;
|
||||
Memory::Memory& memory;
|
||||
};
|
||||
|
||||
} // namespace AudioCore
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "audio_core/cubeb_sink.h"
|
||||
#include "audio_core/stream.h"
|
||||
#include "audio_core/time_stretch.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/ring_buffer.h"
|
||||
#include "core/settings.h"
|
||||
@@ -65,12 +66,25 @@ public:
|
||||
void EnqueueSamples(u32 source_num_channels, const std::vector<s16>& samples) override {
|
||||
if (source_num_channels > num_channels) {
|
||||
// Downsample 6 channels to 2
|
||||
ASSERT_MSG(source_num_channels == 6, "Channel count must be 6");
|
||||
|
||||
std::vector<s16> buf;
|
||||
buf.reserve(samples.size() * num_channels / source_num_channels);
|
||||
for (std::size_t i = 0; i < samples.size(); i += source_num_channels) {
|
||||
for (std::size_t ch = 0; ch < num_channels; ch++) {
|
||||
buf.push_back(samples[i + ch]);
|
||||
}
|
||||
// Downmixing implementation taken from the ATSC standard
|
||||
const s16 left{samples[i + 0]};
|
||||
const s16 right{samples[i + 1]};
|
||||
const s16 center{samples[i + 2]};
|
||||
const s16 surround_left{samples[i + 4]};
|
||||
const s16 surround_right{samples[i + 5]};
|
||||
// Not used in the ATSC reference implementation
|
||||
[[maybe_unused]] const s16 low_frequency_effects { samples[i + 3] };
|
||||
|
||||
constexpr s32 clev{707}; // center mixing level coefficient
|
||||
constexpr s32 slev{707}; // surround mixing level coefficient
|
||||
|
||||
buf.push_back(left + (clev * center / 1000) + (slev * surround_left / 1000));
|
||||
buf.push_back(right + (clev * center / 1000) + (slev * surround_right / 1000));
|
||||
}
|
||||
queue.Push(buf);
|
||||
return;
|
||||
|
||||
@@ -37,7 +37,7 @@ Stream::Stream(Core::Timing::CoreTiming& core_timing, u32 sample_rate, Format fo
|
||||
: sample_rate{sample_rate}, format{format}, release_callback{std::move(release_callback)},
|
||||
sink_stream{sink_stream}, core_timing{core_timing}, name{std::move(name_)} {
|
||||
|
||||
release_event = core_timing.RegisterEvent(
|
||||
release_event = Core::Timing::CreateEvent(
|
||||
name, [this](u64 userdata, s64 cycles_late) { ReleaseActiveBuffer(); });
|
||||
}
|
||||
|
||||
|
||||
@@ -98,18 +98,19 @@ private:
|
||||
/// Gets the number of core cycles when the specified buffer will be released
|
||||
s64 GetBufferReleaseCycles(const Buffer& buffer) const;
|
||||
|
||||
u32 sample_rate; ///< Sample rate of the stream
|
||||
Format format; ///< Format of the stream
|
||||
float game_volume = 1.0f; ///< The volume the game currently has set
|
||||
ReleaseCallback release_callback; ///< Buffer release callback for the stream
|
||||
State state{State::Stopped}; ///< Playback state of the stream
|
||||
Core::Timing::EventType* release_event{}; ///< Core timing release event for the stream
|
||||
BufferPtr active_buffer; ///< Actively playing buffer in the stream
|
||||
std::queue<BufferPtr> queued_buffers; ///< Buffers queued to be played in the stream
|
||||
std::queue<BufferPtr> released_buffers; ///< Buffers recently released from the stream
|
||||
SinkStream& sink_stream; ///< Output sink for the stream
|
||||
Core::Timing::CoreTiming& core_timing; ///< Core timing instance.
|
||||
std::string name; ///< Name of the stream, must be unique
|
||||
u32 sample_rate; ///< Sample rate of the stream
|
||||
Format format; ///< Format of the stream
|
||||
float game_volume = 1.0f; ///< The volume the game currently has set
|
||||
ReleaseCallback release_callback; ///< Buffer release callback for the stream
|
||||
State state{State::Stopped}; ///< Playback state of the stream
|
||||
std::shared_ptr<Core::Timing::EventType>
|
||||
release_event; ///< Core timing release event for the stream
|
||||
BufferPtr active_buffer; ///< Actively playing buffer in the stream
|
||||
std::queue<BufferPtr> queued_buffers; ///< Buffers queued to be played in the stream
|
||||
std::queue<BufferPtr> released_buffers; ///< Buffers recently released from the stream
|
||||
SinkStream& sink_stream; ///< Output sink for the stream
|
||||
Core::Timing::CoreTiming& core_timing; ///< Core timing instance.
|
||||
std::string name; ///< Name of the stream, must be unique
|
||||
};
|
||||
|
||||
using StreamPtr = std::shared_ptr<Stream>;
|
||||
|
||||
@@ -15,6 +15,10 @@ endif ()
|
||||
if (DEFINED ENV{DISPLAYVERSION})
|
||||
set(DISPLAY_VERSION $ENV{DISPLAYVERSION})
|
||||
endif ()
|
||||
|
||||
# Pass the path to git to the GenerateSCMRev.cmake as well
|
||||
find_package(Git QUIET)
|
||||
|
||||
add_custom_command(OUTPUT scm_rev.cpp
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DSRC_DIR="${CMAKE_SOURCE_DIR}"
|
||||
@@ -23,6 +27,7 @@ add_custom_command(OUTPUT scm_rev.cpp
|
||||
-DTITLE_BAR_FORMAT_RUNNING="${TITLE_BAR_FORMAT_RUNNING}"
|
||||
-DBUILD_TAG="${BUILD_TAG}"
|
||||
-DBUILD_ID="${DISPLAY_VERSION}"
|
||||
-DGIT_EXECUTABLE="${GIT_EXECUTABLE}"
|
||||
-P "${CMAKE_SOURCE_DIR}/CMakeModules/GenerateSCMRev.cmake"
|
||||
DEPENDS
|
||||
# WARNING! It was too much work to try and make a common location for this list,
|
||||
|
||||
@@ -41,8 +41,9 @@ __declspec(noinline, noreturn)
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define UNREACHABLE() ASSERT_MSG(false, "Unreachable code!")
|
||||
#define UNREACHABLE_MSG(...) ASSERT_MSG(false, __VA_ARGS__)
|
||||
#define UNREACHABLE() assert_noinline_call([] { LOG_CRITICAL(Debug, "Unreachable code!"); })
|
||||
#define UNREACHABLE_MSG(...) \
|
||||
assert_noinline_call([&] { LOG_CRITICAL(Debug, "Unreachable code!\n" __VA_ARGS__); })
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define DEBUG_ASSERT(_a_) ASSERT(_a_)
|
||||
|
||||
@@ -19,13 +19,15 @@
|
||||
|
||||
/// Helper macros to insert unused bytes or words to properly align structs. These values will be
|
||||
/// zero-initialized.
|
||||
#define INSERT_PADDING_BYTES(num_bytes) std::array<u8, num_bytes> CONCAT2(pad, __LINE__){};
|
||||
#define INSERT_PADDING_WORDS(num_words) std::array<u32, num_words> CONCAT2(pad, __LINE__){};
|
||||
#define INSERT_PADDING_BYTES(num_bytes) \
|
||||
std::array<u8, num_bytes> CONCAT2(pad, __LINE__) {}
|
||||
#define INSERT_PADDING_WORDS(num_words) \
|
||||
std::array<u32, num_words> CONCAT2(pad, __LINE__) {}
|
||||
|
||||
/// These are similar to the INSERT_PADDING_* macros, but are needed for padding unions. This is
|
||||
/// because unions can only be initialized by one member.
|
||||
#define INSERT_UNION_PADDING_BYTES(num_bytes) std::array<u8, num_bytes> CONCAT2(pad, __LINE__);
|
||||
#define INSERT_UNION_PADDING_WORDS(num_words) std::array<u32, num_words> CONCAT2(pad, __LINE__);
|
||||
#define INSERT_UNION_PADDING_BYTES(num_bytes) std::array<u8, num_bytes> CONCAT2(pad, __LINE__)
|
||||
#define INSERT_UNION_PADDING_WORDS(num_words) std::array<u32, num_words> CONCAT2(pad, __LINE__)
|
||||
|
||||
#ifndef _MSC_VER
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ private:
|
||||
duration_cast<std::chrono::microseconds>(steady_clock::now() - time_origin);
|
||||
entry.log_class = log_class;
|
||||
entry.log_level = log_level;
|
||||
entry.filename = Common::TrimSourcePath(filename);
|
||||
entry.filename = filename;
|
||||
entry.line_num = line_nr;
|
||||
entry.function = function;
|
||||
entry.message = std::move(message);
|
||||
@@ -272,8 +272,10 @@ const char* GetLogClassName(Class log_class) {
|
||||
#undef CLS
|
||||
#undef SUB
|
||||
case Class::Count:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
UNREACHABLE();
|
||||
return "Invalid";
|
||||
}
|
||||
|
||||
const char* GetLevelName(Level log_level) {
|
||||
@@ -288,9 +290,11 @@ const char* GetLevelName(Level log_level) {
|
||||
LVL(Error);
|
||||
LVL(Critical);
|
||||
case Level::Count:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
#undef LVL
|
||||
UNREACHABLE();
|
||||
return "Invalid";
|
||||
}
|
||||
|
||||
void SetGlobalFilter(const Filter& filter) {
|
||||
|
||||
@@ -23,7 +23,7 @@ struct Entry {
|
||||
std::chrono::microseconds timestamp;
|
||||
Class log_class;
|
||||
Level log_level;
|
||||
std::string filename;
|
||||
const char* filename;
|
||||
unsigned int line_num;
|
||||
std::string function;
|
||||
std::string message;
|
||||
|
||||
@@ -9,6 +9,15 @@
|
||||
|
||||
namespace Log {
|
||||
|
||||
// trims up to and including the last of ../, ..\, src/, src\ in a string
|
||||
constexpr const char* TrimSourcePath(std::string_view source) {
|
||||
const auto rfind = [source](const std::string_view match) {
|
||||
return source.rfind(match) == source.npos ? 0 : (source.rfind(match) + match.size());
|
||||
};
|
||||
auto idx = std::max({rfind("src/"), rfind("src\\"), rfind("../"), rfind("..\\")});
|
||||
return source.data() + idx;
|
||||
}
|
||||
|
||||
/// Specifies the severity or level of detail of the log message.
|
||||
enum class Level : u8 {
|
||||
Trace, ///< Extremely detailed and repetitive debugging information that is likely to
|
||||
@@ -141,24 +150,24 @@ void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsig
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define LOG_TRACE(log_class, ...) \
|
||||
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Trace, __FILE__, __LINE__, \
|
||||
__func__, __VA_ARGS__)
|
||||
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Trace, \
|
||||
::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__)
|
||||
#else
|
||||
#define LOG_TRACE(log_class, fmt, ...) (void(0))
|
||||
#endif
|
||||
|
||||
#define LOG_DEBUG(log_class, ...) \
|
||||
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Debug, __FILE__, __LINE__, \
|
||||
__func__, __VA_ARGS__)
|
||||
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Debug, \
|
||||
::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__)
|
||||
#define LOG_INFO(log_class, ...) \
|
||||
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Info, __FILE__, __LINE__, \
|
||||
__func__, __VA_ARGS__)
|
||||
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Info, \
|
||||
::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__)
|
||||
#define LOG_WARNING(log_class, ...) \
|
||||
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Warning, __FILE__, __LINE__, \
|
||||
__func__, __VA_ARGS__)
|
||||
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Warning, \
|
||||
::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__)
|
||||
#define LOG_ERROR(log_class, ...) \
|
||||
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Error, __FILE__, __LINE__, \
|
||||
__func__, __VA_ARGS__)
|
||||
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Error, \
|
||||
::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__)
|
||||
#define LOG_CRITICAL(log_class, ...) \
|
||||
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Critical, __FILE__, __LINE__, \
|
||||
__func__, __VA_ARGS__)
|
||||
::Log::FmtLogMessage(::Log::Class::log_class, ::Log::Level::Critical, \
|
||||
::Log::TrimSourcePath(__FILE__), __LINE__, __func__, __VA_ARGS__)
|
||||
|
||||
@@ -24,17 +24,29 @@ struct Rectangle {
|
||||
: left(left), top(top), right(right), bottom(bottom) {}
|
||||
|
||||
T GetWidth() const {
|
||||
return std::abs(static_cast<std::make_signed_t<T>>(right - left));
|
||||
if constexpr (std::is_floating_point_v<T>) {
|
||||
return std::abs(right - left);
|
||||
} else {
|
||||
return std::abs(static_cast<std::make_signed_t<T>>(right - left));
|
||||
}
|
||||
}
|
||||
|
||||
T GetHeight() const {
|
||||
return std::abs(static_cast<std::make_signed_t<T>>(bottom - top));
|
||||
if constexpr (std::is_floating_point_v<T>) {
|
||||
return std::abs(bottom - top);
|
||||
} else {
|
||||
return std::abs(static_cast<std::make_signed_t<T>>(bottom - top));
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle<T> TranslateX(const T x) const {
|
||||
return Rectangle{left + x, top, right + x, bottom};
|
||||
}
|
||||
|
||||
Rectangle<T> TranslateY(const T y) const {
|
||||
return Rectangle{left, top + y, right, bottom + y};
|
||||
}
|
||||
|
||||
Rectangle<T> Scale(const float s) const {
|
||||
return Rectangle{left, top, static_cast<T>(left + GetWidth() * s),
|
||||
static_cast<T>(top + GetHeight() * s)};
|
||||
|
||||
@@ -223,26 +223,4 @@ std::u16string UTF16StringFromFixedZeroTerminatedBuffer(std::u16string_view buff
|
||||
return std::u16string(buffer.begin(), buffer.begin() + len);
|
||||
}
|
||||
|
||||
const char* TrimSourcePath(const char* path, const char* root) {
|
||||
const char* p = path;
|
||||
|
||||
while (*p != '\0') {
|
||||
const char* next_slash = p;
|
||||
while (*next_slash != '\0' && *next_slash != '/' && *next_slash != '\\') {
|
||||
++next_slash;
|
||||
}
|
||||
|
||||
bool is_src = Common::ComparePartialString(p, next_slash, root);
|
||||
p = next_slash;
|
||||
|
||||
if (*p != '\0') {
|
||||
++p;
|
||||
}
|
||||
if (is_src) {
|
||||
path = p;
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
|
||||
@@ -44,20 +44,6 @@ template class Field<std::string>;
|
||||
template class Field<const char*>;
|
||||
template class Field<std::chrono::microseconds>;
|
||||
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
static const char* CpuVendorToStr(Common::CPUVendor vendor) {
|
||||
switch (vendor) {
|
||||
case Common::CPUVendor::INTEL:
|
||||
return "Intel";
|
||||
case Common::CPUVendor::AMD:
|
||||
return "Amd";
|
||||
case Common::CPUVendor::OTHER:
|
||||
return "Other";
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
#endif
|
||||
|
||||
void AppendBuildInfo(FieldCollection& fc) {
|
||||
const bool is_git_dirty{std::strstr(Common::g_scm_desc, "dirty") != nullptr};
|
||||
fc.AddField(FieldType::App, "Git_IsDirty", is_git_dirty);
|
||||
@@ -71,7 +57,6 @@ void AppendCPUInfo(FieldCollection& fc) {
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
fc.AddField(FieldType::UserSystem, "CPU_Model", Common::GetCPUCaps().cpu_string);
|
||||
fc.AddField(FieldType::UserSystem, "CPU_BrandString", Common::GetCPUCaps().brand_string);
|
||||
fc.AddField(FieldType::UserSystem, "CPU_Vendor", CpuVendorToStr(Common::GetCPUCaps().vendor));
|
||||
fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_AES", Common::GetCPUCaps().aes);
|
||||
fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_AVX", Common::GetCPUCaps().avx);
|
||||
fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_AVX2", Common::GetCPUCaps().avx2);
|
||||
|
||||
@@ -28,6 +28,15 @@ public:
|
||||
is_set = false;
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
bool WaitFor(const std::chrono::duration<Duration>& time) {
|
||||
std::unique_lock lk{mutex};
|
||||
if (!condvar.wait_for(lk, time, [this] { return is_set; }))
|
||||
return false;
|
||||
is_set = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Clock, class Duration>
|
||||
bool WaitUntil(const std::chrono::time_point<Clock, Duration>& time) {
|
||||
std::unique_lock lk{mutex};
|
||||
|
||||
@@ -46,9 +46,16 @@ public:
|
||||
ElementPtr* new_ptr = new ElementPtr();
|
||||
write_ptr->next.store(new_ptr, std::memory_order_release);
|
||||
write_ptr = new_ptr;
|
||||
cv.notify_one();
|
||||
|
||||
++size;
|
||||
const size_t previous_size{size++};
|
||||
|
||||
// Acquire the mutex and then immediately release it as a fence.
|
||||
// TODO(bunnei): This can be replaced with C++20 waitable atomics when properly supported.
|
||||
// See discussion on https://github.com/yuzu-emu/yuzu/pull/3173 for details.
|
||||
if (previous_size == 0) {
|
||||
std::lock_guard lock{cv_mutex};
|
||||
}
|
||||
cv.notify_one();
|
||||
}
|
||||
|
||||
void Pop() {
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include "common/common_types.h"
|
||||
#include "common/x64/cpu_detect.h"
|
||||
|
||||
@@ -51,8 +49,6 @@ namespace Common {
|
||||
static CPUCaps Detect() {
|
||||
CPUCaps caps = {};
|
||||
|
||||
caps.num_cores = std::thread::hardware_concurrency();
|
||||
|
||||
// Assumes the CPU supports the CPUID instruction. Those that don't would likely not support
|
||||
// yuzu at all anyway
|
||||
|
||||
@@ -70,12 +66,6 @@ static CPUCaps Detect() {
|
||||
__cpuid(cpu_id, 0x80000000);
|
||||
|
||||
u32 max_ex_fn = cpu_id[0];
|
||||
if (!strcmp(caps.brand_string, "GenuineIntel"))
|
||||
caps.vendor = CPUVendor::INTEL;
|
||||
else if (!strcmp(caps.brand_string, "AuthenticAMD"))
|
||||
caps.vendor = CPUVendor::AMD;
|
||||
else
|
||||
caps.vendor = CPUVendor::OTHER;
|
||||
|
||||
// Set reasonable default brand string even if brand string not available
|
||||
strcpy(caps.cpu_string, caps.brand_string);
|
||||
@@ -96,15 +86,9 @@ static CPUCaps Detect() {
|
||||
caps.sse4_1 = true;
|
||||
if ((cpu_id[2] >> 20) & 1)
|
||||
caps.sse4_2 = true;
|
||||
if ((cpu_id[2] >> 22) & 1)
|
||||
caps.movbe = true;
|
||||
if ((cpu_id[2] >> 25) & 1)
|
||||
caps.aes = true;
|
||||
|
||||
if ((cpu_id[3] >> 24) & 1) {
|
||||
caps.fxsave_fxrstor = true;
|
||||
}
|
||||
|
||||
// AVX support requires 3 separate checks:
|
||||
// - Is the AVX bit set in CPUID?
|
||||
// - Is the XSAVE bit set in CPUID?
|
||||
@@ -129,8 +113,6 @@ static CPUCaps Detect() {
|
||||
}
|
||||
}
|
||||
|
||||
caps.flush_to_zero = caps.sse;
|
||||
|
||||
if (max_ex_fn >= 0x80000004) {
|
||||
// Extract CPU model string
|
||||
__cpuid(cpu_id, 0x80000002);
|
||||
@@ -144,14 +126,8 @@ static CPUCaps Detect() {
|
||||
if (max_ex_fn >= 0x80000001) {
|
||||
// Check for more features
|
||||
__cpuid(cpu_id, 0x80000001);
|
||||
if (cpu_id[2] & 1)
|
||||
caps.lahf_sahf_64 = true;
|
||||
if ((cpu_id[2] >> 5) & 1)
|
||||
caps.lzcnt = true;
|
||||
if ((cpu_id[2] >> 16) & 1)
|
||||
caps.fma4 = true;
|
||||
if ((cpu_id[3] >> 29) & 1)
|
||||
caps.long_mode = true;
|
||||
}
|
||||
|
||||
return caps;
|
||||
@@ -162,48 +138,4 @@ const CPUCaps& GetCPUCaps() {
|
||||
return caps;
|
||||
}
|
||||
|
||||
std::string GetCPUCapsString() {
|
||||
auto caps = GetCPUCaps();
|
||||
|
||||
std::string sum(caps.cpu_string);
|
||||
sum += " (";
|
||||
sum += caps.brand_string;
|
||||
sum += ")";
|
||||
|
||||
if (caps.sse)
|
||||
sum += ", SSE";
|
||||
if (caps.sse2) {
|
||||
sum += ", SSE2";
|
||||
if (!caps.flush_to_zero)
|
||||
sum += " (without DAZ)";
|
||||
}
|
||||
|
||||
if (caps.sse3)
|
||||
sum += ", SSE3";
|
||||
if (caps.ssse3)
|
||||
sum += ", SSSE3";
|
||||
if (caps.sse4_1)
|
||||
sum += ", SSE4.1";
|
||||
if (caps.sse4_2)
|
||||
sum += ", SSE4.2";
|
||||
if (caps.avx)
|
||||
sum += ", AVX";
|
||||
if (caps.avx2)
|
||||
sum += ", AVX2";
|
||||
if (caps.bmi1)
|
||||
sum += ", BMI1";
|
||||
if (caps.bmi2)
|
||||
sum += ", BMI2";
|
||||
if (caps.fma)
|
||||
sum += ", FMA";
|
||||
if (caps.aes)
|
||||
sum += ", AES";
|
||||
if (caps.movbe)
|
||||
sum += ", MOVBE";
|
||||
if (caps.long_mode)
|
||||
sum += ", 64-bit support";
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
|
||||
@@ -4,23 +4,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Common {
|
||||
|
||||
/// x86/x64 CPU vendors that may be detected by this module
|
||||
enum class CPUVendor {
|
||||
INTEL,
|
||||
AMD,
|
||||
OTHER,
|
||||
};
|
||||
|
||||
/// x86/x64 CPU capabilities that may be detected by this module
|
||||
struct CPUCaps {
|
||||
CPUVendor vendor;
|
||||
char cpu_string[0x21];
|
||||
char brand_string[0x41];
|
||||
int num_cores;
|
||||
bool sse;
|
||||
bool sse2;
|
||||
bool sse3;
|
||||
@@ -35,20 +24,6 @@ struct CPUCaps {
|
||||
bool fma;
|
||||
bool fma4;
|
||||
bool aes;
|
||||
|
||||
// Support for the FXSAVE and FXRSTOR instructions
|
||||
bool fxsave_fxrstor;
|
||||
|
||||
bool movbe;
|
||||
|
||||
// This flag indicates that the hardware supports some mode in which denormal inputs and outputs
|
||||
// are automatically set to (signed) zero.
|
||||
bool flush_to_zero;
|
||||
|
||||
// Support for LAHF and SAHF instructions in 64-bit mode
|
||||
bool lahf_sahf_64;
|
||||
|
||||
bool long_mode;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -57,10 +32,4 @@ struct CPUCaps {
|
||||
*/
|
||||
const CPUCaps& GetCPUCaps();
|
||||
|
||||
/**
|
||||
* Gets a string summary of the name and supported capabilities of the host CPU
|
||||
* @return String summary
|
||||
*/
|
||||
std::string GetCPUCapsString();
|
||||
|
||||
} // namespace Common
|
||||
|
||||
@@ -15,14 +15,14 @@ add_library(core STATIC
|
||||
constants.h
|
||||
core.cpp
|
||||
core.h
|
||||
core_cpu.cpp
|
||||
core_cpu.h
|
||||
core_manager.cpp
|
||||
core_manager.h
|
||||
core_timing.cpp
|
||||
core_timing.h
|
||||
core_timing_util.cpp
|
||||
core_timing_util.h
|
||||
cpu_core_manager.cpp
|
||||
cpu_core_manager.h
|
||||
cpu_manager.cpp
|
||||
cpu_manager.h
|
||||
crypto/aes_util.cpp
|
||||
crypto/aes_util.h
|
||||
crypto/encryption_layer.cpp
|
||||
@@ -96,6 +96,8 @@ add_library(core STATIC
|
||||
file_sys/system_archive/system_archive.h
|
||||
file_sys/system_archive/system_version.cpp
|
||||
file_sys/system_archive/system_version.h
|
||||
file_sys/system_archive/time_zone_binary.cpp
|
||||
file_sys/system_archive/time_zone_binary.h
|
||||
file_sys/vfs.cpp
|
||||
file_sys/vfs.h
|
||||
file_sys/vfs_concat.cpp
|
||||
@@ -129,8 +131,8 @@ add_library(core STATIC
|
||||
frontend/framebuffer_layout.cpp
|
||||
frontend/framebuffer_layout.h
|
||||
frontend/input.h
|
||||
frontend/scope_acquire_window_context.cpp
|
||||
frontend/scope_acquire_window_context.h
|
||||
frontend/scope_acquire_context.cpp
|
||||
frontend/scope_acquire_context.h
|
||||
gdbstub/gdbstub.cpp
|
||||
gdbstub/gdbstub.h
|
||||
hardware_interrupt_manager.cpp
|
||||
@@ -156,6 +158,8 @@ add_library(core STATIC
|
||||
hle/kernel/mutex.h
|
||||
hle/kernel/object.cpp
|
||||
hle/kernel/object.h
|
||||
hle/kernel/physical_core.cpp
|
||||
hle/kernel/physical_core.h
|
||||
hle/kernel/process.cpp
|
||||
hle/kernel/process.h
|
||||
hle/kernel/process_capability.cpp
|
||||
@@ -170,20 +174,25 @@ add_library(core STATIC
|
||||
hle/kernel/server_port.h
|
||||
hle/kernel/server_session.cpp
|
||||
hle/kernel/server_session.h
|
||||
hle/kernel/session.cpp
|
||||
hle/kernel/session.h
|
||||
hle/kernel/shared_memory.cpp
|
||||
hle/kernel/shared_memory.h
|
||||
hle/kernel/svc.cpp
|
||||
hle/kernel/svc.h
|
||||
hle/kernel/svc_wrap.h
|
||||
hle/kernel/synchronization_object.cpp
|
||||
hle/kernel/synchronization_object.h
|
||||
hle/kernel/synchronization.cpp
|
||||
hle/kernel/synchronization.h
|
||||
hle/kernel/thread.cpp
|
||||
hle/kernel/thread.h
|
||||
hle/kernel/time_manager.cpp
|
||||
hle/kernel/time_manager.h
|
||||
hle/kernel/transfer_memory.cpp
|
||||
hle/kernel/transfer_memory.h
|
||||
hle/kernel/vm_manager.cpp
|
||||
hle/kernel/vm_manager.h
|
||||
hle/kernel/wait_object.cpp
|
||||
hle/kernel/wait_object.h
|
||||
hle/kernel/writable_event.cpp
|
||||
hle/kernel/writable_event.h
|
||||
hle/lock.cpp
|
||||
@@ -460,12 +469,40 @@ add_library(core STATIC
|
||||
hle/service/spl/spl.h
|
||||
hle/service/ssl/ssl.cpp
|
||||
hle/service/ssl/ssl.h
|
||||
hle/service/time/clock_types.h
|
||||
hle/service/time/ephemeral_network_system_clock_context_writer.h
|
||||
hle/service/time/ephemeral_network_system_clock_core.h
|
||||
hle/service/time/errors.h
|
||||
hle/service/time/interface.cpp
|
||||
hle/service/time/interface.h
|
||||
hle/service/time/local_system_clock_context_writer.h
|
||||
hle/service/time/network_system_clock_context_writer.h
|
||||
hle/service/time/standard_local_system_clock_core.h
|
||||
hle/service/time/standard_network_system_clock_core.h
|
||||
hle/service/time/standard_steady_clock_core.cpp
|
||||
hle/service/time/standard_steady_clock_core.h
|
||||
hle/service/time/standard_user_system_clock_core.cpp
|
||||
hle/service/time/standard_user_system_clock_core.h
|
||||
hle/service/time/steady_clock_core.h
|
||||
hle/service/time/system_clock_context_update_callback.cpp
|
||||
hle/service/time/system_clock_context_update_callback.h
|
||||
hle/service/time/system_clock_core.cpp
|
||||
hle/service/time/system_clock_core.h
|
||||
hle/service/time/tick_based_steady_clock_core.cpp
|
||||
hle/service/time/tick_based_steady_clock_core.h
|
||||
hle/service/time/time.cpp
|
||||
hle/service/time/time.h
|
||||
hle/service/time/time_manager.cpp
|
||||
hle/service/time/time_manager.h
|
||||
hle/service/time/time_sharedmemory.cpp
|
||||
hle/service/time/time_sharedmemory.h
|
||||
hle/service/time/time_zone_content_manager.cpp
|
||||
hle/service/time/time_zone_content_manager.h
|
||||
hle/service/time/time_zone_manager.cpp
|
||||
hle/service/time/time_zone_manager.h
|
||||
hle/service/time/time_zone_service.cpp
|
||||
hle/service/time/time_zone_service.h
|
||||
hle/service/time/time_zone_types.h
|
||||
hle/service/usb/usb.cpp
|
||||
hle/service/usb/usb.h
|
||||
hle/service/vi/display/vi_display.cpp
|
||||
@@ -509,7 +546,6 @@ add_library(core STATIC
|
||||
memory/dmnt_cheat_vm.h
|
||||
memory.cpp
|
||||
memory.h
|
||||
memory_setup.h
|
||||
perf_stats.cpp
|
||||
perf_stats.h
|
||||
reporter.cpp
|
||||
@@ -522,6 +558,23 @@ add_library(core STATIC
|
||||
tools/freezer.h
|
||||
)
|
||||
|
||||
if (MSVC)
|
||||
target_compile_options(core PRIVATE
|
||||
# 'expression' : signed/unsigned mismatch
|
||||
/we4018
|
||||
# 'argument' : conversion from 'type1' to 'type2', possible loss of data (floating-point)
|
||||
/we4244
|
||||
# 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch
|
||||
/we4245
|
||||
# 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
|
||||
/we4254
|
||||
# 'var' : conversion from 'size_t' to 'type', possible loss of data
|
||||
/we4267
|
||||
# 'context' : truncation from 'type1' to 'type2'
|
||||
/we4305
|
||||
)
|
||||
endif()
|
||||
|
||||
create_target_directory_groups(core)
|
||||
|
||||
target_link_libraries(core PUBLIC common PRIVATE audio_core video_core)
|
||||
@@ -542,8 +595,12 @@ endif()
|
||||
|
||||
if (ARCHITECTURE_x86_64)
|
||||
target_sources(core PRIVATE
|
||||
arm/dynarmic/arm_dynarmic.cpp
|
||||
arm/dynarmic/arm_dynarmic.h
|
||||
arm/dynarmic/arm_dynarmic_32.cpp
|
||||
arm/dynarmic/arm_dynarmic_32.h
|
||||
arm/dynarmic/arm_dynarmic_64.cpp
|
||||
arm/dynarmic/arm_dynarmic_64.h
|
||||
arm/dynarmic/arm_dynarmic_cp15.cpp
|
||||
arm/dynarmic/arm_dynarmic_cp15.h
|
||||
)
|
||||
target_link_libraries(core PRIVATE dynarmic)
|
||||
endif()
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "core/memory.h"
|
||||
|
||||
namespace Core {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr u64 ELF_DYNAMIC_TAG_NULL = 0;
|
||||
@@ -61,15 +60,15 @@ static_assert(sizeof(ELFSymbol) == 0x18, "ELFSymbol has incorrect size.");
|
||||
|
||||
using Symbols = std::vector<std::pair<ELFSymbol, std::string>>;
|
||||
|
||||
Symbols GetSymbols(VAddr text_offset) {
|
||||
const auto mod_offset = text_offset + Memory::Read32(text_offset + 4);
|
||||
Symbols GetSymbols(VAddr text_offset, Memory::Memory& memory) {
|
||||
const auto mod_offset = text_offset + memory.Read32(text_offset + 4);
|
||||
|
||||
if (mod_offset < text_offset || (mod_offset & 0b11) != 0 ||
|
||||
Memory::Read32(mod_offset) != Common::MakeMagic('M', 'O', 'D', '0')) {
|
||||
memory.Read32(mod_offset) != Common::MakeMagic('M', 'O', 'D', '0')) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto dynamic_offset = Memory::Read32(mod_offset + 0x4) + mod_offset;
|
||||
const auto dynamic_offset = memory.Read32(mod_offset + 0x4) + mod_offset;
|
||||
|
||||
VAddr string_table_offset{};
|
||||
VAddr symbol_table_offset{};
|
||||
@@ -77,8 +76,8 @@ Symbols GetSymbols(VAddr text_offset) {
|
||||
|
||||
VAddr dynamic_index = dynamic_offset;
|
||||
while (true) {
|
||||
const auto tag = Memory::Read64(dynamic_index);
|
||||
const auto value = Memory::Read64(dynamic_index + 0x8);
|
||||
const u64 tag = memory.Read64(dynamic_index);
|
||||
const u64 value = memory.Read64(dynamic_index + 0x8);
|
||||
dynamic_index += 0x10;
|
||||
|
||||
if (tag == ELF_DYNAMIC_TAG_NULL) {
|
||||
@@ -106,11 +105,11 @@ Symbols GetSymbols(VAddr text_offset) {
|
||||
VAddr symbol_index = symbol_table_address;
|
||||
while (symbol_index < string_table_address) {
|
||||
ELFSymbol symbol{};
|
||||
Memory::ReadBlock(symbol_index, &symbol, sizeof(ELFSymbol));
|
||||
memory.ReadBlock(symbol_index, &symbol, sizeof(ELFSymbol));
|
||||
|
||||
VAddr string_offset = string_table_address + symbol.name_index;
|
||||
std::string name;
|
||||
for (u8 c = Memory::Read8(string_offset); c != 0; c = Memory::Read8(++string_offset)) {
|
||||
for (u8 c = memory.Read8(string_offset); c != 0; c = memory.Read8(++string_offset)) {
|
||||
name += static_cast<char>(c);
|
||||
}
|
||||
|
||||
@@ -142,28 +141,28 @@ constexpr u64 SEGMENT_BASE = 0x7100000000ull;
|
||||
|
||||
std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktrace() const {
|
||||
std::vector<BacktraceEntry> out;
|
||||
auto& memory = system.Memory();
|
||||
|
||||
auto fp = GetReg(29);
|
||||
auto lr = GetReg(30);
|
||||
|
||||
while (true) {
|
||||
out.push_back({"", 0, lr, 0});
|
||||
if (!fp) {
|
||||
break;
|
||||
}
|
||||
lr = Memory::Read64(fp + 8) - 4;
|
||||
fp = Memory::Read64(fp);
|
||||
lr = memory.Read64(fp + 8) - 4;
|
||||
fp = memory.Read64(fp);
|
||||
}
|
||||
|
||||
std::map<VAddr, std::string> modules;
|
||||
auto& loader{System::GetInstance().GetAppLoader()};
|
||||
auto& loader{system.GetAppLoader()};
|
||||
if (loader.ReadNSOModules(modules) != Loader::ResultStatus::Success) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::map<std::string, Symbols> symbols;
|
||||
for (const auto& module : modules) {
|
||||
symbols.insert_or_assign(module.second, GetSymbols(module.first));
|
||||
symbols.insert_or_assign(module.second, GetSymbols(module.first, memory));
|
||||
}
|
||||
|
||||
for (auto& entry : out) {
|
||||
|
||||
@@ -17,13 +17,28 @@ enum class VMAPermission : u8;
|
||||
}
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
|
||||
/// Generic ARMv8 CPU interface
|
||||
class ARM_Interface : NonCopyable {
|
||||
public:
|
||||
virtual ~ARM_Interface() {}
|
||||
explicit ARM_Interface(System& system_) : system{system_} {}
|
||||
virtual ~ARM_Interface() = default;
|
||||
|
||||
struct ThreadContext {
|
||||
struct ThreadContext32 {
|
||||
std::array<u32, 16> cpu_registers;
|
||||
u32 cpsr;
|
||||
std::array<u8, 4> padding;
|
||||
std::array<u64, 32> fprs;
|
||||
u32 fpscr;
|
||||
u32 fpexc;
|
||||
u32 tpidr;
|
||||
};
|
||||
// Internally within the kernel, it expects the AArch32 version of the
|
||||
// thread context to be 344 bytes in size.
|
||||
static_assert(sizeof(ThreadContext32) == 0x158);
|
||||
|
||||
struct ThreadContext64 {
|
||||
std::array<u64, 31> cpu_registers;
|
||||
u64 sp;
|
||||
u64 pc;
|
||||
@@ -36,7 +51,7 @@ public:
|
||||
};
|
||||
// Internally within the kernel, it expects the AArch64 version of the
|
||||
// thread context to be 800 bytes in size.
|
||||
static_assert(sizeof(ThreadContext) == 0x320);
|
||||
static_assert(sizeof(ThreadContext64) == 0x320);
|
||||
|
||||
/// Runs the CPU until an event happens
|
||||
virtual void Run() = 0;
|
||||
@@ -128,17 +143,10 @@ public:
|
||||
*/
|
||||
virtual void SetTPIDR_EL0(u64 value) = 0;
|
||||
|
||||
/**
|
||||
* Saves the current CPU context
|
||||
* @param ctx Thread context to save
|
||||
*/
|
||||
virtual void SaveContext(ThreadContext& ctx) = 0;
|
||||
|
||||
/**
|
||||
* Loads a CPU context
|
||||
* @param ctx Thread context to load
|
||||
*/
|
||||
virtual void LoadContext(const ThreadContext& ctx) = 0;
|
||||
virtual void SaveContext(ThreadContext32& ctx) = 0;
|
||||
virtual void SaveContext(ThreadContext64& ctx) = 0;
|
||||
virtual void LoadContext(const ThreadContext32& ctx) = 0;
|
||||
virtual void LoadContext(const ThreadContext64& ctx) = 0;
|
||||
|
||||
/// Clears the exclusive monitor's state.
|
||||
virtual void ClearExclusiveState() = 0;
|
||||
@@ -163,6 +171,10 @@ public:
|
||||
/// fp+0 : pointer to previous frame record
|
||||
/// fp+8 : value of lr for frame
|
||||
void LogBacktrace() const;
|
||||
|
||||
protected:
|
||||
/// System context that this ARM interface is running under.
|
||||
System& system;
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
|
||||
208
src/core/arm/dynarmic/arm_dynarmic_32.cpp
Normal file
208
src/core/arm/dynarmic/arm_dynarmic_32.cpp
Normal file
@@ -0,0 +1,208 @@
|
||||
// Copyright 2020 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cinttypes>
|
||||
#include <memory>
|
||||
#include <dynarmic/A32/a32.h>
|
||||
#include <dynarmic/A32/config.h>
|
||||
#include <dynarmic/A32/context.h>
|
||||
#include "common/microprofile.h"
|
||||
#include "core/arm/dynarmic/arm_dynarmic_32.h"
|
||||
#include "core/arm/dynarmic/arm_dynarmic_64.h"
|
||||
#include "core/arm/dynarmic/arm_dynarmic_cp15.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_manager.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/svc.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
namespace Core {
|
||||
|
||||
class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
|
||||
public:
|
||||
explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent) : parent(parent) {}
|
||||
|
||||
u8 MemoryRead8(u32 vaddr) override {
|
||||
return parent.system.Memory().Read8(vaddr);
|
||||
}
|
||||
u16 MemoryRead16(u32 vaddr) override {
|
||||
return parent.system.Memory().Read16(vaddr);
|
||||
}
|
||||
u32 MemoryRead32(u32 vaddr) override {
|
||||
return parent.system.Memory().Read32(vaddr);
|
||||
}
|
||||
u64 MemoryRead64(u32 vaddr) override {
|
||||
return parent.system.Memory().Read64(vaddr);
|
||||
}
|
||||
|
||||
void MemoryWrite8(u32 vaddr, u8 value) override {
|
||||
parent.system.Memory().Write8(vaddr, value);
|
||||
}
|
||||
void MemoryWrite16(u32 vaddr, u16 value) override {
|
||||
parent.system.Memory().Write16(vaddr, value);
|
||||
}
|
||||
void MemoryWrite32(u32 vaddr, u32 value) override {
|
||||
parent.system.Memory().Write32(vaddr, value);
|
||||
}
|
||||
void MemoryWrite64(u32 vaddr, u64 value) override {
|
||||
parent.system.Memory().Write64(vaddr, value);
|
||||
}
|
||||
|
||||
void InterpreterFallback(u32 pc, std::size_t num_instructions) override {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override {
|
||||
switch (exception) {
|
||||
case Dynarmic::A32::Exception::UndefinedInstruction:
|
||||
case Dynarmic::A32::Exception::UnpredictableInstruction:
|
||||
break;
|
||||
case Dynarmic::A32::Exception::Breakpoint:
|
||||
break;
|
||||
}
|
||||
LOG_CRITICAL(HW_GPU, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})",
|
||||
static_cast<std::size_t>(exception), pc, MemoryReadCode(pc));
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
void CallSVC(u32 swi) override {
|
||||
Kernel::CallSVC(parent.system, swi);
|
||||
}
|
||||
|
||||
void AddTicks(u64 ticks) override {
|
||||
// Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a
|
||||
// rough approximation of the amount of executed ticks in the system, it may be thrown off
|
||||
// if not all cores are doing a similar amount of work. Instead of doing this, we should
|
||||
// device a way so that timing is consistent across all cores without increasing the ticks 4
|
||||
// times.
|
||||
u64 amortized_ticks = (ticks - num_interpreted_instructions) / Core::NUM_CPU_CORES;
|
||||
// Always execute at least one tick.
|
||||
amortized_ticks = std::max<u64>(amortized_ticks, 1);
|
||||
|
||||
parent.system.CoreTiming().AddTicks(amortized_ticks);
|
||||
num_interpreted_instructions = 0;
|
||||
}
|
||||
u64 GetTicksRemaining() override {
|
||||
return std::max(parent.system.CoreTiming().GetDowncount(), {});
|
||||
}
|
||||
|
||||
ARM_Dynarmic_32& parent;
|
||||
std::size_t num_interpreted_instructions{};
|
||||
u64 tpidrro_el0{};
|
||||
u64 tpidr_el0{};
|
||||
};
|
||||
|
||||
std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable& page_table,
|
||||
std::size_t address_space_bits) const {
|
||||
Dynarmic::A32::UserConfig config;
|
||||
config.callbacks = cb.get();
|
||||
// TODO(bunnei): Implement page table for 32-bit
|
||||
// config.page_table = &page_table.pointers;
|
||||
config.coprocessors[15] = std::make_shared<DynarmicCP15>((u32*)&CP15_regs[0]);
|
||||
config.define_unpredictable_behaviour = true;
|
||||
return std::make_unique<Dynarmic::A32::Jit>(config);
|
||||
}
|
||||
|
||||
MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_32, "ARM JIT", "Dynarmic", MP_RGB(255, 64, 64));
|
||||
|
||||
void ARM_Dynarmic_32::Run() {
|
||||
MICROPROFILE_SCOPE(ARM_Jit_Dynarmic_32);
|
||||
jit->Run();
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::Step() {
|
||||
cb->InterpreterFallback(jit->Regs()[15], 1);
|
||||
}
|
||||
|
||||
ARM_Dynarmic_32::ARM_Dynarmic_32(System& system, ExclusiveMonitor& exclusive_monitor,
|
||||
std::size_t core_index)
|
||||
: ARM_Interface{system},
|
||||
cb(std::make_unique<DynarmicCallbacks32>(*this)), core_index{core_index},
|
||||
exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {}
|
||||
|
||||
ARM_Dynarmic_32::~ARM_Dynarmic_32() = default;
|
||||
|
||||
void ARM_Dynarmic_32::SetPC(u64 pc) {
|
||||
jit->Regs()[15] = static_cast<u32>(pc);
|
||||
}
|
||||
|
||||
u64 ARM_Dynarmic_32::GetPC() const {
|
||||
return jit->Regs()[15];
|
||||
}
|
||||
|
||||
u64 ARM_Dynarmic_32::GetReg(int index) const {
|
||||
return jit->Regs()[index];
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::SetReg(int index, u64 value) {
|
||||
jit->Regs()[index] = static_cast<u32>(value);
|
||||
}
|
||||
|
||||
u128 ARM_Dynarmic_32::GetVectorReg(int index) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::SetVectorReg(int index, u128 value) {}
|
||||
|
||||
u32 ARM_Dynarmic_32::GetPSTATE() const {
|
||||
return jit->Cpsr();
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::SetPSTATE(u32 cpsr) {
|
||||
jit->SetCpsr(cpsr);
|
||||
}
|
||||
|
||||
u64 ARM_Dynarmic_32::GetTlsAddress() const {
|
||||
return CP15_regs[static_cast<std::size_t>(CP15Register::CP15_THREAD_URO)];
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::SetTlsAddress(VAddr address) {
|
||||
CP15_regs[static_cast<std::size_t>(CP15Register::CP15_THREAD_URO)] = static_cast<u32>(address);
|
||||
}
|
||||
|
||||
u64 ARM_Dynarmic_32::GetTPIDR_EL0() const {
|
||||
return cb->tpidr_el0;
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::SetTPIDR_EL0(u64 value) {
|
||||
cb->tpidr_el0 = value;
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) {
|
||||
Dynarmic::A32::Context context;
|
||||
jit->SaveContext(context);
|
||||
ctx.cpu_registers = context.Regs();
|
||||
ctx.cpsr = context.Cpsr();
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::LoadContext(const ThreadContext32& ctx) {
|
||||
Dynarmic::A32::Context context;
|
||||
context.Regs() = ctx.cpu_registers;
|
||||
context.SetCpsr(ctx.cpsr);
|
||||
jit->LoadContext(context);
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::PrepareReschedule() {
|
||||
jit->HaltExecution();
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::ClearInstructionCache() {
|
||||
jit->ClearCache();
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_32::ClearExclusiveState() {}
|
||||
|
||||
void ARM_Dynarmic_32::PageTableChanged(Common::PageTable& page_table,
|
||||
std::size_t new_address_space_size_in_bits) {
|
||||
auto key = std::make_pair(&page_table, new_address_space_size_in_bits);
|
||||
auto iter = jit_cache.find(key);
|
||||
if (iter != jit_cache.end()) {
|
||||
jit = iter->second;
|
||||
return;
|
||||
}
|
||||
jit = MakeJit(page_table, new_address_space_size_in_bits);
|
||||
jit_cache.emplace(key, jit);
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
77
src/core/arm/dynarmic/arm_dynarmic_32.h
Normal file
77
src/core/arm/dynarmic/arm_dynarmic_32.h
Normal file
@@ -0,0 +1,77 @@
|
||||
// Copyright 2020 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <dynarmic/A32/a32.h>
|
||||
#include <dynarmic/A64/a64.h>
|
||||
#include <dynarmic/A64/exclusive_monitor.h>
|
||||
#include "common/common_types.h"
|
||||
#include "common/hash.h"
|
||||
#include "core/arm/arm_interface.h"
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
|
||||
namespace Memory {
|
||||
class Memory;
|
||||
}
|
||||
|
||||
namespace Core {
|
||||
|
||||
class DynarmicCallbacks32;
|
||||
class DynarmicExclusiveMonitor;
|
||||
class System;
|
||||
|
||||
class ARM_Dynarmic_32 final : public ARM_Interface {
|
||||
public:
|
||||
ARM_Dynarmic_32(System& system, ExclusiveMonitor& exclusive_monitor, std::size_t core_index);
|
||||
~ARM_Dynarmic_32() override;
|
||||
|
||||
void SetPC(u64 pc) override;
|
||||
u64 GetPC() const override;
|
||||
u64 GetReg(int index) const override;
|
||||
void SetReg(int index, u64 value) override;
|
||||
u128 GetVectorReg(int index) const override;
|
||||
void SetVectorReg(int index, u128 value) override;
|
||||
u32 GetPSTATE() const override;
|
||||
void SetPSTATE(u32 pstate) override;
|
||||
void Run() override;
|
||||
void Step() override;
|
||||
VAddr GetTlsAddress() const override;
|
||||
void SetTlsAddress(VAddr address) override;
|
||||
void SetTPIDR_EL0(u64 value) override;
|
||||
u64 GetTPIDR_EL0() const override;
|
||||
|
||||
void SaveContext(ThreadContext32& ctx) override;
|
||||
void SaveContext(ThreadContext64& ctx) override {}
|
||||
void LoadContext(const ThreadContext32& ctx) override;
|
||||
void LoadContext(const ThreadContext64& ctx) override {}
|
||||
|
||||
void PrepareReschedule() override;
|
||||
void ClearExclusiveState() override;
|
||||
|
||||
void ClearInstructionCache() override;
|
||||
void PageTableChanged(Common::PageTable& new_page_table,
|
||||
std::size_t new_address_space_size_in_bits) override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<Dynarmic::A32::Jit> MakeJit(Common::PageTable& page_table,
|
||||
std::size_t address_space_bits) const;
|
||||
|
||||
using JitCacheKey = std::pair<Common::PageTable*, std::size_t>;
|
||||
using JitCacheType =
|
||||
std::unordered_map<JitCacheKey, std::shared_ptr<Dynarmic::A32::Jit>, Common::PairHash>;
|
||||
|
||||
friend class DynarmicCallbacks32;
|
||||
std::unique_ptr<DynarmicCallbacks32> cb;
|
||||
JitCacheType jit_cache;
|
||||
std::shared_ptr<Dynarmic::A32::Jit> jit;
|
||||
std::size_t core_index;
|
||||
DynarmicExclusiveMonitor& exclusive_monitor;
|
||||
std::array<u32, 84> CP15_regs{};
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
@@ -8,13 +8,15 @@
|
||||
#include <dynarmic/A64/config.h>
|
||||
#include "common/logging/log.h"
|
||||
#include "common/microprofile.h"
|
||||
#include "core/arm/dynarmic/arm_dynarmic.h"
|
||||
#include "core/arm/dynarmic/arm_dynarmic_64.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_cpu.h"
|
||||
#include "core/core_manager.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core_timing_util.h"
|
||||
#include "core/gdbstub/gdbstub.h"
|
||||
#include "core/hardware_properties.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
#include "core/hle/kernel/scheduler.h"
|
||||
#include "core/hle/kernel/svc.h"
|
||||
#include "core/hle/kernel/vm_manager.h"
|
||||
#include "core/memory.h"
|
||||
@@ -23,51 +25,53 @@ namespace Core {
|
||||
|
||||
using Vector = Dynarmic::A64::Vector;
|
||||
|
||||
class ARM_Dynarmic_Callbacks : public Dynarmic::A64::UserCallbacks {
|
||||
class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
|
||||
public:
|
||||
explicit ARM_Dynarmic_Callbacks(ARM_Dynarmic& parent) : parent(parent) {}
|
||||
explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent) : parent(parent) {}
|
||||
|
||||
u8 MemoryRead8(u64 vaddr) override {
|
||||
return Memory::Read8(vaddr);
|
||||
return parent.system.Memory().Read8(vaddr);
|
||||
}
|
||||
u16 MemoryRead16(u64 vaddr) override {
|
||||
return Memory::Read16(vaddr);
|
||||
return parent.system.Memory().Read16(vaddr);
|
||||
}
|
||||
u32 MemoryRead32(u64 vaddr) override {
|
||||
return Memory::Read32(vaddr);
|
||||
return parent.system.Memory().Read32(vaddr);
|
||||
}
|
||||
u64 MemoryRead64(u64 vaddr) override {
|
||||
return Memory::Read64(vaddr);
|
||||
return parent.system.Memory().Read64(vaddr);
|
||||
}
|
||||
Vector MemoryRead128(u64 vaddr) override {
|
||||
return {Memory::Read64(vaddr), Memory::Read64(vaddr + 8)};
|
||||
auto& memory = parent.system.Memory();
|
||||
return {memory.Read64(vaddr), memory.Read64(vaddr + 8)};
|
||||
}
|
||||
|
||||
void MemoryWrite8(u64 vaddr, u8 value) override {
|
||||
Memory::Write8(vaddr, value);
|
||||
parent.system.Memory().Write8(vaddr, value);
|
||||
}
|
||||
void MemoryWrite16(u64 vaddr, u16 value) override {
|
||||
Memory::Write16(vaddr, value);
|
||||
parent.system.Memory().Write16(vaddr, value);
|
||||
}
|
||||
void MemoryWrite32(u64 vaddr, u32 value) override {
|
||||
Memory::Write32(vaddr, value);
|
||||
parent.system.Memory().Write32(vaddr, value);
|
||||
}
|
||||
void MemoryWrite64(u64 vaddr, u64 value) override {
|
||||
Memory::Write64(vaddr, value);
|
||||
parent.system.Memory().Write64(vaddr, value);
|
||||
}
|
||||
void MemoryWrite128(u64 vaddr, Vector value) override {
|
||||
Memory::Write64(vaddr, value[0]);
|
||||
Memory::Write64(vaddr + 8, value[1]);
|
||||
auto& memory = parent.system.Memory();
|
||||
memory.Write64(vaddr, value[0]);
|
||||
memory.Write64(vaddr + 8, value[1]);
|
||||
}
|
||||
|
||||
void InterpreterFallback(u64 pc, std::size_t num_instructions) override {
|
||||
LOG_INFO(Core_ARM, "Unicorn fallback @ 0x{:X} for {} instructions (instr = {:08X})", pc,
|
||||
num_instructions, MemoryReadCode(pc));
|
||||
|
||||
ARM_Interface::ThreadContext ctx;
|
||||
ARM_Interface::ThreadContext64 ctx;
|
||||
parent.SaveContext(ctx);
|
||||
parent.inner_unicorn.LoadContext(ctx);
|
||||
parent.inner_unicorn.ExecuteInstructions(static_cast<int>(num_instructions));
|
||||
parent.inner_unicorn.ExecuteInstructions(num_instructions);
|
||||
parent.inner_unicorn.SaveContext(ctx);
|
||||
parent.LoadContext(ctx);
|
||||
num_interpreted_instructions += num_instructions;
|
||||
@@ -85,8 +89,8 @@ public:
|
||||
if (GDBStub::IsServerEnabled()) {
|
||||
parent.jit->HaltExecution();
|
||||
parent.SetPC(pc);
|
||||
Kernel::Thread* thread = Kernel::GetCurrentThread();
|
||||
parent.SaveContext(thread->GetContext());
|
||||
Kernel::Thread* const thread = parent.system.CurrentScheduler().GetCurrentThread();
|
||||
parent.SaveContext(thread->GetContext64());
|
||||
GDBStub::Break();
|
||||
GDBStub::SendTrap(thread, 5);
|
||||
return;
|
||||
@@ -122,14 +126,14 @@ public:
|
||||
return Timing::CpuCyclesToClockCycles(parent.system.CoreTiming().GetTicks());
|
||||
}
|
||||
|
||||
ARM_Dynarmic& parent;
|
||||
ARM_Dynarmic_64& parent;
|
||||
std::size_t num_interpreted_instructions = 0;
|
||||
u64 tpidrro_el0 = 0;
|
||||
u64 tpidr_el0 = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit(Common::PageTable& page_table,
|
||||
std::size_t address_space_bits) const {
|
||||
std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable& page_table,
|
||||
std::size_t address_space_bits) const {
|
||||
Dynarmic::A64::UserConfig config;
|
||||
|
||||
// Callbacks
|
||||
@@ -139,6 +143,7 @@ std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit(Common::PageTable& pag
|
||||
config.page_table = reinterpret_cast<void**>(page_table.pointers.data());
|
||||
config.page_table_address_space_bits = address_space_bits;
|
||||
config.silently_mirror_page_table = false;
|
||||
config.absolute_offset_page_table = true;
|
||||
|
||||
// Multi-process state
|
||||
config.processor_id = core_index;
|
||||
@@ -149,83 +154,84 @@ std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit(Common::PageTable& pag
|
||||
config.tpidr_el0 = &cb->tpidr_el0;
|
||||
config.dczid_el0 = 4;
|
||||
config.ctr_el0 = 0x8444c004;
|
||||
config.cntfrq_el0 = Timing::CNTFREQ;
|
||||
config.cntfrq_el0 = Hardware::CNTFREQ;
|
||||
|
||||
// Unpredictable instructions
|
||||
config.define_unpredictable_behaviour = true;
|
||||
|
||||
return std::make_unique<Dynarmic::A64::Jit>(config);
|
||||
return std::make_shared<Dynarmic::A64::Jit>(config);
|
||||
}
|
||||
|
||||
MICROPROFILE_DEFINE(ARM_Jit_Dynarmic, "ARM JIT", "Dynarmic", MP_RGB(255, 64, 64));
|
||||
MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_64, "ARM JIT", "Dynarmic", MP_RGB(255, 64, 64));
|
||||
|
||||
void ARM_Dynarmic::Run() {
|
||||
MICROPROFILE_SCOPE(ARM_Jit_Dynarmic);
|
||||
void ARM_Dynarmic_64::Run() {
|
||||
MICROPROFILE_SCOPE(ARM_Jit_Dynarmic_64);
|
||||
|
||||
jit->Run();
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::Step() {
|
||||
void ARM_Dynarmic_64::Step() {
|
||||
cb->InterpreterFallback(jit->GetPC(), 1);
|
||||
}
|
||||
|
||||
ARM_Dynarmic::ARM_Dynarmic(System& system, ExclusiveMonitor& exclusive_monitor,
|
||||
std::size_t core_index)
|
||||
: cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), inner_unicorn{system},
|
||||
core_index{core_index}, system{system},
|
||||
exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {}
|
||||
ARM_Dynarmic_64::ARM_Dynarmic_64(System& system, ExclusiveMonitor& exclusive_monitor,
|
||||
std::size_t core_index)
|
||||
: ARM_Interface{system},
|
||||
cb(std::make_unique<DynarmicCallbacks64>(*this)), inner_unicorn{system},
|
||||
core_index{core_index}, exclusive_monitor{
|
||||
dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {}
|
||||
|
||||
ARM_Dynarmic::~ARM_Dynarmic() = default;
|
||||
ARM_Dynarmic_64::~ARM_Dynarmic_64() = default;
|
||||
|
||||
void ARM_Dynarmic::SetPC(u64 pc) {
|
||||
void ARM_Dynarmic_64::SetPC(u64 pc) {
|
||||
jit->SetPC(pc);
|
||||
}
|
||||
|
||||
u64 ARM_Dynarmic::GetPC() const {
|
||||
u64 ARM_Dynarmic_64::GetPC() const {
|
||||
return jit->GetPC();
|
||||
}
|
||||
|
||||
u64 ARM_Dynarmic::GetReg(int index) const {
|
||||
u64 ARM_Dynarmic_64::GetReg(int index) const {
|
||||
return jit->GetRegister(index);
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::SetReg(int index, u64 value) {
|
||||
void ARM_Dynarmic_64::SetReg(int index, u64 value) {
|
||||
jit->SetRegister(index, value);
|
||||
}
|
||||
|
||||
u128 ARM_Dynarmic::GetVectorReg(int index) const {
|
||||
u128 ARM_Dynarmic_64::GetVectorReg(int index) const {
|
||||
return jit->GetVector(index);
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::SetVectorReg(int index, u128 value) {
|
||||
void ARM_Dynarmic_64::SetVectorReg(int index, u128 value) {
|
||||
jit->SetVector(index, value);
|
||||
}
|
||||
|
||||
u32 ARM_Dynarmic::GetPSTATE() const {
|
||||
u32 ARM_Dynarmic_64::GetPSTATE() const {
|
||||
return jit->GetPstate();
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::SetPSTATE(u32 pstate) {
|
||||
void ARM_Dynarmic_64::SetPSTATE(u32 pstate) {
|
||||
jit->SetPstate(pstate);
|
||||
}
|
||||
|
||||
u64 ARM_Dynarmic::GetTlsAddress() const {
|
||||
u64 ARM_Dynarmic_64::GetTlsAddress() const {
|
||||
return cb->tpidrro_el0;
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::SetTlsAddress(VAddr address) {
|
||||
void ARM_Dynarmic_64::SetTlsAddress(VAddr address) {
|
||||
cb->tpidrro_el0 = address;
|
||||
}
|
||||
|
||||
u64 ARM_Dynarmic::GetTPIDR_EL0() const {
|
||||
u64 ARM_Dynarmic_64::GetTPIDR_EL0() const {
|
||||
return cb->tpidr_el0;
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::SetTPIDR_EL0(u64 value) {
|
||||
void ARM_Dynarmic_64::SetTPIDR_EL0(u64 value) {
|
||||
cb->tpidr_el0 = value;
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::SaveContext(ThreadContext& ctx) {
|
||||
void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) {
|
||||
ctx.cpu_registers = jit->GetRegisters();
|
||||
ctx.sp = jit->GetSP();
|
||||
ctx.pc = jit->GetPC();
|
||||
@@ -236,7 +242,7 @@ void ARM_Dynarmic::SaveContext(ThreadContext& ctx) {
|
||||
ctx.tpidr = cb->tpidr_el0;
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::LoadContext(const ThreadContext& ctx) {
|
||||
void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) {
|
||||
jit->SetRegisters(ctx.cpu_registers);
|
||||
jit->SetSP(ctx.sp);
|
||||
jit->SetPC(ctx.pc);
|
||||
@@ -247,24 +253,33 @@ void ARM_Dynarmic::LoadContext(const ThreadContext& ctx) {
|
||||
SetTPIDR_EL0(ctx.tpidr);
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::PrepareReschedule() {
|
||||
void ARM_Dynarmic_64::PrepareReschedule() {
|
||||
jit->HaltExecution();
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::ClearInstructionCache() {
|
||||
void ARM_Dynarmic_64::ClearInstructionCache() {
|
||||
jit->ClearCache();
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::ClearExclusiveState() {
|
||||
void ARM_Dynarmic_64::ClearExclusiveState() {
|
||||
jit->ClearExclusiveState();
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::PageTableChanged(Common::PageTable& page_table,
|
||||
std::size_t new_address_space_size_in_bits) {
|
||||
void ARM_Dynarmic_64::PageTableChanged(Common::PageTable& page_table,
|
||||
std::size_t new_address_space_size_in_bits) {
|
||||
auto key = std::make_pair(&page_table, new_address_space_size_in_bits);
|
||||
auto iter = jit_cache.find(key);
|
||||
if (iter != jit_cache.end()) {
|
||||
jit = iter->second;
|
||||
return;
|
||||
}
|
||||
jit = MakeJit(page_table, new_address_space_size_in_bits);
|
||||
jit_cache.emplace(key, jit);
|
||||
}
|
||||
|
||||
DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(std::size_t core_count) : monitor(core_count) {}
|
||||
DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(Memory::Memory& memory, std::size_t core_count)
|
||||
: monitor(core_count), memory{memory} {}
|
||||
|
||||
DynarmicExclusiveMonitor::~DynarmicExclusiveMonitor() = default;
|
||||
|
||||
void DynarmicExclusiveMonitor::SetExclusive(std::size_t core_index, VAddr addr) {
|
||||
@@ -277,29 +292,28 @@ void DynarmicExclusiveMonitor::ClearExclusive() {
|
||||
}
|
||||
|
||||
bool DynarmicExclusiveMonitor::ExclusiveWrite8(std::size_t core_index, VAddr vaddr, u8 value) {
|
||||
return monitor.DoExclusiveOperation(core_index, vaddr, 1,
|
||||
[&] { Memory::Write8(vaddr, value); });
|
||||
return monitor.DoExclusiveOperation(core_index, vaddr, 1, [&] { memory.Write8(vaddr, value); });
|
||||
}
|
||||
|
||||
bool DynarmicExclusiveMonitor::ExclusiveWrite16(std::size_t core_index, VAddr vaddr, u16 value) {
|
||||
return monitor.DoExclusiveOperation(core_index, vaddr, 2,
|
||||
[&] { Memory::Write16(vaddr, value); });
|
||||
[&] { memory.Write16(vaddr, value); });
|
||||
}
|
||||
|
||||
bool DynarmicExclusiveMonitor::ExclusiveWrite32(std::size_t core_index, VAddr vaddr, u32 value) {
|
||||
return monitor.DoExclusiveOperation(core_index, vaddr, 4,
|
||||
[&] { Memory::Write32(vaddr, value); });
|
||||
[&] { memory.Write32(vaddr, value); });
|
||||
}
|
||||
|
||||
bool DynarmicExclusiveMonitor::ExclusiveWrite64(std::size_t core_index, VAddr vaddr, u64 value) {
|
||||
return monitor.DoExclusiveOperation(core_index, vaddr, 8,
|
||||
[&] { Memory::Write64(vaddr, value); });
|
||||
[&] { memory.Write64(vaddr, value); });
|
||||
}
|
||||
|
||||
bool DynarmicExclusiveMonitor::ExclusiveWrite128(std::size_t core_index, VAddr vaddr, u128 value) {
|
||||
return monitor.DoExclusiveOperation(core_index, vaddr, 16, [&] {
|
||||
Memory::Write64(vaddr + 0, value[0]);
|
||||
Memory::Write64(vaddr + 8, value[1]);
|
||||
memory.Write64(vaddr + 0, value[0]);
|
||||
memory.Write64(vaddr + 8, value[1]);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,23 +5,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <dynarmic/A64/a64.h>
|
||||
#include <dynarmic/A64/exclusive_monitor.h>
|
||||
#include "common/common_types.h"
|
||||
#include "common/hash.h"
|
||||
#include "core/arm/arm_interface.h"
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/arm/unicorn/arm_unicorn.h"
|
||||
|
||||
namespace Memory {
|
||||
class Memory;
|
||||
}
|
||||
|
||||
namespace Core {
|
||||
|
||||
class ARM_Dynarmic_Callbacks;
|
||||
class DynarmicCallbacks64;
|
||||
class DynarmicExclusiveMonitor;
|
||||
class System;
|
||||
|
||||
class ARM_Dynarmic final : public ARM_Interface {
|
||||
class ARM_Dynarmic_64 final : public ARM_Interface {
|
||||
public:
|
||||
ARM_Dynarmic(System& system, ExclusiveMonitor& exclusive_monitor, std::size_t core_index);
|
||||
~ARM_Dynarmic() override;
|
||||
ARM_Dynarmic_64(System& system, ExclusiveMonitor& exclusive_monitor, std::size_t core_index);
|
||||
~ARM_Dynarmic_64() override;
|
||||
|
||||
void SetPC(u64 pc) override;
|
||||
u64 GetPC() const override;
|
||||
@@ -38,8 +45,10 @@ public:
|
||||
void SetTPIDR_EL0(u64 value) override;
|
||||
u64 GetTPIDR_EL0() const override;
|
||||
|
||||
void SaveContext(ThreadContext& ctx) override;
|
||||
void LoadContext(const ThreadContext& ctx) override;
|
||||
void SaveContext(ThreadContext32& ctx) override {}
|
||||
void SaveContext(ThreadContext64& ctx) override;
|
||||
void LoadContext(const ThreadContext32& ctx) override {}
|
||||
void LoadContext(const ThreadContext64& ctx) override;
|
||||
|
||||
void PrepareReschedule() override;
|
||||
void ClearExclusiveState() override;
|
||||
@@ -49,22 +58,26 @@ public:
|
||||
std::size_t new_address_space_size_in_bits) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable& page_table,
|
||||
std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable& page_table,
|
||||
std::size_t address_space_bits) const;
|
||||
|
||||
friend class ARM_Dynarmic_Callbacks;
|
||||
std::unique_ptr<ARM_Dynarmic_Callbacks> cb;
|
||||
std::unique_ptr<Dynarmic::A64::Jit> jit;
|
||||
using JitCacheKey = std::pair<Common::PageTable*, std::size_t>;
|
||||
using JitCacheType =
|
||||
std::unordered_map<JitCacheKey, std::shared_ptr<Dynarmic::A64::Jit>, Common::PairHash>;
|
||||
|
||||
friend class DynarmicCallbacks64;
|
||||
std::unique_ptr<DynarmicCallbacks64> cb;
|
||||
JitCacheType jit_cache;
|
||||
std::shared_ptr<Dynarmic::A64::Jit> jit;
|
||||
ARM_Unicorn inner_unicorn;
|
||||
|
||||
std::size_t core_index;
|
||||
System& system;
|
||||
DynarmicExclusiveMonitor& exclusive_monitor;
|
||||
};
|
||||
|
||||
class DynarmicExclusiveMonitor final : public ExclusiveMonitor {
|
||||
public:
|
||||
explicit DynarmicExclusiveMonitor(std::size_t core_count);
|
||||
explicit DynarmicExclusiveMonitor(Memory::Memory& memory, std::size_t core_count);
|
||||
~DynarmicExclusiveMonitor() override;
|
||||
|
||||
void SetExclusive(std::size_t core_index, VAddr addr) override;
|
||||
@@ -77,8 +90,9 @@ public:
|
||||
bool ExclusiveWrite128(std::size_t core_index, VAddr vaddr, u128 value) override;
|
||||
|
||||
private:
|
||||
friend class ARM_Dynarmic;
|
||||
friend class ARM_Dynarmic_64;
|
||||
Dynarmic::A64::ExclusiveMonitor monitor;
|
||||
Memory::Memory& memory;
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
80
src/core/arm/dynarmic/arm_dynarmic_cp15.cpp
Normal file
80
src/core/arm/dynarmic/arm_dynarmic_cp15.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
// Copyright 2017 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/dynarmic/arm_dynarmic_cp15.h"
|
||||
|
||||
using Callback = Dynarmic::A32::Coprocessor::Callback;
|
||||
using CallbackOrAccessOneWord = Dynarmic::A32::Coprocessor::CallbackOrAccessOneWord;
|
||||
using CallbackOrAccessTwoWords = Dynarmic::A32::Coprocessor::CallbackOrAccessTwoWords;
|
||||
|
||||
std::optional<Callback> DynarmicCP15::CompileInternalOperation(bool two, unsigned opc1,
|
||||
CoprocReg CRd, CoprocReg CRn,
|
||||
CoprocReg CRm, unsigned opc2) {
|
||||
return {};
|
||||
}
|
||||
|
||||
CallbackOrAccessOneWord DynarmicCP15::CompileSendOneWord(bool two, unsigned opc1, CoprocReg CRn,
|
||||
CoprocReg CRm, unsigned opc2) {
|
||||
// TODO(merry): Privileged CP15 registers
|
||||
|
||||
if (!two && CRn == CoprocReg::C7 && opc1 == 0 && CRm == CoprocReg::C5 && opc2 == 4) {
|
||||
// This is a dummy write, we ignore the value written here.
|
||||
return &CP15[static_cast<std::size_t>(CP15Register::CP15_FLUSH_PREFETCH_BUFFER)];
|
||||
}
|
||||
|
||||
if (!two && CRn == CoprocReg::C7 && opc1 == 0 && CRm == CoprocReg::C10) {
|
||||
switch (opc2) {
|
||||
case 4:
|
||||
// This is a dummy write, we ignore the value written here.
|
||||
return &CP15[static_cast<std::size_t>(CP15Register::CP15_DATA_SYNC_BARRIER)];
|
||||
case 5:
|
||||
// This is a dummy write, we ignore the value written here.
|
||||
return &CP15[static_cast<std::size_t>(CP15Register::CP15_DATA_MEMORY_BARRIER)];
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
if (!two && CRn == CoprocReg::C13 && opc1 == 0 && CRm == CoprocReg::C0 && opc2 == 2) {
|
||||
return &CP15[static_cast<std::size_t>(CP15Register::CP15_THREAD_UPRW)];
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
CallbackOrAccessTwoWords DynarmicCP15::CompileSendTwoWords(bool two, unsigned opc, CoprocReg CRm) {
|
||||
return {};
|
||||
}
|
||||
|
||||
CallbackOrAccessOneWord DynarmicCP15::CompileGetOneWord(bool two, unsigned opc1, CoprocReg CRn,
|
||||
CoprocReg CRm, unsigned opc2) {
|
||||
// TODO(merry): Privileged CP15 registers
|
||||
|
||||
if (!two && CRn == CoprocReg::C13 && opc1 == 0 && CRm == CoprocReg::C0) {
|
||||
switch (opc2) {
|
||||
case 2:
|
||||
return &CP15[static_cast<std::size_t>(CP15Register::CP15_THREAD_UPRW)];
|
||||
case 3:
|
||||
return &CP15[static_cast<std::size_t>(CP15Register::CP15_THREAD_URO)];
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
CallbackOrAccessTwoWords DynarmicCP15::CompileGetTwoWords(bool two, unsigned opc, CoprocReg CRm) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::optional<Callback> DynarmicCP15::CompileLoadWords(bool two, bool long_transfer, CoprocReg CRd,
|
||||
std::optional<u8> option) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::optional<Callback> DynarmicCP15::CompileStoreWords(bool two, bool long_transfer, CoprocReg CRd,
|
||||
std::optional<u8> option) {
|
||||
return {};
|
||||
}
|
||||
152
src/core/arm/dynarmic/arm_dynarmic_cp15.h
Normal file
152
src/core/arm/dynarmic/arm_dynarmic_cp15.h
Normal file
@@ -0,0 +1,152 @@
|
||||
// Copyright 2017 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include <dynarmic/A32/coprocessor.h>
|
||||
#include "common/common_types.h"
|
||||
|
||||
enum class CP15Register {
|
||||
// c0 - Information registers
|
||||
CP15_MAIN_ID,
|
||||
CP15_CACHE_TYPE,
|
||||
CP15_TCM_STATUS,
|
||||
CP15_TLB_TYPE,
|
||||
CP15_CPU_ID,
|
||||
CP15_PROCESSOR_FEATURE_0,
|
||||
CP15_PROCESSOR_FEATURE_1,
|
||||
CP15_DEBUG_FEATURE_0,
|
||||
CP15_AUXILIARY_FEATURE_0,
|
||||
CP15_MEMORY_MODEL_FEATURE_0,
|
||||
CP15_MEMORY_MODEL_FEATURE_1,
|
||||
CP15_MEMORY_MODEL_FEATURE_2,
|
||||
CP15_MEMORY_MODEL_FEATURE_3,
|
||||
CP15_ISA_FEATURE_0,
|
||||
CP15_ISA_FEATURE_1,
|
||||
CP15_ISA_FEATURE_2,
|
||||
CP15_ISA_FEATURE_3,
|
||||
CP15_ISA_FEATURE_4,
|
||||
|
||||
// c1 - Control registers
|
||||
CP15_CONTROL,
|
||||
CP15_AUXILIARY_CONTROL,
|
||||
CP15_COPROCESSOR_ACCESS_CONTROL,
|
||||
|
||||
// c2 - Translation table registers
|
||||
CP15_TRANSLATION_BASE_TABLE_0,
|
||||
CP15_TRANSLATION_BASE_TABLE_1,
|
||||
CP15_TRANSLATION_BASE_CONTROL,
|
||||
CP15_DOMAIN_ACCESS_CONTROL,
|
||||
CP15_RESERVED,
|
||||
|
||||
// c5 - Fault status registers
|
||||
CP15_FAULT_STATUS,
|
||||
CP15_INSTR_FAULT_STATUS,
|
||||
CP15_COMBINED_DATA_FSR = CP15_FAULT_STATUS,
|
||||
CP15_INST_FSR,
|
||||
|
||||
// c6 - Fault Address registers
|
||||
CP15_FAULT_ADDRESS,
|
||||
CP15_COMBINED_DATA_FAR = CP15_FAULT_ADDRESS,
|
||||
CP15_WFAR,
|
||||
CP15_IFAR,
|
||||
|
||||
// c7 - Cache operation registers
|
||||
CP15_WAIT_FOR_INTERRUPT,
|
||||
CP15_PHYS_ADDRESS,
|
||||
CP15_INVALIDATE_INSTR_CACHE,
|
||||
CP15_INVALIDATE_INSTR_CACHE_USING_MVA,
|
||||
CP15_INVALIDATE_INSTR_CACHE_USING_INDEX,
|
||||
CP15_FLUSH_PREFETCH_BUFFER,
|
||||
CP15_FLUSH_BRANCH_TARGET_CACHE,
|
||||
CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY,
|
||||
CP15_INVALIDATE_DATA_CACHE,
|
||||
CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA,
|
||||
CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX,
|
||||
CP15_INVALIDATE_DATA_AND_INSTR_CACHE,
|
||||
CP15_CLEAN_DATA_CACHE,
|
||||
CP15_CLEAN_DATA_CACHE_LINE_USING_MVA,
|
||||
CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX,
|
||||
CP15_DATA_SYNC_BARRIER,
|
||||
CP15_DATA_MEMORY_BARRIER,
|
||||
CP15_CLEAN_AND_INVALIDATE_DATA_CACHE,
|
||||
CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA,
|
||||
CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX,
|
||||
|
||||
// c8 - TLB operations
|
||||
CP15_INVALIDATE_ITLB,
|
||||
CP15_INVALIDATE_ITLB_SINGLE_ENTRY,
|
||||
CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH,
|
||||
CP15_INVALIDATE_ITLB_ENTRY_ON_MVA,
|
||||
CP15_INVALIDATE_DTLB,
|
||||
CP15_INVALIDATE_DTLB_SINGLE_ENTRY,
|
||||
CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH,
|
||||
CP15_INVALIDATE_DTLB_ENTRY_ON_MVA,
|
||||
CP15_INVALIDATE_UTLB,
|
||||
CP15_INVALIDATE_UTLB_SINGLE_ENTRY,
|
||||
CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH,
|
||||
CP15_INVALIDATE_UTLB_ENTRY_ON_MVA,
|
||||
|
||||
// c9 - Data cache lockdown register
|
||||
CP15_DATA_CACHE_LOCKDOWN,
|
||||
|
||||
// c10 - TLB/Memory map registers
|
||||
CP15_TLB_LOCKDOWN,
|
||||
CP15_PRIMARY_REGION_REMAP,
|
||||
CP15_NORMAL_REGION_REMAP,
|
||||
|
||||
// c13 - Thread related registers
|
||||
CP15_PID,
|
||||
CP15_CONTEXT_ID,
|
||||
CP15_THREAD_UPRW, // Thread ID register - User/Privileged Read/Write
|
||||
CP15_THREAD_URO, // Thread ID register - User Read Only (Privileged R/W)
|
||||
CP15_THREAD_PRW, // Thread ID register - Privileged R/W only.
|
||||
|
||||
// c15 - Performance and TLB lockdown registers
|
||||
CP15_PERFORMANCE_MONITOR_CONTROL,
|
||||
CP15_CYCLE_COUNTER,
|
||||
CP15_COUNT_0,
|
||||
CP15_COUNT_1,
|
||||
CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY,
|
||||
CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY,
|
||||
CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS,
|
||||
CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS,
|
||||
CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE,
|
||||
CP15_TLB_DEBUG_CONTROL,
|
||||
|
||||
// Skyeye defined
|
||||
CP15_TLB_FAULT_ADDR,
|
||||
CP15_TLB_FAULT_STATUS,
|
||||
|
||||
// Not an actual register.
|
||||
// All registers should be defined above this.
|
||||
CP15_REGISTER_COUNT,
|
||||
};
|
||||
|
||||
class DynarmicCP15 final : public Dynarmic::A32::Coprocessor {
|
||||
public:
|
||||
using CoprocReg = Dynarmic::A32::CoprocReg;
|
||||
|
||||
explicit DynarmicCP15(u32* cp15) : CP15(cp15){};
|
||||
|
||||
std::optional<Callback> CompileInternalOperation(bool two, unsigned opc1, CoprocReg CRd,
|
||||
CoprocReg CRn, CoprocReg CRm,
|
||||
unsigned opc2) override;
|
||||
CallbackOrAccessOneWord CompileSendOneWord(bool two, unsigned opc1, CoprocReg CRn,
|
||||
CoprocReg CRm, unsigned opc2) override;
|
||||
CallbackOrAccessTwoWords CompileSendTwoWords(bool two, unsigned opc, CoprocReg CRm) override;
|
||||
CallbackOrAccessOneWord CompileGetOneWord(bool two, unsigned opc1, CoprocReg CRn, CoprocReg CRm,
|
||||
unsigned opc2) override;
|
||||
CallbackOrAccessTwoWords CompileGetTwoWords(bool two, unsigned opc, CoprocReg CRm) override;
|
||||
std::optional<Callback> CompileLoadWords(bool two, bool long_transfer, CoprocReg CRd,
|
||||
std::optional<u8> option) override;
|
||||
std::optional<Callback> CompileStoreWords(bool two, bool long_transfer, CoprocReg CRd,
|
||||
std::optional<u8> option) override;
|
||||
|
||||
private:
|
||||
u32* CP15{};
|
||||
};
|
||||
@@ -2,10 +2,24 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
#include "core/arm/dynarmic/arm_dynarmic_64.h"
|
||||
#endif
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
namespace Core {
|
||||
|
||||
ExclusiveMonitor::~ExclusiveMonitor() = default;
|
||||
|
||||
std::unique_ptr<Core::ExclusiveMonitor> MakeExclusiveMonitor(Memory::Memory& memory,
|
||||
std::size_t num_cores) {
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
return std::make_unique<Core::DynarmicExclusiveMonitor>(memory, num_cores);
|
||||
#else
|
||||
// TODO(merry): Passthrough exclusive monitor
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
|
||||
@@ -4,8 +4,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Memory {
|
||||
class Memory;
|
||||
}
|
||||
|
||||
namespace Core {
|
||||
|
||||
class ExclusiveMonitor {
|
||||
@@ -22,4 +28,7 @@ public:
|
||||
virtual bool ExclusiveWrite128(std::size_t core_index, VAddr vaddr, u128 value) = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<Core::ExclusiveMonitor> MakeExclusiveMonitor(Memory::Memory& memory,
|
||||
std::size_t num_cores);
|
||||
|
||||
} // namespace Core
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "core/arm/unicorn/arm_unicorn.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/scheduler.h"
|
||||
#include "core/hle/kernel/svc.h"
|
||||
|
||||
namespace Core {
|
||||
@@ -52,7 +53,7 @@ static bool UnmappedMemoryHook(uc_engine* uc, uc_mem_type type, u64 addr, int si
|
||||
void* user_data) {
|
||||
auto* const system = static_cast<System*>(user_data);
|
||||
|
||||
ARM_Interface::ThreadContext ctx{};
|
||||
ARM_Interface::ThreadContext64 ctx{};
|
||||
system->CurrentArmInterface().SaveContext(ctx);
|
||||
ASSERT_MSG(false, "Attempted to read from unmapped memory: 0x{:X}, pc=0x{:X}, lr=0x{:X}", addr,
|
||||
ctx.pc, ctx.cpu_registers[30]);
|
||||
@@ -60,17 +61,18 @@ static bool UnmappedMemoryHook(uc_engine* uc, uc_mem_type type, u64 addr, int si
|
||||
return false;
|
||||
}
|
||||
|
||||
ARM_Unicorn::ARM_Unicorn(System& system) : system{system} {
|
||||
ARM_Unicorn::ARM_Unicorn(System& system) : ARM_Interface{system} {
|
||||
CHECKED(uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc));
|
||||
|
||||
auto fpv = 3 << 20;
|
||||
CHECKED(uc_reg_write(uc, UC_ARM64_REG_CPACR_EL1, &fpv));
|
||||
|
||||
uc_hook hook{};
|
||||
CHECKED(uc_hook_add(uc, &hook, UC_HOOK_INTR, (void*)InterruptHook, this, 0, -1));
|
||||
CHECKED(uc_hook_add(uc, &hook, UC_HOOK_MEM_INVALID, (void*)UnmappedMemoryHook, &system, 0, -1));
|
||||
CHECKED(uc_hook_add(uc, &hook, UC_HOOK_INTR, (void*)InterruptHook, this, 0, UINT64_MAX));
|
||||
CHECKED(uc_hook_add(uc, &hook, UC_HOOK_MEM_INVALID, (void*)UnmappedMemoryHook, &system, 0,
|
||||
UINT64_MAX));
|
||||
if (GDBStub::IsServerEnabled()) {
|
||||
CHECKED(uc_hook_add(uc, &hook, UC_HOOK_CODE, (void*)CodeHook, this, 0, -1));
|
||||
CHECKED(uc_hook_add(uc, &hook, UC_HOOK_CODE, (void*)CodeHook, this, 0, UINT64_MAX));
|
||||
last_bkpt_hit = false;
|
||||
}
|
||||
}
|
||||
@@ -154,9 +156,10 @@ void ARM_Unicorn::SetTPIDR_EL0(u64 value) {
|
||||
|
||||
void ARM_Unicorn::Run() {
|
||||
if (GDBStub::IsServerEnabled()) {
|
||||
ExecuteInstructions(std::max(4000000, 0));
|
||||
ExecuteInstructions(std::max(4000000U, 0U));
|
||||
} else {
|
||||
ExecuteInstructions(std::max(system.CoreTiming().GetDowncount(), s64{0}));
|
||||
ExecuteInstructions(
|
||||
std::max(std::size_t(system.CoreTiming().GetDowncount()), std::size_t{0}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,7 +169,7 @@ void ARM_Unicorn::Step() {
|
||||
|
||||
MICROPROFILE_DEFINE(ARM_Jit_Unicorn, "ARM JIT", "Unicorn", MP_RGB(255, 64, 64));
|
||||
|
||||
void ARM_Unicorn::ExecuteInstructions(int num_instructions) {
|
||||
void ARM_Unicorn::ExecuteInstructions(std::size_t num_instructions) {
|
||||
MICROPROFILE_SCOPE(ARM_Jit_Unicorn);
|
||||
CHECKED(uc_emu_start(uc, GetPC(), 1ULL << 63, 0, num_instructions));
|
||||
system.CoreTiming().AddTicks(num_instructions);
|
||||
@@ -175,8 +178,8 @@ void ARM_Unicorn::ExecuteInstructions(int num_instructions) {
|
||||
uc_reg_write(uc, UC_ARM64_REG_PC, &last_bkpt.address);
|
||||
}
|
||||
|
||||
Kernel::Thread* thread = Kernel::GetCurrentThread();
|
||||
SaveContext(thread->GetContext());
|
||||
Kernel::Thread* const thread = system.CurrentScheduler().GetCurrentThread();
|
||||
SaveContext(thread->GetContext64());
|
||||
if (last_bkpt_hit || GDBStub::IsMemoryBreak() || GDBStub::GetCpuStepFlag()) {
|
||||
last_bkpt_hit = false;
|
||||
GDBStub::Break();
|
||||
@@ -185,7 +188,7 @@ void ARM_Unicorn::ExecuteInstructions(int num_instructions) {
|
||||
}
|
||||
}
|
||||
|
||||
void ARM_Unicorn::SaveContext(ThreadContext& ctx) {
|
||||
void ARM_Unicorn::SaveContext(ThreadContext64& ctx) {
|
||||
int uregs[32];
|
||||
void* tregs[32];
|
||||
|
||||
@@ -212,7 +215,7 @@ void ARM_Unicorn::SaveContext(ThreadContext& ctx) {
|
||||
CHECKED(uc_reg_read_batch(uc, uregs, tregs, 32));
|
||||
}
|
||||
|
||||
void ARM_Unicorn::LoadContext(const ThreadContext& ctx) {
|
||||
void ARM_Unicorn::LoadContext(const ThreadContext64& ctx) {
|
||||
int uregs[32];
|
||||
void* tregs[32];
|
||||
|
||||
|
||||
@@ -30,22 +30,24 @@ public:
|
||||
void SetTlsAddress(VAddr address) override;
|
||||
void SetTPIDR_EL0(u64 value) override;
|
||||
u64 GetTPIDR_EL0() const override;
|
||||
void SaveContext(ThreadContext& ctx) override;
|
||||
void LoadContext(const ThreadContext& ctx) override;
|
||||
void PrepareReschedule() override;
|
||||
void ClearExclusiveState() override;
|
||||
void ExecuteInstructions(int num_instructions);
|
||||
void ExecuteInstructions(std::size_t num_instructions);
|
||||
void Run() override;
|
||||
void Step() override;
|
||||
void ClearInstructionCache() override;
|
||||
void PageTableChanged(Common::PageTable&, std::size_t) override {}
|
||||
void RecordBreak(GDBStub::BreakpointAddress bkpt);
|
||||
|
||||
void SaveContext(ThreadContext32& ctx) override {}
|
||||
void SaveContext(ThreadContext64& ctx) override;
|
||||
void LoadContext(const ThreadContext32& ctx) override {}
|
||||
void LoadContext(const ThreadContext64& ctx) override;
|
||||
|
||||
private:
|
||||
static void InterruptHook(uc_engine* uc, u32 int_no, void* user_data);
|
||||
|
||||
uc_engine* uc{};
|
||||
System& system;
|
||||
GDBStub::BreakpointAddress last_bkpt{};
|
||||
bool last_bkpt_hit = false;
|
||||
};
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
#include "common/string_util.h"
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_cpu.h"
|
||||
#include "core/core_manager.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/cpu_core_manager.h"
|
||||
#include "core/cpu_manager.h"
|
||||
#include "core/file_sys/bis_factory.h"
|
||||
#include "core/file_sys/card_image.h"
|
||||
#include "core/file_sys/mode.h"
|
||||
@@ -24,10 +24,12 @@
|
||||
#include "core/file_sys/sdmc_factory.h"
|
||||
#include "core/file_sys/vfs_concat.h"
|
||||
#include "core/file_sys/vfs_real.h"
|
||||
#include "core/frontend/scope_acquire_context.h"
|
||||
#include "core/gdbstub/gdbstub.h"
|
||||
#include "core/hardware_interrupt_manager.h"
|
||||
#include "core/hle/kernel/client_port.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/physical_core.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
#include "core/hle/kernel/scheduler.h"
|
||||
#include "core/hle/kernel/thread.h"
|
||||
@@ -39,13 +41,13 @@
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
#include "core/loader/loader.h"
|
||||
#include "core/memory.h"
|
||||
#include "core/memory/cheat_engine.h"
|
||||
#include "core/perf_stats.h"
|
||||
#include "core/reporter.h"
|
||||
#include "core/settings.h"
|
||||
#include "core/telemetry_session.h"
|
||||
#include "core/tools/freezer.h"
|
||||
#include "video_core/debug_utils/debug_utils.h"
|
||||
#include "video_core/renderer_base.h"
|
||||
#include "video_core/video_core.h"
|
||||
|
||||
@@ -112,17 +114,26 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
|
||||
}
|
||||
struct System::Impl {
|
||||
explicit Impl(System& system)
|
||||
: kernel{system}, fs_controller{system}, cpu_core_manager{system}, reporter{system},
|
||||
applet_manager{system} {}
|
||||
: kernel{system}, fs_controller{system}, memory{system},
|
||||
cpu_manager{system}, reporter{system}, applet_manager{system} {}
|
||||
|
||||
Cpu& CurrentCpuCore() {
|
||||
return cpu_core_manager.GetCurrentCore();
|
||||
CoreManager& CurrentCoreManager() {
|
||||
return cpu_manager.GetCurrentCoreManager();
|
||||
}
|
||||
|
||||
Kernel::PhysicalCore& CurrentPhysicalCore() {
|
||||
const auto index = cpu_manager.GetActiveCoreIndex();
|
||||
return kernel.PhysicalCore(index);
|
||||
}
|
||||
|
||||
Kernel::PhysicalCore& GetPhysicalCore(std::size_t index) {
|
||||
return kernel.PhysicalCore(index);
|
||||
}
|
||||
|
||||
ResultStatus RunLoop(bool tight_loop) {
|
||||
status = ResultStatus::Success;
|
||||
|
||||
cpu_core_manager.RunLoop(tight_loop);
|
||||
cpu_manager.RunLoop(tight_loop);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -131,8 +142,8 @@ struct System::Impl {
|
||||
LOG_DEBUG(HW_Memory, "initialized OK");
|
||||
|
||||
core_timing.Initialize();
|
||||
cpu_core_manager.Initialize();
|
||||
kernel.Initialize();
|
||||
cpu_manager.Initialize();
|
||||
|
||||
const auto current_time = std::chrono::duration_cast<std::chrono::seconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch());
|
||||
@@ -163,6 +174,7 @@ struct System::Impl {
|
||||
}
|
||||
interrupt_manager = std::make_unique<Core::Hardware::InterruptManager>(system);
|
||||
gpu_core = VideoCore::CreateGPU(system);
|
||||
renderer->Rasterizer().SetupDirtyFlags();
|
||||
|
||||
is_powered_on = true;
|
||||
exit_lock = false;
|
||||
@@ -174,6 +186,8 @@ struct System::Impl {
|
||||
|
||||
ResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
|
||||
const std::string& filepath) {
|
||||
Core::Frontend::ScopeAcquireContext acquire_context{emu_window};
|
||||
|
||||
app_loader = Loader::GetLoader(GetGameFileFromPath(virtual_filesystem, filepath));
|
||||
if (!app_loader) {
|
||||
LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
|
||||
@@ -205,7 +219,6 @@ struct System::Impl {
|
||||
// Main process has been loaded and been made current.
|
||||
// Begin GPU and CPU execution.
|
||||
gpu_core->Start();
|
||||
cpu_core_manager.StartThreads();
|
||||
|
||||
// Initialize cheat engine
|
||||
if (cheat_engine) {
|
||||
@@ -259,7 +272,9 @@ struct System::Impl {
|
||||
is_powered_on = false;
|
||||
exit_lock = false;
|
||||
|
||||
gpu_core->WaitIdle();
|
||||
if (gpu_core) {
|
||||
gpu_core->WaitIdle();
|
||||
}
|
||||
|
||||
// Shutdown emulation session
|
||||
renderer.reset();
|
||||
@@ -272,7 +287,7 @@ struct System::Impl {
|
||||
gpu_core.reset();
|
||||
|
||||
// Close all CPU/threading state
|
||||
cpu_core_manager.Shutdown();
|
||||
cpu_manager.Shutdown();
|
||||
|
||||
// Shutdown kernel and core timing
|
||||
kernel.Shutdown();
|
||||
@@ -340,9 +355,9 @@ struct System::Impl {
|
||||
std::unique_ptr<Loader::AppLoader> app_loader;
|
||||
std::unique_ptr<VideoCore::RendererBase> renderer;
|
||||
std::unique_ptr<Tegra::GPU> gpu_core;
|
||||
std::shared_ptr<Tegra::DebugContext> debug_context;
|
||||
std::unique_ptr<Core::Hardware::InterruptManager> interrupt_manager;
|
||||
CpuCoreManager cpu_core_manager;
|
||||
std::unique_ptr<Hardware::InterruptManager> interrupt_manager;
|
||||
Memory::Memory memory;
|
||||
CpuManager cpu_manager;
|
||||
bool is_powered_on = false;
|
||||
bool exit_lock = false;
|
||||
|
||||
@@ -377,12 +392,12 @@ struct System::Impl {
|
||||
System::System() : impl{std::make_unique<Impl>(*this)} {}
|
||||
System::~System() = default;
|
||||
|
||||
Cpu& System::CurrentCpuCore() {
|
||||
return impl->CurrentCpuCore();
|
||||
CoreManager& System::CurrentCoreManager() {
|
||||
return impl->CurrentCoreManager();
|
||||
}
|
||||
|
||||
const Cpu& System::CurrentCpuCore() const {
|
||||
return impl->CurrentCpuCore();
|
||||
const CoreManager& System::CurrentCoreManager() const {
|
||||
return impl->CurrentCoreManager();
|
||||
}
|
||||
|
||||
System::ResultStatus System::RunLoop(bool tight_loop) {
|
||||
@@ -394,7 +409,7 @@ System::ResultStatus System::SingleStep() {
|
||||
}
|
||||
|
||||
void System::InvalidateCpuInstructionCaches() {
|
||||
impl->cpu_core_manager.InvalidateAllInstructionCaches();
|
||||
impl->kernel.InvalidateAllInstructionCaches();
|
||||
}
|
||||
|
||||
System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath) {
|
||||
@@ -406,13 +421,11 @@ bool System::IsPoweredOn() const {
|
||||
}
|
||||
|
||||
void System::PrepareReschedule() {
|
||||
CurrentCpuCore().PrepareReschedule();
|
||||
impl->CurrentPhysicalCore().Stop();
|
||||
}
|
||||
|
||||
void System::PrepareReschedule(const u32 core_index) {
|
||||
if (core_index < GlobalScheduler().CpuCoresCount()) {
|
||||
CpuCore(core_index).PrepareReschedule();
|
||||
}
|
||||
impl->kernel.PrepareReschedule(core_index);
|
||||
}
|
||||
|
||||
PerfStatsResults System::GetAndResetPerfStats() {
|
||||
@@ -428,31 +441,31 @@ const TelemetrySession& System::TelemetrySession() const {
|
||||
}
|
||||
|
||||
ARM_Interface& System::CurrentArmInterface() {
|
||||
return CurrentCpuCore().ArmInterface();
|
||||
return impl->CurrentPhysicalCore().ArmInterface();
|
||||
}
|
||||
|
||||
const ARM_Interface& System::CurrentArmInterface() const {
|
||||
return CurrentCpuCore().ArmInterface();
|
||||
return impl->CurrentPhysicalCore().ArmInterface();
|
||||
}
|
||||
|
||||
std::size_t System::CurrentCoreIndex() const {
|
||||
return CurrentCpuCore().CoreIndex();
|
||||
return impl->cpu_manager.GetActiveCoreIndex();
|
||||
}
|
||||
|
||||
Kernel::Scheduler& System::CurrentScheduler() {
|
||||
return CurrentCpuCore().Scheduler();
|
||||
return impl->CurrentPhysicalCore().Scheduler();
|
||||
}
|
||||
|
||||
const Kernel::Scheduler& System::CurrentScheduler() const {
|
||||
return CurrentCpuCore().Scheduler();
|
||||
return impl->CurrentPhysicalCore().Scheduler();
|
||||
}
|
||||
|
||||
Kernel::Scheduler& System::Scheduler(std::size_t core_index) {
|
||||
return CpuCore(core_index).Scheduler();
|
||||
return impl->GetPhysicalCore(core_index).Scheduler();
|
||||
}
|
||||
|
||||
const Kernel::Scheduler& System::Scheduler(std::size_t core_index) const {
|
||||
return CpuCore(core_index).Scheduler();
|
||||
return impl->GetPhysicalCore(core_index).Scheduler();
|
||||
}
|
||||
|
||||
/// Gets the global scheduler
|
||||
@@ -474,28 +487,36 @@ const Kernel::Process* System::CurrentProcess() const {
|
||||
}
|
||||
|
||||
ARM_Interface& System::ArmInterface(std::size_t core_index) {
|
||||
return CpuCore(core_index).ArmInterface();
|
||||
return impl->GetPhysicalCore(core_index).ArmInterface();
|
||||
}
|
||||
|
||||
const ARM_Interface& System::ArmInterface(std::size_t core_index) const {
|
||||
return CpuCore(core_index).ArmInterface();
|
||||
return impl->GetPhysicalCore(core_index).ArmInterface();
|
||||
}
|
||||
|
||||
Cpu& System::CpuCore(std::size_t core_index) {
|
||||
return impl->cpu_core_manager.GetCore(core_index);
|
||||
CoreManager& System::GetCoreManager(std::size_t core_index) {
|
||||
return impl->cpu_manager.GetCoreManager(core_index);
|
||||
}
|
||||
|
||||
const Cpu& System::CpuCore(std::size_t core_index) const {
|
||||
const CoreManager& System::GetCoreManager(std::size_t core_index) const {
|
||||
ASSERT(core_index < NUM_CPU_CORES);
|
||||
return impl->cpu_core_manager.GetCore(core_index);
|
||||
return impl->cpu_manager.GetCoreManager(core_index);
|
||||
}
|
||||
|
||||
ExclusiveMonitor& System::Monitor() {
|
||||
return impl->cpu_core_manager.GetExclusiveMonitor();
|
||||
return impl->kernel.GetExclusiveMonitor();
|
||||
}
|
||||
|
||||
const ExclusiveMonitor& System::Monitor() const {
|
||||
return impl->cpu_core_manager.GetExclusiveMonitor();
|
||||
return impl->kernel.GetExclusiveMonitor();
|
||||
}
|
||||
|
||||
Memory::Memory& System::Memory() {
|
||||
return impl->memory;
|
||||
}
|
||||
|
||||
const Memory::Memory& System::Memory() const {
|
||||
return impl->memory;
|
||||
}
|
||||
|
||||
Tegra::GPU& System::GPU() {
|
||||
@@ -570,14 +591,6 @@ Loader::AppLoader& System::GetAppLoader() const {
|
||||
return *impl->app_loader;
|
||||
}
|
||||
|
||||
void System::SetGPUDebugContext(std::shared_ptr<Tegra::DebugContext> context) {
|
||||
impl->debug_context = std::move(context);
|
||||
}
|
||||
|
||||
Tegra::DebugContext* System::GetGPUDebugContext() const {
|
||||
return impl->debug_context.get();
|
||||
}
|
||||
|
||||
void System::SetFilesystem(std::shared_ptr<FileSys::VfsFilesystem> vfs) {
|
||||
impl->virtual_filesystem = std::move(vfs);
|
||||
}
|
||||
@@ -698,4 +711,12 @@ const Service::SM::ServiceManager& System::ServiceManager() const {
|
||||
return *impl->service_manager;
|
||||
}
|
||||
|
||||
void System::RegisterCoreThread(std::size_t id) {
|
||||
impl->kernel.RegisterCoreThread(id);
|
||||
}
|
||||
|
||||
void System::RegisterHostThread() {
|
||||
impl->kernel.RegisterHostThread();
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "core/file_sys/vfs_types.h"
|
||||
@@ -85,10 +86,14 @@ namespace Core::Hardware {
|
||||
class InterruptManager;
|
||||
}
|
||||
|
||||
namespace Memory {
|
||||
class Memory;
|
||||
}
|
||||
|
||||
namespace Core {
|
||||
|
||||
class ARM_Interface;
|
||||
class Cpu;
|
||||
class CoreManager;
|
||||
class ExclusiveMonitor;
|
||||
class FrameLimiter;
|
||||
class PerfStats;
|
||||
@@ -213,10 +218,10 @@ public:
|
||||
const ARM_Interface& ArmInterface(std::size_t core_index) const;
|
||||
|
||||
/// Gets a CPU interface to the CPU core with the specified index
|
||||
Cpu& CpuCore(std::size_t core_index);
|
||||
CoreManager& GetCoreManager(std::size_t core_index);
|
||||
|
||||
/// Gets a CPU interface to the CPU core with the specified index
|
||||
const Cpu& CpuCore(std::size_t core_index) const;
|
||||
const CoreManager& GetCoreManager(std::size_t core_index) const;
|
||||
|
||||
/// Gets a reference to the exclusive monitor
|
||||
ExclusiveMonitor& Monitor();
|
||||
@@ -224,6 +229,12 @@ public:
|
||||
/// Gets a constant reference to the exclusive monitor
|
||||
const ExclusiveMonitor& Monitor() const;
|
||||
|
||||
/// Gets a mutable reference to the system memory instance.
|
||||
Memory::Memory& Memory();
|
||||
|
||||
/// Gets a constant reference to the system memory instance.
|
||||
const Memory::Memory& Memory() const;
|
||||
|
||||
/// Gets a mutable reference to the GPU interface
|
||||
Tegra::GPU& GPU();
|
||||
|
||||
@@ -296,10 +307,6 @@ public:
|
||||
Service::SM::ServiceManager& ServiceManager();
|
||||
const Service::SM::ServiceManager& ServiceManager() const;
|
||||
|
||||
void SetGPUDebugContext(std::shared_ptr<Tegra::DebugContext> context);
|
||||
|
||||
Tegra::DebugContext* GetGPUDebugContext() const;
|
||||
|
||||
void SetFilesystem(std::shared_ptr<FileSys::VfsFilesystem> vfs);
|
||||
|
||||
std::shared_ptr<FileSys::VfsFilesystem> GetFilesystem() const;
|
||||
@@ -353,14 +360,20 @@ public:
|
||||
|
||||
const CurrentBuildProcessID& GetCurrentProcessBuildID() const;
|
||||
|
||||
/// Register a host thread as an emulated CPU Core.
|
||||
void RegisterCoreThread(std::size_t id);
|
||||
|
||||
/// Register a host thread as an auxiliary thread.
|
||||
void RegisterHostThread();
|
||||
|
||||
private:
|
||||
System();
|
||||
|
||||
/// Returns the currently running CPU core
|
||||
Cpu& CurrentCpuCore();
|
||||
CoreManager& CurrentCoreManager();
|
||||
|
||||
/// Returns the currently running CPU core
|
||||
const Cpu& CurrentCpuCore() const;
|
||||
const CoreManager& CurrentCoreManager() const;
|
||||
|
||||
/**
|
||||
* Initialize the emulated system.
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
#include "core/arm/dynarmic/arm_dynarmic.h"
|
||||
#endif
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/arm/unicorn/arm_unicorn.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_cpu.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/scheduler.h"
|
||||
#include "core/hle/kernel/thread.h"
|
||||
#include "core/hle/lock.h"
|
||||
#include "core/settings.h"
|
||||
|
||||
namespace Core {
|
||||
|
||||
void CpuBarrier::NotifyEnd() {
|
||||
std::unique_lock lock{mutex};
|
||||
end = true;
|
||||
condition.notify_all();
|
||||
}
|
||||
|
||||
bool CpuBarrier::Rendezvous() {
|
||||
if (!Settings::values.use_multi_core) {
|
||||
// Meaningless when running in single-core mode
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!end) {
|
||||
std::unique_lock lock{mutex};
|
||||
|
||||
--cores_waiting;
|
||||
if (!cores_waiting) {
|
||||
cores_waiting = NUM_CPU_CORES;
|
||||
condition.notify_all();
|
||||
return true;
|
||||
}
|
||||
|
||||
condition.wait(lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Cpu::Cpu(System& system, ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_barrier,
|
||||
std::size_t core_index)
|
||||
: cpu_barrier{cpu_barrier}, global_scheduler{system.GlobalScheduler()},
|
||||
core_timing{system.CoreTiming()}, core_index{core_index} {
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
arm_interface = std::make_unique<ARM_Dynarmic>(system, exclusive_monitor, core_index);
|
||||
#else
|
||||
arm_interface = std::make_unique<ARM_Unicorn>(system);
|
||||
LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available");
|
||||
#endif
|
||||
|
||||
scheduler = std::make_unique<Kernel::Scheduler>(system, *arm_interface, core_index);
|
||||
}
|
||||
|
||||
Cpu::~Cpu() = default;
|
||||
|
||||
std::unique_ptr<ExclusiveMonitor> Cpu::MakeExclusiveMonitor(std::size_t num_cores) {
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
return std::make_unique<DynarmicExclusiveMonitor>(num_cores);
|
||||
#else
|
||||
// TODO(merry): Passthrough exclusive monitor
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Cpu::RunLoop(bool tight_loop) {
|
||||
// Wait for all other CPU cores to complete the previous slice, such that they run in lock-step
|
||||
if (!cpu_barrier.Rendezvous()) {
|
||||
// If rendezvous failed, session has been killed
|
||||
return;
|
||||
}
|
||||
|
||||
Reschedule();
|
||||
|
||||
// If we don't have a currently active thread then don't execute instructions,
|
||||
// instead advance to the next event and try to yield to the next thread
|
||||
if (Kernel::GetCurrentThread() == nullptr) {
|
||||
LOG_TRACE(Core, "Core-{} idling", core_index);
|
||||
core_timing.Idle();
|
||||
} else {
|
||||
if (tight_loop) {
|
||||
arm_interface->Run();
|
||||
} else {
|
||||
arm_interface->Step();
|
||||
}
|
||||
}
|
||||
core_timing.Advance();
|
||||
|
||||
Reschedule();
|
||||
}
|
||||
|
||||
void Cpu::SingleStep() {
|
||||
return RunLoop(false);
|
||||
}
|
||||
|
||||
void Cpu::PrepareReschedule() {
|
||||
arm_interface->PrepareReschedule();
|
||||
}
|
||||
|
||||
void Cpu::Reschedule() {
|
||||
// Lock the global kernel mutex when we manipulate the HLE state
|
||||
std::lock_guard lock(HLE::g_hle_lock);
|
||||
|
||||
global_scheduler.SelectThread(core_index);
|
||||
scheduler->TryDoContextSwitch();
|
||||
}
|
||||
|
||||
void Cpu::Shutdown() {
|
||||
scheduler->Shutdown();
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
@@ -1,104 +0,0 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Kernel {
|
||||
class GlobalScheduler;
|
||||
class Scheduler;
|
||||
} // namespace Kernel
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Core::Timing {
|
||||
class CoreTiming;
|
||||
}
|
||||
|
||||
namespace Core {
|
||||
|
||||
class ARM_Interface;
|
||||
class ExclusiveMonitor;
|
||||
|
||||
constexpr unsigned NUM_CPU_CORES{4};
|
||||
|
||||
class CpuBarrier {
|
||||
public:
|
||||
bool IsAlive() const {
|
||||
return !end;
|
||||
}
|
||||
|
||||
void NotifyEnd();
|
||||
|
||||
bool Rendezvous();
|
||||
|
||||
private:
|
||||
unsigned cores_waiting{NUM_CPU_CORES};
|
||||
std::mutex mutex;
|
||||
std::condition_variable condition;
|
||||
std::atomic<bool> end{};
|
||||
};
|
||||
|
||||
class Cpu {
|
||||
public:
|
||||
Cpu(System& system, ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_barrier,
|
||||
std::size_t core_index);
|
||||
~Cpu();
|
||||
|
||||
void RunLoop(bool tight_loop = true);
|
||||
|
||||
void SingleStep();
|
||||
|
||||
void PrepareReschedule();
|
||||
|
||||
ARM_Interface& ArmInterface() {
|
||||
return *arm_interface;
|
||||
}
|
||||
|
||||
const ARM_Interface& ArmInterface() const {
|
||||
return *arm_interface;
|
||||
}
|
||||
|
||||
Kernel::Scheduler& Scheduler() {
|
||||
return *scheduler;
|
||||
}
|
||||
|
||||
const Kernel::Scheduler& Scheduler() const {
|
||||
return *scheduler;
|
||||
}
|
||||
|
||||
bool IsMainCore() const {
|
||||
return core_index == 0;
|
||||
}
|
||||
|
||||
std::size_t CoreIndex() const {
|
||||
return core_index;
|
||||
}
|
||||
|
||||
void Shutdown();
|
||||
|
||||
static std::unique_ptr<ExclusiveMonitor> MakeExclusiveMonitor(std::size_t num_cores);
|
||||
|
||||
private:
|
||||
void Reschedule();
|
||||
|
||||
std::unique_ptr<ARM_Interface> arm_interface;
|
||||
CpuBarrier& cpu_barrier;
|
||||
Kernel::GlobalScheduler& global_scheduler;
|
||||
std::unique_ptr<Kernel::Scheduler> scheduler;
|
||||
Timing::CoreTiming& core_timing;
|
||||
|
||||
std::atomic<bool> reschedule_pending = false;
|
||||
std::size_t core_index;
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
67
src/core/core_manager.cpp
Normal file
67
src/core/core_manager.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/arm/unicorn/arm_unicorn.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_manager.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/physical_core.h"
|
||||
#include "core/hle/kernel/scheduler.h"
|
||||
#include "core/hle/kernel/thread.h"
|
||||
#include "core/hle/lock.h"
|
||||
#include "core/settings.h"
|
||||
|
||||
namespace Core {
|
||||
|
||||
CoreManager::CoreManager(System& system, std::size_t core_index)
|
||||
: global_scheduler{system.GlobalScheduler()}, physical_core{system.Kernel().PhysicalCore(
|
||||
core_index)},
|
||||
core_timing{system.CoreTiming()}, core_index{core_index} {}
|
||||
|
||||
CoreManager::~CoreManager() = default;
|
||||
|
||||
void CoreManager::RunLoop(bool tight_loop) {
|
||||
Reschedule();
|
||||
|
||||
// If we don't have a currently active thread then don't execute instructions,
|
||||
// instead advance to the next event and try to yield to the next thread
|
||||
if (Kernel::GetCurrentThread() == nullptr) {
|
||||
LOG_TRACE(Core, "Core-{} idling", core_index);
|
||||
core_timing.Idle();
|
||||
} else {
|
||||
if (tight_loop) {
|
||||
physical_core.Run();
|
||||
} else {
|
||||
physical_core.Step();
|
||||
}
|
||||
}
|
||||
core_timing.Advance();
|
||||
|
||||
Reschedule();
|
||||
}
|
||||
|
||||
void CoreManager::SingleStep() {
|
||||
return RunLoop(false);
|
||||
}
|
||||
|
||||
void CoreManager::PrepareReschedule() {
|
||||
physical_core.Stop();
|
||||
}
|
||||
|
||||
void CoreManager::Reschedule() {
|
||||
// Lock the global kernel mutex when we manipulate the HLE state
|
||||
std::lock_guard lock(HLE::g_hle_lock);
|
||||
|
||||
global_scheduler.SelectThread(core_index);
|
||||
|
||||
physical_core.Scheduler().TryDoContextSwitch();
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
63
src/core/core_manager.h
Normal file
63
src/core/core_manager.h
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Kernel {
|
||||
class GlobalScheduler;
|
||||
class PhysicalCore;
|
||||
} // namespace Kernel
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Core::Timing {
|
||||
class CoreTiming;
|
||||
}
|
||||
|
||||
namespace Memory {
|
||||
class Memory;
|
||||
}
|
||||
|
||||
namespace Core {
|
||||
|
||||
constexpr unsigned NUM_CPU_CORES{4};
|
||||
|
||||
class CoreManager {
|
||||
public:
|
||||
CoreManager(System& system, std::size_t core_index);
|
||||
~CoreManager();
|
||||
|
||||
void RunLoop(bool tight_loop = true);
|
||||
|
||||
void SingleStep();
|
||||
|
||||
void PrepareReschedule();
|
||||
|
||||
bool IsMainCore() const {
|
||||
return core_index == 0;
|
||||
}
|
||||
|
||||
std::size_t CoreIndex() const {
|
||||
return core_index;
|
||||
}
|
||||
|
||||
private:
|
||||
void Reschedule();
|
||||
|
||||
Kernel::GlobalScheduler& global_scheduler;
|
||||
Kernel::PhysicalCore& physical_core;
|
||||
Timing::CoreTiming& core_timing;
|
||||
|
||||
std::atomic<bool> reschedule_pending = false;
|
||||
std::size_t core_index;
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
@@ -12,16 +12,21 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/thread.h"
|
||||
#include "core/core_timing_util.h"
|
||||
#include "core/hardware_properties.h"
|
||||
|
||||
namespace Core::Timing {
|
||||
|
||||
constexpr int MAX_SLICE_LENGTH = 10000;
|
||||
|
||||
std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) {
|
||||
return std::make_shared<EventType>(std::move(callback), std::move(name));
|
||||
}
|
||||
|
||||
struct CoreTiming::Event {
|
||||
s64 time;
|
||||
u64 fifo_order;
|
||||
u64 userdata;
|
||||
const EventType* type;
|
||||
std::weak_ptr<EventType> type;
|
||||
|
||||
// Sort by time, unless the times are the same, in which case sort by
|
||||
// the order added to the queue
|
||||
@@ -54,36 +59,15 @@ void CoreTiming::Initialize() {
|
||||
event_fifo_id = 0;
|
||||
|
||||
const auto empty_timed_callback = [](u64, s64) {};
|
||||
ev_lost = RegisterEvent("_lost_event", empty_timed_callback);
|
||||
ev_lost = CreateEvent("_lost_event", empty_timed_callback);
|
||||
}
|
||||
|
||||
void CoreTiming::Shutdown() {
|
||||
ClearPendingEvents();
|
||||
UnregisterAllEvents();
|
||||
}
|
||||
|
||||
EventType* CoreTiming::RegisterEvent(const std::string& name, TimedCallback callback) {
|
||||
std::lock_guard guard{inner_mutex};
|
||||
// check for existing type with same name.
|
||||
// we want event type names to remain unique so that we can use them for serialization.
|
||||
ASSERT_MSG(event_types.find(name) == event_types.end(),
|
||||
"CoreTiming Event \"{}\" is already registered. Events should only be registered "
|
||||
"during Init to avoid breaking save states.",
|
||||
name.c_str());
|
||||
|
||||
auto info = event_types.emplace(name, EventType{callback, nullptr});
|
||||
EventType* event_type = &info.first->second;
|
||||
event_type->name = &info.first->first;
|
||||
return event_type;
|
||||
}
|
||||
|
||||
void CoreTiming::UnregisterAllEvents() {
|
||||
ASSERT_MSG(event_queue.empty(), "Cannot unregister events with events pending");
|
||||
event_types.clear();
|
||||
}
|
||||
|
||||
void CoreTiming::ScheduleEvent(s64 cycles_into_future, const EventType* event_type, u64 userdata) {
|
||||
ASSERT(event_type != nullptr);
|
||||
void CoreTiming::ScheduleEvent(s64 cycles_into_future, const std::shared_ptr<EventType>& event_type,
|
||||
u64 userdata) {
|
||||
std::lock_guard guard{inner_mutex};
|
||||
const s64 timeout = GetTicks() + cycles_into_future;
|
||||
|
||||
@@ -93,13 +77,15 @@ void CoreTiming::ScheduleEvent(s64 cycles_into_future, const EventType* event_ty
|
||||
}
|
||||
|
||||
event_queue.emplace_back(Event{timeout, event_fifo_id++, userdata, event_type});
|
||||
|
||||
std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>());
|
||||
}
|
||||
|
||||
void CoreTiming::UnscheduleEvent(const EventType* event_type, u64 userdata) {
|
||||
void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, u64 userdata) {
|
||||
std::lock_guard guard{inner_mutex};
|
||||
|
||||
const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) {
|
||||
return e.type == event_type && e.userdata == userdata;
|
||||
return e.type.lock().get() == event_type.get() && e.userdata == userdata;
|
||||
});
|
||||
|
||||
// Removing random items breaks the invariant so we have to re-establish it.
|
||||
@@ -130,10 +116,12 @@ void CoreTiming::ClearPendingEvents() {
|
||||
event_queue.clear();
|
||||
}
|
||||
|
||||
void CoreTiming::RemoveEvent(const EventType* event_type) {
|
||||
void CoreTiming::RemoveEvent(const std::shared_ptr<EventType>& event_type) {
|
||||
std::lock_guard guard{inner_mutex};
|
||||
const auto itr = std::remove_if(event_queue.begin(), event_queue.end(),
|
||||
[&](const Event& e) { return e.type == event_type; });
|
||||
|
||||
const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) {
|
||||
return e.type.lock().get() == event_type.get();
|
||||
});
|
||||
|
||||
// Removing random items breaks the invariant so we have to re-establish it.
|
||||
if (itr != event_queue.end()) {
|
||||
@@ -181,7 +169,11 @@ void CoreTiming::Advance() {
|
||||
std::pop_heap(event_queue.begin(), event_queue.end(), std::greater<>());
|
||||
event_queue.pop_back();
|
||||
inner_mutex.unlock();
|
||||
evt.type->callback(evt.userdata, global_timer - evt.time);
|
||||
|
||||
if (auto event_type{evt.type.lock()}) {
|
||||
event_type->callback(evt.userdata, global_timer - evt.time);
|
||||
}
|
||||
|
||||
inner_mutex.lock();
|
||||
}
|
||||
|
||||
@@ -224,7 +216,7 @@ void CoreTiming::Idle() {
|
||||
}
|
||||
|
||||
std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const {
|
||||
return std::chrono::microseconds{GetTicks() * 1000000 / BASE_CLOCK_RATE};
|
||||
return std::chrono::microseconds{GetTicks() * 1000000 / Hardware::BASE_CLOCK_RATE};
|
||||
}
|
||||
|
||||
s64 CoreTiming::GetDowncount() const {
|
||||
|
||||
@@ -6,11 +6,12 @@
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/threadsafe_queue.h"
|
||||
|
||||
@@ -21,10 +22,13 @@ using TimedCallback = std::function<void(u64 userdata, s64 cycles_late)>;
|
||||
|
||||
/// Contains the characteristics of a particular event.
|
||||
struct EventType {
|
||||
EventType(TimedCallback&& callback, std::string&& name)
|
||||
: callback{std::move(callback)}, name{std::move(name)} {}
|
||||
|
||||
/// The event's callback function.
|
||||
TimedCallback callback;
|
||||
/// A pointer to the name of the event.
|
||||
const std::string* name;
|
||||
const std::string name;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -57,31 +61,17 @@ public:
|
||||
/// Tears down all timing related functionality.
|
||||
void Shutdown();
|
||||
|
||||
/// Registers a core timing event with the given name and callback.
|
||||
///
|
||||
/// @param name The name of the core timing event to register.
|
||||
/// @param callback The callback to execute for the event.
|
||||
///
|
||||
/// @returns An EventType instance representing the registered event.
|
||||
///
|
||||
/// @pre The name of the event being registered must be unique among all
|
||||
/// registered events.
|
||||
///
|
||||
EventType* RegisterEvent(const std::string& name, TimedCallback callback);
|
||||
|
||||
/// Unregisters all registered events thus far. Note: not thread unsafe
|
||||
void UnregisterAllEvents();
|
||||
|
||||
/// After the first Advance, the slice lengths and the downcount will be reduced whenever an
|
||||
/// event is scheduled earlier than the current values.
|
||||
///
|
||||
/// Scheduling from a callback will not update the downcount until the Advance() completes.
|
||||
void ScheduleEvent(s64 cycles_into_future, const EventType* event_type, u64 userdata = 0);
|
||||
void ScheduleEvent(s64 cycles_into_future, const std::shared_ptr<EventType>& event_type,
|
||||
u64 userdata = 0);
|
||||
|
||||
void UnscheduleEvent(const EventType* event_type, u64 userdata);
|
||||
void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, u64 userdata);
|
||||
|
||||
/// We only permit one event of each type in the queue at a time.
|
||||
void RemoveEvent(const EventType* event_type);
|
||||
void RemoveEvent(const std::shared_ptr<EventType>& event_type);
|
||||
|
||||
void ForceExceptionCheck(s64 cycles);
|
||||
|
||||
@@ -148,13 +138,18 @@ private:
|
||||
std::vector<Event> event_queue;
|
||||
u64 event_fifo_id = 0;
|
||||
|
||||
// Stores each element separately as a linked list node so pointers to elements
|
||||
// remain stable regardless of rehashes/resizing.
|
||||
std::unordered_map<std::string, EventType> event_types;
|
||||
|
||||
EventType* ev_lost = nullptr;
|
||||
std::shared_ptr<EventType> ev_lost;
|
||||
|
||||
std::mutex inner_mutex;
|
||||
};
|
||||
|
||||
/// Creates a core timing event with the given name and callback.
|
||||
///
|
||||
/// @param name The name of the core timing event to create.
|
||||
/// @param callback The callback to execute for the event.
|
||||
///
|
||||
/// @returns An EventType instance representing the created event.
|
||||
///
|
||||
std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback);
|
||||
|
||||
} // namespace Core::Timing
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
namespace Core::Timing {
|
||||
|
||||
constexpr u64 MAX_VALUE_TO_MULTIPLY = std::numeric_limits<s64>::max() / BASE_CLOCK_RATE;
|
||||
constexpr u64 MAX_VALUE_TO_MULTIPLY = std::numeric_limits<s64>::max() / Hardware::BASE_CLOCK_RATE;
|
||||
|
||||
s64 msToCycles(std::chrono::milliseconds ms) {
|
||||
if (static_cast<u64>(ms.count() / 1000) > MAX_VALUE_TO_MULTIPLY) {
|
||||
@@ -20,9 +20,9 @@ s64 msToCycles(std::chrono::milliseconds ms) {
|
||||
}
|
||||
if (static_cast<u64>(ms.count()) > MAX_VALUE_TO_MULTIPLY) {
|
||||
LOG_DEBUG(Core_Timing, "Time very big, do rounding");
|
||||
return BASE_CLOCK_RATE * (ms.count() / 1000);
|
||||
return Hardware::BASE_CLOCK_RATE * (ms.count() / 1000);
|
||||
}
|
||||
return (BASE_CLOCK_RATE * ms.count()) / 1000;
|
||||
return (Hardware::BASE_CLOCK_RATE * ms.count()) / 1000;
|
||||
}
|
||||
|
||||
s64 usToCycles(std::chrono::microseconds us) {
|
||||
@@ -32,9 +32,9 @@ s64 usToCycles(std::chrono::microseconds us) {
|
||||
}
|
||||
if (static_cast<u64>(us.count()) > MAX_VALUE_TO_MULTIPLY) {
|
||||
LOG_DEBUG(Core_Timing, "Time very big, do rounding");
|
||||
return BASE_CLOCK_RATE * (us.count() / 1000000);
|
||||
return Hardware::BASE_CLOCK_RATE * (us.count() / 1000000);
|
||||
}
|
||||
return (BASE_CLOCK_RATE * us.count()) / 1000000;
|
||||
return (Hardware::BASE_CLOCK_RATE * us.count()) / 1000000;
|
||||
}
|
||||
|
||||
s64 nsToCycles(std::chrono::nanoseconds ns) {
|
||||
@@ -44,14 +44,14 @@ s64 nsToCycles(std::chrono::nanoseconds ns) {
|
||||
}
|
||||
if (static_cast<u64>(ns.count()) > MAX_VALUE_TO_MULTIPLY) {
|
||||
LOG_DEBUG(Core_Timing, "Time very big, do rounding");
|
||||
return BASE_CLOCK_RATE * (ns.count() / 1000000000);
|
||||
return Hardware::BASE_CLOCK_RATE * (ns.count() / 1000000000);
|
||||
}
|
||||
return (BASE_CLOCK_RATE * ns.count()) / 1000000000;
|
||||
return (Hardware::BASE_CLOCK_RATE * ns.count()) / 1000000000;
|
||||
}
|
||||
|
||||
u64 CpuCyclesToClockCycles(u64 ticks) {
|
||||
const u128 temporal = Common::Multiply64Into128(ticks, CNTFREQ);
|
||||
return Common::Divide128On32(temporal, static_cast<u32>(BASE_CLOCK_RATE)).first;
|
||||
const u128 temporal = Common::Multiply64Into128(ticks, Hardware::CNTFREQ);
|
||||
return Common::Divide128On32(temporal, static_cast<u32>(Hardware::BASE_CLOCK_RATE)).first;
|
||||
}
|
||||
|
||||
} // namespace Core::Timing
|
||||
|
||||
@@ -6,28 +6,24 @@
|
||||
|
||||
#include <chrono>
|
||||
#include "common/common_types.h"
|
||||
#include "core/hardware_properties.h"
|
||||
|
||||
namespace Core::Timing {
|
||||
|
||||
// The below clock rate is based on Switch's clockspeed being widely known as 1.020GHz
|
||||
// The exact value used is of course unverified.
|
||||
constexpr u64 BASE_CLOCK_RATE = 1019215872; // Switch clock speed is 1020MHz un/docked
|
||||
constexpr u64 CNTFREQ = 19200000; // Value from fusee.
|
||||
|
||||
s64 msToCycles(std::chrono::milliseconds ms);
|
||||
s64 usToCycles(std::chrono::microseconds us);
|
||||
s64 nsToCycles(std::chrono::nanoseconds ns);
|
||||
|
||||
inline std::chrono::milliseconds CyclesToMs(s64 cycles) {
|
||||
return std::chrono::milliseconds(cycles * 1000 / BASE_CLOCK_RATE);
|
||||
return std::chrono::milliseconds(cycles * 1000 / Hardware::BASE_CLOCK_RATE);
|
||||
}
|
||||
|
||||
inline std::chrono::nanoseconds CyclesToNs(s64 cycles) {
|
||||
return std::chrono::nanoseconds(cycles * 1000000000 / BASE_CLOCK_RATE);
|
||||
return std::chrono::nanoseconds(cycles * 1000000000 / Hardware::BASE_CLOCK_RATE);
|
||||
}
|
||||
|
||||
inline std::chrono::microseconds CyclesToUs(s64 cycles) {
|
||||
return std::chrono::microseconds(cycles * 1000000 / BASE_CLOCK_RATE);
|
||||
return std::chrono::microseconds(cycles * 1000000 / Hardware::BASE_CLOCK_RATE);
|
||||
}
|
||||
|
||||
u64 CpuCyclesToClockCycles(u64 ticks);
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_cpu.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/cpu_core_manager.h"
|
||||
#include "core/gdbstub/gdbstub.h"
|
||||
#include "core/settings.h"
|
||||
|
||||
namespace Core {
|
||||
namespace {
|
||||
void RunCpuCore(const System& system, Cpu& cpu_state) {
|
||||
while (system.IsPoweredOn()) {
|
||||
cpu_state.RunLoop(true);
|
||||
}
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
CpuCoreManager::CpuCoreManager(System& system) : system{system} {}
|
||||
CpuCoreManager::~CpuCoreManager() = default;
|
||||
|
||||
void CpuCoreManager::Initialize() {
|
||||
barrier = std::make_unique<CpuBarrier>();
|
||||
exclusive_monitor = Cpu::MakeExclusiveMonitor(cores.size());
|
||||
|
||||
for (std::size_t index = 0; index < cores.size(); ++index) {
|
||||
cores[index] = std::make_unique<Cpu>(system, *exclusive_monitor, *barrier, index);
|
||||
}
|
||||
}
|
||||
|
||||
void CpuCoreManager::StartThreads() {
|
||||
// Create threads for CPU cores 1-3, and build thread_to_cpu map
|
||||
// CPU core 0 is run on the main thread
|
||||
thread_to_cpu[std::this_thread::get_id()] = cores[0].get();
|
||||
if (!Settings::values.use_multi_core) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (std::size_t index = 0; index < core_threads.size(); ++index) {
|
||||
core_threads[index] = std::make_unique<std::thread>(RunCpuCore, std::cref(system),
|
||||
std::ref(*cores[index + 1]));
|
||||
thread_to_cpu[core_threads[index]->get_id()] = cores[index + 1].get();
|
||||
}
|
||||
}
|
||||
|
||||
void CpuCoreManager::Shutdown() {
|
||||
barrier->NotifyEnd();
|
||||
if (Settings::values.use_multi_core) {
|
||||
for (auto& thread : core_threads) {
|
||||
thread->join();
|
||||
thread.reset();
|
||||
}
|
||||
}
|
||||
|
||||
thread_to_cpu.clear();
|
||||
for (auto& cpu_core : cores) {
|
||||
cpu_core->Shutdown();
|
||||
cpu_core.reset();
|
||||
}
|
||||
|
||||
exclusive_monitor.reset();
|
||||
barrier.reset();
|
||||
}
|
||||
|
||||
Cpu& CpuCoreManager::GetCore(std::size_t index) {
|
||||
return *cores.at(index);
|
||||
}
|
||||
|
||||
const Cpu& CpuCoreManager::GetCore(std::size_t index) const {
|
||||
return *cores.at(index);
|
||||
}
|
||||
|
||||
ExclusiveMonitor& CpuCoreManager::GetExclusiveMonitor() {
|
||||
return *exclusive_monitor;
|
||||
}
|
||||
|
||||
const ExclusiveMonitor& CpuCoreManager::GetExclusiveMonitor() const {
|
||||
return *exclusive_monitor;
|
||||
}
|
||||
|
||||
Cpu& CpuCoreManager::GetCurrentCore() {
|
||||
if (Settings::values.use_multi_core) {
|
||||
const auto& search = thread_to_cpu.find(std::this_thread::get_id());
|
||||
ASSERT(search != thread_to_cpu.end());
|
||||
ASSERT(search->second);
|
||||
return *search->second;
|
||||
}
|
||||
|
||||
// Otherwise, use single-threaded mode active_core variable
|
||||
return *cores[active_core];
|
||||
}
|
||||
|
||||
const Cpu& CpuCoreManager::GetCurrentCore() const {
|
||||
if (Settings::values.use_multi_core) {
|
||||
const auto& search = thread_to_cpu.find(std::this_thread::get_id());
|
||||
ASSERT(search != thread_to_cpu.end());
|
||||
ASSERT(search->second);
|
||||
return *search->second;
|
||||
}
|
||||
|
||||
// Otherwise, use single-threaded mode active_core variable
|
||||
return *cores[active_core];
|
||||
}
|
||||
|
||||
void CpuCoreManager::RunLoop(bool tight_loop) {
|
||||
// Update thread_to_cpu in case Core 0 is run from a different host thread
|
||||
thread_to_cpu[std::this_thread::get_id()] = cores[0].get();
|
||||
|
||||
if (GDBStub::IsServerEnabled()) {
|
||||
GDBStub::HandlePacket();
|
||||
|
||||
// If the loop is halted and we want to step, use a tiny (1) number of instructions to
|
||||
// execute. Otherwise, get out of the loop function.
|
||||
if (GDBStub::GetCpuHaltFlag()) {
|
||||
if (GDBStub::GetCpuStepFlag()) {
|
||||
tight_loop = false;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto& core_timing = system.CoreTiming();
|
||||
core_timing.ResetRun();
|
||||
bool keep_running{};
|
||||
do {
|
||||
keep_running = false;
|
||||
for (active_core = 0; active_core < NUM_CPU_CORES; ++active_core) {
|
||||
core_timing.SwitchContext(active_core);
|
||||
if (core_timing.CanCurrentContextRun()) {
|
||||
cores[active_core]->RunLoop(tight_loop);
|
||||
}
|
||||
keep_running |= core_timing.CanCurrentContextRun();
|
||||
}
|
||||
} while (keep_running);
|
||||
|
||||
if (GDBStub::IsServerEnabled()) {
|
||||
GDBStub::SetCpuStepFlag(false);
|
||||
}
|
||||
}
|
||||
|
||||
void CpuCoreManager::InvalidateAllInstructionCaches() {
|
||||
for (auto& cpu : cores) {
|
||||
cpu->ArmInterface().ClearInstructionCache();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
@@ -1,62 +0,0 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
namespace Core {
|
||||
|
||||
class Cpu;
|
||||
class CpuBarrier;
|
||||
class ExclusiveMonitor;
|
||||
class System;
|
||||
|
||||
class CpuCoreManager {
|
||||
public:
|
||||
explicit CpuCoreManager(System& system);
|
||||
CpuCoreManager(const CpuCoreManager&) = delete;
|
||||
CpuCoreManager(CpuCoreManager&&) = delete;
|
||||
|
||||
~CpuCoreManager();
|
||||
|
||||
CpuCoreManager& operator=(const CpuCoreManager&) = delete;
|
||||
CpuCoreManager& operator=(CpuCoreManager&&) = delete;
|
||||
|
||||
void Initialize();
|
||||
void StartThreads();
|
||||
void Shutdown();
|
||||
|
||||
Cpu& GetCore(std::size_t index);
|
||||
const Cpu& GetCore(std::size_t index) const;
|
||||
|
||||
Cpu& GetCurrentCore();
|
||||
const Cpu& GetCurrentCore() const;
|
||||
|
||||
ExclusiveMonitor& GetExclusiveMonitor();
|
||||
const ExclusiveMonitor& GetExclusiveMonitor() const;
|
||||
|
||||
void RunLoop(bool tight_loop);
|
||||
|
||||
void InvalidateAllInstructionCaches();
|
||||
|
||||
private:
|
||||
static constexpr std::size_t NUM_CPU_CORES = 4;
|
||||
|
||||
std::unique_ptr<ExclusiveMonitor> exclusive_monitor;
|
||||
std::unique_ptr<CpuBarrier> barrier;
|
||||
std::array<std::unique_ptr<Cpu>, NUM_CPU_CORES> cores;
|
||||
std::array<std::unique_ptr<std::thread>, NUM_CPU_CORES - 1> core_threads;
|
||||
std::size_t active_core{}; ///< Active core, only used in single thread mode
|
||||
|
||||
/// Map of guest threads to CPU cores
|
||||
std::map<std::thread::id, Cpu*> thread_to_cpu;
|
||||
|
||||
System& system;
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
81
src/core/cpu_manager.cpp
Normal file
81
src/core/cpu_manager.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_manager.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/cpu_manager.h"
|
||||
#include "core/gdbstub/gdbstub.h"
|
||||
|
||||
namespace Core {
|
||||
|
||||
CpuManager::CpuManager(System& system) : system{system} {}
|
||||
CpuManager::~CpuManager() = default;
|
||||
|
||||
void CpuManager::Initialize() {
|
||||
for (std::size_t index = 0; index < core_managers.size(); ++index) {
|
||||
core_managers[index] = std::make_unique<CoreManager>(system, index);
|
||||
}
|
||||
}
|
||||
|
||||
void CpuManager::Shutdown() {
|
||||
for (auto& cpu_core : core_managers) {
|
||||
cpu_core.reset();
|
||||
}
|
||||
}
|
||||
|
||||
CoreManager& CpuManager::GetCoreManager(std::size_t index) {
|
||||
return *core_managers.at(index);
|
||||
}
|
||||
|
||||
const CoreManager& CpuManager::GetCoreManager(std::size_t index) const {
|
||||
return *core_managers.at(index);
|
||||
}
|
||||
|
||||
CoreManager& CpuManager::GetCurrentCoreManager() {
|
||||
// Otherwise, use single-threaded mode active_core variable
|
||||
return *core_managers[active_core];
|
||||
}
|
||||
|
||||
const CoreManager& CpuManager::GetCurrentCoreManager() const {
|
||||
// Otherwise, use single-threaded mode active_core variable
|
||||
return *core_managers[active_core];
|
||||
}
|
||||
|
||||
void CpuManager::RunLoop(bool tight_loop) {
|
||||
if (GDBStub::IsServerEnabled()) {
|
||||
GDBStub::HandlePacket();
|
||||
|
||||
// If the loop is halted and we want to step, use a tiny (1) number of instructions to
|
||||
// execute. Otherwise, get out of the loop function.
|
||||
if (GDBStub::GetCpuHaltFlag()) {
|
||||
if (GDBStub::GetCpuStepFlag()) {
|
||||
tight_loop = false;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto& core_timing = system.CoreTiming();
|
||||
core_timing.ResetRun();
|
||||
bool keep_running{};
|
||||
do {
|
||||
keep_running = false;
|
||||
for (active_core = 0; active_core < NUM_CPU_CORES; ++active_core) {
|
||||
core_timing.SwitchContext(active_core);
|
||||
if (core_timing.CanCurrentContextRun()) {
|
||||
core_managers[active_core]->RunLoop(tight_loop);
|
||||
}
|
||||
keep_running |= core_timing.CanCurrentContextRun();
|
||||
}
|
||||
} while (keep_running);
|
||||
|
||||
if (GDBStub::IsServerEnabled()) {
|
||||
GDBStub::SetCpuStepFlag(false);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
49
src/core/cpu_manager.h
Normal file
49
src/core/cpu_manager.h
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include "core/hardware_properties.h"
|
||||
|
||||
namespace Core {
|
||||
|
||||
class CoreManager;
|
||||
class System;
|
||||
|
||||
class CpuManager {
|
||||
public:
|
||||
explicit CpuManager(System& system);
|
||||
CpuManager(const CpuManager&) = delete;
|
||||
CpuManager(CpuManager&&) = delete;
|
||||
|
||||
~CpuManager();
|
||||
|
||||
CpuManager& operator=(const CpuManager&) = delete;
|
||||
CpuManager& operator=(CpuManager&&) = delete;
|
||||
|
||||
void Initialize();
|
||||
void Shutdown();
|
||||
|
||||
CoreManager& GetCoreManager(std::size_t index);
|
||||
const CoreManager& GetCoreManager(std::size_t index) const;
|
||||
|
||||
CoreManager& GetCurrentCoreManager();
|
||||
const CoreManager& GetCurrentCoreManager() const;
|
||||
|
||||
std::size_t GetActiveCoreIndex() const {
|
||||
return active_core;
|
||||
}
|
||||
|
||||
void RunLoop(bool tight_loop);
|
||||
|
||||
private:
|
||||
std::array<std::unique_ptr<CoreManager>, Hardware::NUM_CPU_CORES> core_managers;
|
||||
std::size_t active_core{}; ///< Active core, only used in single thread mode
|
||||
|
||||
System& system;
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "common/file_util.h"
|
||||
#include "common/hex_util.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/string_util.h"
|
||||
#include "core/core.h"
|
||||
#include "core/crypto/aes_util.h"
|
||||
#include "core/crypto/key_manager.h"
|
||||
@@ -378,8 +379,9 @@ std::vector<Ticket> GetTicketblob(const FileUtil::IOFile& ticket_save) {
|
||||
template <size_t size>
|
||||
static std::array<u8, size> operator^(const std::array<u8, size>& lhs,
|
||||
const std::array<u8, size>& rhs) {
|
||||
std::array<u8, size> out{};
|
||||
std::transform(lhs.begin(), lhs.end(), rhs.begin(), out.begin(), std::bit_xor<>());
|
||||
std::array<u8, size> out;
|
||||
std::transform(lhs.begin(), lhs.end(), rhs.begin(), out.begin(),
|
||||
[](u8 lhs, u8 rhs) { return u8(lhs ^ rhs); });
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -538,7 +540,7 @@ void KeyManager::LoadFromFile(const std::string& filename, bool is_title_keys) {
|
||||
Key128 key = Common::HexStringToArray<16>(out[1]);
|
||||
s128_keys[{S128KeyType::Titlekey, rights_id[1], rights_id[0]}] = key;
|
||||
} else {
|
||||
std::transform(out[0].begin(), out[0].end(), out[0].begin(), ::tolower);
|
||||
out[0] = Common::ToLower(out[0]);
|
||||
if (s128_file_id.find(out[0]) != s128_file_id.end()) {
|
||||
const auto index = s128_file_id.at(out[0]);
|
||||
Key128 key = Common::HexStringToArray<16>(out[1]);
|
||||
@@ -948,12 +950,10 @@ void KeyManager::DeriveETicket(PartitionDataManager& data) {
|
||||
return;
|
||||
}
|
||||
|
||||
Key128 rsa_oaep_kek{};
|
||||
std::transform(seed3.begin(), seed3.end(), mask0.begin(), rsa_oaep_kek.begin(),
|
||||
std::bit_xor<>());
|
||||
|
||||
if (rsa_oaep_kek == Key128{})
|
||||
const Key128 rsa_oaep_kek = seed3 ^ mask0;
|
||||
if (rsa_oaep_kek == Key128{}) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetKey(S128KeyType::Source, rsa_oaep_kek,
|
||||
static_cast<u64>(SourceKeyType::RSAOaepKekGeneration));
|
||||
|
||||
@@ -204,11 +204,12 @@ static std::array<Key128, 0x20> FindEncryptedMasterKeyFromHex(const std::vector<
|
||||
|
||||
FileSys::VirtualFile FindFileInDirWithNames(const FileSys::VirtualDir& dir,
|
||||
const std::string& name) {
|
||||
auto upper = name;
|
||||
std::transform(upper.begin(), upper.end(), upper.begin(), [](u8 c) { return std::toupper(c); });
|
||||
const auto upper = Common::ToUpper(name);
|
||||
|
||||
for (const auto& fname : {name, name + ".bin", upper, upper + ".BIN"}) {
|
||||
if (dir->GetFile(fname) != nullptr)
|
||||
if (dir->GetFile(fname) != nullptr) {
|
||||
return dir->GetFile(fname);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
enum EntryType : u8 {
|
||||
enum class EntryType : u8 {
|
||||
Directory = 0,
|
||||
File = 1,
|
||||
};
|
||||
|
||||
@@ -147,7 +147,7 @@ std::vector<u32> KIP::GetKernelCapabilities() const {
|
||||
}
|
||||
|
||||
s32 KIP::GetMainThreadPriority() const {
|
||||
return header.main_thread_priority;
|
||||
return static_cast<s32>(header.main_thread_priority);
|
||||
}
|
||||
|
||||
u32 KIP::GetMainThreadStackSize() const {
|
||||
|
||||
@@ -76,7 +76,7 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const {
|
||||
|
||||
const auto& disabled = Settings::values.disabled_addons[title_id];
|
||||
const auto update_disabled =
|
||||
std::find(disabled.begin(), disabled.end(), "Update") != disabled.end();
|
||||
std::find(disabled.cbegin(), disabled.cend(), "Update") != disabled.cend();
|
||||
|
||||
// Game Updates
|
||||
const auto update_tid = GetUpdateTitleID(title_id);
|
||||
@@ -127,7 +127,7 @@ std::vector<VirtualFile> PatchManager::CollectPatches(const std::vector<VirtualD
|
||||
std::vector<VirtualFile> out;
|
||||
out.reserve(patch_dirs.size());
|
||||
for (const auto& subdir : patch_dirs) {
|
||||
if (std::find(disabled.begin(), disabled.end(), subdir->GetName()) != disabled.end())
|
||||
if (std::find(disabled.cbegin(), disabled.cend(), subdir->GetName()) != disabled.cend())
|
||||
continue;
|
||||
|
||||
auto exefs_dir = subdir->GetSubdirectory("exefs");
|
||||
@@ -284,12 +284,17 @@ std::vector<Memory::CheatEntry> PatchManager::CreateCheatList(
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto& disabled = Settings::values.disabled_addons[title_id];
|
||||
auto patch_dirs = load_dir->GetSubdirectories();
|
||||
std::sort(patch_dirs.begin(), patch_dirs.end(),
|
||||
[](const VirtualDir& l, const VirtualDir& r) { return l->GetName() < r->GetName(); });
|
||||
|
||||
std::vector<Memory::CheatEntry> out;
|
||||
for (const auto& subdir : patch_dirs) {
|
||||
if (std::find(disabled.cbegin(), disabled.cend(), subdir->GetName()) != disabled.cend()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto cheats_dir = subdir->GetSubdirectory("cheats");
|
||||
if (cheats_dir != nullptr) {
|
||||
auto res = ReadCheatFileFromFolder(system, title_id, build_id_, cheats_dir, true);
|
||||
@@ -331,8 +336,9 @@ static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType t
|
||||
layers.reserve(patch_dirs.size() + 1);
|
||||
layers_ext.reserve(patch_dirs.size() + 1);
|
||||
for (const auto& subdir : patch_dirs) {
|
||||
if (std::find(disabled.begin(), disabled.end(), subdir->GetName()) != disabled.end())
|
||||
if (std::find(disabled.cbegin(), disabled.cend(), subdir->GetName()) != disabled.cend()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto romfs_dir = subdir->GetSubdirectory("romfs");
|
||||
if (romfs_dir != nullptr)
|
||||
@@ -381,7 +387,7 @@ VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset, Content
|
||||
|
||||
const auto& disabled = Settings::values.disabled_addons[title_id];
|
||||
const auto update_disabled =
|
||||
std::find(disabled.begin(), disabled.end(), "Update") != disabled.end();
|
||||
std::find(disabled.cbegin(), disabled.cend(), "Update") != disabled.cend();
|
||||
|
||||
if (!update_disabled && update != nullptr) {
|
||||
const auto new_nca = std::make_shared<NCA>(update, romfs, ivfc_offset);
|
||||
@@ -431,7 +437,7 @@ std::map<std::string, std::string, std::less<>> PatchManager::GetPatchVersionNam
|
||||
auto [nacp, discard_icon_file] = update.GetControlMetadata();
|
||||
|
||||
const auto update_disabled =
|
||||
std::find(disabled.begin(), disabled.end(), "Update") != disabled.end();
|
||||
std::find(disabled.cbegin(), disabled.cend(), "Update") != disabled.cend();
|
||||
const auto update_label = update_disabled ? "[D] Update" : "Update";
|
||||
|
||||
if (nacp != nullptr) {
|
||||
|
||||
@@ -52,14 +52,14 @@ Loader::ResultStatus ProgramMetadata::Load(VirtualFile file) {
|
||||
}
|
||||
|
||||
void ProgramMetadata::LoadManual(bool is_64_bit, ProgramAddressSpaceType address_space,
|
||||
u8 main_thread_prio, u8 main_thread_core,
|
||||
s32 main_thread_prio, u32 main_thread_core,
|
||||
u32 main_thread_stack_size, u64 title_id,
|
||||
u64 filesystem_permissions,
|
||||
KernelCapabilityDescriptors capabilities) {
|
||||
npdm_header.has_64_bit_instructions.Assign(is_64_bit);
|
||||
npdm_header.address_space_type.Assign(address_space);
|
||||
npdm_header.main_thread_priority = main_thread_prio;
|
||||
npdm_header.main_thread_cpu = main_thread_core;
|
||||
npdm_header.main_thread_priority = static_cast<u8>(main_thread_prio);
|
||||
npdm_header.main_thread_cpu = static_cast<u8>(main_thread_core);
|
||||
npdm_header.main_stack_size = main_thread_stack_size;
|
||||
aci_header.title_id = title_id;
|
||||
aci_file_access.permissions = filesystem_permissions;
|
||||
|
||||
@@ -47,8 +47,8 @@ public:
|
||||
Loader::ResultStatus Load(VirtualFile file);
|
||||
|
||||
// Load from parameters instead of NPDM file, used for KIP
|
||||
void LoadManual(bool is_64_bit, ProgramAddressSpaceType address_space, u8 main_thread_prio,
|
||||
u8 main_thread_core, u32 main_thread_stack_size, u64 title_id,
|
||||
void LoadManual(bool is_64_bit, ProgramAddressSpaceType address_space, s32 main_thread_prio,
|
||||
u32 main_thread_core, u32 main_thread_stack_size, u64 title_id,
|
||||
u64 filesystem_permissions, KernelCapabilityDescriptors capabilities);
|
||||
|
||||
bool Is64BitProgram() const;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/swap.h"
|
||||
#include "core/file_sys/fsmitm_romfsbuild.h"
|
||||
@@ -12,7 +14,7 @@
|
||||
#include "core/file_sys/vfs_vector.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
namespace {
|
||||
constexpr u32 ROMFS_ENTRY_EMPTY = 0xFFFFFFFF;
|
||||
|
||||
struct TableLocation {
|
||||
@@ -51,7 +53,7 @@ struct FileEntry {
|
||||
static_assert(sizeof(FileEntry) == 0x20, "FileEntry has incorrect size.");
|
||||
|
||||
template <typename Entry>
|
||||
static std::pair<Entry, std::string> GetEntry(const VirtualFile& file, std::size_t offset) {
|
||||
std::pair<Entry, std::string> GetEntry(const VirtualFile& file, std::size_t offset) {
|
||||
Entry entry{};
|
||||
if (file->ReadObject(&entry, offset) != sizeof(Entry))
|
||||
return {};
|
||||
@@ -99,6 +101,7 @@ void ProcessDirectory(VirtualFile file, std::size_t dir_offset, std::size_t file
|
||||
this_dir_offset = entry.first.sibling;
|
||||
}
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
VirtualDir ExtractRomFS(VirtualFile file, RomFSExtractionType type) {
|
||||
RomFSHeader header{};
|
||||
|
||||
@@ -5,10 +5,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/swap.h"
|
||||
#include "core/file_sys/vfs.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
@@ -71,12 +71,12 @@ ResultVal<VirtualFile> RomFSFactory::Open(u64 title_id, StorageId storage,
|
||||
|
||||
if (res == nullptr) {
|
||||
// TODO(DarkLordZach): Find the right error code to use here
|
||||
return ResultCode(-1);
|
||||
return RESULT_UNKNOWN;
|
||||
}
|
||||
const auto romfs = res->GetRomFS();
|
||||
if (romfs == nullptr) {
|
||||
// TODO(DarkLordZach): Find the right error code to use here
|
||||
return ResultCode(-1);
|
||||
return RESULT_UNKNOWN;
|
||||
}
|
||||
return MakeResult<VirtualFile>(romfs);
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ ResultVal<VirtualDir> SaveDataFactory::Create(SaveDataSpaceId space,
|
||||
// Return an error if the save data doesn't actually exist.
|
||||
if (out == nullptr) {
|
||||
// TODO(DarkLordZach): Find out correct error code.
|
||||
return ResultCode(-1);
|
||||
return RESULT_UNKNOWN;
|
||||
}
|
||||
|
||||
return MakeResult<VirtualDir>(std::move(out));
|
||||
@@ -111,7 +111,7 @@ ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space,
|
||||
// Return an error if the save data doesn't actually exist.
|
||||
if (out == nullptr) {
|
||||
// TODO(Subv): Find out correct error code.
|
||||
return ResultCode(-1);
|
||||
return RESULT_UNKNOWN;
|
||||
}
|
||||
|
||||
return MakeResult<VirtualDir>(std::move(out));
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "core/file_sys/system_archive/shared_font.h"
|
||||
#include "core/file_sys/system_archive/system_archive.h"
|
||||
#include "core/file_sys/system_archive/system_version.h"
|
||||
#include "core/file_sys/system_archive/time_zone_binary.h"
|
||||
|
||||
namespace FileSys::SystemArchive {
|
||||
|
||||
@@ -38,7 +39,7 @@ constexpr std::array<SystemArchiveDescriptor, SYSTEM_ARCHIVE_COUNT> SYSTEM_ARCHI
|
||||
{0x010000000000080B, "LocalNews", nullptr},
|
||||
{0x010000000000080C, "Eula", nullptr},
|
||||
{0x010000000000080D, "UrlBlackList", nullptr},
|
||||
{0x010000000000080E, "TimeZoneBinary", nullptr},
|
||||
{0x010000000000080E, "TimeZoneBinary", &TimeZoneBinary},
|
||||
{0x010000000000080F, "CertStoreCruiser", nullptr},
|
||||
{0x0100000000000810, "FontNintendoExtension", &FontNintendoExtension},
|
||||
{0x0100000000000811, "FontStandard", &FontStandard},
|
||||
|
||||
657
src/core/file_sys/system_archive/time_zone_binary.cpp
Normal file
657
src/core/file_sys/system_archive/time_zone_binary.cpp
Normal file
@@ -0,0 +1,657 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/swap.h"
|
||||
#include "core/file_sys/system_archive/time_zone_binary.h"
|
||||
#include "core/file_sys/vfs_vector.h"
|
||||
#include "core/hle/service/time/time_zone_types.h"
|
||||
|
||||
namespace FileSys::SystemArchive {
|
||||
|
||||
static constexpr std::array<u8, 9633> LOCATION_NAMES{
|
||||
0x43, 0x45, 0x54, 0x0d, 0x0a, 0x43, 0x53, 0x54, 0x36, 0x43, 0x44, 0x54, 0x0d, 0x0a, 0x43, 0x75,
|
||||
0x62, 0x61, 0x0d, 0x0a, 0x45, 0x45, 0x54, 0x0d, 0x0a, 0x45, 0x67, 0x79, 0x70, 0x74, 0x0d, 0x0a,
|
||||
0x45, 0x69, 0x72, 0x65, 0x0d, 0x0a, 0x45, 0x53, 0x54, 0x0d, 0x0a, 0x45, 0x53, 0x54, 0x35, 0x45,
|
||||
0x44, 0x54, 0x0d, 0x0a, 0x47, 0x42, 0x0d, 0x0a, 0x47, 0x42, 0x2d, 0x45, 0x69, 0x72, 0x65, 0x0d,
|
||||
0x0a, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x47, 0x4d, 0x54, 0x2b, 0x30, 0x0d, 0x0a, 0x47, 0x4d, 0x54,
|
||||
0x2d, 0x30, 0x0d, 0x0a, 0x47, 0x4d, 0x54, 0x30, 0x0d, 0x0a, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x77,
|
||||
0x69, 0x63, 0x68, 0x0d, 0x0a, 0x48, 0x6f, 0x6e, 0x67, 0x6b, 0x6f, 0x6e, 0x67, 0x0d, 0x0a, 0x48,
|
||||
0x53, 0x54, 0x0d, 0x0a, 0x49, 0x63, 0x65, 0x6c, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x49, 0x72, 0x61,
|
||||
0x6e, 0x0d, 0x0a, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x0d, 0x0a, 0x4a, 0x61, 0x6d, 0x61, 0x69,
|
||||
0x63, 0x61, 0x0d, 0x0a, 0x4a, 0x61, 0x70, 0x61, 0x6e, 0x0d, 0x0a, 0x4b, 0x77, 0x61, 0x6a, 0x61,
|
||||
0x6c, 0x65, 0x69, 0x6e, 0x0d, 0x0a, 0x4c, 0x69, 0x62, 0x79, 0x61, 0x0d, 0x0a, 0x4d, 0x45, 0x54,
|
||||
0x0d, 0x0a, 0x4d, 0x53, 0x54, 0x0d, 0x0a, 0x4d, 0x53, 0x54, 0x37, 0x4d, 0x44, 0x54, 0x0d, 0x0a,
|
||||
0x4e, 0x61, 0x76, 0x61, 0x6a, 0x6f, 0x0d, 0x0a, 0x4e, 0x5a, 0x0d, 0x0a, 0x4e, 0x5a, 0x2d, 0x43,
|
||||
0x48, 0x41, 0x54, 0x0d, 0x0a, 0x50, 0x6f, 0x6c, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x50, 0x6f, 0x72,
|
||||
0x74, 0x75, 0x67, 0x61, 0x6c, 0x0d, 0x0a, 0x50, 0x52, 0x43, 0x0d, 0x0a, 0x50, 0x53, 0x54, 0x38,
|
||||
0x50, 0x44, 0x54, 0x0d, 0x0a, 0x52, 0x4f, 0x43, 0x0d, 0x0a, 0x52, 0x4f, 0x4b, 0x0d, 0x0a, 0x53,
|
||||
0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x0d, 0x0a, 0x54, 0x75, 0x72, 0x6b, 0x65, 0x79,
|
||||
0x0d, 0x0a, 0x55, 0x43, 0x54, 0x0d, 0x0a, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c,
|
||||
0x0d, 0x0a, 0x55, 0x54, 0x43, 0x0d, 0x0a, 0x57, 0x2d, 0x53, 0x55, 0x0d, 0x0a, 0x57, 0x45, 0x54,
|
||||
0x0d, 0x0a, 0x5a, 0x75, 0x6c, 0x75, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41,
|
||||
0x62, 0x69, 0x64, 0x6a, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41,
|
||||
0x63, 0x63, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x64, 0x64,
|
||||
0x69, 0x73, 0x5f, 0x41, 0x62, 0x61, 0x62, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x41, 0x6c, 0x67, 0x69, 0x65, 0x72, 0x73, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x41, 0x73, 0x6d, 0x61, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x41, 0x73, 0x6d, 0x65, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42,
|
||||
0x61, 0x6d, 0x61, 0x6b, 0x6f, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61,
|
||||
0x6e, 0x67, 0x75, 0x69, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x6e,
|
||||
0x6a, 0x75, 0x6c, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x73,
|
||||
0x61, 0x75, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x74,
|
||||
0x79, 0x72, 0x65, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x72, 0x61, 0x7a,
|
||||
0x7a, 0x61, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x42, 0x75, 0x6a, 0x75, 0x6d, 0x62, 0x75, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63,
|
||||
0x61, 0x2f, 0x43, 0x61, 0x69, 0x72, 0x6f, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x43, 0x61, 0x73, 0x61, 0x62, 0x6c, 0x61, 0x6e, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x43, 0x65, 0x75, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x43, 0x6f, 0x6e, 0x61, 0x6b, 0x72, 0x79, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x44, 0x61, 0x6b, 0x61, 0x72, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44,
|
||||
0x61, 0x72, 0x5f, 0x65, 0x73, 0x5f, 0x53, 0x61, 0x6c, 0x61, 0x61, 0x6d, 0x0d, 0x0a, 0x41, 0x66,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x0d, 0x0a, 0x41,
|
||||
0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x75, 0x61, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x66,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x6c, 0x5f, 0x41, 0x61, 0x69, 0x75, 0x6e, 0x0d, 0x0a, 0x41,
|
||||
0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x72, 0x65, 0x65, 0x74, 0x6f, 0x77, 0x6e, 0x0d, 0x0a,
|
||||
0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x61, 0x62, 0x6f, 0x72, 0x6f, 0x6e, 0x65, 0x0d,
|
||||
0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x72, 0x61, 0x72, 0x65, 0x0d, 0x0a,
|
||||
0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x6f, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x73, 0x62,
|
||||
0x75, 0x72, 0x67, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x75, 0x62, 0x61,
|
||||
0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x70, 0x61, 0x6c, 0x61,
|
||||
0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x68, 0x61, 0x72, 0x74, 0x6f, 0x75,
|
||||
0x6d, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x67, 0x61, 0x6c, 0x69,
|
||||
0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x6e, 0x73, 0x68, 0x61, 0x73,
|
||||
0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x61, 0x67, 0x6f, 0x73, 0x0d,
|
||||
0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x62, 0x72, 0x65, 0x76, 0x69, 0x6c,
|
||||
0x6c, 0x65, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x6d, 0x65, 0x0d,
|
||||
0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x61, 0x6e, 0x64, 0x61, 0x0d, 0x0a,
|
||||
0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x62, 0x75, 0x6d, 0x62, 0x61, 0x73, 0x68,
|
||||
0x69, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x73, 0x61, 0x6b, 0x61,
|
||||
0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6c, 0x61, 0x62, 0x6f, 0x0d,
|
||||
0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x70, 0x75, 0x74, 0x6f, 0x0d, 0x0a,
|
||||
0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x73, 0x65, 0x72, 0x75, 0x0d, 0x0a, 0x41,
|
||||
0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x62, 0x61, 0x62, 0x61, 0x6e, 0x65, 0x0d, 0x0a, 0x41,
|
||||
0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x67, 0x61, 0x64, 0x69, 0x73, 0x68, 0x75, 0x0d,
|
||||
0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x72, 0x6f, 0x76, 0x69, 0x61,
|
||||
0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61, 0x69, 0x72, 0x6f, 0x62, 0x69,
|
||||
0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x64, 0x6a, 0x61, 0x6d, 0x65, 0x6e,
|
||||
0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x61, 0x6d, 0x65, 0x79,
|
||||
0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x75, 0x61, 0x6b, 0x63, 0x68,
|
||||
0x6f, 0x74, 0x74, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x75, 0x61, 0x67,
|
||||
0x61, 0x64, 0x6f, 0x75, 0x67, 0x6f, 0x75, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x50, 0x6f, 0x72, 0x74, 0x6f, 0x2d, 0x4e, 0x6f, 0x76, 0x6f, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x53, 0x61, 0x6f, 0x5f, 0x54, 0x6f, 0x6d, 0x65, 0x0d, 0x0a, 0x41, 0x66, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x54, 0x69, 0x6d, 0x62, 0x75, 0x6b, 0x74, 0x75, 0x0d, 0x0a, 0x41, 0x66,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x72, 0x69, 0x70, 0x6f, 0x6c, 0x69, 0x0d, 0x0a, 0x41, 0x66,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x75, 0x6e, 0x69, 0x73, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x64, 0x68, 0x6f, 0x65, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x64, 0x61, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x0d, 0x0a, 0x41, 0x6d,
|
||||
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x67, 0x75, 0x69, 0x6c, 0x6c, 0x61, 0x0d, 0x0a,
|
||||
0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x74, 0x69, 0x67, 0x75, 0x61, 0x0d,
|
||||
0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x61, 0x67, 0x75, 0x61, 0x69,
|
||||
0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x75, 0x62,
|
||||
0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x75, 0x6e, 0x63,
|
||||
0x69, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x74, 0x69,
|
||||
0x6b, 0x6f, 0x6b, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41,
|
||||
0x74, 0x6b, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68,
|
||||
0x69, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x69,
|
||||
0x61, 0x5f, 0x42, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x61, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x6f, 0x73, 0x0d, 0x0a, 0x41, 0x6d,
|
||||
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65, 0x6c, 0x65, 0x6d, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x63, 0x2d, 0x53, 0x61, 0x62, 0x6c, 0x6f,
|
||||
0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x61, 0x5f, 0x56,
|
||||
0x69, 0x73, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f,
|
||||
0x67, 0x6f, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f,
|
||||
0x69, 0x73, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65,
|
||||
0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69, 0x72, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x42, 0x61, 0x79,
|
||||
0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x70, 0x6f, 0x5f,
|
||||
0x47, 0x72, 0x61, 0x6e, 0x64, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x43, 0x61, 0x6e, 0x63, 0x75, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x43, 0x61, 0x72, 0x61, 0x63, 0x61, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x43, 0x61, 0x74, 0x61, 0x6d, 0x61, 0x72, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79, 0x65, 0x6e, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79, 0x6d, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x0d, 0x0a, 0x41, 0x6d,
|
||||
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61, 0x0d,
|
||||
0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x72, 0x61, 0x6c, 0x5f, 0x48,
|
||||
0x61, 0x72, 0x62, 0x6f, 0x75, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x43, 0x6f, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x43, 0x6f, 0x73, 0x74, 0x61, 0x5f, 0x52, 0x69, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d,
|
||||
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x69, 0x61, 0x62, 0x61, 0x0d, 0x0a, 0x41, 0x6d,
|
||||
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x61, 0x63, 0x61, 0x6f, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x73, 0x68,
|
||||
0x61, 0x76, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x77,
|
||||
0x73, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x77,
|
||||
0x73, 0x6f, 0x6e, 0x5f, 0x43, 0x72, 0x65, 0x65, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x44, 0x65, 0x74, 0x72, 0x6f, 0x69, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x6d,
|
||||
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x64, 0x6d, 0x6f, 0x6e, 0x74, 0x6f, 0x6e, 0x0d, 0x0a,
|
||||
0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x69, 0x72, 0x75, 0x6e, 0x65, 0x70, 0x65,
|
||||
0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x6c, 0x5f, 0x53, 0x61, 0x6c,
|
||||
0x76, 0x61, 0x64, 0x6f, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45,
|
||||
0x6e, 0x73, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x46, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x65, 0x7a, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x5f, 0x4e, 0x65, 0x6c, 0x73, 0x6f, 0x6e, 0x0d,
|
||||
0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x5f, 0x57, 0x61,
|
||||
0x79, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6c, 0x61,
|
||||
0x63, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x47, 0x6f, 0x64, 0x74, 0x68, 0x61, 0x62, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x47, 0x6f, 0x6f, 0x73, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x61, 0x6e, 0x64, 0x5f, 0x54, 0x75, 0x72, 0x6b, 0x0d, 0x0a,
|
||||
0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x0d,
|
||||
0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x65, 0x6c, 0x6f,
|
||||
0x75, 0x70, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61,
|
||||
0x74, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x47, 0x75, 0x61, 0x79, 0x61, 0x71, 0x75, 0x69, 0x6c, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69, 0x66, 0x61, 0x78, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x76, 0x61, 0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x48, 0x65, 0x72, 0x6d, 0x6f, 0x73, 0x69, 0x6c, 0x6c, 0x6f, 0x0d, 0x0a,
|
||||
0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x70,
|
||||
0x6f, 0x6c, 0x69, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e,
|
||||
0x75, 0x76, 0x69, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x71,
|
||||
0x61, 0x6c, 0x75, 0x69, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a,
|
||||
0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x4a, 0x75, 0x6a, 0x75, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a,
|
||||
0x75, 0x6e, 0x65, 0x61, 0x75, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b,
|
||||
0x6e, 0x6f, 0x78, 0x5f, 0x49, 0x4e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x4b, 0x72, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x69, 0x6a, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x50, 0x61, 0x7a, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x6d, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
|
||||
0x61, 0x2f, 0x4c, 0x6f, 0x73, 0x5f, 0x41, 0x6e, 0x67, 0x65, 0x6c, 0x65, 0x73, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x75, 0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c,
|
||||
0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x77, 0x65, 0x72,
|
||||
0x5f, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
|
||||
0x61, 0x2f, 0x4d, 0x61, 0x63, 0x65, 0x69, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
|
||||
0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x75, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x75, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x67, 0x6f, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x0d, 0x0a,
|
||||
0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x74, 0x61, 0x6d, 0x6f, 0x72, 0x6f,
|
||||
0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x7a, 0x61, 0x74,
|
||||
0x6c, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x6e,
|
||||
0x64, 0x6f, 0x7a, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65,
|
||||
0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x4d, 0x65, 0x72, 0x69, 0x64, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x4d, 0x65, 0x74, 0x6c, 0x61, 0x6b, 0x61, 0x74, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x5f, 0x43, 0x69, 0x74, 0x79,
|
||||
0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x69, 0x71, 0x75, 0x65, 0x6c,
|
||||
0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x63,
|
||||
0x74, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e,
|
||||
0x74, 0x65, 0x72, 0x72, 0x65, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x72, 0x65, 0x61, 0x6c, 0x0d, 0x0a, 0x41, 0x6d,
|
||||
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x73, 0x65, 0x72, 0x72, 0x61, 0x74,
|
||||
0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61, 0x73, 0x73, 0x61, 0x75,
|
||||
0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x59, 0x6f,
|
||||
0x72, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x70, 0x69,
|
||||
0x67, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x6d,
|
||||
0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x6f, 0x6e,
|
||||
0x68, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x6a, 0x69, 0x6e,
|
||||
0x61, 0x67, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e,
|
||||
0x61, 0x6d, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e,
|
||||
0x67, 0x6e, 0x69, 0x72, 0x74, 0x75, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
|
||||
0x61, 0x2f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x61, 0x72, 0x69, 0x62, 0x6f, 0x0d, 0x0a, 0x41, 0x6d,
|
||||
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x68, 0x6f, 0x65, 0x6e, 0x69, 0x78, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x2d, 0x61, 0x75, 0x2d, 0x50,
|
||||
0x72, 0x69, 0x6e, 0x63, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50,
|
||||
0x6f, 0x72, 0x74, 0x6f, 0x5f, 0x41, 0x63, 0x72, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x5f, 0x56, 0x65, 0x6c, 0x68, 0x6f, 0x0d, 0x0a,
|
||||
0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x66, 0x5f,
|
||||
0x53, 0x70, 0x61, 0x69, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50,
|
||||
0x75, 0x65, 0x72, 0x74, 0x6f, 0x5f, 0x52, 0x69, 0x63, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x50, 0x75, 0x6e, 0x74, 0x61, 0x5f, 0x41, 0x72, 0x65, 0x6e, 0x61, 0x73,
|
||||
0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x61, 0x69, 0x6e, 0x79, 0x5f,
|
||||
0x52, 0x69, 0x76, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52,
|
||||
0x61, 0x6e, 0x6b, 0x69, 0x6e, 0x5f, 0x49, 0x6e, 0x6c, 0x65, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x63, 0x69, 0x66, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x67, 0x69, 0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x42, 0x72, 0x61, 0x6e, 0x63,
|
||||
0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x6f, 0x73, 0x61, 0x72,
|
||||
0x69, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74,
|
||||
0x61, 0x72, 0x65, 0x6d, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61,
|
||||
0x6e, 0x74, 0x61, 0x5f, 0x49, 0x73, 0x61, 0x62, 0x65, 0x6c, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x67, 0x6f, 0x0d, 0x0a, 0x41, 0x6d,
|
||||
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x6f, 0x5f, 0x44, 0x6f, 0x6d, 0x69,
|
||||
0x6e, 0x67, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6f,
|
||||
0x5f, 0x50, 0x61, 0x75, 0x6c, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x53, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x73, 0x75, 0x6e, 0x64, 0x0d, 0x0a, 0x41, 0x6d,
|
||||
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x68, 0x69, 0x70, 0x72, 0x6f, 0x63, 0x6b, 0x0d, 0x0a,
|
||||
0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x69, 0x74, 0x6b, 0x61, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x42, 0x61, 0x72, 0x74, 0x68, 0x65,
|
||||
0x6c, 0x65, 0x6d, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74,
|
||||
0x5f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x53, 0x74, 0x5f, 0x4b, 0x69, 0x74, 0x74, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
|
||||
0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4c, 0x75, 0x63, 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x54, 0x68, 0x6f, 0x6d, 0x61, 0x73, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e,
|
||||
0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x77, 0x69, 0x66, 0x74,
|
||||
0x5f, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
|
||||
0x61, 0x2f, 0x54, 0x65, 0x67, 0x75, 0x63, 0x69, 0x67, 0x61, 0x6c, 0x70, 0x61, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6c, 0x65, 0x0d, 0x0a, 0x41, 0x6d,
|
||||
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x42, 0x61,
|
||||
0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x69, 0x6a, 0x75, 0x61,
|
||||
0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f, 0x72, 0x6f,
|
||||
0x6e, 0x74, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f, 0x72,
|
||||
0x74, 0x6f, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x56, 0x61,
|
||||
0x6e, 0x63, 0x6f, 0x75, 0x76, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x56, 0x69, 0x72, 0x67, 0x69, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x57, 0x68, 0x69, 0x74, 0x65, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x6e, 0x69, 0x70, 0x65, 0x67, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x61, 0x74, 0x0d, 0x0a,
|
||||
0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x59, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6b, 0x6e,
|
||||
0x69, 0x66, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67,
|
||||
0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69,
|
||||
0x72, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67,
|
||||
0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x43, 0x61, 0x74, 0x61, 0x6d, 0x61, 0x72, 0x63, 0x61,
|
||||
0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74,
|
||||
0x69, 0x6e, 0x61, 0x2f, 0x43, 0x6f, 0x6d, 0x6f, 0x64, 0x52, 0x69, 0x76, 0x61, 0x64, 0x61, 0x76,
|
||||
0x69, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65,
|
||||
0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x43, 0x6f, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61,
|
||||
0x2f, 0x4a, 0x75, 0x6a, 0x75, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x52, 0x69, 0x6f,
|
||||
0x6a, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65,
|
||||
0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x64, 0x6f, 0x7a, 0x61, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61,
|
||||
0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x47, 0x61, 0x6c, 0x6c, 0x65, 0x67, 0x6f, 0x73, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61,
|
||||
0x2f, 0x53, 0x61, 0x6c, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4a, 0x75,
|
||||
0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65,
|
||||
0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4c, 0x75, 0x69, 0x73, 0x0d, 0x0a,
|
||||
0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e,
|
||||
0x61, 0x2f, 0x54, 0x75, 0x63, 0x75, 0x6d, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x55, 0x73, 0x68,
|
||||
0x75, 0x61, 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e,
|
||||
0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x70, 0x6f, 0x6c,
|
||||
0x69, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69,
|
||||
0x61, 0x6e, 0x61, 0x2f, 0x4b, 0x6e, 0x6f, 0x78, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
|
||||
0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x65, 0x6e, 0x67,
|
||||
0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61,
|
||||
0x6e, 0x61, 0x2f, 0x50, 0x65, 0x74, 0x65, 0x72, 0x73, 0x62, 0x75, 0x72, 0x67, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x54,
|
||||
0x65, 0x6c, 0x6c, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
|
||||
0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x65, 0x76, 0x61, 0x79, 0x0d,
|
||||
0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61,
|
||||
0x2f, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x61,
|
||||
0x6d, 0x61, 0x63, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x65, 0x6e,
|
||||
0x74, 0x75, 0x63, 0x6b, 0x79, 0x2f, 0x4c, 0x6f, 0x75, 0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c, 0x65,
|
||||
0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x65, 0x6e, 0x74, 0x75, 0x63,
|
||||
0x6b, 0x79, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x69, 0x63, 0x65, 0x6c, 0x6c, 0x6f, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b,
|
||||
0x6f, 0x74, 0x61, 0x2f, 0x42, 0x65, 0x75, 0x6c, 0x61, 0x68, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61,
|
||||
0x2f, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x4e, 0x65,
|
||||
0x77, 0x5f, 0x53, 0x61, 0x6c, 0x65, 0x6d, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x73, 0x65, 0x79, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72,
|
||||
0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x76, 0x69, 0x73, 0x0d, 0x0a, 0x41, 0x6e, 0x74,
|
||||
0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x75, 0x6d, 0x6f, 0x6e, 0x74, 0x44, 0x55,
|
||||
0x72, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x71, 0x75, 0x61, 0x72, 0x69, 0x65, 0x0d, 0x0a, 0x41, 0x6e,
|
||||
0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x0d,
|
||||
0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x63, 0x4d, 0x75,
|
||||
0x72, 0x64, 0x6f, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x50, 0x61, 0x6c, 0x6d, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x52, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61,
|
||||
0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x5f, 0x50, 0x6f, 0x6c,
|
||||
0x65, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x79,
|
||||
0x6f, 0x77, 0x61, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x54, 0x72, 0x6f, 0x6c, 0x6c, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63,
|
||||
0x61, 0x2f, 0x56, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0d, 0x0a, 0x41, 0x72, 0x63, 0x74, 0x69, 0x63,
|
||||
0x2f, 0x4c, 0x6f, 0x6e, 0x67, 0x79, 0x65, 0x61, 0x72, 0x62, 0x79, 0x65, 0x6e, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41,
|
||||
0x6c, 0x6d, 0x61, 0x74, 0x79, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6d, 0x6d, 0x61,
|
||||
0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6e, 0x61, 0x64, 0x79, 0x72, 0x0d, 0x0a,
|
||||
0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x61, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x41, 0x71, 0x74, 0x6f, 0x62, 0x65, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x73,
|
||||
0x68, 0x67, 0x61, 0x62, 0x61, 0x74, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x73, 0x68,
|
||||
0x6b, 0x68, 0x61, 0x62, 0x61, 0x64, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x74, 0x79,
|
||||
0x72, 0x61, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x67, 0x68, 0x64, 0x61,
|
||||
0x64, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x72, 0x61, 0x69, 0x6e, 0x0d,
|
||||
0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x6b, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x42, 0x61, 0x6e, 0x67, 0x6b, 0x6f, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42,
|
||||
0x61, 0x72, 0x6e, 0x61, 0x75, 0x6c, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x65, 0x69,
|
||||
0x72, 0x75, 0x74, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x68, 0x6b, 0x65,
|
||||
0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x0d, 0x0a,
|
||||
0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x74, 0x74, 0x61, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f,
|
||||
0x43, 0x68, 0x6f, 0x69, 0x62, 0x61, 0x6c, 0x73, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x43, 0x68, 0x6f, 0x6e, 0x67, 0x71, 0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x43, 0x68, 0x75, 0x6e, 0x67, 0x6b, 0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x43, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x6f, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44,
|
||||
0x61, 0x63, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x61, 0x6d, 0x61, 0x73,
|
||||
0x63, 0x75, 0x73, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x68, 0x61, 0x6b, 0x61, 0x0d,
|
||||
0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x69, 0x6c, 0x69, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x44, 0x75, 0x62, 0x61, 0x69, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x75, 0x73,
|
||||
0x68, 0x61, 0x6e, 0x62, 0x65, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x46, 0x61, 0x6d, 0x61,
|
||||
0x67, 0x75, 0x73, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x47, 0x61, 0x7a, 0x61,
|
||||
0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x61, 0x72, 0x62, 0x69, 0x6e, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x48, 0x65, 0x62, 0x72, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x48, 0x6f, 0x6e, 0x67, 0x5f, 0x4b, 0x6f, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x48, 0x6f, 0x76, 0x64, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x5f, 0x43,
|
||||
0x68, 0x69, 0x5f, 0x4d, 0x69, 0x6e, 0x68, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x49, 0x72,
|
||||
0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x49, 0x73, 0x74, 0x61,
|
||||
0x6e, 0x62, 0x75, 0x6c, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x61, 0x6b, 0x61, 0x72,
|
||||
0x74, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x61, 0x79, 0x61, 0x70, 0x75, 0x72,
|
||||
0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x65, 0x72, 0x75, 0x73, 0x61, 0x6c, 0x65,
|
||||
0x6d, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x62, 0x75, 0x6c, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x72, 0x61, 0x63, 0x68, 0x69, 0x0d, 0x0a, 0x41, 0x73, 0x69,
|
||||
0x61, 0x2f, 0x4b, 0x61, 0x73, 0x68, 0x67, 0x61, 0x72, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f,
|
||||
0x4b, 0x61, 0x74, 0x68, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f,
|
||||
0x4b, 0x61, 0x74, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b,
|
||||
0x68, 0x61, 0x6e, 0x64, 0x79, 0x67, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x6f,
|
||||
0x6c, 0x6b, 0x61, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73,
|
||||
0x6e, 0x6f, 0x79, 0x61, 0x72, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75,
|
||||
0x61, 0x6c, 0x61, 0x5f, 0x4c, 0x75, 0x6d, 0x70, 0x75, 0x72, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x4b, 0x75, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b,
|
||||
0x75, 0x77, 0x61, 0x69, 0x74, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x61,
|
||||
0x6f, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x67, 0x61, 0x64, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69,
|
||||
0x61, 0x2f, 0x4d, 0x61, 0x6b, 0x61, 0x73, 0x73, 0x61, 0x72, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x4d, 0x61, 0x6e, 0x69, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x75,
|
||||
0x73, 0x63, 0x61, 0x74, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x69, 0x63, 0x6f, 0x73,
|
||||
0x69, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f, 0x6b, 0x75, 0x7a,
|
||||
0x6e, 0x65, 0x74, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f,
|
||||
0x73, 0x69, 0x62, 0x69, 0x72, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x6d,
|
||||
0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x72, 0x61, 0x6c, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x50, 0x68, 0x6e, 0x6f, 0x6d, 0x5f, 0x50, 0x65, 0x6e, 0x68, 0x0d, 0x0a,
|
||||
0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x6f, 0x6e, 0x74, 0x69, 0x61, 0x6e, 0x61, 0x6b, 0x0d, 0x0a,
|
||||
0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x79, 0x6f, 0x6e, 0x67, 0x79, 0x61, 0x6e, 0x67, 0x0d, 0x0a,
|
||||
0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x61, 0x74, 0x61, 0x72, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x51, 0x79, 0x7a, 0x79, 0x6c, 0x6f, 0x72, 0x64, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x52, 0x61, 0x6e, 0x67, 0x6f, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x52,
|
||||
0x69, 0x79, 0x61, 0x64, 0x68, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x69, 0x67,
|
||||
0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x6b, 0x68, 0x61, 0x6c, 0x69,
|
||||
0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x6e,
|
||||
0x64, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x65, 0x6f, 0x75, 0x6c, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x53, 0x68, 0x61, 0x6e, 0x67, 0x68, 0x61, 0x69, 0x0d, 0x0a, 0x41, 0x73,
|
||||
0x69, 0x61, 0x2f, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x0d, 0x0a, 0x41, 0x73,
|
||||
0x69, 0x61, 0x2f, 0x53, 0x72, 0x65, 0x64, 0x6e, 0x65, 0x6b, 0x6f, 0x6c, 0x79, 0x6d, 0x73, 0x6b,
|
||||
0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x69, 0x70, 0x65, 0x69, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e, 0x74, 0x0d, 0x0a, 0x41, 0x73,
|
||||
0x69, 0x61, 0x2f, 0x54, 0x62, 0x69, 0x6c, 0x69, 0x73, 0x69, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x54, 0x65, 0x68, 0x72, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x65,
|
||||
0x6c, 0x5f, 0x41, 0x76, 0x69, 0x76, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x68, 0x69,
|
||||
0x6d, 0x62, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x68, 0x69, 0x6d, 0x70, 0x68,
|
||||
0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x54, 0x6f, 0x6d, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f,
|
||||
0x55, 0x6a, 0x75, 0x6e, 0x67, 0x5f, 0x50, 0x61, 0x6e, 0x64, 0x61, 0x6e, 0x67, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61, 0x74, 0x61, 0x72, 0x0d,
|
||||
0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x6e, 0x5f, 0x42, 0x61, 0x74, 0x6f, 0x72,
|
||||
0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x72, 0x75, 0x6d, 0x71, 0x69, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x55, 0x73, 0x74, 0x2d, 0x4e, 0x65, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x73,
|
||||
0x69, 0x61, 0x2f, 0x56, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x73,
|
||||
0x69, 0x61, 0x2f, 0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0d, 0x0a,
|
||||
0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73,
|
||||
0x69, 0x61, 0x2f, 0x59, 0x61, 0x6e, 0x67, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f,
|
||||
0x59, 0x65, 0x6b, 0x61, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x59, 0x65, 0x72, 0x65, 0x76, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x74, 0x6c,
|
||||
0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x74,
|
||||
0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61, 0x0d, 0x0a,
|
||||
0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x6e, 0x61, 0x72, 0x79, 0x0d,
|
||||
0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x70, 0x65, 0x5f, 0x56,
|
||||
0x65, 0x72, 0x64, 0x65, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x46,
|
||||
0x61, 0x65, 0x72, 0x6f, 0x65, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f,
|
||||
0x46, 0x61, 0x72, 0x6f, 0x65, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f,
|
||||
0x4a, 0x61, 0x6e, 0x5f, 0x4d, 0x61, 0x79, 0x65, 0x6e, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e,
|
||||
0x74, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x64, 0x65, 0x69, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x74, 0x6c,
|
||||
0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x52, 0x65, 0x79, 0x6b, 0x6a, 0x61, 0x76, 0x69, 0x6b, 0x0d,
|
||||
0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x5f,
|
||||
0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69,
|
||||
0x63, 0x2f, 0x53, 0x74, 0x61, 0x6e, 0x6c, 0x65, 0x79, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e,
|
||||
0x74, 0x69, 0x63, 0x2f, 0x53, 0x74, 0x5f, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x0d, 0x0a, 0x41,
|
||||
0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x43, 0x54, 0x0d, 0x0a, 0x41, 0x75,
|
||||
0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65, 0x6c, 0x61, 0x69, 0x64, 0x65,
|
||||
0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x69, 0x73,
|
||||
0x62, 0x61, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f,
|
||||
0x42, 0x72, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x48, 0x69, 0x6c, 0x6c, 0x0d, 0x0a, 0x41, 0x75, 0x73,
|
||||
0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6e, 0x62, 0x65, 0x72, 0x72, 0x61, 0x0d,
|
||||
0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x72, 0x69,
|
||||
0x65, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x44, 0x61, 0x72,
|
||||
0x77, 0x69, 0x6e, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x45,
|
||||
0x75, 0x63, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f,
|
||||
0x48, 0x6f, 0x62, 0x61, 0x72, 0x74, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69,
|
||||
0x61, 0x2f, 0x4c, 0x48, 0x49, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
|
||||
0x2f, 0x4c, 0x69, 0x6e, 0x64, 0x65, 0x6d, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72,
|
||||
0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4c, 0x6f, 0x72, 0x64, 0x5f, 0x48, 0x6f, 0x77, 0x65, 0x0d, 0x0a,
|
||||
0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4d, 0x65, 0x6c, 0x62, 0x6f, 0x75,
|
||||
0x72, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4e,
|
||||
0x6f, 0x72, 0x74, 0x68, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f,
|
||||
0x4e, 0x53, 0x57, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x50,
|
||||
0x65, 0x72, 0x74, 0x68, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f,
|
||||
0x51, 0x75, 0x65, 0x65, 0x6e, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74,
|
||||
0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x0d, 0x0a, 0x41, 0x75, 0x73,
|
||||
0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79, 0x0d, 0x0a, 0x41,
|
||||
0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x6d, 0x61, 0x6e, 0x69,
|
||||
0x61, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x56, 0x69, 0x63,
|
||||
0x74, 0x6f, 0x72, 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
|
||||
0x2f, 0x57, 0x65, 0x73, 0x74, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
|
||||
0x2f, 0x59, 0x61, 0x6e, 0x63, 0x6f, 0x77, 0x69, 0x6e, 0x6e, 0x61, 0x0d, 0x0a, 0x42, 0x72, 0x61,
|
||||
0x7a, 0x69, 0x6c, 0x2f, 0x41, 0x63, 0x72, 0x65, 0x0d, 0x0a, 0x42, 0x72, 0x61, 0x7a, 0x69, 0x6c,
|
||||
0x2f, 0x44, 0x65, 0x4e, 0x6f, 0x72, 0x6f, 0x6e, 0x68, 0x61, 0x0d, 0x0a, 0x42, 0x72, 0x61, 0x7a,
|
||||
0x69, 0x6c, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x0d, 0x0a, 0x42, 0x72, 0x61, 0x7a, 0x69, 0x6c, 0x2f,
|
||||
0x57, 0x65, 0x73, 0x74, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x41, 0x74, 0x6c,
|
||||
0x61, 0x6e, 0x74, 0x69, 0x63, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x43, 0x65,
|
||||
0x6e, 0x74, 0x72, 0x61, 0x6c, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x45, 0x61,
|
||||
0x73, 0x74, 0x2d, 0x53, 0x61, 0x73, 0x6b, 0x61, 0x74, 0x63, 0x68, 0x65, 0x77, 0x61, 0x6e, 0x0d,
|
||||
0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x0d,
|
||||
0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e,
|
||||
0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x66, 0x6f, 0x75, 0x6e,
|
||||
0x64, 0x6c, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x50, 0x61,
|
||||
0x63, 0x69, 0x66, 0x69, 0x63, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x53, 0x61,
|
||||
0x73, 0x6b, 0x61, 0x74, 0x63, 0x68, 0x65, 0x77, 0x61, 0x6e, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61,
|
||||
0x64, 0x61, 0x2f, 0x59, 0x75, 0x6b, 0x6f, 0x6e, 0x0d, 0x0a, 0x43, 0x68, 0x69, 0x6c, 0x65, 0x2f,
|
||||
0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x0d, 0x0a, 0x43, 0x68, 0x69,
|
||||
0x6c, 0x65, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x0d,
|
||||
0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
|
||||
0x54, 0x2b, 0x30, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x0d, 0x0a,
|
||||
0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x30, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f,
|
||||
0x47, 0x4d, 0x54, 0x2b, 0x31, 0x31, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b,
|
||||
0x31, 0x32, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x32, 0x0d, 0x0a, 0x45,
|
||||
0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x33, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
|
||||
0x54, 0x2b, 0x34, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x35, 0x0d, 0x0a,
|
||||
0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x36, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47,
|
||||
0x4d, 0x54, 0x2b, 0x37, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x38, 0x0d,
|
||||
0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x39, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f,
|
||||
0x47, 0x4d, 0x54, 0x2d, 0x30, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31,
|
||||
0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x30, 0x0d, 0x0a, 0x45, 0x74,
|
||||
0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x31, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
|
||||
0x54, 0x2d, 0x31, 0x32, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x33,
|
||||
0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x34, 0x0d, 0x0a, 0x45, 0x74,
|
||||
0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x32, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54,
|
||||
0x2d, 0x33, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x34, 0x0d, 0x0a, 0x45,
|
||||
0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x35, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
|
||||
0x54, 0x2d, 0x36, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x37, 0x0d, 0x0a,
|
||||
0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x38, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47,
|
||||
0x4d, 0x54, 0x2d, 0x39, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x30, 0x0d, 0x0a,
|
||||
0x45, 0x74, 0x63, 0x2f, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x77, 0x69, 0x63, 0x68, 0x0d, 0x0a, 0x45,
|
||||
0x74, 0x63, 0x2f, 0x55, 0x43, 0x54, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x55, 0x6e, 0x69, 0x76,
|
||||
0x65, 0x72, 0x73, 0x61, 0x6c, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x55, 0x54, 0x43, 0x0d, 0x0a,
|
||||
0x45, 0x74, 0x63, 0x2f, 0x5a, 0x75, 0x6c, 0x75, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
|
||||
0x2f, 0x41, 0x6d, 0x73, 0x74, 0x65, 0x72, 0x64, 0x61, 0x6d, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f,
|
||||
0x70, 0x65, 0x2f, 0x41, 0x6e, 0x64, 0x6f, 0x72, 0x72, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f,
|
||||
0x70, 0x65, 0x2f, 0x41, 0x73, 0x74, 0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x0d, 0x0a, 0x45, 0x75,
|
||||
0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x74, 0x68, 0x65, 0x6e, 0x73, 0x0d, 0x0a, 0x45, 0x75, 0x72,
|
||||
0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x6c, 0x66, 0x61, 0x73, 0x74, 0x0d, 0x0a, 0x45, 0x75, 0x72,
|
||||
0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x6c, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x45, 0x75,
|
||||
0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72,
|
||||
0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6c, 0x61, 0x76, 0x61, 0x0d, 0x0a,
|
||||
0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x75, 0x73, 0x73, 0x65, 0x6c, 0x73, 0x0d,
|
||||
0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x63, 0x68, 0x61, 0x72, 0x65, 0x73,
|
||||
0x74, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65,
|
||||
0x73, 0x74, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x73, 0x69, 0x6e,
|
||||
0x67, 0x65, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, 0x68, 0x69, 0x73,
|
||||
0x69, 0x6e, 0x61, 0x75, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, 0x6f, 0x70,
|
||||
0x65, 0x6e, 0x68, 0x61, 0x67, 0x65, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
|
||||
0x44, 0x75, 0x62, 0x6c, 0x69, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47,
|
||||
0x69, 0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
|
||||
0x2f, 0x47, 0x75, 0x65, 0x72, 0x6e, 0x73, 0x65, 0x79, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70,
|
||||
0x65, 0x2f, 0x48, 0x65, 0x6c, 0x73, 0x69, 0x6e, 0x6b, 0x69, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f,
|
||||
0x70, 0x65, 0x2f, 0x49, 0x73, 0x6c, 0x65, 0x5f, 0x6f, 0x66, 0x5f, 0x4d, 0x61, 0x6e, 0x0d, 0x0a,
|
||||
0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x49, 0x73, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x6c, 0x0d,
|
||||
0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4a, 0x65, 0x72, 0x73, 0x65, 0x79, 0x0d, 0x0a,
|
||||
0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x61, 0x6c, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x72,
|
||||
0x61, 0x64, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x0d,
|
||||
0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x72, 0x6f, 0x76, 0x0d, 0x0a, 0x45,
|
||||
0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x69, 0x73, 0x62, 0x6f, 0x6e, 0x0d, 0x0a, 0x45, 0x75,
|
||||
0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6a, 0x75, 0x62, 0x6c, 0x6a, 0x61, 0x6e, 0x61, 0x0d, 0x0a,
|
||||
0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e, 0x0d, 0x0a, 0x45,
|
||||
0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x6f, 0x75, 0x72, 0x67,
|
||||
0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x64, 0x72, 0x69, 0x64, 0x0d,
|
||||
0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x6c, 0x74, 0x61, 0x0d, 0x0a, 0x45,
|
||||
0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x65, 0x68, 0x61, 0x6d, 0x6e, 0x0d,
|
||||
0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x69, 0x6e, 0x73, 0x6b, 0x0d, 0x0a, 0x45,
|
||||
0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x6e, 0x61, 0x63, 0x6f, 0x0d, 0x0a, 0x45, 0x75,
|
||||
0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x0d, 0x0a, 0x45, 0x75, 0x72,
|
||||
0x6f, 0x70, 0x65, 0x2f, 0x4e, 0x69, 0x63, 0x6f, 0x73, 0x69, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72,
|
||||
0x6f, 0x70, 0x65, 0x2f, 0x4f, 0x73, 0x6c, 0x6f, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
|
||||
0x2f, 0x50, 0x61, 0x72, 0x69, 0x73, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50,
|
||||
0x6f, 0x64, 0x67, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
|
||||
0x2f, 0x50, 0x72, 0x61, 0x67, 0x75, 0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
|
||||
0x52, 0x69, 0x67, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x52, 0x6f, 0x6d,
|
||||
0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x61,
|
||||
0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4d, 0x61, 0x72,
|
||||
0x69, 0x6e, 0x6f, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72, 0x61,
|
||||
0x6a, 0x65, 0x76, 0x6f, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72,
|
||||
0x61, 0x74, 0x6f, 0x76, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x69, 0x6d,
|
||||
0x66, 0x65, 0x72, 0x6f, 0x70, 0x6f, 0x6c, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
|
||||
0x53, 0x6b, 0x6f, 0x70, 0x6a, 0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53,
|
||||
0x6f, 0x66, 0x69, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x74, 0x6f,
|
||||
0x63, 0x6b, 0x68, 0x6f, 0x6c, 0x6d, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54,
|
||||
0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54,
|
||||
0x69, 0x72, 0x61, 0x6e, 0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54, 0x69,
|
||||
0x72, 0x61, 0x73, 0x70, 0x6f, 0x6c, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x55,
|
||||
0x6c, 0x79, 0x61, 0x6e, 0x6f, 0x76, 0x73, 0x6b, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
|
||||
0x2f, 0x55, 0x7a, 0x68, 0x67, 0x6f, 0x72, 0x6f, 0x64, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70,
|
||||
0x65, 0x2f, 0x56, 0x61, 0x64, 0x75, 0x7a, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
|
||||
0x56, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
|
||||
0x56, 0x69, 0x65, 0x6e, 0x6e, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56,
|
||||
0x69, 0x6c, 0x6e, 0x69, 0x75, 0x73, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56,
|
||||
0x6f, 0x6c, 0x67, 0x6f, 0x67, 0x72, 0x61, 0x64, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
|
||||
0x2f, 0x57, 0x61, 0x72, 0x73, 0x61, 0x77, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
|
||||
0x5a, 0x61, 0x67, 0x72, 0x65, 0x62, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a,
|
||||
0x61, 0x70, 0x6f, 0x72, 0x6f, 0x7a, 0x68, 0x79, 0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70,
|
||||
0x65, 0x2f, 0x5a, 0x75, 0x72, 0x69, 0x63, 0x68, 0x0d, 0x0a, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e,
|
||||
0x2f, 0x41, 0x6e, 0x74, 0x61, 0x6e, 0x61, 0x6e, 0x61, 0x72, 0x69, 0x76, 0x6f, 0x0d, 0x0a, 0x49,
|
||||
0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x68, 0x61, 0x67, 0x6f, 0x73, 0x0d, 0x0a, 0x49, 0x6e,
|
||||
0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x0d, 0x0a,
|
||||
0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x63, 0x6f, 0x73, 0x0d, 0x0a, 0x49, 0x6e,
|
||||
0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x6d, 0x6f, 0x72, 0x6f, 0x0d, 0x0a, 0x49, 0x6e, 0x64,
|
||||
0x69, 0x61, 0x6e, 0x2f, 0x4b, 0x65, 0x72, 0x67, 0x75, 0x65, 0x6c, 0x65, 0x6e, 0x0d, 0x0a, 0x49,
|
||||
0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x68, 0x65, 0x0d, 0x0a, 0x49, 0x6e, 0x64, 0x69,
|
||||
0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x6c, 0x64, 0x69, 0x76, 0x65, 0x73, 0x0d, 0x0a, 0x49, 0x6e, 0x64,
|
||||
0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x0d, 0x0a, 0x49,
|
||||
0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x79, 0x6f, 0x74, 0x74, 0x65, 0x0d, 0x0a, 0x49,
|
||||
0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x52, 0x65, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x0d, 0x0a, 0x4d,
|
||||
0x65, 0x78, 0x69, 0x63, 0x6f, 0x2f, 0x42, 0x61, 0x6a, 0x61, 0x4e, 0x6f, 0x72, 0x74, 0x65, 0x0d,
|
||||
0x0a, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x2f, 0x42, 0x61, 0x6a, 0x61, 0x53, 0x75, 0x72, 0x0d,
|
||||
0x0a, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x2f, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x0d,
|
||||
0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x70, 0x69, 0x61, 0x0d, 0x0a, 0x50,
|
||||
0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x75, 0x63, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x0d,
|
||||
0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x42, 0x6f, 0x75, 0x67, 0x61, 0x69, 0x6e,
|
||||
0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x43,
|
||||
0x68, 0x61, 0x74, 0x68, 0x61, 0x6d, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
|
||||
0x43, 0x68, 0x75, 0x75, 0x6b, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45,
|
||||
0x61, 0x73, 0x74, 0x65, 0x72, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45,
|
||||
0x66, 0x61, 0x74, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x6e,
|
||||
0x64, 0x65, 0x72, 0x62, 0x75, 0x72, 0x79, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
|
||||
0x2f, 0x46, 0x61, 0x6b, 0x61, 0x6f, 0x66, 0x6f, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
|
||||
0x63, 0x2f, 0x46, 0x69, 0x6a, 0x69, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
|
||||
0x46, 0x75, 0x6e, 0x61, 0x66, 0x75, 0x74, 0x69, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
|
||||
0x63, 0x2f, 0x47, 0x61, 0x6c, 0x61, 0x70, 0x61, 0x67, 0x6f, 0x73, 0x0d, 0x0a, 0x50, 0x61, 0x63,
|
||||
0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x65, 0x72, 0x0d, 0x0a, 0x50, 0x61,
|
||||
0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x61, 0x6c, 0x63, 0x61, 0x6e, 0x61,
|
||||
0x6c, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x6d, 0x0d,
|
||||
0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x48, 0x6f, 0x6e, 0x6f, 0x6c, 0x75, 0x6c,
|
||||
0x75, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4a, 0x6f, 0x68, 0x6e, 0x73,
|
||||
0x74, 0x6f, 0x6e, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x69, 0x72,
|
||||
0x69, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
|
||||
0x2f, 0x4b, 0x6f, 0x73, 0x72, 0x61, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
|
||||
0x2f, 0x4b, 0x77, 0x61, 0x6a, 0x61, 0x6c, 0x65, 0x69, 0x6e, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69,
|
||||
0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x6a, 0x75, 0x72, 0x6f, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69,
|
||||
0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x72, 0x71, 0x75, 0x65, 0x73, 0x61, 0x73, 0x0d, 0x0a, 0x50,
|
||||
0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x69, 0x64, 0x77, 0x61, 0x79, 0x0d, 0x0a, 0x50,
|
||||
0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x61, 0x75, 0x72, 0x75, 0x0d, 0x0a, 0x50, 0x61,
|
||||
0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x69, 0x75, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69,
|
||||
0x66, 0x69, 0x63, 0x2f, 0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x0d, 0x0a, 0x50, 0x61, 0x63,
|
||||
0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x6f, 0x75, 0x6d, 0x65, 0x61, 0x0d, 0x0a, 0x50, 0x61, 0x63,
|
||||
0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x67, 0x6f, 0x5f, 0x50, 0x61, 0x67, 0x6f, 0x0d, 0x0a,
|
||||
0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x6c, 0x61, 0x75, 0x0d, 0x0a, 0x50,
|
||||
0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x69, 0x74, 0x63, 0x61, 0x69, 0x72, 0x6e, 0x0d,
|
||||
0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x68, 0x6e, 0x70, 0x65, 0x69,
|
||||
0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x6e, 0x61, 0x70, 0x65,
|
||||
0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x4d,
|
||||
0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
|
||||
0x52, 0x61, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66,
|
||||
0x69, 0x63, 0x2f, 0x53, 0x61, 0x69, 0x70, 0x61, 0x6e, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66,
|
||||
0x69, 0x63, 0x2f, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
|
||||
0x63, 0x2f, 0x54, 0x61, 0x68, 0x69, 0x74, 0x69, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
|
||||
0x63, 0x2f, 0x54, 0x61, 0x72, 0x61, 0x77, 0x61, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
|
||||
0x63, 0x2f, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x74, 0x61, 0x70, 0x75, 0x0d, 0x0a, 0x50, 0x61, 0x63,
|
||||
0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x72, 0x75, 0x6b, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66,
|
||||
0x69, 0x63, 0x2f, 0x57, 0x61, 0x6b, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
|
||||
0x2f, 0x57, 0x61, 0x6c, 0x6c, 0x69, 0x73, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
|
||||
0x2f, 0x59, 0x61, 0x70, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x41, 0x6c, 0x61, 0x73, 0x6b, 0x61, 0x0d,
|
||||
0x0a, 0x55, 0x53, 0x2f, 0x41, 0x6c, 0x65, 0x75, 0x74, 0x69, 0x61, 0x6e, 0x0d, 0x0a, 0x55, 0x53,
|
||||
0x2f, 0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x43, 0x65, 0x6e,
|
||||
0x74, 0x72, 0x61, 0x6c, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x2d, 0x49, 0x6e,
|
||||
0x64, 0x69, 0x61, 0x6e, 0x61, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72,
|
||||
0x6e, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x48, 0x61, 0x77, 0x61, 0x69, 0x69, 0x0d, 0x0a, 0x55, 0x53,
|
||||
0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2d, 0x53, 0x74, 0x61, 0x72, 0x6b, 0x65, 0x0d,
|
||||
0x0a, 0x55, 0x53, 0x2f, 0x4d, 0x69, 0x63, 0x68, 0x69, 0x67, 0x61, 0x6e, 0x0d, 0x0a, 0x55, 0x53,
|
||||
0x2f, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x50, 0x61,
|
||||
0x63, 0x69, 0x66, 0x69, 0x63, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
|
||||
0x63, 0x2d, 0x4e, 0x65, 0x77, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x0d,
|
||||
0x0a};
|
||||
|
||||
static VirtualFile GenerateDefaultTimeZoneFile() {
|
||||
struct {
|
||||
s64_be at;
|
||||
INSERT_PADDING_BYTES(7);
|
||||
std::array<char, 4> time_zone_chars;
|
||||
INSERT_PADDING_BYTES(2);
|
||||
std::array<char, 6> time_zone_name;
|
||||
} time_zone_info{};
|
||||
|
||||
const VirtualFile file{std::make_shared<VectorVfsFile>(
|
||||
std::vector<u8>(sizeof(Service::Time::TimeZone::TzifHeader) + sizeof(time_zone_info)),
|
||||
"GMT")};
|
||||
|
||||
Service::Time::TimeZone::TzifHeader header{};
|
||||
header.magic = 0x545a6966;
|
||||
header.version = 0x32;
|
||||
header.ttis_gmt_count = 0x1;
|
||||
header.ttis_std_count = 0x1;
|
||||
header.time_count = 0x1;
|
||||
header.type_count = 0x1;
|
||||
header.char_count = 0x4;
|
||||
file->WriteObject(header, 0);
|
||||
|
||||
time_zone_info.at = 0xf8;
|
||||
time_zone_info.time_zone_chars = {'G', 'M', 'T', '\0'};
|
||||
time_zone_info.time_zone_name = {'\n', 'G', 'M', 'T', '0', '\n'};
|
||||
file->WriteObject(time_zone_info, sizeof(Service::Time::TimeZone::TzifHeader));
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
VirtualDir TimeZoneBinary() {
|
||||
const std::vector<VirtualDir> root_dirs{std::make_shared<VectorVfsDirectory>(
|
||||
std::vector<VirtualFile>{GenerateDefaultTimeZoneFile()}, std::vector<VirtualDir>{},
|
||||
"zoneinfo")};
|
||||
const std::vector<VirtualFile> root_files{
|
||||
std::make_shared<ArrayVfsFile<LOCATION_NAMES.size()>>(LOCATION_NAMES, "binaryList.txt")};
|
||||
return std::make_shared<VectorVfsDirectory>(root_files, root_dirs, "data");
|
||||
}
|
||||
|
||||
} // namespace FileSys::SystemArchive
|
||||
14
src/core/file_sys/system_archive/time_zone_binary.h
Normal file
14
src/core/file_sys/system_archive/time_zone_binary.h
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "core/file_sys/vfs_types.h"
|
||||
|
||||
namespace FileSys::SystemArchive {
|
||||
|
||||
VirtualDir TimeZoneBinary();
|
||||
|
||||
} // namespace FileSys::SystemArchive
|
||||
@@ -27,7 +27,7 @@ VirtualDir ExtractZIP(VirtualFile file) {
|
||||
|
||||
std::shared_ptr<VectorVfsDirectory> out = std::make_shared<VectorVfsDirectory>();
|
||||
|
||||
const auto num_entries = zip_get_num_entries(zip.get(), 0);
|
||||
const auto num_entries = static_cast<std::size_t>(zip_get_num_entries(zip.get(), 0));
|
||||
|
||||
zip_stat_t stat{};
|
||||
zip_stat_init(&stat);
|
||||
|
||||
@@ -7,12 +7,13 @@
|
||||
#include <cstring>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
|
||||
#include <mbedtls/md.h>
|
||||
#include <mbedtls/sha256.h>
|
||||
#include "common/assert.h"
|
||||
|
||||
#include "common/file_util.h"
|
||||
#include "common/hex_util.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/string_util.h"
|
||||
#include "core/crypto/aes_util.h"
|
||||
#include "core/crypto/xts_encryption_layer.h"
|
||||
#include "core/file_sys/partition_filesystem.h"
|
||||
@@ -53,11 +54,8 @@ NAX::NAX(VirtualFile file_) : header(std::make_unique<NAXHeader>()), file(std::m
|
||||
return;
|
||||
}
|
||||
|
||||
std::string two_dir = match[1];
|
||||
std::string nca_id = match[2];
|
||||
std::transform(two_dir.begin(), two_dir.end(), two_dir.begin(), ::toupper);
|
||||
std::transform(nca_id.begin(), nca_id.end(), nca_id.begin(), ::tolower);
|
||||
|
||||
const std::string two_dir = Common::ToUpper(match[1]);
|
||||
const std::string nca_id = Common::ToLower(match[2]);
|
||||
status = Parse(fmt::format("/registered/{}/{}.nca", two_dir, nca_id));
|
||||
}
|
||||
|
||||
|
||||
@@ -26,9 +26,6 @@ public:
|
||||
|
||||
/// Releases (dunno if this is the "right" word) the context from the caller thread
|
||||
virtual void DoneCurrent() = 0;
|
||||
|
||||
/// Swap buffers to display the next frame
|
||||
virtual void SwapBuffers() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -75,6 +72,13 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Returns if window is shown (not minimized)
|
||||
virtual bool IsShown() const = 0;
|
||||
|
||||
/// Retrieves Vulkan specific handlers from the window
|
||||
virtual void RetrieveVulkanHandlers(void* get_instance_proc_addr, void* instance,
|
||||
void* surface) const = 0;
|
||||
|
||||
/**
|
||||
* Signal that a touch pressed event has occurred (e.g. mouse click pressed)
|
||||
* @param framebuffer_x Framebuffer x-coordinate that was pressed
|
||||
|
||||
@@ -27,9 +27,9 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height) {
|
||||
// so just calculate them both even if the other isn't showing.
|
||||
FramebufferLayout res{width, height};
|
||||
|
||||
const float emulation_aspect_ratio{static_cast<float>(ScreenUndocked::Height) /
|
||||
ScreenUndocked::Width};
|
||||
const auto window_aspect_ratio = static_cast<float>(height) / width;
|
||||
const float window_aspect_ratio = static_cast<float>(height) / width;
|
||||
const float emulation_aspect_ratio = EmulationAspectRatio(
|
||||
static_cast<AspectRatio>(Settings::values.aspect_ratio), window_aspect_ratio);
|
||||
|
||||
const Common::Rectangle<u32> screen_window_area{0, 0, width, height};
|
||||
Common::Rectangle<u32> screen = MaxRectangle(screen_window_area, emulation_aspect_ratio);
|
||||
@@ -48,8 +48,8 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale) {
|
||||
u32 width, height;
|
||||
|
||||
if (Settings::values.use_docked_mode) {
|
||||
width = ScreenDocked::WidthDocked * res_scale;
|
||||
height = ScreenDocked::HeightDocked * res_scale;
|
||||
width = ScreenDocked::Width * res_scale;
|
||||
height = ScreenDocked::Height * res_scale;
|
||||
} else {
|
||||
width = ScreenUndocked::Width * res_scale;
|
||||
height = ScreenUndocked::Height * res_scale;
|
||||
@@ -58,4 +58,19 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale) {
|
||||
return DefaultFrameLayout(width, height);
|
||||
}
|
||||
|
||||
float EmulationAspectRatio(AspectRatio aspect, float window_aspect_ratio) {
|
||||
switch (aspect) {
|
||||
case AspectRatio::Default:
|
||||
return static_cast<float>(ScreenUndocked::Height) / ScreenUndocked::Width;
|
||||
case AspectRatio::R4_3:
|
||||
return 3.0f / 4.0f;
|
||||
case AspectRatio::R21_9:
|
||||
return 9.0f / 21.0f;
|
||||
case AspectRatio::StretchToWindow:
|
||||
return window_aspect_ratio;
|
||||
default:
|
||||
return static_cast<float>(ScreenUndocked::Height) / ScreenUndocked::Width;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Layout
|
||||
|
||||
@@ -8,20 +8,28 @@
|
||||
|
||||
namespace Layout {
|
||||
|
||||
enum ScreenUndocked : u32 {
|
||||
Width = 1280,
|
||||
Height = 720,
|
||||
};
|
||||
namespace ScreenUndocked {
|
||||
constexpr u32 Width = 1280;
|
||||
constexpr u32 Height = 720;
|
||||
} // namespace ScreenUndocked
|
||||
|
||||
enum ScreenDocked : u32 {
|
||||
WidthDocked = 1920,
|
||||
HeightDocked = 1080,
|
||||
namespace ScreenDocked {
|
||||
constexpr u32 Width = 1920;
|
||||
constexpr u32 Height = 1080;
|
||||
} // namespace ScreenDocked
|
||||
|
||||
enum class AspectRatio {
|
||||
Default,
|
||||
R4_3,
|
||||
R21_9,
|
||||
StretchToWindow,
|
||||
};
|
||||
|
||||
/// Describes the layout of the window framebuffer
|
||||
struct FramebufferLayout {
|
||||
u32 width{ScreenUndocked::Width};
|
||||
u32 height{ScreenUndocked::Height};
|
||||
bool is_srgb{};
|
||||
|
||||
Common::Rectangle<u32> screen;
|
||||
|
||||
@@ -48,4 +56,12 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height);
|
||||
*/
|
||||
FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale);
|
||||
|
||||
/**
|
||||
* Convenience method to determine emulation aspect ratio
|
||||
* @param aspect Represents the index of aspect ratio stored in Settings::values.aspect_ratio
|
||||
* @param window_aspect_ratio Current window aspect ratio
|
||||
* @return Emulation render window aspect ratio
|
||||
*/
|
||||
float EmulationAspectRatio(AspectRatio aspect, float window_aspect_ratio);
|
||||
|
||||
} // namespace Layout
|
||||
|
||||
@@ -15,6 +15,13 @@
|
||||
|
||||
namespace Input {
|
||||
|
||||
enum class AnalogDirection : u8 {
|
||||
RIGHT,
|
||||
LEFT,
|
||||
UP,
|
||||
DOWN,
|
||||
};
|
||||
|
||||
/// An abstract class template for an input device (a button, an analog input, etc.).
|
||||
template <typename StatusType>
|
||||
class InputDevice {
|
||||
@@ -23,6 +30,9 @@ public:
|
||||
virtual StatusType GetStatus() const {
|
||||
return {};
|
||||
}
|
||||
virtual bool GetAnalogDirectionStatus(AnalogDirection direction) const {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
/// An abstract class template for a factory that can create input devices.
|
||||
|
||||
18
src/core/frontend/scope_acquire_context.cpp
Normal file
18
src/core/frontend/scope_acquire_context.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright 2019 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/frontend/emu_window.h"
|
||||
#include "core/frontend/scope_acquire_context.h"
|
||||
|
||||
namespace Core::Frontend {
|
||||
|
||||
ScopeAcquireContext::ScopeAcquireContext(Core::Frontend::GraphicsContext& context)
|
||||
: context{context} {
|
||||
context.MakeCurrent();
|
||||
}
|
||||
ScopeAcquireContext::~ScopeAcquireContext() {
|
||||
context.DoneCurrent();
|
||||
}
|
||||
|
||||
} // namespace Core::Frontend
|
||||
@@ -8,16 +8,16 @@
|
||||
|
||||
namespace Core::Frontend {
|
||||
|
||||
class EmuWindow;
|
||||
class GraphicsContext;
|
||||
|
||||
/// Helper class to acquire/release window context within a given scope
|
||||
class ScopeAcquireWindowContext : NonCopyable {
|
||||
class ScopeAcquireContext : NonCopyable {
|
||||
public:
|
||||
explicit ScopeAcquireWindowContext(Core::Frontend::EmuWindow& window);
|
||||
~ScopeAcquireWindowContext();
|
||||
explicit ScopeAcquireContext(Core::Frontend::GraphicsContext& context);
|
||||
~ScopeAcquireContext();
|
||||
|
||||
private:
|
||||
Core::Frontend::EmuWindow& emu_window;
|
||||
Core::Frontend::GraphicsContext& context;
|
||||
};
|
||||
|
||||
} // namespace Core::Frontend
|
||||
@@ -1,18 +0,0 @@
|
||||
// Copyright 2019 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/frontend/emu_window.h"
|
||||
#include "core/frontend/scope_acquire_window_context.h"
|
||||
|
||||
namespace Core::Frontend {
|
||||
|
||||
ScopeAcquireWindowContext::ScopeAcquireWindowContext(Core::Frontend::EmuWindow& emu_window_)
|
||||
: emu_window{emu_window_} {
|
||||
emu_window.MakeCurrent();
|
||||
}
|
||||
ScopeAcquireWindowContext::~ScopeAcquireWindowContext() {
|
||||
emu_window.DoneCurrent();
|
||||
}
|
||||
|
||||
} // namespace Core::Frontend
|
||||
@@ -35,7 +35,7 @@
|
||||
#include "common/swap.h"
|
||||
#include "core/arm/arm_interface.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_cpu.h"
|
||||
#include "core/core_manager.h"
|
||||
#include "core/gdbstub/gdbstub.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
#include "core/hle/kernel/scheduler.h"
|
||||
@@ -217,7 +217,7 @@ static u64 RegRead(std::size_t id, Kernel::Thread* thread = nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const auto& thread_context = thread->GetContext();
|
||||
const auto& thread_context = thread->GetContext64();
|
||||
|
||||
if (id < SP_REGISTER) {
|
||||
return thread_context.cpu_registers[id];
|
||||
@@ -239,7 +239,7 @@ static void RegWrite(std::size_t id, u64 val, Kernel::Thread* thread = nullptr)
|
||||
return;
|
||||
}
|
||||
|
||||
auto& thread_context = thread->GetContext();
|
||||
auto& thread_context = thread->GetContext64();
|
||||
|
||||
if (id < SP_REGISTER) {
|
||||
thread_context.cpu_registers[id] = val;
|
||||
@@ -259,7 +259,7 @@ static u128 FpuRead(std::size_t id, Kernel::Thread* thread = nullptr) {
|
||||
return u128{0};
|
||||
}
|
||||
|
||||
auto& thread_context = thread->GetContext();
|
||||
auto& thread_context = thread->GetContext64();
|
||||
|
||||
if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
|
||||
return thread_context.vector_registers[id - UC_ARM64_REG_Q0];
|
||||
@@ -275,7 +275,7 @@ static void FpuWrite(std::size_t id, u128 val, Kernel::Thread* thread = nullptr)
|
||||
return;
|
||||
}
|
||||
|
||||
auto& thread_context = thread->GetContext();
|
||||
auto& thread_context = thread->GetContext64();
|
||||
|
||||
if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
|
||||
thread_context.vector_registers[id - UC_ARM64_REG_Q0] = val;
|
||||
@@ -468,7 +468,8 @@ static u8 ReadByte() {
|
||||
|
||||
/// Calculate the checksum of the current command buffer.
|
||||
static u8 CalculateChecksum(const u8* buffer, std::size_t length) {
|
||||
return static_cast<u8>(std::accumulate(buffer, buffer + length, 0, std::plus<u8>()));
|
||||
return static_cast<u8>(std::accumulate(buffer, buffer + length, u8{0},
|
||||
[](u8 lhs, u8 rhs) { return u8(lhs + rhs); }));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -507,8 +508,9 @@ static void RemoveBreakpoint(BreakpointType type, VAddr addr) {
|
||||
bp->second.len, bp->second.addr, static_cast<int>(type));
|
||||
|
||||
if (type == BreakpointType::Execute) {
|
||||
Memory::WriteBlock(bp->second.addr, bp->second.inst.data(), bp->second.inst.size());
|
||||
Core::System::GetInstance().InvalidateCpuInstructionCaches();
|
||||
auto& system = Core::System::GetInstance();
|
||||
system.Memory().WriteBlock(bp->second.addr, bp->second.inst.data(), bp->second.inst.size());
|
||||
system.InvalidateCpuInstructionCaches();
|
||||
}
|
||||
p.erase(addr);
|
||||
}
|
||||
@@ -914,7 +916,7 @@ static void WriteRegister() {
|
||||
// Update ARM context, skipping scheduler - no running threads at this point
|
||||
Core::System::GetInstance()
|
||||
.ArmInterface(current_core)
|
||||
.LoadContext(current_thread->GetContext());
|
||||
.LoadContext(current_thread->GetContext64());
|
||||
|
||||
SendReply("OK");
|
||||
}
|
||||
@@ -945,7 +947,7 @@ static void WriteRegisters() {
|
||||
// Update ARM context, skipping scheduler - no running threads at this point
|
||||
Core::System::GetInstance()
|
||||
.ArmInterface(current_core)
|
||||
.LoadContext(current_thread->GetContext());
|
||||
.LoadContext(current_thread->GetContext64());
|
||||
|
||||
SendReply("OK");
|
||||
}
|
||||
@@ -968,12 +970,13 @@ static void ReadMemory() {
|
||||
SendReply("E01");
|
||||
}
|
||||
|
||||
if (!Memory::IsValidVirtualAddress(addr)) {
|
||||
auto& memory = Core::System::GetInstance().Memory();
|
||||
if (!memory.IsValidVirtualAddress(addr)) {
|
||||
return SendReply("E00");
|
||||
}
|
||||
|
||||
std::vector<u8> data(len);
|
||||
Memory::ReadBlock(addr, data.data(), len);
|
||||
memory.ReadBlock(addr, data.data(), len);
|
||||
|
||||
MemToGdbHex(reply, data.data(), len);
|
||||
reply[len * 2] = '\0';
|
||||
@@ -983,22 +986,23 @@ static void ReadMemory() {
|
||||
/// Modify location in memory with data received from the gdb client.
|
||||
static void WriteMemory() {
|
||||
auto start_offset = command_buffer + 1;
|
||||
auto addr_pos = std::find(start_offset, command_buffer + command_length, ',');
|
||||
VAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset));
|
||||
const auto addr_pos = std::find(start_offset, command_buffer + command_length, ',');
|
||||
const VAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset));
|
||||
|
||||
start_offset = addr_pos + 1;
|
||||
auto len_pos = std::find(start_offset, command_buffer + command_length, ':');
|
||||
u64 len = HexToLong(start_offset, static_cast<u64>(len_pos - start_offset));
|
||||
const auto len_pos = std::find(start_offset, command_buffer + command_length, ':');
|
||||
const u64 len = HexToLong(start_offset, static_cast<u64>(len_pos - start_offset));
|
||||
|
||||
if (!Memory::IsValidVirtualAddress(addr)) {
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.Memory();
|
||||
if (!memory.IsValidVirtualAddress(addr)) {
|
||||
return SendReply("E00");
|
||||
}
|
||||
|
||||
std::vector<u8> data(len);
|
||||
|
||||
GdbHexToMem(data.data(), len_pos + 1, len);
|
||||
Memory::WriteBlock(addr, data.data(), len);
|
||||
Core::System::GetInstance().InvalidateCpuInstructionCaches();
|
||||
memory.WriteBlock(addr, data.data(), len);
|
||||
system.InvalidateCpuInstructionCaches();
|
||||
SendReply("OK");
|
||||
}
|
||||
|
||||
@@ -1015,7 +1019,7 @@ static void Step() {
|
||||
// Update ARM context, skipping scheduler - no running threads at this point
|
||||
Core::System::GetInstance()
|
||||
.ArmInterface(current_core)
|
||||
.LoadContext(current_thread->GetContext());
|
||||
.LoadContext(current_thread->GetContext64());
|
||||
}
|
||||
step_loop = true;
|
||||
halt_loop = true;
|
||||
@@ -1054,12 +1058,15 @@ static bool CommitBreakpoint(BreakpointType type, VAddr addr, u64 len) {
|
||||
breakpoint.active = true;
|
||||
breakpoint.addr = addr;
|
||||
breakpoint.len = len;
|
||||
Memory::ReadBlock(addr, breakpoint.inst.data(), breakpoint.inst.size());
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.Memory();
|
||||
memory.ReadBlock(addr, breakpoint.inst.data(), breakpoint.inst.size());
|
||||
|
||||
static constexpr std::array<u8, 4> btrap{0x00, 0x7d, 0x20, 0xd4};
|
||||
if (type == BreakpointType::Execute) {
|
||||
Memory::WriteBlock(addr, btrap.data(), btrap.size());
|
||||
Core::System::GetInstance().InvalidateCpuInstructionCaches();
|
||||
memory.WriteBlock(addr, btrap.data(), btrap.size());
|
||||
system.InvalidateCpuInstructionCaches();
|
||||
}
|
||||
p.insert({addr, breakpoint});
|
||||
|
||||
|
||||
@@ -11,13 +11,12 @@
|
||||
namespace Core::Hardware {
|
||||
|
||||
InterruptManager::InterruptManager(Core::System& system_in) : system(system_in) {
|
||||
gpu_interrupt_event =
|
||||
system.CoreTiming().RegisterEvent("GPUInterrupt", [this](u64 message, s64) {
|
||||
auto nvdrv = system.ServiceManager().GetService<Service::Nvidia::NVDRV>("nvdrv");
|
||||
const u32 syncpt = static_cast<u32>(message >> 32);
|
||||
const u32 value = static_cast<u32>(message);
|
||||
nvdrv->SignalGPUInterruptSyncpt(syncpt, value);
|
||||
});
|
||||
gpu_interrupt_event = Core::Timing::CreateEvent("GPUInterrupt", [this](u64 message, s64) {
|
||||
auto nvdrv = system.ServiceManager().GetService<Service::Nvidia::NVDRV>("nvdrv");
|
||||
const u32 syncpt = static_cast<u32>(message >> 32);
|
||||
const u32 value = static_cast<u32>(message);
|
||||
nvdrv->SignalGPUInterruptSyncpt(syncpt, value);
|
||||
});
|
||||
}
|
||||
|
||||
InterruptManager::~InterruptManager() = default;
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Core {
|
||||
@@ -25,7 +27,7 @@ public:
|
||||
|
||||
private:
|
||||
Core::System& system;
|
||||
Core::Timing::EventType* gpu_interrupt_event{};
|
||||
std::shared_ptr<Core::Timing::EventType> gpu_interrupt_event;
|
||||
};
|
||||
|
||||
} // namespace Core::Hardware
|
||||
|
||||
47
src/core/hardware_properties.h
Normal file
47
src/core/hardware_properties.h
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright 2020 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Core {
|
||||
|
||||
namespace Hardware {
|
||||
|
||||
// The below clock rate is based on Switch's clockspeed being widely known as 1.020GHz
|
||||
// The exact value used is of course unverified.
|
||||
constexpr u64 BASE_CLOCK_RATE = 1019215872; // Switch cpu frequency is 1020MHz un/docked
|
||||
constexpr u64 CNTFREQ = 19200000; // Switch's hardware clock speed
|
||||
constexpr u32 NUM_CPU_CORES = 4; // Number of CPU Cores
|
||||
|
||||
} // namespace Hardware
|
||||
|
||||
constexpr u32 INVALID_HOST_THREAD_ID = 0xFFFFFFFF;
|
||||
|
||||
struct EmuThreadHandle {
|
||||
u32 host_handle;
|
||||
u32 guest_handle;
|
||||
|
||||
u64 GetRaw() const {
|
||||
return (static_cast<u64>(host_handle) << 32) | guest_handle;
|
||||
}
|
||||
|
||||
bool operator==(const EmuThreadHandle& rhs) const {
|
||||
return std::tie(host_handle, guest_handle) == std::tie(rhs.host_handle, rhs.guest_handle);
|
||||
}
|
||||
|
||||
bool operator!=(const EmuThreadHandle& rhs) const {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
static constexpr EmuThreadHandle InvalidHandle() {
|
||||
constexpr u32 invalid_handle = 0xFFFFFFFF;
|
||||
return {invalid_handle, invalid_handle};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
#include "core/hle/kernel/server_session.h"
|
||||
#include "core/hle/kernel/session.h"
|
||||
#include "core/hle/result.h"
|
||||
|
||||
namespace IPC {
|
||||
@@ -139,10 +140,9 @@ public:
|
||||
context->AddDomainObject(std::move(iface));
|
||||
} else {
|
||||
auto& kernel = Core::System::GetInstance().Kernel();
|
||||
auto [server, client] =
|
||||
Kernel::ServerSession::CreateSessionPair(kernel, iface->GetServiceName());
|
||||
iface->ClientConnected(server);
|
||||
auto [client, server] = Kernel::Session::Create(kernel, iface->GetServiceName());
|
||||
context->AddMoveObject(std::move(client));
|
||||
iface->ClientConnected(std::move(server));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,10 +203,10 @@ public:
|
||||
void PushRaw(const T& value);
|
||||
|
||||
template <typename... O>
|
||||
void PushMoveObjects(Kernel::SharedPtr<O>... pointers);
|
||||
void PushMoveObjects(std::shared_ptr<O>... pointers);
|
||||
|
||||
template <typename... O>
|
||||
void PushCopyObjects(Kernel::SharedPtr<O>... pointers);
|
||||
void PushCopyObjects(std::shared_ptr<O>... pointers);
|
||||
|
||||
private:
|
||||
u32 normal_params_size{};
|
||||
@@ -298,7 +298,7 @@ void ResponseBuilder::Push(const First& first_value, const Other&... other_value
|
||||
}
|
||||
|
||||
template <typename... O>
|
||||
inline void ResponseBuilder::PushCopyObjects(Kernel::SharedPtr<O>... pointers) {
|
||||
inline void ResponseBuilder::PushCopyObjects(std::shared_ptr<O>... pointers) {
|
||||
auto objects = {pointers...};
|
||||
for (auto& object : objects) {
|
||||
context->AddCopyObject(std::move(object));
|
||||
@@ -306,7 +306,7 @@ inline void ResponseBuilder::PushCopyObjects(Kernel::SharedPtr<O>... pointers) {
|
||||
}
|
||||
|
||||
template <typename... O>
|
||||
inline void ResponseBuilder::PushMoveObjects(Kernel::SharedPtr<O>... pointers) {
|
||||
inline void ResponseBuilder::PushMoveObjects(std::shared_ptr<O>... pointers) {
|
||||
auto objects = {pointers...};
|
||||
for (auto& object : objects) {
|
||||
context->AddMoveObject(std::move(object));
|
||||
@@ -357,10 +357,10 @@ public:
|
||||
T PopRaw();
|
||||
|
||||
template <typename T>
|
||||
Kernel::SharedPtr<T> GetMoveObject(std::size_t index);
|
||||
std::shared_ptr<T> GetMoveObject(std::size_t index);
|
||||
|
||||
template <typename T>
|
||||
Kernel::SharedPtr<T> GetCopyObject(std::size_t index);
|
||||
std::shared_ptr<T> GetCopyObject(std::size_t index);
|
||||
|
||||
template <class T>
|
||||
std::shared_ptr<T> PopIpcInterface() {
|
||||
@@ -465,12 +465,12 @@ void RequestParser::Pop(First& first_value, Other&... other_values) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Kernel::SharedPtr<T> RequestParser::GetMoveObject(std::size_t index) {
|
||||
std::shared_ptr<T> RequestParser::GetMoveObject(std::size_t index) {
|
||||
return context->GetMoveObject<T>(index);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Kernel::SharedPtr<T> RequestParser::GetCopyObject(std::size_t index) {
|
||||
std::shared_ptr<T> RequestParser::GetCopyObject(std::size_t index) {
|
||||
return context->GetCopyObject<T>(index);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,21 +8,18 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_cpu.h"
|
||||
#include "core/hle/kernel/address_arbiter.h"
|
||||
#include "core/hle/kernel/errors.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
#include "core/hle/kernel/scheduler.h"
|
||||
#include "core/hle/kernel/thread.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
namespace Kernel {
|
||||
namespace {
|
||||
|
||||
// Wake up num_to_wake (or all) threads in a vector.
|
||||
void WakeThreads(const std::vector<SharedPtr<Thread>>& waiting_threads, s32 num_to_wake) {
|
||||
auto& system = Core::System::GetInstance();
|
||||
void AddressArbiter::WakeThreads(const std::vector<std::shared_ptr<Thread>>& waiting_threads,
|
||||
s32 num_to_wake) {
|
||||
// Only process up to 'target' threads, unless 'target' is <= 0, in which case process
|
||||
// them all.
|
||||
std::size_t last = waiting_threads.size();
|
||||
@@ -34,12 +31,12 @@ void WakeThreads(const std::vector<SharedPtr<Thread>>& waiting_threads, s32 num_
|
||||
for (std::size_t i = 0; i < last; i++) {
|
||||
ASSERT(waiting_threads[i]->GetStatus() == ThreadStatus::WaitArb);
|
||||
waiting_threads[i]->SetWaitSynchronizationResult(RESULT_SUCCESS);
|
||||
RemoveThread(waiting_threads[i]);
|
||||
waiting_threads[i]->SetArbiterWaitAddress(0);
|
||||
waiting_threads[i]->ResumeFromWait();
|
||||
system.PrepareReschedule(waiting_threads[i]->GetProcessorID());
|
||||
}
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
AddressArbiter::AddressArbiter(Core::System& system) : system{system} {}
|
||||
AddressArbiter::~AddressArbiter() = default;
|
||||
@@ -59,35 +56,41 @@ ResultCode AddressArbiter::SignalToAddress(VAddr address, SignalType type, s32 v
|
||||
}
|
||||
|
||||
ResultCode AddressArbiter::SignalToAddressOnly(VAddr address, s32 num_to_wake) {
|
||||
const std::vector<SharedPtr<Thread>> waiting_threads = GetThreadsWaitingOnAddress(address);
|
||||
const std::vector<std::shared_ptr<Thread>> waiting_threads =
|
||||
GetThreadsWaitingOnAddress(address);
|
||||
WakeThreads(waiting_threads, num_to_wake);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
ResultCode AddressArbiter::IncrementAndSignalToAddressIfEqual(VAddr address, s32 value,
|
||||
s32 num_to_wake) {
|
||||
auto& memory = system.Memory();
|
||||
|
||||
// Ensure that we can write to the address.
|
||||
if (!Memory::IsValidVirtualAddress(address)) {
|
||||
if (!memory.IsValidVirtualAddress(address)) {
|
||||
return ERR_INVALID_ADDRESS_STATE;
|
||||
}
|
||||
|
||||
if (static_cast<s32>(Memory::Read32(address)) != value) {
|
||||
if (static_cast<s32>(memory.Read32(address)) != value) {
|
||||
return ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
Memory::Write32(address, static_cast<u32>(value + 1));
|
||||
memory.Write32(address, static_cast<u32>(value + 1));
|
||||
return SignalToAddressOnly(address, num_to_wake);
|
||||
}
|
||||
|
||||
ResultCode AddressArbiter::ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value,
|
||||
s32 num_to_wake) {
|
||||
auto& memory = system.Memory();
|
||||
|
||||
// Ensure that we can write to the address.
|
||||
if (!Memory::IsValidVirtualAddress(address)) {
|
||||
if (!memory.IsValidVirtualAddress(address)) {
|
||||
return ERR_INVALID_ADDRESS_STATE;
|
||||
}
|
||||
|
||||
// Get threads waiting on the address.
|
||||
const std::vector<SharedPtr<Thread>> waiting_threads = GetThreadsWaitingOnAddress(address);
|
||||
const std::vector<std::shared_ptr<Thread>> waiting_threads =
|
||||
GetThreadsWaitingOnAddress(address);
|
||||
|
||||
// Determine the modified value depending on the waiting count.
|
||||
s32 updated_value;
|
||||
@@ -107,11 +110,11 @@ ResultCode AddressArbiter::ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr a
|
||||
}
|
||||
}
|
||||
|
||||
if (static_cast<s32>(Memory::Read32(address)) != value) {
|
||||
if (static_cast<s32>(memory.Read32(address)) != value) {
|
||||
return ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
Memory::Write32(address, static_cast<u32>(updated_value));
|
||||
memory.Write32(address, static_cast<u32>(updated_value));
|
||||
WakeThreads(waiting_threads, num_to_wake);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
@@ -132,18 +135,20 @@ ResultCode AddressArbiter::WaitForAddress(VAddr address, ArbitrationType type, s
|
||||
|
||||
ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout,
|
||||
bool should_decrement) {
|
||||
auto& memory = system.Memory();
|
||||
|
||||
// Ensure that we can read the address.
|
||||
if (!Memory::IsValidVirtualAddress(address)) {
|
||||
if (!memory.IsValidVirtualAddress(address)) {
|
||||
return ERR_INVALID_ADDRESS_STATE;
|
||||
}
|
||||
|
||||
const s32 cur_value = static_cast<s32>(Memory::Read32(address));
|
||||
const s32 cur_value = static_cast<s32>(memory.Read32(address));
|
||||
if (cur_value >= value) {
|
||||
return ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (should_decrement) {
|
||||
Memory::Write32(address, static_cast<u32>(cur_value - 1));
|
||||
memory.Write32(address, static_cast<u32>(cur_value - 1));
|
||||
}
|
||||
|
||||
// Short-circuit without rescheduling, if timeout is zero.
|
||||
@@ -155,15 +160,19 @@ ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s6
|
||||
}
|
||||
|
||||
ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout) {
|
||||
auto& memory = system.Memory();
|
||||
|
||||
// Ensure that we can read the address.
|
||||
if (!Memory::IsValidVirtualAddress(address)) {
|
||||
if (!memory.IsValidVirtualAddress(address)) {
|
||||
return ERR_INVALID_ADDRESS_STATE;
|
||||
}
|
||||
|
||||
// Only wait for the address if equal.
|
||||
if (static_cast<s32>(Memory::Read32(address)) != value) {
|
||||
if (static_cast<s32>(memory.Read32(address)) != value) {
|
||||
return ERR_INVALID_STATE;
|
||||
}
|
||||
// Short-circuit without rescheduling, if timeout is zero.
|
||||
|
||||
// Short-circuit without rescheduling if timeout is zero.
|
||||
if (timeout == 0) {
|
||||
return RESULT_TIMEOUT;
|
||||
}
|
||||
@@ -172,36 +181,59 @@ ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 t
|
||||
}
|
||||
|
||||
ResultCode AddressArbiter::WaitForAddressImpl(VAddr address, s64 timeout) {
|
||||
SharedPtr<Thread> current_thread = system.CurrentScheduler().GetCurrentThread();
|
||||
Thread* current_thread = system.CurrentScheduler().GetCurrentThread();
|
||||
current_thread->SetArbiterWaitAddress(address);
|
||||
InsertThread(SharedFrom(current_thread));
|
||||
current_thread->SetStatus(ThreadStatus::WaitArb);
|
||||
current_thread->InvalidateWakeupCallback();
|
||||
|
||||
current_thread->WakeAfterDelay(timeout);
|
||||
|
||||
system.PrepareReschedule(current_thread->GetProcessorID());
|
||||
return RESULT_TIMEOUT;
|
||||
}
|
||||
|
||||
std::vector<SharedPtr<Thread>> AddressArbiter::GetThreadsWaitingOnAddress(VAddr address) const {
|
||||
void AddressArbiter::HandleWakeupThread(std::shared_ptr<Thread> thread) {
|
||||
ASSERT(thread->GetStatus() == ThreadStatus::WaitArb);
|
||||
RemoveThread(thread);
|
||||
thread->SetArbiterWaitAddress(0);
|
||||
}
|
||||
|
||||
// Retrieve all threads that are waiting for this address.
|
||||
std::vector<SharedPtr<Thread>> threads;
|
||||
const auto& scheduler = system.GlobalScheduler();
|
||||
const auto& thread_list = scheduler.GetThreadList();
|
||||
void AddressArbiter::InsertThread(std::shared_ptr<Thread> thread) {
|
||||
const VAddr arb_addr = thread->GetArbiterWaitAddress();
|
||||
std::list<std::shared_ptr<Thread>>& thread_list = arb_threads[arb_addr];
|
||||
|
||||
for (const auto& thread : thread_list) {
|
||||
if (thread->GetArbiterWaitAddress() == address) {
|
||||
threads.push_back(thread);
|
||||
}
|
||||
const auto iter =
|
||||
std::find_if(thread_list.cbegin(), thread_list.cend(), [&thread](const auto& entry) {
|
||||
return entry->GetPriority() >= thread->GetPriority();
|
||||
});
|
||||
|
||||
if (iter == thread_list.cend()) {
|
||||
thread_list.push_back(std::move(thread));
|
||||
} else {
|
||||
thread_list.insert(iter, std::move(thread));
|
||||
}
|
||||
}
|
||||
|
||||
void AddressArbiter::RemoveThread(std::shared_ptr<Thread> thread) {
|
||||
const VAddr arb_addr = thread->GetArbiterWaitAddress();
|
||||
std::list<std::shared_ptr<Thread>>& thread_list = arb_threads[arb_addr];
|
||||
|
||||
const auto iter = std::find_if(thread_list.cbegin(), thread_list.cend(),
|
||||
[&thread](const auto& entry) { return thread == entry; });
|
||||
|
||||
ASSERT(iter != thread_list.cend());
|
||||
|
||||
thread_list.erase(iter);
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Thread>> AddressArbiter::GetThreadsWaitingOnAddress(
|
||||
VAddr address) const {
|
||||
const auto iter = arb_threads.find(address);
|
||||
if (iter == arb_threads.cend()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// Sort them by priority, such that the highest priority ones come first.
|
||||
std::sort(threads.begin(), threads.end(),
|
||||
[](const SharedPtr<Thread>& lhs, const SharedPtr<Thread>& rhs) {
|
||||
return lhs->GetPriority() < rhs->GetPriority();
|
||||
});
|
||||
|
||||
return threads;
|
||||
const std::list<std::shared_ptr<Thread>>& thread_list = iter->second;
|
||||
return {thread_list.cbegin(), thread_list.cend()};
|
||||
}
|
||||
} // namespace Kernel
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
|
||||
union ResultCode;
|
||||
|
||||
@@ -48,6 +50,9 @@ public:
|
||||
/// Waits on an address with a particular arbitration type.
|
||||
ResultCode WaitForAddress(VAddr address, ArbitrationType type, s32 value, s64 timeout_ns);
|
||||
|
||||
/// Removes a thread from the container and resets its address arbiter adress to 0
|
||||
void HandleWakeupThread(std::shared_ptr<Thread> thread);
|
||||
|
||||
private:
|
||||
/// Signals an address being waited on.
|
||||
ResultCode SignalToAddressOnly(VAddr address, s32 num_to_wake);
|
||||
@@ -71,8 +76,20 @@ private:
|
||||
// Waits on the given address with a timeout in nanoseconds
|
||||
ResultCode WaitForAddressImpl(VAddr address, s64 timeout);
|
||||
|
||||
/// Wake up num_to_wake (or all) threads in a vector.
|
||||
void WakeThreads(const std::vector<std::shared_ptr<Thread>>& waiting_threads, s32 num_to_wake);
|
||||
|
||||
/// Insert a thread into the address arbiter container
|
||||
void InsertThread(std::shared_ptr<Thread> thread);
|
||||
|
||||
/// Removes a thread from the address arbiter container
|
||||
void RemoveThread(std::shared_ptr<Thread> thread);
|
||||
|
||||
// Gets the threads waiting on an address.
|
||||
std::vector<SharedPtr<Thread>> GetThreadsWaitingOnAddress(VAddr address) const;
|
||||
std::vector<std::shared_ptr<Thread>> GetThreadsWaitingOnAddress(VAddr address) const;
|
||||
|
||||
/// List of threads waiting for a address arbiter
|
||||
std::unordered_map<VAddr, std::list<std::shared_ptr<Thread>>> arb_threads;
|
||||
|
||||
Core::System& system;
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user