mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-09 17:29:21 -10:00
Compare commits
1081
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b6e564ba3 | ||
|
|
b574780d99 | ||
|
|
1a2ee91117 | ||
|
|
bc6fec6e0c | ||
|
|
ec06ab0941 | ||
|
|
32e2aacd3c | ||
|
|
7f08729a5e | ||
|
|
ea6139b234 | ||
|
|
96d87802cd | ||
|
|
618cfacd59 | ||
|
|
6d9ee4c161 | ||
|
|
46b9432fb8 | ||
|
|
c66bcc05cf | ||
|
|
00b15c4e79 | ||
|
|
597dbfdf9a | ||
|
|
af6b09d950 | ||
|
|
0194ce91bf | ||
|
|
a6901dc85e | ||
|
|
8850a4984b | ||
|
|
daef26f951 | ||
|
|
5ca99fdb51 | ||
|
|
23a06ef1a1 | ||
|
|
cd3e818210 | ||
|
|
619df7e11b | ||
|
|
df98bca9ae | ||
|
|
10e1f5d72a | ||
|
|
aac207b455 | ||
|
|
ca311246b1 | ||
|
|
22de07a662 | ||
|
|
2329a36f54 | ||
|
|
ab3385c73d | ||
|
|
f21f113678 | ||
|
|
d5b1c3092f | ||
|
|
d401816f41 | ||
|
|
dbb74ba5ab | ||
|
|
4e188c0f26 | ||
|
|
376f06c993 | ||
|
|
1bd188c5a7 | ||
|
|
d3813dddb1 | ||
|
|
957b71cfdc | ||
|
|
d35200aa56 | ||
|
|
919954c5be | ||
|
|
cc7247aecf | ||
|
|
024dbb5008 | ||
|
|
41afbc30ef | ||
|
|
8d513f8199 | ||
|
|
eb49458284 | ||
|
|
b2c87baa87 | ||
|
|
71ca56e0fb | ||
|
|
f505d625a3 | ||
|
|
6855b7f2b1 | ||
|
|
1ad0251da9 | ||
|
|
e5d6d411be | ||
|
|
b0c5362da6 | ||
|
|
67bc91c1d0 | ||
|
|
f0a510c8a6 | ||
|
|
f2d574fd87 | ||
|
|
8590e0e3fe | ||
|
|
d44f3e1239 | ||
|
|
1855ce5fc7 | ||
|
|
fa5ec2d4b1 | ||
|
|
bea512b70b | ||
|
|
54ae219302 | ||
|
|
5ac7d89e36 | ||
|
|
755789f825 | ||
|
|
5f3cb1fae2 | ||
|
|
9bd6051581 | ||
|
|
df5a2c5160 | ||
|
|
2482a6f42a | ||
|
|
26d6c8243a | ||
|
|
4fae4ead73 | ||
|
|
0f3ae9b03d | ||
|
|
5a65773b81 | ||
|
|
559a173e8b | ||
|
|
9a97eb47ad | ||
|
|
ac539f6316 | ||
|
|
ca26e50050 | ||
|
|
b620325714 | ||
|
|
1e4557c09a | ||
|
|
11d5d3170d | ||
|
|
21d3c13ed3 | ||
|
|
393343c03c | ||
|
|
4f57b6f6fa | ||
|
|
7a6434ecb2 | ||
|
|
b02ef55a92 | ||
|
|
462137305b | ||
|
|
eb50d7dbb4 | ||
|
|
77a17b213d | ||
|
|
ddd75d3bb9 | ||
|
|
ffb59e5261 | ||
|
|
5f834a8cb3 | ||
|
|
9a6faa3ddd | ||
|
|
0c0de9f0ad | ||
|
|
bbc121cd74 | ||
|
|
48bb705b03 | ||
|
|
78431d0700 | ||
|
|
97144833cb | ||
|
|
ae327a769b | ||
|
|
a66b1b3e48 | ||
|
|
5e879fa201 | ||
|
|
80136dd3ec | ||
|
|
2e82db6447 | ||
|
|
2802817239 | ||
|
|
9750ebcf71 | ||
|
|
0e98b4ddea | ||
|
|
97b9a79fc0 | ||
|
|
3963039102 | ||
|
|
4f26860bb4 | ||
|
|
47b6d4a99d | ||
|
|
52db47d0fd | ||
|
|
92b330f2aa | ||
|
|
bf8f527143 | ||
|
|
5a8920c862 | ||
|
|
dfea030f5b | ||
|
|
e68e3e9bb3 | ||
|
|
f3458fb943 | ||
|
|
d369e06a67 | ||
|
|
fa7dd0f6d9 | ||
|
|
0f142d531a | ||
|
|
6e7e8a7680 | ||
|
|
c2b3ba907c | ||
|
|
ece8ff8ad8 | ||
|
|
89f984400b | ||
|
|
a442c5b14f | ||
|
|
6223ba47fd | ||
|
|
1906a741c2 | ||
|
|
bba924e8d2 | ||
|
|
a6f44ab642 | ||
|
|
e999c65037 | ||
|
|
2d934f4d53 | ||
|
|
f5564120a4 | ||
|
|
b0ac722366 | ||
|
|
757ce5e572 | ||
|
|
def35ebe8e | ||
|
|
a0f3bf7432 | ||
|
|
b837e053e9 | ||
|
|
c8e183fb3c | ||
|
|
29510df156 | ||
|
|
d9157c5dc7 | ||
|
|
692f4443f4 | ||
|
|
d0a08ce959 | ||
|
|
6780f58444 | ||
|
|
a489f1275a | ||
|
|
84f5ab96ea | ||
|
|
fe10d285ec | ||
|
|
9ad6ebc879 | ||
|
|
4116cb6fa5 | ||
|
|
14e974ea07 | ||
|
|
a6b0efa4f0 | ||
|
|
c4880ca840 | ||
|
|
1c4895b8bf | ||
|
|
1ca1d362bf | ||
|
|
beabcebe9d | ||
|
|
1e4af83e2a | ||
|
|
9e84c5c2c8 | ||
|
|
1c82fd29ef | ||
|
|
f0bd4e9172 | ||
|
|
05bf208f7d | ||
|
|
e9e6607fc9 | ||
|
|
5b3942eae7 | ||
|
|
148a489af5 | ||
|
|
d28402b87d | ||
|
|
a736dd27d2 | ||
|
|
ccb8ecec4d | ||
|
|
f1c276b751 | ||
|
|
ef31302bd5 | ||
|
|
28417a02b7 | ||
|
|
cd69803427 | ||
|
|
11b0667e72 | ||
|
|
d4c62a177a | ||
|
|
7c9817b582 | ||
|
|
3ce8d14c2e | ||
|
|
57054a075d | ||
|
|
027bbe0755 | ||
|
|
ac4adabeb9 | ||
|
|
c76cb77202 | ||
|
|
d07e0da412 | ||
|
|
43b72ea23c | ||
|
|
fbeb157bba | ||
|
|
df89a6b604 | ||
|
|
8d7e8bb574 | ||
|
|
20ef0667b0 | ||
|
|
c34982d695 | ||
|
|
0c806447b5 | ||
|
|
b375e08c67 | ||
|
|
b2a4620f3b | ||
|
|
013dd30bde | ||
|
|
7e08c019bc | ||
|
|
8dfaee370a | ||
|
|
c737947d74 | ||
|
|
9a4597d7ba | ||
|
|
82e53d3db8 | ||
|
|
59e36c51a3 | ||
|
|
a4017e69e4 | ||
|
|
8b1fa3bb59 | ||
|
|
2aeb0b079e | ||
|
|
2d9a1d2270 | ||
|
|
075783d4f7 | ||
|
|
a2c378c594 | ||
|
|
9cd5e66b21 | ||
|
|
f58c7f69d9 | ||
|
|
406c8bee7b | ||
|
|
13a2d2419f | ||
|
|
c6e86caeed | ||
|
|
e42a1895af | ||
|
|
efffa2a76e | ||
|
|
5b801bab46 | ||
|
|
187a73d93a | ||
|
|
ef3dbc8378 | ||
|
|
7e1fdafa47 | ||
|
|
92efe48db2 | ||
|
|
1f7532bf52 | ||
|
|
0e3fddf448 | ||
|
|
0515377d63 | ||
|
|
93e5fc60af | ||
|
|
bb30dc3dee | ||
|
|
70ca111a53 | ||
|
|
80225daee0 | ||
|
|
feb4f266fa | ||
|
|
34758d15ef | ||
|
|
6fe45a451d | ||
|
|
f7ad73b494 | ||
|
|
8e46e46a40 | ||
|
|
722e36001f | ||
|
|
8a037a3091 | ||
|
|
f129a55a8a | ||
|
|
390f914357 | ||
|
|
980647c9b8 | ||
|
|
87c1800cb8 | ||
|
|
4c227afb0d | ||
|
|
35c2ec993b | ||
|
|
86b297e0fd | ||
|
|
b513a3d166 | ||
|
|
c19c6a3ca8 | ||
|
|
a40d1ce8b6 | ||
|
|
d9312d09a8 | ||
|
|
97db0291d2 | ||
|
|
ce4fce12c0 | ||
|
|
1661d4e969 | ||
|
|
f459472f6d | ||
|
|
6170fc45ae | ||
|
|
c1ed271a12 | ||
|
|
84a83ef43c | ||
|
|
079070daf7 | ||
|
|
110882903c | ||
|
|
a5f8053533 | ||
|
|
b0e7a4db6a | ||
|
|
9700a009c5 | ||
|
|
64244cd73f | ||
|
|
2178f9d36f | ||
|
|
26c2259b11 | ||
|
|
60e25c5e3b | ||
|
|
fe1f311a35 | ||
|
|
885f9bbcc3 | ||
|
|
7a0dc3c4ca | ||
|
|
a803f652ab | ||
|
|
a2fb0847ae | ||
|
|
bd3533f05d | ||
|
|
5dcec3819e | ||
|
|
a58676709a | ||
|
|
c6af4089b4 | ||
|
|
4e90b731d3 | ||
|
|
5dd06ccfcd | ||
|
|
7b75dc4f9b | ||
|
|
2c47d94bf5 | ||
|
|
e5dc368e20 | ||
|
|
49632bbde9 | ||
|
|
e58b2c9b6b | ||
|
|
9956ff041e | ||
|
|
2d1a657ba8 | ||
|
|
39275e8ce3 | ||
|
|
bdba803909 | ||
|
|
327f220857 | ||
|
|
c844705665 | ||
|
|
109f4fafec | ||
|
|
0527d77de1 | ||
|
|
f9c0cb198c | ||
|
|
e596bf7925 | ||
|
|
2af9441d35 | ||
|
|
f4b79ad13d | ||
|
|
0c7650c525 | ||
|
|
d0612f906d | ||
|
|
05b36ec374 | ||
|
|
1df4fa70e8 | ||
|
|
9dd06996c5 | ||
|
|
c427e9d9ba | ||
|
|
18cc6b4bd9 | ||
|
|
2aee034a24 | ||
|
|
10d7e4c643 | ||
|
|
2962707d5f | ||
|
|
15d28fe2eb | ||
|
|
fe694b8f96 | ||
|
|
8b1e816f77 | ||
|
|
9224329450 | ||
|
|
984d8e2584 | ||
|
|
87f7a7f94d | ||
|
|
85c73d523c | ||
|
|
be1a768bca | ||
|
|
93649d9147 | ||
|
|
902c115d48 | ||
|
|
bb6911077a | ||
|
|
33ac1856f2 | ||
|
|
78341e5824 | ||
|
|
ab9a4a95b1 | ||
|
|
b3aafd2f86 | ||
|
|
b4ccf23701 | ||
|
|
742e195172 | ||
|
|
f831fe9ad0 | ||
|
|
e90f352c2f | ||
|
|
0c2299396c | ||
|
|
9000e81498 | ||
|
|
4714af546b | ||
|
|
a40edc40e9 | ||
|
|
1d988d374a | ||
|
|
d53ff1cc9b | ||
|
|
149beaf061 | ||
|
|
910d729d50 | ||
|
|
0f5f8798ea | ||
|
|
09d496b534 | ||
|
|
5ac432026a | ||
|
|
8e9587f451 | ||
|
|
9de0cc1ffe | ||
|
|
0faddc91f7 | ||
|
|
d2f8af553d | ||
|
|
5c2f79aa29 | ||
|
|
9e1ad64e89 | ||
|
|
0d36cf2a4a | ||
|
|
61aeb982fd | ||
|
|
48e4b02fad | ||
|
|
8373ac6746 | ||
|
|
73342af8b6 | ||
|
|
d972f66faa | ||
|
|
dadf49764b | ||
|
|
c9ca0489ed | ||
|
|
bb2cf59a12 | ||
|
|
e3d2a9b614 | ||
|
|
1071c93c82 | ||
|
|
773c7ed5ee | ||
|
|
a65a5c675a | ||
|
|
0ffd876115 | ||
|
|
fdee0f4e7e | ||
|
|
7f411db808 | ||
|
|
218286aa99 | ||
|
|
d4d9129ad4 | ||
|
|
be89054d07 | ||
|
|
28043d88b0 | ||
|
|
60c32fe494 | ||
|
|
20e70f9caa | ||
|
|
4621ed7dcc | ||
|
|
646cadba8c | ||
|
|
edd9ed3619 | ||
|
|
53a35e87c3 | ||
|
|
e9a5625445 | ||
|
|
8038d899d6 | ||
|
|
e306dd8eeb | ||
|
|
8db304328c | ||
|
|
af88aaee77 | ||
|
|
ea18d4ffcb | ||
|
|
27b02d66aa | ||
|
|
8bde566019 | ||
|
|
7cb5857ed3 | ||
|
|
48830e72df | ||
|
|
fcefefaeab | ||
|
|
21cf6b89a8 | ||
|
|
c007a81103 | ||
|
|
80fc5062c1 | ||
|
|
da8f257323 | ||
|
|
e43f07b85b | ||
|
|
a3be19214e | ||
|
|
90040117af | ||
|
|
5887016db3 | ||
|
|
e5553bde4e | ||
|
|
a35323ace9 | ||
|
|
6521bfcdc1 | ||
|
|
e5bbd9488f | ||
|
|
6b65daf07d | ||
|
|
03f2d2376e | ||
|
|
214a80b338 | ||
|
|
64672b4b63 | ||
|
|
d1c03b22e3 | ||
|
|
260352aa9e | ||
|
|
2ea76c6188 | ||
|
|
9e100b752e | ||
|
|
23b8652656 | ||
|
|
c88226188f | ||
|
|
c3fee95273 | ||
|
|
7900ba604f | ||
|
|
21228cfbd4 | ||
|
|
0437659490 | ||
|
|
d8f780848a | ||
|
|
14580e5f6f | ||
|
|
0ad936f600 | ||
|
|
607711d3f9 | ||
|
|
7439f4d6d0 | ||
|
|
137f18bed1 | ||
|
|
7af4f6e84d | ||
|
|
b644a37622 | ||
|
|
e1daabde65 | ||
|
|
ec685d051e | ||
|
|
f6aeb717ba | ||
|
|
54706bec8a | ||
|
|
eb259174b8 | ||
|
|
3bc06b0d57 | ||
|
|
7f4f1d82bb | ||
|
|
b5c5508e62 | ||
|
|
7a3d78b1c0 | ||
|
|
89b46bc246 | ||
|
|
32ed7ed1d7 | ||
|
|
e4fd172892 | ||
|
|
57c52e4fc7 | ||
|
|
bd04a6412d | ||
|
|
902949ea94 | ||
|
|
0570ed4ca3 | ||
|
|
b3c929499e | ||
|
|
0d46eb9066 | ||
|
|
acf5c2e992 | ||
|
|
7b55b03c96 | ||
|
|
0216aab022 | ||
|
|
c10bac6558 | ||
|
|
d4fb27a7a9 | ||
|
|
4803100dc4 | ||
|
|
ed3412c004 | ||
|
|
63acb6173a | ||
|
|
375eb4b852 | ||
|
|
7dba607d76 | ||
|
|
7d9d57dc50 | ||
|
|
27fbb3f971 | ||
|
|
9188c4a7f0 | ||
|
|
ea7e9aaa61 | ||
|
|
9e85eec4a7 | ||
|
|
41e25902a1 | ||
|
|
bc4a9a3696 | ||
|
|
46ffe5f4b2 | ||
|
|
7aca71e625 | ||
|
|
f556eba0a3 | ||
|
|
197203d09b | ||
|
|
d14c4d2883 | ||
|
|
4954af9dc7 | ||
|
|
b17dd28ff2 | ||
|
|
6e61eb084a | ||
|
|
d0212ec5aa | ||
|
|
523d7d6ee8 | ||
|
|
647e39afaa | ||
|
|
7b46cca917 | ||
|
|
f93499181c | ||
|
|
c31e0ba9b9 | ||
|
|
4a6dc36b1c | ||
|
|
c6967f56bd | ||
|
|
0e654c8e9e | ||
|
|
e1270742b9 | ||
|
|
1c87853496 | ||
|
|
119788593c | ||
|
|
fb2b3695d9 | ||
|
|
aacf2bed34 | ||
|
|
badd588652 | ||
|
|
a40c3767bb | ||
|
|
b0831bf1a0 | ||
|
|
d1f7d8af0d | ||
|
|
f7f007519c | ||
|
|
92a098ee02 | ||
|
|
d00c2a6407 | ||
|
|
991b43d4ee | ||
|
|
ac8a977492 | ||
|
|
1bc588acbd | ||
|
|
eafeb83d0b | ||
|
|
2e215bda5b | ||
|
|
0a5fd837a2 | ||
|
|
edf10b576f | ||
|
|
46dcf1204e | ||
|
|
5feeb362b1 | ||
|
|
d6a1c21fe1 | ||
|
|
67358fb145 | ||
|
|
41fbbda8e8 | ||
|
|
b1b5148090 | ||
|
|
bd1d39d7fb | ||
|
|
b2c7fae912 | ||
|
|
13e88ebe74 | ||
|
|
d5d6b1d91e | ||
|
|
8915d82fd6 | ||
|
|
0785d4aa72 | ||
|
|
0744683c2b | ||
|
|
b483f233d2 | ||
|
|
55afe18872 | ||
|
|
f83e614b4e | ||
|
|
5dc070f041 | ||
|
|
585af66b5c | ||
|
|
c8241f3f21 | ||
|
|
3a82cf980d | ||
|
|
7b47f5f49a | ||
|
|
94e4b1883a | ||
|
|
c73592d379 | ||
|
|
4ba0ba4c70 | ||
|
|
11dba60ea7 | ||
|
|
97ad8cbfd2 | ||
|
|
b5be2006f2 | ||
|
|
8ec39ca7ec | ||
|
|
bd937eb49f | ||
|
|
23b810b820 | ||
|
|
322aeb4e46 | ||
|
|
ed2d6b1730 | ||
|
|
9afa30af5e | ||
|
|
5d3719df44 | ||
|
|
3f00d2f041 | ||
|
|
a30a86a09c | ||
|
|
bd10e5bdc3 | ||
|
|
0e1d5ba30e | ||
|
|
10f42d7034 | ||
|
|
6986caed5b | ||
|
|
c802a549f6 | ||
|
|
0a75b51b29 | ||
|
|
0c64ac0bde | ||
|
|
15b0f5478f | ||
|
|
a6b0199204 | ||
|
|
973f5cda6d | ||
|
|
46a318db45 | ||
|
|
1657d67182 | ||
|
|
7949a9c8ad | ||
|
|
2ae11b7222 | ||
|
|
f05c124c98 | ||
|
|
5f182fa564 | ||
|
|
c2d5003f80 | ||
|
|
6e2709d62a | ||
|
|
eef86d5f72 | ||
|
|
863aaa5b9d | ||
|
|
54eed63418 | ||
|
|
7695298dfc | ||
|
|
917fb1f796 | ||
|
|
81075aa5fa | ||
|
|
ff7982fbcd | ||
|
|
7915b040a9 | ||
|
|
a129764f0d | ||
|
|
aeddcb54e0 | ||
|
|
10f0073778 | ||
|
|
8b6e58eebd | ||
|
|
49bd8d2d27 | ||
|
|
946d87cf89 | ||
|
|
138d5b3a4e | ||
|
|
cdba9accdf | ||
|
|
963350a0f2 | ||
|
|
dd48b65687 | ||
|
|
642d6c9fb8 | ||
|
|
6738fa57aa | ||
|
|
d40d7c389b | ||
|
|
3c2e3f1ce9 | ||
|
|
766c59d469 | ||
|
|
7492f5d60c | ||
|
|
bd9c35d379 | ||
|
|
5d4069cf8f | ||
|
|
0caeed6e1d | ||
|
|
98194ce135 | ||
|
|
4dcda032d0 | ||
|
|
f74fddf3fd | ||
|
|
08481e2a68 | ||
|
|
dc50ff584e | ||
|
|
98be8f0c22 | ||
|
|
3647bdef0f | ||
|
|
75fcd63b4a | ||
|
|
27cacffe54 | ||
|
|
74d85e3269 | ||
|
|
9d92888846 | ||
|
|
adfabcb742 | ||
|
|
620302ddaa | ||
|
|
da9f87c63f | ||
|
|
fe2fd18aad | ||
|
|
1c61068291 | ||
|
|
681983d1b2 | ||
|
|
ec627a9c00 | ||
|
|
462cedb654 | ||
|
|
f1347829c2 | ||
|
|
b08169255d | ||
|
|
610b0b7095 | ||
|
|
caf3f3dadd | ||
|
|
04962e1741 | ||
|
|
44e2530fbb | ||
|
|
52b827155f | ||
|
|
3eecf92f8f | ||
|
|
9184a9d04c | ||
|
|
5534fd7275 | ||
|
|
8e06aa2417 | ||
|
|
f57fcd4048 | ||
|
|
4b4576ed62 | ||
|
|
9f8092dc27 | ||
|
|
e40f0d308b | ||
|
|
2259e9b38e | ||
|
|
e44f0749a1 | ||
|
|
3fe52bb7fb | ||
|
|
2edc6d6e6a | ||
|
|
fce9da5e76 | ||
|
|
4b2f27eff8 | ||
|
|
7919a87b97 | ||
|
|
8584b122e1 | ||
|
|
ec7e528094 | ||
|
|
f0c9c542a2 | ||
|
|
4ed88ec68a | ||
|
|
140b8f5e0a | ||
|
|
b5df2b883a | ||
|
|
4fab84ca9e | ||
|
|
d8a5505204 | ||
|
|
1218aebfbf | ||
|
|
b81ec7d631 | ||
|
|
f8479c2b5a | ||
|
|
69f3dda90a | ||
|
|
a06b303879 | ||
|
|
ef9beea9f8 | ||
|
|
cd8f6ede4e | ||
|
|
e76265e1aa | ||
|
|
6443d6f019 | ||
|
|
293e797146 | ||
|
|
55c855267e | ||
|
|
73a5ec9f42 | ||
|
|
86f8670d0b | ||
|
|
6772b89872 | ||
|
|
d95e46c2bd | ||
|
|
74d9f976a8 | ||
|
|
b1a3ea72c9 | ||
|
|
ab888629a5 | ||
|
|
935c7d0e2c | ||
|
|
a8028d5e8e | ||
|
|
cc1e080dfe | ||
|
|
35f7ef3cc2 | ||
|
|
c226bd87f4 | ||
|
|
c0b7c34264 | ||
|
|
5cf7b57064 | ||
|
|
adf6a7ff20 | ||
|
|
5a7cebf7da | ||
|
|
4a8fdaed84 | ||
|
|
4441219df9 | ||
|
|
750ad9aa7b | ||
|
|
0d7a028ce3 | ||
|
|
84975d71ea | ||
|
|
45c0dc4486 | ||
|
|
2c21e3df8b | ||
|
|
138f41160f | ||
|
|
194de13afb | ||
|
|
2c7c8def4c | ||
|
|
ff3928224e | ||
|
|
a39c38f267 | ||
|
|
8e54b4cec9 | ||
|
|
0dfb2b57fb | ||
|
|
a84c9022af | ||
|
|
0a5d4288f5 | ||
|
|
3c6ac487d0 | ||
|
|
466bd3be7f | ||
|
|
5dc7b7f7c7 | ||
|
|
3e814bc4b6 | ||
|
|
f70b6fbf58 | ||
|
|
30a90adc47 | ||
|
|
621a0b61f6 | ||
|
|
244a2ad052 | ||
|
|
bb04b0b9d3 | ||
|
|
e616b41b62 | ||
|
|
fb8c73508b | ||
|
|
f2a73d1b14 | ||
|
|
2b4f2525d0 | ||
|
|
75175ddbce | ||
|
|
c424315510 | ||
|
|
4dcbd3e383 | ||
|
|
d75e53a11a | ||
|
|
b48ab663b0 | ||
|
|
364d518726 | ||
|
|
d1c7d97b10 | ||
|
|
f8b6443b91 | ||
|
|
8344ed9db5 | ||
|
|
76f3d0c1b7 | ||
|
|
52af69e6cd | ||
|
|
d6b1836919 | ||
|
|
7c483340fc | ||
|
|
33de17548b | ||
|
|
9cd19d4944 | ||
|
|
89e4cac3f1 | ||
|
|
29e9027ec0 | ||
|
|
68c377cd55 | ||
|
|
706ab17b2c | ||
|
|
fede9eee4b | ||
|
|
d84a2ef700 | ||
|
|
4ba92b1643 | ||
|
|
57a728fd41 | ||
|
|
bc8f98358b | ||
|
|
3887db349e | ||
|
|
98448960f5 | ||
|
|
22a2b5ac1c | ||
|
|
6e4620cebc | ||
|
|
458d636861 | ||
|
|
64c01e620d | ||
|
|
57c4802ab4 | ||
|
|
74f1bf59b9 | ||
|
|
cacbd451dc | ||
|
|
7174563f7d | ||
|
|
d5f862ee07 | ||
|
|
f66d4ea33c | ||
|
|
0797fd957a | ||
|
|
b45acf2223 | ||
|
|
30143f15f2 | ||
|
|
24389bbcd5 | ||
|
|
2e50b57643 | ||
|
|
5b995dec26 | ||
|
|
5ae4524176 | ||
|
|
87a7795331 | ||
|
|
44fc3666ed | ||
|
|
cea6b17391 | ||
|
|
334a43a7c5 | ||
|
|
d1300dbdb3 | ||
|
|
b355217e6d | ||
|
|
a6f8355c6f | ||
|
|
ce474040af | ||
|
|
32f68e81d6 | ||
|
|
0bd49c59c6 | ||
|
|
a1ff509276 | ||
|
|
8346c4eeff | ||
|
|
29475a904f | ||
|
|
159602d697 | ||
|
|
de88edf56c | ||
|
|
4fb6bc9f33 | ||
|
|
b82a20ea0c | ||
|
|
8291b18771 | ||
|
|
181824eb00 | ||
|
|
7a2115670a | ||
|
|
951999e5ce | ||
|
|
23acacf436 | ||
|
|
925c459aed | ||
|
|
0482892a9c | ||
|
|
dd922bfc2c | ||
|
|
35543ecd91 | ||
|
|
e08290acb0 | ||
|
|
e34c84d791 | ||
|
|
2e4b734159 | ||
|
|
3b64752f4f | ||
|
|
9829051841 | ||
|
|
fc2a011a5c | ||
|
|
0e7ff6ea4e | ||
|
|
e784cc1aaf | ||
|
|
e4a8f42ad1 | ||
|
|
a04fe66032 | ||
|
|
9669cff16b | ||
|
|
09439332f3 | ||
|
|
216deda910 | ||
|
|
7bbdd6d18a | ||
|
|
b037da7264 | ||
|
|
ef35adc9d6 | ||
|
|
f6a8480f21 | ||
|
|
d3b3b40ea7 | ||
|
|
6972cc2bc6 | ||
|
|
74cef32c1d | ||
|
|
d50be7a0ab | ||
|
|
d228e5f759 | ||
|
|
10546594de | ||
|
|
e9b5f009cc | ||
|
|
d6ec36c707 | ||
|
|
be84700d0a | ||
|
|
ad5b2d614a | ||
|
|
9e87040c02 | ||
|
|
90abd49892 | ||
|
|
654aae58d6 | ||
|
|
e6adca7679 | ||
|
|
095f6d4377 | ||
|
|
b946b146f3 | ||
|
|
4e0f8bf621 | ||
|
|
de4343caeb | ||
|
|
a9426925cf | ||
|
|
aebdc8b747 | ||
|
|
c9d4775ffc | ||
|
|
3b8bd1a6e8 | ||
|
|
734401440d | ||
|
|
9fbf3b9732 | ||
|
|
67b180d63d | ||
|
|
c378665af5 | ||
|
|
3187c87451 | ||
|
|
122be0cc64 | ||
|
|
6b13e3f050 | ||
|
|
87e248f4eb | ||
|
|
2be7106055 | ||
|
|
0a24f5f38a | ||
|
|
6189fd3f42 | ||
|
|
29d5a692d0 | ||
|
|
358cafa978 | ||
|
|
b3eebbd5ec | ||
|
|
cc5b491e21 | ||
|
|
bf0b9f536a | ||
|
|
6f471e0660 | ||
|
|
484c4ad51e | ||
|
|
66c77af4a6 | ||
|
|
667568b0b8 | ||
|
|
f3ff36ac34 | ||
|
|
feaefbef04 | ||
|
|
a16aba2138 | ||
|
|
50d27fada9 | ||
|
|
a6d92de0b2 | ||
|
|
89391ccf9a | ||
|
|
e430f832cc | ||
|
|
9280340fe0 | ||
|
|
85466225de | ||
|
|
c9aaf598bb | ||
|
|
92e795aa28 | ||
|
|
fa2c789c3f | ||
|
|
475213aa0a | ||
|
|
32d6eeaf07 | ||
|
|
6f95e7819a | ||
|
|
f24f827c4c | ||
|
|
53a266728b | ||
|
|
215ed2ccf6 | ||
|
|
a671b6394c | ||
|
|
dec1fd097c | ||
|
|
a0f0d7bed2 | ||
|
|
6a21eca5df | ||
|
|
c37f540b72 | ||
|
|
5aba614b60 | ||
|
|
0680505ebf | ||
|
|
528af55abd | ||
|
|
1167dde73a | ||
|
|
b3abdefb9a | ||
|
|
1b0ae7a0b2 | ||
|
|
f3daf070e1 | ||
|
|
6241909a08 | ||
|
|
7fbb7a8007 | ||
|
|
e96cbcac04 | ||
|
|
0706cdea4c | ||
|
|
07099797bd | ||
|
|
77967f0148 | ||
|
|
56e40e8204 | ||
|
|
218c6f30b9 | ||
|
|
b2c20e8ce0 | ||
|
|
76eeee2c9a | ||
|
|
3b7e0a8db1 | ||
|
|
bc23d070de | ||
|
|
951ea6baaf | ||
|
|
84ab14cb83 | ||
|
|
019130298a | ||
|
|
99917368b4 | ||
|
|
5f12edaae4 | ||
|
|
8eb8b44e83 | ||
|
|
9c534c3550 | ||
|
|
10c1361751 | ||
|
|
2153cd8e2c | ||
|
|
95cea8cc5d | ||
|
|
02630d998e | ||
|
|
77d04af845 | ||
|
|
42e01acfa1 | ||
|
|
b2faff6bf9 | ||
|
|
a58236d69d | ||
|
|
3bc2758d51 | ||
|
|
40f6f7b803 | ||
|
|
b1a7d3e995 | ||
|
|
7fc636c623 | ||
|
|
2c5c4647e3 | ||
|
|
2702ce693b | ||
|
|
71836cacdb | ||
|
|
a501dfd680 | ||
|
|
7e7615c97c | ||
|
|
a4d955357d | ||
|
|
9c0aec1d19 | ||
|
|
28541fe826 | ||
|
|
8466a213e8 | ||
|
|
0cd0ce87f5 | ||
|
|
c7f3fa2b5d | ||
|
|
f601f4ce70 | ||
|
|
56a0300db5 | ||
|
|
d7075296e3 | ||
|
|
a904b1665f | ||
|
|
f4511f6fa4 | ||
|
|
1d81841091 | ||
|
|
d339d5eab5 | ||
|
|
9d13b090d8 | ||
|
|
6f898e611c | ||
|
|
1235a7435e | ||
|
|
2ebf46e241 | ||
|
|
d2af1e905c | ||
|
|
be255ff269 | ||
|
|
0211e7749e | ||
|
|
d24f808d79 | ||
|
|
6d42481c37 | ||
|
|
80753ac741 | ||
|
|
93e467913e | ||
|
|
fc283123bb | ||
|
|
5998c561ee | ||
|
|
4e8a71d034 | ||
|
|
d458729f6c | ||
|
|
3191fec54c | ||
|
|
7a5559aba0 | ||
|
|
29d5963cad | ||
|
|
90529c62b2 | ||
|
|
ae21979b7c | ||
|
|
09c3ef0f6a | ||
|
|
ba791b7de8 | ||
|
|
0ddfbd976c | ||
|
|
d4ba7579d1 | ||
|
|
220bc434be | ||
|
|
2932a835fc | ||
|
|
e88fad00a5 | ||
|
|
36d274d460 | ||
|
|
4c4d5e5837 | ||
|
|
769fb7cd02 | ||
|
|
0cc5b29558 | ||
|
|
191171802b | ||
|
|
32b626704e | ||
|
|
b193fd0ba9 | ||
|
|
c5e5cf28af | ||
|
|
8ff0430370 | ||
|
|
7317b6b98e | ||
|
|
799fcdb5e0 | ||
|
|
6b021f8d14 | ||
|
|
a56fcfb24a | ||
|
|
1811bd6885 | ||
|
|
46a37b9bd9 | ||
|
|
3fcd645a73 | ||
|
|
7cbee3dc8f | ||
|
|
9812f368e7 | ||
|
|
0f4dbcfc53 | ||
|
|
fb79927c05 | ||
|
|
fc05c0805b | ||
|
|
b69e023736 | ||
|
|
54c45bd54e | ||
|
|
67c06d17bb | ||
|
|
b91a1f4788 | ||
|
|
9f902c8bd4 | ||
|
|
52454591aa | ||
|
|
cfe9d60f51 | ||
|
|
36bf1ad112 | ||
|
|
6f29c1ff94 | ||
|
|
58080d6157 | ||
|
|
45bf867d38 | ||
|
|
eb578557c0 | ||
|
|
299a471af2 | ||
|
|
4ec8b82388 | ||
|
|
5ae5463f52 | ||
|
|
9a994eb777 | ||
|
|
bdfbc86ecb | ||
|
|
b5d983cddf | ||
|
|
65c01b35ec | ||
|
|
a6cffc0e29 | ||
|
|
5658ea7047 | ||
|
|
7f3b9e8a89 | ||
|
|
7fe2ad81a0 | ||
|
|
dcc266df12 | ||
|
|
d07043fe26 | ||
|
|
2f0f724813 | ||
|
|
fc5b557a10 | ||
|
|
116bf8058a | ||
|
|
050f44382b | ||
|
|
1392eebfa0 | ||
|
|
544a17926b | ||
|
|
637cff628f | ||
|
|
3841fecc59 | ||
|
|
f1cf5ceb82 | ||
|
|
40c39de5e3 | ||
|
|
0087be2a53 | ||
|
|
d9cacc0b8c | ||
|
|
370751551f | ||
|
|
ac8e1b88e4 | ||
|
|
aa0a9f18d5 | ||
|
|
05a2623875 | ||
|
|
1f506615d3 | ||
|
|
bc08e325ce | ||
|
|
a8f410ed40 | ||
|
|
f29a4b51cc | ||
|
|
924b5830ba | ||
|
|
ab877c429f | ||
|
|
97e5e6beee | ||
|
|
5530b7022f | ||
|
|
0aa266a6ca | ||
|
|
0b52823f2c | ||
|
|
1273536752 | ||
|
|
59449600ad | ||
|
|
c392a475ee | ||
|
|
d024ff553f | ||
|
|
b5d49b9e79 | ||
|
|
f0fa3c5861 | ||
|
|
966dd62551 | ||
|
|
ca5ce839ce | ||
|
|
760fc6b3f7 | ||
|
|
372f939cc9 | ||
|
|
5df321fcaa | ||
|
|
10c9d485c4 | ||
|
|
8f3e02e49c | ||
|
|
8b197e49bb | ||
|
|
200983f938 | ||
|
|
dd7fe2e7e0 | ||
|
|
1e94070dca | ||
|
|
40ab6f839a | ||
|
|
43cb646870 | ||
|
|
d1d9f96ab3 | ||
|
|
d910f520d9 | ||
|
|
5ca666acee | ||
|
|
338c2eb2f0 | ||
|
|
deccc4d8c6 | ||
|
|
204eaf0e76 | ||
|
|
421dbb19c2 | ||
|
|
808f326209 | ||
|
|
9c5f365b2b | ||
|
|
f7a5833cb0 | ||
|
|
0d549fd42b | ||
|
|
2a2f77f0dc | ||
|
|
42bd709f67 | ||
|
|
2c7226de20 | ||
|
|
d6c243143d | ||
|
|
9ab6b9b308 | ||
|
|
d80833d892 | ||
|
|
b7bc1fc51d | ||
|
|
9f6a5e35de | ||
|
|
f8ec815467 | ||
|
|
fb1258b817 | ||
|
|
5334ddd199 | ||
|
|
e5e8e9b5d8 | ||
|
|
2e6393f082 | ||
|
|
95527fb566 | ||
|
|
03849b3e87 | ||
|
|
3a4c19f82d | ||
|
|
c23e32a047 | ||
|
|
5e432a6586 | ||
|
|
ea9f3f13ca | ||
|
|
412a1885b2 | ||
|
|
886a692f1a | ||
|
|
d5ebf9039c | ||
|
|
789cf29d28 | ||
|
|
7cb5de7df4 | ||
|
|
c68c71f7b2 | ||
|
|
09f1404c45 | ||
|
|
f8a88fcb94 | ||
|
|
29a358ee3a | ||
|
|
29513919ca | ||
|
|
45beb1bcdd | ||
|
|
166333a2cd | ||
|
|
ebc567d03c | ||
|
|
529c0f24da | ||
|
|
4855f371f1 | ||
|
|
76f000e4c8 | ||
|
|
2aea7a375d | ||
|
|
5cf2a7abd1 | ||
|
|
d11c7cbbb1 | ||
|
|
5c6cd1b48a | ||
|
|
cbec423413 | ||
|
|
9910dfbee2 | ||
|
|
e2b084b715 | ||
|
|
5f9197bcc2 | ||
|
|
0b9bc85ddd | ||
|
|
66ad300515 | ||
|
|
4ce66f0764 | ||
|
|
0fc6116082 | ||
|
|
48af4fc704 | ||
|
|
8c08b531d6 | ||
|
|
966e0640af | ||
|
|
0e26077a64 | ||
|
|
b830b33cf1 | ||
|
|
a989cfb987 | ||
|
|
5a0c0a26e3 | ||
|
|
cd016824f8 | ||
|
|
af00dca08b | ||
|
|
115b08e0e1 | ||
|
|
daa6152868 | ||
|
|
a81280939e | ||
|
|
8df97a0c75 | ||
|
|
2fbcc99b24 | ||
|
|
77f48c8c8e | ||
|
|
aaf7e1fb0d | ||
|
|
9577f1a46f | ||
|
|
63e5a8b1b5 | ||
|
|
be8dd0dba1 | ||
|
|
9f17cb7a86 | ||
|
|
70acb573d5 | ||
|
|
45047732a7 | ||
|
|
f7d0908ff1 | ||
|
|
9f90833d2b | ||
|
|
93174dcd19 | ||
|
|
72f08bb1b4 | ||
|
|
371d0b7395 | ||
|
|
21b2ec6bd5 | ||
|
|
311c5c133c | ||
|
|
551a671cc6 | ||
|
|
f54098618e | ||
|
|
fc69e73dcf | ||
|
|
41855bb6d4 | ||
|
|
e3ee0ac22b | ||
|
|
e65a891274 | ||
|
|
01944dd80e | ||
|
|
ed6dd6d6d1 | ||
|
|
6d13ace83a | ||
|
|
32bdb49496 | ||
|
|
cc8160d044 | ||
|
|
ba7900a3fb | ||
|
|
b9ff6cb1d9 | ||
|
|
0a83817f25 | ||
|
|
f8b4289811 |
No files matched your search
+1
-1
@@ -1,4 +1,4 @@
|
||||
# EditorConfig: http://EditorConfig.org
|
||||
# EditorConfig: https://EditorConfig.org
|
||||
|
||||
# Top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
+4
-2
@@ -9,6 +9,8 @@
|
||||
*.map
|
||||
*.swp
|
||||
*.cache
|
||||
*.gcda
|
||||
*.gcno
|
||||
.tmp
|
||||
.tmp.c
|
||||
.tmp.cxx
|
||||
@@ -92,7 +94,6 @@ database
|
||||
overlays
|
||||
playlists
|
||||
states
|
||||
system
|
||||
shaders/shaders_cg
|
||||
shaders/shaders_glsl
|
||||
shaders/shaders_slang
|
||||
@@ -218,8 +219,9 @@ libretro-common/samples/streams/rzip/rzip
|
||||
|
||||
#VITA
|
||||
param.sfo
|
||||
*.S
|
||||
*.wo
|
||||
*.elf
|
||||
*.self
|
||||
*.vpk
|
||||
/.vs
|
||||
/deps/SPIRV-Cross/out/build/x64-Debug
|
||||
+47
-1
@@ -392,6 +392,7 @@ build-retroarch-dingux-mips32:
|
||||
- export NUMPROC=$(($(nproc)/3))
|
||||
artifacts:
|
||||
paths:
|
||||
- retroarch
|
||||
- retroarch_rg350.opk
|
||||
- ${MEDIA_PATH}
|
||||
expire_in: 10 min
|
||||
@@ -413,6 +414,7 @@ build-retroarch-dingux-odbeta-mips32:
|
||||
- export NUMPROC=$(($(nproc)/3))
|
||||
artifacts:
|
||||
paths:
|
||||
- retroarch
|
||||
- retroarch_rg350_odbeta.opk
|
||||
- ${MEDIA_PATH}
|
||||
expire_in: 10 min
|
||||
@@ -424,6 +426,50 @@ build-retroarch-dingux-odbeta-mips32:
|
||||
- "cp -f libretro-common/audio/dsp_filters/*.dsp ${MEDIA_PATH}/${CI_PROJECT_NAME}/filters/audio"
|
||||
- "cp -f gfx/video_filters/*.filt ${MEDIA_PATH}/${CI_PROJECT_NAME}/filters/video"
|
||||
|
||||
build-retroarch-rs90-odbeta-mips32:
|
||||
image: $CI_SERVER_HOST:5050/libretro-infrastructure/libretro-build-dingux:odbeta
|
||||
stage: build
|
||||
variables:
|
||||
MEDIA_PATH: .media
|
||||
STRIP_BIN: 1
|
||||
before_script:
|
||||
- export NUMPROC=$(($(nproc)/3))
|
||||
artifacts:
|
||||
paths:
|
||||
- retroarch
|
||||
- retroarch_rs90_odbeta.opk
|
||||
- ${MEDIA_PATH}
|
||||
expire_in: 10 min
|
||||
dependencies: []
|
||||
script:
|
||||
- "make -j$NUMPROC -f Makefile.rs90"
|
||||
- "mkdir -p ${MEDIA_PATH}/${CI_PROJECT_NAME}/filters/audio"
|
||||
- "mkdir -p ${MEDIA_PATH}/${CI_PROJECT_NAME}/filters/video"
|
||||
- "cp -f libretro-common/audio/dsp_filters/*.dsp ${MEDIA_PATH}/${CI_PROJECT_NAME}/filters/audio"
|
||||
- "cp -f gfx/video_filters/*.filt ${MEDIA_PATH}/${CI_PROJECT_NAME}/filters/video"
|
||||
|
||||
build-retroarch-retrofw-mips32:
|
||||
image: $CI_SERVER_HOST:5050/libretro-infrastructure/libretro-build-dingux:odbeta
|
||||
stage: build
|
||||
variables:
|
||||
MEDIA_PATH: .media
|
||||
STRIP_BIN: 1
|
||||
before_script:
|
||||
- export NUMPROC=$(($(nproc)/3))
|
||||
artifacts:
|
||||
paths:
|
||||
- retroarch
|
||||
- retroarch_retrofw.opk
|
||||
- ${MEDIA_PATH}
|
||||
expire_in: 10 min
|
||||
dependencies: []
|
||||
script:
|
||||
- "make -j$NUMPROC -f Makefile.retrofw"
|
||||
- "mkdir -p ${MEDIA_PATH}/${CI_PROJECT_NAME}/filters/audio"
|
||||
- "mkdir -p ${MEDIA_PATH}/${CI_PROJECT_NAME}/filters/video"
|
||||
- "cp -f libretro-common/audio/dsp_filters/*.dsp ${MEDIA_PATH}/${CI_PROJECT_NAME}/filters/audio"
|
||||
- "cp -f gfx/video_filters/*.filt ${MEDIA_PATH}/${CI_PROJECT_NAME}/filters/video"
|
||||
|
||||
build-retroarch-android-normal:
|
||||
image: $CI_SERVER_HOST:5050/libretro-infrastructure/libretro-build-android:latest
|
||||
stage: build
|
||||
@@ -737,7 +783,7 @@ build-static-retroarch-wiiu:
|
||||
- "mv .retroarch-precompiled/ retroarch-precompiled/"
|
||||
|
||||
build-static-retroarch-dummy-wiiu:
|
||||
image: $CI_SERVER_HOST:5050/libretro-infrastructure/libretro-build-devkitpro:latest
|
||||
image: $CI_SERVER_HOST:5050/libretro-infrastructure/libretro-build-wiiu:latest
|
||||
stage: build
|
||||
variables:
|
||||
MEDIA_PATH: .media
|
||||
|
||||
+263
@@ -1,5 +1,268 @@
|
||||
# Future
|
||||
|
||||
# 1.9.8
|
||||
- AUDIO/WINDOWS/WASAPI: Stop deactivating audio on fast forward
|
||||
- CHEEVOS: Hide challenge indicators when resetting
|
||||
- CHEEVOS: Support for more than 64 memory regions
|
||||
- CHEEVOS: Automatically retry 'http error code -1'
|
||||
- CONTENT INFORMATION: Show content info label+path rows always
|
||||
- CORE OPTIONS: Core option categories implemented
|
||||
- CORE OPTIONS: Add option to disable core option categories
|
||||
- D3D10/11/12: Fix gfx_display_draw_texture - fixes OSK (On-Screen Keyboard) issues
|
||||
- DATABASE: Fix heap-buffer-overflow when fetching CRC values
|
||||
- DATABASE/EXPLORE: Fix CRC32 reading in explore menu
|
||||
- DATABASE/LIBRETRODB: Fix writing of numerical values
|
||||
- DATABASE/LIBRETRODB: Fix libretro-db loading on big endian platforms
|
||||
- DUMMY CORE: Skip state_manager_event_{deinit/init} when core type is dummy, should skip warning spam 'Implementation uses threaded audio. Cannot use rewind..' when using rewind
|
||||
- INPUT/UDEV: Limit udev device scan to subsystem 'input'
|
||||
- INPUT/SDL2/WINDOWS: Fix keyboard event keycodes
|
||||
- INPUT/WAYLAND: Fixes a bug where the first player's mouse, pointer, and lightgun are echoed to the other ports. Now, those other ports correctly report zero. In the future support for multiple mouselike devices will need to be added, which is a bigger project
|
||||
- INPUT/WAYLAND: The driver now respects keyboard_mapping_blocked
|
||||
- INPUT/WAYLAND: When possible, deprecated lightgun defines are replaced with the new ones. The coordinates are still using the old relative callbacks
|
||||
- INPUT/WINRAW: Trigger joypad driver reinit on DEVICECHANGE - avoids fullscreen toggle
|
||||
- INPUT/WINRAW: Alt sticky fix
|
||||
- INPUT/WINRAW: Prevent Alt getting stuck when Alt-Tabbing
|
||||
- INPUT/WINRAW: Add pointer status
|
||||
- INPUT/WINRAW: Add missing analog keybinds
|
||||
- LIBNX/SWITCH: Fix poll missing for controller 2-8
|
||||
- LIBNX/SWITCH: Fix layout not applied correctly and hangs when splitting joycons
|
||||
- LIBRETRO: Core options category API implemented
|
||||
- LIBRETRO: Fix RETRO_ENVIRONMENT_SET_FASTFORWARDING_OVERRIDE callback when runahead is enabled
|
||||
- LIBRETRO: Add environment callback for enabling core option menu visibility updates without toggling Quick Menu
|
||||
- LOGGING: Starting logging and verbose mode before first config load
|
||||
- LINUX: In some Linux Desktop Environments, like Budgie, task bar feature is unable to pin applications. With StartupWMClass= present in .desktop file, it is possible to pin the application
|
||||
- LOCALIZATION: Fetch translations from Crowdin
|
||||
- MENU: Relocate 'Manage Playlists' to top
|
||||
- MENU: Fullscreen resolution width/height settings no longer require 'advanced settings'
|
||||
- MENU/REFRESH RATE: Fix double notifications with refresh rate settings
|
||||
- MENU/OZONE: Ensure the existence of values used in selection calculation
|
||||
- MENU/OZONE/VULKAN: Casting to unsigned caused an integer overflow and after float promotion would lead to 'x' being a garbage value, leading to problems when this value was passed to vkCmdSetViewport. This stops Vulkan validation layers from complaining about it
|
||||
- METAL: Fixed font driver memory leaks
|
||||
- MOUSE: Change default mouse index to port index
|
||||
- MOUSE: Friendly names for mice where available
|
||||
- OSX: Fix some memory leaks
|
||||
- OSX: Fix controller duplication bug
|
||||
- PS2: Implement alpha for the video driver
|
||||
- PS2: Aspect ratio handling
|
||||
- RETROFW: Initial port
|
||||
- UWP/XBOX: Enable Explore tab by default - seems to work fine
|
||||
- UWP/XBOX: Fix startup issues with latest Xbox Dashboard updates - ANGLE cores still show up wrong
|
||||
- UWP/XBOX: fix issue where files where opened as OPENALWAYS instead of OPENEXISTING this fixes beetle cores
|
||||
- UWP/XBOX: fix issue where filesizes where not returned properly, this fixes loading arcade dat files
|
||||
- UWP/TRANSLATION: Enabled translation services for both UWP MSVC2017 and 2019. No TTS speech yet.
|
||||
- VIDEO: Fix refresh rate 59Hz rounding
|
||||
- WINDOWS: Remember original refresh rate
|
||||
- WINDOWS/VULKAN: Refresh rate fixes + cleanups
|
||||
- WIIU: Fix L3/R3 buttons
|
||||
- WIIU: Compress RPX libretro cores
|
||||
- WIIU: Add ICInvalidateRange (necessary for JITs)
|
||||
- WIIU: Slight filesystem optimisation
|
||||
- WIIU: Add option for running without core info (emscripten-style)
|
||||
|
||||
# 1.9.7
|
||||
- 3DS: Add unique ID's
|
||||
- CRT/SWITCHRES: Fixed some Monitor index bugs ad updated to the latest SR2
|
||||
- CRT/SWITCHRES: Fixed monitor index corruption on Windows and added correct fractal scaling. Only used when required
|
||||
- CRT/SWITCHRES: Updated log defines to match SR upstream.
|
||||
- CRT/SWITCHRES: Added new SR_CONFIG_PATHS for non Windows and Linux systems.
|
||||
Not that SR works on them but to fix RA compile issues
|
||||
- CRT/SWITCHRES: Updated SR2 code base to latest. Added supprt for windows monitor indexing. Fixed monitor index bug where index 1 was not being used correctly and "auto" was not being sent.
|
||||
- CRT/SWITCHRES: Updated swithres for x86 windows fix
|
||||
- CRT/SWITCHRES: fixed SR2 auto issue
|
||||
- CRT/SWITCHRES: Fixed auto monitor bug
|
||||
- CRT/SWITCHRES: Fixed monitor index corruption on Windows
|
||||
- CRT/SWITCHRES: Fixed buffer size bug
|
||||
- CRT/SWITCHRES: Added correct fractal scalling. only used when required.
|
||||
- CORE INFO: Automatically disable core info cache when core info directory is read-only
|
||||
- EMSCRIPTEN: add MAME2003 / MAME2003-plus to web.libretro
|
||||
- INPUT/UDEV: udev fixes add pointer pressed to pointer device to allow udev users to access this device
|
||||
- LIBNX/SWITCH: Enable 7zip support
|
||||
- LINUX/XDG: Prevent xdg-screensaver's "Protocol error" messages
|
||||
- LOCALIZATION: Fetch translations from Crowdin
|
||||
- LOCALIZATION: Add missing languages for the first startup
|
||||
- MENU/XMB/WIDGETS: Add workaround for FPU bug that breaks scale factor comparisons on certain platforms (fixes XMB thumbnails on 32bit Linux/Windows)
|
||||
- MENU/RGUI: Enable fullscreen thumbnail toggle using RetroPad 'start' button
|
||||
- MENU/RGUI: Fix sublabel length when menu clock is disabled
|
||||
- NETWORK/HTTP: Fix HTTP progress indication for large files on 32-bit systems
|
||||
- NETWORK/NATT: implement natt fix from void()
|
||||
- OPENDINGUX: Fix display when cores 'drop' frames
|
||||
- OPENDINGUX BETA: Use ALSA audio driver by default
|
||||
- OPENDINGUX BETA: Fix IPU scaling when running 256x224 (SNES/Genesis) content
|
||||
- PATHS: Fix garbled path string
|
||||
- PS2: Implement proper ps2_font driver instead of using the font driver from gskit
|
||||
- PS2: Use BDM for increasing up USB stability
|
||||
- PS3: First basic RSX driver for PSL1GHT
|
||||
- RS90: Initial port
|
||||
- RS90: Fix offset of OSD text
|
||||
- RS90: Disable menu clock by default
|
||||
- RS90: Hide 'Bilinear Filtering' video option
|
||||
- RS90: Move appdata (retroarch) base directory to external microsd card
|
||||
- RS90: Add optional approximate 'semi-linear' scaling filter
|
||||
- SHADERS: Max Shader Parameters increased to 1024
|
||||
- VIDEO: Add 'Integer Scale Overlay' - Force integer scaling to round up to the next larger integer instead of rounding down
|
||||
- VIDEO: New 'Full' aspect ratio added. This aspect ratio is useful when used with a shader which has a border in it. The aspect ratio is set to the full window area, so that the viewport spans the whole viewport. When using a border type shader like the Mega Bezel this allows the graphics to span the whole window regardless of the user's monitor aspect ratio
|
||||
- VITA: Wrong flags for not piglet version
|
||||
- UNIX: Correct backlight max_brightness path
|
||||
- UWP/XBOX: Default to Direct3D11 driver on UWP builds
|
||||
- UWP/XBOX: Do not use windowed mode on UWP/Xbox by default, set default resolution to 1920x1080 by default. Should fix display issues with Dolphin/PCSX2 on Xbox
|
||||
- WIIU: Fix inputs breaking when connecting/disconnecting remotes
|
||||
- WIIU: Input - ignore some bogus KPAD results
|
||||
- WIIU: Font rendering fixes - render font lines with correct spacing, and only sample alpha channel when rendering fonts
|
||||
- WIIU/NETWORK: Network speed optimisations - WINSCALE, TCP sACK, large buffers
|
||||
- WIIU/LIBFAT: Increase cache size on WiiU
|
||||
- WIIU/FILE IO: Filesystem optimisations - add fast path for already aligned buffers
|
||||
- WIIU/FILE IO: Use 128K vbufs for WiiU - we have loads of RAM and large vbufs are very beneficial
|
||||
- WIIU/MENU/OZONE: Fix Ozone rendering error (scissor fix)
|
||||
- WIIU/MENU/OZONE: Use Ozone icons instead of XMB Monochrome
|
||||
|
||||
# 1.9.6
|
||||
- ARCHIVE: Fix archive delimiter detection when file path contains no slashes
|
||||
- ANDROID: Do not duplicate port 0 mouse and gun inputs to other ports
|
||||
- AUDIO/XAUDIO2: Fail instead of crashing when disconnecting an audio device
|
||||
- CHEEVOS: Reset cached progress each time menu is opened
|
||||
- CRT/SWITCHRES: Add support for switchres.ini core and directory overrides
|
||||
- D3D11: Don't use allow tearing flag with blit swap chains. Also disables the flip model if the allow tearing flag is not supported.
|
||||
- D3D11: Disable DXGI's ALT+ENTER handling
|
||||
- D3D11: Don't pass ALLOW_TEARING when unsupported
|
||||
- D3D11: Fix non-vsynced output without flip, black screens in fullscreen
|
||||
- D3D12: Relocated 'd3d12_gfx_sync'
|
||||
- D3D12: Fixed swap interval option
|
||||
- GFX: Fix uninitialized variables in gfx_display_draw_cursor
|
||||
- HISTORY: Hide 'Add to Favorites' when viewing an entry of the favorites playlist
|
||||
- INPUT: 'Analog to Digital Type' usability improvements
|
||||
- INPUT: Add support for mapping multiple controllers to a single input device
|
||||
- INPUT/REMAPPING: Add support for mapping multiple controllers to a single input device
|
||||
- INPUT/LIGHTGUN: Bind lightgun trigger to first mouse button by default
|
||||
- INPUT/WINDOWS/RAWINPUT: Mouse access violation fix
|
||||
- INPUT/UDEV: Only add mouse if it has buttons and add vebose device friendly names
|
||||
- INPUT/UDEV: Skip mouse with no button errors and keep the rest
|
||||
- INPUT/UDEV: Fix Game Focus mode
|
||||
- INPUT/UDEV/X11: Change udev driver for dual lightgun support in X11
|
||||
- LIBNX/SWITCH: Update to libnx 4.0.0
|
||||
- LOCALIZATION: Fetch translations from Crowdin
|
||||
- LOCALIZATION: Fix Switchres menu texts
|
||||
- MENU/OZONE: Ensure sidebar display status is updated correctly when performing rapid menu navigation
|
||||
- MENU/XMB: Dynamic wallpaper fix
|
||||
- MENU/XMB: Icon opacity fix
|
||||
- MENU/QT/WIMP: Fix default core detection when playlist file name does not match 'db_name'
|
||||
- PLAYLISTS: Optimise scanning of large rom sets
|
||||
- SECURITY: Plug so-called high-risk vulnerability related to Powershell - avoid injection - don't send speech input as commandline argument
|
||||
- UWP/XBOX: Add expanded resources Rescap to increase performance of UWP version in app mode on Xbox
|
||||
- WINDOWS/INSTALLER: Add smarter isEmptyDir reference implementation that looks for subdirectories from NSIS documentation
|
||||
- WINDOWS/INSTALLER: Register new function DirectorySet that is called when pressing the "Next" button on the MUI_PAGE_DIRECTORY, aka the install folder selection GUI. DirectorySet contains the criteria for an acceptable folder, which are:
|
||||
- `IfFileExists "$INSTDIR\retroarch.exe"` returns 1
|
||||
- `IfFileExists "$INSTDIR\*.*` returns 0, there is no existing folder
|
||||
- `IfFileExists "$INSTDIR\*.*"` returns 1, there is a folder, and `isEmptyDir` returns 1, therefore the folder is empty, including of subdirectories
|
||||
- X11: Fix threaded video segfault
|
||||
|
||||
# 1.9.5
|
||||
- ALSATHREAD: Make alsathread default for all ALSA devices with threads
|
||||
- ARCHIVE: Fix loading of archived content with file names containing '#' characters
|
||||
- CHEEVOS: Upgrade to rcheevos 10.1
|
||||
- CHEEVOS: Challenge indicators
|
||||
- CHEEVOS: Group achievements by category in quick menu
|
||||
- CHEEVOS: Relabel 'Start Active' with 'Encore Mode'
|
||||
- D3D10: Window title should now update
|
||||
- D3D11: Window title should now update
|
||||
- D3D11: Allow fastforward in fullscreen
|
||||
- D3D12: Window title should now update
|
||||
- D3D12: Allow fastforward in fullscreen
|
||||
- CRT/SWITCHRES: New implementation
|
||||
- FONTS: Improve message wrapping with CJK languages
|
||||
- FONTS: Fix garbled characters when converting encodings
|
||||
- INPUT: Allow the 8 analog stick directions to be used as keys for core keyboard mappings
|
||||
- LIBRETRO: Add API extension for setting 'need_fullpath' based on content file extension and to request persistent frontend content data buffers
|
||||
- MENU/SEARCH: Add enhanced search functionality to the 'Manage Cores' menu
|
||||
- OPENDINGUX: Fix black screens when triggering gfx driver initialisation via menu actions
|
||||
- UNIX: Get better battery stats on sysfs nodes
|
||||
- VIDEO: Extend Frame Delay range to 19 to accommodate PAL land too
|
||||
- WIFI/LAKKA: Add nmcli to wifi drivers
|
||||
- WIFI/LAKKA: Add wifi configuration menu
|
||||
- X11: fix fullscreen when swapping monitors/resolution
|
||||
|
||||
# 1.9.4
|
||||
- CHEEVOS: update rcheevos to v10.0.0
|
||||
- CONTENT LOADING/FILE IO: Prevent unnecessary extraction (to disk) of compressed content files when need_fullpath is false
|
||||
- CORE INFO/FILE IO: Enable core info cache by default now for all platforms
|
||||
- CORE INFO/REGRESSION FIX: Fix regression caused by core info file caching - Downloads was no longer showing up in Load Content
|
||||
- FILE IO/COMPRESSED: Ability to load content inside ZIP files directly into RAM
|
||||
- INPUT/OVERLAYS: Add option to select between 'touched' elements and physical controller inputs when showing inputs on overlays
|
||||
- INPUT REMAPPING/OVERLAYS: Prevent duplicate inputs when using remaps with input overlays
|
||||
- LAKKA: Add brightness restore hook
|
||||
- LOCALIZATION: Fetch translations from Crowdin
|
||||
- MENU/OZONE: Added simple playlist entry enumeration
|
||||
- MENU/XMB: Fix display of 'Maximum Users' menu entry dropdown list
|
||||
- PS3/PSL1GHT: Joypad driver works again
|
||||
- PSTV: Fix Vita input driver for PSTV
|
||||
- PSTV: Support for 720p on PSTV when using 'Unlock framebuffer' in Sharpscale plugin
|
||||
- PSTV: Fix scaling on PSTV when not using 720p
|
||||
- RPNG: Fix some memory corruption if processing broken input PNG file
|
||||
- SECURITY: Fix CVE-2021-28927
|
||||
|
||||
# 1.9.3
|
||||
- 3DS: Disable menu screensaver animations in XMB/GLUI
|
||||
- COMMAND: Initialize netcmd->cmd_source_len before recvfrom()
|
||||
- CONTENT LOADING/STATICALLY LINKED: Ensure 'Always Reload Core on Run Content' setting is applied when loading content via the file browser
|
||||
- CONTENT LOADING/EMSCRIPTEN: Fix content loading via file browser on platforms with 'broken' core handling (i.e. emscripten)
|
||||
- CORE INFO: Skip whitespace when writing compressed core info cache files
|
||||
- CORE INFO/FILE IO: Core Info cache; significant file I/O performance improvements on systems with slow disk file I/O
|
||||
- CORE INFO/FILE IO: Enable core info cache by default on all 'console' platforms
|
||||
- FREEBSD: FreeBSD build fix
|
||||
- LAKKA: Support for tweaking CPU governors/scaling policies
|
||||
- LAKKA: This adds managed policies and settings to store them and reload them at startup
|
||||
- LIBRETRO API: Add API extension for cores to override frontend fast-forward state
|
||||
- MENU/RGUI: Fix saving of config files/overrides when 'Lock Menu Aspect Ratio' is enabled
|
||||
- SHADERS: Fix 'Auto-Shader Delay' functionality
|
||||
- UWP/D3D11: Disable mipmap generation
|
||||
- UWP/XBOX: Add 'Force 4K resolution' option (Force the resolution to the fullscreen size on Xbox, if set to 0, a fixed value of 3840 x 2160 will be used)
|
||||
|
||||
# 1.9.2
|
||||
- 3DS: Enable graphics widgets / overlays
|
||||
- 3DS: Load texture images as BGR colors
|
||||
- 3DS: Change default asset directory
|
||||
- CHEEVOS: Allow rcheevos_patch_address to be called on game without achievements
|
||||
- CHEEVOS: Update achievement memory maps (add Supervision)
|
||||
- CONFIG/FILE: Use hash map to optimise key/value lookups
|
||||
- CORE INFO: Performance optimisations + code clean-ups/refactors
|
||||
- CRT/SWITCHRES: Fixed CRTSwitchRes framebuffer bug
|
||||
- DISCORD/RP: Fix regression
|
||||
- DRM: set the correct video mode
|
||||
- FASTFORWARD: Enforce minimum fastforward_ratio of 1.0
|
||||
- FONTS/FREETYPE/STB_UNICODE/BITMAPFONT: Prevent texture bleed when rendering text at non-integer scales
|
||||
- INPUT: Ensure that 'retro_set_controller_port_device' is called when updating 'Max Users'
|
||||
- INPUT/XEGL/MOUSE: Fix xegl_ctx.c mouse activation
|
||||
- INPUT/SDL: Fix crash in SDL input driver when analogs are bound.
|
||||
- INPUT/POINTER: Add scaling to pointer input.
|
||||
- INPUT REMAPPING: Fix regression on loading file
|
||||
- INPUT REMAPPING: Fix regression where disabling input remapping would disable input
|
||||
- IOS: Disable system button gestures on iOS 14
|
||||
- IOS: Prevent potential crash on controller connect - randomly would get a crash when connecting a game controller while RA was running
|
||||
- LAKKA: Add menu for time zone setting
|
||||
- LOGGING: RARCH_LOG_V checking for verbosity level is not necessary and can cause issues; removed said check.
|
||||
- LOGGING: Silence inappropriate cheatfile logging
|
||||
- IOS/MAC: Add CPU VFP unit detection for Darwin
|
||||
- MAC: Swallow 'escape' key being pressed - would previously make the game toggle between fullscreen and windowed
|
||||
- MAC: Intel and ARM64 timer change proposal.
|
||||
- MAC/ARM64: run_fast_mode disabled for 64 bits invalid instructions.
|
||||
- MAC/OPENGL: Fix codesigning issue
|
||||
- MAC/UNIVERSAL: Add TTS translation service support.
|
||||
- MENU: Add optional menu screensaver
|
||||
- MENU: Add search filter support to cheats and overlays file browser menus
|
||||
- MENU/FILEBROWSER: Enhanced 'Load Content' file browser search functionality
|
||||
- MENU/INPUT: Block accidental diagonals in menu navigation
|
||||
- MENU/RGUI: Add option to disable menu transparency
|
||||
- MENU/RGUI: Fix display of 'Video > Scaling' menu when 'Lock Menu Aspect Ratio' is enabled
|
||||
- MENU/MATERIALUI: Add icon to 'Turbo Fire' menu entry
|
||||
- MENU/OZONE: Ozone Dracula theme
|
||||
- OPENDINGUX/BETA: Fix IPU scaling when running GBA-resolution content
|
||||
- OPENDINGUX/BETA: Add 50Hz support
|
||||
- OPENDINGUX: Enable 'SaveRAM Autosave Interval' by default
|
||||
- PATCHES: Added multi-softpatching support + OSD messages for patches
|
||||
- RHMAP: Track the complete string in rhmap
|
||||
- VITA: Align VM block size to 1MB - should fix one of the issues with gpSP
|
||||
- WINDOWS/GDI: Fix non-ASCII text rendering
|
||||
- XEGL: Fix mouse not working when using OpenGLES with X11
|
||||
|
||||
# 1.9.1
|
||||
- 3DS: Graphics widgets support
|
||||
- 3DS: On error, only init gfx on salamander build. This prevents graphical issues if the gfx is already initialized.
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, caste, color, religion, or sexual identity
|
||||
and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at:
|
||||
|
||||
* Via E-Mail to <libretro@gmail.com>, please include in the subject line
|
||||
`RETROARCH COC` so that your e-mail may reach the correct party.
|
||||
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series
|
||||
of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or
|
||||
permanent ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
the community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.1, available at
|
||||
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
||||
|
||||
Community Impact Guidelines were inspired by
|
||||
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available
|
||||
at [https://www.contributor-covenant.org/translations][translations].
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
||||
[Mozilla CoC]: https://github.com/mozilla/diversity
|
||||
[FAQ]: https://www.contributor-covenant.org/faq
|
||||
[translations]: https://www.contributor-covenant.org/translations
|
||||
+79
-44
@@ -1,58 +1,93 @@
|
||||
# Contributing to RetroArch
|
||||
|
||||
If you are a developer and want to contribute to the development of RetroArch, please read this.
|
||||
If you have found a bug and want to submit a minor patch or a bug report, please read this as well.
|
||||
If you are a developer who wishes to contribute to the development of _RetroArch_; or if you have
|
||||
found a bug and wish to submit a minor patch and/or bug report, please read this document.
|
||||
|
||||
# Submitting a bug report
|
||||
When submitting a bug report, make sure that the bug is local to RetroArch.
|
||||
A bug in a libretro core or something deemed to be external is likely to be closed very fast.
|
||||
If you still suspect a bug in RetroArch, make sure to test with several cores to make sure.
|
||||
Active discussions happen on our [Discord](https://discordapp.com/invite/27Xxm2h), mostly within
|
||||
the _Programming_ channel category. We value discussions that happen in real time around
|
||||
these contributions.
|
||||
|
||||
If you have troubles building RetroArch on Linux/BSD/OSX, make sure to paste shell output of ./configure,
|
||||
as well as config.log and shell output of make. If building on Windows, just paste shell output of make.
|
||||
Please do note that contributors to _RetroArch_ do such contributions within their spare time.
|
||||
We do prefer to keep a professional and non-aggressive atmosphere around the project, along
|
||||
with any disagreements to be settled professionally without insults, name calling, or otherwise.
|
||||
If there are any issues, we are willing to have discussions about it.
|
||||
|
||||
If the issue occurs during runtime, make sure to paste RetroArch's verbose log.
|
||||
If using Phoenix frontend, you can find log in (File -> Show Log) after running.
|
||||
In console, make sure to run with verbose (-v) flag.
|
||||
## Submitting Bug Reports
|
||||
|
||||
# Pull Requests
|
||||
Outside contributions are generally only accepted in the form of a pull request. The process is very simple.
|
||||
Fork RetroArch, make your changes, and issue a pull request on GitHub. This can all be done within the browser.
|
||||
The changes are reviewed, and might be merged in. If the pull request isn't acceptable at the time,
|
||||
note that it's possible to continue pushing up commits to your branch.
|
||||
Bug reports in _RetroArch_ may fall into one of two categories:
|
||||
|
||||
If you want to develop a larger feature,
|
||||
we'd like to discuss this first (ideally on IRC) so that you don't risk developing something
|
||||
that won't be merged. A pull request with a proof-of-concept is fine, but please indicate so.
|
||||
* _RetroArch_ itself, the user interface and API around all of the various cores.
|
||||
* Individual _Core_, of which interact with _RetroArch_.
|
||||
|
||||
When submitting a bug report, ensure that the report is submitted to the correct repository.
|
||||
For _RetroArch_ itself, it is done by reporting a bug within the
|
||||
[RetroArch](https://github.com/libretro/RetroArch) repository. For other cores, please use
|
||||
the search function within the [libretro Organization](https://github.com/libretro) on
|
||||
GitHub. Issues that are specific to a core and not _RetroArch_ are likely to be closed very
|
||||
quickly. If an issue is suspected with _RetroArch_, please make sure to test with multiple
|
||||
cores to be sure that is is not isolated.
|
||||
|
||||
If the issue occurs during runtime, please paste the verbose log output:
|
||||
|
||||
* If using the _Pheonix_ interface, the log will be in _File_ -> _Show Log_.
|
||||
* If using the main interface, enable verbose logging with _Settings_ -> _Logging_ ->
|
||||
_Logging Verbosity_. Ensure both _Log to File_ and _Timestamp log Files_ is enabled.
|
||||
* Otherwise, run _RetroArch_ with the verbose (`-v`) flag.
|
||||
|
||||
If the error happens during compilation and/or building, paste the output of `./configure`
|
||||
and `make` accordingly. If using an IDE, please paste any of the errors and log output.
|
||||
|
||||
## Submitting Pull Requests
|
||||
|
||||
Any and all contributions should be submitted through Pull Requests on
|
||||
[GitHub](https://github.com/libretro/RetroArch/pulls). The process requires that you fork the
|
||||
repository, make the appropriate changes, and then open a pull request on _GitHub_. If your
|
||||
pull request is for a proof-of-concept then please indicate as such.
|
||||
|
||||
Your pull request will then be reviewed. There may be comments and requests for additional
|
||||
changes to be made. It may also be possible that the changes will not be accepted. Otherwise, it
|
||||
may be merged in when it is fully approved. The final approval of merge requests is at the
|
||||
discretion of the project.
|
||||
|
||||
If you want to develop a larger feature or make broad changes, please do join our
|
||||
[Discord](https://discordapp.com/invite/27Xxm2h) server to discuss. The discussion is
|
||||
necessary to prevent the possibility of major work being done which will not be accepted at all.
|
||||
|
||||
## libretro API
|
||||
If you wish to add functionality to libretro's API, it can take some time to merge in, because changes
|
||||
to libretro API will affect other projects as well, and we highly value API/ABI stability.
|
||||
Features will only be added when deemed *necessary* for a concrete libretro core to function properly.
|
||||
Features will not be added on basis of hypothetical libretro implementations.
|
||||
|
||||
# Coding style
|
||||
Having a consistent code style throughout the code base is highly valued.
|
||||
Please look through the code to get a feel for the coding style.
|
||||
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".
|
||||
If you wish to contribute additional functionality to _libretro_'s API, there are considerations
|
||||
that must be accepted. Please note that because this API affects multiple different projects, we
|
||||
highly value and require API and ABI stability and backwards-compatibility. Due to this
|
||||
requirement, there will be additional scrutiny in reviews for this added functionality.
|
||||
|
||||
## Non-obvious things:
|
||||
- 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.
|
||||
Any and all features will be added only when **necessary** for an existing _libretro_ core to
|
||||
properly function. Hypothetical implementations of _libretro_ are not considered.
|
||||
|
||||
# Copyright Headers and AUTHORS
|
||||
If you have contributed to a part of a source file (a chunk of code that's written by you),
|
||||
you should add yourself to the copyright header in that file.
|
||||
If you have contributed significantly
|
||||
(a feature, a contribution you can "name", e.g. "Added audio driver foo"), you should add yourself to AUTHORS file.
|
||||
We'd like your full name and email, and which features you have been part of.
|
||||
## Coding style
|
||||
|
||||
# IRC
|
||||
Active development happens on IRC. (#retroarch @ irc.freenode.org)
|
||||
We value discussing things in "real-time".
|
||||
We highly value a consistent code style throughout the entire code base, please make sure you look
|
||||
through the existing code to get a feel for the coding style. When submitting a pull request, it may
|
||||
be asked to fix any coding style issues before submission. In other cases, there may be a follow-up
|
||||
pull request making the code style consistent.
|
||||
|
||||
# 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.
|
||||
For full guidelines please see the [Coding Standards](https://docs.libretro.com/development/coding-standards/).
|
||||
|
||||
Some non-obvious things to be aware of:
|
||||
|
||||
- Code should be both C89 and ISO C++ compatible. This is a requirement for XBox 360 and MSVC to
|
||||
properly build. Think of it as a C++ compatible subset of C99.
|
||||
- There must be no warnings in your code (enabled by `-Wall` for GCC compilers), do also note that
|
||||
different compilers may produce different warnings.
|
||||
- Avoid using deprecated APIs, these will be removed in the future at some point.
|
||||
|
||||
## Copyright Headers and AUTHORS
|
||||
|
||||
If you have contributed a chunk of source code that is written to you, you should add yourself to
|
||||
the copyright header in the file. If you have made a significant contribution you should add
|
||||
yourself to the `AUTHORS` file, adding your full name, e-mail, and the feature you worked on.
|
||||
|
||||
## Commit Access
|
||||
|
||||
Contributors who show a good track record of pull requests over time may eventually
|
||||
get commit access to the repository. This may happen when looking through pull requests
|
||||
over long amounts of time becomes a burden.
|
||||
@@ -22,7 +22,7 @@ endif
|
||||
|
||||
OBJ :=
|
||||
LIBS :=
|
||||
DEF_FLAGS :=
|
||||
DEF_FLAGS := -I.
|
||||
ASFLAGS :=
|
||||
DEFINES := -DHAVE_CONFIG_H -DRARCH_INTERNAL -D_FILE_OFFSET_BITS=64
|
||||
DEFINES += -DGLOBAL_CONFIG_DIR='"$(GLOBAL_CONFIG_DIR)"'
|
||||
@@ -118,7 +118,7 @@ ifneq ($(CXX_BUILD), 1)
|
||||
CFLAGS += -D_GNU_SOURCE
|
||||
endif
|
||||
|
||||
DEF_FLAGS += $(INCLUDE_DIRS) -I. -Ideps -Ideps/stb
|
||||
DEF_FLAGS += $(INCLUDE_DIRS) -Ideps -Ideps/stb
|
||||
|
||||
CFLAGS += $(DEF_FLAGS)
|
||||
CXXFLAGS += $(DEF_FLAGS) -D__STDC_CONSTANT_MACROS
|
||||
|
||||
+103
-43
@@ -134,7 +134,7 @@ ifneq ($(findstring Darwin,$(OS)),)
|
||||
MINVERFLAGS=
|
||||
ifeq ($(shell uname -p),arm)
|
||||
MINVERFLAGS = -mmacosx-version-min=10.15 -stdlib=libc++ # macOS (Metal, ARM 64bit)
|
||||
MINVERFLAGS += -DDONT_WANT_ARM_OPTIMIZATIONS
|
||||
MINVERFLAGS += -DDONT_WANT_ARM_ASM_OPTIMIZATIONS
|
||||
else ifeq ($(HAVE_METAL),1)
|
||||
MINVERFLAGS = -mmacosx-version-min=10.13 -stdlib=libc++ # macOS (Metal, x86 64bit)
|
||||
else ifeq ($(shell uname -p),powerpc)
|
||||
@@ -148,7 +148,7 @@ ifneq ($(findstring Darwin,$(OS)),)
|
||||
# Build for a specific architecture when ARCH is defined as a switch
|
||||
ifeq ($(ARCH),arm64)
|
||||
MINVERFLAGS = -mmacosx-version-min=10.15 -stdlib=libc++ # macOS (Metal, ARM 64bit)
|
||||
MINVERFLAGS += -DDONT_WANT_ARM_OPTIMIZATIONS
|
||||
MINVERFLAGS += -DDONT_WANT_ARM_ASM_OPTIMIZATIONS
|
||||
ARCHFLAGS = -arch arm64
|
||||
else ifeq ($(ARCH),x86_64)
|
||||
ifeq ($(HAVE_METAL),1)
|
||||
@@ -195,8 +195,8 @@ endif
|
||||
ifeq ($(TARGET), retroarch_3ds)
|
||||
OBJ += frontend/drivers/platform_ctr.o
|
||||
endif
|
||||
|
||||
# Git Version
|
||||
ifeq ($(HAVE_GIT_VERSION), 1)
|
||||
GIT_VERSION_CACHEDIR = $(if $(OBJDIR),$(OBJDIR),$(CURDIR))
|
||||
GIT_VERSION_CACHEFILE = $(GIT_VERSION_CACHEDIR)/git-version.cache
|
||||
|
||||
@@ -224,7 +224,6 @@ ifneq ($(GIT_VERSION),) # Enable version_git.o?
|
||||
DEFINES += -DHAVE_GIT_VERSION -DGIT_VERSION=$(GIT_VERSION)
|
||||
OBJ += version_git.o
|
||||
endif
|
||||
endif
|
||||
|
||||
# General object files
|
||||
ifeq ($(HAVE_DR_MP3), 1)
|
||||
@@ -233,6 +232,7 @@ endif
|
||||
|
||||
OBJ += frontend/frontend_driver.o \
|
||||
retroarch.o \
|
||||
command.o \
|
||||
msg_hash.o \
|
||||
intl/msg_hash_us.o \
|
||||
$(LIBRETRO_COMM_DIR)/queues/task_queue.o \
|
||||
@@ -275,6 +275,11 @@ OBJ += \
|
||||
$(LIBRETRO_COMM_DIR)/memmap/memalign.o \
|
||||
$(LIBRETRO_COMM_DIR)/file/nbio/nbio_stdio.o
|
||||
|
||||
OBJ += \
|
||||
$(LIBRETRO_COMM_DIR)/lists/linked_list.o \
|
||||
$(LIBRETRO_COMM_DIR)/lists/nested_list.o \
|
||||
$(LIBRETRO_COMM_DIR)/queues/generic_queue.o
|
||||
|
||||
ifneq ($(findstring Linux,$(OS)),)
|
||||
OBJ += $(LIBRETRO_COMM_DIR)/file/nbio/nbio_linux.o
|
||||
endif
|
||||
@@ -297,10 +302,10 @@ OBJ += \
|
||||
$(LIBRETRO_COMM_DIR)/file/file_path_io.o \
|
||||
file_path_special.o \
|
||||
$(LIBRETRO_COMM_DIR)/hash/lrc_hash.o \
|
||||
input/input_driver.o \
|
||||
input/common/input_hid_common.o \
|
||||
led/led_driver.o \
|
||||
gfx/video_coord_array.o \
|
||||
gfx/video_crt_switch.o \
|
||||
gfx/gfx_display.o \
|
||||
gfx/gfx_animation.o \
|
||||
gfx/gfx_thumbnail_path.o \
|
||||
@@ -333,6 +338,7 @@ endif
|
||||
OBJ += \
|
||||
core_info.o \
|
||||
core_backup.o \
|
||||
core_option_manager.o \
|
||||
$(LIBRETRO_COMM_DIR)/file/config_file.o \
|
||||
$(LIBRETRO_COMM_DIR)/file/config_file_userdata.o \
|
||||
runtime_file.o \
|
||||
@@ -665,7 +671,7 @@ else ifeq ($(HAVE_BUILTINMBEDTLS), 1)
|
||||
DEFINES += -DMBEDTLS_SSL_DEBUG_ALL
|
||||
endif
|
||||
|
||||
# MinGW requires this for some reason,
|
||||
# MinGW requires this for some reason,
|
||||
# even though the include paths are relative to the source
|
||||
INCLUDE_DIRS += -Ideps/mbedtls
|
||||
|
||||
@@ -764,6 +770,12 @@ endif
|
||||
|
||||
ifeq ($(HAVE_LAKKA), 1)
|
||||
OBJ += wifi/drivers/connmanctl.o
|
||||
OBJ += misc/cpufreq/cpufreq.o
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_WIFI), 1)
|
||||
OBJ += wifi/drivers/nmcli.o
|
||||
DEFINES += -DHAVE_WIFI
|
||||
endif
|
||||
|
||||
# Audio
|
||||
@@ -820,7 +832,9 @@ ifeq ($(HAVE_ALSA), 1)
|
||||
|
||||
ifneq ($(HAVE_HAKCHI), 1)
|
||||
ifneq ($(HAVE_SEGAM), 1)
|
||||
OBJ += midi/drivers/alsa_midi.o
|
||||
ifneq ($(DINGUX), 1)
|
||||
OBJ += midi/drivers/alsa_midi.o
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -988,12 +1002,14 @@ ifeq ($(HAVE_MENU), 1)
|
||||
OBJ += menu/drivers/materialui.o
|
||||
DEFINES += -DHAVE_MATERIALUI
|
||||
HAVE_ASSETS = 1
|
||||
HAVE_MENU_SCREENSAVER = 1
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_XMB), 1)
|
||||
OBJ += menu/drivers/xmb.o
|
||||
DEFINES += -DHAVE_XMB
|
||||
HAVE_ASSETS = 1
|
||||
HAVE_MENU_SCREENSAVER = 1
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_OZONE), 1)
|
||||
@@ -1005,12 +1021,17 @@ ifeq ($(HAVE_MENU), 1)
|
||||
menu/drivers/ozone/ozone_sidebar.o
|
||||
DEFINES += -DHAVE_OZONE
|
||||
HAVE_ASSETS = 1
|
||||
HAVE_MENU_SCREENSAVER = 1
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_STRIPES), 1)
|
||||
OBJ += menu/drivers/stripes.o
|
||||
DEFINES += -DHAVE_STRIPES
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_MENU_SCREENSAVER), 1)
|
||||
OBJ += menu/menu_screensaver.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_BLUETOOTH), 1)
|
||||
@@ -1558,8 +1579,14 @@ else ifeq ($(HAVE_SDL), 1)
|
||||
else ifeq ($(HAVE_SDL_DINGUX), 1)
|
||||
HAVE_SDL_COMMON = 1
|
||||
DEF_FLAGS += -DHAVE_SDL -DHAVE_SDL_DINGUX
|
||||
OBJ += gfx/drivers/sdl_dingux_gfx.o \
|
||||
input/drivers/sdl_dingux_input.o \
|
||||
|
||||
ifeq ($(RS90), 1)
|
||||
OBJ += gfx/drivers/sdl_rs90_gfx.o
|
||||
else
|
||||
OBJ += gfx/drivers/sdl_dingux_gfx.o
|
||||
endif
|
||||
|
||||
OBJ += input/drivers/sdl_dingux_input.o \
|
||||
input/drivers_joypad/sdl_dingux_joypad.o
|
||||
DEF_FLAGS += $(SDL_DINGUX_CFLAGS)
|
||||
LIBS += $(SDL_DINGUX_LIBS)
|
||||
@@ -1863,20 +1890,24 @@ ifeq ($(HAVE_7ZIP),1)
|
||||
INCLUDE_DIRS += -I$(DEPS_DIR)/7zip
|
||||
HAVE_COMPRESSION = 1
|
||||
DEFINES += -DHAVE_7ZIP -D_7ZIP_ST
|
||||
7ZOBJ = $(DEPS_DIR)/7zip/7zIn.o \
|
||||
$(DEPS_DIR)/7zip/Bra86.o \
|
||||
$(DEPS_DIR)/7zip/7zFile.o \
|
||||
$(DEPS_DIR)/7zip/7zStream.o \
|
||||
7ZOBJ = $(DEPS_DIR)/7zip/7zArcIn.o \
|
||||
$(DEPS_DIR)/7zip/7zBuf.o \
|
||||
$(DEPS_DIR)/7zip/7zCrc.o \
|
||||
$(DEPS_DIR)/7zip/7zCrcOpt.o \
|
||||
$(DEPS_DIR)/7zip/7zDec.o \
|
||||
$(DEPS_DIR)/7zip/CpuArch.o \
|
||||
$(DEPS_DIR)/7zip/Delta.o \
|
||||
$(DEPS_DIR)/7zip/LzFind.o \
|
||||
$(DEPS_DIR)/7zip/LzmaDec.o \
|
||||
$(DEPS_DIR)/7zip/LzmaEnc.o \
|
||||
$(DEPS_DIR)/7zip/7zCrcOpt.o \
|
||||
$(DEPS_DIR)/7zip/Bra.o \
|
||||
$(DEPS_DIR)/7zip/7zDec.o \
|
||||
$(DEPS_DIR)/7zip/Bcj2.o \
|
||||
$(DEPS_DIR)/7zip/7zCrc.o \
|
||||
$(DEPS_DIR)/7zip/Lzma2Dec.o \
|
||||
$(DEPS_DIR)/7zip/7zBuf.o
|
||||
$(DEPS_DIR)/7zip/LzmaEnc.o \
|
||||
$(DEPS_DIR)/7zip/Bra.o \
|
||||
$(DEPS_DIR)/7zip/Bra86.o \
|
||||
$(DEPS_DIR)/7zip/BraIA64.o \
|
||||
$(DEPS_DIR)/7zip/Bcj2.o \
|
||||
$(DEPS_DIR)/7zip/7zFile.o \
|
||||
$(DEPS_DIR)/7zip/7zStream.o
|
||||
|
||||
OBJ += $(LIBRETRO_COMM_DIR)/file/archive_file_7z.o \
|
||||
$(7ZOBJ)
|
||||
endif
|
||||
@@ -1974,7 +2005,8 @@ ifeq ($(HAVE_CDROM), 1)
|
||||
DEFINES += -DHAVE_CDROM
|
||||
OBJ += $(LIBRETRO_COMM_DIR)/cdrom/cdrom.o \
|
||||
$(LIBRETRO_COMM_DIR)/vfs/vfs_implementation_cdrom.o \
|
||||
$(LIBRETRO_COMM_DIR)/media/media_detect_cd.o
|
||||
$(LIBRETRO_COMM_DIR)/media/media_detect_cd.o \
|
||||
tasks/task_content_disc.o
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_RTGA), 1)
|
||||
@@ -2079,14 +2111,9 @@ ifeq ($(HAVE_NETWORKING), 1)
|
||||
|
||||
# Netplay
|
||||
DEFINES += -DHAVE_NETWORK_CMD
|
||||
OBJ += network/netplay/netplay_delta.o \
|
||||
network/netplay/netplay_handshake.o \
|
||||
network/netplay/netplay_init.o \
|
||||
OBJ += network/netplay/netplay_handshake.o \
|
||||
network/netplay/netplay_io.o \
|
||||
network/netplay/netplay_keyboard.o \
|
||||
network/netplay/netplay_sync.o \
|
||||
network/netplay/netplay_discovery.o \
|
||||
network/netplay/netplay_buf.o \
|
||||
network/netplay/netplay_room_parse.o
|
||||
|
||||
# RetroAchievements
|
||||
@@ -2095,8 +2122,8 @@ ifeq ($(HAVE_NETWORKING), 1)
|
||||
INCLUDE_DIRS += -Ideps/rcheevos/include
|
||||
|
||||
OBJ += cheevos/cheevos.o \
|
||||
cheevos/badges.o \
|
||||
cheevos/cheevos_memory.o \
|
||||
cheevos/cheevos_client.o \
|
||||
cheevos/cheevos_menu.o \
|
||||
cheevos/cheevos_parser.o \
|
||||
$(LIBRETRO_COMM_DIR)/formats/cdfs/cdfs.o \
|
||||
deps/rcheevos/src/rcheevos/alloc.o \
|
||||
@@ -2108,12 +2135,16 @@ ifeq ($(HAVE_NETWORKING), 1)
|
||||
deps/rcheevos/src/rcheevos/lboard.o \
|
||||
deps/rcheevos/src/rcheevos/memref.o \
|
||||
deps/rcheevos/src/rcheevos/operand.o \
|
||||
deps/rcheevos/src/rcheevos/rc_libretro.o \
|
||||
deps/rcheevos/src/rcheevos/richpresence.o \
|
||||
deps/rcheevos/src/rcheevos/runtime.o \
|
||||
deps/rcheevos/src/rcheevos/runtime_progress.o \
|
||||
deps/rcheevos/src/rcheevos/trigger.o \
|
||||
deps/rcheevos/src/rcheevos/value.o \
|
||||
deps/rcheevos/src/rhash/hash.o \
|
||||
deps/rcheevos/src/rapi/rc_api_common.o \
|
||||
deps/rcheevos/src/rapi/rc_api_runtime.o \
|
||||
deps/rcheevos/src/rapi/rc_api_user.o \
|
||||
deps/rcheevos/src/rurl/url.o
|
||||
|
||||
ifeq ($(HAVE_LUA), 1)
|
||||
@@ -2257,6 +2288,39 @@ ifeq ($(HAVE_FFMPEG), 1)
|
||||
INCLUDE_DIRS += -Iffmpeg
|
||||
endif
|
||||
|
||||
# CRT mode switching
|
||||
ifeq ($(HAVE_CRTSWITCHRES), 1)
|
||||
INCLUDE_DIRS += -I$(DEPS_DIR)/switchres
|
||||
OBJ += gfx/video_crt_switch.o \
|
||||
$(DEPS_DIR)/switchres/monitor.o \
|
||||
$(DEPS_DIR)/switchres/modeline.o \
|
||||
$(DEPS_DIR)/switchres/switchres.o \
|
||||
$(DEPS_DIR)/switchres/display.o \
|
||||
$(DEPS_DIR)/switchres/custom_video.o \
|
||||
$(DEPS_DIR)/switchres/log.o \
|
||||
$(DEPS_DIR)/switchres/switchres_wrapper.o \
|
||||
$(DEPS_DIR)/switchres/edid.o
|
||||
ifneq ($(findstring Win32,$(OS)),)
|
||||
OBJ += $(DEPS_DIR)/switchres/display_windows.o \
|
||||
$(DEPS_DIR)/switchres/custom_video_ati_family.o \
|
||||
$(DEPS_DIR)/switchres/custom_video_ati.o \
|
||||
$(DEPS_DIR)/switchres/custom_video_adl.o \
|
||||
$(DEPS_DIR)/switchres/custom_video_pstrip.o \
|
||||
$(DEPS_DIR)/switchres/resync_windows.o
|
||||
endif
|
||||
ifneq ($(findstring Linux,$(OS)),)
|
||||
OBJ += $(DEPS_DIR)/switchres/display_linux.o
|
||||
ifeq ($(HAVE_X11)$(HAVE_XRANDR), 11)
|
||||
OBJ += $(DEPS_DIR)/switchres/custom_video_xrandr.o
|
||||
DEFINES += -DSR_WITH_XRANDR
|
||||
endif
|
||||
endif
|
||||
ifneq ($(findstring Win32,$(OS)),)
|
||||
DEFINES += -DSR_WIN32_STATIC
|
||||
endif
|
||||
LIBS += -lstdc++
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_COMPRESSION), 1)
|
||||
DEFINES += -DHAVE_COMPRESSION
|
||||
OBJ += tasks/task_decompress.o
|
||||
@@ -2274,9 +2338,9 @@ ifeq ($(HAVE_COCOA_COMMON),1)
|
||||
OBJ += input/drivers/cocoa_input.o \
|
||||
ui/drivers/ui_cocoa.o \
|
||||
ui/drivers/cocoa/cocoa_common.o
|
||||
|
||||
|
||||
ifeq ($(HAVE_OPENGL), 1)
|
||||
DEFINES += -DGL_SILENCE_DEPRECATION
|
||||
DEFINES += -DGL_SILENCE_DEPRECATION
|
||||
OBJ += gfx/drivers_context/cocoa_gl_ctx.o
|
||||
endif
|
||||
ifeq ($(HAVE_VULKAN), 1)
|
||||
@@ -2320,10 +2384,10 @@ endif
|
||||
|
||||
ifeq ($(WANT_IOSUHAX), 1)
|
||||
DEFINES += -DHAVE_IOSUHAX
|
||||
INCLUDE_DIRS += -I$(DEPS_DIR)/libiosuhax
|
||||
OBJ += $(DEPS_DIR)/libiosuhax/iosuhax.o \
|
||||
$(DEPS_DIR)/libiosuhax/iosuhax_devoptab.o \
|
||||
$(DEPS_DIR)/libiosuhax/iosuhax_disc_interface.o
|
||||
INCLUDE_DIRS += -I$(DEPS_DIR)/libiosuhax/include
|
||||
OBJ += $(DEPS_DIR)/libiosuhax/source/iosuhax.o \
|
||||
$(DEPS_DIR)/libiosuhax/source/iosuhax_devoptab.o \
|
||||
$(DEPS_DIR)/libiosuhax/source/iosuhax_disc_interface.o
|
||||
endif
|
||||
|
||||
ifeq ($(WANT_LIBFAT), 1)
|
||||
@@ -2360,13 +2424,6 @@ ifneq ($(findstring Win32,$(OS)),)
|
||||
OBJ += led/drivers/led_win32_keyboard.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_VITAGLES), 1)
|
||||
DEFINES += -DHAVE_VITAGLES
|
||||
INCLUDE_DIRS += -I$(DEPS_DIR)/Pigs-In-A-Blanket/include
|
||||
@@ -2374,6 +2431,10 @@ ifeq ($(HAVE_VITAGLES), 1)
|
||||
OBJ += $(patsubst %.c,%.o,$(foreach dir,$(SOURCES), $(wildcard $(dir)/*.c)))
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_WEBOS), 1)
|
||||
DEFINES += -DWEBOS
|
||||
endif
|
||||
|
||||
#####################################
|
||||
### Android Play Feature Delivery ###
|
||||
### (Play Store build core ###
|
||||
@@ -2431,4 +2492,3 @@ ifeq ($(HAVE_ODROIDGO2), 1)
|
||||
endif
|
||||
|
||||
##################################
|
||||
|
||||
+3
-2
@@ -51,14 +51,15 @@ DEFINES :=
|
||||
ifeq ($(GRIFFIN_BUILD), 1)
|
||||
OBJ += griffin/griffin.o
|
||||
DEFINES += -DHAVE_GRIFFIN=1 -DHAVE_MENU -DHAVE_CONFIGFILE -DHAVE_RGUI -DHAVE_XMB -DHAVE_MATERIALUI -DHAVE_LIBRETRODB -DHAVE_CC_RESAMPLER
|
||||
DEFINES += -DHAVE_ZLIB -DHAVE_7ZIP -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA
|
||||
DEFINES += -DHAVE_ZLIB -DHAVE_7ZIP -D_7ZIP_ST -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA
|
||||
DEFINES += -DHAVE_NETWORKING -DHAVE_CHEEVOS -DRC_DISABLE_LUA -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_CORES
|
||||
#DEFINES += -DHAVE_UPDATE_ASSETS
|
||||
DEFINES += -DHAVE_PATCH -DHAVE_RWAV
|
||||
DEFINES += -DHAVE_SCREENSHOTS
|
||||
DEFINES += -DHAVE_REWIND
|
||||
DEFINES += -DHAVE_THREADS
|
||||
#DEFINES += -DHAVE_GFX_WIDGETS
|
||||
DEFINES += -DHAVE_GFX_WIDGETS
|
||||
DEFINES += -DHAVE_OVERLAY
|
||||
#DEFINES += -DHAVE_SOCKET_LEGACY
|
||||
#-DHAVE_SSL -DHAVE_BUILTINMBEDTLS -DMBEDTLS_SSL_DEBUG_ALL
|
||||
#ssl is currently incompatible with griffin due to use of the "static" flag on repeating functions that will conflict when included in one file
|
||||
|
||||
+2
-2
@@ -490,7 +490,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 -D__SSE__
|
||||
PLATCFLAGS += -D_WIN32 -D_WIN32_WINNT=0x0410 -D__STDC_CONSTANT_MACROS -D_MBCS
|
||||
PLATCFLAGS += -DHAVE_OPENGL -DHAVE_OPENGL1 -DHAVE_GLSL -DHAVE_OZONE -DHAVE_GFX_WIDGETS -DHAVE_CC_RESAMPLER
|
||||
PLATCFLAGS += -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS -DHAVE_UPDATE_CORES -DHAVE_CDROM
|
||||
PLATCFLAGS += -bigobj
|
||||
@@ -1102,7 +1102,7 @@ ifeq ($(HAVE_RUNAHEAD), 1)
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_7ZIP), 1)
|
||||
CFLAGS += -DHAVE_7ZIP
|
||||
CFLAGS += -DHAVE_7ZIP -D_7ZIP_ST
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_SCREENSHOTS), 1)
|
||||
|
||||
@@ -32,6 +32,7 @@ HAVE_RTGA = 1
|
||||
HAVE_RPNG = 1
|
||||
HAVE_RJPEG = 1
|
||||
HAVE_RBMP = 1
|
||||
HAVE_7ZIP = 1
|
||||
HAVE_ZLIB = 1
|
||||
HAVE_BUILTINZLIB = 1
|
||||
HAVE_LIBRETRODB = 1
|
||||
|
||||
+1
-1
@@ -205,7 +205,7 @@ ifeq ($(HAVE_RUNAHEAD), 1)
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_7ZIP), 1)
|
||||
CFLAGS += -DHAVE_7ZIP
|
||||
CFLAGS += -DHAVE_7ZIP -D_7ZIP_ST
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_SCREENSHOTS), 1)
|
||||
|
||||
+12
-6
@@ -1,5 +1,6 @@
|
||||
BUILD_FOR_PCSX2 = 0
|
||||
DEBUG = 0
|
||||
SCREEN_DEBUG = 0
|
||||
HAVE_THREADS = 0
|
||||
MUTE_WARNINGS = 1
|
||||
PS2_IP = 192.168.1.10
|
||||
@@ -24,18 +25,22 @@ endif
|
||||
|
||||
INCDIR = -I$(PS2DEV)/gsKit/include -I$(PS2SDK)/ports/include
|
||||
INCDIR += -Ips2/include -Ilibretro-common/include -Ideps -Ideps/stb -Ideps/7zip
|
||||
INCDIR += -Ideps/pthreads -Ideps/pthreads/platform/ps2 -Ideps/pthreads/platform/helper
|
||||
CFLAGS = $(OPTIMIZE_LV) $(DISABLE_WARNINGS) -ffast-math -fsingle-precision-constant
|
||||
ASFLAGS = $(CFLAGS)
|
||||
|
||||
RARCH_DEFINES += -DPS2 -DHAVE_GRIFFIN=1 -DRARCH_INTERNAL -DHAVE_SCREENSHOTS -DHAVE_REWIND -DRARCH_CONSOLE -DHAVE_MENU -DHAVE_CONFIGFILE -DHAVE_PATCH -DHAVE_CHEATS -DHAVE_RGUI
|
||||
RARCH_DEFINES += -DHAVE_ZLIB -DHAVE_NO_BUILTINZLIB -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_FILTERS_BUILTIN -DHAVE_7ZIP -DHAVE_CC_RESAMPLER -DHAVE_AUDIOMIXER
|
||||
RARCH_DEFINES += -DPS2 -DHAVE_GRIFFIN=1 -DRARCH_INTERNAL -DHAVE_SCREENSHOTS -DHAVE_REWIND -DRARCH_CONSOLE -DHAVE_MENU -DHAVE_CONFIGFILE -DHAVE_PATCH -DHAVE_CHEATS
|
||||
RARCH_DEFINES += -DHAVE_ZLIB -DHAVE_NO_BUILTINZLIB -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_FILTERS_BUILTIN -DHAVE_7ZIP -D_7ZIP_ST -DHAVE_CC_RESAMPLER -DHAVE_AUDIOMIXER
|
||||
RARCH_DEFINES += -DHAVE_VIDEO_FILTER -DHAVE_RGUI
|
||||
RARCH_DEFINES += -DHAVE_DSP_FILTER
|
||||
RARCH_DEFINES += -DHAVE_VIDEO_FILTER
|
||||
|
||||
LDFLAGS += -L$(PS2DEV)/gsKit/lib -L$(PS2SDK)/ports/lib -L.
|
||||
# Lib cdvd is needed to get proper time
|
||||
LIBS += -lretro_ps2 -lpatches -lgskit -ldmakit -laudsrv -lmtap -lpadx -lz -lcdvd -lelf-loader
|
||||
LIBS += -lretro_ps2 -lpatches -lgskit -ldmakit -laudsrv -lmtap -lpadx -lz -lcdvd -lelf-loader -lfileXio -lpoweroff
|
||||
|
||||
ifeq ($(SCREEN_DEBUG), 1)
|
||||
LIBS += -ldebug
|
||||
RARCH_DEFINES += -DSCREEN_DEBUG
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_FOR_PCSX2), 1)
|
||||
RARCH_DEFINES += -DBUILD_FOR_PCSX2
|
||||
@@ -50,9 +55,10 @@ CFLAGS += $(RARCH_DEFINES)
|
||||
# All the IRX objects
|
||||
EE_OBJS += $(IRX_DIR)/sio2man_irx.o $ $(IRX_DIR)/iomanX_irx.o $(IRX_DIR)/fileXio_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/mcman_irx.o $(IRX_DIR)/mcserv_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/usbd_irx.o $(IRX_DIR)/usbhdfsd_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/usbd_irx.o $(IRX_DIR)/bdm_irx.o $(IRX_DIR)/bdmfs_vfat_irx.o $(IRX_DIR)/usbmass_bd_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/libsd_irx.o $(IRX_DIR)/audsrv_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/cdfs_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/ps2dev9_irx.o $(IRX_DIR)/ps2atad_irx.o $(IRX_DIR)/ps2hdd_irx.o $(IRX_DIR)/ps2fs_irx.o $(IRX_DIR)/poweroff_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/mtapman_irx.o $(IRX_DIR)/padman_irx.o
|
||||
|
||||
# Missing objecst on the PS2SDK
|
||||
|
||||
+10
-2
@@ -1,5 +1,6 @@
|
||||
BUILD_FOR_PCSX2 = 0
|
||||
DEBUG = 0
|
||||
SCREEN_DEBUG = 0
|
||||
MUTE_WARNINGS = 1
|
||||
PS2_IP = 192.168.1.150
|
||||
|
||||
@@ -30,7 +31,12 @@ RARCH_DEFINES += -DPS2 -DIS_SALAMANDER -DRARCH_CONSOLE
|
||||
|
||||
LIBDIR =
|
||||
LDFLAGS =
|
||||
LIBS = -lelf-loader -lpatches
|
||||
LIBS = -lelf-loader -lpatches -lfileXio -lpoweroff
|
||||
|
||||
ifeq ($(SCREEN_DEBUG), 1)
|
||||
LIBS += -ldebug
|
||||
RARCH_DEFINES += -DSCREEN_DEBUG
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_FOR_PCSX2), 1)
|
||||
RARCH_DEFINES += -DBUILD_FOR_PCSX2
|
||||
@@ -61,8 +67,10 @@ EE_OBJS = frontend/frontend_salamander.o \
|
||||
|
||||
# Needed IRX objects
|
||||
EE_OBJS += $(IRX_DIR)/sio2man_irx.o $ $(IRX_DIR)/iomanX_irx.o $(IRX_DIR)/fileXio_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/mcman_irx.o $(IRX_DIR)/mcserv_irx.o $(IRX_DIR)/usbd_irx.o $(IRX_DIR)/usbhdfsd_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/mcman_irx.o $(IRX_DIR)/mcserv_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/usbd_irx.o $(IRX_DIR)/bdm_irx.o $(IRX_DIR)/bdmfs_vfat_irx.o $(IRX_DIR)/usbmass_bd_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/cdfs_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/ps2dev9_irx.o $(IRX_DIR)/ps2atad_irx.o $(IRX_DIR)/ps2hdd_irx.o $(IRX_DIR)/ps2fs_irx.o $(IRX_DIR)/poweroff_irx.o
|
||||
|
||||
EE_CFLAGS = $(CFLAGS)
|
||||
EE_CXXFLAGS = $(CFLAGS)
|
||||
|
||||
+4
-4
@@ -27,13 +27,13 @@ ELF_TARGET := retroarch_psl1ght.elf
|
||||
SELF_TARGET := $(ELF_TARGET:.elf=.self)
|
||||
CORE_PATH = pkg/psl1ght/pkg/USRDIR/cores/CORE.SELF
|
||||
|
||||
INCLUDE += -I. -Ips3/gcmgl/include/export -Ips3/include -Ideps -Ideps/stb -Ilibretro-common/include/compat/zlib -Ilibretro-common/include $(LIBPSL1GHT_INC) -Iinclude
|
||||
INCLUDE += -I. -Ips3/gcmgl/include/export -Ips3/include -Ideps -Ideps/stb -Ilibretro-common/include/compat/zlib -Ilibretro-common/include $(LIBPSL1GHT_INC) -Iinclude -Idefines
|
||||
LIBDIRS += -L.
|
||||
|
||||
MACHDEP := -D__PSL1GHT__ -mcpu=cell
|
||||
MACHDEP := -D__PSL1GHT__ -D__PS3__ -mcpu=cell
|
||||
CFLAGS += -Wall $(MACHDEP) $(INCLUDE)
|
||||
LDFLAGS := $(MACHDEP)
|
||||
LIBS := -lretro_psl1ght -laudio -lrsx -lgcm_sys -lnet -lio -lsysutil -lsysmodule -lm -ljpgdec -lpngdec -llv2 -lnet -lnetctl
|
||||
LIBS := -lretro_psl1ght -laudio -lrsx -lgcm_sys -lnet -lio -lsysutil -lsysmodule -lm -ljpgdec -lpngdec -llv2 -lnet -lnetctl -lsysfs
|
||||
|
||||
# system platform
|
||||
system_platform = unix
|
||||
@@ -66,7 +66,7 @@ endif
|
||||
SHARED_FLAGS :=
|
||||
|
||||
SHARED_FLAGS += -DHAVE_VIDEO_LAYOUT
|
||||
SHARED_FLAGS += -DHAVE_MENU -DHAVE_CONFIGFILE -DHAVE_PATCH -DHAVE_CHEATS -DRARCH_CONSOLE -DHAVE_OVERLAY -DHAVE_HEADSET -DHAVE_CG -DHAVE_CG_RUNTIME_COMPILER -DHAVE_GCMGL -DHAVE_SYSMODULES -DHAVE_SYSUTILS -DHAVE_RARCH_EXEC -DHAVE_MOUSE -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_GRIFFIN=1 -DHAVE_NETWORKING=1 -DHAVE_SOCKET_LEGACY=1 -DPC_DEVELOPMENT_IP_ADDRESS=\"$(PC_DEVELOPMENT_IP_ADDRESS)\" -DPC_DEVELOPMENT_UDP_PORT=$(PC_DEVELOPMENT_UDP_PORT) -Wno-char-subscripts -DHAVE_CC_RESAMPLER -DRARCH_INTERNAL -DHAVE_SCREENSHOTS -DHAVE_REWIND -DHAVE_MULTIMAN -DHAVE_RGUI
|
||||
SHARED_FLAGS += -DHAVE_MENU -DHAVE_CONFIGFILE -DHAVE_PATCH -DHAVE_CHEATS -DRARCH_CONSOLE -DHAVE_OVERLAY -DHAVE_HEADSET -DHAVE_CG -DHAVE_CG_RUNTIME_COMPILER -DHAVE_SYSMODULES -DHAVE_SYSUTILS -DHAVE_RARCH_EXEC -DHAVE_MOUSE -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_GRIFFIN=1 -DHAVE_NETWORKING=1 -DHAVE_SOCKET_LEGACY=1 -DPC_DEVELOPMENT_IP_ADDRESS=\"$(PC_DEVELOPMENT_IP_ADDRESS)\" -DPC_DEVELOPMENT_UDP_PORT=$(PC_DEVELOPMENT_UDP_PORT) -Wno-char-subscripts -DHAVE_CC_RESAMPLER -DRARCH_INTERNAL -DHAVE_SCREENSHOTS -DHAVE_REWIND -DHAVE_MULTIMAN -DHAVE_RGUI
|
||||
CFLAGS += -std=gnu99 $(SHARED_FLAGS)
|
||||
CXXFLAGS += $(SHARED_FLAGS)
|
||||
|
||||
|
||||
@@ -27,13 +27,14 @@ ELF_TARGET := retroarch_psl1ght_salamander.elf
|
||||
ELF_TARGET_NONSTRIPPED := retroarch_psl1ght_salamander_nonstripped.elf
|
||||
EBOOT_PATH = pkg/psl1ght/pkg/USRDIR/EBOOT.BIN
|
||||
|
||||
INCLUDE += -I. -Ips3/gcmgl/include/export -Ips3/include -Ideps -Ideps/stb -Ilibretro-common/include/compat/zlib -Ilibretro-common/include $(LIBPSL1GHT_INC) -Iinclude
|
||||
INCLUDE += -I. -Ips3/gcmgl/include/export -Ips3/include -Ideps -Ideps/stb -Ilibretro-common/include/compat/zlib \
|
||||
-Ilibretro-common/include $(LIBPSL1GHT_INC) -Iinclude -Idefines
|
||||
LIBDIRS += -L.
|
||||
|
||||
MACHDEP := -D__PSL1GHT__ -mcpu=cell -mhard-float -fmodulo-sched -ffunction-sections -fdata-sections
|
||||
MACHDEP := -D__PS3__ -D__PSL1GHT__ -mcpu=cell -mhard-float -fmodulo-sched -ffunction-sections -fdata-sections
|
||||
CFLAGS += -Wall $(MACHDEP) $(INCLUDE)
|
||||
LDFLAGS := $(MACHDEP)
|
||||
LIBS := -lgcm_sys -lrsx -lsysutil -lio -lnet -lsysmodule -lrt -llv2 -lm
|
||||
LIBS := -lgcm_sys -lrsx -lsysutil -lio -lnet -lsysmodule -lrt -llv2 -lm -lsysfs
|
||||
|
||||
# system platform
|
||||
system_platform = unix
|
||||
|
||||
+3
-3
@@ -19,15 +19,15 @@ ifeq ($(WHOLE_ARCHIVE_LINK), 1)
|
||||
WHOLE_END := -Wl,--no-whole-archive
|
||||
endif
|
||||
|
||||
INCDIR = deps deps/stb deps/7zip deps/pthreads deps/pthreads/platform/psp deps/pthreads/platform/helper libretro-common/include libretro-common/include/compat/zlib
|
||||
INCDIR = deps deps/stb deps/7zip libretro-common/include libretro-common/include/compat/zlib
|
||||
CFLAGS = $(OPTIMIZE_LV) -G0 -std=gnu99 -ffast-math -fsingle-precision-constant
|
||||
ASFLAGS = $(CFLAGS)
|
||||
|
||||
RARCH_DEFINES = -DPSP -D_MIPS_ARCH_ALLEGREX -DHAVE_LANGEXTRA -DHAVE_ZLIB -DHAVE_AUDIOMIXER -DHAVE_RWAV -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_GRIFFIN=1 -DRARCH_INTERNAL -DHAVE_SCREENSHOTS -DHAVE_REWIND -DRARCH_CONSOLE -DHAVE_MENU -DHAVE_CONFIGFILE -DHAVE_PATCH -DHAVE_CHEATS -DHAVE_RGUI -DHAVE_FILTERS_BUILTIN -DHAVE_DSP_FILTER -DHAVE_VIDEO_FILTER -DHAVE_7ZIP -DHAVE_CC_RESAMPLER
|
||||
RARCH_DEFINES = -DPSP -D_MIPS_ARCH_ALLEGREX -DHAVE_LANGEXTRA -DHAVE_ZLIB -DHAVE_AUDIOMIXER -DHAVE_RWAV -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_GRIFFIN=1 -DRARCH_INTERNAL -DHAVE_SCREENSHOTS -DHAVE_REWIND -DRARCH_CONSOLE -DHAVE_MENU -DHAVE_CONFIGFILE -DHAVE_PATCH -DHAVE_CHEATS -DHAVE_RGUI -DHAVE_FILTERS_BUILTIN -DHAVE_DSP_FILTER -DHAVE_VIDEO_FILTER -DHAVE_7ZIP -D_7ZIP_ST -DHAVE_CC_RESAMPLER
|
||||
|
||||
LIBDIR =
|
||||
LDFLAGS =
|
||||
LIBS = $(WHOLE_START) -lretro_psp1 $(WHOLE_END) -lstdc++ -lpspgu -lpspgum -lm -lpspaudio -lpspfpu -lpsppower -lpsprtc
|
||||
LIBS = $(WHOLE_START) -lretro_psp1 $(WHOLE_END) -lstdc++ -lpspgu -lpspgum -lm -lpspaudio -lpspfpu -lpsppower -lpsprtc -lpthread-psp
|
||||
|
||||
ifeq ($(HAVE_THREADS), 1)
|
||||
RARCH_DEFINES += -DHAVE_THREADS
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
#########################
|
||||
## Toolchain variables ##
|
||||
#########################
|
||||
|
||||
# Default toolchain directory
|
||||
TOOLCHAIN_DIR=/opt/retrofw-toolchain
|
||||
|
||||
# All toolchain-related variables may be
|
||||
# overridden via the command line
|
||||
ifdef RETROFW_CC
|
||||
CC = $(GCW0_CC)
|
||||
else
|
||||
CC = $(TOOLCHAIN_DIR)/usr/bin/mipsel-linux-gcc
|
||||
endif
|
||||
|
||||
ifdef RETROFW_CXX
|
||||
CXX = $(GCW0_CXX)
|
||||
else
|
||||
CXX = $(TOOLCHAIN_DIR)/usr/bin/mipsel-linux-g++
|
||||
endif
|
||||
|
||||
ifdef RETROFW_STRIP
|
||||
STRIP = $(GCW0_STRIP)
|
||||
else
|
||||
STRIP = $(TOOLCHAIN_DIR)/usr/bin/mipsel-linux-strip
|
||||
endif
|
||||
|
||||
GCW0_SDL_CONFIG ?= $(TOOLCHAIN_DIR)/usr/mipsel-buildroot-linux-uclibc/sysroot/usr/bin/sdl-config
|
||||
GCW0_FREETYPE_CONFIG ?= $(TOOLCHAIN_DIR)/usr/mipsel-buildroot-linux-uclibc/sysroot/usr/bin/freetype-config
|
||||
#GCW0_MK_SQUASH_FS ?= $(TOOLCHAIN_DIR)/usr/bin/mksquashfs
|
||||
GCW0_MK_SQUASH_FS ?= mksquashfs
|
||||
|
||||
GCW0_INC_DIR ?= $(TOOLCHAIN_DIR)/usr/mipsel-buildroot-linux-uclibc/sysroot/usr/include
|
||||
GCW0_LIB_DIR ?= $(TOOLCHAIN_DIR)/usr/mipsel-buildroot-linux-uclibc/sysroot/usr/lib
|
||||
|
||||
#########################
|
||||
#########################
|
||||
|
||||
PACKAGE_NAME = retroarch
|
||||
RETROFW = 1
|
||||
|
||||
DEBUG ?= 0
|
||||
|
||||
DINGUX = 1
|
||||
HAVE_SCREENSHOTS = 0
|
||||
HAVE_REWIND = 1
|
||||
HAVE_7ZIP = 1
|
||||
HAVE_AL = 0
|
||||
# ALSA freezes when switching back from menu
|
||||
HAVE_ALSA = 0
|
||||
HAVE_DSP_FILTER = 1
|
||||
HAVE_VIDEO_FILTER = 1
|
||||
HAVE_STATIC_VIDEO_FILTERS = 1
|
||||
HAVE_STATIC_AUDIO_FILTERS = 1
|
||||
HAVE_FILTERS_BUILTIN = 1
|
||||
HAVE_BUILTINMBEDTLS = 0
|
||||
HAVE_BUILTINZLIB = 1
|
||||
HAVE_C99 = 1
|
||||
HAVE_CC = 1
|
||||
HAVE_CC_RESAMPLER = 1
|
||||
HAVE_CHD = 1
|
||||
HAVE_COMMAND = 0
|
||||
HAVE_CXX = 1
|
||||
HAVE_DR_MP3 = 1
|
||||
HAVE_DYNAMIC = 1
|
||||
HAVE_EGL = 0
|
||||
HAVE_FREETYPE = 0
|
||||
HAVE_GDI = 1
|
||||
HAVE_GETADDRINFO = 0
|
||||
HAVE_GETOPT_LONG = 1
|
||||
HAVE_GLSL = 0
|
||||
HAVE_HID = 1
|
||||
HAVE_IBXM = 1
|
||||
HAVE_IMAGEVIEWER = 1
|
||||
HAVE_LANGEXTRA = 0
|
||||
HAVE_LIBRETRODB = 1
|
||||
HAVE_MENU = 1
|
||||
HAVE_MENU_COMMON = 1
|
||||
HAVE_GFX_WIDGETS = 0
|
||||
HAVE_MMAP = 1
|
||||
HAVE_OPENDINGUX_FBDEV = 0
|
||||
HAVE_OPENGL = 0
|
||||
HAVE_OPENGL1 = 0
|
||||
HAVE_OPENGLES = 0
|
||||
HAVE_OPENGLES3 = 0
|
||||
HAVE_OPENGL_CORE = 0
|
||||
HAVE_OPENSSL = 1
|
||||
HAVE_OVERLAY = 0
|
||||
HAVE_RBMP = 1
|
||||
HAVE_RJPEG = 1
|
||||
HAVE_RPILED = 0
|
||||
HAVE_RPNG = 1
|
||||
HAVE_RUNAHEAD = 0
|
||||
HAVE_SDL_DINGUX = 1
|
||||
HAVE_SHADERPIPELINE = 0
|
||||
HAVE_STB_FONT = 0
|
||||
HAVE_STB_IMAGE = 1
|
||||
HAVE_STB_VORBIS = 1
|
||||
HAVE_STDIN_CMD = 0
|
||||
HAVE_STRCASESTR = 1
|
||||
HAVE_THREADS = 1
|
||||
HAVE_UDEV = 0
|
||||
HAVE_RGUI = 1
|
||||
HAVE_MATERIALUI = 0
|
||||
HAVE_XMB = 0
|
||||
HAVE_OZONE = 0
|
||||
HAVE_ZLIB = 1
|
||||
HAVE_CONFIGFILE = 1
|
||||
HAVE_PATCH = 1
|
||||
HAVE_CHEATS = 1
|
||||
HAVE_CHEEVOS = 0
|
||||
HAVE_LIBSHAKE = 0
|
||||
|
||||
#comment out for now not working
|
||||
#HAVE_OSS =1
|
||||
#HAVE_OSS_LIB =1
|
||||
|
||||
OS = Linux
|
||||
TARGET = retroarch
|
||||
OPK_NAME = retroarch_retrofw.opk
|
||||
|
||||
OBJ :=
|
||||
LINK := $(CXX)
|
||||
DEF_FLAGS := -march=mips32 -mtune=mips32 -mhard-float -ffast-math -fomit-frame-pointer
|
||||
DEF_FLAGS += -mplt -mno-shared
|
||||
DEF_FLAGS += -ffunction-sections -fdata-sections
|
||||
DEF_FLAGS += -I. -Ideps -Ideps/stb -DDINGUX=1 -DRETROFW=1 -MMD
|
||||
DEF_FLAGS += -Wall -Wno-unused-variable -flto
|
||||
DEF_FLAGS += -std=gnu99 -D_GNU_SOURCE
|
||||
LIBS := -ldl -lz -lrt -pthread
|
||||
CFLAGS :=
|
||||
CXXFLAGS := -fno-exceptions -fno-rtti -std=c++11 -D__STDC_CONSTANT_MACROS
|
||||
ASFLAGS :=
|
||||
LDFLAGS := -Wl,--gc-sections
|
||||
INCLUDE_DIRS = -I$(GCW0_INC_DIR)
|
||||
LIBRARY_DIRS = -L$(GCW0_LIB_DIR)
|
||||
DEFINES := -DRARCH_INTERNAL -D_FILE_OFFSET_BITS=64 -UHAVE_STATIC_DUMMY
|
||||
DEFINES += -DHAVE_C99=1 -DHAVE_CXX=1
|
||||
DEFINES += -DHAVE_GETOPT_LONG=1 -DHAVE_STRCASESTR=1 -DHAVE_DYNAMIC=1
|
||||
DEFINES += -DHAVE_FILTERS_BUILTIN
|
||||
|
||||
SDL_DINGUX_CFLAGS := $(shell $(GCW0_SDL_CONFIG) --cflags)
|
||||
SDL_DINGUX_LIBS := $(shell $(GCW0_SDL_CONFIG) --libs)
|
||||
FREETYPE_CFLAGS := $(shell $(GCW0_FREETYPE_CONFIG) --cflags)
|
||||
FREETYPE_LIBS := $(shell $(GCW0_FREETYPE_CONFIG) --libs)
|
||||
MMAP_LIBS = -lc
|
||||
|
||||
OBJDIR_BASE := obj-unix
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
OBJDIR := $(OBJDIR_BASE)/debug
|
||||
DEF_FLAGS += -O0 -g -DDEBUG -D_DEBUG
|
||||
else
|
||||
OBJDIR := $(OBJDIR_BASE)/release
|
||||
DEF_FLAGS += -O2 -DNDEBUG
|
||||
endif
|
||||
|
||||
include Makefile.common
|
||||
|
||||
DEF_FLAGS += $(INCLUDE_DIRS)
|
||||
LDFLAGS += $(CFLAGS) $(CXXFLAGS) $(DEF_FLAGS)
|
||||
CFLAGS += $(DEF_FLAGS)
|
||||
CXXFLAGS += $(DEF_FLAGS)
|
||||
|
||||
HEADERS = $(wildcard */*/*.h) $(wildcard */*.h) $(wildcard *.h)
|
||||
|
||||
Q := @
|
||||
|
||||
RARCH_OBJ := $(addprefix $(OBJDIR)/,$(OBJ))
|
||||
|
||||
define DESKTOP_ENTRY
|
||||
[Desktop Entry]
|
||||
Name=RetroArch
|
||||
Comment=Frontend for emulators, game engines
|
||||
Exec=retroarch
|
||||
Terminal=false
|
||||
Type=Application
|
||||
StartupNotify=true
|
||||
Icon=retroarch
|
||||
Categories=emulators;
|
||||
X-OD-NeedsDownscaling=true
|
||||
endef
|
||||
export DESKTOP_ENTRY
|
||||
|
||||
|
||||
all: $(TARGET) opk
|
||||
|
||||
-include $(RARCH_OBJ:.o=.d)
|
||||
|
||||
SYMBOL_MAP := -Wl,-Map=output.map
|
||||
|
||||
$(TARGET): $(RARCH_OBJ)
|
||||
@$(if $(Q), $(shell echo echo LD $@),)
|
||||
$(Q)$(LINK) -o $@ $(RARCH_OBJ) $(LIBS) $(LDFLAGS) $(LIBRARY_DIRS)
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
@mkdir -p $(dir $@)
|
||||
@$(if $(Q), $(shell echo echo CC $<),)
|
||||
$(Q)$(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
@mkdir -p $(dir $@)
|
||||
@$(if $(Q), $(shell echo echo CXX $<),)
|
||||
$(Q)$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(DEFINES) -MMD -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: %.m
|
||||
@mkdir -p $(dir $@)
|
||||
@$(if $(Q), $(shell echo echo OBJC $<),)
|
||||
$(Q)$(CXX) $(OBJCFLAGS) $(DEFINES) -MMD -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: %.S $(HEADERS)
|
||||
@mkdir -p $(dir $@)
|
||||
@$(if $(Q), $(shell echo echo AS $<),)
|
||||
$(Q)$(CC) $(CFLAGS) $(ASFLAGS) $(DEFINES) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJDIR_BASE)
|
||||
rm -f $(TARGET)
|
||||
rm -f *.d
|
||||
rm -rf $(OPK_NAME)
|
||||
|
||||
opk: $(TARGET)
|
||||
echo "$$DESKTOP_ENTRY" > default.retrofw.desktop
|
||||
rm -f $(OPK_NAME)
|
||||
cp media/ico_src/icon32.png retroarch.png
|
||||
chmod +x retroarch
|
||||
chmod 777 retroarch
|
||||
ifeq ($(STRIP_BIN),1)
|
||||
$(STRIP) --strip-unneeded retroarch
|
||||
endif
|
||||
$(GCW0_MK_SQUASH_FS) retroarch default.retrofw.desktop retroarch.png $(OPK_NAME) -all-root -no-xattrs -noappend -no-exports
|
||||
rm -f default.retrofw.desktop retroarch.png
|
||||
|
||||
.PHONY: all clean opk
|
||||
|
||||
print-%:
|
||||
@echo '$*=$($*)'
|
||||
+3
-1
@@ -219,7 +219,9 @@ opk: $(TARGET)
|
||||
echo "$$DESKTOP_ENTRY" > default.gcw0.desktop
|
||||
rm -f $(OPK_NAME)
|
||||
cp media/ico_src/icon32.png retroarch.png
|
||||
if [ $$STRIP_BIN -eq 1 ]; then $(STRIP) --strip-unneeded retroarch; fi
|
||||
ifeq ($(STRIP_BIN),1)
|
||||
$(STRIP) --strip-unneeded retroarch
|
||||
endif
|
||||
$(GCW0_MK_SQUASH_FS) retroarch default.gcw0.desktop retroarch.png $(OPK_NAME) -all-root -no-xattrs -noappend -no-exports
|
||||
rm -f default.gcw0.desktop retroarch.png
|
||||
|
||||
|
||||
@@ -45,8 +45,7 @@ HAVE_SCREENSHOTS = 0
|
||||
HAVE_REWIND = 1
|
||||
HAVE_7ZIP = 1
|
||||
HAVE_AL = 1
|
||||
# ALSA freezes when switching back from menu
|
||||
HAVE_ALSA = 0
|
||||
HAVE_ALSA = 1
|
||||
HAVE_DSP_FILTER = 1
|
||||
HAVE_VIDEO_FILTER = 1
|
||||
HAVE_STATIC_VIDEO_FILTERS = 1
|
||||
@@ -121,6 +120,7 @@ DEF_FLAGS += -ffunction-sections -fdata-sections
|
||||
DEF_FLAGS += -I. -Ideps -Ideps/stb -DDINGUX=1 -DDINGUX_BETA=1 -MMD
|
||||
DEF_FLAGS += -Wall -Wno-unused-variable
|
||||
DEF_FLAGS += -std=gnu99 -D_GNU_SOURCE -flto
|
||||
DEF_FLAGS += -lasound
|
||||
LIBS := -ldl -lz -lrt -ludev -pthread
|
||||
CFLAGS :=
|
||||
CXXFLAGS := -fno-exceptions -fno-rtti -std=c++11 -D__STDC_CONSTANT_MACROS
|
||||
@@ -134,6 +134,7 @@ DEFINES += -DHAVE_GETOPT_LONG=1 -DHAVE_STRCASESTR=1 -DHAVE_DYNAMIC=1
|
||||
DEFINES += -DHAVE_AL=1
|
||||
DEFINES += -DHAVE_FILTERS_BUILTIN
|
||||
DEFINES += -DHAVE_UDEV=1
|
||||
DEFINES += -DHAVE_ALSA
|
||||
|
||||
SDL_DINGUX_CFLAGS := $(shell $(GCW0_SDL_CONFIG) --cflags)
|
||||
SDL_DINGUX_LIBS := $(shell $(GCW0_SDL_CONFIG) --libs)
|
||||
@@ -219,7 +220,9 @@ opk: $(TARGET)
|
||||
echo "$$DESKTOP_ENTRY" > default.gcw0.desktop
|
||||
rm -f $(OPK_NAME)
|
||||
cp media/ico_src/icon32.png retroarch.png
|
||||
if [ $$STRIP_BIN -eq 1 ]; then $(STRIP) --strip-unneeded retroarch; fi
|
||||
ifeq ($(STRIP_BIN),1)
|
||||
$(STRIP) --strip-unneeded retroarch
|
||||
endif
|
||||
$(GCW0_MK_SQUASH_FS) retroarch default.gcw0.desktop retroarch.png $(OPK_NAME) -all-root -no-xattrs -noappend -no-exports
|
||||
rm -f default.gcw0.desktop retroarch.png
|
||||
|
||||
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
#########################
|
||||
## Toolchain variables ##
|
||||
#########################
|
||||
|
||||
# Alpha toolchain
|
||||
TOOLCHAIN_DIR=/opt/rs90-toolchain
|
||||
|
||||
# All toolchain-related variables may be
|
||||
# overridden via the command line
|
||||
ifdef GCW0_CC
|
||||
CC = $(GCW0_CC)
|
||||
else
|
||||
CC = $(TOOLCHAIN_DIR)/usr/bin/mipsel-rs90-linux-musl-gcc
|
||||
endif
|
||||
|
||||
ifdef GCW0_CXX
|
||||
CXX = $(GCW0_CXX)
|
||||
else
|
||||
CXX = $(TOOLCHAIN_DIR)/usr/bin/mipsel-rs90-linux-musl-g++
|
||||
endif
|
||||
|
||||
ifdef GCW0_STRIP
|
||||
STRIP = $(GCW0_STRIP)
|
||||
else
|
||||
STRIP = $(TOOLCHAIN_DIR)/usr/bin/mipsel-rs90-linux-musl-strip
|
||||
endif
|
||||
|
||||
GCW0_SDL_CONFIG ?= $(TOOLCHAIN_DIR)/usr/mipsel-rs90-linux-musl/sysroot/usr/bin/sdl-config
|
||||
GCW0_FREETYPE_CONFIG ?= $(TOOLCHAIN_DIR)/usr/mipsel-rs90-linux-musl/sysroot/usr/bin/freetype-config
|
||||
GCW0_MK_SQUASH_FS ?= $(TOOLCHAIN_DIR)/usr/bin/mksquashfs
|
||||
|
||||
GCW0_INC_DIR ?= $(TOOLCHAIN_DIR)/usr/mipsel-rs90-linux-musl/sysroot/usr/include
|
||||
GCW0_LIB_DIR ?= $(TOOLCHAIN_DIR)/usr/mipsel-rs90-linux-musl/sysroot/usr/lib
|
||||
|
||||
#########################
|
||||
#########################
|
||||
|
||||
PACKAGE_NAME = retroarch
|
||||
|
||||
DEBUG ?= 0
|
||||
|
||||
RS90 = 1
|
||||
DINGUX = 1
|
||||
DINGUX_BETA = 1
|
||||
HAVE_SCREENSHOTS = 0
|
||||
HAVE_REWIND = 0
|
||||
HAVE_7ZIP = 1
|
||||
HAVE_AL = 0
|
||||
HAVE_ALSA = 1
|
||||
HAVE_DSP_FILTER = 1
|
||||
HAVE_VIDEO_FILTER = 1
|
||||
HAVE_STATIC_VIDEO_FILTERS = 1
|
||||
HAVE_STATIC_AUDIO_FILTERS = 1
|
||||
HAVE_FILTERS_BUILTIN = 1
|
||||
HAVE_BUILTINMBEDTLS = 0
|
||||
HAVE_BUILTINZLIB = 1
|
||||
HAVE_C99 = 1
|
||||
HAVE_CC = 1
|
||||
HAVE_CC_RESAMPLER = 1
|
||||
|
||||
HAVE_CHD = 0
|
||||
HAVE_COMMAND = 0
|
||||
HAVE_CXX = 1
|
||||
HAVE_DR_MP3 = 0
|
||||
HAVE_DYNAMIC = 1
|
||||
HAVE_EGL = 0
|
||||
HAVE_FREETYPE = 0
|
||||
HAVE_GDI = 0
|
||||
HAVE_GETADDRINFO = 0
|
||||
HAVE_GETOPT_LONG = 1
|
||||
HAVE_GLSL = 0
|
||||
HAVE_HID = 0
|
||||
HAVE_IBXM = 0
|
||||
HAVE_IMAGEVIEWER = 0
|
||||
HAVE_LANGEXTRA = 0
|
||||
HAVE_LIBRETRODB = 1
|
||||
HAVE_MENU = 1
|
||||
HAVE_MENU_COMMON = 1
|
||||
HAVE_GFX_WIDGETS = 0
|
||||
HAVE_MMAP = 1
|
||||
HAVE_OPENDINGUX_FBDEV = 0
|
||||
HAVE_OPENGL = 0
|
||||
HAVE_OPENGL1 = 0
|
||||
HAVE_OPENGLES = 0
|
||||
HAVE_OPENGLES3 = 0
|
||||
HAVE_OPENGL_CORE = 0
|
||||
HAVE_OPENSSL = 0
|
||||
HAVE_OVERLAY = 0
|
||||
HAVE_RBMP = 1
|
||||
HAVE_RJPEG = 1
|
||||
HAVE_RPILED = 0
|
||||
HAVE_RPNG = 1
|
||||
HAVE_RUNAHEAD = 0
|
||||
HAVE_SDL_DINGUX = 1
|
||||
HAVE_SHADERPIPELINE = 0
|
||||
HAVE_STB_FONT = 0
|
||||
HAVE_STB_IMAGE = 0
|
||||
HAVE_STB_VORBIS = 0
|
||||
HAVE_STDIN_CMD = 0
|
||||
HAVE_STRCASESTR = 1
|
||||
HAVE_THREADS = 1
|
||||
HAVE_UDEV = 1
|
||||
HAVE_RGUI = 1
|
||||
HAVE_MATERIALUI = 0
|
||||
HAVE_XMB = 0
|
||||
HAVE_OZONE = 0
|
||||
HAVE_ZLIB = 1
|
||||
HAVE_CONFIGFILE = 1
|
||||
HAVE_PATCH = 1
|
||||
HAVE_CHEATS = 1
|
||||
HAVE_CHEEVOS = 0
|
||||
HAVE_LIBSHAKE = 0
|
||||
HAVE_TINYALSA = 1
|
||||
HAVE_NEAREST_RESAMPLER = 1
|
||||
|
||||
OS = Linux
|
||||
TARGET = retroarch
|
||||
OPK_NAME = retroarch_rs90_odbeta.opk
|
||||
|
||||
OBJ :=
|
||||
LINK := $(CXX)
|
||||
DEF_FLAGS := -mplt -mno-shared
|
||||
DEF_FLAGS += -ffunction-sections -fdata-sections
|
||||
DEF_FLAGS += -I. -Ideps -Ideps/stb -DRS90=1 -DDINGUX=1 -DDINGUX_BETA=1 -MMD
|
||||
DEF_FLAGS += -Wall -Wno-unused-variable
|
||||
DEF_FLAGS += -std=gnu99 -D_GNU_SOURopendinguxCE -flto -lasound
|
||||
LIBS := -ldl -lz -lrt -ludev -pthread
|
||||
CFLAGS :=
|
||||
CXXFLAGS := -fno-exceptions -fno-rtti -std=c++11 -D__STDC_CONSTANT_MACROS
|
||||
ASFLAGS :=
|
||||
LDFLAGS := -Wl,--gc-sections
|
||||
INCLUDE_DIRS = -I$(GCW0_INC_DIR)
|
||||
LIBRARY_DIRS = -L$(GCW0_LIB_DIR)
|
||||
DEFINES := -DRARCH_INTERNAL -D_FILE_OFFSET_BITS=64 -UHAVE_STATIC_DUMMY
|
||||
DEFINES += -DHAVE_C99=1 -DHAVE_CXX=1
|
||||
DEFINES += -DHAVE_GETOPT_LONG=1 -DHAVE_STRCASESTR=1 -DHAVE_DYNAMIC=1
|
||||
DEFINES += -DHAVE_FILTERS_BUILTIN
|
||||
DEFINES += -DHAVE_UDEV=1
|
||||
DEFINES += -DHAVE_ALSA
|
||||
DEFINES += -DCC_RESAMPLER_PRECISION=0
|
||||
|
||||
SDL_DINGUX_CFLAGS := $(shell $(GCW0_SDL_CONFIG) --cflags)
|
||||
SDL_DINGUX_LIBS := $(shell $(GCW0_SDL_CONFIG) --libs)
|
||||
FREETYPE_CFLAGS := $(shell $(GCW0_FREETYPE_CONFIG) --cflags)
|
||||
FREETYPE_LIBS := $(shell $(GCW0_FREETYPE_CONFIG) --libs)
|
||||
MMAP_LIBS = -lc
|
||||
|
||||
OBJDIR_BASE := obj-unix
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
OBJDIR := $(OBJDIR_BASE)/debug
|
||||
DEF_FLAGS += -O0 -g -DDEBUG -D_DEBUG
|
||||
else
|
||||
OBJDIR := $(OBJDIR_BASE)/release
|
||||
DEF_FLAGS += -Ofast -DNDEBUG
|
||||
endif
|
||||
|
||||
include Makefile.common
|
||||
|
||||
DEF_FLAGS += $(INCLUDE_DIRS)
|
||||
LDFLAGS += $(CFLAGS) $(CXXFLAGS) $(DEF_FLAGS)
|
||||
CFLAGS += $(DEF_FLAGS)
|
||||
CXXFLAGS += $(DEF_FLAGS)
|
||||
|
||||
HEADERS = $(wildcard */*/*.h) $(wildcard */*.h) $(wildcard *.h)
|
||||
|
||||
Q := @
|
||||
|
||||
RARCH_OBJ := $(addprefix $(OBJDIR)/,$(OBJ))
|
||||
|
||||
define DESKTOP_ENTRY
|
||||
[Desktop Entry]
|
||||
Name=RetroArch
|
||||
Comment=Frontend for emulators, game engines
|
||||
Exec=retroarch
|
||||
Terminal=false
|
||||
Type=Application
|
||||
StartupNotify=true
|
||||
Icon=retroarch
|
||||
Categories=emulators;
|
||||
X-OD-NeedsDownscaling=true
|
||||
endef
|
||||
export DESKTOP_ENTRY
|
||||
|
||||
all: $(TARGET) opk
|
||||
|
||||
-include $(RARCH_OBJ:.o=.d)
|
||||
|
||||
SYMBOL_MAP := -Wl,-Map=output.map
|
||||
|
||||
$(TARGET): $(RARCH_OBJ)
|
||||
@$(if $(Q), $(shell echo echo LD $@),)
|
||||
$(Q)$(LINK) -o $@ $(RARCH_OBJ) $(LIBS) $(LDFLAGS) $(LIBRARY_DIRS)
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
@mkdir -p $(dir $@)
|
||||
@$(if $(Q), $(shell echo echo CC $<),)
|
||||
$(Q)$(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
@mkdir -p $(dir $@)
|
||||
@$(if $(Q), $(shell echo echo CXX $<),)
|
||||
$(Q)$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(DEFINES) -MMD -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: %.m
|
||||
@mkdir -p $(dir $@)
|
||||
@$(if $(Q), $(shell echo echo OBJC $<),)
|
||||
$(Q)$(CXX) $(OBJCFLAGS) $(DEFINES) -MMD -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: %.S $(HEADERS)
|
||||
@mkdir -p $(dir $@)
|
||||
@$(if $(Q), $(shell echo echo AS $<),)
|
||||
$(Q)$(CC) $(CFLAGS) $(ASFLAGS) $(DEFINES) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJDIR_BASE)
|
||||
rm -f $(TARGET)
|
||||
rm -f *.d
|
||||
rm -rf $(OPK_NAME)
|
||||
|
||||
opk: $(TARGET)
|
||||
echo "$$DESKTOP_ENTRY" > default.rs90.desktop
|
||||
rm -f $(OPK_NAME)
|
||||
cp media/ico_src/icon32.png retroarch.png
|
||||
ifeq ($STRIP_BIN, 1)
|
||||
$(STRIP) --strip-unneeded retroarch
|
||||
endif
|
||||
$(GCW0_MK_SQUASH_FS) retroarch default.rs90.desktop retroarch.png $(OPK_NAME) -all-root -no-xattrs -noappend -no-exports
|
||||
rm -f default.rs90.desktop retroarch.png
|
||||
|
||||
.PHONY: all clean opk
|
||||
|
||||
print-%:
|
||||
@echo '$*=$($*)'
|
||||
+11
-6
@@ -13,7 +13,7 @@ PC_DEVELOPMENT_UDP_PORT =
|
||||
OBJ :=
|
||||
|
||||
SCE_LIBC_SIZE := 4194304
|
||||
DEFINES := -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS
|
||||
DEFINES := -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS -DHAVE_STB_VORBIS
|
||||
INCDIRS :=
|
||||
|
||||
ifeq ($(GRIFFIN_BUILD), 1)
|
||||
@@ -31,7 +31,6 @@ else
|
||||
HAVE_UPDATE_ASSETS := 1
|
||||
HAVE_ONLINE_UPDATER := 1
|
||||
HAVE_NEON := 1
|
||||
HAVE_MATH_NEON := 1
|
||||
HAVE_DSP_FILTER := 1
|
||||
HAVE_VIDEO_FILTER := 1
|
||||
HAVE_SCREENSHOTS := 1
|
||||
@@ -112,17 +111,23 @@ LD := $(CXX)
|
||||
|
||||
LIBDIRS := -L.
|
||||
|
||||
ARCHFLAGS := -march=armv7-a -mfpu=neon -mfloat-abi=hard -DVITA -DSCE_LIBC_SIZE=$(SCE_LIBC_SIZE)
|
||||
CFLAGS += $(ARCHFLAGS) -mword-relocations -fno-optimize-sibling-calls -O2
|
||||
ARCHFLAGS := -march=armv7-a -mfpu=neon -mfloat-abi=hard -DVITA
|
||||
ifeq ($(HAVE_VITAGLES), 1)
|
||||
ARCHFLAGS += -DSCE_LIBC_SIZE=$(SCE_LIBC_SIZE)
|
||||
endif
|
||||
|
||||
CFLAGS += $(ARCHFLAGS) -mword-relocations -fno-optimize-sibling-calls
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
CFLAGS += -g
|
||||
CFLAGS += -g -Og
|
||||
else
|
||||
CFLAGS += -O2
|
||||
endif
|
||||
|
||||
ASFLAGS := $(CFLAGS)
|
||||
LDFLAGS := -Wl,-q
|
||||
|
||||
CFLAGS += -Wall -ffast-math -g
|
||||
CFLAGS += -Wall -ffast-math
|
||||
CFLAGS += -DRARCH_INTERNAL -DHAVE_SCREENSHOTS -DRARCH_CONSOLE
|
||||
CFLAGS += -DHAVE_DSP_FILTER
|
||||
CFLAGS += -DHAVE_VIDEO_FILTER
|
||||
|
||||
+242
@@ -0,0 +1,242 @@
|
||||
include version.all
|
||||
|
||||
$(call assert,$(call seq,$(TARGET_PREFIX),arm-webos-linux-gnueabi-),webOS SDK isn't setup properly. See https://github.com/webosbrew/meta-lg-webos-ndk#compile-program-by-command-line)
|
||||
|
||||
WEBOS_FREETYPE_CONFIG ?= $(SDKTARGETSYSROOT)/usr/bin/freetype-config
|
||||
|
||||
WEBOS_INC_DIR ?= $(SDKTARGETSYSROOT)/usr/include
|
||||
WEBOS_LIB_DIR ?= $(SDKTARGETSYSROOT)/usr/lib
|
||||
|
||||
#########################
|
||||
#########################
|
||||
|
||||
PACKAGE_NAME = com.retroarch
|
||||
PACKAGE_VERSION := $(patsubst "%",%,$(RARCH_VERSION))
|
||||
|
||||
DEBUG ?= 0
|
||||
|
||||
HAVE_SCREENSHOTS = 0
|
||||
HAVE_REWIND = 1
|
||||
HAVE_7ZIP = 1
|
||||
HAVE_ACCESSIBILITY = 1
|
||||
HAVE_AL = 0
|
||||
# ALSA freezes when switching back from menu
|
||||
HAVE_ALSA = 0
|
||||
HAVE_ANGLE = 0
|
||||
HAVE_AUDIOIO = 0
|
||||
HAVE_AUDIOMIXER = 1
|
||||
HAVE_BLISSBOX = 0
|
||||
HAVE_BSV_MOVIE = 1
|
||||
HAVE_BUILTINBEARSSL = 0
|
||||
HAVE_BUILTINFLAC = 1
|
||||
HAVE_DSP_FILTER = 1
|
||||
HAVE_VIDEO_FILTER = 1
|
||||
HAVE_STATIC_VIDEO_FILTERS = 1
|
||||
HAVE_STATIC_AUDIO_FILTERS = 1
|
||||
HAVE_FILTERS_BUILTIN = 1
|
||||
HAVE_BUILTINMBEDTLS = 1
|
||||
HAVE_BUILTINZLIB = 1
|
||||
HAVE_C99 = 1
|
||||
HAVE_CC = 1
|
||||
HAVE_CC_RESAMPLER = 1
|
||||
HAVE_NEAREST_RESAMPLER = 1
|
||||
HAVE_CHD = 1
|
||||
HAVE_COMMAND = 1
|
||||
HAVE_CXX = 1
|
||||
HAVE_DR_MP3 = 1
|
||||
HAVE_DYNAMIC = 1
|
||||
HAVE_DYLIB = 1
|
||||
HAVE_EGL = 0
|
||||
HAVE_FREETYPE = 0
|
||||
HAVE_GDI = 1
|
||||
HAVE_GETADDRINFO = 1
|
||||
HAVE_GETOPT_LONG = 1
|
||||
HAVE_GLSL = 1
|
||||
HAVE_GLSLANG = 0
|
||||
HAVE_GLSLANG_HLSL = 0
|
||||
HAVE_GLSLANG_OGLCOMPILER = 0
|
||||
HAVE_GLSLANG_OSDEPENDENT = 0
|
||||
HAVE_GLSLANG_SPIRV = 0
|
||||
HAVE_GLSLANG_SPIRV_TOOLS = 0
|
||||
HAVE_GLSLANG_SPIRV_TOOLS_OPT = 0
|
||||
HAVE_HID = 1
|
||||
HAVE_IBXM = 1
|
||||
HAVE_IMAGEVIEWER = 1
|
||||
HAVE_LANGEXTRA = 1
|
||||
HAVE_LIBRETRODB = 1
|
||||
HAVE_MENU = 1
|
||||
HAVE_MENU_COMMON = 1
|
||||
HAVE_NEON = 1
|
||||
HAVE_NETPLAYDISCOVERY = 1
|
||||
HAVE_NETPLAYDISCOVERY = 1
|
||||
HAVE_NETWORK_CMD = 1
|
||||
HAVE_NETWORKGAMEPAD = 1
|
||||
HAVE_NETWORKING = 1
|
||||
HAVE_GFX_WIDGETS = 1
|
||||
HAVE_MMAP = 1
|
||||
HAVE_ONLINE_UPDATER = 1
|
||||
HAVE_OPENDINGUX_FBDEV = 0
|
||||
HAVE_OPENGL = 0
|
||||
HAVE_OPENGL1 = 0
|
||||
HAVE_OPENGL_CORE = 0
|
||||
HAVE_OPENGLES = 1
|
||||
HAVE_OPENGLES3 = 0
|
||||
HAVE_OPENGLES3_1 = 0
|
||||
HAVE_OPENGLES3_2 = 0
|
||||
HAVE_OPENSSL = 0
|
||||
HAVE_OVERLAY = 1
|
||||
HAVE_PULSE = 1
|
||||
HAVE_RBMP = 1
|
||||
HAVE_RJPEG = 1
|
||||
HAVE_RPILED = 0
|
||||
HAVE_RPNG = 1
|
||||
HAVE_RUNAHEAD = 1
|
||||
HAVE_SDL = 0
|
||||
HAVE_SDL2 = 1
|
||||
HAVE_SHADERPIPELINE = 1
|
||||
HAVE_STB_FONT = 1
|
||||
HAVE_STB_IMAGE = 1
|
||||
HAVE_STB_VORBIS = 1
|
||||
HAVE_STDIN_CMD = 0
|
||||
HAVE_STRCASESTR = 1
|
||||
HAVE_THREADS = 1
|
||||
HAVE_UDEV = 0
|
||||
HAVE_RGUI = 1
|
||||
HAVE_MATERIALUI = 0
|
||||
HAVE_XMB = 1
|
||||
HAVE_OZONE = 1
|
||||
HAVE_ZLIB = 1
|
||||
HAVE_CONFIGFILE = 1
|
||||
HAVE_PATCH = 1
|
||||
HAVE_CHEATS = 1
|
||||
HAVE_CHEEVOS = 1
|
||||
HAVE_LIBSHAKE = 1
|
||||
HAVE_UPDATE_ASSETS = 1
|
||||
HAVE_UPDATE_CORES = 1
|
||||
|
||||
OS = Linux
|
||||
TARGET = retroarch
|
||||
|
||||
OBJ :=
|
||||
LINK := $(CXX)
|
||||
DEF_FLAGS += -ffunction-sections -fdata-sections
|
||||
DEF_FLAGS += -I. -Ideps -Ideps/stb -DWEBOS=1 -MMD
|
||||
DEF_FLAGS += -Wall -Wno-unused-variable
|
||||
LIBS := -ldl -lz -lrt -pthread
|
||||
CFLAGS :=
|
||||
CXXFLAGS := -fno-exceptions -fno-rtti -std=c++11 -D__STDC_CONSTANT_MACROS
|
||||
ASFLAGS :=
|
||||
LDFLAGS := -Wl,--gc-sections
|
||||
INCLUDE_DIRS = -I$(WEBOS_INC_DIR)
|
||||
LIBRARY_DIRS = -L$(WEBOS_LIB_DIR)
|
||||
DEFINES := -DRARCH_INTERNAL -D_FILE_OFFSET_BITS=64 -UHAVE_STATIC_DUMMY
|
||||
DEFINES += -DHAVE_C99=1 -DHAVE_CXX=1 -D_GNU_SOURCE
|
||||
DEFINES += -DHAVE_GETOPT_LONG=1 -DHAVE_STRCASESTR=1 -DHAVE_DYNAMIC=1
|
||||
DEFINES += -DHAVE_FILTERS_BUILTIN
|
||||
DEFINES += -DHAVE_SDL2
|
||||
DEFINES += -DHAVE_PULSE
|
||||
DEFINES += -DHAVE_NETWORKING -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS -DHAVE_UPDATE_CORES
|
||||
|
||||
SDL2_CFLAGS := $(shell pkg-config --cflags sdl2)
|
||||
SDL2_LIBS := $(shell pkg-config --libs sdl2)
|
||||
OPENGLES_LIBS = -lGLESv2
|
||||
PULSE_LIBS = $(shell pkg-config --libs libpulse)
|
||||
MMAP_LIBS = -lc
|
||||
NEON_CFLAGS = -mfpu=neon
|
||||
NEON_ASFLAGS = -mfpu=neon
|
||||
NETWORKING_LIBS = -lc
|
||||
|
||||
OBJDIR_BASE := obj-unix
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
OBJDIR := $(OBJDIR_BASE)/debug
|
||||
DEF_FLAGS += -O0 -g -DDEBUG -D_DEBUG
|
||||
else
|
||||
OBJDIR := $(OBJDIR_BASE)/release
|
||||
DEF_FLAGS += -O2 -DNDEBUG
|
||||
endif
|
||||
|
||||
include Makefile.common
|
||||
|
||||
DEF_FLAGS += $(INCLUDE_DIRS)
|
||||
LDFLAGS += $(CFLAGS) $(CXXFLAGS) $(DEF_FLAGS)
|
||||
CFLAGS += $(DEF_FLAGS)
|
||||
CXXFLAGS += $(DEF_FLAGS)
|
||||
|
||||
HEADERS = $(wildcard */*/*.h) $(wildcard */*.h) $(wildcard *.h)
|
||||
|
||||
Q := @
|
||||
|
||||
RARCH_OBJ := $(addprefix $(OBJDIR)/,$(OBJ))
|
||||
|
||||
define APPINFO
|
||||
{
|
||||
"id": "$(PACKAGE_NAME)",
|
||||
"version": "$(PACKAGE_VERSION)",
|
||||
"vendor": "webosbrew.org",
|
||||
"title": "RetroArch",
|
||||
"icon": "icon160.png",
|
||||
"main": "retroarch",
|
||||
"iconColor": "#333333",
|
||||
"type": "native",
|
||||
"appDescription": "Emulation frontend"
|
||||
}
|
||||
endef
|
||||
export APPINFO
|
||||
|
||||
all: $(TARGET) ipk
|
||||
|
||||
-include $(RARCH_OBJ:.o=.d)
|
||||
|
||||
SYMBOL_MAP := -Wl,-Map=output.map
|
||||
|
||||
$(TARGET): $(RARCH_OBJ)
|
||||
@$(if $(Q), $(shell echo echo LD $@),)
|
||||
$(Q)$(LINK) -o $@ $(RARCH_OBJ) $(LIBS) $(LDFLAGS) $(LIBRARY_DIRS)
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
@mkdir -p $(dir $@)
|
||||
@$(if $(Q), $(shell echo echo CC $<),)
|
||||
$(Q)$(CC) $(CPPFLAGS) $(CFLAGS) $(DEFINES) -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
@mkdir -p $(dir $@)
|
||||
@$(if $(Q), $(shell echo echo CXX $<),)
|
||||
$(Q)$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(DEFINES) -MMD -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: %.m
|
||||
@mkdir -p $(dir $@)
|
||||
@$(if $(Q), $(shell echo echo OBJC $<),)
|
||||
$(Q)$(CXX) $(OBJCFLAGS) $(DEFINES) -MMD -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: %.S $(HEADERS)
|
||||
@mkdir -p $(dir $@)
|
||||
@$(if $(Q), $(shell echo echo AS $<),)
|
||||
$(Q)$(CC) $(CFLAGS) $(ASFLAGS) $(DEFINES) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJDIR_BASE)
|
||||
rm -f $(TARGET)
|
||||
rm -f *.d
|
||||
rm -rf webos/*.ipk
|
||||
rm -rf webos/dist
|
||||
|
||||
ipk: $(TARGET)
|
||||
rm -rf webos/dist
|
||||
mkdir -p webos/dist/lib
|
||||
echo "$$APPINFO" > webos/dist/appinfo.json
|
||||
cp -t webos/dist -vf $(TARGET) webos/icon160.png
|
||||
cp -t webos/dist/lib -vf $(WEBOS_LIB_DIR)/libstdc++.so.6
|
||||
$(STRIP) webos/dist/$(TARGET)
|
||||
cd webos && ares-package dist
|
||||
|
||||
install: ipk
|
||||
ares-install webos/$(PACKAGE_NAME)_$(PACKAGE_VERSION)_$(ARCH).ipk
|
||||
|
||||
launch: install
|
||||
ares-launch com.retroarch
|
||||
|
||||
.PHONY: all clean ipk
|
||||
|
||||
print-%:
|
||||
@echo '$*=$($*)'
|
||||
+2
-2
@@ -131,7 +131,7 @@ RARCH_CONSOLE = 1
|
||||
#HAVE_LANGEXTRA := 1
|
||||
HAVE_WIIUSB_HID := 1
|
||||
HAVE_RARCH_EXEC := 1
|
||||
HAVE_RSOUND := 1
|
||||
HAVE_RSOUND := 0
|
||||
|
||||
APP_BOOTER_DIR = wii/app_booter
|
||||
PLATOBJS := $(APP_BOOTER_DIR)/app_booter.binobj
|
||||
@@ -222,7 +222,7 @@ ifeq ($(HAVE_RUNAHEAD), 1)
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_7ZIP), 1)
|
||||
CFLAGS += -DHAVE_7ZIP
|
||||
CFLAGS += -DHAVE_7ZIP -D_7ZIP_ST
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_SCREENSHOTS), 1)
|
||||
|
||||
+15
-5
@@ -11,6 +11,7 @@ HAVE_RUNAHEAD = 1
|
||||
WIIU_LOG_RPX = 0
|
||||
BUILD_DIR = objs/wiiu
|
||||
PC_DEVELOPMENT_TCP_PORT ?=
|
||||
LOAD_WITHOUT_CORE_INFO ?= 0
|
||||
|
||||
ifeq ($(SALAMANDER_BUILD),1)
|
||||
BUILD_DIR := $(BUILD_DIR)-salamander
|
||||
@@ -85,6 +86,9 @@ else
|
||||
ifeq ($(HAVE_RUNAHEAD),1)
|
||||
DEFINES += -DHAVE_RUNAHEAD
|
||||
endif
|
||||
ifeq ($(LOAD_WITHOUT_CORE_INFO),1)
|
||||
DEFINES += -DLOAD_WITHOUT_CORE_INFO
|
||||
endif
|
||||
|
||||
OBJ += wiiu/shader_utils.o
|
||||
OBJ += gfx/drivers/gx2_shaders/tex.o
|
||||
@@ -102,7 +106,7 @@ endif
|
||||
|
||||
INCDIRS += -Ilibretro-common/include/compat/zlib
|
||||
# for stb, libfat, iosuhax
|
||||
INCDIRS += -Ideps -Ideps/libfat/include -Ideps/libiosuhax
|
||||
INCDIRS += -Ideps -Ideps/libfat/include -Ideps/libiosuhax/include
|
||||
# pad_functions uses wiiu/input.h
|
||||
INCDIRS += -Iinput/include
|
||||
INCDIRS += -Ideps/SPIRV-Cross
|
||||
@@ -327,17 +331,23 @@ $(BUILD_DIR)/$(TARGET).rpx.elf: $(OBJ) $(RPX_OBJ) libretro_wiiu.a wiiu/link_elf.
|
||||
@$(if $(Q), echo LD $@,)
|
||||
$(Q)$(LD) $(OBJ) $(RPX_OBJ) $(LDFLAGS) $(RPX_LDFLAGS) $(LIBDIRS) $(LIBS) -o $@
|
||||
|
||||
$(BUILD_DIR)/$(TARGET).rpx: $(BUILD_DIR)/$(TARGET).rpx.elf $(ELF2RPL) .$(TARGET).rpx.last
|
||||
$(BUILD_DIR)/$(TARGET).large.rpx: $(BUILD_DIR)/$(TARGET).rpx.elf $(ELF2RPL) .$(TARGET).rpx.large.last
|
||||
@$(if $(Q), echo ELF2RPL $@,)
|
||||
@touch .$(TARGET).rpx.last
|
||||
@touch .$(TARGET).rpx.large.last
|
||||
$(Q)-$(ELF2RPL) $< $@
|
||||
|
||||
$(BUILD_DIR)/$(TARGET).rpx: $(BUILD_DIR)/$(TARGET).large.rpx .$(TARGET).rpx.last
|
||||
@$(if $(Q), echo COMPRESS $@,)
|
||||
@touch .$(TARGET).rpx.large.last
|
||||
$(Q)wiiurpxtool -c $< $@
|
||||
|
||||
clean:
|
||||
@$(if $(Q), echo $@,)
|
||||
$(Q)rm -f $(OBJ) $(RPX_OBJ) $(HBL_ELF_OBJ) $(TARGET).elf $(TARGET).rpx.elf $(TARGET).rpx
|
||||
$(Q)rm -f $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).rpx.elf $(BUILD_DIR)/$(TARGET).rpx
|
||||
$(Q)rm -f .$(TARGET).elf.last .$(TARGET).rpx.elf.last .$(TARGET).rpx.last
|
||||
$(Q)rm -f $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).rpx.elf $(BUILD_DIR)/$(TARGET).large.rpx $(BUILD_DIR)/$(TARGET).rpx
|
||||
$(Q)rm -f .$(TARGET).elf.last .$(TARGET).rpx.elf.last .$(TARGET).rpx.large.last .$(TARGET).rpx.last
|
||||
$(Q)rm -f $(OBJ:.o=.depend) $(RPX_OBJ:.o=.depend) $(HBL_ELF_OBJ:.o=.depend)
|
||||
$(Q)$(MAKE) -C wiiu/wut/elf2rpl/ clean
|
||||
|
||||
.PHONY: clean all
|
||||
.PRECIOUS: %.depend %.last
|
||||
|
||||
@@ -546,7 +546,8 @@ static ssize_t dsound_write(void *data, const void *buf_, size_t size)
|
||||
break;
|
||||
|
||||
if (avail == 0)
|
||||
WaitForSingleObject(ds->event, INFINITE);
|
||||
if (!(WaitForSingleObject(ds->event, 50) == WAIT_OBJECT_0))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <retro_inline.h>
|
||||
|
||||
#include "../../retroarch.h"
|
||||
#include "../../defines/gx_defines.h"
|
||||
#include <defines/gx_defines.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#include "../../retroarch.h"
|
||||
|
||||
#include "../../defines/ps3_defines.h"
|
||||
#include <defines/ps3_defines.h>
|
||||
|
||||
#define AUDIO_BLOCKS 8
|
||||
#define AUDIO_CHANNELS 2
|
||||
|
||||
@@ -49,7 +49,7 @@ static void *rwebaudio_init(const char *device, unsigned rate, unsigned latency,
|
||||
rweb_audio_t *rwebaudio = (rweb_audio_t*)calloc(1, sizeof(rweb_audio_t));
|
||||
if (!rwebaudio)
|
||||
return NULL;
|
||||
if (RWebAudioInit(latency) == 1)
|
||||
if (RWebAudioInit(latency))
|
||||
*new_rate = RWebAudioSampleRate();
|
||||
return rwebaudio;
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ static void *libnx_audren_thread_audio_init(const char *device, unsigned rate, u
|
||||
int mpid;
|
||||
size_t mempool_size;
|
||||
unsigned real_latency;
|
||||
uint32_t thread_priority;
|
||||
int32_t thread_priority;
|
||||
|
||||
RARCH_LOG("[Audio]: Using libnx_audren_thread driver\n");
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ static void *switch_thread_audio_init(const char *device, unsigned rate, unsigne
|
||||
{
|
||||
Result rc;
|
||||
unsigned i;
|
||||
uint32_t prio;
|
||||
int32_t prio;
|
||||
#ifndef HAVE_LIBNX
|
||||
char names[8][0x20];
|
||||
uint32_t num_names = 0;
|
||||
|
||||
@@ -736,7 +736,7 @@ static ssize_t wasapi_write_ex(wasapi_t *w, const void * data, size_t size, DWOR
|
||||
if (!write_avail)
|
||||
{
|
||||
if (WaitForSingleObject(w->write_event, ms) != WAIT_OBJECT_0)
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
if (!wasapi_flush_buffer(w, w->engine_buffer_size))
|
||||
return -1;
|
||||
|
||||
@@ -371,7 +371,8 @@ static ssize_t xa_write(void *data, const void *buf, size_t size)
|
||||
XAUDIO2_BUFFER xa2buffer;
|
||||
|
||||
while (handle->buffers == MAX_BUFFERS - 1)
|
||||
WaitForSingleObject(handle->hEvent, INFINITE);
|
||||
if (!(WaitForSingleObject(handle->hEvent, 50) == WAIT_OBJECT_0))
|
||||
return -1;
|
||||
|
||||
xa2buffer.Flags = 0;
|
||||
xa2buffer.AudioBytes = handle->bufsize;
|
||||
|
||||
@@ -29,9 +29,9 @@
|
||||
|
||||
#include <audio/audio_resampler.h>
|
||||
|
||||
#if (defined(__ARM_NEON__) && !defined(DONT_WANT_ARM_OPTIMIZATIONS)) || defined(HAVE_NEON)
|
||||
#ifndef HAVE_ARM_NEON_OPTIMIZATIONS
|
||||
#define HAVE_ARM_NEON_OPTIMIZATIONS
|
||||
#if (defined(__ARM_NEON__) && !defined(DONT_WANT_ARM_ASM_OPTIMIZATIONS)) || defined(HAVE_NEON)
|
||||
#ifndef HAVE_ARM_NEON_ASM_OPTIMIZATIONS
|
||||
#define HAVE_ARM_NEON_ASM_OPTIMIZATIONS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -350,7 +350,7 @@ static void resampler_CC_upsample(void *re_, struct resampler_data *data)
|
||||
data->output_frames = outp - (audio_frame_float_t*)data->data_out;
|
||||
}
|
||||
|
||||
#elif defined(HAVE_ARM_NEON_OPTIMIZATIONS)
|
||||
#elif defined(HAVE_ARM_NEON_ASM_OPTIMIZATIONS)
|
||||
|
||||
#define CC_RESAMPLER_IDENT "NEON"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include <errno.h>
|
||||
#include <reent.h>
|
||||
#include "../../defines/psp_defines.h"
|
||||
#include <defines/psp_defines.h>
|
||||
#include <psp2/kernel/sysmem.h>
|
||||
#include <psp2/kernel/threadmgr.h>
|
||||
|
||||
@@ -15,6 +15,8 @@ static int _newlib_vm_memblock;
|
||||
extern int _newlib_heap_size_user __attribute__((weak));
|
||||
extern int _newlib_vm_size_user __attribute__((weak));
|
||||
|
||||
#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
|
||||
|
||||
void * _sbrk_r(struct _reent *reent, ptrdiff_t incr) {
|
||||
if (sceKernelLockLwMutex((struct SceKernelLwMutexWork*)_newlib_sbrk_mutex, 1, 0) < 0)
|
||||
goto fail;
|
||||
@@ -36,8 +38,8 @@ void _init_vita_heap(void) {
|
||||
|
||||
int _newlib_vm_size = 0;
|
||||
if (&_newlib_vm_size_user != NULL) {
|
||||
_newlib_vm_size = _newlib_vm_size_user;
|
||||
_newlib_vm_memblock = sceKernelAllocMemBlockForVM("code", _newlib_vm_size_user);
|
||||
_newlib_vm_size = ALIGN(_newlib_vm_size_user, 0x100000);
|
||||
_newlib_vm_memblock = sceKernelAllocMemBlockForVM("code", _newlib_vm_size);
|
||||
|
||||
if (_newlib_vm_memblock < 0){
|
||||
//sceClibPrintf("sceKernelAllocMemBlockForVM failed\n");
|
||||
|
||||
+16
-18
@@ -140,7 +140,6 @@ bool cheat_manager_save(
|
||||
{
|
||||
bool ret;
|
||||
unsigned i;
|
||||
char buf[PATH_MAX_LENGTH];
|
||||
char cheats_file[PATH_MAX_LENGTH];
|
||||
config_file_t *conf = NULL;
|
||||
cheat_manager_t *cheat_st = &cheat_manager_state;
|
||||
@@ -164,7 +163,7 @@ bool cheat_manager_save(
|
||||
(char*)"cheat%u_repeat_add_to_address"
|
||||
};
|
||||
|
||||
buf[0] = cheats_file[0] = '\0';
|
||||
cheats_file[0] = '\0';
|
||||
|
||||
if (!cheat_st->cheats || cheat_st->size == 0)
|
||||
return false;
|
||||
@@ -172,11 +171,10 @@ bool cheat_manager_save(
|
||||
if (!cheat_database)
|
||||
strlcpy(cheats_file, path, sizeof(cheats_file));
|
||||
else
|
||||
{
|
||||
fill_pathname_join(buf, cheat_database, path, sizeof(buf));
|
||||
|
||||
fill_pathname_noext(cheats_file, buf, ".cht", sizeof(cheats_file));
|
||||
}
|
||||
fill_pathname_join_concat(cheats_file,
|
||||
cheat_database, path,
|
||||
".cht",
|
||||
sizeof(cheats_file));
|
||||
|
||||
if (!overwrite)
|
||||
conf = config_file_new_from_path_to_string(cheats_file);
|
||||
@@ -705,7 +703,7 @@ static bool cheat_manager_get_game_specific_filename(
|
||||
return false;
|
||||
|
||||
core_name = system_info.library_name;
|
||||
game_name = path_basename(global->name.cheatfile);
|
||||
game_name = path_basename_nocompression(global->name.cheatfile);
|
||||
|
||||
if (string_is_empty(path_cheat_database) ||
|
||||
string_is_empty(core_name) ||
|
||||
@@ -739,8 +737,8 @@ void cheat_manager_load_game_specific_cheats(const char *path_cheat_database)
|
||||
path_cheat_database,
|
||||
false))
|
||||
{
|
||||
RARCH_LOG("[Cheats]: Load game-specific cheatfile: %s\n", cheat_file);
|
||||
cheat_manager_load(cheat_file, true);
|
||||
if (cheat_manager_load(cheat_file, true))
|
||||
RARCH_LOG("[Cheats]: Load game-specific cheatfile: %s\n", cheat_file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -753,8 +751,8 @@ void cheat_manager_save_game_specific_cheats(const char *path_cheat_database)
|
||||
path_cheat_database,
|
||||
true))
|
||||
{
|
||||
RARCH_LOG("[Cheats]: Save game-specific cheatfile: %s\n", cheat_file);
|
||||
cheat_manager_save(cheat_file, NULL, true);
|
||||
if (cheat_manager_save(cheat_file, NULL, true))
|
||||
RARCH_LOG("[Cheats]: Save game-specific cheatfile: %s\n", cheat_file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1343,8 +1341,8 @@ void cheat_manager_apply_rumble(struct item_cheat *cheat, unsigned int curr_valu
|
||||
{
|
||||
cheat->rumble_primary_end_time = current_time + (cheat->rumble_primary_duration * 1000);
|
||||
cheat->rumble_secondary_end_time = current_time + (cheat->rumble_secondary_duration * 1000);
|
||||
input_driver_set_rumble_state(cheat->rumble_port, RETRO_RUMBLE_STRONG, cheat->rumble_primary_strength);
|
||||
input_driver_set_rumble_state(cheat->rumble_port, RETRO_RUMBLE_WEAK, cheat->rumble_secondary_strength);
|
||||
input_set_rumble_state(cheat->rumble_port, RETRO_RUMBLE_STRONG, cheat->rumble_primary_strength);
|
||||
input_set_rumble_state(cheat->rumble_port, RETRO_RUMBLE_WEAK, cheat->rumble_secondary_strength);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1356,24 +1354,24 @@ void cheat_manager_apply_rumble(struct item_cheat *cheat, unsigned int curr_valu
|
||||
if (cheat->rumble_primary_end_time <= current_time)
|
||||
{
|
||||
if (cheat->rumble_primary_end_time != 0)
|
||||
input_driver_set_rumble_state(cheat->rumble_port,
|
||||
input_set_rumble_state(cheat->rumble_port,
|
||||
RETRO_RUMBLE_STRONG, 0);
|
||||
cheat->rumble_primary_end_time = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
input_driver_set_rumble_state(cheat->rumble_port,
|
||||
input_set_rumble_state(cheat->rumble_port,
|
||||
RETRO_RUMBLE_STRONG, cheat->rumble_primary_strength);
|
||||
}
|
||||
|
||||
if (cheat->rumble_secondary_end_time <= current_time)
|
||||
{
|
||||
if (cheat->rumble_secondary_end_time != 0)
|
||||
input_driver_set_rumble_state(cheat->rumble_port, RETRO_RUMBLE_WEAK, 0);
|
||||
input_set_rumble_state(cheat->rumble_port, RETRO_RUMBLE_WEAK, 0);
|
||||
cheat->rumble_secondary_end_time = 0;
|
||||
}
|
||||
else
|
||||
input_driver_set_rumble_state(cheat->rumble_port, RETRO_RUMBLE_WEAK, cheat->rumble_secondary_strength);
|
||||
input_set_rumble_state(cheat->rumble_port, RETRO_RUMBLE_WEAK, cheat->rumble_secondary_strength);
|
||||
}
|
||||
|
||||
void cheat_manager_apply_retro_cheats(void)
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2016 - Andre Leiradella
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <file/file_path.h>
|
||||
|
||||
#include "../file_path_special.h"
|
||||
#include "../configuration.h"
|
||||
#include "../gfx/gfx_display.h"
|
||||
|
||||
#include "badges.h"
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
|
||||
#define CHEEVOS_MENU_BADGE_LIMIT 256
|
||||
/* TODO/FIXME - public global variables */
|
||||
static uintptr_t cheevos_badge_menu_texture_list[CHEEVOS_MENU_BADGE_LIMIT] = { 0 };
|
||||
|
||||
void cheevos_reset_menu_badges(void)
|
||||
{
|
||||
int index;
|
||||
for (index = 0; index < CHEEVOS_MENU_BADGE_LIMIT; ++index)
|
||||
{
|
||||
if (cheevos_badge_menu_texture_list[index])
|
||||
video_driver_texture_unload(&cheevos_badge_menu_texture_list[index]);
|
||||
}
|
||||
|
||||
memset(&cheevos_badge_menu_texture_list, 0,
|
||||
sizeof(cheevos_badge_menu_texture_list));
|
||||
}
|
||||
|
||||
void cheevos_set_menu_badge(int index, const char *badge, bool locked)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
|
||||
if (index >= CHEEVOS_MENU_BADGE_LIMIT)
|
||||
return;
|
||||
|
||||
if (!settings || !settings->bools.cheevos_badges_enable)
|
||||
cheevos_badge_menu_texture_list[index] = 0;
|
||||
else
|
||||
cheevos_badge_menu_texture_list[index] =
|
||||
cheevos_get_badge_texture(badge, locked);
|
||||
}
|
||||
|
||||
uintptr_t cheevos_get_menu_badge_texture(int index)
|
||||
{
|
||||
if (index < CHEEVOS_MENU_BADGE_LIMIT)
|
||||
return cheevos_badge_menu_texture_list[index];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
uintptr_t cheevos_get_badge_texture(const char *badge, bool locked)
|
||||
{
|
||||
char badge_file[24];
|
||||
char fullpath[PATH_MAX_LENGTH];
|
||||
uintptr_t tex = 0;
|
||||
|
||||
if (!badge)
|
||||
return 0;
|
||||
|
||||
fullpath[0] = badge_file[0] = '\0';
|
||||
|
||||
strlcpy(badge_file, badge, sizeof(badge_file));
|
||||
if (locked)
|
||||
strlcat(badge_file, "_lock", sizeof(badge_file));
|
||||
strlcat(badge_file, FILE_PATH_PNG_EXTENSION, sizeof(badge_file));
|
||||
|
||||
fill_pathname_application_special(fullpath, sizeof(fullpath),
|
||||
APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_CHEEVOS_BADGES);
|
||||
|
||||
if (!gfx_display_reset_textures_list(badge_file, fullpath,
|
||||
&tex, TEXTURE_FILTER_MIPMAP_LINEAR, NULL, NULL))
|
||||
tex = 0;
|
||||
|
||||
return tex;
|
||||
}
|
||||
+369
-1132
File diff suppressed because it is too large.
Load diff
+8
-33
@@ -21,64 +21,39 @@
|
||||
|
||||
#include <boolean.h>
|
||||
|
||||
#include "../verbosity.h"
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
typedef struct rcheevos_ctx_desc
|
||||
{
|
||||
unsigned idx;
|
||||
char *s;
|
||||
size_t len;
|
||||
} rcheevos_ctx_desc_t;
|
||||
|
||||
enum
|
||||
{
|
||||
RCHEEVOS_ACTIVE_SOFTCORE = 1 << 0,
|
||||
RCHEEVOS_ACTIVE_HARDCORE = 1 << 1,
|
||||
RCHEEVOS_ACTIVE_UNOFFICIAL = 1 << 2
|
||||
};
|
||||
|
||||
bool rcheevos_load(const void *data);
|
||||
size_t rcheevos_get_serialize_size(void);
|
||||
bool rcheevos_get_serialized_data(void* buffer);
|
||||
bool rcheevos_set_serialized_data(void* buffer);
|
||||
|
||||
void rcheevos_reset_game(bool widgets_ready);
|
||||
|
||||
void rcheevos_populate_menu(void* data);
|
||||
void rcheevos_populate_hardcore_pause_menu(void* data);
|
||||
void rcheevos_get_achievement_state(unsigned index, char* buffer, size_t buffer_size);
|
||||
|
||||
bool rcheevos_get_description(rcheevos_ctx_desc_t *desc);
|
||||
|
||||
void rcheevos_pause_hardcore(void);
|
||||
|
||||
bool rcheevos_unload(void);
|
||||
|
||||
void rcheevos_test(void);
|
||||
|
||||
void rcheevos_reset_game(bool widgets_ready);
|
||||
|
||||
void rcheevos_pause_hardcore(void);
|
||||
void rcheevos_hardcore_enabled_changed(void);
|
||||
void rcheevos_toggle_hardcore_paused(void);
|
||||
bool rcheevos_hardcore_active(void);
|
||||
|
||||
void rcheevos_validate_config_settings(void);
|
||||
|
||||
void rcheevos_leaderboards_enabled_changed(void);
|
||||
|
||||
void rcheevos_test(void);
|
||||
|
||||
void rcheevos_set_support_cheevos(bool state);
|
||||
|
||||
bool rcheevos_get_support_cheevos(void);
|
||||
|
||||
const char* rcheevos_get_hash(void);
|
||||
|
||||
const char *rcheevos_get_richpresence(void);
|
||||
int rcheevos_get_richpresence(char buffer[], int buffer_size);
|
||||
uintptr_t rcheevos_get_badge_texture(const char *badge, bool locked);
|
||||
|
||||
uint8_t* rcheevos_patch_address(unsigned address);
|
||||
|
||||
bool rcheevos_hardcore_active(void);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif /* __RARCH_CHEEVOS_CHEEVOS_H */
|
||||
@@ -0,0 +1,675 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2019-2021 - Brian Weiss
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "cheevos_client.h"
|
||||
|
||||
#include "cheevos.h"
|
||||
|
||||
#include "../configuration.h"
|
||||
#include "../paths.h"
|
||||
#include "../version.h"
|
||||
|
||||
#include <string/stdstring.h>
|
||||
#include <features/features_cpu.h>
|
||||
|
||||
#include "../frontend/frontend_driver.h"
|
||||
#include "../network/net_http_special.h"
|
||||
#include "../tasks/tasks_internal.h"
|
||||
|
||||
#ifdef HAVE_DISCORD
|
||||
#include "../network/discord.h"
|
||||
#endif
|
||||
|
||||
#include "../deps/rcheevos/include/rc_api_runtime.h"
|
||||
|
||||
|
||||
|
||||
/* Define this macro to log URLs. */
|
||||
#undef CHEEVOS_LOG_URLS
|
||||
|
||||
/* Define this macro to have the password and token logged.
|
||||
* THIS WILL DISCLOSE THE USER'S PASSWORD, TAKE CARE! */
|
||||
#undef CHEEVOS_LOG_PASSWORD
|
||||
|
||||
|
||||
/* Number of usecs to wait between posting rich presence to the site. */
|
||||
/* Keep consistent with SERVER_PING_FREQUENCY from RAIntegration. */
|
||||
#define CHEEVOS_PING_FREQUENCY 2 * 60 * 1000000
|
||||
|
||||
|
||||
/****************************
|
||||
* data types *
|
||||
****************************/
|
||||
|
||||
enum rcheevos_async_io_type
|
||||
{
|
||||
CHEEVOS_ASYNC_RICHPRESENCE = 0,
|
||||
CHEEVOS_ASYNC_AWARD_ACHIEVEMENT,
|
||||
CHEEVOS_ASYNC_SUBMIT_LBOARD
|
||||
};
|
||||
|
||||
typedef void (*rcheevos_async_handler)(int id,
|
||||
http_transfer_data_t *data, char buffer[], size_t buffer_size);
|
||||
|
||||
typedef struct rcheevos_async_io_request
|
||||
{
|
||||
rc_api_request_t request;
|
||||
rcheevos_async_handler handler;
|
||||
int id;
|
||||
int attempt_count;
|
||||
const char* success_message;
|
||||
const char* failure_message;
|
||||
const char* user_agent;
|
||||
char type;
|
||||
} rcheevos_async_io_request;
|
||||
|
||||
|
||||
/****************************
|
||||
* forward declarations *
|
||||
****************************/
|
||||
|
||||
static retro_time_t rcheevos_client_prepare_ping(rcheevos_async_io_request* request);
|
||||
|
||||
static void rcheevos_async_http_task_callback(
|
||||
retro_task_t* task, void* task_data, void* user_data, const char* error);
|
||||
|
||||
|
||||
/****************************
|
||||
* user agent construction *
|
||||
****************************/
|
||||
|
||||
static int append_no_spaces(char* buffer, char* stop, const char* text)
|
||||
{
|
||||
char* ptr = buffer;
|
||||
|
||||
while (ptr < stop && *text)
|
||||
{
|
||||
if (*text == ' ')
|
||||
{
|
||||
*ptr++ = '_';
|
||||
++text;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr++ = *text++;
|
||||
}
|
||||
}
|
||||
|
||||
*ptr = '\0';
|
||||
return (int)(ptr - buffer);
|
||||
}
|
||||
|
||||
void rcheevos_get_user_agent(rcheevos_locals_t *locals,
|
||||
char *buffer, size_t len)
|
||||
{
|
||||
struct retro_system_info *system = runloop_get_libretro_system_info();
|
||||
char* ptr;
|
||||
|
||||
/* if we haven't calculated the non-changing portion yet, do so now
|
||||
* [retroarch version + os version] */
|
||||
if (!locals->user_agent_prefix[0])
|
||||
{
|
||||
const frontend_ctx_driver_t *frontend = frontend_get_ptr();
|
||||
int major, minor;
|
||||
char tmp[64];
|
||||
|
||||
if (frontend && frontend->get_os)
|
||||
{
|
||||
frontend->get_os(tmp, sizeof(tmp), &major, &minor);
|
||||
snprintf(locals->user_agent_prefix, sizeof(locals->user_agent_prefix),
|
||||
"RetroArch/%s (%s %d.%d)", PACKAGE_VERSION, tmp, major, minor);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(locals->user_agent_prefix, sizeof(locals->user_agent_prefix),
|
||||
"RetroArch/%s", PACKAGE_VERSION);
|
||||
}
|
||||
}
|
||||
|
||||
/* append the non-changing portion */
|
||||
ptr = buffer + strlcpy(buffer, locals->user_agent_prefix, len);
|
||||
|
||||
/* if a core is loaded, append its information */
|
||||
if (system && !string_is_empty(system->library_name))
|
||||
{
|
||||
char* stop = buffer + len - 1;
|
||||
const char* path = path_get(RARCH_PATH_CORE);
|
||||
*ptr++ = ' ';
|
||||
|
||||
if (!string_is_empty(path))
|
||||
{
|
||||
append_no_spaces(ptr, stop, path_basename(path));
|
||||
path_remove_extension(ptr);
|
||||
ptr += strlen(ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr += append_no_spaces(ptr, stop, system->library_name);
|
||||
}
|
||||
|
||||
if (system->library_version)
|
||||
{
|
||||
*ptr++ = '/';
|
||||
ptr += append_no_spaces(ptr, stop, system->library_version);
|
||||
}
|
||||
}
|
||||
|
||||
*ptr = '\0';
|
||||
}
|
||||
|
||||
#ifdef CHEEVOS_LOG_URLS
|
||||
#ifndef CHEEVOS_LOG_PASSWORD
|
||||
static void rcheevos_filter_url_param(char* url, char* param)
|
||||
{
|
||||
char *next;
|
||||
size_t param_len = strlen(param);
|
||||
char *start = strchr(url, '?');
|
||||
if (!start)
|
||||
start = url;
|
||||
else
|
||||
++start;
|
||||
|
||||
do
|
||||
{
|
||||
next = strchr(start, '&');
|
||||
|
||||
if (start[param_len] == '=' && memcmp(start, param, param_len) == 0)
|
||||
{
|
||||
if (next)
|
||||
strcpy_literal(start, next + 1);
|
||||
else if (start > url)
|
||||
start[-1] = '\0';
|
||||
else
|
||||
*start = '\0';
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!next)
|
||||
return;
|
||||
|
||||
start = next + 1;
|
||||
} while (1);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void rcheevos_log_url(const char* api, const char* url)
|
||||
{
|
||||
#ifdef CHEEVOS_LOG_URLS
|
||||
#ifdef CHEEVOS_LOG_PASSWORD
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "GET %s\n", url);
|
||||
#else
|
||||
char copy[256];
|
||||
strlcpy(copy, url, sizeof(copy));
|
||||
rcheevos_filter_url_param(copy, "p");
|
||||
rcheevos_filter_url_param(copy, "t");
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "GET %s\n", copy);
|
||||
#endif
|
||||
#else
|
||||
(void)api;
|
||||
(void)url;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void rcheevos_log_post_url(const char* url, const char* post)
|
||||
{
|
||||
#ifdef CHEEVOS_LOG_URLS
|
||||
#ifdef CHEEVOS_LOG_PASSWORD
|
||||
if (post && post[0])
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "POST %s %s\n", url, post);
|
||||
else
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "POST %s\n", url);
|
||||
#else
|
||||
if (post && post[0])
|
||||
{
|
||||
char post_copy[2048];
|
||||
strlcpy(post_copy, post, sizeof(post_copy));
|
||||
rcheevos_filter_url_param(post_copy, "p");
|
||||
rcheevos_filter_url_param(post_copy, "t");
|
||||
|
||||
if (post_copy[0])
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "POST %s %s\n", url, post_copy);
|
||||
else
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "POST %s\n", url);
|
||||
}
|
||||
else
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "POST %s\n", url);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
(void)url;
|
||||
(void)post;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/****************************
|
||||
* dispatch *
|
||||
****************************/
|
||||
|
||||
static void rcheevos_async_retry_request(retro_task_t* task)
|
||||
{
|
||||
rcheevos_async_io_request* request = (rcheevos_async_io_request*)
|
||||
task->user_data;
|
||||
|
||||
/* the timer task has done its job. let it dispose itself */
|
||||
task_set_finished(task, 1);
|
||||
|
||||
/* start a new task for the HTTP call */
|
||||
task_push_http_post_transfer_with_user_agent(request->request.url,
|
||||
request->request.post_data, true, "POST", request->user_agent,
|
||||
rcheevos_async_http_task_callback, request);
|
||||
}
|
||||
|
||||
static void rcheevos_async_retry_request_after_delay(rcheevos_async_io_request* request, const char* error)
|
||||
{
|
||||
retro_task_t* task = task_init();
|
||||
|
||||
/* Double the wait between each attempt until we hit
|
||||
* a maximum delay of two minutes.
|
||||
* 250ms -> 500ms -> 1s -> 2s -> 4s -> 8s -> 16s -> 32s -> 64s -> 120s -> 120s... */
|
||||
retro_time_t retry_delay = (request->attempt_count > 8)
|
||||
? (120 * 1000 * 1000)
|
||||
: ((250 * 1000) << request->attempt_count);
|
||||
|
||||
CHEEVOS_ERR(RCHEEVOS_TAG "%s %u: %s (automatic retry in %dms)\n", request->failure_message,
|
||||
request->id, error, (int)retry_delay / 1000);
|
||||
|
||||
task->when = cpu_features_get_time_usec() + retry_delay;
|
||||
task->handler = rcheevos_async_retry_request;
|
||||
task->user_data = request;
|
||||
task->progress = -1;
|
||||
|
||||
++request->attempt_count;
|
||||
task_queue_push(task);
|
||||
}
|
||||
|
||||
static void rcheevos_async_request_failed(rcheevos_async_io_request* request, const char* error)
|
||||
{
|
||||
if (request->type == CHEEVOS_ASYNC_RICHPRESENCE && request->attempt_count > 0)
|
||||
{
|
||||
/* only retry the ping once (in case of network hiccup), otherwise let
|
||||
* the timer handle it after the normal ping period has elapsed */
|
||||
CHEEVOS_ERR(RCHEEVOS_TAG "%s %u: %s\n", request->failure_message,
|
||||
request->id, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* automatically retry the request */
|
||||
rcheevos_async_retry_request_after_delay(request, error);
|
||||
}
|
||||
}
|
||||
|
||||
static void rcheevos_async_http_task_callback(
|
||||
retro_task_t* task, void* task_data, void* user_data, const char* error)
|
||||
{
|
||||
rcheevos_async_io_request *request = (rcheevos_async_io_request*)user_data;
|
||||
http_transfer_data_t *data = (http_transfer_data_t*)task_data;
|
||||
char buffer[224];
|
||||
|
||||
if (error)
|
||||
{
|
||||
/* there was a communication error */
|
||||
rcheevos_async_request_failed(request, error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data)
|
||||
{
|
||||
/* Server did not return HTTP headers */
|
||||
strlcpy(buffer, "Server communication error", sizeof(buffer));
|
||||
}
|
||||
else if (!data->data || !data->len)
|
||||
{
|
||||
if (data->status <= 0)
|
||||
{
|
||||
/* something occurred which prevented the response from being processed.
|
||||
* assume the server request hasn't happened and try again. */
|
||||
snprintf(buffer, sizeof(buffer), "task status code %d", data->status);
|
||||
rcheevos_async_request_failed(request, buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->status != 200)
|
||||
{
|
||||
/* Server returned an error via status code. */
|
||||
snprintf(buffer, sizeof(buffer), "HTTP error code %d", data->status);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Server sent an empty response without an error status code */
|
||||
strlcpy(buffer, "No response from server", sizeof(buffer));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[0] = '\0'; /* indicate success unless handler provides error */
|
||||
|
||||
/* Call appropriate handler to process the response */
|
||||
if (request->handler)
|
||||
{
|
||||
/* NOTE: data->data is not null-terminated. Most handlers assume the
|
||||
* response is properly formatted or will encounter a parse failure
|
||||
* before reading past the end of the data */
|
||||
request->handler(request->id, data, buffer, sizeof(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
if (!buffer[0])
|
||||
{
|
||||
/* success */
|
||||
if (request->success_message)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "%s %u\n", request->success_message, request->id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* encountered an error */
|
||||
char errbuf[256];
|
||||
snprintf(errbuf, sizeof(errbuf), "%s %u: %s",
|
||||
request->failure_message, request->id, buffer);
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "%s\n", errbuf);
|
||||
|
||||
switch (request->type)
|
||||
{
|
||||
case CHEEVOS_ASYNC_RICHPRESENCE:
|
||||
/* Don't bother informing user when
|
||||
* rich presence update fails */
|
||||
break;
|
||||
|
||||
default:
|
||||
runloop_msg_queue_push(errbuf, 0, 5 * 60, false, NULL,
|
||||
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_ERROR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rc_api_destroy_request(&request->request);
|
||||
|
||||
/* rich presence request will be reused on next ping - reset the attempt
|
||||
* counter. for all other request types, free the request object */
|
||||
if (request->type == CHEEVOS_ASYNC_RICHPRESENCE)
|
||||
request->attempt_count = 0;
|
||||
else
|
||||
free(request);
|
||||
}
|
||||
|
||||
static void rcheevos_async_begin_request(rcheevos_async_io_request* request,
|
||||
rcheevos_async_handler handler, char type, int id,
|
||||
const char* success_message, const char* failure_message)
|
||||
{
|
||||
request->handler = handler;
|
||||
request->type = type;
|
||||
request->id = id;
|
||||
request->success_message = success_message;
|
||||
request->failure_message = failure_message;
|
||||
request->attempt_count = 0;
|
||||
|
||||
if (!request->user_agent)
|
||||
request->user_agent = get_rcheevos_locals()->user_agent_core;
|
||||
|
||||
rcheevos_log_post_url(request->request.url, request->request.post_data);
|
||||
|
||||
task_push_http_post_transfer_with_user_agent(request->request.url,
|
||||
request->request.post_data, true, "POST", request->user_agent,
|
||||
rcheevos_async_http_task_callback, request);
|
||||
}
|
||||
|
||||
static bool rcheevos_async_succeeded(int result,
|
||||
const rc_api_response_t* response, char buffer[], size_t buffer_size)
|
||||
{
|
||||
if (result != RC_OK)
|
||||
{
|
||||
strlcpy(buffer, rc_error_str(result), buffer_size);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!response->succeeded)
|
||||
{
|
||||
strlcpy(buffer, response->error_message, buffer_size);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/****************************
|
||||
* ping *
|
||||
****************************/
|
||||
|
||||
static retro_time_t rcheevos_client_prepare_ping(rcheevos_async_io_request* request)
|
||||
{
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
const settings_t *settings = config_get_ptr();
|
||||
const bool cheevos_richpresence_enable =
|
||||
settings->bools.cheevos_richpresence_enable;
|
||||
rc_api_ping_request_t api_params;
|
||||
char buffer[256] = "";
|
||||
|
||||
memset(&api_params, 0, sizeof(api_params));
|
||||
api_params.username = rcheevos_locals->username;
|
||||
api_params.api_token = rcheevos_locals->token;
|
||||
api_params.game_id = request->id;
|
||||
|
||||
if (cheevos_richpresence_enable)
|
||||
{
|
||||
rcheevos_get_richpresence(buffer, sizeof(buffer));
|
||||
api_params.rich_presence = buffer;
|
||||
}
|
||||
|
||||
rc_api_init_ping_request(&request->request, &api_params);
|
||||
|
||||
rcheevos_log_post_url(request->request.url, request->request.post_data);
|
||||
|
||||
#ifdef HAVE_DISCORD
|
||||
if (settings->bools.discord_enable && discord_is_ready())
|
||||
discord_update(DISCORD_PRESENCE_RETROACHIEVEMENTS);
|
||||
#endif
|
||||
|
||||
/* Update rich presence every two minutes */
|
||||
if (cheevos_richpresence_enable)
|
||||
return cpu_features_get_time_usec() + CHEEVOS_PING_FREQUENCY;
|
||||
|
||||
/* Send ping every four minutes */
|
||||
return cpu_features_get_time_usec() + CHEEVOS_PING_FREQUENCY * 2;
|
||||
}
|
||||
|
||||
static void rcheevos_async_ping_handler(retro_task_t* task)
|
||||
{
|
||||
rcheevos_async_io_request* request = (rcheevos_async_io_request*)
|
||||
task->user_data;
|
||||
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
if (request->id != (int)rcheevos_locals->patchdata.game_id)
|
||||
{
|
||||
/* game changed; stop the recurring task - a new one will
|
||||
* be scheduled if a new game is loaded */
|
||||
task_set_finished(task, 1);
|
||||
/* request->request was destroyed in rcheevos_async_http_task_callback */
|
||||
free(request);
|
||||
return;
|
||||
}
|
||||
|
||||
/* update the request and set the task to fire again in
|
||||
* two minutes */
|
||||
task->when = rcheevos_client_prepare_ping(request);
|
||||
|
||||
/* start the HTTP request */
|
||||
task_push_http_post_transfer_with_user_agent(request->request.url,
|
||||
request->request.post_data, true, "POST", request->user_agent,
|
||||
rcheevos_async_http_task_callback, request);
|
||||
}
|
||||
|
||||
|
||||
/****************************
|
||||
* start session *
|
||||
****************************/
|
||||
|
||||
void rcheevos_client_start_session(unsigned game_id)
|
||||
{
|
||||
rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
|
||||
/* the core won't change while a session is active, so only
|
||||
* calculate the user agent once */
|
||||
rcheevos_get_user_agent(rcheevos_locals,
|
||||
rcheevos_locals->user_agent_core,
|
||||
sizeof(rcheevos_locals->user_agent_core));
|
||||
|
||||
/* force non-HTTPS until everything uses RAPI */
|
||||
rc_api_set_host("http://retroachievements.org");
|
||||
|
||||
/* schedule the first rich presence call in 30 seconds */
|
||||
{
|
||||
rcheevos_async_io_request *request = (rcheevos_async_io_request*)
|
||||
calloc(1, sizeof(rcheevos_async_io_request));
|
||||
if (!request)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Failed to allocate rich presence request\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
retro_task_t* task = task_init();
|
||||
|
||||
request->id = game_id;
|
||||
request->type = CHEEVOS_ASYNC_RICHPRESENCE;
|
||||
request->user_agent = rcheevos_locals->user_agent_core;
|
||||
request->failure_message = "Error sending ping";
|
||||
|
||||
task->handler = rcheevos_async_ping_handler;
|
||||
task->user_data = request;
|
||||
task->progress = -1;
|
||||
task->when = cpu_features_get_time_usec() +
|
||||
CHEEVOS_PING_FREQUENCY / 4;
|
||||
|
||||
task_queue_push(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************
|
||||
* award achievement *
|
||||
****************************/
|
||||
|
||||
static void rcheevos_async_award_achievement_callback(int id,
|
||||
http_transfer_data_t *data, char buffer[], size_t buffer_size)
|
||||
{
|
||||
rc_api_award_achievement_response_t api_response;
|
||||
|
||||
int result = rc_api_process_award_achievement_response(&api_response, data->data);
|
||||
if (rcheevos_async_succeeded(result, &api_response.response, buffer, buffer_size))
|
||||
{
|
||||
if (api_response.awarded_achievement_id != id)
|
||||
{
|
||||
snprintf(buffer, buffer_size, "Achievement %u awarded instead",
|
||||
api_response.awarded_achievement_id);
|
||||
}
|
||||
else if (api_response.response.error_message)
|
||||
{
|
||||
/* previously unlocked achievements are returned as a "successful" error */
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Achievement %u: %s\n",
|
||||
id, api_response.response.error_message);
|
||||
}
|
||||
}
|
||||
|
||||
rc_api_destroy_award_achievement_response(&api_response);
|
||||
}
|
||||
|
||||
void rcheevos_client_award_achievement(unsigned achievement_id)
|
||||
{
|
||||
rcheevos_async_io_request *request = (rcheevos_async_io_request*)
|
||||
calloc(1, sizeof(rcheevos_async_io_request));
|
||||
if (!request)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Failed to allocate unlock request for achievement %u\n",
|
||||
achievement_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
rc_api_award_achievement_request_t api_params;
|
||||
|
||||
memset(&api_params, 0, sizeof(api_params));
|
||||
api_params.username = rcheevos_locals->username;
|
||||
api_params.api_token = rcheevos_locals->token;
|
||||
api_params.achievement_id = achievement_id;
|
||||
api_params.hardcore = rcheevos_locals->hardcore_active ? 1 : 0;
|
||||
api_params.game_hash = rcheevos_locals->hash;
|
||||
|
||||
rc_api_init_award_achievement_request(&request->request, &api_params);
|
||||
|
||||
rcheevos_async_begin_request(request,
|
||||
rcheevos_async_award_achievement_callback,
|
||||
CHEEVOS_ASYNC_AWARD_ACHIEVEMENT, achievement_id,
|
||||
"Awarded achievement",
|
||||
"Error awarding achievement");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************
|
||||
* submit leaderboard *
|
||||
****************************/
|
||||
|
||||
static void rcheevos_async_submit_lboard_entry_callback(int id,
|
||||
http_transfer_data_t* data, char buffer[], size_t buffer_size)
|
||||
{
|
||||
rc_api_submit_lboard_entry_response_t api_response;
|
||||
|
||||
int result = rc_api_process_submit_lboard_entry_response(&api_response, data->data);
|
||||
|
||||
if (rcheevos_async_succeeded(result, &api_response.response, buffer, buffer_size))
|
||||
{
|
||||
/* not currently doing anything with the response */
|
||||
}
|
||||
|
||||
rc_api_destroy_submit_lboard_entry_response(&api_response);
|
||||
}
|
||||
|
||||
void rcheevos_client_submit_lboard_entry(unsigned leaderboard_id, int value)
|
||||
{
|
||||
rcheevos_async_io_request *request = (rcheevos_async_io_request*)
|
||||
calloc(1, sizeof(rcheevos_async_io_request));
|
||||
if (!request)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Failed to allocate request for lboard %u submit\n",
|
||||
leaderboard_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
rc_api_submit_lboard_entry_request_t api_params;
|
||||
|
||||
memset(&api_params, 0, sizeof(api_params));
|
||||
api_params.username = rcheevos_locals->username;
|
||||
api_params.api_token = rcheevos_locals->token;
|
||||
api_params.leaderboard_id = leaderboard_id;
|
||||
api_params.score = value;
|
||||
api_params.game_hash = rcheevos_locals->hash;
|
||||
|
||||
rc_api_init_submit_lboard_entry_request(&request->request, &api_params);
|
||||
|
||||
rcheevos_async_begin_request(request,
|
||||
rcheevos_async_submit_lboard_entry_callback,
|
||||
CHEEVOS_ASYNC_SUBMIT_LBOARD, leaderboard_id,
|
||||
"Submitted leaderboard",
|
||||
"Error submitting leaderboard");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2018 - Andre Leiradella
|
||||
* Copyright (C) 2019-2021 - Brian Weiss
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
@@ -13,23 +13,20 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __RARCH_CHEEVOS_BADGE_H
|
||||
#define __RARCH_CHEEVOS_BADGE_H
|
||||
#ifndef __RARCH_CHEEVOS_CLIENT_H
|
||||
#define __RARCH_CHEEVOS_CLIENT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <retro_common_api.h>
|
||||
#include <boolean.h>
|
||||
#include "cheevos_locals.h"
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
void cheevos_reset_menu_badges(void);
|
||||
void cheevos_set_menu_badge(int index, const char *badge, bool locked);
|
||||
uintptr_t cheevos_get_menu_badge_texture(int index);
|
||||
#endif
|
||||
void rcheevos_client_start_session(unsigned game_id);
|
||||
void rcheevos_client_award_achievement(unsigned achievement_id);
|
||||
void rcheevos_client_submit_lboard_entry(unsigned leaderboard_id, int value);
|
||||
|
||||
uintptr_t cheevos_get_badge_texture(const char* badge, bool locked);
|
||||
void rcheevos_log_url(const char* api, const char* url);
|
||||
void rcheevos_get_user_agent(rcheevos_locals_t *locals, char *buffer, size_t len);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
#endif /* __RARCH_CHEEVOS_MENU_H */
|
||||
@@ -0,0 +1,161 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2018 - Andre Leiradella
|
||||
* Copyright (C) 2019-2021 - Brian Weiss
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __RARCH_CHEEVOS_LOCALS_H
|
||||
#define __RARCH_CHEEVOS_LOCALS_H
|
||||
|
||||
#include "../deps/rcheevos/include/rc_runtime.h"
|
||||
|
||||
#include "../deps/rcheevos/src/rcheevos/rc_libretro.h"
|
||||
|
||||
#include <../command.h>
|
||||
#include <../verbosity.h>
|
||||
#include <boolean.h>
|
||||
#include <queues/task_queue.h>
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
#include <rthreads/rthreads.h>
|
||||
#endif
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
/************************************************************************
|
||||
* Logging *
|
||||
************************************************************************/
|
||||
|
||||
/* Define this macro to get extra-verbose log for cheevos. */
|
||||
#define CHEEVOS_VERBOSE
|
||||
|
||||
#define RCHEEVOS_TAG "[RCHEEVOS]: "
|
||||
#define CHEEVOS_FREE(p) do { void* q = (void*)p; if (q) free(q); } while (0)
|
||||
|
||||
#ifdef CHEEVOS_VERBOSE
|
||||
#define CHEEVOS_LOG RARCH_LOG
|
||||
#define CHEEVOS_ERR RARCH_ERR
|
||||
#else
|
||||
void rcheevos_log(const char *fmt, ...);
|
||||
#define CHEEVOS_LOG rcheevos_log
|
||||
#define CHEEVOS_ERR RARCH_ERR
|
||||
#endif
|
||||
|
||||
/************************************************************************
|
||||
* State *
|
||||
************************************************************************/
|
||||
|
||||
enum
|
||||
{
|
||||
RCHEEVOS_ACTIVE_SOFTCORE = 1 << 0,
|
||||
RCHEEVOS_ACTIVE_HARDCORE = 1 << 1,
|
||||
RCHEEVOS_ACTIVE_UNOFFICIAL = 1 << 2
|
||||
};
|
||||
|
||||
typedef struct rcheevos_racheevo_t
|
||||
{
|
||||
const char* title;
|
||||
const char* description;
|
||||
const char* badge;
|
||||
const char* memaddr;
|
||||
unsigned id;
|
||||
unsigned points;
|
||||
|
||||
retro_time_t unlock_time;
|
||||
uint8_t active;
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
uint8_t menu_bucket;
|
||||
uint8_t menu_progress;
|
||||
uint8_t menu_badge_grayscale;
|
||||
uintptr_t menu_badge_texture;
|
||||
#endif
|
||||
|
||||
} rcheevos_racheevo_t;
|
||||
|
||||
typedef struct rcheevos_ralboard_t
|
||||
{
|
||||
const char* title;
|
||||
const char* description;
|
||||
const char* mem;
|
||||
unsigned id;
|
||||
unsigned format;
|
||||
} rcheevos_ralboard_t;
|
||||
|
||||
typedef struct rcheevos_rapatchdata_t
|
||||
{
|
||||
char* title;
|
||||
rcheevos_racheevo_t* core;
|
||||
rcheevos_racheevo_t* unofficial;
|
||||
rcheevos_ralboard_t* lboards;
|
||||
char* richpresence_script;
|
||||
|
||||
unsigned game_id;
|
||||
unsigned console_id;
|
||||
unsigned core_count;
|
||||
unsigned unofficial_count;
|
||||
unsigned lboard_count;
|
||||
} rcheevos_rapatchdata_t;
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
|
||||
typedef struct rcheevos_menuitem_t
|
||||
{
|
||||
rcheevos_racheevo_t* cheevo;
|
||||
enum msg_hash_enums state_label_idx;
|
||||
} rcheevos_menuitem_t;
|
||||
|
||||
void rcheevos_menu_reset_badges(void);
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct rcheevos_locals_t
|
||||
{
|
||||
rc_runtime_t runtime; /* rcheevos runtime state */
|
||||
rcheevos_rapatchdata_t patchdata; /* achievement/leaderboard data from the server */
|
||||
rc_libretro_memory_regions_t memory;/* achievement addresses to core memory mappings */
|
||||
|
||||
retro_task_t* task; /* load task */
|
||||
#ifdef HAVE_THREADS
|
||||
slock_t* task_lock; /* mutex for starting/stopping load task */
|
||||
enum event_command queued_command; /* action queued by background thread to be run on main thread */
|
||||
#endif
|
||||
|
||||
char username[32]; /* case-corrected username */
|
||||
char token[32]; /* user's session token */
|
||||
char hash[33]; /* retroachievements hash for current content */
|
||||
char user_agent_prefix[128]; /* RetroArch/OS version information */
|
||||
char user_agent_core[256]; /* RetroArch/OS/Core version information */
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
rcheevos_menuitem_t* menuitems; /* array of items for the achievements quick menu */
|
||||
unsigned menuitem_capacity; /* maximum number of items in the menuitems array */
|
||||
unsigned menuitem_count; /* current number of items in the menuitems array */
|
||||
#endif
|
||||
|
||||
bool hardcore_active; /* hardcore functionality is active */
|
||||
bool loaded; /* load task has completed */
|
||||
bool core_supports; /* false if core explicitly disables achievements */
|
||||
bool network_error; /* hash lookup or login failed with network error */
|
||||
bool leaderboards_enabled; /* leaderboards are enabled */
|
||||
bool leaderboard_notifications; /* leaderboard notifications are enabled */
|
||||
bool leaderboard_trackers; /* leaderboard trackers are enabled */
|
||||
} rcheevos_locals_t;
|
||||
|
||||
rcheevos_locals_t* get_rcheevos_locals(void);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif /* __RARCH_CHEEVOS_LOCALS_H */
|
||||
@@ -1,352 +0,0 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2016 - Andre Leiradella
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "cheevos_memory.h"
|
||||
|
||||
#include "util.h"
|
||||
|
||||
#include "../retroarch.h"
|
||||
#include "../verbosity.h"
|
||||
|
||||
#include "../deps/rcheevos/include/rcheevos.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
uint8_t* rcheevos_memory_find(
|
||||
const rcheevos_memory_regions_t* regions, unsigned address)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < regions->count; ++i)
|
||||
{
|
||||
const size_t size = regions->size[i];
|
||||
if (address < size)
|
||||
{
|
||||
if (regions->data[i] == NULL)
|
||||
break;
|
||||
|
||||
return ®ions->data[i][address];
|
||||
}
|
||||
|
||||
address -= size;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* rcheevos_memory_type(int type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case RC_MEMORY_TYPE_SAVE_RAM:
|
||||
return "SRAM";
|
||||
case RC_MEMORY_TYPE_VIDEO_RAM:
|
||||
return "VRAM";
|
||||
case RC_MEMORY_TYPE_UNUSED:
|
||||
return "UNUSED";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return "SYSTEM RAM";
|
||||
}
|
||||
|
||||
static void rcheevos_memory_register_region(rcheevos_memory_regions_t* regions,
|
||||
int type, uint8_t* data, size_t size, const char* description)
|
||||
{
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
if (regions->count == MAX_MEMORY_REGIONS)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Too many memory memory regions to register\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data && regions->count > 0 && !regions->data[regions->count - 1])
|
||||
{
|
||||
/* extend null region */
|
||||
regions->size[regions->count - 1] += size;
|
||||
}
|
||||
else if (data && regions->count > 0 &&
|
||||
data == (regions->data[regions->count - 1] + regions->size[regions->count - 1]))
|
||||
{
|
||||
/* extend non-null region */
|
||||
regions->size[regions->count - 1] += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* create new region */
|
||||
regions->data[regions->count] = data;
|
||||
regions->size[regions->count] = size;
|
||||
++regions->count;
|
||||
}
|
||||
|
||||
regions->total_size += size;
|
||||
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Registered 0x%04X bytes of %s at $%06X (%s)\n", (unsigned)size,
|
||||
rcheevos_memory_type(type), (unsigned)(regions->total_size - size), description);
|
||||
}
|
||||
|
||||
static void rcheevos_memory_init_without_regions(
|
||||
rcheevos_memory_regions_t* regions)
|
||||
{
|
||||
/* no regions specified, assume system RAM followed by save RAM */
|
||||
char description[64];
|
||||
retro_ctx_memory_info_t meminfo;
|
||||
|
||||
snprintf(description, sizeof(description), "offset 0x%06x", 0);
|
||||
|
||||
meminfo.id = RETRO_MEMORY_SYSTEM_RAM;
|
||||
core_get_memory(&meminfo);
|
||||
rcheevos_memory_register_region(regions, RC_MEMORY_TYPE_SYSTEM_RAM, (uint8_t*)meminfo.data, meminfo.size, description);
|
||||
|
||||
meminfo.id = RETRO_MEMORY_SAVE_RAM;
|
||||
core_get_memory(&meminfo);
|
||||
rcheevos_memory_register_region(regions, RC_MEMORY_TYPE_SAVE_RAM, (uint8_t*)meminfo.data, meminfo.size, description);
|
||||
}
|
||||
|
||||
static const rarch_memory_descriptor_t* rcheevos_memory_get_descriptor(const rarch_memory_map_t* mmap, unsigned real_address)
|
||||
{
|
||||
const rarch_memory_descriptor_t* desc = mmap->descriptors;
|
||||
const rarch_memory_descriptor_t* end = desc + mmap->num_descriptors;
|
||||
|
||||
if (mmap->num_descriptors == 0)
|
||||
return NULL;
|
||||
|
||||
for (; desc < end; desc++)
|
||||
{
|
||||
if (desc->core.select == 0)
|
||||
{
|
||||
/* if select is 0, attempt to explcitly match the address */
|
||||
if (real_address >= desc->core.start && real_address < desc->core.start + desc->core.len)
|
||||
return desc;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* otherwise, attempt to match the address by matching the select bits */
|
||||
if (((desc->core.start ^ real_address) & desc->core.select) == 0)
|
||||
{
|
||||
/* sanity check - make sure the descriptor is large enough to hold the target address */
|
||||
if (real_address - desc->core.start < desc->core.len)
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void rcheevos_memory_init_from_memory_map(rcheevos_memory_regions_t* regions, const rarch_memory_map_t* mmap, const rc_memory_regions_t* console_regions)
|
||||
{
|
||||
char description[64];
|
||||
unsigned i;
|
||||
uint8_t* region_start;
|
||||
uint8_t* desc_start;
|
||||
size_t desc_size;
|
||||
size_t offset;
|
||||
|
||||
for (i = 0; i < console_regions->num_regions; ++i)
|
||||
{
|
||||
const rc_memory_region_t* console_region = &console_regions->region[i];
|
||||
size_t console_region_size = console_region->end_address - console_region->start_address + 1;
|
||||
unsigned real_address = console_region->real_address;
|
||||
|
||||
while (console_region_size > 0)
|
||||
{
|
||||
const rarch_memory_descriptor_t* desc = rcheevos_memory_get_descriptor(mmap, real_address);
|
||||
if (!desc)
|
||||
{
|
||||
if (console_region->type != RC_MEMORY_TYPE_UNUSED)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Could not map region starting at $%06X\n",
|
||||
real_address - console_region->real_address + console_region->start_address);
|
||||
}
|
||||
|
||||
rcheevos_memory_register_region(regions, console_region->type, NULL, console_region_size, "null filler");
|
||||
break;
|
||||
}
|
||||
|
||||
offset = real_address - desc->core.start;
|
||||
snprintf(description, sizeof(description),
|
||||
"descriptor %u, offset 0x%06X",
|
||||
(int)(desc - mmap->descriptors) + 1, (int)offset);
|
||||
|
||||
if (desc->core.ptr)
|
||||
{
|
||||
desc_start = (uint8_t*)desc->core.ptr + desc->core.offset;
|
||||
region_start = desc_start + offset;
|
||||
}
|
||||
else
|
||||
region_start = NULL;
|
||||
|
||||
desc_size = desc->core.len - offset;
|
||||
|
||||
if (console_region_size > desc_size)
|
||||
{
|
||||
if (desc_size == 0)
|
||||
{
|
||||
if (console_region->type != RC_MEMORY_TYPE_UNUSED)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Could not map region starting at $%06X\n",
|
||||
real_address - console_region->real_address + console_region->start_address);
|
||||
}
|
||||
|
||||
rcheevos_memory_register_region(regions, console_region->type, NULL, console_region_size, "null filler");
|
||||
console_region_size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
rcheevos_memory_register_region(regions, console_region->type, region_start, desc_size, description);
|
||||
console_region_size -= desc_size;
|
||||
real_address += desc_size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rcheevos_memory_register_region(regions, console_region->type, region_start, console_region_size, description);
|
||||
console_region_size = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned rcheevos_memory_console_region_to_ram_type(int region_type)
|
||||
{
|
||||
switch (region_type)
|
||||
{
|
||||
case RC_MEMORY_TYPE_SAVE_RAM:
|
||||
return RETRO_MEMORY_SAVE_RAM;
|
||||
case RC_MEMORY_TYPE_VIDEO_RAM:
|
||||
return RETRO_MEMORY_VIDEO_RAM;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return RETRO_MEMORY_SYSTEM_RAM;
|
||||
}
|
||||
|
||||
static void rcheevos_memory_init_from_unmapped_memory(rcheevos_memory_regions_t* regions, const rc_memory_regions_t* console_regions, int console)
|
||||
{
|
||||
char description[64];
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < console_regions->num_regions; ++i)
|
||||
{
|
||||
size_t offset;
|
||||
unsigned j;
|
||||
retro_ctx_memory_info_t meminfo;
|
||||
const rc_memory_region_t* console_region = &console_regions->region[i];
|
||||
const size_t console_region_size =
|
||||
console_region->end_address - console_region->start_address + 1;
|
||||
unsigned base_address = 0;
|
||||
|
||||
meminfo.id = rcheevos_memory_console_region_to_ram_type(console_region->type);
|
||||
|
||||
for (j = 0; j <= i; ++j)
|
||||
{
|
||||
const rc_memory_region_t* console_region2 = &console_regions->region[j];
|
||||
if (rcheevos_memory_console_region_to_ram_type(
|
||||
console_region2->type) == meminfo.id)
|
||||
{
|
||||
base_address = console_region2->start_address;
|
||||
break;
|
||||
}
|
||||
}
|
||||
offset = console_region->start_address - base_address;
|
||||
|
||||
core_get_memory(&meminfo);
|
||||
|
||||
if (offset < meminfo.size)
|
||||
{
|
||||
meminfo.size -= offset;
|
||||
|
||||
if (meminfo.data)
|
||||
{
|
||||
snprintf(description, sizeof(description),
|
||||
"offset 0x%06X", (int)offset);
|
||||
meminfo.data = (uint8_t*)meminfo.data + offset;
|
||||
}
|
||||
else
|
||||
snprintf(description, sizeof(description), "null filler");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (console_region->type != RC_MEMORY_TYPE_UNUSED)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Could not map region starting at $%06X\n", console_region->start_address);
|
||||
}
|
||||
|
||||
meminfo.data = NULL;
|
||||
meminfo.size = 0;
|
||||
}
|
||||
|
||||
if (console_region_size > meminfo.size)
|
||||
{
|
||||
/* want more than what is available, take what we can and null fill the rest */
|
||||
rcheevos_memory_register_region(regions, console_region->type, (uint8_t*)meminfo.data, meminfo.size, description);
|
||||
rcheevos_memory_register_region(regions, console_region->type, NULL, console_region_size - meminfo.size, "null filler");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* only take as much as we need */
|
||||
rcheevos_memory_register_region(regions, console_region->type, (uint8_t*)meminfo.data, console_region_size, description);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rcheevos_memory_destroy(rcheevos_memory_regions_t* regions)
|
||||
{
|
||||
memset(regions, 0, sizeof(*regions));
|
||||
}
|
||||
|
||||
bool rcheevos_memory_init(rcheevos_memory_regions_t* regions, int console)
|
||||
{
|
||||
unsigned i;
|
||||
const rc_memory_regions_t* console_regions = rc_console_memory_regions(console);
|
||||
rcheevos_memory_regions_t new_regions;
|
||||
bool has_valid_region = false;
|
||||
|
||||
if (!regions)
|
||||
return false;
|
||||
|
||||
memset(&new_regions, 0, sizeof(new_regions));
|
||||
|
||||
if (console_regions == NULL || console_regions->num_regions == 0)
|
||||
{
|
||||
rcheevos_memory_init_without_regions(&new_regions);
|
||||
}
|
||||
else
|
||||
{
|
||||
rarch_system_info_t* system = runloop_get_system_info();
|
||||
if (system->mmaps.num_descriptors != 0)
|
||||
rcheevos_memory_init_from_memory_map(&new_regions, &system->mmaps, console_regions);
|
||||
else
|
||||
rcheevos_memory_init_from_unmapped_memory(&new_regions, console_regions, console);
|
||||
}
|
||||
|
||||
/* determine if any valid regions were found */
|
||||
for (i = 0; i < new_regions.count; i++)
|
||||
{
|
||||
if (new_regions.data[i])
|
||||
{
|
||||
has_valid_region = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(regions, &new_regions, sizeof(*regions));
|
||||
return has_valid_region;
|
||||
}
|
||||
@@ -0,0 +1,725 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2019-2021 - Brian Weiss
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "cheevos_locals.h"
|
||||
|
||||
#include "../gfx/gfx_display.h"
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
|
||||
#include "cheevos.h"
|
||||
|
||||
#include "../deps/rcheevos/include/rc_runtime_types.h"
|
||||
|
||||
#include "../file_path_special.h"
|
||||
#include "../menu/menu_driver.h"
|
||||
#include "../menu/menu_entries.h"
|
||||
|
||||
#include <features/features_cpu.h>
|
||||
|
||||
enum rcheevos_menuitem_bucket
|
||||
{
|
||||
RCHEEVOS_MENUITEM_BUCKET_UNKNOWN = 0,
|
||||
RCHEEVOS_MENUITEM_BUCKET_LOCKED,
|
||||
RCHEEVOS_MENUITEM_BUCKET_UNLOCKED,
|
||||
RCHEEVOS_MENUITEM_BUCKET_UNSUPPORTED,
|
||||
RCHEEVOS_MENUITEM_BUCKET_RECENTLY_UNLOCKED,
|
||||
RCHEEVOS_MENUITEM_BUCKET_ACTIVE_CHALLENGE,
|
||||
RCHEEVOS_MENUITEM_BUCKET_ALMOST_THERE
|
||||
};
|
||||
|
||||
static void rcheevos_menu_update_bucket(rcheevos_racheevo_t* cheevo)
|
||||
{
|
||||
cheevo->menu_progress = 0;
|
||||
|
||||
if (!cheevo->memaddr)
|
||||
{
|
||||
/* non-active unsupported achievement */
|
||||
cheevo->menu_bucket = RCHEEVOS_MENUITEM_BUCKET_UNSUPPORTED;
|
||||
}
|
||||
else if (!(cheevo->active & RCHEEVOS_ACTIVE_HARDCORE))
|
||||
{
|
||||
/* non-active unlocked in hardcore achievement */
|
||||
cheevo->menu_bucket = RCHEEVOS_MENUITEM_BUCKET_UNLOCKED;
|
||||
}
|
||||
else
|
||||
{
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
rc_trigger_t* trigger;
|
||||
|
||||
if (!rcheevos_locals->hardcore_active && !(cheevo->active & RCHEEVOS_ACTIVE_SOFTCORE))
|
||||
{
|
||||
/* non-active unlocked in softcore achievement in softcore mode */
|
||||
cheevo->menu_bucket = RCHEEVOS_MENUITEM_BUCKET_UNLOCKED;
|
||||
return;
|
||||
}
|
||||
|
||||
/* active achievement */
|
||||
cheevo->menu_bucket = RCHEEVOS_MENUITEM_BUCKET_LOCKED;
|
||||
|
||||
trigger = rc_runtime_get_achievement(&rcheevos_locals->runtime, cheevo->id);
|
||||
if (trigger)
|
||||
{
|
||||
if (trigger->measured_value && trigger->measured_target)
|
||||
{
|
||||
const unsigned long clamped_value = (unsigned long)
|
||||
MIN(trigger->measured_value, trigger->measured_target);
|
||||
cheevo->menu_progress =
|
||||
(uint8_t)((clamped_value * 100) / trigger->measured_target);
|
||||
}
|
||||
|
||||
if (trigger->state == RC_TRIGGER_STATE_PRIMED)
|
||||
cheevo->menu_bucket = RCHEEVOS_MENUITEM_BUCKET_ACTIVE_CHALLENGE;
|
||||
else if (cheevo->menu_progress >= 80)
|
||||
cheevo->menu_bucket = RCHEEVOS_MENUITEM_BUCKET_ALMOST_THERE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rcheevos_menu_update_buckets(bool cheevos_test_unofficial)
|
||||
{
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
rcheevos_racheevo_t* cheevo = rcheevos_locals->patchdata.core;
|
||||
rcheevos_racheevo_t* stop = cheevo + rcheevos_locals->patchdata.core_count;
|
||||
|
||||
while (cheevo < stop)
|
||||
{
|
||||
rcheevos_menu_update_bucket(cheevo);
|
||||
++cheevo;
|
||||
}
|
||||
|
||||
if (cheevos_test_unofficial)
|
||||
{
|
||||
cheevo = rcheevos_locals->patchdata.unofficial;
|
||||
stop = cheevo + rcheevos_locals->patchdata.unofficial_count;
|
||||
|
||||
while (cheevo < stop)
|
||||
{
|
||||
rcheevos_menu_update_bucket(cheevo);
|
||||
++cheevo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool rcheevos_menu_get_state(unsigned menu_offset, char *buffer, size_t len)
|
||||
{
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
if (menu_offset < rcheevos_locals->menuitem_count)
|
||||
{
|
||||
const rcheevos_menuitem_t* menuitem = &rcheevos_locals->menuitems[menu_offset];
|
||||
const rcheevos_racheevo_t* cheevo = menuitem->cheevo;
|
||||
if (cheevo)
|
||||
{
|
||||
if (cheevo->menu_progress)
|
||||
{
|
||||
snprintf(buffer, len, "%s - %d%%",
|
||||
msg_hash_to_str(menuitem->state_label_idx),
|
||||
cheevo->menu_progress);
|
||||
}
|
||||
else
|
||||
{
|
||||
strlcpy(buffer, msg_hash_to_str(menuitem->state_label_idx), len);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer)
|
||||
buffer[0] = '\0';
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool rcheevos_menu_get_sublabel(unsigned menu_offset, char *buffer, size_t len)
|
||||
{
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
if (menu_offset < rcheevos_locals->menuitem_count)
|
||||
{
|
||||
const rcheevos_racheevo_t* cheevo = rcheevos_locals->menuitems[menu_offset].cheevo;
|
||||
if (cheevo && buffer)
|
||||
{
|
||||
strlcpy(buffer, cheevo->description, len);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer)
|
||||
buffer[0] = '\0';
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void rcheevos_menu_reset_badges(void)
|
||||
{
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
rcheevos_racheevo_t* cheevo = rcheevos_locals->patchdata.core;
|
||||
rcheevos_racheevo_t* stop = cheevo + rcheevos_locals->patchdata.core_count;
|
||||
|
||||
while (cheevo < stop)
|
||||
{
|
||||
if (cheevo->menu_badge_texture)
|
||||
video_driver_texture_unload(&cheevo->menu_badge_texture);
|
||||
++cheevo;
|
||||
}
|
||||
|
||||
cheevo = rcheevos_locals->patchdata.unofficial;
|
||||
stop = cheevo + rcheevos_locals->patchdata.unofficial_count;
|
||||
|
||||
while (cheevo < stop)
|
||||
{
|
||||
if (cheevo->menu_badge_texture)
|
||||
video_driver_texture_unload(&cheevo->menu_badge_texture);
|
||||
++cheevo;
|
||||
}
|
||||
}
|
||||
|
||||
static rcheevos_menuitem_t* rcheevos_menu_allocate(
|
||||
rcheevos_locals_t* rcheevos_locals, rcheevos_racheevo_t* cheevo)
|
||||
{
|
||||
rcheevos_menuitem_t* menuitem;
|
||||
|
||||
if (rcheevos_locals->menuitem_count == rcheevos_locals->menuitem_capacity)
|
||||
{
|
||||
if (rcheevos_locals->menuitems)
|
||||
{
|
||||
rcheevos_menuitem_t* new_menuitems;
|
||||
rcheevos_locals->menuitem_capacity += 32;
|
||||
new_menuitems = (rcheevos_menuitem_t*)realloc(rcheevos_locals->menuitems,
|
||||
rcheevos_locals->menuitem_capacity * sizeof(rcheevos_menuitem_t));
|
||||
|
||||
if (new_menuitems)
|
||||
{
|
||||
rcheevos_locals->menuitems = new_menuitems;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* realloc failed */
|
||||
CHEEVOS_ERR(RCHEEVOS_TAG " could not allocate space for %u menu items\n",
|
||||
rcheevos_locals->menuitem_capacity);
|
||||
rcheevos_locals->menuitem_capacity -= 32;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rcheevos_locals->menuitem_capacity = 64;
|
||||
rcheevos_locals->menuitems = (rcheevos_menuitem_t*)
|
||||
malloc(rcheevos_locals->menuitem_capacity * sizeof(rcheevos_menuitem_t));
|
||||
|
||||
if (!rcheevos_locals->menuitems)
|
||||
{
|
||||
/* malloc failed */
|
||||
CHEEVOS_ERR(RCHEEVOS_TAG " could not allocate space for %u menu items\n",
|
||||
rcheevos_locals->menuitem_capacity);
|
||||
rcheevos_locals->menuitem_capacity = 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
menuitem = &rcheevos_locals->menuitems[rcheevos_locals->menuitem_count++];
|
||||
menuitem->cheevo = cheevo;
|
||||
menuitem->state_label_idx = MSG_UNKNOWN;
|
||||
return menuitem;
|
||||
}
|
||||
|
||||
static void rcheevos_menu_append_header(rcheevos_locals_t* rcheevos_locals,
|
||||
enum msg_hash_enums label)
|
||||
{
|
||||
rcheevos_menuitem_t* menuitem = rcheevos_menu_allocate(rcheevos_locals, NULL);
|
||||
if (menuitem)
|
||||
menuitem->state_label_idx = label;
|
||||
}
|
||||
|
||||
static void rcheevos_menu_update_badge(rcheevos_racheevo_t* cheevo)
|
||||
{
|
||||
bool badge_grayscale = false;
|
||||
switch (cheevo->menu_bucket)
|
||||
{
|
||||
case RCHEEVOS_MENUITEM_BUCKET_LOCKED:
|
||||
case RCHEEVOS_MENUITEM_BUCKET_UNSUPPORTED:
|
||||
case RCHEEVOS_MENUITEM_BUCKET_ALMOST_THERE:
|
||||
case RCHEEVOS_MENUITEM_BUCKET_ACTIVE_CHALLENGE:
|
||||
badge_grayscale = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
badge_grayscale = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!cheevo->menu_badge_texture || cheevo->menu_badge_grayscale != badge_grayscale)
|
||||
{
|
||||
uintptr_t new_badge_texture =
|
||||
rcheevos_get_badge_texture(cheevo->badge, badge_grayscale);
|
||||
|
||||
if (new_badge_texture)
|
||||
{
|
||||
if (cheevo->menu_badge_texture)
|
||||
video_driver_texture_unload(&cheevo->menu_badge_texture);
|
||||
|
||||
cheevo->menu_badge_texture = new_badge_texture;
|
||||
cheevo->menu_badge_grayscale = badge_grayscale;
|
||||
}
|
||||
/* menu_badge_grayscale is overloaded such that any value greater than 1 indicates
|
||||
* the server default image is being used */
|
||||
else if (cheevo->menu_badge_grayscale < 2)
|
||||
{
|
||||
if (cheevo->menu_badge_texture)
|
||||
video_driver_texture_unload(&cheevo->menu_badge_texture);
|
||||
|
||||
/* requested badge is not available, check for server default */
|
||||
cheevo->menu_badge_texture =
|
||||
rcheevos_get_badge_texture("00000", false);
|
||||
|
||||
if (cheevo->menu_badge_texture)
|
||||
cheevo->menu_badge_grayscale = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rcheevos_menu_append_items(rcheevos_locals_t* rcheevos_locals,
|
||||
bool cheevos_test_unofficial, enum rcheevos_menuitem_bucket bucket)
|
||||
{
|
||||
const settings_t *settings = config_get_ptr();
|
||||
rcheevos_racheevo_t* cheevo = rcheevos_locals->patchdata.core;
|
||||
rcheevos_racheevo_t* stop = cheevo + rcheevos_locals->patchdata.core_count;
|
||||
bool processing_unofficial = false;
|
||||
const unsigned first_index = rcheevos_locals->menuitem_count;
|
||||
|
||||
do
|
||||
{
|
||||
if (cheevo == stop)
|
||||
{
|
||||
if (!cheevos_test_unofficial || processing_unofficial)
|
||||
break;
|
||||
|
||||
processing_unofficial = true;
|
||||
cheevo = rcheevos_locals->patchdata.unofficial;
|
||||
stop = cheevo + rcheevos_locals->patchdata.unofficial_count;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cheevo->menu_bucket == bucket)
|
||||
{
|
||||
rcheevos_menuitem_t* menuitem = rcheevos_menu_allocate(rcheevos_locals, cheevo);
|
||||
if (!menuitem)
|
||||
return;
|
||||
|
||||
switch (cheevo->menu_bucket)
|
||||
{
|
||||
case RCHEEVOS_MENUITEM_BUCKET_UNSUPPORTED:
|
||||
menuitem->state_label_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_UNSUPPORTED_ENTRY;
|
||||
break;
|
||||
|
||||
case RCHEEVOS_MENUITEM_BUCKET_RECENTLY_UNLOCKED:
|
||||
{
|
||||
/* insert the item such that the unlock times are descending */
|
||||
unsigned entry_index = rcheevos_locals->menuitem_count - 1;
|
||||
while (entry_index > first_index)
|
||||
{
|
||||
rcheevos_menuitem_t* prev_menuitem = menuitem - 1;
|
||||
if (prev_menuitem->cheevo->unlock_time >= cheevo->unlock_time)
|
||||
break;
|
||||
|
||||
memcpy(menuitem, prev_menuitem, sizeof(rcheevos_menuitem_t));
|
||||
menuitem = prev_menuitem;
|
||||
--entry_index;
|
||||
}
|
||||
|
||||
menuitem->cheevo = cheevo;
|
||||
}
|
||||
/* fallthrough to RCHEEVOS_MENUITEM_BUCKET_UNLOCKED */
|
||||
|
||||
case RCHEEVOS_MENUITEM_BUCKET_UNLOCKED:
|
||||
if (!(cheevo->active & RCHEEVOS_ACTIVE_HARDCORE))
|
||||
menuitem->state_label_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ENTRY_HARDCORE;
|
||||
else
|
||||
menuitem->state_label_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ENTRY;
|
||||
break;
|
||||
|
||||
case RCHEEVOS_MENUITEM_BUCKET_ALMOST_THERE:
|
||||
{
|
||||
/* insert the item such that the progresses are descending */
|
||||
unsigned entry_index = rcheevos_locals->menuitem_count - 1;
|
||||
while (entry_index > first_index)
|
||||
{
|
||||
rcheevos_menuitem_t* prev_menuitem = menuitem - 1;
|
||||
if (prev_menuitem->cheevo->menu_progress >= cheevo->menu_progress)
|
||||
break;
|
||||
|
||||
memcpy(menuitem, prev_menuitem, sizeof(rcheevos_menuitem_t));
|
||||
menuitem = prev_menuitem;
|
||||
--entry_index;
|
||||
}
|
||||
|
||||
menuitem->cheevo = cheevo;
|
||||
}
|
||||
/* fallthrough to default */
|
||||
|
||||
default:
|
||||
if (processing_unofficial)
|
||||
menuitem->state_label_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_UNOFFICIAL_ENTRY;
|
||||
else if (!(cheevo->active & RCHEEVOS_ACTIVE_SOFTCORE))
|
||||
menuitem->state_label_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ENTRY;
|
||||
else
|
||||
menuitem->state_label_idx = MENU_ENUM_LABEL_VALUE_CHEEVOS_LOCKED_ENTRY;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cheevo->badge && cheevo->badge[0] && settings &&
|
||||
settings->bools.cheevos_badges_enable)
|
||||
{
|
||||
rcheevos_menu_update_badge(cheevo);
|
||||
}
|
||||
}
|
||||
|
||||
++cheevo;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
uintptr_t rcheevos_menu_get_badge_texture(unsigned menu_offset)
|
||||
{
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
if (menu_offset < rcheevos_locals->menuitem_count)
|
||||
{
|
||||
rcheevos_racheevo_t* cheevo = rcheevos_locals->menuitems[menu_offset].cheevo;
|
||||
if (cheevo)
|
||||
{
|
||||
/* if we're using the placeholder badge, check to see if the real badge
|
||||
* has become available (do this roughly once a second) */
|
||||
if (cheevo->menu_badge_grayscale >= 2)
|
||||
{
|
||||
if (++cheevo->menu_badge_grayscale == 64)
|
||||
{
|
||||
cheevo->menu_badge_grayscale = 2;
|
||||
rcheevos_menu_update_badge(cheevo);
|
||||
}
|
||||
}
|
||||
|
||||
return cheevo->menu_badge_texture;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rcheevos_menu_populate_hardcore_pause_submenu(void* data)
|
||||
{
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
menu_displaylist_info_t* info = (menu_displaylist_info_t*)data;
|
||||
const settings_t* settings = config_get_ptr();
|
||||
const bool cheevos_hardcore_mode_enable = settings->bools.cheevos_hardcore_mode_enable;
|
||||
|
||||
if (cheevos_hardcore_mode_enable && rcheevos_locals->loaded)
|
||||
{
|
||||
if (rcheevos_locals->hardcore_active)
|
||||
{
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_PAUSE_CANCEL),
|
||||
msg_hash_to_str(MENU_ENUM_SUBLABEL_ACHIEVEMENT_PAUSE_CANCEL),
|
||||
MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE_CANCEL,
|
||||
MENU_SETTING_ACTION_CLOSE, 0, 0);
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_PAUSE),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE),
|
||||
MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE,
|
||||
MENU_SETTING_ACTION_PAUSE_ACHIEVEMENTS, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_RESUME_CANCEL),
|
||||
msg_hash_to_str(MENU_ENUM_SUBLABEL_ACHIEVEMENT_RESUME_CANCEL),
|
||||
MENU_ENUM_LABEL_ACHIEVEMENT_RESUME_CANCEL,
|
||||
MENU_SETTING_ACTION_CLOSE, 0, 0);
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_RESUME),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_ACHIEVEMENT_RESUME),
|
||||
MENU_ENUM_LABEL_ACHIEVEMENT_RESUME,
|
||||
MENU_SETTING_ACTION_RESUME_ACHIEVEMENTS, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rcheevos_menu_populate(void* data)
|
||||
{
|
||||
menu_displaylist_info_t* info = (menu_displaylist_info_t*)data;
|
||||
rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
const settings_t* settings = config_get_ptr();
|
||||
const bool cheevos_test_unofficial = settings->bools.cheevos_test_unofficial;
|
||||
unsigned num_locked = 0;
|
||||
unsigned num_unlocked = 0;
|
||||
unsigned num_recently_unlocked = 0;
|
||||
unsigned num_unsupported = 0;
|
||||
unsigned num_active_challenges = 0;
|
||||
unsigned num_almost_there = 0;
|
||||
|
||||
if (rcheevos_locals->loaded)
|
||||
{
|
||||
const retro_time_t now = cpu_features_get_time_usec();
|
||||
const retro_time_t recent_unlock_time = now - (10 * 60 * 1000000); /* 10 minutes ago */
|
||||
bool processing_unofficial = false;
|
||||
rcheevos_racheevo_t* cheevo = NULL;
|
||||
rcheevos_racheevo_t* stop = NULL;
|
||||
|
||||
/* first menu item is the Pause/Resume Hardcore option (unless hardcore is disabled) */
|
||||
if (settings->bools.cheevos_enable && settings->bools.cheevos_hardcore_mode_enable)
|
||||
{
|
||||
if (rcheevos_locals->hardcore_active)
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_PAUSE),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_PAUSE_MENU),
|
||||
MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE_MENU,
|
||||
MENU_SETTING_ACTION_PAUSE_ACHIEVEMENTS, 0, 0);
|
||||
else
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_RESUME),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_PAUSE_MENU),
|
||||
MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE_MENU,
|
||||
MENU_SETTING_ACTION_RESUME_ACHIEVEMENTS, 0, 0);
|
||||
}
|
||||
|
||||
/* update the bucket for each achievement */
|
||||
rcheevos_menu_update_buckets(cheevos_test_unofficial);
|
||||
|
||||
/* count items in each bucket */
|
||||
cheevo = rcheevos_locals->patchdata.core;
|
||||
stop = cheevo + rcheevos_locals->patchdata.core_count;
|
||||
|
||||
do
|
||||
{
|
||||
if (cheevo == stop)
|
||||
{
|
||||
if (!cheevos_test_unofficial || processing_unofficial)
|
||||
break;
|
||||
|
||||
processing_unofficial = true;
|
||||
cheevo = rcheevos_locals->patchdata.unofficial;
|
||||
stop = cheevo + rcheevos_locals->patchdata.unofficial_count;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (cheevo->menu_bucket)
|
||||
{
|
||||
case RCHEEVOS_MENUITEM_BUCKET_UNLOCKED:
|
||||
if (cheevo->unlock_time && cheevo->unlock_time >= recent_unlock_time)
|
||||
{
|
||||
cheevo->menu_bucket = RCHEEVOS_MENUITEM_BUCKET_RECENTLY_UNLOCKED;
|
||||
++num_recently_unlocked;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_unlocked;
|
||||
}
|
||||
break;
|
||||
|
||||
case RCHEEVOS_MENUITEM_BUCKET_LOCKED:
|
||||
++num_locked;
|
||||
break;
|
||||
|
||||
case RCHEEVOS_MENUITEM_BUCKET_UNSUPPORTED:
|
||||
++num_unsupported;
|
||||
break;
|
||||
|
||||
case RCHEEVOS_MENUITEM_BUCKET_ACTIVE_CHALLENGE:
|
||||
++num_active_challenges;
|
||||
break;
|
||||
|
||||
case RCHEEVOS_MENUITEM_BUCKET_ALMOST_THERE:
|
||||
++num_almost_there;
|
||||
break;
|
||||
}
|
||||
|
||||
++cheevo;
|
||||
} while(true);
|
||||
|
||||
if (!rcheevos_locals->menuitems)
|
||||
{
|
||||
/* reserve space for all achievements and up to 6 headers before we need to realloc */
|
||||
rcheevos_locals->menuitem_capacity = rcheevos_locals->patchdata.core_count + 6;
|
||||
if (cheevos_test_unofficial)
|
||||
rcheevos_locals->menuitem_capacity += rcheevos_locals->patchdata.unofficial_count;
|
||||
|
||||
rcheevos_locals->menuitems = (rcheevos_menuitem_t*)
|
||||
malloc(rcheevos_locals->menuitem_capacity * sizeof(rcheevos_menuitem_t));
|
||||
if (!rcheevos_locals->menuitems)
|
||||
rcheevos_locals->menuitem_capacity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* reset menu */
|
||||
rcheevos_locals->menuitem_count = 0;
|
||||
|
||||
/* active challenges */
|
||||
if (num_active_challenges)
|
||||
{
|
||||
rcheevos_menu_append_header(rcheevos_locals,
|
||||
MENU_ENUM_LABEL_VALUE_CHEEVOS_ACTIVE_CHALLENGES_ENTRY);
|
||||
|
||||
rcheevos_menu_append_items(rcheevos_locals, cheevos_test_unofficial,
|
||||
RCHEEVOS_MENUITEM_BUCKET_ACTIVE_CHALLENGE);
|
||||
}
|
||||
|
||||
/* recently unlocked */
|
||||
if (num_recently_unlocked)
|
||||
{
|
||||
rcheevos_menu_append_header(rcheevos_locals,
|
||||
MENU_ENUM_LABEL_VALUE_CHEEVOS_RECENTLY_UNLOCKED_ENTRY);
|
||||
|
||||
rcheevos_menu_append_items(rcheevos_locals, cheevos_test_unofficial,
|
||||
RCHEEVOS_MENUITEM_BUCKET_RECENTLY_UNLOCKED);
|
||||
}
|
||||
|
||||
/* almost there */
|
||||
if (num_almost_there)
|
||||
{
|
||||
rcheevos_menu_append_header(rcheevos_locals,
|
||||
MENU_ENUM_LABEL_VALUE_CHEEVOS_ALMOST_THERE_ENTRY);
|
||||
|
||||
rcheevos_menu_append_items(rcheevos_locals, cheevos_test_unofficial,
|
||||
RCHEEVOS_MENUITEM_BUCKET_ALMOST_THERE);
|
||||
}
|
||||
|
||||
/* locked */
|
||||
if (num_locked)
|
||||
{
|
||||
if (rcheevos_locals->menuitem_count > 0)
|
||||
{
|
||||
rcheevos_menu_append_header(rcheevos_locals,
|
||||
MENU_ENUM_LABEL_VALUE_CHEEVOS_LOCKED_ENTRY);
|
||||
}
|
||||
|
||||
rcheevos_menu_append_items(rcheevos_locals, cheevos_test_unofficial,
|
||||
RCHEEVOS_MENUITEM_BUCKET_LOCKED);
|
||||
}
|
||||
|
||||
/* unlocked */
|
||||
if (num_unlocked)
|
||||
{
|
||||
if (rcheevos_locals->menuitem_count > 0)
|
||||
{
|
||||
rcheevos_menu_append_header(rcheevos_locals,
|
||||
MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ENTRY);
|
||||
}
|
||||
|
||||
rcheevos_menu_append_items(rcheevos_locals, cheevos_test_unofficial,
|
||||
RCHEEVOS_MENUITEM_BUCKET_UNLOCKED);
|
||||
}
|
||||
|
||||
if (rcheevos_locals->menuitem_count > 0)
|
||||
{
|
||||
/* convert to menu entries */
|
||||
rcheevos_menuitem_t* menuitem = rcheevos_locals->menuitems;
|
||||
rcheevos_menuitem_t* stop = menuitem + rcheevos_locals->menuitem_count;
|
||||
char buffer[128];
|
||||
unsigned idx = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (menuitem->cheevo)
|
||||
{
|
||||
menu_entries_append_enum(info->list, menuitem->cheevo->title,
|
||||
menuitem->cheevo->description,
|
||||
MENU_ENUM_LABEL_CHEEVOS_LOCKED_ENTRY,
|
||||
MENU_SETTINGS_CHEEVOS_START + idx, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(buffer, sizeof(buffer), "----- %s -----",
|
||||
msg_hash_to_str(menuitem->state_label_idx));
|
||||
|
||||
menu_entries_append_enum(info->list, buffer, "",
|
||||
MENU_ENUM_LABEL_CHEEVOS_LOCKED_ENTRY,
|
||||
MENU_SETTINGS_CHEEVOS_START + idx, 0, 0);
|
||||
}
|
||||
|
||||
++idx;
|
||||
++menuitem;
|
||||
} while (menuitem != stop);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no achievements found */
|
||||
if (!rcheevos_locals->core_supports)
|
||||
{
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CANNOT_ACTIVATE_ACHIEVEMENTS_WITH_THIS_CORE),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_CANNOT_ACTIVATE_ACHIEVEMENTS_WITH_THIS_CORE),
|
||||
MENU_ENUM_LABEL_CANNOT_ACTIVATE_ACHIEVEMENTS_WITH_THIS_CORE,
|
||||
FILE_TYPE_NONE, 0, 0);
|
||||
}
|
||||
else if (rcheevos_locals->network_error)
|
||||
{
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETWORK_ERROR),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_NETWORK_ERROR),
|
||||
MENU_ENUM_LABEL_NETWORK_ERROR,
|
||||
FILE_TYPE_NONE, 0, 0);
|
||||
}
|
||||
else if (!rcheevos_locals->patchdata.game_id)
|
||||
{
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UNKNOWN_GAME),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_UNKNOWN_GAME),
|
||||
MENU_ENUM_LABEL_UNKNOWN_GAME,
|
||||
FILE_TYPE_NONE, 0, 0);
|
||||
}
|
||||
else if (!rcheevos_locals->token[0])
|
||||
{
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_LOGGED_IN),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_NOT_LOGGED_IN),
|
||||
MENU_ENUM_LABEL_NOT_LOGGED_IN,
|
||||
FILE_TYPE_NONE, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ACHIEVEMENTS_TO_DISPLAY),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_NO_ACHIEVEMENTS_TO_DISPLAY),
|
||||
MENU_ENUM_LABEL_NO_ACHIEVEMENTS_TO_DISPLAY,
|
||||
FILE_TYPE_NONE, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_MENU */
|
||||
|
||||
uintptr_t rcheevos_get_badge_texture(const char *badge, bool locked)
|
||||
{
|
||||
char badge_file[24];
|
||||
char fullpath[PATH_MAX_LENGTH];
|
||||
uintptr_t tex = 0;
|
||||
|
||||
if (!badge)
|
||||
return 0;
|
||||
|
||||
snprintf(badge_file, sizeof(badge_file), "%s%s%s", badge,
|
||||
locked ? "_lock" : "", FILE_PATH_PNG_EXTENSION);
|
||||
|
||||
fill_pathname_application_special(fullpath, sizeof(fullpath),
|
||||
APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_CHEEVOS_BADGES);
|
||||
|
||||
if (!gfx_display_reset_textures_list(badge_file, fullpath,
|
||||
&tex, TEXTURE_FILTER_MIPMAP_LINEAR, NULL, NULL))
|
||||
{
|
||||
tex = 0;
|
||||
}
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2018 - Andre Leiradella
|
||||
* Copyright (C) 2019-2021 - Brian Weiss
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
@@ -12,33 +13,29 @@
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef __RARCH_CHEEVOS_MEMORY_H
|
||||
#define __RARCH_CHEEVOS_MEMORY_H
|
||||
|
||||
#ifndef __RARCH_CHEEVOS_MENU_H
|
||||
#define __RARCH_CHEEVOS_MENU_H
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <boolean.h>
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
#define MAX_MEMORY_REGIONS 32
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t* data[MAX_MEMORY_REGIONS];
|
||||
size_t size[MAX_MEMORY_REGIONS];
|
||||
size_t total_size;
|
||||
unsigned count;
|
||||
} rcheevos_memory_regions_t;
|
||||
|
||||
bool rcheevos_memory_init(rcheevos_memory_regions_t* regions, int console);
|
||||
void rcheevos_memory_destroy(rcheevos_memory_regions_t* regions);
|
||||
|
||||
uint8_t* rcheevos_memory_find(const rcheevos_memory_regions_t* regions,
|
||||
unsigned address);
|
||||
void rcheevos_menu_populate(void* data);
|
||||
void rcheevos_menu_populate_hardcore_pause_submenu(void* data);
|
||||
bool rcheevos_menu_get_state(unsigned menu_offset, char* buffer, size_t buffer_size);
|
||||
bool rcheevos_menu_get_sublabel(unsigned menu_offset, char* buffer, size_t buffer_size);
|
||||
uintptr_t rcheevos_menu_get_badge_texture(unsigned menu_offset);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
#endif /* HAVE_MENU */
|
||||
|
||||
#endif /* __RARCH_CHEEVOS_MENU_H */
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "cheevos_parser.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "cheevos_locals.h"
|
||||
|
||||
#include <encodings/utf.h>
|
||||
#include <formats/rjson.h>
|
||||
@@ -23,6 +23,7 @@
|
||||
#define CHEEVOS_JSON_KEY_BADGENAME 0x887685d9U
|
||||
#define CHEEVOS_JSON_KEY_CONSOLE_ID 0x071656e5U
|
||||
#define CHEEVOS_JSON_KEY_TOKEN 0x0e2dbd26U
|
||||
#define CHEEVOS_JSON_KEY_USERNAME 0x7c8da264U
|
||||
#define CHEEVOS_JSON_KEY_FLAGS 0x0d2e96b2U
|
||||
#define CHEEVOS_JSON_KEY_LEADERBOARDS 0xf1247d2dU
|
||||
#define CHEEVOS_JSON_KEY_RICHPRESENCE 0xf18dd230U
|
||||
@@ -149,14 +150,16 @@ static int rcheevos_get_value(const char* json, unsigned key_hash,
|
||||
Returns the token or the error message
|
||||
*****************************************************************************/
|
||||
|
||||
int rcheevos_get_token(const char* json, char* token, size_t length)
|
||||
int rcheevos_get_token(const char* json, char* username, size_t username_length,
|
||||
char* token, size_t length)
|
||||
{
|
||||
rcheevos_get_value(json, CHEEVOS_JSON_KEY_ERROR, token, length);
|
||||
|
||||
if (!string_is_empty(token))
|
||||
return -1;
|
||||
|
||||
return rcheevos_get_value(json, CHEEVOS_JSON_KEY_TOKEN, token, length);
|
||||
return rcheevos_get_value(json, CHEEVOS_JSON_KEY_TOKEN, token, length) +
|
||||
rcheevos_get_value(json, CHEEVOS_JSON_KEY_USERNAME, username, username_length);
|
||||
}
|
||||
|
||||
int rcheevos_get_json_error(const char* json, char* token, size_t length)
|
||||
|
||||
@@ -16,53 +16,16 @@
|
||||
#ifndef __RARCH_CHEEVOS_PARSER_H
|
||||
#define __RARCH_CHEEVOS_PARSER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <boolean.h>
|
||||
|
||||
#include <retro_common_api.h>
|
||||
#include "cheevos_locals.h"
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char* title;
|
||||
const char* description;
|
||||
const char* badge;
|
||||
const char* memaddr;
|
||||
unsigned points;
|
||||
unsigned id;
|
||||
unsigned active;
|
||||
} rcheevos_racheevo_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char* title;
|
||||
const char* description;
|
||||
const char* mem;
|
||||
unsigned id;
|
||||
unsigned format;
|
||||
} rcheevos_ralboard_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char* title;
|
||||
rcheevos_racheevo_t* core;
|
||||
rcheevos_racheevo_t* unofficial;
|
||||
rcheevos_ralboard_t* lboards;
|
||||
char* richpresence_script;
|
||||
|
||||
unsigned game_id;
|
||||
unsigned console_id;
|
||||
unsigned core_count;
|
||||
unsigned unofficial_count;
|
||||
unsigned lboard_count;
|
||||
} rcheevos_rapatchdata_t;
|
||||
|
||||
typedef void (*rcheevos_unlock_cb_t)(unsigned id, void* userdata);
|
||||
|
||||
int rcheevos_get_json_error(const char* json, char* token, size_t length);
|
||||
int rcheevos_get_token(const char* json, char* token, size_t length);
|
||||
|
||||
int rcheevos_get_token(const char* json, char* username, size_t username_length,
|
||||
char* token, size_t length);
|
||||
|
||||
int rcheevos_get_patchdata(const char* json, rcheevos_rapatchdata_t* patchdata);
|
||||
void rcheevos_free_patchdata(rcheevos_rapatchdata_t* patchdata);
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2015-2016 - Andre Leiradella
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __RARCH_CHEEVOS_UTIL_H
|
||||
#define __RARCH_CHEEVOS_UTIL_H
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
/*****************************************************************************
|
||||
Setup - mainly for debugging
|
||||
*****************************************************************************/
|
||||
|
||||
/* Define this macro to get extra-verbose log for cheevos. */
|
||||
#define CHEEVOS_VERBOSE
|
||||
|
||||
/*****************************************************************************
|
||||
End of setup
|
||||
*****************************************************************************/
|
||||
|
||||
#define RCHEEVOS_TAG "[RCHEEVOS]: "
|
||||
#define CHEEVOS_FREE(p) do { void* q = (void*)p; if (q) free(q); } while (0)
|
||||
|
||||
#ifdef CHEEVOS_VERBOSE
|
||||
|
||||
#define CHEEVOS_LOG RARCH_LOG
|
||||
#define CHEEVOS_ERR RARCH_ERR
|
||||
|
||||
#else
|
||||
|
||||
#define CHEEVOS_LOG rcheevos_log
|
||||
#define CHEEVOS_ERR RARCH_ERR
|
||||
|
||||
void rcheevos_log(const char *fmt, ...);
|
||||
|
||||
#endif
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif /* __RARCH_CHEEVOS_UTIL_H */
|
||||
@@ -0,0 +1,535 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2017 - Daniel De Matteis
|
||||
* Copyright (C) 2021 - David G.F.
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#ifdef HAVE_NETWORKING
|
||||
#include <net/net_compat.h>
|
||||
#include <net/net_socket.h>
|
||||
#endif
|
||||
#include <streams/stdin_stream.h>
|
||||
#include <string/stdstring.h>
|
||||
|
||||
#include "verbosity.h"
|
||||
#include "command.h"
|
||||
|
||||
#define CMD_BUF_SIZE 4096
|
||||
|
||||
#if defined(HAVE_COMMAND)
|
||||
|
||||
/* Generic command parse utilities */
|
||||
|
||||
static bool command_get_arg(const char *tok,
|
||||
const char **arg, unsigned *index)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(map); i++)
|
||||
{
|
||||
if (string_is_equal(tok, map[i].str))
|
||||
{
|
||||
if (arg)
|
||||
*arg = NULL;
|
||||
|
||||
if (index)
|
||||
*index = i;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(action_map); i++)
|
||||
{
|
||||
const char *str = strstr(tok, action_map[i].str);
|
||||
if (str == tok)
|
||||
{
|
||||
const char *argument = str + strlen(action_map[i].str);
|
||||
if (*argument != ' ' && *argument != '\0')
|
||||
return false;
|
||||
|
||||
if (arg)
|
||||
*arg = argument + 1;
|
||||
|
||||
if (index)
|
||||
*index = i;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void command_parse_sub_msg(command_t *handle, const char *tok)
|
||||
{
|
||||
const char *arg = NULL;
|
||||
unsigned index = 0;
|
||||
|
||||
if (command_get_arg(tok, &arg, &index))
|
||||
{
|
||||
if (arg)
|
||||
{
|
||||
if (!action_map[index].action(handle, arg))
|
||||
RARCH_ERR("Command \"%s\" failed.\n", arg);
|
||||
}
|
||||
else
|
||||
handle->state[map[index].id] = true;
|
||||
}
|
||||
else
|
||||
RARCH_WARN("%s \"%s\" %s.\n",
|
||||
msg_hash_to_str(MSG_UNRECOGNIZED_COMMAND),
|
||||
tok,
|
||||
msg_hash_to_str(MSG_RECEIVED));
|
||||
}
|
||||
|
||||
static void command_parse_msg(
|
||||
command_t *handle, char *buf)
|
||||
{
|
||||
char *save = NULL;
|
||||
const char *tok = strtok_r(buf, "\n", &save);
|
||||
|
||||
while (tok)
|
||||
{
|
||||
command_parse_sub_msg(handle, tok);
|
||||
tok = strtok_r(NULL, "\n", &save);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HAVE_NETWORK_CMD)
|
||||
typedef struct
|
||||
{
|
||||
/* Network socket FD */
|
||||
int net_fd;
|
||||
/* Source address for the command received */
|
||||
struct sockaddr_storage cmd_source;
|
||||
/* Size of the previous structure in use */
|
||||
socklen_t cmd_source_len;
|
||||
} command_network_t;
|
||||
|
||||
static void network_command_reply(
|
||||
command_t *cmd,
|
||||
const char * data, size_t len)
|
||||
{
|
||||
command_network_t *netcmd = (command_network_t*)cmd->userptr;
|
||||
/* Respond (fire and forget since it's UDP) */
|
||||
sendto(netcmd->net_fd, data, len, 0,
|
||||
(struct sockaddr*)&netcmd->cmd_source, netcmd->cmd_source_len);
|
||||
}
|
||||
|
||||
static void network_command_free(command_t *handle)
|
||||
{
|
||||
command_network_t *netcmd = (command_network_t*)handle->userptr;
|
||||
|
||||
if (netcmd->net_fd >= 0)
|
||||
socket_close(netcmd->net_fd);
|
||||
|
||||
free(netcmd);
|
||||
free(handle);
|
||||
}
|
||||
|
||||
static void command_network_poll(command_t *handle)
|
||||
{
|
||||
fd_set fds;
|
||||
struct timeval tmp_tv = {0};
|
||||
command_network_t *netcmd = (command_network_t*)handle->userptr;
|
||||
|
||||
if (netcmd->net_fd < 0)
|
||||
return;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(netcmd->net_fd, &fds);
|
||||
|
||||
if (socket_select(netcmd->net_fd + 1, &fds, NULL, NULL, &tmp_tv) <= 0)
|
||||
return;
|
||||
|
||||
if (!FD_ISSET(netcmd->net_fd, &fds))
|
||||
return;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
ssize_t ret;
|
||||
char buf[1024];
|
||||
|
||||
buf[0] = '\0';
|
||||
netcmd->cmd_source_len = sizeof(struct sockaddr_storage);
|
||||
ret = recvfrom(netcmd->net_fd, buf, sizeof(buf) - 1, 0,
|
||||
(struct sockaddr*)&netcmd->cmd_source,
|
||||
&netcmd->cmd_source_len);
|
||||
|
||||
if (ret <= 0)
|
||||
break;
|
||||
|
||||
buf[ret] = '\0';
|
||||
|
||||
command_parse_msg(handle, buf);
|
||||
}
|
||||
}
|
||||
|
||||
command_t* command_network_new(uint16_t port)
|
||||
{
|
||||
struct addrinfo *res = NULL;
|
||||
command_t *cmd = (command_t*)calloc(1, sizeof(command_t));
|
||||
command_network_t *netcmd = (command_network_t*)calloc(
|
||||
1, sizeof(command_network_t));
|
||||
int fd = socket_init(
|
||||
(void**)&res, port, NULL, SOCKET_TYPE_DATAGRAM);
|
||||
|
||||
RARCH_LOG("%s %hu.\n",
|
||||
msg_hash_to_str(MSG_BRINGING_UP_COMMAND_INTERFACE_ON_PORT),
|
||||
(unsigned short)port);
|
||||
|
||||
if (fd < 0)
|
||||
goto error;
|
||||
|
||||
netcmd->net_fd = fd;
|
||||
cmd->userptr = netcmd;
|
||||
cmd->poll = command_network_poll;
|
||||
cmd->replier = network_command_reply;
|
||||
cmd->destroy = network_command_free;
|
||||
|
||||
if (!socket_nonblock(netcmd->net_fd))
|
||||
goto error;
|
||||
|
||||
if (!socket_bind(netcmd->net_fd, (void*)res))
|
||||
{
|
||||
RARCH_ERR("%s.\n",
|
||||
msg_hash_to_str(MSG_FAILED_TO_BIND_SOCKET));
|
||||
goto error;
|
||||
}
|
||||
|
||||
freeaddrinfo_retro(res);
|
||||
return cmd;
|
||||
|
||||
error:
|
||||
if (res)
|
||||
freeaddrinfo_retro(res);
|
||||
free(netcmd);
|
||||
free(cmd);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(HAVE_STDIN_CMD)
|
||||
typedef struct
|
||||
{
|
||||
/* Buffer and pointer for stdin reads */
|
||||
size_t stdin_buf_ptr;
|
||||
char stdin_buf[CMD_BUF_SIZE];
|
||||
} command_stdin_t;
|
||||
|
||||
static void stdin_command_reply(
|
||||
command_t *cmd,
|
||||
const char * data, size_t len)
|
||||
{
|
||||
/* Just write to stdout! */
|
||||
fwrite(data, 1, len, stdout);
|
||||
}
|
||||
|
||||
static void stdin_command_free(command_t *handle)
|
||||
{
|
||||
free(handle->userptr);
|
||||
free(handle);
|
||||
}
|
||||
|
||||
static void command_stdin_poll(command_t *handle)
|
||||
{
|
||||
ptrdiff_t msg_len;
|
||||
char *last_newline = NULL;
|
||||
command_stdin_t *stdincmd = (command_stdin_t*)handle->userptr;
|
||||
ssize_t ret = read_stdin(
|
||||
stdincmd->stdin_buf + stdincmd->stdin_buf_ptr,
|
||||
CMD_BUF_SIZE - stdincmd->stdin_buf_ptr - 1);
|
||||
|
||||
if (ret == 0)
|
||||
return;
|
||||
|
||||
stdincmd->stdin_buf_ptr += ret;
|
||||
stdincmd->stdin_buf[stdincmd->stdin_buf_ptr] = '\0';
|
||||
|
||||
last_newline = strrchr(stdincmd->stdin_buf, '\n');
|
||||
|
||||
if (!last_newline)
|
||||
{
|
||||
/* We're receiving bogus data in pipe
|
||||
* (no terminating newline), flush out the buffer. */
|
||||
if (stdincmd->stdin_buf_ptr + 1 >= CMD_BUF_SIZE)
|
||||
{
|
||||
stdincmd->stdin_buf_ptr = 0;
|
||||
stdincmd->stdin_buf[0] = '\0';
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
*last_newline++ = '\0';
|
||||
msg_len = last_newline - stdincmd->stdin_buf;
|
||||
|
||||
command_parse_msg(handle, stdincmd->stdin_buf);
|
||||
|
||||
memmove(stdincmd->stdin_buf, last_newline,
|
||||
stdincmd->stdin_buf_ptr - msg_len);
|
||||
stdincmd->stdin_buf_ptr -= msg_len;
|
||||
}
|
||||
|
||||
command_t* command_stdin_new(void)
|
||||
{
|
||||
command_t *cmd;
|
||||
command_stdin_t *stdincmd;
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifdef HAVE_NETWORKING
|
||||
if (!socket_nonblock(STDIN_FILENO))
|
||||
return NULL;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
cmd = (command_t*)calloc(1, sizeof(command_t));
|
||||
stdincmd = (command_stdin_t*)calloc(1, sizeof(command_stdin_t));
|
||||
cmd->userptr = stdincmd;
|
||||
cmd->poll = command_stdin_poll;
|
||||
cmd->replier = stdin_command_reply;
|
||||
cmd->destroy = stdin_command_free;
|
||||
|
||||
return cmd;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_LAKKA)
|
||||
#include <sys/un.h>
|
||||
#define MAX_USER_CONNECTIONS 4
|
||||
typedef struct
|
||||
{
|
||||
/* File descriptor for the domain socket */
|
||||
int sfd;
|
||||
/* Client sockets */
|
||||
int userfd[MAX_USER_CONNECTIONS];
|
||||
/* Last received user socket */
|
||||
int last_fd;
|
||||
} command_uds_t;
|
||||
|
||||
static void uds_command_reply(
|
||||
command_t *cmd,
|
||||
const char * data, size_t len)
|
||||
{
|
||||
command_uds_t *subcmd = (command_uds_t*)cmd->userptr;
|
||||
write(subcmd->last_fd, data, len);
|
||||
}
|
||||
|
||||
static void uds_command_free(command_t *handle)
|
||||
{
|
||||
int i;
|
||||
command_uds_t *udscmd = (command_uds_t*)handle->userptr;
|
||||
|
||||
for (i = 0; i < MAX_USER_CONNECTIONS; i++)
|
||||
if (udscmd->userfd[i] >= 0)
|
||||
socket_close(udscmd->userfd[i]);
|
||||
socket_close(udscmd->sfd);
|
||||
|
||||
free(handle->userptr);
|
||||
free(handle);
|
||||
}
|
||||
|
||||
static void command_uds_poll(command_t *handle)
|
||||
{
|
||||
int i;
|
||||
fd_set fds;
|
||||
command_uds_t *udscmd = (command_uds_t*)handle->userptr;
|
||||
int maxfd = udscmd->sfd;
|
||||
struct timeval tmp_tv = {0};
|
||||
|
||||
if (udscmd->sfd < 0)
|
||||
return;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(udscmd->sfd, &fds);
|
||||
|
||||
for (i = 0; i < MAX_USER_CONNECTIONS; i++)
|
||||
{
|
||||
if (udscmd->userfd[i] >= 0)
|
||||
{
|
||||
maxfd = MAX(udscmd->userfd[i], maxfd);
|
||||
FD_SET(udscmd->userfd[i], &fds);
|
||||
}
|
||||
}
|
||||
|
||||
if (socket_select(maxfd + 1, &fds, NULL, NULL, &tmp_tv) <= 0)
|
||||
return;
|
||||
|
||||
/* Read data from clients and process commands */
|
||||
for (i = 0; i < MAX_USER_CONNECTIONS; i++)
|
||||
{
|
||||
if (udscmd->userfd[i] >= 0 && FD_ISSET(udscmd->userfd[i], &fds))
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
char buf[2048];
|
||||
ssize_t ret = recv(udscmd->userfd[i], buf, sizeof(buf) - 1, 0);
|
||||
|
||||
if (ret < 0)
|
||||
break; /* no more data */
|
||||
if (!ret)
|
||||
{
|
||||
socket_close(udscmd->userfd[i]);
|
||||
udscmd->userfd[i] = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
buf[ret] = 0;
|
||||
udscmd->last_fd = udscmd->userfd[i];
|
||||
command_parse_msg(handle, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (FD_ISSET(udscmd->sfd, &fds))
|
||||
{
|
||||
/* Accepts new connections from clients */
|
||||
int cfd = accept(udscmd->sfd, NULL, NULL);
|
||||
if (cfd >= 0) {
|
||||
if (!socket_nonblock(cfd))
|
||||
socket_close(cfd);
|
||||
else {
|
||||
for (i = 0; i < MAX_USER_CONNECTIONS; i++)
|
||||
if (udscmd->userfd[i] < 0)
|
||||
{
|
||||
udscmd->userfd[i] = cfd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
command_t* command_uds_new(void)
|
||||
{
|
||||
int i;
|
||||
command_t *cmd;
|
||||
command_uds_t *subcmd;
|
||||
struct sockaddr_un addr;
|
||||
const char *sp = "retroarch/cmd";
|
||||
socklen_t addrsz = offsetof(struct sockaddr_un, sun_path) + strlen(sp) + 1;
|
||||
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
|
||||
/* use an abstract socket for simplicity */
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
strcpy(&addr.sun_path[1], sp);
|
||||
|
||||
if (bind(fd, (struct sockaddr*)&addr, addrsz) < 0 ||
|
||||
listen(fd, MAX_USER_CONNECTIONS) < 0)
|
||||
{
|
||||
socket_close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!socket_nonblock(fd))
|
||||
{
|
||||
socket_close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cmd = (command_t*)calloc(1, sizeof(command_t));
|
||||
subcmd = (command_uds_t*)calloc(1, sizeof(command_uds_t));
|
||||
subcmd->sfd = fd;
|
||||
subcmd->last_fd = -1;
|
||||
for (i = 0; i < MAX_USER_CONNECTIONS; i++)
|
||||
subcmd->userfd[i] = -1;
|
||||
|
||||
cmd->userptr = subcmd;
|
||||
cmd->poll = command_uds_poll;
|
||||
cmd->replier = uds_command_reply;
|
||||
cmd->destroy = uds_command_free;
|
||||
|
||||
return cmd;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Routines used to invoke retroarch command ... */
|
||||
|
||||
#ifdef HAVE_NETWORK_CMD
|
||||
static bool command_verify(const char *cmd)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
if (command_get_arg(cmd, NULL, NULL))
|
||||
return true;
|
||||
|
||||
RARCH_ERR("Command \"%s\" is not recognized by the program.\n", cmd);
|
||||
RARCH_ERR("\tValid commands:\n");
|
||||
for (i = 0; i < ARRAY_SIZE(map); i++)
|
||||
RARCH_ERR("\t\t%s\n", map[i].str);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(action_map); i++)
|
||||
RARCH_ERR("\t\t%s %s\n", action_map[i].str, action_map[i].arg_desc);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool command_network_send(const char *cmd_)
|
||||
{
|
||||
char *command = NULL;
|
||||
char *save = NULL;
|
||||
const char *cmd = NULL;
|
||||
|
||||
if (!network_init())
|
||||
return false;
|
||||
|
||||
if (!(command = strdup(cmd_)))
|
||||
return false;
|
||||
|
||||
cmd = strtok_r(command, ";", &save);
|
||||
if (cmd)
|
||||
{
|
||||
uint16_t port = DEFAULT_NETWORK_CMD_PORT;
|
||||
const char *port_ = NULL;
|
||||
const char *host = strtok_r(NULL, ";", &save);
|
||||
if (host)
|
||||
port_ = strtok_r(NULL, ";", &save);
|
||||
else
|
||||
{
|
||||
#ifdef _WIN32
|
||||
host = "127.0.0.1";
|
||||
#else
|
||||
host = "localhost";
|
||||
#endif
|
||||
}
|
||||
|
||||
if (port_)
|
||||
port = strtoul(port_, NULL, 0);
|
||||
|
||||
RARCH_LOG("%s: \"%s\" to %s:%hu\n",
|
||||
msg_hash_to_str(MSG_SENDING_COMMAND),
|
||||
cmd, host, (unsigned short)port);
|
||||
|
||||
if (command_verify(cmd) && udp_send_packet(host, port, cmd))
|
||||
{
|
||||
free(command);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
free(command);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,7 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2016 - Daniel De Matteis
|
||||
* Copyright (C) 2016-2019 - Brad Parker
|
||||
* Copyright (C) 2021 - David G.F.
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
@@ -23,12 +23,46 @@
|
||||
#include <boolean.h>
|
||||
#include <retro_common_api.h>
|
||||
|
||||
#include "retroarch.h"
|
||||
#include "input/input_defines.h"
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
#define MAX_CMD_DRIVERS 3
|
||||
#define DEFAULT_NETWORK_CMD_PORT 55355
|
||||
|
||||
struct cmd_map
|
||||
{
|
||||
const char *str;
|
||||
unsigned id;
|
||||
};
|
||||
|
||||
struct command_handler;
|
||||
|
||||
typedef void (*command_poller_t)(struct command_handler *cmd);
|
||||
typedef void (*command_replier_t)(struct command_handler *cmd, const char * data, size_t len);
|
||||
typedef void (*command_destructor_t)(struct command_handler *cmd);
|
||||
|
||||
struct command_handler
|
||||
{
|
||||
/* Interface to poll the driver */
|
||||
command_poller_t poll;
|
||||
/* Interface to reply */
|
||||
command_replier_t replier;
|
||||
/* Interface to delete the underlying command */
|
||||
command_destructor_t destroy;
|
||||
/* Underlying command storage */
|
||||
void *userptr;
|
||||
/* State received */
|
||||
bool state[RARCH_BIND_LIST_END];
|
||||
};
|
||||
|
||||
typedef struct command_handler command_t;
|
||||
|
||||
enum event_command
|
||||
{
|
||||
CMD_EVENT_NONE = 0,
|
||||
@@ -166,7 +200,6 @@ enum event_command
|
||||
CMD_EVENT_AUDIO_REINIT,
|
||||
/* Resizes windowed scale. Will reinitialize video driver. */
|
||||
CMD_EVENT_RESIZE_WINDOWED_SCALE,
|
||||
CMD_EVENT_LOG_FILE_DEINIT,
|
||||
/* Toggles disk eject. */
|
||||
CMD_EVENT_DISK_EJECT_TOGGLE,
|
||||
/* Cycle to next disk. */
|
||||
@@ -205,17 +238,25 @@ enum event_command
|
||||
CMD_EVENT_CHEAT_INDEX_MINUS,
|
||||
CMD_EVENT_CHEAT_TOGGLE,
|
||||
CMD_EVENT_AI_SERVICE_CALL,
|
||||
CMD_EVENT_SAVE_FILES
|
||||
CMD_EVENT_SAVE_FILES,
|
||||
CMD_EVENT_CONTROLLER_INIT
|
||||
};
|
||||
|
||||
typedef struct command command_t;
|
||||
|
||||
typedef struct command_handle
|
||||
{
|
||||
command_t *handle;
|
||||
unsigned id;
|
||||
} command_handle_t;
|
||||
|
||||
enum cmd_source_t
|
||||
{
|
||||
CMD_NONE = 0,
|
||||
CMD_STDIN,
|
||||
CMD_NETWORK
|
||||
};
|
||||
|
||||
struct rarch_state;
|
||||
|
||||
/**
|
||||
* command_event:
|
||||
* @cmd : Command index.
|
||||
@@ -226,6 +267,107 @@ typedef struct command_handle
|
||||
**/
|
||||
bool command_event(enum event_command action, void *data);
|
||||
|
||||
/* Constructors for the supported drivers */
|
||||
command_t* command_network_new(uint16_t port);
|
||||
command_t* command_stdin_new(void);
|
||||
command_t* command_uds_new(void);
|
||||
|
||||
bool command_network_send(const char *cmd_);
|
||||
|
||||
/* These forward declarations need to be declared before
|
||||
* the global state is declared */
|
||||
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
|
||||
bool command_set_shader(command_t *cmd, const char *arg);
|
||||
#endif
|
||||
#if defined(HAVE_COMMAND)
|
||||
bool command_version(command_t *cmd, const char* arg);
|
||||
bool command_get_status(command_t *cmd, const char* arg);
|
||||
bool command_get_config_param(command_t *cmd, const char* arg);
|
||||
bool command_show_osd_msg(command_t *cmd, const char* arg);
|
||||
#ifdef HAVE_CHEEVOS
|
||||
bool command_read_ram(command_t *cmd, const char *arg);
|
||||
bool command_write_ram(command_t *cmd, const char *arg);
|
||||
#endif
|
||||
bool command_read_memory(command_t *cmd, const char *arg);
|
||||
bool command_write_memory(command_t *cmd, const char *arg);
|
||||
|
||||
struct cmd_action_map
|
||||
{
|
||||
const char *str;
|
||||
bool (*action)(command_t* cmd, const char *arg);
|
||||
const char *arg_desc;
|
||||
};
|
||||
|
||||
static const struct cmd_action_map action_map[] = {
|
||||
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
|
||||
{ "SET_SHADER", command_set_shader, "<shader path>" },
|
||||
#endif
|
||||
{ "VERSION", command_version, "No argument"},
|
||||
{ "GET_STATUS", command_get_status, "No argument" },
|
||||
{ "GET_CONFIG_PARAM", command_get_config_param, "<param name>" },
|
||||
{ "SHOW_MSG", command_show_osd_msg, "No argument" },
|
||||
#if defined(HAVE_CHEEVOS)
|
||||
/* These functions use achievement addresses and only work if a game with achievements is
|
||||
* loaded. READ_CORE_MEMORY and WRITE_CORE_MEMORY are preferred and use system addresses. */
|
||||
{ "READ_CORE_RAM", command_read_ram, "<address> <number of bytes>" },
|
||||
{ "WRITE_CORE_RAM", command_write_ram, "<address> <byte1> <byte2> ..." },
|
||||
#endif
|
||||
{ "READ_CORE_MEMORY", command_read_memory, "<address> <number of bytes>" },
|
||||
{ "WRITE_CORE_MEMORY",command_write_memory, "<address> <byte1> <byte2> ..." },
|
||||
};
|
||||
|
||||
static const struct cmd_map map[] = {
|
||||
{ "FAST_FORWARD", RARCH_FAST_FORWARD_KEY },
|
||||
{ "FAST_FORWARD_HOLD", RARCH_FAST_FORWARD_HOLD_KEY },
|
||||
{ "SLOWMOTION", RARCH_SLOWMOTION_KEY },
|
||||
{ "SLOWMOTION_HOLD", RARCH_SLOWMOTION_HOLD_KEY },
|
||||
{ "LOAD_STATE", RARCH_LOAD_STATE_KEY },
|
||||
{ "SAVE_STATE", RARCH_SAVE_STATE_KEY },
|
||||
{ "FULLSCREEN_TOGGLE", RARCH_FULLSCREEN_TOGGLE_KEY },
|
||||
{ "CLOSE_CONTENT", RARCH_CLOSE_CONTENT_KEY },
|
||||
{ "QUIT", RARCH_QUIT_KEY },
|
||||
{ "STATE_SLOT_PLUS", RARCH_STATE_SLOT_PLUS },
|
||||
{ "STATE_SLOT_MINUS", RARCH_STATE_SLOT_MINUS },
|
||||
{ "REWIND", RARCH_REWIND },
|
||||
{ "BSV_RECORD_TOGGLE", RARCH_BSV_RECORD_TOGGLE },
|
||||
{ "PAUSE_TOGGLE", RARCH_PAUSE_TOGGLE },
|
||||
{ "FRAMEADVANCE", RARCH_FRAMEADVANCE },
|
||||
{ "RESET", RARCH_RESET },
|
||||
{ "SHADER_NEXT", RARCH_SHADER_NEXT },
|
||||
{ "SHADER_PREV", RARCH_SHADER_PREV },
|
||||
{ "CHEAT_INDEX_PLUS", RARCH_CHEAT_INDEX_PLUS },
|
||||
{ "CHEAT_INDEX_MINUS", RARCH_CHEAT_INDEX_MINUS },
|
||||
{ "CHEAT_TOGGLE", RARCH_CHEAT_TOGGLE },
|
||||
{ "SCREENSHOT", RARCH_SCREENSHOT },
|
||||
{ "MUTE", RARCH_MUTE },
|
||||
{ "OSK", RARCH_OSK },
|
||||
{ "FPS_TOGGLE", RARCH_FPS_TOGGLE },
|
||||
{ "SEND_DEBUG_INFO", RARCH_SEND_DEBUG_INFO },
|
||||
{ "NETPLAY_HOST_TOGGLE", RARCH_NETPLAY_HOST_TOGGLE },
|
||||
{ "NETPLAY_GAME_WATCH", RARCH_NETPLAY_GAME_WATCH },
|
||||
{ "VOLUME_UP", RARCH_VOLUME_UP },
|
||||
{ "VOLUME_DOWN", RARCH_VOLUME_DOWN },
|
||||
{ "OVERLAY_NEXT", RARCH_OVERLAY_NEXT },
|
||||
{ "DISK_EJECT_TOGGLE", RARCH_DISK_EJECT_TOGGLE },
|
||||
{ "DISK_NEXT", RARCH_DISK_NEXT },
|
||||
{ "DISK_PREV", RARCH_DISK_PREV },
|
||||
{ "GRAB_MOUSE_TOGGLE", RARCH_GRAB_MOUSE_TOGGLE },
|
||||
{ "UI_COMPANION_TOGGLE", RARCH_UI_COMPANION_TOGGLE },
|
||||
{ "GAME_FOCUS_TOGGLE", RARCH_GAME_FOCUS_TOGGLE },
|
||||
{ "MENU_TOGGLE", RARCH_MENU_TOGGLE },
|
||||
{ "RECORDING_TOGGLE", RARCH_RECORDING_TOGGLE },
|
||||
{ "STREAMING_TOGGLE", RARCH_STREAMING_TOGGLE },
|
||||
{ "RUNAHEAD_TOGGLE", RARCH_RUNAHEAD_TOGGLE },
|
||||
{ "MENU_UP", RETRO_DEVICE_ID_JOYPAD_UP },
|
||||
{ "MENU_DOWN", RETRO_DEVICE_ID_JOYPAD_DOWN },
|
||||
{ "MENU_LEFT", RETRO_DEVICE_ID_JOYPAD_LEFT },
|
||||
{ "MENU_RIGHT", RETRO_DEVICE_ID_JOYPAD_RIGHT },
|
||||
{ "MENU_A", RETRO_DEVICE_ID_JOYPAD_A },
|
||||
{ "MENU_B", RETRO_DEVICE_ID_JOYPAD_B },
|
||||
{ "AI_SERVICE", RARCH_AI_SERVICE },
|
||||
};
|
||||
#endif
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
+168
-26
@@ -37,11 +37,22 @@
|
||||
#include "gfx/common/ctr_common.h"
|
||||
#endif
|
||||
|
||||
/* Required for OpenDingux IPU filter setting */
|
||||
/* Required for OpenDingux IPU filter + refresh
|
||||
* rate settings */
|
||||
#if defined(DINGUX)
|
||||
#include "dingux/dingux_utils.h"
|
||||
#endif
|
||||
|
||||
/* Required for menu screensaver animation */
|
||||
#if defined(HAVE_MATERIALUI) || defined(HAVE_XMB) || defined(HAVE_OZONE)
|
||||
#include "menu/menu_screensaver.h"
|
||||
#endif
|
||||
|
||||
/* Required for 'show inputs on overlay' setting */
|
||||
#if defined(HAVE_OVERLAY)
|
||||
#include "../input/input_overlay.h"
|
||||
#endif
|
||||
|
||||
#if defined(HW_RVL)
|
||||
#define MAX_GAMMA_SETTING 30
|
||||
#elif defined(GEKKO)
|
||||
@@ -55,14 +66,16 @@
|
||||
#elif defined(_XBOX1) || defined(GEKKO) || defined(ANDROID)
|
||||
#define DEFAULT_ASPECT_RATIO 1.3333f
|
||||
#else
|
||||
#define DEFAULT_ASPECT_RATIO -1.0f
|
||||
#define DEFAULT_ASPECT_RATIO 1.3333f
|
||||
#endif
|
||||
|
||||
#if defined(GEKKO)
|
||||
#define DEFAULT_MOUSE_SCALE 1
|
||||
#endif
|
||||
|
||||
#if defined(RARCH_MOBILE) || defined(HAVE_LIBNX) || defined(__WINRT__)
|
||||
#define DEFAULT_TOUCH_SCALE 1
|
||||
|
||||
#if defined(RARCH_MOBILE) || defined(HAVE_LIBNX) || defined(__WINRT__) || defined(EMSCRIPTEN)
|
||||
#define DEFAULT_POINTER_ENABLE true
|
||||
#else
|
||||
#define DEFAULT_POINTER_ENABLE false
|
||||
@@ -144,6 +157,8 @@
|
||||
|
||||
#define DEFAULT_CRT_SWITCH_PORCH_ADJUST 0
|
||||
|
||||
#define DEFAULT_CRT_SWITCH_HIRES_MENU true
|
||||
|
||||
#define DEFAULT_HISTORY_LIST_ENABLE true
|
||||
|
||||
#define DEFAULT_PLAYLIST_ENTRY_RENAME true
|
||||
@@ -186,32 +201,80 @@
|
||||
|
||||
/* To start in Fullscreen, or not. */
|
||||
|
||||
#if defined(HAVE_STEAM) || defined(DINGUX)
|
||||
/* Start in fullscreen mode for Steam and
|
||||
* Dingux builds */
|
||||
#if defined(HAVE_STEAM) || defined(DINGUX) || defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
/* Start in fullscreen mode for Steam and Dingux
|
||||
* WinRT and Winapi Family builds */
|
||||
#define DEFAULT_FULLSCREEN true
|
||||
#else
|
||||
#define DEFAULT_FULLSCREEN false
|
||||
#endif
|
||||
|
||||
/* To use windowed mode or not when going fullscreen. */
|
||||
#define DEFAULT_WINDOWED_FULLSCREEN true
|
||||
#if defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
/* Do not use windowed mode for WinRT and Winapi Family builds on the Xbox UWP with fixed resolution shrinks the image into the left top corner of the screen with some libretro cores */
|
||||
#define DEFAULT_WINDOWED_FULLSCREEN false
|
||||
#else
|
||||
#define DEFAULT_WINDOWED_FULLSCREEN true
|
||||
#endif
|
||||
|
||||
/* Which monitor to prefer. 0 is any monitor, 1 and up selects
|
||||
* specific monitors, 1 being the first monitor. */
|
||||
#define DEFAULT_MONITOR_INDEX 0
|
||||
|
||||
/* Window */
|
||||
/* Window size. A value of 0 uses window scale
|
||||
* multiplied by the core framebuffer size. */
|
||||
#define DEFAULT_WINDOW_WIDTH 1280
|
||||
|
||||
/* DEFAULT_WINDOW_DECORATIONS:
|
||||
Whether to show the usual window decorations like border, titlebar etc. */
|
||||
#ifdef WEBOS
|
||||
#define DEFAULT_WINDOW_DECORATIONS false
|
||||
#else
|
||||
#define DEFAULT_WINDOW_DECORATIONS true
|
||||
#endif
|
||||
|
||||
/* Amount of transparency to use for the main window.
|
||||
* 1 is the most transparent while 100 is opaque. */
|
||||
#define DEFAULT_WINDOW_OPACITY 100
|
||||
|
||||
/* DEFAULT_WINDOW_SAVE_POSITIONS:
|
||||
* Whether to remember window positions
|
||||
* NOTE: Only enabled for desktop Windows
|
||||
* at present. */
|
||||
#define DEFAULT_WINDOW_SAVE_POSITIONS false
|
||||
|
||||
/* Whether to use custom (fixed size)
|
||||
* window dimensions in windowed mode. */
|
||||
#ifdef WEBOS
|
||||
#define DEFAULT_WINDOW_CUSTOM_SIZE_ENABLE true
|
||||
#else
|
||||
#define DEFAULT_WINDOW_CUSTOM_SIZE_ENABLE false
|
||||
#endif
|
||||
|
||||
/* Window dimensions when using a fixed size
|
||||
* window. A value of 0 disables fixed size
|
||||
* windows, using nominal dimensions of
|
||||
* window scale multiplied by the core
|
||||
* framebuffer size. */
|
||||
#if defined(WEBOS)
|
||||
#define DEFAULT_WINDOW_WIDTH 1920
|
||||
#define DEFAULT_WINDOW_HEIGHT 1080
|
||||
#else
|
||||
#define DEFAULT_WINDOW_WIDTH 1280
|
||||
#define DEFAULT_WINDOW_HEIGHT 720
|
||||
#endif
|
||||
|
||||
/* Maximum auto-set window dimensions
|
||||
* when not using a fixed size window */
|
||||
#define DEFAULT_WINDOW_AUTO_WIDTH_MAX 1920
|
||||
#define DEFAULT_WINDOW_AUTO_HEIGHT_MAX 1080
|
||||
|
||||
/* Fullscreen resolution. A value of 0 uses the desktop
|
||||
* resolution. */
|
||||
#if defined(DINGUX)
|
||||
#define DEFAULT_FULLSCREEN_X 320
|
||||
#define DEFAULT_FULLSCREEN_Y 240
|
||||
#elif defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
|
||||
#define DEFAULT_FULLSCREEN_X 1920
|
||||
#define DEFAULT_FULLSCREEN_Y 1080
|
||||
#else
|
||||
#define DEFAULT_FULLSCREEN_X 0
|
||||
#define DEFAULT_FULLSCREEN_Y 0
|
||||
@@ -220,14 +283,6 @@
|
||||
/* Number of threads to use for video recording */
|
||||
#define DEFAULT_VIDEO_RECORD_THREADS 2
|
||||
|
||||
/* Amount of transparency to use for the main window.
|
||||
* 1 is the most transparent while 100 is opaque.
|
||||
*/
|
||||
#define DEFAULT_WINDOW_OPACITY 100
|
||||
|
||||
/* Whether to show the usual window decorations like border, titlebar etc. */
|
||||
#define DEFAULT_WINDOW_DECORATIONS true
|
||||
|
||||
#if defined(RARCH_CONSOLE) || defined(__APPLE__)
|
||||
#define DEFAULT_LOAD_DUMMY_ON_CORE_SHUTDOWN false
|
||||
#else
|
||||
@@ -235,6 +290,15 @@
|
||||
#endif
|
||||
#define DEFAULT_CHECK_FIRMWARE_BEFORE_LOADING false
|
||||
|
||||
/* Specifies whether cores are allowed to
|
||||
* present core options in category submenus */
|
||||
#define DEFAULT_CORE_OPTION_CATEGORY_ENABLE true
|
||||
|
||||
/* Specifies whether to cache core info
|
||||
* into a single (compressed) file for improved
|
||||
* load times on platforms with slow IO */
|
||||
#define DEFAULT_CORE_INFO_CACHE_ENABLE true
|
||||
|
||||
/* Specifies whether to 'reload' (fork and quit)
|
||||
* RetroArch when launching content with the
|
||||
* currently loaded core
|
||||
@@ -273,6 +337,7 @@
|
||||
* Can reduce latency at cost of higher risk of stuttering.
|
||||
*/
|
||||
#define DEFAULT_FRAME_DELAY 0
|
||||
#define MAXIMUM_FRAME_DELAY 19
|
||||
|
||||
/* Inserts black frame(s) inbetween frames.
|
||||
* Useful for Higher Hz monitors (set to multiples of 60 Hz) who want to play 60 Hz
|
||||
@@ -356,8 +421,10 @@
|
||||
/* Only scale in integer steps.
|
||||
* The base size depends on system-reported geometry and aspect ratio.
|
||||
* If video_force_aspect is not set, X/Y will be integer scaled independently.
|
||||
* Overscale rounds up instead of down, default is downscale.
|
||||
*/
|
||||
#define DEFAULT_SCALE_INTEGER false
|
||||
#define DEFAULT_SCALE_INTEGER_OVERSCALE false
|
||||
|
||||
/* Controls aspect ratio handling. */
|
||||
|
||||
@@ -380,9 +447,24 @@
|
||||
#define DEFAULT_DINGUX_IPU_KEEP_ASPECT true
|
||||
/* Sets image filtering method when using the
|
||||
* IPU hardware scaler in Dingux devices */
|
||||
#if defined(RETROFW)
|
||||
#define DEFAULT_DINGUX_IPU_FILTER_TYPE DINGUX_IPU_FILTER_NEAREST
|
||||
#else
|
||||
#define DEFAULT_DINGUX_IPU_FILTER_TYPE DINGUX_IPU_FILTER_BICUBIC
|
||||
#endif
|
||||
|
||||
#if defined(DINGUX_BETA)
|
||||
/* Sets refresh rate of integral LCD panel
|
||||
* in Dingux devices */
|
||||
#define DEFAULT_DINGUX_REFRESH_RATE DINGUX_REFRESH_RATE_60HZ
|
||||
#endif
|
||||
#if defined(RS90)
|
||||
/* Sets image filtering method on the RS90
|
||||
* when integer scaling is disabled */
|
||||
#define DEFAULT_DINGUX_RS90_SOFTFILTER_TYPE DINGUX_RS90_SOFTFILTER_POINT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Save configuration file on exit. */
|
||||
#define DEFAULT_CONFIG_SAVE_ON_EXIT true
|
||||
|
||||
@@ -514,6 +596,9 @@ static const bool quick_menu_show_start_streaming = true;
|
||||
static const bool quick_menu_show_set_core_association = true;
|
||||
static const bool quick_menu_show_reset_core_association = true;
|
||||
static const bool quick_menu_show_options = true;
|
||||
|
||||
#define DEFAULT_QUICK_MENU_SHOW_CORE_OPTIONS_FLUSH false
|
||||
|
||||
static const bool quick_menu_show_controls = true;
|
||||
static const bool quick_menu_show_cheats = true;
|
||||
static const bool quick_menu_show_shaders = true;
|
||||
@@ -574,6 +659,19 @@ static const bool menu_savestate_resume = false;
|
||||
|
||||
#define DEFAULT_QUIT_ON_CLOSE_CONTENT QUIT_ON_CLOSE_CONTENT_DISABLED
|
||||
|
||||
/* While the menu is active, supported drivers
|
||||
* will display a screensaver after SCREENSAVER_TIMEOUT
|
||||
* seconds of inactivity. A timeout of zero disables
|
||||
* the screensaver */
|
||||
#define DEFAULT_MENU_SCREENSAVER_TIMEOUT 0
|
||||
|
||||
#if defined(HAVE_MATERIALUI) || defined(HAVE_XMB) || defined(HAVE_OZONE)
|
||||
/* When menu screensaver is enabled, specifies
|
||||
* animation effect and animation speed */
|
||||
#define DEFAULT_MENU_SCREENSAVER_ANIMATION MENU_SCREENSAVER_BLANK
|
||||
#define DEFAULT_MENU_SCREENSAVER_ANIMATION_SPEED 1.0f
|
||||
#endif
|
||||
|
||||
static const bool content_show_settings = true;
|
||||
static const bool content_show_favorites = true;
|
||||
#ifdef HAVE_IMAGEVIEWER
|
||||
@@ -643,6 +741,7 @@ static const float menu_header_opacity = 1.000;
|
||||
#define DEFAULT_SHOW_ADVANCED_SETTINGS false
|
||||
|
||||
#define DEFAULT_RGUI_COLOR_THEME RGUI_THEME_CLASSIC_GREEN
|
||||
#define DEFAULT_RGUI_TRANSPARENCY true
|
||||
|
||||
static const bool rgui_inline_thumbnails = false;
|
||||
static const bool rgui_swap_thumbnails = false;
|
||||
@@ -655,6 +754,7 @@ static const unsigned rgui_aspect_lock = RGUI_ASPECT_RATIO_LOCK_NONE;
|
||||
static const bool rgui_shadows = false;
|
||||
static const unsigned rgui_particle_effect = RGUI_PARTICLE_EFFECT_NONE;
|
||||
#define DEFAULT_RGUI_PARTICLE_EFFECT_SPEED 1.0f
|
||||
#define DEFAULT_RGUI_PARTICLE_EFFECT_SCREENSAVER true
|
||||
static const bool rgui_extended_ascii = false;
|
||||
#define DEFAULT_RGUI_SWITCH_ICONS true
|
||||
#endif
|
||||
@@ -685,7 +785,9 @@ static const bool default_savefiles_in_content_dir = false;
|
||||
static const bool default_systemfiles_in_content_dir = false;
|
||||
static const bool default_screenshots_in_content_dir = false;
|
||||
|
||||
#if defined(_XBOX1) || defined(__PS3__) || defined(_XBOX360) || defined(DINGUX)
|
||||
#if defined(RS90) || defined(RETROFW)
|
||||
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_TOGGLE_START_SELECT
|
||||
#elif defined(_XBOX1) || defined(__PS3__) || defined(_XBOX360) || defined(DINGUX)
|
||||
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_TOGGLE_L3_R3
|
||||
#elif defined(PS2) || defined(PSP)
|
||||
#define DEFAULT_MENU_TOGGLE_GAMEPAD_COMBO INPUT_TOGGLE_HOLD_START
|
||||
@@ -706,7 +808,15 @@ static const unsigned input_backtouch_toggle = false;
|
||||
|
||||
#define DEFAULT_OVERLAY_ENABLE_AUTOPREFERRED true
|
||||
|
||||
#define DEFAULT_SHOW_PHYSICAL_INPUTS true
|
||||
#if defined(HAVE_OVERLAY)
|
||||
#if defined(RARCH_MOBILE)
|
||||
#define DEFAULT_OVERLAY_SHOW_INPUTS OVERLAY_SHOW_INPUT_TOUCHED
|
||||
#else
|
||||
#define DEFAULT_OVERLAY_SHOW_INPUTS OVERLAY_SHOW_INPUT_PHYSICAL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define DEFAULT_OVERLAY_SHOW_INPUTS_PORT 0
|
||||
|
||||
#define DEFAULT_ALL_USERS_CONTROL_MENU false
|
||||
|
||||
@@ -728,6 +838,8 @@ static const unsigned input_backtouch_toggle = false;
|
||||
/* Font size for on-screen messages. */
|
||||
#if defined(DINGUX)
|
||||
#define DEFAULT_FONT_SIZE 12
|
||||
#elif defined(PS2)
|
||||
#define DEFAULT_FONT_SIZE 16
|
||||
#else
|
||||
#define DEFAULT_FONT_SIZE 32
|
||||
#endif
|
||||
@@ -838,6 +950,10 @@ static const bool audio_enable_menu_bgm = false;
|
||||
* applied */
|
||||
#define DEFAULT_NOTIFICATION_SHOW_CHEATS_APPLIED true
|
||||
|
||||
/* Display a notification when applying an
|
||||
* IPS/BPS/UPS patch file */
|
||||
#define DEFAULT_NOTIFICATION_SHOW_PATCH_APPLIED true
|
||||
|
||||
/* Display a notification when loading an
|
||||
* input remap file */
|
||||
#define DEFAULT_NOTIFICATION_SHOW_REMAP_LOAD true
|
||||
@@ -866,13 +982,20 @@ static const bool audio_enable_menu_bgm = false;
|
||||
#define DEFAULT_NOTIFICATION_SHOW_SCREENSHOT_FLASH 0
|
||||
#endif
|
||||
|
||||
/*Display a notification when setting the refresh rate*/
|
||||
/* Display a notification when setting the refresh rate*/
|
||||
#if defined(_3DS) || (defined(DINGUX) && defined(DINGUX_BETA))
|
||||
/* 3DS and OpenDingux Beta devices set refresh rate
|
||||
* on gfx driver init - set default notification
|
||||
* state to 'false' in order to avoid OSD log spam */
|
||||
#define DEFAULT_NOTIFICATION_SHOW_REFRESH_RATE false
|
||||
#else
|
||||
#define DEFAULT_NOTIFICATION_SHOW_REFRESH_RATE true
|
||||
#endif
|
||||
|
||||
/* Output samplerate. */
|
||||
#ifdef GEKKO
|
||||
#define DEFAULT_OUTPUT_RATE 32000
|
||||
#elif defined(_3DS)
|
||||
#elif defined(_3DS) || defined(RETROFW)
|
||||
#define DEFAULT_OUTPUT_RATE 32730
|
||||
#else
|
||||
#define DEFAULT_OUTPUT_RATE 48000
|
||||
@@ -883,7 +1006,7 @@ static const bool audio_enable_menu_bgm = false;
|
||||
|
||||
/* Desired audio latency in milliseconds. Might not be honored
|
||||
* if driver can't provide given latency. */
|
||||
#if defined(ANDROID) || defined(EMSCRIPTEN)
|
||||
#if defined(ANDROID) || defined(EMSCRIPTEN) || defined(RETROFW)
|
||||
/* For most Android devices, 64ms is way too low. */
|
||||
#define DEFAULT_OUT_LATENCY 128
|
||||
#else
|
||||
@@ -956,6 +1079,13 @@ static const bool audio_enable_menu_bgm = false;
|
||||
/* When set, all enabled cheats are auto-applied when a game is loaded. */
|
||||
#define DEFAULT_APPLY_CHEATS_AFTER_LOAD false
|
||||
|
||||
|
||||
#if defined(RETROFW)
|
||||
/*RETROFW jz4760 has signficant slowdown with default settings */
|
||||
#define DEFAULT_REWIND_BUFFER_SIZE (1 << 20)
|
||||
#define DEFAULT_REWIND_BUFFER_SIZE_STEP 1
|
||||
#define DEFAULT_REWIND_GRANULARITY 6
|
||||
#else
|
||||
/* The buffer size for the rewind buffer. This needs to be about
|
||||
* 15-20MB per minute. Very game dependant. */
|
||||
#define DEFAULT_REWIND_BUFFER_SIZE (20 << 20) /* 20MiB */
|
||||
@@ -965,9 +1095,9 @@ static const bool audio_enable_menu_bgm = false;
|
||||
|
||||
/* How many frames to rewind at a time. */
|
||||
#define DEFAULT_REWIND_GRANULARITY 1
|
||||
|
||||
#endif
|
||||
/* Pause gameplay when gameplay loses focus. */
|
||||
#ifdef EMSCRIPTEN
|
||||
#if defined(EMSCRIPTEN) || defined(WEBOS)
|
||||
#define DEFAULT_PAUSE_NONACTIVE false
|
||||
#else
|
||||
#define DEFAULT_PAUSE_NONACTIVE true
|
||||
@@ -975,7 +1105,7 @@ static const bool audio_enable_menu_bgm = false;
|
||||
|
||||
/* Saves non-volatile SRAM at a regular interval.
|
||||
* It is measured in seconds. A value of 0 disables autosave. */
|
||||
#if defined(__i386__) || defined(__i486__) || defined(__i686__) || defined(__x86_64__) || defined(_M_X64) || defined(_WIN32) || defined(OSX) || defined(ANDROID) || defined(IOS)
|
||||
#if defined(__i386__) || defined(__i486__) || defined(__i686__) || defined(__x86_64__) || defined(_M_X64) || defined(_WIN32) || defined(OSX) || defined(ANDROID) || defined(IOS) || defined(DINGUX)
|
||||
/* Flush to file every 10 seconds on modern platforms by default */
|
||||
#define DEFAULT_AUTOSAVE_INTERVAL 10
|
||||
#else
|
||||
@@ -1146,6 +1276,10 @@ static const int default_content_favorites_size = 200;
|
||||
#define DEFAULT_PLAYLIST_SHOW_SUBLABELS true
|
||||
#endif
|
||||
|
||||
/* Show the indices of playlist entries in
|
||||
* a menu-driver-specific fashion */
|
||||
#define DEFAULT_PLAYLIST_SHOW_ENTRY_IDX true
|
||||
|
||||
#define DEFAULT_PLAYLIST_FUZZY_ARCHIVE_MATCH false
|
||||
|
||||
#define DEFAULT_PLAYLIST_PORTABLE_PATHS false
|
||||
@@ -1245,6 +1379,14 @@ static const unsigned menu_left_thumbnails_default = 0;
|
||||
static const unsigned gfx_thumbnail_upscale_threshold = 0;
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
#if defined(RS90)
|
||||
/* The RS-90 has a hardware clock that is neither
|
||||
* configurable nor persistent, rendering it useless.
|
||||
* We therefore hide it in the menu by default. */
|
||||
#define DEFAULT_MENU_TIMEDATE_ENABLE false
|
||||
#else
|
||||
#define DEFAULT_MENU_TIMEDATE_ENABLE true
|
||||
#endif
|
||||
#define DEFAULT_MENU_TIMEDATE_STYLE MENU_TIMEDATE_STYLE_DDMM_HM
|
||||
#define DEFAULT_MENU_TIMEDATE_DATE_SEPARATOR MENU_TIMEDATE_DATE_SEPARATOR_HYPHEN
|
||||
#endif
|
||||
|
||||
@@ -195,7 +195,7 @@ static const struct retro_keybind retro_keybinds_1[] = {
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_TRIGGER, RETROK_UNKNOWN,
|
||||
RARCH_LIGHTGUN_TRIGGER, NO_BTN, NO_BTN, 0,
|
||||
RARCH_LIGHTGUN_TRIGGER, RETRO_DEVICE_ID_MOUSE_LEFT, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
@@ -750,7 +750,7 @@ static const struct retro_keybind retro_keybinds_1[] = {
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_TRIGGER, RETROK_UNKNOWN,
|
||||
RARCH_LIGHTGUN_TRIGGER, NO_BTN, NO_BTN, 0,
|
||||
RARCH_LIGHTGUN_TRIGGER, RETRO_DEVICE_ID_MOUSE_LEFT, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
@@ -1304,7 +1304,7 @@ static const struct retro_keybind retro_keybinds_1[] = {
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_TRIGGER, RETROK_UNKNOWN,
|
||||
RARCH_LIGHTGUN_TRIGGER, NO_BTN, NO_BTN, 0,
|
||||
RARCH_LIGHTGUN_TRIGGER, RETRO_DEVICE_ID_MOUSE_LEFT, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
@@ -1872,7 +1872,7 @@ static const struct retro_keybind retro_keybinds_rest[] = {
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_TRIGGER, RETROK_UNKNOWN,
|
||||
RARCH_LIGHTGUN_TRIGGER, NO_BTN, NO_BTN, 0,
|
||||
RARCH_LIGHTGUN_TRIGGER, RETRO_DEVICE_ID_MOUSE_LEFT, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
|
||||
@@ -350,6 +350,12 @@
|
||||
#define SUPPORTS_CORETEXT false
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHECK
|
||||
#define SUPPORTS_CHECK true
|
||||
#else
|
||||
#define SUPPORTS_CHECK false
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) && !defined(GLOBAL_CONFIG_DIR)
|
||||
#if defined(__HAIKU__)
|
||||
#define GLOBAL_CONFIG_DIR "/system/settings"
|
||||
|
||||
+370
-221
File diff suppressed because it is too large.
Load diff
+52
-7
@@ -29,6 +29,10 @@
|
||||
#include "input/input_defines.h"
|
||||
#include "led/led_defines.h"
|
||||
|
||||
#ifdef HAVE_LAKKA
|
||||
#include "lakka.h"
|
||||
#endif
|
||||
|
||||
#define configuration_set_float(settings, var, newvar) \
|
||||
{ \
|
||||
settings->modified = true; \
|
||||
@@ -63,7 +67,9 @@ enum crt_switch_type
|
||||
{
|
||||
CRT_SWITCH_NONE = 0,
|
||||
CRT_SWITCH_15KHZ,
|
||||
CRT_SWITCH_31KHZ
|
||||
CRT_SWITCH_31KHZ,
|
||||
CRT_SWITCH_32_120,
|
||||
CRT_SWITCH_INI
|
||||
};
|
||||
|
||||
enum override_type
|
||||
@@ -116,7 +122,7 @@ typedef struct settings
|
||||
unsigned placeholder;
|
||||
|
||||
unsigned input_split_joycon[MAX_USERS];
|
||||
unsigned input_joypad_map[MAX_USERS];
|
||||
unsigned input_joypad_index[MAX_USERS];
|
||||
unsigned input_device[MAX_USERS];
|
||||
unsigned input_mouse_index[MAX_USERS];
|
||||
/* Set by autoconfiguration in joypad_autoconfig_dir.
|
||||
@@ -124,13 +130,14 @@ typedef struct settings
|
||||
unsigned input_libretro_device[MAX_USERS];
|
||||
unsigned input_analog_dpad_mode[MAX_USERS];
|
||||
|
||||
unsigned input_keymapper_ids[MAX_USERS][RARCH_CUSTOM_BIND_LIST_END];
|
||||
|
||||
unsigned input_remap_ports[MAX_USERS];
|
||||
unsigned input_remap_ids[MAX_USERS][RARCH_CUSTOM_BIND_LIST_END];
|
||||
unsigned input_keymapper_ids[MAX_USERS][RARCH_CUSTOM_BIND_LIST_END];
|
||||
unsigned input_remap_port_map[MAX_USERS][MAX_USERS + 1];
|
||||
|
||||
unsigned led_map[MAX_LEDS];
|
||||
|
||||
unsigned audio_out_rate;
|
||||
unsigned audio_output_sample_rate;
|
||||
unsigned audio_block_frames;
|
||||
unsigned audio_latency;
|
||||
|
||||
@@ -151,12 +158,14 @@ typedef struct settings
|
||||
#ifdef GEKKO
|
||||
unsigned input_mouse_scale;
|
||||
#endif
|
||||
unsigned input_touch_scale;
|
||||
unsigned input_hotkey_block_delay;
|
||||
unsigned input_menu_toggle_gamepad_combo;
|
||||
unsigned input_keyboard_gamepad_mapping_type;
|
||||
unsigned input_poll_type_behavior;
|
||||
unsigned input_dingux_rumble_gain;
|
||||
unsigned input_auto_game_focus;
|
||||
unsigned input_max_users;
|
||||
|
||||
unsigned netplay_port;
|
||||
unsigned netplay_input_latency_frames_min;
|
||||
@@ -200,6 +209,8 @@ typedef struct settings
|
||||
unsigned video_stream_scale_factor;
|
||||
unsigned video_3ds_display_mode;
|
||||
unsigned video_dingux_ipu_filter_type;
|
||||
unsigned video_dingux_refresh_rate;
|
||||
unsigned video_dingux_rs90_softfilter_type;
|
||||
#ifdef HAVE_VIDEO_LAYOUT
|
||||
unsigned video_layout_selected_view;
|
||||
#endif
|
||||
@@ -249,6 +260,8 @@ typedef struct settings
|
||||
unsigned menu_ticker_type;
|
||||
unsigned menu_scroll_delay;
|
||||
unsigned menu_content_show_add_entry;
|
||||
unsigned menu_screensaver_timeout;
|
||||
unsigned menu_screensaver_animation;
|
||||
|
||||
unsigned playlist_entry_remove_enable;
|
||||
unsigned playlist_show_inline_core_name;
|
||||
@@ -258,7 +271,8 @@ typedef struct settings
|
||||
unsigned camera_width;
|
||||
unsigned camera_height;
|
||||
|
||||
unsigned input_overlay_show_physical_inputs_port;
|
||||
unsigned input_overlay_show_inputs;
|
||||
unsigned input_overlay_show_inputs_port;
|
||||
|
||||
unsigned run_ahead_frames;
|
||||
|
||||
@@ -269,6 +283,8 @@ typedef struct settings
|
||||
unsigned window_position_y;
|
||||
unsigned window_position_width;
|
||||
unsigned window_position_height;
|
||||
unsigned window_auto_width_max;
|
||||
unsigned window_auto_height_max;
|
||||
|
||||
unsigned video_record_threads;
|
||||
|
||||
@@ -280,6 +296,12 @@ typedef struct settings
|
||||
unsigned core_updater_auto_backup_history_size;
|
||||
unsigned video_black_frame_insertion;
|
||||
unsigned quit_on_close_content;
|
||||
|
||||
#ifdef HAVE_LAKKA
|
||||
unsigned cpu_scaling_mode;
|
||||
unsigned cpu_min_freq;
|
||||
unsigned cpu_max_freq;
|
||||
#endif
|
||||
} uints;
|
||||
|
||||
struct
|
||||
@@ -306,6 +328,7 @@ typedef struct settings
|
||||
float menu_header_opacity;
|
||||
float menu_ticker_speed;
|
||||
float menu_rgui_particle_effect_speed;
|
||||
float menu_screensaver_animation_speed;
|
||||
|
||||
float audio_max_timing_skew;
|
||||
float audio_volume; /* dB scale. */
|
||||
@@ -330,6 +353,7 @@ typedef struct settings
|
||||
float slowmotion_ratio;
|
||||
float fastforward_ratio;
|
||||
float input_analog_deadzone;
|
||||
float input_axis_threshold;
|
||||
float input_analog_sensitivity;
|
||||
} floats;
|
||||
|
||||
@@ -376,6 +400,11 @@ typedef struct settings
|
||||
char ai_service_url[PATH_MAX_LENGTH];
|
||||
|
||||
char crt_switch_timings[255];
|
||||
#ifdef HAVE_LAKKA
|
||||
char timezone[TIMEZONE_LENGTH];
|
||||
char cpu_main_gov[32];
|
||||
char cpu_menu_gov[32];
|
||||
#endif
|
||||
} arrays;
|
||||
|
||||
struct
|
||||
@@ -473,6 +502,7 @@ typedef struct settings
|
||||
bool video_aspect_ratio_auto;
|
||||
bool video_dingux_ipu_keep_aspect;
|
||||
bool video_scale_integer;
|
||||
bool video_scale_integer_overscale;
|
||||
bool video_shader_enable;
|
||||
bool video_shader_watch_files;
|
||||
bool video_shader_remember_last_dir;
|
||||
@@ -521,7 +551,6 @@ typedef struct settings
|
||||
bool input_overlay_enable_autopreferred;
|
||||
bool input_overlay_hide_in_menu;
|
||||
bool input_overlay_hide_when_gamepad_connected;
|
||||
bool input_overlay_show_physical_inputs;
|
||||
bool input_overlay_show_mouse_cursor;
|
||||
bool input_overlay_auto_rotate;
|
||||
bool input_overlay_auto_scale;
|
||||
@@ -532,6 +561,7 @@ typedef struct settings
|
||||
bool input_backtouch_toggle;
|
||||
bool input_small_keyboard_enable;
|
||||
bool input_keyboard_gamepad_enable;
|
||||
bool input_auto_mouse_grab;
|
||||
#if defined(HAVE_DINPUT) || defined(HAVE_WINRAWINPUT)
|
||||
bool input_nowinkey_enable;
|
||||
#endif
|
||||
@@ -547,6 +577,7 @@ typedef struct settings
|
||||
bool menu_show_load_content_animation;
|
||||
bool notification_show_autoconfig;
|
||||
bool notification_show_cheats_applied;
|
||||
bool notification_show_patch_applied;
|
||||
bool notification_show_remap_load;
|
||||
bool notification_show_config_override_load;
|
||||
bool notification_show_set_initial_disk;
|
||||
@@ -605,11 +636,13 @@ typedef struct settings
|
||||
bool menu_rgui_border_filler_thickness_enable;
|
||||
bool menu_rgui_border_filler_enable;
|
||||
bool menu_rgui_full_width_layout;
|
||||
bool menu_rgui_transparency;
|
||||
bool menu_rgui_shadows;
|
||||
bool menu_rgui_inline_thumbnails;
|
||||
bool menu_rgui_swap_thumbnails;
|
||||
bool menu_rgui_extended_ascii;
|
||||
bool menu_rgui_switch_icons;
|
||||
bool menu_rgui_particle_effect_screensaver;
|
||||
bool menu_xmb_shadows_enable;
|
||||
bool menu_xmb_vertical_thumbnails;
|
||||
bool menu_content_show_settings;
|
||||
@@ -660,6 +693,7 @@ typedef struct settings
|
||||
bool quick_menu_show_set_core_association;
|
||||
bool quick_menu_show_reset_core_association;
|
||||
bool quick_menu_show_options;
|
||||
bool quick_menu_show_core_options_flush;
|
||||
bool quick_menu_show_controls;
|
||||
bool quick_menu_show_cheats;
|
||||
bool quick_menu_show_shaders;
|
||||
@@ -673,6 +707,7 @@ typedef struct settings
|
||||
bool kiosk_mode_enable;
|
||||
|
||||
bool crt_switch_custom_refresh_enable;
|
||||
bool crt_switch_hires_menu;
|
||||
|
||||
/* Netplay */
|
||||
bool netplay_public_announce;
|
||||
@@ -708,6 +743,7 @@ typedef struct settings
|
||||
bool cheevos_auto_screenshot;
|
||||
bool cheevos_start_active;
|
||||
bool cheevos_unlock_sound_enable;
|
||||
bool cheevos_challenge_indicators;
|
||||
|
||||
/* Camera */
|
||||
bool camera_allow;
|
||||
@@ -762,6 +798,8 @@ typedef struct settings
|
||||
bool network_remote_enable_user[MAX_USERS];
|
||||
bool load_dummy_on_core_shutdown;
|
||||
bool check_firmware_before_loading;
|
||||
bool core_option_category_enable;
|
||||
bool core_info_cache_enable;
|
||||
#ifndef HAVE_DYNAMIC
|
||||
bool always_reload_core_on_run_content;
|
||||
#endif
|
||||
@@ -792,6 +830,7 @@ typedef struct settings
|
||||
|
||||
bool video_window_show_decorations;
|
||||
bool video_window_save_positions;
|
||||
bool video_window_custom_size_enable;
|
||||
|
||||
bool sustained_performance_mode;
|
||||
bool playlist_use_old_format;
|
||||
@@ -801,6 +840,7 @@ typedef struct settings
|
||||
|
||||
bool playlist_sort_alphabetical;
|
||||
bool playlist_show_sublabels;
|
||||
bool playlist_show_entry_idx;
|
||||
bool playlist_fuzzy_archive_match;
|
||||
bool playlist_portable_paths;
|
||||
|
||||
@@ -1004,6 +1044,11 @@ void config_save_file_salamander(void);
|
||||
|
||||
settings_t *config_get_ptr(void);
|
||||
|
||||
#ifdef HAVE_LAKKA
|
||||
const char *config_get_all_timezones(void);
|
||||
void config_set_timezone(char *timezone);
|
||||
#endif
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
@@ -124,6 +124,10 @@ bool content_set_subsystem_by_name(const char* subsystem_name);
|
||||
/* Get the current subsystem "friendly name" */
|
||||
void content_get_subsystem_friendly_name(const char* subsystem_name, char* subsystem_friendly_name, size_t len);
|
||||
|
||||
/* Sets overrides which modify frontend handling of
|
||||
* specific content file types */
|
||||
bool content_file_override_set(const struct retro_system_content_info_override *overrides);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
+3
-18
@@ -116,7 +116,6 @@ bool core_backup_get_backup_path(
|
||||
const char *core_path, uint32_t crc, enum core_backup_mode backup_mode,
|
||||
const char *dir_core_assets, char *backup_path, size_t len)
|
||||
{
|
||||
int n;
|
||||
time_t current_time;
|
||||
struct tm time_info;
|
||||
const char *core_filename = NULL;
|
||||
@@ -152,7 +151,7 @@ bool core_backup_get_backup_path(
|
||||
rtime_localtime(¤t_time, &time_info);
|
||||
|
||||
/* Generate backup filename */
|
||||
n = snprintf(backup_filename, sizeof(backup_filename),
|
||||
snprintf(backup_filename, sizeof(backup_filename),
|
||||
"%s.%04u%02u%02uT%02u%02u%02u.%08x.%u%s",
|
||||
core_filename,
|
||||
(unsigned)time_info.tm_year + 1900,
|
||||
@@ -165,10 +164,6 @@ bool core_backup_get_backup_path(
|
||||
(unsigned)backup_mode,
|
||||
FILE_PATH_CORE_BACKUP_EXTENSION);
|
||||
|
||||
if ((n < 0) || (n >= 128))
|
||||
n = 0; /* Silence GCC warnings... */
|
||||
|
||||
(void)n;
|
||||
/* Build final path */
|
||||
fill_pathname_join(backup_path, backup_dir,
|
||||
backup_filename, len);
|
||||
@@ -712,7 +707,6 @@ bool core_backup_list_get_entry_timestamp_str(
|
||||
enum core_backup_date_separator_type date_separator,
|
||||
char *timestamp, size_t len)
|
||||
{
|
||||
int n;
|
||||
const char *format_str = "";
|
||||
|
||||
if (!entry || (len < 20))
|
||||
@@ -732,7 +726,7 @@ bool core_backup_list_get_entry_timestamp_str(
|
||||
break;
|
||||
}
|
||||
|
||||
n = snprintf(timestamp, len,
|
||||
snprintf(timestamp, len,
|
||||
format_str,
|
||||
entry->date.year,
|
||||
entry->date.month,
|
||||
@@ -741,9 +735,6 @@ bool core_backup_list_get_entry_timestamp_str(
|
||||
entry->date.minute,
|
||||
entry->date.second);
|
||||
|
||||
if ((n < 0) || (n >= 32))
|
||||
n = 0; /* Silence GCC warnings... */
|
||||
(void)n;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -754,15 +745,9 @@ bool core_backup_list_get_entry_crc_str(
|
||||
const core_backup_list_entry_t *entry,
|
||||
char *crc, size_t len)
|
||||
{
|
||||
int n;
|
||||
|
||||
if (!entry || (len < 9))
|
||||
return false;
|
||||
|
||||
n = snprintf(crc, len, "%08x", entry->crc);
|
||||
|
||||
if ((n < 0) || (n >= 32))
|
||||
n = 0; /* Silence GCC warnings... */
|
||||
(void)n;
|
||||
snprintf(crc, len, "%08x", entry->crc);
|
||||
return true;
|
||||
}
|
||||
+1865
-591
File diff suppressed because it is too large.
Load diff
+22
-36
@@ -45,25 +45,19 @@ typedef struct
|
||||
|
||||
/* Simple container/convenience struct for
|
||||
* holding the 'id' of a core file
|
||||
* > 'id' is the filename without extension or
|
||||
* > 'str' is the filename without extension or
|
||||
* platform-specific suffix
|
||||
* > 'id' is used for core info searches - enables
|
||||
* matching regardless of core file base path,
|
||||
* and is platform-independent (e.g. an Android
|
||||
* core file will be correctly identified on Linux)
|
||||
* > 'len' is used to cache the length of 'str', for
|
||||
* improved performance when performing string
|
||||
* comparisons */
|
||||
* > 'hash' is a hash key used for efficient core
|
||||
* list searches */
|
||||
typedef struct
|
||||
{
|
||||
char *str;
|
||||
size_t len;
|
||||
uint32_t hash;
|
||||
} core_file_id_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *path;
|
||||
void *config_data;
|
||||
char *display_name;
|
||||
char *display_version;
|
||||
char *core_name;
|
||||
@@ -89,12 +83,13 @@ typedef struct
|
||||
struct string_list *required_hw_api_list;
|
||||
core_info_firmware_t *firmware;
|
||||
core_file_id_t core_file_id; /* ptr alignment */
|
||||
void *userdata;
|
||||
size_t firmware_count;
|
||||
bool has_info;
|
||||
bool supports_no_game;
|
||||
bool database_match_archive_member;
|
||||
bool is_experimental;
|
||||
bool is_locked;
|
||||
bool is_installed;
|
||||
} core_info_t;
|
||||
|
||||
/* A subset of core_info parameters required for
|
||||
@@ -112,6 +107,7 @@ typedef struct
|
||||
core_info_t *list;
|
||||
char *all_ext;
|
||||
size_t count;
|
||||
size_t info_count;
|
||||
} core_info_list_t;
|
||||
|
||||
typedef struct core_info_ctx_firmware
|
||||
@@ -123,12 +119,6 @@ typedef struct core_info_ctx_firmware
|
||||
} directory;
|
||||
} core_info_ctx_firmware_t;
|
||||
|
||||
typedef struct core_info_ctx_find
|
||||
{
|
||||
core_info_t *inf;
|
||||
const char *path;
|
||||
} core_info_ctx_find_t;
|
||||
|
||||
struct core_info_state
|
||||
{
|
||||
#ifdef HAVE_COMPRESSION
|
||||
@@ -141,30 +131,21 @@ struct core_info_state
|
||||
|
||||
typedef struct core_info_state core_info_state_t;
|
||||
|
||||
size_t core_info_list_num_info_files(core_info_list_t *list);
|
||||
|
||||
/* Non-reentrant, does not allocate. Returns pointer to internal state. */
|
||||
void core_info_list_get_supported_cores(core_info_list_t *list,
|
||||
const char *path, const core_info_t **infos, size_t *num_infos);
|
||||
|
||||
bool core_info_list_get_display_name(core_info_list_t *list,
|
||||
const char *path, char *s, size_t len);
|
||||
|
||||
bool core_info_get_display_name(const char *path, char *s, size_t len);
|
||||
const char *core_path, char *s, size_t len);
|
||||
|
||||
/* Returns core_info parameters required for
|
||||
* core updater tasks, read from specified file.
|
||||
* Returned core_updater_info_t object must be
|
||||
* freed using core_info_free_core_updater_info().
|
||||
* Returns NULL if 'path' is invalid. */
|
||||
core_updater_info_t *core_info_get_core_updater_info(const char *path);
|
||||
core_updater_info_t *core_info_get_core_updater_info(const char *info_path);
|
||||
void core_info_free_core_updater_info(core_updater_info_t *info);
|
||||
|
||||
void core_info_get_name(const char *path, char *s, size_t len,
|
||||
const char *path_info, const char *dir_cores,
|
||||
const char *exts, bool show_hidden_files,
|
||||
bool get_display_name);
|
||||
|
||||
core_info_t *core_info_get(core_info_list_t *list, size_t i);
|
||||
|
||||
void core_info_free_current_core(core_info_state_t *p_coreinfo);
|
||||
@@ -176,7 +157,8 @@ bool core_info_get_current_core(core_info_t **core);
|
||||
void core_info_deinit_list(void);
|
||||
|
||||
bool core_info_init_list(const char *path_info, const char *dir_cores,
|
||||
const char *exts, bool show_hidden_files);
|
||||
const char *exts, bool show_hidden_files,
|
||||
bool enable_cache, bool *cache_supported);
|
||||
|
||||
bool core_info_get_list(core_info_list_t **core);
|
||||
|
||||
@@ -186,22 +168,20 @@ size_t core_info_count(void);
|
||||
bool core_info_list_update_missing_firmware(core_info_ctx_firmware_t *info,
|
||||
bool *set_missing_bios);
|
||||
|
||||
bool core_info_find(core_info_ctx_find_t *info);
|
||||
bool core_info_find(const char *core_path,
|
||||
core_info_t **core_info);
|
||||
|
||||
bool core_info_load(
|
||||
core_info_ctx_find_t *info,
|
||||
bool core_info_load(const char *core_path,
|
||||
core_info_state_t *p_coreinfo);
|
||||
|
||||
bool core_info_database_supports_content_path(const char *database_path, const char *path);
|
||||
|
||||
bool core_info_database_match_archive_member(const char *database_path);
|
||||
|
||||
bool core_info_unsupported_content_path(const char *path);
|
||||
|
||||
void core_info_qsort(core_info_list_t *core_info_list, enum core_info_list_qsort_type qsort_type);
|
||||
|
||||
bool core_info_list_get_info(core_info_list_t *core_info_list,
|
||||
core_info_t *out_info, const char *path);
|
||||
core_info_t *out_info, const char *core_path);
|
||||
|
||||
bool core_info_hw_api_supported(core_info_t *info);
|
||||
|
||||
@@ -223,7 +203,13 @@ bool core_info_get_core_lock(const char *core_path, bool validate_path);
|
||||
|
||||
core_info_state_t *coreinfo_get_ptr(void);
|
||||
|
||||
bool core_info_core_file_id_is_equal(const char* core_path_a, const char* core_path_b);
|
||||
bool core_info_core_file_id_is_equal(const char *core_path_a, const char *core_path_b);
|
||||
|
||||
/* When called, generates a temporary file
|
||||
* that will force an info cache refresh the
|
||||
* next time that core info is initialised with
|
||||
* caching enabled */
|
||||
bool core_info_cache_force_refresh(const char *path_info);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
+374
-29
@@ -22,6 +22,7 @@
|
||||
#include <boolean.h>
|
||||
#include <retro_common_api.h>
|
||||
#include <lists/string_list.h>
|
||||
#include <lists/nested_list.h>
|
||||
|
||||
#include "retroarch.h"
|
||||
|
||||
@@ -30,99 +31,443 @@ RETRO_BEGIN_DECLS
|
||||
struct core_option
|
||||
{
|
||||
char *desc;
|
||||
char *desc_categorized;
|
||||
char *info;
|
||||
char *info_categorized;
|
||||
char *key;
|
||||
char *category_key;
|
||||
struct string_list *vals;
|
||||
struct string_list *val_labels;
|
||||
/* opt_idx: option index, used for internal
|
||||
* bookkeeping */
|
||||
size_t opt_idx;
|
||||
/* default_index, index: correspond to
|
||||
* option *value* indices */
|
||||
size_t default_index;
|
||||
size_t index;
|
||||
uint32_t key_hash;
|
||||
bool visible;
|
||||
};
|
||||
|
||||
struct core_catagory
|
||||
{
|
||||
char *key;
|
||||
char *desc;
|
||||
char *info;
|
||||
uint32_t key_hash;
|
||||
};
|
||||
|
||||
/* TODO/FIXME: This struct should be made
|
||||
* 'private', with restricted access to its
|
||||
* members via interface functions. This
|
||||
* requires significant refactoring... */
|
||||
struct core_option_manager
|
||||
{
|
||||
config_file_t *conf;
|
||||
char conf_path[PATH_MAX_LENGTH];
|
||||
|
||||
struct core_catagory *cats;
|
||||
struct core_option *opts;
|
||||
nested_list_t *option_map;
|
||||
|
||||
size_t cats_size;
|
||||
size_t size;
|
||||
|
||||
bool updated;
|
||||
};
|
||||
|
||||
typedef struct core_option_manager core_option_manager_t;
|
||||
|
||||
/*********************/
|
||||
/* Option Conversion */
|
||||
/*********************/
|
||||
|
||||
/**
|
||||
* core_option_manager_set_default:
|
||||
* @opt : pointer to core option manager object.
|
||||
* @idx : index of core option to be reset to defaults.
|
||||
* core_option_manager_convert_v1:
|
||||
*
|
||||
* Reset core option specified by @idx and sets default value for option.
|
||||
* @options_v1 : an array of retro_core_option_definition
|
||||
* structs
|
||||
*
|
||||
* Converts an array of core option v1 definitions into
|
||||
* a v2 core options struct. Returned pointer must be
|
||||
* freed using core_option_manager_free_converted().
|
||||
*
|
||||
* Returns: Valid pointer to a new v2 core options struct
|
||||
* if successful, otherwise NULL.
|
||||
**/
|
||||
void core_option_manager_set_default(core_option_manager_t *opt, size_t idx);
|
||||
struct retro_core_options_v2 *core_option_manager_convert_v1(
|
||||
const struct retro_core_option_definition *options_v1);
|
||||
|
||||
/**
|
||||
* core_option_manager_convert_v1_intl:
|
||||
*
|
||||
* @options_v1_intl : pointer to a retro_core_options_intl
|
||||
* struct
|
||||
*
|
||||
* Converts a v1 'international' core options definition
|
||||
* struct into a v2 core options struct. Returned pointer
|
||||
* must be freed using core_option_manager_free_converted().
|
||||
*
|
||||
* Returns: Valid pointer to a new v2 core options struct
|
||||
* if successful, otherwise NULL.
|
||||
**/
|
||||
struct retro_core_options_v2 *core_option_manager_convert_v1_intl(
|
||||
const struct retro_core_options_intl *options_v1_intl);
|
||||
|
||||
/**
|
||||
* core_option_manager_convert_v2_intl:
|
||||
*
|
||||
* @options_v2_intl : pointer to a retro_core_options_v2_intl
|
||||
* struct
|
||||
*
|
||||
* Converts a v2 'international' core options struct
|
||||
* into a regular v2 core options struct. Returned pointer
|
||||
* must be freed using core_option_manager_free_converted().
|
||||
*
|
||||
* Returns: Valid pointer to a new v2 core options struct
|
||||
* if successful, otherwise NULL.
|
||||
**/
|
||||
struct retro_core_options_v2 *core_option_manager_convert_v2_intl(
|
||||
const struct retro_core_options_v2_intl *options_v2_intl);
|
||||
|
||||
/**
|
||||
* core_option_manager_free_converted:
|
||||
*
|
||||
* @options_v2 : pointer to a retro_core_options_v2
|
||||
* struct
|
||||
*
|
||||
* Frees the pointer returned by any
|
||||
* core_option_manager_convert_*() function.
|
||||
**/
|
||||
void core_option_manager_free_converted(
|
||||
struct retro_core_options_v2 *options_v2);
|
||||
|
||||
/**************************************/
|
||||
/* Initialisation / De-Initialisation */
|
||||
/**************************************/
|
||||
|
||||
/**
|
||||
* core_option_manager_new_vars:
|
||||
*
|
||||
* @conf_path : Filesystem path to write core option
|
||||
* config file to
|
||||
* @src_conf_path : Filesystem path from which to load
|
||||
* initial config settings.
|
||||
* @vars : Pointer to core option variable array
|
||||
* handle
|
||||
*
|
||||
* Legacy version of core_option_manager_new().
|
||||
* Creates and initializes a core manager handle.
|
||||
*
|
||||
* Returns: handle to new core manager handle if successful,
|
||||
* otherwise NULL.
|
||||
**/
|
||||
core_option_manager_t *core_option_manager_new_vars(
|
||||
const char *conf_path, const char *src_conf_path,
|
||||
const struct retro_variable *vars);
|
||||
|
||||
/**
|
||||
* core_option_manager_new:
|
||||
*
|
||||
* @conf_path : Filesystem path to write core option
|
||||
* config file to
|
||||
* @src_conf_path : Filesystem path from which to load
|
||||
* initial config settings.
|
||||
* @options_v2 : Pointer to retro_core_options_v2 struct
|
||||
* @categorized : Flag specifying whether core option
|
||||
* category information should be read
|
||||
* from @options_v2
|
||||
*
|
||||
* Creates and initializes a core manager handle. Parses
|
||||
* information from a retro_core_options_v2 struct.
|
||||
* If @categorized is false, all option category
|
||||
* assignments will be ignored.
|
||||
*
|
||||
* Returns: handle to new core manager handle if successful,
|
||||
* otherwise NULL.
|
||||
**/
|
||||
core_option_manager_t *core_option_manager_new(
|
||||
const char *conf_path, const char *src_conf_path,
|
||||
const struct retro_core_options_v2 *options_v2,
|
||||
bool categorized);
|
||||
|
||||
/**
|
||||
* core_option_manager_free:
|
||||
*
|
||||
* @opt : options manager handle
|
||||
*
|
||||
* Frees specified core options manager handle.
|
||||
**/
|
||||
void core_option_manager_free(core_option_manager_t *opt);
|
||||
|
||||
/********************/
|
||||
/* Category Getters */
|
||||
/********************/
|
||||
|
||||
/**
|
||||
* core_option_manager_get_category_desc:
|
||||
*
|
||||
* @opt : options manager handle
|
||||
* @key : core option category id string
|
||||
*
|
||||
* Fetches the 'description' text of the core option
|
||||
* category identified by @key (used as the
|
||||
* category label in the menu).
|
||||
*
|
||||
* Returns: description string (menu label) of the
|
||||
* specified option category if successful,
|
||||
* otherwise NULL.
|
||||
**/
|
||||
const char *core_option_manager_get_category_desc(core_option_manager_t *opt,
|
||||
const char *key);
|
||||
|
||||
/**
|
||||
* core_option_manager_get_category_info:
|
||||
*
|
||||
* @opt : options manager handle
|
||||
* @key : core option category id string
|
||||
*
|
||||
* Fetches the 'info' text of the core option
|
||||
* category identified by @key (used as the category
|
||||
* sublabel in the menu).
|
||||
*
|
||||
* Returns: information string (menu sublabel) of
|
||||
* the specified option category if successful,
|
||||
* otherwise NULL.
|
||||
**/
|
||||
const char *core_option_manager_get_category_info(core_option_manager_t *opt,
|
||||
const char *key);
|
||||
|
||||
/**
|
||||
* core_option_manager_get_category_visible:
|
||||
*
|
||||
* @opt : options manager handle
|
||||
* @key : core option category id string
|
||||
*
|
||||
* Queries whether the core option category
|
||||
* identified by @key should be displayed in
|
||||
* the frontend menu. (A category is deemed to
|
||||
* be visible if at least one of the options
|
||||
* in the category is visible)
|
||||
*
|
||||
* Returns: true if option category should be
|
||||
* displayed by the frontend, otherwise false.
|
||||
**/
|
||||
bool core_option_manager_get_category_visible(core_option_manager_t *opt,
|
||||
const char *key);
|
||||
|
||||
/******************/
|
||||
/* Option Getters */
|
||||
/******************/
|
||||
|
||||
/**
|
||||
* core_option_manager_get_idx:
|
||||
*
|
||||
* @opt : options manager handle
|
||||
* @key : core option key string (variable to query
|
||||
* in RETRO_ENVIRONMENT_GET_VARIABLE)
|
||||
* @idx : index of core option corresponding
|
||||
* to @key
|
||||
*
|
||||
* Fetches the index of the core option identified
|
||||
* by the specified @key.
|
||||
*
|
||||
* Returns: true if option matching the specified
|
||||
* key was found, otherwise false.
|
||||
**/
|
||||
bool core_option_manager_get_idx(core_option_manager_t *opt,
|
||||
const char *key, size_t *idx);
|
||||
|
||||
/**
|
||||
* core_option_manager_get_desc:
|
||||
* @opt : options manager handle
|
||||
* @idx : idx identifier of the option
|
||||
*
|
||||
* Gets description for an option.
|
||||
* @opt : options manager handle
|
||||
* @idx : core option index
|
||||
* @categorized : flag specifying whether to
|
||||
* fetch the categorised description
|
||||
* or the legacy fallback
|
||||
*
|
||||
* Returns: Description for an option.
|
||||
* Fetches the 'description' of the core option at
|
||||
* index @idx (used as the option label in the menu).
|
||||
* If menu has option category support, @categorized
|
||||
* should be true. (At present, only the Qt interface
|
||||
* requires @categorized to be false)
|
||||
*
|
||||
* Returns: description string (menu label) of the
|
||||
* specified option if successful, otherwise NULL.
|
||||
**/
|
||||
const char *core_option_manager_get_desc(core_option_manager_t *opt,
|
||||
size_t idx);
|
||||
size_t idx, bool categorized);
|
||||
|
||||
/**
|
||||
* core_option_manager_get_info:
|
||||
* @opt : options manager handle
|
||||
* @idx : idx identifier of the option
|
||||
*
|
||||
* Gets information text for an option.
|
||||
* @opt : options manager handle
|
||||
* @idx : core option index
|
||||
* @categorized : flag specifying whether to
|
||||
* fetch the categorised information
|
||||
* or the legacy fallback
|
||||
*
|
||||
* Returns: Information text for an option.
|
||||
* Fetches the 'info' text of the core option at
|
||||
* index @idx (used as the option sublabel in the
|
||||
* menu). If menu has option category support,
|
||||
* @categorized should be true. (At present, only
|
||||
* the Qt interface requires @categorized to be false)
|
||||
*
|
||||
* Returns: information string (menu sublabel) of the
|
||||
* specified option if successful, otherwise NULL.
|
||||
**/
|
||||
const char *core_option_manager_get_info(core_option_manager_t *opt,
|
||||
size_t idx);
|
||||
size_t idx, bool categorized);
|
||||
|
||||
/**
|
||||
* core_option_manager_get_val:
|
||||
* @opt : options manager handle
|
||||
* @idx : idx identifier of the option
|
||||
*
|
||||
* Gets value for an option.
|
||||
* @opt : options manager handle
|
||||
* @idx : core option index
|
||||
*
|
||||
* Returns: Value for an option.
|
||||
* Fetches the string representation of the current
|
||||
* value of the core option at index @idx.
|
||||
*
|
||||
* Returns: core option value string if successful,
|
||||
* otherwise NULL.
|
||||
**/
|
||||
const char *core_option_manager_get_val(core_option_manager_t *opt,
|
||||
size_t idx);
|
||||
|
||||
/**
|
||||
* core_option_manager_get_val_label:
|
||||
* @opt : options manager handle
|
||||
* @idx : idx identifier of the option
|
||||
*
|
||||
* Gets value label for an option.
|
||||
* @opt : options manager handle
|
||||
* @idx : core option index
|
||||
*
|
||||
* Returns: Value label for an option.
|
||||
* Fetches the 'label' text (used for display purposes
|
||||
* in the menu) for the current value of the core
|
||||
* option at index @idx.
|
||||
*
|
||||
* Returns: core option value label string if
|
||||
* successful, otherwise NULL.
|
||||
**/
|
||||
const char *core_option_manager_get_val_label(core_option_manager_t *opt,
|
||||
size_t idx);
|
||||
|
||||
/**
|
||||
* core_option_manager_get_visible:
|
||||
* @opt : options manager handle
|
||||
* @idx : idx identifier of the option
|
||||
*
|
||||
* Gets whether option should be visible when displaying
|
||||
* core options in the frontend
|
||||
* @opt : options manager handle
|
||||
* @idx : core option index
|
||||
*
|
||||
* Returns: 'true' if option should be displayed by the frontend.
|
||||
* Queries whether the core option at index @idx
|
||||
* should be displayed in the frontend menu.
|
||||
*
|
||||
* Returns: true if option should be displayed by
|
||||
* the frontend, otherwise false.
|
||||
**/
|
||||
bool core_option_manager_get_visible(core_option_manager_t *opt,
|
||||
size_t idx);
|
||||
|
||||
/******************/
|
||||
/* Option Setters */
|
||||
/******************/
|
||||
|
||||
/**
|
||||
* core_option_manager_set_val:
|
||||
*
|
||||
* @opt : options manager handle
|
||||
* @idx : core option index
|
||||
* @val_idx : index of the value to set
|
||||
* @refresh_menu : flag specifying whether menu
|
||||
* should be refreshed if changes
|
||||
* to option visibility are detected
|
||||
*
|
||||
* Sets the core option at index @idx to the
|
||||
* option value corresponding to @val_idx.
|
||||
* After setting the option value, a request
|
||||
* will be made for the core to update the
|
||||
* in-menu visibility of all options; if
|
||||
* visibility changes are detected and
|
||||
* @refresh_menu is true, the menu will be
|
||||
* redrawn.
|
||||
**/
|
||||
void core_option_manager_set_val(core_option_manager_t *opt,
|
||||
size_t idx, size_t val_idx);
|
||||
size_t idx, size_t val_idx, bool refresh_menu);
|
||||
|
||||
/**
|
||||
* core_option_manager_adjust_val:
|
||||
*
|
||||
* @opt : options manager handle
|
||||
* @idx : core option index
|
||||
* @adjustment : offset to apply from current
|
||||
* value index
|
||||
* @refresh_menu : flag specifying whether menu
|
||||
* should be refreshed if changes
|
||||
* to option visibility are detected
|
||||
*
|
||||
* Modifies the value of the core option at
|
||||
* index @idx by incrementing the current option
|
||||
* value index by @adjustment.
|
||||
* After setting the option value, a request
|
||||
* will be made for the core to update the
|
||||
* in-menu visibility of all options; if
|
||||
* visibility changes are detected and
|
||||
* @refresh_menu is true, the menu will be
|
||||
* redrawn.
|
||||
**/
|
||||
void core_option_manager_adjust_val(core_option_manager_t* opt,
|
||||
size_t idx, int adjustment, bool refresh_menu);
|
||||
|
||||
/**
|
||||
* core_option_manager_set_default:
|
||||
*
|
||||
* @opt : options manager handle
|
||||
* @idx : core option index
|
||||
* @refresh_menu : flag specifying whether menu
|
||||
* should be refreshed if changes
|
||||
* to option visibility are detected
|
||||
*
|
||||
* Resets the core option at index @idx to
|
||||
* its default value.
|
||||
* After setting the option value, a request
|
||||
* will be made for the core to update the
|
||||
* in-menu visibility of all options; if
|
||||
* visibility changes are detected and
|
||||
* @refresh_menu is true, the menu will be
|
||||
* redrawn.
|
||||
**/
|
||||
void core_option_manager_set_default(core_option_manager_t *opt,
|
||||
size_t idx, bool refresh_menu);
|
||||
|
||||
/**
|
||||
* core_option_manager_set_visible:
|
||||
*
|
||||
* @opt : options manager handle
|
||||
* @key : core option key string (variable to query
|
||||
* in RETRO_ENVIRONMENT_GET_VARIABLE)
|
||||
* @visible : flag specifying whether option should
|
||||
* be shown in the menu
|
||||
*
|
||||
* Sets the in-menu visibility of the core option
|
||||
* identified by the specified @key.
|
||||
**/
|
||||
void core_option_manager_set_visible(core_option_manager_t *opt,
|
||||
const char *key, bool visible);
|
||||
|
||||
/**********************/
|
||||
/* Configuration File */
|
||||
/**********************/
|
||||
|
||||
/**
|
||||
* core_option_manager_flush:
|
||||
*
|
||||
* @opt : options manager handle
|
||||
* @conf : configuration file handle
|
||||
*
|
||||
* Writes all core option key-pair values from the
|
||||
* specified core option manager handle to the
|
||||
* specified configuration file struct.
|
||||
**/
|
||||
void core_option_manager_flush(core_option_manager_t *opt,
|
||||
config_file_t *conf);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
|
||||
+20
-3
@@ -37,7 +37,9 @@ int database_info_build_query_enum(char *s, size_t len,
|
||||
bool add_quotes = true;
|
||||
bool add_glob = false;
|
||||
|
||||
strcpy_literal(s, "{'");
|
||||
s[0] = '{';
|
||||
s[1] = '\'';
|
||||
s[2] = '\0';
|
||||
|
||||
switch (type)
|
||||
{
|
||||
@@ -279,8 +281,23 @@ static int database_cursor_iterate(libretrodb_cursor_t *cur,
|
||||
else if (string_is_equal(str, "size"))
|
||||
db_info->size = (unsigned)val->val.uint_;
|
||||
else if (string_is_equal(str, "crc"))
|
||||
db_info->crc32 = swap_if_little32(
|
||||
*(uint32_t*)val->val.binary.buff);
|
||||
{
|
||||
switch (val->val.binary.len)
|
||||
{
|
||||
case 1:
|
||||
db_info->crc32 = *(uint8_t*)val->val.binary.buff;
|
||||
break;
|
||||
case 2:
|
||||
db_info->crc32 = swap_if_little16(*(uint16_t*)val->val.binary.buff);
|
||||
break;
|
||||
case 4:
|
||||
db_info->crc32 = swap_if_little32(*(uint32_t*)val->val.binary.buff);
|
||||
break;
|
||||
default:
|
||||
db_info->crc32 = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (string_is_equal(str, "sha1"))
|
||||
db_info->sha1 = bin_to_hex_alloc(
|
||||
(uint8_t*)val->val.binary.buff, val->val.binary.len);
|
||||
|
||||
Vendored
+109
-114
@@ -1,91 +1,57 @@
|
||||
/* 7z.h -- 7z interface
|
||||
2010-03-11 : Igor Pavlov : Public domain */
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_H
|
||||
#define __7Z_H
|
||||
|
||||
#include "7zBuf.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#define k7zStartHeaderSize 0x20
|
||||
#define k7zSignatureSize 6
|
||||
extern uint8_t k7zSignature[k7zSignatureSize];
|
||||
#define k7zMajorVersion 0
|
||||
|
||||
enum EIdEnum
|
||||
{
|
||||
k7zIdEnd,
|
||||
k7zIdHeader,
|
||||
k7zIdArchiveProperties,
|
||||
k7zIdAdditionalStreamsInfo,
|
||||
k7zIdMainStreamsInfo,
|
||||
k7zIdFilesInfo,
|
||||
k7zIdPackInfo,
|
||||
k7zIdUnpackInfo,
|
||||
k7zIdSubStreamsInfo,
|
||||
k7zIdSize,
|
||||
k7zIdCRC,
|
||||
k7zIdFolder,
|
||||
k7zIdCodersUnpackSize,
|
||||
k7zIdNumUnpackStream,
|
||||
k7zIdEmptyStream,
|
||||
k7zIdEmptyFile,
|
||||
k7zIdAnti,
|
||||
k7zIdName,
|
||||
k7zIdCTime,
|
||||
k7zIdATime,
|
||||
k7zIdMTime,
|
||||
k7zIdWinAttributes,
|
||||
k7zIdComment,
|
||||
k7zIdEncodedHeader,
|
||||
k7zIdStartPos,
|
||||
k7zIdDummy
|
||||
};
|
||||
extern const Byte k7zSignature[k7zSignatureSize];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t NumInStreams;
|
||||
uint32_t NumOutStreams;
|
||||
uint64_t MethodID;
|
||||
CBuf Props;
|
||||
} CSzCoderInfo;
|
||||
const Byte *Data;
|
||||
size_t Size;
|
||||
} CSzData;
|
||||
|
||||
void SzCoderInfo_Init(CSzCoderInfo *p);
|
||||
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);
|
||||
/* CSzCoderInfo & CSzFolder support only default methods */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t PropsOffset;
|
||||
uint32_t MethodID;
|
||||
Byte NumStreams;
|
||||
Byte PropsSize;
|
||||
} CSzCoderInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t InIndex;
|
||||
uint32_t OutIndex;
|
||||
} CSzBindPair;
|
||||
} CSzBond;
|
||||
|
||||
#define SZ_NUM_CODERS_IN_FOLDER_MAX 4
|
||||
#define SZ_NUM_BONDS_IN_FOLDER_MAX 3
|
||||
#define SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX 4
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CSzCoderInfo *Coders;
|
||||
CSzBindPair *BindPairs;
|
||||
uint32_t *PackStreams;
|
||||
uint64_t *UnpackSizes;
|
||||
uint32_t NumCoders;
|
||||
uint32_t NumBindPairs;
|
||||
uint32_t NumBonds;
|
||||
uint32_t NumPackStreams;
|
||||
int UnpackCRCDefined;
|
||||
uint32_t UnpackCRC;
|
||||
|
||||
uint32_t NumUnpackStreams;
|
||||
uint32_t UnpackStream;
|
||||
uint32_t PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX];
|
||||
CSzBond Bonds[SZ_NUM_BONDS_IN_FOLDER_MAX];
|
||||
CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX];
|
||||
} CSzFolder;
|
||||
|
||||
void SzFolder_Init(CSzFolder *p);
|
||||
uint64_t SzFolder_GetUnpackSize(CSzFolder *p);
|
||||
int SzFolder_FindBindPairForInStream(CSzFolder *p, uint32_t inStreamIndex);
|
||||
uint32_t SzFolder_GetNumOutStreams(CSzFolder *p);
|
||||
uint64_t SzFolder_GetUnpackSize(CSzFolder *p);
|
||||
|
||||
SRes SzFolder_Decode(const CSzFolder *folder, const uint64_t *packSizes,
|
||||
ILookInStream *stream, uint64_t startPos,
|
||||
uint8_t *outBuffer, size_t outSize, ISzAlloc *allocMain);
|
||||
SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -95,55 +61,44 @@ typedef struct
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CNtfsFileTime MTime;
|
||||
uint64_t Size;
|
||||
uint32_t Crc;
|
||||
uint32_t Attrib;
|
||||
uint8_t HasStream;
|
||||
uint8_t IsDir;
|
||||
uint8_t IsAnti;
|
||||
uint8_t CrcDefined;
|
||||
uint8_t MTimeDefined;
|
||||
uint8_t AttribDefined;
|
||||
} CSzFileItem;
|
||||
Byte *Defs; /* MSB 0 bit numbering */
|
||||
uint32_t *Vals;
|
||||
} CSzBitUi32s;
|
||||
|
||||
void SzFile_Init(CSzFileItem *p);
|
||||
typedef struct
|
||||
{
|
||||
Byte *Defs; /* MSB 0 bit numbering */
|
||||
/* uint64_t *Vals; */
|
||||
CNtfsFileTime *Vals;
|
||||
} CSzBitUi64s;
|
||||
|
||||
#define SzBitArray_Check(p, i) (((p)[(i) >> 3] & (0x80 >> ((i) & 7))) != 0)
|
||||
|
||||
#define SzBitWithVals_Check(p, i) ((p)->Defs && ((p)->Defs[(i) >> 3] & (0x80 >> ((i) & 7))) != 0)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t *PackSizes;
|
||||
uint8_t *PackCRCsDefined;
|
||||
uint32_t *PackCRCs;
|
||||
CSzFolder *Folders;
|
||||
CSzFileItem *Files;
|
||||
uint32_t NumPackStreams;
|
||||
uint32_t NumFolders;
|
||||
uint32_t NumFiles;
|
||||
|
||||
uint64_t *PackPositions; /* NumPackStreams + 1 */
|
||||
CSzBitUi32s FolderCRCs; /* NumFolders */
|
||||
|
||||
size_t *FoCodersOffsets; /* NumFolders + 1 */
|
||||
uint32_t *FoStartPackStreamIndex; /* NumFolders + 1 */
|
||||
uint32_t *FoToCoderUnpackSizes; /* NumFolders + 1 */
|
||||
Byte *FoToMainUnpackSizeIndex; /* NumFolders */
|
||||
uint64_t *CoderUnpackSizes; /* for all coders in all folders */
|
||||
|
||||
Byte *CodersData;
|
||||
} CSzAr;
|
||||
|
||||
void SzAr_Init(CSzAr *p);
|
||||
void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
|
||||
uint64_t SzAr_GetFolderUnpackSize(const CSzAr *p, uint32_t folderIndex);
|
||||
|
||||
|
||||
/*
|
||||
SzExtract extracts file from archive
|
||||
|
||||
*outBuffer must be 0 before first call for each new archive.
|
||||
|
||||
Extracting cache:
|
||||
If you need to decompress more than one file, you can send
|
||||
these values from previous call:
|
||||
*blockIndex,
|
||||
*outBuffer,
|
||||
*outBufferSize
|
||||
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
|
||||
it will increase decompression speed.
|
||||
|
||||
If you use external function, you can declare these 3 cache variables
|
||||
(blockIndex, outBuffer, outBufferSize) as static in that external function.
|
||||
|
||||
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
|
||||
*/
|
||||
SRes SzAr_DecodeFolder(const CSzAr *p, uint32_t folderIndex,
|
||||
ILookInStream *stream, uint64_t startPos,
|
||||
Byte *outBuffer, size_t outSize,
|
||||
ISzAllocPtr allocMain);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -151,18 +106,32 @@ typedef struct
|
||||
|
||||
uint64_t startPosAfterHeader;
|
||||
uint64_t dataPos;
|
||||
|
||||
uint32_t NumFiles;
|
||||
|
||||
uint32_t *FolderStartPackStreamIndex;
|
||||
uint64_t *PackStreamStartPositions;
|
||||
uint32_t *FolderStartFileIndex;
|
||||
uint32_t *FileIndexToFolderIndexMap;
|
||||
uint64_t *UnpackPositions; /* NumFiles + 1 */
|
||||
/* Byte *IsEmptyFiles; */
|
||||
Byte *IsDirs;
|
||||
CSzBitUi32s CRCs;
|
||||
|
||||
CSzBitUi32s Attribs;
|
||||
/* CSzBitUi32s Parents; */
|
||||
CSzBitUi64s MTime;
|
||||
CSzBitUi64s CTime;
|
||||
|
||||
uint32_t *FolderToFile; /* NumFolders + 1 */
|
||||
uint32_t *FileToFolder; /* NumFiles */
|
||||
|
||||
size_t *FileNameOffsets; /* in 2-byte steps */
|
||||
CBuf FileNames; /* UTF-16-LE */
|
||||
Byte *FileNames; /* UTF-16-LE */
|
||||
} CSzArEx;
|
||||
|
||||
#define SzArEx_IsDir(p, i) (SzBitArray_Check((p)->IsDirs, i))
|
||||
|
||||
#define SzArEx_GetFileSize(p, i) ((p)->UnpackPositions[(i) + 1] - (p)->UnpackPositions[i])
|
||||
|
||||
void SzArEx_Init(CSzArEx *p);
|
||||
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);
|
||||
void SzArEx_Free(CSzArEx *p, ISzAllocPtr alloc);
|
||||
uint64_t SzArEx_GetFolderStreamPos(const CSzArEx *p, uint32_t folderIndex, uint32_t indexInFolder);
|
||||
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, uint32_t folderIndex, uint64_t *resSize);
|
||||
|
||||
@@ -174,17 +143,44 @@ if dest != NULL, the return value specifies the number of 16-bit characters that
|
||||
|
||||
size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, uint16_t *dest);
|
||||
|
||||
/*
|
||||
size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex);
|
||||
uint16_t *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, uint16_t *dest);
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
SzArEx_Extract extracts file from archive
|
||||
|
||||
*outBuffer must be 0 before first call for each new archive.
|
||||
|
||||
Extracting cache:
|
||||
If you need to decompress more than one file, you can send
|
||||
these values from previous call:
|
||||
*blockIndex,
|
||||
*outBuffer,
|
||||
*outBufferSize
|
||||
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
|
||||
it will increase decompression speed.
|
||||
|
||||
If you use external function, you can declare these 3 cache variables
|
||||
(blockIndex, outBuffer, outBufferSize) as static in that external function.
|
||||
|
||||
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
|
||||
*/
|
||||
|
||||
SRes SzArEx_Extract(
|
||||
const CSzArEx *db,
|
||||
ILookInStream *inStream,
|
||||
uint32_t fileIndex, /* index of file */
|
||||
uint32_t *blockIndex, /* index of solid block */
|
||||
uint8_t **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
|
||||
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
|
||||
size_t *outBufferSize, /* buffer size for output buffer */
|
||||
size_t *offset, /* offset of stream for required file in *outBuffer */
|
||||
size_t *outSizeProcessed, /* size of file in *outBuffer */
|
||||
ISzAlloc *allocMain,
|
||||
ISzAlloc *allocTemp);
|
||||
ISzAllocPtr allocMain,
|
||||
ISzAllocPtr allocTemp);
|
||||
|
||||
|
||||
/*
|
||||
@@ -198,10 +194,9 @@ SZ_ERROR_INPUT_EOF
|
||||
SZ_ERROR_FAIL
|
||||
*/
|
||||
|
||||
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
|
||||
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream,
|
||||
ISzAllocPtr allocMain, ISzAllocPtr allocTemp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
Vendored
+1771
File diff suppressed because it is too large.
Load diff
Vendored
+23
-24
@@ -1,37 +1,36 @@
|
||||
/* 7zBuf.c -- Byte Buffer
|
||||
2008-03-28
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include "7zBuf.h"
|
||||
|
||||
void Buf_Init(CBuf *p)
|
||||
{
|
||||
p->data = 0;
|
||||
p->size = 0;
|
||||
p->data = 0;
|
||||
p->size = 0;
|
||||
}
|
||||
|
||||
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc)
|
||||
int Buf_Create(CBuf *p, size_t size, ISzAllocPtr alloc)
|
||||
{
|
||||
p->size = 0;
|
||||
if (size == 0)
|
||||
{
|
||||
p->data = 0;
|
||||
return 1;
|
||||
}
|
||||
p->data = (uint8_t *)alloc->Alloc(alloc, size);
|
||||
if (p->data != 0)
|
||||
{
|
||||
p->size = size;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
p->size = 0;
|
||||
if (size == 0)
|
||||
{
|
||||
p->data = 0;
|
||||
return 1;
|
||||
}
|
||||
p->data = (Byte *)ISzAlloc_Alloc(alloc, size);
|
||||
if (p->data)
|
||||
{
|
||||
p->size = size;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Buf_Free(CBuf *p, ISzAlloc *alloc)
|
||||
void Buf_Free(CBuf *p, ISzAllocPtr alloc)
|
||||
{
|
||||
alloc->Free(alloc, p->data);
|
||||
p->data = 0;
|
||||
p->size = 0;
|
||||
ISzAlloc_Free(alloc, p->data);
|
||||
p->data = 0;
|
||||
p->size = 0;
|
||||
}
|
||||
Vendored
+18
-10
@@ -1,27 +1,35 @@
|
||||
/* 7zBuf.h -- Byte Buffer
|
||||
2009-02-07 : Igor Pavlov : Public domain */
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_BUF_H
|
||||
#define __7Z_BUF_H
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t *data;
|
||||
Byte *data;
|
||||
size_t size;
|
||||
} CBuf;
|
||||
|
||||
void Buf_Init(CBuf *p);
|
||||
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc);
|
||||
void Buf_Free(CBuf *p, ISzAlloc *alloc);
|
||||
int Buf_Create(CBuf *p, size_t size, ISzAllocPtr alloc);
|
||||
void Buf_Free(CBuf *p, ISzAllocPtr alloc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
typedef struct
|
||||
{
|
||||
Byte *data;
|
||||
size_t size;
|
||||
size_t pos;
|
||||
} CDynBuf;
|
||||
|
||||
void DynBuf_Construct(CDynBuf *p);
|
||||
void DynBuf_SeekToBeg(CDynBuf *p);
|
||||
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAllocPtr alloc);
|
||||
void DynBuf_Free(CDynBuf *p, ISzAllocPtr alloc);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
Vendored
+104
-52
@@ -1,76 +1,128 @@
|
||||
/* 7zCrc.c -- CRC32 calculation
|
||||
2009-11-23 : Igor Pavlov : Public domain */
|
||||
/* 7zCrc.c -- CRC32 init
|
||||
2017-06-06 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include "7zCrc.h"
|
||||
#include "CpuArch.h"
|
||||
|
||||
#define kCrcPoly 0xEDB88320
|
||||
|
||||
#ifdef MSB_FIRST
|
||||
#define CRC_NUM_TABLES 1
|
||||
#ifdef MY_CPU_LE
|
||||
#define CRC_NUM_TABLES 8
|
||||
#else
|
||||
#define CRC_NUM_TABLES 8
|
||||
#define CRC_NUM_TABLES 9
|
||||
|
||||
#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24))
|
||||
|
||||
uint32_t MY_FAST_CALL CrcUpdateT1_BeT4(uint32_t v, const void *data, size_t size, const uint32_t *table);
|
||||
uint32_t MY_FAST_CALL CrcUpdateT1_BeT8(uint32_t v, const void *data, size_t size, const uint32_t *table);
|
||||
#endif
|
||||
|
||||
#ifndef MY_CPU_BE
|
||||
uint32_t MY_FAST_CALL CrcUpdateT4(uint32_t v, const void *data, size_t size, const uint32_t *table);
|
||||
uint32_t MY_FAST_CALL CrcUpdateT8(uint32_t v, const void *data, size_t size, const uint32_t *table);
|
||||
#endif
|
||||
|
||||
typedef uint32_t (MY_FAST_CALL *CRC_FUNC)(uint32_t v, const void *data, size_t size, const uint32_t *table);
|
||||
|
||||
static CRC_FUNC g_CrcUpdate;
|
||||
CRC_FUNC g_CrcUpdateT4;
|
||||
CRC_FUNC g_CrcUpdateT8;
|
||||
CRC_FUNC g_CrcUpdate;
|
||||
|
||||
uint32_t g_CrcTable[256 * CRC_NUM_TABLES];
|
||||
|
||||
#if CRC_NUM_TABLES == 1
|
||||
|
||||
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
||||
|
||||
static uint32_t MY_FAST_CALL CrcUpdateT1(uint32_t v, const void *data, size_t size, const uint32_t *table)
|
||||
{
|
||||
const uint8_t *p = (const uint8_t *)data;
|
||||
for (; size > 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
return v;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
uint32_t MY_FAST_CALL CrcUpdateT4(uint32_t v, const void *data, size_t size, const uint32_t *table);
|
||||
uint32_t MY_FAST_CALL CrcUpdateT8(uint32_t v, const void *data, size_t size, const uint32_t *table);
|
||||
|
||||
#endif
|
||||
|
||||
uint32_t MY_FAST_CALL CrcUpdate(uint32_t v, const void *data, size_t size)
|
||||
{
|
||||
return g_CrcUpdate(v, data, size, g_CrcTable);
|
||||
return g_CrcUpdate(v, data, size, g_CrcTable);
|
||||
}
|
||||
|
||||
uint32_t MY_FAST_CALL CrcCalc(const void *data, size_t size)
|
||||
{
|
||||
return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;
|
||||
return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;
|
||||
}
|
||||
|
||||
void MY_FAST_CALL CrcGenerateTable(void)
|
||||
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
||||
|
||||
uint32_t MY_FAST_CALL CrcUpdateT1(uint32_t v, const void *data, size_t size, const uint32_t *table)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
uint32_t r = i;
|
||||
unsigned j;
|
||||
for (j = 0; j < 8; j++)
|
||||
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
|
||||
g_CrcTable[i] = r;
|
||||
}
|
||||
#if CRC_NUM_TABLES == 1
|
||||
g_CrcUpdate = CrcUpdateT1;
|
||||
#else
|
||||
for (; i < 256 * CRC_NUM_TABLES; i++)
|
||||
{
|
||||
uint32_t r = g_CrcTable[i - 256];
|
||||
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
|
||||
}
|
||||
const Byte *p = (const Byte *)data;
|
||||
const Byte *pEnd = p + size;
|
||||
for (; p != pEnd; p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
return v;
|
||||
}
|
||||
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
g_CrcUpdate = CrcUpdateT8;
|
||||
#else
|
||||
g_CrcUpdate = CrcUpdateT4;
|
||||
#endif
|
||||
#endif
|
||||
void MY_FAST_CALL CrcGenerateTable()
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
uint32_t r = i;
|
||||
unsigned j;
|
||||
for (j = 0; j < 8; j++)
|
||||
r = (r >> 1) ^ (kCrcPoly & ((uint32_t)0 - (r & 1)));
|
||||
g_CrcTable[i] = r;
|
||||
}
|
||||
for (i = 256; i < 256 * CRC_NUM_TABLES; i++)
|
||||
{
|
||||
uint32_t r = g_CrcTable[(size_t)i - 256];
|
||||
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
|
||||
}
|
||||
|
||||
#if CRC_NUM_TABLES < 4
|
||||
|
||||
g_CrcUpdate = CrcUpdateT1;
|
||||
|
||||
#else
|
||||
|
||||
#ifdef MY_CPU_LE
|
||||
|
||||
g_CrcUpdateT4 = CrcUpdateT4;
|
||||
g_CrcUpdate = CrcUpdateT4;
|
||||
|
||||
#if CRC_NUM_TABLES >= 8
|
||||
g_CrcUpdateT8 = CrcUpdateT8;
|
||||
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
if (!CPU_Is_InOrder())
|
||||
#endif
|
||||
g_CrcUpdate = CrcUpdateT8;
|
||||
#endif
|
||||
|
||||
#else
|
||||
{
|
||||
#ifndef MY_CPU_BE
|
||||
uint32_t k = 0x01020304;
|
||||
const Byte *p = (const Byte *)&k;
|
||||
if (p[0] == 4 && p[1] == 3)
|
||||
{
|
||||
g_CrcUpdateT4 = CrcUpdateT4;
|
||||
g_CrcUpdate = CrcUpdateT4;
|
||||
#if CRC_NUM_TABLES >= 8
|
||||
g_CrcUpdateT8 = CrcUpdateT8;
|
||||
g_CrcUpdate = CrcUpdateT8;
|
||||
#endif
|
||||
}
|
||||
else if (p[0] != 1 || p[1] != 2)
|
||||
g_CrcUpdate = CrcUpdateT1;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--)
|
||||
{
|
||||
uint32_t x = g_CrcTable[(size_t)i - 256];
|
||||
g_CrcTable[i] = CRC_UINT32_SWAP(x);
|
||||
}
|
||||
g_CrcUpdateT4 = CrcUpdateT1_BeT4;
|
||||
g_CrcUpdate = CrcUpdateT1_BeT4;
|
||||
#if CRC_NUM_TABLES >= 8
|
||||
g_CrcUpdateT8 = CrcUpdateT1_BeT8;
|
||||
g_CrcUpdate = CrcUpdateT1_BeT8;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
Vendored
+3
-7
@@ -1,14 +1,12 @@
|
||||
/* 7zCrc.h -- CRC32 calculation
|
||||
2009-11-21 : Igor Pavlov : Public domain */
|
||||
2013-01-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_CRC_H
|
||||
#define __7Z_CRC_H
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
extern uint32_t g_CrcTable[];
|
||||
|
||||
@@ -22,8 +20,6 @@ void MY_FAST_CALL CrcGenerateTable(void);
|
||||
uint32_t MY_FAST_CALL CrcUpdate(uint32_t crc, const void *data, size_t size);
|
||||
uint32_t MY_FAST_CALL CrcCalc(const void *data, size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
Vendored
+100
-23
@@ -1,38 +1,115 @@
|
||||
/* 7zCrcOpt.c -- CRC32 calculation : optimized version
|
||||
2009-11-23 : Igor Pavlov : Public domain */
|
||||
/* 7zCrcOpt.c -- CRC32 calculation
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include "CpuArch.h"
|
||||
|
||||
#ifndef MSB_FIRST
|
||||
#ifndef MY_CPU_BE
|
||||
|
||||
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
||||
|
||||
uint32_t MY_FAST_CALL CrcUpdateT4(uint32_t v, const void *data, size_t size, const uint32_t *table);
|
||||
uint32_t MY_FAST_CALL CrcUpdateT8(uint32_t v, const void *data, size_t size, const uint32_t *table);
|
||||
|
||||
uint32_t MY_FAST_CALL CrcUpdateT4(uint32_t v, const void *data, size_t size, const uint32_t *table)
|
||||
{
|
||||
const uint8_t *p = (const uint8_t*)data;
|
||||
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
for (; size >= 4; size -= 4, p += 4)
|
||||
{
|
||||
v ^= *(const uint32_t *)p;
|
||||
v =
|
||||
table[0x300 + (v & 0xFF)] ^
|
||||
table[0x200 + ((v >> 8) & 0xFF)] ^
|
||||
table[0x100 + ((v >> 16) & 0xFF)] ^
|
||||
table[0x000 + ((v >> 24))];
|
||||
}
|
||||
for (; size > 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
return v;
|
||||
const Byte *p = (const Byte *)data;
|
||||
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
for (; size >= 4; size -= 4, p += 4)
|
||||
{
|
||||
v ^= *(const uint32_t *)p;
|
||||
v =
|
||||
(table + 0x300)[((v ) & 0xFF)]
|
||||
^ (table + 0x200)[((v >> 8) & 0xFF)]
|
||||
^ (table + 0x100)[((v >> 16) & 0xFF)]
|
||||
^ (table + 0x000)[((v >> 24))];
|
||||
}
|
||||
for (; size > 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
return v;
|
||||
}
|
||||
|
||||
uint32_t MY_FAST_CALL CrcUpdateT8(uint32_t v, const void *data, size_t size, const uint32_t *table)
|
||||
{
|
||||
return CrcUpdateT4(v, data, size, table);
|
||||
const Byte *p = (const Byte *)data;
|
||||
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
for (; size >= 8; size -= 8, p += 8)
|
||||
{
|
||||
uint32_t d;
|
||||
v ^= *(const uint32_t *)p;
|
||||
v =
|
||||
(table + 0x700)[((v ) & 0xFF)]
|
||||
^ (table + 0x600)[((v >> 8) & 0xFF)]
|
||||
^ (table + 0x500)[((v >> 16) & 0xFF)]
|
||||
^ (table + 0x400)[((v >> 24))];
|
||||
d = *((const uint32_t *)p + 1);
|
||||
v ^=
|
||||
(table + 0x300)[((d ) & 0xFF)]
|
||||
^ (table + 0x200)[((d >> 8) & 0xFF)]
|
||||
^ (table + 0x100)[((d >> 16) & 0xFF)]
|
||||
^ (table + 0x000)[((d >> 24))];
|
||||
}
|
||||
for (; size > 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
return v;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef MY_CPU_LE
|
||||
|
||||
#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24))
|
||||
|
||||
#define CRC_UPDATE_BYTE_2_BE(crc, b) (table[(((crc) >> 24) ^ (b))] ^ ((crc) << 8))
|
||||
|
||||
uint32_t MY_FAST_CALL CrcUpdateT1_BeT4(uint32_t v, const void *data, size_t size, const uint32_t *table)
|
||||
{
|
||||
const Byte *p = (const Byte *)data;
|
||||
table += 0x100;
|
||||
v = CRC_UINT32_SWAP(v);
|
||||
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2_BE(v, *p);
|
||||
for (; size >= 4; size -= 4, p += 4)
|
||||
{
|
||||
v ^= *(const uint32_t *)p;
|
||||
v =
|
||||
(table + 0x000)[((v ) & 0xFF)]
|
||||
^ (table + 0x100)[((v >> 8) & 0xFF)]
|
||||
^ (table + 0x200)[((v >> 16) & 0xFF)]
|
||||
^ (table + 0x300)[((v >> 24))];
|
||||
}
|
||||
for (; size > 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2_BE(v, *p);
|
||||
return CRC_UINT32_SWAP(v);
|
||||
}
|
||||
|
||||
uint32_t MY_FAST_CALL CrcUpdateT1_BeT8(uint32_t v, const void *data, size_t size, const uint32_t *table)
|
||||
{
|
||||
const Byte *p = (const Byte *)data;
|
||||
table += 0x100;
|
||||
v = CRC_UINT32_SWAP(v);
|
||||
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2_BE(v, *p);
|
||||
for (; size >= 8; size -= 8, p += 8)
|
||||
{
|
||||
uint32_t d;
|
||||
v ^= *(const uint32_t *)p;
|
||||
v =
|
||||
(table + 0x400)[((v ) & 0xFF)]
|
||||
^ (table + 0x500)[((v >> 8) & 0xFF)]
|
||||
^ (table + 0x600)[((v >> 16) & 0xFF)]
|
||||
^ (table + 0x700)[((v >> 24))];
|
||||
d = *((const uint32_t *)p + 1);
|
||||
v ^=
|
||||
(table + 0x000)[((d ) & 0xFF)]
|
||||
^ (table + 0x100)[((d >> 8) & 0xFF)]
|
||||
^ (table + 0x200)[((d >> 16) & 0xFF)]
|
||||
^ (table + 0x300)[((d >> 24))];
|
||||
}
|
||||
for (; size > 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2_BE(v, *p);
|
||||
return CRC_UINT32_SWAP(v);
|
||||
}
|
||||
|
||||
#endif
|
||||
Vendored
+487
-339
@@ -1,83 +1,184 @@
|
||||
/* 7zDec.c -- Decoding from 7z folder
|
||||
2010-11-02 : Igor Pavlov : Public domain */
|
||||
2019-02-02 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <boolean.h>
|
||||
|
||||
/* #define _7ZIP_PPMD_SUPPPORT */
|
||||
|
||||
#include "7z.h"
|
||||
#include "7zCrc.h"
|
||||
|
||||
#include "Bcj2.h"
|
||||
#include "Bra.h"
|
||||
#include "CpuArch.h"
|
||||
#include "Delta.h"
|
||||
#include "LzmaDec.h"
|
||||
#include "Lzma2Dec.h"
|
||||
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||
#include "Ppmd7.h"
|
||||
#endif
|
||||
|
||||
#define k_Copy 0
|
||||
#define k_Delta 3
|
||||
#define k_LZMA2 0x21
|
||||
#define k_LZMA 0x30101
|
||||
#define k_BCJ 0x03030103
|
||||
#define k_PPC 0x03030205
|
||||
#define k_ARM 0x03030501
|
||||
#define k_ARMT 0x03030701
|
||||
#define k_SPARC 0x03030805
|
||||
#define k_BCJ2 0x0303011B
|
||||
#define k_BCJ 0x3030103
|
||||
#define k_BCJ2 0x303011B
|
||||
#define k_PPC 0x3030205
|
||||
#define k_IA64 0x3030401
|
||||
#define k_ARM 0x3030501
|
||||
#define k_ARMT 0x3030701
|
||||
#define k_SPARC 0x3030805
|
||||
|
||||
static SRes SzDecodeLzma(CSzCoderInfo *coder,
|
||||
uint64_t inSize, ILookInStream *inStream,
|
||||
uint8_t *outBuffer, size_t outSize, ISzAlloc *allocMain)
|
||||
|
||||
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||
|
||||
#define k_PPMD 0x30401
|
||||
|
||||
typedef struct
|
||||
{
|
||||
IByteIn vt;
|
||||
const Byte *cur;
|
||||
const Byte *end;
|
||||
const Byte *begin;
|
||||
uint64_t processed;
|
||||
BoolInt extra;
|
||||
SRes res;
|
||||
const ILookInStream *inStream;
|
||||
} CByteInToLook;
|
||||
|
||||
static Byte ReadByte(const IByteIn *pp)
|
||||
{
|
||||
CByteInToLook *p = CONTAINER_FROM_VTBL(pp, CByteInToLook, vt);
|
||||
if (p->cur != p->end)
|
||||
return *p->cur++;
|
||||
if (p->res == SZ_OK)
|
||||
{
|
||||
size_t size = p->cur - p->begin;
|
||||
p->processed += size;
|
||||
p->res = ILookInStream_Skip(p->inStream, size);
|
||||
size = (1 << 25);
|
||||
p->res = ILookInStream_Look(p->inStream, (const void **)&p->begin, &size);
|
||||
p->cur = p->begin;
|
||||
p->end = p->begin + size;
|
||||
if (size != 0)
|
||||
return *p->cur++;;
|
||||
}
|
||||
p->extra = True;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, uint64_t inSize, const ILookInStream *inStream,
|
||||
Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain)
|
||||
{
|
||||
CPpmd7 ppmd;
|
||||
CByteInToLook s;
|
||||
SRes res = SZ_OK;
|
||||
|
||||
s.vt.Read = ReadByte;
|
||||
s.inStream = inStream;
|
||||
s.begin = s.end = s.cur = NULL;
|
||||
s.extra = False;
|
||||
s.res = SZ_OK;
|
||||
s.processed = 0;
|
||||
|
||||
if (propsSize != 5)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
|
||||
{
|
||||
unsigned order = props[0];
|
||||
uint32_t memSize = GetUi32(props + 1);
|
||||
if (order < PPMD7_MIN_ORDER ||
|
||||
order > PPMD7_MAX_ORDER ||
|
||||
memSize < PPMD7_MIN_MEM_SIZE ||
|
||||
memSize > PPMD7_MAX_MEM_SIZE)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
Ppmd7_Construct(&ppmd);
|
||||
if (!Ppmd7_Alloc(&ppmd, memSize, allocMain))
|
||||
return SZ_ERROR_MEM;
|
||||
Ppmd7_Init(&ppmd, order);
|
||||
}
|
||||
{
|
||||
CPpmd7z_RangeDec rc;
|
||||
Ppmd7z_RangeDec_CreateVTable(&rc);
|
||||
rc.Stream = &s.vt;
|
||||
if (!Ppmd7z_RangeDec_Init(&rc))
|
||||
res = SZ_ERROR_DATA;
|
||||
else if (s.extra)
|
||||
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
|
||||
else
|
||||
{
|
||||
SizeT i;
|
||||
for (i = 0; i < outSize; i++)
|
||||
{
|
||||
int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.vt);
|
||||
if (s.extra || sym < 0)
|
||||
break;
|
||||
outBuffer[i] = (Byte)sym;
|
||||
}
|
||||
if (i != outSize)
|
||||
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
|
||||
else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc))
|
||||
res = SZ_ERROR_DATA;
|
||||
}
|
||||
}
|
||||
Ppmd7_Free(&ppmd, allocMain);
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, uint64_t inSize, ILookInStream *inStream,
|
||||
Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain)
|
||||
{
|
||||
SRes result;
|
||||
CLzmaDec state;
|
||||
SRes res = SZ_OK;
|
||||
SRes res = SZ_OK;
|
||||
|
||||
LzmaDec_Construct(&state);
|
||||
result = LzmaDec_AllocateProbs(
|
||||
&state, coder->Props.data,
|
||||
(unsigned)coder->Props.size, allocMain);
|
||||
if (result != 0)
|
||||
return result;
|
||||
state.dic = outBuffer;
|
||||
RINOK(LzmaDec_AllocateProbs(&state, props, propsSize, allocMain));
|
||||
state.dic = outBuffer;
|
||||
state.dicBufSize = outSize;
|
||||
LzmaDec_Init(&state);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
uint8_t *inBuf = NULL;
|
||||
const void *inBuf = NULL;
|
||||
size_t lookahead = (1 << 18);
|
||||
if (lookahead > inSize)
|
||||
lookahead = (size_t)inSize;
|
||||
res = inStream->Look(
|
||||
(void *)inStream, (const void **)&inBuf, &lookahead);
|
||||
|
||||
lookahead = (size_t)inSize;
|
||||
res = ILookInStream_Look(inStream, &inBuf, &lookahead);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
|
||||
{
|
||||
SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos;
|
||||
ELzmaStatus status;
|
||||
size_t inProcessed = (size_t)lookahead, dicPos = state.dicPos;
|
||||
res = LzmaDec_DecodeToDic(
|
||||
&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
|
||||
lookahead -= inProcessed;
|
||||
inSize -= inProcessed;
|
||||
|
||||
res = LzmaDec_DecodeToDic(&state, outSize, (const Byte *)inBuf, &inProcessed, LZMA_FINISH_END, &status);
|
||||
lookahead -= inProcessed;
|
||||
inSize -= inProcessed;
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
|
||||
if (
|
||||
state.dicPos == state.dicBufSize ||
|
||||
(inProcessed == 0 && dicPos == state.dicPos))
|
||||
if (status == LZMA_STATUS_FINISHED_WITH_MARK)
|
||||
{
|
||||
if (
|
||||
state.dicBufSize != outSize ||
|
||||
lookahead != 0 ||
|
||||
(status != LZMA_STATUS_FINISHED_WITH_MARK &&
|
||||
status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))
|
||||
if (outSize != state.dicPos || inSize != 0)
|
||||
res = SZ_ERROR_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
res = inStream->Skip((void *)inStream, inProcessed);
|
||||
if (outSize == state.dicPos && inSize == 0 && status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
|
||||
break;
|
||||
|
||||
if (inProcessed == 0 && dicPos == state.dicPos)
|
||||
{
|
||||
res = SZ_ERROR_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
res = ILookInStream_Skip(inStream, inProcessed);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
}
|
||||
@@ -87,357 +188,404 @@ static SRes SzDecodeLzma(CSzCoderInfo *coder,
|
||||
return res;
|
||||
}
|
||||
|
||||
static SRes SzDecodeLzma2(CSzCoderInfo *coder,
|
||||
uint64_t inSize, ILookInStream *inStream,
|
||||
uint8_t *outBuffer, size_t outSize, ISzAlloc *allocMain)
|
||||
|
||||
#ifndef _7Z_NO_METHOD_LZMA2
|
||||
|
||||
static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, uint64_t inSize, ILookInStream *inStream,
|
||||
Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain)
|
||||
{
|
||||
SRes result;
|
||||
CLzma2Dec state;
|
||||
SRes res = SZ_OK;
|
||||
CLzma2Dec state;
|
||||
SRes res = SZ_OK;
|
||||
|
||||
Lzma2Dec_Construct(&state);
|
||||
if (coder->Props.size != 1)
|
||||
return SZ_ERROR_DATA;
|
||||
Lzma2Dec_Construct(&state);
|
||||
if (propsSize != 1)
|
||||
return SZ_ERROR_DATA;
|
||||
RINOK(Lzma2Dec_AllocateProbs(&state, props[0], allocMain));
|
||||
state.decoder.dic = outBuffer;
|
||||
state.decoder.dicBufSize = outSize;
|
||||
Lzma2Dec_Init(&state);
|
||||
|
||||
result = Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain);
|
||||
if (result != 0)
|
||||
return result;
|
||||
for (;;)
|
||||
{
|
||||
const void *inBuf = NULL;
|
||||
size_t lookahead = (1 << 18);
|
||||
if (lookahead > inSize)
|
||||
lookahead = (size_t)inSize;
|
||||
res = ILookInStream_Look(inStream, &inBuf, &lookahead);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
|
||||
state.decoder.dic = outBuffer;
|
||||
state.decoder.dicBufSize = outSize;
|
||||
Lzma2Dec_Init(&state);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
uint8_t *inBuf = NULL;
|
||||
size_t lookahead = (1 << 18);
|
||||
if (lookahead > inSize)
|
||||
lookahead = (size_t)inSize;
|
||||
res = inStream->Look(
|
||||
(void *)inStream, (const void **)&inBuf, &lookahead);
|
||||
{
|
||||
SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos;
|
||||
ELzmaStatus status;
|
||||
res = Lzma2Dec_DecodeToDic(&state, outSize, (const Byte *)inBuf, &inProcessed, LZMA_FINISH_END, &status);
|
||||
lookahead -= inProcessed;
|
||||
inSize -= inProcessed;
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
break;
|
||||
|
||||
if (status == LZMA_STATUS_FINISHED_WITH_MARK)
|
||||
{
|
||||
ELzmaStatus status;
|
||||
size_t inProcessed = (size_t)lookahead, dicPos = state.decoder.dicPos;
|
||||
res = Lzma2Dec_DecodeToDic(
|
||||
&state, outSize, inBuf, &inProcessed,
|
||||
LZMA_FINISH_END, &status);
|
||||
lookahead -= inProcessed;
|
||||
inSize -= inProcessed;
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
if (
|
||||
state.decoder.dicPos == state.decoder.dicBufSize ||
|
||||
(inProcessed == 0 && dicPos == state.decoder.dicPos))
|
||||
{
|
||||
if (state.decoder.dicBufSize != outSize || lookahead != 0 ||
|
||||
(status != LZMA_STATUS_FINISHED_WITH_MARK))
|
||||
res = SZ_ERROR_DATA;
|
||||
break;
|
||||
}
|
||||
res = inStream->Skip((void *)inStream, inProcessed);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
if (outSize != state.decoder.dicPos || inSize != 0)
|
||||
res = SZ_ERROR_DATA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Lzma2Dec_FreeProbs(&state, allocMain);
|
||||
return res;
|
||||
if (inProcessed == 0 && dicPos == state.decoder.dicPos)
|
||||
{
|
||||
res = SZ_ERROR_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
res = ILookInStream_Skip(inStream, inProcessed);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Lzma2Dec_FreeProbs(&state, allocMain);
|
||||
return res;
|
||||
}
|
||||
|
||||
static SRes SzDecodeCopy(uint64_t inSize,
|
||||
ILookInStream *inStream, uint8_t *outBuffer)
|
||||
#endif
|
||||
|
||||
|
||||
static SRes SzDecodeCopy(uint64_t inSize, ILookInStream *inStream, Byte *outBuffer)
|
||||
{
|
||||
while (inSize > 0)
|
||||
{
|
||||
SRes result;
|
||||
void *inBuf = NULL;
|
||||
size_t curSize = (1 << 18);
|
||||
if (curSize > inSize)
|
||||
curSize = (size_t)inSize;
|
||||
result = inStream->Look(
|
||||
(void *)inStream, (const void **)&inBuf, &curSize);
|
||||
|
||||
if (result != 0)
|
||||
return result;
|
||||
if (curSize == 0)
|
||||
return SZ_ERROR_INPUT_EOF;
|
||||
|
||||
memcpy(outBuffer, inBuf, curSize);
|
||||
outBuffer += curSize;
|
||||
inSize -= curSize;
|
||||
result = inStream->Skip((void *)inStream, curSize);
|
||||
|
||||
if (result != 0)
|
||||
return result;
|
||||
}
|
||||
return SZ_OK;
|
||||
while (inSize > 0)
|
||||
{
|
||||
const void *inBuf;
|
||||
size_t curSize = (1 << 18);
|
||||
if (curSize > inSize)
|
||||
curSize = (size_t)inSize;
|
||||
RINOK(ILookInStream_Look(inStream, &inBuf, &curSize));
|
||||
if (curSize == 0)
|
||||
return SZ_ERROR_INPUT_EOF;
|
||||
memcpy(outBuffer, inBuf, curSize);
|
||||
outBuffer += curSize;
|
||||
inSize -= curSize;
|
||||
RINOK(ILookInStream_Skip(inStream, curSize));
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static bool is_main_method(uint32_t m)
|
||||
static BoolInt IS_MAIN_METHOD(uint32_t m)
|
||||
{
|
||||
switch(m)
|
||||
{
|
||||
case k_Copy:
|
||||
case k_LZMA:
|
||||
case k_LZMA2:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
switch (m)
|
||||
{
|
||||
case k_Copy:
|
||||
case k_LZMA:
|
||||
#ifndef _7Z_NO_METHOD_LZMA2
|
||||
case k_LZMA2:
|
||||
#endif
|
||||
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||
case k_PPMD:
|
||||
#endif
|
||||
return True;
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
static bool is_supported_coder(const CSzCoderInfo *c)
|
||||
static BoolInt IS_SUPPORTED_CODER(const CSzCoderInfo *c)
|
||||
{
|
||||
return
|
||||
c->NumInStreams == 1 &&
|
||||
c->NumOutStreams == 1 &&
|
||||
c->MethodID <= (uint32_t)0xFFFFFFFF &&
|
||||
is_main_method((uint32_t)c->MethodID);
|
||||
c->NumStreams == 1
|
||||
/* && c->MethodID <= (uint32_t)0xFFFFFFFF */
|
||||
&& IS_MAIN_METHOD((uint32_t)c->MethodID);
|
||||
}
|
||||
|
||||
#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1)
|
||||
#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumStreams == 4)
|
||||
|
||||
static SRes check_supported_folder(const CSzFolder *f)
|
||||
static SRes CheckSupportedFolder(const CSzFolder *f)
|
||||
{
|
||||
if (f->NumCoders < 1 || f->NumCoders > 4)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
|
||||
if (!is_supported_coder(&f->Coders[0]))
|
||||
if (!IS_SUPPORTED_CODER(&f->Coders[0]))
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
|
||||
switch (f->NumCoders)
|
||||
if (f->NumCoders == 1)
|
||||
{
|
||||
case 1:
|
||||
if ( f->NumPackStreams != 1
|
||||
|| f->PackStreams[0] != 0
|
||||
|| f->NumBindPairs != 0)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
return SZ_OK;
|
||||
case 2:
|
||||
{
|
||||
CSzCoderInfo *c = &f->Coders[1];
|
||||
|
||||
if (c->MethodID > (uint32_t)0xFFFFFFFF ||
|
||||
c->NumInStreams != 1 ||
|
||||
c->NumOutStreams != 1 ||
|
||||
f->NumPackStreams != 1 ||
|
||||
f->PackStreams[0] != 0 ||
|
||||
f->NumBindPairs != 1 ||
|
||||
f->BindPairs[0].InIndex != 1 ||
|
||||
f->BindPairs[0].OutIndex != 0)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
|
||||
switch ((uint32_t)c->MethodID)
|
||||
{
|
||||
case k_BCJ:
|
||||
case k_ARM:
|
||||
break;
|
||||
default:
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
return SZ_OK;
|
||||
case 4:
|
||||
if (!is_supported_coder(&f->Coders[1]) ||
|
||||
!is_supported_coder(&f->Coders[2]) ||
|
||||
!IS_BCJ2(&f->Coders[3]))
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
|
||||
if (f->NumPackStreams != 4 ||
|
||||
f->PackStreams[0] != 2 ||
|
||||
f->PackStreams[1] != 6 ||
|
||||
f->PackStreams[2] != 1 ||
|
||||
f->PackStreams[3] != 0 ||
|
||||
f->NumBindPairs != 3 ||
|
||||
f->BindPairs[0].InIndex != 5 ||
|
||||
f->BindPairs[0].OutIndex != 0 ||
|
||||
f->BindPairs[1].InIndex != 4 ||
|
||||
f->BindPairs[1].OutIndex != 1 ||
|
||||
f->BindPairs[2].InIndex != 3 ||
|
||||
f->BindPairs[2].OutIndex != 2)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
return SZ_OK;
|
||||
if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBonds != 0)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
|
||||
#ifndef _7Z_NO_METHODS_FILTERS
|
||||
|
||||
if (f->NumCoders == 2)
|
||||
{
|
||||
const CSzCoderInfo *c = &f->Coders[1];
|
||||
if (
|
||||
/* c->MethodID > (uint32_t)0xFFFFFFFF || */
|
||||
c->NumStreams != 1
|
||||
|| f->NumPackStreams != 1
|
||||
|| f->PackStreams[0] != 0
|
||||
|| f->NumBonds != 1
|
||||
|| f->Bonds[0].InIndex != 1
|
||||
|| f->Bonds[0].OutIndex != 0)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
switch ((uint32_t)c->MethodID)
|
||||
{
|
||||
case k_Delta:
|
||||
case k_BCJ:
|
||||
case k_PPC:
|
||||
case k_IA64:
|
||||
case k_SPARC:
|
||||
case k_ARM:
|
||||
case k_ARMT:
|
||||
break;
|
||||
default:
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
if (f->NumCoders == 4)
|
||||
{
|
||||
if (!IS_SUPPORTED_CODER(&f->Coders[1])
|
||||
|| !IS_SUPPORTED_CODER(&f->Coders[2])
|
||||
|| !IS_BCJ2(&f->Coders[3]))
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
if (f->NumPackStreams != 4
|
||||
|| f->PackStreams[0] != 2
|
||||
|| f->PackStreams[1] != 6
|
||||
|| f->PackStreams[2] != 1
|
||||
|| f->PackStreams[3] != 0
|
||||
|| f->NumBonds != 3
|
||||
|| f->Bonds[0].InIndex != 5 || f->Bonds[0].OutIndex != 0
|
||||
|| f->Bonds[1].InIndex != 4 || f->Bonds[1].OutIndex != 1
|
||||
|| f->Bonds[2].InIndex != 3 || f->Bonds[2].OutIndex != 2)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static uint64_t get_sum(const uint64_t *values, uint32_t idx)
|
||||
{
|
||||
uint64_t sum = 0;
|
||||
uint32_t i;
|
||||
for (i = 0; i < idx; i++)
|
||||
sum += values[i];
|
||||
return sum;
|
||||
}
|
||||
#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break;
|
||||
|
||||
static SRes SzFolder_Decode2(const CSzFolder *folder,
|
||||
const uint64_t *packSizes,
|
||||
ILookInStream *inStream, uint64_t startPos,
|
||||
uint8_t *outBuffer, size_t outSize, ISzAlloc *allocMain,
|
||||
uint8_t *tempBuf[])
|
||||
const Byte *propsData,
|
||||
const uint64_t *unpackSizes,
|
||||
const uint64_t *packPositions,
|
||||
ILookInStream *inStream, uint64_t startPos,
|
||||
Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain,
|
||||
Byte *tempBuf[])
|
||||
{
|
||||
uint32_t ci;
|
||||
size_t tempSizes[3] = { 0, 0, 0};
|
||||
size_t tempSize3 = 0;
|
||||
uint8_t *tempBuf3 = 0;
|
||||
SRes result = check_supported_folder(folder);
|
||||
uint32_t ci;
|
||||
SizeT tempSizes[3] = { 0, 0, 0};
|
||||
SizeT tempSize3 = 0;
|
||||
Byte *tempBuf3 = 0;
|
||||
|
||||
if (result != 0)
|
||||
return result;
|
||||
RINOK(CheckSupportedFolder(folder));
|
||||
|
||||
for (ci = 0; ci < folder->NumCoders; ci++)
|
||||
{
|
||||
CSzCoderInfo *coder = &folder->Coders[ci];
|
||||
for (ci = 0; ci < folder->NumCoders; ci++)
|
||||
{
|
||||
const CSzCoderInfo *coder = &folder->Coders[ci];
|
||||
|
||||
if (is_main_method((uint32_t)coder->MethodID))
|
||||
if (IS_MAIN_METHOD((uint32_t)coder->MethodID))
|
||||
{
|
||||
uint32_t si = 0;
|
||||
uint64_t offset;
|
||||
uint64_t inSize;
|
||||
Byte *outBufCur = outBuffer;
|
||||
SizeT outSizeCur = outSize;
|
||||
if (folder->NumCoders == 4)
|
||||
{
|
||||
SRes result;
|
||||
uint64_t offset = 0;
|
||||
uint64_t inSize = 0;
|
||||
uint32_t si = 0;
|
||||
uint8_t *outBufCur = outBuffer;
|
||||
size_t outSizeCur = outSize;
|
||||
|
||||
if (folder->NumCoders == 4)
|
||||
{
|
||||
uint32_t indices[] = { 3, 2, 0 };
|
||||
uint64_t unpackSize = folder->UnpackSizes[ci];
|
||||
si = indices[ci];
|
||||
|
||||
if (ci < 2)
|
||||
{
|
||||
uint8_t *temp;
|
||||
outSizeCur = (size_t)unpackSize;
|
||||
if (outSizeCur != unpackSize)
|
||||
return SZ_ERROR_MEM;
|
||||
temp = (uint8_t *)IAlloc_Alloc(allocMain, outSizeCur);
|
||||
if (temp == 0 && outSizeCur != 0)
|
||||
return SZ_ERROR_MEM;
|
||||
outBufCur = tempBuf[1 - ci] = temp;
|
||||
tempSizes[1 - ci] = outSizeCur;
|
||||
}
|
||||
else if (ci == 2)
|
||||
{
|
||||
if (unpackSize > outSize) /* check it */
|
||||
return SZ_ERROR_PARAM;
|
||||
tempBuf3 = outBufCur = outBuffer
|
||||
+ (outSize - (size_t)unpackSize);
|
||||
tempSize3 = outSizeCur = (size_t)unpackSize;
|
||||
}
|
||||
else
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
offset = get_sum(packSizes, si);
|
||||
inSize = packSizes[si];
|
||||
result = LookInStream_SeekTo(inStream, startPos + offset);
|
||||
|
||||
if (result != 0)
|
||||
return result;
|
||||
|
||||
switch (coder->MethodID)
|
||||
{
|
||||
case k_Copy:
|
||||
if (inSize != outSizeCur) /* check it */
|
||||
return SZ_ERROR_DATA;
|
||||
result = SzDecodeCopy(inSize, inStream, outBufCur);
|
||||
if (result != 0)
|
||||
return result;
|
||||
break;
|
||||
case k_LZMA:
|
||||
result = SzDecodeLzma(
|
||||
coder, inSize, inStream,
|
||||
outBufCur, outSizeCur, allocMain);
|
||||
if (result != 0)
|
||||
return result;
|
||||
break;
|
||||
case k_LZMA2:
|
||||
result = SzDecodeLzma2(
|
||||
coder, inSize, inStream,
|
||||
outBufCur, outSizeCur, allocMain);
|
||||
if (result != 0)
|
||||
return result;
|
||||
break;
|
||||
default:
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
uint32_t indices[] = { 3, 2, 0 };
|
||||
uint64_t unpackSize = unpackSizes[ci];
|
||||
si = indices[ci];
|
||||
if (ci < 2)
|
||||
{
|
||||
Byte *temp;
|
||||
outSizeCur = (SizeT)unpackSize;
|
||||
if (outSizeCur != unpackSize)
|
||||
return SZ_ERROR_MEM;
|
||||
temp = (Byte *)ISzAlloc_Alloc(allocMain, outSizeCur);
|
||||
if (!temp && outSizeCur != 0)
|
||||
return SZ_ERROR_MEM;
|
||||
outBufCur = tempBuf[1 - ci] = temp;
|
||||
tempSizes[1 - ci] = outSizeCur;
|
||||
}
|
||||
else if (ci == 2)
|
||||
{
|
||||
if (unpackSize > outSize) /* check it */
|
||||
return SZ_ERROR_PARAM;
|
||||
tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
|
||||
tempSize3 = outSizeCur = (SizeT)unpackSize;
|
||||
}
|
||||
else
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
else if (coder->MethodID == k_BCJ2)
|
||||
offset = packPositions[si];
|
||||
inSize = packPositions[(size_t)si + 1] - offset;
|
||||
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
|
||||
|
||||
if (coder->MethodID == k_Copy)
|
||||
{
|
||||
SRes res;
|
||||
SRes result;
|
||||
uint64_t offset = get_sum(packSizes, 1);
|
||||
uint64_t s3Size = packSizes[1];
|
||||
if (inSize != outSizeCur) /* check it */
|
||||
return SZ_ERROR_DATA;
|
||||
RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
|
||||
}
|
||||
else if (coder->MethodID == k_LZMA)
|
||||
{
|
||||
RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||
}
|
||||
#ifndef _7Z_NO_METHOD_LZMA2
|
||||
else if (coder->MethodID == k_LZMA2)
|
||||
{
|
||||
RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||
}
|
||||
#endif
|
||||
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||
else if (coder->MethodID == k_PPMD)
|
||||
{
|
||||
RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||
}
|
||||
#endif
|
||||
else
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
else if (coder->MethodID == k_BCJ2)
|
||||
{
|
||||
uint64_t offset = packPositions[1];
|
||||
uint64_t s3Size = packPositions[2] - offset;
|
||||
|
||||
if (ci != 3)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
|
||||
tempSizes[2] = (SizeT)s3Size;
|
||||
if (tempSizes[2] != s3Size)
|
||||
return SZ_ERROR_MEM;
|
||||
tempBuf[2] = (Byte *)ISzAlloc_Alloc(allocMain, tempSizes[2]);
|
||||
if (!tempBuf[2] && tempSizes[2] != 0)
|
||||
return SZ_ERROR_MEM;
|
||||
|
||||
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
|
||||
RINOK(SzDecodeCopy(s3Size, inStream, tempBuf[2]));
|
||||
|
||||
if (ci != 3)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
if ((tempSizes[0] & 3) != 0 ||
|
||||
(tempSizes[1] & 3) != 0 ||
|
||||
tempSize3 + tempSizes[0] + tempSizes[1] != outSize)
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
result = LookInStream_SeekTo(inStream, startPos + offset);
|
||||
{
|
||||
CBcj2Dec p;
|
||||
|
||||
p.bufs[0] = tempBuf3; p.lims[0] = tempBuf3 + tempSize3;
|
||||
p.bufs[1] = tempBuf[0]; p.lims[1] = tempBuf[0] + tempSizes[0];
|
||||
p.bufs[2] = tempBuf[1]; p.lims[2] = tempBuf[1] + tempSizes[1];
|
||||
p.bufs[3] = tempBuf[2]; p.lims[3] = tempBuf[2] + tempSizes[2];
|
||||
|
||||
p.dest = outBuffer;
|
||||
p.destLim = outBuffer + outSize;
|
||||
|
||||
Bcj2Dec_Init(&p);
|
||||
RINOK(Bcj2Dec_Decode(&p));
|
||||
|
||||
if (result != 0)
|
||||
return result;
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < 4; i++)
|
||||
if (p.bufs[i] != p.lims[i])
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
if (!Bcj2Dec_IsFinished(&p))
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
tempSizes[2] = (size_t)s3Size;
|
||||
if (tempSizes[2] != s3Size)
|
||||
return SZ_ERROR_MEM;
|
||||
|
||||
tempBuf[2] = (uint8_t *)IAlloc_Alloc(allocMain, tempSizes[2]);
|
||||
if (tempBuf[2] == 0 && tempSizes[2] != 0)
|
||||
return SZ_ERROR_MEM;
|
||||
|
||||
res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
|
||||
if (res != 0)
|
||||
return res;
|
||||
|
||||
res = Bcj2_Decode(
|
||||
tempBuf3, tempSize3,
|
||||
tempBuf[0], tempSizes[0],
|
||||
tempBuf[1], tempSizes[1],
|
||||
tempBuf[2], tempSizes[2],
|
||||
outBuffer, outSize);
|
||||
|
||||
if (res != 0)
|
||||
return res;
|
||||
if (p.dest != p.destLim
|
||||
|| p.state != BCJ2_STREAM_MAIN)
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifndef _7Z_NO_METHODS_FILTERS
|
||||
else if (ci == 1)
|
||||
{
|
||||
if (coder->MethodID == k_Delta)
|
||||
{
|
||||
if (coder->PropsSize != 1)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
{
|
||||
Byte state[DELTA_STATE_SIZE];
|
||||
Delta_Init(state);
|
||||
Delta_Decode(state, (unsigned)(propsData[coder->PropsOffset]) + 1, outBuffer, outSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ci != 1)
|
||||
if (coder->PropsSize != 0)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
switch (coder->MethodID)
|
||||
{
|
||||
case k_BCJ:
|
||||
{
|
||||
uint32_t state;
|
||||
x86_Convert_Init(state);
|
||||
x86_Convert(outBuffer, outSize, 0, &state, 0);
|
||||
break;
|
||||
}
|
||||
CASE_BRA_CONV(PPC)
|
||||
CASE_BRA_CONV(IA64)
|
||||
CASE_BRA_CONV(SPARC)
|
||||
CASE_BRA_CONV(ARM)
|
||||
CASE_BRA_CONV(ARMT)
|
||||
default:
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
switch(coder->MethodID)
|
||||
{
|
||||
case k_BCJ:
|
||||
{
|
||||
uint32_t state;
|
||||
x86_Convert_Init(state);
|
||||
x86_Convert(outBuffer, outSize, 0, &state, 0);
|
||||
break;
|
||||
}
|
||||
case k_ARM:
|
||||
ARM_Convert(outBuffer, outSize, 0, 0);
|
||||
break;
|
||||
default:
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes SzFolder_Decode(const CSzFolder *folder, const uint64_t *packSizes,
|
||||
|
||||
SRes SzAr_DecodeFolder(const CSzAr *p, uint32_t folderIndex,
|
||||
ILookInStream *inStream, uint64_t startPos,
|
||||
uint8_t *outBuffer, size_t outSize, ISzAlloc *allocMain)
|
||||
Byte *outBuffer, size_t outSize,
|
||||
ISzAllocPtr allocMain)
|
||||
{
|
||||
int i;
|
||||
uint8_t *tempBuf[3] = { 0, 0, 0};
|
||||
SRes res = SzFolder_Decode2(folder,
|
||||
packSizes, inStream, startPos,
|
||||
outBuffer, (size_t)outSize, allocMain, tempBuf);
|
||||
SRes res;
|
||||
CSzFolder folder;
|
||||
CSzData sd;
|
||||
|
||||
const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex];
|
||||
sd.Data = data;
|
||||
sd.Size = p->FoCodersOffsets[(size_t)folderIndex + 1] - p->FoCodersOffsets[folderIndex];
|
||||
|
||||
res = SzGetNextFolderItem(&folder, &sd);
|
||||
|
||||
if (res != SZ_OK)
|
||||
return res;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
IAlloc_Free(allocMain, tempBuf[i]);
|
||||
return res;
|
||||
if (sd.Size != 0
|
||||
|| folder.UnpackStream != p->FoToMainUnpackSizeIndex[folderIndex]
|
||||
|| outSize != SzAr_GetFolderUnpackSize(p, folderIndex))
|
||||
return SZ_ERROR_FAIL;
|
||||
{
|
||||
unsigned i;
|
||||
Byte *tempBuf[3] = { 0, 0, 0};
|
||||
|
||||
res = SzFolder_Decode2(&folder, data,
|
||||
&p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex]],
|
||||
p->PackPositions + p->FoStartPackStreamIndex[folderIndex],
|
||||
inStream, startPos,
|
||||
outBuffer, (SizeT)outSize, allocMain, tempBuf);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
ISzAlloc_Free(allocMain, tempBuf[i]);
|
||||
|
||||
if (res == SZ_OK)
|
||||
if (SzBitWithVals_Check(&p->FolderCRCs, folderIndex))
|
||||
if (CrcCalc(outBuffer, outSize) != p->FolderCRCs.Vals[folderIndex])
|
||||
res = SZ_ERROR_CRC;
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
Vendored
+214
-88
@@ -1,160 +1,286 @@
|
||||
/* 7zFile.c -- File IO
|
||||
2009-11-24 : Igor Pavlov : Public domain */
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#define SKIP_STDIO_REDEFINES
|
||||
#include <streams/file_stream_transforms.h>
|
||||
#include "7zFile.h"
|
||||
|
||||
#ifndef USE_WINDOWS_FILE
|
||||
|
||||
#ifndef UNDER_CE
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
ReadFile and WriteFile functions in Windows have BUG:
|
||||
If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1)
|
||||
from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES
|
||||
(Insufficient system resources exist to complete the requested service).
|
||||
Probably in some version of Windows there are problems with other sizes:
|
||||
for 32 MB (maybe also for 16 MB).
|
||||
And message can be "Network connection was lost"
|
||||
*/
|
||||
|
||||
#define kChunkSizeMax (1 << 22)
|
||||
|
||||
#endif
|
||||
|
||||
void File_Construct(CSzFile *p)
|
||||
{
|
||||
p->file = NULL;
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
p->handle = INVALID_HANDLE_VALUE;
|
||||
#else
|
||||
p->file = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)
|
||||
static WRes File_Open(CSzFile *p, const char *name, int writeMode)
|
||||
{
|
||||
p->file = rfopen(name, writeMode ? "wb+" : "rb");
|
||||
if (!p->file)
|
||||
{
|
||||
#ifdef UNDER_CE
|
||||
return 2; /* ENOENT */
|
||||
#else
|
||||
return errno;
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
p->handle = CreateFileA(name,
|
||||
writeMode ? GENERIC_WRITE : GENERIC_READ,
|
||||
FILE_SHARE_READ, NULL,
|
||||
writeMode ? CREATE_ALWAYS : OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();
|
||||
#else
|
||||
p->file = fopen(name, writeMode ? "wb+" : "rb");
|
||||
return (p->file != 0) ? 0 :
|
||||
#ifdef UNDER_CE
|
||||
2; /* ENOENT */
|
||||
#else
|
||||
errno;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); }
|
||||
WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); }
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
WRes InFile_Open(CSzFile *p, const char *name)
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode)
|
||||
{
|
||||
return File_Open(p, name, 0);
|
||||
}
|
||||
|
||||
WRes OutFile_Open(CSzFile *p, const char *name)
|
||||
{
|
||||
return File_Open(p, name, 1);
|
||||
p->handle = CreateFileW(name,
|
||||
writeMode ? GENERIC_WRITE : GENERIC_READ,
|
||||
FILE_SHARE_READ, NULL,
|
||||
writeMode ? CREATE_ALWAYS : OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();
|
||||
}
|
||||
WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); }
|
||||
WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); }
|
||||
#endif
|
||||
|
||||
WRes File_Close(CSzFile *p)
|
||||
{
|
||||
if (p->file)
|
||||
{
|
||||
int res = rfclose((RFILE*)p->file);
|
||||
if (res != 0)
|
||||
return res;
|
||||
p->file = NULL;
|
||||
}
|
||||
return 0;
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
if (p->handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (!CloseHandle(p->handle))
|
||||
return GetLastError();
|
||||
p->handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
#else
|
||||
if (p->file != NULL)
|
||||
{
|
||||
int res = fclose(p->file);
|
||||
if (res != 0)
|
||||
return res;
|
||||
p->file = NULL;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
WRes File_Read(CSzFile *p, void *data, size_t *size)
|
||||
{
|
||||
int64_t originalSize = *size;
|
||||
if (originalSize == 0)
|
||||
return 0;
|
||||
size_t originalSize = *size;
|
||||
if (originalSize == 0)
|
||||
return 0;
|
||||
|
||||
*size = rfread(data, 1, originalSize, (RFILE*)p->file);
|
||||
if (*size == originalSize)
|
||||
return 0;
|
||||
return rferror((RFILE*)p->file);
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
|
||||
*size = 0;
|
||||
do
|
||||
{
|
||||
DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;
|
||||
DWORD processed = 0;
|
||||
BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL);
|
||||
data = (void *)((Byte *)data + processed);
|
||||
originalSize -= processed;
|
||||
*size += processed;
|
||||
if (!res)
|
||||
return GetLastError();
|
||||
if (processed == 0)
|
||||
break;
|
||||
}
|
||||
while (originalSize > 0);
|
||||
return 0;
|
||||
|
||||
#else
|
||||
|
||||
*size = fread(data, 1, originalSize, p->file);
|
||||
if (*size == originalSize)
|
||||
return 0;
|
||||
return ferror(p->file);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
WRes File_Write(CSzFile *p, const void *data, size_t *size)
|
||||
{
|
||||
int64_t originalSize = *size;
|
||||
if (originalSize == 0)
|
||||
return 0;
|
||||
size_t originalSize = *size;
|
||||
if (originalSize == 0)
|
||||
return 0;
|
||||
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
|
||||
*size = rfwrite(data, 1, originalSize, (RFILE*)p->file);
|
||||
if (*size == originalSize)
|
||||
return 0;
|
||||
return rferror((RFILE*)p->file);
|
||||
*size = 0;
|
||||
do
|
||||
{
|
||||
DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;
|
||||
DWORD processed = 0;
|
||||
BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL);
|
||||
data = (void *)((Byte *)data + processed);
|
||||
originalSize -= processed;
|
||||
*size += processed;
|
||||
if (!res)
|
||||
return GetLastError();
|
||||
if (processed == 0)
|
||||
break;
|
||||
}
|
||||
while (originalSize > 0);
|
||||
return 0;
|
||||
|
||||
#else
|
||||
|
||||
*size = fwrite(data, 1, originalSize, p->file);
|
||||
if (*size == originalSize)
|
||||
return 0;
|
||||
return ferror(p->file);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
WRes File_Seek(CSzFile *p, int64_t *pos, ESzSeek origin)
|
||||
{
|
||||
int whence;
|
||||
int64_t res;
|
||||
switch (origin)
|
||||
{
|
||||
case SZ_SEEK_SET:
|
||||
whence = SEEK_SET;
|
||||
break;
|
||||
case SZ_SEEK_CUR:
|
||||
whence = SEEK_CUR;
|
||||
break;
|
||||
case SZ_SEEK_END:
|
||||
whence = SEEK_END;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
res = rfseek((RFILE*)p->file, (int64_t)*pos, whence);
|
||||
*pos = rftell((RFILE*)p->file);
|
||||
return res;
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
|
||||
LARGE_INTEGER value;
|
||||
DWORD moveMethod;
|
||||
value.LowPart = (DWORD)*pos;
|
||||
value.HighPart = (LONG)((uint64_t)*pos >> 16 >> 16); /* for case when uint64_t is 32-bit only */
|
||||
switch (origin)
|
||||
{
|
||||
case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break;
|
||||
case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break;
|
||||
case SZ_SEEK_END: moveMethod = FILE_END; break;
|
||||
default: return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod);
|
||||
if (value.LowPart == 0xFFFFFFFF)
|
||||
{
|
||||
WRes res = GetLastError();
|
||||
if (res != NO_ERROR)
|
||||
return res;
|
||||
}
|
||||
*pos = ((int64_t)value.HighPart << 32) | value.LowPart;
|
||||
return 0;
|
||||
|
||||
#else
|
||||
|
||||
int moveMethod;
|
||||
int res;
|
||||
switch (origin)
|
||||
{
|
||||
case SZ_SEEK_SET: moveMethod = SEEK_SET; break;
|
||||
case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break;
|
||||
case SZ_SEEK_END: moveMethod = SEEK_END; break;
|
||||
default: return 1;
|
||||
}
|
||||
res = fseek(p->file, (long)*pos, moveMethod);
|
||||
*pos = ftell(p->file);
|
||||
return res;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
WRes File_GetLength(CSzFile *p, uint64_t *length)
|
||||
{
|
||||
int64_t pos = rftell((RFILE*)p->file);
|
||||
int64_t res = rfseek((RFILE*)p->file, 0, SEEK_END);
|
||||
*length = rftell((RFILE*)p->file);
|
||||
rfseek((RFILE*)p->file, pos, SEEK_SET);
|
||||
return res;
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
|
||||
DWORD sizeHigh;
|
||||
DWORD sizeLow = GetFileSize(p->handle, &sizeHigh);
|
||||
if (sizeLow == 0xFFFFFFFF)
|
||||
{
|
||||
DWORD res = GetLastError();
|
||||
if (res != NO_ERROR)
|
||||
return res;
|
||||
}
|
||||
*length = (((uint64_t)sizeHigh) << 32) + sizeLow;
|
||||
return 0;
|
||||
|
||||
#else
|
||||
|
||||
long pos = ftell(p->file);
|
||||
int res = fseek(p->file, 0, SEEK_END);
|
||||
*length = ftell(p->file);
|
||||
fseek(p->file, pos, SEEK_SET);
|
||||
return res;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* ---------- FileSeqInStream ---------- */
|
||||
|
||||
static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size)
|
||||
static SRes FileSeqInStream_Read(const ISeqInStream *pp, void *buf, size_t *size)
|
||||
{
|
||||
CFileSeqInStream *p = (CFileSeqInStream *)pp;
|
||||
return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ;
|
||||
CFileSeqInStream *p = CONTAINER_FROM_VTBL(pp, CFileSeqInStream, vt);
|
||||
return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ;
|
||||
}
|
||||
|
||||
void FileSeqInStream_CreateVTable(CFileSeqInStream *p)
|
||||
{
|
||||
p->s.Read = FileSeqInStream_Read;
|
||||
p->vt.Read = FileSeqInStream_Read;
|
||||
}
|
||||
|
||||
|
||||
/* ---------- FileInStream ---------- */
|
||||
|
||||
static SRes FileInStream_Read(void *pp, void *buf, size_t *size)
|
||||
static SRes FileInStream_Read(const ISeekInStream *pp, void *buf, size_t *size)
|
||||
{
|
||||
CFileInStream *p = (CFileInStream *)pp;
|
||||
return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ;
|
||||
CFileInStream *p = CONTAINER_FROM_VTBL(pp, CFileInStream, vt);
|
||||
return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ;
|
||||
}
|
||||
|
||||
static SRes FileInStream_Seek(void *pp, int64_t *pos, ESzSeek origin)
|
||||
static SRes FileInStream_Seek(const ISeekInStream *pp, int64_t *pos, ESzSeek origin)
|
||||
{
|
||||
CFileInStream *p = (CFileInStream *)pp;
|
||||
return File_Seek(&p->file, pos, origin);
|
||||
CFileInStream *p = CONTAINER_FROM_VTBL(pp, CFileInStream, vt);
|
||||
return File_Seek(&p->file, pos, origin);
|
||||
}
|
||||
|
||||
void FileInStream_CreateVTable(CFileInStream *p)
|
||||
{
|
||||
p->s.Read = FileInStream_Read;
|
||||
p->s.Seek = FileInStream_Seek;
|
||||
p->vt.Read = FileInStream_Read;
|
||||
p->vt.Seek = FileInStream_Seek;
|
||||
}
|
||||
|
||||
|
||||
/* ---------- FileOutStream ---------- */
|
||||
|
||||
static size_t FileOutStream_Write(void *pp, const void *data, size_t size)
|
||||
static size_t FileOutStream_Write(const ISeqOutStream *pp, const void *data, size_t size)
|
||||
{
|
||||
CFileOutStream *p = (CFileOutStream *)pp;
|
||||
File_Write(&p->file, data, &size);
|
||||
return size;
|
||||
CFileOutStream *p = CONTAINER_FROM_VTBL(pp, CFileOutStream, vt);
|
||||
File_Write(&p->file, data, &size);
|
||||
return size;
|
||||
}
|
||||
|
||||
void FileOutStream_CreateVTable(CFileOutStream *p)
|
||||
{
|
||||
p->s.Write = FileOutStream_Write;
|
||||
p->vt.Write = FileOutStream_Write;
|
||||
}
|
||||
|
||||
#undef SKIP_STDIO_REDEFINES
|
||||
Vendored
+25
-11
@@ -1,27 +1,43 @@
|
||||
/* 7zFile.h -- File IO
|
||||
2009-11-24 : Igor Pavlov : Public domain */
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_FILE_H
|
||||
#define __7Z_FILE_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#define USE_WINDOWS_FILE
|
||||
#endif
|
||||
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
/* ---------- File ---------- */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *file;
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
HANDLE handle;
|
||||
#else
|
||||
FILE *file;
|
||||
#endif
|
||||
} CSzFile;
|
||||
|
||||
void File_Construct(CSzFile *p);
|
||||
#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)
|
||||
WRes InFile_Open(CSzFile *p, const char *name);
|
||||
WRes OutFile_Open(CSzFile *p, const char *name);
|
||||
#endif
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
WRes InFile_OpenW(CSzFile *p, const WCHAR *name);
|
||||
WRes OutFile_OpenW(CSzFile *p, const WCHAR *name);
|
||||
#endif
|
||||
WRes File_Close(CSzFile *p);
|
||||
|
||||
/* reads max(*size, remain file's size) bytes */
|
||||
@@ -38,7 +54,7 @@ WRes File_GetLength(CSzFile *p, uint64_t *length);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeqInStream s;
|
||||
ISeqInStream vt;
|
||||
CSzFile file;
|
||||
} CFileSeqInStream;
|
||||
|
||||
@@ -47,7 +63,7 @@ void FileSeqInStream_CreateVTable(CFileSeqInStream *p);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeekInStream s;
|
||||
ISeekInStream vt;
|
||||
CSzFile file;
|
||||
} CFileInStream;
|
||||
|
||||
@@ -56,14 +72,12 @@ void FileInStream_CreateVTable(CFileInStream *p);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeqOutStream s;
|
||||
ISeqOutStream vt;
|
||||
CSzFile file;
|
||||
} CFileOutStream;
|
||||
|
||||
void FileOutStream_CreateVTable(CFileOutStream *p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
Vendored
-1633
File diff suppressed because it is too large.
Load diff
Vendored
+116
-124
@@ -1,184 +1,176 @@
|
||||
/* 7zStream.c -- 7z Stream functions
|
||||
2010-03-11 : Igor Pavlov : Public domain */
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
SRes SeqInStream_Readuint8_t(ISeqInStream *stream, uint8_t *buf)
|
||||
SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType)
|
||||
{
|
||||
size_t processed = 1;
|
||||
SRes result = stream->Read(stream, buf, &processed);
|
||||
if (result != 0)
|
||||
return result;
|
||||
if (processed != 1)
|
||||
return SZ_ERROR_INPUT_EOF;
|
||||
return SZ_OK;
|
||||
while (size != 0)
|
||||
{
|
||||
size_t processed = size;
|
||||
RINOK(ISeqInStream_Read(stream, buf, &processed));
|
||||
if (processed == 0)
|
||||
return errorType;
|
||||
buf = (void *)((Byte *)buf + processed);
|
||||
size -= processed;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType)
|
||||
SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size)
|
||||
{
|
||||
while (size != 0)
|
||||
{
|
||||
size_t processed = size;
|
||||
SRes result = stream->Read(stream, buf, &processed);
|
||||
if (result != 0)
|
||||
return result;
|
||||
if (processed == 0)
|
||||
return errorType;
|
||||
buf = (void *)((uint8_t *)buf + processed);
|
||||
size -= processed;
|
||||
}
|
||||
return SZ_OK;
|
||||
return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
|
||||
}
|
||||
|
||||
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size)
|
||||
SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf)
|
||||
{
|
||||
return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
|
||||
size_t processed = 1;
|
||||
RINOK(ISeqInStream_Read(stream, buf, &processed));
|
||||
return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF;
|
||||
}
|
||||
|
||||
|
||||
SRes LookInStream_SeekTo(ILookInStream *stream, uint64_t offset)
|
||||
|
||||
SRes LookInStream_SeekTo(const ILookInStream *stream, uint64_t offset)
|
||||
{
|
||||
int64_t t = offset;
|
||||
return stream->Seek(stream, &t, SZ_SEEK_SET);
|
||||
int64_t t = offset;
|
||||
return ILookInStream_Seek(stream, &t, SZ_SEEK_SET);
|
||||
}
|
||||
|
||||
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size)
|
||||
SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size)
|
||||
{
|
||||
SRes result;
|
||||
const void *lookBuf;
|
||||
if (*size == 0)
|
||||
return SZ_OK;
|
||||
result = stream->Look(stream, &lookBuf, size);
|
||||
if (result != 0)
|
||||
return result;
|
||||
memcpy(buf, lookBuf, *size);
|
||||
return stream->Skip(stream, *size);
|
||||
const void *lookBuf;
|
||||
if (*size == 0)
|
||||
return SZ_OK;
|
||||
RINOK(ILookInStream_Look(stream, &lookBuf, size));
|
||||
memcpy(buf, lookBuf, *size);
|
||||
return ILookInStream_Skip(stream, *size);
|
||||
}
|
||||
|
||||
SRes LookInStream_Read2(ILookInStream *stream,
|
||||
void *buf, size_t size, SRes errorType)
|
||||
SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType)
|
||||
{
|
||||
while (size != 0)
|
||||
{
|
||||
size_t processed = size;
|
||||
SRes result = stream->Read(stream, buf, &processed);
|
||||
if (result != 0)
|
||||
return result;
|
||||
if (processed == 0)
|
||||
return errorType;
|
||||
buf = (void *)((uint8_t *)buf + processed);
|
||||
size -= processed;
|
||||
}
|
||||
return SZ_OK;
|
||||
while (size != 0)
|
||||
{
|
||||
size_t processed = size;
|
||||
RINOK(ILookInStream_Read(stream, buf, &processed));
|
||||
if (processed == 0)
|
||||
return errorType;
|
||||
buf = (void *)((Byte *)buf + processed);
|
||||
size -= processed;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size)
|
||||
SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size)
|
||||
{
|
||||
return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
|
||||
return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
|
||||
}
|
||||
|
||||
static SRes LookToRead_Look_Lookahead(void *pp, const void **buf, size_t *size)
|
||||
|
||||
|
||||
#define GET_LookToRead2 CLookToRead2 *p = CONTAINER_FROM_VTBL(pp, CLookToRead2, vt);
|
||||
|
||||
static SRes LookToRead2_Look_Lookahead(const ILookInStream *pp, const void **buf, size_t *size)
|
||||
{
|
||||
SRes res = SZ_OK;
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
size_t size2 = p->size - p->pos;
|
||||
if (size2 == 0 && *size > 0)
|
||||
{
|
||||
p->pos = 0;
|
||||
size2 = LookToRead_BUF_SIZE;
|
||||
res = p->realStream->Read(p->realStream, p->buf, &size2);
|
||||
p->size = size2;
|
||||
}
|
||||
if (size2 < *size)
|
||||
*size = size2;
|
||||
*buf = p->buf + p->pos;
|
||||
return res;
|
||||
SRes res = SZ_OK;
|
||||
GET_LookToRead2
|
||||
size_t size2 = p->size - p->pos;
|
||||
if (size2 == 0 && *size != 0)
|
||||
{
|
||||
p->pos = 0;
|
||||
p->size = 0;
|
||||
size2 = p->bufSize;
|
||||
res = ISeekInStream_Read(p->realStream, p->buf, &size2);
|
||||
p->size = size2;
|
||||
}
|
||||
if (*size > size2)
|
||||
*size = size2;
|
||||
*buf = p->buf + p->pos;
|
||||
return res;
|
||||
}
|
||||
|
||||
static SRes LookToRead_Look_Exact(void *pp, const void **buf, size_t *size)
|
||||
static SRes LookToRead2_Look_Exact(const ILookInStream *pp, const void **buf, size_t *size)
|
||||
{
|
||||
SRes res = SZ_OK;
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
size_t size2 = p->size - p->pos;
|
||||
if (size2 == 0 && *size > 0)
|
||||
{
|
||||
p->pos = 0;
|
||||
if (*size > LookToRead_BUF_SIZE)
|
||||
*size = LookToRead_BUF_SIZE;
|
||||
res = p->realStream->Read(p->realStream, p->buf, size);
|
||||
size2 = p->size = *size;
|
||||
}
|
||||
if (size2 < *size)
|
||||
*size = size2;
|
||||
*buf = p->buf + p->pos;
|
||||
return res;
|
||||
SRes res = SZ_OK;
|
||||
GET_LookToRead2
|
||||
size_t size2 = p->size - p->pos;
|
||||
if (size2 == 0 && *size != 0)
|
||||
{
|
||||
p->pos = 0;
|
||||
p->size = 0;
|
||||
if (*size > p->bufSize)
|
||||
*size = p->bufSize;
|
||||
res = ISeekInStream_Read(p->realStream, p->buf, size);
|
||||
size2 = p->size = *size;
|
||||
}
|
||||
if (*size > size2)
|
||||
*size = size2;
|
||||
*buf = p->buf + p->pos;
|
||||
return res;
|
||||
}
|
||||
|
||||
static SRes LookToRead_Skip(void *pp, size_t offset)
|
||||
static SRes LookToRead2_Skip(const ILookInStream *pp, size_t offset)
|
||||
{
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
p->pos += offset;
|
||||
return SZ_OK;
|
||||
GET_LookToRead2
|
||||
p->pos += offset;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static SRes LookToRead_Read(void *pp, void *buf, size_t *size)
|
||||
static SRes LookToRead2_Read(const ILookInStream *pp, void *buf, size_t *size)
|
||||
{
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
size_t rem = p->size - p->pos;
|
||||
if (rem == 0)
|
||||
return p->realStream->Read(p->realStream, buf, size);
|
||||
if (rem > *size)
|
||||
rem = *size;
|
||||
memcpy(buf, p->buf + p->pos, rem);
|
||||
p->pos += rem;
|
||||
*size = rem;
|
||||
return SZ_OK;
|
||||
GET_LookToRead2
|
||||
size_t rem = p->size - p->pos;
|
||||
if (rem == 0)
|
||||
return ISeekInStream_Read(p->realStream, buf, size);
|
||||
if (rem > *size)
|
||||
rem = *size;
|
||||
memcpy(buf, p->buf + p->pos, rem);
|
||||
p->pos += rem;
|
||||
*size = rem;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static SRes LookToRead_Seek(void *pp, int64_t *pos, ESzSeek origin)
|
||||
static SRes LookToRead2_Seek(const ILookInStream *pp, int64_t *pos, ESzSeek origin)
|
||||
{
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
p->pos = p->size = 0;
|
||||
return p->realStream->Seek(p->realStream, pos, origin);
|
||||
GET_LookToRead2
|
||||
p->pos = p->size = 0;
|
||||
return ISeekInStream_Seek(p->realStream, pos, origin);
|
||||
}
|
||||
|
||||
void LookToRead_CreateVTable(CLookToRead *p, int lookahead)
|
||||
void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead)
|
||||
{
|
||||
p->s.Look = lookahead ?
|
||||
LookToRead_Look_Lookahead :
|
||||
LookToRead_Look_Exact;
|
||||
p->s.Skip = LookToRead_Skip;
|
||||
p->s.Read = LookToRead_Read;
|
||||
p->s.Seek = LookToRead_Seek;
|
||||
p->vt.Look = lookahead ?
|
||||
LookToRead2_Look_Lookahead :
|
||||
LookToRead2_Look_Exact;
|
||||
p->vt.Skip = LookToRead2_Skip;
|
||||
p->vt.Read = LookToRead2_Read;
|
||||
p->vt.Seek = LookToRead2_Seek;
|
||||
}
|
||||
|
||||
void LookToRead_Init(CLookToRead *p)
|
||||
{
|
||||
p->pos = p->size = 0;
|
||||
}
|
||||
|
||||
static SRes SecToLook_Read(void *pp, void *buf, size_t *size)
|
||||
|
||||
static SRes SecToLook_Read(const ISeqInStream *pp, void *buf, size_t *size)
|
||||
{
|
||||
CSecToLook *p = (CSecToLook *)pp;
|
||||
return LookInStream_LookRead(p->realStream, buf, size);
|
||||
CSecToLook *p = CONTAINER_FROM_VTBL(pp, CSecToLook, vt);
|
||||
return LookInStream_LookRead(p->realStream, buf, size);
|
||||
}
|
||||
|
||||
void SecToLook_CreateVTable(CSecToLook *p)
|
||||
{
|
||||
p->s.Read = SecToLook_Read;
|
||||
p->vt.Read = SecToLook_Read;
|
||||
}
|
||||
|
||||
static SRes SecToRead_Read(void *pp, void *buf, size_t *size)
|
||||
static SRes SecToRead_Read(const ISeqInStream *pp, void *buf, size_t *size)
|
||||
{
|
||||
CSecToRead *p = (CSecToRead *)pp;
|
||||
return p->realStream->Read(p->realStream, buf, size);
|
||||
CSecToRead *p = CONTAINER_FROM_VTBL(pp, CSecToRead, vt);
|
||||
return ILookInStream_Read(p->realStream, buf, size);
|
||||
}
|
||||
|
||||
void SecToRead_CreateVTable(CSecToRead *p)
|
||||
{
|
||||
p->s.Read = SecToRead_Read;
|
||||
p->vt.Read = SecToRead_Read;
|
||||
}
|
||||
Vendored
+258
-66
@@ -1,11 +1,11 @@
|
||||
/* 7zTypes.h -- Basic types
|
||||
2013-11-12 : Igor Pavlov : Public domain */
|
||||
2018-08-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_TYPES_H
|
||||
#define __7Z_TYPES_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef EXTERN_C_BEGIN
|
||||
#ifdef __cplusplus
|
||||
@@ -19,10 +19,6 @@
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
#define _7ZIP_ST
|
||||
#endif
|
||||
|
||||
#define SZ_OK 0
|
||||
|
||||
#define SZ_ERROR_DATA 1
|
||||
@@ -41,50 +37,144 @@ EXTERN_C_BEGIN
|
||||
#define SZ_ERROR_ARCHIVE 16
|
||||
#define SZ_ERROR_NO_ARCHIVE 17
|
||||
|
||||
typedef int64_t SRes;
|
||||
typedef int SRes;
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/* typedef DWORD WRes; */
|
||||
typedef unsigned WRes;
|
||||
#define MY_SRes_HRESULT_FROM_WRes(x) HRESULT_FROM_WIN32(x)
|
||||
|
||||
#else
|
||||
|
||||
typedef int WRes;
|
||||
#define MY__FACILITY_WIN32 7
|
||||
#define MY__FACILITY__WRes MY__FACILITY_WIN32
|
||||
#define MY_SRes_HRESULT_FROM_WRes(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (MY__FACILITY__WRes << 16) | 0x80000000)))
|
||||
|
||||
#endif
|
||||
|
||||
typedef int64_t WRes;
|
||||
|
||||
#ifndef RINOK
|
||||
#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define MY_FAST_CALL __fastcall
|
||||
#else
|
||||
#define MY_FAST_CALL
|
||||
#ifndef ZCONF_H
|
||||
typedef unsigned char Byte;
|
||||
#endif
|
||||
typedef short Int16;
|
||||
|
||||
#ifdef _SZ_NO_INT_64
|
||||
|
||||
/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
|
||||
NOTES: Some code will work incorrectly in that case! */
|
||||
|
||||
typedef long Int64;
|
||||
#else
|
||||
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
typedef __int64 Int64;
|
||||
#define UINT64_CONST(n) n
|
||||
#else
|
||||
typedef long long int Int64;
|
||||
#define UINT64_CONST(n) n ## ULL
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _LZMA_NO_SYSTEM_SIZE_T
|
||||
typedef uint32_t SizeT;
|
||||
#else
|
||||
typedef size_t SizeT;
|
||||
#endif
|
||||
|
||||
typedef int BoolInt;
|
||||
/* typedef BoolInt Bool; */
|
||||
#define True 1
|
||||
#define False 0
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#define MY_STD_CALL __stdcall
|
||||
#else
|
||||
#define MY_STD_CALL
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#if _MSC_VER >= 1300
|
||||
#define MY_NO_INLINE __declspec(noinline)
|
||||
#else
|
||||
#define MY_NO_INLINE
|
||||
#endif
|
||||
|
||||
#define MY_FORCE_INLINE __forceinline
|
||||
|
||||
#define MY_CDECL __cdecl
|
||||
#define MY_FAST_CALL __fastcall
|
||||
|
||||
#else
|
||||
|
||||
#define MY_NO_INLINE
|
||||
#define MY_FORCE_INLINE
|
||||
#define MY_CDECL
|
||||
#define MY_FAST_CALL
|
||||
|
||||
/* inline keyword : for C++ / C99 */
|
||||
|
||||
/* GCC, clang: */
|
||||
/*
|
||||
#if defined (__GNUC__) && (__GNUC__ >= 4)
|
||||
#define MY_FORCE_INLINE __attribute__((always_inline))
|
||||
#define MY_NO_INLINE __attribute__((noinline))
|
||||
#endif
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* The following interfaces use first parameter as pointer to structure */
|
||||
|
||||
typedef struct
|
||||
typedef struct IByteIn IByteIn;
|
||||
struct IByteIn
|
||||
{
|
||||
unsigned char (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
|
||||
} IByteIn;
|
||||
Byte (*Read)(const IByteIn *p); /* reads one byte, returns 0 in case of EOF or error */
|
||||
};
|
||||
#define IByteIn_Read(p) (p)->Read(p)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void (*Write)(void *p, unsigned char b);
|
||||
} IByteOut;
|
||||
|
||||
typedef struct
|
||||
typedef struct IByteOut IByteOut;
|
||||
struct IByteOut
|
||||
{
|
||||
SRes (*Read)(void *p, void *buf, size_t *size);
|
||||
void (*Write)(const IByteOut *p, Byte b);
|
||||
};
|
||||
#define IByteOut_Write(p, b) (p)->Write(p, b)
|
||||
|
||||
|
||||
typedef struct ISeqInStream ISeqInStream;
|
||||
struct ISeqInStream
|
||||
{
|
||||
SRes (*Read)(const ISeqInStream *p, void *buf, size_t *size);
|
||||
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
|
||||
(output(*size) < input(*size)) is allowed */
|
||||
} ISeqInStream;
|
||||
};
|
||||
#define ISeqInStream_Read(p, buf, size) (p)->Read(p, buf, size)
|
||||
|
||||
/* it can return SZ_ERROR_INPUT_EOF */
|
||||
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
|
||||
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
|
||||
SRes SeqInStream_ReadByte(ISeqInStream *stream, unsigned char *buf);
|
||||
SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size);
|
||||
SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType);
|
||||
SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf);
|
||||
|
||||
typedef struct
|
||||
|
||||
typedef struct ISeqOutStream ISeqOutStream;
|
||||
struct ISeqOutStream
|
||||
{
|
||||
size_t (*Write)(void *p, const void *buf, size_t size);
|
||||
size_t (*Write)(const ISeqOutStream *p, const void *buf, size_t size);
|
||||
/* Returns: result - the number of actually written bytes.
|
||||
(result < size) means error */
|
||||
} ISeqOutStream;
|
||||
};
|
||||
#define ISeqOutStream_Write(p, buf, size) (p)->Write(p, buf, size)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@@ -93,76 +183,178 @@ typedef enum
|
||||
SZ_SEEK_END = 2
|
||||
} ESzSeek;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
|
||||
SRes (*Seek)(void *p, int64_t *pos, ESzSeek origin);
|
||||
} ISeekInStream;
|
||||
|
||||
typedef struct
|
||||
typedef struct ISeekInStream ISeekInStream;
|
||||
struct ISeekInStream
|
||||
{
|
||||
SRes (*Look)(void *p, const void **buf, size_t *size);
|
||||
SRes (*Read)(const ISeekInStream *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
|
||||
SRes (*Seek)(const ISeekInStream *p, int64_t *pos, ESzSeek origin);
|
||||
};
|
||||
#define ISeekInStream_Read(p, buf, size) (p)->Read(p, buf, size)
|
||||
#define ISeekInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin)
|
||||
|
||||
|
||||
typedef struct ILookInStream ILookInStream;
|
||||
struct ILookInStream
|
||||
{
|
||||
SRes (*Look)(const ILookInStream *p, const void **buf, size_t *size);
|
||||
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
|
||||
(output(*size) > input(*size)) is not allowed
|
||||
(output(*size) < input(*size)) is allowed */
|
||||
SRes (*Skip)(void *p, size_t offset);
|
||||
SRes (*Skip)(const ILookInStream *p, size_t offset);
|
||||
/* offset must be <= output(*size) of Look */
|
||||
|
||||
SRes (*Read)(void *p, void *buf, size_t *size);
|
||||
SRes (*Read)(const ILookInStream *p, void *buf, size_t *size);
|
||||
/* reads directly (without buffer). It's same as ISeqInStream::Read */
|
||||
SRes (*Seek)(void *p, int64_t *pos, ESzSeek origin);
|
||||
} ILookInStream;
|
||||
SRes (*Seek)(const ILookInStream *p, int64_t *pos, ESzSeek origin);
|
||||
};
|
||||
|
||||
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
|
||||
SRes LookInStream_SeekTo(ILookInStream *stream, uint64_t offset);
|
||||
#define ILookInStream_Look(p, buf, size) (p)->Look(p, buf, size)
|
||||
#define ILookInStream_Skip(p, offset) (p)->Skip(p, offset)
|
||||
#define ILookInStream_Read(p, buf, size) (p)->Read(p, buf, size)
|
||||
#define ILookInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin)
|
||||
|
||||
|
||||
SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size);
|
||||
SRes LookInStream_SeekTo(const ILookInStream *stream, uint64_t offset);
|
||||
|
||||
/* reads via ILookInStream::Read */
|
||||
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);
|
||||
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
|
||||
SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType);
|
||||
SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size);
|
||||
|
||||
|
||||
#define LookToRead_BUF_SIZE (1 << 14)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ILookInStream s;
|
||||
ISeekInStream *realStream;
|
||||
ILookInStream vt;
|
||||
const ISeekInStream *realStream;
|
||||
|
||||
size_t pos;
|
||||
size_t size;
|
||||
unsigned char buf[LookToRead_BUF_SIZE];
|
||||
} CLookToRead;
|
||||
size_t size; /* it's data size */
|
||||
|
||||
/* the following variables must be set outside */
|
||||
Byte *buf;
|
||||
size_t bufSize;
|
||||
} CLookToRead2;
|
||||
|
||||
void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead);
|
||||
|
||||
#define LookToRead2_Init(p) { (p)->pos = (p)->size = 0; }
|
||||
|
||||
void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
|
||||
void LookToRead_Init(CLookToRead *p);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeqInStream s;
|
||||
ILookInStream *realStream;
|
||||
ISeqInStream vt;
|
||||
const ILookInStream *realStream;
|
||||
} CSecToLook;
|
||||
|
||||
void SecToLook_CreateVTable(CSecToLook *p);
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeqInStream s;
|
||||
ILookInStream *realStream;
|
||||
ISeqInStream vt;
|
||||
const ILookInStream *realStream;
|
||||
} CSecToRead;
|
||||
|
||||
void SecToRead_CreateVTable(CSecToRead *p);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SRes (*Progress)(void *p, uint64_t inSize, uint64_t outSize);
|
||||
} ICompressProgress;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *(*Alloc)(void *p, size_t size);
|
||||
void (*Free)(void *p, void *address); /* address can be 0 */
|
||||
} ISzAlloc;
|
||||
typedef struct ICompressProgress ICompressProgress;
|
||||
|
||||
#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
|
||||
#define IAlloc_Free(p, a) (p)->Free((p), a)
|
||||
struct ICompressProgress
|
||||
{
|
||||
SRes (*Progress)(const ICompressProgress *p, uint64_t inSize, uint64_t outSize);
|
||||
/* Returns: result. (result != SZ_OK) means break.
|
||||
Value (uint64_t)(int64_t)-1 for size means unknown value. */
|
||||
};
|
||||
#define ICompressProgress_Progress(p, inSize, outSize) (p)->Progress(p, inSize, outSize)
|
||||
|
||||
|
||||
|
||||
typedef struct ISzAlloc ISzAlloc;
|
||||
typedef const ISzAlloc * ISzAllocPtr;
|
||||
|
||||
struct ISzAlloc
|
||||
{
|
||||
void *(*Alloc)(ISzAllocPtr p, size_t size);
|
||||
void (*Free)(ISzAllocPtr p, void *address); /* address can be 0 */
|
||||
};
|
||||
|
||||
#define ISzAlloc_Alloc(p, size) (p)->Alloc(p, size)
|
||||
#define ISzAlloc_Free(p, a) (p)->Free(p, a)
|
||||
|
||||
/* deprecated */
|
||||
#define IAlloc_Alloc(p, size) ISzAlloc_Alloc(p, size)
|
||||
#define IAlloc_Free(p, a) ISzAlloc_Free(p, a)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef MY_offsetof
|
||||
#ifdef offsetof
|
||||
#define MY_offsetof(type, m) offsetof(type, m)
|
||||
/*
|
||||
#define MY_offsetof(type, m) FIELD_OFFSET(type, m)
|
||||
*/
|
||||
#else
|
||||
#define MY_offsetof(type, m) ((size_t)&(((type *)0)->m))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifndef MY_container_of
|
||||
|
||||
/*
|
||||
#define MY_container_of(ptr, type, m) container_of(ptr, type, m)
|
||||
#define MY_container_of(ptr, type, m) CONTAINING_RECORD(ptr, type, m)
|
||||
#define MY_container_of(ptr, type, m) ((type *)((char *)(ptr) - offsetof(type, m)))
|
||||
#define MY_container_of(ptr, type, m) (&((type *)0)->m == (ptr), ((type *)(((char *)(ptr)) - MY_offsetof(type, m))))
|
||||
*/
|
||||
|
||||
/*
|
||||
GCC shows warning: "perhaps the 'offsetof' macro was used incorrectly"
|
||||
GCC 3.4.4 : classes with constructor
|
||||
GCC 4.8.1 : classes with non-public variable members"
|
||||
*/
|
||||
|
||||
#define MY_container_of(ptr, type, m) ((type *)((char *)(1 ? (ptr) : &((type *)0)->m) - MY_offsetof(type, m)))
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#define CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(ptr))
|
||||
|
||||
/*
|
||||
#define CONTAINER_FROM_VTBL(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m)
|
||||
*/
|
||||
#define CONTAINER_FROM_VTBL(ptr, type, m) MY_container_of(ptr, type, m)
|
||||
|
||||
#define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m)
|
||||
/*
|
||||
#define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL(ptr, type, m)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#define CHAR_PATH_SEPARATOR '\\'
|
||||
#define WCHAR_PATH_SEPARATOR L'\\'
|
||||
#define STRING_PATH_SEPARATOR "\\"
|
||||
#define WSTRING_PATH_SEPARATOR L"\\"
|
||||
|
||||
#else
|
||||
|
||||
#define CHAR_PATH_SEPARATOR '/'
|
||||
#define WCHAR_PATH_SEPARATOR L'/'
|
||||
#define STRING_PATH_SEPARATOR "/"
|
||||
#define WSTRING_PATH_SEPARATOR L"/"
|
||||
|
||||
#endif
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
|
||||
Vendored
+26
-6
@@ -1,7 +1,27 @@
|
||||
#define MY_VER_MAJOR 9
|
||||
#define MY_VER_MINOR 20
|
||||
#define MY_VER_MAJOR 19
|
||||
#define MY_VER_MINOR 00
|
||||
#define MY_VER_BUILD 0
|
||||
#define MY_VERSION "9.20"
|
||||
#define MY_DATE "2010-11-18"
|
||||
#define MY_COPYRIGHT ": Igor Pavlov : Public domain"
|
||||
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE
|
||||
#define MY_VERSION_NUMBERS "19.00"
|
||||
#define MY_VERSION MY_VERSION_NUMBERS
|
||||
|
||||
#ifdef MY_CPU_NAME
|
||||
#define MY_VERSION_CPU MY_VERSION " (" MY_CPU_NAME ")"
|
||||
#else
|
||||
#define MY_VERSION_CPU MY_VERSION
|
||||
#endif
|
||||
|
||||
#define MY_DATE "2019-02-21"
|
||||
#undef MY_COPYRIGHT
|
||||
#undef MY_VERSION_COPYRIGHT_DATE
|
||||
#define MY_AUTHOR_NAME "Igor Pavlov"
|
||||
#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain"
|
||||
#define MY_COPYRIGHT_CR "Copyright (c) 1999-2018 Igor Pavlov"
|
||||
|
||||
#ifdef USE_COPYRIGHT_CR
|
||||
#define MY_COPYRIGHT MY_COPYRIGHT_CR
|
||||
#else
|
||||
#define MY_COPYRIGHT MY_COPYRIGHT_PD
|
||||
#endif
|
||||
|
||||
#define MY_COPYRIGHT_DATE MY_COPYRIGHT " : " MY_DATE
|
||||
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION_CPU " : " MY_COPYRIGHT " : " MY_DATE
|
||||
Vendored
+235
-125
@@ -1,149 +1,259 @@
|
||||
/* Bcj2.c -- Converter for x86 code (BCJ2)
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
/* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)
|
||||
2018-04-28 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include "Bcj2.h"
|
||||
#include "CpuArch.h"
|
||||
|
||||
#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80)
|
||||
#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1))
|
||||
#define CProb uint16_t
|
||||
|
||||
#define kNumTopBits 24
|
||||
#define kTopValue ((uint32_t)1 << kNumTopBits)
|
||||
|
||||
#define kNumBitModelTotalBits 11
|
||||
#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
||||
#undef kTopValue
|
||||
#define kTopValue ((uint32_t)1 << 24)
|
||||
#define kNumModelBits 11
|
||||
#undef kBitModelTotal
|
||||
#define kBitModelTotal (1 << kNumModelBits)
|
||||
#define kNumMoveBits 5
|
||||
|
||||
#define RC_READ_BYTE (*buffer++)
|
||||
#define _IF_BIT_0 ttt = *prob; bound = (p->range >> kNumModelBits) * ttt; if (p->code < bound)
|
||||
#define _UPDATE_0 p->range = bound; *prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
|
||||
#define _UPDATE_1 p->range -= bound; p->code -= bound; *prob = (CProb)(ttt - (ttt >> kNumMoveBits));
|
||||
|
||||
int Bcj2_Decode(
|
||||
const uint8_t *buf0, size_t size0,
|
||||
const uint8_t *buf1, size_t size1,
|
||||
const uint8_t *buf2, size_t size2,
|
||||
const uint8_t *buf3, size_t size3,
|
||||
uint8_t *outBuf, size_t outSize)
|
||||
void Bcj2Dec_Init(CBcj2Dec *p)
|
||||
{
|
||||
uint16_t p[256 + 2];
|
||||
size_t inPos = 0, outPos = 0;
|
||||
unsigned i;
|
||||
|
||||
const uint8_t *buffer, *bufferLim;
|
||||
uint32_t range, codes = 0;
|
||||
uint8_t prevuint8_t = 0;
|
||||
p->state = BCJ2_DEC_STATE_OK;
|
||||
p->ip = 0;
|
||||
p->temp[3] = 0;
|
||||
p->range = 0;
|
||||
p->code = 0;
|
||||
for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++)
|
||||
p->probs[i] = kBitModelTotal >> 1;
|
||||
}
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(p) / sizeof(p[0]); i++)
|
||||
p[i] = kBitModelTotal >> 1;
|
||||
SRes Bcj2Dec_Decode(CBcj2Dec *p)
|
||||
{
|
||||
if (p->range <= 5)
|
||||
{
|
||||
p->state = BCJ2_DEC_STATE_OK;
|
||||
for (; p->range != 5; p->range++)
|
||||
{
|
||||
if (p->range == 1 && p->code != 0)
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])
|
||||
{
|
||||
p->state = BCJ2_STREAM_RC;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
buffer = buf3;
|
||||
bufferLim = buffer + size3;
|
||||
range = 0xFFFFFFFF;
|
||||
p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
|
||||
}
|
||||
|
||||
if (p->code == 0xFFFFFFFF)
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
p->range = 0xFFFFFFFF;
|
||||
}
|
||||
else if (p->state >= BCJ2_DEC_STATE_ORIG_0)
|
||||
{
|
||||
while (p->state <= BCJ2_DEC_STATE_ORIG_3)
|
||||
{
|
||||
Byte *dest = p->dest;
|
||||
if (dest == p->destLim)
|
||||
return SZ_OK;
|
||||
*dest = p->temp[(size_t)p->state - BCJ2_DEC_STATE_ORIG_0];
|
||||
p->state++;
|
||||
p->dest = dest + 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
if (buffer == bufferLim)
|
||||
return SZ_ERROR_DATA;
|
||||
codes = (codes << 8) | RC_READ_BYTE;
|
||||
}
|
||||
/*
|
||||
if (BCJ2_IS_32BIT_STREAM(p->state))
|
||||
{
|
||||
const Byte *cur = p->bufs[p->state];
|
||||
if (cur == p->lims[p->state])
|
||||
return SZ_OK;
|
||||
p->bufs[p->state] = cur + 4;
|
||||
|
||||
{
|
||||
uint32_t val;
|
||||
Byte *dest;
|
||||
SizeT rem;
|
||||
|
||||
p->ip += 4;
|
||||
val = GetBe32(cur) - p->ip;
|
||||
dest = p->dest;
|
||||
rem = p->destLim - dest;
|
||||
if (rem < 4)
|
||||
{
|
||||
SizeT i;
|
||||
SetUi32(p->temp, val);
|
||||
for (i = 0; i < rem; i++)
|
||||
dest[i] = p->temp[i];
|
||||
p->dest = dest + rem;
|
||||
p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;
|
||||
return SZ_OK;
|
||||
}
|
||||
SetUi32(dest, val);
|
||||
p->temp[3] = (Byte)(val >> 24);
|
||||
p->dest = dest + 4;
|
||||
p->state = BCJ2_DEC_STATE_OK;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (outSize == 0)
|
||||
return SZ_OK;
|
||||
for (;;)
|
||||
{
|
||||
if (BCJ2_IS_32BIT_STREAM(p->state))
|
||||
p->state = BCJ2_DEC_STATE_OK;
|
||||
else
|
||||
{
|
||||
if (p->range < kTopValue)
|
||||
{
|
||||
if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])
|
||||
{
|
||||
p->state = BCJ2_STREAM_RC;
|
||||
return SZ_OK;
|
||||
}
|
||||
p->range <<= 8;
|
||||
p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
uint8_t b;
|
||||
uint16_t *prob;
|
||||
uint32_t bound;
|
||||
uint32_t ttt;
|
||||
{
|
||||
const Byte *src = p->bufs[BCJ2_STREAM_MAIN];
|
||||
const Byte *srcLim;
|
||||
Byte *dest;
|
||||
SizeT num = p->lims[BCJ2_STREAM_MAIN] - src;
|
||||
|
||||
if (num == 0)
|
||||
{
|
||||
p->state = BCJ2_STREAM_MAIN;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
dest = p->dest;
|
||||
if (num > (SizeT)(p->destLim - dest))
|
||||
{
|
||||
num = p->destLim - dest;
|
||||
if (num == 0)
|
||||
{
|
||||
p->state = BCJ2_DEC_STATE_ORIG;
|
||||
return SZ_OK;
|
||||
}
|
||||
}
|
||||
|
||||
srcLim = src + num;
|
||||
|
||||
size_t limit = size0 - inPos;
|
||||
if (outSize - outPos < limit)
|
||||
limit = outSize - outPos;
|
||||
while (limit != 0)
|
||||
{
|
||||
b = buf0[inPos];
|
||||
outBuf[outPos++] = b;
|
||||
if (IsJ(prevuint8_t, b))
|
||||
if (p->temp[3] == 0x0F && (src[0] & 0xF0) == 0x80)
|
||||
*dest = src[0];
|
||||
else for (;;)
|
||||
{
|
||||
Byte b = *src;
|
||||
*dest = b;
|
||||
if (b != 0x0F)
|
||||
{
|
||||
if ((b & 0xFE) == 0xE8)
|
||||
break;
|
||||
dest++;
|
||||
if (++src != srcLim)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
dest++;
|
||||
if (++src == srcLim)
|
||||
break;
|
||||
inPos++;
|
||||
prevuint8_t = b;
|
||||
limit--;
|
||||
if ((*src & 0xF0) != 0x80)
|
||||
continue;
|
||||
*dest = *src;
|
||||
break;
|
||||
}
|
||||
|
||||
num = src - p->bufs[BCJ2_STREAM_MAIN];
|
||||
|
||||
if (src == srcLim)
|
||||
{
|
||||
p->temp[3] = src[-1];
|
||||
p->bufs[BCJ2_STREAM_MAIN] = src;
|
||||
p->ip += (uint32_t)num;
|
||||
p->dest += num;
|
||||
p->state =
|
||||
p->bufs[BCJ2_STREAM_MAIN] ==
|
||||
p->lims[BCJ2_STREAM_MAIN] ?
|
||||
(unsigned)BCJ2_STREAM_MAIN :
|
||||
(unsigned)BCJ2_DEC_STATE_ORIG;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
{
|
||||
uint32_t bound, ttt;
|
||||
CProb *prob;
|
||||
Byte b = src[0];
|
||||
Byte prev = (Byte)(num == 0 ? p->temp[3] : src[-1]);
|
||||
|
||||
p->temp[3] = b;
|
||||
p->bufs[BCJ2_STREAM_MAIN] = src + 1;
|
||||
num++;
|
||||
p->ip += (uint32_t)num;
|
||||
p->dest += num;
|
||||
|
||||
prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)prev : (b == 0xE9 ? 1 : 0));
|
||||
|
||||
_IF_BIT_0
|
||||
{
|
||||
_UPDATE_0
|
||||
continue;
|
||||
}
|
||||
_UPDATE_1
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (limit == 0 || outPos == outSize)
|
||||
break;
|
||||
{
|
||||
uint32_t val;
|
||||
unsigned cj = (p->temp[3] == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP;
|
||||
const Byte *cur = p->bufs[cj];
|
||||
Byte *dest;
|
||||
SizeT rem;
|
||||
|
||||
if (cur == p->lims[cj])
|
||||
{
|
||||
p->state = cj;
|
||||
break;
|
||||
}
|
||||
|
||||
val = GetBe32(cur);
|
||||
p->bufs[cj] = cur + 4;
|
||||
|
||||
b = buf0[inPos++];
|
||||
|
||||
if (b == 0xE8)
|
||||
prob = p + prevuint8_t;
|
||||
else if (b == 0xE9)
|
||||
prob = p + 256;
|
||||
else
|
||||
prob = p + 257;
|
||||
|
||||
ttt = *(prob);
|
||||
bound = (range >> kNumBitModelTotalBits) * ttt;
|
||||
|
||||
if (codes < bound)
|
||||
p->ip += 4;
|
||||
val -= p->ip;
|
||||
dest = p->dest;
|
||||
rem = p->destLim - dest;
|
||||
|
||||
if (rem < 4)
|
||||
{
|
||||
range = bound;
|
||||
*(prob) = (uint16_t)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
|
||||
|
||||
if (range < kTopValue)
|
||||
{
|
||||
if (buffer == bufferLim)
|
||||
return SZ_ERROR_DATA;
|
||||
range <<= 8;
|
||||
codes = (codes << 8) | RC_READ_BYTE;
|
||||
}
|
||||
prevuint8_t = b;
|
||||
p->temp[0] = (Byte)val; if (rem > 0) dest[0] = (Byte)val; val >>= 8;
|
||||
p->temp[1] = (Byte)val; if (rem > 1) dest[1] = (Byte)val; val >>= 8;
|
||||
p->temp[2] = (Byte)val; if (rem > 2) dest[2] = (Byte)val; val >>= 8;
|
||||
p->temp[3] = (Byte)val;
|
||||
p->dest = dest + rem;
|
||||
p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t dest;
|
||||
const uint8_t *v;
|
||||
|
||||
SetUi32(dest, val);
|
||||
p->temp[3] = (Byte)(val >> 24);
|
||||
p->dest = dest + 4;
|
||||
}
|
||||
}
|
||||
|
||||
range -= bound;
|
||||
codes -= bound;
|
||||
*(prob) = (uint16_t)(ttt - (ttt >> kNumMoveBits));
|
||||
if (p->range < kTopValue && p->bufs[BCJ2_STREAM_RC] != p->lims[BCJ2_STREAM_RC])
|
||||
{
|
||||
p->range <<= 8;
|
||||
p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
|
||||
}
|
||||
|
||||
if (range < kTopValue)
|
||||
{
|
||||
if (buffer == bufferLim)
|
||||
return SZ_ERROR_DATA;
|
||||
range <<= 8;
|
||||
codes = (codes << 8) | RC_READ_BYTE;
|
||||
}
|
||||
|
||||
if (b == 0xE8)
|
||||
{
|
||||
v = buf1;
|
||||
if (size1 < 4)
|
||||
return SZ_ERROR_DATA;
|
||||
buf1 += 4;
|
||||
size1 -= 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
v = buf2;
|
||||
if (size2 < 4)
|
||||
return SZ_ERROR_DATA;
|
||||
buf2 += 4;
|
||||
size2 -= 4;
|
||||
}
|
||||
dest = (((uint32_t)v[0] << 24) | ((uint32_t)v[1] << 16) |
|
||||
((uint32_t)v[2] << 8) | ((uint32_t)v[3])) - ((uint32_t)outPos + 4);
|
||||
outBuf[outPos++] = (uint8_t)dest;
|
||||
if (outPos == outSize)
|
||||
break;
|
||||
outBuf[outPos++] = (uint8_t)(dest >> 8);
|
||||
if (outPos == outSize)
|
||||
break;
|
||||
outBuf[outPos++] = (uint8_t)(dest >> 16);
|
||||
if (outPos == outSize)
|
||||
break;
|
||||
outBuf[outPos++] = prevuint8_t = (uint8_t)(dest >> 24);
|
||||
}
|
||||
}
|
||||
return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA;
|
||||
return SZ_OK;
|
||||
}
|
||||
Vendored
+133
-25
@@ -1,38 +1,146 @@
|
||||
/* Bcj2.h -- Converter for x86 code (BCJ2)
|
||||
2009-02-07 : Igor Pavlov : Public domain */
|
||||
/* Bcj2.h -- BCJ2 Converter for x86 code
|
||||
2014-11-10 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __BCJ2_H
|
||||
#define __BCJ2_H
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#define BCJ2_NUM_STREAMS 4
|
||||
|
||||
enum
|
||||
{
|
||||
BCJ2_STREAM_MAIN,
|
||||
BCJ2_STREAM_CALL,
|
||||
BCJ2_STREAM_JUMP,
|
||||
BCJ2_STREAM_RC
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
BCJ2_DEC_STATE_ORIG_0 = BCJ2_NUM_STREAMS,
|
||||
BCJ2_DEC_STATE_ORIG_1,
|
||||
BCJ2_DEC_STATE_ORIG_2,
|
||||
BCJ2_DEC_STATE_ORIG_3,
|
||||
|
||||
BCJ2_DEC_STATE_ORIG,
|
||||
BCJ2_DEC_STATE_OK
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
BCJ2_ENC_STATE_ORIG = BCJ2_NUM_STREAMS,
|
||||
BCJ2_ENC_STATE_OK
|
||||
};
|
||||
|
||||
|
||||
#define BCJ2_IS_32BIT_STREAM(s) ((s) == BCJ2_STREAM_CALL || (s) == BCJ2_STREAM_JUMP)
|
||||
|
||||
/*
|
||||
Conditions:
|
||||
outSize <= FullOutputSize,
|
||||
where FullOutputSize is full size of output stream of x86_2 filter.
|
||||
|
||||
If buf0 overlaps outBuf, there are two required conditions:
|
||||
1) (buf0 >= outBuf)
|
||||
2) (buf0 + size0 >= outBuf + FullOutputSize).
|
||||
|
||||
Returns:
|
||||
SZ_OK
|
||||
SZ_ERROR_DATA - Data error
|
||||
CBcj2Dec / CBcj2Enc
|
||||
bufs sizes:
|
||||
BUF_SIZE(n) = lims[n] - bufs[n]
|
||||
bufs sizes for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP must be mutliply of 4:
|
||||
(BUF_SIZE(BCJ2_STREAM_CALL) & 3) == 0
|
||||
(BUF_SIZE(BCJ2_STREAM_JUMP) & 3) == 0
|
||||
*/
|
||||
|
||||
int Bcj2_Decode(
|
||||
const uint8_t *buf0, size_t size0,
|
||||
const uint8_t *buf1, size_t size1,
|
||||
const uint8_t *buf2, size_t size2,
|
||||
const uint8_t *buf3, size_t size3,
|
||||
uint8_t *outBuf, size_t outSize);
|
||||
/*
|
||||
CBcj2Dec:
|
||||
dest is allowed to overlap with bufs[BCJ2_STREAM_MAIN], with the following conditions:
|
||||
bufs[BCJ2_STREAM_MAIN] >= dest &&
|
||||
bufs[BCJ2_STREAM_MAIN] - dest >= tempReserv +
|
||||
BUF_SIZE(BCJ2_STREAM_CALL) +
|
||||
BUF_SIZE(BCJ2_STREAM_JUMP)
|
||||
tempReserv = 0 : for first call of Bcj2Dec_Decode
|
||||
tempReserv = 4 : for any other calls of Bcj2Dec_Decode
|
||||
overlap with offset = 1 is not allowed
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
typedef struct
|
||||
{
|
||||
const Byte *bufs[BCJ2_NUM_STREAMS];
|
||||
const Byte *lims[BCJ2_NUM_STREAMS];
|
||||
Byte *dest;
|
||||
const Byte *destLim;
|
||||
|
||||
unsigned state; /* BCJ2_STREAM_MAIN has more priority than BCJ2_STATE_ORIG */
|
||||
|
||||
uint32_t ip;
|
||||
Byte temp[4];
|
||||
uint32_t range;
|
||||
uint32_t code;
|
||||
uint16_t probs[2 + 256];
|
||||
} CBcj2Dec;
|
||||
|
||||
void Bcj2Dec_Init(CBcj2Dec *p);
|
||||
|
||||
/* Returns: SZ_OK or SZ_ERROR_DATA */
|
||||
SRes Bcj2Dec_Decode(CBcj2Dec *p);
|
||||
|
||||
#define Bcj2Dec_IsFinished(_p_) ((_p_)->code == 0)
|
||||
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BCJ2_ENC_FINISH_MODE_CONTINUE,
|
||||
BCJ2_ENC_FINISH_MODE_END_BLOCK,
|
||||
BCJ2_ENC_FINISH_MODE_END_STREAM
|
||||
} EBcj2Enc_FinishMode;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Byte *bufs[BCJ2_NUM_STREAMS];
|
||||
const Byte *lims[BCJ2_NUM_STREAMS];
|
||||
const Byte *src;
|
||||
const Byte *srcLim;
|
||||
|
||||
unsigned state;
|
||||
EBcj2Enc_FinishMode finishMode;
|
||||
|
||||
Byte prevByte;
|
||||
|
||||
Byte cache;
|
||||
uint32_t range;
|
||||
uint64_t low;
|
||||
uint64_t cacheSize;
|
||||
|
||||
uint32_t ip;
|
||||
|
||||
/* 32-bit ralative offset in JUMP/CALL commands is
|
||||
- (mod 4 GB) in 32-bit mode
|
||||
- signed Int32 in 64-bit mode
|
||||
We use (mod 4 GB) check for fileSize.
|
||||
Use fileSize up to 2 GB, if you want to support 32-bit and 64-bit code conversion. */
|
||||
uint32_t fileIp;
|
||||
uint32_t fileSize; /* (fileSize <= ((uint32_t)1 << 31)), 0 means no_limit */
|
||||
uint32_t relatLimit; /* (relatLimit <= ((uint32_t)1 << 31)), 0 means desable_conversion */
|
||||
|
||||
uint32_t tempTarget;
|
||||
unsigned tempPos;
|
||||
Byte temp[4 * 2];
|
||||
|
||||
unsigned flushPos;
|
||||
|
||||
uint16_t probs[2 + 256];
|
||||
} CBcj2Enc;
|
||||
|
||||
void Bcj2Enc_Init(CBcj2Enc *p);
|
||||
void Bcj2Enc_Encode(CBcj2Enc *p);
|
||||
|
||||
#define Bcj2Enc_Get_InputData_Size(p) ((SizeT)((p)->srcLim - (p)->src) + (p)->tempPos)
|
||||
#define Bcj2Enc_IsFinished(p) ((p)->flushPos == 5)
|
||||
|
||||
|
||||
#define BCJ2_RELAT_LIMIT_NUM_BITS 26
|
||||
#define BCJ2_RELAT_LIMIT ((uint32_t)1 << BCJ2_RELAT_LIMIT_NUM_BITS)
|
||||
|
||||
/* limit for CBcj2Enc::fileSize variable */
|
||||
#define BCJ2_FileSize_MAX ((uint32_t)1 << 31)
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
Vendored
+212
-116
@@ -1,134 +1,230 @@
|
||||
/* Bra.c -- Converters for RISC code
|
||||
2010-04-16 : Igor Pavlov : Public domain */
|
||||
2017-04-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#include <stdint.h>
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "CpuArch.h"
|
||||
#include "Bra.h"
|
||||
|
||||
size_t ARM_Convert(uint8_t *data, size_t size, uint32_t ip, int encoding)
|
||||
SizeT ARM_Convert(Byte *data, SizeT size, uint32_t ip, int encoding)
|
||||
{
|
||||
size_t i;
|
||||
if (size < 4)
|
||||
return 0;
|
||||
size -= 4;
|
||||
ip += 8;
|
||||
for (i = 0; i <= size; i += 4)
|
||||
{
|
||||
if (data[i + 3] == 0xEB)
|
||||
{
|
||||
uint32_t dest;
|
||||
uint32_t src = ((uint32_t)data[i + 2] << 16) | ((uint32_t)data[i + 1] << 8) | (data[i + 0]);
|
||||
src <<= 2;
|
||||
if (encoding)
|
||||
dest = ip + (uint32_t)i + src;
|
||||
else
|
||||
dest = src - (ip + (uint32_t)i);
|
||||
dest >>= 2;
|
||||
data[i + 2] = (uint8_t)(dest >> 16);
|
||||
data[i + 1] = (uint8_t)(dest >> 8);
|
||||
data[i + 0] = (uint8_t)dest;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
Byte *p;
|
||||
const Byte *lim;
|
||||
size &= ~(size_t)3;
|
||||
ip += 4;
|
||||
p = data;
|
||||
lim = data + size;
|
||||
|
||||
if (encoding)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (p >= lim)
|
||||
return p - data;
|
||||
p += 4;
|
||||
if (p[-1] == 0xEB)
|
||||
break;
|
||||
}
|
||||
{
|
||||
uint32_t v = GetUi32(p - 4);
|
||||
v <<= 2;
|
||||
v += ip + (uint32_t)(p - data);
|
||||
v >>= 2;
|
||||
v &= 0x00FFFFFF;
|
||||
v |= 0xEB000000;
|
||||
SetUi32(p - 4, v);
|
||||
}
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (p >= lim)
|
||||
return p - data;
|
||||
p += 4;
|
||||
if (p[-1] == 0xEB)
|
||||
break;
|
||||
}
|
||||
{
|
||||
uint32_t v = GetUi32(p - 4);
|
||||
v <<= 2;
|
||||
v -= ip + (uint32_t)(p - data);
|
||||
v >>= 2;
|
||||
v &= 0x00FFFFFF;
|
||||
v |= 0xEB000000;
|
||||
SetUi32(p - 4, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t ARMT_Convert(uint8_t *data, size_t size, uint32_t ip, int encoding)
|
||||
|
||||
SizeT ARMT_Convert(Byte *data, SizeT size, uint32_t ip, int encoding)
|
||||
{
|
||||
size_t i;
|
||||
if (size < 4)
|
||||
return 0;
|
||||
size -= 4;
|
||||
ip += 4;
|
||||
for (i = 0; i <= size; i += 2)
|
||||
{
|
||||
if ((data[i + 1] & 0xF8) == 0xF0 &&
|
||||
(data[i + 3] & 0xF8) == 0xF8)
|
||||
Byte *p;
|
||||
const Byte *lim;
|
||||
size &= ~(size_t)1;
|
||||
p = data;
|
||||
lim = data + size - 4;
|
||||
|
||||
if (encoding)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
uint32_t b1;
|
||||
for (;;)
|
||||
{
|
||||
uint32_t b3;
|
||||
if (p > lim)
|
||||
return p - data;
|
||||
b1 = p[1];
|
||||
b3 = p[3];
|
||||
p += 2;
|
||||
b1 ^= 8;
|
||||
if ((b3 & b1) >= 0xF8)
|
||||
break;
|
||||
}
|
||||
{
|
||||
uint32_t v =
|
||||
((uint32_t)b1 << 19)
|
||||
+ (((uint32_t)p[1] & 0x7) << 8)
|
||||
+ (((uint32_t)p[-2] << 11))
|
||||
+ (p[0]);
|
||||
|
||||
p += 2;
|
||||
{
|
||||
uint32_t dest;
|
||||
uint32_t src =
|
||||
(((uint32_t)data[i + 1] & 0x7) << 19) |
|
||||
((uint32_t)data[i + 0] << 11) |
|
||||
(((uint32_t)data[i + 3] & 0x7) << 8) |
|
||||
(data[i + 2]);
|
||||
|
||||
src <<= 1;
|
||||
if (encoding)
|
||||
dest = ip + (uint32_t)i + src;
|
||||
else
|
||||
dest = src - (ip + (uint32_t)i);
|
||||
dest >>= 1;
|
||||
|
||||
data[i + 1] = (uint8_t)(0xF0 | ((dest >> 19) & 0x7));
|
||||
data[i + 0] = (uint8_t)(dest >> 11);
|
||||
data[i + 3] = (uint8_t)(0xF8 | ((dest >> 8) & 0x7));
|
||||
data[i + 2] = (uint8_t)dest;
|
||||
i += 2;
|
||||
uint32_t cur = (ip + (uint32_t)(p - data)) >> 1;
|
||||
v += cur;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
|
||||
p[-4] = (Byte)(v >> 11);
|
||||
p[-3] = (Byte)(0xF0 | ((v >> 19) & 0x7));
|
||||
p[-2] = (Byte)v;
|
||||
p[-1] = (Byte)(0xF8 | (v >> 8));
|
||||
}
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
uint32_t b1;
|
||||
for (;;)
|
||||
{
|
||||
uint32_t b3;
|
||||
if (p > lim)
|
||||
return p - data;
|
||||
b1 = p[1];
|
||||
b3 = p[3];
|
||||
p += 2;
|
||||
b1 ^= 8;
|
||||
if ((b3 & b1) >= 0xF8)
|
||||
break;
|
||||
}
|
||||
{
|
||||
uint32_t v =
|
||||
((uint32_t)b1 << 19)
|
||||
+ (((uint32_t)p[1] & 0x7) << 8)
|
||||
+ (((uint32_t)p[-2] << 11))
|
||||
+ (p[0]);
|
||||
|
||||
p += 2;
|
||||
{
|
||||
uint32_t cur = (ip + (uint32_t)(p - data)) >> 1;
|
||||
v -= cur;
|
||||
}
|
||||
|
||||
/*
|
||||
SetUi16(p - 4, (uint16_t)(((v >> 11) & 0x7FF) | 0xF000));
|
||||
SetUi16(p - 2, (uint16_t)(v | 0xF800));
|
||||
*/
|
||||
|
||||
p[-4] = (Byte)(v >> 11);
|
||||
p[-3] = (Byte)(0xF0 | ((v >> 19) & 0x7));
|
||||
p[-2] = (Byte)v;
|
||||
p[-1] = (Byte)(0xF8 | (v >> 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t PPC_Convert(uint8_t *data, size_t size, uint32_t ip, int encoding)
|
||||
{
|
||||
size_t i;
|
||||
if (size < 4)
|
||||
return 0;
|
||||
size -= 4;
|
||||
for (i = 0; i <= size; i += 4)
|
||||
{
|
||||
if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1)
|
||||
{
|
||||
uint32_t src = ((uint32_t)(data[i + 0] & 3) << 24) |
|
||||
((uint32_t)data[i + 1] << 16) |
|
||||
((uint32_t)data[i + 2] << 8) |
|
||||
((uint32_t)data[i + 3] & (~3));
|
||||
|
||||
uint32_t dest;
|
||||
if (encoding)
|
||||
dest = ip + (uint32_t)i + src;
|
||||
else
|
||||
dest = src - (ip + (uint32_t)i);
|
||||
data[i + 0] = (uint8_t)(0x48 | ((dest >> 24) & 0x3));
|
||||
data[i + 1] = (uint8_t)(dest >> 16);
|
||||
data[i + 2] = (uint8_t)(dest >> 8);
|
||||
data[i + 3] &= 0x3;
|
||||
data[i + 3] |= dest;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
SizeT PPC_Convert(Byte *data, SizeT size, uint32_t ip, int encoding)
|
||||
{
|
||||
Byte *p;
|
||||
const Byte *lim;
|
||||
size &= ~(size_t)3;
|
||||
ip -= 4;
|
||||
p = data;
|
||||
lim = data + size;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (p >= lim)
|
||||
return p - data;
|
||||
p += 4;
|
||||
/* if ((v & 0xFC000003) == 0x48000001) */
|
||||
if ((p[-4] & 0xFC) == 0x48 && (p[-1] & 3) == 1)
|
||||
break;
|
||||
}
|
||||
{
|
||||
uint32_t v = GetBe32(p - 4);
|
||||
if (encoding)
|
||||
v += ip + (uint32_t)(p - data);
|
||||
else
|
||||
v -= ip + (uint32_t)(p - data);
|
||||
v &= 0x03FFFFFF;
|
||||
v |= 0x48000000;
|
||||
SetBe32(p - 4, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t SPARC_Convert(uint8_t *data, size_t size, uint32_t ip, int encoding)
|
||||
|
||||
SizeT SPARC_Convert(Byte *data, SizeT size, uint32_t ip, int encoding)
|
||||
{
|
||||
uint32_t i;
|
||||
if (size < 4)
|
||||
return 0;
|
||||
size -= 4;
|
||||
for (i = 0; i <= size; i += 4)
|
||||
{
|
||||
if ((data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00) ||
|
||||
(data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0))
|
||||
{
|
||||
uint32_t src =
|
||||
((uint32_t)data[i + 0] << 24) |
|
||||
((uint32_t)data[i + 1] << 16) |
|
||||
((uint32_t)data[i + 2] << 8) |
|
||||
((uint32_t)data[i + 3]);
|
||||
uint32_t dest;
|
||||
Byte *p;
|
||||
const Byte *lim;
|
||||
size &= ~(size_t)3;
|
||||
ip -= 4;
|
||||
p = data;
|
||||
lim = data + size;
|
||||
|
||||
src <<= 2;
|
||||
if (encoding)
|
||||
dest = ip + i + src;
|
||||
else
|
||||
dest = src - (ip + i);
|
||||
dest >>= 2;
|
||||
|
||||
dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000;
|
||||
|
||||
data[i + 0] = (uint8_t)(dest >> 24);
|
||||
data[i + 1] = (uint8_t)(dest >> 16);
|
||||
data[i + 2] = (uint8_t)(dest >> 8);
|
||||
data[i + 3] = (uint8_t)dest;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
for (;;)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (p >= lim)
|
||||
return p - data;
|
||||
/*
|
||||
v = GetBe32(p);
|
||||
p += 4;
|
||||
m = v + ((uint32_t)5 << 29);
|
||||
m ^= (uint32_t)7 << 29;
|
||||
m += (uint32_t)1 << 22;
|
||||
if ((m & ((uint32_t)0x1FF << 23)) == 0)
|
||||
break;
|
||||
*/
|
||||
p += 4;
|
||||
if ((p[-4] == 0x40 && (p[-3] & 0xC0) == 0) ||
|
||||
(p[-4] == 0x7F && (p[-3] >= 0xC0)))
|
||||
break;
|
||||
}
|
||||
{
|
||||
uint32_t v = GetBe32(p - 4);
|
||||
v <<= 2;
|
||||
if (encoding)
|
||||
v += ip + (uint32_t)(p - data);
|
||||
else
|
||||
v -= ip + (uint32_t)(p - data);
|
||||
|
||||
v &= 0x01FFFFFF;
|
||||
v -= (uint32_t)1 << 24;
|
||||
v ^= 0xFF000000;
|
||||
v >>= 2;
|
||||
v |= 0x40000000;
|
||||
SetBe32(p - 4, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+46
-50
@@ -1,68 +1,64 @@
|
||||
/* Bra.h -- Branch converters for executables
|
||||
2009-02-07 : Igor Pavlov : Public domain */
|
||||
2013-01-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __BRA_H
|
||||
#define __BRA_H
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
/*
|
||||
These functions convert relative addresses to absolute addresses
|
||||
in CALL instructions to increase the compression ratio.
|
||||
/*
|
||||
These functions convert relative addresses to absolute addresses
|
||||
in CALL instructions to increase the compression ratio.
|
||||
|
||||
In:
|
||||
data - data buffer
|
||||
size - size of data
|
||||
ip - current virtual Instruction Pinter (IP) value
|
||||
state - state variable for x86 converter
|
||||
encoding - 0 (for decoding), 1 (for encoding)
|
||||
|
||||
Out:
|
||||
state - state variable for x86 converter
|
||||
|
||||
In:
|
||||
data - data buffer
|
||||
size - size of data
|
||||
ip - current virtual Instruction Pinter (IP) value
|
||||
state - state variable for x86 converter
|
||||
encoding - 0 (for decoding), 1 (for encoding)
|
||||
Returns:
|
||||
The number of processed bytes. If you call these functions with multiple calls,
|
||||
you must start next call with first byte after block of processed bytes.
|
||||
|
||||
Type Endian Alignment LookAhead
|
||||
|
||||
x86 little 1 4
|
||||
ARMT little 2 2
|
||||
ARM little 4 0
|
||||
PPC big 4 0
|
||||
SPARC big 4 0
|
||||
IA64 little 16 0
|
||||
|
||||
Out:
|
||||
state - state variable for x86 converter
|
||||
size must be >= Alignment + LookAhead, if it's not last block.
|
||||
If (size < Alignment + LookAhead), converter returns 0.
|
||||
|
||||
Returns:
|
||||
The number of processed bytes. If you call these functions with multiple calls,
|
||||
you must start next call with first byte after block of processed bytes.
|
||||
Example:
|
||||
|
||||
Type Endian Alignment LookAhead
|
||||
|
||||
x86 little 1 4
|
||||
ARMT little 2 2
|
||||
ARM little 4 0
|
||||
PPC big 4 0
|
||||
SPARC big 4 0
|
||||
IA64 little 16 0
|
||||
|
||||
size must be >= Alignment + LookAhead, if it's not last block.
|
||||
If (size < Alignment + LookAhead), converter returns 0.
|
||||
|
||||
Example:
|
||||
|
||||
uint32_t ip = 0;
|
||||
for ()
|
||||
{
|
||||
; size must be >= Alignment + LookAhead, if it's not last block
|
||||
size_t processed = Convert(data, size, ip, 1);
|
||||
data += processed;
|
||||
size -= processed;
|
||||
ip += processed;
|
||||
}
|
||||
uint32_t ip = 0;
|
||||
for ()
|
||||
{
|
||||
; size must be >= Alignment + LookAhead, if it's not last block
|
||||
SizeT processed = Convert(data, size, ip, 1);
|
||||
data += processed;
|
||||
size -= processed;
|
||||
ip += processed;
|
||||
}
|
||||
*/
|
||||
|
||||
#define x86_Convert_Init(state) { state = 0; }
|
||||
size_t x86_Convert(uint8_t *data, size_t size, uint32_t ip, uint32_t *state, int encoding);
|
||||
size_t ARM_Convert(uint8_t *data, size_t size, uint32_t ip, int encoding);
|
||||
size_t ARMT_Convert(uint8_t *data, size_t size, uint32_t ip, int encoding);
|
||||
size_t PPC_Convert(uint8_t *data, size_t size, uint32_t ip, int encoding);
|
||||
size_t SPARC_Convert(uint8_t *data, size_t size, uint32_t ip, int encoding);
|
||||
size_t IA64_Convert(uint8_t *data, size_t size, uint32_t ip, int encoding);
|
||||
SizeT x86_Convert(Byte *data, SizeT size, uint32_t ip, uint32_t *state, int encoding);
|
||||
SizeT ARM_Convert(Byte *data, SizeT size, uint32_t ip, int encoding);
|
||||
SizeT ARMT_Convert(Byte *data, SizeT size, uint32_t ip, int encoding);
|
||||
SizeT PPC_Convert(Byte *data, SizeT size, uint32_t ip, int encoding);
|
||||
SizeT SPARC_Convert(Byte *data, SizeT size, uint32_t ip, int encoding);
|
||||
SizeT IA64_Convert(Byte *data, SizeT size, uint32_t ip, int encoding);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
Vendored
+66
-70
@@ -1,86 +1,82 @@
|
||||
/* Bra86.c -- Converter for x86 code (BCJ)
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include "Bra.h"
|
||||
|
||||
#define Test86MSuint8_t(b) ((b) == 0 || (b) == 0xFF)
|
||||
#define Test86MSByte(b) ((((b) + 1) & 0xFE) == 0)
|
||||
|
||||
const uint8_t kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0};
|
||||
const uint8_t kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3};
|
||||
|
||||
size_t x86_Convert(uint8_t *data, size_t size, uint32_t ip, uint32_t *state, int encoding)
|
||||
SizeT x86_Convert(Byte *data, SizeT size, uint32_t ip, uint32_t *state, int encoding)
|
||||
{
|
||||
size_t bufferPos = 0, prevPosT;
|
||||
uint32_t prevMask = *state & 0x7;
|
||||
if (size < 5)
|
||||
return 0;
|
||||
ip += 5;
|
||||
prevPosT = (size_t)0 - 1;
|
||||
SizeT pos = 0;
|
||||
uint32_t mask = *state & 7;
|
||||
if (size < 5)
|
||||
return 0;
|
||||
size -= 4;
|
||||
ip += 5;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
uint8_t *p = data + bufferPos;
|
||||
uint8_t *limit = data + size - 4;
|
||||
for (; p < limit; p++)
|
||||
if ((*p & 0xFE) == 0xE8)
|
||||
break;
|
||||
bufferPos = (size_t)(p - data);
|
||||
for (;;)
|
||||
{
|
||||
Byte *p = data + pos;
|
||||
const Byte *limit = data + size;
|
||||
for (; p < limit; p++)
|
||||
if ((*p & 0xFE) == 0xE8)
|
||||
break;
|
||||
|
||||
{
|
||||
SizeT d = (SizeT)(p - data - pos);
|
||||
pos = (SizeT)(p - data);
|
||||
if (p >= limit)
|
||||
break;
|
||||
prevPosT = bufferPos - prevPosT;
|
||||
if (prevPosT > 3)
|
||||
prevMask = 0;
|
||||
{
|
||||
*state = (d > 2 ? 0 : mask >> (unsigned)d);
|
||||
return pos;
|
||||
}
|
||||
if (d > 2)
|
||||
mask = 0;
|
||||
else
|
||||
{
|
||||
prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7;
|
||||
if (prevMask != 0)
|
||||
{
|
||||
uint8_t b = p[4 - kMaskToBitNumber[prevMask]];
|
||||
if (!kMaskToAllowedStatus[prevMask] || Test86MSuint8_t(b))
|
||||
{
|
||||
prevPosT = bufferPos;
|
||||
prevMask = ((prevMask << 1) & 0x7) | 1;
|
||||
bufferPos++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
mask >>= (unsigned)d;
|
||||
if (mask != 0 && (mask > 4 || mask == 3 || Test86MSByte(p[(size_t)(mask >> 1) + 1])))
|
||||
{
|
||||
mask = (mask >> 1) | 4;
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
prevPosT = bufferPos;
|
||||
}
|
||||
|
||||
if (Test86MSuint8_t(p[4]))
|
||||
{
|
||||
uint32_t src = ((uint32_t)p[4] << 24) | ((uint32_t)p[3] << 16) | ((uint32_t)p[2] << 8) | ((uint32_t)p[1]);
|
||||
uint32_t dest;
|
||||
for (;;)
|
||||
{
|
||||
uint8_t b;
|
||||
int idx;
|
||||
if (encoding)
|
||||
dest = (ip + (uint32_t)bufferPos) + src;
|
||||
else
|
||||
dest = src - (ip + (uint32_t)bufferPos);
|
||||
if (prevMask == 0)
|
||||
break;
|
||||
idx = kMaskToBitNumber[prevMask] * 8;
|
||||
b = (uint8_t)(dest >> (24 - idx));
|
||||
if (!Test86MSuint8_t(b))
|
||||
break;
|
||||
src = dest ^ ((1 << (32 - idx)) - 1);
|
||||
}
|
||||
p[4] = (uint8_t)(~(((dest >> 24) & 1) - 1));
|
||||
p[3] = (uint8_t)(dest >> 16);
|
||||
p[2] = (uint8_t)(dest >> 8);
|
||||
p[1] = (uint8_t)dest;
|
||||
bufferPos += 5;
|
||||
}
|
||||
if (Test86MSByte(p[4]))
|
||||
{
|
||||
uint32_t v = ((uint32_t)p[4] << 24) | ((uint32_t)p[3] << 16) | ((uint32_t)p[2] << 8) | ((uint32_t)p[1]);
|
||||
uint32_t cur = ip + (uint32_t)pos;
|
||||
pos += 5;
|
||||
if (encoding)
|
||||
v += cur;
|
||||
else
|
||||
v -= cur;
|
||||
if (mask != 0)
|
||||
{
|
||||
prevMask = ((prevMask << 1) & 0x7) | 1;
|
||||
bufferPos++;
|
||||
unsigned sh = (mask & 6) << 2;
|
||||
if (Test86MSByte((Byte)(v >> sh)))
|
||||
{
|
||||
v ^= (((uint32_t)0x100 << sh) - 1);
|
||||
if (encoding)
|
||||
v += cur;
|
||||
else
|
||||
v -= cur;
|
||||
}
|
||||
mask = 0;
|
||||
}
|
||||
}
|
||||
prevPosT = bufferPos - prevPosT;
|
||||
*state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7));
|
||||
return bufferPos;
|
||||
p[1] = (Byte)v;
|
||||
p[2] = (Byte)(v >> 8);
|
||||
p[3] = (Byte)(v >> 16);
|
||||
p[4] = (Byte)(0 - ((v >> 24) & 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = (mask >> 1) | 4;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+53
@@ -0,0 +1,53 @@
|
||||
/* BraIA64.c -- Converter for IA-64 code
|
||||
2017-01-26 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "CpuArch.h"
|
||||
#include "Bra.h"
|
||||
|
||||
SizeT IA64_Convert(Byte *data, SizeT size, uint32_t ip, int encoding)
|
||||
{
|
||||
SizeT i;
|
||||
if (size < 16)
|
||||
return 0;
|
||||
size -= 16;
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
unsigned m = ((uint32_t)0x334B0000 >> (data[i] & 0x1E)) & 3;
|
||||
if (m)
|
||||
{
|
||||
m++;
|
||||
do
|
||||
{
|
||||
Byte *p = data + (i + (size_t)m * 5 - 8);
|
||||
if (((p[3] >> m) & 15) == 5
|
||||
&& (((p[-1] | ((uint32_t)p[0] << 8)) >> m) & 0x70) == 0)
|
||||
{
|
||||
unsigned raw = GetUi32(p);
|
||||
unsigned v = raw >> m;
|
||||
v = (v & 0xFFFFF) | ((v & (1 << 23)) >> 3);
|
||||
|
||||
v <<= 4;
|
||||
if (encoding)
|
||||
v += ip + (uint32_t)i;
|
||||
else
|
||||
v -= ip + (uint32_t)i;
|
||||
v >>= 4;
|
||||
|
||||
v &= 0x1FFFFF;
|
||||
v += 0x700000;
|
||||
v &= 0x8FFFFF;
|
||||
raw &= ~((uint32_t)0x8FFFFF << m);
|
||||
raw |= (v << m);
|
||||
SetUi32(p, raw);
|
||||
}
|
||||
}
|
||||
while (++m <= 4);
|
||||
}
|
||||
i += 16;
|
||||
}
|
||||
while (i <= size);
|
||||
return i;
|
||||
}
|
||||
Vendored
+33
@@ -0,0 +1,33 @@
|
||||
/* Compiler.h
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_COMPILER_H
|
||||
#define __7Z_COMPILER_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#ifdef UNDER_CE
|
||||
#define RPC_NO_WINDOWS_H
|
||||
/* #pragma warning(disable : 4115) // '_RPC_ASYNC_STATE' : named type definition in parentheses */
|
||||
#pragma warning(disable : 4201) /* nonstandard extension used : nameless struct/union */
|
||||
#pragma warning(disable : 4214) /* nonstandard extension used : bit field types other than int */
|
||||
#endif
|
||||
|
||||
#if _MSC_VER >= 1300
|
||||
#pragma warning(disable : 4996) /* This function or variable may be unsafe */
|
||||
#else
|
||||
#pragma warning(disable : 4511) /* copy constructor could not be generated */
|
||||
#pragma warning(disable : 4512) /* assignment operator could not be generated */
|
||||
#pragma warning(disable : 4514) /* unreferenced inline function has been removed */
|
||||
#pragma warning(disable : 4702) /* unreachable code */
|
||||
#pragma warning(disable : 4710) /* not inlined */
|
||||
#pragma warning(disable : 4714) /* function marked as __forceinline not inlined */
|
||||
#pragma warning(disable : 4786) /* identifier was truncated to '255' characters in the debug information */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#define UNUSED_VAR(x) (void)x;
|
||||
/* #define UNUSED_VAR(x) x=x; */
|
||||
|
||||
#endif
|
||||
Vendored
+218
@@ -0,0 +1,218 @@
|
||||
/* CpuArch.c -- CPU specific code
|
||||
2018-02-18: Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "CpuArch.h"
|
||||
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
|
||||
#if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__)
|
||||
#define USE_ASM
|
||||
#endif
|
||||
|
||||
#if !defined(USE_ASM) && _MSC_VER >= 1500
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#if defined(USE_ASM) && !defined(MY_CPU_AMD64)
|
||||
static uint32_t CheckFlag(uint32_t flag)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
__asm pushfd;
|
||||
__asm pop EAX;
|
||||
__asm mov EDX, EAX;
|
||||
__asm xor EAX, flag;
|
||||
__asm push EAX;
|
||||
__asm popfd;
|
||||
__asm pushfd;
|
||||
__asm pop EAX;
|
||||
__asm xor EAX, EDX;
|
||||
__asm push EDX;
|
||||
__asm popfd;
|
||||
__asm and flag, EAX;
|
||||
#else
|
||||
__asm__ __volatile__ (
|
||||
"pushf\n\t"
|
||||
"pop %%EAX\n\t"
|
||||
"movl %%EAX,%%EDX\n\t"
|
||||
"xorl %0,%%EAX\n\t"
|
||||
"push %%EAX\n\t"
|
||||
"popf\n\t"
|
||||
"pushf\n\t"
|
||||
"pop %%EAX\n\t"
|
||||
"xorl %%EDX,%%EAX\n\t"
|
||||
"push %%EDX\n\t"
|
||||
"popf\n\t"
|
||||
"andl %%EAX, %0\n\t":
|
||||
"=c" (flag) : "c" (flag) :
|
||||
"%eax", "%edx");
|
||||
#endif
|
||||
return flag;
|
||||
}
|
||||
#define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False;
|
||||
#else
|
||||
#define CHECK_CPUID_IS_SUPPORTED
|
||||
#endif
|
||||
|
||||
void MyCPUID(uint32_t function, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)
|
||||
{
|
||||
#ifdef USE_ASM
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
uint32_t a2, b2, c2, d2;
|
||||
__asm xor EBX, EBX;
|
||||
__asm xor ECX, ECX;
|
||||
__asm xor EDX, EDX;
|
||||
__asm mov EAX, function;
|
||||
__asm cpuid;
|
||||
__asm mov a2, EAX;
|
||||
__asm mov b2, EBX;
|
||||
__asm mov c2, ECX;
|
||||
__asm mov d2, EDX;
|
||||
|
||||
*a = a2;
|
||||
*b = b2;
|
||||
*c = c2;
|
||||
*d = d2;
|
||||
|
||||
#else
|
||||
|
||||
__asm__ __volatile__ (
|
||||
#if defined(MY_CPU_AMD64) && defined(__PIC__)
|
||||
"mov %%rbx, %%rdi;"
|
||||
"cpuid;"
|
||||
"xchg %%rbx, %%rdi;"
|
||||
: "=a" (*a) ,
|
||||
"=D" (*b) ,
|
||||
#elif defined(MY_CPU_X86) && defined(__PIC__)
|
||||
"mov %%ebx, %%edi;"
|
||||
"cpuid;"
|
||||
"xchgl %%ebx, %%edi;"
|
||||
: "=a" (*a) ,
|
||||
"=D" (*b) ,
|
||||
#else
|
||||
"cpuid"
|
||||
: "=a" (*a) ,
|
||||
"=b" (*b) ,
|
||||
#endif
|
||||
"=c" (*c) ,
|
||||
"=d" (*d)
|
||||
: "0" (function)) ;
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
int CPUInfo[4];
|
||||
__cpuid(CPUInfo, function);
|
||||
*a = CPUInfo[0];
|
||||
*b = CPUInfo[1];
|
||||
*c = CPUInfo[2];
|
||||
*d = CPUInfo[3];
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
BoolInt x86cpuid_CheckAndRead(Cx86cpuid *p)
|
||||
{
|
||||
CHECK_CPUID_IS_SUPPORTED
|
||||
MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]);
|
||||
MyCPUID(1, &p->ver, &p->b, &p->c, &p->d);
|
||||
return True;
|
||||
}
|
||||
|
||||
static const uint32_t kVendors[][3] =
|
||||
{
|
||||
{ 0x756E6547, 0x49656E69, 0x6C65746E},
|
||||
{ 0x68747541, 0x69746E65, 0x444D4163},
|
||||
{ 0x746E6543, 0x48727561, 0x736C7561}
|
||||
};
|
||||
|
||||
int x86cpuid_GetFirm(const Cx86cpuid *p)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++)
|
||||
{
|
||||
const uint32_t *v = kVendors[i];
|
||||
if (v[0] == p->vendor[0] &&
|
||||
v[1] == p->vendor[1] &&
|
||||
v[2] == p->vendor[2])
|
||||
return (int)i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
BoolInt CPU_Is_InOrder(void)
|
||||
{
|
||||
Cx86cpuid p;
|
||||
int firm;
|
||||
uint32_t family, model;
|
||||
if (!x86cpuid_CheckAndRead(&p))
|
||||
return True;
|
||||
|
||||
family = x86cpuid_GetFamily(p.ver);
|
||||
model = x86cpuid_GetModel(p.ver);
|
||||
|
||||
firm = x86cpuid_GetFirm(&p);
|
||||
|
||||
switch (firm)
|
||||
{
|
||||
case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && (
|
||||
/* In-Order Atom CPU */
|
||||
model == 0x1C /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */
|
||||
|| model == 0x26 /* 45 nm, Z6xx */
|
||||
|| model == 0x27 /* 32 nm, Z2460 */
|
||||
|| model == 0x35 /* 32 nm, Z2760 */
|
||||
|| model == 0x36 /* 32 nm, N2xxx, D2xxx */
|
||||
)));
|
||||
case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));
|
||||
case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
#if !defined(MY_CPU_AMD64) && defined(_WIN32)
|
||||
#include <windows.h>
|
||||
static BoolInt CPU_Sys_Is_SSE_Supported(void)
|
||||
{
|
||||
OSVERSIONINFO vi;
|
||||
vi.dwOSVersionInfoSize = sizeof(vi);
|
||||
if (!GetVersionEx(&vi))
|
||||
return False;
|
||||
return (vi.dwMajorVersion >= 5);
|
||||
}
|
||||
#define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False;
|
||||
#else
|
||||
#define CHECK_SYS_SSE_SUPPORT
|
||||
#endif
|
||||
|
||||
BoolInt CPU_Is_Aes_Supported(void)
|
||||
{
|
||||
Cx86cpuid p;
|
||||
CHECK_SYS_SSE_SUPPORT
|
||||
if (!x86cpuid_CheckAndRead(&p))
|
||||
return False;
|
||||
return (p.c >> 25) & 1;
|
||||
}
|
||||
|
||||
BoolInt CPU_IsSupported_PageGB(void)
|
||||
{
|
||||
Cx86cpuid cpuid;
|
||||
if (!x86cpuid_CheckAndRead(&cpuid))
|
||||
return False;
|
||||
{
|
||||
uint32_t d[4] = { 0 };
|
||||
MyCPUID(0x80000000, &d[0], &d[1], &d[2], &d[3]);
|
||||
if (d[0] < 0x80000001)
|
||||
return False;
|
||||
}
|
||||
{
|
||||
uint32_t d[4] = { 0 };
|
||||
MyCPUID(0x80000001, &d[0], &d[1], &d[2], &d[3]);
|
||||
return (d[3] >> 26) & 1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Vendored
+309
-29
@@ -1,56 +1,336 @@
|
||||
/* CpuArch.h -- CPU specific code
|
||||
2010-10-26: Igor Pavlov : Public domain */
|
||||
2018-02-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __CPU_ARCH_H
|
||||
#define __CPU_ARCH_H
|
||||
|
||||
#include <retro_endianness.h>
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
/* MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and
|
||||
CPU supports unaligned memory accesses.
|
||||
If MY_CPU_LE_UNALIGN is not defined, we don't know
|
||||
about these properties of platform.
|
||||
/*
|
||||
MY_CPU_LE means that CPU is LITTLE ENDIAN.
|
||||
MY_CPU_BE means that CPU is BIG ENDIAN.
|
||||
If MY_CPU_LE and MY_CPU_BE are not defined, we don't know about ENDIANNESS of platform.
|
||||
|
||||
MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses.
|
||||
*/
|
||||
|
||||
#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__)
|
||||
#define MY_CPU_AMD64
|
||||
#if defined(_M_X64) \
|
||||
|| defined(_M_AMD64) \
|
||||
|| defined(__x86_64__) \
|
||||
|| defined(__AMD64__) \
|
||||
|| defined(__amd64__)
|
||||
#define MY_CPU_AMD64
|
||||
#ifdef __ILP32__
|
||||
#define MY_CPU_NAME "x32"
|
||||
#else
|
||||
#define MY_CPU_NAME "x64"
|
||||
#endif
|
||||
#define MY_CPU_64BIT
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_AMD64) || defined(_M_IA64)
|
||||
#define MY_CPU_64BIT
|
||||
|
||||
#if defined(_M_IX86) \
|
||||
|| defined(__i386__)
|
||||
#define MY_CPU_X86
|
||||
#define MY_CPU_NAME "x86"
|
||||
#define MY_CPU_32BIT
|
||||
#endif
|
||||
|
||||
#if defined(_M_IX86) || defined(__i386__)
|
||||
#define MY_CPU_X86
|
||||
|
||||
#if defined(_M_ARM64) \
|
||||
|| defined(__AARCH64EL__) \
|
||||
|| defined(__AARCH64EB__) \
|
||||
|| defined(__aarch64__)
|
||||
#define MY_CPU_ARM64
|
||||
#define MY_CPU_NAME "arm64"
|
||||
#define MY_CPU_64BIT
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_M_ARM) \
|
||||
|| defined(_M_ARM_NT) \
|
||||
|| defined(_M_ARMT) \
|
||||
|| defined(__arm__) \
|
||||
|| defined(__thumb__) \
|
||||
|| defined(__ARMEL__) \
|
||||
|| defined(__ARMEB__) \
|
||||
|| defined(__THUMBEL__) \
|
||||
|| defined(__THUMBEB__)
|
||||
#define MY_CPU_ARM
|
||||
#define MY_CPU_NAME "arm"
|
||||
#define MY_CPU_32BIT
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_M_IA64) \
|
||||
|| defined(__ia64__)
|
||||
#define MY_CPU_IA64
|
||||
#define MY_CPU_NAME "ia64"
|
||||
#define MY_CPU_64BIT
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__mips64) \
|
||||
|| defined(__mips64__) \
|
||||
|| (defined(__mips) && (__mips == 64 || __mips == 4 || __mips == 3))
|
||||
#define MY_CPU_NAME "mips64"
|
||||
#define MY_CPU_64BIT
|
||||
#elif defined(__mips__)
|
||||
#define MY_CPU_NAME "mips"
|
||||
/* #define MY_CPU_32BIT */
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__ppc64__) \
|
||||
|| defined(__powerpc64__)
|
||||
#ifdef __ILP32__
|
||||
#define MY_CPU_NAME "ppc64-32"
|
||||
#else
|
||||
#define MY_CPU_NAME "ppc64"
|
||||
#endif
|
||||
#define MY_CPU_64BIT
|
||||
#elif defined(__ppc__) \
|
||||
|| defined(__powerpc__)
|
||||
#define MY_CPU_NAME "ppc"
|
||||
#define MY_CPU_32BIT
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__sparc64__)
|
||||
#define MY_CPU_NAME "sparc64"
|
||||
#define MY_CPU_64BIT
|
||||
#elif defined(__sparc__)
|
||||
#define MY_CPU_NAME "sparc"
|
||||
/* #define MY_CPU_32BIT */
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)
|
||||
#define MY_CPU_X86_OR_AMD64
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_X86) || defined(_M_ARM)
|
||||
#define MY_CPU_32BIT
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && defined(_M_ARM)
|
||||
#define MY_CPU_ARM_LE
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
|
||||
#if defined(_WIN32) && defined(_M_IA64)
|
||||
#define MY_CPU_IA64_LE
|
||||
#endif
|
||||
#ifdef MY_CPU_ARM
|
||||
#define MY_CPU_ARM_LE
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_X86_OR_AMD64)
|
||||
#define MY_CPU_LE_UNALIGN
|
||||
#endif
|
||||
#ifdef MY_CPU_ARM64
|
||||
#define MY_CPU_ARM64_LE
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#ifdef _M_IA64
|
||||
#define MY_CPU_IA64_LE
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(MY_CPU_X86_OR_AMD64) \
|
||||
|| defined(MY_CPU_ARM_LE) \
|
||||
|| defined(MY_CPU_ARM64_LE) \
|
||||
|| defined(MY_CPU_IA64_LE) \
|
||||
|| defined(__LITTLE_ENDIAN__) \
|
||||
|| defined(__ARMEL__) \
|
||||
|| defined(__THUMBEL__) \
|
||||
|| defined(__AARCH64EL__) \
|
||||
|| defined(__MIPSEL__) \
|
||||
|| defined(__MIPSEL) \
|
||||
|| defined(_MIPSEL) \
|
||||
|| defined(__BFIN__) \
|
||||
|| (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
|
||||
#define MY_CPU_LE
|
||||
#endif
|
||||
|
||||
#if defined(__BIG_ENDIAN__) \
|
||||
|| defined(__ARMEB__) \
|
||||
|| defined(__THUMBEB__) \
|
||||
|| defined(__AARCH64EB__) \
|
||||
|| defined(__MIPSEB__) \
|
||||
|| defined(__MIPSEB) \
|
||||
|| defined(_MIPSEB) \
|
||||
|| defined(__m68k__) \
|
||||
|| defined(__s390__) \
|
||||
|| defined(__s390x__) \
|
||||
|| defined(__zarch__) \
|
||||
|| (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
||||
#define MY_CPU_BE
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(MY_CPU_LE) && defined(MY_CPU_BE)
|
||||
#error Stop_Compiling_Bad_Endian
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(MY_CPU_32BIT) && defined(MY_CPU_64BIT)
|
||||
#error Stop_Compiling_Bad_32_64_BIT
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef MY_CPU_NAME
|
||||
#ifdef MY_CPU_LE
|
||||
#define MY_CPU_NAME "LE"
|
||||
#elif defined(MY_CPU_BE)
|
||||
#define MY_CPU_NAME "BE"
|
||||
#else
|
||||
/*
|
||||
#define MY_CPU_NAME ""
|
||||
*/
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef MY_CPU_LE
|
||||
#if defined(MY_CPU_X86_OR_AMD64) \
|
||||
|| defined(MY_CPU_ARM64) \
|
||||
|| defined(__ARM_FEATURE_UNALIGNED)
|
||||
#define MY_CPU_LE_UNALIGN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MY_CPU_LE_UNALIGN
|
||||
|
||||
#define GetUi16(p) (*(const uint16_t *)(const void *)(p))
|
||||
#define GetUi32(p) (*(const uint32_t *)(const void *)(p))
|
||||
#define GetUi64(p) (*(const uint64_t *)(const void *)(p))
|
||||
|
||||
#define SetUi16(p, v) { *(uint16_t *)(p) = (v); }
|
||||
#define SetUi32(p, v) { *(uint32_t *)(p) = (v); }
|
||||
#define SetUi64(p, v) { *(uint64_t *)(p) = (v); }
|
||||
|
||||
#else
|
||||
|
||||
#define GetUi16(p) ( (uint16_t) ( \
|
||||
((const Byte *)(p))[0] | \
|
||||
((uint16_t)((const Byte *)(p))[1] << 8) ))
|
||||
|
||||
#define GetUi32(p) ( \
|
||||
((const Byte *)(p))[0] | \
|
||||
((uint32_t)((const Byte *)(p))[1] << 8) | \
|
||||
((uint32_t)((const Byte *)(p))[2] << 16) | \
|
||||
((uint32_t)((const Byte *)(p))[3] << 24))
|
||||
|
||||
#define GetUi64(p) (GetUi32(p) | ((uint64_t)GetUi32(((const Byte *)(p)) + 4) << 32))
|
||||
|
||||
#define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); uint32_t _vvv_ = (v); \
|
||||
_ppp_[0] = (Byte)_vvv_; \
|
||||
_ppp_[1] = (Byte)(_vvv_ >> 8); }
|
||||
|
||||
#define SetUi32(p, v) { Byte *_ppp_ = (Byte *)(p); uint32_t _vvv_ = (v); \
|
||||
_ppp_[0] = (Byte)_vvv_; \
|
||||
_ppp_[1] = (Byte)(_vvv_ >> 8); \
|
||||
_ppp_[2] = (Byte)(_vvv_ >> 16); \
|
||||
_ppp_[3] = (Byte)(_vvv_ >> 24); }
|
||||
|
||||
#define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); uint64_t _vvv2_ = (v); \
|
||||
SetUi32(_ppp2_ , (uint32_t)_vvv2_); \
|
||||
SetUi32(_ppp2_ + 4, (uint32_t)(_vvv2_ >> 32)); }
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __has_builtin
|
||||
#define MY__has_builtin(x) __has_builtin(x)
|
||||
#else
|
||||
#define MY__has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ (_MSC_VER >= 1300)
|
||||
|
||||
/* Note: we use bswap instruction, that is unsupported in 386 cpu */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#pragma intrinsic(_byteswap_ushort)
|
||||
#pragma intrinsic(_byteswap_ulong)
|
||||
#pragma intrinsic(_byteswap_uint64)
|
||||
|
||||
/* #define GetBe16(p) _byteswap_ushort(*(const uint16_t *)(const Byte *)(p)) */
|
||||
#define GetBe32(p) _byteswap_ulong(*(const uint32_t *)(const Byte *)(p))
|
||||
#define GetBe64(p) _byteswap_uint64(*(const uint64_t *)(const Byte *)(p))
|
||||
|
||||
#define SetBe32(p, v) (*(uint32_t *)(void *)(p)) = _byteswap_ulong(v)
|
||||
|
||||
#elif defined(MY_CPU_LE_UNALIGN) && ( \
|
||||
(defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \
|
||||
|| (defined(__clang__) && MY__has_builtin(__builtin_bswap16)) )
|
||||
|
||||
/* #define GetBe16(p) __builtin_bswap16(*(const uint16_t *)(const Byte *)(p)) */
|
||||
#define GetBe32(p) __builtin_bswap32(*(const uint32_t *)(const Byte *)(p))
|
||||
#define GetBe64(p) __builtin_bswap64(*(const uint64_t *)(const Byte *)(p))
|
||||
|
||||
#define SetBe32(p, v) (*(uint32_t *)(void *)(p)) = __builtin_bswap32(v)
|
||||
|
||||
#else
|
||||
|
||||
#define GetBe32(p) ( \
|
||||
((uint32_t)((const Byte *)(p))[0] << 24) | \
|
||||
((uint32_t)((const Byte *)(p))[1] << 16) | \
|
||||
((uint32_t)((const Byte *)(p))[2] << 8) | \
|
||||
((const Byte *)(p))[3] )
|
||||
|
||||
#define GetBe64(p) (((uint64_t)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
|
||||
|
||||
#define SetBe32(p, v) { Byte *_ppp_ = (Byte *)(p); uint32_t _vvv_ = (v); \
|
||||
_ppp_[0] = (Byte)(_vvv_ >> 24); \
|
||||
_ppp_[1] = (Byte)(_vvv_ >> 16); \
|
||||
_ppp_[2] = (Byte)(_vvv_ >> 8); \
|
||||
_ppp_[3] = (Byte)_vvv_; }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef GetBe16
|
||||
|
||||
#define GetBe16(p) ( (uint16_t) ( \
|
||||
((uint16_t)((const Byte *)(p))[0] << 8) | \
|
||||
((const Byte *)(p))[1] ))
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t maxFunc;
|
||||
uint32_t vendor[3];
|
||||
uint32_t ver;
|
||||
uint32_t b;
|
||||
uint32_t c;
|
||||
uint32_t d;
|
||||
} Cx86cpuid;
|
||||
|
||||
enum
|
||||
{
|
||||
CPU_FIRM_INTEL,
|
||||
CPU_FIRM_AMD,
|
||||
CPU_FIRM_VIA
|
||||
};
|
||||
|
||||
void MyCPUID(uint32_t function, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d);
|
||||
|
||||
BoolInt x86cpuid_CheckAndRead(Cx86cpuid *p);
|
||||
int x86cpuid_GetFirm(const Cx86cpuid *p);
|
||||
|
||||
#define x86cpuid_GetFamily(ver) (((ver >> 16) & 0xFF0) | ((ver >> 8) & 0xF))
|
||||
#define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF))
|
||||
#define x86cpuid_GetStepping(ver) (ver & 0xF)
|
||||
|
||||
BoolInt CPU_Is_InOrder(void);
|
||||
BoolInt CPU_Is_Aes_Supported(void);
|
||||
BoolInt CPU_IsSupported_PageGB(void);
|
||||
|
||||
#endif
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
Vendored
+64
@@ -0,0 +1,64 @@
|
||||
/* Delta.c -- Delta converter
|
||||
2009-05-26 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "Delta.h"
|
||||
|
||||
void Delta_Init(Byte *state)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < DELTA_STATE_SIZE; i++)
|
||||
state[i] = 0;
|
||||
}
|
||||
|
||||
static void MyMemCpy(Byte *dest, const Byte *src, unsigned size)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < size; i++)
|
||||
dest[i] = src[i];
|
||||
}
|
||||
|
||||
void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size)
|
||||
{
|
||||
Byte buf[DELTA_STATE_SIZE];
|
||||
unsigned j = 0;
|
||||
MyMemCpy(buf, state, delta);
|
||||
{
|
||||
SizeT i;
|
||||
for (i = 0; i < size;)
|
||||
{
|
||||
for (j = 0; j < delta && i < size; i++, j++)
|
||||
{
|
||||
Byte b = data[i];
|
||||
data[i] = (Byte)(b - buf[j]);
|
||||
buf[j] = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (j == delta)
|
||||
j = 0;
|
||||
MyMemCpy(state, buf + j, delta - j);
|
||||
MyMemCpy(state + delta - j, buf, j);
|
||||
}
|
||||
|
||||
void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size)
|
||||
{
|
||||
Byte buf[DELTA_STATE_SIZE];
|
||||
unsigned j = 0;
|
||||
MyMemCpy(buf, state, delta);
|
||||
{
|
||||
SizeT i;
|
||||
for (i = 0; i < size;)
|
||||
{
|
||||
for (j = 0; j < delta && i < size; i++, j++)
|
||||
{
|
||||
buf[j] = data[i] = (Byte)(buf[j] + data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (j == delta)
|
||||
j = 0;
|
||||
MyMemCpy(state, buf + j, delta - j);
|
||||
MyMemCpy(state + delta - j, buf, j);
|
||||
}
|
||||
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
/* Delta.h -- Delta converter
|
||||
2013-01-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __DELTA_H
|
||||
#define __DELTA_H
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#define DELTA_STATE_SIZE 256
|
||||
|
||||
void Delta_Init(Byte *state);
|
||||
void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size);
|
||||
void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
Vendored
+425
-128
@@ -1,9 +1,9 @@
|
||||
/* LzFind.c -- Match finder for LZ algorithms
|
||||
2015-10-15 : Igor Pavlov : Public domain */
|
||||
2018-07-08 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <boolean.h>
|
||||
|
||||
#include "LzFind.h"
|
||||
#include "LzHash.h"
|
||||
@@ -12,22 +12,22 @@
|
||||
#define kMaxValForNormalize ((uint32_t)0xFFFFFFFF)
|
||||
#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
|
||||
#define kNormalizeMask (~(uint32_t)(kNormalizeStepMin - 1))
|
||||
#define LzFindkMaxHistorySize ((uint32_t)7 << 29)
|
||||
#define kMaxHistorySize ((uint32_t)7 << 29)
|
||||
|
||||
#define kStartMaxLen 3
|
||||
|
||||
static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)
|
||||
static void LzInWindow_Free(CMatchFinder *p, ISzAllocPtr alloc)
|
||||
{
|
||||
if (!p->directInput)
|
||||
{
|
||||
alloc->Free(alloc, p->bufferBase);
|
||||
ISzAlloc_Free(alloc, p->bufferBase);
|
||||
p->bufferBase = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
|
||||
|
||||
static int LzInWindow_Create(CMatchFinder *p, uint32_t keepSizeReserv, ISzAlloc *alloc)
|
||||
static int LzInWindow_Create(CMatchFinder *p, uint32_t keepSizeReserv, ISzAllocPtr alloc)
|
||||
{
|
||||
uint32_t blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
|
||||
if (p->directInput)
|
||||
@@ -39,12 +39,12 @@ static int LzInWindow_Create(CMatchFinder *p, uint32_t keepSizeReserv, ISzAlloc
|
||||
{
|
||||
LzInWindow_Free(p, alloc);
|
||||
p->blockSize = blockSize;
|
||||
p->bufferBase = (unsigned char*)alloc->Alloc(alloc, (size_t)blockSize);
|
||||
p->bufferBase = (Byte *)ISzAlloc_Alloc(alloc, (size_t)blockSize);
|
||||
}
|
||||
return (p->bufferBase != NULL);
|
||||
}
|
||||
|
||||
unsigned char *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
|
||||
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
|
||||
|
||||
uint32_t MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
|
||||
|
||||
@@ -73,15 +73,15 @@ static void MatchFinder_ReadBlock(CMatchFinder *p)
|
||||
p->streamEndWasReached = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for (;;)
|
||||
{
|
||||
unsigned char *dest = p->buffer + (p->streamPos - p->pos);
|
||||
Byte *dest = p->buffer + (p->streamPos - p->pos);
|
||||
size_t size = (p->bufferBase + p->blockSize - dest);
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
p->result = p->stream->Read(p->stream, dest, &size);
|
||||
p->result = ISeqInStream_Read(p->stream, dest, &size);
|
||||
if (p->result != SZ_OK)
|
||||
return;
|
||||
if (size == 0)
|
||||
@@ -138,65 +138,66 @@ static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
|
||||
|
||||
void MatchFinder_Construct(CMatchFinder *p)
|
||||
{
|
||||
uint32_t i;
|
||||
unsigned i;
|
||||
p->bufferBase = NULL;
|
||||
p->directInput = 0;
|
||||
p->hash = NULL;
|
||||
p->expectedDataSize = (uint64_t)(int64_t)-1;
|
||||
MatchFinder_SetDefaultSettings(p);
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
uint32_t r = i;
|
||||
uint32_t r = (uint32_t)i;
|
||||
unsigned j;
|
||||
for (j = 0; j < 8; j++)
|
||||
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
|
||||
r = (r >> 1) ^ (kCrcPoly & ((uint32_t)0 - (r & 1)));
|
||||
p->crc[i] = r;
|
||||
}
|
||||
}
|
||||
|
||||
static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)
|
||||
static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAllocPtr alloc)
|
||||
{
|
||||
alloc->Free(alloc, p->hash);
|
||||
ISzAlloc_Free(alloc, p->hash);
|
||||
p->hash = NULL;
|
||||
}
|
||||
|
||||
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
|
||||
void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc)
|
||||
{
|
||||
MatchFinder_FreeThisClassMemory(p, alloc);
|
||||
LzInWindow_Free(p, alloc);
|
||||
}
|
||||
|
||||
static CLzRef* AllocRefs(size_t num, ISzAlloc *alloc)
|
||||
static CLzRef* AllocRefs(size_t num, ISzAllocPtr alloc)
|
||||
{
|
||||
size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
|
||||
if (sizeInBytes / sizeof(CLzRef) != num)
|
||||
return NULL;
|
||||
return (CLzRef *)alloc->Alloc(alloc, sizeInBytes);
|
||||
return (CLzRef *)ISzAlloc_Alloc(alloc, sizeInBytes);
|
||||
}
|
||||
|
||||
int MatchFinder_Create(CMatchFinder *p, uint32_t historySize,
|
||||
uint32_t keepAddBufferBefore, uint32_t matchMaxLen, uint32_t keepAddBufferAfter,
|
||||
ISzAlloc *alloc)
|
||||
ISzAllocPtr alloc)
|
||||
{
|
||||
uint32_t sizeReserv;
|
||||
|
||||
if (historySize > LzFindkMaxHistorySize)
|
||||
|
||||
if (historySize > kMaxHistorySize)
|
||||
{
|
||||
MatchFinder_Free(p, alloc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
sizeReserv = historySize >> 1;
|
||||
if (historySize >= ((uint32_t)3 << 30)) sizeReserv = historySize >> 3;
|
||||
else if (historySize >= ((uint32_t)2 << 30)) sizeReserv = historySize >> 2;
|
||||
|
||||
|
||||
sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
|
||||
|
||||
p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
|
||||
p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
|
||||
|
||||
|
||||
/* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
|
||||
|
||||
|
||||
if (LzInWindow_Create(p, sizeReserv, alloc))
|
||||
{
|
||||
uint32_t newCyclicBufferSize = historySize + 1;
|
||||
@@ -208,7 +209,11 @@ int MatchFinder_Create(CMatchFinder *p, uint32_t historySize,
|
||||
hs = (1 << 16) - 1;
|
||||
else
|
||||
{
|
||||
hs = historySize - 1;
|
||||
hs = historySize;
|
||||
if (hs > p->expectedDataSize)
|
||||
hs = (uint32_t)p->expectedDataSize;
|
||||
if (hs != 0)
|
||||
hs--;
|
||||
hs |= (hs >> 1);
|
||||
hs |= (hs >> 2);
|
||||
hs |= (hs >> 4);
|
||||
@@ -238,7 +243,7 @@ int MatchFinder_Create(CMatchFinder *p, uint32_t historySize,
|
||||
p->historySize = historySize;
|
||||
p->hashSizeSum = hs;
|
||||
p->cyclicBufferSize = newCyclicBufferSize;
|
||||
|
||||
|
||||
numSons = newCyclicBufferSize;
|
||||
if (p->btMode)
|
||||
numSons <<= 1;
|
||||
@@ -246,11 +251,11 @@ int MatchFinder_Create(CMatchFinder *p, uint32_t historySize,
|
||||
|
||||
if (p->hash && p->numRefs == newSize)
|
||||
return 1;
|
||||
|
||||
|
||||
MatchFinder_FreeThisClassMemory(p, alloc);
|
||||
p->numRefs = newSize;
|
||||
p->hash = AllocRefs(newSize, alloc);
|
||||
|
||||
|
||||
if (p->hash)
|
||||
{
|
||||
p->son = p->hash + p->hashSizeSum;
|
||||
@@ -267,11 +272,11 @@ static void MatchFinder_SetLimits(CMatchFinder *p)
|
||||
{
|
||||
uint32_t limit = kMaxValForNormalize - p->pos;
|
||||
uint32_t limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
|
||||
|
||||
|
||||
if (limit2 < limit)
|
||||
limit = limit2;
|
||||
limit2 = p->streamPos - p->pos;
|
||||
|
||||
|
||||
if (limit2 <= p->keepSizeAfter)
|
||||
{
|
||||
if (limit2 > 0)
|
||||
@@ -279,10 +284,10 @@ static void MatchFinder_SetLimits(CMatchFinder *p)
|
||||
}
|
||||
else
|
||||
limit2 -= p->keepSizeAfter;
|
||||
|
||||
|
||||
if (limit2 < limit)
|
||||
limit = limit2;
|
||||
|
||||
|
||||
{
|
||||
uint32_t lenLimit = p->streamPos - p->pos;
|
||||
if (lenLimit > p->matchMaxLen)
|
||||
@@ -292,31 +297,51 @@ static void MatchFinder_SetLimits(CMatchFinder *p)
|
||||
p->posLimit = p->pos + limit;
|
||||
}
|
||||
|
||||
void MatchFinder_Init_2(CMatchFinder *p, int readData)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t *hash = p->hash;
|
||||
uint32_t num = p->hashSizeSum;
|
||||
for (i = 0; i < num; i++)
|
||||
hash[i] = kEmptyHashValue;
|
||||
|
||||
void MatchFinder_Init_LowHash(CMatchFinder *p)
|
||||
{
|
||||
size_t i;
|
||||
CLzRef *items = p->hash;
|
||||
size_t numItems = p->fixedHashSize;
|
||||
for (i = 0; i < numItems; i++)
|
||||
items[i] = kEmptyHashValue;
|
||||
}
|
||||
|
||||
|
||||
void MatchFinder_Init_HighHash(CMatchFinder *p)
|
||||
{
|
||||
size_t i;
|
||||
CLzRef *items = p->hash + p->fixedHashSize;
|
||||
size_t numItems = (size_t)p->hashMask + 1;
|
||||
for (i = 0; i < numItems; i++)
|
||||
items[i] = kEmptyHashValue;
|
||||
}
|
||||
|
||||
|
||||
void MatchFinder_Init_3(CMatchFinder *p, int readData)
|
||||
{
|
||||
p->cyclicBufferPos = 0;
|
||||
p->buffer = p->bufferBase;
|
||||
p->pos = p->streamPos = p->cyclicBufferSize;
|
||||
p->pos =
|
||||
p->streamPos = p->cyclicBufferSize;
|
||||
p->result = SZ_OK;
|
||||
p->streamEndWasReached = 0;
|
||||
|
||||
|
||||
if (readData)
|
||||
MatchFinder_ReadBlock(p);
|
||||
|
||||
|
||||
MatchFinder_SetLimits(p);
|
||||
}
|
||||
|
||||
|
||||
void MatchFinder_Init(CMatchFinder *p)
|
||||
{
|
||||
MatchFinder_Init_2(p, true);
|
||||
MatchFinder_Init_HighHash(p);
|
||||
MatchFinder_Init_LowHash(p);
|
||||
MatchFinder_Init_3(p, True);
|
||||
}
|
||||
|
||||
|
||||
static uint32_t MatchFinder_GetSubValue(CMatchFinder *p)
|
||||
{
|
||||
return (p->pos - p->historySize - 1) & kNormalizeMask;
|
||||
@@ -343,6 +368,8 @@ static void MatchFinder_Normalize(CMatchFinder *p)
|
||||
MatchFinder_ReduceOffsets(p, subValue);
|
||||
}
|
||||
|
||||
|
||||
MY_NO_INLINE
|
||||
static void MatchFinder_CheckLimits(CMatchFinder *p)
|
||||
{
|
||||
if (p->pos == kMaxValForNormalize)
|
||||
@@ -354,10 +381,16 @@ static void MatchFinder_CheckLimits(CMatchFinder *p)
|
||||
MatchFinder_SetLimits(p);
|
||||
}
|
||||
|
||||
static uint32_t * Hc_GetMatchesSpec(uint32_t lenLimit, uint32_t curMatch, uint32_t pos, const unsigned char *cur, CLzRef *son,
|
||||
|
||||
/*
|
||||
(lenLimit > maxLen)
|
||||
*/
|
||||
MY_FORCE_INLINE
|
||||
static uint32_t * Hc_GetMatchesSpec(unsigned lenLimit, uint32_t curMatch, uint32_t pos, const Byte *cur, CLzRef *son,
|
||||
uint32_t _cyclicBufferPos, uint32_t _cyclicBufferSize, uint32_t cutValue,
|
||||
uint32_t *distances, uint32_t maxLen)
|
||||
uint32_t *distances, unsigned maxLen)
|
||||
{
|
||||
/*
|
||||
son[_cyclicBufferPos] = curMatch;
|
||||
for (;;)
|
||||
{
|
||||
@@ -365,7 +398,7 @@ static uint32_t * Hc_GetMatchesSpec(uint32_t lenLimit, uint32_t curMatch, uint32
|
||||
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
|
||||
return distances;
|
||||
{
|
||||
const unsigned char *pb = cur - delta;
|
||||
const Byte *pb = cur - delta;
|
||||
curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
|
||||
if (pb[maxLen] == cur[maxLen] && *pb == *cur)
|
||||
{
|
||||
@@ -375,7 +408,8 @@ static uint32_t * Hc_GetMatchesSpec(uint32_t lenLimit, uint32_t curMatch, uint32
|
||||
break;
|
||||
if (maxLen < len)
|
||||
{
|
||||
*distances++ = maxLen = len;
|
||||
maxLen = len;
|
||||
*distances++ = len;
|
||||
*distances++ = delta - 1;
|
||||
if (len == lenLimit)
|
||||
return distances;
|
||||
@@ -383,15 +417,58 @@ static uint32_t * Hc_GetMatchesSpec(uint32_t lenLimit, uint32_t curMatch, uint32
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
const Byte *lim = cur + lenLimit;
|
||||
son[_cyclicBufferPos] = curMatch;
|
||||
do
|
||||
{
|
||||
uint32_t delta = pos - curMatch;
|
||||
if (delta >= _cyclicBufferSize)
|
||||
break;
|
||||
{
|
||||
ptrdiff_t diff;
|
||||
curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
|
||||
diff = (ptrdiff_t)0 - delta;
|
||||
if (cur[maxLen] == cur[maxLen + diff])
|
||||
{
|
||||
const Byte *c = cur;
|
||||
while (*c == c[diff])
|
||||
{
|
||||
if (++c == lim)
|
||||
{
|
||||
distances[0] = (uint32_t)(lim - cur);
|
||||
distances[1] = delta - 1;
|
||||
return distances + 2;
|
||||
}
|
||||
}
|
||||
{
|
||||
unsigned len = (unsigned)(c - cur);
|
||||
if (maxLen < len)
|
||||
{
|
||||
maxLen = len;
|
||||
distances[0] = (uint32_t)len;
|
||||
distances[1] = delta - 1;
|
||||
distances += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (--cutValue);
|
||||
|
||||
return distances;
|
||||
}
|
||||
|
||||
uint32_t * GetMatchesSpec1(uint32_t lenLimit, uint32_t curMatch, uint32_t pos, const unsigned char *cur, CLzRef *son,
|
||||
|
||||
MY_FORCE_INLINE
|
||||
uint32_t * GetMatchesSpec1(uint32_t lenLimit, uint32_t curMatch, uint32_t pos, const Byte *cur, CLzRef *son,
|
||||
uint32_t _cyclicBufferPos, uint32_t _cyclicBufferSize, uint32_t cutValue,
|
||||
uint32_t *distances, uint32_t maxLen)
|
||||
{
|
||||
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
|
||||
CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
|
||||
uint32_t len0 = 0, len1 = 0;
|
||||
CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;
|
||||
CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
|
||||
unsigned len0 = 0, len1 = 0;
|
||||
for (;;)
|
||||
{
|
||||
uint32_t delta = pos - curMatch;
|
||||
@@ -401,9 +478,10 @@ uint32_t * GetMatchesSpec1(uint32_t lenLimit, uint32_t curMatch, uint32_t pos, c
|
||||
return distances;
|
||||
}
|
||||
{
|
||||
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
|
||||
const unsigned char *pb = cur - delta;
|
||||
uint32_t len = (len0 < len1 ? len0 : len1);
|
||||
CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
|
||||
const Byte *pb = cur - delta;
|
||||
unsigned len = (len0 < len1 ? len0 : len1);
|
||||
uint32_t pair0 = pair[0];
|
||||
if (pb[len] == cur[len])
|
||||
{
|
||||
if (++len != lenLimit && pb[len] == cur[len])
|
||||
@@ -412,11 +490,12 @@ uint32_t * GetMatchesSpec1(uint32_t lenLimit, uint32_t curMatch, uint32_t pos, c
|
||||
break;
|
||||
if (maxLen < len)
|
||||
{
|
||||
*distances++ = maxLen = len;
|
||||
maxLen = (uint32_t)len;
|
||||
*distances++ = (uint32_t)len;
|
||||
*distances++ = delta - 1;
|
||||
if (len == lenLimit)
|
||||
{
|
||||
*ptr1 = pair[0];
|
||||
*ptr1 = pair0;
|
||||
*ptr0 = pair[1];
|
||||
return distances;
|
||||
}
|
||||
@@ -440,12 +519,12 @@ uint32_t * GetMatchesSpec1(uint32_t lenLimit, uint32_t curMatch, uint32_t pos, c
|
||||
}
|
||||
}
|
||||
|
||||
static void SkipMatchesSpec(uint32_t lenLimit, uint32_t curMatch, uint32_t pos, const unsigned char *cur, CLzRef *son,
|
||||
static void SkipMatchesSpec(uint32_t lenLimit, uint32_t curMatch, uint32_t pos, const Byte *cur, CLzRef *son,
|
||||
uint32_t _cyclicBufferPos, uint32_t _cyclicBufferSize, uint32_t cutValue)
|
||||
{
|
||||
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
|
||||
CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
|
||||
uint32_t len0 = 0, len1 = 0;
|
||||
CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;
|
||||
CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
|
||||
unsigned len0 = 0, len1 = 0;
|
||||
for (;;)
|
||||
{
|
||||
uint32_t delta = pos - curMatch;
|
||||
@@ -455,9 +534,9 @@ static void SkipMatchesSpec(uint32_t lenLimit, uint32_t curMatch, uint32_t pos,
|
||||
return;
|
||||
}
|
||||
{
|
||||
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
|
||||
const unsigned char *pb = cur - delta;
|
||||
uint32_t len = (len0 < len1 ? len0 : len1);
|
||||
CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
|
||||
const Byte *pb = cur - delta;
|
||||
unsigned len = (len0 < len1 ? len0 : len1);
|
||||
if (pb[len] == cur[len])
|
||||
{
|
||||
while (++len != lenLimit)
|
||||
@@ -495,13 +574,13 @@ static void SkipMatchesSpec(uint32_t lenLimit, uint32_t curMatch, uint32_t pos,
|
||||
p->buffer++; \
|
||||
if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
|
||||
|
||||
#define MOVE_POS_RET MOVE_POS return offset;
|
||||
#define MOVE_POS_RET MOVE_POS return (uint32_t)offset;
|
||||
|
||||
static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
|
||||
|
||||
#define GET_MATCHES_HEADER2(minLen, ret_op) \
|
||||
uint32_t lenLimit; uint32_t hv; const unsigned char *cur; uint32_t curMatch; \
|
||||
lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
|
||||
unsigned lenLimit; uint32_t hv; const Byte *cur; uint32_t curMatch; \
|
||||
lenLimit = (unsigned)p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
|
||||
cur = p->buffer;
|
||||
|
||||
#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
|
||||
@@ -510,22 +589,22 @@ static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
|
||||
#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
|
||||
|
||||
#define GET_MATCHES_FOOTER(offset, maxLen) \
|
||||
offset = (uint32_t)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \
|
||||
distances + offset, maxLen) - distances); MOVE_POS_RET;
|
||||
offset = (unsigned)(GetMatchesSpec1((uint32_t)lenLimit, curMatch, MF_PARAMS(p), \
|
||||
distances + offset, (uint32_t)maxLen) - distances); MOVE_POS_RET;
|
||||
|
||||
#define SKIP_FOOTER \
|
||||
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
|
||||
SkipMatchesSpec((uint32_t)lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
|
||||
|
||||
#define UPDATE_maxLen { \
|
||||
ptrdiff_t diff = (ptrdiff_t)0 - d2; \
|
||||
const unsigned char *c = cur + maxLen; \
|
||||
const unsigned char *lim = cur + lenLimit; \
|
||||
const Byte *c = cur + maxLen; \
|
||||
const Byte *lim = cur + lenLimit; \
|
||||
for (; c != lim; c++) if (*(c + diff) != *c) break; \
|
||||
maxLen = (uint32_t)(c - cur); }
|
||||
maxLen = (unsigned)(c - cur); }
|
||||
|
||||
static uint32_t Bt2_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances)
|
||||
{
|
||||
uint32_t offset;
|
||||
unsigned offset;
|
||||
GET_MATCHES_HEADER(2)
|
||||
HASH2_CALC;
|
||||
curMatch = p->hash[hv];
|
||||
@@ -536,7 +615,7 @@ static uint32_t Bt2_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances)
|
||||
|
||||
uint32_t Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances)
|
||||
{
|
||||
uint32_t offset;
|
||||
unsigned offset;
|
||||
GET_MATCHES_HEADER(3)
|
||||
HASH_ZIP_CALC;
|
||||
curMatch = p->hash[hv];
|
||||
@@ -547,7 +626,8 @@ uint32_t Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances)
|
||||
|
||||
static uint32_t Bt3_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances)
|
||||
{
|
||||
uint32_t h2, d2, maxLen, offset, pos;
|
||||
uint32_t h2, d2, pos;
|
||||
unsigned maxLen, offset;
|
||||
uint32_t *hash;
|
||||
GET_MATCHES_HEADER(3)
|
||||
|
||||
@@ -558,10 +638,10 @@ static uint32_t Bt3_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances)
|
||||
|
||||
d2 = pos - hash[h2];
|
||||
|
||||
curMatch = hash[kFix3HashSize + hv];
|
||||
|
||||
curMatch = (hash + kFix3HashSize)[hv];
|
||||
|
||||
hash[h2] = pos;
|
||||
hash[kFix3HashSize + hv] = pos;
|
||||
(hash + kFix3HashSize)[hv] = pos;
|
||||
|
||||
maxLen = 2;
|
||||
offset = 0;
|
||||
@@ -569,22 +649,23 @@ static uint32_t Bt3_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances)
|
||||
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
|
||||
{
|
||||
UPDATE_maxLen
|
||||
distances[0] = maxLen;
|
||||
distances[0] = (uint32_t)maxLen;
|
||||
distances[1] = d2 - 1;
|
||||
offset = 2;
|
||||
if (maxLen == lenLimit)
|
||||
{
|
||||
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
|
||||
SkipMatchesSpec((uint32_t)lenLimit, curMatch, MF_PARAMS(p));
|
||||
MOVE_POS_RET;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GET_MATCHES_FOOTER(offset, maxLen)
|
||||
}
|
||||
|
||||
static uint32_t Bt4_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances)
|
||||
{
|
||||
uint32_t h2, h3, d2, d3, maxLen, offset, pos;
|
||||
uint32_t h2, h3, d2, d3, pos;
|
||||
unsigned maxLen, offset;
|
||||
uint32_t *hash;
|
||||
GET_MATCHES_HEADER(4)
|
||||
|
||||
@@ -593,14 +674,73 @@ static uint32_t Bt4_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances)
|
||||
hash = p->hash;
|
||||
pos = p->pos;
|
||||
|
||||
d2 = pos - hash[ h2];
|
||||
d3 = pos - hash[kFix3HashSize + h3];
|
||||
d2 = pos - hash [h2];
|
||||
d3 = pos - (hash + kFix3HashSize)[h3];
|
||||
|
||||
curMatch = hash[kFix4HashSize + hv];
|
||||
curMatch = (hash + kFix4HashSize)[hv];
|
||||
|
||||
hash[ h2] = pos;
|
||||
hash[kFix3HashSize + h3] = pos;
|
||||
hash[kFix4HashSize + hv] = pos;
|
||||
hash [h2] = pos;
|
||||
(hash + kFix3HashSize)[h3] = pos;
|
||||
(hash + kFix4HashSize)[hv] = pos;
|
||||
|
||||
maxLen = 0;
|
||||
offset = 0;
|
||||
|
||||
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
|
||||
{
|
||||
maxLen = 2;
|
||||
distances[0] = 2;
|
||||
distances[1] = d2 - 1;
|
||||
offset = 2;
|
||||
}
|
||||
|
||||
if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
|
||||
{
|
||||
maxLen = 3;
|
||||
distances[(size_t)offset + 1] = d3 - 1;
|
||||
offset += 2;
|
||||
d2 = d3;
|
||||
}
|
||||
|
||||
if (offset != 0)
|
||||
{
|
||||
UPDATE_maxLen
|
||||
distances[(size_t)offset - 2] = (uint32_t)maxLen;
|
||||
if (maxLen == lenLimit)
|
||||
{
|
||||
SkipMatchesSpec((uint32_t)lenLimit, curMatch, MF_PARAMS(p));
|
||||
MOVE_POS_RET;
|
||||
}
|
||||
}
|
||||
|
||||
if (maxLen < 3)
|
||||
maxLen = 3;
|
||||
|
||||
GET_MATCHES_FOOTER(offset, maxLen)
|
||||
}
|
||||
|
||||
/*
|
||||
static uint32_t Bt5_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances)
|
||||
{
|
||||
uint32_t h2, h3, h4, d2, d3, d4, maxLen, offset, pos;
|
||||
uint32_t *hash;
|
||||
GET_MATCHES_HEADER(5)
|
||||
|
||||
HASH5_CALC;
|
||||
|
||||
hash = p->hash;
|
||||
pos = p->pos;
|
||||
|
||||
d2 = pos - hash [h2];
|
||||
d3 = pos - (hash + kFix3HashSize)[h3];
|
||||
d4 = pos - (hash + kFix4HashSize)[h4];
|
||||
|
||||
curMatch = (hash + kFix5HashSize)[hv];
|
||||
|
||||
hash [h2] = pos;
|
||||
(hash + kFix3HashSize)[h3] = pos;
|
||||
(hash + kFix4HashSize)[h4] = pos;
|
||||
(hash + kFix5HashSize)[hv] = pos;
|
||||
|
||||
maxLen = 0;
|
||||
offset = 0;
|
||||
@@ -610,20 +750,38 @@ static uint32_t Bt4_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances)
|
||||
distances[0] = maxLen = 2;
|
||||
distances[1] = d2 - 1;
|
||||
offset = 2;
|
||||
if (*(cur - d2 + 2) == cur[2])
|
||||
distances[0] = maxLen = 3;
|
||||
else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
|
||||
{
|
||||
distances[2] = maxLen = 3;
|
||||
distances[3] = d3 - 1;
|
||||
offset = 4;
|
||||
d2 = d3;
|
||||
}
|
||||
}
|
||||
|
||||
if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
|
||||
else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
|
||||
{
|
||||
maxLen = 3;
|
||||
distances[offset + 1] = d3 - 1;
|
||||
offset += 2;
|
||||
distances[0] = maxLen = 3;
|
||||
distances[1] = d3 - 1;
|
||||
offset = 2;
|
||||
d2 = d3;
|
||||
}
|
||||
|
||||
|
||||
if (d2 != d4 && d4 < p->cyclicBufferSize
|
||||
&& *(cur - d4) == *cur
|
||||
&& *(cur - d4 + 3) == *(cur + 3))
|
||||
{
|
||||
maxLen = 4;
|
||||
distances[(size_t)offset + 1] = d4 - 1;
|
||||
offset += 2;
|
||||
d2 = d4;
|
||||
}
|
||||
|
||||
if (offset != 0)
|
||||
{
|
||||
UPDATE_maxLen
|
||||
distances[offset - 2] = maxLen;
|
||||
distances[(size_t)offset - 2] = maxLen;
|
||||
if (maxLen == lenLimit)
|
||||
{
|
||||
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
|
||||
@@ -631,15 +789,17 @@ static uint32_t Bt4_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances)
|
||||
}
|
||||
}
|
||||
|
||||
if (maxLen < 3)
|
||||
maxLen = 3;
|
||||
|
||||
if (maxLen < 4)
|
||||
maxLen = 4;
|
||||
|
||||
GET_MATCHES_FOOTER(offset, maxLen)
|
||||
}
|
||||
*/
|
||||
|
||||
static uint32_t Hc4_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances)
|
||||
{
|
||||
uint32_t h2, h3, d2, d3, maxLen, offset, pos;
|
||||
uint32_t h2, h3, d2, d3, pos;
|
||||
unsigned maxLen, offset;
|
||||
uint32_t *hash;
|
||||
GET_MATCHES_HEADER(4)
|
||||
|
||||
@@ -647,61 +807,140 @@ static uint32_t Hc4_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances)
|
||||
|
||||
hash = p->hash;
|
||||
pos = p->pos;
|
||||
|
||||
d2 = pos - hash [h2];
|
||||
d3 = pos - (hash + kFix3HashSize)[h3];
|
||||
curMatch = (hash + kFix4HashSize)[hv];
|
||||
|
||||
d2 = pos - hash[ h2];
|
||||
d3 = pos - hash[kFix3HashSize + h3];
|
||||
|
||||
curMatch = hash[kFix4HashSize + hv];
|
||||
|
||||
hash[ h2] = pos;
|
||||
hash[kFix3HashSize + h3] = pos;
|
||||
hash[kFix4HashSize + hv] = pos;
|
||||
hash [h2] = pos;
|
||||
(hash + kFix3HashSize)[h3] = pos;
|
||||
(hash + kFix4HashSize)[hv] = pos;
|
||||
|
||||
maxLen = 0;
|
||||
offset = 0;
|
||||
|
||||
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
|
||||
{
|
||||
distances[0] = maxLen = 2;
|
||||
maxLen = 2;
|
||||
distances[0] = 2;
|
||||
distances[1] = d2 - 1;
|
||||
offset = 2;
|
||||
}
|
||||
|
||||
|
||||
if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
|
||||
{
|
||||
maxLen = 3;
|
||||
distances[offset + 1] = d3 - 1;
|
||||
distances[(size_t)offset + 1] = d3 - 1;
|
||||
offset += 2;
|
||||
d2 = d3;
|
||||
}
|
||||
|
||||
|
||||
if (offset != 0)
|
||||
{
|
||||
UPDATE_maxLen
|
||||
distances[offset - 2] = maxLen;
|
||||
distances[(size_t)offset - 2] = (uint32_t)maxLen;
|
||||
if (maxLen == lenLimit)
|
||||
{
|
||||
p->son[p->cyclicBufferPos] = curMatch;
|
||||
MOVE_POS_RET;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (maxLen < 3)
|
||||
maxLen = 3;
|
||||
|
||||
offset = (unsigned)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
|
||||
distances + offset, maxLen) - (distances));
|
||||
MOVE_POS_RET
|
||||
}
|
||||
|
||||
/*
|
||||
static uint32_t Hc5_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances)
|
||||
{
|
||||
uint32_t h2, h3, h4, d2, d3, d4, maxLen, offset, pos
|
||||
uint32_t *hash;
|
||||
GET_MATCHES_HEADER(5)
|
||||
|
||||
HASH5_CALC;
|
||||
|
||||
hash = p->hash;
|
||||
pos = p->pos;
|
||||
|
||||
d2 = pos - hash [h2];
|
||||
d3 = pos - (hash + kFix3HashSize)[h3];
|
||||
d4 = pos - (hash + kFix4HashSize)[h4];
|
||||
|
||||
curMatch = (hash + kFix5HashSize)[hv];
|
||||
|
||||
hash [h2] = pos;
|
||||
(hash + kFix3HashSize)[h3] = pos;
|
||||
(hash + kFix4HashSize)[h4] = pos;
|
||||
(hash + kFix5HashSize)[hv] = pos;
|
||||
|
||||
maxLen = 0;
|
||||
offset = 0;
|
||||
|
||||
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
|
||||
{
|
||||
distances[0] = maxLen = 2;
|
||||
distances[1] = d2 - 1;
|
||||
offset = 2;
|
||||
if (*(cur - d2 + 2) == cur[2])
|
||||
distances[0] = maxLen = 3;
|
||||
else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
|
||||
{
|
||||
distances[2] = maxLen = 3;
|
||||
distances[3] = d3 - 1;
|
||||
offset = 4;
|
||||
d2 = d3;
|
||||
}
|
||||
}
|
||||
else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur)
|
||||
{
|
||||
distances[0] = maxLen = 3;
|
||||
distances[1] = d3 - 1;
|
||||
offset = 2;
|
||||
d2 = d3;
|
||||
}
|
||||
|
||||
if (d2 != d4 && d4 < p->cyclicBufferSize
|
||||
&& *(cur - d4) == *cur
|
||||
&& *(cur - d4 + 3) == *(cur + 3))
|
||||
{
|
||||
maxLen = 4;
|
||||
distances[(size_t)offset + 1] = d4 - 1;
|
||||
offset += 2;
|
||||
d2 = d4;
|
||||
}
|
||||
|
||||
if (offset != 0)
|
||||
{
|
||||
UPDATE_maxLen
|
||||
distances[(size_t)offset - 2] = maxLen;
|
||||
if (maxLen == lenLimit)
|
||||
{
|
||||
p->son[p->cyclicBufferPos] = curMatch;
|
||||
MOVE_POS_RET;
|
||||
}
|
||||
}
|
||||
|
||||
if (maxLen < 4)
|
||||
maxLen = 4;
|
||||
|
||||
offset = (uint32_t)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
|
||||
distances + offset, maxLen) - (distances));
|
||||
MOVE_POS_RET
|
||||
}
|
||||
*/
|
||||
|
||||
uint32_t Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances)
|
||||
{
|
||||
uint32_t offset;
|
||||
unsigned offset;
|
||||
GET_MATCHES_HEADER(3)
|
||||
HASH_ZIP_CALC;
|
||||
curMatch = p->hash[hv];
|
||||
p->hash[hv] = p->pos;
|
||||
offset = (uint32_t)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
|
||||
offset = (unsigned)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
|
||||
distances, 2) - (distances));
|
||||
MOVE_POS_RET
|
||||
}
|
||||
@@ -741,9 +980,9 @@ static void Bt3_MatchFinder_Skip(CMatchFinder *p, uint32_t num)
|
||||
SKIP_HEADER(3)
|
||||
HASH3_CALC;
|
||||
hash = p->hash;
|
||||
curMatch = hash[kFix3HashSize + hv];
|
||||
curMatch = (hash + kFix3HashSize)[hv];
|
||||
hash[h2] =
|
||||
hash[kFix3HashSize + hv] = p->pos;
|
||||
(hash + kFix3HashSize)[hv] = p->pos;
|
||||
SKIP_FOOTER
|
||||
}
|
||||
while (--num != 0);
|
||||
@@ -758,15 +997,36 @@ static void Bt4_MatchFinder_Skip(CMatchFinder *p, uint32_t num)
|
||||
SKIP_HEADER(4)
|
||||
HASH4_CALC;
|
||||
hash = p->hash;
|
||||
curMatch = hash[kFix4HashSize + hv];
|
||||
hash[ h2] =
|
||||
hash[kFix3HashSize + h3] =
|
||||
hash[kFix4HashSize + hv] = p->pos;
|
||||
curMatch = (hash + kFix4HashSize)[hv];
|
||||
hash [h2] =
|
||||
(hash + kFix3HashSize)[h3] =
|
||||
(hash + kFix4HashSize)[hv] = p->pos;
|
||||
SKIP_FOOTER
|
||||
}
|
||||
while (--num != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
static void Bt5_MatchFinder_Skip(CMatchFinder *p, uint32_t num)
|
||||
{
|
||||
do
|
||||
{
|
||||
uint32_t h2, h3, h4;
|
||||
uint32_t *hash;
|
||||
SKIP_HEADER(5)
|
||||
HASH5_CALC;
|
||||
hash = p->hash;
|
||||
curMatch = (hash + kFix5HashSize)[hv];
|
||||
hash [h2] =
|
||||
(hash + kFix3HashSize)[h3] =
|
||||
(hash + kFix4HashSize)[h4] =
|
||||
(hash + kFix5HashSize)[hv] = p->pos;
|
||||
SKIP_FOOTER
|
||||
}
|
||||
while (--num != 0);
|
||||
}
|
||||
*/
|
||||
|
||||
static void Hc4_MatchFinder_Skip(CMatchFinder *p, uint32_t num)
|
||||
{
|
||||
do
|
||||
@@ -776,16 +1036,38 @@ static void Hc4_MatchFinder_Skip(CMatchFinder *p, uint32_t num)
|
||||
SKIP_HEADER(4)
|
||||
HASH4_CALC;
|
||||
hash = p->hash;
|
||||
curMatch = hash[kFix4HashSize + hv];
|
||||
hash[ h2] =
|
||||
hash[kFix3HashSize + h3] =
|
||||
hash[kFix4HashSize + hv] = p->pos;
|
||||
curMatch = (hash + kFix4HashSize)[hv];
|
||||
hash [h2] =
|
||||
(hash + kFix3HashSize)[h3] =
|
||||
(hash + kFix4HashSize)[hv] = p->pos;
|
||||
p->son[p->cyclicBufferPos] = curMatch;
|
||||
MOVE_POS
|
||||
}
|
||||
while (--num != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
static void Hc5_MatchFinder_Skip(CMatchFinder *p, uint32_t num)
|
||||
{
|
||||
do
|
||||
{
|
||||
uint32_t h2, h3, h4;
|
||||
uint32_t *hash;
|
||||
SKIP_HEADER(5)
|
||||
HASH5_CALC;
|
||||
hash = p->hash;
|
||||
curMatch = hash + kFix5HashSize)[hv];
|
||||
hash [h2] =
|
||||
(hash + kFix3HashSize)[h3] =
|
||||
(hash + kFix4HashSize)[h4] =
|
||||
(hash + kFix5HashSize)[hv] = p->pos;
|
||||
p->son[p->cyclicBufferPos] = curMatch;
|
||||
MOVE_POS
|
||||
}
|
||||
while (--num != 0);
|
||||
}
|
||||
*/
|
||||
|
||||
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, uint32_t num)
|
||||
{
|
||||
do
|
||||
@@ -807,10 +1089,18 @@ void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
|
||||
vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
|
||||
if (!p->btMode)
|
||||
{
|
||||
/* if (p->numHashBytes <= 4) */
|
||||
{
|
||||
vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
|
||||
vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
vTable->GetMatches = (Mf_GetMatches_Func)Hc5_MatchFinder_GetMatches;
|
||||
vTable->Skip = (Mf_Skip_Func)Hc5_MatchFinder_Skip;
|
||||
}
|
||||
*/
|
||||
}
|
||||
else if (p->numHashBytes == 2)
|
||||
{
|
||||
@@ -827,4 +1117,11 @@ void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
|
||||
vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
|
||||
vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
vTable->GetMatches = (Mf_GetMatches_Func)Bt5_MatchFinder_GetMatches;
|
||||
vTable->Skip = (Mf_Skip_Func)Bt5_MatchFinder_Skip;
|
||||
}
|
||||
*/
|
||||
}
|
||||
Vendored
+19
-15
@@ -1,5 +1,5 @@
|
||||
/* LzFind.h -- Match finder for LZ algorithms
|
||||
2015-10-15 : Igor Pavlov : Public domain */
|
||||
2017-06-10 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZ_FIND_H
|
||||
#define __LZ_FIND_H
|
||||
@@ -12,7 +12,7 @@ typedef uint32_t CLzRef;
|
||||
|
||||
typedef struct _CMatchFinder
|
||||
{
|
||||
unsigned char *buffer;
|
||||
Byte *buffer;
|
||||
uint32_t pos;
|
||||
uint32_t posLimit;
|
||||
uint32_t streamPos;
|
||||
@@ -21,10 +21,10 @@ typedef struct _CMatchFinder
|
||||
uint32_t cyclicBufferPos;
|
||||
uint32_t cyclicBufferSize; /* it must be = (historySize + 1) */
|
||||
|
||||
unsigned char streamEndWasReached;
|
||||
unsigned char btMode;
|
||||
unsigned char bigHash;
|
||||
unsigned char directInput;
|
||||
Byte streamEndWasReached;
|
||||
Byte btMode;
|
||||
Byte bigHash;
|
||||
Byte directInput;
|
||||
|
||||
uint32_t matchMaxLen;
|
||||
CLzRef *hash;
|
||||
@@ -32,9 +32,9 @@ typedef struct _CMatchFinder
|
||||
uint32_t hashMask;
|
||||
uint32_t cutValue;
|
||||
|
||||
unsigned char *bufferBase;
|
||||
Byte *bufferBase;
|
||||
ISeqInStream *stream;
|
||||
|
||||
|
||||
uint32_t blockSize;
|
||||
uint32_t keepSizeBefore;
|
||||
uint32_t keepSizeAfter;
|
||||
@@ -47,6 +47,8 @@ typedef struct _CMatchFinder
|
||||
SRes result;
|
||||
uint32_t crc[256];
|
||||
size_t numRefs;
|
||||
|
||||
uint64_t expectedDataSize;
|
||||
} CMatchFinder;
|
||||
|
||||
#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
|
||||
@@ -57,9 +59,9 @@ typedef struct _CMatchFinder
|
||||
((p)->streamEndWasReached \
|
||||
&& (p)->streamPos == (p)->pos \
|
||||
&& (!(p)->directInput || (p)->directInputRem == 0))
|
||||
|
||||
|
||||
int MatchFinder_NeedMove(CMatchFinder *p);
|
||||
unsigned char *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
|
||||
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
|
||||
void MatchFinder_MoveBlock(CMatchFinder *p);
|
||||
void MatchFinder_ReadIfRequired(CMatchFinder *p);
|
||||
|
||||
@@ -71,12 +73,12 @@ void MatchFinder_Construct(CMatchFinder *p);
|
||||
*/
|
||||
int MatchFinder_Create(CMatchFinder *p, uint32_t historySize,
|
||||
uint32_t keepAddBufferBefore, uint32_t matchMaxLen, uint32_t keepAddBufferAfter,
|
||||
ISzAlloc *alloc);
|
||||
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
|
||||
ISzAllocPtr alloc);
|
||||
void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc);
|
||||
void MatchFinder_Normalize3(uint32_t subValue, CLzRef *items, size_t numItems);
|
||||
void MatchFinder_ReduceOffsets(CMatchFinder *p, uint32_t subValue);
|
||||
|
||||
uint32_t * GetMatchesSpec1(uint32_t lenLimit, uint32_t curMatch, uint32_t pos, const unsigned char *buffer, CLzRef *son,
|
||||
uint32_t * GetMatchesSpec1(uint32_t lenLimit, uint32_t curMatch, uint32_t pos, const Byte *buffer, CLzRef *son,
|
||||
uint32_t _cyclicBufferPos, uint32_t _cyclicBufferSize, uint32_t _cutValue,
|
||||
uint32_t *distances, uint32_t maxLen);
|
||||
|
||||
@@ -88,7 +90,7 @@ Conditions:
|
||||
|
||||
typedef void (*Mf_Init_Func)(void *object);
|
||||
typedef uint32_t (*Mf_GetNumAvailableBytes_Func)(void *object);
|
||||
typedef const unsigned char * (*Mf_GetPointerToCurrentPos_Func)(void *object);
|
||||
typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
|
||||
typedef uint32_t (*Mf_GetMatches_Func)(void *object, uint32_t *distances);
|
||||
typedef void (*Mf_Skip_Func)(void *object, uint32_t);
|
||||
|
||||
@@ -103,7 +105,9 @@ typedef struct _IMatchFinder
|
||||
|
||||
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
|
||||
|
||||
void MatchFinder_Init_2(CMatchFinder *p, int readData);
|
||||
void MatchFinder_Init_LowHash(CMatchFinder *p);
|
||||
void MatchFinder_Init_HighHash(CMatchFinder *p);
|
||||
void MatchFinder_Init_3(CMatchFinder *p, int readData);
|
||||
void MatchFinder_Init(CMatchFinder *p);
|
||||
|
||||
uint32_t Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances);
|
||||
|
||||
Vendored
+1
@@ -35,6 +35,7 @@
|
||||
h4 = temp & (kHash4Size - 1); \
|
||||
hv = (temp ^ (p->crc[cur[4]] << 3)) & p->hashMask; }
|
||||
|
||||
/* #define HASH_ZIP_CALC hv = ((cur[0] | ((uint32_t)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
|
||||
#define HASH_ZIP_CALC hv = ((cur[2] | ((uint32_t)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
|
||||
|
||||
|
||||
|
||||
Vendored
+438
-307
@@ -1,357 +1,488 @@
|
||||
/* Lzma2Dec.c -- LZMA2 Decoder
|
||||
2009-05-03 : Igor Pavlov : Public domain */
|
||||
2019-02-02 : Igor Pavlov : Public domain */
|
||||
|
||||
/* #define SHOW_DEBUG_INFO */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#ifdef SHOW_DEBUG_INFO
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "Lzma2Dec.h"
|
||||
|
||||
/*
|
||||
00000000 - EOS
|
||||
00000001 U U - Uncompressed Reset Dic
|
||||
00000010 U U - Uncompressed No Reset
|
||||
100uuuuu U U P P - LZMA no reset
|
||||
101uuuuu U U P P - LZMA reset state
|
||||
110uuuuu U U P P S - LZMA reset state + new prop
|
||||
111uuuuu U U P P S - LZMA reset state + new prop + reset dic
|
||||
00000000 - End of data
|
||||
00000001 U U - Uncompressed, reset dic, need reset state and set new prop
|
||||
00000010 U U - Uncompressed, no reset
|
||||
100uuuuu U U P P - LZMA, no reset
|
||||
101uuuuu U U P P - LZMA, reset state
|
||||
110uuuuu U U P P S - LZMA, reset state + set new prop
|
||||
111uuuuu U U P P S - LZMA, reset state + set new prop, reset dic
|
||||
|
||||
u, U - Unpack Size
|
||||
P - Pack Size
|
||||
S - Props
|
||||
*/
|
||||
u, U - Unpack Size
|
||||
P - Pack Size
|
||||
S - Props
|
||||
*/
|
||||
|
||||
#define LZMA2_CONTROL_LZMA (1 << 7)
|
||||
#define LZMA2_CONTROL_COPY_NO_RESET 2
|
||||
#define LZMA2_CONTROL_COPY_RESET_DIC 1
|
||||
#define LZMA2_CONTROL_EOF 0
|
||||
|
||||
#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)
|
||||
|
||||
#define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)
|
||||
#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)
|
||||
#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & (1 << 7)) == 0)
|
||||
|
||||
#define LZMA2_LCLP_MAX 4
|
||||
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((uint32_t)2 | ((p) & 1)) << ((p) / 2 + 11))
|
||||
|
||||
#ifdef SHOW_DEBUG_INFO
|
||||
#define PRF(x) x
|
||||
#else
|
||||
#define PRF(x)
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LZMA2_STATE_CONTROL,
|
||||
LZMA2_STATE_UNPACK0,
|
||||
LZMA2_STATE_UNPACK1,
|
||||
LZMA2_STATE_PACK0,
|
||||
LZMA2_STATE_PACK1,
|
||||
LZMA2_STATE_PROP,
|
||||
LZMA2_STATE_DATA,
|
||||
LZMA2_STATE_DATA_CONT,
|
||||
LZMA2_STATE_FINISHED,
|
||||
LZMA2_STATE_ERROR
|
||||
LZMA2_STATE_CONTROL,
|
||||
LZMA2_STATE_UNPACK0,
|
||||
LZMA2_STATE_UNPACK1,
|
||||
LZMA2_STATE_PACK0,
|
||||
LZMA2_STATE_PACK1,
|
||||
LZMA2_STATE_PROP,
|
||||
LZMA2_STATE_DATA,
|
||||
LZMA2_STATE_DATA_CONT,
|
||||
LZMA2_STATE_FINISHED,
|
||||
LZMA2_STATE_ERROR
|
||||
} ELzma2State;
|
||||
|
||||
static SRes Lzma2Dec_GetOldProps(uint8_t prop, uint8_t *props)
|
||||
static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
|
||||
{
|
||||
uint32_t dicSize;
|
||||
if (prop > 40)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
|
||||
props[0] = (uint8_t)LZMA2_LCLP_MAX;
|
||||
props[1] = (uint8_t)(dicSize);
|
||||
props[2] = (uint8_t)(dicSize >> 8);
|
||||
props[3] = (uint8_t)(dicSize >> 16);
|
||||
props[4] = (uint8_t)(dicSize >> 24);
|
||||
return SZ_OK;
|
||||
uint32_t dicSize;
|
||||
if (prop > 40)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
|
||||
props[0] = (Byte)LZMA2_LCLP_MAX;
|
||||
props[1] = (Byte)(dicSize);
|
||||
props[2] = (Byte)(dicSize >> 8);
|
||||
props[3] = (Byte)(dicSize >> 16);
|
||||
props[4] = (Byte)(dicSize >> 24);
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, uint8_t prop, ISzAlloc *alloc)
|
||||
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
|
||||
{
|
||||
uint8_t props[LZMA_PROPS_SIZE];
|
||||
SRes result = Lzma2Dec_GetOldProps(prop, props);
|
||||
if (result != 0)
|
||||
return result;
|
||||
return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
||||
Byte props[LZMA_PROPS_SIZE];
|
||||
RINOK(Lzma2Dec_GetOldProps(prop, props));
|
||||
return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
||||
}
|
||||
|
||||
SRes Lzma2Dec_Allocate(CLzma2Dec *p, uint8_t prop, ISzAlloc *alloc)
|
||||
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
|
||||
{
|
||||
uint8_t props[LZMA_PROPS_SIZE];
|
||||
SRes result = Lzma2Dec_GetOldProps(prop, props);
|
||||
if (result != 0)
|
||||
return result;
|
||||
return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
||||
Byte props[LZMA_PROPS_SIZE];
|
||||
RINOK(Lzma2Dec_GetOldProps(prop, props));
|
||||
return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
||||
}
|
||||
|
||||
void Lzma2Dec_Init(CLzma2Dec *p)
|
||||
{
|
||||
p->state = LZMA2_STATE_CONTROL;
|
||||
p->needInitDic = true;
|
||||
p->needInitState = true;
|
||||
p->needInitProp = true;
|
||||
LzmaDec_Init(&p->decoder);
|
||||
p->state = LZMA2_STATE_CONTROL;
|
||||
p->needInitLevel = 0xE0;
|
||||
p->isExtraMode = False;
|
||||
p->unpackSize = 0;
|
||||
|
||||
/* p->decoder.dicPos = 0; // we can use it instead of full init */
|
||||
LzmaDec_Init(&p->decoder);
|
||||
}
|
||||
|
||||
static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, uint8_t b)
|
||||
static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
|
||||
{
|
||||
switch(p->state)
|
||||
{
|
||||
case LZMA2_STATE_CONTROL:
|
||||
p->control = b;
|
||||
PRF(printf("\n %4X ", p->decoder.dicPos));
|
||||
PRF(printf(" %2X", b));
|
||||
if (p->control == 0)
|
||||
return LZMA2_STATE_FINISHED;
|
||||
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||
{
|
||||
if ((p->control & 0x7F) > 2)
|
||||
return LZMA2_STATE_ERROR;
|
||||
p->unpackSize = 0;
|
||||
}
|
||||
else
|
||||
p->unpackSize = (uint32_t)(p->control & 0x1F) << 16;
|
||||
return LZMA2_STATE_UNPACK0;
|
||||
|
||||
case LZMA2_STATE_UNPACK0:
|
||||
p->unpackSize |= (uint32_t)b << 8;
|
||||
return LZMA2_STATE_UNPACK1;
|
||||
|
||||
case LZMA2_STATE_UNPACK1:
|
||||
p->unpackSize |= (uint32_t)b;
|
||||
p->unpackSize++;
|
||||
PRF(printf(" %8d", p->unpackSize));
|
||||
return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
|
||||
|
||||
case LZMA2_STATE_PACK0:
|
||||
p->packSize = (uint32_t)b << 8;
|
||||
return LZMA2_STATE_PACK1;
|
||||
|
||||
case LZMA2_STATE_PACK1:
|
||||
p->packSize |= (uint32_t)b;
|
||||
p->packSize++;
|
||||
PRF(printf(" %8d", p->packSize));
|
||||
return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
|
||||
(p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
|
||||
|
||||
case LZMA2_STATE_PROP:
|
||||
{
|
||||
int lc, lp;
|
||||
if (b >= (9 * 5 * 5))
|
||||
return LZMA2_STATE_ERROR;
|
||||
lc = b % 9;
|
||||
b /= 9;
|
||||
p->decoder.prop.pb = b / 5;
|
||||
lp = b % 5;
|
||||
if (lc + lp > LZMA2_LCLP_MAX)
|
||||
return LZMA2_STATE_ERROR;
|
||||
p->decoder.prop.lc = lc;
|
||||
p->decoder.prop.lp = lp;
|
||||
p->needInitProp = false;
|
||||
return LZMA2_STATE_DATA;
|
||||
}
|
||||
}
|
||||
return LZMA2_STATE_ERROR;
|
||||
}
|
||||
|
||||
static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const uint8_t *src, size_t size)
|
||||
{
|
||||
memcpy(p->dic + p->dicPos, src, size);
|
||||
p->dicPos += size;
|
||||
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
|
||||
p->checkDicSize = p->prop.dicSize;
|
||||
p->processedPos += (uint32_t)size;
|
||||
}
|
||||
|
||||
void LzmaDec_InitDicAndState(CLzmaDec *p, bool initDic, bool initState);
|
||||
|
||||
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, size_t dicLimit,
|
||||
const uint8_t *src, size_t *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||
{
|
||||
size_t inSize = *srcLen;
|
||||
*srcLen = 0;
|
||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||
|
||||
while (p->state != LZMA2_STATE_FINISHED)
|
||||
{
|
||||
size_t dicPos = p->decoder.dicPos;
|
||||
if (p->state == LZMA2_STATE_ERROR)
|
||||
return SZ_ERROR_DATA;
|
||||
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
|
||||
switch (p->state)
|
||||
{
|
||||
case LZMA2_STATE_CONTROL:
|
||||
p->isExtraMode = False;
|
||||
p->control = b;
|
||||
PRF(printf("\n %8X", (unsigned)p->decoder.dicPos));
|
||||
PRF(printf(" %02X", (unsigned)b));
|
||||
if (b == 0)
|
||||
return LZMA2_STATE_FINISHED;
|
||||
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||
{
|
||||
*status = LZMA_STATUS_NOT_FINISHED;
|
||||
return SZ_OK;
|
||||
}
|
||||
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
|
||||
{
|
||||
if (*srcLen == inSize)
|
||||
{
|
||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
return SZ_OK;
|
||||
}
|
||||
(*srcLen)++;
|
||||
p->state = Lzma2Dec_UpdateState(p, *src++);
|
||||
continue;
|
||||
}
|
||||
{
|
||||
size_t destSizeCur = dicLimit - dicPos;
|
||||
size_t srcSizeCur = inSize - *srcLen;
|
||||
ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
|
||||
|
||||
if (p->unpackSize <= destSizeCur)
|
||||
{
|
||||
destSizeCur = (size_t)p->unpackSize;
|
||||
curFinishMode = LZMA_FINISH_END;
|
||||
}
|
||||
|
||||
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||
{
|
||||
if (*srcLen == inSize)
|
||||
{
|
||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
if (p->state == LZMA2_STATE_DATA)
|
||||
{
|
||||
bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
|
||||
if (initDic)
|
||||
p->needInitProp = p->needInitState = true;
|
||||
else if (p->needInitDic)
|
||||
return SZ_ERROR_DATA;
|
||||
p->needInitDic = false;
|
||||
LzmaDec_InitDicAndState(&p->decoder, initDic, false);
|
||||
}
|
||||
|
||||
if (srcSizeCur > destSizeCur)
|
||||
srcSizeCur = destSizeCur;
|
||||
|
||||
if (srcSizeCur == 0)
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
|
||||
|
||||
src += srcSizeCur;
|
||||
*srcLen += srcSizeCur;
|
||||
p->unpackSize -= (uint32_t)srcSizeCur;
|
||||
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t outSizeProcessed;
|
||||
SRes res;
|
||||
|
||||
if (p->state == LZMA2_STATE_DATA)
|
||||
{
|
||||
int mode = LZMA2_GET_LZMA_MODE(p);
|
||||
bool initDic = (mode == 3);
|
||||
bool initState = (mode > 0);
|
||||
if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
|
||||
p->needInitDic = false;
|
||||
p->needInitState = false;
|
||||
p->state = LZMA2_STATE_DATA_CONT;
|
||||
}
|
||||
if (srcSizeCur > p->packSize)
|
||||
srcSizeCur = (size_t)p->packSize;
|
||||
|
||||
res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);
|
||||
|
||||
src += srcSizeCur;
|
||||
*srcLen += srcSizeCur;
|
||||
p->packSize -= (uint32_t)srcSizeCur;
|
||||
|
||||
outSizeProcessed = p->decoder.dicPos - dicPos;
|
||||
p->unpackSize -= (uint32_t)outSizeProcessed;
|
||||
|
||||
if (res != 0)
|
||||
return res;
|
||||
if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||
return res;
|
||||
|
||||
if (srcSizeCur == 0 && outSizeProcessed == 0)
|
||||
{
|
||||
if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ||
|
||||
p->unpackSize != 0 || p->packSize != 0)
|
||||
return SZ_ERROR_DATA;
|
||||
p->state = LZMA2_STATE_CONTROL;
|
||||
}
|
||||
if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
|
||||
*status = LZMA_STATUS_NOT_FINISHED;
|
||||
}
|
||||
}
|
||||
}
|
||||
*status = LZMA_STATUS_FINISHED_WITH_MARK;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, uint8_t *dest, size_t *destLen, const uint8_t *src, size_t *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||
{
|
||||
size_t outSize = *destLen, inSize = *srcLen;
|
||||
*srcLen = *destLen = 0;
|
||||
for (;;)
|
||||
{
|
||||
size_t srcSizeCur = inSize, outSizeCur, dicPos;
|
||||
ELzmaFinishMode curFinishMode;
|
||||
SRes res;
|
||||
if (p->decoder.dicPos == p->decoder.dicBufSize)
|
||||
p->decoder.dicPos = 0;
|
||||
dicPos = p->decoder.dicPos;
|
||||
if (outSize > p->decoder.dicBufSize - dicPos)
|
||||
{
|
||||
outSizeCur = p->decoder.dicBufSize;
|
||||
curFinishMode = LZMA_FINISH_ANY;
|
||||
if (b == LZMA2_CONTROL_COPY_RESET_DIC)
|
||||
p->needInitLevel = 0xC0;
|
||||
else if (b > 2 || p->needInitLevel == 0xE0)
|
||||
return LZMA2_STATE_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
outSizeCur = dicPos + outSize;
|
||||
curFinishMode = finishMode;
|
||||
if (b < p->needInitLevel)
|
||||
return LZMA2_STATE_ERROR;
|
||||
p->needInitLevel = 0;
|
||||
p->unpackSize = (uint32_t)(b & 0x1F) << 16;
|
||||
}
|
||||
return LZMA2_STATE_UNPACK0;
|
||||
|
||||
case LZMA2_STATE_UNPACK0:
|
||||
p->unpackSize |= (uint32_t)b << 8;
|
||||
return LZMA2_STATE_UNPACK1;
|
||||
|
||||
case LZMA2_STATE_UNPACK1:
|
||||
p->unpackSize |= (uint32_t)b;
|
||||
p->unpackSize++;
|
||||
PRF(printf(" %7u", (unsigned)p->unpackSize));
|
||||
return LZMA2_IS_UNCOMPRESSED_STATE(p) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
|
||||
|
||||
case LZMA2_STATE_PACK0:
|
||||
p->packSize = (uint32_t)b << 8;
|
||||
return LZMA2_STATE_PACK1;
|
||||
|
||||
case LZMA2_STATE_PACK1:
|
||||
p->packSize |= (uint32_t)b;
|
||||
p->packSize++;
|
||||
/* if (p->packSize < 5) return LZMA2_STATE_ERROR; */
|
||||
PRF(printf(" %5u", (unsigned)p->packSize));
|
||||
return (p->control & 0x40) ? LZMA2_STATE_PROP : LZMA2_STATE_DATA;
|
||||
|
||||
case LZMA2_STATE_PROP:
|
||||
{
|
||||
unsigned lc, lp;
|
||||
if (b >= (9 * 5 * 5))
|
||||
return LZMA2_STATE_ERROR;
|
||||
lc = b % 9;
|
||||
b /= 9;
|
||||
p->decoder.prop.pb = (Byte)(b / 5);
|
||||
lp = b % 5;
|
||||
if (lc + lp > LZMA2_LCLP_MAX)
|
||||
return LZMA2_STATE_ERROR;
|
||||
p->decoder.prop.lc = (Byte)lc;
|
||||
p->decoder.prop.lp = (Byte)lp;
|
||||
return LZMA2_STATE_DATA;
|
||||
}
|
||||
}
|
||||
return LZMA2_STATE_ERROR;
|
||||
}
|
||||
|
||||
static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
|
||||
{
|
||||
memcpy(p->dic + p->dicPos, src, size);
|
||||
p->dicPos += size;
|
||||
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
|
||||
p->checkDicSize = p->prop.dicSize;
|
||||
p->processedPos += (uint32_t)size;
|
||||
}
|
||||
|
||||
void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState);
|
||||
|
||||
|
||||
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||
{
|
||||
SizeT inSize = *srcLen;
|
||||
*srcLen = 0;
|
||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||
|
||||
while (p->state != LZMA2_STATE_ERROR)
|
||||
{
|
||||
SizeT dicPos;
|
||||
|
||||
if (p->state == LZMA2_STATE_FINISHED)
|
||||
{
|
||||
*status = LZMA_STATUS_FINISHED_WITH_MARK;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
dicPos = p->decoder.dicPos;
|
||||
|
||||
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
|
||||
{
|
||||
*status = LZMA_STATUS_NOT_FINISHED;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
|
||||
{
|
||||
if (*srcLen == inSize)
|
||||
{
|
||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
return SZ_OK;
|
||||
}
|
||||
(*srcLen)++;
|
||||
p->state = Lzma2Dec_UpdateState(p, *src++);
|
||||
if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
SizeT inCur = inSize - *srcLen;
|
||||
SizeT outCur = dicLimit - dicPos;
|
||||
ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
|
||||
|
||||
if (outCur >= p->unpackSize)
|
||||
{
|
||||
outCur = (SizeT)p->unpackSize;
|
||||
curFinishMode = LZMA_FINISH_END;
|
||||
}
|
||||
|
||||
res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);
|
||||
src += srcSizeCur;
|
||||
inSize -= srcSizeCur;
|
||||
*srcLen += srcSizeCur;
|
||||
outSizeCur = p->decoder.dicPos - dicPos;
|
||||
memcpy(dest, p->decoder.dic + dicPos, outSizeCur);
|
||||
dest += outSizeCur;
|
||||
outSize -= outSizeCur;
|
||||
*destLen += outSizeCur;
|
||||
if (res != 0)
|
||||
return res;
|
||||
if (outSizeCur == 0 || outSize == 0)
|
||||
return SZ_OK;
|
||||
}
|
||||
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||
{
|
||||
if (inCur == 0)
|
||||
{
|
||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
if (p->state == LZMA2_STATE_DATA)
|
||||
{
|
||||
BoolInt initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
|
||||
LzmaDec_InitDicAndState(&p->decoder, initDic, False);
|
||||
}
|
||||
|
||||
if (inCur > outCur)
|
||||
inCur = outCur;
|
||||
if (inCur == 0)
|
||||
break;
|
||||
|
||||
LzmaDec_UpdateWithUncompressed(&p->decoder, src, inCur);
|
||||
|
||||
src += inCur;
|
||||
*srcLen += inCur;
|
||||
p->unpackSize -= (uint32_t)inCur;
|
||||
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
|
||||
}
|
||||
else
|
||||
{
|
||||
SRes res;
|
||||
|
||||
if (p->state == LZMA2_STATE_DATA)
|
||||
{
|
||||
BoolInt initDic = (p->control >= 0xE0);
|
||||
BoolInt initState = (p->control >= 0xA0);
|
||||
LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
|
||||
p->state = LZMA2_STATE_DATA_CONT;
|
||||
}
|
||||
|
||||
if (inCur > p->packSize)
|
||||
inCur = (SizeT)p->packSize;
|
||||
|
||||
res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status);
|
||||
|
||||
src += inCur;
|
||||
*srcLen += inCur;
|
||||
p->packSize -= (uint32_t)inCur;
|
||||
outCur = p->decoder.dicPos - dicPos;
|
||||
p->unpackSize -= (uint32_t)outCur;
|
||||
|
||||
if (res != 0)
|
||||
break;
|
||||
|
||||
if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||
{
|
||||
if (p->packSize == 0)
|
||||
break;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
if (inCur == 0 && outCur == 0)
|
||||
{
|
||||
if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||
|| p->unpackSize != 0
|
||||
|| p->packSize != 0)
|
||||
break;
|
||||
p->state = LZMA2_STATE_CONTROL;
|
||||
}
|
||||
|
||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||
p->state = LZMA2_STATE_ERROR;
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
|
||||
SRes Lzma2Decode(uint8_t *dest, size_t *destLen, const uint8_t *src, size_t *srcLen,
|
||||
uint8_t prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)
|
||||
|
||||
|
||||
|
||||
ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
|
||||
SizeT outSize,
|
||||
const Byte *src, SizeT *srcLen,
|
||||
int checkFinishBlock)
|
||||
{
|
||||
SRes res;
|
||||
SRes result;
|
||||
CLzma2Dec decoder;
|
||||
size_t outSize = *destLen, inSize = *srcLen;
|
||||
uint8_t props[LZMA_PROPS_SIZE];
|
||||
SizeT inSize = *srcLen;
|
||||
*srcLen = 0;
|
||||
|
||||
Lzma2Dec_Construct(&decoder);
|
||||
while (p->state != LZMA2_STATE_ERROR)
|
||||
{
|
||||
if (p->state == LZMA2_STATE_FINISHED)
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_FINISHED_WITH_MARK;
|
||||
|
||||
*destLen = *srcLen = 0;
|
||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||
decoder.decoder.dic = dest;
|
||||
decoder.decoder.dicBufSize = outSize;
|
||||
if (outSize == 0 && !checkFinishBlock)
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
|
||||
|
||||
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
|
||||
{
|
||||
if (*srcLen == inSize)
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
(*srcLen)++;
|
||||
|
||||
result = Lzma2Dec_GetOldProps(prop, props);
|
||||
if (result != 0)
|
||||
return result;
|
||||
result = LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc);
|
||||
if (result != 0)
|
||||
return result;
|
||||
p->state = Lzma2Dec_UpdateState(p, *src++);
|
||||
|
||||
*srcLen = inSize;
|
||||
res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status);
|
||||
*destLen = decoder.decoder.dicPos;
|
||||
if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||
res = SZ_ERROR_INPUT_EOF;
|
||||
if (p->state == LZMA2_STATE_UNPACK0)
|
||||
{
|
||||
/* if (p->decoder.dicPos != 0) */
|
||||
if (p->control == LZMA2_CONTROL_COPY_RESET_DIC || p->control >= 0xE0)
|
||||
return LZMA2_PARSE_STATUS_NEW_BLOCK;
|
||||
/* if (outSize == 0) return LZMA_STATUS_NOT_FINISHED; */
|
||||
}
|
||||
|
||||
LzmaDec_FreeProbs(&decoder.decoder, alloc);
|
||||
return res;
|
||||
/* The following code can be commented.
|
||||
* It's not big problem, if we read additional input bytes.
|
||||
* It will be stopped later in LZMA2_STATE_DATA / LZMA2_STATE_DATA_CONT state. */
|
||||
|
||||
if (outSize == 0 && p->state != LZMA2_STATE_FINISHED)
|
||||
{
|
||||
/* checkFinishBlock is true. So we expect that block must be finished,
|
||||
* We can return LZMA_STATUS_NOT_SPECIFIED or LZMA_STATUS_NOT_FINISHED here
|
||||
* break; */
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
|
||||
}
|
||||
|
||||
if (p->state == LZMA2_STATE_DATA)
|
||||
return LZMA2_PARSE_STATUS_NEW_CHUNK;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (outSize == 0)
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
|
||||
|
||||
{
|
||||
SizeT inCur = inSize - *srcLen;
|
||||
|
||||
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||
{
|
||||
if (inCur == 0)
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
if (inCur > p->unpackSize)
|
||||
inCur = p->unpackSize;
|
||||
if (inCur > outSize)
|
||||
inCur = outSize;
|
||||
p->decoder.dicPos += inCur;
|
||||
src += inCur;
|
||||
*srcLen += inCur;
|
||||
outSize -= inCur;
|
||||
p->unpackSize -= (uint32_t)inCur;
|
||||
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->isExtraMode = True;
|
||||
|
||||
if (inCur == 0)
|
||||
{
|
||||
if (p->packSize != 0)
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
}
|
||||
else if (p->state == LZMA2_STATE_DATA)
|
||||
{
|
||||
p->state = LZMA2_STATE_DATA_CONT;
|
||||
if (*src != 0)
|
||||
{
|
||||
/* first byte of lzma chunk must be Zero */
|
||||
*srcLen += 1;
|
||||
p->packSize--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (inCur > p->packSize)
|
||||
inCur = (SizeT)p->packSize;
|
||||
|
||||
src += inCur;
|
||||
*srcLen += inCur;
|
||||
p->packSize -= (uint32_t)inCur;
|
||||
|
||||
if (p->packSize == 0)
|
||||
{
|
||||
SizeT rem = outSize;
|
||||
if (rem > p->unpackSize)
|
||||
rem = p->unpackSize;
|
||||
p->decoder.dicPos += rem;
|
||||
p->unpackSize -= (uint32_t)rem;
|
||||
outSize -= rem;
|
||||
if (p->unpackSize == 0)
|
||||
p->state = LZMA2_STATE_CONTROL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p->state = LZMA2_STATE_ERROR;
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||
{
|
||||
SizeT outSize = *destLen, inSize = *srcLen;
|
||||
*srcLen = *destLen = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
SizeT inCur = inSize, outCur, dicPos;
|
||||
ELzmaFinishMode curFinishMode;
|
||||
SRes res;
|
||||
|
||||
if (p->decoder.dicPos == p->decoder.dicBufSize)
|
||||
p->decoder.dicPos = 0;
|
||||
dicPos = p->decoder.dicPos;
|
||||
curFinishMode = LZMA_FINISH_ANY;
|
||||
outCur = p->decoder.dicBufSize - dicPos;
|
||||
|
||||
if (outCur >= outSize)
|
||||
{
|
||||
outCur = outSize;
|
||||
curFinishMode = finishMode;
|
||||
}
|
||||
|
||||
res = Lzma2Dec_DecodeToDic(p, dicPos + outCur, src, &inCur, curFinishMode, status);
|
||||
|
||||
src += inCur;
|
||||
inSize -= inCur;
|
||||
*srcLen += inCur;
|
||||
outCur = p->decoder.dicPos - dicPos;
|
||||
memcpy(dest, p->decoder.dic + dicPos, outCur);
|
||||
dest += outCur;
|
||||
outSize -= outCur;
|
||||
*destLen += outCur;
|
||||
if (res != 0)
|
||||
return res;
|
||||
if (outCur == 0 || outSize == 0)
|
||||
return SZ_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc)
|
||||
{
|
||||
CLzma2Dec p;
|
||||
SRes res;
|
||||
SizeT outSize = *destLen, inSize = *srcLen;
|
||||
*destLen = *srcLen = 0;
|
||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||
Lzma2Dec_Construct(&p);
|
||||
RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc));
|
||||
p.decoder.dic = dest;
|
||||
p.decoder.dicBufSize = outSize;
|
||||
Lzma2Dec_Init(&p);
|
||||
*srcLen = inSize;
|
||||
res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
|
||||
*destLen = p.decoder.dicPos;
|
||||
if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||
res = SZ_ERROR_INPUT_EOF;
|
||||
Lzma2Dec_FreeProbs(&p, alloc);
|
||||
return res;
|
||||
}
|
||||
Vendored
+60
-25
@@ -1,39 +1,35 @@
|
||||
/* Lzma2Dec.h -- LZMA2 Decoder
|
||||
2009-05-03 : Igor Pavlov : Public domain */
|
||||
2018-02-19 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMA2_DEC_H
|
||||
#define __LZMA2_DEC_H
|
||||
|
||||
#include <boolean.h>
|
||||
#include "LzmaDec.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
/* ---------- State Interface ---------- */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CLzmaDec decoder;
|
||||
unsigned state;
|
||||
Byte control;
|
||||
Byte needInitLevel;
|
||||
Byte isExtraMode;
|
||||
Byte _pad_;
|
||||
uint32_t packSize;
|
||||
uint32_t unpackSize;
|
||||
int state;
|
||||
uint8_t control;
|
||||
bool needInitDic;
|
||||
bool needInitState;
|
||||
bool needInitProp;
|
||||
CLzmaDec decoder;
|
||||
} CLzma2Dec;
|
||||
|
||||
#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder)
|
||||
#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc);
|
||||
#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc);
|
||||
#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc)
|
||||
#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc)
|
||||
|
||||
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, uint8_t prop, ISzAlloc *alloc);
|
||||
SRes Lzma2Dec_Allocate(CLzma2Dec *p, uint8_t prop, ISzAlloc *alloc);
|
||||
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc);
|
||||
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc);
|
||||
void Lzma2Dec_Init(CLzma2Dec *p);
|
||||
|
||||
|
||||
/*
|
||||
finishMode:
|
||||
It has meaning only if the decoding reaches output limit (*destLen or dicLimit).
|
||||
@@ -49,11 +45,52 @@ Returns:
|
||||
SZ_ERROR_DATA - Data error
|
||||
*/
|
||||
|
||||
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, size_t dicLimit,
|
||||
const uint8_t *src, size_t *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
|
||||
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, uint8_t *dest, size_t *destLen,
|
||||
const uint8_t *src, size_t *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen,
|
||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
|
||||
|
||||
/* ---------- LZMA2 block and chunk parsing ---------- */
|
||||
|
||||
/*
|
||||
Lzma2Dec_Parse() parses compressed data stream up to next independent block or next chunk data.
|
||||
It can return LZMA_STATUS_* code or LZMA2_PARSE_STATUS_* code:
|
||||
- LZMA2_PARSE_STATUS_NEW_BLOCK - there is new block, and 1 additional byte (control byte of next block header) was read from input.
|
||||
- LZMA2_PARSE_STATUS_NEW_CHUNK - there is new chunk, and only lzma2 header of new chunk was read.
|
||||
CLzma2Dec::unpackSize contains unpack size of that chunk
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/*
|
||||
LZMA_STATUS_NOT_SPECIFIED // data error
|
||||
LZMA_STATUS_FINISHED_WITH_MARK
|
||||
LZMA_STATUS_NOT_FINISHED //
|
||||
LZMA_STATUS_NEEDS_MORE_INPUT
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK // unused
|
||||
*/
|
||||
LZMA2_PARSE_STATUS_NEW_BLOCK = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + 1,
|
||||
LZMA2_PARSE_STATUS_NEW_CHUNK
|
||||
} ELzma2ParseStatus;
|
||||
|
||||
ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
|
||||
SizeT outSize, /* output size */
|
||||
const Byte *src, SizeT *srcLen,
|
||||
int checkFinishBlock /* set (checkFinishBlock = 1), if it must read full input data, if decoder.dicPos reaches blockMax position. */
|
||||
);
|
||||
|
||||
/*
|
||||
LZMA2 parser doesn't decode LZMA chunks, so we must read
|
||||
full input LZMA chunk to decode some part of LZMA chunk.
|
||||
|
||||
Lzma2Dec_GetUnpackExtra() returns the value that shows
|
||||
max possible number of output bytes that can be output by decoder
|
||||
at current input positon.
|
||||
*/
|
||||
|
||||
#define Lzma2Dec_GetUnpackExtra(p) ((p)->isExtraMode ? (p)->unpackSize : 0);
|
||||
|
||||
|
||||
/* ---------- One Call Interface ---------- */
|
||||
@@ -75,11 +112,9 @@ Returns:
|
||||
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
|
||||
*/
|
||||
|
||||
SRes Lzma2Decode(uint8_t *dest, size_t *destLen, const uint8_t *src, size_t *srcLen,
|
||||
uint8_t prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc);
|
||||
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
Vendored
+997
-881
File diff suppressed because it is too large.
Load diff
Vendored
+175
-161
@@ -1,174 +1,190 @@
|
||||
/* LzmaDec.h -- LZMA Decoder
|
||||
2009-02-07 : Igor Pavlov : Public domain */
|
||||
2018-04-21 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMA_DEC_H
|
||||
#define __LZMA_DEC_H
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
/* #define _LZMA_PROB32 */
|
||||
/* _LZMA_PROB32 can increase the speed on some CPUs,
|
||||
but memory usage for CLzmaDec::probs will be doubled in that case */
|
||||
|
||||
typedef
|
||||
#ifdef _LZMA_PROB32
|
||||
uint32_t
|
||||
#else
|
||||
uint16_t
|
||||
#endif
|
||||
CLzmaProb;
|
||||
|
||||
|
||||
/* ---------- LZMA Properties ---------- */
|
||||
|
||||
#define LZMA_PROPS_SIZE 5
|
||||
|
||||
typedef struct _CLzmaProps
|
||||
{
|
||||
unsigned lc, lp, pb;
|
||||
uint32_t dicSize;
|
||||
} CLzmaProps;
|
||||
typedef struct _CLzmaProps
|
||||
{
|
||||
Byte lc;
|
||||
Byte lp;
|
||||
Byte pb;
|
||||
Byte _pad_;
|
||||
uint32_t dicSize;
|
||||
} CLzmaProps;
|
||||
|
||||
/* LzmaProps_Decode - decodes properties
|
||||
/* LzmaProps_Decode - decodes properties
|
||||
Returns:
|
||||
SZ_OK
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
SZ_OK
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
*/
|
||||
|
||||
SRes LzmaProps_Decode(CLzmaProps *p, const uint8_t *data, unsigned size);
|
||||
SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
|
||||
|
||||
|
||||
/* ---------- LZMA Decoder state ---------- */
|
||||
/* ---------- LZMA Decoder state ---------- */
|
||||
|
||||
/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
|
||||
Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
|
||||
/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
|
||||
Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
|
||||
|
||||
#define LZMA_REQUIRED_INPUT_MAX 20
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CLzmaProps prop;
|
||||
uint16_t *probs;
|
||||
uint8_t *dic;
|
||||
const uint8_t *buf;
|
||||
uint32_t range, code;
|
||||
size_t dicPos;
|
||||
size_t dicBufSize;
|
||||
uint32_t processedPos;
|
||||
uint32_t checkDicSize;
|
||||
unsigned state;
|
||||
uint32_t reps[4];
|
||||
unsigned remainLen;
|
||||
int needFlush;
|
||||
int needInitState;
|
||||
uint32_t numProbs;
|
||||
unsigned tempBufSize;
|
||||
uint8_t tempBuf[LZMA_REQUIRED_INPUT_MAX];
|
||||
} CLzmaDec;
|
||||
|
||||
#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
|
||||
|
||||
void LzmaDec_Init(CLzmaDec *p);
|
||||
|
||||
/* There are two types of LZMA streams:
|
||||
0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
|
||||
1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LZMA_FINISH_ANY, /* finish at any point */
|
||||
LZMA_FINISH_END /* block must be finished at the end */
|
||||
} ELzmaFinishMode;
|
||||
|
||||
/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
|
||||
|
||||
You must use LZMA_FINISH_END, when you know that current output buffer
|
||||
covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
|
||||
|
||||
If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
|
||||
and output value of destLen will be less than output buffer size limit.
|
||||
You can check status result also.
|
||||
|
||||
You can use multiple checks to test data integrity after full decompression:
|
||||
1) Check Result and "status" variable.
|
||||
2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
|
||||
3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
|
||||
You must use correct finish mode in that case. */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */
|
||||
LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
|
||||
LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
|
||||
LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
|
||||
} ELzmaStatus;
|
||||
|
||||
/* ELzmaStatus is used only as output value for function call */
|
||||
|
||||
|
||||
/* ---------- Interfaces ---------- */
|
||||
|
||||
/* There are 3 levels of interfaces:
|
||||
1) Dictionary Interface
|
||||
2) Buffer Interface
|
||||
3) One Call Interface
|
||||
You can select any of these interfaces, but don't mix functions from different
|
||||
groups for same object. */
|
||||
|
||||
|
||||
/* There are two variants to allocate state for Dictionary Interface:
|
||||
1) LzmaDec_Allocate / LzmaDec_Free
|
||||
2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
|
||||
You can use variant 2, if you set dictionary buffer manually.
|
||||
For Buffer Interface you must always use variant 1.
|
||||
|
||||
LzmaDec_Allocate* can return:
|
||||
SZ_OK
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
*/
|
||||
|
||||
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const uint8_t *props, unsigned propsSize, ISzAlloc *alloc);
|
||||
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
|
||||
|
||||
SRes LzmaDec_Allocate(CLzmaDec *state, const uint8_t *prop, unsigned propsSize, ISzAlloc *alloc);
|
||||
void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
|
||||
|
||||
/* ---------- Dictionary Interface ---------- */
|
||||
|
||||
/* You can use it, if you want to eliminate the overhead for data copying from
|
||||
dictionary to some other external buffer.
|
||||
You must work with CLzmaDec variables directly in this interface.
|
||||
|
||||
STEPS:
|
||||
LzmaDec_Constr()
|
||||
LzmaDec_Allocate()
|
||||
for (each new stream)
|
||||
typedef struct
|
||||
{
|
||||
LzmaDec_Init()
|
||||
while (it needs more decompression)
|
||||
/* Don't change this structure. ASM code can use it. */
|
||||
CLzmaProps prop;
|
||||
CLzmaProb *probs;
|
||||
CLzmaProb *probs_1664;
|
||||
Byte *dic;
|
||||
SizeT dicBufSize;
|
||||
SizeT dicPos;
|
||||
const Byte *buf;
|
||||
uint32_t range;
|
||||
uint32_t code;
|
||||
uint32_t processedPos;
|
||||
uint32_t checkDicSize;
|
||||
uint32_t reps[4];
|
||||
uint32_t state;
|
||||
uint32_t remainLen;
|
||||
|
||||
uint32_t numProbs;
|
||||
unsigned tempBufSize;
|
||||
Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
|
||||
} CLzmaDec;
|
||||
|
||||
#define LzmaDec_Construct(p) { (p)->dic = NULL; (p)->probs = NULL; }
|
||||
|
||||
void LzmaDec_Init(CLzmaDec *p);
|
||||
|
||||
/* There are two types of LZMA streams:
|
||||
- Stream with end mark. That end mark adds about 6 bytes to compressed size.
|
||||
- Stream without end mark. You must know exact uncompressed size to decompress such stream. */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LzmaDec_DecodeToDic()
|
||||
use data from CLzmaDec::dic and update CLzmaDec::dicPos
|
||||
}
|
||||
}
|
||||
LzmaDec_Free()
|
||||
LZMA_FINISH_ANY, /* finish at any point */
|
||||
LZMA_FINISH_END /* block must be finished at the end */
|
||||
} ELzmaFinishMode;
|
||||
|
||||
/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
|
||||
|
||||
You must use LZMA_FINISH_END, when you know that current output buffer
|
||||
covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
|
||||
|
||||
If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
|
||||
and output value of destLen will be less than output buffer size limit.
|
||||
You can check status result also.
|
||||
|
||||
You can use multiple checks to test data integrity after full decompression:
|
||||
1) Check Result and "status" variable.
|
||||
2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
|
||||
3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
|
||||
You must use correct finish mode in that case. */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */
|
||||
LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
|
||||
LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
|
||||
LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
|
||||
} ELzmaStatus;
|
||||
|
||||
/* ELzmaStatus is used only as output value for function call */
|
||||
|
||||
|
||||
/* ---------- Interfaces ---------- */
|
||||
|
||||
/* There are 3 levels of interfaces:
|
||||
1) Dictionary Interface
|
||||
2) Buffer Interface
|
||||
3) One Call Interface
|
||||
You can select any of these interfaces, but don't mix functions from different
|
||||
groups for same object. */
|
||||
|
||||
|
||||
/* There are two variants to allocate state for Dictionary Interface:
|
||||
1) LzmaDec_Allocate / LzmaDec_Free
|
||||
2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
|
||||
You can use variant 2, if you set dictionary buffer manually.
|
||||
For Buffer Interface you must always use variant 1.
|
||||
|
||||
LzmaDec_Allocate* can return:
|
||||
SZ_OK
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
*/
|
||||
|
||||
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);
|
||||
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc);
|
||||
|
||||
SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);
|
||||
void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc);
|
||||
|
||||
/* ---------- Dictionary Interface ---------- */
|
||||
|
||||
/* You can use it, if you want to eliminate the overhead for data copying from
|
||||
dictionary to some other external buffer.
|
||||
You must work with CLzmaDec variables directly in this interface.
|
||||
|
||||
STEPS:
|
||||
LzmaDec_Construct()
|
||||
LzmaDec_Allocate()
|
||||
for (each new stream)
|
||||
{
|
||||
LzmaDec_Init()
|
||||
while (it needs more decompression)
|
||||
{
|
||||
LzmaDec_DecodeToDic()
|
||||
use data from CLzmaDec::dic and update CLzmaDec::dicPos
|
||||
}
|
||||
}
|
||||
LzmaDec_Free()
|
||||
*/
|
||||
|
||||
/* LzmaDec_DecodeToDic
|
||||
|
||||
The decoding to internal dictionary buffer (CLzmaDec::dic).
|
||||
You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
|
||||
/* LzmaDec_DecodeToDic
|
||||
|
||||
The decoding to internal dictionary buffer (CLzmaDec::dic).
|
||||
You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
|
||||
|
||||
finishMode:
|
||||
It has meaning only if the decoding reaches output limit (dicLimit).
|
||||
LZMA_FINISH_ANY - Decode just dicLimit bytes.
|
||||
LZMA_FINISH_END - Stream must be finished after dicLimit.
|
||||
It has meaning only if the decoding reaches output limit (dicLimit).
|
||||
LZMA_FINISH_ANY - Decode just dicLimit bytes.
|
||||
LZMA_FINISH_END - Stream must be finished after dicLimit.
|
||||
|
||||
Returns:
|
||||
SZ_OK
|
||||
status:
|
||||
LZMA_STATUS_FINISHED_WITH_MARK
|
||||
LZMA_STATUS_NOT_FINISHED
|
||||
LZMA_STATUS_NEEDS_MORE_INPUT
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||
SZ_ERROR_DATA - Data error
|
||||
SZ_OK
|
||||
status:
|
||||
LZMA_STATUS_FINISHED_WITH_MARK
|
||||
LZMA_STATUS_NOT_FINISHED
|
||||
LZMA_STATUS_NEEDS_MORE_INPUT
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||
SZ_ERROR_DATA - Data error
|
||||
*/
|
||||
|
||||
SRes LzmaDec_DecodeToDic(CLzmaDec *p, size_t dicLimit,
|
||||
const uint8_t *src, size_t *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
|
||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
|
||||
|
||||
/* ---------- Buffer Interface ---------- */
|
||||
@@ -179,13 +195,13 @@ SZ_ERROR_DATA - Data error
|
||||
to work with CLzmaDec variables manually.
|
||||
|
||||
finishMode:
|
||||
It has meaning only if the decoding reaches output limit (*destLen).
|
||||
LZMA_FINISH_ANY - Decode just destLen bytes.
|
||||
LZMA_FINISH_END - Stream must be finished after (*destLen).
|
||||
It has meaning only if the decoding reaches output limit (*destLen).
|
||||
LZMA_FINISH_ANY - Decode just destLen bytes.
|
||||
LZMA_FINISH_END - Stream must be finished after (*destLen).
|
||||
*/
|
||||
|
||||
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, uint8_t *dest, size_t *destLen,
|
||||
const uint8_t *src, size_t *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
|
||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
|
||||
|
||||
/* ---------- One Call Interface ---------- */
|
||||
@@ -193,28 +209,26 @@ SRes LzmaDec_DecodeToBuf(CLzmaDec *p, uint8_t *dest, size_t *destLen,
|
||||
/* LzmaDecode
|
||||
|
||||
finishMode:
|
||||
It has meaning only if the decoding reaches output limit (*destLen).
|
||||
LZMA_FINISH_ANY - Decode just destLen bytes.
|
||||
LZMA_FINISH_END - Stream must be finished after (*destLen).
|
||||
It has meaning only if the decoding reaches output limit (*destLen).
|
||||
LZMA_FINISH_ANY - Decode just destLen bytes.
|
||||
LZMA_FINISH_END - Stream must be finished after (*destLen).
|
||||
|
||||
Returns:
|
||||
SZ_OK
|
||||
status:
|
||||
LZMA_STATUS_FINISHED_WITH_MARK
|
||||
LZMA_STATUS_NOT_FINISHED
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||
SZ_ERROR_DATA - Data error
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
|
||||
SZ_OK
|
||||
status:
|
||||
LZMA_STATUS_FINISHED_WITH_MARK
|
||||
LZMA_STATUS_NOT_FINISHED
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||
SZ_ERROR_DATA - Data error
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
|
||||
*/
|
||||
|
||||
SRes LzmaDecode(uint8_t *dest, size_t *destLen, const uint8_t *src, size_t *srcLen,
|
||||
const uint8_t *propData, unsigned propSize, ELzmaFinishMode finishMode,
|
||||
ELzmaStatus *status, ISzAlloc *alloc);
|
||||
SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
|
||||
ELzmaStatus *status, ISzAllocPtr alloc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
Vendored
+2131
-1464
File diff suppressed because it is too large.
Load diff
Vendored
+27
-31
@@ -1,11 +1,9 @@
|
||||
/* LzmaEnc.h -- LZMA Encoder
|
||||
2013-01-18 : Igor Pavlov : Public domain */
|
||||
2017-07-27 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMA_ENC_H
|
||||
#define __LZMA_ENC_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
@@ -14,12 +12,10 @@ EXTERN_C_BEGIN
|
||||
|
||||
typedef struct _CLzmaEncProps
|
||||
{
|
||||
int level; /* 0 <= level <= 9 */
|
||||
int level; /* 0 <= level <= 9 */
|
||||
uint32_t dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
|
||||
(1 << 12) <= dictSize <= (1 << 30) for 64-bit version
|
||||
default = (1 << 24) */
|
||||
uint64_t reduceSize; /* estimated size of data that will be compressed. default = 0xFFFFFFFF.
|
||||
Encoder uses this value to reduce dictionary size */
|
||||
(1 << 12) <= dictSize <= (3 << 29) for 64-bit version
|
||||
default = (1 << 24) */
|
||||
int lc; /* 0 <= lc <= 8, default = 3 */
|
||||
int lp; /* 0 <= lp <= 4, default = 0 */
|
||||
int pb; /* 0 <= pb <= 4, default = 2 */
|
||||
@@ -27,9 +23,12 @@ typedef struct _CLzmaEncProps
|
||||
int fb; /* 5 <= fb <= 273, default = 32 */
|
||||
int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */
|
||||
int numHashBytes; /* 2, 3 or 4, default = 4 */
|
||||
uint32_t mc; /* 1 <= mc <= (1 << 30), default = 32 */
|
||||
uint32_t mc; /* 1 <= mc <= (1 << 30), default = 32 */
|
||||
unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
|
||||
int numThreads; /* 1 or 2, default = 2 */
|
||||
|
||||
uint64_t reduceSize; /* estimated size of data that will be compressed. default = (uint64_t)(int64_t)-1.
|
||||
Encoder uses this value to reduce dictionary size */
|
||||
} CLzmaEncProps;
|
||||
|
||||
void LzmaEncProps_Init(CLzmaEncProps *p);
|
||||
@@ -39,41 +38,38 @@ uint32_t LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
|
||||
|
||||
/* ---------- CLzmaEncHandle Interface ---------- */
|
||||
|
||||
/* LzmaEnc_* functions can return the following exit codes:
|
||||
Returns:
|
||||
/* LzmaEnc* functions can return the following exit codes:
|
||||
SRes:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_PARAM - Incorrect paramater in props
|
||||
SZ_ERROR_WRITE - Write callback error.
|
||||
SZ_ERROR_WRITE - ISeqOutStream write callback error
|
||||
SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output
|
||||
SZ_ERROR_PROGRESS - some break from progress callback
|
||||
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
|
||||
SZ_ERROR_THREAD - error in multithreading functions (only for Mt version)
|
||||
*/
|
||||
|
||||
typedef void * CLzmaEncHandle;
|
||||
|
||||
CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc);
|
||||
void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||
CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc);
|
||||
void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig);
|
||||
|
||||
SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
|
||||
SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, unsigned char *properties, size_t *size);
|
||||
void LzmaEnc_SetDataSize(CLzmaEncHandle p, uint64_t expectedDataSiize);
|
||||
SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
|
||||
unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle p);
|
||||
|
||||
SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,
|
||||
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||
SRes LzmaEnc_MemEncode(CLzmaEncHandle p, unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,
|
||||
int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||
ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
|
||||
SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
|
||||
int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
|
||||
|
||||
|
||||
/* ---------- One Call Interface ---------- */
|
||||
|
||||
/* LzmaEncode
|
||||
Return code:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_PARAM - Incorrect paramater
|
||||
SZ_ERROR_OUTPUT_EOF - output buffer overflow
|
||||
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
|
||||
*/
|
||||
|
||||
SRes LzmaEncode(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,
|
||||
const CLzmaEncProps *props, unsigned char *propsEncoded, size_t *propsSize, int writeEndMark,
|
||||
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||
SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
|
||||
const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
|
||||
ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
/* Precomp.h -- StdAfx
|
||||
2013-11-12 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_PRECOMP_H
|
||||
#define __7Z_PRECOMP_H
|
||||
|
||||
#include "Compiler.h"
|
||||
/* #include "7zTypes.h" */
|
||||
|
||||
#endif
|
||||
+2
@@ -57,7 +57,9 @@ void Discord_RunCallbacks(void);
|
||||
|
||||
/* If you disable the lib starting its own I/O thread,
|
||||
* you'll need to call this from your own */
|
||||
#ifdef DISCORD_DISABLE_IO_THREAD
|
||||
void Discord_UpdateConnection(void);
|
||||
#endif
|
||||
|
||||
void Discord_UpdatePresence(const DiscordRichPresence* presence);
|
||||
void Discord_ClearPresence(void);
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@ struct BaseConnectionUnix : public BaseConnection {
|
||||
int sock{-1};
|
||||
};
|
||||
|
||||
static BaseConnectionUnix Connection;
|
||||
static BaseConnectionUnix ConnectionUnix;
|
||||
static sockaddr_un PipeAddr{};
|
||||
#ifdef MSG_NOSIGNAL
|
||||
static int MsgFlags = MSG_NOSIGNAL;
|
||||
@@ -34,7 +34,7 @@ static const char* GetTempPath(void)
|
||||
/*static*/ BaseConnection* BaseConnection::Create()
|
||||
{
|
||||
PipeAddr.sun_family = AF_UNIX;
|
||||
return &Connection;
|
||||
return &ConnectionUnix;
|
||||
}
|
||||
|
||||
/*static*/ void BaseConnection::Destroy(BaseConnection*& c)
|
||||
|
||||
Vendored
+134
-58
@@ -10,10 +10,22 @@
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
|
||||
#ifndef DISCORD_DISABLE_IO_THREAD
|
||||
#include <condition_variable>
|
||||
#include <thread>
|
||||
#endif
|
||||
|
||||
struct QueuedMessage
|
||||
{
|
||||
size_t length;
|
||||
char buffer[16384];
|
||||
|
||||
void Copy(const QueuedMessage& other)
|
||||
{
|
||||
length = other.length;
|
||||
if (length)
|
||||
memcpy(buffer, other.buffer, length);
|
||||
}
|
||||
};
|
||||
|
||||
struct User
|
||||
@@ -68,13 +80,66 @@ static User connectedUser;
|
||||
static Backoff ReconnectTimeMs(500, 60 * 1000);
|
||||
static auto NextConnect = std::chrono::system_clock::now();
|
||||
|
||||
static void update_reconnect_time(void)
|
||||
#ifndef DISCORD_DISABLE_IO_THREAD
|
||||
static void Discord_UpdateConnection(void);
|
||||
class IoThreadHolder
|
||||
{
|
||||
private:
|
||||
std::atomic_bool keepRunning{true};
|
||||
std::mutex waitForIOMutex;
|
||||
std::condition_variable waitForIOActivity;
|
||||
std::thread ioThread;
|
||||
|
||||
public:
|
||||
void Start()
|
||||
{
|
||||
keepRunning.store(true);
|
||||
ioThread = std::thread([&]() {
|
||||
const std::chrono::duration<int64_t, std::milli> maxWait{500LL};
|
||||
Discord_UpdateConnection();
|
||||
while (keepRunning.load()) {
|
||||
std::unique_lock<std::mutex> lock(waitForIOMutex);
|
||||
waitForIOActivity.wait_for(lock, maxWait);
|
||||
Discord_UpdateConnection();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Notify() { waitForIOActivity.notify_all(); }
|
||||
|
||||
void Stop()
|
||||
{
|
||||
keepRunning.exchange(false);
|
||||
Notify();
|
||||
if (ioThread.joinable())
|
||||
ioThread.join();
|
||||
}
|
||||
|
||||
~IoThreadHolder() { Stop(); }
|
||||
};
|
||||
#else
|
||||
class IoThreadHolder
|
||||
{
|
||||
public:
|
||||
void Start() {}
|
||||
void Stop() {}
|
||||
void Notify() {}
|
||||
};
|
||||
#endif /* DISCORD_DISABLE_IO_THREAD */
|
||||
|
||||
static IoThreadHolder* IoThread{nullptr};
|
||||
|
||||
static void UpdateReconnectTime(void)
|
||||
{
|
||||
NextConnect = std::chrono::system_clock::now() +
|
||||
std::chrono::duration<int64_t, std::milli>{ReconnectTimeMs.nextDelay()};
|
||||
}
|
||||
|
||||
#ifdef DISCORD_DISABLE_IO_THREAD
|
||||
extern "C" void Discord_UpdateConnection(void)
|
||||
#else
|
||||
static void Discord_UpdateConnection(void)
|
||||
#endif
|
||||
{
|
||||
if (!Connection)
|
||||
return;
|
||||
@@ -83,7 +148,7 @@ extern "C" void Discord_UpdateConnection(void)
|
||||
{
|
||||
if (std::chrono::system_clock::now() >= NextConnect)
|
||||
{
|
||||
update_reconnect_time();
|
||||
UpdateReconnectTime();
|
||||
Connection->Open();
|
||||
}
|
||||
}
|
||||
@@ -203,19 +268,16 @@ extern "C" void Discord_UpdateConnection(void)
|
||||
if (QueuedPresence.length)
|
||||
{
|
||||
QueuedMessage local;
|
||||
std::lock_guard<std::mutex> guard(PresenceMutex);
|
||||
local.length = QueuedPresence.length;
|
||||
if (local.length)
|
||||
memcpy(local.buffer, QueuedPresence.buffer, local.length);
|
||||
QueuedPresence.length = 0;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(PresenceMutex);
|
||||
local.Copy(QueuedPresence);
|
||||
QueuedPresence.length = 0;
|
||||
}
|
||||
if (!Connection->Write(local.buffer, local.length))
|
||||
{
|
||||
/* if we fail to send, requeue */
|
||||
std::lock_guard<std::mutex> guard(PresenceMutex);
|
||||
QueuedPresence.length = local.length;
|
||||
if (QueuedPresence.length)
|
||||
memcpy(QueuedPresence.buffer, local.buffer, QueuedPresence.length);
|
||||
QueuedPresence.Copy(local);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,6 +298,8 @@ static bool RegisterForEvent(const char* evtName)
|
||||
qmessage->length =
|
||||
JsonWriteSubscribeCommand(qmessage->buffer, sizeof(qmessage->buffer), Nonce++, evtName);
|
||||
SendQueue.CommitAdd();
|
||||
if (IoThread)
|
||||
IoThread->Notify();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -249,6 +313,8 @@ static bool DeregisterForEvent(const char* evtName)
|
||||
qmessage->length =
|
||||
JsonWriteUnsubscribeCommand(qmessage->buffer, sizeof(qmessage->buffer), Nonce++, evtName);
|
||||
SendQueue.CommitAdd();
|
||||
if (IoThread)
|
||||
IoThread->Notify();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -260,6 +326,10 @@ extern "C" void Discord_Initialize(
|
||||
int autoRegister,
|
||||
const char* optionalSteamId)
|
||||
{
|
||||
IoThread = new (std::nothrow) IoThreadHolder();
|
||||
if (!IoThread)
|
||||
return;
|
||||
|
||||
if (autoRegister)
|
||||
{
|
||||
if (optionalSteamId && optionalSteamId[0])
|
||||
@@ -284,38 +354,34 @@ extern "C" void Discord_Initialize(
|
||||
if (Connection)
|
||||
return;
|
||||
|
||||
Connection = RpcConnection::Create(applicationId);
|
||||
Connection = RpcConnection::Create(applicationId);
|
||||
Connection->onConnect = [](JsonDocument& readyMessage)
|
||||
{
|
||||
Discord_UpdateHandlers(&QueuedHandlers);
|
||||
char *userId = NULL;
|
||||
char *username = NULL;
|
||||
char *avatar = NULL;
|
||||
char *discriminator = NULL;
|
||||
bool in_data = false;
|
||||
bool in_user = false;
|
||||
|
||||
Discord_UpdateHandlers(&QueuedHandlers);
|
||||
|
||||
bool in_data = false, in_user = false;
|
||||
for (JsonReader r(readyMessage); r.NextKey();)
|
||||
{
|
||||
if (r.depth == 1)
|
||||
{
|
||||
in_data = !strcmp(r.key,"data");
|
||||
in_user = false;
|
||||
}
|
||||
else if (r.depth == 2 && in_data)
|
||||
in_user = !strcmp(r.key, "user");
|
||||
else if (r.depth == 3 && in_user)
|
||||
{
|
||||
if (!strcmp(r.key, "id" ))
|
||||
r.NextStrDup(&userId);
|
||||
else if (!strcmp(r.key, "username" ))
|
||||
r.NextStrDup(&username);
|
||||
else if (!strcmp(r.key, "avatar" ))
|
||||
r.NextStrDup(&avatar);
|
||||
else if (!strcmp(r.key, "discriminator"))
|
||||
r.NextStrDup(&discriminator);
|
||||
}
|
||||
if (r.depth == 1)
|
||||
{
|
||||
in_data = !strcmp(r.key,"data");
|
||||
in_user = false;
|
||||
}
|
||||
else if (r.depth == 2 && in_data)
|
||||
{
|
||||
in_user = !strcmp(r.key, "user");
|
||||
}
|
||||
else if (r.depth == 3 && in_user)
|
||||
{
|
||||
if (!strcmp(r.key, "id" )) r.NextStrDup(&userId);
|
||||
else if (!strcmp(r.key, "username" )) r.NextStrDup(&username);
|
||||
else if (!strcmp(r.key, "avatar" )) r.NextStrDup(&avatar);
|
||||
else if (!strcmp(r.key, "discriminator")) r.NextStrDup(&discriminator);
|
||||
}
|
||||
}
|
||||
|
||||
if (userId && username)
|
||||
@@ -332,14 +398,10 @@ extern "C" void Discord_Initialize(
|
||||
WasJustConnected.exchange(true);
|
||||
ReconnectTimeMs.reset();
|
||||
|
||||
if (userId)
|
||||
free(userId);
|
||||
if (username)
|
||||
free(username);
|
||||
if (avatar)
|
||||
free(avatar);
|
||||
if (discriminator)
|
||||
free(discriminator);
|
||||
if (userId ) free(userId );
|
||||
if (username ) free(username );
|
||||
if (avatar ) free(avatar );
|
||||
if (discriminator) free(discriminator);
|
||||
};
|
||||
Connection->onDisconnect = [](int err, const char* message)
|
||||
{
|
||||
@@ -350,8 +412,10 @@ extern "C" void Discord_Initialize(
|
||||
Handlers = {};
|
||||
}
|
||||
WasJustDisconnected.exchange(true);
|
||||
update_reconnect_time();
|
||||
UpdateReconnectTime();
|
||||
};
|
||||
|
||||
IoThread->Start();
|
||||
}
|
||||
|
||||
extern "C" void Discord_Shutdown(void)
|
||||
@@ -360,17 +424,26 @@ extern "C" void Discord_Shutdown(void)
|
||||
return;
|
||||
Connection->onConnect = nullptr;
|
||||
Connection->onDisconnect = nullptr;
|
||||
Handlers = {};
|
||||
Handlers = {};
|
||||
if (IoThread)
|
||||
{
|
||||
IoThread->Stop();
|
||||
delete IoThread;
|
||||
IoThread = nullptr;
|
||||
}
|
||||
|
||||
RpcConnection::Destroy(Connection);
|
||||
}
|
||||
|
||||
extern "C" void Discord_UpdatePresence(const DiscordRichPresence* presence)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(PresenceMutex);
|
||||
QueuedPresence.length = JsonWriteRichPresenceObj(
|
||||
QueuedPresence.buffer, sizeof(QueuedPresence.buffer),
|
||||
Nonce++, Pid, presence);
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(PresenceMutex);
|
||||
QueuedPresence.length = JsonWriteRichPresenceObj(
|
||||
QueuedPresence.buffer, sizeof(QueuedPresence.buffer), Nonce++, Pid, presence);
|
||||
}
|
||||
if (IoThread)
|
||||
IoThread->Notify();
|
||||
}
|
||||
|
||||
extern "C" void Discord_ClearPresence(void)
|
||||
@@ -378,8 +451,7 @@ extern "C" void Discord_ClearPresence(void)
|
||||
Discord_UpdatePresence(nullptr);
|
||||
}
|
||||
|
||||
extern "C" void Discord_Respond(const char* userId,
|
||||
/* DISCORD_REPLY_ */ int reply)
|
||||
extern "C" void Discord_Respond(const char* userId, /* DISCORD_REPLY_ */ int reply)
|
||||
{
|
||||
/* if we are not connected, let's not batch up stale messages for later */
|
||||
if (!Connection || !Connection->IsOpen())
|
||||
@@ -390,6 +462,8 @@ extern "C" void Discord_Respond(const char* userId,
|
||||
qmessage->length =
|
||||
JsonWriteJoinReply(qmessage->buffer, sizeof(qmessage->buffer), userId, reply, Nonce++);
|
||||
SendQueue.CommitAdd();
|
||||
if (IoThread)
|
||||
IoThread->Notify();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -456,14 +530,16 @@ extern "C" void Discord_RunCallbacks(void)
|
||||
*/
|
||||
while (JoinAskQueue.HavePendingSends())
|
||||
{
|
||||
auto req = JoinAskQueue.GetNextSendMessage();
|
||||
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||
if (Handlers.joinRequest)
|
||||
{
|
||||
DiscordUser du{req->userId, req->username, req->discriminator, req->avatar};
|
||||
Handlers.joinRequest(&du);
|
||||
}
|
||||
JoinAskQueue.CommitSend();
|
||||
auto req = JoinAskQueue.GetNextSendMessage();
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(HandlerMutex);
|
||||
if (Handlers.joinRequest)
|
||||
{
|
||||
DiscordUser du{req->userId, req->username, req->discriminator, req->avatar};
|
||||
Handlers.joinRequest(&du);
|
||||
}
|
||||
}
|
||||
JoinAskQueue.CommitSend();
|
||||
}
|
||||
|
||||
if (!isConnected)
|
||||
|
||||
Loaded 100 of 821 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user