mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-10 03:21:30 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf97f39cac | ||
|
|
b6a45645d8 | ||
|
|
3d3c848ba7 | ||
|
|
c98dc7ef34 | ||
|
|
586f54a0f7 | ||
|
|
75f3a79aa6 | ||
|
|
27c3c1f684 | ||
|
|
5ee803682f | ||
|
|
e52daa8602 | ||
|
|
65cddce865 | ||
|
|
973ae36fe5 | ||
|
|
7b1819e988 | ||
|
|
538f0c534f | ||
|
|
921e470b05 | ||
|
|
ea4e5ab9ef | ||
|
|
96d0de4e7c | ||
|
|
04bd684258 | ||
|
|
58852ec9bb | ||
|
|
e4fcce118c | ||
|
|
ef149605cd | ||
|
|
c240449b10 | ||
|
|
8d63faa74d | ||
|
|
226f2d52ff | ||
|
|
1165f8dfe9 | ||
|
|
4e34611d1d | ||
|
|
0df043aff1 | ||
|
|
9573b53390 | ||
|
|
ca0edad8c2 | ||
|
|
f47b07e35a | ||
|
|
45db2122c9 | ||
|
|
d33624c623 | ||
|
|
abb1b28e96 | ||
|
|
a19da4bf22 | ||
|
|
347cb15722 | ||
|
|
20f3b8d404 | ||
|
|
31a7f2b4d9 | ||
|
|
e5a6517897 | ||
|
|
80f3f99845 | ||
|
|
4322d0c3fe | ||
|
|
764f1d846e | ||
|
|
1d0be580c5 | ||
|
|
44f2986665 | ||
|
|
9d6490e38a | ||
|
|
7aa914fde7 | ||
|
|
0930cd29fb | ||
|
|
695749f155 | ||
|
|
3ca8623b29 | ||
|
|
c6309d963d | ||
|
|
305aee2c33 | ||
|
|
cbcdfa572a | ||
|
|
2512365012 | ||
|
|
9988bae6f4 | ||
|
|
18f2b9c63e | ||
|
|
b5cc71720c | ||
|
|
6eed40f80c | ||
|
|
e93d90bc45 | ||
|
|
d057d2a202 | ||
|
|
cb67ace703 | ||
|
|
759724facb | ||
|
|
3033491f3d | ||
|
|
751ff8f72c | ||
|
|
d6d76a53b9 | ||
|
|
3224eefdf1 | ||
|
|
776ae626a6 | ||
|
|
8ad44acc5d | ||
|
|
ecbbf1e3bb | ||
|
|
2d31377ba8 | ||
|
|
e55692d74f | ||
|
|
6164e33b07 | ||
|
|
4850cc0f97 | ||
|
|
5674c46f38 | ||
|
|
a33280b08e | ||
|
|
48799b73d5 | ||
|
|
7c028596fb | ||
|
|
d93200d2eb | ||
|
|
aafee65238 | ||
|
|
f5a7504c38 | ||
|
|
ef4d24600e | ||
|
|
28ec64e200 | ||
|
|
1fcded67ef | ||
|
|
3be60539ce | ||
|
|
779c0a01d3 | ||
|
|
e1a5b80ae1 | ||
|
|
021102c62d | ||
|
|
de1e66f7a9 | ||
|
|
13793885f3 | ||
|
|
cdeef9dc95 | ||
|
|
55400e9b42 | ||
|
|
110bc5abbe | ||
|
|
21ffbc0cca | ||
|
|
559c6df0c3 | ||
|
|
b7b0348c3c | ||
|
|
779b8b32cf | ||
|
|
a73555f672 | ||
|
|
03d0e0d799 | ||
|
|
64597e47c6 | ||
|
|
6713c6ebed | ||
|
|
051342cc8b | ||
|
|
94cf920751 | ||
|
|
dcac9de58b | ||
|
|
23ce202d38 | ||
|
|
362dd7241a | ||
|
|
94907678eb | ||
|
|
9cb94e00b0 | ||
|
|
3b4e55d0e5 | ||
|
|
8779151fef | ||
|
|
923c19356b | ||
|
|
3d95f3c7b1 | ||
|
|
6f6bd95a84 | ||
|
|
aa537310ad | ||
|
|
39ebd6e8d1 | ||
|
|
faf8c83f54 | ||
|
|
e8babede53 | ||
|
|
36af159991 | ||
|
|
7150d6ef59 | ||
|
|
2a500baaca | ||
|
|
cb85b3e8dd | ||
|
|
ea9d5e3a5e | ||
|
|
d96409ff37 | ||
|
|
95e11234a7 | ||
|
|
97329367e4 | ||
|
|
4217369709 | ||
|
|
09832d09fb | ||
|
|
168395af74 | ||
|
|
60b182b821 | ||
|
|
587a56026e | ||
|
|
3e8e6d35d6 | ||
|
|
9a7a8efb39 | ||
|
|
4db4d5e8bc | ||
|
|
d046594591 | ||
|
|
417d1b7de7 | ||
|
|
a88e6f4e1f | ||
|
|
96723c6f70 | ||
|
|
5062374c72 | ||
|
|
76bb0031cb | ||
|
|
8ba17dd985 | ||
|
|
4437cd1eac | ||
|
|
3cfed7ba01 | ||
|
|
e9a264217a | ||
|
|
15ffffa835 | ||
|
|
79ce997156 | ||
|
|
15838c2850 | ||
|
|
0545c42db9 | ||
|
|
f3001c9bba | ||
|
|
42aa83b2a5 | ||
|
|
15e8be4074 | ||
|
|
3c27300a4e | ||
|
|
65f406a39e | ||
|
|
0d06dfa948 | ||
|
|
b4be7b0c74 | ||
|
|
9ad874eef8 | ||
|
|
d52f3ba3e9 | ||
|
|
3d44faf6c3 | ||
|
|
8ad3cb14f8 | ||
|
|
0be7e96437 | ||
|
|
d1aa7dbedc | ||
|
|
eef7611cf1 | ||
|
|
758b3ad2cc | ||
|
|
b468aa8c01 | ||
|
|
31d86e6e78 | ||
|
|
1617cd7e2a | ||
|
|
ac318f2c8c | ||
|
|
42d02565af | ||
|
|
18d3eba614 | ||
|
|
3171c71639 | ||
|
|
32444f8188 | ||
|
|
73729e7a33 | ||
|
|
c6f55eeb94 | ||
|
|
5e156b9d73 | ||
|
|
004d100ed8 | ||
|
|
1f866dbad4 | ||
|
|
127e07c210 | ||
|
|
745fb4b40c | ||
|
|
a96ea2492d | ||
|
|
3b8e3c613f | ||
|
|
f7445bcc98 | ||
|
|
0fd2cfbab6 | ||
|
|
d5d643ca28 | ||
|
|
2dc9616509 | ||
|
|
739f7b47fe | ||
|
|
82df0c3aa3 | ||
|
|
3e22d7bbd5 | ||
|
|
b67894586f | ||
|
|
5e20d16ef8 | ||
|
|
83235dc484 | ||
|
|
bd0d8fd8ea | ||
|
|
ec7faddd26 | ||
|
|
6591844b3e | ||
|
|
14c5825769 | ||
|
|
dfda4f3519 | ||
|
|
7117cb8f8e | ||
|
|
00f755a822 | ||
|
|
328d5bf648 | ||
|
|
7f1c1db651 | ||
|
|
b90bd91731 | ||
|
|
5aa87c1734 | ||
|
|
1fd6d024eb | ||
|
|
c6b325e4d6 | ||
|
|
df588ca422 | ||
|
|
17a161afa2 | ||
|
|
5628d3ba91 | ||
|
|
94f82ece4e | ||
|
|
6b2ac3afcd | ||
|
|
1aaf933a1a | ||
|
|
3af86cab07 | ||
|
|
d0ed4e90b3 | ||
|
|
355aaac73a | ||
|
|
fbd973147b | ||
|
|
6d2b81c6b3 | ||
|
|
b01b4de91d | ||
|
|
36e7cc4bbd | ||
|
|
7429124cd4 | ||
|
|
e3658cbc7b | ||
|
|
3031556e73 | ||
|
|
105fadd668 | ||
|
|
a8a4e60171 | ||
|
|
bfe167fae8 | ||
|
|
7cbdd845ad | ||
|
|
de203390be | ||
|
|
55916a40ab | ||
|
|
002f2ab6e7 | ||
|
|
e61fc4e427 | ||
|
|
c198c0737a | ||
|
|
03b18dbfc4 | ||
|
|
c88f2b31ee | ||
|
|
a01e99aa63 | ||
|
|
1ea82b8b5d | ||
|
|
4b393eb22a | ||
|
|
bb6f13a725 | ||
|
|
7519d3562b | ||
|
|
0f924bd083 | ||
|
|
004d782323 | ||
|
|
1bd9d503f0 | ||
|
|
918b08e910 | ||
|
|
83cb526153 | ||
|
|
aa19d5180b | ||
|
|
d44d1537d9 | ||
|
|
1392143d14 | ||
|
|
ca03491e63 | ||
|
|
25fb69a7a5 | ||
|
|
c1717fc028 | ||
|
|
49fb0d7909 | ||
|
|
28e88c95ec | ||
|
|
4c198a7cb3 | ||
|
|
e1f8b66c05 | ||
|
|
f03f6d6a63 | ||
|
|
b06314cda3 | ||
|
|
fc6580200a | ||
|
|
ed20c14f23 | ||
|
|
cbe46dfd99 | ||
|
|
1223f74f5c | ||
|
|
8c2135f2bb | ||
|
|
d20dc01aff | ||
|
|
cd29485d6e | ||
|
|
a8430acd66 | ||
|
|
3a67e072bb | ||
|
|
535f2f23f3 | ||
|
|
a27ee73622 | ||
|
|
9b012e907a | ||
|
|
ebe9f1861e | ||
|
|
9462fd301a | ||
|
|
6992f580e8 | ||
|
|
6dd7f65322 | ||
|
|
72e6601702 | ||
|
|
cab8663713 | ||
|
|
8d9419128e | ||
|
|
e3bf70dc10 | ||
|
|
0647e0d2c2 | ||
|
|
2f43a1b5f4 | ||
|
|
831e33739e | ||
|
|
90008242eb | ||
|
|
43017cb65b | ||
|
|
2f17cbaef3 | ||
|
|
688acb1e41 | ||
|
|
7b2d7a9ec7 | ||
|
|
01e62efb72 | ||
|
|
82391b6ac1 | ||
|
|
2ad2983b25 | ||
|
|
5df0516318 | ||
|
|
56014a6bf7 | ||
|
|
dd923d55f2 | ||
|
|
3c2d30c510 | ||
|
|
a4982cd460 | ||
|
|
e6a3785b01 | ||
|
|
d09ae22147 | ||
|
|
d2e83df498 | ||
|
|
c490b06fe9 | ||
|
|
c9a97d255c | ||
|
|
f0a9f4e6a4 | ||
|
|
177ca956f1 | ||
|
|
e13febc82b | ||
|
|
04ee55f202 | ||
|
|
ee6c2393c1 | ||
|
|
52fe3d2c7d | ||
|
|
1dbc7cdc9a | ||
|
|
07f3abfda1 | ||
|
|
a2c7b17cd3 | ||
|
|
56393bd253 | ||
|
|
3d52d7a8f6 | ||
|
|
b5958359d2 | ||
|
|
e7257c1855 | ||
|
|
6329b28e4a | ||
|
|
c3743a74f6 | ||
|
|
e7d2e7ebcb | ||
|
|
71f4ff6b84 | ||
|
|
bfe00ac6f3 | ||
|
|
2b2d6742e0 | ||
|
|
aa9934a722 | ||
|
|
ec4ecb5d34 | ||
|
|
8551d175ab | ||
|
|
d0bce8bc9f | ||
|
|
12ae92ef66 | ||
|
|
c1a2dd81c7 | ||
|
|
a4d8ecf2b8 | ||
|
|
c80d18c446 | ||
|
|
2a41f1fb99 | ||
|
|
901932a8e1 | ||
|
|
e57e4dbf57 | ||
|
|
00ca7297f3 | ||
|
|
cfc2a15d41 | ||
|
|
e8f55e8b24 | ||
|
|
c09c4299ba | ||
|
|
dda12da672 | ||
|
|
96b6789855 | ||
|
|
17107a1563 | ||
|
|
c3c2f5bfb6 | ||
|
|
3953659901 | ||
|
|
c3f2469832 | ||
|
|
2e0c1daf1b | ||
|
|
93df88a5d6 | ||
|
|
3ed2cf7812 | ||
|
|
c0dfcd2adf | ||
|
|
f349784bd6 | ||
|
|
ba2c870d95 | ||
|
|
b382ea2a33 | ||
|
|
b6094d6f3b | ||
|
|
170397456c | ||
|
|
944485b9ae | ||
|
|
c8adaaaab2 | ||
|
|
d8ba2839c4 | ||
|
|
576213b048 | ||
|
|
1f97d31f2a | ||
|
|
1e6e7a698f | ||
|
|
9170bca9b3 | ||
|
|
388879da38 | ||
|
|
4476d3e971 | ||
|
|
4e4802e5c6 | ||
|
|
203a80aeaa | ||
|
|
50a50b8519 | ||
|
|
4203b4fb78 | ||
|
|
a990c0bca4 | ||
|
|
4eec21b4d1 | ||
|
|
6625eff3d8 | ||
|
|
677f13a2fe | ||
|
|
ba74747860 | ||
|
|
de3ac2c549 | ||
|
|
ccaba7d465 | ||
|
|
e553e19996 | ||
|
|
ce9ba045ff | ||
|
|
c69a11a219 | ||
|
|
4aa936ce33 | ||
|
|
f09561026a | ||
|
|
5cdef89b86 | ||
|
|
b1d5542d77 | ||
|
|
1671f16b0c | ||
|
|
5a5640155a | ||
|
|
822eb3bb86 | ||
|
|
3e55d598db | ||
|
|
def1e352d4 | ||
|
|
34b744aff6 | ||
|
|
bff8e8204d | ||
|
|
4cd3934610 | ||
|
|
33206b8847 | ||
|
|
b26fa714a8 | ||
|
|
9983976ddb | ||
|
|
d3ed02dd87 | ||
|
|
d392d90a6e | ||
|
|
c8067ba0c0 | ||
|
|
932071952d | ||
|
|
f081cfa314 | ||
|
|
861379d8e3 | ||
|
|
64b23937d3 | ||
|
|
11a4a4cffb | ||
|
|
8da54e2349 | ||
|
|
87cc90741d | ||
|
|
27da1c94f2 | ||
|
|
d2d240ecf5 | ||
|
|
540edd7b5d | ||
|
|
81c020d300 | ||
|
|
e3506ed06b | ||
|
|
387e18b528 | ||
|
|
bac58c99c4 | ||
|
|
964fcda79a | ||
|
|
b241b5769b | ||
|
|
376598a6e0 | ||
|
|
ed8e440b0d | ||
|
|
442608981d | ||
|
|
8191f2775f | ||
|
|
f142caea11 | ||
|
|
d2f381d121 | ||
|
|
90b56fb487 | ||
|
|
8533512a82 | ||
|
|
dbe4be7e7f | ||
|
|
912ab4ff00 | ||
|
|
460cfc9efd | ||
|
|
309045e0ac | ||
|
|
944e89bdc8 | ||
|
|
885eb4f15b | ||
|
|
27ecc119e0 | ||
|
|
ded406984f | ||
|
|
2a7b76249c | ||
|
|
e49d505254 | ||
|
|
79c336b6fd | ||
|
|
249c73d68c | ||
|
|
5d8c566dbc | ||
|
|
aa2348823c | ||
|
|
10a234908f | ||
|
|
6d5104f6d7 | ||
|
|
fbdc53f926 | ||
|
|
8e028f4db3 | ||
|
|
29ced2a72f | ||
|
|
77b05d6078 | ||
|
|
b351fac466 | ||
|
|
ffda27c8a7 | ||
|
|
72601103ba | ||
|
|
4736bef77b | ||
|
|
1581d23a6c | ||
|
|
15b6da2a17 | ||
|
|
f0784351c4 | ||
|
|
9df2a6fd99 | ||
|
|
8518b4f50b | ||
|
|
53b7fb2ba2 | ||
|
|
6a541125aa | ||
|
|
947e15f34f | ||
|
|
c7ce2c7053 | ||
|
|
d5a5380e6d | ||
|
|
496104005b | ||
|
|
33ab147514 | ||
|
|
c0bc8d2df2 | ||
|
|
d2a1d96f59 | ||
|
|
9d0356dd73 | ||
|
|
a46027bed7 | ||
|
|
a68e9b5014 | ||
|
|
88d4ae6790 | ||
|
|
48cca00d91 | ||
|
|
9555f70440 | ||
|
|
db9a067e64 | ||
|
|
0aa9bd9c22 | ||
|
|
aba96fbf03 | ||
|
|
2a72d90e8a | ||
|
|
479ba58042 | ||
|
|
9c0028c1d1 | ||
|
|
53d18cf95e | ||
|
|
63e437d58f | ||
|
|
ddd9fbf6ae | ||
|
|
68719ac8d4 | ||
|
|
934697b0da | ||
|
|
cbe68cbf88 | ||
|
|
9e547699c6 | ||
|
|
f9bc57bcf8 | ||
|
|
09b7202c54 | ||
|
|
8c799f978b | ||
|
|
34125a6d14 | ||
|
|
c252cbe9e0 | ||
|
|
8e6e30370d | ||
|
|
154c2d388d | ||
|
|
e8c027cbc3 | ||
|
|
e3a8e28edc | ||
|
|
1c9d0dbf48 | ||
|
|
939770929f | ||
|
|
756b4636f6 | ||
|
|
80e49531b1 | ||
|
|
b6aa9f2fd1 | ||
|
|
09a9b7d254 | ||
|
|
f804e0738f | ||
|
|
a28e57e42d | ||
|
|
7088281b52 | ||
|
|
ba183cf7a6 | ||
|
|
9df755bdb4 | ||
|
|
4eebfa237b | ||
|
|
cc99b9f949 | ||
|
|
6c47f02bdf | ||
|
|
30f36a30f2 | ||
|
|
b6dc887d52 | ||
|
|
9b192dc3c1 | ||
|
|
686a0ce199 | ||
|
|
27f88abb02 | ||
|
|
3b0cbc1e41 | ||
|
|
0d284c42bc | ||
|
|
11f054e646 | ||
|
|
6ec7eddfc9 | ||
|
|
7eefec6945 | ||
|
|
95dede9039 | ||
|
|
82898ea194 | ||
|
|
666ebb0ae1 | ||
|
|
8548771025 | ||
|
|
6adfff6995 | ||
|
|
724865a8fc | ||
|
|
eab80384ab | ||
|
|
cbf0bc9cfc | ||
|
|
474110b818 | ||
|
|
52b3a4fe17 | ||
|
|
2f7a6fa394 | ||
|
|
2a77dc5600 | ||
|
|
d84dfee044 | ||
|
|
616759ed8c | ||
|
|
637319c938 | ||
|
|
d7572399cc | ||
|
|
2678789bd8 | ||
|
|
96845f4a7e | ||
|
|
baaf27c268 | ||
|
|
3038e9e1ce | ||
|
|
a30f7dc79f | ||
|
|
2b20c8d350 | ||
|
|
3f88a49bdc | ||
|
|
bed9847b48 | ||
|
|
66bdf711f4 | ||
|
|
f3ca57e6f0 | ||
|
|
6b7673f806 | ||
|
|
312f143253 | ||
|
|
3a552e08ff | ||
|
|
1533d618e5 | ||
|
|
6394342b9c | ||
|
|
9c27f0e7c3 | ||
|
|
a0486c3cd7 | ||
|
|
4cca0c1eb7 | ||
|
|
a75491375c | ||
|
|
d31dcbed81 | ||
|
|
25a417cdd7 | ||
|
|
df6d65e061 | ||
|
|
95f68b0625 | ||
|
|
f9f7092370 | ||
|
|
9e2ac1100c | ||
|
|
8f492adac3 | ||
|
|
0a4795f6d5 | ||
|
|
8a26931622 | ||
|
|
52db3779c7 | ||
|
|
84de1ce2f2 | ||
|
|
6443169bac | ||
|
|
08ce33eed0 | ||
|
|
1fc1a48bfe | ||
|
|
e4bcfa6a2a | ||
|
|
cf586b7273 | ||
|
|
bc657778fe | ||
|
|
ad5874b94d | ||
|
|
0e6f33103a | ||
|
|
455982da91 | ||
|
|
0c83d2a7cf | ||
|
|
dbd1e70410 | ||
|
|
c62af7dc49 | ||
|
|
946713100a | ||
|
|
a3aef0f3f5 | ||
|
|
f3506054a1 | ||
|
|
a5f1e9f817 | ||
|
|
ff03272e07 | ||
|
|
bba454207e | ||
|
|
f2898f4404 | ||
|
|
a247ee14cd | ||
|
|
42a85938e7 | ||
|
|
4d6555d58b | ||
|
|
0493ecc7a6 | ||
|
|
44219c00aa | ||
|
|
545996f52e | ||
|
|
16e7fe41dc | ||
|
|
4a4b76111f | ||
|
|
38716b518c | ||
|
|
a28bbf5d14 | ||
|
|
6afd684ae5 | ||
|
|
ab56aca3ef | ||
|
|
7e6ce4e279 | ||
|
|
67e9fba9d7 | ||
|
|
d326828fd6 | ||
|
|
82b31c12c1 | ||
|
|
bfdc8e6a62 | ||
|
|
078961648f | ||
|
|
044851f608 | ||
|
|
dc696ab112 | ||
|
|
ec4f49d860 | ||
|
|
73e3620d20 | ||
|
|
112483e824 | ||
|
|
36f13e0520 | ||
|
|
f0aafce88b | ||
|
|
e9643d189b | ||
|
|
79b2b098b1 | ||
|
|
e60f72388e | ||
|
|
26f1e8be95 | ||
|
|
697d16dd01 | ||
|
|
841b3d620f | ||
|
|
b427f44908 | ||
|
|
98de418b7a | ||
|
|
8fc4a788e1 | ||
|
|
b590d0a219 | ||
|
|
eb2a881d55 | ||
|
|
b8d6e1d2c3 | ||
|
|
72d416d5f2 | ||
|
|
98b04b99dc | ||
|
|
14e159decf | ||
|
|
8809932b49 | ||
|
|
5a9f435863 | ||
|
|
72a087384b | ||
|
|
c356969c3a | ||
|
|
9ba48d8a4e | ||
|
|
01bf1c9710 | ||
|
|
370c28f0d4 | ||
|
|
c10175030f | ||
|
|
3a8e58ada4 | ||
|
|
d915787c9c | ||
|
|
7d5e24806c | ||
|
|
ee39d62031 | ||
|
|
064f821cf0 | ||
|
|
9a3512df31 | ||
|
|
fad8a0f29c | ||
|
|
7021a4909e | ||
|
|
d4b7be4ae4 | ||
|
|
eb77d84716 | ||
|
|
5639b3ebbd | ||
|
|
d215d3ff44 | ||
|
|
a488876a6a | ||
|
|
9c0f4c737e | ||
|
|
1f56d944ae | ||
|
|
7dbd46c978 | ||
|
|
b854201bc1 | ||
|
|
0719f9861c | ||
|
|
d15f8e0dc5 | ||
|
|
86a7e500e9 | ||
|
|
d641e67876 | ||
|
|
eb72061b27 | ||
|
|
b64289bd5f | ||
|
|
b3df81e791 | ||
|
|
eae8470dce | ||
|
|
6456b5dcb1 | ||
|
|
2ebf1a2c67 | ||
|
|
640a2b8991 | ||
|
|
6b4d76fc26 | ||
|
|
49b87724eb | ||
|
|
f7f0499601 | ||
|
|
0e79aa80d9 | ||
|
|
c9b8164b0c | ||
|
|
1436dcfb30 | ||
|
|
1ccd4d56fa | ||
|
|
a4f0176089 | ||
|
|
4a76399583 | ||
|
|
5e2f0428c7 | ||
|
|
8d4d69e218 | ||
|
|
14f8ee1e40 | ||
|
|
0615d655af | ||
|
|
45deb2c218 | ||
|
|
1194b29c12 | ||
|
|
b56551e978 | ||
|
|
32c2ae8278 | ||
|
|
0b92224c36 | ||
|
|
a723a833a8 | ||
|
|
c78a0da045 | ||
|
|
bf122a33e6 | ||
|
|
37ea3d0cee | ||
|
|
3734ccbcc0 | ||
|
|
362b76fd74 | ||
|
|
e968dd85e2 | ||
|
|
d51b32f662 | ||
|
|
4e78375340 | ||
|
|
1bab26dc3d | ||
|
|
f678a06b95 | ||
|
|
ef464d9785 | ||
|
|
682775ba83 | ||
|
|
24c798f550 | ||
|
|
73c853def4 | ||
|
|
38600f4cf3 | ||
|
|
e24ee95558 | ||
|
|
3cfde6cc45 | ||
|
|
1c8d147d7c | ||
|
|
37d12c3859 | ||
|
|
8283092367 | ||
|
|
ed7c3dcff4 | ||
|
|
836fb17d0d | ||
|
|
564eb6a4a0 | ||
|
|
969ed176d6 | ||
|
|
8e2be92c72 | ||
|
|
f9d9dc8adb | ||
|
|
a127d2bf48 | ||
|
|
5fca67974d | ||
|
|
02c35441d6 | ||
|
|
10d652a9f7 | ||
|
|
77069b7299 | ||
|
|
e34fdedfb4 | ||
|
|
dea603dcc1 | ||
|
|
011078f991 | ||
|
|
d0442f4468 | ||
|
|
615c581cd2 | ||
|
|
fd75ae487e | ||
|
|
c2c3ed6a76 | ||
|
|
4ac264b1d0 | ||
|
|
65935696c3 | ||
|
|
4d9fb951df | ||
|
|
836aa69f9c | ||
|
|
253f770259 | ||
|
|
50fbf04df5 | ||
|
|
55d123d95a | ||
|
|
7fee4ad11b | ||
|
|
14308e0b98 | ||
|
|
6b93b77d0d | ||
|
|
70fd455b13 | ||
|
|
839747f420 | ||
|
|
d1a74e1b96 | ||
|
|
89e9bdc413 | ||
|
|
87d0bce799 | ||
|
|
b29fbbb587 | ||
|
|
f983519589 | ||
|
|
4fbf823707 | ||
|
|
26b0bc771d | ||
|
|
0eff23eeed | ||
|
|
97f0357407 | ||
|
|
92272fe01e | ||
|
|
52c73e6382 | ||
|
|
b26a031ca8 | ||
|
|
5309036463 | ||
|
|
ca78e1c2bf | ||
|
|
5340387164 | ||
|
|
912fb252c6 | ||
|
|
1907deb8de | ||
|
|
042783af21 | ||
|
|
7bed40d17b | ||
|
|
ff726d212c | ||
|
|
d6d0bb5e4e | ||
|
|
2fe4cf6ca5 | ||
|
|
ef0eba5c5f | ||
|
|
77d185ba8b | ||
|
|
e47e055508 | ||
|
|
7afbd4632d | ||
|
|
cb576b1b95 | ||
|
|
778571e3d0 | ||
|
|
9144583fdb | ||
|
|
e394b439a8 | ||
|
|
b12d1d7d8a | ||
|
|
c41e2218f7 | ||
|
|
f7dba5d331 | ||
|
|
4dcd7a0247 | ||
|
|
956d08e9bc | ||
|
|
9fe72bfa7b | ||
|
|
b6eb048a12 | ||
|
|
875ff0e28c | ||
|
|
2b415292c6 | ||
|
|
0f55f8f12b | ||
|
|
41d3dfc591 | ||
|
|
a02245ade2 | ||
|
|
f0bfdbf209 | ||
|
|
2d769d4bfb | ||
|
|
64dc3dde40 | ||
|
|
385dfdd33d | ||
|
|
777b0a33c3 | ||
|
|
f8f29fbccf | ||
|
|
fb6a2ef746 | ||
|
|
7969221919 | ||
|
|
918b0619d0 | ||
|
|
0da68dacf5 | ||
|
|
4cf27651ba | ||
|
|
7e9e330e99 | ||
|
|
7175c3ec22 | ||
|
|
221df13250 | ||
|
|
7b4c4efd11 | ||
|
|
d18ae6dac6 | ||
|
|
b6e6b78843 | ||
|
|
eed65a64b2 | ||
|
|
908974dfe4 | ||
|
|
904f0e65e5 | ||
|
|
51722b628c | ||
|
|
28ab397d60 | ||
|
|
8a06263ba6 | ||
|
|
811138221a | ||
|
|
daa30b1dc8 | ||
|
|
d2ec1ba2cc | ||
|
|
6467d24070 | ||
|
|
eebe0eda48 | ||
|
|
419eb5a6c0 | ||
|
|
0cd1843bc2 | ||
|
|
8066a6938f | ||
|
|
16a5a69bae | ||
|
|
eed44eea9c | ||
|
|
1788042c9e | ||
|
|
bf95fa34da | ||
|
|
32f7d73835 | ||
|
|
88e56faafa | ||
|
|
1df3e20bdd | ||
|
|
6a5af218c7 | ||
|
|
b3316fea35 | ||
|
|
db030f6472 | ||
|
|
c48ccdb1fc | ||
|
|
9ea18c433b | ||
|
|
453781af9c | ||
|
|
a529b7b487 | ||
|
|
690670e2b5 | ||
|
|
5351b56a0b | ||
|
|
b757304513 | ||
|
|
cc0ce43a57 | ||
|
|
5904839bc6 | ||
|
|
fffc7597fd | ||
|
|
4a7dfba6ee | ||
|
|
addc75748b | ||
|
|
ece9851afb | ||
|
|
2e480a37ea | ||
|
|
890e076d20 | ||
|
|
547f8968aa | ||
|
|
b0b3abe775 | ||
|
|
27d2877106 | ||
|
|
897488862e | ||
|
|
0212567d75 | ||
|
|
109adf9739 | ||
|
|
ca2a4cdb27 | ||
|
|
3057c31798 | ||
|
|
0a123e8215 | ||
|
|
1eaf6f54cc | ||
|
|
9be6d265b4 | ||
|
|
8fff917341 | ||
|
|
adc3c9e36b | ||
|
|
da06dfca0d | ||
|
|
030231038c | ||
|
|
38fe58e746 | ||
|
|
b80b9cd157 | ||
|
|
8a68c620ac | ||
|
|
4b73879369 | ||
|
|
1ab81e5711 | ||
|
|
999887bda5 | ||
|
|
b9a08520ff | ||
|
|
1da7baa49d | ||
|
|
1b8093513d | ||
|
|
2061b465fb | ||
|
|
6dd46e6971 | ||
|
|
6ac8b89601 | ||
|
|
4b586b6496 | ||
|
|
e8bd94aab8 | ||
|
|
b5cf9b639e | ||
|
|
91caf28bfc | ||
|
|
2409831a14 | ||
|
|
bc52b952d7 | ||
|
|
4428b545bb | ||
|
|
fdf3a07b15 | ||
|
|
c8c5b69b5e | ||
|
|
473400902c | ||
|
|
58ad81f063 | ||
|
|
b01149f068 | ||
|
|
89ae74fba6 | ||
|
|
a1f2c6197f | ||
|
|
f4467d6595 | ||
|
|
688d1ef81c | ||
|
|
4f2ed12e4f | ||
|
|
ef710442f1 | ||
|
|
2bd71b55bc | ||
|
|
c78dcbd382 | ||
|
|
80b62fc635 | ||
|
|
7d466c8177 | ||
|
|
516bace3ca | ||
|
|
3307e65ad3 | ||
|
|
01dc71f598 | ||
|
|
17fb07cb85 | ||
|
|
85d9eeb50d | ||
|
|
0314921434 | ||
|
|
dde7c28730 | ||
|
|
682b403a9c | ||
|
|
08d3fe8c04 | ||
|
|
82259a086e | ||
|
|
d045484788 | ||
|
|
dd522cdc6f | ||
|
|
ae7d956341 | ||
|
|
b94b9e2adb | ||
|
|
621c79dd3c | ||
|
|
21a2ba3f79 | ||
|
|
579c41535a | ||
|
|
107b5eec44 | ||
|
|
882a66b49a | ||
|
|
b4e1ca8a2c | ||
|
|
f309c85f92 | ||
|
|
db723df879 | ||
|
|
5f87fa1aca | ||
|
|
f33264f7a6 | ||
|
|
c5b3428408 | ||
|
|
efdc07ab10 | ||
|
|
920a20f060 | ||
|
|
2414224df8 | ||
|
|
511f43d5cf | ||
|
|
a6ec5a9831 | ||
|
|
6fe4559b8e | ||
|
|
83f1b28f98 | ||
|
|
4f564360e7 | ||
|
|
1ddd7ee79d | ||
|
|
23bb1414ff | ||
|
|
ad1fb29092 | ||
|
|
6a9feb7978 | ||
|
|
ae21bd98aa | ||
|
|
eadfb1398a | ||
|
|
bbb2bda20a | ||
|
|
4e155dbc8e | ||
|
|
9f0f53b1d7 | ||
|
|
fbb8a9640c | ||
|
|
2135e86fc7 | ||
|
|
69a38f9b9f | ||
|
|
c7fd375120 | ||
|
|
464df18ac2 | ||
|
|
3a39a51f11 | ||
|
|
c2b26a3cd9 | ||
|
|
ed29c6f59c | ||
|
|
a855447d11 | ||
|
|
111d666f85 | ||
|
|
d356f88fb5 | ||
|
|
03bddff8e6 | ||
|
|
ccc2bea0c4 | ||
|
|
c1504555ac | ||
|
|
08393b1d0c | ||
|
|
2fca06c994 | ||
|
|
f4feda6323 | ||
|
|
c5750da85a | ||
|
|
c81d363a6e | ||
|
|
302e2fdc53 | ||
|
|
f65e005d97 | ||
|
|
7cfd996802 | ||
|
|
1ed38ddb2d | ||
|
|
6d8bc91220 | ||
|
|
2f0a5f48aa | ||
|
|
3b057d9605 | ||
|
|
76f4cf5cc5 | ||
|
|
99a3aa8ee1 | ||
|
|
73c63d8768 | ||
|
|
3da84396b6 | ||
|
|
2e9a793519 | ||
|
|
bcb7e14d0f | ||
|
|
42818a2310 | ||
|
|
eb72a2e7d2 | ||
|
|
dacf9e327a | ||
|
|
2a8798b729 | ||
|
|
2892abf155 | ||
|
|
3bd585a94e | ||
|
|
2d4236882f | ||
|
|
ec4bfd7827 | ||
|
|
7173efe10f | ||
|
|
43000d2e24 | ||
|
|
db624a7c99 | ||
|
|
72a9d77638 | ||
|
|
36e5909057 | ||
|
|
8655038601 | ||
|
|
9250f649db | ||
|
|
71cc43651a | ||
|
|
e7eb0e2b3e | ||
|
|
33353d5cd9 | ||
|
|
1149487fbd | ||
|
|
f192e8618f | ||
|
|
4eac009c27 | ||
|
|
15470596ad | ||
|
|
f4c6b06b49 | ||
|
|
1d621c412c | ||
|
|
7dc2ca425f | ||
|
|
1075522147 | ||
|
|
9a5b8f0475 | ||
|
|
bd39d72acd | ||
|
|
b582f1c7c6 | ||
|
|
1027762db5 | ||
|
|
ab515daa0c | ||
|
|
3a61cfe6ec | ||
|
|
d09362ed6f | ||
|
|
6eaf19533b | ||
|
|
8f8a9863ad | ||
|
|
c186747edc | ||
|
|
922680851a | ||
|
|
3fbeb0617b | ||
|
|
306d7f6f8a | ||
|
|
ab60005cdc | ||
|
|
f663c64cd4 | ||
|
|
a9ef8333eb | ||
|
|
6d89bbfe61 | ||
|
|
b0a8f5d775 | ||
|
|
ed77d46cc9 | ||
|
|
1ced1b3f73 | ||
|
|
698387e762 | ||
|
|
8928052863 | ||
|
|
8fa6230426 | ||
|
|
7dd3939a26 | ||
|
|
b28c405377 | ||
|
|
b6a6127509 | ||
|
|
7d58bb9799 | ||
|
|
65aa939296 | ||
|
|
c3c4638b22 | ||
|
|
a36d5926d7 | ||
|
|
6f6b1a8333 | ||
|
|
861262ef3a | ||
|
|
c7c7d0988e | ||
|
|
712547cb2b | ||
|
|
5024b77492 | ||
|
|
d01ae6929d | ||
|
|
c2cad1f122 | ||
|
|
25f232616b | ||
|
|
4ea493c86c | ||
|
|
d526530167 | ||
|
|
ae6e2f5df5 | ||
|
|
4354ad296d | ||
|
|
86839db417 | ||
|
|
b9e8e95498 | ||
|
|
150f4f0f4b | ||
|
|
66794d2166 | ||
|
|
81ec152f10 | ||
|
|
60574f04d2 | ||
|
|
419fe62da8 | ||
|
|
aacc544300 | ||
|
|
9fd4ff7a8d | ||
|
|
352be447df | ||
|
|
5ba77289d9 | ||
|
|
497868ecaf | ||
|
|
ef216d3010 | ||
|
|
d2add47f1e | ||
|
|
f45a1d797e | ||
|
|
80311970cf | ||
|
|
1040d3eedf | ||
|
|
07c6b4c363 | ||
|
|
454b4ea715 | ||
|
|
7c2d2246fe | ||
|
|
725430994d | ||
|
|
ea7e682253 | ||
|
|
97d2be1ff3 | ||
|
|
d38dfa60f6 | ||
|
|
b179dde1e7 | ||
|
|
4c7beacfe4 | ||
|
|
b7fe19b6c8 | ||
|
|
744fac6777 | ||
|
|
f0adf90ec0 | ||
|
|
70b573c951 | ||
|
|
e1a7b82b2e | ||
|
|
c24caa8f48 | ||
|
|
753be84ae0 | ||
|
|
27ada9b7b2 | ||
|
|
785ed87117 | ||
|
|
85f07b6f27 | ||
|
|
f004666674 | ||
|
|
eb012a353a | ||
|
|
c645d43598 | ||
|
|
ef3c83da04 | ||
|
|
a0fd9d21d2 | ||
|
|
f6d1cbe6b9 | ||
|
|
ac5c03c458 | ||
|
|
25006cadfe | ||
|
|
d00af57b4a | ||
|
|
85f46b9899 | ||
|
|
50f2beb15b | ||
|
|
561a4cd4bf | ||
|
|
1b7e95b1bd | ||
|
|
f382589083 | ||
|
|
7cdc5c8e93 | ||
|
|
2179c16f60 | ||
|
|
fde7026ac2 | ||
|
|
8520a94b8f | ||
|
|
e39f5d7143 | ||
|
|
3047c55121 | ||
|
|
b875a69266 | ||
|
|
518f1bae20 | ||
|
|
9edd5eeaeb | ||
|
|
b0cc504d7c | ||
|
|
5d5de8ce51 | ||
|
|
a6ee786a4f | ||
|
|
48db589ed2 | ||
|
|
dec30677d9 | ||
|
|
c566b7eca5 | ||
|
|
e8df78f508 | ||
|
|
7cca6ea394 | ||
|
|
3a680df733 | ||
|
|
97d91a895c | ||
|
|
f4aabd0226 | ||
|
|
af75ddd04a | ||
|
|
5140bf9bd0 | ||
|
|
204407b64a | ||
|
|
48d28aa734 | ||
|
|
7e50bedd07 | ||
|
|
7d267d124e | ||
|
|
8b3fcf7740 | ||
|
|
3ac29eb659 | ||
|
|
a55a159fb9 | ||
|
|
e6227f9898 | ||
|
|
a52130e368 | ||
|
|
350eeeebbf | ||
|
|
0ab26a1371 | ||
|
|
49032ae2f2 | ||
|
|
b1fb7a1c1e | ||
|
|
2997c26069 | ||
|
|
a7723ba13f | ||
|
|
3fdd7a4b61 |
No files matched your search
+1
-1
@@ -1,6 +1,6 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
github: [twinaphex]
|
||||
patreon: libretro
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
|
||||
+38
-3
@@ -1,3 +1,9 @@
|
||||
# This setting is to prevent travis to launch duplicate builds on PRs
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- /^v.*$/
|
||||
|
||||
# Use 'generic' to be able to override CC/CXX for clang
|
||||
language: generic
|
||||
|
||||
@@ -36,6 +42,10 @@ matrix:
|
||||
env: DISABLE_OVERLAY=1 CC=gcc-8 CXX=g++-8
|
||||
- compiler: gcc
|
||||
env: DISABLE_CDROM=1 CC=gcc-8 CXX=g++-8
|
||||
- compiler: gcc
|
||||
env: DISABLE_VIDEO_LAYOUT=1 CC=gcc-8 CXX=g++-8
|
||||
- compiler: gcc
|
||||
env: DISABLE_AUDIOMIXER=1 CC=gcc-8 CXX=g++-8
|
||||
- compiler: gcc
|
||||
env: ENABLE_GLES=1 CC=gcc-8 CXX=g++-8
|
||||
- compiler: gcc
|
||||
@@ -48,14 +58,28 @@ matrix:
|
||||
env: CXX_BUILD=1 CC=clang-6.0 CXX=clang++-6.0
|
||||
- os: osx
|
||||
env: CC=clang CXX=clang++
|
||||
- name: OSX OpenGL Make
|
||||
os: osx
|
||||
osx_image: xcode11.2
|
||||
script:
|
||||
- ./configure --enable-opengl --disable-metal
|
||||
- make
|
||||
- os: osx
|
||||
osx_image: xcode8
|
||||
script:
|
||||
- xcodebuild -target RetroArch -configuration Release -project pkg/apple/RetroArch.xcodeproj
|
||||
- os: osx
|
||||
osx_image: xcode10.1
|
||||
osx_image: xcode11.2
|
||||
script:
|
||||
- brew update-reset
|
||||
- brew install --force-bottle qt5
|
||||
- security create-keychain -p travis build.keychain
|
||||
- security default-keychain -s build.keychain
|
||||
- security unlock-keychain -p travis build.keychain
|
||||
- echo $OSX_CERT | base64 --decode > dev.p12
|
||||
- security import dev.p12 -k build.keychain -P $OSX_CERT_PASS -T /usr/bin/codesign
|
||||
- rm dev.p12
|
||||
- security set-key-partition-list -S "apple-tool:,apple:,codesign:" -s -k travis build.keychain
|
||||
- xcodebuild -target RetroArchQt -configuration Release -project pkg/apple/RetroArch_Metal.xcodeproj
|
||||
deploy:
|
||||
skip_cleanup: true
|
||||
@@ -93,7 +117,7 @@ before_install:
|
||||
sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix
|
||||
fi
|
||||
|
||||
script:
|
||||
before_script:
|
||||
- |
|
||||
if [ -n "$CROSS_COMPILE" ]; then
|
||||
ARGS="$ARGS --disable-d3d8 --disable-d3d9 --disable-d3d10 --disable-d3d11 --disable-d3d12"
|
||||
@@ -110,6 +134,14 @@ script:
|
||||
if [ -n "$DISABLE_CDROM" ]; then
|
||||
ARGS="$ARGS --disable-cdrom"
|
||||
fi
|
||||
- |
|
||||
if [ -n "$DISABLE_VIDEO_LAYOUT" ]; then
|
||||
ARGS="$ARGS --disable-video_layout"
|
||||
fi
|
||||
- |
|
||||
if [ -n "$DISABLE_AUDIOMIXER" ]; then
|
||||
ARGS="$ARGS --disable-audiomixer"
|
||||
fi
|
||||
- |
|
||||
if [ -n "$ENABLE_GLES" ]; then
|
||||
ARGS="$ARGS --enable-opengles"
|
||||
@@ -118,6 +150,9 @@ script:
|
||||
if [ -n "$ENABLE_GLES3" ]; then
|
||||
ARGS="$ARGS --enable-opengles3"
|
||||
fi
|
||||
- echo "Configure arguments = $ARGS"
|
||||
|
||||
script:
|
||||
- ./configure $ARGS
|
||||
- |
|
||||
if [ -n "$C89_BUILD" ]; then
|
||||
@@ -152,4 +187,4 @@ addons:
|
||||
build_command: "make"
|
||||
branch_pattern: coverity_scan
|
||||
notifications:
|
||||
email: false
|
||||
email: true
|
||||
+233
-1
@@ -1,4 +1,235 @@
|
||||
# 1.7.9 (future)
|
||||
# Future
|
||||
|
||||
# 1.8.2
|
||||
- BUG/CRASH/GLSLANG: Fix glslang crashing error - managed to reproduce an issue which has been plaguing
|
||||
users for a while, where glslang throws an assert after closing a game (and starting a new one). This would affect all video drivers that use Slang for shaders, such as D3D10/11/12/Vulkan/Metal
|
||||
- CHEEVOS: Display Unofficial and Unsupported achievement states
|
||||
- CHEEVOS: Pass RetroArch and core versions through User-Agent HTTP header
|
||||
- CHEEVOS: Use PSX.EXE if SYSTEM.CNF cannot be found
|
||||
- CHEEVOS: Prevent loading state while achievements are still being fetched from server
|
||||
- CHEEVOS: Pause hardcore if core doesn't support achievements
|
||||
- CHEEVOS/CRASH: Fix AddressSanitizer + CHD cause hard crash when Cheevos are enabled
|
||||
- CORE UPDATER: Only download when new core is available
|
||||
- CORE UPDATER: Add option to update all installed cores
|
||||
- DRM/KMS: Better detection for the current video mode
|
||||
- DYNAMIC RATE CONTROL: Support DRC even when using a vsync swap interval higher than 1
|
||||
- EMSCRIPTEN: Fix bug in Emscripten input code
|
||||
- EMSCRIPTEN: Changes to support upgraded emscripten SDK
|
||||
- FFMPEG CORE: Hardware accelerated video decoding
|
||||
- FFMPEG CORE: Implement send/receive encoding API, will allow for hardware accelerated AMD video encoding
|
||||
- FFMPEG CORE: The video FIFO can be removed, since we have a ring buffer in its place. This removes unneeded copy operations and as a positive side improves overall decoding speed. Makes 8k60p SW and 4k60p HW decoding feasible on many systems. For now the ring buffer is 32 images deep. This limitation will be removed, once audio and video decoder have their own packet handling.
|
||||
- INPUT: Fix 'Analog stick controls menu even if autoconfig disabled'
|
||||
- INPUT/TURBO: Added alternate Turbo-Mode 'Single Button' - For systems supporting only a single button, the turbo-button will toggle firing that button without the need to hold it. When holding the button turbo will be suspended and resumed when the button is released. Holding the button may have a different function to just tapping it.
|
||||
- IOS: Forcibly disable Threaded Video until UIWindow concurrency issues are fixed
|
||||
- INPUT/ANALOG: Fix radial analog deadzone scaling
|
||||
- INPUT/ANALOG: Implement proper analog button deadzone
|
||||
- INPUT/MENU: Analog stick controls menu even if autoconfig disabled
|
||||
- LOCALIZATION: Update Italian translation
|
||||
- LOCALIZATION: Update French translation
|
||||
- LOCALIZATION: Update Polish translation
|
||||
- LOCALIZATION: Update Portuguese Brazilian Translation
|
||||
- LOCALIZATION: Update Turkish translation
|
||||
- LINUX/LOCALIZATION: Correct Droid Sans Fallback font path in Linux. This should fix Chinese/Korean font display issues on Fedora/RHEL/CentOS/openSUSE/SLE
|
||||
- MENU/BUGFIX: When using a keyboard/gamepad/mouse wheel to navigate, the menu scroll position is always maintained and updated in a consistent (and expected) fashion
|
||||
- MENU/BUGFIX: When resizing the window, or changing the orientation of a mobile device, the current scroll position is correctly preserved
|
||||
- MENU/BUGFIX: All 'normal' pointer input is now inhibited when showing message boxes
|
||||
- MENU/BUGFIX: The pointer actions 'select' and 'cancel' both now properly close a message box if it is currently being shown
|
||||
- MENU/BUGFIX: Pointer 'select' and 'cancel' actions are now inhibited when an input bind dialog is active
|
||||
- MENU/INPUT: Change 'User' terminology to 'Port' for input binding
|
||||
- MENU/LINUX: Add proper drives to Load Content
|
||||
- MENU/MATERIALUI: Halt scrolling when pointer is pressed/stationary
|
||||
- MENU/MATERIALUI: Dual thumbnail view
|
||||
- MENU/MATERIALUI: Fullscreen thumbnail viewer for boxart
|
||||
- MENU/MATERIALUI: Scroll rapidly by press and holding the scrollbar
|
||||
- MENU/RGUI: New theme 'Flux'
|
||||
- MENU/OZONE: Thumbnails now have a fade-in animation
|
||||
- MENU/OZONE: Fullscreen thumbnail viewer for boxart and pictures
|
||||
- MENU/QT/WIMP: Fix dock titles getting cut off
|
||||
- MENU/XMB: Fullscreen thumbnail viewer for boxart and pictures
|
||||
- MENU/USABILITY: Selectively hide 'Disallow Non-Slave Mode Clients' if 'Allow Slave-Mode Clients' is disabled
|
||||
- MENU/USABILITY: Hide 'Show desktop menu on startup' if 'Desktop menu' setting itself is disabled
|
||||
- MENU/USABILITY: Reimplement Quick Menu - > Shaders -> Watch shader files for changes - can now be turned on/off through touch
|
||||
- MENU/USABILITY: Refactor Quick Menu - Controls - each port now has its own submenu
|
||||
- MENU/USABILITY: Quick Menu - Cheats - Delete All no longer requires five right button presses - this should fix this functionality for mobile touch users too
|
||||
- MENU/USABILITY: Hide Refresh Rate options when Threaded Video is enabled - these settings do nothing with Threaded Video
|
||||
- MENU/USABILITY: Hide Logging Verbosity levels behind Logging Verbosity
|
||||
- MENU/USABILITY: Get rid of 'Port Number' label for Port Binds screen
|
||||
- MENU/USABILITY/MOBILE: Should no longer crash when clicking on a cheat entry
|
||||
- MENU/USABILITY: Shader parameters now have a dropdown list
|
||||
- MENU/USABILITY: Shader passes now has a dropdown list
|
||||
- MENU/USABILITY: Video - Hide Windowed Mode settings selectively
|
||||
- MENU/USABILITY: Video - Hide Fullscreen Mode settings if windowed mode is not supported by context driver
|
||||
- MENU/USABILITY: Selectively hide Network Command Port
|
||||
- MENU/USABILITY: Selectively hide Relay Server Location
|
||||
- MENU/USABILITY: User Interface -> Appearance - Selectively hide XMB Horizontal Animation setting
|
||||
- MENU/USABILITY: Playlists - more selective hiding
|
||||
- MENU/USABILITY: Selectively hide Rewind Settings
|
||||
- MENU/USABILITY: Selectively hide Overlay Settings
|
||||
- MENU/USABILITY: Selectively hide FPS Update Interval based on Display Framerate being enabled
|
||||
- MENU/USABILITY: Selectively hide Onscreen Notifications BG Color Settings
|
||||
- MENU/USABILITY: Settings -> Logging - Hide 'Log To File Timestamp' if 'Log To File' is disabled
|
||||
- MENU/USABILITY: Video -> Scaling - Hide Custom Viewport X/Y when Integer Scale is enabled as description indicates
|
||||
- MENU/USABILITY: Achievement submenu - selectively hide
|
||||
- MENU/USABILITY: Settings -> Video -> Aspect ratio - selectively hide/show values based on whether you have Custom or Config selected
|
||||
- MENU/USABILITY: Settings -> Video -> Selectively hide Hard Sync
|
||||
- MENU/USABILITY: Settings -> Video -> Implement selective hiding for VSync and Hard Sync
|
||||
- MENU/USABILITY: Selective hiding of Runahead settings based on global setting
|
||||
- MENU/USABILITY: Add Input -> Haptic Feedback submenu
|
||||
- MENU/USABILITY: Add Input -> Menu Controls submenu
|
||||
- MENU/USABILITY: Settings -> Video -> Max Swapchain Images - Add OK action
|
||||
- MENU/USABILITY: Input - Implement OK action for Bind Hold, Turbo Period and Duty Cycle
|
||||
- MENU/USABILITY: Input - Hotkey Binds refactor
|
||||
- MENU/USABILITY: Move 'Press Quit Twice' and 'Menu Toggle Gamepad Combo' to Input -> Hotkey Binds
|
||||
- MENU/USABILITY: Video - Add sublabel for Video Output submenu
|
||||
- MENU/USABILITY: If 'Favorites Tab' is disabled, don't show 'Add To Favorites' option in Quick Menu/Playlist menu
|
||||
- MENU/USABILITY: If On-Demand Thumbnail Downloader is enabled, hide 'Download Thumbnails' from playlist menu screen
|
||||
- MENU/USABILITY: Add Audio Driver setting to Audio -> Output
|
||||
- MENU/USABILITY: Add Audio -> Resampler settings
|
||||
- MENU/USABILITY: Add Audio -> Output and Audio -> Synchronization
|
||||
- OPENGL: Shaders are now working properly (only in OpenGL) when rotating both from Core API rotation and from menu video rotation. The fix is clearly visible with crt-royale for example
|
||||
- OPENGL: 1:1 PAR is now correct when rotating (both from Core API rotation and from menu video rotation, as you said, in the latter case you currently have to change Aspect Ratio after menu video rotation for it to work)
|
||||
- OPENGL: When using Custom Aspect Ratio and rotation (both from Core API rotation and from menu video rotation), Integer Scaling is now working properly (correct multiples of internal resolution). Even when Integer Scaling is not activated, the Custom AR width / height are now correctly labeled using (1x), (2x), ... suffixes. You also have to activate Integer Scaling after menu video rotation for it to work
|
||||
- OPENGL: For all other Aspect Ratio options, Integer Scaling and rotation (both from Core API rotation and from menu video rotation) are now working properly together (correct multiples of internal resolution). You also have to activate Integer Scaling after menu video rotation for it to work
|
||||
- OPENBSD/POWERPC: Should build now on OpenBSD PowerPC
|
||||
- PLAYLISTS: Pressing 'Start' or long touching a playlist will bring you to a Playlist submenu where you can set a default core, setup thumbnail view, delete the playlist, etc
|
||||
- OSX: Forcibly disable Threaded Video until NSWindow concurrency issues are fixed
|
||||
- PSP: Solving issue exiting RetroArch by HOME button
|
||||
- SCANNER: Manual scanner, not dependent on database files
|
||||
- SCANNER/MANUAL: Add option to scan inside archives
|
||||
- SCANNER/MANUAL: Enable automatic naming of arcade content via DAT files. This is compatible with DAT files in either Logiqx XML or MAME List XML format.
|
||||
- VIDEO: Do not reinit video driver on SET_SYSTEM_AV_INFO unless needed
|
||||
- VIDEO: Support DRC even when using a vsync swap interval higher than 1
|
||||
- VIDEO LAYOUT: Fixed XML parsing of attributes with spaces, should fix issues with several video layouts
|
||||
- VITA: GL1 driver support
|
||||
- VITA/VITA2D: Several improvements to Vita 2D driver - menu widgets implemented
|
||||
- VITA/VITA2D: Fix clipping and reduce number of calls
|
||||
- VULKAN/ANDROID: Workaround weird WSI return codes in landscape mode - Android WSI wants you to use preTransform, and if it is not used correctly, Android 10 will return VK_SUBOPTIMAL_KHR, and we would create a new swapchain every frame. This workaround just ignores this error, since it's not really an error. A more "proper" fix is to use prerotate and modify the MVP matrices,
|
||||
which might help certain devices with crummy display processors
|
||||
- VULKAN/ANDROID: Recreate swapchain on orientation change. ANativeWindow getWidth/Height does not detect any changes when using
|
||||
Vulkan, so use the old onContentRectChanged callback to get notified when size changed. Use those values instead when figuring out how large swapchain to create
|
||||
- WINDOWS/XINPUT: Get rid of 128 byte device name limit for XInput device discover - when device name was too long, it would not be picked up by the XInput driver and would instead fallback to DirectInput
|
||||
- WINDOWS: ANGLE OpenGL ES 2 support
|
||||
- UWP: Fix crashes on startup / prompt for folder permissions when trying to load custom.ini
|
||||
- UWP: Fix - Mouse input is offset on high DPI monitors
|
||||
- UWP: Fix - Keyboard input hangs sometimes
|
||||
- UWP: Fix - Multi-touch support
|
||||
- UWP: Fix - Enable menu touch input by default
|
||||
- UWP: Fix - Get user language
|
||||
- UWP: Fix - Get CPU model name
|
||||
- UWP: Fix - Use GLUI instead of XMB on Windows Mobile 10
|
||||
- UWP: ANGLE OpenGL ES 2 support
|
||||
|
||||
# (1.8.1)
|
||||
- BUGFIX/MENU: Fix menu rendering with Mali GPUs after changing video dimensions
|
||||
- CDROM: Adds pregap support to cdfs helper methods
|
||||
- CHEEVOS: Provides the new PCEngine hashing algorithm for RetroAchievements
|
||||
- LOCALIZATION: Update French translation
|
||||
- LOCALIZATION: Update Polish translation
|
||||
- LOCALIZATION: Update Spanish translation
|
||||
- MENU/MATERIALUI: Initial thumbnail support
|
||||
- MENU/MATERIALUI: Cutie / Virtual Boy theme added
|
||||
- MENU/MATERIALUI: Bugfix - Under certain extreme circumstances, entries with very long sublabel strings could have their text prematurely 'clipped' as the entry is scrolled beyond the top of the screen
|
||||
- MENU/MATERIALUI: Bugfix - Certain setting value strings were unnecessarily truncated (with a ...) when using smooth ticker text
|
||||
- MENU/XMB: Sunbeam theme added
|
||||
- SWITCH: Accelerometer, gyroscope and illuminance sensor support
|
||||
- VITA: Accelerometer and gyroscope sensor support
|
||||
|
||||
# (1.8.0)
|
||||
- AI SERVICE: Added in fix for BMP returns to AI service. Added in label passing to AI service call
|
||||
- BSV: Fix BSV recording/playback
|
||||
- BUGFIX: Fix crash when setting Thumbnail Directory
|
||||
- BUGFIX/STABILITY: Set "Automatically Add Content to Playlist" to false by default, this was unstable on PS3 and Mac and other platforms potentially as well.
|
||||
- COMMON: Graceful driver switching for Windows and Linux
|
||||
- COMMON: Cache frame before converting 0RGB1555
|
||||
- LAKKA: Wi-Fi Access Point settings
|
||||
- MENU: Menu scaling improvements
|
||||
- MENU/MATERIALUI: There are no longer any animation glitches when 'wraparound' scrolling from the last entry in a list to the first, or when performing horizontal swipe navigation gestures on certain settings-type entries
|
||||
- MENU/MATERIALUI: List entries underneath the title and navigation bars are no longer highlighted when touching the title/navigation bars (this was only a cosmetic issue, but it was annoying...)
|
||||
- MENU/MATERIALUI: The current menu list is no longer reloaded when pressing the currently active tab on the navigation bar
|
||||
- MENU/MATERIALUI: The ticker text spacer has been set to a 'bullet' character (same as Ozone)
|
||||
- MENU/MATERIALUI: The default colour theme has been set to 'Ozone Dark'
|
||||
- MENU/MATERIALUI: Three new colour themes have been added.
|
||||
- MENU/MATERIALUI: A new Menu Transition Animation option has been added under User Interface > Appearance. When this is enabled, menu transition events are animated
|
||||
- MENU/MATERIALUI: The navigation bar is now shown at all times - i.e. it is an actual navigation tool, rather than a 'top-level-menu' curiosity
|
||||
- MENU/MATERIALUI: Two new context-sensitive buttons have been added to the navigation bar - back button and resume button
|
||||
- MENU/MATERIALUI: A new Auto-Rotate Navigation Bar option has been added under User Interface > Appearance. When enabled (this is the default setting), the navigation bar is moved to the right hand side of the screen when using landscape screen orientations.
|
||||
- MENU/MATERIALUI: The playlists tab is now correctly hidden when User Interface > Views > Show Playlist Tabs is disabled
|
||||
- MENU/MATERIALUI: Material UI now correctly readjusts its layout when screen orientation changes on mobile devices
|
||||
- MENU/MATERIALUI: Material UI now resizes in real-time when the user manually sets the Menu Scale Factor (this never worked properly with the old DPI override)
|
||||
- MENU/MATERIALUI: Material UI no longer leaks memory on 'context reset' (fonts were previously never free()'d)
|
||||
- MENU/MATERIALUI: A new Android-style 'system bar' has been added. This shows current core name, clock and battery level
|
||||
- MENU/MATERIALUI: A new search icon is shown on the title bar when viewing playlists and file browser lists. Pressing this launches the search interface
|
||||
- MENU/MATERIALUI: The title bar now uses a larger font, and the sublabel font has also been enlarged a little, to more closely align with Material UI standards
|
||||
- MENU/MATERIALUI: A number (quite a large number) of layout/spacing issues have been fixed
|
||||
- MENU/MATERIALUI: The existing colour theme handling code is not fit for purpose, so the whole lot got ripped out and reimplemented. In doing so, also adjusted all the theme colours to better match Material UI standards - with a few liberties taken for aesthetic purposes.
|
||||
- OSD: Fix fast forward indicator when not using menu widgets
|
||||
- PSP1: Remove duplicated FPS indicator on the screen
|
||||
- SWITCH: Make audren threaded audio driver the new default
|
||||
- VIDEO LAYOUT: Add video layout mame overlay compatibility. Enabled for Windows/Linux/OSX/iOS/Android/libnx. Only works with GL driver for now, no glcore yet
|
||||
|
||||
# (1.7.9) (v2)
|
||||
- 3DS: Fix 3DS screen flickering when OSD is enabled
|
||||
- IOS: Fix crash that could happen at startup
|
||||
- MENU/MATERIALUI: Change DPI scaling back to original - too many issues with current implementation, requires a redesign
|
||||
|
||||
# (1.7.9)
|
||||
- AI SERVICE: Image mode is now much faster, it now saves the image in-memory in PNG format then passes it along to the translation service
|
||||
- BUGFIX: Touch input - When using an overlay to toggle the quick menu on touchscreen devices, we no longer get 'phantom' menu input - i.e. the old bug of hitting the toggle and instantly resuming content (or performing a save state) is fixed
|
||||
- BUGFIX: Networking - RetroArch crashed when pressing left while Relay Server Location entry was selected
|
||||
- BUGFIX: Networking - fix memory leak that could happen at exit after a network
|
||||
operation had run
|
||||
- CHEEVOS: Improve handling of line endings when calculating CD hashes for retroachievements
|
||||
- CHEEVOS: Add support for Sega CD/Saturn; reduce hash calls to server
|
||||
- FPGA: Add initial FPGA port for Z-Turn boards - not really release-ready yet, will need community support to continue. Currently employs naive framebuffer approach, not fullspeed
|
||||
- GL1: GLDirect (D3D9 to OGL1.1 wrapper) support
|
||||
- GONG: Stability fixes
|
||||
- LINUX/UDEV: Fix touchscreen/lightgun issues
|
||||
- MENU/MATERIALUI: MaterialUI no longer 'forgets' its place when navigating backwards in menus, and navigation in general is 'cleaner'.
|
||||
- MENU/MATERIALUI: Add initial gesture support
|
||||
- MENU/MATERIALUI: Improved touch support
|
||||
- MENU/MATERIALUI: Bugfix - Random' items are no longer automatically highlighted when performing standard up/down 'flick' scrolling through lists (items are only highlighted when you keep the pointer still for > 200 ms)
|
||||
- MENU/MATERIALUI: Bugfix - The display no longer 'jerks' for one frame when navigating backwards through lists
|
||||
- MENU/MATERIALUI: Bugfix - The Material UI scaling factor is now based upon the device-reported screen DPI value (previously it relied upon a hard-coded magic number, which was never correct)
|
||||
- MENU/RGUI: Functional mouse/touchscreen support
|
||||
- MENU/ONSCREEN KEYBOARD: On-screen keyboard entry via mouse/touchscreen has been tidied up - no more double inputs (or unwanted menu interaction in the background)
|
||||
- MENU/MOUSE: Mouse wheel up/down is now a proper 'up/down', same as using cursor keys or a dpad
|
||||
- MENU/MOUSE: Mouse wheel tilt left/right has been wired up to normal 'left/right' commands. Also further improved mouse wheel tilt
|
||||
- MENU/OZONE: Add option to toggle between static and scrolling content metadata
|
||||
- MENU/XMB: Add full gesture support
|
||||
- MENU/OSX: Fixed mouse buttons - mouse down events were not hooked up
|
||||
- MENU: When navigating backwards from a core options drop-down list (i.e. pressing select or cancel), the last menu position is remembered (instead of resetting back to the first core option item each time)
|
||||
- MENU: Add mouse/touchscreen gesture support
|
||||
- MENU: Add option to delete playlists (Settings > Playlists > Playlist Management)
|
||||
- MOBILE (ANDROID/IOS): Add option to automatically rotate overlays when changing orientation
|
||||
- OSD: Memory details should now be available on every platform (get_mem_total and get_mem_free need to be implemented in the frontend driver for it to work)
|
||||
- OSD: Memory details can now be shown individually without FPS and frame count
|
||||
- PS2: Fix memory leaks in font/video driver
|
||||
- SWITCH: Set default aspect ratio to core provided instead of 4:3
|
||||
- THREADED VIDEO: Fix FPS text in threaded video mode
|
||||
- VITA: Set default aspect ratio to core provided instead of 4:3
|
||||
- VITA: Add system language detection
|
||||
- VITA: More memory support
|
||||
- WIN32: Log window now has title 'Logging Console'
|
||||
- WII: Add Wiimote lightgun support
|
||||
|
||||
# 1.7.8 (v4)
|
||||
- COMMON: Enable customisation of runtime 'last played' display format.
|
||||
- CHEEVOS: Add hashing support for PSX (bin/cue, chd, or real CD) (for real this time, got added in the CHANGELOG for v2 then reverted before it hit release)
|
||||
- IOS: Update for iOS 13, fix the asset packaging issues
|
||||
- LOCALIZATION: Update Portuguese Brazilian Translation
|
||||
- MENU: Add 12-hour time/date versions of all formats
|
||||
- SWITCH: Add 'AI Service' option to Switch (untested)
|
||||
- SWITCH: Update to newest libnx
|
||||
|
||||
# 1.7.8 (v3)
|
||||
- GLCORE: Ensure correct scaling of menu texture (with RGUI)
|
||||
- IPS: Soft-Patch any IPS size
|
||||
- METAL: Fix overlay issue - setup correct viewport before rendering overlay
|
||||
- METAL/STB: Fix font driver issue with AMD GPUs on MacOS.
|
||||
- MENU/RGUI: Correctly rescale menu when resizing window if aspect ratio lock is enabled.
|
||||
- OSX: Remove OSX suffix in window title
|
||||
- PSP: Fix audio conversion code
|
||||
- REMAPS: Fix analog remapping regression -analog remapping would break controls
|
||||
|
||||
# 1.7.8 (v2)
|
||||
- 3DS: Fix 3DS startup crash
|
||||
@@ -880,3 +1111,4 @@ Skipped this one
|
||||
|
||||
# 1.4.1
|
||||
|
||||
|
||||
+2
-2
@@ -38,7 +38,7 @@ A pull request may be asked to fix the coding style before submission.
|
||||
In other cases, a pull request may be followed up with a "style nit commit".
|
||||
|
||||
## Non-obvious things:
|
||||
- Code should be both ISO C99 and ISO C++ compatible. This dual requirement is for XBox360 and MSVC in general. Think of it as a C++ compatible subset of C99.
|
||||
- Code should be both C89 and ISO C++ compatible. This dual requirement is for XBox360 and MSVC in general. Think of it as a C++ compatible subset of C99.
|
||||
- Warnings are not allowed (-Wall). Make sure your code is warning-free. Note that warning sensitivity differs a bit across compiler versions.
|
||||
- Using deprecated APIs is discouraged.
|
||||
|
||||
@@ -55,4 +55,4 @@ We value discussing things in "real-time".
|
||||
|
||||
# Commit Access
|
||||
Contributors who show a track record of making good pull requests over time will eventually get commit access to the repo.
|
||||
This typically happens when the "overhead" of looking through pull requests over time becomes a burden.
|
||||
This typically happens when the "overhead" of looking through pull requests over time becomes a burden.
|
||||
@@ -53,6 +53,10 @@ ifneq ($(findstring DOS,$(OS)),)
|
||||
LDFLAGS += -lemu
|
||||
endif
|
||||
|
||||
ifneq ($(findstring FPGA,$(OS)),)
|
||||
DEFINES += -DHAVE_FPGA
|
||||
endif
|
||||
|
||||
ifneq ($(findstring Win32,$(OS)),)
|
||||
LDFLAGS += -static-libgcc -lwinmm
|
||||
endif
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
# This build was put together and is maintained by ModMyClassic.com for Libretro.
|
||||
# The purpose is to give Libretro a proper "official" build platform for classic consoles.
|
||||
# If you need any help in building for the classics or have any questions then please visit
|
||||
# https://modmyclassic.com/comp and we will help in any way possible!
|
||||
|
||||
# Building Prerequisites ##############
|
||||
# arm-linux-gnueabihf-strip
|
||||
# patchelf
|
||||
# bc
|
||||
|
||||
include version.all
|
||||
|
||||
# Classic Readme Variables ############
|
||||
CLASSIC_ALT_VER := $(shell echo $(RARCH_VERSION) | tr . _)
|
||||
CLASSIC_MODS_VER := Official_Retroarch_v$(CLASSIC_ALT_VER)
|
||||
CLASSIC_MODS_NAME := RetroArch v$(RARCH_VERSION) (Official Optimised)
|
||||
CLASSIC_VERSION := $(RARCH_VERSION)
|
||||
MOD_CREATOR := Libretro + ModMyClassic
|
||||
MOD_CATEGORY := RetroArch
|
||||
GIT_COMMIT := $(shell echo "`git rev-parse --short HEAD``git diff-index --quiet HEAD -- || echo '-dirty'`")
|
||||
|
||||
# Platform dependant Variables ########
|
||||
HAKCHI_DIR := RA_Platform-Hakchi
|
||||
HAKCHI_GIT := https://github.com/Classicmods/RA_Platform-Hakchi
|
||||
|
||||
# General Shared Variables ############
|
||||
TARGET := retroarch
|
||||
|
||||
# Libretro Defines ####################
|
||||
#HAVE_CLASSIC = Classic Hook, disable some features
|
||||
#HAVE_C_A7A7 = Classic Armv7 Cortex A7 optimisation override
|
||||
#HAVE_HAKCHI = Hakchi Hook, change default configurations etc (TODO)
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
retroarch:
|
||||
#Build the RetroArch Binary for cross platform classics (ARMv7 Cortex A7)
|
||||
patchelf --version #Check if you have patchelf installed... (sudo apt-get install patchelf)
|
||||
CFLAGS="-marm -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard" ./configure --host=arm-linux-gnueabihf --enable-mali_fbdev --disable-freetype --enable-opengles --enable-udev --enable-alsa --enable-neon --enable-floathard --disable-discord
|
||||
make HAVE_CLASSIC=1 HAVE_C_A7A7=1 HAVE_HAKCHI=1 -j #Cook it
|
||||
arm-linux-gnueabihf-strip -v retroarch
|
||||
patchelf --replace-needed libSDL2-2.0.so.0 libSDL2.so retroarch #libSDL2-2.0.so.0 sym link doesn't exist on native build. Just patch the binary...
|
||||
|
||||
#HAKCHI BUILD (NESC, SNESC)
|
||||
#FYI this build was originally known as RetroArch 'Neo' for Hakchi.
|
||||
@echo "** BUILDING CLASSIC_MODS HAKCHI - $(CLASSIC_MODS_VER) HMOD PACKAGE **"
|
||||
rm -fr /tmp/$(HAKCHI_DIR)
|
||||
cd /tmp/; git clone $(HAKCHI_GIT)
|
||||
cp retroarch /tmp/$(HAKCHI_DIR)/bin/retroarch
|
||||
echo $$(echo "Built by: " $$USER @ $$(date) \\\\\\ Git Commit: $(GIT_COMMIT)) > /tmp/$(HAKCHI_DIR)/etc/libretro/retroarch_version
|
||||
cp /tmp/$(HAKCHI_DIR)/readme.md /tmp/$(HAKCHI_DIR)/readme_COPY.md
|
||||
printf "%s\n" \
|
||||
"---" \
|
||||
"Name: $(CLASSIC_MODS_NAME)" \
|
||||
"Creator: $(MOD_CREATOR)" \
|
||||
"Category: $(MOD_CATEGORY)" \
|
||||
"Version: $(CLASSIC_MODS_VER)" \
|
||||
"Built on: $(shell date)" \
|
||||
"Git commit: $(GIT_COMMIT)" \
|
||||
"---" > /tmp/$(HAKCHI_DIR)/readme.md
|
||||
cat /tmp/$(HAKCHI_DIR)/readme_COPY.md >> /tmp/$(HAKCHI_DIR)/readme.md
|
||||
rm /tmp/$(HAKCHI_DIR)/readme_COPY.md
|
||||
@echo "** COMPRESSING $(CLASSIC_MODS_VER) HMOD PACKAGE **"
|
||||
cd /tmp/$(HAKCHI_DIR)/; tar -czvf "$(CLASSIC_MODS_VER).hmod" *
|
||||
mv /tmp/$(HAKCHI_DIR)/$(CLASSIC_MODS_VER).hmod .
|
||||
@echo "** BUILT CLASSIC_MODS HAKCHI - $(CLASSIC_MODS_VER) HMOD PACKAGE **"
|
||||
rm -fr /tmp/$(HAKCHI_DIR) #clean up tmp
|
||||
|
||||
@echo "*********************************************************************"
|
||||
@echo "*** Classic ARM7 Cortex A7 build and packages built successfully! ***"
|
||||
@echo "*********************************************************************"
|
||||
clean:
|
||||
rm -rf obj-unix
|
||||
rm -f *.d
|
||||
rm -f *.o
|
||||
rm -f audio/*.o
|
||||
rm -f conf/*.o
|
||||
rm -f gfx/*.o
|
||||
rm -f gfx/drivers_font/*.o
|
||||
rm -f gfx/drivers_font_renderer/*.o
|
||||
rm -f gfx/drivers_context/*.o
|
||||
rm -f gfx/py_state/*.o
|
||||
rm -f compat/*.o
|
||||
rm -f record/*.o
|
||||
rm -f input/*.o
|
||||
rm -f tools/*.o
|
||||
rm -f $(BINDIR)/retroarch
|
||||
rm -f $(BINDIR)/retroarch-joyconfig
|
||||
rm -f $(PNDDIR)/readme.html
|
||||
rm -f retroarch
|
||||
rm -f $(CLASSIC_MODS_VER).hmod
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
# This build was put together and is maintained by ModMyClassic.com for Libretro.
|
||||
# The purpose is to give Libretro a proper "official" build platform for classic consoles.
|
||||
# If you need any help in building for the classics or have any questions then please visit
|
||||
# https://modmyclassic.com and we will help in any way possible!
|
||||
|
||||
# Building Prerequisites ##############
|
||||
# arm-linux-gnueabihf-strip
|
||||
|
||||
include version.all
|
||||
|
||||
# General Shared Variables ############
|
||||
TARGET := retroarch
|
||||
|
||||
# Libretro Defines ####################
|
||||
#HAVE_CLASSIC = Classic Hook, disable some features
|
||||
#HAVE_C_A7A7 = Classic Armv7 Cortex A7 optimisation override
|
||||
#HAVE_SEGAM = Sega Mini Hook, change default configurations etc (TODO)
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
retroarch:
|
||||
#Build the RetroArch Binary for cross platform classics (ARMv7 Cortex A7)
|
||||
patchelf --version #Check if you have patchelf installed... (sudo apt-get install patchelf)
|
||||
CFLAGS="-marm -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard" ./configure --host=arm-linux-gnueabihf --disable-wayland --disable-x11 --disable-opengl --disable-opengl1 --disable-opengl_core --enable-mali_fbdev --disable-freetype --enable-opengles --enable-udev --enable-alsa --enable-neon --enable-floathard --disable-discord
|
||||
make HAVE_CLASSIC=1 HAVE_C_A7A7=1 HAVE_SEGAM=1 -j #Cook it
|
||||
arm-linux-gnueabihf-strip -v retroarch
|
||||
@echo "*********************************************************************"
|
||||
@echo "*** SEGA Mega Drive Mini RetroArch binary built successfully! ***"
|
||||
@echo "*********************************************************************"
|
||||
clean:
|
||||
rm -rf obj-unix
|
||||
rm -f *.d
|
||||
rm -f *.o
|
||||
rm -f audio/*.o
|
||||
rm -f conf/*.o
|
||||
rm -f gfx/*.o
|
||||
rm -f gfx/drivers_font/*.o
|
||||
rm -f gfx/drivers_font_renderer/*.o
|
||||
rm -f gfx/drivers_context/*.o
|
||||
rm -f gfx/py_state/*.o
|
||||
rm -f compat/*.o
|
||||
rm -f record/*.o
|
||||
rm -f input/*.o
|
||||
rm -f tools/*.o
|
||||
rm -f $(BINDIR)/retroarch
|
||||
rm -f $(BINDIR)/retroarch-joyconfig
|
||||
rm -f $(PNDDIR)/readme.html
|
||||
rm -f retroarch
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
# This build was put together and is maintained by ModMyClassic.com for Libretro.
|
||||
# The purpose is to give Libretro a proper "official" build platform for classic consoles.
|
||||
# If you need any help in building for the classics or have any questions then please visit
|
||||
# https://modmyclassic.com and we will help in any way possible!
|
||||
|
||||
# INFO: THIS BUILD TARGET ALSO COVERS THE NESC!!!
|
||||
|
||||
# Building Prerequisites ##############
|
||||
# arm-linux-gnueabihf-strip
|
||||
# patchelf
|
||||
|
||||
include version.all
|
||||
|
||||
# General Shared Variables ############
|
||||
TARGET := retroarch
|
||||
|
||||
# Libretro Defines ####################
|
||||
#HAVE_CLASSIC = Classic Hook, disable some features
|
||||
#HAVE_C_A7A7 = Classic Armv7 Cortex A7 optimisation override
|
||||
#HAVE_HAKCHI = Hakchi Hook, change default configurations etc (TODO)
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
retroarch:
|
||||
#Build the RetroArch Binary for cross platform classics (ARMv7 Cortex A7)
|
||||
patchelf --version #Check if you have patchelf installed... (sudo apt-get install patchelf)
|
||||
CFLAGS="-marm -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard" ./configure --host=arm-linux-gnueabihf --disable-wayland --disable-x11 --disable-opengl --disable-opengl1 --disable-opengl_core --enable-mali_fbdev --disable-freetype --enable-opengles --enable-udev --enable-alsa --enable-neon --enable-floathard --disable-discord
|
||||
make HAVE_CLASSIC=1 HAVE_C_A7A7=1 HAVE_HAKCHI=1 -j #Cook it
|
||||
arm-linux-gnueabihf-strip -v retroarch
|
||||
patchelf --replace-needed libSDL2-2.0.so.0 libSDL2.so retroarch #libSDL2-2.0.so.0 sym link doesn't exist on native build. Just patch the binary...
|
||||
@echo "*********************************************************************"
|
||||
@echo "*** NES/SNES Classic RetroArch binary built successfully! ***"
|
||||
@echo "*********************************************************************"
|
||||
clean:
|
||||
rm -rf obj-unix
|
||||
rm -f *.d
|
||||
rm -f *.o
|
||||
rm -f audio/*.o
|
||||
rm -f conf/*.o
|
||||
rm -f gfx/*.o
|
||||
rm -f gfx/drivers_font/*.o
|
||||
rm -f gfx/drivers_font_renderer/*.o
|
||||
rm -f gfx/drivers_context/*.o
|
||||
rm -f gfx/py_state/*.o
|
||||
rm -f compat/*.o
|
||||
rm -f record/*.o
|
||||
rm -f input/*.o
|
||||
rm -f tools/*.o
|
||||
rm -f $(BINDIR)/retroarch
|
||||
rm -f $(BINDIR)/retroarch-joyconfig
|
||||
rm -f $(PNDDIR)/readme.html
|
||||
rm -f retroarch
|
||||
|
||||
+93
-21
@@ -155,7 +155,6 @@ endif
|
||||
OBJ += frontend/frontend_driver.o \
|
||||
frontend/drivers/platform_null.o \
|
||||
retroarch.o \
|
||||
paths.o \
|
||||
msg_hash.o \
|
||||
intl/msg_hash_us.o \
|
||||
$(LIBRETRO_COMM_DIR)/queues/task_queue.o \
|
||||
@@ -164,6 +163,7 @@ OBJ += frontend/frontend_driver.o \
|
||||
tasks/task_file_transfer.o \
|
||||
tasks/task_image.o \
|
||||
tasks/task_playlist_manager.o \
|
||||
tasks/task_manual_content_scan.o \
|
||||
$(LIBRETRO_COMM_DIR)/encodings/encoding_utf.o \
|
||||
$(LIBRETRO_COMM_DIR)/encodings/encoding_crc32.o \
|
||||
$(LIBRETRO_COMM_DIR)/encodings/encoding_base64.o \
|
||||
@@ -181,7 +181,6 @@ OBJ += frontend/frontend_driver.o \
|
||||
$(LIBRETRO_COMM_DIR)/lists/string_list.o \
|
||||
$(LIBRETRO_COMM_DIR)/string/stdstring.o \
|
||||
$(LIBRETRO_COMM_DIR)/memmap/memalign.o \
|
||||
list_special.o \
|
||||
$(LIBRETRO_COMM_DIR)/file/nbio/nbio_stdio.o
|
||||
|
||||
ifneq ($(findstring Linux,$(OS)),)
|
||||
@@ -260,8 +259,8 @@ OBJ += \
|
||||
performance_counters.o \
|
||||
verbosity.o \
|
||||
midi/drivers/null_midi.o \
|
||||
$(LIBRETRO_COMM_DIR)/playlists/label_sanitization.o
|
||||
|
||||
$(LIBRETRO_COMM_DIR)/playlists/label_sanitization.o \
|
||||
manual_content_scan.o
|
||||
|
||||
ifeq ($(HAVE_AUDIOMIXER), 1)
|
||||
DEFINES += -DHAVE_AUDIOMIXER
|
||||
@@ -595,7 +594,9 @@ ifeq ($(HAVE_ALSA), 1)
|
||||
OBJ += audio/drivers/alsa.o
|
||||
|
||||
ifneq ($(HAVE_HAKCHI), 1)
|
||||
OBJ += midi/drivers/alsa_midi.o
|
||||
ifneq ($(HAVE_SEGAM), 1)
|
||||
OBJ += midi/drivers/alsa_midi.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_THREADS), 1)
|
||||
@@ -799,7 +800,6 @@ endif
|
||||
|
||||
ifeq ($(HAVE_MENU_COMMON), 1)
|
||||
OBJ += menu/menu_driver.o \
|
||||
menu/menu_content.o \
|
||||
menu/menu_setting.o \
|
||||
menu/widgets/menu_filebrowser.o \
|
||||
menu/widgets/menu_dialog.o \
|
||||
@@ -828,6 +828,7 @@ ifeq ($(HAVE_MENU_COMMON), 1)
|
||||
menu/drivers/menu_generic.o \
|
||||
menu/drivers/null.o \
|
||||
menu/menu_thumbnail_path.o \
|
||||
menu/menu_thumbnail.o \
|
||||
menu/drivers_display/menu_display_null.o
|
||||
|
||||
ifeq ($(HAVE_MENU_WIDGETS), 1)
|
||||
@@ -843,13 +844,14 @@ endif
|
||||
|
||||
ifeq ($(HAVE_VIDEO_LAYOUT), 1)
|
||||
DEFINES += -DHAVE_VIDEO_LAYOUT
|
||||
OBJ += gfx/video_layout.o \
|
||||
gfx/video_layout/view.o \
|
||||
gfx/video_layout/element.o \
|
||||
gfx/video_layout/component.o \
|
||||
gfx/video_layout/internal.o \
|
||||
gfx/video_layout/scope.o \
|
||||
gfx/video_layout/load.o
|
||||
OBJ += \
|
||||
gfx/video_layout.o \
|
||||
gfx/video_layout/view.o \
|
||||
gfx/video_layout/element.o \
|
||||
gfx/video_layout/component.o \
|
||||
gfx/video_layout/internal.o \
|
||||
gfx/video_layout/scope.o \
|
||||
gfx/video_layout/load.o
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_STB_FONT), 1)
|
||||
@@ -890,6 +892,7 @@ ifeq ($(HAVE_VITA2D), 1)
|
||||
$(DEPS_DIR)/libvita2d/shader/color_f_gxp.o \
|
||||
$(DEPS_DIR)/libvita2d/shader/texture_v_gxp.o \
|
||||
$(DEPS_DIR)/libvita2d/shader/texture_f_gxp.o \
|
||||
$(DEPS_DIR)/libvita2d/shader/texture_tint_v_gxp.o \
|
||||
$(DEPS_DIR)/libvita2d/shader/texture_tint_f_gxp.o
|
||||
|
||||
ifeq ($(HAVE_MENU_COMMON),1)
|
||||
@@ -984,6 +987,12 @@ ifeq ($(HAVE_WAYLAND), 1)
|
||||
|
||||
endif
|
||||
|
||||
# XML
|
||||
OBJ += \
|
||||
$(LIBRETRO_COMM_DIR)/formats/xml/rxml.o \
|
||||
$(LIBRETRO_COMM_DIR)/formats/logiqx_dat/logiqx_dat.o \
|
||||
deps/yxml/yxml.o
|
||||
|
||||
#Input
|
||||
|
||||
ifeq ($(HAVE_DINPUT), 1)
|
||||
@@ -1129,12 +1138,38 @@ ifeq ($(HAVE_SIXEL), 1)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_NETWORK_VIDEO), 1)
|
||||
ifneq ($(NETWORK_VIDEO_HOST),)
|
||||
DEFINES += -DNETWORK_VIDEO_HOST=$(NETWORK_VIDEO_HOST)
|
||||
else
|
||||
DEFINES += -DNETWORK_VIDEO_HOST=127.0.0.1
|
||||
endif
|
||||
|
||||
ifneq ($(NETWORK_VIDEO_PORT),)
|
||||
DEFINES += -DNETWORK_VIDEO_PORT=$(NETWORK_VIDEO_PORT)
|
||||
else
|
||||
DEFINES += -DNETWORK_VIDEO_PORT=4953
|
||||
endif
|
||||
|
||||
DEFINES += -DHAVE_NETWORK_VIDEO
|
||||
OBJ += gfx/drivers/network_gfx.o \
|
||||
gfx/drivers_context/network_ctx.o
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_PLAIN_DRM), 1)
|
||||
OBJ += gfx/drivers/drm_gfx.o
|
||||
INCLUDE_DIRS += -I/usr/include/libdrm
|
||||
LIBS += -ldrm
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_VITAGL), 1)
|
||||
DEFINES += -DHAVE_OPENGL1
|
||||
OBJ += gfx/drivers/gl1.o \
|
||||
gfx/drivers_font/gl1_raster_font.o \
|
||||
gfx/drivers_context/vita_ctx.o \
|
||||
menu/drivers_display/menu_display_gl1.o
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_GL_CONTEXT), 1)
|
||||
ifeq ($(HAVE_GL_MODERN), 1)
|
||||
DEFINES += -DHAVE_OPENGL
|
||||
@@ -1255,7 +1290,8 @@ endif
|
||||
|
||||
ifeq ($(HAVE_SDL2), 1)
|
||||
HAVE_SDL_COMMON = 1
|
||||
OBJ += gfx/drivers/sdl2_gfx.o
|
||||
OBJ += gfx/drivers/sdl2_gfx.o \
|
||||
gfx/common/sdl2_common.o
|
||||
DEF_FLAGS += $(SDL2_CFLAGS)
|
||||
LIBS += $(SDL2_LIBS)
|
||||
else ifeq ($(HAVE_SDL), 1)
|
||||
@@ -1695,12 +1731,11 @@ endif
|
||||
OBJ += $(LIBRETRO_COMM_DIR)/formats/bmp/rbmp_encode.o \
|
||||
$(LIBRETRO_COMM_DIR)/formats/json/jsonsax.o \
|
||||
$(LIBRETRO_COMM_DIR)/formats/json/jsonsax_full.o \
|
||||
$(LIBRETRO_COMM_DIR)/formats/xml/rxml.o \
|
||||
$(LIBRETRO_COMM_DIR)/formats/image_transfer.o
|
||||
|
||||
# Easter Egg
|
||||
ifeq ($(HAVE_EASTEREGG),1)
|
||||
DEFINES += -DHAVE_EASTEREGG
|
||||
# Gong embedded core
|
||||
ifeq ($(HAVE_GONG),1)
|
||||
DEFINES += -DHAVE_GONG
|
||||
OBJ += cores/libretro-gong/gong.o
|
||||
endif
|
||||
|
||||
@@ -1725,6 +1760,7 @@ ifeq ($(HAVE_NETWORKING), 1)
|
||||
$(LIBRETRO_COMM_DIR)/net/net_http_parse.o \
|
||||
$(LIBRETRO_COMM_DIR)/net/net_socket.o \
|
||||
$(LIBRETRO_COMM_DIR)/net/net_natt.o \
|
||||
core_updater_list.o \
|
||||
network/net_http_special.o \
|
||||
tasks/task_http.o \
|
||||
tasks/task_netplay_lan_scan.o \
|
||||
@@ -1734,7 +1770,8 @@ ifeq ($(HAVE_NETWORKING), 1)
|
||||
|
||||
ifeq ($(HAVE_MENU_COMMON), 1)
|
||||
OBJ += tasks/task_pl_thumbnail_download.o \
|
||||
menu/menu_networking.o
|
||||
tasks/task_core_updater.o \
|
||||
menu/menu_networking.o
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_SSL), 1)
|
||||
@@ -1777,6 +1814,7 @@ ifeq ($(HAVE_NETWORKING), 1)
|
||||
cheevos-new/fixup.o \
|
||||
cheevos-new/parser.o \
|
||||
cheevos-new/hash.o \
|
||||
$(LIBRETRO_COMM_DIR)/formats/cdfs/cdfs.o \
|
||||
deps/rcheevos/src/rcheevos/trigger.o \
|
||||
deps/rcheevos/src/rcheevos/condset.o \
|
||||
deps/rcheevos/src/rcheevos/condition.o \
|
||||
@@ -1893,6 +1931,13 @@ ifeq ($(HAVE_NETWORKING), 1)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(findstring FPGA,$(OS)),)
|
||||
OBJ += gfx/drivers/fpga_gfx.o \
|
||||
gfx/drivers_context/fpga_ctx.o \
|
||||
gfx/drivers_font/fpga_font.o \
|
||||
menu/drivers_display/menu_display_fpga.o
|
||||
endif
|
||||
|
||||
ifneq ($(findstring Win32,$(OS)),)
|
||||
OBJ += media/rarch.o \
|
||||
gfx/common/win32_common.o \
|
||||
@@ -1911,11 +1956,20 @@ ifneq ($(findstring Win32,$(OS)),)
|
||||
LIBS += -lhid -lsetupapi
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_ANGLE), 1)
|
||||
OBJ += gfx/common/angle_common.o
|
||||
DEFINES += -DHAVE_ANGLE
|
||||
# TODO/FIXME - should perhaps set these libraries as separate CFLAG variables in qb system
|
||||
LIBS += -lEGL
|
||||
endif
|
||||
|
||||
# Record
|
||||
|
||||
ifeq ($(HAVE_FFMPEG), 1)
|
||||
OBJ += record/drivers/record_ffmpeg.o \
|
||||
cores/libretro-ffmpeg/ffmpeg_core.o
|
||||
cores/libretro-ffmpeg/ffmpeg_core.o \
|
||||
cores/libretro-ffmpeg/video_buffer.o \
|
||||
$(LIBRETRO_COMM_DIR)/rthreads/tpool.o
|
||||
|
||||
LIBS += $(AVCODEC_LIBS) $(AVFORMAT_LIBS) $(AVUTIL_LIBS) $(SWSCALE_LIBS) $(SWRESAMPLE_LIBS) $(FFMPEG_LIBS)
|
||||
DEFINES += -DHAVE_FFMPEG
|
||||
@@ -2007,10 +2061,24 @@ ifeq ($(HAVE_RPILED), 1)
|
||||
OBJ += led/drivers/led_rpi.o
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_MATH_NEON), 1)
|
||||
DEFINES += -DHAVE_MATH_NEON
|
||||
INCLUDE_DIRS += -I$(DEPS_DIR)/math-neon/source
|
||||
SOURCES := $(DEPS_DIR)/math-neon/source
|
||||
OBJ += $(patsubst %.c,%.o,$(foreach dir,$(SOURCES), $(wildcard $(dir)/*.c)))
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_VITAGL), 1)
|
||||
DEFINES += -DHAVE_VITAGL -DTRANSPOSE_MATRICES
|
||||
INCLUDE_DIRS += -I$(DEPS_DIR)/vitaGL/source
|
||||
SOURCES := $(DEPS_DIR)/vitaGL/source $(DEPS_DIR)/vitaGL/source/utils
|
||||
OBJ += $(patsubst %.c,%.o,$(foreach dir,$(SOURCES), $(wildcard $(dir)/*.c)))
|
||||
endif
|
||||
|
||||
##################################
|
||||
### Classic Platform specifics ###
|
||||
###############WIP################
|
||||
# Help at https://modmyclassic.com/comp
|
||||
# Help at https://modmyclassic.com
|
||||
|
||||
ifeq ($(HAVE_CLASSIC), 1)
|
||||
DEFINES += -DHAVE_CLASSIC
|
||||
@@ -2040,4 +2108,8 @@ endif
|
||||
ifeq ($(HAVE_HAKCHI), 1)
|
||||
DEFINES += -DHAVE_HAKCHI
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_SEGAM), 1)
|
||||
DEFINES += -DHAVE_SEGAM
|
||||
endif
|
||||
##################################
|
||||
+7
-8
@@ -17,7 +17,6 @@ HAVE_CC_RESAMPLER = 1
|
||||
HAVE_EGL = 1
|
||||
HAVE_OPENGLES = 1
|
||||
HAVE_RJPEG = 0
|
||||
HAVE_RPNG = 1
|
||||
HAVE_EMSCRIPTEN = 1
|
||||
HAVE_MENU = 1
|
||||
HAVE_MENU_WIDGETS = 1
|
||||
@@ -30,7 +29,7 @@ HAVE_STATIC_VIDEO_FILTERS = 1
|
||||
HAVE_STATIC_AUDIO_FILTERS = 1
|
||||
HAVE_STB_FONT = 1
|
||||
|
||||
MEMORY = 536870912
|
||||
MEMORY = 134217728
|
||||
|
||||
PRECISE_F32 = 1
|
||||
|
||||
@@ -38,9 +37,9 @@ OBJDIR := obj-emscripten
|
||||
|
||||
#if you compile with SDL2 flag add this Emscripten flag "-s USE_SDL=2" to LDFLAGS:
|
||||
|
||||
LIBS := -s USE_ZLIB=1
|
||||
LDFLAGS := -L. --no-heap-copy -s USE_ZLIB=1 -s TOTAL_MEMORY=$(MEMORY) -s NO_EXIT_RUNTIME=0 -s FULL_ES2=1 \
|
||||
-s EXPORTED_FUNCTIONS="['_main', '_malloc', '_cmd_savefiles', '_cmd_save_state', '_cmd_load_state', '_cmd_take_screenshot']" \
|
||||
LIBS := -s USE_ZLIB=1 -s USE_LIBPNG=1
|
||||
LDFLAGS := -L. --no-heap-copy -s $(LIBS) -s TOTAL_MEMORY=$(MEMORY) -s NO_EXIT_RUNTIME=0 -s FULL_ES2=1 -s "EXTRA_EXPORTED_RUNTIME_METHODS=['callMain']" \
|
||||
-s ALLOW_MEMORY_GROWTH=1 -s EXPORTED_FUNCTIONS="['_main', '_malloc', '_cmd_savefiles', '_cmd_save_state', '_cmd_load_state', '_cmd_take_screenshot']" \
|
||||
--js-library emscripten/library_rwebaudio.js \
|
||||
--js-library emscripten/library_rwebcam.js \
|
||||
--js-library emscripten/library_errno_codes.js
|
||||
@@ -70,16 +69,16 @@ ifeq ($(DEBUG), 1)
|
||||
LDFLAGS += -O0 -g
|
||||
CFLAGS += -O0 -g
|
||||
else
|
||||
LDFLAGS += -O2 -s WASM=1
|
||||
LDFLAGS += -O3 -s WASM=1
|
||||
# WARNING: some optimizations can break some cores (ex: LTO breaks tyrquake)
|
||||
LDFLAGS += -s PRECISE_F32=$(PRECISE_F32)
|
||||
ifeq ($(LTO), 1)
|
||||
LDFLAGS += --llvm-lto 3
|
||||
endif
|
||||
CFLAGS += -O2
|
||||
CFLAGS += -O3
|
||||
endif
|
||||
|
||||
CFLAGS += -DHAVE_RPNG -Wall -I. -Ilibretro-common/include -std=gnu99 -s USE_ZLIB=1 \
|
||||
CFLAGS += -Wall -I. -Ilibretro-common/include -std=gnu99 $(LIBS) \
|
||||
-s EXPORTED_FUNCTIONS="['_main', '_malloc', '_cmd_savefiles', '_cmd_save_state', '_cmd_take_screenshot']"
|
||||
|
||||
RARCH_OBJ := $(addprefix $(OBJDIR)/,$(OBJ))
|
||||
|
||||
+6
-6
@@ -439,7 +439,7 @@ else ifeq ($(platform), windows_msvc2005_x86)
|
||||
CXX = cl.exe
|
||||
LD = link.exe
|
||||
|
||||
PLATCFLAGS += -D_WIN32 -D_WIN32_WINNT=0x0410 -D__STDC_CONSTANT_MACROS -D_MBCS -DHAVE_EASTEREGG -D__MMX__ -D__SSE__ -DHAVE_OPENGL -DHAVE_OPENGL1 -DHAVE_GLSL -DHAVE_SHADERPIPELINE -DHAVE_OZONE
|
||||
PLATCFLAGS += -D_WIN32 -D_WIN32_WINNT=0x0410 -D__STDC_CONSTANT_MACROS -D_MBCS -D__MMX__ -D__SSE__ -DHAVE_OPENGL -DHAVE_OPENGL1 -DHAVE_GLSL -DHAVE_SHADERPIPELINE -DHAVE_OZONE
|
||||
LDFLAGS += shell32.lib user32.lib gdi32.lib comdlg32.lib winmm.lib ole32.lib msimg32.lib
|
||||
|
||||
PATH := $(shell IFS=$$'\n'; cygpath "$(VS80COMNTOOLS)../../VC/bin"):$(PATH)
|
||||
@@ -491,7 +491,7 @@ else ifneq (,$(findstring windows_msvc2010,$(platform)))
|
||||
LD = link.exe
|
||||
|
||||
PLATCFLAGS += -D_WIN32 -D__STDC_CONSTANT_MACROS -D_MBCS
|
||||
PLATCFLAGS += -D__i686__ -D__MMX__ -D__SSE__ -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -D_WINDOWS -DHAVE_CC_RESAMPLER -DHAVE_GL_SYNC -DHAVE_GLSL -DHAVE_IMAGEVIEWER -DHAVE_LANGEXTRA -DHAVE_OPENGL -DHAVE_SHADERPIPELINE -DHAVE_UPDATE_ASSETS -DWIN32 -DHAVE_EASTEREGG -DHAVE_CDROM
|
||||
PLATCFLAGS += -D__i686__ -D__MMX__ -D__SSE__ -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -D_WINDOWS -DHAVE_CC_RESAMPLER -DHAVE_GL_SYNC -DHAVE_GLSL -DHAVE_IMAGEVIEWER -DHAVE_LANGEXTRA -DHAVE_OPENGL -DHAVE_SHADERPIPELINE -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS -DHAVE_UPDATE_CORES -DWIN32 -DHAVE_CDROM
|
||||
LDFLAGS += shell32.lib user32.lib gdi32.lib comdlg32.lib winmm.lib ole32.lib iphlpapi.lib msimg32.lib
|
||||
|
||||
PlatformSuffix = $(subst windows_msvc2010_,,$(platform))
|
||||
@@ -565,7 +565,7 @@ else ifneq (,$(findstring windows_msvc2012,$(platform)))
|
||||
LD = link.exe
|
||||
|
||||
PLATCFLAGS += -D_WIN32 -D__STDC_CONSTANT_MACROS -D_MBCS
|
||||
PLATCFLAGS += -D__i686__ -D__MMX__ -D__SSE__ -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -D_WINDOWS -DHAVE_CC_RESAMPLER -DHAVE_GL_SYNC -DHAVE_GLSL -DHAVE_IMAGEVIEWER -DHAVE_LANGEXTRA -DHAVE_OPENGL -DHAVE_SHADERPIPELINE -DHAVE_UPDATE_ASSETS -DWIN32 -DHAVE_EASTEREGG -DHAVE_CDROM
|
||||
PLATCFLAGS += -D__i686__ -D__MMX__ -D__SSE__ -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -D_WINDOWS -DHAVE_CC_RESAMPLER -DHAVE_GL_SYNC -DHAVE_GLSL -DHAVE_IMAGEVIEWER -DHAVE_LANGEXTRA -DHAVE_OPENGL -DHAVE_SHADERPIPELINE -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS -DHAVE_UPDATE_CORES -DWIN32 -DHAVE_CDROM
|
||||
LDFLAGS += shell32.lib user32.lib gdi32.lib comdlg32.lib winmm.lib ole32.lib iphlpapi.lib
|
||||
|
||||
PlatformSuffix = $(subst windows_msvc2012_,,$(platform))
|
||||
@@ -643,7 +643,7 @@ else ifneq (,$(findstring windows_msvc2013,$(platform)))
|
||||
LD = link.exe
|
||||
|
||||
PLATCFLAGS += -D_WIN32 -D__STDC_CONSTANT_MACROS -D_MBCS
|
||||
PLATCFLAGS += -D__i686__ -D__MMX__ -D__SSE__ -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -D_WINDOWS -DHAVE_CC_RESAMPLER -DHAVE_GL_SYNC -DHAVE_GLSL -DHAVE_IMAGEVIEWER -DHAVE_LANGEXTRA -DHAVE_OPENGL -DHAVE_SHADERPIPELINE -DHAVE_UPDATE_ASSETS -DWIN32 -DHAVE_EASTEREGG -DHAVE_CDROM
|
||||
PLATCFLAGS += -D__i686__ -D__MMX__ -D__SSE__ -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -D_WINDOWS -DHAVE_CC_RESAMPLER -DHAVE_GL_SYNC -DHAVE_GLSL -DHAVE_IMAGEVIEWER -DHAVE_LANGEXTRA -DHAVE_OPENGL -DHAVE_SHADERPIPELINE -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS -DHAVE_UPDATE_CORES -DWIN32 -DHAVE_CDROM
|
||||
LDFLAGS += shell32.lib user32.lib gdi32.lib comdlg32.lib winmm.lib ole32.lib iphlpapi.lib
|
||||
|
||||
PlatformSuffix = $(subst windows_msvc2013_,,$(platform))
|
||||
@@ -722,7 +722,7 @@ else ifneq (,$(findstring windows_msvc2015,$(platform)))
|
||||
|
||||
PLATCFLAGS += -utf-8
|
||||
PLATCFLAGS += -D_WIN32 -D__STDC_CONSTANT_MACROS -D_MBCS
|
||||
PLATCFLAGS += -D__i686__ -D__MMX__ -D__SSE__ -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -D_WINDOWS -DHAVE_CC_RESAMPLER -DHAVE_GL_SYNC -DHAVE_GLSL -DHAVE_IMAGEVIEWER -DHAVE_LANGEXTRA -DHAVE_OPENGL -DHAVE_SHADERPIPELINE -DHAVE_UPDATE_ASSETS -DWIN32 -DHAVE_EASTEREGG -DHAVE_CDROM
|
||||
PLATCFLAGS += -D__i686__ -D__MMX__ -D__SSE__ -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -D_WINDOWS -DHAVE_CC_RESAMPLER -DHAVE_GL_SYNC -DHAVE_GLSL -DHAVE_IMAGEVIEWER -DHAVE_LANGEXTRA -DHAVE_OPENGL -DHAVE_SHADERPIPELINE -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS -DHAVE_UPDATE_CORES -DWIN32 -DHAVE_CDROM
|
||||
LDFLAGS += shell32.lib user32.lib gdi32.lib comdlg32.lib winmm.lib ole32.lib iphlpapi.lib
|
||||
|
||||
PlatformSuffix = $(subst windows_msvc2015_,,$(platform))
|
||||
@@ -806,7 +806,7 @@ else ifneq (,$(findstring unix,$(platform)))
|
||||
HAVE_GRIFFIN_CPP := 1
|
||||
WANT_GLSLANG := 1
|
||||
|
||||
PLATCFLAGS += -DHAVE_EASTEREGG -D__MMX__ -D__SSE__ -DHAVE_OPENGL -DHAVE_OPENGL1 -DHAVE_GLSL -DHAVE_SHADERPIPELINE -DHAVE_OZONE -DHAVE_CC_RESAMPLER -DHAVE_CHEEVOS -DRC_DISABLE_LUA -DHAVE_FBO -DHAVE_GL_SYNC -DHAVE_SLANG -DHAVE_GLSLANG -DHAVE_IMAGEVIEWER -DHAVE_LANGEXTRA -DHAVE_RUNAHEAD -DHAVE_MENU_WIDGETS -DHAVE_SPIRV_CROSS -DHAVE_STB_FONT -DHAVE_UPDATE_ASSETS -DHAVE_VULKAN -DHAVE_XMB -DRARCH_INTERNAL -DWANT_GLSLANG -DHAVE_X11 -DHAVE_XCB -DHAVE_UDEV -DHAVE_PULSE
|
||||
PLATCFLAGS += -D__MMX__ -D__SSE__ -DHAVE_OPENGL -DHAVE_OPENGL1 -DHAVE_GLSL -DHAVE_SHADERPIPELINE -DHAVE_OZONE -DHAVE_CC_RESAMPLER -DHAVE_CHEEVOS -DRC_DISABLE_LUA -DHAVE_FBO -DHAVE_GL_SYNC -DHAVE_SLANG -DHAVE_GLSLANG -DHAVE_IMAGEVIEWER -DHAVE_LANGEXTRA -DHAVE_RUNAHEAD -DHAVE_MENU_WIDGETS -DHAVE_SPIRV_CROSS -DHAVE_STB_FONT -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS -DHAVE_UPDATE_CORES -DHAVE_VULKAN -DHAVE_XMB -DRARCH_INTERNAL -DWANT_GLSLANG -DHAVE_X11 -DHAVE_XCB -DHAVE_UDEV -DHAVE_PULSE
|
||||
EXT_TARGET := $(TARGET_NAME)
|
||||
EXT_INTER_TARGET := $(TARGET_NAME)
|
||||
INCLUDE += -Ilibretro-common/include -Igfx/include -Ideps -Ideps/stb -Ideps/rcheevos/include -Ideps/SPIRV-Cross -Ideps/glslang -I.
|
||||
|
||||
+4
-2
@@ -21,6 +21,8 @@ OBJ :=
|
||||
|
||||
DEFINES := -D__SWITCH__=1 -U__linux__ -U__linux -DGLM_FORCE_PURE=1 -DRARCH_CONSOLE -DRARCH_INTERNAL -DGLOBAL_CONFIG_DIR='"/switch"' -DHAVE_STB_VORBIS
|
||||
|
||||
HAVE_DR_MP3 = 1
|
||||
HAVE_TRANSLATE = 1
|
||||
HAVE_AUDIOMIXER = 1
|
||||
HAVE_CC_RESAMPLER = 1
|
||||
HAVE_MENU_COMMON = 1
|
||||
@@ -60,7 +62,7 @@ ifeq ($(HAVE_OPENGL), 1)
|
||||
HAVE_XMB = 1
|
||||
HAVE_OZONE = 1
|
||||
HAVE_OVERLAY = 1
|
||||
HAVE_VIDEO_LAYOUT = 0
|
||||
HAVE_VIDEO_LAYOUT = 1
|
||||
HAVE_GLSL = 1
|
||||
else
|
||||
HAVE_RGUI = 1
|
||||
@@ -116,7 +118,7 @@ ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE -mcpu=cortex-a57+crc+fp
|
||||
CFLAGS := -g -Wall -O3 -ffast-math -ffunction-sections \
|
||||
$(ARCH) $(DEFINES) $(INCLUDE_DIRS) -I$(LIBNX)/include -I$(PORTLIBS)/include/ -include $(LIBNX)/include/switch.h #$(shell $(PORTLIBS)/bin/freetype-config --cflags)
|
||||
|
||||
CFLAGS += $(INCLUDE) -DSWITCH=1 -DHAVE_LIBNX=1 -DNXLINK=1 -DHAVE_SHADERPIPELINE -DHAVE_UPDATE_ASSETS -DHAVE_STB_FONT #-DHAVE_FREETYPE
|
||||
CFLAGS += $(INCLUDE) -DSWITCH=1 -DHAVE_LIBNX=1 -DNXLINK=1 -DHAVE_SHADERPIPELINE -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS -DHAVE_UPDATE_CORES -DHAVE_STB_FONT #-DHAVE_FREETYPE
|
||||
|
||||
ifeq ($(strip $(HAVE_STATIC_DUMMY)),1)
|
||||
CFLAGS += -DHAVE_STATIC_DUMMY=1
|
||||
|
||||
+4
-1
@@ -1,4 +1,4 @@
|
||||
BUILD_PRX = 0
|
||||
BUILD_FOR_PCSX2 = 0
|
||||
DEBUG = 0
|
||||
HAVE_KERNEL_PRX = 0
|
||||
HAVE_LOGGER = 0
|
||||
@@ -45,6 +45,9 @@ LDFLAGS += -L$(PS2SDK)/ports/lib -L$(PS2DEV)/gsKit/lib -L$(PS2SDK)/ee/lib -L$(CD
|
||||
LIBS += -lretro_ps2 -lgskit -ldmakit -lgskit_toolkit -laudsrv -lmf -lpadx -lmtap -lmc -lhdd -lsdl -lfileXio -lz
|
||||
LIBS += -lcdvdfs -lpatches -lpoweroff
|
||||
|
||||
ifeq ($(BUILD_FOR_PCSX2), 1)
|
||||
RARCH_DEFINES += -DBUILD_FOR_PCSX2
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_THREADS), 1)
|
||||
RARCH_DEFINES += -DHAVE_THREADS
|
||||
|
||||
+13
-10
@@ -18,7 +18,7 @@ ifeq ($(GRIFFIN_BUILD), 1)
|
||||
OBJ += griffin/griffin.o
|
||||
DEFINES += -DHAVE_GRIFFIN=1
|
||||
DEFINES += -DHAVE_NEON -DHAVE_MENU -DHAVE_XMB -DHAVE_MATERIALUI -DHAVE_LIBRETRODB DEFINES -DHAVE_KEYMAPPER
|
||||
DEFINES += -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA -DHAVE_CC_RESAMPLER -DHAVE_UPDATE_ASSETS
|
||||
DEFINES += -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA -DHAVE_CC_RESAMPLER -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS -DHAVE_UPDATE_CORES
|
||||
ifeq ($(DEBUG), 1)
|
||||
DEFINES += -DHAVE_NETLOGGER
|
||||
endif
|
||||
@@ -26,6 +26,7 @@ ifeq ($(GRIFFIN_BUILD), 1)
|
||||
else
|
||||
|
||||
HAVE_NEON := 1
|
||||
HAVE_MATH_NEON := 1
|
||||
HAVE_FILTERS_BUILTIN := 1
|
||||
HAVE_LANGEXTRA := 1
|
||||
HAVE_RPNG := 1
|
||||
@@ -35,10 +36,12 @@ else
|
||||
HAVE_ZLIB := 1
|
||||
HAVE_7ZIP := 1
|
||||
HAVE_VITA2D := 1
|
||||
HAVE_VITAGL := 1
|
||||
HAVE_NETWORKING := 1
|
||||
HAVE_SOCKET_LEGACY := 1
|
||||
HAVE_MENU := 1
|
||||
HAVE_MENU_COMMON := 1
|
||||
HAVE_MENU_WIDGETS = 1
|
||||
HAVE_OVERLAY := 1
|
||||
HAVE_VIDEO_LAYOUT := 0
|
||||
HAVE_MATERIALUI := 1
|
||||
@@ -85,18 +88,16 @@ LD := $(CXX)
|
||||
LIBDIRS := -L.
|
||||
|
||||
ARCHFLAGS := -march=armv7-a -mfpu=neon -mfloat-abi=hard -DVITA
|
||||
CFLAGS += $(ARCHFLAGS) -mword-relocations -fno-optimize-sibling-calls
|
||||
CFLAGS += $(ARCHFLAGS) -mword-relocations -fno-optimize-sibling-calls -O2
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
CFLAGS += -O2 -g
|
||||
else
|
||||
CFLAGS += -O3
|
||||
CFLAGS += -g
|
||||
endif
|
||||
|
||||
ASFLAGS := $(CFLAGS)
|
||||
LDFLAGS := -Wl,-q
|
||||
|
||||
CFLAGS += -Wall -ffast-math
|
||||
CFLAGS += -Wall -ffast-math -g
|
||||
CFLAGS += -DRARCH_INTERNAL -DRARCH_CONSOLE
|
||||
CFLAGS += -DHAVE_FILTERS_BUILTIN $(DEFINES)
|
||||
|
||||
@@ -114,9 +115,9 @@ ifeq ($(WHOLE_ARCHIVE_LINK), 1)
|
||||
endif
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
|
||||
|
||||
VITA_LIBS := -lSceDisplay_stub -lSceGxm_stub -lSceNet_stub -lSceNetCtl_stub \
|
||||
VITA_LIBS := -lSceDisplay_stub -lSceGxm_stub -lSceNet_stub -lSceNetCtl_stub -lSceAppUtil_stub \
|
||||
-lSceSysmodule_stub -lSceCtrl_stub -lSceHid_stub -lSceTouch_stub -lSceAudio_stub \
|
||||
-lScePower_stub -lSceRtc_stub -lSceCommonDialog_stub -lScePgf_stub \
|
||||
-lScePower_stub -lSceRtc_stub -lSceCommonDialog_stub -lScePgf_stub -lSceMotion_stub \
|
||||
-lSceFiber_stub -lSceMotion_stub -lSceAppMgr_stub -lpthread -lpng -lz
|
||||
|
||||
LIBS := $(WHOLE_START) -lretro_vita $(WHOLE_END) $(VITA_LIBS) -lm -lc
|
||||
@@ -154,17 +155,19 @@ $(TARGET).elf: $(OBJ) libretro_vita.a
|
||||
$(LD) $(OBJ) $(LDFLAGS) $(LIBDIRS) $(LIBS) -o $@
|
||||
|
||||
%.velf: %.elf
|
||||
cp $< $<.unstripped.elf
|
||||
$(PREFIX)strip -g $<
|
||||
vita-elf-create $< $@
|
||||
|
||||
%.self: %.velf
|
||||
vita-make-fself -c -s $< $@
|
||||
|
||||
%.vpk: %.self
|
||||
vita-mksfoex -s TITLE_ID=$(VITA_TITLE_ID) "$(VITA_TITLE_NAME)" param.sfo
|
||||
vita-mksfoex -s TITLE_ID=$(VITA_TITLE_ID) "$(VITA_TITLE_NAME)" -d ATTRIBUTE2=12 param.sfo
|
||||
vita-pack-vpk -s param.sfo -b $< $@
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ) $(TARGET).elf $(TARGET).velf $(TARGET).self param.sfo $(TARGET).vpk
|
||||
rm -f $(OBJ) $(TARGET).elf $(TARGET).elf.unstripped.elf $(TARGET).velf $(TARGET).self param.sfo $(TARGET).vpk
|
||||
rm -f $(OBJ:.o=.depend)
|
||||
|
||||
# Useful for developers
|
||||
|
||||
@@ -21,9 +21,9 @@ RARCH_DEFINES = -DVITA -DIS_SALAMANDER -DRARCH_CONSOLE
|
||||
|
||||
LIBDIR =
|
||||
LDFLAGS =
|
||||
LIBS = -lSceDisplay_stub -lSceGxm_stub -lSceNet_stub -lSceNetCtl_stub\
|
||||
LIBS = -lSceDisplay_stub -lSceGxm_stub -lSceNet_stub -lSceNetCtl_stub -lSceAppUtil_stub\
|
||||
-lSceSysmodule_stub -lSceCtrl_stub -lSceHid_stub -lSceAudio_stub -lSceFiber_stub\
|
||||
-lScePower_stub -lSceRtc_stub -lSceCommonDialog_stub -lScePgf_stub \
|
||||
-lScePower_stub -lSceRtc_stub -lSceCommonDialog_stub -lScePgf_stub -lSceMotion_stub \
|
||||
-lSceMotion_stub -lSceAppMgr_stub -lfreetype -lpng -lm -lc
|
||||
|
||||
ifeq ($(HAVE_FILE_LOGGER), 1)
|
||||
@@ -55,7 +55,7 @@ OBJS = frontend/frontend_salamander.o \
|
||||
all: $(TARGET).vpk
|
||||
|
||||
%.vpk: eboot.bin
|
||||
vita-mksfoex -s TITLE_ID=$(TITLE_ID) "$(TARGET)" param.sfo
|
||||
vita-mksfoex -s TITLE_ID=$(TITLE_ID) "$(TARGET)" -d ATTRIBUTE2=12 param.sfo
|
||||
vita-pack-vpk -s param.sfo -b eboot.bin $@
|
||||
|
||||
eboot.bin: $(TARGET).velf
|
||||
|
||||
@@ -74,7 +74,9 @@ ifeq ($(SALAMANDER_BUILD),1)
|
||||
else
|
||||
DEFINES += -DRARCH_INTERNAL
|
||||
DEFINES += -DHAVE_KEYMAPPER
|
||||
DEFINES += -DHAVE_ONLINE_UPDATER
|
||||
DEFINES += -DHAVE_UPDATE_ASSETS
|
||||
DEFINES += -DHAVE_UPDATE_CORES
|
||||
DEFINES += -DHAVE_FILTERS_BUILTIN
|
||||
DEFINES += -DHAVE_SLANG
|
||||
DEFINES += -DHAVE_SHADERPIPELINE
|
||||
|
||||
+11
-4
@@ -4,9 +4,11 @@
|
||||
#include <psp2/kernel/sysmem.h>
|
||||
#include <psp2/kernel/threadmgr.h>
|
||||
|
||||
static int _newlib_heap_memblock;
|
||||
static unsigned _newlib_heap_size;
|
||||
static char *_newlib_heap_base, *_newlib_heap_end, *_newlib_heap_cur;
|
||||
#define RAM_THRESHOLD 0x1000000 // Memory left to the system for threads and other internal stuffs
|
||||
|
||||
int _newlib_heap_memblock;
|
||||
unsigned _newlib_heap_size;
|
||||
char *_newlib_heap_base, *_newlib_heap_end, *_newlib_heap_cur;
|
||||
static char _newlib_sbrk_mutex[32] __attribute__ ((aligned (8)));
|
||||
|
||||
static int _newlib_vm_memblock;
|
||||
@@ -50,11 +52,16 @@ void _init_vita_heap(void) {
|
||||
if (sceKernelCreateLwMutex((struct SceKernelLwMutexWork*)_newlib_sbrk_mutex, "sbrk mutex", 0, 0, 0) < 0) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
// Always allocating the max avaliable USER_RW mem on the system
|
||||
SceKernelFreeMemorySizeInfo info;
|
||||
info.size = sizeof(SceKernelFreeMemorySizeInfo);
|
||||
sceKernelGetFreeMemorySize(&info);
|
||||
|
||||
if (&_newlib_heap_size_user != NULL) {
|
||||
_newlib_heap_size = _newlib_heap_size_user;
|
||||
}else{
|
||||
_newlib_heap_size = 192 * 1024 * 1024;
|
||||
_newlib_heap_size = info.size_user - RAM_THRESHOLD;
|
||||
}
|
||||
|
||||
_newlib_heap_size -= _newlib_vm_size;
|
||||
|
||||
+898
-324
File diff suppressed because it is too large.
Load diff
+24
-3
@@ -168,9 +168,30 @@ const uint8_t* rcheevos_patch_address(unsigned address, int console)
|
||||
}
|
||||
else if (console == RC_CONSOLE_PC_ENGINE)
|
||||
{
|
||||
/* RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "PCE memory address %X adjusted to %X\n", address, address + 0x1f0000);
|
||||
address += 0x1f0000;
|
||||
if (address < 0x002000)
|
||||
{
|
||||
/* RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "PCE memory address %X adjusted to %X\n", address, address + 0x1f0000);
|
||||
address += 0x1f0000;
|
||||
}
|
||||
else if (address < 0x012000)
|
||||
{
|
||||
/* CD-ROM RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "PCE memory address %X adjusted to %X\n", address, address + 0x100000 - 0x002000);
|
||||
address += 0x100000 - 0x002000;
|
||||
}
|
||||
else if (address < 0x042000)
|
||||
{
|
||||
/* Super System Card RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "PCE memory address %X adjusted to %X\n", address, address + 0x0d0000 - 0x012000);
|
||||
address += 0x0d0000 - 0x012000;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* CD-ROM battery backed RAM. */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "PCE memory address %X adjusted to %X\n", address, address + 0x1ee000 - 0x042000);
|
||||
address += 0x1ee000 - 0x042000;
|
||||
}
|
||||
}
|
||||
else if (console == RC_CONSOLE_SUPER_NINTENDO)
|
||||
{
|
||||
|
||||
+91
-22
@@ -93,7 +93,11 @@
|
||||
#define DEFAULT_MAX_PADS 16
|
||||
#endif
|
||||
|
||||
#if defined(RARCH_MOBILE) || defined(HAVE_LIBNX)
|
||||
#if defined(GEKKO)
|
||||
#define DEFAULT_MOUSE_SCALE 1
|
||||
#endif
|
||||
|
||||
#if defined(RARCH_MOBILE) || defined(HAVE_LIBNX) || defined(__WINRT__)
|
||||
#define DEFAULT_POINTER_ENABLE true
|
||||
#else
|
||||
#define DEFAULT_POINTER_ENABLE false
|
||||
@@ -110,9 +114,54 @@
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MATERIALUI
|
||||
/* Show icons to the left of each menu entry */
|
||||
#define DEFAULT_MATERIALUI_ICONS_ENABLE true
|
||||
#endif
|
||||
|
||||
/* Material UI colour theme */
|
||||
#define DEFAULT_MATERIALUI_THEME MATERIALUI_THEME_OZONE_DARK
|
||||
|
||||
/* Type of animation to use when performing menu transitions
|
||||
* > 'Auto' follows Material UI standards:
|
||||
* - Slide when switching between parent menus (tabs)
|
||||
* - Fade when changing levels in a menu
|
||||
* Note: Not wrapping this with a HAVE_MATERIALUI ifdef
|
||||
* because there's too much baggage involved... */
|
||||
#define DEFAULT_MATERIALUI_TRANSITION_ANIM MATERIALUI_TRANSITION_ANIM_AUTO
|
||||
|
||||
/* Adjust menu padding etc. to better fit the
|
||||
* screen when using landscape layouts */
|
||||
#if defined(RARCH_MOBILE)
|
||||
#define DEFAULT_MATERIALUI_LANDSCAPE_LAYOUT_OPTIMIZATION MATERIALUI_LANDSCAPE_LAYOUT_OPTIMIZATION_DISABLED
|
||||
#else
|
||||
#define DEFAULT_MATERIALUI_LANDSCAPE_LAYOUT_OPTIMIZATION MATERIALUI_LANDSCAPE_LAYOUT_OPTIMIZATION_ALWAYS
|
||||
#endif
|
||||
|
||||
/* Reposition navigation bar to make better use
|
||||
* of screen space when using landscape layouts */
|
||||
#define DEFAULT_MATERIALUI_AUTO_ROTATE_NAV_BAR true
|
||||
|
||||
/* Default portrait/landscape playlist view modes
|
||||
* (when thumbnails are enabled) */
|
||||
#define DEFAULT_MATERIALUI_THUMBNAIL_VIEW_PORTRAIT MATERIALUI_THUMBNAIL_VIEW_PORTRAIT_LIST_SMALL
|
||||
#define DEFAULT_MATERIALUI_THUMBNAIL_VIEW_LANDSCAPE MATERIALUI_THUMBNAIL_VIEW_LANDSCAPE_LIST_MEDIUM
|
||||
|
||||
/* Enable second thumbnail when using 'list view'
|
||||
* thumbnail views
|
||||
* Note: Second thumbnail will only be drawn if
|
||||
* display has sufficient horizontal real estate */
|
||||
#if defined(RARCH_MOBILE)
|
||||
#define DEFAULT_MATERIALUI_DUAL_THUMBNAIL_LIST_VIEW_ENABLE false
|
||||
#else
|
||||
#define DEFAULT_MATERIALUI_DUAL_THUMBNAIL_LIST_VIEW_ENABLE true
|
||||
#endif
|
||||
|
||||
/* Draw solid colour 4:3 background when rendering
|
||||
* thumbnails
|
||||
* > Helps to unify menu appearance when viewing
|
||||
* thumbnails of different sizes */
|
||||
#define DEFAULT_MATERIALUI_THUMBNAIL_BACKGROUND_ENABLE true
|
||||
|
||||
#define DEFAULT_CRT_SWITCH_RESOLUTION CRT_SWITCH_NONE
|
||||
|
||||
#define DEFAULT_CRT_SWITCH_RESOLUTION_SUPER 2560
|
||||
@@ -123,6 +172,12 @@
|
||||
|
||||
#define DEFAULT_PLAYLIST_ENTRY_RENAME true
|
||||
|
||||
#define DEFAULT_ACCESSIBILITY_ENABLE false
|
||||
|
||||
#define DEFAULT_ACCESSIBILITY_NARRATOR_SPEECH_SPEED 5
|
||||
|
||||
#define DEFAULT_DRIVER_SWITCH_ENABLE true
|
||||
|
||||
#define DEFAULT_USER_LANGUAGE 0
|
||||
|
||||
#if (defined(_WIN32) && !defined(_XBOX)) || (defined(__linux) && !defined(ANDROID) && !defined(HAVE_LAKKA)) || (defined(__MACH__) && !defined(IOS)) || defined(EMSCRIPTEN)
|
||||
@@ -152,7 +207,13 @@
|
||||
/* Fullscreen */
|
||||
|
||||
/* To start in Fullscreen, or not. */
|
||||
|
||||
#ifdef HAVE_STEAM
|
||||
/* Start in fullscreen mode for Steam build */
|
||||
#define DEFAULT_FULLSCREEN true
|
||||
#else
|
||||
#define DEFAULT_FULLSCREEN false
|
||||
#endif
|
||||
|
||||
/* To use windowed mode or not when going fullscreen. */
|
||||
#define DEFAULT_WINDOWED_FULLSCREEN true
|
||||
@@ -293,12 +354,7 @@
|
||||
|
||||
#if defined(__CELLOS_LV2) || defined(_XBOX360)
|
||||
#define DEFAULT_ASPECT_RATIO_IDX ASPECT_RATIO_16_9
|
||||
#elif defined(PSP)
|
||||
#define DEFAULT_ASPECT_RATIO_IDX ASPECT_RATIO_CORE
|
||||
#elif defined(_3DS)
|
||||
/* Previously defaulted to ASPECT_RATIO_4_3.
|
||||
* Non-4:3 content looks dreadful when stretched
|
||||
* to 4:3 on the 3DS screen... */
|
||||
#elif defined(PSP) || defined(_3DS) || defined(HAVE_LIBNX) || defined(VITA)
|
||||
#define DEFAULT_ASPECT_RATIO_IDX ASPECT_RATIO_CORE
|
||||
#elif defined(RARCH_CONSOLE)
|
||||
#define DEFAULT_ASPECT_RATIO_IDX ASPECT_RATIO_4_3
|
||||
@@ -322,6 +378,12 @@
|
||||
#define DEFAULT_INPUT_OVERLAY_OPACITY 0.7f
|
||||
#endif
|
||||
|
||||
#if defined(RARCH_MOBILE)
|
||||
#define DEFAULT_OVERLAY_AUTO_ROTATE true
|
||||
#else
|
||||
#define DEFAULT_OVERLAY_AUTO_ROTATE false
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
#include "menu/menu_driver.h"
|
||||
#include "menu/menu_animation.h"
|
||||
@@ -335,6 +397,7 @@
|
||||
#ifdef HAVE_OZONE
|
||||
#define DEFAULT_OZONE_COLLAPSE_SIDEBAR false
|
||||
#define DEFAULT_OZONE_TRUNCATE_PLAYLIST_NAME true
|
||||
#define DEFAULT_OZONE_SCROLL_CONTENT_METADATA false
|
||||
#endif
|
||||
|
||||
#define DEFAULT_SETTINGS_SHOW_DRIVERS true
|
||||
@@ -407,7 +470,8 @@ static bool quick_menu_show_download_thumbnails = true;
|
||||
|
||||
static bool kiosk_mode_enable = false;
|
||||
|
||||
static bool menu_horizontal_animation = true;
|
||||
#define DEFAULT_MENU_HORIZONTAL_ANIMATION true
|
||||
|
||||
static bool menu_show_online_updater = true;
|
||||
static bool menu_show_load_core = true;
|
||||
static bool menu_show_load_content = true;
|
||||
@@ -454,13 +518,10 @@ static bool content_show_video = true;
|
||||
static bool content_show_netplay = true;
|
||||
#endif
|
||||
static bool content_show_history = true;
|
||||
#ifdef HAVE_LIBRETRODB
|
||||
static bool content_show_add = true;
|
||||
#endif
|
||||
static bool content_show_playlists = true;
|
||||
|
||||
#ifdef HAVE_XMB
|
||||
static unsigned xmb_scale_factor = 100;
|
||||
static unsigned xmb_alpha_factor = 75;
|
||||
static unsigned menu_font_color_red = 255;
|
||||
static unsigned menu_font_color_green = 255;
|
||||
@@ -514,7 +575,8 @@ static bool rgui_extended_ascii = false;
|
||||
#define DEFAULT_BLOCK_CONFIG_READ false
|
||||
#endif
|
||||
|
||||
#define DEFAULT_AUTOMATICALLY_ADD_CONTENT_TO_PLAYLIST true
|
||||
/* TODO/FIXME - this setting is thread-unsafe right now and can corrupt the stack - default to off */
|
||||
#define DEFAULT_AUTOMATICALLY_ADD_CONTENT_TO_PLAYLIST false
|
||||
|
||||
static bool default_game_specific_options = true;
|
||||
static bool default_auto_overrides_enable = true;
|
||||
@@ -839,7 +901,11 @@ static const bool stdin_cmd_enable = false;
|
||||
|
||||
static const uint16_t network_remote_base_port = 55400;
|
||||
|
||||
#if defined(ANDROID) || defined(IOS)
|
||||
static const bool network_on_demand_thumbnails = true;
|
||||
#else
|
||||
static const bool network_on_demand_thumbnails = false;
|
||||
#endif
|
||||
|
||||
/* Number of entries that will be kept in content history playlist file. */
|
||||
static const unsigned default_content_history_size = 100;
|
||||
@@ -861,6 +927,9 @@ static const unsigned playlist_show_inline_core_name = PLAYLIST_INLINE_CORE_DISP
|
||||
/* Specifies which runtime record to use on playlist sublabels */
|
||||
static const unsigned playlist_sublabel_runtime_type = PLAYLIST_RUNTIME_PER_CORE;
|
||||
|
||||
/* Specifies time/date display format for runtime 'last played' data */
|
||||
#define DEFAULT_PLAYLIST_SUBLABEL_LAST_PLAYED_STYLE PLAYLIST_LAST_PLAYED_STYLE_YMD_HMS
|
||||
|
||||
static const unsigned playlist_entry_remove_enable = PLAYLIST_ENTRY_REMOVE_ENABLE_ALL;
|
||||
#endif
|
||||
|
||||
@@ -879,15 +948,9 @@ static const bool playlist_fuzzy_archive_match = false;
|
||||
/* Show Menu start-up screen on boot. */
|
||||
static const bool default_menu_show_start_screen = true;
|
||||
|
||||
#define DEFAULT_MENU_DPI_OVERRIDE_ENABLE false
|
||||
|
||||
#ifdef RARCH_MOBILE
|
||||
#define DEFAULT_MENU_DPI_OVERRIDE_VALUE 72
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
#define DEFAULT_MENU_DPI_OVERRIDE_VALUE 360
|
||||
#else
|
||||
#define DEFAULT_MENU_DPI_OVERRIDE_VALUE 200
|
||||
#endif
|
||||
/* Default scale factor for non-frambuffer-based menu
|
||||
* drivers and menu widgets */
|
||||
#define DEFAULT_MENU_SCALE_FACTOR 1.0f
|
||||
|
||||
/* Log level for the frontend */
|
||||
#define DEFAULT_FRONTEND_LOG_LEVEL 1
|
||||
@@ -916,6 +979,8 @@ static const float analog_sensitivity = 1.0f;
|
||||
/* Describes speed of which turbo-enabled buttons toggle. */
|
||||
static const unsigned turbo_period = 6;
|
||||
static const unsigned turbo_duty_cycle = 3;
|
||||
static const unsigned turbo_mode = 0;
|
||||
static const unsigned turbo_default_btn = RETRO_DEVICE_ID_JOYPAD_B;
|
||||
|
||||
/* Enable input auto-detection. Will attempt to autoconfigure
|
||||
* gamepads, plug-and-play style. */
|
||||
@@ -941,7 +1006,9 @@ static const unsigned menu_left_thumbnails_default = 0;
|
||||
|
||||
static const unsigned menu_thumbnail_upscale_threshold = 0;
|
||||
|
||||
static const unsigned menu_timedate_style = 5;
|
||||
#ifdef HAVE_MENU
|
||||
static const unsigned menu_timedate_style = MENU_TIMEDATE_STYLE_DM_HM;
|
||||
#endif
|
||||
|
||||
static const bool xmb_vertical_thumbnails = false;
|
||||
|
||||
@@ -1113,6 +1180,8 @@ static char default_discord_app_id[] = "475456035851599874";
|
||||
|
||||
#define DEFAULT_AI_SERVICE_ENABLE true
|
||||
|
||||
#define DEFAULT_AI_SERVICE_PAUSE false
|
||||
|
||||
#define DEFAULT_AI_SERVICE_MODE 1
|
||||
|
||||
#define DEFAULT_AI_SERVICE_URL "http://localhost:4404/"
|
||||
|
||||
+70
-88
@@ -166,6 +166,7 @@ enum video_driver_enum
|
||||
VIDEO_CACA,
|
||||
VIDEO_GDI,
|
||||
VIDEO_VGA,
|
||||
VIDEO_FPGA,
|
||||
VIDEO_NULL
|
||||
};
|
||||
|
||||
@@ -318,6 +319,8 @@ enum midi_driver_enum
|
||||
|
||||
#if defined(HAVE_METAL)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_METAL;
|
||||
#elif defined(HAVE_VITA2D)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_VITA2D;
|
||||
#elif defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) || defined(__CELLOS_LV2__)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_GL;
|
||||
#elif defined(HAVE_OPENGL_CORE)
|
||||
@@ -344,8 +347,6 @@ static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_D3D9;
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_D3D8;
|
||||
#elif defined(HAVE_VG)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_VG;
|
||||
#elif defined(HAVE_VITA2D)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_VITA2D;
|
||||
#elif defined(PSP)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_PSP1;
|
||||
#elif defined(PS2)
|
||||
@@ -364,6 +365,8 @@ static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_SDL2;
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_GDI;
|
||||
#elif defined(DJGPP)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_VGA;
|
||||
#elif defined(HAVE_FPGA)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_FPGA;
|
||||
#elif defined(HAVE_DYLIB) && !defined(ANDROID)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_EXT;
|
||||
#else
|
||||
@@ -400,7 +403,7 @@ static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_AUDIOIO;
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_OSS;
|
||||
#elif defined(HAVE_JACK)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_JACK;
|
||||
#elif defined(HAVE_COREAUDIO)
|
||||
#elif defined(HAVE_COREAUDIO) && !defined(HAVE_COCOA_METAL)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_COREAUDIO;
|
||||
#elif defined(HAVE_COREAUDIO3)
|
||||
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_COREAUDIO3;
|
||||
@@ -444,7 +447,7 @@ static enum record_driver_enum RECORD_DEFAULT_DRIVER = RECORD_NULL;
|
||||
|
||||
#ifdef HAVE_WINMM
|
||||
static enum midi_driver_enum MIDI_DEFAULT_DRIVER = MIDI_WINMM;
|
||||
#elif defined(HAVE_ALSA) && !defined(HAVE_HAKCHI)
|
||||
#elif defined(HAVE_ALSA) && !defined(HAVE_HAKCHI) && !defined(HAVE_SEGAM)
|
||||
static enum midi_driver_enum MIDI_DEFAULT_DRIVER = MIDI_ALSA;
|
||||
#else
|
||||
static enum midi_driver_enum MIDI_DEFAULT_DRIVER = MIDI_NULL;
|
||||
@@ -696,7 +699,7 @@ const char *config_get_default_audio(void)
|
||||
return "dsp";
|
||||
case AUDIO_SWITCH:
|
||||
#if defined(HAVE_LIBNX)
|
||||
return "switch_thread";
|
||||
return "switch_audren_thread";
|
||||
#else
|
||||
return "switch";
|
||||
#endif
|
||||
@@ -827,6 +830,8 @@ const char *config_get_default_video(void)
|
||||
return "gdi";
|
||||
case VIDEO_VGA:
|
||||
return "vga";
|
||||
case VIDEO_FPGA:
|
||||
return "fpga";
|
||||
case VIDEO_NULL:
|
||||
break;
|
||||
}
|
||||
@@ -1325,6 +1330,8 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
|
||||
struct config_bool_setting *tmp = (struct config_bool_setting*)calloc(1, (*size + 1) * sizeof(struct config_bool_setting));
|
||||
unsigned count = 0;
|
||||
|
||||
SETTING_BOOL("accessibility_enable", &settings->bools.accessibility_enable, true, DEFAULT_ACCESSIBILITY_ENABLE, false);
|
||||
SETTING_BOOL("driver_switch_enable", &settings->bools.driver_switch_enable, true, DEFAULT_DRIVER_SWITCH_ENABLE, false);
|
||||
SETTING_BOOL("frame_time_counter_reset_after_fastforwarding", &settings->bools.frame_time_counter_reset_after_fastforwarding, true, false, false);
|
||||
SETTING_BOOL("frame_time_counter_reset_after_load_state", &settings->bools.frame_time_counter_reset_after_load_state, true, false, false);
|
||||
SETTING_BOOL("frame_time_counter_reset_after_save_state", &settings->bools.frame_time_counter_reset_after_save_state, true, false, false);
|
||||
@@ -1445,8 +1452,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
|
||||
SETTING_BOOL("menu_unified_controls", &settings->bools.menu_unified_controls, true, false, false);
|
||||
SETTING_BOOL("menu_throttle_framerate", &settings->bools.menu_throttle_framerate, true, true, false);
|
||||
SETTING_BOOL("menu_linear_filter", &settings->bools.menu_linear_filter, true, true, false);
|
||||
SETTING_BOOL("menu_horizontal_animation", &settings->bools.menu_horizontal_animation, true, true, false);
|
||||
SETTING_BOOL("dpi_override_enable", &settings->bools.menu_dpi_override_enable, true, DEFAULT_MENU_DPI_OVERRIDE_ENABLE, false);
|
||||
SETTING_BOOL("menu_horizontal_animation", &settings->bools.menu_horizontal_animation, true, DEFAULT_MENU_HORIZONTAL_ANIMATION, false);
|
||||
SETTING_BOOL("menu_pause_libretro", &settings->bools.menu_pause_libretro, true, true, false);
|
||||
SETTING_BOOL("menu_savestate_resume", &settings->bools.menu_savestate_resume, true, menu_savestate_resume, false);
|
||||
SETTING_BOOL("menu_mouse_enable", &settings->bools.menu_mouse_enable, true, DEFAULT_MOUSE_ENABLE, false);
|
||||
@@ -1517,9 +1523,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
|
||||
SETTING_BOOL("content_show_netplay", &settings->bools.menu_content_show_netplay, true, content_show_netplay, false);
|
||||
#endif
|
||||
SETTING_BOOL("content_show_history", &settings->bools.menu_content_show_history, true, content_show_history, false);
|
||||
#ifdef HAVE_LIBRETRODB
|
||||
SETTING_BOOL("content_show_add", &settings->bools.menu_content_show_add, true, content_show_add, false);
|
||||
#endif
|
||||
SETTING_BOOL("content_show_playlists", &settings->bools.menu_content_show_playlists, true, content_show_playlists, false);
|
||||
SETTING_BOOL("menu_show_load_core", &settings->bools.menu_show_load_core, true, menu_show_load_core, false);
|
||||
SETTING_BOOL("menu_show_load_content", &settings->bools.menu_show_load_content, true, menu_show_load_content, false);
|
||||
@@ -1551,6 +1555,9 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
|
||||
SETTING_BOOL("menu_show_advanced_settings", &settings->bools.menu_show_advanced_settings, true, DEFAULT_SHOW_ADVANCED_SETTINGS, false);
|
||||
#ifdef HAVE_MATERIALUI
|
||||
SETTING_BOOL("materialui_icons_enable", &settings->bools.menu_materialui_icons_enable, true, DEFAULT_MATERIALUI_ICONS_ENABLE, false);
|
||||
SETTING_BOOL("materialui_auto_rotate_nav_bar", &settings->bools.menu_materialui_auto_rotate_nav_bar, true, DEFAULT_MATERIALUI_AUTO_ROTATE_NAV_BAR, false);
|
||||
SETTING_BOOL("materialui_dual_thumbnail_list_view_enable", &settings->bools.menu_materialui_dual_thumbnail_list_view_enable, true, DEFAULT_MATERIALUI_DUAL_THUMBNAIL_LIST_VIEW_ENABLE, false);
|
||||
SETTING_BOOL("materialui_thumbnail_background_enable", &settings->bools.menu_materialui_thumbnail_background_enable, true, DEFAULT_MATERIALUI_THUMBNAIL_BACKGROUND_ENABLE, false);
|
||||
#endif
|
||||
#ifdef HAVE_RGUI
|
||||
SETTING_BOOL("rgui_background_filler_thickness_enable", &settings->bools.menu_rgui_background_filler_thickness_enable, true, true, false);
|
||||
@@ -1584,6 +1591,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
|
||||
SETTING_BOOL("input_overlay_show_physical_inputs", &settings->bools.input_overlay_show_physical_inputs, true, false, false);
|
||||
SETTING_BOOL("input_overlay_hide_in_menu", &settings->bools.input_overlay_hide_in_menu, true, DEFAULT_OVERLAY_HIDE_IN_MENU, false);
|
||||
SETTING_BOOL("input_overlay_show_mouse_cursor", &settings->bools.input_overlay_show_mouse_cursor, true, DEFAULT_OVERLAY_SHOW_MOUSE_CURSOR, false);
|
||||
SETTING_BOOL("input_overlay_auto_rotate", &settings->bools.input_overlay_auto_rotate, true, DEFAULT_OVERLAY_AUTO_ROTATE, false);
|
||||
#endif
|
||||
#ifdef HAVE_VIDEO_LAYOUT
|
||||
SETTING_BOOL("video_layout_enable", &settings->bools.video_layout_enable, true, true, false);
|
||||
@@ -1651,11 +1659,13 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
|
||||
#ifdef HAVE_OZONE
|
||||
SETTING_BOOL("ozone_collapse_sidebar", &settings->bools.ozone_collapse_sidebar, true, DEFAULT_OZONE_COLLAPSE_SIDEBAR, false);
|
||||
SETTING_BOOL("ozone_truncate_playlist_name", &settings->bools.ozone_truncate_playlist_name, true, DEFAULT_OZONE_TRUNCATE_PLAYLIST_NAME, false);
|
||||
SETTING_BOOL("ozone_scroll_content_metadata",&settings->bools.ozone_scroll_content_metadata, true, DEFAULT_OZONE_SCROLL_CONTENT_METADATA, false);
|
||||
#endif
|
||||
SETTING_BOOL("log_to_file", &settings->bools.log_to_file, true, DEFAULT_LOG_TO_FILE, false);
|
||||
SETTING_OVERRIDE(RARCH_OVERRIDE_SETTING_LOG_TO_FILE);
|
||||
SETTING_BOOL("log_to_file_timestamp", &settings->bools.log_to_file_timestamp, true, DEFAULT_LOG_TO_FILE_TIMESTAMP, false);
|
||||
SETTING_BOOL("ai_service_enable", &settings->bools.ai_service_enable, DEFAULT_AI_SERVICE_ENABLE, false, false);
|
||||
SETTING_BOOL("ai_service_pause", &settings->bools.ai_service_pause, true, DEFAULT_AI_SERVICE_PAUSE, false);
|
||||
|
||||
*size = count;
|
||||
|
||||
@@ -1685,6 +1695,7 @@ static struct config_float_setting *populate_settings_float(settings_t *settings
|
||||
SETTING_FLOAT("input_overlay_scale", &settings->floats.input_overlay_scale, true, 1.0f, false);
|
||||
#endif
|
||||
#ifdef HAVE_MENU
|
||||
SETTING_FLOAT("menu_scale_factor", &settings->floats.menu_scale_factor, true, DEFAULT_MENU_SCALE_FACTOR, false);
|
||||
SETTING_FLOAT("menu_wallpaper_opacity", &settings->floats.menu_wallpaper_opacity, true, menu_wallpaper_opacity, false);
|
||||
SETTING_FLOAT("menu_framebuffer_opacity", &settings->floats.menu_framebuffer_opacity, true, menu_framebuffer_opacity, false);
|
||||
SETTING_FLOAT("menu_footer_opacity", &settings->floats.menu_footer_opacity, true, menu_footer_opacity, false);
|
||||
@@ -1715,6 +1726,7 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
|
||||
if (!tmp)
|
||||
return NULL;
|
||||
|
||||
SETTING_UINT("accessibility_narrator_speech_speed", &settings->uints.accessibility_narrator_speech_speed, true, DEFAULT_ACCESSIBILITY_NARRATOR_SPEECH_SPEED, false);
|
||||
#ifdef HAVE_NETWORKING
|
||||
SETTING_UINT("streaming_mode", &settings->uints.streaming_mode, true, STREAMING_MODE_TWITCH, false);
|
||||
#endif
|
||||
@@ -1723,9 +1735,14 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
|
||||
SETTING_UINT("input_bind_hold", &settings->uints.input_bind_hold, true, input_bind_hold, false);
|
||||
SETTING_UINT("input_turbo_period", &settings->uints.input_turbo_period, true, turbo_period, false);
|
||||
SETTING_UINT("input_duty_cycle", &settings->uints.input_turbo_duty_cycle, true, turbo_duty_cycle, false);
|
||||
SETTING_UINT("input_turbo_mode", &settings->uints.input_turbo_mode, true, turbo_mode, false);
|
||||
SETTING_UINT("input_turbo_default_button", &settings->uints.input_turbo_default_button, true, turbo_default_btn, false);
|
||||
SETTING_UINT("input_max_users", input_driver_get_uint(INPUT_ACTION_MAX_USERS), true, input_max_users, false);
|
||||
SETTING_UINT("fps_update_interval", &settings->uints.fps_update_interval, true, DEFAULT_FPS_UPDATE_INTERVAL, false);
|
||||
SETTING_UINT("input_menu_toggle_gamepad_combo", &settings->uints.input_menu_toggle_gamepad_combo, true, menu_toggle_gamepad_combo, false);
|
||||
#ifdef GEKKO
|
||||
SETTING_UINT("input_mouse_scale", &settings->uints.input_mouse_scale, true, DEFAULT_MOUSE_SCALE, false);
|
||||
#endif
|
||||
SETTING_UINT("audio_latency", &settings->uints.audio_latency, false, 0 /* TODO */, false);
|
||||
SETTING_UINT("audio_resampler_quality", &settings->uints.audio_resampler_quality, true, audio_resampler_quality_level, false);
|
||||
SETTING_UINT("audio_block_frames", &settings->uints.audio_block_frames, true, 0, false);
|
||||
@@ -1759,7 +1776,6 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
|
||||
SETTING_UINT("video_overscan_correction_bottom", &settings->uints.video_overscan_correction_bottom, true, DEFAULT_VIDEO_OVERSCAN_CORRECTION_BOTTOM, false);
|
||||
#endif
|
||||
#ifdef HAVE_MENU
|
||||
SETTING_UINT("dpi_override_value", &settings->uints.menu_dpi_override_value, true, DEFAULT_MENU_DPI_OVERRIDE_VALUE, false);
|
||||
SETTING_UINT("menu_thumbnails", &settings->uints.menu_thumbnails, true, menu_thumbnails_default, false);
|
||||
SETTING_UINT("menu_left_thumbnails", &settings->uints.menu_left_thumbnails, true, menu_left_thumbnails_default, false);
|
||||
SETTING_UINT("menu_thumbnail_upscale_threshold", &settings->uints.menu_thumbnail_upscale_threshold, true, menu_thumbnail_upscale_threshold, false);
|
||||
@@ -1789,7 +1805,6 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
|
||||
SETTING_UINT("menu_xmb_animation_horizontal_highlight", &settings->uints.menu_xmb_animation_horizontal_highlight, true, 0 /* TODO/FIXME - implement */, false);
|
||||
SETTING_UINT("menu_xmb_animation_move_up_down", &settings->uints.menu_xmb_animation_move_up_down, true, 0 /* TODO/FIXME - implement */, false);
|
||||
SETTING_UINT("xmb_alpha_factor", &settings->uints.menu_xmb_alpha_factor, true, xmb_alpha_factor, false);
|
||||
SETTING_UINT("xmb_scale_factor", &settings->uints.menu_xmb_scale_factor, true, xmb_scale_factor, false);
|
||||
SETTING_UINT("xmb_layout", &settings->uints.menu_xmb_layout, true, xmb_menu_layout, false);
|
||||
SETTING_UINT("xmb_theme", &settings->uints.menu_xmb_theme, true, xmb_icon_theme, false);
|
||||
SETTING_UINT("xmb_menu_color_theme", &settings->uints.menu_xmb_color_theme, true, xmb_theme, false);
|
||||
@@ -1798,7 +1813,11 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
|
||||
SETTING_UINT("menu_font_color_blue", &settings->uints.menu_font_color_blue, true, menu_font_color_blue, false);
|
||||
SETTING_UINT("menu_xmb_thumbnail_scale_factor", &settings->uints.menu_xmb_thumbnail_scale_factor, true, xmb_thumbnail_scale_factor, false);
|
||||
#endif
|
||||
SETTING_UINT("materialui_menu_color_theme", &settings->uints.menu_materialui_color_theme, true, MATERIALUI_THEME_BLUE, false);
|
||||
SETTING_UINT("materialui_menu_color_theme", &settings->uints.menu_materialui_color_theme, true, DEFAULT_MATERIALUI_THEME, false);
|
||||
SETTING_UINT("materialui_menu_transition_animation", &settings->uints.menu_materialui_transition_animation, true, DEFAULT_MATERIALUI_TRANSITION_ANIM, false);
|
||||
SETTING_UINT("materialui_thumbnail_view_portrait", &settings->uints.menu_materialui_thumbnail_view_portrait, true, DEFAULT_MATERIALUI_THUMBNAIL_VIEW_PORTRAIT, false);
|
||||
SETTING_UINT("materialui_thumbnail_view_landscape", &settings->uints.menu_materialui_thumbnail_view_landscape, true, DEFAULT_MATERIALUI_THUMBNAIL_VIEW_LANDSCAPE, false);
|
||||
SETTING_UINT("materialui_landscape_layout_optimization", &settings->uints.menu_materialui_landscape_layout_optimization, true, DEFAULT_MATERIALUI_LANDSCAPE_LAYOUT_OPTIMIZATION, false);
|
||||
SETTING_UINT("menu_shader_pipeline", &settings->uints.menu_xmb_shader_pipeline, true, DEFAULT_MENU_SHADER_PIPELINE, false);
|
||||
#ifdef HAVE_OZONE
|
||||
SETTING_UINT("ozone_menu_color_theme", &settings->uints.menu_ozone_color_theme, true, 1, false);
|
||||
@@ -1827,7 +1846,11 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
|
||||
SETTING_UINT("netplay_share_analog", &settings->uints.netplay_share_analog, true, netplay_share_analog, false);
|
||||
#endif
|
||||
#ifdef HAVE_LANGEXTRA
|
||||
#ifdef VITA
|
||||
SETTING_UINT("user_language", msg_hash_get_uint(MSG_HASH_USER_LANGUAGE), true, frontend_driver_get_user_language(), false);
|
||||
#else
|
||||
SETTING_UINT("user_language", msg_hash_get_uint(MSG_HASH_USER_LANGUAGE), true, DEFAULT_USER_LANGUAGE, false);
|
||||
#endif
|
||||
#endif
|
||||
SETTING_UINT("bundle_assets_extract_version_current", &settings->uints.bundle_assets_extract_version_current, true, 0, false);
|
||||
SETTING_UINT("bundle_assets_extract_last_version", &settings->uints.bundle_assets_extract_last_version, true, 0, false);
|
||||
@@ -1867,6 +1890,7 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings,
|
||||
SETTING_UINT("playlist_entry_remove_enable", &settings->uints.playlist_entry_remove_enable, true, playlist_entry_remove_enable, false);
|
||||
SETTING_UINT("playlist_show_inline_core_name", &settings->uints.playlist_show_inline_core_name, true, playlist_show_inline_core_name, false);
|
||||
SETTING_UINT("playlist_sublabel_runtime_type", &settings->uints.playlist_sublabel_runtime_type, true, playlist_sublabel_runtime_type, false);
|
||||
SETTING_UINT("playlist_sublabel_last_played_style", &settings->uints.playlist_sublabel_last_played_style, true, DEFAULT_PLAYLIST_SUBLABEL_LAST_PLAYED_STYLE, false);
|
||||
#endif
|
||||
|
||||
*size = count;
|
||||
@@ -1930,12 +1954,13 @@ static struct config_int_setting *populate_settings_int(settings_t *settings, in
|
||||
*
|
||||
* Set 'default' configuration values.
|
||||
**/
|
||||
void config_set_defaults(void)
|
||||
void config_set_defaults(void *data)
|
||||
{
|
||||
unsigned i, j;
|
||||
#ifdef HAVE_MENU
|
||||
static bool first_initialized = true;
|
||||
#endif
|
||||
global_t *global = (global_t*)data;
|
||||
settings_t *settings = config_get_ptr();
|
||||
int bool_settings_size = sizeof(settings->bools) / sizeof(settings->bools.placeholder);
|
||||
int float_settings_size = sizeof(settings->floats) / sizeof(settings->floats.placeholder);
|
||||
@@ -2110,6 +2135,7 @@ void config_set_defaults(void)
|
||||
settings->bools.ssh_enable = filestream_exists(LAKKA_SSH_PATH);
|
||||
settings->bools.samba_enable = filestream_exists(LAKKA_SAMBA_PATH);
|
||||
settings->bools.bluetooth_enable = filestream_exists(LAKKA_BLUETOOTH_PATH);
|
||||
settings->bools.localap_enable = false;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
@@ -2193,14 +2219,10 @@ void config_set_defaults(void)
|
||||
rarch_ctl(RARCH_CTL_UNSET_BPS_PREF, NULL);
|
||||
rarch_ctl(RARCH_CTL_UNSET_IPS_PREF, NULL);
|
||||
|
||||
if (global)
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
if (global)
|
||||
{
|
||||
*global->record.output_dir = '\0';
|
||||
*global->record.config_dir = '\0';
|
||||
}
|
||||
*global->record.output_dir = '\0';
|
||||
*global->record.config_dir = '\0';
|
||||
}
|
||||
|
||||
*settings->paths.path_core_options = '\0';
|
||||
@@ -2666,7 +2688,8 @@ static bool check_menu_driver_compatibility(void)
|
||||
* Loads a config file and reads all the values into memory.
|
||||
*
|
||||
*/
|
||||
static bool config_load_file(const char *path, settings_t *settings)
|
||||
static bool config_load_file(global_t *global,
|
||||
const char *path, settings_t *settings)
|
||||
{
|
||||
unsigned i;
|
||||
size_t path_size = PATH_MAX_LENGTH * sizeof(char);
|
||||
@@ -3092,8 +3115,6 @@ static bool config_load_file(const char *path, settings_t *settings)
|
||||
|
||||
else if (path_is_directory(tmp_str))
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
dir_set(RARCH_DIR_SAVEFILE, tmp_str);
|
||||
|
||||
if (global)
|
||||
@@ -3102,7 +3123,7 @@ static bool config_load_file(const char *path, settings_t *settings)
|
||||
sizeof(global->name.savefile));
|
||||
fill_pathname_dir(global->name.savefile,
|
||||
path_get(RARCH_PATH_BASENAME),
|
||||
file_path_str(FILE_PATH_SRM_EXTENSION),
|
||||
".srm",
|
||||
sizeof(global->name.savefile));
|
||||
}
|
||||
}
|
||||
@@ -3117,8 +3138,6 @@ static bool config_load_file(const char *path, settings_t *settings)
|
||||
dir_set(RARCH_DIR_SAVESTATE, g_defaults.dirs[DEFAULT_DIR_SAVESTATE]);
|
||||
else if (path_is_directory(tmp_str))
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
dir_set(RARCH_DIR_SAVESTATE, tmp_str);
|
||||
|
||||
if (global)
|
||||
@@ -3127,7 +3146,7 @@ static bool config_load_file(const char *path, settings_t *settings)
|
||||
sizeof(global->name.savestate));
|
||||
fill_pathname_dir(global->name.savestate,
|
||||
path_get(RARCH_PATH_BASENAME),
|
||||
file_path_str(FILE_PATH_STATE_EXTENSION),
|
||||
".state",
|
||||
sizeof(global->name.savestate));
|
||||
}
|
||||
}
|
||||
@@ -3252,19 +3271,19 @@ bool config_load_override(void)
|
||||
fill_pathname_join_special_ext(game_path,
|
||||
config_directory, core_name,
|
||||
game_name,
|
||||
file_path_str(FILE_PATH_CONFIG_EXTENSION),
|
||||
".cfg",
|
||||
path_size);
|
||||
|
||||
fill_pathname_join_special_ext(content_path,
|
||||
config_directory, core_name,
|
||||
content_dir_name,
|
||||
file_path_str(FILE_PATH_CONFIG_EXTENSION),
|
||||
".cfg",
|
||||
path_size);
|
||||
|
||||
fill_pathname_join_special_ext(core_path,
|
||||
config_directory, core_name,
|
||||
core_name,
|
||||
file_path_str(FILE_PATH_CONFIG_EXTENSION),
|
||||
".cfg",
|
||||
path_size);
|
||||
|
||||
free(config_directory);
|
||||
@@ -3361,7 +3380,8 @@ bool config_load_override(void)
|
||||
retroarch_override_setting_unset(RARCH_OVERRIDE_SETTING_STATE_PATH, NULL);
|
||||
retroarch_override_setting_unset(RARCH_OVERRIDE_SETTING_SAVE_PATH, NULL);
|
||||
|
||||
if (!config_load_file(path_get(RARCH_PATH_CONFIG), config_get_ptr()))
|
||||
if (!config_load_file(global_get_ptr(),
|
||||
path_get(RARCH_PATH_CONFIG), config_get_ptr()))
|
||||
goto error;
|
||||
|
||||
/* Restore the libretro_path we're using
|
||||
@@ -3407,7 +3427,8 @@ bool config_unload_override(void)
|
||||
retroarch_override_setting_unset(RARCH_OVERRIDE_SETTING_STATE_PATH, NULL);
|
||||
retroarch_override_setting_unset(RARCH_OVERRIDE_SETTING_SAVE_PATH, NULL);
|
||||
|
||||
if (!config_load_file(path_get(RARCH_PATH_CONFIG), config_get_ptr()))
|
||||
if (!config_load_file(global_get_ptr(),
|
||||
path_get(RARCH_PATH_CONFIG), config_get_ptr()))
|
||||
return false;
|
||||
|
||||
RARCH_LOG("[Overrides] configuration overrides unloaded, original configuration restored.\n");
|
||||
@@ -3479,19 +3500,19 @@ bool config_load_remap(const char *directory_input_remapping)
|
||||
fill_pathname_join_special_ext(core_path,
|
||||
remap_directory, core_name,
|
||||
core_name,
|
||||
file_path_str(FILE_PATH_REMAP_EXTENSION),
|
||||
".rmp",
|
||||
path_size);
|
||||
|
||||
fill_pathname_join_special_ext(content_path,
|
||||
remap_directory, core_name,
|
||||
content_dir_name,
|
||||
file_path_str(FILE_PATH_REMAP_EXTENSION),
|
||||
".rmp",
|
||||
path_size);
|
||||
|
||||
fill_pathname_join_special_ext(game_path,
|
||||
remap_directory, core_name,
|
||||
game_name,
|
||||
file_path_str(FILE_PATH_REMAP_EXTENSION),
|
||||
".rmp",
|
||||
path_size);
|
||||
|
||||
input_remapping_set_defaults(false);
|
||||
@@ -3554,8 +3575,9 @@ success:
|
||||
* Loads a config file and reads all the values into memory.
|
||||
*
|
||||
*/
|
||||
void config_parse_file(void)
|
||||
void config_parse_file(void *data)
|
||||
{
|
||||
global_t *global = (global_t*)data;
|
||||
if (path_is_empty(RARCH_PATH_CONFIG))
|
||||
{
|
||||
RARCH_LOG("[config] Loading default config.\n");
|
||||
@@ -3565,7 +3587,7 @@ void config_parse_file(void)
|
||||
const char *config_path = path_get(RARCH_PATH_CONFIG);
|
||||
RARCH_LOG("[config] loading config from: %s.\n", config_path);
|
||||
|
||||
if (!config_load_file(config_path, config_get_ptr()))
|
||||
if (!config_load_file(global, config_path, config_get_ptr()))
|
||||
{
|
||||
RARCH_ERR("[config] couldn't find config at path: \"%s\"\n",
|
||||
config_path);
|
||||
@@ -3579,10 +3601,11 @@ void config_parse_file(void)
|
||||
* Loads a config file and reads all the values into memory.
|
||||
*
|
||||
*/
|
||||
void config_load(void)
|
||||
void config_load(void *data)
|
||||
{
|
||||
config_set_defaults();
|
||||
config_parse_file();
|
||||
global_t *global = (global_t*)data;
|
||||
config_set_defaults(global);
|
||||
config_parse_file(global);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3635,7 +3658,7 @@ bool config_save_autoconf_profile(const char *path, unsigned user)
|
||||
fill_pathname_join(buf_new, buf,
|
||||
path, path_size);
|
||||
fill_pathname_noext(autoconf_file, buf_new,
|
||||
file_path_str(FILE_PATH_CONFIG_EXTENSION),
|
||||
".cfg",
|
||||
path_size);
|
||||
|
||||
free(buf_new);
|
||||
@@ -3645,7 +3668,7 @@ bool config_save_autoconf_profile(const char *path, unsigned user)
|
||||
fill_pathname_join(buf, autoconf_dir,
|
||||
path, path_size);
|
||||
fill_pathname_noext(autoconf_file, buf,
|
||||
file_path_str(FILE_PATH_CONFIG_EXTENSION),
|
||||
".cfg",
|
||||
path_size);
|
||||
}
|
||||
|
||||
@@ -3994,26 +4017,27 @@ bool config_save_overrides(int override_type)
|
||||
fill_pathname_join_special_ext(game_path,
|
||||
config_directory, core_name,
|
||||
game_name,
|
||||
file_path_str(FILE_PATH_CONFIG_EXTENSION),
|
||||
".cfg",
|
||||
path_size);
|
||||
|
||||
fill_pathname_join_special_ext(content_path,
|
||||
config_directory, core_name,
|
||||
content_dir_name,
|
||||
file_path_str(FILE_PATH_CONFIG_EXTENSION),
|
||||
".cfg",
|
||||
path_size);
|
||||
|
||||
fill_pathname_join_special_ext(core_path,
|
||||
config_directory, core_name,
|
||||
core_name,
|
||||
file_path_str(FILE_PATH_CONFIG_EXTENSION),
|
||||
".cfg",
|
||||
path_size);
|
||||
|
||||
if (!conf)
|
||||
conf = config_file_new_alloc();
|
||||
|
||||
/* Load the original config file in memory */
|
||||
config_load_file(path_get(RARCH_PATH_CONFIG), settings);
|
||||
config_load_file(global_get_ptr(),
|
||||
path_get(RARCH_PATH_CONFIG), settings);
|
||||
|
||||
bool_settings = populate_settings_bool(settings, &bool_settings_size);
|
||||
tmp_i = sizeof(settings->bools) / sizeof(settings->bools.placeholder);
|
||||
@@ -4050,88 +4074,46 @@ bool config_save_overrides(int override_type)
|
||||
for (i = 0; i < (unsigned)bool_settings_size; i++)
|
||||
{
|
||||
if ((*bool_settings[i].ptr) != (*bool_overrides[i].ptr))
|
||||
{
|
||||
RARCH_LOG(" original: %s=%d\n",
|
||||
bool_settings[i].ident, (*bool_settings[i].ptr));
|
||||
RARCH_LOG(" override: %s=%d\n",
|
||||
bool_overrides[i].ident, (*bool_overrides[i].ptr));
|
||||
config_set_bool(conf, bool_overrides[i].ident,
|
||||
(*bool_overrides[i].ptr));
|
||||
}
|
||||
}
|
||||
for (i = 0; i < (unsigned)int_settings_size; i++)
|
||||
{
|
||||
if ((*int_settings[i].ptr) != (*int_overrides[i].ptr))
|
||||
{
|
||||
RARCH_LOG(" original: %s=%d\n",
|
||||
int_settings[i].ident, (*int_settings[i].ptr));
|
||||
RARCH_LOG(" override: %s=%d\n",
|
||||
int_overrides[i].ident, (*int_overrides[i].ptr));
|
||||
config_set_int(conf, int_overrides[i].ident,
|
||||
(*int_overrides[i].ptr));
|
||||
}
|
||||
}
|
||||
for (i = 0; i < (unsigned)uint_settings_size; i++)
|
||||
{
|
||||
if ((*uint_settings[i].ptr) != (*uint_overrides[i].ptr))
|
||||
{
|
||||
RARCH_LOG(" original: %s=%d\n",
|
||||
uint_settings[i].ident, (*uint_settings[i].ptr));
|
||||
RARCH_LOG(" override: %s=%d\n",
|
||||
uint_overrides[i].ident, (*uint_overrides[i].ptr));
|
||||
config_set_int(conf, uint_overrides[i].ident,
|
||||
(*uint_overrides[i].ptr));
|
||||
}
|
||||
}
|
||||
for (i = 0; i < (unsigned)size_settings_size; i++)
|
||||
{
|
||||
if ((*size_settings[i].ptr) != (*size_overrides[i].ptr))
|
||||
{
|
||||
RARCH_LOG(" original: %s=%d\n",
|
||||
size_settings[i].ident, (*size_settings[i].ptr));
|
||||
RARCH_LOG(" override: %s=%d\n",
|
||||
size_overrides[i].ident, (*size_overrides[i].ptr));
|
||||
config_set_int(conf, size_overrides[i].ident,
|
||||
(int)(*size_overrides[i].ptr));
|
||||
}
|
||||
}
|
||||
for (i = 0; i < (unsigned)float_settings_size; i++)
|
||||
{
|
||||
if ((*float_settings[i].ptr) != (*float_overrides[i].ptr))
|
||||
{
|
||||
RARCH_LOG(" original: %s=%f\n",
|
||||
float_settings[i].ident, *float_settings[i].ptr);
|
||||
RARCH_LOG(" override: %s=%f\n",
|
||||
float_overrides[i].ident, *float_overrides[i].ptr);
|
||||
config_set_float(conf, float_overrides[i].ident,
|
||||
*float_overrides[i].ptr);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < (unsigned)array_settings_size; i++)
|
||||
{
|
||||
if (!string_is_equal(array_settings[i].ptr, array_overrides[i].ptr))
|
||||
{
|
||||
RARCH_LOG(" original: %s=%s\n",
|
||||
array_settings[i].ident, array_settings[i].ptr);
|
||||
RARCH_LOG(" override: %s=%s\n",
|
||||
array_overrides[i].ident, array_overrides[i].ptr);
|
||||
config_set_string(conf, array_overrides[i].ident,
|
||||
array_overrides[i].ptr);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < (unsigned)path_settings_size; i++)
|
||||
{
|
||||
if (!string_is_equal(path_settings[i].ptr, path_overrides[i].ptr))
|
||||
{
|
||||
RARCH_LOG(" original: %s=%s\n",
|
||||
path_settings[i].ident, path_settings[i].ptr);
|
||||
RARCH_LOG(" override: %s=%s\n",
|
||||
path_overrides[i].ident, path_overrides[i].ptr);
|
||||
config_set_path(conf, path_overrides[i].ident,
|
||||
path_overrides[i].ptr);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_USERS; i++)
|
||||
|
||||
+29
-6
@@ -110,6 +110,9 @@ typedef struct settings
|
||||
bool video_layout_enable;
|
||||
#endif
|
||||
|
||||
/* Accessibility */
|
||||
bool accessibility_enable;
|
||||
|
||||
/* Audio */
|
||||
bool audio_enable;
|
||||
bool audio_enable_menu;
|
||||
@@ -130,6 +133,7 @@ typedef struct settings
|
||||
bool input_overlay_hide_in_menu;
|
||||
bool input_overlay_show_physical_inputs;
|
||||
bool input_overlay_show_mouse_cursor;
|
||||
bool input_overlay_auto_rotate;
|
||||
bool input_descriptor_label_show;
|
||||
bool input_descriptor_hide_unbound;
|
||||
bool input_all_users_control_menu;
|
||||
@@ -160,7 +164,6 @@ typedef struct settings
|
||||
bool menu_pointer_enable;
|
||||
bool menu_navigation_wraparound_enable;
|
||||
bool menu_navigation_browser_filter_supported_extensions_enable;
|
||||
bool menu_dpi_override_enable;
|
||||
bool menu_show_advanced_settings;
|
||||
bool menu_throttle_framerate;
|
||||
bool menu_linear_filter;
|
||||
@@ -186,6 +189,9 @@ typedef struct settings
|
||||
bool menu_show_video_layout;
|
||||
#endif
|
||||
bool menu_materialui_icons_enable;
|
||||
bool menu_materialui_auto_rotate_nav_bar;
|
||||
bool menu_materialui_dual_thumbnail_list_view_enable;
|
||||
bool menu_materialui_thumbnail_background_enable;
|
||||
bool menu_rgui_background_filler_thickness_enable;
|
||||
bool menu_rgui_border_filler_thickness_enable;
|
||||
bool menu_rgui_border_filler_enable;
|
||||
@@ -303,6 +309,9 @@ typedef struct settings
|
||||
bool bundle_finished;
|
||||
bool bundle_assets_extract_enable;
|
||||
|
||||
/* Driver */
|
||||
bool driver_switch_enable;
|
||||
|
||||
/* Misc. */
|
||||
bool discord_enable;
|
||||
bool threaded_data_runloop_enable;
|
||||
@@ -349,6 +358,7 @@ typedef struct settings
|
||||
bool ssh_enable;
|
||||
bool samba_enable;
|
||||
bool bluetooth_enable;
|
||||
bool localap_enable;
|
||||
|
||||
bool automatically_add_content_to_playlist;
|
||||
bool video_window_show_decorations;
|
||||
@@ -368,6 +378,7 @@ typedef struct settings
|
||||
bool enable_device_vibration;
|
||||
bool ozone_collapse_sidebar;
|
||||
bool ozone_truncate_playlist_name;
|
||||
bool ozone_scroll_content_metadata;
|
||||
|
||||
bool log_to_file;
|
||||
bool log_to_file_timestamp;
|
||||
@@ -375,6 +386,7 @@ typedef struct settings
|
||||
bool scan_without_core_match;
|
||||
|
||||
bool ai_service_enable;
|
||||
bool ai_service_pause;
|
||||
} bools;
|
||||
|
||||
struct
|
||||
@@ -392,6 +404,7 @@ typedef struct settings
|
||||
float video_msg_color_b;
|
||||
float video_msg_bgcolor_opacity;
|
||||
|
||||
float menu_scale_factor;
|
||||
float menu_wallpaper_opacity;
|
||||
float menu_framebuffer_opacity;
|
||||
float menu_footer_opacity;
|
||||
@@ -451,10 +464,14 @@ typedef struct settings
|
||||
|
||||
unsigned input_turbo_period;
|
||||
unsigned input_turbo_duty_cycle;
|
||||
unsigned input_turbo_mode;
|
||||
unsigned input_turbo_default_button;
|
||||
|
||||
unsigned input_bind_timeout;
|
||||
unsigned input_bind_hold;
|
||||
|
||||
#ifdef GEKKO
|
||||
unsigned input_mouse_scale;
|
||||
#endif
|
||||
unsigned input_menu_toggle_gamepad_combo;
|
||||
unsigned input_keyboard_gamepad_mapping_type;
|
||||
unsigned input_poll_type_behavior;
|
||||
@@ -506,25 +523,30 @@ typedef struct settings
|
||||
#endif
|
||||
unsigned video_shader_delay;
|
||||
|
||||
/* Accessibility */
|
||||
unsigned accessibility_narrator_speech_speed;
|
||||
|
||||
unsigned menu_timedate_style;
|
||||
unsigned menu_thumbnails;
|
||||
unsigned menu_left_thumbnails;
|
||||
unsigned menu_thumbnail_upscale_threshold;
|
||||
unsigned menu_rgui_thumbnail_downscaler;
|
||||
unsigned menu_rgui_thumbnail_delay;
|
||||
unsigned menu_dpi_override_value;
|
||||
unsigned menu_rgui_color_theme;
|
||||
unsigned menu_xmb_animation_opening_main_menu;
|
||||
unsigned menu_xmb_animation_horizontal_highlight;
|
||||
unsigned menu_xmb_animation_move_up_down;
|
||||
unsigned menu_xmb_layout;
|
||||
unsigned menu_xmb_shader_pipeline;
|
||||
unsigned menu_xmb_scale_factor;
|
||||
unsigned menu_xmb_alpha_factor;
|
||||
unsigned menu_xmb_theme;
|
||||
unsigned menu_xmb_color_theme;
|
||||
unsigned menu_xmb_thumbnail_scale_factor;
|
||||
unsigned menu_materialui_color_theme;
|
||||
unsigned menu_materialui_transition_animation;
|
||||
unsigned menu_materialui_thumbnail_view_portrait;
|
||||
unsigned menu_materialui_thumbnail_view_landscape;
|
||||
unsigned menu_materialui_landscape_layout_optimization;
|
||||
unsigned menu_ozone_color_theme;
|
||||
unsigned menu_font_color_red;
|
||||
unsigned menu_font_color_green;
|
||||
@@ -538,6 +560,7 @@ typedef struct settings
|
||||
unsigned playlist_entry_remove_enable;
|
||||
unsigned playlist_show_inline_core_name;
|
||||
unsigned playlist_sublabel_runtime_type;
|
||||
unsigned playlist_sublabel_last_played_style;
|
||||
|
||||
unsigned camera_width;
|
||||
unsigned camera_height;
|
||||
@@ -792,7 +815,7 @@ const char *config_get_default_record(void);
|
||||
* Loads a config file and reads all the values into memory.
|
||||
*
|
||||
*/
|
||||
void config_parse_file(void);
|
||||
void config_parse_file(void *data);
|
||||
|
||||
/**
|
||||
* config_load_override:
|
||||
@@ -861,7 +884,7 @@ bool config_replace(bool config_save_on_exit, char *path);
|
||||
|
||||
bool config_overlay_enable_default(void);
|
||||
|
||||
void config_set_defaults(void);
|
||||
void config_set_defaults(void *data);
|
||||
|
||||
settings_t *config_get_ptr(void);
|
||||
|
||||
|
||||
+2
-4
@@ -228,9 +228,7 @@ static config_file_t *core_info_list_iterate(
|
||||
}
|
||||
#endif
|
||||
|
||||
strlcat(info_path_base,
|
||||
file_path_str(FILE_PATH_CORE_INFO_EXTENSION),
|
||||
info_path_base_size);
|
||||
strlcat(info_path_base, ".info", info_path_base_size);
|
||||
|
||||
info_path = (char*)malloc(info_path_base_size);
|
||||
fill_pathname_join(info_path,
|
||||
@@ -1136,7 +1134,7 @@ bool core_info_hw_api_supported(core_info_t *info)
|
||||
if (string_is_empty(cur_api))
|
||||
continue;
|
||||
|
||||
cur_api_len = strlen(cur_api);
|
||||
cur_api_len = (int)strlen(cur_api);
|
||||
|
||||
for (j = 0; j < cur_api_len; j++)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,778 @@
|
||||
/* Copyright (C) 2010-2019 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (core_updater_list.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <file/file_path.h>
|
||||
#include <string/stdstring.h>
|
||||
#include <lists/string_list.h>
|
||||
#include <net/net_http.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
|
||||
#include "configuration.h"
|
||||
#include "file_path_special.h"
|
||||
#include "core_info.h"
|
||||
|
||||
#include "core_updater_list.h"
|
||||
|
||||
/* Holds all entries in a core updater list */
|
||||
struct core_updater_list
|
||||
{
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
core_updater_list_entry_t *entries;
|
||||
};
|
||||
|
||||
/* Cached ('global') core updater list */
|
||||
static core_updater_list_t *core_list_cached = NULL;
|
||||
|
||||
/**************************************/
|
||||
/* Initialisation / De-Initialisation */
|
||||
/**************************************/
|
||||
|
||||
/* Frees contents of specified core updater
|
||||
* list entry */
|
||||
static void core_updater_list_free_entry(core_updater_list_entry_t *entry)
|
||||
{
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
if (entry->remote_filename)
|
||||
{
|
||||
free(entry->remote_filename);
|
||||
entry->remote_filename = NULL;
|
||||
}
|
||||
|
||||
if (entry->remote_core_path)
|
||||
{
|
||||
free(entry->remote_core_path);
|
||||
entry->remote_core_path = NULL;
|
||||
}
|
||||
|
||||
if (entry->local_core_path)
|
||||
{
|
||||
free(entry->local_core_path);
|
||||
entry->local_core_path = NULL;
|
||||
}
|
||||
|
||||
if (entry->local_info_path)
|
||||
{
|
||||
free(entry->local_info_path);
|
||||
entry->local_info_path = NULL;
|
||||
}
|
||||
|
||||
if (entry->display_name)
|
||||
{
|
||||
free(entry->display_name);
|
||||
entry->display_name = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Creates a new, empty core updater list.
|
||||
* Returns a handle to a new core_updater_list_t object
|
||||
* on success, otherwise returns NULL. */
|
||||
core_updater_list_t *core_updater_list_init(size_t max_size)
|
||||
{
|
||||
core_updater_list_t *core_list = NULL;
|
||||
core_updater_list_entry_t *entries = NULL;
|
||||
|
||||
/* Sanity check */
|
||||
if (max_size < 1)
|
||||
return NULL;
|
||||
|
||||
/* Create core updater list */
|
||||
core_list = (core_updater_list_t*)calloc(1, sizeof(*core_list));
|
||||
|
||||
if (!core_list)
|
||||
return NULL;
|
||||
|
||||
/* Create entries array */
|
||||
entries = (core_updater_list_entry_t*)calloc(max_size, sizeof(*entries));
|
||||
|
||||
if (!entries)
|
||||
{
|
||||
free(core_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initial configuration */
|
||||
core_list->size = 0;
|
||||
core_list->capacity = max_size;
|
||||
core_list->entries = entries;
|
||||
|
||||
return core_list;
|
||||
}
|
||||
|
||||
/* Resets (removes all entries of) specified core
|
||||
* updater list */
|
||||
void core_updater_list_reset(core_updater_list_t *core_list)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!core_list)
|
||||
return;
|
||||
|
||||
for (i = 0; i < core_list->size; i++)
|
||||
{
|
||||
core_updater_list_entry_t *entry = &core_list->entries[i];
|
||||
|
||||
if (entry)
|
||||
core_updater_list_free_entry(entry);
|
||||
}
|
||||
|
||||
core_list->size = 0;
|
||||
}
|
||||
|
||||
/* Frees specified core updater list */
|
||||
void core_updater_list_free(core_updater_list_t *core_list)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!core_list)
|
||||
return;
|
||||
|
||||
for (i = 0; i < core_list->size; i++)
|
||||
{
|
||||
core_updater_list_entry_t *entry = &core_list->entries[i];
|
||||
|
||||
if (entry)
|
||||
core_updater_list_free_entry(entry);
|
||||
}
|
||||
|
||||
free(core_list->entries);
|
||||
core_list->entries = NULL;
|
||||
|
||||
free(core_list);
|
||||
}
|
||||
|
||||
/***************/
|
||||
/* Cached List */
|
||||
/***************/
|
||||
|
||||
/* Creates a new, empty cached core updater list
|
||||
* (i.e. 'global' list).
|
||||
* Returns false in the event of an error. */
|
||||
bool core_updater_list_init_cached(size_t max_size)
|
||||
{
|
||||
/* Free any existing cached core updater list */
|
||||
if (core_list_cached)
|
||||
{
|
||||
core_updater_list_free(core_list_cached);
|
||||
core_list_cached = NULL;
|
||||
}
|
||||
|
||||
core_list_cached = core_updater_list_init(max_size);
|
||||
|
||||
if (!core_list_cached)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Fetches cached core updater list */
|
||||
core_updater_list_t *core_updater_list_get_cached(void)
|
||||
{
|
||||
if (core_list_cached)
|
||||
return core_list_cached;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Frees cached core updater list */
|
||||
void core_updater_list_free_cached(void)
|
||||
{
|
||||
core_updater_list_free(core_list_cached);
|
||||
core_list_cached = NULL;
|
||||
}
|
||||
|
||||
/***********/
|
||||
/* Getters */
|
||||
/***********/
|
||||
|
||||
/* Returns number of entries in core updater list */
|
||||
size_t core_updater_list_size(core_updater_list_t *core_list)
|
||||
{
|
||||
if (!core_list)
|
||||
return 0;
|
||||
|
||||
return core_list->size;
|
||||
}
|
||||
|
||||
/* Returns maximum allowed number of entries in core
|
||||
* updater list */
|
||||
size_t core_updater_list_capacity(core_updater_list_t *core_list)
|
||||
{
|
||||
if (!core_list)
|
||||
return 0;
|
||||
|
||||
return core_list->capacity;
|
||||
}
|
||||
|
||||
/* Fetches core updater list entry corresponding
|
||||
* to the specified entry index.
|
||||
* Returns false if index is invalid. */
|
||||
bool core_updater_list_get_index(
|
||||
core_updater_list_t *core_list,
|
||||
size_t idx,
|
||||
const core_updater_list_entry_t **entry)
|
||||
{
|
||||
if (!core_list || !entry)
|
||||
return false;
|
||||
|
||||
if (idx >= core_list->size)
|
||||
return false;
|
||||
|
||||
if (entry)
|
||||
*entry = &core_list->entries[idx];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Fetches core updater list entry corresponding
|
||||
* to the specified remote core filename.
|
||||
* Returns false if core is not found. */
|
||||
bool core_updater_list_get_filename(
|
||||
core_updater_list_t *core_list,
|
||||
const char *remote_filename,
|
||||
const core_updater_list_entry_t **entry)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!core_list || string_is_empty(remote_filename))
|
||||
return false;
|
||||
|
||||
if (core_list->size < 1)
|
||||
return false;
|
||||
|
||||
/* Search for specified filename */
|
||||
for (i = 0; i < core_list->size; i++)
|
||||
{
|
||||
core_updater_list_entry_t *current_entry = &core_list->entries[i];
|
||||
|
||||
if (string_is_empty(current_entry->remote_filename))
|
||||
continue;
|
||||
|
||||
if (string_is_equal(remote_filename, current_entry->remote_filename))
|
||||
{
|
||||
if (entry)
|
||||
*entry = current_entry;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Fetches core updater list entry corresponding
|
||||
* to the specified core.
|
||||
* Returns false if core is not found. */
|
||||
bool core_updater_list_get_core(
|
||||
core_updater_list_t *core_list,
|
||||
const char *local_core_path,
|
||||
const core_updater_list_entry_t **entry)
|
||||
{
|
||||
size_t i;
|
||||
char real_core_path[PATH_MAX_LENGTH];
|
||||
|
||||
real_core_path[0] = '\0';
|
||||
|
||||
if (!core_list || !entry || string_is_empty(local_core_path))
|
||||
return false;
|
||||
|
||||
if (core_list->size < 1)
|
||||
return false;
|
||||
|
||||
/* Resolve absolute pathname of local_core_path */
|
||||
strlcpy(real_core_path, local_core_path, sizeof(real_core_path));
|
||||
path_resolve_realpath(real_core_path, sizeof(real_core_path), true);
|
||||
|
||||
if (string_is_empty(real_core_path))
|
||||
return false;
|
||||
|
||||
/* Search for specified core */
|
||||
for (i = 0; i < core_list->size; i++)
|
||||
{
|
||||
core_updater_list_entry_t *current_entry = &core_list->entries[i];
|
||||
|
||||
if (string_is_empty(current_entry->local_core_path))
|
||||
continue;
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Handle case-insensitive operating systems*/
|
||||
if (string_is_equal_noncase(real_core_path, current_entry->local_core_path))
|
||||
{
|
||||
#else
|
||||
if (string_is_equal(real_core_path, current_entry->local_core_path))
|
||||
{
|
||||
#endif
|
||||
if (entry)
|
||||
*entry = current_entry;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/***********/
|
||||
/* Setters */
|
||||
/***********/
|
||||
|
||||
/* Parses date string and adds contents to
|
||||
* specified core updater list entry */
|
||||
static bool core_updater_list_set_date(
|
||||
core_updater_list_entry_t *entry, const char *date_str)
|
||||
{
|
||||
struct string_list *date_list = NULL;
|
||||
|
||||
if (!entry || string_is_empty(date_str))
|
||||
goto error;
|
||||
|
||||
/* Split date string into component values */
|
||||
date_list = string_split(date_str, "-");
|
||||
|
||||
if (!date_list)
|
||||
goto error;
|
||||
|
||||
/* Date string must have 3 values:
|
||||
* [year] [month] [day] */
|
||||
if (date_list->size < 3)
|
||||
goto error;
|
||||
|
||||
/* Convert date string values */
|
||||
entry->date.year = string_to_unsigned(date_list->elems[0].data);
|
||||
entry->date.month = string_to_unsigned(date_list->elems[1].data);
|
||||
entry->date.day = string_to_unsigned(date_list->elems[2].data);
|
||||
|
||||
/* Clean up */
|
||||
string_list_free(date_list);
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
|
||||
if (date_list)
|
||||
string_list_free(date_list);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Parses crc string and adds value to
|
||||
* specified core updater list entry */
|
||||
static bool core_updater_list_set_crc(
|
||||
core_updater_list_entry_t *entry, const char *crc_str)
|
||||
{
|
||||
uint32_t crc;
|
||||
|
||||
if (!entry || string_is_empty(crc_str))
|
||||
return false;
|
||||
|
||||
crc = (uint32_t)string_hex_to_unsigned(crc_str);
|
||||
|
||||
if (crc == 0)
|
||||
return false;
|
||||
|
||||
entry->crc = crc;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Parses core filename string and adds all
|
||||
* associated paths to the specified core
|
||||
* updater list entry */
|
||||
static bool core_updater_list_set_paths(
|
||||
core_updater_list_entry_t *entry, const char *filename_str)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
char *last_underscore = NULL;
|
||||
char *tmp_url = NULL;
|
||||
char remote_core_path[PATH_MAX_LENGTH];
|
||||
char local_core_path[PATH_MAX_LENGTH];
|
||||
char local_info_path[PATH_MAX_LENGTH];
|
||||
char display_name[255];
|
||||
bool is_archive;
|
||||
|
||||
remote_core_path[0] = '\0';
|
||||
local_core_path[0] = '\0';
|
||||
local_info_path[0] = '\0';
|
||||
display_name[0] = '\0';
|
||||
|
||||
if (!entry || string_is_empty(filename_str) || !settings)
|
||||
return false;
|
||||
|
||||
if (string_is_empty(settings->paths.directory_libretro) ||
|
||||
string_is_empty(settings->paths.path_libretro_info) ||
|
||||
string_is_empty(settings->paths.network_buildbot_url))
|
||||
return false;
|
||||
|
||||
/* Check whether remote file is an archive */
|
||||
is_archive = path_is_compressed_file(filename_str);
|
||||
|
||||
/* remote_filename */
|
||||
if (entry->remote_filename)
|
||||
{
|
||||
free(entry->remote_filename);
|
||||
entry->remote_filename = NULL;
|
||||
}
|
||||
|
||||
entry->remote_filename = strdup(filename_str);
|
||||
|
||||
/* remote_core_path */
|
||||
fill_pathname_join(
|
||||
remote_core_path,
|
||||
settings->paths.network_buildbot_url,
|
||||
filename_str,
|
||||
sizeof(remote_core_path));
|
||||
|
||||
/* > Apply proper URL encoding (messy...) */
|
||||
tmp_url = strdup(remote_core_path);
|
||||
remote_core_path[0] = '\0';
|
||||
net_http_urlencode_full(
|
||||
remote_core_path, tmp_url, sizeof(remote_core_path));
|
||||
if (tmp_url)
|
||||
free(tmp_url);
|
||||
|
||||
if (entry->remote_core_path)
|
||||
{
|
||||
free(entry->remote_core_path);
|
||||
entry->remote_core_path = NULL;
|
||||
}
|
||||
|
||||
entry->remote_core_path = strdup(remote_core_path);
|
||||
|
||||
/* local_core_path */
|
||||
fill_pathname_join(
|
||||
local_core_path,
|
||||
settings->paths.directory_libretro,
|
||||
filename_str,
|
||||
sizeof(local_core_path));
|
||||
|
||||
if (is_archive)
|
||||
path_remove_extension(local_core_path);
|
||||
|
||||
path_resolve_realpath(local_core_path, sizeof(local_core_path), true);
|
||||
|
||||
if (entry->local_core_path)
|
||||
{
|
||||
free(entry->local_core_path);
|
||||
entry->local_core_path = NULL;
|
||||
}
|
||||
|
||||
entry->local_core_path = strdup(local_core_path);
|
||||
|
||||
/* local_info_path */
|
||||
fill_pathname_join_noext(
|
||||
local_info_path,
|
||||
settings->paths.path_libretro_info,
|
||||
filename_str,
|
||||
sizeof(local_info_path));
|
||||
|
||||
if (is_archive)
|
||||
path_remove_extension(local_info_path);
|
||||
|
||||
/* > Remove any non-standard core filename
|
||||
* additions (i.e. info files end with
|
||||
* '_libretro' but core files may have
|
||||
* a platform specific addendum,
|
||||
* e.g. '_android')*/
|
||||
last_underscore = (char*)strrchr(local_info_path, '_');
|
||||
|
||||
if (!string_is_empty(last_underscore))
|
||||
{
|
||||
if (string_is_not_equal_fast(last_underscore, "_libretro", 9))
|
||||
*last_underscore = '\0';
|
||||
}
|
||||
|
||||
/* > Add proper file extension */
|
||||
strlcat(
|
||||
local_info_path,
|
||||
file_path_str(FILE_PATH_CORE_INFO_EXTENSION),
|
||||
sizeof(local_info_path));
|
||||
|
||||
if (entry->local_info_path)
|
||||
{
|
||||
free(entry->local_info_path);
|
||||
entry->local_info_path = NULL;
|
||||
}
|
||||
|
||||
entry->local_info_path = strdup(local_info_path);
|
||||
|
||||
/* display_name
|
||||
* > Note: It's a bit rubbish that we have to
|
||||
* read the actual core info files here...
|
||||
* Would be better to cache this globally
|
||||
* (at present, we only cache info for
|
||||
* *installed* cores...) */
|
||||
if (path_is_valid(local_info_path))
|
||||
if (!core_info_get_display_name(
|
||||
local_info_path, display_name, sizeof(display_name)))
|
||||
display_name[0] = '\0';
|
||||
|
||||
/* > If info file does not exist, just use
|
||||
* core filename */
|
||||
if (string_is_empty(display_name))
|
||||
strlcpy(display_name, filename_str, sizeof(display_name));
|
||||
|
||||
if (entry->display_name)
|
||||
{
|
||||
free(entry->display_name);
|
||||
entry->display_name = NULL;
|
||||
}
|
||||
|
||||
entry->display_name = strdup(display_name);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Adds entry to the end of the specified core
|
||||
* updater list
|
||||
* NOTE: Entry string values are passed by
|
||||
* reference - *do not free the entry passed
|
||||
* to this function* */
|
||||
static bool core_updater_list_push_entry(
|
||||
core_updater_list_t *core_list, core_updater_list_entry_t *entry)
|
||||
{
|
||||
core_updater_list_entry_t *list_entry = NULL;
|
||||
|
||||
if (!core_list || !entry)
|
||||
return false;
|
||||
|
||||
/* Ensure there is enough space for the new entry */
|
||||
if (core_list->capacity <= core_list->size)
|
||||
return false;
|
||||
|
||||
/* Get handle of new entry inside list */
|
||||
list_entry = &core_list->entries[core_list->size];
|
||||
|
||||
if (!list_entry)
|
||||
return false;
|
||||
|
||||
/* Ensure list entry is empty */
|
||||
core_updater_list_free_entry(list_entry);
|
||||
|
||||
/* Assign paths */
|
||||
list_entry->remote_filename = entry->remote_filename;
|
||||
list_entry->remote_core_path = entry->remote_core_path;
|
||||
list_entry->local_core_path = entry->local_core_path;
|
||||
list_entry->local_info_path = entry->local_info_path;
|
||||
list_entry->display_name = entry->display_name;
|
||||
|
||||
/* Copy crc */
|
||||
list_entry->crc = entry->crc;
|
||||
|
||||
/* Copy date */
|
||||
memcpy(&list_entry->date, &entry->date, sizeof(core_updater_list_date_t));
|
||||
|
||||
/* Increment list size */
|
||||
core_list->size++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Parses the contents of a single buildbot
|
||||
* core listing and adds it to the specified
|
||||
* core updater list */
|
||||
static void core_updater_list_add_entry(
|
||||
core_updater_list_t *core_list,
|
||||
struct string_list *network_core_entry_list)
|
||||
{
|
||||
const char *date_str = NULL;
|
||||
const char *crc_str = NULL;
|
||||
const char *filename_str = NULL;
|
||||
core_updater_list_entry_t entry = {0};
|
||||
|
||||
if (!core_list || !network_core_entry_list)
|
||||
goto error;
|
||||
|
||||
/* > Listings must have 3 entries:
|
||||
* [date] [crc] [filename] */
|
||||
if (network_core_entry_list->size < 3)
|
||||
goto error;
|
||||
|
||||
/* Get handles of the individual listing strings */
|
||||
date_str = network_core_entry_list->elems[0].data;
|
||||
crc_str = network_core_entry_list->elems[1].data;
|
||||
filename_str = network_core_entry_list->elems[2].data;
|
||||
|
||||
if (string_is_empty(date_str) ||
|
||||
string_is_empty(crc_str) ||
|
||||
string_is_empty(filename_str))
|
||||
goto error;
|
||||
|
||||
/* Check whether core file is already included
|
||||
* in the list (this is *not* an error condition,
|
||||
* it just means we can skip the current listing) */
|
||||
if (core_updater_list_get_filename(core_list, filename_str, NULL))
|
||||
goto error;
|
||||
|
||||
/* Parse individual listing strings */
|
||||
if (!core_updater_list_set_date(&entry, date_str))
|
||||
goto error;
|
||||
|
||||
if (!core_updater_list_set_crc(&entry, crc_str))
|
||||
goto error;
|
||||
|
||||
if (!core_updater_list_set_paths(&entry, filename_str))
|
||||
goto error;
|
||||
|
||||
/* Add entry to list */
|
||||
if (!core_updater_list_push_entry(core_list, &entry))
|
||||
goto error;
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
/* This is not a *fatal* error - it just
|
||||
* means one of the following:
|
||||
* - The current line of entry text received
|
||||
* from the buildbot is broken somehow
|
||||
* (could be the case that the network buffer
|
||||
* wasn't large enough to cache the entire
|
||||
* string, so the last line was truncated)
|
||||
* - The core updater list struct is at capacity
|
||||
* In either case, the current entry is discarded
|
||||
* and we move on to the next one
|
||||
* (network transfers are fishy business, so we
|
||||
* choose to ignore this sort of error - don't
|
||||
* want the whole fetch to fail because of a
|
||||
* trivial glitch...) */
|
||||
core_updater_list_free_entry(&entry);
|
||||
}
|
||||
|
||||
/* Core updater list qsort helper function */
|
||||
static int core_updater_list_qsort_func(
|
||||
const core_updater_list_entry_t *a, const core_updater_list_entry_t *b)
|
||||
{
|
||||
if (!a || !b)
|
||||
return 0;
|
||||
|
||||
if (string_is_empty(a->display_name) || string_is_empty(b->display_name))
|
||||
return 0;
|
||||
|
||||
return strcasecmp(a->display_name, b->display_name);
|
||||
}
|
||||
|
||||
/* Sorts core updater list into alphabetical order */
|
||||
static void core_updater_list_qsort(core_updater_list_t *core_list)
|
||||
{
|
||||
if (!core_list)
|
||||
return;
|
||||
|
||||
if (core_list->size < 2)
|
||||
return;
|
||||
|
||||
qsort(
|
||||
core_list->entries,
|
||||
core_list->size,
|
||||
sizeof(core_updater_list_entry_t),
|
||||
(int (*)(const void *, const void *))
|
||||
core_updater_list_qsort_func);
|
||||
}
|
||||
|
||||
/* Reads the contents of a buildbot core list
|
||||
* network request into the specified
|
||||
* core_updater_list_t object.
|
||||
* Returns false in the event of an error. */
|
||||
bool core_updater_list_parse_network_data(
|
||||
core_updater_list_t *core_list, const char *data, size_t len)
|
||||
{
|
||||
struct string_list *network_core_list = NULL;
|
||||
struct string_list *network_core_entry_list = NULL;
|
||||
char *data_buf = NULL;
|
||||
size_t i;
|
||||
|
||||
/* Sanity check */
|
||||
if (!core_list || string_is_empty(data) || (len < 1))
|
||||
goto error;
|
||||
|
||||
/* We're populating a list 'from scratch' - remove
|
||||
* any existing entries */
|
||||
core_updater_list_reset(core_list);
|
||||
|
||||
/* Input data string is not terminated - have
|
||||
* to copy it to a temporary buffer... */
|
||||
data_buf = (char*)malloc((len + 1) * sizeof(char));
|
||||
|
||||
if (!data_buf)
|
||||
goto error;
|
||||
|
||||
memcpy(data_buf, data, len * sizeof(char));
|
||||
data_buf[len] = '\0';
|
||||
|
||||
/* Split network listing request into lines */
|
||||
network_core_list = string_split(data_buf, "\n");
|
||||
|
||||
if (!network_core_list)
|
||||
goto error;
|
||||
|
||||
if (network_core_list->size < 1)
|
||||
goto error;
|
||||
|
||||
/* Temporary data buffer is no longer required */
|
||||
free(data_buf);
|
||||
|
||||
/* Loop over lines */
|
||||
for (i = 0; i < network_core_list->size; i++)
|
||||
{
|
||||
const char *line = network_core_list->elems[i].data;
|
||||
|
||||
if (string_is_empty(line))
|
||||
continue;
|
||||
|
||||
/* Split line into listings info components */
|
||||
network_core_entry_list = string_split(line, " ");
|
||||
|
||||
/* Parse listings info and add to core updater
|
||||
* list */
|
||||
core_updater_list_add_entry(
|
||||
core_list, network_core_entry_list);
|
||||
|
||||
/* Clean up */
|
||||
string_list_free(network_core_entry_list);
|
||||
network_core_entry_list = NULL;
|
||||
}
|
||||
|
||||
/* Sanity check */
|
||||
if (core_list->size < 1)
|
||||
goto error;
|
||||
|
||||
/* Clean up */
|
||||
string_list_free(network_core_list);
|
||||
|
||||
/* Sort completed list */
|
||||
core_updater_list_qsort(core_list);
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
|
||||
if (network_core_list)
|
||||
string_list_free(network_core_list);
|
||||
|
||||
if (network_core_entry_list)
|
||||
string_list_free(network_core_entry_list);
|
||||
|
||||
if (data_buf)
|
||||
free(data_buf);
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/* Copyright (C) 2010-2019 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (core_updater_list.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __CORE_UPDATER_LIST_H
|
||||
#define __CORE_UPDATER_LIST_H
|
||||
|
||||
#include <retro_common_api.h>
|
||||
#include <libretro.h>
|
||||
|
||||
#include <boolean.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
/* Default maximum number of entries in
|
||||
* a core updater list */
|
||||
#define CORE_UPDATER_LIST_SIZE 9999
|
||||
|
||||
/* Holds all date info for a core file
|
||||
* on the buildbot */
|
||||
typedef struct
|
||||
{
|
||||
unsigned year;
|
||||
unsigned month;
|
||||
unsigned day;
|
||||
} core_updater_list_date_t;
|
||||
|
||||
/* Holds all info related to a core
|
||||
* file on the buildbot */
|
||||
typedef struct
|
||||
{
|
||||
char *remote_filename;
|
||||
char *remote_core_path;
|
||||
char *local_core_path;
|
||||
char *local_info_path;
|
||||
char *display_name;
|
||||
uint32_t crc;
|
||||
core_updater_list_date_t date;
|
||||
} core_updater_list_entry_t;
|
||||
|
||||
/* Prevent direct access to core_updater_list_t
|
||||
* members */
|
||||
typedef struct core_updater_list core_updater_list_t;
|
||||
|
||||
/**************************************/
|
||||
/* Initialisation / De-Initialisation */
|
||||
/**************************************/
|
||||
|
||||
/* Creates a new, empty core updater list with a
|
||||
* maximum number of 'max_size' entries.
|
||||
* Returns a handle to a new core_updater_list_t object
|
||||
* on success, otherwise returns NULL. */
|
||||
core_updater_list_t *core_updater_list_init(size_t max_size);
|
||||
|
||||
/* Resets (removes all entries of) specified core
|
||||
* updater list */
|
||||
void core_updater_list_reset(core_updater_list_t *core_list);
|
||||
|
||||
/* Frees specified core updater list */
|
||||
void core_updater_list_free(core_updater_list_t *core_list);
|
||||
|
||||
/***************/
|
||||
/* Cached List */
|
||||
/***************/
|
||||
|
||||
/* Creates a new, empty cached core updater list
|
||||
* (i.e. 'global' list).
|
||||
* Returns false in the event of an error. */
|
||||
bool core_updater_list_init_cached(size_t max_size);
|
||||
|
||||
/* Fetches cached core updater list */
|
||||
core_updater_list_t *core_updater_list_get_cached(void);
|
||||
|
||||
/* Frees cached core updater list */
|
||||
void core_updater_list_free_cached(void);
|
||||
|
||||
/***********/
|
||||
/* Getters */
|
||||
/***********/
|
||||
|
||||
/* Returns number of entries in core updater list */
|
||||
size_t core_updater_list_size(core_updater_list_t *core_list);
|
||||
|
||||
/* Returns maximum allowed number of entries in core
|
||||
* updater list */
|
||||
size_t core_updater_list_capacity(core_updater_list_t *core_list);
|
||||
|
||||
/* Fetches core updater list entry corresponding
|
||||
* to the specified entry index.
|
||||
* Returns false if index is invalid. */
|
||||
bool core_updater_list_get_index(
|
||||
core_updater_list_t *core_list,
|
||||
size_t idx,
|
||||
const core_updater_list_entry_t **entry);
|
||||
|
||||
/* Fetches core updater list entry corresponding
|
||||
* to the specified remote core filename.
|
||||
* Returns false if core is not found. */
|
||||
bool core_updater_list_get_filename(
|
||||
core_updater_list_t *core_list,
|
||||
const char *remote_filename,
|
||||
const core_updater_list_entry_t **entry);
|
||||
|
||||
/* Fetches core updater list entry corresponding
|
||||
* to the specified core.
|
||||
* Returns false if core is not found. */
|
||||
bool core_updater_list_get_core(
|
||||
core_updater_list_t *core_list,
|
||||
const char *local_core_path,
|
||||
const core_updater_list_entry_t **entry);
|
||||
|
||||
/***********/
|
||||
/* Setters */
|
||||
/***********/
|
||||
|
||||
/* Reads the contents of a buildbot core list
|
||||
* network request into the specified
|
||||
* core_updater_list_t object.
|
||||
* Returns false in the event of an error. */
|
||||
bool core_updater_list_parse_network_data(
|
||||
core_updater_list_t *core_list, const char *data, size_t len);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
@@ -360,7 +360,7 @@ size_t libretro_videoprocessor_retro_get_memory_size(unsigned id);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_EASTEREGG
|
||||
#ifdef HAVE_GONG
|
||||
/* Internal gong core. */
|
||||
|
||||
void libretro_gong_retro_init(void);
|
||||
|
||||
@@ -75,6 +75,11 @@ endif
|
||||
|
||||
TARGET_NAME := ffmpeg
|
||||
|
||||
GIT_VERSION ?= " $(shell git rev-parse --short HEAD || echo unknown)"
|
||||
ifneq ($(GIT_VERSION)," unknown")
|
||||
CFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\"
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring unix,$(platform)))
|
||||
ARCH_X86 = 1
|
||||
TARGET := $(TARGET_NAME)_libretro.so
|
||||
@@ -123,7 +128,7 @@ else ifneq (,$(findstring ios,$(platform)))
|
||||
TARGET := $(TARGET_NAME)_libretro_ios.dylib
|
||||
fpic := -fPIC
|
||||
SHARED := -dynamiclib
|
||||
CFLAGS += -I. -I.. -DHAVE_FMINF -DIOS
|
||||
CFLAGS += -I. -I.. -DHAVE_FMINF -DIOS -DHAVE_UNISTD_H
|
||||
ifeq ($(OPENGL),1)
|
||||
HAVE_OPENGL = 1
|
||||
GLES = 1
|
||||
@@ -140,11 +145,16 @@ ifeq ($(IOSSDK),)
|
||||
IOSSDK := $(shell xcodebuild -version -sdk iphoneos Path)
|
||||
endif
|
||||
|
||||
ifeq ($(platform),ios-arm64)
|
||||
CC = cc -arch arm64 -isysroot $(IOSSDK)
|
||||
CXX = c++ -arch arm64 -isysroot $(IOSSDK)
|
||||
else
|
||||
CC = cc -arch armv7 -isysroot $(IOSSDK)
|
||||
CXX = c++ -arch armv7 -isysroot $(IOSSDK)
|
||||
LD = armv7-apple-darwin11-ld
|
||||
endif
|
||||
|
||||
ifeq ($(platform),ios9)
|
||||
ifeq ($(platform),$(filter $(platform),ios9 ios-arm64))
|
||||
CC += -miphoneos-version-min=8.0
|
||||
CFLAGS += -miphoneos-version-min=8.0
|
||||
else
|
||||
@@ -177,20 +187,23 @@ else ifeq ($(platform), emscripten)
|
||||
else
|
||||
|
||||
ARCH_X86 = 1
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
TARGET := $(TARGET_NAME)_libretro.dll
|
||||
SHARED := -shared -static-libgcc -static-libstdc++ -s -Wl,--version-script=link.T -Wl,--no-undefined
|
||||
CFLAGS += -Iffmpeg
|
||||
ifeq ($(OPENGL),1)
|
||||
GL_LIB := -lopengl32
|
||||
CFLAGS += -DHAVE_OPENGL
|
||||
HAVE_OPENGL = 1
|
||||
HAVE_GL_FFT := 1
|
||||
WIN32_PLATFORM := 1
|
||||
endif
|
||||
LIBS += -L.
|
||||
endif
|
||||
|
||||
ifeq ($(LIBRETRO_SWITCH), 1)
|
||||
CFLAGS += -DUPSTREAM_VERSION=\"$(shell cat ../RELEASE)\"
|
||||
endif
|
||||
|
||||
CFLAGS += -D__LIBRETRO__
|
||||
|
||||
include Makefile.common
|
||||
|
||||
@@ -19,10 +19,12 @@ SWRESAMPLE_DIR := $(BASE_DIR)/libswresample
|
||||
INCFLAGS += -I$(BASE_DIR) -I$(CORE_DIR) -I$(LIBRETRO_COMM_DIR)/include -I$(LIBRETRO_COMM_DIR)/include/compat
|
||||
|
||||
LIBRETRO_SOURCE += $(CORE_DIR)/ffmpeg_core.c \
|
||||
$(CORE_DIR)/video_buffer.c \
|
||||
$(LIBRETRO_COMM_DIR)/rthreads/tpool.c \
|
||||
$(LIBRETRO_COMM_DIR)/queues/fifo_queue.c \
|
||||
$(LIBRETRO_COMM_DIR)/rthreads/rthreads.c
|
||||
|
||||
ifeq ($(LIBRETRO_SWITCH),1)
|
||||
ifeq ($(LIBRETRO_SWITCH), 1)
|
||||
DEFINES += -DLIBRETRO_SWITCH=1
|
||||
INTERNAL_LIBAVCODEC = 1
|
||||
INTERNAL_LIBAVFORMAT = 1
|
||||
|
||||
@@ -5,6 +5,7 @@ ifeq ($(INTERNAL_ZLIB),0)
|
||||
HAVE_ZLIB = 1
|
||||
else
|
||||
HAVE_ZLIB = 1
|
||||
DEFINES += -DWANT_ZLIB
|
||||
INCFLAGS += -I$(DEPS_DIR)/libz
|
||||
DEPS_SOURCE += $(wildcard $(DEPS_DIR)/libz/*.c)
|
||||
endif
|
||||
|
||||
+627
-292
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,246 @@
|
||||
#include <libavformat/avformat.h>
|
||||
|
||||
#include <rthreads/rthreads.h>
|
||||
|
||||
#include "video_buffer.h"
|
||||
|
||||
enum kbStatus
|
||||
{
|
||||
KB_OPEN,
|
||||
KB_IN_PROGRESS,
|
||||
KB_FINISHED
|
||||
};
|
||||
|
||||
struct video_buffer
|
||||
{
|
||||
video_decoder_context_t *buffer;
|
||||
enum kbStatus *status;
|
||||
size_t size;
|
||||
slock_t *lock;
|
||||
scond_t *open_cond;
|
||||
scond_t *finished_cond;
|
||||
int64_t head;
|
||||
int64_t tail;
|
||||
};
|
||||
|
||||
video_buffer_t *video_buffer_create(size_t num, int frame_size, int width, int height)
|
||||
{
|
||||
video_buffer_t *b = malloc(sizeof (video_buffer_t));
|
||||
if (!b)
|
||||
return NULL;
|
||||
|
||||
b->lock = NULL;
|
||||
b->open_cond = NULL;
|
||||
b->finished_cond = NULL;
|
||||
b->buffer = NULL;
|
||||
b->size = num;
|
||||
b->head = 0;
|
||||
b->tail = 0;
|
||||
|
||||
b->status = malloc(sizeof(enum kbStatus) * num);
|
||||
if (!b->status)
|
||||
goto fail;
|
||||
for (int i = 0; i < num; i++)
|
||||
b->status[i] = KB_OPEN;
|
||||
|
||||
b->lock = slock_new();
|
||||
b->open_cond = scond_new();
|
||||
b->finished_cond = scond_new();
|
||||
if (!b->lock || !b->open_cond || !b->finished_cond)
|
||||
goto fail;
|
||||
|
||||
b->buffer = malloc(sizeof(video_decoder_context_t) * num);
|
||||
if (!b->buffer)
|
||||
goto fail;
|
||||
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
b->buffer[i].index = i;
|
||||
b->buffer[i].pts = 0;
|
||||
b->buffer[i].sws = sws_alloc_context();
|
||||
b->buffer[i].source = av_frame_alloc();
|
||||
#if LIBAVUTIL_VERSION_MAJOR > 55
|
||||
b->buffer[i].hw_source = av_frame_alloc();
|
||||
#endif
|
||||
b->buffer[i].target = av_frame_alloc();
|
||||
b->buffer[i].frame_buf = av_malloc(frame_size);
|
||||
|
||||
avpicture_fill((AVPicture*)b->buffer[i].target, (const uint8_t*)b->buffer[i].frame_buf,
|
||||
PIX_FMT_RGB32, width, height);
|
||||
|
||||
if (!b->buffer[i].sws ||
|
||||
!b->buffer[i].source ||
|
||||
#if LIBAVUTIL_VERSION_MAJOR > 55
|
||||
!b->buffer[i].hw_source ||
|
||||
#endif
|
||||
!b->buffer[i].target ||
|
||||
!b->buffer[i].frame_buf)
|
||||
goto fail;
|
||||
}
|
||||
return b;
|
||||
|
||||
fail:
|
||||
video_buffer_destroy(b);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void video_buffer_destroy(video_buffer_t *video_buffer)
|
||||
{
|
||||
if (!video_buffer)
|
||||
return;
|
||||
|
||||
slock_free(video_buffer->lock);
|
||||
scond_free(video_buffer->open_cond);
|
||||
scond_free(video_buffer->finished_cond);
|
||||
free(video_buffer->status);
|
||||
if (video_buffer->buffer)
|
||||
for (int i = 0; i < video_buffer->size; i++)
|
||||
{
|
||||
#if LIBAVUTIL_VERSION_MAJOR > 55
|
||||
av_frame_free(&video_buffer->buffer[i].hw_source);
|
||||
#endif
|
||||
av_frame_free(&video_buffer->buffer[i].source);
|
||||
av_frame_free(&video_buffer->buffer[i].target);
|
||||
av_freep(&video_buffer->buffer[i].frame_buf);
|
||||
sws_freeContext(video_buffer->buffer[i].sws);
|
||||
}
|
||||
free(video_buffer->buffer);
|
||||
free(video_buffer);
|
||||
}
|
||||
|
||||
void video_buffer_clear(video_buffer_t *video_buffer)
|
||||
{
|
||||
if (!video_buffer)
|
||||
return;
|
||||
|
||||
slock_lock(video_buffer->lock);
|
||||
|
||||
scond_signal(video_buffer->open_cond);
|
||||
scond_signal(video_buffer->finished_cond);
|
||||
|
||||
video_buffer->head = 0;
|
||||
video_buffer->tail = 0;
|
||||
for (int i = 0; i < video_buffer->size; i++)
|
||||
video_buffer->status[i] = KB_OPEN;
|
||||
|
||||
slock_unlock(video_buffer->lock);
|
||||
}
|
||||
|
||||
void video_buffer_get_open_slot(video_buffer_t *video_buffer, video_decoder_context_t **context)
|
||||
{
|
||||
slock_lock(video_buffer->lock);
|
||||
|
||||
if (video_buffer->status[video_buffer->head] == KB_OPEN)
|
||||
{
|
||||
*context = &video_buffer->buffer[video_buffer->head];
|
||||
video_buffer->status[video_buffer->head] = KB_IN_PROGRESS;
|
||||
video_buffer->head++;
|
||||
video_buffer->head %= video_buffer->size;
|
||||
}
|
||||
|
||||
slock_unlock(video_buffer->lock);
|
||||
}
|
||||
|
||||
void video_buffer_return_open_slot(video_buffer_t *video_buffer, video_decoder_context_t *context)
|
||||
{
|
||||
slock_lock(video_buffer->lock);
|
||||
|
||||
if (video_buffer->status[context->index] == KB_IN_PROGRESS)
|
||||
{
|
||||
video_buffer->status[context->index] = KB_OPEN;
|
||||
video_buffer->head--;
|
||||
video_buffer->head %= video_buffer->size;
|
||||
}
|
||||
|
||||
slock_unlock(video_buffer->lock);
|
||||
}
|
||||
|
||||
void video_buffer_open_slot(video_buffer_t *video_buffer, video_decoder_context_t *context)
|
||||
{
|
||||
slock_lock(video_buffer->lock);
|
||||
|
||||
if (video_buffer->status[context->index] == KB_FINISHED)
|
||||
{
|
||||
video_buffer->status[context->index] = KB_OPEN;
|
||||
video_buffer->tail++;
|
||||
video_buffer->tail %= (video_buffer->size);
|
||||
scond_signal(video_buffer->open_cond);
|
||||
}
|
||||
|
||||
slock_unlock(video_buffer->lock);
|
||||
}
|
||||
|
||||
void video_buffer_get_finished_slot(video_buffer_t *video_buffer, video_decoder_context_t **context)
|
||||
{
|
||||
slock_lock(video_buffer->lock);
|
||||
|
||||
if (video_buffer->status[video_buffer->tail] == KB_FINISHED)
|
||||
*context = &video_buffer->buffer[video_buffer->tail];
|
||||
|
||||
slock_unlock(video_buffer->lock);
|
||||
}
|
||||
|
||||
void video_buffer_finish_slot(video_buffer_t *video_buffer, video_decoder_context_t *context)
|
||||
{
|
||||
slock_lock(video_buffer->lock);
|
||||
|
||||
if (video_buffer->status[context->index] == KB_IN_PROGRESS)
|
||||
{
|
||||
video_buffer->status[context->index] = KB_FINISHED;
|
||||
scond_signal(video_buffer->finished_cond);
|
||||
}
|
||||
|
||||
slock_unlock(video_buffer->lock);
|
||||
}
|
||||
|
||||
bool video_buffer_wait_for_open_slot(video_buffer_t *video_buffer)
|
||||
{
|
||||
slock_lock(video_buffer->lock);
|
||||
|
||||
while (video_buffer->status[video_buffer->head] != KB_OPEN)
|
||||
scond_wait(video_buffer->open_cond, video_buffer->lock);
|
||||
|
||||
slock_unlock(video_buffer->lock);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool video_buffer_wait_for_finished_slot(video_buffer_t *video_buffer)
|
||||
{
|
||||
slock_lock(video_buffer->lock);
|
||||
|
||||
while (video_buffer->status[video_buffer->tail] != KB_FINISHED)
|
||||
scond_wait(video_buffer->finished_cond, video_buffer->lock);
|
||||
|
||||
slock_unlock(video_buffer->lock);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool video_buffer_has_open_slot(video_buffer_t *video_buffer)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
slock_lock(video_buffer->lock);
|
||||
|
||||
if (video_buffer->status[video_buffer->head] == KB_OPEN)
|
||||
ret = true;
|
||||
|
||||
slock_unlock(video_buffer->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool video_buffer_has_finished_slot(video_buffer_t *video_buffer)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
slock_lock(video_buffer->lock);
|
||||
|
||||
if (video_buffer->status[video_buffer->tail] == KB_FINISHED)
|
||||
ret = true;
|
||||
|
||||
slock_unlock(video_buffer->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
#ifndef __LIBRETRO_SDK_SWSBUFFER_H__
|
||||
#define __LIBRETRO_SDK_SWSBUFFER_H__
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
#include <boolean.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef HAVE_SSA
|
||||
#include <ass/ass.h>
|
||||
#endif
|
||||
|
||||
#include <libavutil/frame.h>
|
||||
#include <libswscale/swscale.h>
|
||||
|
||||
#include <retro_miscellaneous.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
#ifndef PIX_FMT_RGB32
|
||||
#define PIX_FMT_RGB32 AV_PIX_FMT_RGB32
|
||||
#endif
|
||||
|
||||
/**
|
||||
* video_decoder_context
|
||||
*
|
||||
* Context object for the sws worker threads.
|
||||
*
|
||||
*/
|
||||
struct video_decoder_context
|
||||
{
|
||||
int index;
|
||||
int64_t pts;
|
||||
struct SwsContext *sws;
|
||||
AVFrame *source;
|
||||
#if LIBAVUTIL_VERSION_MAJOR > 55
|
||||
AVFrame *hw_source;
|
||||
#endif
|
||||
AVFrame *target;
|
||||
#ifdef HAVE_SSA
|
||||
ASS_Track *ass_track_active;
|
||||
#endif
|
||||
uint8_t *frame_buf;
|
||||
};
|
||||
typedef struct video_decoder_context video_decoder_context_t;
|
||||
|
||||
/**
|
||||
* video_buffer
|
||||
*
|
||||
* The video_buffer is a ring buffer, that can be used as a
|
||||
* buffer for many workers while keeping the order.
|
||||
*
|
||||
* It is thread safe in a sensem that it is designed to work
|
||||
* with one work coordinator, that allocates work slots for
|
||||
* workers threads to work on and later collect the work
|
||||
* product in the same order, as the slots were allocated.
|
||||
*
|
||||
*/
|
||||
struct video_buffer;
|
||||
typedef struct video_buffer video_buffer_t;
|
||||
|
||||
/**
|
||||
* video_buffer_create:
|
||||
* @num : Size of the buffer.
|
||||
* @frame_size : Size of the target frame.
|
||||
* @width : Width of the target frame.
|
||||
* @height : Height of the target frame.
|
||||
*
|
||||
* Create a video_buffer.
|
||||
*
|
||||
* Returns: A video buffer.
|
||||
*/
|
||||
video_buffer_t *video_buffer_create(size_t num, int frame_size, int width, int height);
|
||||
|
||||
/**
|
||||
* video_buffer_destroy:
|
||||
* @video_buffer : video buffer.
|
||||
*
|
||||
* Destory a video_buffer.
|
||||
*
|
||||
* Does also free the buffer allocated with video_buffer_create().
|
||||
* User has to shut down any external worker threads that may have
|
||||
* a reference to this video_buffer.
|
||||
*
|
||||
**/
|
||||
void video_buffer_destroy(video_buffer_t *video_buffer);
|
||||
|
||||
/**
|
||||
* video_buffer_clear:
|
||||
* @video_buffer : video buffer.
|
||||
*
|
||||
* Clears a video_buffer.
|
||||
*
|
||||
**/
|
||||
void video_buffer_clear(video_buffer_t *video_buffer);
|
||||
|
||||
/**
|
||||
* video_buffer_get_open_slot:
|
||||
* @video_buffer : video buffer.
|
||||
* @contex : sws context.
|
||||
*
|
||||
* Returns the next open context inside the ring buffer
|
||||
* and it's index. The status of the slot will be marked as
|
||||
* 'in progress' until slot is marked as finished with
|
||||
* video_buffer_finish_slot();
|
||||
*
|
||||
**/
|
||||
void video_buffer_get_open_slot(video_buffer_t *video_buffer, video_decoder_context_t **context);
|
||||
|
||||
/**
|
||||
* video_buffer_return_open_slot:
|
||||
* @video_buffer : video buffer.
|
||||
* @contex : sws context.
|
||||
*
|
||||
* Marks the given sws context that is "in progress" as "open" again.
|
||||
*
|
||||
**/
|
||||
void video_buffer_return_open_slot(video_buffer_t *video_buffer, video_decoder_context_t *context);
|
||||
|
||||
/**
|
||||
* video_buffer_open_slot:
|
||||
* @video_buffer : video buffer.
|
||||
* @context : sws context.
|
||||
*
|
||||
* Sets the status of the given context from "finished" to "open".
|
||||
* The slot is then available for producers to claim again with video_buffer_get_open_slot().
|
||||
**/
|
||||
void video_buffer_open_slot(video_buffer_t *video_buffer, video_decoder_context_t *context);
|
||||
|
||||
/**
|
||||
* video_buffer_get_finished_slot:
|
||||
* @video_buffer : video buffer.
|
||||
* @context : sws context.
|
||||
*
|
||||
* Returns a reference for the next context inside
|
||||
* the ring buffer. User needs to use video_buffer_open_slot()
|
||||
* to open the slot in the ringbuffer for the next
|
||||
* work assignment. User is free to re-allocate or
|
||||
* re-use the context.
|
||||
*
|
||||
*/
|
||||
void video_buffer_get_finished_slot(video_buffer_t *video_buffer, video_decoder_context_t **context);
|
||||
|
||||
/**
|
||||
* video_buffer_finish_slot:
|
||||
* @video_buffer : video buffer.
|
||||
* @context : sws context.
|
||||
*
|
||||
* Sets the status of the given context from "in progress" to "finished".
|
||||
* This is normally done by a producer. User can then retrieve the finished work
|
||||
* context by calling video_buffer_get_finished_slot().
|
||||
*/
|
||||
void video_buffer_finish_slot(video_buffer_t *video_buffer, video_decoder_context_t *context);
|
||||
|
||||
/**
|
||||
* video_buffer_wait_for_open_slot:
|
||||
* @video_buffer : video buffer.
|
||||
*
|
||||
* Blocks until open slot is available.
|
||||
*
|
||||
* Returns true if the buffer has a open slot available.
|
||||
*/
|
||||
bool video_buffer_wait_for_open_slot(video_buffer_t *video_buffer);
|
||||
|
||||
/**
|
||||
* video_buffer_wait_for_finished_slot:
|
||||
* @video_buffer : video buffer.
|
||||
*
|
||||
* Blocks until finished slot is available.
|
||||
*
|
||||
* Returns true if the buffers next slot is finished and a
|
||||
* context available.
|
||||
*/
|
||||
bool video_buffer_wait_for_finished_slot(video_buffer_t *video_buffer);
|
||||
|
||||
/**
|
||||
* bool video_buffer_has_open_slot(video_buffer_t *video_buffer)
|
||||
:
|
||||
* @video_buffer : video buffer.
|
||||
*
|
||||
* Returns true if the buffer has a open slot available.
|
||||
*/
|
||||
bool video_buffer_has_open_slot(video_buffer_t *video_buffer);
|
||||
|
||||
/**
|
||||
* video_buffer_has_finished_slot:
|
||||
* @video_buffer : video buffer.
|
||||
*
|
||||
* Returns true if the buffers next slot is finished and a
|
||||
* context available.
|
||||
*/
|
||||
bool video_buffer_has_finished_slot(video_buffer_t *video_buffer);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
@@ -386,7 +386,7 @@ void GONG_CORE_PREFIX(retro_init)(void)
|
||||
else
|
||||
GONG_CORE_PREFIX(log_cb) = NULL;
|
||||
|
||||
video_buf = (unsigned char*)calloc(1, WIDTH * HEIGHT * sizeof(unsigned char));
|
||||
video_buf = (unsigned char*)calloc(1, WIDTH * HEIGHT * sizeof(unsigned));
|
||||
|
||||
game_buffer.width = WIDTH;
|
||||
game_buffer.height = HEIGHT;
|
||||
|
||||
+22
-6
@@ -464,6 +464,19 @@ static void do_memchunkhax1(void)
|
||||
write_kaddr(0x1F000008, saved_vram_value);
|
||||
}
|
||||
|
||||
Result get_luma_version(u32 *major, u32 *minor) {
|
||||
s64 out;
|
||||
u32 version;
|
||||
|
||||
if (R_FAILED(svcGetSystemInfo(&out, 0x10000, 0)))
|
||||
return -1;
|
||||
|
||||
version = (u32)out;
|
||||
*major = GET_VERSION_MAJOR(version);
|
||||
*minor = GET_VERSION_MINOR(version);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result svchax_init(bool patch_srv)
|
||||
{
|
||||
bool isNew3DS;
|
||||
@@ -475,12 +488,15 @@ Result svchax_init(bool patch_srv)
|
||||
{
|
||||
if (__service_ptr)
|
||||
{
|
||||
if (kver > SYSTEM_VERSION(2, 50, 11))
|
||||
return -1;
|
||||
else if (kver > SYSTEM_VERSION(2, 46, 0))
|
||||
do_memchunkhax2();
|
||||
else
|
||||
do_memchunkhax1();
|
||||
u32 luma_major, luma_minor;
|
||||
|
||||
if (kver > SYSTEM_VERSION(2, 50, 11) &&
|
||||
(R_FAILED(get_luma_version(&luma_major, &luma_minor) || luma_major < 8)))
|
||||
return -1;
|
||||
else if (kver > SYSTEM_VERSION(2, 46, 0) && kver <= SYSTEM_VERSION(2, 50, 11))
|
||||
do_memchunkhax2();
|
||||
else if (kver <= SYSTEM_VERSION(2, 46, 0))
|
||||
do_memchunkhax1();
|
||||
}
|
||||
|
||||
svc_7b((backdoor_fn)k_enable_all_svcs, isNew3DS);
|
||||
|
||||
+8
-10
@@ -38,8 +38,7 @@ int database_info_build_query_enum(char *s, size_t len,
|
||||
bool add_quotes = true;
|
||||
bool add_glob = false;
|
||||
|
||||
string_add_bracket_open(s, len);
|
||||
string_add_single_quote(s, len);
|
||||
strlcpy(s, "{'", len);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
@@ -51,7 +50,7 @@ int database_info_build_query_enum(char *s, size_t len,
|
||||
break;
|
||||
case DATABASE_QUERY_ENTRY_DEVELOPER:
|
||||
strlcat(s, "developer", len);
|
||||
add_glob = true;
|
||||
add_glob = true;
|
||||
add_quotes = false;
|
||||
break;
|
||||
case DATABASE_QUERY_ENTRY_ORIGIN:
|
||||
@@ -110,19 +109,18 @@ int database_info_build_query_enum(char *s, size_t len,
|
||||
break;
|
||||
}
|
||||
|
||||
string_add_single_quote(s, len);
|
||||
string_add_colon(s, len);
|
||||
strlcat(s, "':", len);
|
||||
if (add_glob)
|
||||
string_add_glob_open(s, len);
|
||||
strlcat(s, "glob('*", len);
|
||||
if (add_quotes)
|
||||
string_add_quote(s, len);
|
||||
strlcat(s, "\"", len);
|
||||
strlcat(s, path, len);
|
||||
if (add_glob)
|
||||
string_add_glob_close(s, len);
|
||||
strlcat(s, "*')", len);
|
||||
if (add_quotes)
|
||||
string_add_quote(s, len);
|
||||
strlcat(s, "\"", len);
|
||||
|
||||
string_add_bracket_close(s, len);
|
||||
strlcat(s, "}", len);
|
||||
|
||||
#if 0
|
||||
RARCH_LOG("query: %s\n", s);
|
||||
|
||||
Vendored
+21
-4
@@ -21,6 +21,7 @@
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <mutex>
|
||||
|
||||
#include "../../verbosity.h"
|
||||
|
||||
@@ -31,18 +32,33 @@ struct SlangProcess
|
||||
{
|
||||
public:
|
||||
SlangProcess();
|
||||
|
||||
TBuiltInResource& GetResources() { return Resources; }
|
||||
~SlangProcess() { FinalizeProcess(); }
|
||||
|
||||
private:
|
||||
TBuiltInResource Resources;
|
||||
};
|
||||
|
||||
// We don't use glslang from multiple threads, but to be sure.
|
||||
// Initializing TLS and freeing it for glslang works around a really bizarre issue
|
||||
// where the TLS key is suddenly corrupted *somehow*.
|
||||
static std::mutex glslang_global_lock;
|
||||
struct SlangProcessHolder
|
||||
{
|
||||
SlangProcessHolder()
|
||||
{
|
||||
glslang_global_lock.lock();
|
||||
InitializeProcess();
|
||||
}
|
||||
|
||||
~SlangProcessHolder()
|
||||
{
|
||||
FinalizeProcess();
|
||||
glslang_global_lock.unlock();
|
||||
}
|
||||
};
|
||||
|
||||
SlangProcess::SlangProcess()
|
||||
{
|
||||
InitializeProcess();
|
||||
|
||||
char DefaultConfig[] =
|
||||
"MaxLights 32\n"
|
||||
"MaxClipPlanes 6\n"
|
||||
@@ -337,6 +353,7 @@ SlangProcess::SlangProcess()
|
||||
bool glslang::compile_spirv(const string &source, Stage stage, std::vector<uint32_t> *spirv)
|
||||
{
|
||||
static SlangProcess process;
|
||||
SlangProcessHolder process_holder;
|
||||
|
||||
TProgram program;
|
||||
EShLanguage language;
|
||||
|
||||
@@ -158,6 +158,7 @@ bool DetachProcess()
|
||||
|
||||
OS_FreeTLSIndex(ThreadInitializeIndex);
|
||||
ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
|
||||
DeinitializePoolIndex();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
namespace glslang {
|
||||
|
||||
bool InitializePoolIndex();
|
||||
bool DeinitializePoolIndex();
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
|
||||
@@ -65,6 +65,15 @@ bool InitializePoolIndex()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeinitializePoolIndex()
|
||||
{
|
||||
if (PoolIndex == OS_INVALID_TLS_INDEX)
|
||||
return false;
|
||||
OS_FreeTLSIndex(PoolIndex);
|
||||
PoolIndex = OS_INVALID_TLS_INDEX;
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Implement the functionality of the TPoolAllocator class, which
|
||||
// is documented in PoolAlloc.h.
|
||||
|
||||
@@ -1312,6 +1312,7 @@ int __fastcall ShFinalize()
|
||||
glslang::HlslScanContext::deleteKeywordMap();
|
||||
#endif
|
||||
|
||||
DetachProcess();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
Vendored
+2
-1
@@ -8,10 +8,11 @@ extern SceGxmVertexProgram *_vita2d_colorVertexProgram;
|
||||
extern SceGxmFragmentProgram *_vita2d_colorFragmentProgram;
|
||||
extern SceGxmVertexProgram *_vita2d_textureVertexProgram;
|
||||
extern SceGxmFragmentProgram *_vita2d_textureFragmentProgram;
|
||||
extern SceGxmVertexProgram *_vita2d_textureTintVertexProgram;
|
||||
extern SceGxmFragmentProgram *_vita2d_textureTintFragmentProgram;
|
||||
extern const SceGxmProgramParameter *_vita2d_colorWvpParam;
|
||||
extern const SceGxmProgramParameter *_vita2d_textureWvpParam;
|
||||
extern const SceGxmProgramParameter *_vita2d_textureTintColorParam;
|
||||
extern const SceGxmProgramParameter *_vita2d_textureTintWvpParam;
|
||||
|
||||
|
||||
#endif
|
||||
Vendored
+15
-1
@@ -31,6 +31,18 @@ typedef struct vita2d_texture_vertex {
|
||||
float v;
|
||||
} vita2d_texture_vertex;
|
||||
|
||||
typedef struct vita2d_texture_tint_vertex {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float u;
|
||||
float v;
|
||||
float r;
|
||||
float g;
|
||||
float b;
|
||||
float a;
|
||||
} vita2d_texture_tint_vertex;
|
||||
|
||||
typedef struct vita2d_texture {
|
||||
SceGxmTexture gxm_tex;
|
||||
SceUID data_UID;
|
||||
@@ -77,6 +89,7 @@ int vita2d_get_clipping_enabled();
|
||||
void vita2d_set_clip_rectangle(int x_min, int y_min, int x_max, int y_max);
|
||||
void vita2d_get_clip_rectangle(int *x_min, int *y_min, int *x_max, int *y_max);
|
||||
void vita2d_set_blend_mode_add(int enable);
|
||||
void vita2d_set_viewport(int x, int y, int width, int height);
|
||||
|
||||
void *vita2d_pool_malloc(unsigned int size);
|
||||
void *vita2d_pool_memalign(unsigned int size, unsigned int alignment);
|
||||
@@ -120,13 +133,14 @@ void vita2d_draw_texture_part_scale_rotate(const vita2d_texture *texture, float
|
||||
void vita2d_draw_texture_tint(const vita2d_texture *texture, float x, float y, unsigned int color);
|
||||
void vita2d_draw_texture_tint_rotate(const vita2d_texture *texture, float x, float y, float rad, unsigned int color);
|
||||
void vita2d_draw_texture_tint_rotate_hotspot(const vita2d_texture *texture, float x, float y, float rad, float center_x, float center_y, unsigned int color);
|
||||
void vita2d_draw_texture_tint_scale(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale, unsigned int color);
|
||||
void vita2d_draw_texture_tint_scale(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale, const float *color);
|
||||
void vita2d_draw_texture_tint_part(const vita2d_texture *texture, float x, float y, float tex_x, float tex_y, float tex_w, float tex_h, unsigned int color);
|
||||
void vita2d_draw_texture_tint_part_scale(const vita2d_texture *texture, float x, float y, float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale, unsigned int color);
|
||||
void vita2d_draw_texture_tint_scale_rotate_hotspot(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale, float rad, float center_x, float center_y, unsigned int color);
|
||||
void vita2d_draw_texture_tint_scale_rotate(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale, float rad, unsigned int color);
|
||||
void vita2d_draw_texture_part_tint_scale_rotate(const vita2d_texture *texture, float x, float y, float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale, float rad, unsigned int color);
|
||||
void vita2d_draw_array_textured(const vita2d_texture *texture, SceGxmPrimitiveType mode, const vita2d_texture_vertex *vertices, size_t count, unsigned int color);
|
||||
void vita2d_draw_array_textured_mat(const vita2d_texture *texture, const vita2d_texture_tint_vertex *vertices, size_t count, float *mat);
|
||||
|
||||
/** ADVANCED **/
|
||||
void vita2d_texture_set_wvp(float x, float y, float width, float height);
|
||||
|
||||
+20
-22
@@ -1,24 +1,22 @@
|
||||
/* Generated by bin2c, do not edit manually */
|
||||
|
||||
/* Contents of file texture_tint_f.gxp */
|
||||
const long int texture_tint_f_gxp_size = 288;
|
||||
// Imported from file 'shader_f.gxp'
|
||||
const unsigned char texture_tint_f_gxp[288] = {
|
||||
0x47, 0x58, 0x50, 0x00, 0x01, 0x04, 0x00, 0x00, 0x1F, 0x01, 0x00, 0x00, 0xEA, 0xFC, 0xA0, 0xCB,
|
||||
0x79, 0x0C, 0xE6, 0xA5, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00,
|
||||
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xF9, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x44, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x40, 0x09, 0x00, 0xF8,
|
||||
0x02, 0x80, 0x99, 0xAF, 0xBC, 0x0D, 0xC0, 0x40, 0x3C, 0x00, 0x04, 0xCF, 0x84, 0x47, 0xA4, 0x08,
|
||||
0x00, 0xBC, 0x19, 0x20, 0x7E, 0x0D, 0x81, 0x40, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
|
||||
0x20, 0x00, 0x00, 0x00, 0x01, 0xE4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x1B, 0x00, 0x00, 0x00, 0x02, 0x04, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x75, 0x54, 0x69, 0x6E, 0x74, 0x43, 0x6F, 0x6C, 0x6F, 0x72, 0x00, 0x74, 0x65, 0x78, 0x00, 0x00
|
||||
0x47,0x58,0x50,0x00,0x01,0x05,0x10,0x03,0x20,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x05,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xc4,0x00,0x00,0x00,0x70,0x00,0x00,0x00,
|
||||
0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x05,0x00,0x00,0x00,
|
||||
0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x74,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x84,0x00,0x00,0x00,0xc0,0x3c,0x03,0x00,
|
||||
0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x04,0x01,0x00,0x01,0x00,0x04,0x00,0x00,0x00,
|
||||
0x00,0xa9,0xd0,0x0e,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x30,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x44,0xfa,0x00,0x00,0x00,0x00,
|
||||
0x40,0x09,0x00,0xf8,0x02,0x80,0x99,0xaf,0xbc,0x0d,0xc0,0x40,0x06,0x82,0xb9,0xaf,
|
||||
0xbc,0x0d,0x80,0x40,0x7c,0x0f,0x04,0x00,0x86,0x47,0xa4,0x10,0x30,0x00,0x00,0x00,
|
||||
0x02,0x04,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x74,0x65,0x78,0x00
|
||||
};
|
||||
const unsigned int texture_tint_f_gxp_size = 288;
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
// Imported from file 'shader_v.gxp'
|
||||
const unsigned char texture_tint_v_gxp[384] = {
|
||||
0x47,0x58,0x50,0x00,0x01,0x05,0x10,0x03,0x7f,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x70,0x00,0x00,0x00,
|
||||
0x0c,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x0b,0x00,0x00,0x00,
|
||||
0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x74,0x00,0x00,0x00,0x70,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0xb0,0x00,0x00,0x00,0xc0,0x3c,0x03,0x00,
|
||||
0x00,0x00,0x00,0x00,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa4,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8c,0x00,0x00,0x00,
|
||||
0x01,0x00,0x00,0x00,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0x0f,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x0a,
|
||||
0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x07,0x44,0xfa,0x01,0x0e,0x01,0x01,0x02,0x00,0x10,0xfa,
|
||||
0x80,0x00,0x08,0x83,0x21,0x25,0x80,0x38,0x01,0x01,0x01,0x01,0x00,0x00,0x14,0xfa,
|
||||
0x02,0x80,0x81,0xaf,0x9c,0x0d,0xc0,0x40,0x0e,0x86,0xb9,0xff,0xbc,0x0d,0xc0,0x40,
|
||||
0x04,0x11,0x49,0xcf,0x80,0x8f,0xb1,0x18,0x02,0x11,0x45,0xcf,0x80,0x8f,0xb1,0x18,
|
||||
0x00,0x11,0x01,0xc0,0x81,0x81,0xb1,0x18,0x01,0xd1,0x42,0xc0,0x81,0x81,0xb1,0x18,
|
||||
0x00,0x00,0x20,0xa0,0x00,0x50,0x27,0xfb,0x0e,0x00,0x00,0x00,0x00,0x00,0x10,0x00,
|
||||
0x40,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x3a,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x01,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
|
||||
0x34,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
|
||||
0x2b,0x00,0x00,0x00,0x01,0xe4,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x61,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x00,0x61,0x54,0x65,0x78,0x63,0x6f,
|
||||
0x6f,0x72,0x64,0x00,0x61,0x43,0x6f,0x6c,0x6f,0x72,0x00,0x77,0x76,0x70,0x00,0x00
|
||||
};
|
||||
const unsigned int texture_tint_v_gxp_size = 384;
|
||||
Vendored
+78
-5
@@ -39,6 +39,7 @@ extern const SceGxmProgram color_v_gxp;
|
||||
extern const SceGxmProgram color_f_gxp;
|
||||
extern const SceGxmProgram texture_v_gxp;
|
||||
extern const SceGxmProgram texture_f_gxp;
|
||||
extern const SceGxmProgram texture_tint_v_gxp;
|
||||
extern const SceGxmProgram texture_tint_f_gxp;
|
||||
|
||||
/* Static variables */
|
||||
@@ -51,6 +52,7 @@ static const SceGxmProgram *const colorVertexProgramGxp = &color_v_gxp;
|
||||
static const SceGxmProgram *const colorFragmentProgramGxp = &color_f_gxp;
|
||||
static const SceGxmProgram *const textureVertexProgramGxp = &texture_v_gxp;
|
||||
static const SceGxmProgram *const textureFragmentProgramGxp = &texture_f_gxp;
|
||||
static const SceGxmProgram *const textureTintVertexProgramGxp = &texture_tint_v_gxp;
|
||||
static const SceGxmProgram *const textureTintFragmentProgramGxp = &texture_tint_f_gxp;
|
||||
|
||||
static int vita2d_initialized = 0;
|
||||
@@ -95,6 +97,7 @@ static SceGxmShaderPatcherId colorVertexProgramId;
|
||||
static SceGxmShaderPatcherId colorFragmentProgramId;
|
||||
static SceGxmShaderPatcherId textureVertexProgramId;
|
||||
static SceGxmShaderPatcherId textureFragmentProgramId;
|
||||
static SceGxmShaderPatcherId textureTintVertexProgramId;
|
||||
static SceGxmShaderPatcherId textureTintFragmentProgramId;
|
||||
|
||||
static SceUID patcherBufferUid;
|
||||
@@ -113,11 +116,12 @@ SceGxmVertexProgram *_vita2d_colorVertexProgram = NULL;
|
||||
SceGxmFragmentProgram *_vita2d_colorFragmentProgram = NULL;
|
||||
SceGxmVertexProgram *_vita2d_textureVertexProgram = NULL;
|
||||
SceGxmFragmentProgram *_vita2d_textureFragmentProgram = NULL;
|
||||
SceGxmVertexProgram *_vita2d_textureTintVertexProgram = NULL;
|
||||
SceGxmFragmentProgram *_vita2d_textureTintFragmentProgram = NULL;
|
||||
const SceGxmProgramParameter *_vita2d_clearClearColorParam = NULL;
|
||||
const SceGxmProgramParameter *_vita2d_colorWvpParam = NULL;
|
||||
const SceGxmProgramParameter *_vita2d_textureWvpParam = NULL;
|
||||
const SceGxmProgramParameter *_vita2d_textureTintColorParam = NULL;
|
||||
const SceGxmProgramParameter *_vita2d_textureTintWvpParam = NULL;
|
||||
|
||||
typedef struct vita2d_fragment_programs {
|
||||
SceGxmFragmentProgram *color;
|
||||
@@ -208,7 +212,7 @@ static void _vita2d_make_fragment_programs(vita2d_fragment_programs *out,
|
||||
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
|
||||
msaa,
|
||||
blend_info,
|
||||
textureVertexProgramGxp,
|
||||
textureTintVertexProgramGxp,
|
||||
&out->textureTint);
|
||||
|
||||
VITA2D_DEBUG("texture_tint sceGxmShaderPatcherCreateFragmentProgram(): 0x%08X\n", err);
|
||||
@@ -442,6 +446,8 @@ static int vita2d_init_internal(unsigned int temp_pool_size, SceGxmMultisampleMo
|
||||
VITA2D_DEBUG("texture_v sceGxmProgramCheck(): 0x%08X\n", err);
|
||||
err = sceGxmProgramCheck(textureFragmentProgramGxp);
|
||||
VITA2D_DEBUG("texture_f sceGxmProgramCheck(): 0x%08X\n", err);
|
||||
err = sceGxmProgramCheck(textureTintVertexProgramGxp);
|
||||
VITA2D_DEBUG("texture_v sceGxmProgramCheck(): 0x%08X\n", err);
|
||||
err = sceGxmProgramCheck(textureTintFragmentProgramGxp);
|
||||
VITA2D_DEBUG("texture_tint_f sceGxmProgramCheck(): 0x%08X\n", err);
|
||||
|
||||
@@ -464,6 +470,9 @@ static int vita2d_init_internal(unsigned int temp_pool_size, SceGxmMultisampleMo
|
||||
err = sceGxmShaderPatcherRegisterProgram(shaderPatcher, textureFragmentProgramGxp, &textureFragmentProgramId);
|
||||
VITA2D_DEBUG("texture_f sceGxmShaderPatcherRegisterProgram(): 0x%08X\n", err);
|
||||
|
||||
err = sceGxmShaderPatcherRegisterProgram(shaderPatcher, textureTintVertexProgramGxp, &textureTintVertexProgramId);
|
||||
VITA2D_DEBUG("texture_v sceGxmShaderPatcherRegisterProgram(): 0x%08X\n", err);
|
||||
|
||||
err = sceGxmShaderPatcherRegisterProgram(shaderPatcher, textureTintFragmentProgramGxp, &textureTintFragmentProgramId);
|
||||
VITA2D_DEBUG("texture_tint_f sceGxmShaderPatcherRegisterProgram(): 0x%08X\n", err);
|
||||
|
||||
@@ -630,6 +639,52 @@ static int vita2d_init_internal(unsigned int temp_pool_size, SceGxmMultisampleMo
|
||||
|
||||
VITA2D_DEBUG("texture sceGxmShaderPatcherCreateVertexProgram(): 0x%08X\n", err);
|
||||
|
||||
const SceGxmProgramParameter *paramTextureTintPositionAttribute = sceGxmProgramFindParameterByName(textureTintVertexProgramGxp, "aPosition");
|
||||
VITA2D_DEBUG("aPosition sceGxmProgramFindParameterByName(): %p\n", paramTextureTintPositionAttribute);
|
||||
|
||||
const SceGxmProgramParameter *paramTextureTintTexcoordAttribute = sceGxmProgramFindParameterByName(textureTintVertexProgramGxp, "aTexcoord");
|
||||
VITA2D_DEBUG("aTexcoord sceGxmProgramFindParameterByName(): %p\n", paramTextureTintTexcoordAttribute);
|
||||
|
||||
const SceGxmProgramParameter *paramTextureTintColorAttribute = sceGxmProgramFindParameterByName(textureTintVertexProgramGxp, "aColor");
|
||||
VITA2D_DEBUG("aColor sceGxmProgramFindParameterByName(): %p\n", paramTextureTintColorAttribute);
|
||||
|
||||
// create texture vertex format
|
||||
SceGxmVertexAttribute textureTintVertexAttributes[3];
|
||||
SceGxmVertexStream textureTintVertexStreams[1];
|
||||
/* x,y,z: 3 float 32 bits */
|
||||
textureTintVertexAttributes[0].streamIndex = 0;
|
||||
textureTintVertexAttributes[0].offset = 0;
|
||||
textureTintVertexAttributes[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
|
||||
textureTintVertexAttributes[0].componentCount = 3; // (x, y, z)
|
||||
textureTintVertexAttributes[0].regIndex = sceGxmProgramParameterGetResourceIndex(paramTextureTintPositionAttribute);
|
||||
/* u,v: 2 floats 32 bits */
|
||||
textureTintVertexAttributes[1].streamIndex = 0;
|
||||
textureTintVertexAttributes[1].offset = 12; // (x, y, z) * 4 = 12 bytes
|
||||
textureTintVertexAttributes[1].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
|
||||
textureTintVertexAttributes[1].componentCount = 2; // (u, v)
|
||||
textureTintVertexAttributes[1].regIndex = sceGxmProgramParameterGetResourceIndex(paramTextureTintTexcoordAttribute);
|
||||
/* r,g,b,a: 4 floats 32 bits */
|
||||
textureTintVertexAttributes[2].streamIndex = 0;
|
||||
textureTintVertexAttributes[2].offset = 20; // (u, v) * 4 = 8 bytes
|
||||
textureTintVertexAttributes[2].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
|
||||
textureTintVertexAttributes[2].componentCount = 4; // (r, g, b, a)
|
||||
textureTintVertexAttributes[2].regIndex = sceGxmProgramParameterGetResourceIndex(paramTextureTintColorAttribute);
|
||||
// 16 bit (short) indices
|
||||
textureTintVertexStreams[0].stride = sizeof(vita2d_texture_tint_vertex);
|
||||
textureTintVertexStreams[0].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT;
|
||||
|
||||
// create texture shaders
|
||||
err = sceGxmShaderPatcherCreateVertexProgram(
|
||||
shaderPatcher,
|
||||
textureTintVertexProgramId,
|
||||
textureTintVertexAttributes,
|
||||
3,
|
||||
textureTintVertexStreams,
|
||||
1,
|
||||
&_vita2d_textureTintVertexProgram);
|
||||
|
||||
VITA2D_DEBUG("texture sceGxmShaderPatcherCreateVertexProgram(): 0x%08X\n", err);
|
||||
|
||||
// Create variations of the fragment program based on blending mode
|
||||
_vita2d_make_fragment_programs(&_vita2d_fragmentPrograms.blend_mode_normal, &blend_info, msaa);
|
||||
_vita2d_make_fragment_programs(&_vita2d_fragmentPrograms.blend_mode_add, &blend_info_add, msaa);
|
||||
@@ -647,8 +702,8 @@ static int vita2d_init_internal(unsigned int temp_pool_size, SceGxmMultisampleMo
|
||||
_vita2d_textureWvpParam = sceGxmProgramFindParameterByName(textureVertexProgramGxp, "wvp");
|
||||
VITA2D_DEBUG("texture wvp sceGxmProgramFindParameterByName(): %p\n", _vita2d_textureWvpParam);
|
||||
|
||||
_vita2d_textureTintColorParam = sceGxmProgramFindParameterByName(textureTintFragmentProgramGxp, "uTintColor");
|
||||
VITA2D_DEBUG("texture wvp sceGxmProgramFindParameterByName(): %p\n", _vita2d_textureWvpParam);
|
||||
_vita2d_textureTintWvpParam = sceGxmProgramFindParameterByName(textureTintVertexProgramGxp, "wvp");
|
||||
VITA2D_DEBUG("texture tint wvp sceGxmProgramFindParameterByName(): %p\n", _vita2d_textureTintWvpParam);
|
||||
|
||||
// Allocate memory for the memory pool
|
||||
pool_size = temp_pool_size;
|
||||
@@ -743,7 +798,8 @@ int vita2d_fini()
|
||||
sceGxmShaderPatcherUnregisterProgram(shaderPatcher, colorVertexProgramId);
|
||||
sceGxmShaderPatcherUnregisterProgram(shaderPatcher, textureFragmentProgramId);
|
||||
sceGxmShaderPatcherUnregisterProgram(shaderPatcher, textureTintFragmentProgramId);
|
||||
sceGxmShaderPatcherUnregisterProgram(shaderPatcher, textureVertexProgramId);
|
||||
sceGxmShaderPatcherUnregisterProgram(shaderPatcher, textureTintVertexProgramId);
|
||||
sceGxmShaderPatcherUnregisterProgram(shaderPatcher, textureVertexProgramId);
|
||||
|
||||
sceGxmShaderPatcherDestroy(shaderPatcher);
|
||||
fragment_usse_free(patcherFragmentUsseUid);
|
||||
@@ -877,12 +933,16 @@ int vita2d_get_clipping_enabled()
|
||||
|
||||
void vita2d_set_clip_rectangle(int x_min, int y_min, int x_max, int y_max)
|
||||
{
|
||||
vita2d_set_viewport(0,0,DISPLAY_WIDTH,DISPLAY_HEIGHT);
|
||||
clipping_enabled = 1;
|
||||
clip_rect_x_min = x_min;
|
||||
clip_rect_y_min = y_min;
|
||||
clip_rect_x_max = x_max;
|
||||
clip_rect_y_max = y_max;
|
||||
// we can only draw during a scene, but we can cache the values since they're not going to have any visible effect till the scene starts anyways
|
||||
if(drawing) {
|
||||
sceGxmSetFrontDepthWriteEnable(_vita2d_context,
|
||||
SCE_GXM_DEPTH_WRITE_DISABLED);
|
||||
// clear the stencil buffer to 0
|
||||
sceGxmSetFrontStencilFunc(
|
||||
_vita2d_context,
|
||||
@@ -903,6 +963,8 @@ void vita2d_set_clip_rectangle(int x_min, int y_min, int x_max, int y_max)
|
||||
0xFF,
|
||||
0xFF);
|
||||
vita2d_draw_rectangle(x_min, y_min, x_max - x_min, y_max - y_min, 0);
|
||||
sceGxmSetFrontDepthWriteEnable(_vita2d_context,
|
||||
SCE_GXM_DEPTH_WRITE_ENABLED);
|
||||
if(clipping_enabled) {
|
||||
// set the stencil function to only accept pixels where the stencil is 1
|
||||
sceGxmSetFrontStencilFunc(
|
||||
@@ -1035,4 +1097,15 @@ void vita2d_set_blend_mode_add(int enable)
|
||||
_vita2d_colorFragmentProgram = in->color;
|
||||
_vita2d_textureFragmentProgram = in->texture;
|
||||
_vita2d_textureTintFragmentProgram = in->textureTint;
|
||||
}
|
||||
|
||||
void vita2d_set_viewport(int x, int y, int width, int height){
|
||||
static float vh = DISPLAY_HEIGHT;
|
||||
float sw = width / 2.;
|
||||
float sh = height / 2.;
|
||||
float x_scale = sw;
|
||||
float x_port = x + sw;
|
||||
float y_scale = -(sh);
|
||||
float y_port = vh - y - sh;
|
||||
sceGxmSetViewport(_vita2d_context, x_port, x_scale, y_port, y_scale, -0.5f, 0.5f);
|
||||
}
|
||||
+127
-27
@@ -271,7 +271,7 @@ static inline void set_texture_program()
|
||||
|
||||
static inline void set_texture_tint_program()
|
||||
{
|
||||
sceGxmSetVertexProgram(_vita2d_context, _vita2d_textureVertexProgram);
|
||||
sceGxmSetVertexProgram(_vita2d_context, _vita2d_textureTintVertexProgram);
|
||||
sceGxmSetFragmentProgram(_vita2d_context, _vita2d_textureTintFragmentProgram);
|
||||
}
|
||||
|
||||
@@ -282,21 +282,11 @@ static inline void set_texture_wvp_uniform()
|
||||
sceGxmSetUniformDataF(vertex_wvp_buffer, _vita2d_textureWvpParam, 0, 16, _vita2d_ortho_matrix);
|
||||
}
|
||||
|
||||
static inline void set_texture_tint_color_uniform(unsigned int color)
|
||||
static inline void set_texture_tint_wvp_uniform()
|
||||
{
|
||||
void *texture_tint_color_buffer;
|
||||
sceGxmReserveFragmentDefaultUniformBuffer(_vita2d_context, &texture_tint_color_buffer);
|
||||
|
||||
float *tint_color = vita2d_pool_memalign(
|
||||
4 * sizeof(float), // RGBA
|
||||
sizeof(float));
|
||||
|
||||
tint_color[0] = ((color >> 8*0) & 0xFF)/255.0f;
|
||||
tint_color[1] = ((color >> 8*1) & 0xFF)/255.0f;
|
||||
tint_color[2] = ((color >> 8*2) & 0xFF)/255.0f;
|
||||
tint_color[3] = ((color >> 8*3) & 0xFF)/255.0f;
|
||||
|
||||
sceGxmSetUniformDataF(texture_tint_color_buffer, _vita2d_textureTintColorParam, 0, 4, tint_color);
|
||||
void *vertex_wvp_buffer;
|
||||
sceGxmReserveVertexDefaultUniformBuffer(_vita2d_context, &vertex_wvp_buffer);
|
||||
sceGxmSetUniformDataF(vertex_wvp_buffer, _vita2d_textureTintWvpParam, 0, 16, _vita2d_ortho_matrix);
|
||||
}
|
||||
|
||||
static inline void draw_texture_generic(const vita2d_texture *texture, float x, float y)
|
||||
@@ -350,7 +340,6 @@ void vita2d_draw_texture_tint(const vita2d_texture *texture, float x, float y, u
|
||||
{
|
||||
set_texture_tint_program();
|
||||
set_texture_wvp_uniform();
|
||||
set_texture_tint_color_uniform(color);
|
||||
draw_texture_generic(texture, x, y);
|
||||
}
|
||||
|
||||
@@ -430,7 +419,6 @@ void vita2d_draw_texture_tint_rotate_hotspot(const vita2d_texture *texture, floa
|
||||
{
|
||||
set_texture_tint_program();
|
||||
set_texture_wvp_uniform();
|
||||
set_texture_tint_color_uniform(color);
|
||||
draw_texture_rotate_hotspot_generic(texture, x, y, rad, center_x, center_y);
|
||||
}
|
||||
|
||||
@@ -474,6 +462,54 @@ static inline void draw_texture_scale_generic(const vita2d_texture *texture, flo
|
||||
sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), 4);
|
||||
}
|
||||
|
||||
static inline void draw_texture_tint_scale_generic(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale, const float *color)
|
||||
{
|
||||
vita2d_texture_tint_vertex *vertices = (vita2d_texture_tint_vertex *)vita2d_pool_memalign(
|
||||
4 * sizeof(vita2d_texture_tint_vertex), // 4 vertices
|
||||
sizeof(vita2d_texture_tint_vertex));
|
||||
|
||||
const float w = x_scale * vita2d_texture_get_width(texture);
|
||||
const float h = y_scale * vita2d_texture_get_height(texture);
|
||||
|
||||
vertices[0].x = x;
|
||||
vertices[0].y = y;
|
||||
vertices[0].z = +0.5f;
|
||||
vertices[0].u = 0.0f;
|
||||
vertices[0].v = 0.0f;
|
||||
|
||||
vertices[1].x = x + w;
|
||||
vertices[1].y = y;
|
||||
vertices[1].z = +0.5f;
|
||||
vertices[1].u = 1.0f;
|
||||
vertices[1].v = 0.0f;
|
||||
|
||||
vertices[2].x = x;
|
||||
vertices[2].y = y + h;
|
||||
vertices[2].z = +0.5f;
|
||||
vertices[2].u = 0.0f;
|
||||
vertices[2].v = 1.0f;
|
||||
|
||||
vertices[3].x = x + w;
|
||||
vertices[3].y = y + h;
|
||||
vertices[3].z = +0.5f;
|
||||
vertices[3].u = 1.0f;
|
||||
vertices[3].v = 1.0f;
|
||||
|
||||
for(int n = 0; n < 4; n++){
|
||||
int k = (n + 2) % 4 ;
|
||||
vertices[n].r = color[4*k+0];
|
||||
vertices[n].g = color[4*k+1];
|
||||
vertices[n].b = color[4*k+2];
|
||||
vertices[n].a = color[4*k+3];
|
||||
}
|
||||
|
||||
// Set the texture to the TEXUNIT0
|
||||
sceGxmSetFragmentTexture(_vita2d_context, 0, &texture->gxm_tex);
|
||||
|
||||
sceGxmSetVertexStream(_vita2d_context, 0, vertices);
|
||||
sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), 4);
|
||||
}
|
||||
|
||||
void vita2d_draw_texture_scale(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale)
|
||||
{
|
||||
set_texture_program();
|
||||
@@ -481,12 +517,11 @@ void vita2d_draw_texture_scale(const vita2d_texture *texture, float x, float y,
|
||||
draw_texture_scale_generic(texture, x, y, x_scale, y_scale);
|
||||
}
|
||||
|
||||
void vita2d_draw_texture_tint_scale(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale, unsigned int color)
|
||||
void vita2d_draw_texture_tint_scale(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale, const float *color)
|
||||
{
|
||||
set_texture_tint_program();
|
||||
set_texture_wvp_uniform();
|
||||
set_texture_tint_color_uniform(color);
|
||||
draw_texture_scale_generic(texture, x, y, x_scale, y_scale);
|
||||
set_texture_tint_wvp_uniform();
|
||||
draw_texture_tint_scale_generic(texture, x, y, x_scale, y_scale, color);
|
||||
}
|
||||
|
||||
|
||||
@@ -546,7 +581,6 @@ void vita2d_draw_texture_tint_part(const vita2d_texture *texture, float x, float
|
||||
{
|
||||
set_texture_tint_program();
|
||||
set_texture_wvp_uniform();
|
||||
set_texture_tint_color_uniform(color);
|
||||
draw_texture_part_generic(texture, x, y, tex_x, tex_y, tex_w, tex_h);
|
||||
}
|
||||
|
||||
@@ -598,6 +632,61 @@ static inline void draw_texture_part_scale_generic(const vita2d_texture *texture
|
||||
sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), 4);
|
||||
}
|
||||
|
||||
static inline void draw_texture_tint_part_scale_generic(const vita2d_texture *texture, float x, float y, float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale, unsigned int color)
|
||||
{
|
||||
vita2d_texture_tint_vertex *vertices = (vita2d_texture_tint_vertex *)vita2d_pool_memalign(
|
||||
4 * sizeof(vita2d_texture_tint_vertex), // 4 vertices
|
||||
sizeof(vita2d_texture_tint_vertex));
|
||||
|
||||
const float w = vita2d_texture_get_width(texture);
|
||||
const float h = vita2d_texture_get_height(texture);
|
||||
|
||||
const float u0 = tex_x/w;
|
||||
const float v0 = tex_y/h;
|
||||
const float u1 = (tex_x+tex_w)/w;
|
||||
const float v1 = (tex_y+tex_h)/h;
|
||||
|
||||
tex_w *= x_scale;
|
||||
tex_h *= y_scale;
|
||||
|
||||
vertices[0].x = x;
|
||||
vertices[0].y = y;
|
||||
vertices[0].z = +0.5f;
|
||||
vertices[0].u = u0;
|
||||
vertices[0].v = v0;
|
||||
|
||||
vertices[1].x = x + tex_w;
|
||||
vertices[1].y = y;
|
||||
vertices[1].z = +0.5f;
|
||||
vertices[1].u = u1;
|
||||
vertices[1].v = v0;
|
||||
|
||||
vertices[2].x = x;
|
||||
vertices[2].y = y + tex_h;
|
||||
vertices[2].z = +0.5f;
|
||||
vertices[2].u = u0;
|
||||
vertices[2].v = v1;
|
||||
|
||||
vertices[3].x = x + tex_w;
|
||||
vertices[3].y = y + tex_h;
|
||||
vertices[3].z = +0.5f;
|
||||
vertices[3].u = u1;
|
||||
vertices[3].v = v1;
|
||||
|
||||
for(int n = 0; n < 4; n++){
|
||||
vertices[n].r = ((color >> 8*0) & 0xFF)/255.0f;
|
||||
vertices[n].g = ((color >> 8*1) & 0xFF)/255.0f;
|
||||
vertices[n].b = ((color >> 8*2) & 0xFF)/255.0f;
|
||||
vertices[n].a = ((color >> 8*3) & 0xFF)/255.0f;
|
||||
}
|
||||
|
||||
// Set the texture to the TEXUNIT0
|
||||
sceGxmSetFragmentTexture(_vita2d_context, 0, &texture->gxm_tex);
|
||||
|
||||
sceGxmSetVertexStream(_vita2d_context, 0, vertices);
|
||||
sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), 4);
|
||||
}
|
||||
|
||||
void vita2d_draw_texture_part_scale(const vita2d_texture *texture, float x, float y, float tex_x, float tex_y, float tex_w, float tex_h, float x_scale, float y_scale)
|
||||
{
|
||||
set_texture_program();
|
||||
@@ -609,8 +698,7 @@ void vita2d_draw_texture_tint_part_scale(const vita2d_texture *texture, float x,
|
||||
{
|
||||
set_texture_tint_program();
|
||||
set_texture_wvp_uniform();
|
||||
set_texture_tint_color_uniform(color);
|
||||
draw_texture_part_scale_generic(texture, x, y, tex_x, tex_y, tex_w, tex_h, x_scale, y_scale);
|
||||
draw_texture_tint_part_scale_generic(texture, x, y, tex_x, tex_y, tex_w, tex_h, x_scale, y_scale, color);
|
||||
}
|
||||
|
||||
static inline void draw_texture_scale_rotate_hotspot_generic(const vita2d_texture *texture, float x, float y, float x_scale, float y_scale, float rad, float center_x, float center_y)
|
||||
@@ -684,7 +772,6 @@ void vita2d_draw_texture_tint_scale_rotate_hotspot(const vita2d_texture *texture
|
||||
{
|
||||
set_texture_tint_program();
|
||||
set_texture_wvp_uniform();
|
||||
set_texture_tint_color_uniform(color);
|
||||
draw_texture_scale_rotate_hotspot_generic(texture, x, y, x_scale, y_scale,
|
||||
rad, center_x, center_y);
|
||||
}
|
||||
@@ -769,7 +856,6 @@ void vita2d_draw_texture_part_tint_scale_rotate(const vita2d_texture *texture, f
|
||||
{
|
||||
set_texture_tint_program();
|
||||
set_texture_wvp_uniform();
|
||||
set_texture_tint_color_uniform(color);
|
||||
draw_texture_part_scale_rotate_generic(texture, x, y,
|
||||
tex_x, tex_y, tex_w, tex_h, x_scale, y_scale, rad);
|
||||
}
|
||||
@@ -778,7 +864,6 @@ void vita2d_draw_array_textured(const vita2d_texture *texture, SceGxmPrimitiveTy
|
||||
{
|
||||
set_texture_tint_program();
|
||||
set_texture_wvp_uniform();
|
||||
set_texture_tint_color_uniform(color);
|
||||
|
||||
sceGxmSetBackPolygonMode(_vita2d_context, SCE_GXM_POLYGON_MODE_TRIANGLE_FILL);
|
||||
|
||||
@@ -788,3 +873,18 @@ void vita2d_draw_array_textured(const vita2d_texture *texture, SceGxmPrimitiveTy
|
||||
sceGxmSetVertexStream(_vita2d_context, 0, vertices);
|
||||
sceGxmDraw(_vita2d_context, mode, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), count);
|
||||
}
|
||||
|
||||
void vita2d_draw_array_textured_mat(const vita2d_texture *texture, const vita2d_texture_tint_vertex *vertices, size_t count, float *mat)
|
||||
{
|
||||
set_texture_tint_program();
|
||||
|
||||
void *vertex_wvp_buffer;
|
||||
sceGxmReserveVertexDefaultUniformBuffer(_vita2d_context, &vertex_wvp_buffer);
|
||||
sceGxmSetUniformDataF(vertex_wvp_buffer, _vita2d_textureWvpParam, 0, 16, mat);
|
||||
|
||||
// Set the texture to the TEXUNIT0
|
||||
sceGxmSetFragmentTexture(_vita2d_context, 0, &texture->gxm_tex);
|
||||
|
||||
sceGxmSetVertexStream(_vita2d_context, 0, vertices);
|
||||
sceGxmDraw(_vita2d_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, vita2d_get_linear_indices(), count);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
|
||||
# Custom for Visual Studio
|
||||
*.cs diff=csharp
|
||||
|
||||
# Standard to msysgit
|
||||
*.doc diff=astextplain
|
||||
*.DOC diff=astextplain
|
||||
*.docx diff=astextplain
|
||||
*.DOCX diff=astextplain
|
||||
*.dot diff=astextplain
|
||||
*.DOT diff=astextplain
|
||||
*.pdf diff=astextplain
|
||||
*.PDF diff=astextplain
|
||||
*.rtf diff=astextplain
|
||||
*.RTF diff=astextplain
|
||||
@@ -0,0 +1,26 @@
|
||||
*.o
|
||||
*.a
|
||||
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# =========================
|
||||
# Operating System Files
|
||||
# =========================
|
||||
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
TARGET := libmathneon
|
||||
SOURCES := source
|
||||
|
||||
LIBS = -lc -lm -lSceGxm_stub -lSceDisplay_stub
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.c))
|
||||
CGFILES := $(foreach dir,$(SHADERS), $(wildcard $(dir)/*.cg))
|
||||
HEADERS := $(CGFILES:.cg=.h)
|
||||
OBJS := $(CFILES:.c=.o)
|
||||
|
||||
PREFIX = arm-vita-eabi
|
||||
CC = $(PREFIX)-gcc
|
||||
AR = $(PREFIX)-gcc-ar
|
||||
CFLAGS = -g -Wl,-q -O2 -ffast-math -mtune=cortex-a9 -mfpu=neon -flto -ftree-vectorize
|
||||
ASFLAGS = $(CFLAGS)
|
||||
|
||||
all: $(TARGET).a
|
||||
|
||||
$(TARGET).a: $(OBJS)
|
||||
$(AR) -rc $@ $^
|
||||
|
||||
clean:
|
||||
@rm -rf $(TARGET).a $(TARGET).elf $(OBJS)
|
||||
|
||||
install: $(TARGET).a
|
||||
@mkdir -p $(VITASDK)/$(PREFIX)/lib/
|
||||
cp $(TARGET).a $(VITASDK)/$(PREFIX)/lib/
|
||||
@mkdir -p $(VITASDK)/$(PREFIX)/include/
|
||||
cp source/math_neon.h $(VITASDK)/$(PREFIX)/include/
|
||||
Vendored
+169
@@ -0,0 +1,169 @@
|
||||
|
||||
Library: MATH-NEON
|
||||
By: Lachlan Tychsen-Smith
|
||||
Licence: MIT (expat)
|
||||
=======================================================================================
|
||||
This project implements the cmath functions and some optimised matrix functions
|
||||
with the aim of increasing the floating point performance of ARM Cortex A-8
|
||||
based platforms. As well as implementing the functions in ARM NEON assembly,
|
||||
they sacrifice error checking and some accuracy to achieve better performance.
|
||||
|
||||
Function Errors:
|
||||
=======================================================================================
|
||||
The measurement and characterisations of the inaccuracies present within these
|
||||
functions is really a field within itself. For the benchmark i provide the
|
||||
maximum absolute, maximum relative and root mean squared error compared to the
|
||||
cmath implementations over the specified range. However these values can be
|
||||
misleading, especially for functions which quickly go to infinity. So its always a
|
||||
good idea to test it within your actual program. In general, this library will not
|
||||
be as accurate as cmath, however for many functions it is close enough to be
|
||||
negilible.
|
||||
|
||||
Notes:
|
||||
=======================================================================================
|
||||
- The *_c functions are c implementations of the *_neon code.
|
||||
- Like cmath, The errors present in the functions are very dependent on the
|
||||
range which your operating in. So you should test them first.
|
||||
- Look in the "math_neon.h" file for discriptions of the functions. In some
|
||||
function files there are also notes on the specific implementation.
|
||||
- The *_neon functions make certain assumptions about the location of arguments
|
||||
that is incompatible with inlining.
|
||||
|
||||
Contact:
|
||||
=======================================================================================
|
||||
Name: Lachlan Tychsen-Smith
|
||||
Email: [email protected]
|
||||
|
||||
PSVITA performances test results:
|
||||
|
||||
RUNFAST: Enabled
|
||||
------------------------------------------------------------------------------------------------------
|
||||
MATRIX FUNCTION TESTS
|
||||
------------------------------------------------------------------------------------------------------
|
||||
matmul2_c =
|
||||
|-7.16, 9.42|
|
||||
|17.86, -10.70|
|
||||
matmul2_neon =
|
||||
|-7.16, 9.42|
|
||||
|17.86, -10.70|
|
||||
matmul2: c=183985 neon=87480 rate=2.10
|
||||
matvec2_c = |-7.16, 17.86|
|
||||
matvec2_neon = |-7.16, 17.86|
|
||||
matvec2: c=98178 neon=66040 rate=1.49
|
||||
matmul3_c =
|
||||
|11.14, -0.78, -3.98|
|
||||
|16.56, 17.96, 23.58|
|
||||
|8.73, -0.18, 1.57|
|
||||
matmul3_neon =
|
||||
|11.14, -0.78, -3.98|
|
||||
|16.56, 17.96, 23.58|
|
||||
|8.73, -0.18, 1.57|
|
||||
matmul3: c=551838 neon=340292 rate=1.62
|
||||
matvec3_c = |11.14, 16.56, 8.73|
|
||||
matvec3_neon = |11.14, 16.56, 8.73|
|
||||
matvec3: c=98178 neon=66040 rate=1.49
|
||||
matmul4_c =
|
||||
|17.91, -23.96, 1.86, 16.53|
|
||||
|4.10, -18.16, 4.17, 29.06|
|
||||
|6.92, -1.60, 3.12, 27.81|
|
||||
|-15.13, -7.46, -17.91, 22.49|
|
||||
matmul4_neon =
|
||||
|17.91, -23.96, 1.86, 16.53|
|
||||
|4.10, -18.16, 4.17, 29.06|
|
||||
|6.92, -1.60, 3.12, 27.81|
|
||||
|-15.13, -7.46, -17.91, 22.49|
|
||||
matmul4: c=1316131 neon=315444 rate=4.17
|
||||
matvec4_c = |17.91, 4.10, 6.92, -15.126419|
|
||||
matvec4_neon = |17.91, 4.10, 6.92, -15.126419|
|
||||
matvec4: c=98178 neon=66040 rate=1.49
|
||||
|
||||
dot2_c = 5.804099
|
||||
dot2_neon = 5.804099
|
||||
dot2: c=291526 neon=307025 rate=0.95
|
||||
normalize2_c = [0.97, 0.24]
|
||||
normalize2_neon = [0.97, 0.24]
|
||||
normalize2: c=1058588 neon=965696 rate=1.10
|
||||
|
||||
dot3_c = -0.817487
|
||||
dot3_neon = -0.817487
|
||||
dot3: c=322094 neon=444834 rate=0.72
|
||||
normalize3_c = [0.50, 0.12, -0.86]
|
||||
normalize3_neon = [0.50, 0.12, -0.86]
|
||||
normalize3: c=1257201 neon=1134375 rate=1.11
|
||||
cross3_c = [-13.16, -17.29, -10.19]
|
||||
cross3_neon = [-13.16, -17.29, -10.19]
|
||||
cross3: c=705298 neon=766477 rate=0.92
|
||||
|
||||
dot4_c = -7.880241
|
||||
dot4_neon = -7.880241
|
||||
dot4: c=414431 neon=506460 rate=0.82
|
||||
normalize4_c = [0.45, 0.11, -0.77, -0.44]
|
||||
normalize4_neon = [0.45, 0.11, -0.77, -0.44]
|
||||
normalize4: c=1410727 neon=1102802 rate=1.28
|
||||
|
||||
------------------------------------------------------------------------------------------------------
|
||||
CMATH FUNCTION TESTS
|
||||
------------------------------------------------------------------------------------------------------
|
||||
Function Range Number ABS Max Error REL Max Error RMS Error Time Rate
|
||||
------------------------------------------------------------------------------------------------------
|
||||
sinf [-3.14, 3.14] 500000 0.00e+00 0.00e+00% 0.00e+00 647042739 x1.00
|
||||
sinf_c [-3.14, 3.14] 500000 7.75e-07 1.00e+02% 4.09e-07 646276691 x1.00
|
||||
sinf_neon [-3.14, 3.14] 500000 1.00e+00 1.00e+02% 7.07e-01 645546381 x1.00
|
||||
cosf [-3.14, 3.14] 500000 0.00e+00 0.00e+00% 0.00e+00 644742077 x1.00
|
||||
cosf_c [-3.14, 3.14] 500000 7.75e-07 6.74e-01% 4.15e-07 643957358 x1.00
|
||||
cosf_neon [-3.14, 3.14] 500000 1.00e+00 1.00e+02% 7.06e-01 643211256 x1.00
|
||||
tanf [-0.79, 0.79] 500000 0.00e+00 0.00e+00% 0.00e+00 642444112 x1.00
|
||||
tanf_c [-0.79, 0.79] 500000 2.98e-06 7.94e-04% 1.31e-06 641628507 x1.00
|
||||
tanf_neon [-0.79, 0.79] 500000 1.00e+00 1.00e+02% nan 640740514 x1.00
|
||||
asinf [-1.00, 1.00] 500000 0.00e+00 0.00e+00% 0.00e+00 639560380 x1.00
|
||||
asinf_c [-1.00, 1.00] 500000 5.54e-05 1.06e-02% nan 638453383 x1.00
|
||||
asinf_neon [-1.00, 1.00] 500000 1.57e+00 1.00e+02% 6.84e-01 637349653 x1.00
|
||||
acosf [-1.00, 1.00] 500000 0.00e+00 0.00e+00% 0.00e+00 636078992 x1.00
|
||||
acosf_c [-1.00, 1.00] 500000 5.56e-05 6.46e-03% nan 634934201 x1.00
|
||||
acosf_neon [-1.00, 1.00] 500000 1.57e+00 1.02e+05% 6.84e-01 633793585 x1.00
|
||||
atanf [-1.00, 1.00] 500000 0.00e+00 0.00e+00% 0.00e+00 632835241 x1.00
|
||||
atanf_c [-1.00, 1.00] 500000 1.67e-04 2.12e-02% 7.40e-05 632142823 x1.00
|
||||
atanf_neon [-1.00, 1.00] 500000 7.85e-01 0.00e+00% nan 631387330 x1.00
|
||||
sinhf [-3.14, 3.14] 500000 0.00e+00 0.00e+00% 0.00e+00 630142014 x1.00
|
||||
sinhf_c [-3.14, 3.14] 500000 1.91e-06 1.52e-01% 1.85e-07 628992714 x1.00
|
||||
sinhf_neon [-3.14, 3.14] 500000 1.15e+01 1.00e+02% 4.55e+00 627998454 x1.00
|
||||
coshf [-3.14, 3.14] 500000 0.00e+00 0.00e+00% 0.00e+00 626869866 x1.00
|
||||
coshf_c [-3.14, 3.14] 500000 9.54e-07 2.38e-05% 1.64e-07 625829657 x1.00
|
||||
coshf_neon [-3.14, 3.14] 500000 1.06e+01 9.14e+01% 3.92e+00 624873969 x1.00
|
||||
tanhf [-3.14, 3.14] 500000 0.00e+00 0.00e+00% 0.00e+00 623689093 x1.00
|
||||
tanhf_c [-3.14, 3.14] 500000 1.20e-05 2.48e-01% 5.48e-06 622547097 x1.00
|
||||
tanhf_neon [-3.14, 3.14] 500000 9.96e-01 1.00e+02% 8.26e-01 621506812 x1.00
|
||||
expf [0.00, 10.00] 500000 0.00e+00 0.00e+00% 0.00e+00 620497304 x1.00
|
||||
expf_c [0.00, 10.00] 500000 9.77e-03 6.15e-05% 1.64e-03 619569554 x1.00
|
||||
expf_neon [0.00, 10.00] 500000 2.20e+04 1.00e+02% 4.92e+03 618761400 x1.00
|
||||
logf [1.00, 1000.00] 500000 0.00e+00 0.00e+00% 0.00e+00 617882765 x1.00
|
||||
logf_c [1.00, 1000.00] 500000 6.20e-06 1.62e-02% 9.83e-07 617087810 x1.00
|
||||
logf_neon [1.00, 1000.00] 500000 9.49e+01 inf% 9.39e+01 616388420 x1.00
|
||||
log10f [1.00, 1000.00] 500000 0.00e+00 0.00e+00% 0.00e+00 615405364 x1.00
|
||||
log10f_c [1.00, 1000.00] 500000 2.86e-06 6.68e-03% 4.79e-07 614442585 x1.00
|
||||
log10f_neon [1.00, 1000.00] 500000 4.12e+01 inf% 4.07e+01 613671782 x1.00
|
||||
floorf [1.00, 1000.00] 5000000 0.00e+00 0.00e+00% 0.00e+00 611113689 x1.00
|
||||
floorf_c [1.00, 1000.00] 5000000 0.00e+00 0.00e+00% 0.00e+00 608159325 x1.00
|
||||
floorf_neon [1.00, 1000.00] 5000000 2.00e+00 2.00e+02% 1.42e-02 604769008 x1.01
|
||||
ceilf [1.00, 1000.00] 5000000 0.00e+00 0.00e+00% 0.00e+00 601342443 x1.00
|
||||
ceilf_c [1.00, 1000.00] 5000000 0.00e+00 0.00e+00% 0.00e+00 598387998 x1.00
|
||||
ceilf_neon [1.00, 1000.00] 5000000 2.00e+00 1.00e+02% 1.02e+00 594959710 x1.01
|
||||
fabsf [1.00, 1000.00] 5000000 0.00e+00 0.00e+00% 0.00e+00 592068236 x1.00
|
||||
fabsf_c [1.00, 1000.00] 5000000 0.00e+00 0.00e+00% 0.00e+00 589808748 x1.00
|
||||
fabsf_neon [1.00, 1000.00] 5000000 0.00e+00 0.00e+00% 0.00e+00 587712180 x1.01
|
||||
sqrtf [1.00, 1000.00] 500000 0.00e+00 0.00e+00% 0.00e+00 586496654 x1.00
|
||||
sqrtf_c [1.00, 1000.00] 500000 2.33e-04 1.06e-03% 8.69e-05 585470866 x1.00
|
||||
sqrtf_neon [1.00, 1000.00] 500000 0.00e+00 0.00e+00% nan 584594551 x1.00
|
||||
invsqrtf [1.00, 1000.00] 500000 0.00e+00 0.00e+00% 0.00e+00 583492213 x1.00
|
||||
invsqrtf_c [1.00, 1000.00] 500000 4.35e-06 4.78e-04% 2.00e-07 582448164 x1.00
|
||||
invsqrtf_neon [1.00, 1000.00] 500000 0.00e+00 0.00e+00% nan 581642365 x1.00
|
||||
atan2f [0.10, 10.00] 10000 0.00e+00 0.00e+00% 0.00e+00 83594269 x1.00
|
||||
atan2f_c [0.10, 10.00] 10000 1.73e-04 2.23e-02% 0.00e+00 85383651 x0.98
|
||||
atan2f_neon [0.10, 10.00] 10000 0.00e+00 0.00e+00% 0.00e+00 87387055 x0.96
|
||||
powf [1.00, 10.00] 10000 0.00e+00 0.00e+00% 0.00e+00 93430489 x1.00
|
||||
powf_c [1.00, 10.00] 10000 1.08e+05 4.37e-03% 0.00e+00 96726976 x0.97
|
||||
powf_neon [1.00, 10.00] 10000 9.97e+09 1.00e+02% 0.00e+00 100185753 x0.93
|
||||
fmodf [1.00, 10.00] 10000 0.00e+00 0.00e+00% 0.00e+00 101653673 x1.00
|
||||
fmodf_c [1.00, 10.00] 10000 9.90e+00 8.06e-02% 0.00e+00 103177551 x0.99
|
||||
fmodf_neon [1.00, 10.00] 10000 9.99e+00 1.00e+02% 0.00e+00 104771240 x0.97
|
||||
|
||||
Vendored
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "math_neon.h"
|
||||
|
||||
/*
|
||||
Test func : acosf(x)
|
||||
Test Range: -1.0 < x < 1.0
|
||||
Peak Error: ~0.005%
|
||||
RMS Error: ~0.001%
|
||||
*/
|
||||
|
||||
const float __acosf_pi_2 = M_PI_2;
|
||||
|
||||
float acosf_c(float x)
|
||||
{
|
||||
return __acosf_pi_2 - asinf_c(x);
|
||||
}
|
||||
|
||||
|
||||
float acosf_neon_hfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asinf_neon_hfp(x);
|
||||
asm volatile (
|
||||
"vdup.f32 d1, %0 \n\t" //d1 = {pi/2, pi/2};
|
||||
"vsub.f32 d0, d1, d0 \n\t" //d0 = d1 - d0;
|
||||
::"r"(__acosf_pi_2):
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
float acosf_neon_sfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile ("vmov.f32 s0, r0 \n\t");
|
||||
acosf_neon_hfp(x);
|
||||
asm volatile ("vmov.f32 r0, s0 \n\t");
|
||||
#else
|
||||
return acosf_c(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
Vendored
+183
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "math_neon.h"
|
||||
|
||||
/*
|
||||
Test func : asinf(x)
|
||||
Test Range: -1.0 < x < 1.0
|
||||
Peak Error: ~0.005%
|
||||
RMS Error: ~0.001%
|
||||
*/
|
||||
|
||||
|
||||
const float __asinf_lut[4] = {
|
||||
0.105312459675071, //p7
|
||||
0.169303418571894, //p3
|
||||
0.051599985887214, //p5
|
||||
0.999954835104825 //p1
|
||||
};
|
||||
|
||||
const float __asinf_pi_2 = M_PI_2;
|
||||
|
||||
float asinf_c(float x)
|
||||
{
|
||||
|
||||
float a, b, c, d, r, ax;
|
||||
int m;
|
||||
|
||||
union {
|
||||
float f;
|
||||
int i;
|
||||
} xx;
|
||||
|
||||
ax = fabs(x);
|
||||
d = 0.5;
|
||||
d = d - ax*0.5;
|
||||
|
||||
//fast invsqrt approx
|
||||
xx.f = d;
|
||||
xx.i = 0x5F3759DF - (xx.i >> 1); //VRSQRTE
|
||||
c = d * xx.f;
|
||||
b = (3.0f - c * xx.f) * 0.5; //VRSQRTS
|
||||
xx.f = xx.f * b;
|
||||
c = d * xx.f;
|
||||
b = (3.0f - c * xx.f) * 0.5;
|
||||
xx.f = xx.f * b;
|
||||
|
||||
//fast inverse approx
|
||||
d = xx.f;
|
||||
m = 0x3F800000 - (xx.i & 0x7F800000);
|
||||
xx.i = xx.i + m;
|
||||
xx.f = 1.41176471f - 0.47058824f * xx.f;
|
||||
xx.i = xx.i + m;
|
||||
b = 2.0 - xx.f * d;
|
||||
xx.f = xx.f * b;
|
||||
b = 2.0 - xx.f * d;
|
||||
xx.f = xx.f * b;
|
||||
|
||||
//if |x|>0.5 -> x = sqrt((1-x)/2)
|
||||
xx.f = xx.f - ax;
|
||||
a = (ax > 0.5f);
|
||||
d = __asinf_pi_2 * a;
|
||||
c = 1.0f - 3.0f * a;
|
||||
ax = ax + xx.f * a;
|
||||
|
||||
//polynomial evaluation
|
||||
xx.f = ax * ax;
|
||||
a = (__asinf_lut[0] * ax) * xx.f + (__asinf_lut[2] * ax);
|
||||
b = (__asinf_lut[1] * ax) * xx.f + (__asinf_lut[3] * ax);
|
||||
xx.f = xx.f * xx.f;
|
||||
r = b + a * xx.f;
|
||||
r = d + c * r;
|
||||
|
||||
a = r + r;
|
||||
b = (x < 0.0f);
|
||||
r = r - a * b;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
float asinf_neon_hfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
|
||||
"vdup.f32 d0, d0[0] \n\t" //d0 = {x, x};
|
||||
"vdup.f32 d4, %1 \n\t" //d4 = {pi/2, pi/2};
|
||||
"vmov.f32 d6, d0 \n\t" //d6 = d0;
|
||||
"vabs.f32 d0, d0 \n\t" //d0 = fabs(d0) ;
|
||||
|
||||
"vmov.f32 d5, #0.5 \n\t" //d5 = 0.5;
|
||||
"vmls.f32 d5, d0, d5 \n\t" //d5 = d5 - d0*d5;
|
||||
|
||||
//fast invsqrt approx
|
||||
"vmov.f32 d1, d5 \n\t" //d1 = d5
|
||||
"vrsqrte.f32 d5, d5 \n\t" //d5 = ~ 1.0 / sqrt(d5)
|
||||
"vmul.f32 d2, d5, d1 \n\t" //d2 = d5 * d1
|
||||
"vrsqrts.f32 d3, d2, d5 \n\t" //d3 = (3 - d5 * d2) / 2
|
||||
"vmul.f32 d5, d5, d3 \n\t" //d5 = d5 * d3
|
||||
"vmul.f32 d2, d5, d1 \n\t" //d2 = d5 * d1
|
||||
"vrsqrts.f32 d3, d2, d5 \n\t" //d3 = (3 - d5 * d3) / 2
|
||||
"vmul.f32 d5, d5, d3 \n\t" //d5 = d5 * d3
|
||||
|
||||
//fast reciporical approximation
|
||||
"vrecpe.f32 d1, d5 \n\t" //d1 = ~ 1 / d5;
|
||||
"vrecps.f32 d2, d1, d5 \n\t" //d2 = 2.0 - d1 * d5;
|
||||
"vmul.f32 d1, d1, d2 \n\t" //d1 = d1 * d2;
|
||||
"vrecps.f32 d2, d1, d5 \n\t" //d2 = 2.0 - d1 * d5;
|
||||
"vmul.f32 d5, d1, d2 \n\t" //d5 = d1 * d2;
|
||||
|
||||
//if |x| > 0.5 -> ax = sqrt((1-ax)/2), r = pi/2
|
||||
"vsub.f32 d5, d0, d5 \n\t" //d5 = d0 - d5;
|
||||
"vmov.f32 d2, #0.5 \n\t" //d2 = 0.5;
|
||||
"vcgt.f32 d3, d0, d2 \n\t" //d3 = (d0 > d2);
|
||||
"vmov.f32 d1, #3.0 \n\t" //d5 = 3.0;
|
||||
"vshr.u32 d3, #31 \n\t" //d3 = d3 >> 31;
|
||||
"vmov.f32 d16, #1.0 \n\t" //d16 = 1.0;
|
||||
"vcvt.f32.u32 d3, d3 \n\t" //d3 = (float) d3;
|
||||
"vmls.f32 d0, d5, d3[0] \n\t" //d0 = d0 - d5 * d3[0];
|
||||
"vmul.f32 d7, d4, d3[0] \n\t" //d7 = d5 * d4;
|
||||
"vmls.f32 d16, d1, d3[0] \n\t" //d16 = d16 - d1 * d3;
|
||||
|
||||
//polynomial:
|
||||
"vmul.f32 d2, d0, d0 \n\t" //d2 = d0*d0 = {ax^2, ax^2}
|
||||
"vld1.32 {d4, d5}, [%0] \n\t" //d4 = {p7, p3}, d5 = {p5, p1}
|
||||
"vmul.f32 d3, d2, d2 \n\t" //d3 = d2*d2 = {x^4, x^4}
|
||||
"vmul.f32 q0, q2, d0[0] \n\t" //q0 = q2 * d0[0] = {p7x, p3x, p5x, p1x}
|
||||
"vmla.f32 d1, d0, d2[0] \n\t" //d1 = d1 + d0*d2[0] = {p5x + p7x^3, p1x + p3x^3}
|
||||
"vmla.f32 d1, d3, d1[0] \n\t" //d1 = d1 + d3*d1[0] = {..., p1x + p3x^3 + p5x^5 + p7x^7}
|
||||
|
||||
"vmla.f32 d7, d1, d16 \n\t" //d7 = d7 + d1*d16
|
||||
|
||||
"vadd.f32 d2, d7, d7 \n\t" //d2 = d7 + d7
|
||||
"vclt.f32 d3, d6, #0 \n\t" //d3 = (d6 < 0)
|
||||
"vshr.u32 d3, #31 \n\t" //d3 = d3 >> 31;
|
||||
"vcvt.f32.u32 d3, d3 \n\t" //d3 = (float) d3
|
||||
"vmls.f32 d7, d2, d3[0] \n\t" //d7 = d7 - d2 * d3[0];
|
||||
|
||||
"vmov.f32 s0, s15 \n\t" //s0 = s3
|
||||
|
||||
:: "r"(__asinf_lut), "r"(__asinf_pi_2)
|
||||
: "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
float asinf_neon_sfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile ("vmov.f32 s0, r0 \n\t");
|
||||
asinf_neon_hfp(x);
|
||||
asm volatile ("vmov.f32 r0, s0 \n\t");
|
||||
#else
|
||||
return asinf_c(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Vendored
+170
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "math_neon.h"
|
||||
|
||||
const float __atan2f_lut[4] = {
|
||||
-0.0443265554792128, //p7
|
||||
-0.3258083974640975, //p3
|
||||
+0.1555786518463281, //p5
|
||||
+0.9997878412794807 //p1
|
||||
};
|
||||
|
||||
const float __atan2f_pi_2 = M_PI_2;
|
||||
|
||||
float atan2f_c(float y, float x)
|
||||
{
|
||||
float a, b, c, r, xx;
|
||||
int m;
|
||||
union {
|
||||
float f;
|
||||
int i;
|
||||
} xinv;
|
||||
|
||||
//fast inverse approximation (2x newton)
|
||||
xx = fabs(x);
|
||||
xinv.f = xx;
|
||||
m = 0x3F800000 - (xinv.i & 0x7F800000);
|
||||
xinv.i = xinv.i + m;
|
||||
xinv.f = 1.41176471f - 0.47058824f * xinv.f;
|
||||
xinv.i = xinv.i + m;
|
||||
b = 2.0 - xinv.f * xx;
|
||||
xinv.f = xinv.f * b;
|
||||
b = 2.0 - xinv.f * xx;
|
||||
xinv.f = xinv.f * b;
|
||||
|
||||
c = fabs(y * xinv.f);
|
||||
|
||||
//fast inverse approximation (2x newton)
|
||||
xinv.f = c;
|
||||
m = 0x3F800000 - (xinv.i & 0x7F800000);
|
||||
xinv.i = xinv.i + m;
|
||||
xinv.f = 1.41176471f - 0.47058824f * xinv.f;
|
||||
xinv.i = xinv.i + m;
|
||||
b = 2.0 - xinv.f * c;
|
||||
xinv.f = xinv.f * b;
|
||||
b = 2.0 - xinv.f * c;
|
||||
xinv.f = xinv.f * b;
|
||||
|
||||
//if |x| > 1.0 -> ax = -1/ax, r = pi/2
|
||||
xinv.f = xinv.f + c;
|
||||
a = (c > 1.0f);
|
||||
c = c - a * xinv.f;
|
||||
r = a * __atan2f_pi_2;
|
||||
|
||||
//polynomial evaluation
|
||||
xx = c * c;
|
||||
a = (__atan2f_lut[0] * c) * xx + (__atan2f_lut[2] * c);
|
||||
b = (__atan2f_lut[1] * c) * xx + (__atan2f_lut[3] * c);
|
||||
xx = xx * xx;
|
||||
r = r + a * xx;
|
||||
r = r + b;
|
||||
|
||||
//determine quadrant and test for small x.
|
||||
b = M_PI;
|
||||
b = b - 2.0f * r;
|
||||
r = r + (x < 0.0f) * b;
|
||||
b = (fabs(x) < 0.000001f);
|
||||
c = !b;
|
||||
r = c * r;
|
||||
r = r + __atan2f_pi_2 * b;
|
||||
b = r + r;
|
||||
r = r - (y < 0.0f) * b;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
float atan2f_neon_hfp(float y, float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
|
||||
"vdup.f32 d17, d0[1] \n\t" //d17 = {x, x};
|
||||
"vdup.f32 d16, d0[0] \n\t" //d16 = {y, y};
|
||||
|
||||
//1.0 / x
|
||||
"vrecpe.f32 d18, d17 \n\t" //d16 = ~ 1 / d1;
|
||||
"vrecps.f32 d19, d18, d17 \n\t" //d17 = 2.0 - d16 * d1;
|
||||
"vmul.f32 d18, d18, d19 \n\t" //d16 = d16 * d17;
|
||||
"vrecps.f32 d19, d18, d17 \n\t" //d17 = 2.0 - d16 * d1;
|
||||
"vmul.f32 d18, d18, d19 \n\t" //d16 = d16 * d17;
|
||||
|
||||
//y * (1.0 /x)
|
||||
"vmul.f32 d0, d16, d18 \n\t" //d0 = d16 * d18;
|
||||
|
||||
|
||||
"vdup.f32 d4, %1 \n\t" //d4 = {pi/2, pi/2};
|
||||
"vmov.f32 d6, d0 \n\t" //d6 = d0;
|
||||
"vabs.f32 d0, d0 \n\t" //d0 = fabs(d0) ;
|
||||
|
||||
//fast reciporical approximation
|
||||
"vrecpe.f32 d1, d0 \n\t" //d1 = ~ 1 / d0;
|
||||
"vrecps.f32 d2, d1, d0 \n\t" //d2 = 2.0 - d1 * d0;
|
||||
"vmul.f32 d1, d1, d2 \n\t" //d1 = d1 * d2;
|
||||
"vrecps.f32 d2, d1, d0 \n\t" //d2 = 2.0 - d1 * d0;
|
||||
"vmul.f32 d1, d1, d2 \n\t" //d1 = d1 * d2;
|
||||
|
||||
//if |x| > 1.0 -> ax = 1/ax, r = pi/2
|
||||
"vadd.f32 d1, d1, d0 \n\t" //d1 = d1 + d0;
|
||||
"vmov.f32 d2, #1.0 \n\t" //d2 = 1.0;
|
||||
"vcgt.f32 d3, d0, d2 \n\t" //d3 = (d0 > d2);
|
||||
"vcvt.f32.u32 d3, d3 \n\t" //d3 = (float) d3;
|
||||
"vmls.f32 d0, d1, d3 \n\t" //d0 = d0 - d1 * d3;
|
||||
"vmul.f32 d7, d3, d4 \n\t" //d7 = d3 * d4;
|
||||
|
||||
//polynomial:
|
||||
"vmul.f32 d2, d0, d0 \n\t" //d2 = d0*d0 = {ax^2, ax^2}
|
||||
"vld1.32 {d4, d5}, [%0] \n\t" //d4 = {p7, p3}, d5 = {p5, p1}
|
||||
"vmul.f32 d3, d2, d2 \n\t" //d3 = d2*d2 = {x^4, x^4}
|
||||
"vmul.f32 q0, q2, d0[0] \n\t" //q0 = q2 * d0[0] = {p7x, p3x, p5x, p1x}
|
||||
"vmla.f32 d1, d0, d2[0] \n\t" //d1 = d1 + d0*d2[0] = {p5x + p7x^3, p1x + p3x^3}
|
||||
"vmla.f32 d1, d3, d1[0] \n\t" //d1 = d1 + d3*d1[0] = {..., p1x + p3x^3 + p5x^5 + p7x^7}
|
||||
"vadd.f32 d1, d1, d7 \n\t" //d1 = d1 + d7
|
||||
|
||||
"vadd.f32 d2, d1, d1 \n\t" //d2 = d1 + d1
|
||||
"vclt.f32 d3, d6, #0 \n\t" //d3 = (d6 < 0)
|
||||
"vcvt.f32.u32 d3, d3 \n\t" //d3 = (float) d3
|
||||
"vmls.f32 d1, d3, d2 \n\t" //d1 = d1 - d2 * d3;
|
||||
|
||||
"vmov.f32 s0, s3 \n\t" //s0 = s3
|
||||
|
||||
:: "r"(__atan2f_lut), "r"(__atan2f_pi_2)
|
||||
: "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
float atan2f_neon_sfp(float x, float y)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile ("vmov.f32 s0, r0 \n\t");
|
||||
asm volatile ("vmov.f32 s1, r1 \n\t");
|
||||
atan2f_neon_hfp(x, y);
|
||||
asm volatile ("vmov.f32 r0, s0 \n\t");
|
||||
#else
|
||||
return atan2f_c(y, x);
|
||||
#endif
|
||||
};
|
||||
Vendored
+149
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "math_neon.h"
|
||||
|
||||
const float __atanf_lut[4] = {
|
||||
-0.0443265554792128, //p7
|
||||
-0.3258083974640975, //p3
|
||||
+0.1555786518463281, //p5
|
||||
+0.9997878412794807 //p1
|
||||
};
|
||||
|
||||
const float __atanf_pi_2 = M_PI_2;
|
||||
|
||||
float atanf_c(float x)
|
||||
{
|
||||
|
||||
float a, b, r, xx;
|
||||
int m;
|
||||
|
||||
union {
|
||||
float f;
|
||||
int i;
|
||||
} xinv, ax;
|
||||
|
||||
ax.f = fabs(x);
|
||||
|
||||
//fast inverse approximation (2x newton)
|
||||
xinv.f = ax.f;
|
||||
m = 0x3F800000 - (xinv.i & 0x7F800000);
|
||||
xinv.i = xinv.i + m;
|
||||
xinv.f = 1.41176471f - 0.47058824f * xinv.f;
|
||||
xinv.i = xinv.i + m;
|
||||
b = 2.0 - xinv.f * ax.f;
|
||||
xinv.f = xinv.f * b;
|
||||
b = 2.0 - xinv.f * ax.f;
|
||||
xinv.f = xinv.f * b;
|
||||
|
||||
//if |x| > 1.0 -> ax = -1/ax, r = pi/2
|
||||
xinv.f = xinv.f + ax.f;
|
||||
a = (ax.f > 1.0f);
|
||||
ax.f = ax.f - a * xinv.f;
|
||||
r = a * __atanf_pi_2;
|
||||
|
||||
//polynomial evaluation
|
||||
xx = ax.f * ax.f;
|
||||
a = (__atanf_lut[0] * ax.f) * xx + (__atanf_lut[2] * ax.f);
|
||||
b = (__atanf_lut[1] * ax.f) * xx + (__atanf_lut[3] * ax.f);
|
||||
xx = xx * xx;
|
||||
b = b + a * xx;
|
||||
r = r + b;
|
||||
|
||||
//if x < 0 -> r = -r
|
||||
a = 2 * r;
|
||||
b = (x < 0.0f);
|
||||
r = r - a * b;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
float atanf_neon_hfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
|
||||
"vdup.f32 d0, d0[0] \n\t" //d0 = {x, x};
|
||||
|
||||
"vdup.f32 d4, %1 \n\t" //d4 = {pi/2, pi/2};
|
||||
"vmov.f32 d6, d0 \n\t" //d6 = d0;
|
||||
"vabs.f32 d0, d0 \n\t" //d0 = fabs(d0) ;
|
||||
|
||||
//fast reciporical approximation
|
||||
"vrecpe.f32 d1, d0 \n\t" //d1 = ~ 1 / d0;
|
||||
"vrecps.f32 d2, d1, d0 \n\t" //d2 = 2.0 - d1 * d0;
|
||||
"vmul.f32 d1, d1, d2 \n\t" //d1 = d1 * d2;
|
||||
"vrecps.f32 d2, d1, d0 \n\t" //d2 = 2.0 - d1 * d0;
|
||||
"vmul.f32 d1, d1, d2 \n\t" //d1 = d1 * d2;
|
||||
|
||||
|
||||
//if |x| > 1.0 -> ax = -1/ax, r = pi/2
|
||||
"vadd.f32 d1, d1, d0 \n\t" //d1 = d1 + d0;
|
||||
"vmov.f32 d2, #1.0 \n\t" //d2 = 1.0;
|
||||
"vcgt.f32 d3, d0, d2 \n\t" //d3 = (d0 > d2);
|
||||
"vshr.u32 d3, #31 \n\t" //d3 = (d0 > d2);
|
||||
"vcvt.f32.u32 d3, d3 \n\t" //d5 = (float) d3;
|
||||
"vmls.f32 d0, d1, d3[0] \n\t" //d0 = d0 - d1 * d3[0];
|
||||
"vmul.f32 d7, d4, d3[0] \n\t" //d7 = d5 * d4;
|
||||
|
||||
//polynomial:
|
||||
"vmul.f32 d2, d0, d0 \n\t" //d2 = d0*d0 = {ax^2, ax^2}
|
||||
"vld1.32 {d4, d5}, [%0] \n\t" //d4 = {p7, p3}, d5 = {p5, p1}
|
||||
"vmul.f32 d3, d2, d2 \n\t" //d3 = d2*d2 = {x^4, x^4}
|
||||
"vmul.f32 q0, q2, d0[0] \n\t" //q0 = q2 * d0[0] = {p7x, p3x, p5x, p1x}
|
||||
"vmla.f32 d1, d0, d2[0] \n\t" //d1 = d1 + d0*d2[0] = {p5x + p7x^3, p1x + p3x^3}
|
||||
"vmla.f32 d1, d3, d1[0] \n\t" //d1 = d1 + d3*d1[0] = {..., p1x + p3x^3 + p5x^5 + p7x^7}
|
||||
"vadd.f32 d1, d1, d7 \n\t" //d1 = d1 + d7
|
||||
|
||||
"vadd.f32 d2, d1, d1 \n\t" //d2 = d1 + d1
|
||||
"vclt.f32 d3, d6, #0 \n\t" //d3 = (d6 < 0)
|
||||
"vshr.u32 d3, #31 \n\t" //d3 = (d0 > d2);
|
||||
"vcvt.f32.u32 d3, d3 \n\t" //d3 = (float) d3
|
||||
"vmls.f32 d1, d3, d2 \n\t" //d1 = d1 - d2 * d3;
|
||||
|
||||
"vmov.f32 s0, s3 \n\t" //s0 = s3
|
||||
|
||||
:: "r"(__atanf_lut), "r"(__atanf_pi_2)
|
||||
: "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7"
|
||||
);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
float atanf_neon_sfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile ("vdup.f32 d0, r0 \n\t");
|
||||
atanf_neon_hfp(x);
|
||||
asm volatile ("vmov.f32 r0, s0 \n\t");
|
||||
#else
|
||||
return atanf_c(x);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
Vendored
+71
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Assumes the floating point value |x| < 2147483648
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "math_neon.h"
|
||||
|
||||
float ceilf_c(float x)
|
||||
{
|
||||
int n;
|
||||
float r;
|
||||
n = (int) x;
|
||||
r = (float) n;
|
||||
r = r + (x > r);
|
||||
return r;
|
||||
}
|
||||
|
||||
float ceilf_neon_hfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
|
||||
"vcvt.s32.f32 d1, d0 \n\t" //d1 = (int) d0;
|
||||
"vcvt.f32.s32 d1, d1 \n\t" //d1 = (float) d1;
|
||||
"vcgt.f32 d0, d0, d1 \n\t" //d0 = (d0 > d1);
|
||||
"vshr.u32 d0, #31 \n\t" //d0 = d0 >> 31;
|
||||
"vcvt.f32.u32 d0, d0 \n\t" //d0 = (float) d0;
|
||||
"vadd.f32 d0, d1, d0 \n\t" //d0 = d1 + d0;
|
||||
|
||||
::: "d0", "d1"
|
||||
);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
float ceilf_neon_sfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile ("vmov.f32 s0, r0 \n\t");
|
||||
ceilf_neon_hfp(x);
|
||||
asm volatile ("vmov.f32 r0, s0 \n\t");
|
||||
#else
|
||||
return ceilf_c(x);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
Vendored
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "math_neon.h"
|
||||
|
||||
float cosf_c(float x)
|
||||
{
|
||||
return sinf_c(x + M_PI_2);
|
||||
}
|
||||
|
||||
float cosf_neon_hfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
float xx = x + M_PI_2;
|
||||
return sinf_neon_hfp(xx);
|
||||
#endif
|
||||
}
|
||||
|
||||
float cosf_neon_sfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile ("vdup.f32 d0, r0 \n\t");
|
||||
cosf_neon_hfp(x);
|
||||
asm volatile ("vmov.f32 r0, s0 \n\t");
|
||||
#else
|
||||
return cosf_c(x);
|
||||
#endif
|
||||
};
|
||||
|
||||
Vendored
+120
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "math_neon.h"
|
||||
|
||||
const float __coshf_rng[2] = {
|
||||
1.442695041f,
|
||||
0.693147180f
|
||||
};
|
||||
|
||||
const float __coshf_lut[16] = {
|
||||
0.00019578093328483123, //p7
|
||||
0.00019578093328483123, //p7
|
||||
0.0014122663401803872, //p6
|
||||
0.0014122663401803872, //p6
|
||||
0.008336936973260111, //p5
|
||||
0.008336936973260111, //p5
|
||||
0.04165989275009526, //p4
|
||||
0.04165989275009526, //p4
|
||||
0.16666570253074878, //p3
|
||||
0.16666570253074878, //p3
|
||||
0.5000006143673624, //p2
|
||||
0.5000006143673624, //p2
|
||||
1.000000059694879, //p1
|
||||
1.000000059694879, //p1
|
||||
0.9999999916728642, //p0
|
||||
0.9999999916728642 //p0
|
||||
};
|
||||
|
||||
|
||||
float coshf_c(float x)
|
||||
{
|
||||
float a, b, xx;
|
||||
xx = -x;
|
||||
a = expf_c(x);
|
||||
b = expf_c(xx);
|
||||
a = a * 0.5f;
|
||||
a = a + 0.5f * b;
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
float coshf_neon_hfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
"vdup.f32 d0, d0[0] \n\t" //d0 = {x, x}
|
||||
"fnegs s1, s1 \n\t" //s1 = -s1
|
||||
|
||||
//Range Reduction:
|
||||
"vld1.32 d2, [%0] \n\t" //d2 = {invrange, range}
|
||||
"vld1.32 {d16, d17}, [%1]! \n\t"
|
||||
"vmul.f32 d6, d0, d2[0] \n\t" //d6 = d0 * d2[0]
|
||||
"vcvt.s32.f32 d6, d6 \n\t" //d6 = (int) d6
|
||||
"vld1.32 {d18}, [%1]! \n\t"
|
||||
"vcvt.f32.s32 d1, d6 \n\t" //d1 = (float) d6
|
||||
"vld1.32 {d19}, [%1]! \n\t"
|
||||
"vmls.f32 d0, d1, d2[1] \n\t" //d0 = d0 - d1 * d2[1]
|
||||
"vld1.32 {d20}, [%1]! \n\t"
|
||||
|
||||
//polynomial:
|
||||
"vmla.f32 d17, d16, d0 \n\t" //d17 = d17 + d16 * d0;
|
||||
"vld1.32 {d21}, [%1]! \n\t"
|
||||
"vmla.f32 d18, d17, d0 \n\t" //d18 = d18 + d17 * d0;
|
||||
"vld1.32 {d22}, [%1]! \n\t"
|
||||
"vmla.f32 d19, d18, d0 \n\t" //d19 = d19 + d18 * d0;
|
||||
"vld1.32 {d23}, [%1]! \n\t"
|
||||
"vmla.f32 d20, d19, d0 \n\t" //d20 = d20 + d19 * d0;
|
||||
"vmla.f32 d21, d20, d0 \n\t" //d21 = d21 + d20 * d0;
|
||||
"vmla.f32 d22, d21, d0 \n\t" //d22 = d22 + d21 * d0;
|
||||
"vmla.f32 d23, d22, d0 \n\t" //d23 = d23 + d22 * d0;
|
||||
|
||||
//multiply by 2 ^ m
|
||||
"vshl.i32 d6, d6, #23 \n\t" //d6 = d6 << 23
|
||||
"vadd.i32 d0, d23, d6 \n\t" //d0 = d22 + d6
|
||||
|
||||
"vdup.f32 d2, d0[1] \n\t" //d2 = s1
|
||||
"vmov.f32 d1, #0.5 \n\t" //d1 = 0.5
|
||||
"vadd.f32 d0, d0, d2 \n\t" //d0 = d0 + d2
|
||||
"vmul.f32 d0, d1 \n\t" //d0 = d0 * d1
|
||||
|
||||
:: "r"(__coshf_rng), "r"(__coshf_lut)
|
||||
: "d0", "d1", "q1", "q2", "d6"
|
||||
);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
float coshf_neon_sfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile ("vmov.f32 s0, r0 \n\t");
|
||||
coshf_neon_hfp(x);
|
||||
asm volatile ("vmov.f32 r0, s0 \n\t");
|
||||
#else
|
||||
return coshf_c(x);
|
||||
#endif
|
||||
};
|
||||
Vendored
+135
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Based on:
|
||||
|
||||
e ^ x = (1+m) * (2^n)
|
||||
x = log(1+m) + n * log(2)
|
||||
n = (int) (x * 1.0 / log(2))
|
||||
(1+m) = e ^ (x - n * log(2))
|
||||
(1+m) = Poly(x - n * log(2))
|
||||
|
||||
where Poly(x) is the Minimax approximation of e ^ x over the
|
||||
range [-Log(2), Log(2)]
|
||||
|
||||
Test func : expf(x)
|
||||
Test Range: 0 < x < 50
|
||||
Peak Error: ~0.00024%
|
||||
RMS Error: ~0.00007%
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "math_neon.h"
|
||||
|
||||
const float __expf_rng[2] = {
|
||||
1.442695041f,
|
||||
0.693147180f
|
||||
};
|
||||
|
||||
const float __expf_lut[8] = {
|
||||
0.9999999916728642, //p0
|
||||
0.04165989275009526, //p4
|
||||
0.5000006143673624, //p2
|
||||
0.0014122663401803872, //p6
|
||||
1.000000059694879, //p1
|
||||
0.008336936973260111, //p5
|
||||
0.16666570253074878, //p3
|
||||
0.00019578093328483123 //p7
|
||||
};
|
||||
|
||||
float expf_c(float x)
|
||||
{
|
||||
float a, b, c, d, xx;
|
||||
int m;
|
||||
|
||||
union {
|
||||
float f;
|
||||
int i;
|
||||
} r;
|
||||
|
||||
//Range Reduction:
|
||||
m = (int) (x * __expf_rng[0]);
|
||||
x = x - ((float) m) * __expf_rng[1];
|
||||
|
||||
//Taylor Polynomial (Estrins)
|
||||
a = (__expf_lut[4] * x) + (__expf_lut[0]);
|
||||
b = (__expf_lut[6] * x) + (__expf_lut[2]);
|
||||
c = (__expf_lut[5] * x) + (__expf_lut[1]);
|
||||
d = (__expf_lut[7] * x) + (__expf_lut[3]);
|
||||
xx = x * x;
|
||||
a = a + b * xx;
|
||||
c = c + d * xx;
|
||||
xx = xx* xx;
|
||||
r.f = a + c * xx;
|
||||
|
||||
//multiply by 2 ^ m
|
||||
m = m << 23;
|
||||
r.i = r.i + m;
|
||||
|
||||
return r.f;
|
||||
}
|
||||
|
||||
float expf_neon_hfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
"vdup.f32 d0, d0[0] \n\t" //d0 = {x, x}
|
||||
|
||||
//Range Reduction:
|
||||
"vld1.32 d2, [%0] \n\t" //d2 = {invrange, range}
|
||||
"vmul.f32 d6, d0, d2[0] \n\t" //d6 = d0 * d2[0]
|
||||
"vcvt.s32.f32 d6, d6 \n\t" //d6 = (int) d6
|
||||
"vcvt.f32.s32 d1, d6 \n\t" //d1 = (float) d6
|
||||
"vmls.f32 d0, d1, d2[1] \n\t" //d0 = d0 - d1 * d2[1]
|
||||
|
||||
//polynomial:
|
||||
"vmul.f32 d1, d0, d0 \n\t" //d1 = d0*d0 = {x^2, x^2}
|
||||
"vld1.32 {d2, d3, d4, d5}, [%1] \n\t" //q1 = {p0, p4, p2, p6}, q2 = {p1, p5, p3, p7} ;
|
||||
"vmla.f32 q1, q2, d0[0] \n\t" //q1 = q1 + q2 * d0[0]
|
||||
"vmla.f32 d2, d3, d1[0] \n\t" //d2 = d2 + d3 * d1[0]
|
||||
"vmul.f32 d1, d1, d1 \n\t" //d1 = d1 * d1 = {x^4, x^4}
|
||||
"vmla.f32 d2, d1, d2[1] \n\t" //d2 = d2 + d1 * d2[1]
|
||||
|
||||
//multiply by 2 ^ m
|
||||
"vshl.i32 d6, d6, #23 \n\t" //d6 = d6 << 23
|
||||
"vadd.i32 d0, d2, d6 \n\t" //d0 = d2 + d6
|
||||
|
||||
:: "r"(__expf_rng), "r"(__expf_lut)
|
||||
: "d0", "d1", "q1", "q2", "d6"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
float expf_neon_sfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile ("vmov.f32 s0, r0 \n\t");
|
||||
expf_neon_hfp(x);
|
||||
asm volatile ("vmov.f32 r0, s0 \n\t");
|
||||
#else
|
||||
return expf_c(x);
|
||||
#endif
|
||||
};
|
||||
|
||||
Vendored
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "math_neon.h"
|
||||
|
||||
|
||||
float fabsf_c(float x)
|
||||
{
|
||||
union {
|
||||
int i;
|
||||
float f;
|
||||
} xx;
|
||||
|
||||
xx.f = x;
|
||||
xx.i = xx.i & 0x7FFFFFFF;
|
||||
return xx.f;
|
||||
}
|
||||
|
||||
float fabsf_neon_hfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
"fabss s0, s0 \n\t" //s0 = fabs(s0)
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
float fabsf_neon_sfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
"bic r0, r0, #0x80000000 \n\t" //r0 = r0 & ~(1 << 31)
|
||||
);
|
||||
#else
|
||||
return fabsf_c(x);
|
||||
#endif
|
||||
}
|
||||
Vendored
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Assumes the floating point value |x| < 2147483648
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "math_neon.h"
|
||||
|
||||
float floorf_c(float x)
|
||||
{
|
||||
int n;
|
||||
float r;
|
||||
n = (int) x;
|
||||
r = (float) n;
|
||||
r = r - (r > x);
|
||||
return r;
|
||||
}
|
||||
|
||||
float floorf_neon_hfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
"vcvt.s32.f32 d1, d0 \n\t" //d1 = (int) d0;
|
||||
"vcvt.f32.s32 d1, d1 \n\t" //d1 = (float) d1;
|
||||
"vcgt.f32 d0, d1, d0 \n\t" //d0 = (d1 > d0);
|
||||
"vshr.u32 d0, #31 \n\t" //d0 = d0 >> 31;
|
||||
"vcvt.f32.u32 d0, d0 \n\t" //d0 = (float) d0;
|
||||
"vsub.f32 d0, d1, d0 \n\t" //d0 = d1 - d0;
|
||||
::: "d0", "d1"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
float floorf_neon_sfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile ("vmov.f32 s0, r0 \n\t");
|
||||
floorf_neon_hfp(x);
|
||||
asm volatile ("vmov.f32 r0, s0 \n\t");
|
||||
#else
|
||||
return floorf_c(x);
|
||||
#endif
|
||||
};
|
||||
Vendored
+100
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Assumes the floating point value |x / y| < 2,147,483,648
|
||||
*/
|
||||
|
||||
#include "math_neon.h"
|
||||
|
||||
float fmodf_c(float x, float y)
|
||||
{
|
||||
int n;
|
||||
union {
|
||||
float f;
|
||||
int i;
|
||||
} yinv;
|
||||
float a;
|
||||
|
||||
//fast reciporical approximation (4x Newton)
|
||||
yinv.f = y;
|
||||
n = 0x3F800000 - (yinv.i & 0x7F800000);
|
||||
yinv.i = yinv.i + n;
|
||||
yinv.f = 1.41176471f - 0.47058824f * yinv.f;
|
||||
yinv.i = yinv.i + n;
|
||||
a = 2.0 - yinv.f * y;
|
||||
yinv.f = yinv.f * a;
|
||||
a = 2.0 - yinv.f * y;
|
||||
yinv.f = yinv.f * a;
|
||||
a = 2.0 - yinv.f * y;
|
||||
yinv.f = yinv.f * a;
|
||||
a = 2.0 - yinv.f * y;
|
||||
yinv.f = yinv.f * a;
|
||||
|
||||
n = (int)(x * yinv.f);
|
||||
x = x - ((float)n) * y;
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
float fmodf_neon_hfp(float x, float y)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
"vdup.f32 d1, d0[1] \n\t" //d1[0] = y
|
||||
"vdup.f32 d0, d0[0] \n\t" //d1[0] = y
|
||||
|
||||
//fast reciporical approximation
|
||||
"vrecpe.f32 d2, d1 \n\t" //d2 = ~1.0 / d1
|
||||
"vrecps.f32 d3, d2, d1 \n\t" //d3 = 2.0 - d2 * d1;
|
||||
"vmul.f32 d2, d2, d3 \n\t" //d2 = d2 * d3;
|
||||
"vrecps.f32 d3, d2, d1 \n\t" //d3 = 2.0 - d2 * d1;
|
||||
"vmul.f32 d2, d2, d3 \n\t" //d2 = d2 * d3;
|
||||
"vrecps.f32 d3, d2, d1 \n\t" //d3 = 2.0 - d2 * d1;
|
||||
"vmul.f32 d2, d2, d3 \n\t" //d2 = d2 * d3;
|
||||
"vrecps.f32 d3, d2, d1 \n\t" //d3 = 2.0 - d2 * d1;
|
||||
"vmul.f32 d2, d2, d3 \n\t" //d2 = d2 * d3;
|
||||
|
||||
"vmul.f32 d2, d2, d0 \n\t" //d2 = d2 * d0;
|
||||
"vcvt.s32.f32 d2, d2 \n\t" //d2 = (int) d2;
|
||||
"vcvt.f32.s32 d2, d2 \n\t" //d2 = (float) d2;
|
||||
"vmls.f32 d0, d1, d2 \n\t" //d0 = d0 - d1 * d2;
|
||||
|
||||
::: "d0", "d1", "d2", "d3"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
float fmodf_neon_sfp(float x, float y)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile ("vmov.f32 s0, r0 \n\t");
|
||||
asm volatile ("vmov.f32 s1, r1 \n\t");
|
||||
fmodf_neon_hfp(x, y);
|
||||
asm volatile ("vmov.f32 r0, s0 \n\t");
|
||||
#else
|
||||
return fmodf_c(x,y);
|
||||
#endif
|
||||
};
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "math_neon.h"
|
||||
|
||||
float invsqrtf_c(float x)
|
||||
{
|
||||
|
||||
float b, c;
|
||||
union {
|
||||
float f;
|
||||
int i;
|
||||
} a;
|
||||
|
||||
//fast invsqrt approx
|
||||
a.f = x;
|
||||
a.i = 0x5F3759DF - (a.i >> 1); //VRSQRTE
|
||||
c = x * a.f;
|
||||
b = (3.0f - c * a.f) * 0.5; //VRSQRTS
|
||||
a.f = a.f * b;
|
||||
c = x * a.f;
|
||||
b = (3.0f - c * a.f) * 0.5;
|
||||
a.f = a.f * b;
|
||||
|
||||
return a.f;
|
||||
}
|
||||
|
||||
float invsqrtf_neon_hfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
|
||||
"vmov.f32 d1, d0 \n\t" //d1 = d0
|
||||
"vrsqrte.f32 d0, d0 \n\t" //d0 = ~ 1.0 / sqrt(d0)
|
||||
"vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1
|
||||
"vrsqrts.f32 d3, d2, d0 \n\t" //d3 = (3 - d0 * d2) / 2
|
||||
"vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d3
|
||||
"vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1
|
||||
"vrsqrts.f32 d3, d2, d0 \n\t" //d4 = (3 - d0 * d3) / 2
|
||||
"vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d4
|
||||
|
||||
::: "d0", "d1", "d2", "d3"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
float invsqrtf_neon_sfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile ("vmov.f32 s0, r0 \n\t");
|
||||
invsqrtf_neon_hfp(x);
|
||||
asm volatile ("vmov.f32 r0, s0 \n\t");
|
||||
#else
|
||||
return invsqrtf_c(x);
|
||||
#endif
|
||||
};
|
||||
|
||||
Vendored
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "math_neon.h"
|
||||
|
||||
float ldexpf_c(float m, int e)
|
||||
{
|
||||
union {
|
||||
float f;
|
||||
int i;
|
||||
} r;
|
||||
r.f = m;
|
||||
r.i += (e << 23);
|
||||
return r.f;
|
||||
}
|
||||
|
||||
float ldexpf_neon_hfp(float m, int e)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
float r;
|
||||
asm volatile (
|
||||
"lsl r0, r0, #23 \n\t" //r0 = r0 << 23
|
||||
"vdup.i32 d1, r0 \n\t" //d1 = {r0, r0}
|
||||
"vadd.i32 d0, d0, d1 \n\t" //d0 = d0 + d1
|
||||
::: "d0", "d1"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
float ldexpf_neon_sfp(float m, int e)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
float r;
|
||||
asm volatile (
|
||||
"lsl r1, r1, #23 \n\t" //r1 = r1 << 23
|
||||
"vdup.f32 d0, r0 \n\t" //d0 = {r0, r0}
|
||||
"vdup.i32 d1, r1 \n\t" //d1 = {r1, r1}
|
||||
"vadd.i32 d0, d0, d1 \n\t" //d0 = d0 + d1
|
||||
"vmov.f32 r0, s0 \n\t" //r0 = s0
|
||||
::: "d0", "d1"
|
||||
);
|
||||
#else
|
||||
return ldexpf_c(m,e);
|
||||
#endif
|
||||
}
|
||||
Vendored
+135
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Based on:
|
||||
|
||||
log10(x) = log10((1+m) * (2^n))
|
||||
log(x) = n * log10(2) + log10(1 + m)
|
||||
log(1+m) = Poly(1+m)
|
||||
|
||||
where Poly(x) is the Minimax approximation of log10(x) over the
|
||||
range [1, 2]
|
||||
|
||||
Test func : log10f(x)
|
||||
Test Range: 1 < x < 10000
|
||||
Peak Error: ~0.000040%
|
||||
RMS Error: ~0.000008%
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "math_neon.h"
|
||||
|
||||
const float __log10f_rng = 0.3010299957f;
|
||||
|
||||
const float __log10f_lut[8] = {
|
||||
-0.99697286229624, //p0
|
||||
-1.07301643912502, //p4
|
||||
-2.46980061535534, //p2
|
||||
-0.07176870463131, //p6
|
||||
2.247870219989470, //p1
|
||||
0.366547581117400, //p5
|
||||
1.991005185100089, //p3
|
||||
0.006135635201050, //p7
|
||||
};
|
||||
|
||||
float log10f_c(float x)
|
||||
{
|
||||
float a, b, c, d, xx;
|
||||
int m;
|
||||
|
||||
union {
|
||||
float f;
|
||||
int i;
|
||||
} r;
|
||||
|
||||
//extract exponent
|
||||
r.f = x;
|
||||
m = (r.i >> 23);
|
||||
m = m - 127;
|
||||
r.i = r.i - (m << 23);
|
||||
|
||||
//Taylor Polynomial (Estrins)
|
||||
xx = r.f * r.f;
|
||||
a = (__log10f_lut[4] * r.f) + (__log10f_lut[0]);
|
||||
b = (__log10f_lut[6] * r.f) + (__log10f_lut[2]);
|
||||
c = (__log10f_lut[5] * r.f) + (__log10f_lut[1]);
|
||||
d = (__log10f_lut[7] * r.f) + (__log10f_lut[3]);
|
||||
a = a + b * xx;
|
||||
c = c + d * xx;
|
||||
xx = xx * xx;
|
||||
r.f = a + c * xx;
|
||||
|
||||
//add exponent
|
||||
r.f = r.f + ((float) m) * __log10f_rng;
|
||||
|
||||
return r.f;
|
||||
}
|
||||
|
||||
float log10f_neon_hfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
|
||||
"vdup.f32 d0, d0[0] \n\t" //d0 = {x,x};
|
||||
|
||||
//extract exponent
|
||||
"vmov.i32 d2, #127 \n\t" //d2 = 127;
|
||||
"vshr.u32 d6, d0, #23 \n\t" //d6 = d0 >> 23;
|
||||
"vsub.i32 d6, d6, d2 \n\t" //d6 = d6 - d2;
|
||||
"vshl.u32 d1, d6, #23 \n\t" //d1 = d6 << 23;
|
||||
"vsub.i32 d0, d0, d1 \n\t" //d0 = d0 + d1;
|
||||
|
||||
//polynomial:
|
||||
"vmul.f32 d1, d0, d0 \n\t" //d1 = d0*d0 = {x^2, x^2}
|
||||
"vld1.32 {d2, d3, d4, d5}, [%1] \n\t" //q1 = {p0, p4, p2, p6}, q2 = {p1, p5, p3, p7} ;
|
||||
"vmla.f32 q1, q2, d0[0] \n\t" //q1 = q1 + q2 * d0[0]
|
||||
"vmla.f32 d2, d3, d1[0] \n\t" //d2 = d2 + d3 * d1[0]
|
||||
"vmul.f32 d1, d1, d1 \n\t" //d1 = d1 * d1 = {x^4, x^4}
|
||||
"vmla.f32 d2, d1, d2[1] \n\t" //d2 = d2 + d1 * d2[1]
|
||||
|
||||
//add exponent
|
||||
"vdup.32 d7, %0 \n\t" //d7 = {rng, rng}
|
||||
"vcvt.f32.s32 d6, d6 \n\t" //d6 = (float) d6
|
||||
"vmla.f32 d2, d6, d7 \n\t" //d2 = d2 + d6 * d7
|
||||
|
||||
"vmov.f32 s0, s4 \n\t" //s0 = s4
|
||||
|
||||
:: "r"(__log10f_rng), "r"(__log10f_lut)
|
||||
: "d0", "d1", "q1", "q2", "d6", "d7"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
float log10f_neon_sfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile ("vmov.f32 s0, r0 \n\t");
|
||||
log10f_neon_hfp(x);
|
||||
asm volatile ("vmov.f32 r0, s0 \n\t");
|
||||
#else
|
||||
return log10f_c(x);
|
||||
#endif
|
||||
};
|
||||
Vendored
+135
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Based on:
|
||||
|
||||
log(x) = log((1+m) * (2^n))
|
||||
log(x) = n * log(2) + log(1 + m)
|
||||
log(1+m) = Poly(1+m)
|
||||
|
||||
where Poly(x) is the Minimax approximation of log(x) over the
|
||||
range [1, 2]
|
||||
|
||||
Test func : logf(x)
|
||||
Test Range: 1 < x < 10000
|
||||
Peak Error: ~0.000601%
|
||||
RMS Error: ~0.000005%
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "math_neon.h"
|
||||
|
||||
const float __logf_rng = 0.693147180f;
|
||||
|
||||
const float __logf_lut[8] = {
|
||||
-2.295614848256274, //p0
|
||||
-2.470711633419806, //p4
|
||||
-5.686926051100417, //p2
|
||||
-0.165253547131978, //p6
|
||||
+5.175912446351073, //p1
|
||||
+0.844006986174912, //p5
|
||||
+4.584458825456749, //p3
|
||||
+0.014127821926000 //p7
|
||||
};
|
||||
|
||||
float logf_c(float x)
|
||||
{
|
||||
float a, b, c, d, xx;
|
||||
int m;
|
||||
|
||||
union {
|
||||
float f;
|
||||
int i;
|
||||
} r;
|
||||
|
||||
//extract exponent
|
||||
r.f = x;
|
||||
m = (r.i >> 23);
|
||||
m = m - 127;
|
||||
r.i = r.i - (m << 23);
|
||||
|
||||
//Taylor Polynomial (Estrins)
|
||||
xx = r.f * r.f;
|
||||
a = (__logf_lut[4] * r.f) + (__logf_lut[0]);
|
||||
b = (__logf_lut[6] * r.f) + (__logf_lut[2]);
|
||||
c = (__logf_lut[5] * r.f) + (__logf_lut[1]);
|
||||
d = (__logf_lut[7] * r.f) + (__logf_lut[3]);
|
||||
a = a + b * xx;
|
||||
c = c + d * xx;
|
||||
xx = xx * xx;
|
||||
r.f = a + c * xx;
|
||||
|
||||
//add exponent
|
||||
r.f = r.f + ((float) m) * __logf_rng;
|
||||
|
||||
return r.f;
|
||||
}
|
||||
|
||||
float logf_neon_hfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
|
||||
"vdup.f32 d0, d0[0] \n\t" //d0 = {x,x};
|
||||
|
||||
//extract exponent
|
||||
"vmov.i32 d2, #127 \n\t" //d2 = 127;
|
||||
"vshr.u32 d6, d0, #23 \n\t" //d6 = d0 >> 23;
|
||||
"vsub.i32 d6, d6, d2 \n\t" //d6 = d6 - d2;
|
||||
"vshl.u32 d1, d6, #23 \n\t" //d1 = d6 << 23;
|
||||
"vsub.i32 d0, d0, d1 \n\t" //d0 = d0 + d1;
|
||||
|
||||
//polynomial:
|
||||
"vmul.f32 d1, d0, d0 \n\t" //d1 = d0*d0 = {x^2, x^2}
|
||||
"vld1.32 {d2, d3, d4, d5}, [%1] \n\t" //q1 = {p0, p4, p2, p6}, q2 = {p1, p5, p3, p7} ;
|
||||
"vmla.f32 q1, q2, d0[0] \n\t" //q1 = q1 + q2 * d0[0]
|
||||
"vmla.f32 d2, d3, d1[0] \n\t" //d2 = d2 + d3 * d1[0]
|
||||
"vmul.f32 d1, d1, d1 \n\t" //d1 = d1 * d1 = {x^4, x^4}
|
||||
"vmla.f32 d2, d1, d2[1] \n\t" //d2 = d2 + d1 * d2[1]
|
||||
|
||||
//add exponent
|
||||
"vdup.32 d7, %0 \n\t" //d7 = {rng, rng}
|
||||
"vcvt.f32.s32 d6, d6 \n\t" //d6 = (float) d6
|
||||
"vmla.f32 d2, d6, d7 \n\t" //d2 = d2 + d6 * d7
|
||||
|
||||
"vmov.f32 s0, s4 \n\t" //s0 = s4
|
||||
|
||||
:: "r"(__logf_rng), "r"(__logf_lut)
|
||||
: "d0", "d1", "q1", "q2", "d6", "d7"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
float logf_neon_sfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile ("vmov.f32 s0, r0 \n\t");
|
||||
logf_neon_hfp(x);
|
||||
asm volatile ("vmov.f32 r0, s0 \n\t");
|
||||
#else
|
||||
return logf_c(x);
|
||||
#endif
|
||||
};
|
||||
|
||||
Vendored
+95
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Matrices are specified in column major format:
|
||||
|
||||
| a c |
|
||||
| b d |
|
||||
|
||||
therefore m[2] = c
|
||||
*/
|
||||
|
||||
#include "math_neon.h"
|
||||
|
||||
//matrix matrix multipication. d = m0 * m1;
|
||||
void
|
||||
matmul2_c(float m0[4], float m1[4], float d[4])
|
||||
{
|
||||
d[0] = m0[0]*m1[0] + m0[2]*m1[1];
|
||||
d[1] = m0[1]*m1[0] + m0[3]*m1[1];
|
||||
d[2] = m0[0]*m1[2] + m0[2]*m1[3];
|
||||
d[3] = m0[1]*m1[2] + m0[3]*m1[3];
|
||||
}
|
||||
|
||||
void
|
||||
matmul2_neon(float m0[4], float m1[4], float d[4])
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
"vld1.32 {d0, d1}, [%0] \n\t" //Q1 = m0
|
||||
"vld1.32 {d2, d3}, [%1] \n\t" //Q2 = m1
|
||||
|
||||
"vmul.f32 d4, d0, d2[0] \n\t" //D4 = D0*D2[0]
|
||||
"vmul.f32 d5, d0, d3[0] \n\t" //D5 = D0*D3[0]
|
||||
"vmla.f32 d4, d1, d2[1] \n\t" //D4 += D1*D2[1]
|
||||
"vmla.f32 d5, d1, d3[1] \n\t" //D5 += D1*D3[1]
|
||||
|
||||
"vst1.32 {d4, d5}, [%2] \n\t" //Q4 = m+12
|
||||
:: "r"(m0), "r"(m1), "r"(d)
|
||||
: "q0", "q1", "q2", "memory"
|
||||
);
|
||||
#else
|
||||
matmul2_c(m0, m1, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//matrix vector multiplication. d = m * v
|
||||
void
|
||||
matvec2_c(float m[4], float v[2], float d[2])
|
||||
{
|
||||
d[0] = m[0]*v[0] + m[2]*v[1];
|
||||
d[1] = m[1]*v[0] + m[3]*v[1];
|
||||
}
|
||||
|
||||
void
|
||||
matvec2_neon(float m[4], float v[2], float d[2])
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
"vld1.32 d0, [%1] \n\t" //d0 = v
|
||||
"vld1.32 {d1, d2}, [%0] \n\t" //Q1 = m
|
||||
|
||||
"vmul.f32 d3, d1, d0[0] \n\t" //Q5 = Q1*d0[0]
|
||||
"vmla.f32 d3, d2, d0[1] \n\t" //Q5 += Q1*d0[1]
|
||||
|
||||
"vst1.32 d3, [%2] \n\t" //Q4 = m+12
|
||||
:: "r"(m), "r"(v), "r"(d)
|
||||
: "d0", "d1", "d2","d3", "memory"
|
||||
);
|
||||
#else
|
||||
matvec2_c(m, v, d);
|
||||
#endif
|
||||
}
|
||||
Vendored
+131
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Matrices are specified in row major format:
|
||||
|
||||
| x0 x2 |
|
||||
| x1 x3 |
|
||||
|
||||
therefore m[2] = x2
|
||||
|
||||
*/
|
||||
|
||||
#include "math_neon.h"
|
||||
|
||||
//matrix matrix multipication. d = m0 * m1;
|
||||
void
|
||||
matmul3_c(float m0[9], float m1[9], float d[9])
|
||||
{
|
||||
d[0] = m0[0]*m1[0] + m0[3]*m1[1] + m0[6]*m1[2];
|
||||
d[1] = m0[1]*m1[0] + m0[4]*m1[1] + m0[7]*m1[2];
|
||||
d[2] = m0[2]*m1[0] + m0[5]*m1[1] + m0[8]*m1[2];
|
||||
d[3] = m0[0]*m1[3] + m0[3]*m1[4] + m0[6]*m1[5];
|
||||
d[4] = m0[1]*m1[3] + m0[4]*m1[4] + m0[7]*m1[5];
|
||||
d[5] = m0[2]*m1[3] + m0[5]*m1[4] + m0[8]*m1[5];
|
||||
d[6] = m0[0]*m1[6] + m0[3]*m1[7] + m0[6]*m1[8];
|
||||
d[7] = m0[1]*m1[6] + m0[4]*m1[7] + m0[7]*m1[8];
|
||||
d[8] = m0[2]*m1[6] + m0[5]*m1[7] + m0[8]*m1[8];
|
||||
}
|
||||
|
||||
void
|
||||
matmul3_neon(float m0[9], float m1[9], float d[9])
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
"vld1.32 {d0, d1}, [%1]! \n\t" //q0 = m1
|
||||
"vld1.32 {d2, d3}, [%1]! \n\t" //q1 = m1+4
|
||||
"flds s8, [%1] \n\t" //q2 = m1+8
|
||||
|
||||
"vld1.32 {d6, d7}, [%0] \n\t" //q3[0] = m0
|
||||
"add %0, %0, #12 \n\t" //q3[0] = m0
|
||||
"vld1.32 {d8, d9}, [%0] \n\t" //q4[0] = m0+12
|
||||
"add %0, %0, #12 \n\t" //q3[0] = m0
|
||||
"vld1.32 {d10}, [%0] \n\t" //q5[0] = m0+24
|
||||
"add %0, %0, #8 \n\t" //q3[0] = m0
|
||||
"flds s22, [%0] \n\t" //q2 = m1+8
|
||||
|
||||
"vmul.f32 q6, q3, d0[0] \n\t" //q12 = q3 * d0[0]
|
||||
"vmul.f32 q7, q3, d1[1] \n\t" //q13 = q3 * d2[0]
|
||||
"vmul.f32 q8, q3, d3[0] \n\t" //q14 = q3 * d4[0]
|
||||
"vmla.f32 q6, q4, d0[1] \n\t" //q12 = q9 * d0[1]
|
||||
"vmla.f32 q7, q4, d2[0] \n\t" //q13 = q9 * d2[1]
|
||||
"vmla.f32 q8, q4, d3[1] \n\t" //q14 = q9 * d4[1]
|
||||
"vmla.f32 q6, q5, d1[0] \n\t" //q12 = q10 * d0[0]
|
||||
"vmla.f32 q7, q5, d2[1] \n\t" //q13 = q10 * d2[0]
|
||||
"vmla.f32 q8, q5, d4[0] \n\t" //q14 = q10 * d4[0]
|
||||
|
||||
"vmov.f32 q0, q8 \n\t" //q14 = q10 * d4[0]
|
||||
"vst1.32 {d12, d13}, [%2] \n\t" //d = q12
|
||||
"add %2, %2, #12 \n\t" //q3[0] = m0
|
||||
"vst1.32 {d14, d15}, [%2] \n\t" //d+4 = q13
|
||||
"add %2, %2, #12 \n\t" //q3[0] = m0
|
||||
"vst1.32 {d0}, [%2] \n\t" //d+8 = q14
|
||||
"add %2, %2, #8 \n\t" //q3[0] = m0
|
||||
"fsts s2, [%2] \n\t" //d = q12
|
||||
|
||||
: "+r"(m0), "+r"(m1), "+r"(d):
|
||||
: "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15", "memory"
|
||||
);
|
||||
#else
|
||||
matmul3_c(m0, m1, d);
|
||||
#endif
|
||||
};
|
||||
|
||||
//matrix vector multiplication. d = m * v
|
||||
void
|
||||
matvec3_c(float m[9], float v[3], float d[3])
|
||||
{
|
||||
d[0] = m[0]*v[0] + m[3]*v[1] + m[6]*v[2];
|
||||
d[1] = m[1]*v[0] + m[4]*v[1] + m[7]*v[2];
|
||||
d[2] = m[2]*v[0] + m[5]*v[1] + m[8]*v[2];
|
||||
}
|
||||
|
||||
void
|
||||
matvec3_neon(float m[9], float v[3], float d[3])
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
int tmp;
|
||||
asm volatile (
|
||||
"mov %3, #12 \n\t" //r3 = 12
|
||||
"vld1.32 {d0, d1}, [%1] \n\t" //Q0 = v
|
||||
"vld1.32 {d2, d3}, [%0], %3 \n\t" //Q1 = m
|
||||
"vld1.32 {d4, d5}, [%0], %3 \n\t" //Q2 = m+12
|
||||
"vld1.32 {d6, d7}, [%0], %3 \n\t" //Q3 = m+24
|
||||
|
||||
"vmul.f32 q9, q1, d0[0] \n\t" //Q9 = Q1*Q0[0]
|
||||
"vmla.f32 q9, q2, d0[1] \n\t" //Q9 += Q2*Q0[1]
|
||||
"vmla.f32 q9, q3, d1[0] \n\t" //Q9 += Q3*Q0[2]
|
||||
"vmov.f32 q0, q9 \n\t" //Q0 = q9
|
||||
|
||||
"vst1.32 d0, [%2]! \n\t" //r2 = D24
|
||||
"fsts s2, [%2] \n\t" //r2 = D25[0]
|
||||
|
||||
: "+r"(m), "+r"(v), "+r"(d), "+r"(tmp):
|
||||
: "q0", "q9", "q10","q11", "q12", "q13", "memory"
|
||||
);
|
||||
#else
|
||||
matvec3_c(m, v, d);
|
||||
#endif
|
||||
}
|
||||
Vendored
+144
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Matrices are specified in row major format:
|
||||
|
||||
| x0 x2 |
|
||||
| x1 x3 |
|
||||
|
||||
therefore m[2] = x2
|
||||
|
||||
*/
|
||||
|
||||
#include "math_neon.h"
|
||||
|
||||
//matrix matrix multipication. d = m0 * m1;
|
||||
void
|
||||
matmul4_c(float m0[16], float m1[16], float d[16])
|
||||
{
|
||||
d[0] = m0[0]*m1[0] + m0[4]*m1[1] + m0[8]*m1[2] + m0[12]*m1[3];
|
||||
d[1] = m0[1]*m1[0] + m0[5]*m1[1] + m0[9]*m1[2] + m0[13]*m1[3];
|
||||
d[2] = m0[2]*m1[0] + m0[6]*m1[1] + m0[10]*m1[2] + m0[14]*m1[3];
|
||||
d[3] = m0[3]*m1[0] + m0[7]*m1[1] + m0[11]*m1[2] + m0[15]*m1[3];
|
||||
d[4] = m0[0]*m1[4] + m0[4]*m1[5] + m0[8]*m1[6] + m0[12]*m1[7];
|
||||
d[5] = m0[1]*m1[4] + m0[5]*m1[5] + m0[9]*m1[6] + m0[13]*m1[7];
|
||||
d[6] = m0[2]*m1[4] + m0[6]*m1[5] + m0[10]*m1[6] + m0[14]*m1[7];
|
||||
d[7] = m0[3]*m1[4] + m0[7]*m1[5] + m0[11]*m1[6] + m0[15]*m1[7];
|
||||
d[8] = m0[0]*m1[8] + m0[4]*m1[9] + m0[8]*m1[10] + m0[12]*m1[11];
|
||||
d[9] = m0[1]*m1[8] + m0[5]*m1[9] + m0[9]*m1[10] + m0[13]*m1[11];
|
||||
d[10] = m0[2]*m1[8] + m0[6]*m1[9] + m0[10]*m1[10] + m0[14]*m1[11];
|
||||
d[11] = m0[3]*m1[8] + m0[7]*m1[9] + m0[11]*m1[10] + m0[15]*m1[11];
|
||||
d[12] = m0[0]*m1[12] + m0[4]*m1[13] + m0[8]*m1[14] + m0[12]*m1[15];
|
||||
d[13] = m0[1]*m1[12] + m0[5]*m1[13] + m0[9]*m1[14] + m0[13]*m1[15];
|
||||
d[14] = m0[2]*m1[12] + m0[6]*m1[13] + m0[10]*m1[14] + m0[14]*m1[15];
|
||||
d[15] = m0[3]*m1[12] + m0[7]*m1[13] + m0[11]*m1[14] + m0[15]*m1[15];
|
||||
}
|
||||
|
||||
void
|
||||
matmul4_neon(float m0[16], float m1[16], float d[16])
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
"vld1.32 {d0, d1}, [%1]! \n\t" //q0 = m1
|
||||
"vld1.32 {d2, d3}, [%1]! \n\t" //q1 = m1+4
|
||||
"vld1.32 {d4, d5}, [%1]! \n\t" //q2 = m1+8
|
||||
"vld1.32 {d6, d7}, [%1] \n\t" //q3 = m1+12
|
||||
"vld1.32 {d16, d17}, [%0]! \n\t" //q8 = m0
|
||||
"vld1.32 {d18, d19}, [%0]! \n\t" //q9 = m0+4
|
||||
"vld1.32 {d20, d21}, [%0]! \n\t" //q10 = m0+8
|
||||
"vld1.32 {d22, d23}, [%0] \n\t" //q11 = m0+12
|
||||
|
||||
"vmul.f32 q12, q8, d0[0] \n\t" //q12 = q8 * d0[0]
|
||||
"vmul.f32 q13, q8, d2[0] \n\t" //q13 = q8 * d2[0]
|
||||
"vmul.f32 q14, q8, d4[0] \n\t" //q14 = q8 * d4[0]
|
||||
"vmul.f32 q15, q8, d6[0] \n\t" //q15 = q8 * d6[0]
|
||||
"vmla.f32 q12, q9, d0[1] \n\t" //q12 = q9 * d0[1]
|
||||
"vmla.f32 q13, q9, d2[1] \n\t" //q13 = q9 * d2[1]
|
||||
"vmla.f32 q14, q9, d4[1] \n\t" //q14 = q9 * d4[1]
|
||||
"vmla.f32 q15, q9, d6[1] \n\t" //q15 = q9 * d6[1]
|
||||
"vmla.f32 q12, q10, d1[0] \n\t" //q12 = q10 * d0[0]
|
||||
"vmla.f32 q13, q10, d3[0] \n\t" //q13 = q10 * d2[0]
|
||||
"vmla.f32 q14, q10, d5[0] \n\t" //q14 = q10 * d4[0]
|
||||
"vmla.f32 q15, q10, d7[0] \n\t" //q15 = q10 * d6[0]
|
||||
"vmla.f32 q12, q11, d1[1] \n\t" //q12 = q11 * d0[1]
|
||||
"vmla.f32 q13, q11, d3[1] \n\t" //q13 = q11 * d2[1]
|
||||
"vmla.f32 q14, q11, d5[1] \n\t" //q14 = q11 * d4[1]
|
||||
"vmla.f32 q15, q11, d7[1] \n\t" //q15 = q11 * d6[1]
|
||||
|
||||
"vst1.32 {d24, d25}, [%2]! \n\t" //d = q12
|
||||
"vst1.32 {d26, d27}, [%2]! \n\t" //d+4 = q13
|
||||
"vst1.32 {d28, d29}, [%2]! \n\t" //d+8 = q14
|
||||
"vst1.32 {d30, d31}, [%2] \n\t" //d+12 = q15
|
||||
|
||||
: "+r"(m0), "+r"(m1), "+r"(d) :
|
||||
: "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15",
|
||||
"memory"
|
||||
);
|
||||
#else
|
||||
matmul4_c(m0, m1, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//matrix vector multiplication. d = m * v
|
||||
void
|
||||
matvec4_c(float m[16], float v[4], float d[4])
|
||||
{
|
||||
d[0] = m[0]*v[0] + m[4]*v[1] + m[8]*v[2] + m[12]*v[3];
|
||||
d[1] = m[1]*v[0] + m[5]*v[1] + m[9]*v[2] + m[13]*v[3];
|
||||
d[2] = m[2]*v[0] + m[6]*v[1] + m[10]*v[2] + m[14]*v[3];
|
||||
d[3] = m[3]*v[0] + m[7]*v[1] + m[11]*v[2] + m[15]*v[3];
|
||||
}
|
||||
|
||||
void
|
||||
matvec4_neon(float m[16], float v[4], float d[4])
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
"vld1.32 {d0, d1}, [%1] \n\t" //Q0 = v
|
||||
"vld1.32 {d18, d19}, [%0]! \n\t" //Q1 = m
|
||||
"vld1.32 {d20, d21}, [%0]! \n\t" //Q2 = m+4
|
||||
"vld1.32 {d22, d23}, [%0]! \n\t" //Q3 = m+8
|
||||
"vld1.32 {d24, d25}, [%0]! \n\t" //Q4 = m+12
|
||||
|
||||
"vmul.f32 q13, q9, d0[0] \n\t" //Q5 = Q1*Q0[0]
|
||||
"vmla.f32 q13, q10, d0[1] \n\t" //Q5 += Q1*Q0[1]
|
||||
"vmla.f32 q13, q11, d1[0] \n\t" //Q5 += Q2*Q0[2]
|
||||
"vmla.f32 q13, q12, d1[1] \n\t" //Q5 += Q3*Q0[3]
|
||||
|
||||
"vst1.32 {d26, d27}, [%2] \n\t" //Q4 = m+12
|
||||
:
|
||||
: "r"(m), "r"(v), "r"(d)
|
||||
: "q0", "q9", "q10","q11", "q12", "q13", "memory"
|
||||
);
|
||||
#else
|
||||
matvec4_c(m, v, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Vendored
+71
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Assumes the floating point value |x| < 2,147,483,648
|
||||
*/
|
||||
|
||||
#include "math_neon.h"
|
||||
|
||||
float modf_c(float x, int *i)
|
||||
{
|
||||
int n;
|
||||
n = (int)x;
|
||||
*i = n;
|
||||
x = x - (float)n;
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
float modf_neon_hfp(float x, int *i)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
"vcvt.s32.f32 d1, d0 \n\t" //d1 = (int) d0;
|
||||
"vcvt.f32.s32 d2, d1 \n\t" //d2 = (float) d1;
|
||||
"vsub.f32 d0, d0, d2 \n\t" //d0 = d0 - d2;
|
||||
"vstr.i32 s2, [r0] \n\t" //[r0] = d1[0]
|
||||
::: "d0", "d1", "d2"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
float modf_neon_sfp(float x, int *i)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
"vdup.f32 d0, r0 \n\t" //d0 = {x, x}
|
||||
"vcvt.s32.f32 d1, d0 \n\t" //d1 = (int) d0;
|
||||
"vcvt.f32.s32 d2, d1 \n\t" //d2 = (float) d1;
|
||||
"vsub.f32 d0, d0, d2 \n\t" //d0 = d0 - d2;
|
||||
"vstr.i32 s2, [r1] \n\t" //[r0] = d1[0]
|
||||
"vmov.f32 r0, s0 \n\t" //r0 = d0[0];
|
||||
::: "d0", "d1", "d2"
|
||||
);
|
||||
|
||||
#else
|
||||
return modf_c(x, i);
|
||||
#endif
|
||||
}
|
||||
Vendored
+435
@@ -0,0 +1,435 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __MATH_NEON_H__
|
||||
#define __MATH_NEON_H__
|
||||
|
||||
#if !defined(__i386__) && defined(__arm__)
|
||||
//if defined neon ASM routines are used, otherwise all calls to *_neon
|
||||
//functions are rerouted to their equivalent *_c function.
|
||||
#define __MATH_NEON
|
||||
|
||||
//Default Floating Point value ABI: 0=softfp, 1=hardfp. Only effects *_neon routines.
|
||||
//You can access the hardfp versions directly via the *_hard suffix.
|
||||
//You can access the softfp versions directly via the *_soft suffix.
|
||||
#define __MATH_FPABI 0
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef GCC
|
||||
#define ALIGN(A) __attribute__ ((aligned (A))
|
||||
#else
|
||||
#define ALIGN(A)
|
||||
#endif
|
||||
|
||||
#ifndef _MATH_H
|
||||
#define M_PI 3.14159265358979323846 /* pi */
|
||||
#define M_PI_2 1.57079632679489661923 /* pi/2 */
|
||||
#define M_PI_4 0.78539816339744830962 /* pi/4 */
|
||||
#define M_E 2.7182818284590452354 /* e */
|
||||
#define M_LOG2E 1.4426950408889634074 /* log_2 e */
|
||||
#define M_LOG10E 0.43429448190325182765 /* log_10 e */
|
||||
#define M_LN2 0.69314718055994530942 /* log_e 2 */
|
||||
#define M_LN10 2.30258509299404568402 /* log_e 10 */
|
||||
#define M_1_PI 0.31830988618379067154 /* 1/pi */
|
||||
#define M_2_PI 0.63661977236758134308 /* 2/pi */
|
||||
#define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */
|
||||
#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
|
||||
#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
|
||||
#endif
|
||||
|
||||
#if __MATH_FPABI == 1
|
||||
#define sinf_neon sinf_neon_hfp
|
||||
#define cosf_neon cosf_neon_hfp
|
||||
#define sincosf_neon sincosf_neon_hfp
|
||||
#define tanf_neon tanf_neon_hfp
|
||||
#define atanf_neon atanf_neon_hfp
|
||||
#define atan2f_neon atan2f_neon_hfp
|
||||
#define asinf_neon asinf_neon_hfp
|
||||
#define acosf_neon acosf_neon_hfp
|
||||
#define sinhf_neon sinhf_neon_hfp
|
||||
#define coshf_neon coshf_neon_hfp
|
||||
#define tanhf_neon tanhf_neon_hfp
|
||||
#define expf_neon expf_neon_hfp
|
||||
#define logf_neon logf_neon_hfp
|
||||
#define log10f_neon log10f_neon_hfp
|
||||
#define powf_neon powf_neon_hfp
|
||||
#define floorf_neon floorf_neon_hfp
|
||||
#define ceilf_neon ceilf_neon_hfp
|
||||
#define fabsf_neon fabsf_neon_hfp
|
||||
#define ldexpf_neon ldexpf_neon_hfp
|
||||
#define frexpf_neon frexpf_neon_hfp
|
||||
#define fmodf_neon fmodf_neon_hfp
|
||||
#define modf_neon modf_neon_hfp
|
||||
#define sqrtf_neon sqrtf_neon_hfp
|
||||
#define invsqrtf_neon invsqrtf_neon_hfp
|
||||
#else
|
||||
#define sinf_neon sinf_neon_sfp
|
||||
#define cosf_neon cosf_neon_sfp
|
||||
#define sincosf_neon sincosf_neon_sfp
|
||||
#define tanf_neon tanf_neon_sfp
|
||||
#define atanf_neon atanf_neon_sfp
|
||||
#define atan2f_neon atan2f_neon_sfp
|
||||
#define asinf_neon asinf_neon_sfp
|
||||
#define acosf_neon acosf_neon_sfp
|
||||
#define sinhf_neon sinhf_neon_sfp
|
||||
#define coshf_neon coshf_neon_sfp
|
||||
#define tanhf_neon tanhf_neon_sfp
|
||||
#define expf_neon expf_neon_sfp
|
||||
#define logf_neon logf_neon_sfp
|
||||
#define log10f_neon log10f_neon_sfp
|
||||
#define powf_neon powf_neon_sfp
|
||||
#define floorf_neon floorf_neon_sfp
|
||||
#define ceilf_neon ceilf_neon_sfp
|
||||
#define fabsf_neon fabsf_neon_sfp
|
||||
#define ldexpf_neon ldexpf_neon_sfp
|
||||
#define frexpf_neon frexpf_neon_sfp
|
||||
#define fmodf_neon fmodf_neon_sfp
|
||||
#define modf_neon modf_neon_sfp
|
||||
#define sqrtf_neon sqrtf_neon_sfp
|
||||
#define invsqrtf_neon invsqrtf_neon_sfp
|
||||
|
||||
#define dot2_neon dot2_neon_sfp
|
||||
#define dot3_neon dot3_neon_sfp
|
||||
#define dot4_neon dot4_neon_sfp
|
||||
#endif
|
||||
|
||||
/*
|
||||
function: enable_runfast
|
||||
this function enables the floating point runfast mode on the
|
||||
ARM Cortex A8.
|
||||
*/
|
||||
void enable_runfast();
|
||||
|
||||
|
||||
float dot2_c(float v0[2], float v1[2]);
|
||||
float dot2_neon(float v0[2], float v1[2]);
|
||||
float dot3_c(float v0[3], float v1[3]);
|
||||
float dot3_neon(float v0[3], float v1[3]);
|
||||
float dot4_c(float v0[4], float v1[4]);
|
||||
float dot4_neon(float v0[4], float v1[4]);
|
||||
|
||||
void cross3_c(float v0[3], float v1[3], float d[3]);
|
||||
void cross3_neon(float v0[3], float v1[3], float d[3]);
|
||||
|
||||
void normalize2_c(float v[2], float d[2]);
|
||||
void normalize2_neon(float v[2], float d[2]);
|
||||
void normalize3_c(float v[3], float d[3]);
|
||||
void normalize3_neon(float v[3], float d[3]);
|
||||
void normalize4_c(float v[4], float d[4]);
|
||||
void normalize4_neon(float v[4], float d[4]);
|
||||
|
||||
/*
|
||||
function: matmul2
|
||||
arguments: m0 2x2 matrix, m1 2x2 matrix
|
||||
return: d 2x2 matrix
|
||||
expression: d = m0 * m1
|
||||
*/
|
||||
void matmul2_c(float m0[4], float m1[4], float d[4]);
|
||||
void matmul2_neon(float m0[4], float m1[4], float d[4]);
|
||||
|
||||
/*
|
||||
function: matmul3
|
||||
arguments: m0 3x3 matrix, m1 3x3 matrix
|
||||
return: d 3x3 matrix
|
||||
expression: d = m0 * m1
|
||||
*/
|
||||
void matmul3_c(float m0[9], float m1[9], float d[9]);
|
||||
void matmul3_neon(float m0[9], float m1[9], float d[9]);
|
||||
|
||||
/*
|
||||
function: matmul4
|
||||
arguments: m0 4x4 matrix, m1 4x4 matrix
|
||||
return: d 4x4 matrix
|
||||
expression: d = m0 * m1
|
||||
*/
|
||||
void matmul4_c(float m0[16], float m1[16], float d[16]);
|
||||
void matmul4_neon(float m0[16], float m1[16], float d[16]);
|
||||
|
||||
/*
|
||||
function: matvec2
|
||||
arguments: m 2x2 matrix, v 2 element vector
|
||||
return: d 2x2 matrix
|
||||
expression: d = m * v
|
||||
*/
|
||||
void matvec2_c(float m[4], float v[2], float d[2]);
|
||||
void matvec2_neon(float m[4], float v[2], float d[2]);
|
||||
|
||||
/*
|
||||
function: matvec3
|
||||
arguments: m 3x3 matrix, v 3 element vector
|
||||
return: d 3x3 matrix
|
||||
expression: d = m * v
|
||||
*/
|
||||
void matvec3_c(float m[9], float v[3], float d[3]);
|
||||
void matvec3_neon(float m[9], float v[3], float d[3]);
|
||||
|
||||
/*
|
||||
function: matvec4
|
||||
arguments: m 4x4 matrix, v 4 element vector
|
||||
return: d 4x4 matrix
|
||||
expression: d = m * v
|
||||
*/
|
||||
void matvec4_c(float m[16], float v[4], float d[4]);
|
||||
void matvec4_neon(float m[16], float v[4], float d[4]);
|
||||
|
||||
/*
|
||||
function: sinf
|
||||
arguments: x radians
|
||||
return: the sine function evaluated at x radians.
|
||||
expression: r = sin(x)
|
||||
*/
|
||||
float sinf_c(float x);
|
||||
float sinf_neon_hfp(float x);
|
||||
float sinf_neon_sfp(float x);
|
||||
|
||||
/*
|
||||
function: cosf
|
||||
arguments: x radians
|
||||
return: the cosine function evaluated at x radians.
|
||||
expression: r = cos(x)
|
||||
notes: computed using cos(x) = sin(x + pi/2)
|
||||
*/
|
||||
float cosf_c(float x);
|
||||
float cosf_neon_hfp(float x);
|
||||
float cosf_neon_sfp(float x);
|
||||
|
||||
/*
|
||||
function: sincosf
|
||||
arguments: x radians, r[2] result array.
|
||||
return: both the sine and the cosine evaluated at x radians.
|
||||
expression: r = {sin(x), cos(x)}
|
||||
notes: faster than evaluating seperately.
|
||||
*/
|
||||
void sincosf_c(float x, float r[2]);
|
||||
void sincosf_neon_hfp(float x, float r[2]);
|
||||
void sincosf_neon_sfp(float x, float r[2]);
|
||||
|
||||
/*
|
||||
function: sinfv
|
||||
return: the sine function evaluated at x[i] radians
|
||||
expression: r[i] = sin(x[i])
|
||||
notes: faster than evaluating individually.
|
||||
r and x can be the same memory location.
|
||||
*/
|
||||
void sinfv_c(float *x, int n, float *r);
|
||||
void sinfv_neon(float *x, int n, float *r);
|
||||
|
||||
/*
|
||||
function: tanf
|
||||
return: the tangent evaluated at x radians.
|
||||
expression: r = tan(x)
|
||||
notes: computed using tan(x) = sin(x) / cos(x)
|
||||
*/
|
||||
float tanf_c(float x);
|
||||
float tanf_neon_hfp(float x);
|
||||
float tanf_neon_sfp(float x);
|
||||
|
||||
/*
|
||||
function: atanf
|
||||
return: the arctangent evaluated at x.
|
||||
expression: r = atan(x)
|
||||
*/
|
||||
float atanf_c(float x);
|
||||
float atanf_neon_hfp(float x);
|
||||
float atanf_neon_sfp(float x);
|
||||
|
||||
/*
|
||||
function: atanf
|
||||
return: the arctangent evaluated at x.
|
||||
expression: r = atan(x)
|
||||
*/
|
||||
float atan2f_c(float y, float x);
|
||||
float atan2f_neon_hfp(float y, float x);
|
||||
float atan2f_neon_sfp(float y, float x);
|
||||
|
||||
/*
|
||||
function: asinf
|
||||
return: the arcsine evaluated at x.
|
||||
expression: r = asin(x)
|
||||
*/
|
||||
float asinf_c(float x);
|
||||
float asinf_neon_hfp(float x);
|
||||
float asinf_neon_sfp(float x);
|
||||
|
||||
/*
|
||||
function: acosf
|
||||
return: the arcsine evaluated at x.
|
||||
expression: r = asin(x)
|
||||
*/
|
||||
float acosf_c(float x);
|
||||
float acosf_neon_hfp(float x);
|
||||
float acosf_neon_sfp(float x);
|
||||
|
||||
/*
|
||||
function: sinhf
|
||||
return: the arcsine evaluated at x.
|
||||
expression: r = asin(x)
|
||||
*/
|
||||
float sinhf_c(float x);
|
||||
float sinhf_neon_hfp(float x);
|
||||
float sinhf_neon_sfp(float x);
|
||||
|
||||
/*
|
||||
function: coshf
|
||||
return: the arcsine evaluated at x.
|
||||
expression: r = asin(x)
|
||||
*/
|
||||
float coshf_c(float x);
|
||||
float coshf_neon_hfp(float x);
|
||||
float coshf_neon_sfp(float x);
|
||||
|
||||
/*
|
||||
function: tanhf
|
||||
return: the arcsine evaluated at x.
|
||||
expression: r = asin(x)
|
||||
*/
|
||||
float tanhf_c(float x);
|
||||
float tanhf_neon_hfp(float x);
|
||||
float tanhf_neon_sfp(float x);
|
||||
|
||||
/*
|
||||
function: expf
|
||||
return: the natural exponential evaluated at x.
|
||||
expression: r = e ** x
|
||||
*/
|
||||
float expf_c(float x);
|
||||
float expf_neon_hfp(float x);
|
||||
float expf_neon_sfp(float x);
|
||||
|
||||
/*
|
||||
function: logf
|
||||
return: the value of the natural logarithm of x.
|
||||
expression: r = ln(x)
|
||||
notes: assumes x > 0
|
||||
*/
|
||||
float logf_c(float x);
|
||||
float logf_neon_hfp(float x);
|
||||
float logf_neon_sfp(float x);
|
||||
|
||||
/*
|
||||
function: log10f
|
||||
return: the value of the power 10 logarithm of x.
|
||||
expression: r = log10(x)
|
||||
notes: assumes x > 0
|
||||
*/
|
||||
float log10f_c(float x);
|
||||
float log10f_neon_hfp(float x);
|
||||
float log10f_neon_sfp(float x);
|
||||
|
||||
/*
|
||||
function: powf
|
||||
return: x raised to the power of n, x ** n.
|
||||
expression: r = x ** y
|
||||
notes: computed using e ** (y * ln(x))
|
||||
*/
|
||||
float powf_c(float x, float n);
|
||||
float powf_neon_sfp(float x, float n);
|
||||
float powf_neon_hfp(float x, float n);
|
||||
|
||||
/*
|
||||
function: floorf
|
||||
return: x rounded down (towards negative infinity) to its nearest
|
||||
integer value.
|
||||
notes: assumes |x| < 2 ** 31
|
||||
*/
|
||||
float floorf_c(float x);
|
||||
float floorf_neon_sfp(float x);
|
||||
float floorf_neon_hfp(float x);
|
||||
|
||||
/*
|
||||
function: ceilf
|
||||
return: x rounded up (towards positive infinity) to its nearest
|
||||
integer value.
|
||||
notes: assumes |x| < 2 ** 31
|
||||
*/
|
||||
float ceilf_c(float x);
|
||||
float ceilf_neon_hfp(float x);
|
||||
float ceilf_neon_sfp(float x);
|
||||
|
||||
/*
|
||||
function: fabsf
|
||||
return: absolute vvalue of x
|
||||
notes: assumes |x| < 2 ** 31
|
||||
*/
|
||||
float fabsf_c(float x);
|
||||
float fabsf_neon_hfp(float x);
|
||||
float fabsf_neon_sfp(float x);
|
||||
|
||||
/*
|
||||
function: ldexpf
|
||||
return: the value of m multiplied by 2 to the power of e.
|
||||
expression: r = m * (2 ** e)
|
||||
*/
|
||||
float ldexpf_c(float m, int e);
|
||||
float ldexpf_neon_hfp(float m, int e);
|
||||
float ldexpf_neon_sfp(float m, int e);
|
||||
|
||||
/*
|
||||
function: frexpf
|
||||
return: the exponent and mantissa of x
|
||||
*/
|
||||
float frexpf_c(float x, int *e);
|
||||
float frexpf_neon_hfp(float x, int *e);
|
||||
float frexpf_neon_sfp(float x, int *e);
|
||||
|
||||
/*
|
||||
function: fmodf
|
||||
return: the remainder of x divided by y, x % y
|
||||
expression: r = x - floor(x / y) * y;
|
||||
notes: assumes that |x / y| < 2 ** 31
|
||||
*/
|
||||
float fmodf_c(float x, float y);
|
||||
float fmodf_neon_hfp(float x, float y);
|
||||
float fmodf_neon_sfp(float x, float y);
|
||||
|
||||
/*
|
||||
function: modf
|
||||
return: breaks x into the integer (i) and fractional part (return)
|
||||
notes: assumes that |x| < 2 ** 31
|
||||
*/
|
||||
float modf_c(float x, int *i);
|
||||
float modf_neon_hfp(float x, int *i);
|
||||
float modf_neon_sfp(float x, int *i);
|
||||
|
||||
/*
|
||||
function: sqrtf
|
||||
return: (x^0.5)
|
||||
notes:
|
||||
*/
|
||||
float sqrtf_c(float x);
|
||||
float sqrtf_neon_hfp(float x);
|
||||
float sqrtf_neon_sfp(float x);
|
||||
|
||||
|
||||
/*
|
||||
function: invsqrtf
|
||||
return: 1.0f / (x^0.5)
|
||||
notes:
|
||||
*/
|
||||
float invsqrtf_c(float x);
|
||||
float invsqrtf_neon_hfp(float x);
|
||||
float invsqrtf_neon_sfp(float x);
|
||||
|
||||
#endif
|
||||
Vendored
+182
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Based on x ^ n = exp(n * log(x))
|
||||
|
||||
Test func : powf(x, n)
|
||||
Test Range: (1,1) < (x, n) < (10, 10)
|
||||
Peak Error: ~0.0010%
|
||||
RMS Error: ~0.0002%
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "math_neon.h"
|
||||
|
||||
const float __powf_rng[2] = {
|
||||
1.442695041f,
|
||||
0.693147180f
|
||||
};
|
||||
|
||||
const float __powf_lut[16] = {
|
||||
-2.295614848256274, //p0 log
|
||||
-2.470711633419806, //p4
|
||||
-5.686926051100417, //p2
|
||||
-0.165253547131978, //p6
|
||||
+5.175912446351073, //p1
|
||||
+0.844006986174912, //p5
|
||||
+4.584458825456749, //p3
|
||||
+0.014127821926000, //p7
|
||||
0.9999999916728642, //p0 exp
|
||||
0.04165989275009526, //p4
|
||||
0.5000006143673624, //p2
|
||||
0.0014122663401803872, //p6
|
||||
1.000000059694879, //p1
|
||||
0.008336936973260111, //p5
|
||||
0.16666570253074878, //p3
|
||||
0.00019578093328483123 //p7
|
||||
};
|
||||
|
||||
float powf_c(float x, float n)
|
||||
{
|
||||
float a, b, c, d, xx;
|
||||
int m;
|
||||
|
||||
union {
|
||||
float f;
|
||||
int i;
|
||||
} r;
|
||||
|
||||
//extract exponent
|
||||
r.f = x;
|
||||
m = (r.i >> 23);
|
||||
m = m - 127;
|
||||
r.i = r.i - (m << 23);
|
||||
|
||||
//Taylor Polynomial (Estrins)
|
||||
xx = r.f * r.f;
|
||||
a = (__powf_lut[4] * r.f) + (__powf_lut[0]);
|
||||
b = (__powf_lut[6] * r.f) + (__powf_lut[2]);
|
||||
c = (__powf_lut[5] * r.f) + (__powf_lut[1]);
|
||||
d = (__powf_lut[7] * r.f) + (__powf_lut[3]);
|
||||
a = a + b * xx;
|
||||
c = c + d * xx;
|
||||
xx = xx * xx;
|
||||
r.f = a + c * xx;
|
||||
|
||||
//add exponent
|
||||
r.f = r.f + ((float) m) * __powf_rng[1];
|
||||
|
||||
r.f = r.f * n;
|
||||
|
||||
|
||||
//Range Reduction:
|
||||
m = (int) (r.f * __powf_rng[0]);
|
||||
r.f = r.f - ((float) m) * __powf_rng[1];
|
||||
|
||||
//Taylor Polynomial (Estrins)
|
||||
a = (__powf_lut[12] * r.f) + (__powf_lut[8]);
|
||||
b = (__powf_lut[14] * r.f) + (__powf_lut[10]);
|
||||
c = (__powf_lut[13] * r.f) + (__powf_lut[9]);
|
||||
d = (__powf_lut[15] * r.f) + (__powf_lut[11]);
|
||||
xx = r.f * r.f;
|
||||
a = a + b * xx;
|
||||
c = c + d * xx;
|
||||
xx = xx* xx;
|
||||
r.f = a + c * xx;
|
||||
|
||||
//multiply by 2 ^ m
|
||||
m = m << 23;
|
||||
r.i = r.i + m;
|
||||
|
||||
return r.f;
|
||||
}
|
||||
|
||||
float powf_neon_hfp(float x, float n)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
|
||||
"vdup.f32 d16, d0[1] \n\t" //d16 = {y,y};
|
||||
"vdup.f32 d0, d0[0] \n\t" //d0 = {x,x};
|
||||
|
||||
//extract exponent
|
||||
"vmov.i32 d2, #127 \n\t" //d2 = 127;
|
||||
"vshr.u32 d6, d0, #23 \n\t" //d6 = d0 >> 23;
|
||||
"vsub.i32 d6, d6, d2 \n\t" //d6 = d6 - d2;
|
||||
"vshl.u32 d1, d6, #23 \n\t" //d1 = d6 << 23;
|
||||
"vsub.i32 d0, d0, d1 \n\t" //d0 = d0 + d1;
|
||||
|
||||
//polynomial:
|
||||
"vmul.f32 d1, d0, d0 \n\t" //d1 = d0*d0 = {x^2, x^2}
|
||||
"vld1.32 {d2, d3, d4, d5}, [%1]! \n\t" //q1 = {p0, p4, p2, p6}, q2 = {p1, p5, p3, p7} ;
|
||||
"vmla.f32 q1, q2, d0[0] \n\t" //q1 = q1 + q2 * d0[0]
|
||||
"vmla.f32 d2, d3, d1[0] \n\t" //d2 = d2 + d3 * d1[0]
|
||||
"vmul.f32 d1, d1, d1 \n\t" //d1 = d1 * d1 = {x^4, x^4}
|
||||
"vmla.f32 d2, d1, d2[1] \n\t" //d2 = d2 + d1 * d2[1]
|
||||
|
||||
//add exponent
|
||||
"vld1.32 d7, [%0] \n\t" //d7 = {invrange, range}
|
||||
"vcvt.f32.s32 d6, d6 \n\t" //d6 = (float) d6
|
||||
"vmla.f32 d2, d6, d7[1] \n\t" //d2 = d2 + d6 * d7[1]
|
||||
|
||||
"vdup.f32 d0, d2[0] \n\t" //d0 = d2[0]
|
||||
"vmul.f32 d0, d0, d16 \n\t" //d0 = d0 * d16
|
||||
|
||||
//Range Reduction:
|
||||
"vmul.f32 d6, d0, d7[0] \n\t" //d6 = d0 * d7[0]
|
||||
"vcvt.u32.f32 d6, d6 \n\t" //d6 = (int) d6
|
||||
"vcvt.f32.u32 d1, d6 \n\t" //d1 = (float) d6
|
||||
"vmls.f32 d0, d1, d7[1] \n\t" //d0 = d0 - d1 * d7[1]
|
||||
|
||||
//polynomial:
|
||||
"vmul.f32 d1, d0, d0 \n\t" //d1 = d0*d0 = {x^2, x^2}
|
||||
"vld1.32 {d2, d3, d4, d5}, [%1] \n\t" //q1 = {p0, p4, p2, p6}, q2 = {p1, p5, p3, p7} ;
|
||||
"vmla.f32 q1, q2, d0[0] \n\t" //q1 = q1 + q2 * d0[0]
|
||||
"vmla.f32 d2, d3, d1[0] \n\t" //d2 = d2 + d3 * d1[0]
|
||||
"vmul.f32 d1, d1, d1 \n\t" //d1 = d1 * d1 = {x^4, x^4}
|
||||
"vmla.f32 d2, d1, d2[1] \n\t" //d2 = d2 + d1 * d2[1]
|
||||
|
||||
//multiply by 2 ^ m
|
||||
"vshl.i32 d6, d6, #23 \n\t" //d6 = d6 << 23
|
||||
"vadd.i32 d0, d2, d6 \n\t" //d0 = d2 + d6
|
||||
|
||||
|
||||
:: "r"(__powf_rng), "r"(__powf_lut)
|
||||
: "d0", "d1", "d2","d3", "d4", "d5", "d6", "d7"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
float powf_neon_sfp(float x, float n)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile ("vmov.f32 s0, r0 \n\t");
|
||||
asm volatile ("vmov.f32 s1, r1 \n\t");
|
||||
powf_neon_hfp(x, n);
|
||||
asm volatile ("vmov.f32 r0, s0 \n\t");
|
||||
#else
|
||||
return powf_c(x, n);
|
||||
#endif
|
||||
};
|
||||
Vendored
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
void
|
||||
enable_runfast()
|
||||
{
|
||||
#ifdef __arm__
|
||||
static const unsigned int x = 0x04086060;
|
||||
static const unsigned int y = 0x03000000;
|
||||
int r;
|
||||
asm volatile (
|
||||
"fmrx %0, fpscr \n\t" //r0 = FPSCR
|
||||
"and %0, %0, %1 \n\t" //r0 = r0 & 0x04086060
|
||||
"orr %0, %0, %2 \n\t" //r0 = r0 | 0x03000000
|
||||
"fmxr fpscr, %0 \n\t" //FPSCR = r0
|
||||
: "=r"(r)
|
||||
: "r"(x), "r"(y)
|
||||
);
|
||||
#endif
|
||||
}
|
||||
Vendored
+163
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "math_neon.h"
|
||||
|
||||
const float __sincosf_rng[2] = {
|
||||
2.0 / M_PI,
|
||||
M_PI / 2.0
|
||||
};
|
||||
|
||||
const float __sincosf_lut[8] = {
|
||||
-0.00018365f, //p7
|
||||
-0.00018365f, //p7
|
||||
+0.00830636f, //p5
|
||||
+0.00830636f, //p5
|
||||
-0.16664831f, //p3
|
||||
-0.16664831f, //p3
|
||||
+0.99999661f, //p1
|
||||
+0.99999661f, //p1
|
||||
};
|
||||
|
||||
void sincosf_c( float x, float r[2])
|
||||
{
|
||||
union {
|
||||
float f;
|
||||
int i;
|
||||
} ax, bx;
|
||||
|
||||
float y;
|
||||
float a, b, c, d, xx, yy;
|
||||
int m, n, o, p;
|
||||
|
||||
y = x + __sincosf_rng[1];
|
||||
ax.f = fabsf(x);
|
||||
bx.f = fabsf(y);
|
||||
|
||||
//Range Reduction:
|
||||
m = (int) (ax.f * __sincosf_rng[0]);
|
||||
o = (int) (bx.f * __sincosf_rng[0]);
|
||||
ax.f = ax.f - (((float)m) * __sincosf_rng[1]);
|
||||
bx.f = bx.f - (((float)o) * __sincosf_rng[1]);
|
||||
|
||||
//Test Quadrant
|
||||
n = m & 1;
|
||||
p = o & 1;
|
||||
ax.f = ax.f - n * __sincosf_rng[1];
|
||||
bx.f = bx.f - p * __sincosf_rng[1];
|
||||
m = m >> 1;
|
||||
o = o >> 1;
|
||||
n = n ^ m;
|
||||
p = p ^ o;
|
||||
m = (x < 0.0);
|
||||
o = (y < 0.0);
|
||||
n = n ^ m;
|
||||
p = p ^ o;
|
||||
n = n << 31;
|
||||
p = p << 31;
|
||||
ax.i = ax.i ^ n;
|
||||
bx.i = bx.i ^ p;
|
||||
|
||||
//Taylor Polynomial
|
||||
xx = ax.f * ax.f;
|
||||
yy = bx.f * bx.f;
|
||||
r[0] = __sincosf_lut[0];
|
||||
r[1] = __sincosf_lut[1];
|
||||
r[0] = r[0] * xx + __sincosf_lut[2];
|
||||
r[1] = r[1] * yy + __sincosf_lut[3];
|
||||
r[0] = r[0] * xx + __sincosf_lut[4];
|
||||
r[1] = r[1] * yy + __sincosf_lut[5];
|
||||
r[0] = r[0] * xx + __sincosf_lut[6];
|
||||
r[1] = r[1] * yy + __sincosf_lut[7];
|
||||
r[0] = r[0] * ax.f;
|
||||
r[1] = r[1] * bx.f;
|
||||
|
||||
}
|
||||
|
||||
void sincosf_neon_hfp(float x, float r[2])
|
||||
{
|
||||
//HACK: Assumes for softfp that r1 = x, and for hardfp that s0 = x.
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
//{x, y} = {x, x + pi/2}
|
||||
"vdup.f32 d1, d0[0] \n\t" //d1 = {x, x}
|
||||
"vld1.32 d3, [%1] \n\t" //d3 = {invrange, range}
|
||||
"vadd.f32 d0, d1, d3 \n\t" //d0 = d1 + d3
|
||||
"vmov.f32 s0, s2 \n\t" //d0[0] = d1[0]
|
||||
"vabs.f32 d1, d0 \n\t" //d1 = {abs(x), abs(y)}
|
||||
|
||||
//Range Reduction:
|
||||
"vmul.f32 d2, d1, d3[0] \n\t" //d2 = d1 * d3[0]
|
||||
"vcvt.u32.f32 d2, d2 \n\t" //d2 = (int) d2
|
||||
"vcvt.f32.u32 d4, d2 \n\t" //d4 = (float) d2
|
||||
"vmls.f32 d1, d4, d3[1] \n\t" //d1 = d1 - d4 * d3[1]
|
||||
|
||||
//Checking Quadrant:
|
||||
//ax = ax - (k&1) * M_PI_2
|
||||
"vmov.i32 d4, #1 \n\t" //d4 = 1
|
||||
"vand.i32 d4, d4, d2 \n\t" //d4 = d4 & d2
|
||||
"vcvt.f32.u32 d5, d4 \n\t" //d5 = (float) d4
|
||||
"vmls.f32 d1, d5, d3[1] \n\t" //d1 = d1 - d5 * d3[1]
|
||||
|
||||
//ax = ax ^ ((k & 1) ^ (k >> 1) ^ (x < 0) << 31)
|
||||
"vshr.u32 d3, d2, #1 \n\t" //d3 = d2 >> 1
|
||||
"veor.i32 d4, d4, d3 \n\t" //d4 = d4 ^ d3
|
||||
"vclt.f32 d3, d0, #0 \n\t" //d3 = (d0 < 0.0)
|
||||
"veor.i32 d4, d4, d3 \n\t" //d4 = d4 ^ d3
|
||||
"vshl.i32 d4, d4, #31 \n\t" //d4 = d4 << 31
|
||||
"veor.i32 d0, d1, d4 \n\t" //d0 = d1 ^ d4
|
||||
|
||||
//polynomial:
|
||||
"vldm %2!, {d2, d3} \n\t" //d2 = {p7, p7}, d3 = {p5, p5}, r3 += 4;
|
||||
"vmul.f32 d1, d0, d0 \n\t" //d1 = d0 * d0 = {x^2, y^2}
|
||||
"vldm %2!, {d4} \n\t" //d4 = {p3, p3}, r3 += 2;
|
||||
"vmla.f32 d3, d2, d1 \n\t" //d3 = d3 + d2 * d1;
|
||||
"vldm %2!, {d5} \n\t" //d5 = {p1, p1}, r3 += 2;
|
||||
"vmla.f32 d4, d3, d1 \n\t" //d4 = d4 + d3 * d1;
|
||||
"vmla.f32 d5, d4, d1 \n\t" //d5 = d5 + d4 * d1;
|
||||
"vmul.f32 d5, d5, d0 \n\t" //d5 = d5 * d0;
|
||||
|
||||
"vstm.f32 %0, {d5} \n\t" //r[0] = d5[0], r[1]=d5[1];
|
||||
|
||||
: "+r"(r)
|
||||
: "r"(__sincosf_rng), "r"(__sincosf_lut)
|
||||
: "d0", "d1", "d2", "d3", "d4", "d5"
|
||||
);
|
||||
#else
|
||||
sincosf_c(x, r);
|
||||
#endif
|
||||
}
|
||||
|
||||
void sincosf_neon_sfp(float x, float r[2])
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile ("vdup.f32 d0, r0 \n\t");
|
||||
sincosf_neon_hfp(x, r);
|
||||
asm volatile ("vmov.f32 r0, s0 \n\t");
|
||||
#else
|
||||
sincosf_c(x, r);
|
||||
#endif
|
||||
};
|
||||
|
||||
Vendored
+128
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "math_neon.h"
|
||||
|
||||
static const float __sinf_rng[2] = {
|
||||
2.0 / M_PI,
|
||||
M_PI / 2.0
|
||||
} ALIGN(16);
|
||||
|
||||
static const float __sinf_lut[4] = {
|
||||
-0.00018365f, //p7
|
||||
-0.16664831f, //p3
|
||||
+0.00830636f, //p5
|
||||
+0.99999661f, //p1
|
||||
} ALIGN(16);
|
||||
|
||||
float sinf_c(float x)
|
||||
{
|
||||
union {
|
||||
float f;
|
||||
int i;
|
||||
} ax;
|
||||
|
||||
float r, a, b, xx;
|
||||
int m, n;
|
||||
|
||||
ax.f = fabsf(x);
|
||||
|
||||
//Range Reduction:
|
||||
m = (int) (ax.f * __sinf_rng[0]);
|
||||
ax.f = ax.f - (((float)m) * __sinf_rng[1]);
|
||||
|
||||
//Test Quadrant
|
||||
n = m & 1;
|
||||
ax.f = ax.f - n * __sinf_rng[1];
|
||||
m = m >> 1;
|
||||
n = n ^ m;
|
||||
m = (x < 0.0);
|
||||
n = n ^ m;
|
||||
n = n << 31;
|
||||
ax.i = ax.i ^ n;
|
||||
|
||||
//Taylor Polynomial (Estrins)
|
||||
xx = ax.f * ax.f;
|
||||
a = (__sinf_lut[0] * ax.f) * xx + (__sinf_lut[2] * ax.f);
|
||||
b = (__sinf_lut[1] * ax.f) * xx + (__sinf_lut[3] * ax.f);
|
||||
xx = xx * xx;
|
||||
r = b + a * xx;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
float sinf_neon_hfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
|
||||
"vld1.32 d3, [%0] \n\t" //d3 = {invrange, range}
|
||||
"vdup.f32 d0, d0[0] \n\t" //d0 = {x, x}
|
||||
"vabs.f32 d1, d0 \n\t" //d1 = {ax, ax}
|
||||
|
||||
"vmul.f32 d2, d1, d3[0] \n\t" //d2 = d1 * d3[0]
|
||||
"vcvt.u32.f32 d2, d2 \n\t" //d2 = (int) d2
|
||||
"vmov.i32 d5, #1 \n\t" //d5 = 1
|
||||
"vcvt.f32.u32 d4, d2 \n\t" //d4 = (float) d2
|
||||
"vshr.u32 d7, d2, #1 \n\t" //d7 = d2 >> 1
|
||||
"vmls.f32 d1, d4, d3[1] \n\t" //d1 = d1 - d4 * d3[1]
|
||||
|
||||
"vand.i32 d5, d2, d5 \n\t" //d5 = d2 & d5
|
||||
"vclt.f32 d18, d0, #0 \n\t" //d18 = (d0 < 0.0)
|
||||
"vcvt.f32.u32 d6, d5 \n\t" //d6 = (float) d5
|
||||
"vmls.f32 d1, d6, d3[1] \n\t" //d1 = d1 - d6 * d3[1]
|
||||
"veor.i32 d5, d5, d7 \n\t" //d5 = d5 ^ d7
|
||||
"vmul.f32 d2, d1, d1 \n\t" //d2 = d1*d1 = {x^2, x^2}
|
||||
|
||||
"vld1.32 {d16, d17}, [%1] \n\t" //q8 = {p7, p3, p5, p1}
|
||||
"veor.i32 d5, d5, d18 \n\t" //d5 = d5 ^ d18
|
||||
"vshl.i32 d5, d5, #31 \n\t" //d5 = d5 << 31
|
||||
"veor.i32 d1, d1, d5 \n\t" //d1 = d1 ^ d5
|
||||
|
||||
"vmul.f32 d3, d2, d2 \n\t" //d3 = d2*d2 = {x^4, x^4}
|
||||
"vmul.f32 q0, q8, d1[0] \n\t" //q0 = q8 * d1[0] = {p7x, p3x, p5x, p1x}
|
||||
"vmla.f32 d1, d0, d2[0] \n\t" //d1 = d1 + d0*d2 = {p5x + p7x^3, p1x + p3x^3}
|
||||
"vmla.f32 d1, d3, d1[0] \n\t" //d1 = d1 + d3*d0 = {...., p1x + p3x^3 + p5x^5 + p7x^7}
|
||||
|
||||
"vmov.f32 s0, s3 \n\t" //s0 = s3
|
||||
:
|
||||
: "r"(__sinf_rng), "r"(__sinf_lut)
|
||||
: "q0", "q1", "q2", "q3", "q8", "q9"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
float sinf_neon_sfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile ("vdup.f32 d0, r0 \n\t");
|
||||
sinf_neon_hfp(x);
|
||||
asm volatile ("vmov.f32 r0, s0 \n\t");
|
||||
#else
|
||||
return sinf_c(x);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
Vendored
+110
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "math_neon.h"
|
||||
|
||||
const float __sinfv_rng[2] = {
|
||||
2.0 / M_PI,
|
||||
M_PI / 2.0,
|
||||
};
|
||||
|
||||
const float __sinfv_lut[4] = {
|
||||
-0.00018365f, //p7
|
||||
-0.16664831f, //p3
|
||||
+0.00830636f, //p5
|
||||
+0.99999661f, //p1
|
||||
};
|
||||
|
||||
void sinfv_c(float *x, int n, float *r)
|
||||
{
|
||||
union {
|
||||
float f;
|
||||
int i;
|
||||
} ax, bx;
|
||||
|
||||
float aa, ab, ba, bb, axx, bxx;
|
||||
int am, bm, an, bn;
|
||||
|
||||
if (n & 0x1) {
|
||||
*r++ = sinf_c(*x++);
|
||||
n--;
|
||||
}
|
||||
|
||||
float rng0 = __sinfv_rng[0];
|
||||
float rng1 = __sinfv_rng[1];
|
||||
|
||||
while(n > 0){
|
||||
|
||||
float x0 = *x++;
|
||||
float x1 = *x++;
|
||||
|
||||
ax.f = fabsf(x0);
|
||||
bx.f = fabsf(x1);
|
||||
|
||||
//Range Reduction:
|
||||
am = (int) (ax.f * rng0);
|
||||
bm = (int) (bx.f * rng0);
|
||||
|
||||
ax.f = ax.f - (((float)am) * rng1);
|
||||
bx.f = bx.f - (((float)bm) * rng1);
|
||||
|
||||
//Test Quadrant
|
||||
an = am & 1;
|
||||
bn = bm & 1;
|
||||
ax.f = ax.f - an * rng1;
|
||||
bx.f = bx.f - bn * rng1;
|
||||
am = (am & 2) >> 1;
|
||||
bm = (bm & 2) >> 1;
|
||||
ax.i = ax.i ^ ((an ^ am ^ (x0 < 0)) << 31);
|
||||
bx.i = bx.i ^ ((bn ^ bm ^ (x1 < 0)) << 31);
|
||||
|
||||
//Taylor Polynomial (Estrins)
|
||||
axx = ax.f * ax.f;
|
||||
bxx = bx.f * bx.f;
|
||||
aa = (__sinfv_lut[0] * ax.f) * axx + (__sinfv_lut[2] * ax.f);
|
||||
ba = (__sinfv_lut[0] * bx.f) * bxx + (__sinfv_lut[2] * bx.f);
|
||||
ab = (__sinfv_lut[1] * ax.f) * axx + (__sinfv_lut[3] * ax.f);
|
||||
bb = (__sinfv_lut[1] * bx.f) * bxx + (__sinfv_lut[3] * bx.f);
|
||||
axx = axx * axx;
|
||||
bxx = bxx * bxx;
|
||||
*r++ = ab + aa * axx;
|
||||
*r++ = bb + ba * bxx;
|
||||
n -= 2;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void sinfv_neon(float *x, int n, float *r)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (""
|
||||
:
|
||||
:"r"(x), "r"(n)
|
||||
);
|
||||
#else
|
||||
sinfv_c(x, n, r);
|
||||
#endif
|
||||
}
|
||||
Vendored
+120
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "math_neon.h"
|
||||
|
||||
const float __sinhf_rng[2] = {
|
||||
1.442695041f,
|
||||
0.693147180f
|
||||
};
|
||||
|
||||
const float __sinhf_lut[16] = {
|
||||
0.00019578093328483123, //p7
|
||||
0.00019578093328483123, //p7
|
||||
0.0014122663401803872, //p6
|
||||
0.0014122663401803872, //p6
|
||||
0.008336936973260111, //p5
|
||||
0.008336936973260111, //p5
|
||||
0.04165989275009526, //p4
|
||||
0.04165989275009526, //p4
|
||||
0.16666570253074878, //p3
|
||||
0.16666570253074878, //p3
|
||||
0.5000006143673624, //p2
|
||||
0.5000006143673624, //p2
|
||||
1.000000059694879, //p1
|
||||
1.000000059694879, //p1
|
||||
0.9999999916728642, //p0
|
||||
0.9999999916728642 //p0
|
||||
};
|
||||
|
||||
|
||||
float sinhf_c(float x)
|
||||
{
|
||||
float a, b, xx;
|
||||
xx = -x;
|
||||
a = expf_c(x);
|
||||
b = expf_c(xx);
|
||||
a = a - b;
|
||||
a = a * 0.5f;
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
float sinhf_neon_hfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
"vdup.f32 d0, d0[0] \n\t" //d0 = {x, x}
|
||||
"fnegs s1, s1 \n\t" //s1 = -s1
|
||||
|
||||
//Range Reduction:
|
||||
"vld1.32 d2, [%0] \n\t" //d2 = {invrange, range}
|
||||
"vld1.32 {d16, d17}, [%1]! \n\t"
|
||||
"vmul.f32 d6, d0, d2[0] \n\t" //d6 = d0 * d2[0]
|
||||
"vcvt.s32.f32 d6, d6 \n\t" //d6 = (int) d6
|
||||
"vld1.32 {d18}, [%1]! \n\t"
|
||||
"vcvt.f32.s32 d1, d6 \n\t" //d1 = (float) d6
|
||||
"vld1.32 {d19}, [%1]! \n\t"
|
||||
"vmls.f32 d0, d1, d2[1] \n\t" //d0 = d0 - d1 * d2[1]
|
||||
"vld1.32 {d20}, [%1]! \n\t"
|
||||
|
||||
//polynomial:
|
||||
"vmla.f32 d17, d16, d0 \n\t" //d17 = d17 + d16 * d0;
|
||||
"vld1.32 {d21}, [%1]! \n\t"
|
||||
"vmla.f32 d18, d17, d0 \n\t" //d18 = d18 + d17 * d0;
|
||||
"vld1.32 {d22}, [%1]! \n\t"
|
||||
"vmla.f32 d19, d18, d0 \n\t" //d19 = d19 + d18 * d0;
|
||||
"vld1.32 {d23}, [%1]! \n\t"
|
||||
"vmla.f32 d20, d19, d0 \n\t" //d20 = d20 + d19 * d0;
|
||||
"vmla.f32 d21, d20, d0 \n\t" //d21 = d21 + d20 * d0;
|
||||
"vmla.f32 d22, d21, d0 \n\t" //d22 = d22 + d21 * d0;
|
||||
"vmla.f32 d23, d22, d0 \n\t" //d23 = d23 + d22 * d0;
|
||||
|
||||
//multiply by 2 ^ m
|
||||
"vshl.i32 d6, d6, #23 \n\t" //d6 = d6 << 23
|
||||
"vadd.i32 d0, d23, d6 \n\t" //d0 = d22 + d6
|
||||
|
||||
"vdup.f32 d2, d0[1] \n\t" //d2 = s1
|
||||
"vmov.f32 d1, #0.5 \n\t" //d1 = 0.5
|
||||
"vsub.f32 d0, d0, d2 \n\t" //d0 = d0 - d2
|
||||
"vmul.f32 d0, d1 \n\t" //d0 = d0 * d1
|
||||
|
||||
:: "r"(__sinhf_rng), "r"(__sinhf_lut)
|
||||
: "d0", "d1", "q1", "q2", "d6"
|
||||
);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
float sinhf_neon_sfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile ("vmov.f32 s0, r0 \n\t");
|
||||
sinhf_neon_hfp(x);
|
||||
asm volatile ("vmov.f32 r0, s0 \n\t");
|
||||
#else
|
||||
return sinhf_c(x);
|
||||
#endif
|
||||
};
|
||||
Vendored
+105
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Test func : sqrtf(x)
|
||||
Test Range: 0 < x < 1,000,000,000
|
||||
Peak Error: ~0.0010%
|
||||
RMS Error: ~0.0005%
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "math_neon.h"
|
||||
|
||||
float sqrtf_c(float x)
|
||||
{
|
||||
|
||||
float b, c;
|
||||
int m;
|
||||
union {
|
||||
float f;
|
||||
int i;
|
||||
} a;
|
||||
|
||||
//fast invsqrt approx
|
||||
a.f = x;
|
||||
a.i = 0x5F3759DF - (a.i >> 1); //VRSQRTE
|
||||
c = x * a.f;
|
||||
b = (3.0f - c * a.f) * 0.5; //VRSQRTS
|
||||
a.f = a.f * b;
|
||||
c = x * a.f;
|
||||
b = (3.0f - c * a.f) * 0.5;
|
||||
a.f = a.f * b;
|
||||
|
||||
//fast inverse approx
|
||||
x = a.f;
|
||||
m = 0x3F800000 - (a.i & 0x7F800000);
|
||||
a.i = a.i + m;
|
||||
a.f = 1.41176471f - 0.47058824f * a.f;
|
||||
a.i = a.i + m;
|
||||
b = 2.0 - a.f * x;
|
||||
a.f = a.f * b;
|
||||
b = 2.0 - a.f * x;
|
||||
a.f = a.f * b;
|
||||
|
||||
return a.f;
|
||||
}
|
||||
|
||||
float sqrtf_neon_hfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
|
||||
//fast invsqrt approx
|
||||
"vmov.f32 d1, d0 \n\t" //d1 = d0
|
||||
"vrsqrte.f32 d0, d0 \n\t" //d0 = ~ 1.0 / sqrt(d0)
|
||||
"vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1
|
||||
"vrsqrts.f32 d3, d2, d0 \n\t" //d3 = (3 - d0 * d2) / 2
|
||||
"vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d3
|
||||
"vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1
|
||||
"vrsqrts.f32 d3, d2, d0 \n\t" //d4 = (3 - d0 * d3) / 2
|
||||
"vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d3
|
||||
|
||||
//fast reciporical approximation
|
||||
"vrecpe.f32 d1, d0 \n\t" //d1 = ~ 1 / d0;
|
||||
"vrecps.f32 d2, d1, d0 \n\t" //d2 = 2.0 - d1 * d0;
|
||||
"vmul.f32 d1, d1, d2 \n\t" //d1 = d1 * d2;
|
||||
"vrecps.f32 d2, d1, d0 \n\t" //d2 = 2.0 - d1 * d0;
|
||||
"vmul.f32 d0, d1, d2 \n\t" //d0 = d1 * d2;
|
||||
|
||||
::: "d0", "d1", "d2", "d3"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
float sqrtf_neon_sfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile ("vmov.f32 s0, r0 \n\t");
|
||||
sqrtf_neon_hfp(x);
|
||||
asm volatile ("vmov.f32 r0, s0 \n\t");
|
||||
#else
|
||||
return sqrtf_c(x);
|
||||
#endif
|
||||
};
|
||||
Vendored
+147
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
/*
|
||||
Test func : sqrtf(x)
|
||||
Test Range: 0 < x < 1,000,000,000
|
||||
Peak Error: ~0.0010%
|
||||
RMS Error: ~0.0005%
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "math_neon.h"
|
||||
|
||||
void sqrtfv_c(float *x, int n, float *r)
|
||||
{
|
||||
|
||||
float x0, x1;
|
||||
float b0, b1, c0, c1;
|
||||
int m0, m1;
|
||||
union {
|
||||
float f;
|
||||
int i;
|
||||
} a0, a1;
|
||||
|
||||
|
||||
if (n & 0x1){
|
||||
*r++ = sqrtf_c(*x++);
|
||||
n--;
|
||||
}
|
||||
|
||||
while(n > 0){
|
||||
|
||||
x0 = *x++;
|
||||
x1 = *x++;
|
||||
|
||||
//fast invsqrt approx
|
||||
a0.f = x0;
|
||||
a1.f = x1;
|
||||
a0.i = 0x5F3759DF - (a0.i >> 1); //VRSQRTE
|
||||
a1.i = 0x5F3759DF - (a1.i >> 1); //VRSQRTE
|
||||
c0 = x0 * a0.f;
|
||||
c1 = x1 * a1.f;
|
||||
b0 = (3.0f - c0 * a0.f) * 0.5; //VRSQRTS
|
||||
b1 = (3.0f - c1 * a1.f) * 0.5; //VRSQRTS
|
||||
a0.f = a0.f * b0;
|
||||
a1.f = a1.f * b1;
|
||||
c0 = x0 * a0.f;
|
||||
c1 = x1 * a1.f;
|
||||
b0 = (3.0f - c0 * a0.f) * 0.5; //VRSQRTS
|
||||
b1 = (3.0f - c1 * a1.f) * 0.5; //VRSQRTS
|
||||
a0.f = a0.f * b0;
|
||||
a1.f = a1.f * b1;
|
||||
|
||||
//fast inverse approx
|
||||
c0 = a0.f;
|
||||
c0 = a1.f;
|
||||
m0 = 0x3F800000 - (a0.i & 0x7F800000);
|
||||
m1 = 0x3F800000 - (a1.i & 0x7F800000);
|
||||
a0.i = a0.i + m0;
|
||||
a1.i = a1.i + m1;
|
||||
a0.f = 1.41176471f - 0.47058824f * a0.f;
|
||||
a1.f = 1.41176471f - 0.47058824f * a1.f;
|
||||
a0.i = a0.i + m0;
|
||||
a1.i = a1.i + m1;
|
||||
b0 = 2.0 - a0.f * c0;
|
||||
b1 = 2.0 - a1.f * c1;
|
||||
a0.f = a0.f * b0;
|
||||
a1.f = a1.f * b1;
|
||||
b0 = 2.0 - a0.f * c0;
|
||||
b1 = 2.0 - a1.f * c1;
|
||||
a0.f = a0.f * b0;
|
||||
a1.f = a1.f * b1;
|
||||
|
||||
*r++ = a0.f;
|
||||
*r++ = a1.f;
|
||||
n -= 2;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void sqrtfv_neon(float *x, int n, float *r)
|
||||
{
|
||||
#if 0
|
||||
asm volatile (
|
||||
|
||||
"tst r1, #1 \n\t" //r1 & 1
|
||||
"beq 1f \n\t" //
|
||||
|
||||
"vld1.32 d0[0], [r0]! \n\t" //s0 = *x++
|
||||
"mov ip, lr \n\t" //ip = lr
|
||||
//"bl sqrtf_neon_hfp \n\t" //sqrtf_neon
|
||||
"mov lr, ip \n\t" //lr = ip
|
||||
"vst1.32 d0[0], [r2]! \n\t" //*r++ = r0
|
||||
"subs r1, r1, #1 \n\t" //r1 = r1 - 1;
|
||||
"bxeq lr \n\t" //
|
||||
|
||||
"1: \n\t" //
|
||||
|
||||
"vld1.32 d0, [r0]! \n\t" //d0 = (*x[0], *x[1]), x+=2;
|
||||
|
||||
//fast invsqrt approx
|
||||
"vmov.f32 d1, d0 \n\t" //d1 = d0
|
||||
"vrsqrte.f32 d0, d0 \n\t" //d0 = ~ 1.0 / sqrt(d0)
|
||||
"vmul.f32 d2, d0, d1 \n\t" //d3 = d0 * d2
|
||||
"vrsqrts.f32 d3, d2, d0 \n\t" //d4 = (3 - d0 * d3) / 2
|
||||
"vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d4
|
||||
"vmul.f32 d2, d0, d1 \n\t" //d3 = d0 * d2
|
||||
"vrsqrts.f32 d3, d2, d0 \n\t" //d4 = (3 - d0 * d3) / 2
|
||||
"vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d4
|
||||
|
||||
//fast reciporical approximation
|
||||
"vrecpe.f32 d1, d0 \n\t" //d1 = ~ 1 / d0;
|
||||
"vrecps.f32 d2, d1, d0 \n\t" //d2 = 2.0 - d1 * d0;
|
||||
"vmul.f32 d1, d1, d2 \n\t" //d1 = d1 * d2;
|
||||
"vrecps.f32 d2, d1, d0 \n\t" //d2 = 2.0 - d1 * d0;
|
||||
"vmul.f32 d0, d1, d2 \n\t" //d0 = d1 * d2;
|
||||
|
||||
"vst1.64 d0, [r2]! \n\t" //*r++ = d0;
|
||||
"subs r1, r1, #2 \n\t" //n = n - 2; update flags
|
||||
"bgt 1b \n\t" //
|
||||
|
||||
::: "d0", "d1", "d2", "d3"
|
||||
);
|
||||
#else
|
||||
sqrtfv_c(x, n, r);
|
||||
#endif
|
||||
}
|
||||
Vendored
+156
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "math_neon.h"
|
||||
|
||||
const float __tanf_rng[2] = {
|
||||
2.0 / M_PI,
|
||||
M_PI / 2.0
|
||||
};
|
||||
|
||||
const float __tanf_lut[4] = {
|
||||
-0.00018365f, //p7
|
||||
-0.16664831f, //p3
|
||||
+0.00830636f, //p5
|
||||
+0.99999661f, //p1
|
||||
};
|
||||
|
||||
float tanf_c(float x){
|
||||
|
||||
union {
|
||||
float f;
|
||||
int i;
|
||||
} ax, c;
|
||||
|
||||
float r, a, b, xx, cc, cx;
|
||||
int m;
|
||||
|
||||
ax.f = fabsf(x);
|
||||
|
||||
//Range Reduction:
|
||||
m = (int) (ax.f * __tanf_rng[0]);
|
||||
ax.f = ax.f - (((float)m) * __tanf_rng[1]);
|
||||
|
||||
//Test Quadrant
|
||||
ax.f = ax.f - (m & 1) * __tanf_rng[1];
|
||||
ax.i = ax.i ^ ((*(int*)&x) & 0x80000000);
|
||||
|
||||
//Taylor Polynomial (Estrins)
|
||||
xx = ax.f * ax.f;
|
||||
a = (__tanf_lut[0] * ax.f) * xx + (__tanf_lut[2] * ax.f);
|
||||
b = (__tanf_lut[1] * ax.f) * xx + (__tanf_lut[3] * ax.f);
|
||||
xx = xx * xx;
|
||||
r = b + a * xx;
|
||||
|
||||
//cosine
|
||||
c.f = 1.0 - r * r;
|
||||
|
||||
//fast invsqrt approximation (2x newton iterations)
|
||||
cc = c.f;
|
||||
c.i = 0x5F3759DF - (c.i >> 1); //VRSQRTE
|
||||
cx = cc * c.f;
|
||||
a = (3.0f - cx * c.f) / 2; //VRSQRTS
|
||||
c.f = c.f * a;
|
||||
cx = cc * c.f;
|
||||
a = (3.0f - cx * c.f) / 2;
|
||||
c.f = c.f * a;
|
||||
|
||||
r = r * c.f;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
float tanf_neon_hfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
|
||||
"vdup.f32 d0, d0[0] \n\t" //d0 = {x, x}
|
||||
"vabs.f32 d1, d0 \n\t" //d1 = {ax, ax}
|
||||
|
||||
//Range Reduction:
|
||||
"vld1.32 d3, [%0] \n\t" //d3 = {invrange, range}
|
||||
"vmul.f32 d2, d1, d3[0] \n\t" //d2 = d1 * d3[0]
|
||||
"vcvt.u32.f32 d2, d2 \n\t" //d2 = (int) d2
|
||||
"vcvt.f32.u32 d4, d2 \n\t" //d4 = (float) d2
|
||||
"vmls.f32 d1, d4, d3[1] \n\t" //d1 = d1 - d4 * d3[1]
|
||||
|
||||
//Checking Quadrant:
|
||||
//ax = ax - (k&1) * M_PI_2
|
||||
"vmov.i32 d4, #1 \n\t" //d4 = 1
|
||||
"vand.i32 d2, d2, d4 \n\t" //d2 = d2 & d4
|
||||
"vcvt.f32.u32 d2, d2 \n\t" //d2 = (float) d2
|
||||
"vmls.f32 d1, d2, d3[1] \n\t" //d1 = d1 - d2 * d3[1]
|
||||
|
||||
//ax = ax ^ ( x.i & 0x800000000)
|
||||
"vmov.i32 d4, #0x80000000 \n\t" //d4 = 0x80000000
|
||||
"vand.i32 d0, d0, d4 \n\t" //d0 = d0 & d4
|
||||
"veor.i32 d1, d1, d0 \n\t" //d1 = d1 ^ d0
|
||||
|
||||
//polynomial:
|
||||
"vmul.f32 d2, d1, d1 \n\t" //d2 = d1*d1 = {x^2, x^2}
|
||||
"vld1.32 {d4, d5}, [%1] \n\t" //d4 = {p7, p3}, d5 = {p5, p1}
|
||||
"vmul.f32 d3, d2, d2 \n\t" //d3 = d2*d2 = {x^4, x^4}
|
||||
"vmul.f32 q0, q2, d1[0] \n\t" //q0 = q2 * d1[0] = {p7x, p3x, p5x, p1x}
|
||||
"vmla.f32 d1, d0, d2[0] \n\t" //d1 = d1 + d0*d2 = {p5x + p7x^3, p1x + p3x^3}
|
||||
"vmla.f32 d1, d3, d1[0] \n\t" //d1 = d1 + d3*d0 = {..., p1x + p3x^3 + p5x^5 + p7x^7}
|
||||
|
||||
//cosine
|
||||
"vmov.f32 s1, #1.0 \n\t" //d0[1] = 1.0
|
||||
"vmls.f32 d0, d1, d1 \n\t" //d0 = {..., 1.0 - sx*sx}
|
||||
|
||||
//invsqrt approx
|
||||
"vmov.f32 d2, d0 \n\t" //d2 = d0
|
||||
"vrsqrte.f32 d0, d0 \n\t" //d0 = ~ 1.0 / sqrt(d0)
|
||||
"vmul.f32 d3, d0, d2 \n\t" //d3 = d0 * d2
|
||||
"vrsqrts.f32 d4, d3, d0 \n\t" //d4 = (3 - d0 * d3) / 2
|
||||
"vmul.f32 d0, d0, d4 \n\t" //d0 = d0 * d4
|
||||
"vmul.f32 d3, d0, d2 \n\t" //d3 = d0 * d2
|
||||
"vrsqrts.f32 d4, d3, d0 \n\t" //d4 = (3 - d0 * d3) / 2
|
||||
"vmul.f32 d0, d0, d4 \n\t" //d0 = d0 * d4
|
||||
|
||||
"vmul.f32 d0, d0, d1 \n\t" //d0 = d0 * d1
|
||||
|
||||
"vmov.f32 s0, s1 \n\t" //s0 = s1
|
||||
|
||||
:: "r"(__tanf_rng), "r"(__tanf_lut)
|
||||
: "d0", "d1", "d2", "d3", "d4", "d5"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
float tanf_neon_sfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile ("vdup.f32 d0, r0 \n\t");
|
||||
tanf_neon_hfp(x);
|
||||
asm volatile ("vmov.f32 r0, s0 \n\t");
|
||||
#else
|
||||
return tanf_c(x);
|
||||
#endif
|
||||
};
|
||||
|
||||
Vendored
+95
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "math_neon.h"
|
||||
|
||||
/*
|
||||
TanH = (e^x - e^-x) / (e^x + e^-x)
|
||||
TanH = (e^x - e^-x)(e^x) / (e^x + e^-x)(e^x)
|
||||
TanH = (e^2x - 1) / (e^2x + 1)
|
||||
|
||||
*/
|
||||
|
||||
float tanhf_c(float x)
|
||||
{
|
||||
float a, b, c;
|
||||
int m;
|
||||
union{
|
||||
float f;
|
||||
int i;
|
||||
} xx;
|
||||
|
||||
x = 2.0f * x;
|
||||
a = expf_c(x);
|
||||
c = a + 1.0f;
|
||||
|
||||
//reciporical approx.
|
||||
xx.f = c;
|
||||
m = 0x3F800000 - (xx.i & 0x7F800000);
|
||||
xx.i = xx.i + m;
|
||||
xx.f = 1.41176471f - 0.47058824f * xx.f;
|
||||
xx.i = xx.i + m;
|
||||
b = 2.0 - xx.f * c;
|
||||
xx.f = xx.f * b;
|
||||
b = 2.0 - xx.f * c;
|
||||
xx.f = xx.f * b;
|
||||
c = a - 1.0;
|
||||
xx.f *= c;
|
||||
return xx.f;
|
||||
}
|
||||
|
||||
|
||||
float tanhf_neon_hfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile ("vadd.f32 d0, d0, d0 \n\t");
|
||||
expf_neon_hfp(x);
|
||||
asm volatile (
|
||||
"vmov.f32 d2, #1.0 \n\t"
|
||||
"vsub.f32 d3, d0, d2 \n\t"
|
||||
"vadd.f32 d0, d0, d2 \n\t"
|
||||
|
||||
"vrecpe.f32 d1, d0 \n\t" //d1 = ~ 1 / d0;
|
||||
"vrecps.f32 d2, d1, d0 \n\t" //d2 = 2.0 - d1 * d0;
|
||||
"vmul.f32 d1, d1, d2 \n\t" //d1 = d1 * d2;
|
||||
"vrecps.f32 d2, d1, d0 \n\t" //d2 = 2.0 - d1 * d0;
|
||||
"vmul.f32 d0, d1, d2 \n\t" //d0 = d1 * d2;
|
||||
"vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d3;
|
||||
::: "d0", "d1", "d2", "d3"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
float tanhf_neon_sfp(float x)
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile ("vmov.f32 s0, r0 \n\t");
|
||||
tanhf_neon_hfp(x);
|
||||
asm volatile ("vmov.f32 r0, s0 \n\t");
|
||||
#else
|
||||
return tanhf_c(x);
|
||||
#endif
|
||||
};
|
||||
|
||||
Vendored
+118
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include "math_neon.h"
|
||||
|
||||
//vec2 scalar product
|
||||
float
|
||||
dot2_c(float v0[2], float v1[2])
|
||||
{
|
||||
float r;
|
||||
r = v0[0]*v1[0];
|
||||
r += v0[1]*v1[1];
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
normalize2_c(float v[2], float d[2])
|
||||
{
|
||||
float b, c, x;
|
||||
union {
|
||||
float f;
|
||||
int i;
|
||||
} a;
|
||||
|
||||
x = v[0]*v[0];
|
||||
x += v[1]*v[1];
|
||||
|
||||
//fast invsqrt approx
|
||||
a.f = x;
|
||||
a.i = 0x5F3759DF - (a.i >> 1); //VRSQRTE
|
||||
c = x * a.f;
|
||||
b = (3.0f - c * a.f) * 0.5; //VRSQRTS
|
||||
a.f = a.f * b;
|
||||
c = x * a.f;
|
||||
b = (3.0f - c * a.f) * 0.5;
|
||||
a.f = a.f * b;
|
||||
|
||||
d[0] = v[0]*a.f;
|
||||
d[1] = v[1]*a.f;
|
||||
}
|
||||
|
||||
float
|
||||
dot2_neon_hfp(float v0[2], float v1[2])
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
"vld1.32 {d2}, [%0] \n\t" //d2={x0,y0}
|
||||
"vld1.32 {d4}, [%1] \n\t" //d4={x1,y1}
|
||||
"vmul.f32 d0, d2, d4 \n\t" //d0 = d2*d4
|
||||
"vpadd.f32 d0, d0, d0 \n\t" //d0 = d[0] + d[1]
|
||||
:: "r"(v0), "r"(v1)
|
||||
:
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
float
|
||||
dot2_neon_sfp(float v0[2], float v1[2])
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
dot2_neon_hfp(v0, v1);
|
||||
asm volatile ("vmov.f32 r0, s0 \n\t");
|
||||
#else
|
||||
return dot2_c(v0, v1);
|
||||
#endif
|
||||
};
|
||||
|
||||
void
|
||||
normalize2_neon(float v[2], float d[2])
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
"vld1.32 d4, [%0] \n\t" //d4 = {x0,y0}
|
||||
"vmul.f32 d0, d4, d4 \n\t" //d0 = d2*d2
|
||||
"vpadd.f32 d0, d0 \n\t" //d0 = d[0] + d[1]
|
||||
|
||||
"vmov.f32 d1, d0 \n\t" //d1 = d0
|
||||
"vrsqrte.f32 d0, d0 \n\t" //d0 = ~ 1.0 / sqrt(d0)
|
||||
"vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1
|
||||
"vrsqrts.f32 d3, d2, d0 \n\t" //d3 = (3 - d0 * d2) / 2
|
||||
"vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d3
|
||||
"vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1
|
||||
"vrsqrts.f32 d3, d2, d0 \n\t" //d3 = (3 - d0 * d2) / 2
|
||||
"vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d3
|
||||
|
||||
"vmul.f32 d4, d4, d0[0] \n\t" //d4 = d4*d0[0]
|
||||
"vst1.32 d4, [%1] \n\t" //
|
||||
|
||||
:: "r"(v), "r"(d)
|
||||
: "d0", "d1", "d2", "d3", "d4", "memory"
|
||||
);
|
||||
#else
|
||||
normalize2_c(v, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
Vendored
+172
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "math_neon.h"
|
||||
|
||||
//vec4 scalar product
|
||||
float
|
||||
dot3_c(float v0[3], float v1[3])
|
||||
{
|
||||
float r;
|
||||
r = v0[0]*v1[0];
|
||||
r += v0[1]*v1[1];
|
||||
r += v0[2]*v1[2];
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
cross3_c(float v0[3], float v1[3], float d[3])
|
||||
{
|
||||
d[0] = v0[1]*v1[2] - v0[2]*v1[1];
|
||||
d[1] = v0[2]*v1[0] - v0[0]*v1[2];
|
||||
d[2] = v0[0]*v1[1] - v0[1]*v1[0];
|
||||
}
|
||||
|
||||
void
|
||||
normalize3_c(float v[3], float d[3])
|
||||
{
|
||||
float b, c, x;
|
||||
union {
|
||||
float f;
|
||||
int i;
|
||||
} a;
|
||||
|
||||
x = v[0]*v[0];
|
||||
x += v[1]*v[1];
|
||||
x += v[2]*v[2];
|
||||
|
||||
//fast invsqrt approx
|
||||
a.f = x;
|
||||
a.i = 0x5F3759DF - (a.i >> 1); //VRSQRTE
|
||||
c = x * a.f;
|
||||
b = (3.0f - c * a.f) * 0.5; //VRSQRTS
|
||||
a.f = a.f * b;
|
||||
c = x * a.f;
|
||||
b = (3.0f - c * a.f) * 0.5;
|
||||
a.f = a.f * b;
|
||||
|
||||
d[0] = v[0]*a.f;
|
||||
d[1] = v[1]*a.f;
|
||||
d[2] = v[2]*a.f;
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
dot3_neon_hfp(float v0[3], float v1[3])
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
"vld1.32 {d2}, [%0] \n\t" //d2={x0,y0}
|
||||
"flds s6, [%0, #8] \n\t" //d3[0]={z0}
|
||||
"vld1.32 {d4}, [%1] \n\t" //d4={x1,y1}
|
||||
"flds s10, [%1, #8] \n\t" //d5[0]={z1}
|
||||
|
||||
"vmul.f32 d0, d2, d4 \n\t" //d0= d2*d4
|
||||
"vpadd.f32 d0, d0, d0 \n\t" //d0 = d[0] + d[1]
|
||||
"vmla.f32 d0, d3, d5 \n\t" //d0 = d0 + d3*d5
|
||||
:: "r"(v0), "r"(v1)
|
||||
: "d0","d1","d2","d3","d4","d5"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
float
|
||||
dot3_neon_sfp(float v0[3], float v1[3])
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
dot3_neon_hfp(v0, v1);
|
||||
asm volatile ("vmov.f32 r0, s0 \n\t");
|
||||
#else
|
||||
return dot3_c(v0, v1);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
void cross3_neon(float v0[3], float v1[3], float d[3])
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
"flds s3, [%0] \n\t" //d1[1]={x0}
|
||||
"add %0, %0, #4 \n\t" //
|
||||
"vld1.32 {d0}, [%0] \n\t" //d0={y0,z0}
|
||||
"vmov.f32 s2, s1 \n\t" //d1[0]={z0}
|
||||
|
||||
"flds s5, [%1] \n\t" //d2[1]={x1}
|
||||
"add %1, %1, #4 \n\t" //
|
||||
"vld1.32 {d3}, [%1] \n\t" //d3={y1,z1}
|
||||
"vmov.f32 s4, s7 \n\t" //d2[0]=d3[1]
|
||||
|
||||
"vmul.f32 d4, d0, d2 \n\t" //d4=d0*d2
|
||||
"vmls.f32 d4, d1, d3 \n\t" //d4-=d1*d3
|
||||
|
||||
"vmul.f32 d5, d3, d1[1] \n\t" //d5=d3*d1[1]
|
||||
"vmls.f32 d5, d0, d2[1] \n\t" //d5-=d0*d2[1]
|
||||
|
||||
"vst1.32 d4, [%2] \n\t" //
|
||||
"add %2, %2, #8 \n\t" //
|
||||
"fsts s10, [%2] \n\t" //
|
||||
|
||||
: "+r"(v0), "+r"(v1), "+r"(d):
|
||||
: "d0", "d1", "d2", "d3", "d4", "d5", "memory"
|
||||
);
|
||||
#else
|
||||
cross3_c(v0,v1,d);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
normalize3_neon(float v[3], float d[3])
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
"vld1.32 {d4}, [%0] \n\t" //d4={x0,y0}
|
||||
"flds s10, [%0, #8] \n\t" //d5[0]={z0}
|
||||
|
||||
"vmul.f32 d0, d4, d4 \n\t" //d0= d4*d4
|
||||
"vpadd.f32 d0, d0 \n\t" //d0 = d[0] + d[1]
|
||||
"vmla.f32 d0, d5, d5 \n\t" //d0 = d0 + d5*d5
|
||||
|
||||
"vmov.f32 d1, d0 \n\t" //d1 = d0
|
||||
"vrsqrte.f32 d0, d0 \n\t" //d0 = ~ 1.0 / sqrt(d0)
|
||||
"vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1
|
||||
"vrsqrts.f32 d3, d2, d0 \n\t" //d3 = (3 - d0 * d2) / 2
|
||||
"vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d3
|
||||
"vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1
|
||||
"vrsqrts.f32 d3, d2, d0 \n\t" //d4 = (3 - d0 * d3) / 2
|
||||
"vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d4
|
||||
|
||||
"vmul.f32 q2, q2, d0[0] \n\t" //d0= d2*d4
|
||||
"vst1.32 {d4}, [%1] \n\t" //
|
||||
"fsts s10, [%1, #8] \n\t" //
|
||||
|
||||
:: "r"(v), "r"(d)
|
||||
: "d0", "d1", "d2", "d3", "d4", "d5", "memory"
|
||||
);
|
||||
#else
|
||||
normalize3_c(v, d);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
Vendored
+126
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lachlan Tychsen-Smith (lachlan.ts@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "math_neon.h"
|
||||
|
||||
|
||||
#ifdef __MATH_NEON
|
||||
#include "arm_neon.h"
|
||||
#endif
|
||||
|
||||
//vec4 scalar product
|
||||
float dot4_c(float v0[4], float v1[4])
|
||||
{
|
||||
float r;
|
||||
r = v0[0]*v1[0];
|
||||
r += v0[1]*v1[1];
|
||||
r += v0[2]*v1[2];
|
||||
r += v0[3]*v1[3];
|
||||
return r;
|
||||
}
|
||||
|
||||
void normalize4_c(float v[4], float d[4])
|
||||
{
|
||||
float b, c, x;
|
||||
union {
|
||||
float f;
|
||||
int i;
|
||||
} a;
|
||||
|
||||
x = v[0]*v[0];
|
||||
x += v[1]*v[1];
|
||||
x += v[2]*v[2];
|
||||
x += v[3]*v[3];
|
||||
|
||||
//fast invsqrt approx
|
||||
a.f = x;
|
||||
a.i = 0x5F3759DF - (a.i >> 1); //VRSQRTE
|
||||
c = x * a.f;
|
||||
b = (3.0f - c * a.f) * 0.5; //VRSQRTS
|
||||
a.f = a.f * b;
|
||||
c = x * a.f;
|
||||
b = (3.0f - c * a.f) * 0.5;
|
||||
a.f = a.f * b;
|
||||
|
||||
d[0] = v[0]*a.f;
|
||||
d[1] = v[1]*a.f;
|
||||
d[2] = v[2]*a.f;
|
||||
d[3] = v[3]*a.f;
|
||||
}
|
||||
|
||||
void normalize4_neon(float v[4], float d[4])
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
"vld1.32 {d4, d5}, [%0] \n\t" //d2={x0,y0}, d3={z0, w0}
|
||||
"vmul.f32 d0, d4, d4 \n\t" //d0= d4*d4
|
||||
"vmla.f32 d0, d5, d5 \n\t" //d0 = d0 + d5*d5
|
||||
"vpadd.f32 d0, d0 \n\t" //d0 = d[0] + d[1]
|
||||
|
||||
"vmov.f32 d1, d0 \n\t" //d1 = d0
|
||||
"vrsqrte.f32 d0, d0 \n\t" //d0 = ~ 1.0 / sqrt(d0)
|
||||
"vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1
|
||||
"vrsqrts.f32 d3, d2, d0 \n\t" //d3 = (3 - d0 * d2) / 2
|
||||
"vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d3
|
||||
"vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1
|
||||
"vrsqrts.f32 d3, d2, d0 \n\t" //d4 = (3 - d0 * d3) / 2
|
||||
"vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d4
|
||||
|
||||
"vmul.f32 q2, q2, d0[0] \n\t" //d0= d2*d4
|
||||
"vst1.32 {d4, d5}, [%1] \n\t" //d2={x0,y0}, d3={z0, w0}
|
||||
|
||||
:: "r"(v), "r"(d)
|
||||
: "d0", "d1", "d2", "d3", "d4", "d5", "memory"
|
||||
);
|
||||
#else
|
||||
normalize4_c(v, d);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
float dot4_neon_hfp(float v0[4], float v1[4])
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
asm volatile (
|
||||
"vld1.32 {d2, d3}, [%0] \n\t" //d2={x0,y0}, d3={z0, w0}
|
||||
"vld1.32 {d4, d5}, [%1] \n\t" //d4={x1,y1}, d5={z1, w1}
|
||||
"vmul.f32 d0, d2, d4 \n\t" //d0= d2*d4
|
||||
"vmla.f32 d0, d3, d5 \n\t" //d0 = d0 + d3*d5
|
||||
"vpadd.f32 d0, d0 \n\t" //d0 = d[0] + d[1]
|
||||
:: "r"(v0), "r"(v1) :
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
float dot4_neon_sfp(float v0[4], float v1[4])
|
||||
{
|
||||
#ifdef __MATH_NEON
|
||||
dot4_neon_hfp(v0, v1);
|
||||
asm volatile ("vmov.f32 r0, s0 \n\t");
|
||||
#else
|
||||
return dot4_c(v0, v1);
|
||||
#endif
|
||||
};
|
||||
|
||||
Vendored
+43
-16
@@ -53,7 +53,13 @@ enum {
|
||||
RC_MISSING_CANCEL = -14,
|
||||
RC_MISSING_SUBMIT = -15,
|
||||
RC_MISSING_VALUE = -16,
|
||||
RC_INVALID_LBOARD_FIELD = -17
|
||||
RC_INVALID_LBOARD_FIELD = -17,
|
||||
RC_MISSING_DISPLAY_STRING = -18,
|
||||
RC_OUT_OF_MEMORY = -19,
|
||||
RC_INVALID_VALUE_FLAG = -20,
|
||||
RC_MISSING_VALUE_MEASURED = -21,
|
||||
RC_MULTIPLE_MEASURED = -22,
|
||||
RC_INVALID_MEASURED_TARGET = -23
|
||||
};
|
||||
```
|
||||
|
||||
@@ -190,16 +196,14 @@ struct rc_condition_t {
|
||||
/* Number of hits so far. */
|
||||
unsigned current_hits;
|
||||
|
||||
/**
|
||||
* Set if the condition needs to processed as part of the "check if paused"
|
||||
* pass
|
||||
*/
|
||||
char pause;
|
||||
|
||||
/* The type of the condition. */
|
||||
char type;
|
||||
/* The comparison operator to use. */
|
||||
char oper; /* operator is a reserved word in C++. */
|
||||
/* Set if the condition needs to processed as part of the "check if paused" pass. */
|
||||
char pause;
|
||||
/* Whether or not the condition evaluated as true on the last check. */
|
||||
char is_true;
|
||||
};
|
||||
```
|
||||
|
||||
@@ -212,7 +216,10 @@ enum {
|
||||
RC_CONDITION_RESET_IF,
|
||||
RC_CONDITION_ADD_SOURCE,
|
||||
RC_CONDITION_SUB_SOURCE,
|
||||
RC_CONDITION_ADD_HITS
|
||||
RC_CONDITION_ADD_HITS,
|
||||
RC_CONDITION_AND_NEXT,
|
||||
RC_CONDITION_MEASURED,
|
||||
RC_CONDITION_ADD_ADDRESS
|
||||
};
|
||||
```
|
||||
|
||||
@@ -225,7 +232,8 @@ enum {
|
||||
RC_CONDITION_LE,
|
||||
RC_CONDITION_GT,
|
||||
RC_CONDITION_GE,
|
||||
RC_CONDITION_NE
|
||||
RC_CONDITION_NE,
|
||||
RC_CONDITION_NONE
|
||||
};
|
||||
```
|
||||
|
||||
@@ -279,10 +287,10 @@ rc_trigger_t* rc_parse_trigger(void* buffer, const char* memaddr, lua_State* L,
|
||||
|
||||
`buffer` is the caller-allocated buffer, which must have enough space for the trigger. `memaddr` describes the trigger, and must be the same one used to compute the trigger's size with `rc_trigger_size`. `L` must be a valid Lua state, and `funcs_ndx` must be an index to the current Lua stack which contains a table which is a map of names to functions. This map is used to look for operands which are Lua functions.
|
||||
|
||||
Once the trigger is created, `rc_test_trigger` can be called to test whether the trigger fires or not.
|
||||
Once the trigger is created, `rc_evaluate_trigger` can be called to test whether the trigger fires or not.
|
||||
|
||||
```c
|
||||
int rc_test_trigger(rc_trigger_t* trigger, rc_peek_t peek, void* ud, lua_State* L);
|
||||
int rc_evaluate_trigger(rc_trigger_t* trigger, rc_peek_t peek, void* ud, lua_State* L);
|
||||
```
|
||||
|
||||
`trigger` is the trigger to test. `peek` is a callback used to read bytes from the emulated memory. `ud` is an user-provided opaque value that is passed to `peek`. `L` is the Lua state in which context the Lua functions are looked for and called, if necessary.
|
||||
@@ -297,6 +305,18 @@ where `address` is the starting address to read from, `num_bytes` the number of
|
||||
|
||||
> Addresses passed to `peek` do *not* map 1:1 to the emulated memory. (**TODO**: document the mapping from `peek` addresses to emulated memory for each supported system.)
|
||||
|
||||
The return value of `rc_evaluate_trigger` is one of the following:
|
||||
```c
|
||||
enum {
|
||||
RC_TRIGGER_STATE_INACTIVE, /* achievement is not being processed */
|
||||
RC_TRIGGER_STATE_WAITING, /* achievement cannot trigger until it has been false for at least one frame */
|
||||
RC_TRIGGER_STATE_ACTIVE, /* achievement is active and may trigger */
|
||||
RC_TRIGGER_STATE_PAUSED, /* achievement is currently paused and will not trigger */
|
||||
RC_TRIGGER_STATE_RESET, /* achievement hit counts were reset */
|
||||
RC_TRIGGER_STATE_TRIGGERED /* achievement has triggered */
|
||||
};
|
||||
```
|
||||
|
||||
Finally, `rc_reset_trigger` can be used to reset the internal state of a trigger.
|
||||
|
||||
```c
|
||||
@@ -348,6 +368,12 @@ A value is a collection of expressions. It's used to give the value for a leader
|
||||
typedef struct {
|
||||
/* The list of expression to evaluate. */
|
||||
rc_expression_t* expressions;
|
||||
|
||||
/* The list of conditions to evaluate. */
|
||||
rc_condset_t* conditions;
|
||||
|
||||
/* The memory references required by the value. */
|
||||
rc_memref_value_t* memrefs;
|
||||
}
|
||||
rc_value_t;
|
||||
```
|
||||
@@ -369,7 +395,7 @@ rc_value_t* rc_parse_value(void* buffer, const char* memaddr, lua_State* L, int
|
||||
To compute the value, use `rc_evaluate_value`:
|
||||
|
||||
```c
|
||||
unsigned rc_evaluate_value(rc_value_t* value, rc_peek_t peek, void* ud, lua_State* L);
|
||||
int rc_evaluate_value(rc_value_t* value, rc_peek_t peek, void* ud, lua_State* L);
|
||||
```
|
||||
|
||||
`value` is the value to compute the value of, and `peek`, `ud`, and `L`, are as in [`rc_test_trigger`](#rc_test_trigger).
|
||||
@@ -404,7 +430,7 @@ rc_lboard_t* rc_parse_lboard(void* buffer, const char* memaddr, lua_State* L, in
|
||||
A leaderboard can be evaluated with the `rc_evaluate_lboard` function:
|
||||
|
||||
```c
|
||||
int rc_evaluate_lboard(rc_lboard_t* lboard, unsigned* value, rc_peek_t peek, void* peek_ud, lua_State* L);
|
||||
int rc_evaluate_lboard(rc_lboard_t* lboard, int* value, rc_peek_t peek, void* peek_ud, lua_State* L);
|
||||
```
|
||||
|
||||
The function returns an action that must be performed by the caller, and `value` contains the value to be used for that action when the function returns. The action can be one of:
|
||||
@@ -451,7 +477,8 @@ enum {
|
||||
RC_FORMAT_CENTISECS,
|
||||
RC_FORMAT_SCORE,
|
||||
RC_FORMAT_VALUE,
|
||||
RC_FORMAT_OTHER,
|
||||
RC_FORMAT_MINUTES,
|
||||
RC_FORMAT_SECONDS_AS_MINUTES
|
||||
};
|
||||
```
|
||||
|
||||
@@ -460,10 +487,10 @@ enum {
|
||||
`rc_format_value` can be used to format the given value into the provided buffer:
|
||||
|
||||
```c
|
||||
void rc_format_value(char* buffer, int size, unsigned value, int format);
|
||||
int rc_format_value(char* buffer, int size, int value, int format);
|
||||
```
|
||||
|
||||
`buffer` receives `value` formatted according to `format`. No more than `size` characters will be written to `buffer`. 32 characters are enough to hold any valid value with any format.
|
||||
`buffer` receives `value` formatted according to `format`. No more than `size` characters will be written to `buffer`. 32 characters are enough to hold any valid value with any format. The returned value is the number of characters written.
|
||||
|
||||
# **rurl**
|
||||
|
||||
|
||||
Vendored
+52
-13
@@ -31,7 +31,11 @@ enum {
|
||||
RC_MISSING_VALUE = -16,
|
||||
RC_INVALID_LBOARD_FIELD = -17,
|
||||
RC_MISSING_DISPLAY_STRING = -18,
|
||||
RC_OUT_OF_MEMORY = -19
|
||||
RC_OUT_OF_MEMORY = -19,
|
||||
RC_INVALID_VALUE_FLAG = -20,
|
||||
RC_MISSING_VALUE_MEASURED = -21,
|
||||
RC_MULTIPLE_MEASURED = -22,
|
||||
RC_INVALID_MEASURED_TARGET = -23
|
||||
};
|
||||
|
||||
/*****************************************************************************\
|
||||
@@ -112,6 +116,8 @@ typedef struct {
|
||||
char size;
|
||||
/* True if the value is in BCD. */
|
||||
char is_bcd;
|
||||
/* True if the reference will be used in indirection */
|
||||
char is_indirect;
|
||||
} rc_memref_t;
|
||||
|
||||
typedef struct rc_memref_value_t rc_memref_value_t;
|
||||
@@ -176,7 +182,9 @@ enum {
|
||||
RC_CONDITION_ADD_SOURCE,
|
||||
RC_CONDITION_SUB_SOURCE,
|
||||
RC_CONDITION_ADD_HITS,
|
||||
RC_CONDITION_AND_NEXT
|
||||
RC_CONDITION_AND_NEXT,
|
||||
RC_CONDITION_MEASURED,
|
||||
RC_CONDITION_ADD_ADDRESS
|
||||
};
|
||||
|
||||
/* operators */
|
||||
@@ -186,7 +194,8 @@ enum {
|
||||
RC_CONDITION_LE,
|
||||
RC_CONDITION_GT,
|
||||
RC_CONDITION_GE,
|
||||
RC_CONDITION_NE
|
||||
RC_CONDITION_NE,
|
||||
RC_CONDITION_NONE
|
||||
};
|
||||
|
||||
typedef struct rc_condition_t rc_condition_t;
|
||||
@@ -204,16 +213,17 @@ struct rc_condition_t {
|
||||
/* The next condition in the chain. */
|
||||
rc_condition_t* next;
|
||||
|
||||
/**
|
||||
* Set if the condition needs to processed as part of the "check if paused"
|
||||
* pass
|
||||
*/
|
||||
char pause;
|
||||
|
||||
/* The type of the condition. */
|
||||
char type;
|
||||
|
||||
/* The comparison operator to use. */
|
||||
char oper; /* operator is a reserved word in C++. */
|
||||
|
||||
/* Set if the condition needs to processed as part of the "check if paused" pass. */
|
||||
char pause;
|
||||
|
||||
/* Whether or not the condition evaluated true on the last check */
|
||||
char is_true;
|
||||
};
|
||||
|
||||
/*****************************************************************************\
|
||||
@@ -231,12 +241,24 @@ struct rc_condset_t {
|
||||
|
||||
/* True if any condition in the set is a pause condition. */
|
||||
char has_pause;
|
||||
|
||||
/* True if the set is currently paused. */
|
||||
char is_paused;
|
||||
};
|
||||
|
||||
/*****************************************************************************\
|
||||
| Trigger |
|
||||
\*****************************************************************************/
|
||||
|
||||
enum {
|
||||
RC_TRIGGER_STATE_INACTIVE, /* achievement is not being processed */
|
||||
RC_TRIGGER_STATE_WAITING, /* achievement cannot trigger until it has been false for at least one frame */
|
||||
RC_TRIGGER_STATE_ACTIVE, /* achievement is active and may trigger */
|
||||
RC_TRIGGER_STATE_PAUSED, /* achievement is currently paused and will not trigger */
|
||||
RC_TRIGGER_STATE_RESET, /* achievement hit counts were reset */
|
||||
RC_TRIGGER_STATE_TRIGGERED /* achievement has triggered */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
/* The main condition set. */
|
||||
rc_condset_t* requirement;
|
||||
@@ -246,11 +268,24 @@ typedef struct {
|
||||
|
||||
/* The memory references required by the trigger. */
|
||||
rc_memref_value_t* memrefs;
|
||||
|
||||
/* The current state of the MEASURED condition. */
|
||||
unsigned measured_value;
|
||||
|
||||
/* The target state of the MEASURED condition */
|
||||
unsigned measured_target;
|
||||
|
||||
/* The current state of the trigger */
|
||||
char state;
|
||||
|
||||
/* True if at least one condition has a non-zero hit count */
|
||||
char has_hits;
|
||||
}
|
||||
rc_trigger_t;
|
||||
|
||||
int rc_trigger_size(const char* memaddr);
|
||||
rc_trigger_t* rc_parse_trigger(void* buffer, const char* memaddr, lua_State* L, int funcs_ndx);
|
||||
int rc_evaluate_trigger(rc_trigger_t* trigger, rc_peek_t peek, void* ud, lua_State* L);
|
||||
int rc_test_trigger(rc_trigger_t* trigger, rc_peek_t peek, void* ud, lua_State* L);
|
||||
void rc_reset_trigger(rc_trigger_t* self);
|
||||
|
||||
@@ -287,6 +322,9 @@ typedef struct {
|
||||
/* The list of expression to evaluate. */
|
||||
rc_expression_t* expressions;
|
||||
|
||||
/* The list of conditions to evaluate. */
|
||||
rc_condset_t* conditions;
|
||||
|
||||
/* The memory references required by the value. */
|
||||
rc_memref_value_t* memrefs;
|
||||
}
|
||||
@@ -294,7 +332,7 @@ rc_value_t;
|
||||
|
||||
int rc_value_size(const char* memaddr);
|
||||
rc_value_t* rc_parse_value(void* buffer, const char* memaddr, lua_State* L, int funcs_ndx);
|
||||
unsigned rc_evaluate_value(rc_value_t* value, rc_peek_t peek, void* ud, lua_State* L);
|
||||
int rc_evaluate_value(rc_value_t* value, rc_peek_t peek, void* ud, lua_State* L);
|
||||
|
||||
/*****************************************************************************\
|
||||
| Leaderboards |
|
||||
@@ -324,7 +362,7 @@ rc_lboard_t;
|
||||
|
||||
int rc_lboard_size(const char* memaddr);
|
||||
rc_lboard_t* rc_parse_lboard(void* buffer, const char* memaddr, lua_State* L, int funcs_ndx);
|
||||
int rc_evaluate_lboard(rc_lboard_t* lboard, unsigned* value, rc_peek_t peek, void* peek_ud, lua_State* L);
|
||||
int rc_evaluate_lboard(rc_lboard_t* lboard, int* value, rc_peek_t peek, void* peek_ud, lua_State* L);
|
||||
void rc_reset_lboard(rc_lboard_t* lboard);
|
||||
|
||||
/*****************************************************************************\
|
||||
@@ -338,11 +376,12 @@ enum {
|
||||
RC_FORMAT_CENTISECS,
|
||||
RC_FORMAT_SCORE,
|
||||
RC_FORMAT_VALUE,
|
||||
RC_FORMAT_OTHER
|
||||
RC_FORMAT_MINUTES,
|
||||
RC_FORMAT_SECONDS_AS_MINUTES
|
||||
};
|
||||
|
||||
int rc_parse_format(const char* format_str);
|
||||
int rc_format_value(char* buffer, int size, unsigned value, int format);
|
||||
int rc_format_value(char* buffer, int size, int value, int format);
|
||||
|
||||
/*****************************************************************************\
|
||||
| Rich Presence |
|
||||
|
||||
Vendored
+1
-1
@@ -9,7 +9,7 @@ extern "C" {
|
||||
|
||||
int rc_url_award_cheevo(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned cheevo_id, int hardcore);
|
||||
|
||||
int rc_url_submit_lboard(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned lboard_id, unsigned value, unsigned char hash[16]);
|
||||
int rc_url_submit_lboard(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned lboard_id, int value, unsigned char hash[16]);
|
||||
|
||||
int rc_url_get_gameid(char* buffer, size_t size, unsigned char hash[16]);
|
||||
|
||||
|
||||
Vendored
+1
@@ -44,6 +44,7 @@ void rc_init_parse_state(rc_parse_state_t* parse, void* buffer, lua_State* L, in
|
||||
parse->scratch.memref_size = sizeof(parse->scratch.memref_buffer) / sizeof(parse->scratch.memref_buffer[0]);
|
||||
parse->scratch.memref_count = 0;
|
||||
parse->first_memref = 0;
|
||||
parse->measured_target = 0;
|
||||
}
|
||||
|
||||
void rc_destroy_parse_state(rc_parse_state_t* parse)
|
||||
|
||||
+19
-6
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse) {
|
||||
rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse, int is_indirect) {
|
||||
rc_condition_t* self;
|
||||
const char* aux;
|
||||
int ret2;
|
||||
@@ -19,6 +19,8 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse
|
||||
case 'b': case 'B': self->type = RC_CONDITION_SUB_SOURCE; break;
|
||||
case 'c': case 'C': self->type = RC_CONDITION_ADD_HITS; break;
|
||||
case 'n': case 'N': self->type = RC_CONDITION_AND_NEXT; break;
|
||||
case 'm': case 'M': self->type = RC_CONDITION_MEASURED; break;
|
||||
case 'i': case 'I': self->type = RC_CONDITION_ADD_ADDRESS; break;
|
||||
default: parse->offset = RC_INVALID_CONDITION_TYPE; return 0;
|
||||
}
|
||||
|
||||
@@ -28,7 +30,7 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse
|
||||
self->type = RC_CONDITION_STANDARD;
|
||||
}
|
||||
|
||||
ret2 = rc_parse_operand(&self->operand1, &aux, 1, parse);
|
||||
ret2 = rc_parse_operand(&self->operand1, &aux, 1, is_indirect, parse);
|
||||
|
||||
if (ret2 < 0) {
|
||||
parse->offset = ret2;
|
||||
@@ -71,9 +73,19 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '_':
|
||||
case ')':
|
||||
case '\0':
|
||||
self->oper = RC_CONDITION_NONE;
|
||||
self->operand2.type = RC_OPERAND_CONST;
|
||||
self->operand2.value.num = 1;
|
||||
self->required_hits = 0;
|
||||
*memaddr = aux - 1;
|
||||
return self;
|
||||
}
|
||||
|
||||
ret2 = rc_parse_operand(&self->operand2, &aux, 1, parse);
|
||||
ret2 = rc_parse_operand(&self->operand2, &aux, 1, is_indirect, parse);
|
||||
|
||||
if (ret2 < 0) {
|
||||
parse->offset = ret2;
|
||||
@@ -110,9 +122,9 @@ rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse
|
||||
return self;
|
||||
}
|
||||
|
||||
int rc_test_condition(rc_condition_t* self, unsigned add_buffer, rc_peek_t peek, void* ud, lua_State* L) {
|
||||
unsigned value1 = rc_evaluate_operand(&self->operand1, peek, ud, L) + add_buffer;
|
||||
unsigned value2 = rc_evaluate_operand(&self->operand2, peek, ud, L);
|
||||
int rc_test_condition(rc_condition_t* self, rc_eval_state_t* eval_state) {
|
||||
unsigned value1 = rc_evaluate_operand(&self->operand1, eval_state) + eval_state->add_value;
|
||||
unsigned value2 = rc_evaluate_operand(&self->operand2, eval_state);
|
||||
|
||||
switch (self->oper) {
|
||||
case RC_CONDITION_EQ: return value1 == value2;
|
||||
@@ -121,6 +133,7 @@ int rc_test_condition(rc_condition_t* self, unsigned add_buffer, rc_peek_t peek,
|
||||
case RC_CONDITION_LE: return value1 <= value2;
|
||||
case RC_CONDITION_GT: return value1 > value2;
|
||||
case RC_CONDITION_GE: return value1 >= value2;
|
||||
case RC_CONDITION_NONE: return 1;
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
Vendored
+101
-23
@@ -14,6 +14,7 @@ static void rc_update_condition_pause(rc_condition_t* condition, int* in_pause)
|
||||
case RC_CONDITION_SUB_SOURCE:
|
||||
case RC_CONDITION_ADD_HITS:
|
||||
case RC_CONDITION_AND_NEXT:
|
||||
case RC_CONDITION_ADD_ADDRESS:
|
||||
condition->pause = *in_pause;
|
||||
break;
|
||||
|
||||
@@ -27,9 +28,10 @@ rc_condset_t* rc_parse_condset(const char** memaddr, rc_parse_state_t* parse) {
|
||||
rc_condset_t* self;
|
||||
rc_condition_t** next;
|
||||
int in_pause;
|
||||
int in_add_address;
|
||||
|
||||
self = RC_ALLOC(rc_condset_t, parse);
|
||||
self->has_pause = 0;
|
||||
self->has_pause = self->is_paused = 0;
|
||||
next = &self->conditions;
|
||||
|
||||
if (**memaddr == 'S' || **memaddr == 's' || !**memaddr) {
|
||||
@@ -38,14 +40,54 @@ rc_condset_t* rc_parse_condset(const char** memaddr, rc_parse_state_t* parse) {
|
||||
return self;
|
||||
}
|
||||
|
||||
in_add_address = 0;
|
||||
for (;;) {
|
||||
*next = rc_parse_condition(memaddr, parse);
|
||||
*next = rc_parse_condition(memaddr, parse, in_add_address);
|
||||
|
||||
if (parse->offset < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((*next)->oper == RC_CONDITION_NONE) {
|
||||
switch ((*next)->type) {
|
||||
case RC_CONDITION_ADD_ADDRESS:
|
||||
case RC_CONDITION_ADD_HITS:
|
||||
case RC_CONDITION_ADD_SOURCE:
|
||||
case RC_CONDITION_SUB_SOURCE:
|
||||
case RC_CONDITION_AND_NEXT:
|
||||
break;
|
||||
|
||||
default:
|
||||
parse->offset = RC_INVALID_OPERATOR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
self->has_pause |= (*next)->type == RC_CONDITION_PAUSE_IF;
|
||||
in_add_address = (*next)->type == RC_CONDITION_ADD_ADDRESS;
|
||||
|
||||
if ((*next)->type == RC_CONDITION_MEASURED) {
|
||||
unsigned measured_target = 0;
|
||||
if ((*next)->required_hits == 0) {
|
||||
if ((*next)->operand2.type != RC_OPERAND_CONST) {
|
||||
parse->offset = RC_INVALID_MEASURED_TARGET;
|
||||
return 0;
|
||||
}
|
||||
|
||||
measured_target = (*next)->operand2.value.num;
|
||||
}
|
||||
else {
|
||||
measured_target = (*next)->required_hits;
|
||||
}
|
||||
|
||||
if (parse->measured_target && measured_target != parse->measured_target) {
|
||||
parse->offset = RC_MULTIPLE_MEASURED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
parse->measured_target = measured_target;
|
||||
}
|
||||
|
||||
next = &(*next)->next;
|
||||
|
||||
if (**memaddr != '_') {
|
||||
@@ -66,14 +108,13 @@ rc_condset_t* rc_parse_condset(const char** memaddr, rc_parse_state_t* parse) {
|
||||
return self;
|
||||
}
|
||||
|
||||
static int rc_test_condset_internal(rc_condset_t* self, int processing_pause, int* reset, rc_peek_t peek, void* ud, lua_State* L) {
|
||||
static int rc_test_condset_internal(rc_condset_t* self, int processing_pause, rc_eval_state_t* eval_state) {
|
||||
rc_condition_t* condition;
|
||||
int set_valid, cond_valid, prev_cond;
|
||||
unsigned add_buffer, add_hits;
|
||||
|
||||
set_valid = 1;
|
||||
prev_cond = 1;
|
||||
add_buffer = add_hits = 0;
|
||||
eval_state->add_value = eval_state->add_hits = eval_state->add_address = 0;
|
||||
|
||||
for (condition = self->conditions; condition != 0; condition = condition->next) {
|
||||
if (condition->pause != processing_pause) {
|
||||
@@ -82,39 +123,60 @@ static int rc_test_condset_internal(rc_condset_t* self, int processing_pause, in
|
||||
|
||||
switch (condition->type) {
|
||||
case RC_CONDITION_ADD_SOURCE:
|
||||
add_buffer += rc_evaluate_operand(&condition->operand1, peek, ud, L);
|
||||
eval_state->add_value += rc_evaluate_operand(&condition->operand1, eval_state);
|
||||
eval_state->add_address = 0;
|
||||
continue;
|
||||
|
||||
case RC_CONDITION_SUB_SOURCE:
|
||||
add_buffer -= rc_evaluate_operand(&condition->operand1, peek, ud, L);
|
||||
eval_state->add_value -= rc_evaluate_operand(&condition->operand1, eval_state);
|
||||
eval_state->add_address = 0;
|
||||
continue;
|
||||
|
||||
case RC_CONDITION_ADD_HITS:
|
||||
if (rc_test_condition(condition, add_buffer, peek, ud, L)) {
|
||||
/* always evaluate the condition to ensure everything is updated correctly */
|
||||
cond_valid = rc_test_condition(condition, eval_state);
|
||||
|
||||
/* merge AndNext value and reset it for the next condition */
|
||||
cond_valid &= prev_cond;
|
||||
prev_cond = 1;
|
||||
|
||||
/* if the condition is true, tally it */
|
||||
if (cond_valid) {
|
||||
if (condition->required_hits == 0 || condition->current_hits < condition->required_hits) {
|
||||
condition->current_hits++;
|
||||
}
|
||||
|
||||
condition->is_true = (condition->required_hits == 0 || condition->current_hits >= condition->required_hits);
|
||||
}
|
||||
else {
|
||||
condition->is_true = 0;
|
||||
}
|
||||
|
||||
add_buffer = 0;
|
||||
add_hits += condition->current_hits;
|
||||
eval_state->add_value = 0;
|
||||
eval_state->add_address = 0;
|
||||
eval_state->add_hits += condition->current_hits;
|
||||
continue;
|
||||
|
||||
case RC_CONDITION_AND_NEXT:
|
||||
prev_cond &= rc_test_condition(condition, add_buffer, peek, ud, L);
|
||||
add_buffer = 0;
|
||||
prev_cond &= rc_test_condition(condition, eval_state);
|
||||
eval_state->add_value = 0;
|
||||
eval_state->add_address = 0;
|
||||
continue;
|
||||
|
||||
case RC_CONDITION_ADD_ADDRESS:
|
||||
eval_state->add_address = rc_evaluate_operand(&condition->operand1, eval_state);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* always evaluate the condition to ensure delta values get tracked correctly */
|
||||
cond_valid = rc_test_condition(condition, add_buffer, peek, ud, L);
|
||||
/* always evaluate the condition to ensure everything is updated correctly */
|
||||
cond_valid = rc_test_condition(condition, eval_state);
|
||||
|
||||
/* merge AndNext value and reset it for the next condition */
|
||||
cond_valid &= prev_cond;
|
||||
prev_cond = 1;
|
||||
|
||||
/* if the condition has a target hit count that has already been met, it's automatically true, even if not currently true. */
|
||||
if (condition->required_hits != 0 && (condition->current_hits + add_hits) >= condition->required_hits) {
|
||||
if (condition->required_hits != 0 && (condition->current_hits + eval_state->add_hits) >= condition->required_hits) {
|
||||
cond_valid = 1;
|
||||
}
|
||||
else if (cond_valid) {
|
||||
@@ -123,14 +185,28 @@ static int rc_test_condset_internal(rc_condset_t* self, int processing_pause, in
|
||||
if (condition->required_hits == 0) {
|
||||
/* not a hit-based requirement: ignore any additional logic! */
|
||||
}
|
||||
else if ((condition->current_hits + add_hits) < condition->required_hits) {
|
||||
else if ((condition->current_hits + eval_state->add_hits) < condition->required_hits) {
|
||||
/* HitCount target has not yet been met, condition is not yet valid */
|
||||
cond_valid = 0;
|
||||
}
|
||||
}
|
||||
condition->is_true = cond_valid;
|
||||
eval_state->has_hits |= (condition->current_hits || eval_state->add_hits);
|
||||
|
||||
/* capture measured state */
|
||||
if (condition->type == RC_CONDITION_MEASURED) {
|
||||
unsigned int measured_value;
|
||||
if (condition->required_hits > 0)
|
||||
measured_value = condition->current_hits + eval_state->add_hits;
|
||||
else
|
||||
measured_value = rc_evaluate_operand(&condition->operand1, eval_state) + eval_state->add_value;
|
||||
|
||||
if (measured_value > eval_state->measured_value)
|
||||
eval_state->measured_value = measured_value;
|
||||
}
|
||||
|
||||
/* reset AddHits and AddSource/SubSource values */
|
||||
add_buffer = add_hits = 0;
|
||||
eval_state->add_value = eval_state->add_hits = eval_state->add_address = 0;
|
||||
|
||||
switch (condition->type) {
|
||||
case RC_CONDITION_PAUSE_IF:
|
||||
@@ -155,7 +231,7 @@ static int rc_test_condset_internal(rc_condset_t* self, int processing_pause, in
|
||||
|
||||
case RC_CONDITION_RESET_IF:
|
||||
if (cond_valid) {
|
||||
*reset = 1; /* let caller know to reset all hit counts */
|
||||
eval_state->was_reset = 1; /* let caller know to reset all hit counts */
|
||||
set_valid = 0; /* cannot be valid if we've hit a reset condition */
|
||||
}
|
||||
|
||||
@@ -170,18 +246,20 @@ static int rc_test_condset_internal(rc_condset_t* self, int processing_pause, in
|
||||
return set_valid;
|
||||
}
|
||||
|
||||
int rc_test_condset(rc_condset_t* self, int* reset, rc_peek_t peek, void* ud, lua_State* L) {
|
||||
int rc_test_condset(rc_condset_t* self, rc_eval_state_t* eval_state) {
|
||||
if (self->conditions == 0) {
|
||||
/* important: empty group must evaluate true */
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (self->has_pause && rc_test_condset_internal(self, 1, reset, peek, ud, L)) {
|
||||
/* one or more Pause conditions exists, if any of them are true, stop processing this group */
|
||||
return 0;
|
||||
if (self->has_pause) {
|
||||
if ((self->is_paused = rc_test_condset_internal(self, 1, eval_state))) {
|
||||
/* one or more Pause conditions exists, if any of them are true, stop processing this group */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return rc_test_condset_internal(self, 0, reset, peek, ud, L);
|
||||
return rc_test_condset_internal(self, 0, eval_state);
|
||||
}
|
||||
|
||||
void rc_reset_condset(rc_condset_t* self) {
|
||||
|
||||
+4
-4
@@ -8,7 +8,7 @@ rc_expression_t* rc_parse_expression(const char** memaddr, rc_parse_state_t* par
|
||||
next = &self->terms;
|
||||
|
||||
for (;;) {
|
||||
*next = rc_parse_term(memaddr, parse);
|
||||
*next = rc_parse_term(memaddr, 0, parse);
|
||||
|
||||
if (parse->offset < 0) {
|
||||
return 0;
|
||||
@@ -27,14 +27,14 @@ rc_expression_t* rc_parse_expression(const char** memaddr, rc_parse_state_t* par
|
||||
return self;
|
||||
}
|
||||
|
||||
unsigned rc_evaluate_expression(rc_expression_t* self, rc_peek_t peek, void* ud, lua_State* L) {
|
||||
int rc_evaluate_expression(rc_expression_t* self, rc_eval_state_t* eval_state) {
|
||||
rc_term_t* term;
|
||||
unsigned value;
|
||||
int value;
|
||||
|
||||
value = 0;
|
||||
|
||||
for (term = self->terms; term != 0; term = term->next) {
|
||||
value += rc_evaluate_term(term, peek, ud, L);
|
||||
value += rc_evaluate_term(term, eval_state);
|
||||
}
|
||||
|
||||
return value;
|
||||
|
||||
Vendored
+67
-24
@@ -29,6 +29,9 @@ int rc_parse_format(const char* format_str) {
|
||||
if (!strcmp(format_str, "CORE")) {
|
||||
return RC_FORMAT_SCORE;
|
||||
}
|
||||
if (!strcmp(format_str, "ECS_AS_MINS")) {
|
||||
return RC_FORMAT_SECONDS_AS_MINUTES;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -36,6 +39,9 @@ int rc_parse_format(const char* format_str) {
|
||||
if (!strcmp(format_str, "ILLISECS")) {
|
||||
return RC_FORMAT_CENTISECS;
|
||||
}
|
||||
if (!strcmp(format_str, "INUTES")) {
|
||||
return RC_FORMAT_MINUTES;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -55,7 +61,7 @@ int rc_parse_format(const char* format_str) {
|
||||
|
||||
case 'O':
|
||||
if (!strcmp(format_str, "THER")) {
|
||||
return RC_FORMAT_OTHER;
|
||||
return RC_FORMAT_SCORE;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -64,45 +70,82 @@ int rc_parse_format(const char* format_str) {
|
||||
return RC_FORMAT_VALUE;
|
||||
}
|
||||
|
||||
int rc_format_value(char* buffer, int size, unsigned value, int format) {
|
||||
unsigned a, b, c;
|
||||
static int rc_format_value_minutes(char* buffer, int size, unsigned minutes) {
|
||||
unsigned hours;
|
||||
|
||||
hours = minutes / 60;
|
||||
minutes -= hours * 60;
|
||||
return snprintf(buffer, size, "%uh%02u", hours, minutes);
|
||||
}
|
||||
|
||||
static int rc_format_value_seconds(char* buffer, int size, unsigned seconds) {
|
||||
unsigned hours, minutes;
|
||||
|
||||
/* apply modulus math to split the seconds into hours/minutes/seconds */
|
||||
minutes = seconds / 60;
|
||||
seconds -= minutes * 60;
|
||||
if (minutes < 60) {
|
||||
return snprintf(buffer, size, "%u:%02u", minutes, seconds);
|
||||
}
|
||||
|
||||
hours = minutes / 60;
|
||||
minutes -= hours * 60;
|
||||
return snprintf(buffer, size, "%uh%02u:%02u", hours, minutes, seconds);
|
||||
}
|
||||
|
||||
static int rc_format_value_centiseconds(char* buffer, int size, unsigned centiseconds) {
|
||||
unsigned seconds;
|
||||
int chars, chars2;
|
||||
|
||||
/* modulus off the centiseconds */
|
||||
seconds = centiseconds / 100;
|
||||
centiseconds -= seconds * 100;
|
||||
|
||||
chars = rc_format_value_seconds(buffer, size, seconds);
|
||||
if (chars > 0) {
|
||||
chars2 = snprintf(buffer + chars, size - chars, ".%02u", centiseconds);
|
||||
if (chars2 > 0) {
|
||||
chars += chars2;
|
||||
} else {
|
||||
chars = chars2;
|
||||
}
|
||||
}
|
||||
|
||||
return chars;
|
||||
}
|
||||
|
||||
int rc_format_value(char* buffer, int size, int value, int format) {
|
||||
int chars;
|
||||
|
||||
switch (format) {
|
||||
case RC_FORMAT_FRAMES:
|
||||
a = value * 10 / 6; /* centisecs */
|
||||
b = a / 100; /* seconds */
|
||||
a -= b * 100;
|
||||
c = b / 60; /* minutes */
|
||||
b -= c * 60;
|
||||
chars = snprintf(buffer, size, "%02u:%02u.%02u", c, b, a);
|
||||
/* 60 frames per second = 100 centiseconds / 60 frames; multiply frames by 100 / 60 */
|
||||
chars = rc_format_value_centiseconds(buffer, size, value * 10 / 6);
|
||||
break;
|
||||
|
||||
case RC_FORMAT_SECONDS:
|
||||
a = value / 60; /* minutes */
|
||||
value -= a * 60;
|
||||
chars = snprintf(buffer, size, "%02u:%02u", a, value);
|
||||
chars = rc_format_value_seconds(buffer, size, value);
|
||||
break;
|
||||
|
||||
case RC_FORMAT_CENTISECS:
|
||||
a = value / 100; /* seconds */
|
||||
value -= a * 100;
|
||||
b = a / 60; /* minutes */
|
||||
a -= b * 60;
|
||||
chars = snprintf(buffer, size, "%02u:%02u.%02u", b, a, value);
|
||||
chars = rc_format_value_centiseconds(buffer, size, value);
|
||||
break;
|
||||
|
||||
case RC_FORMAT_SECONDS_AS_MINUTES:
|
||||
chars = rc_format_value_minutes(buffer, size, value / 60);
|
||||
break;
|
||||
|
||||
case RC_FORMAT_MINUTES:
|
||||
chars = rc_format_value_minutes(buffer, size, value);
|
||||
break;
|
||||
|
||||
case RC_FORMAT_SCORE:
|
||||
chars = snprintf(buffer, size, "%06u Points", value);
|
||||
chars = snprintf(buffer, size, "%06d", value);
|
||||
break;
|
||||
|
||||
case RC_FORMAT_VALUE:
|
||||
chars = snprintf(buffer, size, "%01u", value);
|
||||
break;
|
||||
|
||||
case RC_FORMAT_OTHER:
|
||||
default:
|
||||
chars = snprintf(buffer, size, "%06u", value);
|
||||
case RC_FORMAT_VALUE:
|
||||
chars = snprintf(buffer, size, "%d", value);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+29
-13
@@ -1,8 +1,7 @@
|
||||
#ifndef INTERNAL_H
|
||||
#define INTERNAL_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <rcheevos.h>
|
||||
#include "rcheevos.h"
|
||||
|
||||
#define RC_ALLOW_ALIGN(T) struct __align_ ## T { char ch; T t; };
|
||||
RC_ALLOW_ALIGN(rc_condition_t)
|
||||
@@ -21,8 +20,6 @@ RC_ALLOW_ALIGN(rc_trigger_t)
|
||||
RC_ALLOW_ALIGN(rc_value_t)
|
||||
RC_ALLOW_ALIGN(char)
|
||||
|
||||
#define RC_TAG2(x,y) x ## y
|
||||
#define RC_TAG(x,y) RC_TAG2(x,y)
|
||||
#define RC_ALIGNOF(T) (sizeof(struct __align_ ## T) - sizeof(T))
|
||||
|
||||
#define RC_ALLOC(t, p) ((t*)rc_alloc((p)->buffer, &(p)->offset, sizeof(t), RC_ALIGNOF(t), &(p)->scratch))
|
||||
@@ -52,6 +49,21 @@ typedef struct {
|
||||
}
|
||||
rc_scratch_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned add_value; /* AddSource/SubSource */
|
||||
unsigned add_hits; /* AddHits */
|
||||
unsigned add_address; /* AddAddress */
|
||||
|
||||
rc_peek_t peek;
|
||||
void* peek_userdata;
|
||||
lua_State* L;
|
||||
|
||||
unsigned measured_value; /* Measured */
|
||||
char was_reset; /* ResetIf triggered */
|
||||
char has_hits; /* one of more hit counts is non-zero */
|
||||
}
|
||||
rc_eval_state_t;
|
||||
|
||||
typedef struct {
|
||||
int offset;
|
||||
|
||||
@@ -62,6 +74,8 @@ typedef struct {
|
||||
rc_scratch_t scratch;
|
||||
|
||||
rc_memref_value_t** first_memref;
|
||||
|
||||
unsigned measured_target;
|
||||
}
|
||||
rc_parse_state_t;
|
||||
|
||||
@@ -72,26 +86,28 @@ void rc_destroy_parse_state(rc_parse_state_t* parse);
|
||||
void* rc_alloc(void* pointer, int* offset, int size, int alignment, rc_scratch_t* scratch);
|
||||
char* rc_alloc_str(rc_parse_state_t* parse, const char* text, int length);
|
||||
|
||||
rc_memref_value_t* rc_alloc_memref_value(rc_parse_state_t* parse, unsigned address, char size, char is_bcd);
|
||||
rc_memref_value_t* rc_alloc_memref_value(rc_parse_state_t* parse, unsigned address, char size, char is_bcd, char is_indirect);
|
||||
void rc_update_memref_values(rc_memref_value_t* memref, rc_peek_t peek, void* ud);
|
||||
void rc_update_memref_value(rc_memref_value_t* memref, rc_peek_t peek, void* ud);
|
||||
rc_memref_value_t* rc_get_indirect_memref(rc_memref_value_t* memref, rc_eval_state_t* eval_state);
|
||||
|
||||
void rc_parse_trigger_internal(rc_trigger_t* self, const char** memaddr, rc_parse_state_t* parse);
|
||||
|
||||
rc_condset_t* rc_parse_condset(const char** memaddr, rc_parse_state_t* parse);
|
||||
int rc_test_condset(rc_condset_t* self, int* reset, rc_peek_t peek, void* ud, lua_State* L);
|
||||
int rc_test_condset(rc_condset_t* self, rc_eval_state_t* eval_state);
|
||||
void rc_reset_condset(rc_condset_t* self);
|
||||
|
||||
rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse);
|
||||
int rc_test_condition(rc_condition_t* self, unsigned add_buffer, rc_peek_t peek, void* ud, lua_State* L);
|
||||
rc_condition_t* rc_parse_condition(const char** memaddr, rc_parse_state_t* parse, int is_indirect);
|
||||
int rc_test_condition(rc_condition_t* self, rc_eval_state_t* eval_state);
|
||||
|
||||
int rc_parse_operand(rc_operand_t* self, const char** memaddr, int is_trigger, rc_parse_state_t* parse);
|
||||
unsigned rc_evaluate_operand(rc_operand_t* self, rc_peek_t peek, void* ud, lua_State* L);
|
||||
int rc_parse_operand(rc_operand_t* self, const char** memaddr, int is_trigger, int is_indirect, rc_parse_state_t* parse);
|
||||
unsigned rc_evaluate_operand(rc_operand_t* self, rc_eval_state_t* eval_state);
|
||||
|
||||
rc_term_t* rc_parse_term(const char** memaddr, rc_parse_state_t* parse);
|
||||
unsigned rc_evaluate_term(rc_term_t* self, rc_peek_t peek, void* ud, lua_State* L);
|
||||
rc_term_t* rc_parse_term(const char** memaddr, int is_indirect, rc_parse_state_t* parse);
|
||||
int rc_evaluate_term(rc_term_t* self, rc_eval_state_t* eval_state);
|
||||
|
||||
rc_expression_t* rc_parse_expression(const char** memaddr, rc_parse_state_t* parse);
|
||||
unsigned rc_evaluate_expression(rc_expression_t* self, rc_peek_t peek, void* ud, lua_State* L);
|
||||
int rc_evaluate_expression(rc_expression_t* self, rc_eval_state_t* eval_state);
|
||||
|
||||
void rc_parse_value_internal(rc_value_t* self, const char** memaddr, rc_parse_state_t* parse);
|
||||
|
||||
|
||||
Vendored
+5
-2
@@ -162,7 +162,7 @@ rc_lboard_t* rc_parse_lboard(void* buffer, const char* memaddr, lua_State* L, in
|
||||
return parse.offset >= 0 ? self : 0;
|
||||
}
|
||||
|
||||
int rc_evaluate_lboard(rc_lboard_t* self, unsigned* value, rc_peek_t peek, void* peek_ud, lua_State* L) {
|
||||
int rc_evaluate_lboard(rc_lboard_t* self, int* value, rc_peek_t peek, void* peek_ud, lua_State* L) {
|
||||
int start_ok, cancel_ok, submit_ok;
|
||||
int action = -1;
|
||||
|
||||
@@ -217,8 +217,11 @@ int rc_evaluate_lboard(rc_lboard_t* self, unsigned* value, rc_peek_t peek, void*
|
||||
|
||||
/* Calculate the value */
|
||||
switch (action) {
|
||||
case RC_LBOARD_ACTIVE: /* fall through */
|
||||
case RC_LBOARD_STARTED:
|
||||
if (self->value.conditions)
|
||||
rc_reset_condset(self->value.conditions);
|
||||
/* fall through */
|
||||
case RC_LBOARD_ACTIVE:
|
||||
*value = rc_evaluate_value(self->progress != 0 ? self->progress : &self->value, peek, peek_ud, L);
|
||||
break;
|
||||
|
||||
|
||||
Vendored
+143
-66
@@ -3,75 +3,101 @@
|
||||
#include <stdlib.h> /* malloc/realloc */
|
||||
#include <string.h> /* memcpy */
|
||||
|
||||
rc_memref_value_t* rc_alloc_memref_value(rc_parse_state_t* parse, unsigned address, char size, char is_bcd) {
|
||||
rc_memref_value_t** next_memref_value;
|
||||
rc_memref_value_t* memref_value;
|
||||
#define MEMREF_PLACEHOLDER_ADDRESS 0xFFFFFFFF
|
||||
|
||||
static rc_memref_value_t* rc_alloc_memref_value_sizing_mode(rc_parse_state_t* parse, unsigned address, char size, char is_bcd, char is_indirect) {
|
||||
rc_memref_t* memref;
|
||||
int i;
|
||||
|
||||
if (!parse->first_memref) {
|
||||
/* sizing mode - have to track unique address/size/bcd combinations */
|
||||
for (i = 0; i < parse->scratch.memref_count; ++i) {
|
||||
memref = &parse->scratch.memref[i];
|
||||
if (memref->address == address && memref->size == size && memref->is_bcd == is_bcd) {
|
||||
return &parse->scratch.obj.memref_value;
|
||||
}
|
||||
}
|
||||
|
||||
/* resize unique tracking buffer if necessary */
|
||||
if (parse->scratch.memref_count == parse->scratch.memref_size) {
|
||||
if (parse->scratch.memref == parse->scratch.memref_buffer) {
|
||||
parse->scratch.memref_size += 16;
|
||||
memref = (rc_memref_t*)malloc(parse->scratch.memref_size * sizeof(parse->scratch.memref_buffer[0]));
|
||||
if (memref) {
|
||||
parse->scratch.memref = memref;
|
||||
memcpy(memref, parse->scratch.memref_buffer, parse->scratch.memref_count * sizeof(parse->scratch.memref_buffer[0]));
|
||||
}
|
||||
else {
|
||||
parse->offset = RC_OUT_OF_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
parse->scratch.memref_size += 32;
|
||||
memref = (rc_memref_t*)realloc(parse->scratch.memref, parse->scratch.memref_size * sizeof(parse->scratch.memref_buffer[0]));
|
||||
if (memref) {
|
||||
parse->scratch.memref = memref;
|
||||
}
|
||||
else {
|
||||
parse->offset = RC_OUT_OF_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* add new unique tracking entry */
|
||||
if (parse->scratch.memref) {
|
||||
memref = &parse->scratch.memref[parse->scratch.memref_count++];
|
||||
memref->address = address;
|
||||
memref->size = size;
|
||||
memref->is_bcd = is_bcd;
|
||||
}
|
||||
|
||||
/* allocate memory but don't actually populate, as it might overwrite the self object referencing the rc_memref_value_t */
|
||||
/* indirect address always creates two new entries; don't bother tracking them */
|
||||
if (is_indirect) {
|
||||
RC_ALLOC(rc_memref_value_t, parse);
|
||||
return RC_ALLOC(rc_memref_value_t, parse);
|
||||
}
|
||||
|
||||
/* construction mode - find or create the appropriate rc_memref_value_t */
|
||||
next_memref_value = parse->first_memref;
|
||||
while (*next_memref_value) {
|
||||
memref_value = *next_memref_value;
|
||||
if (memref_value->memref.address == address && memref_value->memref.size == size && memref_value->memref.is_bcd == is_bcd) {
|
||||
return memref_value;
|
||||
}
|
||||
|
||||
next_memref_value = &memref_value->next;
|
||||
}
|
||||
|
||||
memref = NULL;
|
||||
|
||||
/* have to track unique address/size/bcd combinations - use scratch.memref for sizing mode */
|
||||
for (i = 0; i < parse->scratch.memref_count; ++i) {
|
||||
memref = &parse->scratch.memref[i];
|
||||
if (memref->address == address && memref->size == size && memref->is_bcd == is_bcd) {
|
||||
return &parse->scratch.obj.memref_value;
|
||||
}
|
||||
}
|
||||
|
||||
/* no match found - resize unique tracking buffer if necessary */
|
||||
if (parse->scratch.memref_count == parse->scratch.memref_size) {
|
||||
if (parse->scratch.memref == parse->scratch.memref_buffer) {
|
||||
parse->scratch.memref_size += 16;
|
||||
memref = (rc_memref_t*)malloc(parse->scratch.memref_size * sizeof(parse->scratch.memref_buffer[0]));
|
||||
if (memref) {
|
||||
parse->scratch.memref = memref;
|
||||
memcpy(memref, parse->scratch.memref_buffer, parse->scratch.memref_count * sizeof(parse->scratch.memref_buffer[0]));
|
||||
}
|
||||
else {
|
||||
parse->offset = RC_OUT_OF_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
parse->scratch.memref_size += 32;
|
||||
memref = (rc_memref_t*)realloc(parse->scratch.memref, parse->scratch.memref_size * sizeof(parse->scratch.memref_buffer[0]));
|
||||
if (memref) {
|
||||
parse->scratch.memref = memref;
|
||||
}
|
||||
else {
|
||||
parse->offset = RC_OUT_OF_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* add new unique tracking entry */
|
||||
if (parse->scratch.memref) {
|
||||
memref = &parse->scratch.memref[parse->scratch.memref_count++];
|
||||
memref->address = address;
|
||||
memref->size = size;
|
||||
memref->is_bcd = is_bcd;
|
||||
memref->is_indirect = is_indirect;
|
||||
}
|
||||
|
||||
/* allocate memory but don't actually populate, as it might overwrite the self object referencing the rc_memref_value_t */
|
||||
return RC_ALLOC(rc_memref_value_t, parse);
|
||||
}
|
||||
|
||||
static rc_memref_value_t* rc_alloc_memref_value_constuct_mode(rc_parse_state_t* parse, unsigned address, char size, char is_bcd, char is_indirect) {
|
||||
rc_memref_value_t** next_memref_value;
|
||||
rc_memref_value_t* memref_value;
|
||||
rc_memref_value_t* indirect_memref_value;
|
||||
|
||||
if (!is_indirect) {
|
||||
/* attempt to find an existing rc_memref_value_t */
|
||||
next_memref_value = parse->first_memref;
|
||||
while (*next_memref_value) {
|
||||
memref_value = *next_memref_value;
|
||||
if (!memref_value->memref.is_indirect && memref_value->memref.address == address &&
|
||||
memref_value->memref.size == size && memref_value->memref.is_bcd == is_bcd) {
|
||||
return memref_value;
|
||||
}
|
||||
|
||||
next_memref_value = &memref_value->next;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* indirect address always creates two new entries - one for the original address, and one for
|
||||
the indirect dereference - just skip ahead to the end of the list */
|
||||
next_memref_value = parse->first_memref;
|
||||
while (*next_memref_value) {
|
||||
next_memref_value = &(*next_memref_value)->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* no match found, create a new entry */
|
||||
memref_value = RC_ALLOC(rc_memref_value_t, parse);
|
||||
memref_value->memref.address = address;
|
||||
memref_value->memref.size = size;
|
||||
memref_value->memref.is_bcd = is_bcd;
|
||||
memref_value->memref.is_indirect = is_indirect;
|
||||
memref_value->value = 0;
|
||||
memref_value->previous = 0;
|
||||
memref_value->prior = 0;
|
||||
@@ -79,9 +105,31 @@ rc_memref_value_t* rc_alloc_memref_value(rc_parse_state_t* parse, unsigned addre
|
||||
|
||||
*next_memref_value = memref_value;
|
||||
|
||||
/* also create the indirect deference entry for indirect references */
|
||||
if (is_indirect) {
|
||||
indirect_memref_value = RC_ALLOC(rc_memref_value_t, parse);
|
||||
indirect_memref_value->memref.address = MEMREF_PLACEHOLDER_ADDRESS;
|
||||
indirect_memref_value->memref.size = size;
|
||||
indirect_memref_value->memref.is_bcd = is_bcd;
|
||||
indirect_memref_value->memref.is_indirect = 1;
|
||||
indirect_memref_value->value = 0;
|
||||
indirect_memref_value->previous = 0;
|
||||
indirect_memref_value->prior = 0;
|
||||
indirect_memref_value->next = 0;
|
||||
|
||||
memref_value->next = indirect_memref_value;
|
||||
}
|
||||
|
||||
return memref_value;
|
||||
}
|
||||
|
||||
rc_memref_value_t* rc_alloc_memref_value(rc_parse_state_t* parse, unsigned address, char size, char is_bcd, char is_indirect) {
|
||||
if (!parse->first_memref)
|
||||
return rc_alloc_memref_value_sizing_mode(parse, address, size, is_bcd, is_indirect);
|
||||
|
||||
return rc_alloc_memref_value_constuct_mode(parse, address, size, is_bcd, is_indirect);
|
||||
}
|
||||
|
||||
static unsigned rc_memref_get_value(rc_memref_t* self, rc_peek_t peek, void* ud) {
|
||||
unsigned value;
|
||||
|
||||
@@ -149,6 +197,7 @@ static unsigned rc_memref_get_value(rc_memref_t* self, rc_peek_t peek, void* ud)
|
||||
break;
|
||||
|
||||
case RC_MEMSIZE_24_BITS:
|
||||
/* peek 4 bytes - don't expect the caller to understand 24-bit numbers */
|
||||
value = peek(self->address, 4, ud);
|
||||
|
||||
if (self->is_bcd) {
|
||||
@@ -158,6 +207,8 @@ static unsigned rc_memref_get_value(rc_memref_t* self, rc_peek_t peek, void* ud)
|
||||
+ ((value >> 8) & 0x0f) * 100
|
||||
+ ((value >> 4) & 0x0f) * 10
|
||||
+ ((value >> 0) & 0x0f) * 1;
|
||||
} else {
|
||||
value &= 0x00FFFFFF;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -186,19 +237,45 @@ static unsigned rc_memref_get_value(rc_memref_t* self, rc_peek_t peek, void* ud)
|
||||
return value;
|
||||
}
|
||||
|
||||
void rc_update_memref_value(rc_memref_value_t* memref, rc_peek_t peek, void* ud) {
|
||||
memref->previous = memref->value;
|
||||
memref->value = rc_memref_get_value(&memref->memref, peek, ud);
|
||||
if (memref->value != memref->previous)
|
||||
memref->prior = memref->previous;
|
||||
}
|
||||
|
||||
void rc_update_memref_values(rc_memref_value_t* memref, rc_peek_t peek, void* ud) {
|
||||
while (memref) {
|
||||
memref->previous = memref->value;
|
||||
memref->value = rc_memref_get_value(&memref->memref, peek, ud);
|
||||
if (memref->value != memref->previous)
|
||||
memref->prior = memref->previous;
|
||||
|
||||
if (memref->memref.address != MEMREF_PLACEHOLDER_ADDRESS)
|
||||
rc_update_memref_value(memref, peek, ud);
|
||||
memref = memref->next;
|
||||
}
|
||||
}
|
||||
|
||||
void rc_init_parse_state_memrefs(rc_parse_state_t* parse, rc_memref_value_t** memrefs)
|
||||
{
|
||||
void rc_init_parse_state_memrefs(rc_parse_state_t* parse, rc_memref_value_t** memrefs) {
|
||||
parse->first_memref = memrefs;
|
||||
*memrefs = 0;
|
||||
}
|
||||
|
||||
rc_memref_value_t* rc_get_indirect_memref(rc_memref_value_t* memref, rc_eval_state_t* eval_state) {
|
||||
unsigned new_address;
|
||||
|
||||
if (eval_state->add_address == 0)
|
||||
return memref;
|
||||
|
||||
if (!memref->memref.is_indirect)
|
||||
return memref;
|
||||
|
||||
new_address = memref->memref.address + eval_state->add_address;
|
||||
|
||||
/* an extra rc_memref_value_t is allocated for offset calculations */
|
||||
memref = memref->next;
|
||||
|
||||
/* if the adjusted address has changed, update the record */
|
||||
if (memref->memref.address != new_address) {
|
||||
memref->memref.address = new_address;
|
||||
rc_update_memref_value(memref, eval_state->peek, eval_state->peek_userdata);
|
||||
}
|
||||
|
||||
return memref;
|
||||
}
|
||||
Vendored
+34
-28
@@ -66,7 +66,7 @@ static int rc_parse_operand_lua(rc_operand_t* self, const char** memaddr, rc_par
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
static int rc_parse_operand_memory(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse) {
|
||||
static int rc_parse_operand_memory(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse, int is_indirect) {
|
||||
const char* aux = *memaddr;
|
||||
char* end;
|
||||
unsigned long address;
|
||||
@@ -135,7 +135,7 @@ static int rc_parse_operand_memory(rc_operand_t* self, const char** memaddr, rc_
|
||||
address = 0xffffffffU;
|
||||
}
|
||||
|
||||
self->value.memref = rc_alloc_memref_value(parse, (unsigned)address, size, is_bcd);
|
||||
self->value.memref = rc_alloc_memref_value(parse, address, size, is_bcd, is_indirect);
|
||||
if (parse->offset < 0)
|
||||
return parse->offset;
|
||||
|
||||
@@ -143,7 +143,7 @@ static int rc_parse_operand_memory(rc_operand_t* self, const char** memaddr, rc_
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
static int rc_parse_operand_trigger(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse) {
|
||||
static int rc_parse_operand_trigger(rc_operand_t* self, const char** memaddr, int is_indirect, rc_parse_state_t* parse) {
|
||||
const char* aux = *memaddr;
|
||||
char* end;
|
||||
int ret;
|
||||
@@ -151,6 +151,11 @@ static int rc_parse_operand_trigger(rc_operand_t* self, const char** memaddr, rc
|
||||
|
||||
switch (*aux) {
|
||||
case 'h': case 'H':
|
||||
if (aux[2] == 'x' || aux[2] == 'X') {
|
||||
/* H0x1234 is a typo - either H1234 or 0xH1234 was probably meant */
|
||||
return RC_INVALID_CONST_OPERAND;
|
||||
}
|
||||
|
||||
value = strtoul(++aux, &end, 16);
|
||||
|
||||
if (end == aux) {
|
||||
@@ -171,7 +176,7 @@ static int rc_parse_operand_trigger(rc_operand_t* self, const char** memaddr, rc
|
||||
if (aux[1] == 'x' || aux[1] == 'X') {
|
||||
/* fall through */
|
||||
default:
|
||||
ret = rc_parse_operand_memory(self, &aux, parse);
|
||||
ret = rc_parse_operand_memory(self, &aux, parse, is_indirect);
|
||||
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
@@ -214,11 +219,12 @@ static int rc_parse_operand_trigger(rc_operand_t* self, const char** memaddr, rc
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
static int rc_parse_operand_term(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse) {
|
||||
static int rc_parse_operand_term(rc_operand_t* self, const char** memaddr, int is_indirect, rc_parse_state_t* parse) {
|
||||
const char* aux = *memaddr;
|
||||
char* end;
|
||||
int ret;
|
||||
unsigned long value;
|
||||
long svalue;
|
||||
|
||||
switch (*aux) {
|
||||
case 'h': case 'H':
|
||||
@@ -239,18 +245,18 @@ static int rc_parse_operand_term(rc_operand_t* self, const char** memaddr, rc_pa
|
||||
break;
|
||||
|
||||
case 'v': case 'V':
|
||||
value = strtoul(++aux, &end, 10);
|
||||
svalue = strtol(++aux, &end, 10);
|
||||
|
||||
if (end == aux) {
|
||||
return RC_INVALID_CONST_OPERAND;
|
||||
}
|
||||
|
||||
if (value > 0xffffffffU) {
|
||||
value = 0xffffffffU;
|
||||
if (svalue > 0xffffffffU) {
|
||||
svalue = 0xffffffffU;
|
||||
}
|
||||
|
||||
self->type = RC_OPERAND_CONST;
|
||||
self->value.num = (unsigned)value;
|
||||
self->value.num = (unsigned)svalue;
|
||||
|
||||
aux = end;
|
||||
break;
|
||||
@@ -259,7 +265,7 @@ static int rc_parse_operand_term(rc_operand_t* self, const char** memaddr, rc_pa
|
||||
if (aux[1] == 'x' || aux[1] == 'X') {
|
||||
/* fall through */
|
||||
default:
|
||||
ret = rc_parse_operand_memory(self, &aux, parse);
|
||||
ret = rc_parse_operand_memory(self, &aux, parse, is_indirect);
|
||||
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
@@ -303,12 +309,12 @@ static int rc_parse_operand_term(rc_operand_t* self, const char** memaddr, rc_pa
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
int rc_parse_operand(rc_operand_t* self, const char** memaddr, int is_trigger, rc_parse_state_t* parse) {
|
||||
int rc_parse_operand(rc_operand_t* self, const char** memaddr, int is_trigger, int is_indirect, rc_parse_state_t* parse) {
|
||||
if (is_trigger) {
|
||||
return rc_parse_operand_trigger(self, memaddr, parse);
|
||||
return rc_parse_operand_trigger(self, memaddr, is_indirect, parse);
|
||||
}
|
||||
else {
|
||||
return rc_parse_operand_term(self, memaddr, parse);
|
||||
return rc_parse_operand_term(self, memaddr, is_indirect, parse);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,7 +339,7 @@ static int rc_luapeek(lua_State* L) {
|
||||
|
||||
#endif /* RC_DISABLE_LUA */
|
||||
|
||||
unsigned rc_evaluate_operand(rc_operand_t* self, rc_peek_t peek, void* ud, lua_State* L) {
|
||||
unsigned rc_evaluate_operand(rc_operand_t* self, rc_eval_state_t* eval_state) {
|
||||
#ifndef RC_DISABLE_LUA
|
||||
rc_luapeek_t luapeek;
|
||||
#endif /* RC_DISABLE_LUA */
|
||||
@@ -352,25 +358,25 @@ unsigned rc_evaluate_operand(rc_operand_t* self, rc_peek_t peek, void* ud, lua_S
|
||||
case RC_OPERAND_LUA:
|
||||
#ifndef RC_DISABLE_LUA
|
||||
|
||||
if (L != 0) {
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, self->value.luafunc);
|
||||
lua_pushcfunction(L, rc_luapeek);
|
||||
if (eval_state->L != 0) {
|
||||
lua_rawgeti(eval_state->L, LUA_REGISTRYINDEX, self->value.luafunc);
|
||||
lua_pushcfunction(eval_state->L, rc_luapeek);
|
||||
|
||||
luapeek.peek = peek;
|
||||
luapeek.ud = ud;
|
||||
luapeek.peek = eval_state->peek;
|
||||
luapeek.ud = eval_state->peek_userdata;
|
||||
|
||||
lua_pushlightuserdata(L, &luapeek);
|
||||
lua_pushlightuserdata(eval_state->L, &luapeek);
|
||||
|
||||
if (lua_pcall(L, 2, 1, 0) == LUA_OK) {
|
||||
if (lua_isboolean(L, -1)) {
|
||||
value = lua_toboolean(L, -1);
|
||||
if (lua_pcall(eval_state->L, 2, 1, 0) == LUA_OK) {
|
||||
if (lua_isboolean(eval_state->L, -1)) {
|
||||
value = lua_toboolean(eval_state->L, -1);
|
||||
}
|
||||
else {
|
||||
value = (unsigned)lua_tonumber(L, -1);
|
||||
value = (unsigned)lua_tonumber(eval_state->L, -1);
|
||||
}
|
||||
}
|
||||
|
||||
lua_pop(L, 1);
|
||||
lua_pop(eval_state->L, 1);
|
||||
}
|
||||
|
||||
#endif /* RC_DISABLE_LUA */
|
||||
@@ -378,15 +384,15 @@ unsigned rc_evaluate_operand(rc_operand_t* self, rc_peek_t peek, void* ud, lua_S
|
||||
break;
|
||||
|
||||
case RC_OPERAND_ADDRESS:
|
||||
value = self->value.memref->value;
|
||||
value = rc_get_indirect_memref(self->value.memref, eval_state)->value;
|
||||
break;
|
||||
|
||||
case RC_OPERAND_DELTA:
|
||||
value = self->value.memref->previous;
|
||||
value = rc_get_indirect_memref(self->value.memref, eval_state)->previous;
|
||||
break;
|
||||
|
||||
case RC_OPERAND_PRIOR:
|
||||
value = self->value.memref->prior;
|
||||
value = rc_get_indirect_memref(self->value.memref, eval_state)->prior;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+20
-3
@@ -51,8 +51,10 @@ static rc_richpresence_display_t* rc_parse_richpresence_display_internal(const c
|
||||
const char* in;
|
||||
char* out;
|
||||
|
||||
if (endline - line < 1)
|
||||
if (endline - line < 1) {
|
||||
parse->offset = RC_MISSING_DISPLAY_STRING;
|
||||
return 0;
|
||||
}
|
||||
|
||||
{
|
||||
self = RC_ALLOC(rc_richpresence_display_t, parse);
|
||||
@@ -103,6 +105,11 @@ static rc_richpresence_display_t* rc_parse_richpresence_display_internal(const c
|
||||
while (ptr < endline && *ptr != '(')
|
||||
++ptr;
|
||||
|
||||
if (ptr == endline) {
|
||||
parse->offset = RC_MISSING_VALUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ptr > line) {
|
||||
if (!parse->buffer) {
|
||||
/* just calculating size, can't confirm lookup exists */
|
||||
@@ -179,6 +186,7 @@ static const char* rc_parse_richpresence_lookup(rc_richpresence_lookup_t* lookup
|
||||
const char* line;
|
||||
const char* endline;
|
||||
const char* defaultlabel = 0;
|
||||
char* endptr = 0;
|
||||
unsigned key;
|
||||
int chars;
|
||||
|
||||
@@ -208,9 +216,14 @@ static const char* rc_parse_richpresence_lookup(rc_richpresence_lookup_t* lookup
|
||||
}
|
||||
|
||||
if (number[0] == '0' && number[1] == 'x')
|
||||
key = (unsigned)strtoul(&number[2], 0, 16);
|
||||
key = strtoul(&number[2], &endptr, 16);
|
||||
else
|
||||
key = (unsigned)strtoul(&number[0], 0, 10);
|
||||
key = strtoul(&number[0], &endptr, 10);
|
||||
|
||||
if (*endptr && !isspace(*endptr)) {
|
||||
parse->offset = RC_INVALID_CONST_OPERAND;
|
||||
return nextline;
|
||||
}
|
||||
|
||||
item = RC_ALLOC(rc_richpresence_lookup_item_t, parse);
|
||||
item->value = key;
|
||||
@@ -263,6 +276,8 @@ void rc_parse_richpresence_internal(rc_richpresence_t* self, const char* script,
|
||||
nextlookup = &lookup->next;
|
||||
|
||||
nextline = rc_parse_richpresence_lookup(lookup, nextline, parse);
|
||||
if (parse->offset < 0)
|
||||
return;
|
||||
|
||||
} else if (strncmp(line, "Format:", 7) == 0) {
|
||||
line += 7;
|
||||
@@ -316,6 +331,8 @@ void rc_parse_richpresence_internal(rc_richpresence_t* self, const char* script,
|
||||
|
||||
if (ptr < endline) {
|
||||
*nextdisplay = rc_parse_richpresence_display_internal(ptr + 1, endline, parse, self);
|
||||
if (parse->offset < 0)
|
||||
return;
|
||||
trigger = &((*nextdisplay)->trigger);
|
||||
rc_parse_trigger_internal(trigger, &line, parse);
|
||||
trigger->memrefs = 0;
|
||||
|
||||
Vendored
+11
-7
@@ -1,6 +1,6 @@
|
||||
#include "internal.h"
|
||||
|
||||
rc_term_t* rc_parse_term(const char** memaddr, rc_parse_state_t* parse) {
|
||||
rc_term_t* rc_parse_term(const char** memaddr, int is_indirect, rc_parse_state_t* parse) {
|
||||
rc_term_t* self;
|
||||
const char* aux;
|
||||
char size;
|
||||
@@ -10,7 +10,7 @@ rc_term_t* rc_parse_term(const char** memaddr, rc_parse_state_t* parse) {
|
||||
self = RC_ALLOC(rc_term_t, parse);
|
||||
self->invert = 0;
|
||||
|
||||
ret2 = rc_parse_operand(&self->operand1, &aux, 0, parse);
|
||||
ret2 = rc_parse_operand(&self->operand1, &aux, 0, is_indirect, parse);
|
||||
|
||||
if (ret2 < 0) {
|
||||
parse->offset = ret2;
|
||||
@@ -25,7 +25,7 @@ rc_term_t* rc_parse_term(const char** memaddr, rc_parse_state_t* parse) {
|
||||
self->invert = 1;
|
||||
}
|
||||
|
||||
ret2 = rc_parse_operand(&self->operand2, &aux, 0, parse);
|
||||
ret2 = rc_parse_operand(&self->operand2, &aux, 0, is_indirect, parse);
|
||||
|
||||
if (ret2 < 0) {
|
||||
parse->offset = ret2;
|
||||
@@ -88,12 +88,16 @@ rc_term_t* rc_parse_term(const char** memaddr, rc_parse_state_t* parse) {
|
||||
return self;
|
||||
}
|
||||
|
||||
unsigned rc_evaluate_term(rc_term_t* self, rc_peek_t peek, void* ud, lua_State* L) {
|
||||
unsigned value = rc_evaluate_operand(&self->operand1, peek, ud, L);
|
||||
int rc_evaluate_term(rc_term_t* self, rc_eval_state_t* eval_state) {
|
||||
/* Operands are usually memory references and are always retrieved as unsigned. The floating
|
||||
* point operand is signed, and will automatically make the result signed. Otherwise, multiply
|
||||
* by the secondary operand (which is usually 1) and cast to signed.
|
||||
*/
|
||||
unsigned value = rc_evaluate_operand(&self->operand1, eval_state);
|
||||
|
||||
if (self->operand2.type != RC_OPERAND_FP) {
|
||||
return value * (rc_evaluate_operand(&self->operand2, peek, ud, L) ^ self->invert);
|
||||
return (int)(value * (rc_evaluate_operand(&self->operand2, eval_state) ^ self->invert));
|
||||
}
|
||||
|
||||
return (unsigned)((double)value * self->operand2.value.dbl);
|
||||
return (int)((double)value * self->operand2.value.dbl);
|
||||
}
|
||||
Vendored
+106
-30
@@ -1,6 +1,7 @@
|
||||
#include "internal.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <memory.h>
|
||||
|
||||
void rc_parse_trigger_internal(rc_trigger_t* self, const char** memaddr, rc_parse_state_t* parse) {
|
||||
rc_condset_t** next;
|
||||
@@ -35,6 +36,11 @@ void rc_parse_trigger_internal(rc_trigger_t* self, const char** memaddr, rc_pars
|
||||
|
||||
*next = 0;
|
||||
*memaddr = aux;
|
||||
|
||||
self->measured_value = 0;
|
||||
self->measured_target = parse->measured_target;
|
||||
self->state = RC_TRIGGER_STATE_WAITING;
|
||||
self->has_hits = 0;
|
||||
}
|
||||
|
||||
int rc_trigger_size(const char* memaddr) {
|
||||
@@ -63,36 +69,7 @@ rc_trigger_t* rc_parse_trigger(void* buffer, const char* memaddr, lua_State* L,
|
||||
return parse.offset >= 0 ? self : 0;
|
||||
}
|
||||
|
||||
int rc_test_trigger(rc_trigger_t* self, rc_peek_t peek, void* ud, lua_State* L) {
|
||||
int ret, reset;
|
||||
rc_condset_t* condset;
|
||||
|
||||
rc_update_memref_values(self->memrefs, peek, ud);
|
||||
|
||||
reset = 0;
|
||||
ret = self->requirement != 0 ? rc_test_condset(self->requirement, &reset, peek, ud, L) : 1;
|
||||
condset = self->alternative;
|
||||
|
||||
if (condset) {
|
||||
int sub = 0;
|
||||
|
||||
do {
|
||||
sub |= rc_test_condset(condset, &reset, peek, ud, L);
|
||||
condset = condset->next;
|
||||
}
|
||||
while (condset != 0);
|
||||
|
||||
ret &= sub && !reset;
|
||||
}
|
||||
|
||||
if (reset) {
|
||||
rc_reset_trigger(self);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void rc_reset_trigger(rc_trigger_t* self) {
|
||||
static void rc_reset_trigger_hitcounts(rc_trigger_t* self) {
|
||||
rc_condset_t* condset;
|
||||
|
||||
if (self->requirement != 0) {
|
||||
@@ -106,3 +83,102 @@ void rc_reset_trigger(rc_trigger_t* self) {
|
||||
condset = condset->next;
|
||||
}
|
||||
}
|
||||
|
||||
int rc_evaluate_trigger(rc_trigger_t* self, rc_peek_t peek, void* ud, lua_State* L) {
|
||||
rc_eval_state_t eval_state;
|
||||
rc_condset_t* condset;
|
||||
int ret;
|
||||
char is_paused;
|
||||
|
||||
/* previously triggered, do nothing - return INACTIVE so caller doesn't report a repeated trigger */
|
||||
if (self->state == RC_TRIGGER_STATE_TRIGGERED)
|
||||
return RC_TRIGGER_STATE_INACTIVE;
|
||||
|
||||
rc_update_memref_values(self->memrefs, peek, ud);
|
||||
|
||||
/* not yet active, only update the memrefs - so deltas are corrent when it becomes active */
|
||||
if (self->state == RC_TRIGGER_STATE_INACTIVE)
|
||||
return RC_TRIGGER_STATE_INACTIVE;
|
||||
|
||||
/* process the trigger */
|
||||
memset(&eval_state, 0, sizeof(eval_state));
|
||||
eval_state.peek = peek;
|
||||
eval_state.peek_userdata = ud;
|
||||
eval_state.L = L;
|
||||
|
||||
ret = self->requirement != 0 ? rc_test_condset(self->requirement, &eval_state) : 1;
|
||||
condset = self->alternative;
|
||||
|
||||
if (condset) {
|
||||
int sub = 0;
|
||||
|
||||
do {
|
||||
sub |= rc_test_condset(condset, &eval_state);
|
||||
condset = condset->next;
|
||||
}
|
||||
while (condset != 0);
|
||||
|
||||
ret &= sub;
|
||||
}
|
||||
|
||||
self->measured_value = eval_state.measured_value;
|
||||
|
||||
/* if the state is WAITING and the trigger is ready to fire, ignore it and reset the hit counts */
|
||||
/* otherwise, if the state is WAITING, proceed to activating the trigger */
|
||||
if (self->state == RC_TRIGGER_STATE_WAITING && ret) {
|
||||
rc_reset_trigger(self);
|
||||
self->has_hits = 0;
|
||||
return RC_TRIGGER_STATE_WAITING;
|
||||
}
|
||||
|
||||
if (eval_state.was_reset) {
|
||||
/* if any ResetIf condition was true, reset the hit counts */
|
||||
rc_reset_trigger_hitcounts(self);
|
||||
|
||||
/* if there were hit counts to clear, return RESET, but don't change the state */
|
||||
if (self->has_hits) {
|
||||
self->has_hits = 0;
|
||||
return RC_TRIGGER_STATE_RESET;
|
||||
}
|
||||
|
||||
/* any hits that were tallied were just reset */
|
||||
eval_state.has_hits = 0;
|
||||
}
|
||||
else if (ret) {
|
||||
/* trigger was triggered */
|
||||
self->state = RC_TRIGGER_STATE_TRIGGERED;
|
||||
return RC_TRIGGER_STATE_TRIGGERED;
|
||||
}
|
||||
|
||||
/* did not trigger this frame - update the information we'll need for next time */
|
||||
self->has_hits = eval_state.has_hits;
|
||||
|
||||
/* check to see if the trigger is paused */
|
||||
is_paused = (self->requirement != NULL) ? self->requirement->is_paused : 0;
|
||||
if (!is_paused) {
|
||||
/* if the core is not paused, all alts must be paused to count as a paused trigger */
|
||||
is_paused = (self->alternative != NULL);
|
||||
for (condset = self->alternative; condset != NULL; condset = condset->next) {
|
||||
if (!condset->is_paused) {
|
||||
is_paused = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self->state = is_paused ? RC_TRIGGER_STATE_PAUSED : RC_TRIGGER_STATE_ACTIVE;
|
||||
return self->state;
|
||||
}
|
||||
|
||||
int rc_test_trigger(rc_trigger_t* self, rc_peek_t peek, void* ud, lua_State* L) {
|
||||
/* for backwards compatibilty, rc_test_trigger always assumes the achievement is active */
|
||||
self->state = RC_TRIGGER_STATE_ACTIVE;
|
||||
|
||||
return (rc_evaluate_trigger(self, peek, ud, L) == RC_TRIGGER_STATE_TRIGGERED);
|
||||
}
|
||||
|
||||
void rc_reset_trigger(rc_trigger_t* self) {
|
||||
rc_reset_trigger_hitcounts(self);
|
||||
|
||||
self->state = RC_TRIGGER_STATE_WAITING;
|
||||
}
|
||||
Vendored
+101
-6
@@ -1,8 +1,88 @@
|
||||
#include "internal.h"
|
||||
|
||||
#include <memory.h>
|
||||
|
||||
static void rc_parse_cond_value(rc_value_t* self, const char** memaddr, rc_parse_state_t* parse) {
|
||||
rc_condition_t** next;
|
||||
int has_measured;
|
||||
int in_add_address;
|
||||
|
||||
has_measured = 0;
|
||||
in_add_address = 0;
|
||||
self->expressions = 0;
|
||||
|
||||
/* this largely duplicates rc_parse_condset, but we cannot call it directly, as we need to check the
|
||||
* type of each condition as we go */
|
||||
self->conditions = RC_ALLOC(rc_condset_t, parse);
|
||||
self->conditions->next = 0;
|
||||
self->conditions->has_pause = 0;
|
||||
|
||||
next = &self->conditions->conditions;
|
||||
for (;;) {
|
||||
*next = rc_parse_condition(memaddr, parse, in_add_address);
|
||||
|
||||
if (parse->offset < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
in_add_address = (*next)->type == RC_CONDITION_ADD_ADDRESS;
|
||||
|
||||
switch ((*next)->type) {
|
||||
case RC_CONDITION_ADD_HITS:
|
||||
case RC_CONDITION_ADD_SOURCE:
|
||||
case RC_CONDITION_SUB_SOURCE:
|
||||
case RC_CONDITION_AND_NEXT:
|
||||
case RC_CONDITION_ADD_ADDRESS:
|
||||
/* combining flags are allowed */
|
||||
break;
|
||||
|
||||
case RC_CONDITION_RESET_IF:
|
||||
/* ResetIf is allowed (primarily for rich presense - leaderboard will typically cancel instead of resetting) */
|
||||
break;
|
||||
|
||||
case RC_CONDITION_MEASURED:
|
||||
if (has_measured) {
|
||||
parse->offset = RC_MULTIPLE_MEASURED;
|
||||
return;
|
||||
}
|
||||
has_measured = 1;
|
||||
if ((*next)->required_hits == 0 && (*next)->oper != RC_CONDITION_NONE)
|
||||
(*next)->required_hits = (unsigned)-1;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* non-combinding flags and PauseIf are not allowed */
|
||||
parse->offset = RC_INVALID_VALUE_FLAG;
|
||||
return;
|
||||
}
|
||||
|
||||
(*next)->pause = 0;
|
||||
next = &(*next)->next;
|
||||
|
||||
if (**memaddr != '_') {
|
||||
break;
|
||||
}
|
||||
|
||||
(*memaddr)++;
|
||||
}
|
||||
|
||||
*next = 0;
|
||||
|
||||
if (!has_measured) {
|
||||
parse->offset = RC_MISSING_VALUE_MEASURED;
|
||||
}
|
||||
}
|
||||
|
||||
void rc_parse_value_internal(rc_value_t* self, const char** memaddr, rc_parse_state_t* parse) {
|
||||
rc_expression_t** next;
|
||||
|
||||
/* if it starts with a condition flag (M: A: B: C:), parse the conditions */
|
||||
if ((*memaddr)[1] == ':') {
|
||||
rc_parse_cond_value(self, memaddr, parse);
|
||||
return;
|
||||
}
|
||||
|
||||
self->conditions = 0;
|
||||
next = &self->expressions;
|
||||
|
||||
for (;;) {
|
||||
@@ -50,17 +130,15 @@ rc_value_t* rc_parse_value(void* buffer, const char* memaddr, lua_State* L, int
|
||||
return parse.offset >= 0 ? self : 0;
|
||||
}
|
||||
|
||||
unsigned rc_evaluate_value(rc_value_t* self, rc_peek_t peek, void* ud, lua_State* L) {
|
||||
static int rc_evaluate_expr_value(rc_value_t* self, rc_eval_state_t* eval_state) {
|
||||
rc_expression_t* exp;
|
||||
unsigned value, max;
|
||||
|
||||
rc_update_memref_values(self->memrefs, peek, ud);
|
||||
int value, max;
|
||||
|
||||
exp = self->expressions;
|
||||
max = rc_evaluate_expression(exp, peek, ud, L);
|
||||
max = rc_evaluate_expression(exp, eval_state);
|
||||
|
||||
for (exp = exp->next; exp != 0; exp = exp->next) {
|
||||
value = rc_evaluate_expression(exp, peek, ud, L);
|
||||
value = rc_evaluate_expression(exp, eval_state);
|
||||
|
||||
if (value > max) {
|
||||
max = value;
|
||||
@@ -69,3 +147,20 @@ unsigned rc_evaluate_value(rc_value_t* self, rc_peek_t peek, void* ud, lua_State
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
int rc_evaluate_value(rc_value_t* self, rc_peek_t peek, void* ud, lua_State* L) {
|
||||
rc_eval_state_t eval_state;
|
||||
memset(&eval_state, 0, sizeof(eval_state));
|
||||
eval_state.peek = peek;
|
||||
eval_state.peek_userdata = ud;
|
||||
eval_state.L = L;
|
||||
|
||||
rc_update_memref_values(self->memrefs, peek, ud);
|
||||
|
||||
if (self->expressions) {
|
||||
return rc_evaluate_expr_value(self, &eval_state);
|
||||
}
|
||||
|
||||
rc_test_condset(self->conditions, &eval_state);
|
||||
return (int)eval_state.measured_value;
|
||||
}
|
||||
Vendored
+2
-2
@@ -69,7 +69,7 @@ int rc_url_award_cheevo(char* buffer, size_t size, const char* user_name, const
|
||||
return (size_t)written >= size ? -1 : 0;
|
||||
}
|
||||
|
||||
int rc_url_submit_lboard(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned lboard_id, unsigned value, unsigned char hash[16]) {
|
||||
int rc_url_submit_lboard(char* buffer, size_t size, const char* user_name, const char* login_token, unsigned lboard_id, int value, unsigned char hash[16]) {
|
||||
char urle_user_name[64];
|
||||
char urle_login_token[64];
|
||||
int written;
|
||||
@@ -85,7 +85,7 @@ int rc_url_submit_lboard(char* buffer, size_t size, const char* user_name, const
|
||||
written = snprintf(
|
||||
buffer,
|
||||
size,
|
||||
"http://retroachievements.org/dorequest.php?r=submitlbentry&u=%s&t=%s&i=%u&s=%u&v=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
"http://retroachievements.org/dorequest.php?r=submitlbentry&u=%s&t=%s&i=%u&s=%d&v=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
urle_user_name,
|
||||
urle_login_token,
|
||||
lboard_id,
|
||||
|
||||
Loaded 100 of 579 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user