mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-08 07:28:22 -10:00
Compare commits
663
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
022a04472c | ||
|
|
e80b91c27e | ||
|
|
26a66f9c53 | ||
|
|
a337c9a5d5 | ||
|
|
85da72fb16 | ||
|
|
13ee1bdb60 | ||
|
|
02465b9db6 | ||
|
|
b33417a918 | ||
|
|
f802db8345 | ||
|
|
56054d6782 | ||
|
|
1c3fb592cb | ||
|
|
049870c973 | ||
|
|
22c0882bc6 | ||
|
|
ffd3fbd922 | ||
|
|
42e496d103 | ||
|
|
71f159840b | ||
|
|
854041749b | ||
|
|
a4a77744d6 | ||
|
|
dac335f3dd | ||
|
|
275ba09a3b | ||
|
|
40ab7fc0f3 | ||
|
|
3b16380936 | ||
|
|
67e18e30a7 | ||
|
|
293e984d60 | ||
|
|
35bf641cb7 | ||
|
|
c86461fd22 | ||
|
|
498edeb86e | ||
|
|
e6c7719bf4 | ||
|
|
e907a052e5 | ||
|
|
6f089c21c5 | ||
|
|
3d8ad87da9 | ||
|
|
92a0ed3c6d | ||
|
|
988b86238f | ||
|
|
f2c019adc3 | ||
|
|
bda256f095 | ||
|
|
77e48b4849 | ||
|
|
0ea85483dc | ||
|
|
54a034da9a | ||
|
|
84d249db18 | ||
|
|
5a1b5233b8 | ||
|
|
3a88ee37ed | ||
|
|
67464a2ad4 | ||
|
|
e1775947ec | ||
|
|
f18771b309 | ||
|
|
1716850f80 | ||
|
|
9ff5945744 | ||
|
|
13d91d590b | ||
|
|
4611c36631 | ||
|
|
0d5eb222a9 | ||
|
|
3508e8d309 | ||
|
|
cafe8965c1 | ||
|
|
5604bced59 | ||
|
|
08e2943edb | ||
|
|
656623be9c | ||
|
|
3ccc1da630 | ||
|
|
01c12c8010 | ||
|
|
dbd2ee4f3c | ||
|
|
84a5ae3268 | ||
|
|
949d8446f1 | ||
|
|
f7e17e90a7 | ||
|
|
f0078cc8fc | ||
|
|
833164823d | ||
|
|
77deede2de | ||
|
|
085a0aa0d4 | ||
|
|
3edcb0a519 | ||
|
|
c6ba1645a1 | ||
|
|
e1d2dfcf9e | ||
|
|
dccaa30202 | ||
|
|
e205ab47a2 | ||
|
|
a2e351779d | ||
|
|
f85ca67666 | ||
|
|
e1261c0340 | ||
|
|
89e4dc4fd5 | ||
|
|
fa480451d1 | ||
|
|
a42cf30bdb | ||
|
|
225bc96739 | ||
|
|
e15beaa7f9 | ||
|
|
fcc1ea98c4 | ||
|
|
afb0e066b0 | ||
|
|
7b5548642a | ||
|
|
5f1898c503 | ||
|
|
7854fb293f | ||
|
|
1e04df322c | ||
|
|
fb12c1df6e | ||
|
|
c4fcafccc5 | ||
|
|
cfbc2ebb46 | ||
|
|
4a85d415e5 | ||
|
|
94c2fab5b0 | ||
|
|
d6b179d3b5 | ||
|
|
32f7fd2c11 | ||
|
|
5a858562cc | ||
|
|
eb800ebbbc | ||
|
|
f3bd46dab2 | ||
|
|
b11a8c02a0 | ||
|
|
7564ecb19f | ||
|
|
65fd9ef338 | ||
|
|
aab49a95db | ||
|
|
f0110fab45 | ||
|
|
3c053feb30 | ||
|
|
68fde7a8ce | ||
|
|
abf067f708 | ||
|
|
0151279a55 | ||
|
|
633c391b4d | ||
|
|
fee9ff59ef | ||
|
|
290da64ffe | ||
|
|
46479ac3a0 | ||
|
|
016e525f62 | ||
|
|
58cb8f4a36 | ||
|
|
240c74da4e | ||
|
|
897d3f8ad5 | ||
|
|
3916653149 | ||
|
|
0baf2f7bc9 | ||
|
|
ef83ecbc05 | ||
|
|
53834ee415 | ||
|
|
7dcc40de8a | ||
|
|
edfd3fdc85 | ||
|
|
39e9cddb5f | ||
|
|
450ea5c63e | ||
|
|
36668ce6a1 | ||
|
|
8cacc9b1a0 | ||
|
|
03dd93b79d | ||
|
|
ee79809edc | ||
|
|
257675bb93 | ||
|
|
d9a01620f6 | ||
|
|
3b15d779d6 | ||
|
|
19796f7538 | ||
|
|
e594563d00 | ||
|
|
15d394edbf | ||
|
|
b07476fc96 | ||
|
|
d3e4c5c30b | ||
|
|
839be403b1 | ||
|
|
5c2c0ab09f | ||
|
|
81f8a9e375 | ||
|
|
4386cab9bc | ||
|
|
00773de340 | ||
|
|
450bd1e213 | ||
|
|
2092c2705f | ||
|
|
e592c64d8f | ||
|
|
0f275acc12 | ||
|
|
af1da198b3 | ||
|
|
e75e4b5640 | ||
|
|
9ed49694bf | ||
|
|
b0088c67ba | ||
|
|
3505a530d0 | ||
|
|
ec87a1f3ad | ||
|
|
0c9c758dbd | ||
|
|
17a9178c8b | ||
|
|
7628e19f26 | ||
|
|
97b506ca15 | ||
|
|
7c1c973917 | ||
|
|
e7340e703b | ||
|
|
1fa5e2bf54 | ||
|
|
dc12e5dd1e | ||
|
|
2c62498b62 | ||
|
|
2eb193101a | ||
|
|
11d8d11b04 | ||
|
|
37b0bd28ce | ||
|
|
13cccac317 | ||
|
|
4fce3b9610 | ||
|
|
fc22d35695 | ||
|
|
091c8b4d7e | ||
|
|
8d4512a612 | ||
|
|
c80bab1fcc | ||
|
|
ca0683ecfa | ||
|
|
31cfd8011f | ||
|
|
371f2e3869 | ||
|
|
cd48667a38 | ||
|
|
45d02246ee | ||
|
|
25e339a4d6 | ||
|
|
155f0f1cce | ||
|
|
807ee34c9d | ||
|
|
123515a33d | ||
|
|
cc741f5029 | ||
|
|
0fc5f831fc | ||
|
|
ecf181a2c7 | ||
|
|
000257bd8e | ||
|
|
30cbbfedf3 | ||
|
|
47cd793262 | ||
|
|
ed6be03aa0 | ||
|
|
afd83a21fb | ||
|
|
4a030dfb73 | ||
|
|
e4b6bc70bc | ||
|
|
fcaa985c2d | ||
|
|
3574628259 | ||
|
|
be71b9f6b5 | ||
|
|
5f5fe2b8cc | ||
|
|
5ff5467673 | ||
|
|
809b0155df | ||
|
|
1e6670c1b7 | ||
|
|
bda9f63f59 | ||
|
|
ea966211b5 | ||
|
|
1771fd2d3b | ||
|
|
7dd22631a9 | ||
|
|
7146c9f90c | ||
|
|
63a90da345 | ||
|
|
29a0e77753 | ||
|
|
1760554305 | ||
|
|
3f391d36b2 | ||
|
|
fee9efe1db | ||
|
|
c8a2551a6e | ||
|
|
9e5a3781b7 | ||
|
|
fa960dc625 | ||
|
|
364767a0b4 | ||
|
|
abdd8a6a79 | ||
|
|
15be002888 | ||
|
|
af9f703302 | ||
|
|
944981b835 | ||
|
|
f7760d69c0 | ||
|
|
b63c14fcb7 | ||
|
|
7ec2608d58 | ||
|
|
881b31f7fa | ||
|
|
6be53b57e1 | ||
|
|
13338a1c76 | ||
|
|
f843302d16 | ||
|
|
f4fe757d5d | ||
|
|
1a410e1f09 | ||
|
|
79fff22d2e | ||
|
|
e6536f612a | ||
|
|
031c50768a | ||
|
|
a805b8e293 | ||
|
|
7145251058 | ||
|
|
5a5e364bee | ||
|
|
6351a06b68 | ||
|
|
4dd27db603 | ||
|
|
d01ed806b9 | ||
|
|
2b6c194af7 | ||
|
|
87409846f0 | ||
|
|
88dca1dbea | ||
|
|
4bf29edec3 | ||
|
|
d1abacf7ae | ||
|
|
9d6126086c | ||
|
|
4c74af0b4a | ||
|
|
fb738a9319 | ||
|
|
c470ecc598 | ||
|
|
47302dd5ad | ||
|
|
431b588cef | ||
|
|
0f931f0275 | ||
|
|
0a3a0c525f | ||
|
|
c818bd61d5 | ||
|
|
3e220d87f0 | ||
|
|
58691c0d15 | ||
|
|
a59a1bbaad | ||
|
|
1d84bd94ea | ||
|
|
e777b3806e | ||
|
|
74afd2522f | ||
|
|
da831bf833 | ||
|
|
d21190d765 | ||
|
|
ae2eefeb92 | ||
|
|
c0968ba348 | ||
|
|
d469a505c4 | ||
|
|
34244e313b | ||
|
|
d77c3feef5 | ||
|
|
0fa9b99445 | ||
|
|
433688cc92 | ||
|
|
790af7d332 | ||
|
|
4fb733df43 | ||
|
|
0794d14a7a | ||
|
|
324747af39 | ||
|
|
5377b50e53 | ||
|
|
b745b8e545 | ||
|
|
cfa65cfe5c | ||
|
|
7d52af37fa | ||
|
|
d8f9376d55 | ||
|
|
2c95fa52f8 | ||
|
|
993740e06f | ||
|
|
da67b2b53c | ||
|
|
7d08fec7cc | ||
|
|
6ec2c31678 | ||
|
|
e469a54429 | ||
|
|
2352055d98 | ||
|
|
7892625474 | ||
|
|
58a1497614 | ||
|
|
76d94278a8 | ||
|
|
47b2c3cd88 | ||
|
|
1f55e87876 | ||
|
|
cdd1a0b743 | ||
|
|
f864a28bb3 | ||
|
|
993a176572 | ||
|
|
414a344f33 | ||
|
|
28848dcbc8 | ||
|
|
ea32341410 | ||
|
|
ad53507f1c | ||
|
|
8f9e7cf941 | ||
|
|
1f1339cb01 | ||
|
|
e5eafea546 | ||
|
|
373d2c201c | ||
|
|
ec63b64b1f | ||
|
|
e6da9a6d68 | ||
|
|
4fac9708ec | ||
|
|
71d4bd62b2 | ||
|
|
3e96899ace | ||
|
|
51c590c6a6 | ||
|
|
e7d1452827 | ||
|
|
137e7a8cdd | ||
|
|
77f769b328 | ||
|
|
c85cb1377b | ||
|
|
f3362d6a2f | ||
|
|
043310f88a | ||
|
|
46f524706c | ||
|
|
7b7df3caba | ||
|
|
a47ff4d7a5 | ||
|
|
70fc3119e7 | ||
|
|
830be35c58 | ||
|
|
2fff39194f | ||
|
|
fffa377d2f | ||
|
|
a819e73388 | ||
|
|
0562965e69 | ||
|
|
7928823b96 | ||
|
|
3b92333b16 | ||
|
|
7238ae9025 | ||
|
|
f6634e882c | ||
|
|
f99a3916de | ||
|
|
cc9f972e80 | ||
|
|
609da60af3 | ||
|
|
7b794ea056 | ||
|
|
3f66617c68 | ||
|
|
f8f60965a9 | ||
|
|
6f0832c6d8 | ||
|
|
33c321d328 | ||
|
|
16fdb53870 | ||
|
|
b5ab80797d | ||
|
|
1385a9c6ac | ||
|
|
a11c390fd5 | ||
|
|
a498b79b2d | ||
|
|
6a22f2443e | ||
|
|
cd2597f3a2 | ||
|
|
d32a38c267 | ||
|
|
64bcc9942e | ||
|
|
cf750429cb | ||
|
|
32843f18f8 | ||
|
|
d7bd110ffe | ||
|
|
36176b8eb4 | ||
|
|
8c94fbd199 | ||
|
|
d9e1e01afc | ||
|
|
8edec19426 | ||
|
|
5419f3b5de | ||
|
|
6df0403964 | ||
|
|
2bef522bfc | ||
|
|
4e86a928b3 | ||
|
|
254b4f6603 | ||
|
|
7373203236 | ||
|
|
55a4c34bab | ||
|
|
b060ac5928 | ||
|
|
ab27958761 | ||
|
|
dca1600f46 | ||
|
|
218ac8a0d7 | ||
|
|
cac96f1a44 | ||
|
|
55948f0db1 | ||
|
|
c80033de55 | ||
|
|
dd378506ee | ||
|
|
9e890d8df5 | ||
|
|
f4030700dc | ||
|
|
b7f924ea6b | ||
|
|
c5c4fd08e9 | ||
|
|
bf7871905e | ||
|
|
28ef47c26f | ||
|
|
7a6e12df06 | ||
|
|
97130623dc | ||
|
|
a1ad295557 | ||
|
|
ecc552eda8 | ||
|
|
56d7afd8a0 | ||
|
|
46e465b1d2 | ||
|
|
4c52cb0441 | ||
|
|
4da09ccefc | ||
|
|
389921bd48 | ||
|
|
e9f6827211 | ||
|
|
042d935a80 | ||
|
|
1f7fee5baa | ||
|
|
ff33077291 | ||
|
|
70c909302c | ||
|
|
900f57bc94 | ||
|
|
41fabe25bd | ||
|
|
1e634da6dd | ||
|
|
a4386862f5 | ||
|
|
7435ddd89b | ||
|
|
f1e5508023 | ||
|
|
0fd8e46ea2 | ||
|
|
cb4764e8d0 | ||
|
|
0c55ff682b | ||
|
|
8659222b82 | ||
|
|
64b2332534 | ||
|
|
303278228a | ||
|
|
16baec8877 | ||
|
|
0b7cc9aa9d | ||
|
|
77bc1ed93b | ||
|
|
d2969046d4 | ||
|
|
b3c67343e5 | ||
|
|
f26624902f | ||
|
|
f96196c271 | ||
|
|
f47b3c0fd0 | ||
|
|
170ac43ebe | ||
|
|
93e0b43b03 | ||
|
|
b9c9069c5a | ||
|
|
fdc9b42d14 | ||
|
|
6cb690996d | ||
|
|
eb63396934 | ||
|
|
f1aa394d29 | ||
|
|
415969fca0 | ||
|
|
dfbd9ad9d0 | ||
|
|
a50424930b | ||
|
|
9843ff7b49 | ||
|
|
7ea79b3ed4 | ||
|
|
b783b7e364 | ||
|
|
60d0011159 | ||
|
|
e730044cc1 | ||
|
|
60ea566ecc | ||
|
|
fd797419dd | ||
|
|
3a5a785f51 | ||
|
|
65564198ef | ||
|
|
def0b0ceb0 | ||
|
|
01776721ab | ||
|
|
6f7d012184 | ||
|
|
7d4d468e58 | ||
|
|
d1a870b372 | ||
|
|
680e55e493 | ||
|
|
c779bae39a | ||
|
|
5a4fafec31 | ||
|
|
cfcc94c2bb | ||
|
|
8d1c8fad7c | ||
|
|
c6cc437092 | ||
|
|
6a30e96439 | ||
|
|
95d7869aa6 | ||
|
|
95a26b87ce | ||
|
|
6c0bfdd0b7 | ||
|
|
0e19a3a614 | ||
|
|
35350315b7 | ||
|
|
8f97380d75 | ||
|
|
fe6bac98c7 | ||
|
|
77c5502b19 | ||
|
|
065eb6f1d5 | ||
|
|
103e4b2b22 | ||
|
|
cb4e5b551f | ||
|
|
c22d9a7e99 | ||
|
|
2b52cf3896 | ||
|
|
5b16bd3748 | ||
|
|
40bbe0cd39 | ||
|
|
661dc39d9c | ||
|
|
07c240e9a1 | ||
|
|
93f20cb8e4 | ||
|
|
e512f60386 | ||
|
|
59442ea786 | ||
|
|
ee8a7f67a7 | ||
|
|
c2c24787da | ||
|
|
60f69cb79b | ||
|
|
3bc70fc2c2 | ||
|
|
f09a3c0a09 | ||
|
|
f15a879898 | ||
|
|
984f3f0aa7 | ||
|
|
1559d18757 | ||
|
|
c2c0ca0eeb | ||
|
|
754c35f2f5 | ||
|
|
2bbd5a806b | ||
|
|
5891192fda | ||
|
|
5effb36530 | ||
|
|
bc72cea911 | ||
|
|
ec8886cf09 | ||
|
|
bce0cc4ca0 | ||
|
|
66eaf28ac8 | ||
|
|
d728b3d745 | ||
|
|
11426ed5a2 | ||
|
|
386abb7000 | ||
|
|
476fb7bbfc | ||
|
|
c825720ae0 | ||
|
|
6e407fff7b | ||
|
|
11b24d23aa | ||
|
|
2135e20299 | ||
|
|
123277167b | ||
|
|
4a9f85674f | ||
|
|
719579177e | ||
|
|
3f6a1f33d4 | ||
|
|
688dee73c2 | ||
|
|
5fa10d82f4 | ||
|
|
4cde77929f | ||
|
|
41f66ee2f3 | ||
|
|
2ee9db9479 | ||
|
|
f87883712e | ||
|
|
ea22ebfe09 | ||
|
|
0edd905be5 | ||
|
|
47e2ff7500 | ||
|
|
c011621363 | ||
|
|
8c47d95901 | ||
|
|
e08be40462 | ||
|
|
d7022ad67b | ||
|
|
38f435eba8 | ||
|
|
6f429c16ee | ||
|
|
dfaebd0908 | ||
|
|
d6abb06544 | ||
|
|
d950369202 | ||
|
|
745fc385e9 | ||
|
|
f02a1caced | ||
|
|
e547962d31 | ||
|
|
31fe8e2a4c | ||
|
|
1b1dc86fb6 | ||
|
|
7539390fc3 | ||
|
|
ad7b508184 | ||
|
|
0fa37a5b62 | ||
|
|
1cbfc73384 | ||
|
|
c58ae29dd5 | ||
|
|
96e442b564 | ||
|
|
e817f867af | ||
|
|
8c8c96bb89 | ||
|
|
f0e7af10bb | ||
|
|
4e44bcfdef | ||
|
|
d4cea3a9ff | ||
|
|
f06b7dfd20 | ||
|
|
6dd4f692e2 | ||
|
|
d860dc0011 | ||
|
|
d5d8e66dee | ||
|
|
ad4843b8ea | ||
|
|
3162ede091 | ||
|
|
f9e3871b3e | ||
|
|
53abc32182 | ||
|
|
39267bcb05 | ||
|
|
7398df34ec | ||
|
|
62c8792c2a | ||
|
|
e561a547a7 | ||
|
|
5128907c07 | ||
|
|
5ddef96ccc | ||
|
|
e75251141a | ||
|
|
4f419025fe | ||
|
|
c6cf69e4a3 | ||
|
|
10e444df95 | ||
|
|
eeab39d62d | ||
|
|
28e46d411b | ||
|
|
1195eb3ada | ||
|
|
5f779fae4c | ||
|
|
cdb274654e | ||
|
|
b486c02ac8 | ||
|
|
9bcb08776c | ||
|
|
d36c788e00 | ||
|
|
00bbac6ae1 | ||
|
|
40db1ce831 | ||
|
|
bbf18d5667 | ||
|
|
377f78db0f | ||
|
|
ad96da3537 | ||
|
|
db8cf9134f | ||
|
|
0d65873a0b | ||
|
|
c38ff6302d | ||
|
|
abc9a3ddb1 | ||
|
|
650c4dea46 | ||
|
|
a2d1cf8f37 | ||
|
|
23c449af6c | ||
|
|
2d548f46bf | ||
|
|
c3c4ce064c | ||
|
|
fb7a0d5257 | ||
|
|
f8351a9818 | ||
|
|
5aefddd246 | ||
|
|
facefe5872 | ||
|
|
ef794efbb3 | ||
|
|
573a1f2fa3 | ||
|
|
a763d84b56 | ||
|
|
c06ccbb602 | ||
|
|
ffd8a5ae2a | ||
|
|
aa753d5d6e | ||
|
|
1cf042064f | ||
|
|
a4e14a94d2 | ||
|
|
5871d644cc | ||
|
|
145a149873 | ||
|
|
7492c51ee6 | ||
|
|
be4954a69e | ||
|
|
875a95b82e | ||
|
|
f6b129577b | ||
|
|
4d30bbba3e | ||
|
|
8823dc67eb | ||
|
|
8690c9d7f6 | ||
|
|
f70d242903 | ||
|
|
5b4306dbd6 | ||
|
|
013870fc6a | ||
|
|
0e3d4e562f | ||
|
|
48d1ec4575 | ||
|
|
32ad077676 | ||
|
|
9942308fc8 | ||
|
|
af3b97aae5 | ||
|
|
c3c0b0e1f4 | ||
|
|
9d5863bc76 | ||
|
|
4b2d436b04 | ||
|
|
404195d389 | ||
|
|
df29aad213 | ||
|
|
026601e350 | ||
|
|
05a48addc6 | ||
|
|
a1e9e62b6e | ||
|
|
64ea61c93a | ||
|
|
a0bbf8fd54 | ||
|
|
15e9872bb5 | ||
|
|
a1f592ffef | ||
|
|
07de43ffc4 | ||
|
|
522fa4c906 | ||
|
|
7611e0a2d2 | ||
|
|
9290659edf | ||
|
|
3a88c2f9e3 | ||
|
|
a732686bf6 | ||
|
|
2ede27a557 | ||
|
|
8300b018f0 | ||
|
|
93aed25251 | ||
|
|
591563118c | ||
|
|
b59b5dd5d8 | ||
|
|
bb0bde6409 | ||
|
|
66a392ddae | ||
|
|
8bfc9fa709 | ||
|
|
ccbdeeff67 | ||
|
|
0f1176adaf | ||
|
|
b75fce3d5c | ||
|
|
ab68ad4855 | ||
|
|
426cf0b969 | ||
|
|
2d1f7ba50f | ||
|
|
69145e65f1 | ||
|
|
3dcb4b380a | ||
|
|
8e996fdf67 | ||
|
|
7367d8a31f | ||
|
|
d5fcfc773c | ||
|
|
5cdd3a676d | ||
|
|
fd95da4c0a | ||
|
|
1aa613e0f5 | ||
|
|
7d91a35878 | ||
|
|
fa2c566b3f | ||
|
|
f2b7f9718a | ||
|
|
08c0bd3aee | ||
|
|
3a39133e04 | ||
|
|
c3ec5825a4 | ||
|
|
baddd6703d | ||
|
|
0c3733d2cd | ||
|
|
c536d49afd | ||
|
|
b031aee73a | ||
|
|
c480e2c944 | ||
|
|
c7cd913df4 | ||
|
|
58a465e805 | ||
|
|
cf08ff0cd5 | ||
|
|
c839e8168a | ||
|
|
3257777c18 | ||
|
|
1028e14398 | ||
|
|
b733679875 | ||
|
|
723cbd5938 | ||
|
|
0e48ea11ac | ||
|
|
57ab92645c | ||
|
|
2431f5db2c | ||
|
|
34d960638a | ||
|
|
3bb26b10a3 | ||
|
|
3cdc511b2d | ||
|
|
4543d0c80c | ||
|
|
2a740ad2c8 | ||
|
|
7187da0233 | ||
|
|
ab43e4d987 | ||
|
|
8056476db1 | ||
|
|
4b471d6045 | ||
|
|
8b19d7c8eb | ||
|
|
90c6679f03 | ||
|
|
4c73e5fe20 | ||
|
|
dd3a3138a7 | ||
|
|
9e8a091172 | ||
|
|
5d72560a30 | ||
|
|
2a9c65bd3f | ||
|
|
6b4cca55be | ||
|
|
c18139e73f | ||
|
|
be6ee814c2 | ||
|
|
ea6130e542 | ||
|
|
48a566a2d5 | ||
|
|
dab5b293d4 | ||
|
|
2a2cd3c873 | ||
|
|
51ffb56b16 | ||
|
|
211e7a4284 | ||
|
|
24643586f1 | ||
|
|
08986cb47e | ||
|
|
c3d878b1b3 |
No files matched your search
@@ -1,182 +0,0 @@
|
||||
version: 2
|
||||
|
||||
references:
|
||||
container_config: &container_config
|
||||
docker:
|
||||
- image: "debian:stretch"
|
||||
working_directory: /root/build
|
||||
|
||||
restore_repo: &restore_repo
|
||||
restore_cache:
|
||||
keys:
|
||||
- source-repo-{{ .Branch }}-{{ .Revision }}
|
||||
- source-repo-{{ .Branch }}
|
||||
- source-repo
|
||||
|
||||
cmake_configure: &cmake_configure
|
||||
run:
|
||||
name: Creating Build Files
|
||||
command: |
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
CXXFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
|
||||
CFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
|
||||
|
||||
if [[ "$CC" =~ ^clang.*$ ]]; then
|
||||
CXXFLAGS="$CXXFLAGS -stdlib=libc++"
|
||||
fi
|
||||
|
||||
eval $CC --version
|
||||
|
||||
export CXXFLAGS
|
||||
export CFLAGS
|
||||
CMAKE="cmake -G Ninja -DFSO_FATAL_WARNINGS=ON $CMAKE_OPTIONS"
|
||||
eval $CMAKE -DCMAKE_BUILD_TYPE=$CONFIGURATION -DFSO_BUILD_TESTS=ON -DFSO_BUILD_INCLUDED_LIBS=ON ..
|
||||
|
||||
compile: &compile
|
||||
run:
|
||||
name: Compiling Source code
|
||||
command: |
|
||||
cd build
|
||||
ninja -k 20 all
|
||||
|
||||
run_tests: &run_tests
|
||||
run:
|
||||
name: Run unit tests
|
||||
command: |
|
||||
./build/bin/unittests --gtest_shuffle
|
||||
|
||||
compile_steps: &compile_steps
|
||||
steps:
|
||||
- *restore_repo
|
||||
- *cmake_configure
|
||||
- *compile
|
||||
- *run_tests
|
||||
jobs:
|
||||
checkout_code:
|
||||
<<: *container_config
|
||||
steps:
|
||||
- run:
|
||||
name: Installing Git
|
||||
command: 'apt-get update && apt-get -yq install git'
|
||||
- *restore_repo
|
||||
- checkout
|
||||
- run:
|
||||
name: Updating submodules
|
||||
command: 'git submodule update --init --recursive'
|
||||
- save_cache:
|
||||
key: source-repo-{{ .Branch }}-{{ .Revision }}
|
||||
paths:
|
||||
- .
|
||||
|
||||
build_gcc_lowest_debug:
|
||||
docker:
|
||||
- image: asarium/fso_compile:gcc-lowest
|
||||
working_directory: /root/build
|
||||
environment:
|
||||
CC: gcc
|
||||
CXX: g++
|
||||
CONFIGURATION: Debug
|
||||
<<: *compile_steps
|
||||
|
||||
build_gcc_lowest_release:
|
||||
docker:
|
||||
- image: asarium/fso_compile:gcc-lowest
|
||||
working_directory: /root/build
|
||||
environment:
|
||||
CC: gcc
|
||||
CXX: g++
|
||||
CONFIGURATION: Release
|
||||
<<: *compile_steps
|
||||
|
||||
build_gcc_latest_debug:
|
||||
docker:
|
||||
- image: asarium/fso_compile:gcc-latest
|
||||
working_directory: /root/build
|
||||
environment:
|
||||
CC: gcc
|
||||
CXX: g++
|
||||
CONFIGURATION: Debug
|
||||
<<: *compile_steps
|
||||
|
||||
build_gcc_latest_release:
|
||||
docker:
|
||||
- image: asarium/fso_compile:gcc-latest
|
||||
working_directory: /root/build
|
||||
environment:
|
||||
CC: gcc
|
||||
CXX: g++
|
||||
CONFIGURATION: Release
|
||||
<<: *compile_steps
|
||||
|
||||
build_clang_latest_debug:
|
||||
docker:
|
||||
- image: asarium/fso_compile:clang-latest
|
||||
working_directory: /root/build
|
||||
environment:
|
||||
CC: clang-8
|
||||
CXX: clang++-8
|
||||
CONFIGURATION: Debug
|
||||
<<: *compile_steps
|
||||
|
||||
build_clang_latest_release:
|
||||
docker:
|
||||
- image: asarium/fso_compile:clang-latest
|
||||
working_directory: /root/build
|
||||
environment:
|
||||
CC: clang-8
|
||||
CXX: clang++-8
|
||||
CONFIGURATION: Release
|
||||
<<: *compile_steps
|
||||
|
||||
build_clang_lowest_debug:
|
||||
docker:
|
||||
- image: asarium/fso_compile:clang-lowest
|
||||
working_directory: /root/build
|
||||
environment:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
CONFIGURATION: Debug
|
||||
<<: *compile_steps
|
||||
|
||||
build_clang_lowest_release:
|
||||
docker:
|
||||
- image: asarium/fso_compile:clang-lowest
|
||||
working_directory: /root/build
|
||||
environment:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
CONFIGURATION: Release
|
||||
<<: *compile_steps
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
|
||||
build_test:
|
||||
jobs:
|
||||
- checkout_code
|
||||
- build_gcc_lowest_debug:
|
||||
requires:
|
||||
- checkout_code
|
||||
- build_gcc_lowest_release:
|
||||
requires:
|
||||
- checkout_code
|
||||
- build_gcc_latest_debug:
|
||||
requires:
|
||||
- checkout_code
|
||||
- build_gcc_latest_release:
|
||||
requires:
|
||||
- checkout_code
|
||||
- build_clang_latest_debug:
|
||||
requires:
|
||||
- checkout_code
|
||||
- build_clang_latest_release:
|
||||
requires:
|
||||
- checkout_code
|
||||
- build_clang_lowest_debug:
|
||||
requires:
|
||||
- checkout_code
|
||||
- build_clang_lowest_release:
|
||||
requires:
|
||||
- checkout_code
|
||||
-100
@@ -1,100 +0,0 @@
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: true
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlinesLeft: false
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 120
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
|
||||
IncludeBlocks: Regroup
|
||||
IncludeCategories:
|
||||
- Regex: '^(<.*\.(h|hh|hpp)>)$' # Includes of external libraries
|
||||
Priority: 4
|
||||
- Regex: '^(<.*>)$' # standard library includes (won't match deprecated C headers)
|
||||
Priority: 5
|
||||
- Regex: '^"[^/]*\.(h)"$' # Local includes
|
||||
Priority: 1
|
||||
- Regex: '^".*\.(h)"$' # standard engine includes
|
||||
Priority: 2
|
||||
- Regex: '.*' # Catch all in case something is unhandled above
|
||||
Priority: 3
|
||||
IncludeIsMainRegex: '$'
|
||||
IndentCaseLabels: false
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Left
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
TabWidth: 4
|
||||
UseTab: ForIndentation
|
||||
...
|
||||
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
---
|
||||
Checks: "-*,\
|
||||
modernize-*,\
|
||||
-modernize-raw-string-literal,\
|
||||
-modernize-use-using,\
|
||||
-modernize-make-unique,\
|
||||
performance-*,\
|
||||
-performance-type-promotion-in-math-fn,\
|
||||
misc-*,\
|
||||
-misc-macro-parentheses,\
|
||||
-misc-misplaced-widening-cast,\
|
||||
-misc-static-assert,\
|
||||
-modernize-make-unique,\
|
||||
"
|
||||
WarningsAsErrors: ''
|
||||
HeaderFilterRegex: 'code/.*$|freespace2/.*$|qtfred/.*$|test/src/.*$|build/.*$'
|
||||
AnalyzeTemporaryDtors: false
|
||||
CheckOptions:
|
||||
- key: 'misc-assert-side-effect.AssertMacros'
|
||||
value: 'assert,Assert,Assertion'
|
||||
- key: 'modernize-use-emplace.ContainersWithPushBack'
|
||||
value: 'std::vector;std::deque;std::list;SCP_vector;SCP_deque;SCP_list'
|
||||
...
|
||||
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
|
||||
build:
|
||||
image: teaci/msys$$arch
|
||||
pull: true
|
||||
shell: mingw$$arch
|
||||
commands:
|
||||
- git submodule update --init --recursive
|
||||
- if [ $$arch = 32 ]; then target=i686; fi
|
||||
- if [ $$arch = 64 ]; then target=x86_64; fi
|
||||
- pacman -S --needed --noconfirm --noprogressbar mingw-w64-${target}-pkg-config mingw-w64-${target}-cmake
|
||||
- mkdir build && cd build
|
||||
- cmake -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=$$CONFIGURATION -DFSO_USE_SPEECH=OFF -DFSO_USE_VOICEREC=OFF -DFSO_FATAL_WARNINGS=ON -DFSO_BUILD_FRED2=OFF ..
|
||||
- make -j$(nproc) all
|
||||
|
||||
matrix:
|
||||
arch:
|
||||
- 64
|
||||
- 32
|
||||
CONFIGURATION:
|
||||
- Debug
|
||||
- Release
|
||||
@@ -1,7 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*.{h,cpp}]
|
||||
indent_style = tab
|
||||
|
||||
[*.sdr]
|
||||
indent_style = tab
|
||||
-259
@@ -1,259 +0,0 @@
|
||||
#OS junk files
|
||||
[Tt]humbs.db
|
||||
*.DS_Store
|
||||
|
||||
#Visual Studio files
|
||||
*.[Oo]bj
|
||||
*.user
|
||||
*.aps
|
||||
*.pch
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
*_i.c
|
||||
*_p.c
|
||||
*.ncb
|
||||
*.suo
|
||||
*.tlb
|
||||
*.tlh
|
||||
*.bak
|
||||
*.[Cc]ache
|
||||
*.ilk
|
||||
*.log
|
||||
*.lib
|
||||
*.sbr
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.unsuccessfulbuild
|
||||
ipch/
|
||||
[Oo]bj/
|
||||
Ankh.NoLoad
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
#MonoDevelop
|
||||
*.pidb
|
||||
*.userprefs
|
||||
|
||||
#Tooling
|
||||
_ReSharper*/
|
||||
*.resharper
|
||||
[Tt]est[Rr]esult*
|
||||
*.sass-cache
|
||||
|
||||
#Project files
|
||||
[Bb]uild/
|
||||
|
||||
#Subversion files
|
||||
.svn
|
||||
|
||||
# Office Temp Files
|
||||
~$*
|
||||
|
||||
# vim Temp Files
|
||||
*~
|
||||
|
||||
#NuGet
|
||||
packages/
|
||||
*.nupkg
|
||||
|
||||
#ncrunch
|
||||
*ncrunch*
|
||||
*crunch*.local.xml
|
||||
|
||||
# visual studio database projects
|
||||
*.dbmdl
|
||||
|
||||
#Test files
|
||||
*.testsettings
|
||||
|
||||
#===========
|
||||
|
||||
#########################
|
||||
# .gitignore file for Xcode4 and Xcode5 Source projects
|
||||
#
|
||||
# Apple bugs, waiting for Apple to fix/respond:
|
||||
#
|
||||
# 15564624 - what does the xccheckout file in Xcode5 do? Where's the documentation?
|
||||
#
|
||||
# Version 2.1
|
||||
# For latest version, see: http://stackoverflow.com/questions/49478/git-ignore-file-for-xcode-projects
|
||||
#
|
||||
# 2013 updates:
|
||||
# - fixed the broken "save personal Schemes"
|
||||
# - added line-by-line explanations for EVERYTHING (some were missing)
|
||||
#
|
||||
# NB: if you are storing "built" products, this WILL NOT WORK,
|
||||
# and you should use a different .gitignore (or none at all)
|
||||
# This file is for SOURCE projects, where there are many extra
|
||||
# files that we want to exclude
|
||||
#
|
||||
#########################
|
||||
|
||||
#####
|
||||
# OS X temporary files that should never be committed
|
||||
#
|
||||
# c.f. http://www.westwind.com/reference/os-x/invisibles.html
|
||||
|
||||
.DS_Store
|
||||
|
||||
# c.f. http://www.westwind.com/reference/os-x/invisibles.html
|
||||
|
||||
.Trashes
|
||||
|
||||
# c.f. http://www.westwind.com/reference/os-x/invisibles.html
|
||||
|
||||
*.swp
|
||||
|
||||
# *.lock - this is used and abused by many editors for many different things.
|
||||
# For the main ones I use (e.g. Eclipse), it should be excluded
|
||||
# from source-control, but YMMV
|
||||
|
||||
*.lock
|
||||
|
||||
#
|
||||
# profile - REMOVED temporarily (on double-checking, this seems incorrect; I can't find it in OS X docs?)
|
||||
#profile
|
||||
|
||||
|
||||
####
|
||||
# Xcode temporary files that should never be committed
|
||||
#
|
||||
# NB: NIB/XIB files still exist even on Storyboard projects, so we want this...
|
||||
|
||||
*~.nib
|
||||
|
||||
|
||||
####
|
||||
# Xcode build files -
|
||||
#
|
||||
# NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "DerivedData"
|
||||
|
||||
DerivedData/
|
||||
|
||||
# NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "build"
|
||||
|
||||
build/
|
||||
|
||||
|
||||
#####
|
||||
# Xcode private settings (window sizes, bookmarks, breakpoints, custom executables, smart groups)
|
||||
#
|
||||
# This is complicated:
|
||||
#
|
||||
# SOMETIMES you need to put this file in version control.
|
||||
# Apple designed it poorly - if you use "custom executables", they are
|
||||
# saved in this file.
|
||||
# 99% of projects do NOT use those, so they do NOT want to version control this file.
|
||||
# ..but if you're in the 1%, comment out the line "*.pbxuser"
|
||||
|
||||
# .pbxuser: http://lists.apple.com/archives/xcode-users/2004/Jan/msg00193.html
|
||||
|
||||
*.pbxuser
|
||||
|
||||
# .mode1v3: http://lists.apple.com/archives/xcode-users/2007/Oct/msg00465.html
|
||||
|
||||
*.mode1v3
|
||||
|
||||
# .mode2v3: http://lists.apple.com/archives/xcode-users/2007/Oct/msg00465.html
|
||||
|
||||
*.mode2v3
|
||||
|
||||
# .perspectivev3: http://stackoverflow.com/questions/5223297/xcode-projects-what-is-a-perspectivev3-file
|
||||
|
||||
*.perspectivev3
|
||||
|
||||
# NB: also, whitelist the default ones, some projects need to use these
|
||||
!default.pbxuser
|
||||
!default.mode1v3
|
||||
!default.mode2v3
|
||||
!default.perspectivev3
|
||||
|
||||
|
||||
####
|
||||
# Xcode 4 - semi-personal settings
|
||||
#
|
||||
#
|
||||
# OPTION 1: ---------------------------------
|
||||
# throw away ALL personal settings (including custom schemes!
|
||||
# - unless they are "shared")
|
||||
#
|
||||
# NB: this is exclusive with OPTION 2 below
|
||||
xcuserdata
|
||||
|
||||
# OPTION 2: ---------------------------------
|
||||
# get rid of ALL personal settings, but KEEP SOME OF THEM
|
||||
# - NB: you must manually uncomment the bits you want to keep
|
||||
#
|
||||
# NB: this *requires* git v1.8.2 or above; you may need to upgrade to latest OS X,
|
||||
# or manually install git over the top of the OS X version
|
||||
# NB: this is exclusive with OPTION 1 above
|
||||
#
|
||||
#xcuserdata/**/*
|
||||
|
||||
# (requires option 2 above): Personal Schemes
|
||||
#
|
||||
#!xcuserdata/**/xcschemes/*
|
||||
|
||||
####
|
||||
# XCode 4 workspaces - more detailed
|
||||
#
|
||||
# Workspaces are important! They are a core feature of Xcode - don't exclude them :)
|
||||
#
|
||||
# Workspace layout is quite spammy. For reference:
|
||||
#
|
||||
# /(root)/
|
||||
# /(project-name).xcodeproj/
|
||||
# project.pbxproj
|
||||
# /project.xcworkspace/
|
||||
# contents.xcworkspacedata
|
||||
# /xcuserdata/
|
||||
# /(your name)/xcuserdatad/
|
||||
# UserInterfaceState.xcuserstate
|
||||
# /xcsshareddata/
|
||||
# /xcschemes/
|
||||
# (shared scheme name).xcscheme
|
||||
# /xcuserdata/
|
||||
# /(your name)/xcuserdatad/
|
||||
# (private scheme).xcscheme
|
||||
# xcschememanagement.plist
|
||||
#
|
||||
#
|
||||
|
||||
####
|
||||
# Xcode 4 - Deprecated classes
|
||||
#
|
||||
# Allegedly, if you manually "deprecate" your classes, they get moved here.
|
||||
#
|
||||
# We're using source-control, so this is a "feature" that we do not want!
|
||||
|
||||
*.moved-aside
|
||||
|
||||
# .xccheckout
|
||||
#
|
||||
# Per http://stackoverflow.com/questions/18340453/should-xccheckout-files-in-xcode5-be-ignored-under-vcs
|
||||
#
|
||||
|
||||
*.xccheckout
|
||||
|
||||
####
|
||||
# Visual Studio Code
|
||||
.vscode
|
||||
|
||||
####
|
||||
# Documentation
|
||||
#
|
||||
documentation/doxygen/*
|
||||
!documentation/doxygen/.gitkeep
|
||||
|
||||
|
||||
.idea/*
|
||||
projects/*
|
||||
/.vs
|
||||
CMakeSettings.json
|
||||
|
||||
# Weird files created by Linux
|
||||
.fuse_hidden*
|
||||
|
||||
# This gets ignored by one of the rules above for some reason...
|
||||
!/code/scripting/lua/LuaConvert.h
|
||||
!/code/debugconsole/
|
||||
@@ -1,6 +0,0 @@
|
||||
[submodule "cmake/external/rpavlik-cmake-modules"]
|
||||
path = cmake/external/rpavlik-cmake-modules
|
||||
url = https://github.com/asarium/cmake-modules.git
|
||||
[submodule "lib/libRocket"]
|
||||
path = lib/libRocket
|
||||
url = https://github.com/asarium/libRocket.git
|
||||
-182
@@ -1,182 +0,0 @@
|
||||
language: bash
|
||||
sudo: required
|
||||
dist: trusty
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/cmake-3.8
|
||||
- $HOME/.ccache
|
||||
- $HOME/curl_cache
|
||||
addons:
|
||||
apt:
|
||||
packages: &global_deps
|
||||
- ninja-build
|
||||
- libopenal-dev
|
||||
- libreadline6-dev
|
||||
- libpng12-dev
|
||||
- libjpeg62-dev
|
||||
- liblua5.1-0-dev
|
||||
- libjansson-dev
|
||||
- libsdl2-dev
|
||||
- libfreetype6-dev
|
||||
- valgrind
|
||||
- qt57base
|
||||
coverity_scan:
|
||||
project:
|
||||
name: "scp-fs2open/fs2open.github.com"
|
||||
notification_email: [email protected]
|
||||
build_command: "ci/travis/script.sh"
|
||||
# must match TRAVIS_BRANCH check below
|
||||
branch_pattern: coverity_scan
|
||||
env:
|
||||
global:
|
||||
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
||||
# via the "travis encrypt" command using the project repo's public key
|
||||
# also note that fork's don't get access to secure keys
|
||||
# you have to test using a branch in the main repo
|
||||
- secure: "C3wF967ZeliwwP1vC12EMIBOaC568n26Z/cPnwzn317ve59DWH3YSfPZVgvt08GzmaXITGGsJvPB+qxfGoKvQzYE4O1B73q81RpUe5pB3IhF+ThQ91VfQZIRJR5xEGJaLINUlHTTZGX5jxlkVO9wAcauVj/s3b8sQ3dvUZauPvk="
|
||||
# These declarations set INDIEGAMES_USER and INDIEGAMES_PASSWORD for uploading nightly builds to the indiegames server
|
||||
- secure: "lUuRu8XIi8MKNf1ebOfyC4iVEpPyASojJIDWXRo2bNqEF4ILAljXdkVeXeN6H5yKCHD52cxCNTtyePIG/o3p3QEuGSVud9bDS3D7LaQicLETGGrsw3l07U49gF2OKHXGopg0MzBbZUU9QmhoFTAe8t6PV9NDuEayYCheqvTqjZg="
|
||||
- secure: "E/DHLYcPK/hBUqxBYYlUqp5sjgvIqY5A0qRHyQ4bmjsB+WB/Xx71bGCSiF7hk6lTxar1ZI1i5RAXXh9AIvNVaYAIdEOlCP+q3gvwCYuc5naZEKmkxlUCf0oEL4O9Fye93A/3VkFHuBdC1TGPYYf69m4W5r4367wWO9dPRIdWpJA="
|
||||
# These declarations set FS2DOWNLOADS_USER and FS2DOWNLOADS_PASSWORD
|
||||
- secure: "h6GbMX2jLsW1bS9fCM9fthOSJ1nfQQIRWi6EUH2p8u4NFLD5Bfi/C8JhQPKHUzyo3wvKkSHl+PsW7bgr1oXLusRwAur/dtv2N3imqvtbfIz305b00hZlsvbcYmQmUzQFSAdOGShK57JJ5aKQKccaUBP25KqB7Q+JaqBRdaMBS54="
|
||||
- secure: "fUDAPAUUaaYZy8I4zU3SJ0JcK7aw4eb6eTdaEr7LyNyTMSfPgwY6P1MrbSQC0lJNQIUQ5ffjdxE5g7D7OYpoJF9L14ni4UY8t2QASt7kmpgcYihmjeuYy8FQXgmFG8CTxiWBPKTybZJ7voQcvIvRaNG7b2wM9PMfc5lRIondB6c="
|
||||
deploy:
|
||||
- provider: releases
|
||||
api_key:
|
||||
secure: "Wdt4Ccefo7a0ZDjEJQJgpghh7n72FtNJuKSAPUvoz4gtEX6Ct9J8yJI1t9V3jE3CTbbLJ21/Q6eZRDfT7UfNJe5DdepoJsP9DeFhKMWqQCq+AChqQWlm0KeZAffJoJreL8vXYhnRYcLT9ceZHEH6AqwN9TPV+xJziGPISAkYNZ8="
|
||||
skip_cleanup: true
|
||||
file_glob: true
|
||||
file: "/tmp/builds/*"
|
||||
on:
|
||||
condition: '"$RELEASE_BUILD" == true'
|
||||
tags: true
|
||||
|
||||
- provider: script
|
||||
script: bash ci/travis/ftp_deploy.sh
|
||||
on:
|
||||
condition: '"$NIGHTLY_BUILD" == true'
|
||||
tags: true
|
||||
|
||||
- provider: script
|
||||
skip_cleanup: true
|
||||
script: bash ci/travis/ftp_deploy.sh
|
||||
on:
|
||||
condition: $TEST_BUILD = true
|
||||
all_branches: true
|
||||
|
||||
matrix:
|
||||
include:
|
||||
# note that gcc Debug MUST be 1st for Coverity
|
||||
- os: linux
|
||||
env: CONFIGURATION="Debug" CC=gcc-5 CXX=g++-5
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- *global_deps
|
||||
- g++-5
|
||||
- os: linux
|
||||
env: CONFIGURATION="Debug" CC=gcc-8 CXX=g++-8
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- g++-8
|
||||
- *global_deps
|
||||
- os: linux
|
||||
env: CONFIGURATION="Debug" CC=clang-4.0 CXX=clang++-4.0 CMAKE_OPTIONS="-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-4.0
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- *global_deps
|
||||
- clang-4.0
|
||||
- clang-tidy-4.0
|
||||
- libc++-dev
|
||||
script:
|
||||
- ./ci/travis/script.sh
|
||||
- ./ci/travis/clang_tidy.sh
|
||||
- os: osx
|
||||
env: CONFIGURATION="Debug"
|
||||
|
||||
- os: windows
|
||||
env: CONFIGURATION="Debug" CMAKE_TOOLSET=v141_xp CMAKE_GENERATOR="Visual Studio 15 2017"
|
||||
- os: windows
|
||||
env: CONFIGURATION="Debug" CMAKE_TOOLSET="" CMAKE_GENERATOR="Ninja"
|
||||
|
||||
- os: linux
|
||||
env: CONFIGURATION="Release" CC=gcc-5 CXX=g++-5
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- *global_deps
|
||||
- g++-5
|
||||
- os: linux
|
||||
env: CONFIGURATION="Release" CC=gcc-8 CXX=g++-8
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- g++-8
|
||||
- *global_deps
|
||||
- os: linux
|
||||
env: CONFIGURATION="Release" CC=clang-4.0 CXX=clang++-4.0
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-4.0
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- *global_deps
|
||||
- clang-4.0
|
||||
- libc++-dev
|
||||
- os: osx
|
||||
env: CONFIGURATION="Release"
|
||||
|
||||
- os: windows
|
||||
env: CONFIGURATION="Release" CMAKE_TOOLSET=v141_xp CMAKE_GENERATOR="Visual Studio 15 2017"
|
||||
- os: windows
|
||||
env: CONFIGURATION="Release" CMAKE_TOOLSET="" CMAKE_GENERATOR="Ninja"
|
||||
# As long as Windows is still experimental on Travis CI, allow failures
|
||||
allow_failures:
|
||||
- os: windows
|
||||
env: CONFIGURATION="Debug" CMAKE_TOOLSET=v141_xp CMAKE_GENERATOR="Visual Studio 15 2017"
|
||||
- os: windows
|
||||
env: CONFIGURATION="Debug" CMAKE_TOOLSET="" CMAKE_GENERATOR="Ninja"
|
||||
- os: windows
|
||||
env: CONFIGURATION="Release" CMAKE_TOOLSET=v141_xp CMAKE_GENERATOR="Visual Studio 15 2017"
|
||||
- os: windows
|
||||
env: CONFIGURATION="Release" CMAKE_TOOLSET="" CMAKE_GENERATOR="Ninja"
|
||||
fast_finish: true
|
||||
|
||||
before_install:
|
||||
# ugly hack; if running a coverity scan abort all except the 1st build
|
||||
# see note re gcc compiler above needing to be 1st
|
||||
# also note that branch_pattern & the TRAVIS_BRANCH check must match
|
||||
# unfortunately COVERITY_SCAN_BRANCH isn't defined until later in the
|
||||
# build process
|
||||
- if ([[ "${TRAVIS_JOB_NUMBER##*.}" != "1" ]] && [[ "${TRAVIS_BRANCH}" == "coverity_scan" ]]); then false ; fi
|
||||
- source "./ci/travis/check_release.sh"
|
||||
- "./ci/travis/before_install.sh"
|
||||
install:
|
||||
- if [ "$TRAVIS_OS_NAME" = "windows" ]; then export PATH="/c/Program Files/CMake/bin":$PATH; fi
|
||||
- "./ci/travis/install.sh"
|
||||
- export PATH=$HOME/cmake-3.6/bin:$PATH
|
||||
before_script:
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then QT_ENV_SCRIPT=$(find /opt -name 'qt*-env.sh'); source $QT_ENV_SCRIPT; fi
|
||||
- "./ci/travis/before_script.sh"
|
||||
script:
|
||||
- if [ "$BUILD_DEPLOYMENT" = true ] ; then ./ci/travis/release.sh ; else ./ci/travis/script.sh ; fi
|
||||
-199
@@ -1,199 +0,0 @@
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.4)
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
# Make sure the source and binary directory are not the sample
|
||||
if ("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
message(FATAL_ERROR "Binary and source directory can not be the same! Choose another build directory.")
|
||||
endif()
|
||||
|
||||
include(cmake/util.cmake)
|
||||
|
||||
# Set a few policies
|
||||
set_policy(CMP0051 OLD)
|
||||
set_policy(CMP0053 NEW)
|
||||
set_policy(CMP0054 NEW)
|
||||
|
||||
SET(FSO_PROJECT_DESCRIPTION "Open source project based on the original FreeSpace 2 source code.")
|
||||
|
||||
SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin CACHE PATH "Executable output path")
|
||||
SET(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin CACHE PATH "Library output path")
|
||||
|
||||
# CMAKE_INSTALL_PREFIX is defined but also overwritten by the PROJECT command so we need to set it later
|
||||
IF(NOT DEFINED CMAKE_INSTALL_PREFIX)
|
||||
SET(RESET_INSTALL_PREFIX TRUE)
|
||||
ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX)
|
||||
|
||||
# Reset this variable
|
||||
SET(TARGET_COPY_FILES "" CACHE INTERNAL "" FORCE)
|
||||
SET(TARGET_COPY_DIRS "" CACHE INTERNAL "" FORCE)
|
||||
|
||||
### Define options and editable variables in the section below:
|
||||
# This is only needed for single configuration generators so don't annoy others
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT DEFINED CMAKE_CONFIGURATION_TYPES)
|
||||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Default build configuration used." FORCE)
|
||||
message(WARNING "CMAKE_BUILD_TYPE was not specified, defaulting to Release configuration.")
|
||||
endif(NOT CMAKE_BUILD_TYPE AND NOT DEFINED CMAKE_CONFIGURATION_TYPES)
|
||||
|
||||
# Override standard CMake configurations
|
||||
set(CMAKE_CONFIGURATION_TYPES Debug Release FastDebug CACHE STRING "Available configurations" FORCE)
|
||||
|
||||
PROJECT(FS2_Open)
|
||||
|
||||
find_program(CCACHE_PROGRAM ccache)
|
||||
# Currently only GCC support ccache properly without generating additional warnings
|
||||
if(CCACHE_PROGRAM AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
message(STATUS "Using ccache for compilation: ${CCACHE_PROGRAM}")
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "${CCACHE_PROGRAM}")
|
||||
endif()
|
||||
|
||||
IF(CMAKE_CROSSCOMPILING)
|
||||
SET(IMPORT_EXE_DIR "IMPORT_EXE_DIR-NOTFOUND" CACHE FILEPATH "Required for a cross compiling build, point to binary directory of a cmake build for the real OS")
|
||||
INCLUDE(${IMPORT_EXE_DIR}/ImportExecutables.cmake)
|
||||
ENDIF(CMAKE_CROSSCOMPILING)
|
||||
|
||||
# Check if the external modules exists
|
||||
IF(NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/cmake/external/rpavlik-cmake-modules/launcher-templates")
|
||||
message(FATAL_ERROR "External submodules could not be found. Please make sure you have updated your submodules.")
|
||||
endif()
|
||||
|
||||
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/finder")
|
||||
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/external/rpavlik-cmake-modules")
|
||||
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/external/cotire")
|
||||
|
||||
IF(RESET_INSTALL_PREFIX)
|
||||
IF(NOT $ENV{FS2PATH} STREQUAL "")
|
||||
IF(NOT IS_DIRECTORY $ENV{FS2PATH})
|
||||
MESSAGE(WARNING "The path '$ENV{FS2PATH}' of the environment variable FS2PATH does not point to a directory! Install prefix wasn't set.")
|
||||
ELSE(NOT IS_DIRECTORY $ENV{FS2PATH})
|
||||
SET(CMAKE_INSTALL_PREFIX "$ENV{FS2PATH}" CACHE FILEPATH "Install path" FORCE)
|
||||
FILE(TO_CMAKE_PATH ${CMAKE_INSTALL_PREFIX} CMAKE_INSTALL_PREFIX)
|
||||
ENDIF(NOT IS_DIRECTORY $ENV{FS2PATH})
|
||||
ELSE(NOT $ENV{FS2PATH} STREQUAL "")
|
||||
MESSAGE(STATUS "NO FS2PATH environment variable found, you can define this to point to your freespace install but it is not required.")
|
||||
ENDIF(NOT $ENV{FS2PATH} STREQUAL "")
|
||||
ENDIF(RESET_INSTALL_PREFIX)
|
||||
|
||||
IF (WIN32)
|
||||
OPTION(FSO_USE_SPEECH "Use Windows specific text-to-speach libraries" ON)
|
||||
|
||||
OPTION(FSO_USE_VOICEREC "Enable voice recognition support" ON)
|
||||
|
||||
OPTION(FSO_BUILD_FRED2 "Build FRED2 binary" ON)
|
||||
elseif(UNIX)
|
||||
option(FSO_BUILD_APPIMAGE "Build an AppImage package" OFF)
|
||||
ENDIF(WIN32)
|
||||
|
||||
OPTION(FSO_BUILD_TOOLS "Build tools related to FSO" OFF)
|
||||
|
||||
OPTION(FSO_BUILD_TESTS "Build unit tests" OFF)
|
||||
|
||||
OPTION(FSO_DEVELOPMENT_MODE "Generate binaries in development mode, only use if you know what you're doing!" OFF)
|
||||
|
||||
OPTION(FSO_BUILD_QTFRED "Build qtFRED2 binary" OFF)
|
||||
|
||||
IF(WIN32 OR APPLE)
|
||||
# On windows and mac the default should be to always build the included libraries
|
||||
SET(FSO_BUILD_INCLUDED_LIBS_DEFAULT ON)
|
||||
ELSE()
|
||||
SET(FSO_BUILD_INCLUDED_LIBS_DEFAULT OFF)
|
||||
ENDIF()
|
||||
|
||||
OPTION(FSO_BUILD_INCLUDED_LIBS "Build and use the included libraries istead of using the system headers and libraries" ${FSO_BUILD_INCLUDED_LIBS_DEFAULT})
|
||||
|
||||
OPTION(FSO_USE_LUAJIT "Use LuaJIT for Lua scripting, needs a working internet connection!" OFF)
|
||||
|
||||
OPTION(FSO_USE_OPENALSOFT "Download and build OpenAL Soft instead of using the system libraries" OFF)
|
||||
|
||||
OPTION(FSO_FATAL_WARNINGS "Determines if warnings in the build are considered fatal errors, primarily used for CI" OFF)
|
||||
|
||||
SET(FSO_FREESPACE_PATH "${CMAKE_INSTALL_PREFIX}" CACHE FILEPATH "The path of the FreeSpace directory you want to use. Please note that you will have to change CMAKE_INSTALL_PREFIX if you change this at some point.")
|
||||
|
||||
SET(FSO_RUN_ARGUMENTS "" CACHE STRING "Additional arguments passed to a generated executable when run with the generated build files.")
|
||||
|
||||
option(FSO_INSTALL_DEBUG_FILES "Install some debug files (currently only PDB files on windows)" OFF)
|
||||
|
||||
option(ENABLE_COTIRE "Enable cotire for faster compilation. Enabled by default." ON)
|
||||
|
||||
MARK_AS_ADVANCED(FORCE FSO_CMAKE_DEBUG)
|
||||
MARK_AS_ADVANCED(FORCE FSO_BUILD_INCLUDED_LIBS)
|
||||
MARK_AS_ADVANCED(FORCE FSO_USE_OPENALSOFT)
|
||||
MARK_AS_ADVANCED(FORCE FSO_USE_LUAJIT)
|
||||
MARK_AS_ADVANCED(FORCE FSO_DEVELOPMENT_MODE)
|
||||
MARK_AS_ADVANCED(FORCE FSO_FATAL_WARNINGS)
|
||||
mark_as_advanced(FORCE FSO_INSTALL_DEBUG_FILES)
|
||||
mark_as_advanced(FORCE ENABLE_COTIRE)
|
||||
|
||||
# Include cotire file from https://github.com/sakra/cotire/
|
||||
include(cotire)
|
||||
|
||||
INCLUDE(globals)
|
||||
INCLUDE(toolchain)
|
||||
INCLUDE(platforms)
|
||||
include(version)
|
||||
|
||||
INCLUDE(headers)
|
||||
|
||||
SET(GENERATED_SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated_source)
|
||||
|
||||
include(generateHeaders)
|
||||
|
||||
if(FSO_BUILD_APPIMAGE)
|
||||
include(appimage)
|
||||
endif()
|
||||
|
||||
include(clang-tidy)
|
||||
|
||||
# This includes source code for some tools, either used in the build or also for something else
|
||||
ADD_SUBDIRECTORY(tools)
|
||||
|
||||
ADD_SUBDIRECTORY(lib)
|
||||
|
||||
ADD_SUBDIRECTORY(code)
|
||||
|
||||
ADD_SUBDIRECTORY(freespace2)
|
||||
|
||||
IF(FSO_BUILD_FRED2)
|
||||
ADD_SUBDIRECTORY(fred2)
|
||||
ENDIF(FSO_BUILD_FRED2)
|
||||
|
||||
IF(FSO_BUILD_QTFRED)
|
||||
ADD_SUBDIRECTORY(qtfred)
|
||||
ENDIF()
|
||||
|
||||
if(FSO_BUILD_TESTS)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
if ("${CMAKE_VERSION}" VERSION_GREATER "3.5")
|
||||
# Default to using Freespace2 as startup project if CMake supports it.
|
||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Freespace2)
|
||||
endif()
|
||||
|
||||
IF(MSVC_USE_RUNTIME_DLL)
|
||||
SET(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION "${BINARY_DESTINATION}")
|
||||
|
||||
IF(FSO_BUILD_FRED2)
|
||||
SET(CMAKE_INSTALL_MFC_LIBRARIES ON)
|
||||
ENDIF(FSO_BUILD_FRED2)
|
||||
|
||||
INCLUDE(InstallRequiredSystemLibraries)
|
||||
ENDIF(MSVC_USE_RUNTIME_DLL)
|
||||
|
||||
include(package)
|
||||
|
||||
include(doxygen)
|
||||
|
||||
# Print used options to log
|
||||
IF (WIN32)
|
||||
message(STATUS "Using text to speech: ${FSO_USE_SPEECH}")
|
||||
message(STATUS "Using voice recogition: ${FSO_USE_VOICEREC}")
|
||||
message(STATUS "Building FRED2: ${FSO_BUILD_FRED2}")
|
||||
elseif(UNIX)
|
||||
message(STATUS "Building AppImage: ${FSO_BUILD_APPIMAGE}")
|
||||
ENDIF()
|
||||
message(STATUS "Building FSO tools: ${FSO_BUILD_TOOLS}")
|
||||
message(STATUS "Building qtFRED: ${FSO_BUILD_QTFRED}")
|
||||
message(STATUS "Fatal warnings: ${FSO_FATAL_WARNINGS}")
|
||||
@@ -1,29 +0,0 @@
|
||||
This is still in pretty rough form.
|
||||
|
||||
|
||||
=== for people building fs2_open:
|
||||
|
||||
Win32-MSVC:
|
||||
Use the Freespace2.dsw workspace and build within the IDE.
|
||||
|
||||
|
||||
Win32-MinGW:
|
||||
make
|
||||
|
||||
|
||||
Linux and other unix variants (NOT YET COMPLETE)
|
||||
./configure [options]
|
||||
make
|
||||
|
||||
|
||||
|
||||
=== for the project maintainers (people who need to
|
||||
=== keep the makefiles up to date) and those building
|
||||
=== from CVS:
|
||||
|
||||
./autogen.sh (should only has to be done once)
|
||||
./configure [options]
|
||||
make
|
||||
|
||||
automake v1.6.1+ and
|
||||
autoconf v2.54+ are required
|
||||
@@ -1,42 +0,0 @@
|
||||
FreeSpace2 *S*ource *C*ode *P*roject
|
||||
==
|
||||
[](https://travis-ci.org/scp-fs2open/fs2open.github.com)
|
||||
[](https://ci.appveyor.com/project/SirKnightly/fs2open-github-com/branch/master)
|
||||
[](https://scan.coverity.com/projects/870)
|
||||
|
||||
Building
|
||||
--
|
||||
Before you do anything, make sure you have updated your git submodules, either by running `git submodule update --init --recursive` or by cloning the repository with the `--recursive` flag.<br/>
|
||||
<br/>
|
||||
For building you will need [CMake](http://www.cmake.org/cmake/resources/software.html). Version 3.4 is required. Once you have installed CMake you should create a build directory where the project/make files should be created, **do not create them inside the source tree!**<br>
|
||||
<br>
|
||||
On Windows you can use the `cmake-gui` executable to get a nice GUI, on Unix just use `cmake`. Use the newly created directory as build directory (change to this directory on Unix) and run cmake. On Windows this can be done by clicking the `Configure` button. Choose your compiler version and hit `Generate` when configuring is done. <br>
|
||||
Depending on the makefile generator used build the `all` or `ALL_BUILD` target to compile the project.<br>
|
||||
|
||||
### Available variables to control the build
|
||||
* `FSO_BUILD_WXFRED2`: Build the wxfred2 project, requires wxWidgets
|
||||
* `FSO_FREESPACE_PATH`: Sets the path of your FreeSpace install, can be used to automatically run the generated executables with the correct working directory, this is an optional variable. By default this will use the value of the `FS2PATH` environment variable.
|
||||
* `FSO_BUILD_TOOLS`: Build some tools related to FSO
|
||||
* `CMAKE_BUILD_TYPE`: Sets the binary build type between `Debug` and `Release` (default)
|
||||
|
||||
#### Windows only variables
|
||||
* `FSO_BUILD_FRED2`: Build FRED2, requires a Visual Studio version that ships with MFC
|
||||
* `FSO_USE_SPEECH`: Build a binary with text-to-speech support
|
||||
* `FSO_USE_VOICEREC`: Build a binary with voice recognition support
|
||||
|
||||
#### Advanced variables
|
||||
You should only use these variables if you know what you're doing
|
||||
* `FSO_CMAKE_DEBUG`: Print CMake debugging informations
|
||||
* `FSO_BUILD_INCLUDED_LIBS`: Build libraries from the included source
|
||||
* `FSO_USE_OPENALSOFT`: Use [OpenALSoft](http://kcat.strangesoft.net/openal.html) for OpenAL support
|
||||
* `FSO_USE_LUAJIT`: Use [luajit](http://luajit.org/) as a replacement for lua
|
||||
* `FSO_DEVELOPMENT_MODE`: Toggles some development behavior, only use if you really need it.
|
||||
* `FSO_RUN_ARGUMENTS`: If you run an executable from within the project, these arguments will also be passed to the executable
|
||||
* `FSO_BUILD_POSTFIX`: Sets a postfix to be added to the executable name, may be useful for release candidates.
|
||||
|
||||
#### Visual Studio specific variables
|
||||
* `MSVC_USE_RUNTIME_DLL`: Use the DLL version of the runtime, experimental and not well tested.
|
||||
* `MSVC_SIMD_INSTRUCTIONS`: The instruction set the executables will be optimized for.
|
||||
|
||||
### Generating an installation package
|
||||
CMake can automatically generate installation packages of the project. To do this you will just need to run the `package` target of the build system and the package will be placed inside your build directory. On Windows you will have to install [NSIS](http://nsis.sourceforge.net/Main_Page) to use this.
|
||||
@@ -1,64 +0,0 @@
|
||||
version: 1.0.0.{build}
|
||||
image: Visual Studio 2015
|
||||
configuration:
|
||||
- Debug
|
||||
- Release
|
||||
clone_depth: 10
|
||||
environment:
|
||||
matrix:
|
||||
- BuildID: 0
|
||||
CMAKE_GENERATOR: Visual Studio 14 2015
|
||||
PlatformToolset: v140_xp
|
||||
QT_DIR: C:\Qt\5.9\msvc2015
|
||||
- BuildID: 1
|
||||
CMAKE_GENERATOR: Visual Studio 14 2015 Win64
|
||||
PlatformToolset: v140_xp
|
||||
QT_DIR: C:\Qt\5.9\msvc2015_64
|
||||
before_build:
|
||||
- git submodule update --init --recursive
|
||||
build_script:
|
||||
- ps: . $Env:APPVEYOR_BUILD_FOLDER/ci/appveyor/build.ps1
|
||||
test_script:
|
||||
- ps: . $Env:APPVEYOR_BUILD_FOLDER/ci/appveyor/test.ps1
|
||||
|
||||
deploy:
|
||||
- provider: GitHub
|
||||
auth_token:
|
||||
secure: 3kV4efHXwRnfXzmJPRAOs8D7+MhwXUXYeayI/P5y114L09kJa6b6L70beXdW7yYr
|
||||
on:
|
||||
ReleaseBuild: true # deploy on release push only
|
||||
|
||||
- provider: FTP
|
||||
protocol: sftp
|
||||
host: scp.indiegames.us
|
||||
username:
|
||||
secure: SFivQZfatqWHXK1ijYK3GQ==
|
||||
password:
|
||||
secure: q6Zk/412o1ri+NEya1dl1Q==
|
||||
folder: public_html/builds/nightly/$(VersionName)
|
||||
on:
|
||||
NightlyBuild: true # deploy on nightly push only
|
||||
|
||||
- provider: FTP
|
||||
protocol: ftp
|
||||
host: swc.fs2downloads.com
|
||||
username:
|
||||
secure: EXg2ADoKzMduZF90ip2Q0g==
|
||||
password:
|
||||
secure: x0LL0uY9yBAQ7JTARhQ6AA==
|
||||
folder: swc.fs2downloads.com/builds/nightly/$(VersionName)
|
||||
beta: true
|
||||
on:
|
||||
NightlyBuild: true # deploy on nightly push only
|
||||
|
||||
- provider: FTP
|
||||
protocol: ftp
|
||||
host: swc.fs2downloads.com
|
||||
username:
|
||||
secure: EXg2ADoKzMduZF90ip2Q0g==
|
||||
password:
|
||||
secure: x0LL0uY9yBAQ7JTARhQ6AA==
|
||||
folder: swc.fs2downloads.com/builds/test/$(VersionName)
|
||||
beta: true
|
||||
on:
|
||||
TestBuild: true # deploy on test build push only
|
||||
@@ -1,160 +0,0 @@
|
||||
|
||||
class BuildConfig {
|
||||
[string]$Generator
|
||||
[string]$PackageType
|
||||
[string]$Toolset
|
||||
[string]$SimdType
|
||||
[string]$QtDir
|
||||
[Bool]$SourcePackage
|
||||
}
|
||||
|
||||
$NightlyConfigurations = @(
|
||||
[BuildConfig]@{
|
||||
Generator="Visual Studio 14 2015 Win64";
|
||||
PackageType="Win64";
|
||||
Toolset="v140_xp";
|
||||
SimdType="SSE2";
|
||||
QtDir="C:\Qt\5.9\msvc2015_64";
|
||||
SourcePackage=$false;
|
||||
},
|
||||
[BuildConfig]@{
|
||||
Generator="Visual Studio 14 2015";
|
||||
PackageType="Win32";
|
||||
Toolset="v140_xp";
|
||||
SimdType="SSE2";
|
||||
QtDir="C:\Qt\5.9\msvc2015";
|
||||
SourcePackage=$false;
|
||||
}
|
||||
)
|
||||
$ReleaseConfigurations = @(
|
||||
[BuildConfig]@{
|
||||
Generator="Visual Studio 14 2015";
|
||||
PackageType="Win32";
|
||||
Toolset="v140_xp";
|
||||
SimdType="SSE2";
|
||||
QtDir="C:\Qt\5.9\msvc2015";
|
||||
SourcePackage=$true;
|
||||
}
|
||||
[BuildConfig]@{
|
||||
Generator="Visual Studio 14 2015";
|
||||
PackageType="Win32-AVX";
|
||||
Toolset="v140_xp";
|
||||
SimdType="AVX";
|
||||
QtDir="C:\Qt\5.9\msvc2015";
|
||||
SourcePackage=$false;
|
||||
}
|
||||
[BuildConfig]@{
|
||||
Generator="Visual Studio 14 2015 Win64";
|
||||
PackageType="Win64";
|
||||
Toolset="v140_xp";
|
||||
SimdType="SSE2";
|
||||
QtDir="C:\Qt\5.9\msvc2015_64";
|
||||
SourcePackage=$false;
|
||||
}
|
||||
[BuildConfig]@{
|
||||
Generator="Visual Studio 14 2015 Win64";
|
||||
PackageType="Win64-AVX";
|
||||
Toolset="v140_xp";
|
||||
SimdType="AVX";
|
||||
QtDir="C:\Qt\5.9\msvc2015_64";
|
||||
SourcePackage=$false;
|
||||
}
|
||||
)
|
||||
|
||||
$BuildConfigurations = $null
|
||||
|
||||
# Default values
|
||||
$ReleaseBuild = $false
|
||||
$NightlyBuild = $false
|
||||
$TestBuild = $false
|
||||
|
||||
# Set to true to test either the release or the nightly part of this script
|
||||
$ReleaseTest = $false
|
||||
$NightlyTest = $false
|
||||
$TestBuildTest = $false
|
||||
|
||||
if ($ReleaseTest -Or ([System.Convert]::ToBoolean($env:APPVEYOR_REPO_TAG) -And ("$env:APPVEYOR_REPO_TAG_NAME" -match "^release_(.*)"))) {
|
||||
# Tag matches
|
||||
$ReleaseBuild = $true
|
||||
$PackageName = "fs2_open_$($matches[1])"
|
||||
$BuildConfigurations = $ReleaseConfigurations
|
||||
}
|
||||
|
||||
if ($NightlyTest -Or ([System.Convert]::ToBoolean($env:APPVEYOR_REPO_TAG) -And ("$env:APPVEYOR_REPO_TAG_NAME" -match "^nightly_(.*)"))) {
|
||||
# Tag matches
|
||||
$NightlyBuild = $true
|
||||
$PackageName = "nightly_$($matches[1])"
|
||||
Set-AppveyorBuildVariable 'VersionName' "$($matches[1])"
|
||||
$BuildConfigurations = $NightlyConfigurations
|
||||
}
|
||||
|
||||
if ($TestBuildTest -Or ([System.Convert]::ToInt32($env:APPVEYOR_PULL_REQUEST_NUMBER) -le 0 -And ("$env:APPVEYOR_REPO_BRANCH" -match "^test\/(.*)"))) {
|
||||
# Tag matches
|
||||
$TestBuild = $true
|
||||
$PackageName = "test_$($matches[1])"
|
||||
Set-AppveyorBuildVariable 'VersionName' "$($matches[1])"
|
||||
$BuildConfigurations = $NightlyConfigurations
|
||||
|
||||
# Override the revision string so that the builds are named correctly
|
||||
[System.IO.File]::WriteAllLines("$env:APPVEYOR_BUILD_FOLDER/version_override.cmake", "set(FSO_VERSION_REVISION_STR $env:VersionName)")
|
||||
}
|
||||
|
||||
# Multiply by 2 so that we can add 0 or 1 for debug or release Configs
|
||||
$buildID = [convert]::ToInt32($env:BuildID) * 2
|
||||
if ($Env:Configuration -eq "Release") {
|
||||
$buildID = $buildID + 1
|
||||
}
|
||||
|
||||
$DeployBuild = $false
|
||||
if ($ReleaseBuild -Or $NightlyBuild -Or $TestBuild) {
|
||||
$DeployBuild = $true
|
||||
}
|
||||
|
||||
Set-AppveyorBuildVariable 'ReleaseBuild' "$ReleaseBuild"
|
||||
Set-AppveyorBuildVariable 'NightlyBuild' "$NightlyBuild"
|
||||
Set-AppveyorBuildVariable 'TestBuild' "$TestBuild"
|
||||
|
||||
New-Item build -type directory
|
||||
Set-Location -Path build
|
||||
|
||||
if ($DeployBuild) {
|
||||
# Release build
|
||||
if ($buildID -ge $BuildConfigurations.Length) {
|
||||
# Not needed
|
||||
exit 0
|
||||
}
|
||||
|
||||
$buildConfig = $BuildConfigurations[$buildID]
|
||||
|
||||
if ($buildConfig.SourcePackage -eq $True) {
|
||||
7z a -xr'!.git' "$($PackageName)-source-Win.zip" "$env:APPVEYOR_BUILD_FOLDER"
|
||||
Push-AppveyorArtifact "$($PackageName)-source-Win.zip"
|
||||
}
|
||||
|
||||
cmake -DCMAKE_INSTALL_PREFIX="$env:APPVEYOR_BUILD_FOLDER/../install" -DFSO_USE_SPEECH="ON" `
|
||||
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS="$($buildConfig.SimdType)" `
|
||||
-DQT5_INSTALL_ROOT="$($buildConfig.QtDir)" -DFSO_BUILD_QTFRED=ON `
|
||||
-G "$($buildConfig.Generator)" -T "$($buildConfig.Toolset)" ..
|
||||
|
||||
$Configs = @("Release", "FastDebug")
|
||||
foreach ($config in $Configs) {
|
||||
cmake --build . --config "$config" --target INSTALL -- /verbosity:minimal
|
||||
if (! ($?)) {
|
||||
Add-AppveyorMessage "A release build failed!"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
7z a "$($PackageName)-builds-$($buildConfig.PackageType).zip" "$env:APPVEYOR_BUILD_FOLDER/../install/*"
|
||||
Push-AppveyorArtifact "$($PackageName)-builds-$($buildConfig.PackageType).zip"
|
||||
} else {
|
||||
cmake -DFSO_USE_SPEECH="ON" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="ON" -DFSO_BUILD_TESTS="ON" -DMSVC_SIMD_INSTRUCTIONS=SSE2 `
|
||||
-DFSO_BUILD_QTFRED=ON -DQT5_INSTALL_ROOT="$env:QT_DIR" -DFSO_BUILD_FRED2="ON" `
|
||||
-G "$Env:CMAKE_GENERATOR" -T "$Env:PlatformToolset" ..
|
||||
|
||||
cmake --build . --config "$Env:CONFIGURATION" -- /verbosity:minimal
|
||||
|
||||
if (! ($?)) {
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
|
||||
if ([System.Convert]::ToBoolean($env:ReleaseBuild) -Or [System.Convert]::ToBoolean($env:NightlyBuild) -Or [System.Convert]::ToBoolean($env:TestBuild)) {
|
||||
# Skip tests for deployment
|
||||
exit 0
|
||||
} else {
|
||||
write "Running unit tests..."
|
||||
# Run unit tests
|
||||
&"$pwd\bin\$Env:CONFIGURATION\unittests.exe" --gtest_shuffle 2>&1
|
||||
|
||||
if (! ($?)) {
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"package": {
|
||||
"subject": "scp-fs2open",
|
||||
"repo": "FSO",
|
||||
"name": "nightly"
|
||||
},
|
||||
|
||||
"version": {
|
||||
"name": "$VERSION_NAME"
|
||||
},
|
||||
|
||||
"files": [
|
||||
{
|
||||
"includePattern": "/tmp/builds/(.*)",
|
||||
"uploadPattern": "$1"
|
||||
}
|
||||
],
|
||||
"publish": true
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
set -ex
|
||||
|
||||
if [ "$NIGHTLY_BUILD" = true ]; then
|
||||
echo "Generating bintray config..."
|
||||
sed -e "s/\$VERSION_NAME/$VERSION_NAME/" ci/bintray.template.json > ci/bintray.json
|
||||
fi
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
set -ex
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
# Nothing to do here
|
||||
:
|
||||
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
# Nothing to do here
|
||||
:
|
||||
elif [ "$TRAVIS_OS_NAME" = "windows" ]; then
|
||||
# Nothing to do here
|
||||
:
|
||||
fi
|
||||
@@ -1,54 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -ex
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
mkdir -p /tmp/builds
|
||||
if [ "$RELEASE_BUILD" = true ]; then
|
||||
# Package the source code in release builds
|
||||
PARENT_DIR="$(basename "$PWD")"
|
||||
(cd .. && tar -czvf /tmp/builds/$PACKAGE_NAME-source-Unix.tar.gz --exclude-vcs "$PARENT_DIR")
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -p build
|
||||
cd build
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
CXXFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
|
||||
CFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
|
||||
|
||||
if [[ "$CC" =~ ^clang.*$ ]]; then
|
||||
CXXFLAGS="$CXXFLAGS -stdlib=libc++"
|
||||
fi
|
||||
|
||||
export CXXFLAGS
|
||||
export CFLAGS
|
||||
CMAKE="cmake -G Ninja -DFSO_FATAL_WARNINGS=ON $CMAKE_OPTIONS"
|
||||
if [ "$BUILD_DEPLOYMENT" = true ]; then
|
||||
for config in $BUILD_CONFIGS
|
||||
do
|
||||
mkdir -p $config
|
||||
cd $config
|
||||
eval $CMAKE -DFSO_INSTALL_DEBUG_FILES=ON -DCMAKE_BUILD_TYPE=$config -DCMAKE_INSTALL_PREFIX="/tmp/release/$config" \
|
||||
-DFSO_BUILD_APPIMAGE=ON -DFSO_BUILD_INCLUDED_LIBS=ON -DFFMPEG_USE_PRECOMPILED=ON -DFSO_BUILD_QTFRED=OFF ../..
|
||||
cd ..
|
||||
done
|
||||
else
|
||||
eval $CMAKE -DCMAKE_BUILD_TYPE=$CONFIGURATION -DFSO_BUILD_TESTS=ON -DFSO_BUILD_INCLUDED_LIBS=ON -DFSO_BUILD_QTFRED=ON ..
|
||||
fi
|
||||
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
if [ "$BUILD_DEPLOYMENT" = true ]; then
|
||||
cmake -G "Xcode" -DFSO_FATAL_WARNINGS=ON -DFSO_INSTALL_DEBUG_FILES=ON -DCMAKE_INSTALL_PREFIX="/tmp/release" ..
|
||||
else
|
||||
cmake -G "Xcode" $CMAKE_OPTIONS ..
|
||||
fi
|
||||
elif [ "$TRAVIS_OS_NAME" = "windows" ]; then
|
||||
if [ "$CMAKE_GENERATOR" = "Ninja" ]; then
|
||||
cmake -DFSO_USE_SPEECH="OFF" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="OFF" -DFSO_BUILD_TESTS="ON" \
|
||||
-DFSO_BUILD_FRED2="OFF" -G "$CMAKE_GENERATOR" ..
|
||||
else
|
||||
cmake -DFSO_USE_SPEECH="ON" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="OFF" -DFSO_BUILD_TESTS="ON" \
|
||||
-DMSVC_SIMD_INSTRUCTIONS=SSE2 -DFSO_BUILD_FRED2="ON" -G "$CMAKE_GENERATOR" -T "$CMAKE_TOOLSET" ..
|
||||
fi
|
||||
fi
|
||||
@@ -1,74 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
RELEASE_BUILD=false
|
||||
NIGHTLY_BUILD=false
|
||||
TEST_BUILD=false
|
||||
|
||||
BUILD_DEPLOYMENT=false
|
||||
BUILD_CONFIGS="Release FastDebug"
|
||||
VERSION_NAME=""
|
||||
PACKAGE_NAME=""
|
||||
|
||||
RELEASE_PATTERN="^release_(.*)$"
|
||||
NIGHTLY_PATTERN="^nightly_(.*)$"
|
||||
TEST_BUILD_PATTERN="^test\/(.*)$"
|
||||
|
||||
# These are for testing
|
||||
NIGHTLY_TEST=false
|
||||
RELEASE_TEST=false
|
||||
TEST_BUILD_TEST=false
|
||||
|
||||
if [ "$RELEASE_TEST" = true ] || [[ "$TRAVIS_TAG" =~ $RELEASE_PATTERN ]]; then
|
||||
echo "This is a release tag!";
|
||||
RELEASE_BUILD=true;
|
||||
PACKAGE_NAME="fs2_open_${BASH_REMATCH[1]}";
|
||||
fi
|
||||
if [ "$NIGHTLY_TEST" = true ] || [[ "$TRAVIS_TAG" =~ $NIGHTLY_PATTERN ]]; then
|
||||
echo "This is a nightly tag!";
|
||||
NIGHTLY_BUILD=true;
|
||||
VERSION_NAME="${BASH_REMATCH[1]}";
|
||||
PACKAGE_NAME="nightly_${BASH_REMATCH[1]}";
|
||||
fi
|
||||
if [ "$TEST_BUILD_TEST" = true ] || [[ "$TRAVIS_PULL_REQUEST" == "false" && "$TRAVIS_BRANCH" =~ $TEST_BUILD_PATTERN ]]; then
|
||||
echo "This is a test build branch!";
|
||||
TEST_BUILD=true;
|
||||
if [ "$TEST_BUILD_TEST" = true ]; then
|
||||
VERSION_NAME="test";
|
||||
PACKAGE_NAME="test_test";
|
||||
else
|
||||
VERSION_NAME="${BASH_REMATCH[1]}";
|
||||
PACKAGE_NAME="test_${BASH_REMATCH[1]}";
|
||||
fi
|
||||
|
||||
# Override the revision string so that the builds are named correctly
|
||||
echo "set(FSO_VERSION_REVISION_STR $VERSION_NAME)" > "$TRAVIS_BUILD_DIR/version_override.cmake"
|
||||
fi
|
||||
|
||||
if ([ "$RELEASE_BUILD" = true ] || [ "$NIGHTLY_BUILD" = true ] || [ "$TEST_BUILD" = true ]); then
|
||||
BUILD_DEPLOYMENT=true;
|
||||
fi
|
||||
|
||||
if [ "$BUILD_DEPLOYMENT" = true ]; then
|
||||
if ([ "$TRAVIS_OS_NAME" = "linux" ] && (! [[ "$CC" =~ ^gcc-5.*$ ]])); then
|
||||
echo "Skipping non-release compiler";
|
||||
exit 0;
|
||||
fi
|
||||
|
||||
if ([[ "$CONFIGURATION" == "Debug" ]]); then
|
||||
echo "Skipping non-release configuration";
|
||||
exit 0;
|
||||
fi
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" = "windows" ]; then
|
||||
echo "Skipping non-release platform"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
export RELEASE_BUILD
|
||||
export NIGHTLY_BUILD
|
||||
export TEST_BUILD
|
||||
export BUILD_DEPLOYMENT
|
||||
export BUILD_CONFIGS
|
||||
export VERSION_NAME
|
||||
export PACKAGE_NAME
|
||||
@@ -1,141 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
#===- clang-tidy-diff.py - ClangTidy Diff Checker ------------*- python -*--===#
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
#===------------------------------------------------------------------------===#
|
||||
|
||||
r"""
|
||||
ClangTidy Diff Checker
|
||||
======================
|
||||
|
||||
This script reads input from a unified diff, runs clang-tidy on all changed
|
||||
files and outputs clang-tidy warnings in changed lines only. This is useful to
|
||||
detect clang-tidy regressions in the lines touched by a specific patch.
|
||||
Example usage for git/svn users:
|
||||
|
||||
git diff -U0 HEAD^ | clang-tidy-diff.py -p1
|
||||
svn diff --diff-cmd=diff -x-U0 | \
|
||||
clang-tidy-diff.py -fix -checks=-*,modernize-use-override
|
||||
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=
|
||||
'Run clang-tidy against changed files, and '
|
||||
'output diagnostics only for modified '
|
||||
'lines.')
|
||||
parser.add_argument('-clang-tidy-binary', metavar='PATH',
|
||||
default='clang-tidy',
|
||||
help='path to clang-tidy binary')
|
||||
parser.add_argument('-p', metavar='NUM', default=0,
|
||||
help='strip the smallest prefix containing P slashes')
|
||||
parser.add_argument('-regex', metavar='PATTERN', default=None,
|
||||
help='custom pattern selecting file paths to check '
|
||||
'(case sensitive, overrides -iregex)')
|
||||
parser.add_argument('-iregex', metavar='PATTERN', default=
|
||||
r'.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hpp|m|mm|inc)',
|
||||
help='custom pattern selecting file paths to check '
|
||||
'(case insensitive, overridden by -regex)')
|
||||
|
||||
parser.add_argument('-fix', action='store_true', default=False,
|
||||
help='apply suggested fixes')
|
||||
parser.add_argument('-checks',
|
||||
help='checks filter, when not specified, use clang-tidy '
|
||||
'default',
|
||||
default='')
|
||||
parser.add_argument('-path', dest='build_path',
|
||||
help='Path used to read a compile command database.')
|
||||
parser.add_argument('-extra-arg', dest='extra_arg',
|
||||
action='append', default=[],
|
||||
help='Additional argument to append to the compiler '
|
||||
'command line.')
|
||||
parser.add_argument('-extra-arg-before', dest='extra_arg_before',
|
||||
action='append', default=[],
|
||||
help='Additional argument to prepend to the compiler '
|
||||
'command line.')
|
||||
parser.add_argument('-quiet', action='store_true', default=False,
|
||||
help='Run clang-tidy in quiet mode')
|
||||
clang_tidy_args = []
|
||||
argv = sys.argv[1:]
|
||||
if '--' in argv:
|
||||
clang_tidy_args.extend(argv[argv.index('--'):])
|
||||
argv = argv[:argv.index('--')]
|
||||
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
# Extract changed lines for each file.
|
||||
filename = None
|
||||
lines_by_file = {}
|
||||
for line in sys.stdin:
|
||||
match = re.search('^\+\+\+\ \"?(.*?/){%s}([^ \t\n\"]*)' % args.p, line)
|
||||
if match:
|
||||
filename = match.group(2)
|
||||
if filename == None:
|
||||
continue
|
||||
|
||||
if args.regex is not None:
|
||||
if not re.match('^%s$' % args.regex, filename):
|
||||
continue
|
||||
else:
|
||||
if not re.match('^%s$' % args.iregex, filename, re.IGNORECASE):
|
||||
continue
|
||||
|
||||
match = re.search('^@@.*\+(\d+)(,(\d+))?', line)
|
||||
if match:
|
||||
start_line = int(match.group(1))
|
||||
line_count = 1
|
||||
if match.group(3):
|
||||
line_count = int(match.group(3))
|
||||
if line_count == 0:
|
||||
continue
|
||||
end_line = start_line + line_count - 1;
|
||||
lines_by_file.setdefault(filename, []).append([start_line, end_line])
|
||||
|
||||
if len(lines_by_file) == 0:
|
||||
print("No relevant changes found.")
|
||||
sys.exit(0)
|
||||
|
||||
line_filter_json = json.dumps(
|
||||
[{"name" : name, "lines" : lines_by_file[name]} for name in lines_by_file],
|
||||
separators = (',', ':'))
|
||||
|
||||
quote = "";
|
||||
if sys.platform == 'win32':
|
||||
line_filter_json=re.sub(r'"', r'"""', line_filter_json)
|
||||
else:
|
||||
quote = "'";
|
||||
|
||||
# Run clang-tidy on files containing changes.
|
||||
command = [args.clang_tidy_binary]
|
||||
command.append('-line-filter=' + quote + line_filter_json + quote)
|
||||
if args.fix:
|
||||
command.append('-fix')
|
||||
if args.checks != '':
|
||||
command.append('-checks=' + quote + args.checks + quote)
|
||||
if args.quiet:
|
||||
command.append('-quiet')
|
||||
if args.build_path is not None:
|
||||
command.append('-p=%s' % args.build_path)
|
||||
command.extend(lines_by_file.keys())
|
||||
for arg in args.extra_arg:
|
||||
command.append('-extra-arg=%s' % arg)
|
||||
for arg in args.extra_arg_before:
|
||||
command.append('-extra-arg-before=%s' % arg)
|
||||
command.extend(clang_tidy_args)
|
||||
|
||||
sys.exit(subprocess.call(' '.join(command), shell=True))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,24 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
if ! git rev-list $TRAVIS_COMMIT_RANGE 2>1 >/dev/null; then
|
||||
echo "\$TRAVIS_COMMIT_RANGE ($TRAVIS_COMMIT_RANGE) is not valid for this build (probably caused by a rebase)."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cd "$TRAVIS_BUILD_DIR"
|
||||
|
||||
echo "Running clang-tidy on changed files"
|
||||
git diff -U0 --no-color $TRAVIS_COMMIT_RANGE | \
|
||||
$TRAVIS_BUILD_DIR/ci/travis/clang-tidy-diff.py -path "$TRAVIS_BUILD_DIR/build" -p1 \
|
||||
-regex 'code/.*$|freespace2/.*$|qtfred/.*$|test/src/.*$|build/.*$|tools/.*' \
|
||||
-clang-tidy-binary /usr/bin/clang-tidy-4.0 2>/dev/null | \
|
||||
tee clang-tidy-output.txt
|
||||
|
||||
if [[ -n $(grep "warning: " clang-tidy-output.txt) ]] || [[ -n $(grep "error: " clang-tidy-output.txt) ]]; then
|
||||
echo "Errors or warnings were detected in the clang-tidy output!"
|
||||
exit 1
|
||||
else
|
||||
echo -e "\033[1;32m\xE2\x9C\x93 passed:\033[0m clang-tidy test succeeded";
|
||||
fi
|
||||
@@ -1,89 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -u
|
||||
|
||||
if [[ ! "$(curl -V)" == *"sftp"* ]]; then
|
||||
# Before
|
||||
echo "Before:"
|
||||
curl -V
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
|
||||
if [ -f ~/curl_cache/curl*.deb ]; then
|
||||
cd ~/curl_cache
|
||||
sudo dpkg -i libcurl3*.deb
|
||||
sudo dpkg -i curl*.deb
|
||||
else
|
||||
# Since the Travis CI people are not capable of enabling SSH/SCP support for their libcurl we need to build that manually...
|
||||
# These commands are based on the tutorial from here: http://zeroset.mnim.org/2013/03/14/sftp-support-for-curl-in-ubuntu-12-10-quantal-quetzal-and-later/
|
||||
mkdir /tmp/curl
|
||||
cd /tmp/curl
|
||||
sudo apt-get update
|
||||
sudo apt-get install build-essential debhelper libssh2-1-dev libgnutls-dev libidn11-dev libkrb5-dev libldap2-dev libnss3-dev librtmp-dev libtool openssh-server quilt
|
||||
apt-get source curl
|
||||
sudo apt-get build-dep curl
|
||||
|
||||
cd curl-*
|
||||
export DEB_BUILD_OPTIONS="nocheck"
|
||||
sudo dpkg-buildpackage -uc -us -j"$(grep -c ^processor /proc/cpuinfo)"
|
||||
|
||||
cd ..
|
||||
dpkg -l | grep curl
|
||||
ls -al
|
||||
|
||||
if [ ! -d ~/curl_cache ]; then
|
||||
mkdir ~/curl_cache
|
||||
fi
|
||||
|
||||
cp libcurl3*.deb curl*.deb ~/curl_cache
|
||||
|
||||
sudo dpkg -i libcurl3*.deb
|
||||
sudo dpkg -i curl*.deb
|
||||
fi
|
||||
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
brew install libssh2
|
||||
|
||||
if [ -d ~/curl_cache/curl ]; then
|
||||
cd ~/curl_cache/curl
|
||||
sudo make install
|
||||
else
|
||||
mkdir /tmp/curl
|
||||
cd /tmp/curl
|
||||
|
||||
curl -LO "https://curl.haxx.se/download/curl-7.64.0.tar.bz2"
|
||||
tar -xjf curl-7.64.0.tar.bz2
|
||||
|
||||
cd curl-7.64.0
|
||||
./configure --disable-debug --disable-dependency-tracking --disable-silent-rules --with-libssh2 --with-darwinssl --without-ca-bundle --without-ca-path
|
||||
make -j"$(sysctl hw.logicalcpu | cut -d " " -f 2)"
|
||||
|
||||
if [ ! -d ~/curl_cache ]; then
|
||||
mkdir ~/curl_cache
|
||||
fi
|
||||
|
||||
cp -a . ~/curl_cache/curl
|
||||
sudo make install
|
||||
fi
|
||||
export PATH=/usr/local/bin:$PATH
|
||||
fi
|
||||
|
||||
# After
|
||||
echo "After:"
|
||||
curl -V
|
||||
fi
|
||||
|
||||
cd /tmp/builds
|
||||
|
||||
for file in *; do
|
||||
if [ "$TEST_BUILD" = true ]; then
|
||||
# Upload to fs2downloads
|
||||
curl -k "ftp://swc.fs2downloads.com/swc.fs2downloads.com/builds/test/$VERSION_NAME/" --user "$FS2DOWNLOADS_USER:$FS2DOWNLOADS_PASSWORD" -T "$file" --ftp-create-dirs
|
||||
else
|
||||
# Upload to indiegames
|
||||
curl -k "sftp://scp.indiegames.us/~/public_html/builds/nightly/$VERSION_NAME/" --user "$INDIEGAMES_USER:$INDIEGAMES_PASSWORD" -T "$file" --ftp-create-dirs
|
||||
|
||||
# Upload to fs2downloads
|
||||
curl -k "ftp://swc.fs2downloads.com/swc.fs2downloads.com/builds/nightly/$VERSION_NAME/" --user "$FS2DOWNLOADS_USER:$FS2DOWNLOADS_PASSWORD" -T "$file" --ftp-create-dirs
|
||||
fi
|
||||
done
|
||||
@@ -1,34 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
set -ex
|
||||
|
||||
FILENAME=
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
if [ ! -d "$HOME/cmake-3.8/bin" ]; then
|
||||
# If the cache does not currently contain CMake then download and install it
|
||||
mkdir -p $HOME/cmake-3.8/
|
||||
|
||||
wget -O /tmp/cmake.tar.gz --no-check-certificate https://cmake.org/files/v3.8/cmake-3.8.2-Linux-x86_64.tar.gz
|
||||
tar -xzf /tmp/cmake.tar.gz -C $HOME/cmake-3.8/ --strip-components=1
|
||||
fi
|
||||
export PATH=$HOME/cmake-3.8/bin:$PATH
|
||||
|
||||
cd $HOME
|
||||
|
||||
if [ "${BUILD_DEPLOYMENT}" = true ]; then
|
||||
wget -O appimagetool -c "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage" # (64-bit)
|
||||
chmod a+x ./appimagetool
|
||||
|
||||
wget -O linuxdeployqt -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" # (64-bit)
|
||||
chmod a+x ./linuxdeployqt
|
||||
fi
|
||||
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
gem install xcpretty
|
||||
|
||||
brew update
|
||||
brew outdated cmake || brew upgrade cmake
|
||||
elif [ "$TRAVIS_OS_NAME" = "windows" ]; then
|
||||
choco install mingw ninja
|
||||
fi
|
||||
|
||||
cmake --version
|
||||
@@ -1,68 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
set -ex
|
||||
mkdir -p /tmp/builds
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
cd build
|
||||
for config in $BUILD_CONFIGS
|
||||
do
|
||||
cd "$config"
|
||||
|
||||
# Compile all targets
|
||||
ninja all
|
||||
|
||||
# Install Freespace2 targets
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/tmp/release/$config/fso -DCOMPONENT=Unspecified -P cmake_install.cmake
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/tmp/release/$config/fso -DCOMPONENT=Freespace2 -P cmake_install.cmake
|
||||
|
||||
# We need to be a bit creative for determining the AppImage name since we don't want to hard-code the name
|
||||
FILENAME="$(find /tmp/release/$config/fso/bin -name 'fs2_open_*' -type f -printf "%f\n").AppImage"
|
||||
$HOME/appimagetool -n /tmp/release/$config/fso "/tmp/release/$config/fso/$FILENAME"
|
||||
|
||||
: <<'END'
|
||||
# Install qtFRED targets
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/tmp/release/$config/qtfred/usr -DCOMPONENT=Unspecified -P cmake_install.cmake
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/tmp/release/$config/qtfred/usr -DCOMPONENT=qtFRED -P cmake_install.cmake
|
||||
|
||||
PREV="$(pwd)"
|
||||
cd /tmp/release/$config/qtfred
|
||||
|
||||
unset QTDIR; unset QT_PLUGIN_PATH; unset LD_LIBRARY_PATH
|
||||
$HOME/linuxdeployqt usr/qtfred.desktop -bundle-non-qt-libs
|
||||
# Move our AppRun script to the right location
|
||||
mv usr/AppRun AppRun
|
||||
|
||||
echo "Embed newer libstdc++ for distros that don't come with it (ubuntu 14.04)";
|
||||
mkdir -p usr/optional/; mkdir -p usr/optional/libstdc++/;
|
||||
cp /usr/lib/x86_64-linux-gnu/libstdc++.so.6 ./usr/optional/libstdc++/;
|
||||
|
||||
$HOME/appimagetool -n . "$(find /tmp/release/$config/qtfred/usr/bin -name 'qtfred_*' -type f -printf "%f\n").AppImage"
|
||||
|
||||
cd "$PREV"
|
||||
END
|
||||
|
||||
cd ..
|
||||
done
|
||||
|
||||
cp `find /tmp/release -name '*.AppImage' -print` /tmp/release
|
||||
(cd /tmp/release && tar -cvzf /tmp/builds/$PACKAGE_NAME-builds-Linux.tar.gz *.AppImage)
|
||||
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
cd build
|
||||
|
||||
for config in $BUILD_CONFIGS
|
||||
do
|
||||
cmake --build . --config "$config" --target install | tee build.log \
|
||||
| xcpretty
|
||||
XCODE_RET=${PIPESTATUS[0]}
|
||||
if [ "$XCODE_RET" -ne "0" ]; then
|
||||
tar -cvzf build.log.tar.gz build.log
|
||||
curl --upload-file build.log.tar.gz "https://transfer.sh/build.log.tar.gz"
|
||||
exit $XCODE_RET
|
||||
fi
|
||||
done
|
||||
|
||||
ls -al /tmp/release
|
||||
|
||||
(cd /tmp/release && tar -cvzf /tmp/builds/$PACKAGE_NAME-builds-MacOSX.tar.gz *)
|
||||
fi
|
||||
@@ -1,31 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
set -e
|
||||
|
||||
cd build
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
ninja -k 20 all
|
||||
|
||||
|
||||
if [ "$CONFIGURATION" = "Debug" ]; then
|
||||
valgrind --leak-check=full --error-exitcode=1 --gen-suppressions=all \
|
||||
--suppressions="$TRAVIS_BUILD_DIR/ci/travis/valgrind.supp" ./bin/unittests --gtest_shuffle
|
||||
else
|
||||
./bin/unittests --gtest_shuffle
|
||||
fi
|
||||
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
cmake --build . --config "$CONFIGURATION" | tee build.log | xcpretty
|
||||
XCODE_RET=${PIPESTATUS[0]}
|
||||
if [ "$XCODE_RET" -ne "0" ]; then
|
||||
tar -cvzf build.log.tar.gz build.log
|
||||
curl --upload-file build.log.tar.gz "https://transfer.sh/build.log.tar.gz"
|
||||
exit $XCODE_RET
|
||||
fi
|
||||
elif [ "$TRAVIS_OS_NAME" = "windows" ]; then
|
||||
if [ "$CMAKE_GENERATOR" = "Ninja" ]; then
|
||||
cmake --build . --config "$CONFIGURATION"
|
||||
else
|
||||
cmake --build . --config "$CONFIGURATION" -- /verbosity:minimal
|
||||
fi
|
||||
fi
|
||||
@@ -1,43 +0,0 @@
|
||||
{
|
||||
liblsan Invalid read
|
||||
Memcheck:Addr8
|
||||
obj:/usr/lib64/liblsan.so.0.0.0
|
||||
obj:/usr/lib64/liblsan.so.0.0.0
|
||||
obj:/usr/lib64/liblsan.so.0.0.0
|
||||
obj:*
|
||||
obj:*
|
||||
obj:*
|
||||
}
|
||||
{
|
||||
Travis memleak
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:malloc
|
||||
fun:_dl_signal_error
|
||||
fun:_dl_open
|
||||
fun:dlopen_doit
|
||||
fun:_dl_catch_error
|
||||
fun:_dlerror_run
|
||||
fun:dlopen@@GLIBC_2.2.5
|
||||
obj:/usr/lib/x86_64-linux-gnu/libmirclient.so.7
|
||||
fun:call_init.part.0
|
||||
fun:call_init
|
||||
fun:_dl_init
|
||||
fun:dl_open_worker
|
||||
fun:_dl_catch_error
|
||||
}
|
||||
{
|
||||
CLang Lua unitialized value error
|
||||
Memcheck:Cond
|
||||
...
|
||||
fun:luaH_get
|
||||
fun:lua_rawget
|
||||
fun:_ZN12_GLOBAL__N_117ade_index_handlerEP9lua_State
|
||||
}
|
||||
{
|
||||
False-positive uninitialized variable warning
|
||||
Memcheck:Cond
|
||||
fun:_Z23cf_check_location_flagsjj
|
||||
fun:_Z29cf_create_default_path_stringPcjiPKcbj
|
||||
...
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=FreeSpace Open
|
||||
Exec=$<TARGET_FILE_NAME:Freespace2>
|
||||
Icon=app_icon
|
||||
Categories=Game;
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/sh
|
||||
HERE=$(dirname $(readlink -f "${0}"))
|
||||
export LD_LIBRARY_PATH="${HERE}"/lib:"$LD_LIBRARY_PATH"
|
||||
"${HERE}"/bin/$<TARGET_FILE_NAME:Freespace2> $@
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
include(WriteCompilerDetectionHeader)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED 11)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
set(REQUIRED_CXX_FEATURES cxx_rvalue_references cxx_nullptr)
|
||||
|
||||
get_property(CMAKE_CXX_KNOWN_FEATURES GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES)
|
||||
|
||||
write_compiler_detection_header(
|
||||
FILE "${GENERATED_SOURCE_DIR}/scp_compiler_detection.h"
|
||||
PREFIX SCP
|
||||
COMPILERS AppleClang Clang GNU MSVC
|
||||
FEATURES ${CMAKE_CXX_KNOWN_FEATURES}
|
||||
VERSION 3.2
|
||||
)
|
||||
@@ -1,21 +0,0 @@
|
||||
|
||||
SET(BINARY_DESTINATION "bin")
|
||||
SET(LIBRAY_DESTINATION "lib")
|
||||
|
||||
configure_file("${CMAKE_CURRENT_LIST_DIR}/AppRun.in" "${CMAKE_CURRENT_BINARY_DIR}/AppRun.gen" @ONLY)
|
||||
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/AppRun-$<CONFIG>"
|
||||
INPUT "${CMAKE_CURRENT_BINARY_DIR}/AppRun.gen")
|
||||
|
||||
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/AppRun-$<CONFIG>" DESTINATION "." RENAME "AppRun"
|
||||
COMPONENT "Freespace2")
|
||||
|
||||
|
||||
configure_file("${CMAKE_CURRENT_LIST_DIR}/AppImage.desktop.in" "${CMAKE_CURRENT_BINARY_DIR}/AppImage.desktop.gen" @ONLY)
|
||||
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/AppImage-$<CONFIG>.desktop"
|
||||
INPUT "${CMAKE_CURRENT_BINARY_DIR}/AppImage.desktop.gen")
|
||||
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/AppImage-$<CONFIG>.desktop" DESTINATION "." RENAME "fso.desktop"
|
||||
COMPONENT "Freespace2")
|
||||
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/freespace2/resources/app_icon.png" DESTINATION "."
|
||||
COMPONENT "Freespace2")
|
||||
@@ -1,37 +0,0 @@
|
||||
option(ENABLE_CLANG_TIDY "Enable source code checking using clang-tidy" OFF)
|
||||
|
||||
find_program(
|
||||
CLANG_TIDY_EXE
|
||||
NAMES "clang-tidy"
|
||||
DOC "Path to clang-tidy executable"
|
||||
)
|
||||
|
||||
function(enable_clang_tidy target)
|
||||
# Not enabled in this configuration
|
||||
endfunction()
|
||||
|
||||
if(NOT ENABLE_CLANG_TIDY)
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${CLANG_TIDY_EXE}")
|
||||
message(SEND_ERROR "clang-tidy: Could not find clang-tidy executable (value of variable is \"${CLANG_TIDY_EXE}\".")
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(CMAKE_VERSION VERSION_LESS "3.6.0")
|
||||
message(SEND_ERROR "Clang-tidy support requires CMake 3.6")
|
||||
return()
|
||||
endif()
|
||||
|
||||
message(STATUS "clang-tidy: Using \"${CLANG_TIDY_EXE}\"")
|
||||
|
||||
function(enable_clang_tidy target)
|
||||
SET(TIDY_OPTIONS "${CLANG_TIDY_EXE}")
|
||||
if(FSO_FATAL_WARNINGS)
|
||||
set(TIDY_OPTIONS "${TIDY_OPTIONS};-warnings-as-errors=*")
|
||||
endif()
|
||||
|
||||
set_target_properties(${target} PROPERTIES CXX_CLANG_TIDY "${TIDY_OPTIONS}")
|
||||
endfunction()
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
// Code snippet from http://stackoverflow.com/a/7495023
|
||||
#ifdef _WIN32
|
||||
#include <intrin.h>
|
||||
// Windows
|
||||
#define cpuid __cpuid
|
||||
|
||||
#else
|
||||
|
||||
// GCC Inline Assembly
|
||||
void cpuid(int CPUInfo[4],int InfoType){
|
||||
__asm__ __volatile__ (
|
||||
"cpuid":
|
||||
"=a" (CPUInfo[0]),
|
||||
"=b" (CPUInfo[1]),
|
||||
"=c" (CPUInfo[2]),
|
||||
"=d" (CPUInfo[3]) :
|
||||
"a" (InfoType)
|
||||
);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
int SSE = false;
|
||||
int SSE2 = false;
|
||||
int AVX = false;
|
||||
int AVX2 = false;
|
||||
|
||||
int info[4];
|
||||
cpuid(info, 0);
|
||||
int nIds = info[0];
|
||||
|
||||
// Detect Instruction Set
|
||||
if (nIds >= 1){
|
||||
cpuid(info,0x00000001);
|
||||
SSE = (info[3] & ((int)1 << 25)) != 0;
|
||||
SSE2 = (info[3] & ((int)1 << 26)) != 0;
|
||||
|
||||
AVX = (info[2] & ((int)1 << 28)) != 0;
|
||||
}
|
||||
if (nIds >= 7){
|
||||
cpuid(info,0x00000007);
|
||||
AVX2 = (info[1] & ((int)1 << 5)) != 0;
|
||||
}
|
||||
|
||||
if (AVX2)
|
||||
std::cout << "AVX2";
|
||||
else if(AVX)
|
||||
std::cout << "AVX";
|
||||
else if(SSE2)
|
||||
std::cout << "SSE2";
|
||||
else if(SSE)
|
||||
std::cout << "SSE";
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
|
||||
# Sample toolchain file for building for Windows from a Linux system.
|
||||
#
|
||||
# Typical usage:
|
||||
# *) install cross compiler: `sudo apt-get install mingw-w64 g++-mingw-w64`
|
||||
# *) cd build
|
||||
# *) cmake -DCMAKE_TOOLCHAIN_FILE=~/Toolchain-Ubuntu-mingw64.cmake ..
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Windows)
|
||||
set(TOOLCHAIN_PREFIX x86_64-w64-mingw32)
|
||||
|
||||
# cross compilers to use for C and C++
|
||||
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc)
|
||||
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++)
|
||||
set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres)
|
||||
|
||||
# target environment on the build host system
|
||||
# set 1st to dir with the cross compiler's C/C++ headers/libs
|
||||
set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})
|
||||
|
||||
# modify default behavior of FIND_XXX() commands to
|
||||
# search for headers/libs in the target environment and
|
||||
# don't search for programs in the build host environment
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
@@ -1,154 +0,0 @@
|
||||
# ------------------------- Begin Generic CMake Variable Logging ------------------
|
||||
|
||||
# /* C++ comment style not allowed */
|
||||
|
||||
|
||||
# if you are building in-source, this is the same as CMAKE_SOURCE_DIR, otherwise
|
||||
# this is the top level directory of your build tree
|
||||
MESSAGE( STATUS "CMAKE_BINARY_DIR: " ${CMAKE_BINARY_DIR} )
|
||||
|
||||
# if you are building in-source, this is the same as CMAKE_CURRENT_SOURCE_DIR, otherwise this
|
||||
# is the directory where the compiled or generated files from the current CMakeLists.txt will go to
|
||||
MESSAGE( STATUS "CMAKE_CURRENT_BINARY_DIR: " ${CMAKE_CURRENT_BINARY_DIR} )
|
||||
|
||||
# this is the directory, from which cmake was started, i.e. the top level source directory
|
||||
MESSAGE( STATUS "CMAKE_SOURCE_DIR: " ${CMAKE_SOURCE_DIR} )
|
||||
|
||||
# this is the directory where the currently processed CMakeLists.txt is located in
|
||||
MESSAGE( STATUS "CMAKE_CURRENT_SOURCE_DIR: " ${CMAKE_CURRENT_SOURCE_DIR} )
|
||||
|
||||
# contains the full path to the top level directory of your build tree
|
||||
MESSAGE( STATUS "PROJECT_BINARY_DIR: " ${PROJECT_BINARY_DIR} )
|
||||
|
||||
MESSAGE( STATUS "CMAKE_CXX_COMPILER_ID: " ${CMAKE_CXX_COMPILER_ID} )
|
||||
|
||||
# contains the full path to the root of your project source directory,
|
||||
# i.e. to the nearest directory where CMakeLists.txt contains the PROJECT() command
|
||||
MESSAGE( STATUS "PROJECT_SOURCE_DIR: " ${PROJECT_SOURCE_DIR} )
|
||||
|
||||
# set this variable to specify a common place where CMake should put all executable files
|
||||
# (instead of CMAKE_CURRENT_BINARY_DIR)
|
||||
MESSAGE( STATUS "EXECUTABLE_OUTPUT_PATH: " ${EXECUTABLE_OUTPUT_PATH} )
|
||||
|
||||
# set this variable to specify a common place where CMake should put all libraries
|
||||
# (instead of CMAKE_CURRENT_BINARY_DIR)
|
||||
MESSAGE( STATUS "LIBRARY_OUTPUT_PATH: " ${LIBRARY_OUTPUT_PATH} )
|
||||
|
||||
# tell CMake to search first in directories listed in CMAKE_MODULE_PATH
|
||||
# when you use FIND_PACKAGE() or INCLUDE()
|
||||
MESSAGE( STATUS "CMAKE_MODULE_PATH: " ${CMAKE_MODULE_PATH} )
|
||||
|
||||
# this is the complete path of the cmake which runs currently (e.g. /usr/local/bin/cmake)
|
||||
MESSAGE( STATUS "CMAKE_COMMAND: " ${CMAKE_COMMAND} )
|
||||
|
||||
# this is the CMake installation directory
|
||||
MESSAGE( STATUS "CMAKE_ROOT: " ${CMAKE_ROOT} )
|
||||
|
||||
# this is the filename including the complete path of the file where this variable is used.
|
||||
MESSAGE( STATUS "CMAKE_CURRENT_LIST_FILE: " ${CMAKE_CURRENT_LIST_FILE} )
|
||||
|
||||
# this is linenumber where the variable is used
|
||||
MESSAGE( STATUS "CMAKE_CURRENT_LIST_LINE: " ${CMAKE_CURRENT_LIST_LINE} )
|
||||
|
||||
# this is used when searching for include files e.g. using the FIND_PATH() command.
|
||||
MESSAGE( STATUS "CMAKE_INCLUDE_PATH: " ${CMAKE_INCLUDE_PATH} )
|
||||
|
||||
# this is used when searching for libraries e.g. using the FIND_LIBRARY() command.
|
||||
MESSAGE( STATUS "CMAKE_LIBRARY_PATH: " ${CMAKE_LIBRARY_PATH} )
|
||||
|
||||
# the complete system name, e.g. "Linux-2.4.22", "FreeBSD-5.4-RELEASE" or "Windows 5.1"
|
||||
MESSAGE( STATUS "CMAKE_SYSTEM: " ${CMAKE_SYSTEM} )
|
||||
|
||||
# the short system name, e.g. "Linux", "FreeBSD" or "Windows"
|
||||
MESSAGE( STATUS "CMAKE_SYSTEM_NAME: " ${CMAKE_SYSTEM_NAME} )
|
||||
|
||||
# only the version part of CMAKE_SYSTEM
|
||||
MESSAGE( STATUS "CMAKE_SYSTEM_VERSION: " ${CMAKE_SYSTEM_VERSION} )
|
||||
|
||||
# the processor name (e.g. "Intel(R) Pentium(R) M processor 2.00GHz")
|
||||
MESSAGE( STATUS "CMAKE_SYSTEM_PROCESSOR: " ${CMAKE_SYSTEM_PROCESSOR} )
|
||||
|
||||
# is TRUE on all UNIX-like OS's, including Apple OS X and CygWin
|
||||
MESSAGE( STATUS "UNIX: " ${UNIX} )
|
||||
|
||||
# is TRUE on Windows, including CygWin
|
||||
MESSAGE( STATUS "WIN32: " ${WIN32} )
|
||||
|
||||
# is TRUE on Apple OS X
|
||||
MESSAGE( STATUS "APPLE: " ${APPLE} )
|
||||
|
||||
# is TRUE when using the MinGW compiler in Windows
|
||||
MESSAGE( STATUS "MINGW: " ${MINGW} )
|
||||
|
||||
# is TRUE on Windows when using the CygWin version of cmake
|
||||
MESSAGE( STATUS "CYGWIN: " ${CYGWIN} )
|
||||
|
||||
# is TRUE on Windows when using a Borland compiler
|
||||
MESSAGE( STATUS "BORLAND: " ${BORLAND} )
|
||||
|
||||
# Microsoft compiler
|
||||
MESSAGE( STATUS "MSVC: " ${MSVC} )
|
||||
MESSAGE( STATUS "MSVC_IDE: " ${MSVC_IDE} )
|
||||
MESSAGE( STATUS "MSVC60: " ${MSVC60} )
|
||||
MESSAGE( STATUS "MSVC70: " ${MSVC70} )
|
||||
MESSAGE( STATUS "MSVC71: " ${MSVC71} )
|
||||
MESSAGE( STATUS "MSVC80: " ${MSVC80} )
|
||||
MESSAGE( STATUS "CMAKE_COMPILER_2005: " ${CMAKE_COMPILER_2005} )
|
||||
|
||||
|
||||
# set this to true if you don't want to rebuild the object files if the rules have changed,
|
||||
# but not the actual source files or headers (e.g. if you changed the some compiler switches)
|
||||
MESSAGE( STATUS "CMAKE_SKIP_RULE_DEPENDENCY: " ${CMAKE_SKIP_RULE_DEPENDENCY} )
|
||||
|
||||
# since CMake 2.1 the install rule depends on all, i.e. everything will be built before installing.
|
||||
# If you don't like this, set this one to true.
|
||||
MESSAGE( STATUS "CMAKE_SKIP_INSTALL_ALL_DEPENDENCY: " ${CMAKE_SKIP_INSTALL_ALL_DEPENDENCY} )
|
||||
|
||||
# If set, runtime paths are not added when using shared libraries. Default it is set to OFF
|
||||
MESSAGE( STATUS "CMAKE_SKIP_RPATH: " ${CMAKE_SKIP_RPATH} )
|
||||
|
||||
# set this to true if you are using makefiles and want to see the full compile and link
|
||||
# commands instead of only the shortened ones
|
||||
MESSAGE( STATUS "CMAKE_VERBOSE_MAKEFILE: " ${CMAKE_VERBOSE_MAKEFILE} )
|
||||
|
||||
# this will cause CMake to not put in the rules that re-run CMake. This might be useful if
|
||||
# you want to use the generated build files on another machine.
|
||||
MESSAGE( STATUS "CMAKE_SUPPRESS_REGENERATION: " ${CMAKE_SUPPRESS_REGENERATION} )
|
||||
|
||||
|
||||
# A simple way to get switches to the compiler is to use ADD_DEFINITIONS().
|
||||
# But there are also two variables exactly for this purpose:
|
||||
|
||||
# the compiler flags for compiling C sources
|
||||
MESSAGE( STATUS "CMAKE_C_FLAGS: " ${CMAKE_C_FLAGS} )
|
||||
|
||||
# the compiler flags for compiling C++ sources
|
||||
MESSAGE( STATUS "CMAKE_CXX_FLAGS: " ${CMAKE_CXX_FLAGS} )
|
||||
|
||||
|
||||
# Choose the type of build. Example: SET(CMAKE_BUILD_TYPE Debug)
|
||||
MESSAGE( STATUS "CMAKE_BUILD_TYPE: " ${CMAKE_BUILD_TYPE} )
|
||||
|
||||
# if this is set to ON, then all libraries are built as shared libraries by default.
|
||||
MESSAGE( STATUS "BUILD_SHARED_LIBS: " ${BUILD_SHARED_LIBS} )
|
||||
|
||||
# the compiler used for C files
|
||||
MESSAGE( STATUS "CMAKE_C_COMPILER: " ${CMAKE_C_COMPILER} )
|
||||
|
||||
# the compiler used for C++ files
|
||||
MESSAGE( STATUS "CMAKE_CXX_COMPILER: " ${CMAKE_CXX_COMPILER} )
|
||||
|
||||
# if the compiler is a variant of gcc, this should be set to 1
|
||||
MESSAGE( STATUS "CMAKE_COMPILER_IS_GNUCC: " ${CMAKE_COMPILER_IS_GNUCC} )
|
||||
|
||||
# if the compiler is a variant of g++, this should be set to 1
|
||||
MESSAGE( STATUS "CMAKE_COMPILER_IS_GNUCXX : " ${CMAKE_COMPILER_IS_GNUCXX} )
|
||||
|
||||
# the tools for creating libraries
|
||||
MESSAGE( STATUS "CMAKE_AR: " ${CMAKE_AR} )
|
||||
MESSAGE( STATUS "CMAKE_RANLIB: " ${CMAKE_RANLIB} )
|
||||
|
||||
#
|
||||
#MESSAGE( STATUS ": " ${} )
|
||||
|
||||
# ------------------------- End of Generic CMake Variable Logging ------------------
|
||||
@@ -1,37 +0,0 @@
|
||||
|
||||
# add a target to generate API documentation with Doxygen
|
||||
find_package(Doxygen)
|
||||
if(DOXYGEN_FOUND)
|
||||
SET(OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/documentation/doxygen")
|
||||
FILE(MAKE_DIRECTORY "${OUTPUT_DIR}")
|
||||
|
||||
FILE(TO_NATIVE_PATH ${OUTPUT_DIR} OUTPUT_DIR)
|
||||
SET(OUTPUT_DIR \"${OUTPUT_DIR}\")
|
||||
|
||||
SET(INPUTS "${CMAKE_CURRENT_SOURCE_DIR}/code" "${CMAKE_CURRENT_SOURCE_DIR}/freespace2" "${CMAKE_CURRENT_SOURCE_DIR}/fred2" "${CMAKE_CURRENT_SOURCE_DIR}/wxfred2")
|
||||
|
||||
SET(INPUT_DIRS)
|
||||
FOREACH(DIR IN LISTS INPUTS)
|
||||
FILE(TO_NATIVE_PATH ${DIR} native_dir)
|
||||
|
||||
LIST(APPEND INPUT_DIRS \"${native_dir}\")
|
||||
ENDFOREACH(DIR)
|
||||
STRING(REPLACE ";" " " INPUT_DIRS "${INPUT_DIRS}")
|
||||
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/fs2open.Doxyfile.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/fs2open.Doxyfile
|
||||
@ONLY)
|
||||
|
||||
add_custom_target(doxygen
|
||||
${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/fs2open.Doxyfile
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMENT "Generating API documentation with Doxygen" VERBATIM
|
||||
)
|
||||
|
||||
set_target_properties(doxygen
|
||||
PROPERTIES
|
||||
FOLDER "Documentation"
|
||||
EXCLUDE_FROM_ALL ON
|
||||
EXCLUDE_FROM_DEFAULT_BUILD ON
|
||||
)
|
||||
endif(DOXYGEN_FOUND)
|
||||
Vendored
-4054
File diff suppressed because it is too large.
Load diff
Vendored
-1
Submodule cmake/external/rpavlik-cmake-modules deleted from 7cef9577d6.
@@ -1,16 +0,0 @@
|
||||
|
||||
include(CheckIncludeFile)
|
||||
|
||||
add_library(speech INTERFACE)
|
||||
|
||||
if (WIN32)
|
||||
CHECK_INCLUDE_FILE_CXX("sapi.h" HAVE_SAPI_H)
|
||||
|
||||
if (NOT HAVE_SAPI_H)
|
||||
message(SEND_ERROR "sapi.h could not be found on your platform. Please disable speech support.")
|
||||
endif()
|
||||
else()
|
||||
message(SEND_ERROR "Text to Speech is not supported on this platform!")
|
||||
endif()
|
||||
|
||||
target_compile_definitions(speech INTERFACE -DFS2_SPEECH)
|
||||
@@ -1,9 +0,0 @@
|
||||
|
||||
|
||||
#ifndef __FREDRC_H
|
||||
#define __FREDRC_H
|
||||
|
||||
#define ABOUT_LINE_1 "FRED2_OPEN - FreeSpace Editor, Version @FSO_PRODUCT_VERSION_STRING@ OpenGL"
|
||||
#define MAINFRAME_CONTENTS "FRED2_OPEN @FSO_PRODUCT_VERSION_STRING@ - FreeSpace2 Mission Editor\nUntitled\nFRED2\nFreeSpace2 Missions (*.fs2)\n.fs2\nFreeSpace2Mission\nFreeSpace2 Mission"
|
||||
|
||||
#endif // __FREDRC_H
|
||||
@@ -1,7 +0,0 @@
|
||||
|
||||
|
||||
include(Cxx11)
|
||||
include(platformChecks)
|
||||
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_LIST_DIR}/project.h.in ${GENERATED_SOURCE_DIR}/project.h)
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_LIST_DIR}/fred_rc.h.in ${GENERATED_SOURCE_DIR}/fred_rc.h)
|
||||
@@ -1,9 +0,0 @@
|
||||
|
||||
SET(BINARY_DESTINATION ".")
|
||||
SET(LIBRAY_DESTINATION "${BINARY_DESTINATION}")
|
||||
|
||||
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(IS_64BIT TRUE)
|
||||
else()
|
||||
set(IS_64BIT FALSE)
|
||||
endif()
|
||||
@@ -1,8 +0,0 @@
|
||||
|
||||
SET(CODE_HEADERS ${CMAKE_SOURCE_DIR}/code)
|
||||
|
||||
SET(FREESPACE_HEADERS ${CMAKE_SOURCE_DIR}/freespace2)
|
||||
|
||||
SET(FRED_HEADERS ${CMAKE_SOURCE_DIR}/fred2)
|
||||
|
||||
SET(WXFRED_HEADERS ${CMAKE_SOURCE_DIR}/wxfred2)
|
||||
@@ -1,14 +0,0 @@
|
||||
|
||||
SET(CPACK_PACKAGE_VERSION_MAJOR ${FSO_VERSION_MAJOR})
|
||||
SET(CPACK_PACKAGE_VERSION_MINOR ${FSO_VERSION_MINOR})
|
||||
SET(CPACK_PACKAGE_VERSION_PATCH ${FSO_VERSION_BUILD})
|
||||
|
||||
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${FSO_PROJECT_DESCRIPTION})
|
||||
|
||||
IF(WIN32)
|
||||
SET(CPACK_NSIS_MUI_ICON ${FSO_INSTALLER_ICON})
|
||||
|
||||
set(CPACK_NSIS_MENU_LINKS "http://www.hard-light.net/" "FreeSpace Community")
|
||||
ENDIF(WIN32)
|
||||
|
||||
include(CPack)
|
||||
@@ -1,34 +0,0 @@
|
||||
|
||||
MESSAGE(STATUS "Doing Mac OSX specific things...")
|
||||
target_compile_definitions(platform INTERFACE APPLE_APP)
|
||||
SET(EXE_GUI_TYPE MACOSX_BUNDLE)
|
||||
|
||||
FIND_LIBRARY(COCOA_LIBRARY Cocoa)
|
||||
|
||||
if (NOT COCOA_LIBRARY)
|
||||
message(FATAL_ERROR "Couldn't find Cocoa!")
|
||||
endif()
|
||||
|
||||
target_link_libraries(platform INTERFACE ${COCOA_LIBRARY})
|
||||
|
||||
SET(CMAKE_OSX_DEPLOYMENT_TARGET "10.9")
|
||||
|
||||
SET(CMAKE_SKIP_RPATH FALSE)
|
||||
SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
|
||||
SET(CMAKE_INSTALL_RPATH @loader_path/../Frameworks/)
|
||||
|
||||
# Set the path where library dependencies are copied to
|
||||
SET(LIBRAY_DESTINATION "../Frameworks")
|
||||
|
||||
set(PLATFORM_MAC TRUE CACHE INTERNAL "" FORCE)
|
||||
|
||||
# Generate and don't strip debug symbols
|
||||
# These settings don't seem to generate debug symbols for code and Freespace2
|
||||
# so those settings are set manually in code and Freespace2's CMakeLists.txt files
|
||||
set(CMAKE_XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS "YES")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_COPY_PHASE_STRIP "NO")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_STRIP_INSTALLED_PRODUCT "NO")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN "NO")
|
||||
|
||||
# Generate .dSYM file
|
||||
set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "dwarf-with-dsym")
|
||||
@@ -1,10 +0,0 @@
|
||||
|
||||
target_compile_definitions(platform INTERFACE SCP_BSD)
|
||||
|
||||
find_library(EXECINFO_LIB execinfo)
|
||||
|
||||
if (NOT EXECINFO_LIB)
|
||||
message(FATAL_ERROR "Couldn't find libexecinfo! Please install it and rerun the configuration.")
|
||||
else()
|
||||
target_link_libraries(platform INTERFACE "${EXECINFO_LIB}")
|
||||
endif()
|
||||
@@ -1,18 +0,0 @@
|
||||
|
||||
target_compile_definitions(platform INTERFACE SCP_SOLARIS)
|
||||
|
||||
find_library(SOCKET_LIB socket)
|
||||
|
||||
if (NOT SOCKET_LIB)
|
||||
message(FATAL_ERROR "Couldn't find libsocket! Please install it and rerun the configuration.")
|
||||
else()
|
||||
target_link_libraries(platform INTERFACE "${SOCKET_LIB}")
|
||||
endif()
|
||||
|
||||
find_library(NSL_LIB nsl)
|
||||
|
||||
if (NOT NSL_LIB)
|
||||
message(FATAL_ERROR "Couldn't find libnsl! Please install it and rerun the configuration.")
|
||||
else()
|
||||
target_link_libraries(platform INTERFACE "${NSL_LIB}")
|
||||
endif()
|
||||
@@ -1,13 +0,0 @@
|
||||
|
||||
INCLUDE(util)
|
||||
|
||||
MESSAGE(STATUS "Configuring UNIX specific things and stuff...")
|
||||
|
||||
target_compile_definitions(platform INTERFACE SCP_UNIX USE_OPENAL)
|
||||
|
||||
# Set RPATH
|
||||
set(CMAKE_SKIP_BUILD_RPATH TRUE)
|
||||
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
|
||||
set(CMAKE_INSTALL_RPATH "\$ORIGIN")
|
||||
|
||||
set(PLATFORM_UNIX TRUE CACHE INTERNAL "" FORCE)
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
MESSAGE(STATUS "Configuring Windows specific things and stuff...")
|
||||
|
||||
SET(WIN32_LIBS
|
||||
comctl32
|
||||
msacm32
|
||||
odbc32
|
||||
odbccp32
|
||||
vfw32
|
||||
winmm
|
||||
wsock32
|
||||
psapi
|
||||
)
|
||||
|
||||
IF (MINGW)
|
||||
SET(WIN32_LIBS ${WIN32_LIBS} mingw32)
|
||||
ENDIF (MINGW)
|
||||
|
||||
target_link_libraries(platform INTERFACE ${WIN32_LIBS})
|
||||
|
||||
target_compile_definitions(platform INTERFACE WIN32 USE_OPENAL _WINDOWS)
|
||||
|
||||
# Specify minimum Windows version for the headers (currently this is XP)
|
||||
target_compile_definitions(platform INTERFACE NTDDI_VERSION=0x05010000 _WIN32_WINNT=0x0501)
|
||||
|
||||
SET(EXE_GUI_TYPE WIN32)
|
||||
set(PLATFORM_WINDOWS TRUE CACHE INTERNAL "" FORCE)
|
||||
@@ -1,48 +0,0 @@
|
||||
|
||||
include(CheckFunctionExists)
|
||||
include(CheckIncludeFiles)
|
||||
include(CheckIncludeFile)
|
||||
include(CheckIncludeFileCXX)
|
||||
include(CheckLibraryExists)
|
||||
include(CheckPrototypeDefinition)
|
||||
include(CheckStructHasMember)
|
||||
include(CheckSymbolExists)
|
||||
include(CheckCXXSymbolExists)
|
||||
include(CheckTypeSize)
|
||||
|
||||
CHECK_INCLUDE_FILE("execinfo.h" HAVE_EXECINFO_H)
|
||||
CHECK_INCLUDE_FILE_CXX("cxxabi.h" HAVE_CXXAPI_H)
|
||||
|
||||
CHECK_TYPE_SIZE("max_align_t" MAX_ALIGN_T)
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
set(CMAKE_REQUIRED_FLAGS "-std=c++11") # required for g++ <= 5
|
||||
endif()
|
||||
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES "cstddef")
|
||||
CHECK_TYPE_SIZE("std::max_align_t" STD_MAX_ALIGN_T LANGUAGE CXX)
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES "type_traits")
|
||||
CHECK_TYPE_SIZE("std::is_trivially_copyable<int>" STD_IS_TRIVIALLY_COPYABLE LANGUAGE CXX)
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES)
|
||||
|
||||
CHECK_TYPE_SIZE("char32_t" CHAR32_T LANGUAGE CXX)
|
||||
CHECK_TYPE_SIZE("U'b'" UNICODE_CHAR_LITERAL LANGUAGE CXX)
|
||||
|
||||
set(CMAKE_REQUIRED_FLAGS)
|
||||
|
||||
|
||||
CHECK_FUNCTION_EXISTS(strcasecmp HAVE_STRCASECMP)
|
||||
CHECK_FUNCTION_EXISTS(strncasecmp HAVE_STRNCASECMP)
|
||||
|
||||
CHECK_FUNCTION_EXISTS(_stricmp HAVE__STRICMP)
|
||||
CHECK_FUNCTION_EXISTS(_strnicmp HAVE__STRNICMP)
|
||||
|
||||
CHECK_FUNCTION_EXISTS(strlwr HAVE_STRLWR)
|
||||
|
||||
CHECK_INCLUDE_FILE("strings.h" HAVE_STRINGS_H)
|
||||
|
||||
check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF)
|
||||
check_symbol_exists(_snprintf "stdio.h" HAVE__SNPRINTF)
|
||||
|
||||
set(PLATFORM_CHECK_HEADER "${GENERATED_SOURCE_DIR}/platformChecks.h")
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_LIST_DIR}/platformChecks.h.in "${PLATFORM_CHECK_HEADER}")
|
||||
@@ -1,31 +0,0 @@
|
||||
|
||||
#ifndef __PLATFORM_CHECKS_H__
|
||||
#define __PLATFORM_CHECKS_H__
|
||||
#pragma once
|
||||
|
||||
#cmakedefine HAVE_EXECINFO_H
|
||||
#cmakedefine HAVE_CXXAPI_H
|
||||
#cmakedefine HAVE_MAX_ALIGN_T
|
||||
#cmakedefine HAVE_STD_MAX_ALIGN_T
|
||||
|
||||
#cmakedefine HAVE_STD_IS_TRIVIALLY_COPYABLE
|
||||
#cmakedefine HAVE_STD_IS_TRIVIALLY_COPYABLE_ARRAY
|
||||
|
||||
#cmakedefine01 IS_64BIT
|
||||
|
||||
#cmakedefine01 HAVE_STRCASECMP
|
||||
#cmakedefine01 HAVE_STRNCASECMP
|
||||
#cmakedefine01 HAVE__STRICMP
|
||||
#cmakedefine01 HAVE__STRNICMP
|
||||
|
||||
#cmakedefine01 HAVE_STRLWR
|
||||
|
||||
#cmakedefine01 HAVE_STRINGS_H
|
||||
|
||||
#cmakedefine01 HAVE_CHAR32_T
|
||||
#cmakedefine01 HAVE_UNICODE_CHAR_LITERAL
|
||||
|
||||
#cmakedefine01 HAVE_SNPRINTF
|
||||
#cmakedefine01 HAVE__SNPRINTF
|
||||
|
||||
#endif // __PLATFORM_CHECKS_H__
|
||||
@@ -1,29 +0,0 @@
|
||||
|
||||
add_library(platform INTERFACE)
|
||||
|
||||
IF(FSO_CMAKE_DEBUG)
|
||||
INCLUDE(debug-vars)
|
||||
ENDIF(FSO_CMAKE_DEBUG)
|
||||
|
||||
set(PLATFORM_WINDOWS FALSE CACHE INTERNAL "" FORCE)
|
||||
set(PLATFORM_UNIX FALSE CACHE INTERNAL "" FORCE)
|
||||
set(PLATFORM_LINUX FALSE CACHE INTERNAL "" FORCE)
|
||||
set(PLATFORM_MAC FALSE CACHE INTERNAL "" FORCE)
|
||||
|
||||
IF(WIN32)
|
||||
INCLUDE(platform-win32)
|
||||
ELSEIF(UNIX)
|
||||
INCLUDE(platform-unix)
|
||||
|
||||
IF(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
||||
INCLUDE(platform-freebsd)
|
||||
ELSEIF(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
|
||||
INCLUDE(platform-solaris)
|
||||
ELSEIF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
include(platform-darwin)
|
||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
set(PLATFORM_LINUX TRUE CACHE INTERNAL "" FORCE)
|
||||
ENDIF()
|
||||
ELSE(WIN32)
|
||||
MESSAGE(STATUS "This platform is not supported, good luck!")
|
||||
ENDIF(WIN32)
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
|
||||
#ifndef __PROJECT_H
|
||||
#define __PROJECT_H
|
||||
|
||||
#define FS_VERSION_MAJOR @FSO_VERSION_MAJOR@
|
||||
#define FS_VERSION_MINOR @FSO_VERSION_MINOR@
|
||||
#define FS_VERSION_BUILD @FSO_VERSION_BUILD@
|
||||
#define FS_VERSION_REVIS @FSO_VERSION_REVISION@
|
||||
#define FS_VERSION_REVIS_STR "@FSO_VERSION_REVISION_STR@"
|
||||
|
||||
#define FS_VERSION_HAS_REVIS @FSO_VERSION_HAS_REVISION@
|
||||
|
||||
#define FS_VERSION_FULL "@FSO_FULL_VERSION_STRING@"
|
||||
#define FS_PRODUCT_VERSION "@FSO_PRODUCT_VERSION_STRING@"
|
||||
|
||||
#endif // __PROJECT_H
|
||||
@@ -1,18 +0,0 @@
|
||||
|
||||
MESSAGE(STATUS "Doing configuration specific to Apple Clang...")
|
||||
|
||||
# TODO: Actually add Mac specific flags here...
|
||||
|
||||
# Suppress specific warning
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -funroll-loops -fsigned-char -Wno-unknown-pragmas")
|
||||
|
||||
# Omit "conversion from string literal to 'char *' is deprecated" warnings.
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-write-strings")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated -Wno-char-subscripts")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics")
|
||||
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-Wno-unused-variable")
|
||||
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-Wextra -Wshadow -Wno-unused-parameter")
|
||||
@@ -1,109 +0,0 @@
|
||||
# Clang
|
||||
include(EnableExtraCompilerWarnings)
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
||||
MESSAGE(STATUS "Doing configuration specific to clang...")
|
||||
|
||||
option(CLANG_ENABLE_LEAK_CHECK "Enable -fsanitize=leak" OFF)
|
||||
option(CLANG_ENABLE_ADDRESS_SANITIZER "Enable -fsanitize=address" OFF)
|
||||
|
||||
# These are the default values
|
||||
set(C_BASE_FLAGS "-march=native -pipe")
|
||||
set(CXX_BASE_FLAGS "-march=native -pipe")
|
||||
|
||||
# For C and C++, the values can be overwritten independently
|
||||
if(DEFINED ENV{CXXFLAGS})
|
||||
set(CXX_BASE_FLAGS $ENV{CXXFLAGS})
|
||||
endif()
|
||||
if(DEFINED ENV{CFLAGS})
|
||||
set(C_BASE_FLAGS $ENV{CFLAGS})
|
||||
endif()
|
||||
|
||||
# Initialize with an empty string to make sure we always get a clean start
|
||||
set(COMPILER_FLAGS "")
|
||||
|
||||
# This is a slight hack since our flag setup is a bit more complicated
|
||||
_enable_extra_compiler_warnings_flags()
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} ${_flags}")
|
||||
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -funroll-loops -fsigned-char -Wno-unknown-pragmas")
|
||||
|
||||
# Omit "argument unused during compilation" when clang is used with ccache.
|
||||
if(${CMAKE_CXX_COMPILER} MATCHES "ccache")
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Qunused-arguments")
|
||||
endif()
|
||||
|
||||
if ("${CMAKE_GENERATOR}" STREQUAL "Ninja")
|
||||
# Force color diagnostics for Ninja generator
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -fdiagnostics-color")
|
||||
endif()
|
||||
|
||||
# Start with an empty list
|
||||
set(SANITIZE_FLAGS)
|
||||
|
||||
if(CLANG_ENABLE_ADDRESS_SANITIZER)
|
||||
set(CMAKE_REQUIRED_FLAGS "-fsanitize=address")
|
||||
CHECK_C_COMPILER_FLAG("-fsanitize=address" SUPPORTS_SANITIZE_ADDRESS)
|
||||
|
||||
if (SUPPORTS_SANITIZE_ADDRESS)
|
||||
set(SANITIZE_FLAGS ${SANITIZE_FLAGS} "address")
|
||||
endif()
|
||||
endif()
|
||||
if (CLANG_ENABLE_LEAK_CHECK)
|
||||
check_linker_flag("-fsanitize=leak" SUPPORTS_FSANITIZE_LEAK)
|
||||
|
||||
if (SUPPORTS_FSANITIZE_LEAK)
|
||||
set(SANITIZE_FLAGS ${SANITIZE_FLAGS} "leak")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
string(REPLACE ";" "," SANITIZE_FLAGS "${SANITIZE_FLAGS}")
|
||||
if (NOT "${SANITIZE_FLAGS}" STREQUAL "")
|
||||
set(SANITIZE_FLAGS "-fsanitize=${SANITIZE_FLAGS}")
|
||||
endif()
|
||||
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} ${SANITIZE_FLAGS}")
|
||||
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wformat-security")
|
||||
|
||||
# Dear Clang, please tell us if a function does not return a value since that part of the standard is stupid!
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wreturn-type")
|
||||
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-char-subscripts")
|
||||
|
||||
check_cxx_compiler_flag(-Wshift-negative-value SUPPORTS_SHIFT_NEGATIVE_VALUE)
|
||||
if(SUPPORTS_SHIFT_NEGATIVE_VALUE)
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-shift-negative-value")
|
||||
endif()
|
||||
|
||||
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-parameter")
|
||||
|
||||
set(COMPILER_FLAGS_DEBUG "-O0 -g -Wshadow")
|
||||
|
||||
# Always use the base flags and add our compiler flags at the bacl
|
||||
set(CMAKE_CXX_FLAGS "${CXX_BASE_FLAGS} ${COMPILER_FLAGS}")
|
||||
set(CMAKE_C_FLAGS "${C_BASE_FLAGS} ${COMPILER_FLAGS}")
|
||||
|
||||
set(CMAKE_CXX_FLAGS_RELEASE ${COMPILER_FLAGS_RELEASE})
|
||||
set(CMAKE_C_FLAGS_RELEASE ${COMPILER_FLAGS_RELEASE})
|
||||
|
||||
set(CMAKE_CXX_FLAGS_DEBUG ${COMPILER_FLAGS_DEBUG})
|
||||
set(CMAKE_C_FLAGS_DEBUG ${COMPILER_FLAGS_DEBUG})
|
||||
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "")
|
||||
|
||||
if (SANITIZE_FLAGS)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${SANITIZE_FLAGS}")
|
||||
endif()
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "-g -rdynamic")
|
||||
|
||||
if (FSO_FATAL_WARNINGS)
|
||||
# Make warnings fatal if the right variable is set
|
||||
target_compile_options(compiler INTERFACE "-Werror")
|
||||
endif()
|
||||
|
||||
# Always define this to make sure that the fixed width format macros are available
|
||||
target_compile_definitions(compiler INTERFACE __STDC_FORMAT_MACROS)
|
||||
@@ -1,142 +0,0 @@
|
||||
|
||||
include(EnableExtraCompilerWarnings)
|
||||
include(CheckCCompilerFlag)
|
||||
include(util)
|
||||
|
||||
MESSAGE(STATUS "Doing configuration specific to gcc...")
|
||||
|
||||
option(GCC_ENABLE_LEAK_CHECK "Enable -fsanitize=leak" OFF)
|
||||
option(GCC_ENABLE_ADDRESS_SANITIZER "Enable -fsanitize=address" OFF)
|
||||
option(GCC_ENABLE_SANITIZE_UNDEFINED "Enable -fsanitize=undefined" OFF)
|
||||
|
||||
# These are the default values
|
||||
set(C_BASE_FLAGS "-march=native -pipe")
|
||||
set(CXX_BASE_FLAGS "-march=native -pipe")
|
||||
|
||||
# For C and C++, the values can be overwritten independently
|
||||
if(DEFINED ENV{CFLAGS})
|
||||
set(C_BASE_FLAGS $ENV{CFLAGS})
|
||||
endif()
|
||||
if(DEFINED ENV{CXXFLAGS})
|
||||
set(CXX_BASE_FLAGS $ENV{CXXFLAGS})
|
||||
endif()
|
||||
|
||||
# Initialize with an empty string to make sure we always get a clean start
|
||||
set(COMPILER_FLAGS "")
|
||||
|
||||
# This is a slight hack since our flag setup is a bit more complicated
|
||||
_enable_extra_compiler_warnings_flags()
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} ${_flags}")
|
||||
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -funroll-loops -fsigned-char -Wno-unknown-pragmas")
|
||||
|
||||
# Place each function and data in its own section so the linker can
|
||||
# perform dead code elimination
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -fdata-sections -ffunction-sections")
|
||||
|
||||
if ("${CMAKE_GENERATOR}" STREQUAL "Ninja")
|
||||
# Force color diagnostics for Ninja generator
|
||||
CHECK_C_COMPILER_FLAG(-fdiagnostics-color SUPPORTS_DIAGNOSTIC_COLOR)
|
||||
|
||||
if(SUPPORTS_DIAGNOSTIC_COLOR)
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -fdiagnostics-color")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Start with an empty list
|
||||
set(SANITIZE_FLAGS)
|
||||
|
||||
if(GCC_ENABLE_ADDRESS_SANITIZER)
|
||||
set(CMAKE_REQUIRED_FLAGS "-fsanitize=address")
|
||||
CHECK_C_COMPILER_FLAG("-fsanitize=address" SUPPORTS_SANITIZE_ADDRESS)
|
||||
|
||||
if (SUPPORTS_SANITIZE_ADDRESS)
|
||||
set(SANITIZE_FLAGS ${SANITIZE_FLAGS} "address")
|
||||
endif()
|
||||
endif()
|
||||
if (GCC_ENABLE_LEAK_CHECK)
|
||||
check_linker_flag("-fsanitize=leak" SUPPORTS_FSANITIZE_LEAK)
|
||||
|
||||
if (SUPPORTS_FSANITIZE_LEAK)
|
||||
set(SANITIZE_FLAGS ${SANITIZE_FLAGS} "leak")
|
||||
endif()
|
||||
endif()
|
||||
if (GCC_ENABLE_SANITIZE_UNDEFINED)
|
||||
check_linker_flag("-fsanitize=undefined" SUPPORTS_SANITIZE_UNDEFINED)
|
||||
|
||||
if (SUPPORTS_SANITIZE_UNDEFINED)
|
||||
set(SANITIZE_FLAGS ${SANITIZE_FLAGS} "undefined")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
string(REPLACE ";" "," SANITIZE_FLAGS "${SANITIZE_FLAGS}")
|
||||
if (NOT "${SANITIZE_FLAGS}" STREQUAL "")
|
||||
set(SANITIZE_FLAGS "-fsanitize=${SANITIZE_FLAGS}")
|
||||
endif()
|
||||
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} ${SANITIZE_FLAGS}")
|
||||
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wformat-security")
|
||||
|
||||
# Dear GCC, please tell us if a function does not return a value since that part of the standard is stupid!
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wreturn-type")
|
||||
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-deprecated -Wno-char-subscripts")
|
||||
|
||||
# These two warnings cause a lot of false-positives in the FSO code base
|
||||
check_cxx_compiler_flag(-Wstringop-truncation SUPPORTS_STRINGOP_TRUNCATION)
|
||||
if(SUPPORTS_STRINGOP_TRUNCATION)
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-stringop-truncation")
|
||||
endif()
|
||||
|
||||
check_cxx_compiler_flag(-Wstringop-overflow SUPPORTS_STRINGOP_OVERFLOW)
|
||||
if(SUPPORTS_STRINGOP_TRUNCATION)
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-stringop-overflow")
|
||||
endif()
|
||||
|
||||
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-but-set-variable -Wno-array-bounds -Wno-empty-body -Wno-clobbered -Wno-unused-parameter")
|
||||
|
||||
set(COMPILER_FLAGS_DEBUG "-O0 -g -Wshadow")
|
||||
|
||||
# Always use the base flags and add our compiler flags at the bacl
|
||||
set(CMAKE_CXX_FLAGS "${CXX_BASE_FLAGS} ${COMPILER_FLAGS}")
|
||||
set(CMAKE_C_FLAGS "${C_BASE_FLAGS} ${COMPILER_FLAGS}")
|
||||
|
||||
set(CMAKE_CXX_FLAGS_RELEASE ${COMPILER_FLAGS_RELEASE})
|
||||
set(CMAKE_C_FLAGS_RELEASE ${COMPILER_FLAGS_RELEASE})
|
||||
|
||||
set(CMAKE_CXX_FLAGS_DEBUG ${COMPILER_FLAGS_DEBUG})
|
||||
set(CMAKE_C_FLAGS_DEBUG ${COMPILER_FLAGS_DEBUG})
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "")
|
||||
|
||||
IF (MINGW)
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static -static-libgcc -static-libstdc++ -Wl,--enable-auto-import")
|
||||
target_compile_definitions(compiler INTERFACE __USE_MINGW_ANSI_STDIO=1)
|
||||
ENDIF(MINGW)
|
||||
|
||||
if (SANITIZE_FLAGS)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${SANITIZE_FLAGS}")
|
||||
endif()
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "-g")
|
||||
IF(NOT MINGW)
|
||||
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -rdynamic")
|
||||
# Allow the linker to perform dead code elimination; this is considered
|
||||
# experimental for COFF and PE formats and thus disabled for Windows builds
|
||||
# (https://sourceware.org/binutils/docs/ld/Options.html)
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
|
||||
ENDIF(NOT MINGW)
|
||||
|
||||
IF(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "-Wl,-zignore")
|
||||
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
|
||||
|
||||
if (FSO_FATAL_WARNINGS)
|
||||
# Make warnings fatal if the right variable is set
|
||||
target_compile_options(compiler INTERFACE "-Werror")
|
||||
endif()
|
||||
|
||||
# Always define this to make sure that the fixed width format macros are available
|
||||
target_compile_definitions(compiler INTERFACE __STDC_FORMAT_MACROS=1)
|
||||
@@ -1,145 +0,0 @@
|
||||
|
||||
include(EnableExtraCompilerWarnings)
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(util)
|
||||
|
||||
MESSAGE(STATUS "Doing configuration specific to visual studio...")
|
||||
|
||||
set_property(GLOBAL PROPERTY DEBUG_CONFIGURATIONS Debug)
|
||||
|
||||
option(MSVC_USE_RUNTIME_DLL "Use the dynamically linked version of the runtime" OFF)
|
||||
option(MSVC_RELEASE_DEBUGGING "Set options that allow to debug release builds" OFF)
|
||||
|
||||
MARK_AS_ADVANCED(FORCE MSVC_USE_RUNTIME_DLL)
|
||||
MARK_AS_ADVANCED(FORCE MSVC_RELEASE_DEBUGGING)
|
||||
|
||||
# These are the warnings we disable
|
||||
set(WARNING_FLAGS
|
||||
/wd4100 # unreferenced formal parameters
|
||||
/wd4127 # constant conditional (assert)
|
||||
/wd4201 # nonstandard extension used: nameless struct/union (happens a lot in Windows include headers)
|
||||
/wd4290 # C++ exception specification ignored except to indicate a function is not __declspec(nothrow)
|
||||
/wd4390 # empty control statement (triggered by nprintf and mprintf's inside of one-line if's, etc)
|
||||
/wd4410 # illegal size for operand... ie... fxch st(1)
|
||||
/wd4511 # copy constructor could not be generated (happens a lot in Windows include headers)
|
||||
/wd4512 # assignment operator could not be generated (happens a lot in Windows include headers)
|
||||
/wd4514 # unreferenced inline function removed
|
||||
/wd4611 # _setjmp warning. Since we use setjmp alot, and we don't really use constructors or destructors, this warning doesn't really apply to us.
|
||||
/wd4663 # C++ language change (template specification)
|
||||
/wd4710 # is inline function not expanded (who cares?)
|
||||
/wd4711 # tells us an inline function was expanded (who cares?)
|
||||
/wd4786 # is identifier truncated to 255 characters (happens all the time in Microsoft #includes) -- Goober5000"
|
||||
/wd4996 # deprecated strcpy, strcat, sprintf, etc. (from MSVC 2005) - taylor
|
||||
/wd4311 # Disables warnings about casting pointer types to ints. The funny thing is these warnings can't be resolved, just disabled... - m!m
|
||||
/wd4302 # Same as above - m!m
|
||||
/wd4366 # The result of the unary '&' operator may be unaligned - m!m
|
||||
/wd4592 # "symbol will be dynamically initialized" is being generated by a compiler bug, see https://stackoverflow.com/a/34027257 for an explanation - m!m
|
||||
$<$<CONFIG:Release>:/wd4101> # In release mode there are unreferenced variables because debug needs them
|
||||
/wd4995 # "'vsprintf': name was marked as #pragma deprecated" is being caused by our custom definition of vsprintf. I have no idea what causes this or how to fix it - m!m
|
||||
/wd4723 # "potential divide by 0" is caused by some code that definitely will not divide by zero - m!m
|
||||
)
|
||||
|
||||
target_compile_options(compiler INTERFACE ${WARNING_FLAGS})
|
||||
|
||||
# Base
|
||||
set(CMAKE_C_FLAGS "/MP /GS- /analyze- /Zc:wchar_t /errorReport:prompt /WX- /Zc:forScope /Gd /EHsc /nologo /Zm200")
|
||||
set(CMAKE_CXX_FLAGS "/MP /GS- /analyze- /Zc:wchar_t /errorReport:prompt /WX- /Zc:forScope /Gd /EHsc /nologo /Zm200")
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "/MANIFEST /DYNAMICBASE:NO /SAFESEH:NO /ERRORREPORT:PROMPT /NOLOGO")
|
||||
set(CMAKE_STATIC_LINKER_FLAGS "")
|
||||
|
||||
# Release
|
||||
set(CMAKE_C_FLAGS_RELEASE "/GL /W2 /Gy- /Ox /Ot /Ob2 /fp:precise /GF /Oy /Oi /Zi /W3")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "/GL /W2 /Gy- /Ox /Ot /Ob2 /fp:precise /GF /Oy /Oi /Zi /W3")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/OPT:REF /LTCG /INCREMENTAL:NO")
|
||||
set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "/LTCG")
|
||||
|
||||
globally_enable_extra_compiler_warnings()
|
||||
|
||||
if (MSVC_RELEASE_DEBUGGING)
|
||||
CHECK_CXX_COMPILER_FLAG("/Zo" MSVC_COMPILER_SUPPORTS_ARCH_ZO)
|
||||
|
||||
if (MSVC_COMPILER_SUPPORTS_ARCH_ZO)
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Zo")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zo")
|
||||
endif()
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG")
|
||||
endif()
|
||||
|
||||
IF(MSVC_USE_RUNTIME_DLL)
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MD")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD")
|
||||
ELSE(MSVC_USE_RUNTIME_DLL)
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
|
||||
ENDIF(MSVC_USE_RUNTIME_DLL)
|
||||
|
||||
# Debug
|
||||
set(CMAKE_C_FLAGS_DEBUG "/W4 /Gy /Zi /Od /RTC1 /Gd /Oy-")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "/W4 /Gy /Zi /Od /RTC1 /Gd /Oy-")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "/DEBUG /INCREMENTAL:NO /MAPINFO:EXPORTS /NODEFAULTLIB:libcmt.lib")
|
||||
|
||||
IF(MSVC_USE_RUNTIME_DLL)
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MDd")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd")
|
||||
ELSE(MSVC_USE_RUNTIME_DLL)
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
|
||||
ENDIF(MSVC_USE_RUNTIME_DLL)
|
||||
|
||||
INCLUDE(MSVCMultipleProcessCompile)
|
||||
|
||||
# Visual Studio supports compiling for multiple vector instruction sets
|
||||
SET(POSSIBLE_INSTUCTION_SETS "" SSE SSE2 AVX AVX2)
|
||||
|
||||
if (NOT DEFINED MSVC_SIMD_INSTRUCTIONS)
|
||||
detect_simd_instructions(MSVC_DETECTED_SIMD_INSTRUCTIONS)
|
||||
|
||||
SET(MSVC_SIMD_INSTRUCTIONS "${MSVC_DETECTED_SIMD_INSTRUCTIONS}" CACHE FILEPATH "The SIMD instructions which will be used, possible values are ${POSSIBLE_INSTUCTION_SETS}")
|
||||
MARK_AS_ADVANCED(FORCE MSVC_SIMD_INSTRUCTIONS)
|
||||
endif()
|
||||
set(FSO_INSTRUCTION_SET ${MSVC_SIMD_INSTRUCTIONS})
|
||||
|
||||
LIST(FIND POSSIBLE_INSTUCTION_SETS "${MSVC_SIMD_INSTRUCTIONS}" SET_INDEX)
|
||||
|
||||
if (SET_INDEX LESS 0)
|
||||
MESSAGE(STATUS "An invalid instruction set was specified, defaulting to no special compiler options.")
|
||||
else()
|
||||
IF (NOT SET_INDEX EQUAL 0)
|
||||
SET(FOUND)
|
||||
|
||||
FOREACH(list_index RANGE ${SET_INDEX} 1)
|
||||
list(GET POSSIBLE_INSTUCTION_SETS ${list_index} _simd_set)
|
||||
CHECK_CXX_COMPILER_FLAG("/arch:${_simd_set}" COMPILER_SUPPORTS_ARCH_${_simd_set})
|
||||
|
||||
IF(COMPILER_SUPPORTS_ARCH_${_simd_set})
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /arch:${_simd_set}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:${_simd_set}")
|
||||
|
||||
SET(FOUND TRUE)
|
||||
BREAK()
|
||||
ENDIF()
|
||||
ENDFOREACH(list_index)
|
||||
|
||||
IF(NOT FOUND)
|
||||
# Don't set anything, it will likely not work
|
||||
MESSAGE(STATUS "Your compiler does not support any optimization flags, defaulting to none")
|
||||
ENDIF(NOT FOUND)
|
||||
ELSE()
|
||||
CHECK_CXX_COMPILER_FLAG("/arch:IA32" COMPILER_SUPPORTS_ARCH_IA32)
|
||||
|
||||
IF(COMPILER_SUPPORTS_ARCH_IA32)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /arch:IA32")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:IA32")
|
||||
ENDIF(COMPILER_SUPPORTS_ARCH_IA32)
|
||||
ENDIF()
|
||||
endif()
|
||||
|
||||
target_compile_definitions(compiler INTERFACE _CRT_SECURE_NO_DEPRECATE _CRT_SECURE_NO_WARNINGS _SECURE_SCL=0 NOMINMAX
|
||||
"$<$<CONFIG:FastDebug>:_ITERATOR_DEBUG_LEVEL=0>" _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
|
||||
|
||||
if (FSO_FATAL_WARNINGS)
|
||||
# Make warnings fatal if the right variable is set
|
||||
target_compile_options(compiler INTERFACE "/WX")
|
||||
endif()
|
||||
@@ -1,33 +0,0 @@
|
||||
|
||||
# File to execute compiler specific commands
|
||||
|
||||
add_library(compiler INTERFACE)
|
||||
|
||||
target_compile_definitions(compiler INTERFACE "$<$<CONFIG:Release>:NDEBUG>;$<$<CONFIG:Debug>:_DEBUG>;$<$<CONFIG:FastDebug>:_DEBUG>")
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
include(toolchain-gcc)
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
include(toolchain-msvc)
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
include(toolchain-clang)
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
|
||||
include(toolchain-apple-clang)
|
||||
ELSE("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
MESSAGE(STATUS "No special handling for this compiler present, good luck!")
|
||||
ENDIF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
|
||||
# Copy release settings to FastDebug
|
||||
set(CMAKE_C_FLAGS_FASTDEBUG "${CMAKE_C_FLAGS_RELEASE}")
|
||||
set(CMAKE_CXX_FLAGS_FASTDEBUG "${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_FASTDEBUG "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
|
||||
set(CMAKE_STATIC_LINKER_FLAGS_FASTDEBUG "${CMAKE_STATIC_LINKER_FLAGS_RELEASE}")
|
||||
|
||||
if (MSVC)
|
||||
# Adjust runtime library
|
||||
string(REPLACE "/MD" "/MDd" CMAKE_C_FLAGS_FASTDEBUG "${CMAKE_C_FLAGS_FASTDEBUG}")
|
||||
string(REPLACE "/MT" "/MTd" CMAKE_C_FLAGS_FASTDEBUG "${CMAKE_C_FLAGS_FASTDEBUG}")
|
||||
|
||||
string(REPLACE "/MD" "/MDd" CMAKE_CXX_FLAGS_FASTDEBUG "${CMAKE_CXX_FLAGS_FASTDEBUG}")
|
||||
string(REPLACE "/MT" "/MTd" CMAKE_CXX_FLAGS_FASTDEBUG "${CMAKE_CXX_FLAGS_FASTDEBUG}")
|
||||
endif()
|
||||
@@ -1,237 +0,0 @@
|
||||
|
||||
include(CheckCCompilerFlag)
|
||||
|
||||
FUNCTION(MAKE_CACHE_INTERNAL VARIABLE)
|
||||
SET(${VARIABLE} ${${VARIABLE}} CACHE INTERNAL "Internal cache variable")
|
||||
ENDFUNCTION(MAKE_CACHE_INTERNAL)
|
||||
|
||||
FUNCTION(ADD_IMPORTED_LIB NAME INCLUDES LIBS)
|
||||
ADD_LIBRARY(${NAME} INTERFACE)
|
||||
|
||||
target_link_libraries(${NAME} INTERFACE "${LIBS}")
|
||||
|
||||
target_include_directories(${NAME} SYSTEM INTERFACE "${INCLUDES}")
|
||||
ENDFUNCTION(ADD_IMPORTED_LIB)
|
||||
|
||||
MACRO(PKG_CONFIG_LIB_RESOLVE NAME OUTVAR)
|
||||
SET(${OUTVAR} "")
|
||||
foreach(lib ${${NAME}_LIBRARIES})
|
||||
find_library(${lib}_LIBRARY
|
||||
NAMES ${lib}
|
||||
HINTS ${${NAME}_LIBDIR} ${${NAME}_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if (NOT ${${lib}_LIBRARY} MATCHES ".*NOTFOUND.*")
|
||||
SET(${OUTVAR} ${${OUTVAR}} ${${lib}_LIBRARY})
|
||||
endif (NOT ${${lib}_LIBRARY} MATCHES ".*NOTFOUND.*")
|
||||
endforeach(lib)
|
||||
ENDMACRO(PKG_CONFIG_LIB_RESOLVE)
|
||||
|
||||
# Copy from http://cmake.3232098.n2.nabble.com/RFC-cmake-analog-to-AC-SEARCH-LIBS-td7585423.html
|
||||
INCLUDE (CheckFunctionExists)
|
||||
INCLUDE (CheckLibraryExists)
|
||||
|
||||
MACRO (CMAKE_SEARCH_LIBS v_func v_lib func)
|
||||
CHECK_FUNCTION_EXISTS (${func} ${v_func})
|
||||
IF (NOT ${v_func})
|
||||
FOREACH (lib ${ARGN})
|
||||
CHECK_LIBRARY_EXISTS (${lib} ${func} "" "HAVE_${func}_IN_${lib}")
|
||||
IF (${HAVE_${func}_IN_${lib}})
|
||||
SET (${v_func} TRUE)
|
||||
SET (${v_lib} "${lib}" CACHE INTERNAL "Library providing ${func}")
|
||||
BREAK()
|
||||
ENDIF (${HAVE_${func}_IN_${lib}})
|
||||
ENDFOREACH (lib)
|
||||
ENDIF (NOT ${v_func})
|
||||
ENDMACRO (CMAKE_SEARCH_LIBS)
|
||||
# End copy
|
||||
|
||||
FUNCTION(EP_CHECK_FILE_EXISTS FILE OUTVAR TARGET NAME COMMAND WORKING_DIR)
|
||||
string (REPLACE ";" " " COMMAND_STR "${COMMAND}")
|
||||
IF(WIN32)
|
||||
# Do something special for windows...
|
||||
SET(COMMAND "cmd /C \"${COMMAND_STR}\"")
|
||||
ELSE(WIN32)
|
||||
SET(COMMAND "${COMMAND_STR}")
|
||||
ENDIF(WIN32)
|
||||
|
||||
FILE(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}/${NAME}" "
|
||||
IF(EXISTS \"${CMAKE_CURRENT_BINARY_DIR}/${TARGET}/${FILE}\")
|
||||
MESSAGE(\"'${CMAKE_CURRENT_BINARY_DIR}/${TARGET}/${FILE}' already exists, nothing to be done.\")
|
||||
ELSE(EXISTS \"${CMAKE_CURRENT_BINARY_DIR}/${TARGET}/${FILE}\")
|
||||
execute_process(COMMAND ${COMMAND} WORKING_DIRECTORY \"${CMAKE_CURRENT_BINARY_DIR}/${TARGET}/${WORKING_DIR}\")
|
||||
ENDIF(EXISTS \"${CMAKE_CURRENT_BINARY_DIR}/${TARGET}/${FILE}\")
|
||||
")
|
||||
|
||||
SET(${OUTVAR} "${CMAKE_COMMAND}" -P ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}/${NAME} PARENT_SCOPE)
|
||||
ENDFUNCTION(EP_CHECK_FILE_EXISTS)
|
||||
|
||||
MACRO(COPY_FILE_TO_TARGET _target _file)
|
||||
if(UNIX)
|
||||
ADD_CUSTOM_COMMAND(
|
||||
TARGET ${_target} POST_BUILD
|
||||
COMMAND cp -a "${_file}" "$<TARGET_FILE_DIR:${_target}>/${LIBRAY_DESTINATION}/"
|
||||
COMMENT "copying '${_file}'..."
|
||||
)
|
||||
else()
|
||||
ADD_CUSTOM_COMMAND(
|
||||
TARGET ${_target} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_file}" "$<TARGET_FILE_DIR:${_target}>/${LIBRAY_DESTINATION}/"
|
||||
COMMENT "copying '${_file}'..."
|
||||
)
|
||||
endif()
|
||||
endmacro(COPY_FILE_TO_TARGET)
|
||||
|
||||
MACRO(COPY_FILES_TO_TARGET _target)
|
||||
if(UNIX)
|
||||
ADD_CUSTOM_COMMAND(
|
||||
TARGET ${_target} POST_BUILD
|
||||
COMMAND mkdir -p "$<TARGET_FILE_DIR:${_target}>/${LIBRAY_DESTINATION}/"
|
||||
COMMENT "Creating '$<TARGET_FILE_DIR:${_target}>/${LIBRAY_DESTINATION}/'..."
|
||||
)
|
||||
endif()
|
||||
|
||||
FOREACH(file IN LISTS TARGET_COPY_FILES)
|
||||
COPY_FILE_TO_TARGET("${_target}" "${file}")
|
||||
ENDFOREACH(file)
|
||||
ENDMACRO(COPY_FILES_TO_TARGET)
|
||||
|
||||
macro(_clear_old_libraries_state)
|
||||
set(is_debug FALSE)
|
||||
set(is_optimized FALSE)
|
||||
endmacro(_clear_old_libraries_state)
|
||||
|
||||
function(CONVERT_OLD_LIBRARIES)
|
||||
_clear_old_libraries_state()
|
||||
set(out_list)
|
||||
foreach(lib ${ARGV})
|
||||
if ("${lib}" STREQUAL "debug")
|
||||
_clear_old_libraries_state()
|
||||
set(is_debug TRUE)
|
||||
elseif("${lib}" STREQUAL "optimized")
|
||||
_clear_old_libraries_state()
|
||||
set(is_optimized TRUE)
|
||||
elseif("${lib}" STREQUAL "general")
|
||||
_clear_old_libraries_state()
|
||||
else("${lib}" STREQUAL "debug")
|
||||
# Expecting normal library
|
||||
if(is_debug)
|
||||
list(APPEND out_list "$<$<CONFIG:Debug>:${lib}>" "$<$<CONFIG:FastDebug>:${lib}>")
|
||||
elseif(is_optimized)
|
||||
list(APPEND out_list "$<$<CONFIG:Release>:${lib}>")
|
||||
else(is_debug)
|
||||
list(APPEND out_list "${lib}")
|
||||
endif(is_debug)
|
||||
endif("${lib}" STREQUAL "debug")
|
||||
endforeach(lib)
|
||||
|
||||
set(CONVERTED_LIBRARIES ${out_list} PARENT_SCOPE)
|
||||
endfunction(CONVERT_OLD_LIBRARIES)
|
||||
|
||||
macro(set_policy policy value)
|
||||
if (POLICY ${policy})
|
||||
cmake_policy(SET ${policy} ${value})
|
||||
endif ()
|
||||
endmacro(set_policy)
|
||||
|
||||
macro(set_if_not_defined VAR VALUE)
|
||||
if (NOT DEFINED ${VAR})
|
||||
set(${VAR} ${VALUE})
|
||||
endif()
|
||||
endmacro(set_if_not_defined)
|
||||
|
||||
macro(configure_cotire target)
|
||||
if(ENABLE_COTIRE)
|
||||
# Disable unity build as it doesn't work well for us
|
||||
set_target_properties(${target} PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE)
|
||||
|
||||
cotire(${target})
|
||||
endif()
|
||||
endmacro(configure_cotire)
|
||||
|
||||
macro(add_target_copy_files)
|
||||
foreach(file ${ARGN})
|
||||
if (IS_DIRECTORY "${file}")
|
||||
INSTALL(DIRECTORY ${file}
|
||||
DESTINATION ${LIBRAY_DESTINATION}
|
||||
)
|
||||
else()
|
||||
INSTALL(FILES ${file}
|
||||
DESTINATION ${LIBRAY_DESTINATION}
|
||||
)
|
||||
endif()
|
||||
|
||||
SET(TARGET_COPY_FILES ${TARGET_COPY_FILES} ${file} CACHE INTERNAL "" FORCE)
|
||||
endforeach()
|
||||
endmacro(add_target_copy_files)
|
||||
|
||||
function(detect_simd_instructions _out_var)
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
set(${_out_var} "" PARENT_SCOPE)
|
||||
else()
|
||||
message(STATUS "Detecting SIMD features of current CPU...")
|
||||
TRY_RUN(RUN_RESULT COMPILE_RESULT "${CMAKE_BINARY_DIR}/temp" "${CMAKE_SOURCE_DIR}/cmake/cpufeatures.cpp"
|
||||
RUN_OUTPUT_VARIABLE FEATURE_OUTPUT)
|
||||
|
||||
IF(COMPILE_RESULT)
|
||||
MESSAGE(STATUS "Detected compatibility for the ${FEATURE_OUTPUT} feature set.")
|
||||
SET(${_out_var} ${FEATURE_OUTPUT} PARENT_SCOPE)
|
||||
ELSE(COMPILE_RESULT)
|
||||
MESSAGE("Compilation of CPU feature detector failed, please set the instruction set manually.")
|
||||
set(${_out_var} "" PARENT_SCOPE)
|
||||
ENDIF(COMPILE_RESULT)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function (check_linker_flag _flag _out_var)
|
||||
SET(CMAKE_REQUIRED_FLAGS "${_flag}")
|
||||
CHECK_C_COMPILER_FLAG("" ${_out_var})
|
||||
endfunction(check_linker_flag)
|
||||
|
||||
# Suppresses warnings for the specified target
|
||||
function(suppress_warnings _target)
|
||||
if (MSVC)
|
||||
target_compile_options(${_target} PRIVATE "/W0")
|
||||
else()
|
||||
# Assume everything else uses GCC style options
|
||||
target_compile_options(${_target} PRIVATE "-w")
|
||||
endif()
|
||||
endfunction(suppress_warnings)
|
||||
|
||||
|
||||
function(list_target_dependencies _target _out_var)
|
||||
set(out_list)
|
||||
set(work_libs ${_target})
|
||||
list(LENGTH work_libs libs_length)
|
||||
|
||||
while(libs_length GREATER 0)
|
||||
list(GET work_libs 0 current)
|
||||
list(REMOVE_AT work_libs 0)
|
||||
list(APPEND out_list ${current})
|
||||
|
||||
get_target_property(current_libs ${current} INTERFACE_LINK_LIBRARIES)
|
||||
|
||||
if(current_libs)
|
||||
foreach(lib ${current_libs})
|
||||
if (TARGET ${lib})
|
||||
list(APPEND work_libs ${lib})
|
||||
endif (TARGET ${lib})
|
||||
endforeach(lib)
|
||||
endif(current_libs)
|
||||
|
||||
list(LENGTH work_libs libs_length)
|
||||
endwhile(libs_length GREATER 0)
|
||||
|
||||
list(REMOVE_DUPLICATES out_list)
|
||||
set(${_out_var} ${out_list} PARENT_SCOPE)
|
||||
endfunction(list_target_dependencies)
|
||||
|
||||
macro(add_file_folder FOLDER_NAME)
|
||||
string(MAKE_C_IDENTIFIER "${FOLDER_NAME}" VARIABLE_NAME)
|
||||
set(files_${VARIABLE_NAME} ${files_${VARIABLE_NAME}} ${ARGN})
|
||||
|
||||
string(REPLACE "/" "\\" FIXED_FOLDER_FILE "${FOLDER_NAME}")
|
||||
|
||||
source_group("${FIXED_FOLDER_FILE}" FILES ${ARGN})
|
||||
set(source_files ${source_files} ${ARGN})
|
||||
endmacro(add_file_folder)
|
||||
@@ -1,52 +0,0 @@
|
||||
|
||||
include(util)
|
||||
|
||||
if (EXISTS "${PROJECT_SOURCE_DIR}/version_override.cmake")
|
||||
# This allows to override the values by using a special file
|
||||
include("${PROJECT_SOURCE_DIR}/version_override.cmake")
|
||||
endif()
|
||||
|
||||
set_if_not_defined(FSO_VERSION_MAJOR 3)
|
||||
set_if_not_defined(FSO_VERSION_MINOR 8)
|
||||
set_if_not_defined(FSO_VERSION_BUILD 1)
|
||||
|
||||
# A numeric revision e.g. the CI build number
|
||||
set_if_not_defined(FSO_VERSION_REVISION 0)
|
||||
|
||||
# A generic revision string, can be anything
|
||||
set_if_not_defined(FSO_VERSION_REVISION_STR "${FSO_VERSION_REVISION}")
|
||||
|
||||
if("${FSO_VERSION_REVISION}" STREQUAL "0" AND "${FSO_VERSION_REVISION_STR}" STREQUAL "${FSO_VERSION_REVISION}")
|
||||
set(FSO_VERSION_HAS_REVISION 0)
|
||||
else()
|
||||
set(FSO_VERSION_HAS_REVISION 1)
|
||||
endif()
|
||||
|
||||
set(FSO_FULL_VERSION_STRING "${FSO_VERSION_MAJOR}.${FSO_VERSION_MINOR}.${FSO_VERSION_BUILD}")
|
||||
set(FSO_PRODUCT_VERSION_STRING "${FSO_FULL_VERSION_STRING}")
|
||||
|
||||
if (FSO_VERSION_HAS_REVISION)
|
||||
set(FSO_FULL_VERSION_STRING "${FSO_FULL_VERSION_STRING}.${FSO_VERSION_REVISION_STR}")
|
||||
endif()
|
||||
|
||||
IF(NOT FSO_VERSION_HAS_REVISION)
|
||||
SET(FSO_BINARY_SUFFIX "${FSO_VERSION_MAJOR}_${FSO_VERSION_MINOR}_${FSO_VERSION_BUILD}")
|
||||
ELSE()
|
||||
SET(FSO_BINARY_SUFFIX "${FSO_VERSION_MAJOR}_${FSO_VERSION_MINOR}_${FSO_VERSION_BUILD}_${FSO_VERSION_REVISION_STR}")
|
||||
ENDIF()
|
||||
|
||||
IF(IS_64BIT)
|
||||
# This is a 64-bit builds
|
||||
SET(FSO_BINARY_SUFFIX "${FSO_BINARY_SUFFIX}_x64")
|
||||
ENDIF()
|
||||
|
||||
IF (NOT "${FSO_INSTRUCTION_SET}" STREQUAL "")
|
||||
SET(FSO_BINARY_SUFFIX "${FSO_BINARY_SUFFIX}_${FSO_INSTRUCTION_SET}")
|
||||
ENDIF()
|
||||
|
||||
IF (NOT "${FSO_BUILD_POSTFIX}" STREQUAL "")
|
||||
SET(FSO_BINARY_SUFFIX "${FSO_BINARY_SUFFIX}_${FSO_BUILD_POSTFIX}")
|
||||
ENDIF()
|
||||
|
||||
set(CONFIG_POSTFIX "$<$<CONFIG:Release>:>$<$<CONFIG:Debug>:-DEBUG>$<$<CONFIG:FastDebug>:-FASTDBG>")
|
||||
set(FSO_BINARY_SUFFIX "${FSO_BINARY_SUFFIX}${CONFIG_POSTFIX}")
|
||||
@@ -1,87 +0,0 @@
|
||||
|
||||
INCLUDE(source_groups.cmake)
|
||||
|
||||
INCLUDE(voice_rec.cmake)
|
||||
|
||||
ADD_LIBRARY(code STATIC ${source_files} ${VOICE_REC_FILES})
|
||||
|
||||
target_compile_features(code PUBLIC ${REQUIRED_CXX_FEATURES})
|
||||
|
||||
INCLUDE(default_files.cmake)
|
||||
|
||||
if (MSVC)
|
||||
target_compile_definitions(code PUBLIC "PDB_DEBUGGING=1")
|
||||
endif(MSVC)
|
||||
|
||||
TARGET_INCLUDE_DIRECTORIES(code PUBLIC ${CODE_HEADERS})
|
||||
TARGET_INCLUDE_DIRECTORIES(code PUBLIC ${FREESPACE_HEADERS})
|
||||
|
||||
TARGET_INCLUDE_DIRECTORIES(code PUBLIC ${GENERATED_SOURCE_DIR})
|
||||
TARGET_INCLUDE_DIRECTORIES(code PUBLIC ${GENERATED_SOURCE_DIR}/code)
|
||||
|
||||
target_link_libraries(code PUBLIC OpenGL)
|
||||
|
||||
TARGET_LINK_LIBRARIES(code PUBLIC openal)
|
||||
TARGET_LINK_LIBRARIES(code PUBLIC ${LUA_LIBS})
|
||||
TARGET_LINK_LIBRARIES(code PUBLIC ${PNG_LIBS})
|
||||
TARGET_LINK_LIBRARIES(code PUBLIC ${JPEG_LIBS})
|
||||
|
||||
TARGET_LINK_LIBRARIES(code PUBLIC sdl2)
|
||||
|
||||
TARGET_LINK_LIBRARIES(code PUBLIC ffmpeg)
|
||||
|
||||
TARGET_LINK_LIBRARIES(code PUBLIC utfcpp)
|
||||
|
||||
TARGET_LINK_LIBRARIES(code PUBLIC platform)
|
||||
TARGET_LINK_LIBRARIES(code PUBLIC compiler)
|
||||
|
||||
target_link_libraries(code PUBLIC md5)
|
||||
|
||||
target_link_libraries(code PUBLIC discord-rpc)
|
||||
|
||||
target_link_libraries(code PUBLIC libRocket)
|
||||
|
||||
enable_clang_tidy(code)
|
||||
|
||||
IF (FSO_USE_SPEECH)
|
||||
find_package(Speech REQUIRED)
|
||||
target_link_libraries(code PUBLIC speech)
|
||||
ENDIF(FSO_USE_SPEECH)
|
||||
|
||||
TARGET_LINK_LIBRARIES(code PUBLIC jansson)
|
||||
|
||||
# Headers for standalone "gui" on UNIX
|
||||
IF(UNIX)
|
||||
TARGET_LINK_LIBRARIES(code PUBLIC ${MONGOOSE_LIBS})
|
||||
ENDIF(UNIX)
|
||||
|
||||
IF(FSO_BUILD_TOOLS)
|
||||
ADD_SUBDIRECTORY(cfilearchiver)
|
||||
|
||||
ADD_SUBDIRECTORY(cfileextractor)
|
||||
ENDIF(FSO_BUILD_TOOLS)
|
||||
|
||||
if (ENABLE_COTIRE)
|
||||
set_target_properties(code PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h")
|
||||
else()
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
target_compile_options(code PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:-include${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h>")
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
target_compile_options(code PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:/FI ${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h>")
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
target_compile_options(code PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:-include${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h>")
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
|
||||
target_compile_options(code PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:-include${CMAKE_CURRENT_SOURCE_DIR}/prefix_header.h>")
|
||||
ELSE()
|
||||
MESSAGE("Unknown compiler for global includes. This will probably break the build.")
|
||||
ENDIF()
|
||||
endif()
|
||||
|
||||
include(util)
|
||||
configure_cotire(code)
|
||||
|
||||
# Ensure that Xcode generates debug symbols on macOS for Debug builds
|
||||
set_target_properties(code PROPERTIES XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS[variant=Debug] "YES")
|
||||
set_target_properties(code PROPERTIES XCODE_ATTRIBUTE_COPY_PHASE_STRIP[variant=Debug] "NO")
|
||||
set_target_properties(code PROPERTIES XCODE_ATTRIBUTE_STRIP_INSTALLED_PRODUCT[variant=Debug] "NO")
|
||||
set_target_properties(code PROPERTIES XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN[variant=Debug] "NO")
|
||||
-103
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* The code in here is just for bookeeping, allocating AI slots and linking them to ships.
|
||||
* See AiCode.cpp for the actual AI code.
|
||||
*/
|
||||
|
||||
#include "ai/ai.h"
|
||||
#include "object/object.h"
|
||||
#include "ship/ship.h"
|
||||
|
||||
|
||||
int Total_goal_target_names = 0;
|
||||
char Goal_target_names[MAX_GOAL_TARGET_NAMES][NAME_LENGTH];
|
||||
ai_info Ai_info[MAX_AI_INFO];
|
||||
ai_info *Player_ai;
|
||||
|
||||
/**
|
||||
* @brief Returns index of free AI slot.
|
||||
* @return Return -1 if no free slot.
|
||||
*/
|
||||
int ai_get_slot(int shipnum)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<MAX_AI_INFO ; i++)
|
||||
if (Ai_info[i].shipnum == -1) {
|
||||
Ai_info[i].shipnum = shipnum;
|
||||
return i;
|
||||
}
|
||||
|
||||
Warning( LOCATION, "Couldn't get AI slot" );
|
||||
Int3();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Frees a currently used AI slot.
|
||||
* @details Only modifies in ::Ai_info struct. Does not modify hook in ship.
|
||||
*/
|
||||
void ai_free_slot(int ai_index)
|
||||
{
|
||||
Assert( (ai_index >= 0) && (ai_index < MAX_AI_INFO) );
|
||||
|
||||
Ai_info[ai_index].shipnum = -1;
|
||||
}
|
||||
|
||||
int get_wingnum(int objnum)
|
||||
{
|
||||
int shipnum, ai_index;
|
||||
|
||||
shipnum = Objects[objnum].instance;
|
||||
|
||||
ai_index = Ships[shipnum].ai_index;
|
||||
|
||||
return Ai_info[ai_index].wing;
|
||||
}
|
||||
|
||||
void set_wingnum(int objnum, int wingnum)
|
||||
{
|
||||
int shipnum, ai_index;
|
||||
|
||||
Assert(Objects[objnum].type == OBJ_SHIP);
|
||||
|
||||
shipnum = Objects[objnum].instance;
|
||||
|
||||
Assert((shipnum >= 0) && (shipnum < MAX_SHIPS));
|
||||
|
||||
ai_index = Ships[shipnum].ai_index;
|
||||
|
||||
Assert( (ai_index >= 0) && (ai_index < MAX_AI_INFO) );
|
||||
|
||||
Ai_info[ai_index].wing = wingnum;
|
||||
}
|
||||
|
||||
char *ai_get_goal_target_name(const char *name, int *index)
|
||||
{
|
||||
Assert(name != NULL);
|
||||
Assert(index != NULL);
|
||||
int i;
|
||||
|
||||
for (i=0; i < Total_goal_target_names; i++)
|
||||
if (!stricmp(name, Goal_target_names[i])) {
|
||||
*index = i;
|
||||
return Goal_target_names[i];
|
||||
}
|
||||
|
||||
Assert(Total_goal_target_names < MAX_GOAL_TARGET_NAMES);
|
||||
Assertion(strlen(name) <= NAME_LENGTH - 1, "Goal target name %s is too long. Needs to be 31 characters or less.", name);
|
||||
i = Total_goal_target_names++;
|
||||
strcpy_s(Goal_target_names[i], name);
|
||||
*index = i;
|
||||
return Goal_target_names[i];
|
||||
}
|
||||
-669
@@ -1,669 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _AI_H
|
||||
#define _AI_H
|
||||
|
||||
#include "ai/ai_profiles.h"
|
||||
#include "globalincs/globals.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "globalincs/systemvars.h"
|
||||
#include "object/waypoint.h"
|
||||
#include "physics/physics.h"
|
||||
#include "ship/ship_flags.h"
|
||||
|
||||
class ship_weapon;
|
||||
class ship_subsys;
|
||||
class object;
|
||||
class ship_info;
|
||||
|
||||
#define AI_DEFAULT_CLASS 3 // default AI class for new ships (Fred)
|
||||
|
||||
typedef struct ai_flag_name {
|
||||
AI::AI_Flags flag;
|
||||
char flag_name[TOKEN_LENGTH];
|
||||
} ai_flag_name;
|
||||
|
||||
#define MAX_AI_FLAG_NAMES 2
|
||||
extern ai_flag_name Ai_flag_names[];
|
||||
|
||||
// dock_orient_and_approach() modes.
|
||||
#define DOA_APPROACH 1 // Approach the current point on the path (aip->path_cur)
|
||||
#define DOA_DOCK 2 // Dock with goal object.
|
||||
#define DOA_UNDOCK_1 3 // Begin undocking with goal object. Just move away.
|
||||
#define DOA_UNDOCK_2 4 // Secondary undocking. Move away.
|
||||
#define DOA_UNDOCK_3 5 // Tertiary undocking. Move away and orient away.
|
||||
#define DOA_DOCK_STAY 6 // Rigidly maintain position in dock bay.
|
||||
|
||||
// Type values for ai_dock_with_object() dock_type parameter.
|
||||
#define AIDO_DOCK 1 // Set goal of docking with object.
|
||||
#define AIDO_DOCK_NOW 2 // Immediately move into dock position. For ships that start mission docked.
|
||||
#define AIDO_UNDOCK 3 // Set goal of undocking with object.
|
||||
|
||||
// Submodes for seeking safety.
|
||||
#define AISS_1 41 // Pick a spot to fly to.
|
||||
#define AISS_2 42 // Flying to spot.
|
||||
#define AISS_3 43 // Gotten near spot, fly about there.
|
||||
#define AISS_1a 44 // Pick a new nearby spot because we are endangered, then go to AISS_2
|
||||
|
||||
#define MAX_AI_GOALS 5
|
||||
|
||||
// types of ai goals -- tyese types will help us to determination on which goals should
|
||||
// have priority over others (i.e. when a player issues a goal to a wing, then a seperate
|
||||
// goal to a ship in that wing). We would probably use this type in conjunction with
|
||||
// goal priority to establish which goal to follow
|
||||
#define AIG_TYPE_EVENT_SHIP 1 // from mission event direct to ship
|
||||
#define AIG_TYPE_EVENT_WING 2 // from mission event direct to wing
|
||||
#define AIG_TYPE_PLAYER_SHIP 3 // from player direct to ship
|
||||
#define AIG_TYPE_PLAYER_WING 4 // from player direct to wing
|
||||
#define AIG_TYPE_DYNAMIC 5 // created on the fly
|
||||
|
||||
// Flags to ai_turn_towards_vector().
|
||||
#define AITTV_FAST (1<<0) // Turn fast, not slowed down based on skill level.
|
||||
#define AITTV_VIA_SEXP (1<<1) // Goober5000 - via sexp
|
||||
#define AITTV_IGNORE_BANK (1<<2) // Goober5000 - ignore bank when turning
|
||||
|
||||
#define KAMIKAZE_HULL_ON_DEATH -1000.0f // Hull strength ship gets set to if it crash-dies.
|
||||
|
||||
// structure for AI goals
|
||||
typedef struct ai_goal {
|
||||
int signature; // Unique identifier. All goals ever created (per mission) have a unique signature.
|
||||
int ai_mode; // one of the AIM_* modes for this goal
|
||||
int ai_submode; // maybe need a submode
|
||||
int type; // one of the AIG_TYPE_* values above
|
||||
flagset<AI::Goal_Flags> flags; // one of the AIGF_* values above
|
||||
fix time; // time at which this goal was issued.
|
||||
int priority; // how important is this goal -- number 0 - 100
|
||||
|
||||
char *target_name; // name of the thing that this goal acts upon
|
||||
int target_name_index; // index of goal_target_name in Goal_target_names[][]
|
||||
waypoint_list *wp_list; // waypoints that this ship might fly.
|
||||
int target_instance; // instance of thing this ship might be chasing (currently only used for weapons; note, not the same as objnum!)
|
||||
int target_signature; // signature of object this ship might be chasing (currently only used for weapons; paired with above value to confirm target)
|
||||
|
||||
// unions for docking stuff.
|
||||
// (AIGF_DOCKER_INDEX_VALID and AIGF_DOCKEE_INDEX_VALID tell us to use indexes; otherwise we use names)
|
||||
// these are the dockpoints used on the docker and dockee ships, not the ships themselves
|
||||
union {
|
||||
char *name;
|
||||
int index;
|
||||
} docker;
|
||||
|
||||
union {
|
||||
char *name;
|
||||
int index;
|
||||
} dockee;
|
||||
|
||||
} ai_goal;
|
||||
|
||||
#define MAX_GOAL_TARGET_NAMES 100
|
||||
|
||||
#define AIM_CHASE 0
|
||||
#define AIM_EVADE 1
|
||||
#define AIM_GET_BEHIND 2
|
||||
#define AIM_STAY_NEAR 3 // Stay near another ship.
|
||||
#define AIM_STILL 4 // Sit still. Don't move. Hold your breath. Don't blink.
|
||||
#define AIM_GUARD 5 // Guard an object
|
||||
#define AIM_AVOID 6 // Avoid an object
|
||||
#define AIM_WAYPOINTS 7 // Fly waypoints
|
||||
#define AIM_DOCK 8 // Dock with ship.
|
||||
#define AIM_NONE 9 // Uh, do nothing.
|
||||
#define AIM_BIGSHIP 10 // Like a capital ship, doesn't focus on one ship.
|
||||
#define AIM_PATH 11 // Follow path on ship
|
||||
#define AIM_BE_REARMED 12 // Allow self to be rearmed
|
||||
#define AIM_SAFETY 13 // Seek safety at periphery of battle
|
||||
#define AIM_EVADE_WEAPON 14 // Evade a weapon.
|
||||
#define AIM_STRAFE 15 // Attack a big ship by strafing it
|
||||
#define AIM_PLAY_DEAD 16 // Play dead. Get it? Don't move, fire, etc.
|
||||
#define AIM_BAY_EMERGE 17 // Emerging from a fighter bay, following path to do so
|
||||
#define AIM_BAY_DEPART 18 // Departing to a fighter bay, following path to do so
|
||||
#define AIM_SENTRYGUN 19 // AI mode for sentry guns only (floating turrets)
|
||||
#define AIM_WARP_OUT 20 // Commence warp out sequence. Point in legal direction. Then call John's code.
|
||||
#define AIM_FLY_TO_SHIP 21 // [Kazan] Fly to a ship, doesn't matter if it's hostile or friendly -- for Autopilot usage
|
||||
|
||||
#define MAX_AI_BEHAVIORS 22 // Number of AIM_xxxx types
|
||||
|
||||
#define MAX_WAYPOINTS_PER_LIST 20
|
||||
#define MAX_ENEMY_DISTANCE 2500.0f // Maximum distance from which a ship will pursue an enemy.
|
||||
|
||||
#define AI_GOAL_NONE -1
|
||||
|
||||
#define AI_ACTIVE_GOAL_DYNAMIC 999
|
||||
|
||||
typedef struct ai_class {
|
||||
char name[NAME_LENGTH];
|
||||
float ai_accuracy[NUM_SKILL_LEVELS];
|
||||
float ai_evasion[NUM_SKILL_LEVELS];
|
||||
float ai_courage[NUM_SKILL_LEVELS];
|
||||
float ai_patience[NUM_SKILL_LEVELS];
|
||||
|
||||
//SUSHI: These were originally in AI_Profiles, adding the option to override in AI.tbl
|
||||
//INT_MIN and FLT_MIN represent the "not set" state for which defaults are used instead.
|
||||
float ai_cmeasure_fire_chance[NUM_SKILL_LEVELS];
|
||||
float ai_in_range_time[NUM_SKILL_LEVELS];
|
||||
float ai_link_ammo_levels_maybe[NUM_SKILL_LEVELS];
|
||||
float ai_link_ammo_levels_always[NUM_SKILL_LEVELS];
|
||||
float ai_primary_ammo_burst_mult[NUM_SKILL_LEVELS];
|
||||
float ai_link_energy_levels_maybe[NUM_SKILL_LEVELS];
|
||||
float ai_link_energy_levels_always[NUM_SKILL_LEVELS];
|
||||
fix ai_predict_position_delay[NUM_SKILL_LEVELS];
|
||||
float ai_shield_manage_delay[NUM_SKILL_LEVELS];
|
||||
float ai_ship_fire_delay_scale_friendly[NUM_SKILL_LEVELS];
|
||||
float ai_ship_fire_delay_scale_hostile[NUM_SKILL_LEVELS];
|
||||
float ai_ship_fire_secondary_delay_scale_friendly[NUM_SKILL_LEVELS];
|
||||
float ai_ship_fire_secondary_delay_scale_hostile[NUM_SKILL_LEVELS];
|
||||
float ai_turn_time_scale[NUM_SKILL_LEVELS];
|
||||
float ai_glide_attack_percent[NUM_SKILL_LEVELS];
|
||||
float ai_circle_strafe_percent[NUM_SKILL_LEVELS];
|
||||
float ai_glide_strafe_percent[NUM_SKILL_LEVELS];
|
||||
float ai_random_sidethrust_percent[NUM_SKILL_LEVELS];
|
||||
float ai_stalemate_time_thresh[NUM_SKILL_LEVELS];
|
||||
float ai_stalemate_dist_thresh[NUM_SKILL_LEVELS];
|
||||
int ai_chance_to_use_missiles_on_plr[NUM_SKILL_LEVELS];
|
||||
float ai_max_aim_update_delay[NUM_SKILL_LEVELS];
|
||||
float ai_turret_max_aim_update_delay[NUM_SKILL_LEVELS];
|
||||
flagset<AI::Profile_Flags> ai_profile_flags; //Holds the state of flags that are set
|
||||
flagset<AI::Profile_Flags> ai_profile_flags_set; //Holds which flags are set and which are just left alone
|
||||
|
||||
//SUSHI: These are optional overrides to an AI class to prevent the automatic scaling based on AI class index
|
||||
int ai_aburn_use_factor[NUM_SKILL_LEVELS];
|
||||
float ai_shockwave_evade_chance[NUM_SKILL_LEVELS];
|
||||
float ai_get_away_chance[NUM_SKILL_LEVELS];
|
||||
float ai_secondary_range_mult[NUM_SKILL_LEVELS];
|
||||
bool ai_class_autoscale; //Defaults to true, but can be turned off in order to disable extra scaling of some AI behaviors
|
||||
//based on AI class index
|
||||
} ai_class;
|
||||
|
||||
// Submode definitions.
|
||||
// Note: These need to be renamed to be of the form: AIS_mode_xxxx
|
||||
#define SM_CONTINUOUS_TURN 1 // takes parm: vector_id {0..3 = right, -right, up, -up}
|
||||
#define SM_ATTACK 2
|
||||
#define SM_EVADE_SQUIGGLE 3
|
||||
#define SM_EVADE_BRAKE 4
|
||||
#define SM_EVADE 5
|
||||
#define SM_SUPER_ATTACK 6
|
||||
#define SM_AVOID 7
|
||||
#define SM_GET_BEHIND 8
|
||||
#define SM_GET_AWAY 9
|
||||
#define SM_EVADE_WEAPON 10 // Evade incoming weapon
|
||||
#define SM_FLY_AWAY 11 // Fly away from target_objnum
|
||||
#define SM_ATTACK_FOREVER 12 // Engine subsystem destroyed, so attack, never evading, avoiding, etc.
|
||||
#define SM_STEALTH_FIND 13 // Stealth ship is "targeted", but not visible, so try to find based on predicted pos
|
||||
#define SM_STEALTH_SWEEP 14 // General sweep, looking for stealth after not visible for some time.
|
||||
#define SM_BIG_APPROACH 15 // Big ship approaches another
|
||||
#define SM_BIG_CIRCLE 16 // Big ship flies circle around other big ship to get good angle to go parallel
|
||||
#define SM_BIG_PARALLEL 17 // Big ship flies parallel to another
|
||||
|
||||
//SUSHI: Attack submodes (besides those implicitly listed above)
|
||||
#define AIS_CHASE_GLIDEATTACK 18 // Ship uses glide to move in a constant direction while pointing and shooting at target
|
||||
#define AIS_CHASE_CIRCLESTRAFE 19 // Attempt a circle-strafe on the target
|
||||
|
||||
// Submodes for docking behavior
|
||||
#define AIS_DOCK_0 20
|
||||
#define AIS_DOCK_1 21
|
||||
#define AIS_DOCK_2 22
|
||||
#define AIS_DOCK_3 23
|
||||
#define AIS_DOCK_4 24 // Only for rearm/repair.
|
||||
#define AIS_DOCK_4A 25 // Only for not rearm/repair. MK, 7/15/97
|
||||
#define AIS_UNDOCK_0 30
|
||||
#define AIS_UNDOCK_1 31
|
||||
#define AIS_UNDOCK_2 32
|
||||
#define AIS_UNDOCK_3 33
|
||||
#define AIS_UNDOCK_4 34
|
||||
|
||||
// Submodes for Guard behavior
|
||||
#define AIS_GUARD_PATROL 101
|
||||
#define AIS_GUARD_ATTACK 102
|
||||
#define AIS_GUARD_2 103
|
||||
#define AIS_GUARD_STATIC 104 // maintain current relative position to guard object, if possible
|
||||
|
||||
// Submodes for strafing big ships behavior (AIM_STRAFE)
|
||||
#define AIS_STRAFE_ATTACK 201 // fly towards target and attack
|
||||
#define AIS_STRAFE_AVOID 202 // fly evasive vector to avoid incoming fire
|
||||
#define AIS_STRAFE_RETREAT1 203 // fly away from attack point
|
||||
#define AIS_STRAFE_RETREAT2 204
|
||||
#define AIS_STRAFE_POSITION 205 // re-position to resume strafing attack
|
||||
#define AIS_STRAFE_GLIDE_ATTACK 206 // SUSHI: Glide strafe atack
|
||||
|
||||
#define WPF_REPEAT (1 << 0)
|
||||
#define WPF_BACKTRACK (1 << 1)
|
||||
|
||||
#define PD_FORWARD 1
|
||||
#define PD_BACKWARD -1
|
||||
|
||||
#define MIN_TRACKABLE_ASPECT_DOT 0.992f // dot of fvec and vec_to_enemy to progress towards aspect lock
|
||||
|
||||
// Submodes for warping out.
|
||||
#define AIS_WARP_1 300 // Make sure there is no obstruction to warping out.
|
||||
#define AIS_WARP_2 301
|
||||
#define AIS_WARP_3 302
|
||||
#define AIS_WARP_4 303
|
||||
#define AIS_WARP_5 304
|
||||
#define AIS_DEPART_TO_BAY 305
|
||||
|
||||
// A node on a path.
|
||||
// Contains global location of point.
|
||||
// Contains hooks back to original path information.
|
||||
// This hook is used to extract information on the point such as whether it is
|
||||
// protected by turrets.
|
||||
typedef struct pnode {
|
||||
vec3d pos;
|
||||
int path_num; // path number from polymodel, ie in polymodel, paths[path_num]
|
||||
int path_index; // index in original model path of point, ie in model_path, use verts[path_index]
|
||||
} pnode;
|
||||
|
||||
#define MAX_PATH_POINTS 1000
|
||||
extern pnode Path_points[MAX_PATH_POINTS];
|
||||
extern pnode *Ppfp; // Free pointer in path points.
|
||||
|
||||
// Goober5000 (based on the "you can only remember 7 things in short-term memory" assumption)
|
||||
#define MAX_IGNORE_NEW_OBJECTS 7
|
||||
|
||||
typedef struct ai_info {
|
||||
flagset<AI::AI_Flags> ai_flags; // Special flags for AI behavior.
|
||||
int shipnum; // Ship using this slot, -1 means none.
|
||||
int type; //
|
||||
int wing; // Member of what wing? -1 means none.
|
||||
|
||||
int behavior; // AI behavior; vestigial field from early development of FS1
|
||||
int mode;
|
||||
int previous_mode;
|
||||
int mode_time; // timestamp at which current mode elapses.
|
||||
int target_objnum; // object index of current target.
|
||||
int target_signature; // Signature of current target.
|
||||
int previous_target_objnum; // On 5/19/97, only used for player.
|
||||
|
||||
int stealth_last_cheat_visible_stamp; // when within 100m, always update pos and velocity, with error increasing for increasing time from last legal visible
|
||||
int stealth_last_visible_stamp;
|
||||
float stealth_sweep_box_size;
|
||||
vec3d stealth_last_pos;
|
||||
vec3d stealth_velocity;
|
||||
|
||||
float previous_dot_to_enemy; // dot(fvec, vec_to_enemy) last frame
|
||||
float target_time; // Amount of time continuously targeting this ship.
|
||||
|
||||
int enemy_wing; // When picking an enemy wing, only allow to be in enemy_wing, unless == -1, in which case don't care.
|
||||
int attacker_objnum;
|
||||
|
||||
int goal_objnum; // mode specific goal. In DOCK, ship to dock with.
|
||||
int goal_signature;
|
||||
|
||||
int guard_objnum; // Ship to guard.
|
||||
int guard_signature; // Signature of ship to guard.
|
||||
int guard_wingnum; // Wing to guard. guard_objnum set to leader.
|
||||
|
||||
int ignore_objnum; // ship to be ignored, based on player order. UNUSED_OBJNUM if none. -(wing_num+1) if ignoring wing.
|
||||
int ignore_signature; // signature of ship to be ignored
|
||||
|
||||
// Goober5000
|
||||
int ignore_new_objnums[MAX_IGNORE_NEW_OBJECTS];
|
||||
int ignore_new_signatures[MAX_IGNORE_NEW_OBJECTS];
|
||||
|
||||
int ai_class; // Class. Might be override of default.
|
||||
|
||||
// Probably become obsolete, to be replaced by path_start, path_cur, etc.
|
||||
waypoint_list *wp_list; // waypoint list being followed
|
||||
size_t wp_index; // waypoint index in list
|
||||
int wp_flags; // waypoint flags, see WPF_xxxx
|
||||
int waypoint_speed_cap; // -1 no cap, otherwise cap - changed to int by Goober5000
|
||||
|
||||
// Path following information
|
||||
int path_start; // Index into global array, start of path.
|
||||
int path_cur; // Index into global array, current location in path.
|
||||
int path_length; // Number of links in this path.
|
||||
int path_dir; // PD_FORWARD, PD_BACKWARD
|
||||
int path_flags; // loop, backtrack, whatever else.
|
||||
int path_objnum; // Object of interest. It's model contains the path.
|
||||
int path_goal_obj_hash; // Hash value of goal object when global path created.
|
||||
fix path_next_create_time; // Next time at which we'll create a global path.
|
||||
vec3d path_create_pos; // Object's position at time of global path creation.
|
||||
matrix path_create_orient; // Object's orientation at time of global path creation.
|
||||
int mp_index; // Model path index. Index in polymodel:model_paths
|
||||
fix path_next_check_time; // Last time checked to see if would collide with model.
|
||||
int path_goal_dist; // minimum distance to first path point to consider path reached
|
||||
int path_subsystem_next_check; // timestamp to next check if subsystem is still visible
|
||||
vec3d path_depart_orient; //Rotational orientation associated with the path
|
||||
|
||||
int submode;
|
||||
int previous_submode; // previous submode, get it?
|
||||
float best_dot_to_enemy; // best dot product to enemy in last BEST_DOT_TIME seconds
|
||||
float best_dot_from_enemy; // best dot product for enemy to player in last BEST_DOT_TIME seconds
|
||||
fix best_dot_to_time; // time at which best dot occurred
|
||||
fix best_dot_from_time; // time at which best dot occurred
|
||||
fix submode_start_time; // time at which we entered the current submode
|
||||
int submode_parm0; // parameter specific to current submode
|
||||
int submode_parm1; // SUSHI: Another optional parameter
|
||||
fix next_predict_pos_time; // Next time to predict position.
|
||||
|
||||
//SUSHI: like last_predicted_enemy_pos, but for aiming (which currently ignores predicted position)
|
||||
//Unlike the predicted position stuff, also takes into account velocity
|
||||
//Only used against small ships
|
||||
fix next_aim_pos_time;
|
||||
vec3d last_aim_enemy_pos;
|
||||
vec3d last_aim_enemy_vel;
|
||||
|
||||
ai_goal goals[MAX_AI_GOALS];
|
||||
int active_goal; // index of active goal, -1 if none, AI_ACTIVE_GOAL_DYNAMIC if dynamic (runtime-created) goal
|
||||
int goal_check_time; // timer used for processing goals for this ai object
|
||||
|
||||
vec3d last_predicted_enemy_pos; // Where he thought enemy was last time.
|
||||
float time_enemy_in_range; // Amount of time enemy continuously in "sight", near crosshair.
|
||||
float time_enemy_near; // SUSHI: amount of time enemy continuously "near" the player
|
||||
fix last_attack_time; // Missiontime of last time this ship attacked its enemy.
|
||||
fix last_hit_time; // Missiontime of last time this ship was hit by anyone.
|
||||
int last_hit_quadrant; // Shield section of last hit.
|
||||
fix last_hit_target_time; // Missiontime of last time this ship successfully hit target.
|
||||
int hitter_objnum; // Object index of ship that hit this ship last time.
|
||||
int hitter_signature; // Signature of hitter. Prevents stupidity if hitter gets killed.
|
||||
fix resume_goal_time; // Time at which to resume interrupted goal, if nothing else intervenes.
|
||||
float prev_accel; // Acceleration last frame.
|
||||
float prev_dot_to_goal; // dot of fvec to goal last frame, used to see if making progress towards goal.
|
||||
vec3d goal_point; // Used in AIM_SAFETY, AIM_STILL and in circling.
|
||||
vec3d prev_goal_point; // Previous location of goal point, used at least for evading.
|
||||
|
||||
//Values copied from the AI class
|
||||
float ai_accuracy, ai_evasion, ai_courage, ai_patience;
|
||||
int ai_aburn_use_factor;
|
||||
float ai_shockwave_evade_chance;
|
||||
float ai_get_away_chance;
|
||||
float ai_secondary_range_mult;
|
||||
bool ai_class_autoscale;
|
||||
|
||||
//SUSHI: These were originally in AI_Profiles, adding the option to override in AI.tbl
|
||||
float ai_cmeasure_fire_chance;
|
||||
float ai_in_range_time;
|
||||
float ai_link_ammo_levels_maybe;
|
||||
float ai_link_ammo_levels_always;
|
||||
float ai_primary_ammo_burst_mult;
|
||||
float ai_link_energy_levels_maybe;
|
||||
float ai_link_energy_levels_always;
|
||||
fix ai_predict_position_delay;
|
||||
float ai_shield_manage_delay;
|
||||
float ai_ship_fire_delay_scale_friendly;
|
||||
float ai_ship_fire_delay_scale_hostile;
|
||||
float ai_ship_fire_secondary_delay_scale_friendly;
|
||||
float ai_ship_fire_secondary_delay_scale_hostile;
|
||||
float ai_turn_time_scale;
|
||||
float ai_glide_attack_percent;
|
||||
float ai_circle_strafe_percent;
|
||||
float ai_glide_strafe_percent;
|
||||
float ai_random_sidethrust_percent;
|
||||
float ai_stalemate_time_thresh;
|
||||
float ai_stalemate_dist_thresh;
|
||||
int ai_chance_to_use_missiles_on_plr;
|
||||
float ai_max_aim_update_delay;
|
||||
float ai_turret_max_aim_update_delay;
|
||||
flagset<AI::Profile_Flags> ai_profile_flags; //Holds AI_Profiles flags (possibly overriden by AI class) that actually apply to AI
|
||||
|
||||
|
||||
union {
|
||||
float lead_scale; // Amount to lead current opponent by.
|
||||
float stay_near_distance; // Distance to stay within for AIM_STAY_NEAR mode.
|
||||
};
|
||||
|
||||
ship_subsys* targeted_subsys; // Targeted subobject on current target. NULL if none;
|
||||
ship_subsys* last_subsys_target; // last known subsystem target
|
||||
int targeted_subsys_parent; // Parent objnum of subobject, not necessarily targeted
|
||||
|
||||
float aspect_locked_time; // Time towards acquiring lock for current_target
|
||||
|
||||
// Goober5000
|
||||
int support_ship_objnum; // objnum of support ship docking with us, or (if we're a support ship) object we're docking to
|
||||
int support_ship_signature; // signature of the same
|
||||
|
||||
int danger_weapon_objnum; // Closest objnum of weapon fired at this ship.
|
||||
int danger_weapon_signature; // Signature of object danger_weapon_objnum.
|
||||
|
||||
vec3d guard_vec; // vector to object being guarded, only used in AIS_GUARD_STATIC submode
|
||||
int nearest_locked_object; // Nearest locked object.
|
||||
float nearest_locked_distance; // Distance to nearest locked object.
|
||||
|
||||
float current_target_distance; // Distance of current target from player
|
||||
int current_target_is_locked; // Flag to indicate whether the current target is locked for missile fire
|
||||
int current_target_dist_trend; // Tracks whether distance to target is increasing or decreasing
|
||||
int current_target_speed_trend; // Tracks whether speed of target is increasing or decreasing
|
||||
|
||||
float last_dist; // last frame's distance between player and target
|
||||
float last_speed; // last frame's target speed
|
||||
int last_secondary_index; // needed for secondary weapon change check
|
||||
int last_target;
|
||||
|
||||
int rearm_first_missile; // flag to show that reloading of missilies hasn't begun yet
|
||||
int rearm_first_ballistic_primary; // flag to show that reloading of ballistic primaries hasn't begun yet
|
||||
int rearm_release_delay; // timestamp used to delay separation of ships after rearm complete
|
||||
|
||||
fix afterburner_stop_time; // Missiontime to turn off afterburner
|
||||
int last_objsig_hit; // The object number signature of the ship last hit by this ship
|
||||
int ignore_expire_timestamp; // Timestamp at which temporary ignore (AIF_TEMPORARY_IGNORE) expires.
|
||||
int warp_out_timestamp; // Timestamp at which this ship is to warp out.
|
||||
int next_rearm_request_timestamp; // Timestamp at which ship might next request rearm.
|
||||
int primary_select_timestamp; // When to next select a primary weapon.
|
||||
int secondary_select_timestamp; // When to next select a secondary weapon.
|
||||
|
||||
int scan_for_enemy_timestamp; // When to next look for enemy fighters if sitting still while pounding
|
||||
// on a bigship. SCAN_FIGHTERS_INTERVAL is defined in AiBig.h
|
||||
int choose_enemy_timestamp; // Time at which it is next legal to choose a new enemy (does not apply
|
||||
// to special situations, like getting hit by a weapon)
|
||||
int force_warp_time; // time at which to give up avoiding a ship and just warp out
|
||||
|
||||
int shockwave_object; // Object index of missile that will generate a shockwave. We will try to avoid.
|
||||
|
||||
int shield_manage_timestamp; // Time at which to next manage shield.
|
||||
int self_destruct_timestamp; // Time at which to self-destruct, probably due to being disabled.
|
||||
int ok_to_target_timestamp; // Time at which this ship can dynamically target.
|
||||
|
||||
int kamikaze_damage; // some damage value used to produce a shockwave from a kamikaze ship
|
||||
vec3d big_attack_point; // Global point this ship is attacking on a big ship.
|
||||
vec3d big_attack_surface_normal; // Surface normal at ship at big_attack_point;
|
||||
int pick_big_attack_point_timestamp; // timestamp at which to pick a new point to attack on a big ship.
|
||||
|
||||
// Note: These three avoid_XX terms are shared between the code that avoids small (only player now) and large ships
|
||||
// The bits in ai_flags determine which is occurring. AIF_AVOID_SMALL_SHIP, AIF_AVOID_BIG_SHIP
|
||||
int avoid_ship_num; // object index of small ship to avoid
|
||||
vec3d avoid_goal_point; // point to aim at when avoiding a ship
|
||||
fix avoid_check_timestamp; // timestamp at which to next check for having to avoid ship
|
||||
|
||||
vec3d big_collision_normal; // Global normal of collision with big ship. Helps find direction to fly away from big ship. Set for each collision.
|
||||
vec3d big_recover_pos_1; // Global point to fly towards when recovering from collision with a big ship, stage 1.
|
||||
vec3d big_recover_pos_2; // Global point to fly towards when recovering from collision with a big ship, stage 2.
|
||||
int big_recover_timestamp; // timestamp at which it's OK to re-enter stage 1.
|
||||
|
||||
int abort_rearm_timestamp; // time at which this rearm should be aborted in a multiplayer game.
|
||||
|
||||
// artillery targeting info
|
||||
int artillery_objnum; // object currently being targeted for artillery lock/attack
|
||||
int artillery_sig; // artillery object signature
|
||||
float artillery_lock_time; // how long we've been locked onto this guy
|
||||
vec3d artillery_lock_pos; // base position of the lock point on (in model's frame of reference)
|
||||
float lethality; // measure of how dangerous ship is to enemy BIG|HUGE ships (likelyhood of targeting)
|
||||
|
||||
flagset<AI::Maneuver_Override_Flags> ai_override_flags; // flags for marking ai overrides from sexp or lua systems
|
||||
control_info ai_override_ci; // ai override control info
|
||||
int ai_override_timestamp; // mark for when to end the current override
|
||||
} ai_info;
|
||||
|
||||
// Goober5000
|
||||
typedef struct {
|
||||
vec3d docker_point;
|
||||
vec3d dockee_point;
|
||||
int dock_mode;
|
||||
int submodel;
|
||||
vec3d submodel_pos;
|
||||
float submodel_r;
|
||||
float submodel_w;
|
||||
} rotating_dockpoint_info;
|
||||
|
||||
#define MAX_AI_INFO MAX_SHIPS
|
||||
|
||||
// SUBSYS_PATH_DIST is used as the distance that a subsystem path should terminate from the actual
|
||||
// subsystem. We don't want to rely on the model path points for this, since we may need to be
|
||||
// changed.
|
||||
#define SUBSYS_PATH_DIST 500.0f
|
||||
|
||||
// Friendly damage defines
|
||||
#define MAX_BURST_DAMAGE 20 // max damage that can be done in BURST_DURATION
|
||||
#define BURST_DURATION 500 // decay time over which Player->damage_this_burst falls from MAX_BURST_DAMAGE to 0
|
||||
|
||||
extern int Mission_all_attack; // !0 means all teams attack all teams.
|
||||
extern int Total_goal_target_names;
|
||||
extern char Goal_target_names[MAX_GOAL_TARGET_NAMES][NAME_LENGTH];
|
||||
|
||||
extern void update_ai_info_for_hit(int hitter_obj, int hit_obj);
|
||||
extern void ai_frame_all(void);
|
||||
|
||||
extern int find_guard_obj(void);
|
||||
|
||||
extern ai_info Ai_info[];
|
||||
extern ai_info *Player_ai;
|
||||
|
||||
extern ai_class *Ai_classes;
|
||||
extern char** Ai_class_names;
|
||||
|
||||
extern int Num_ai_classes;
|
||||
extern int Ai_firing_enabled;
|
||||
|
||||
extern const char *Skill_level_names(int skill_level, int translate = 1);
|
||||
extern int Ai_goal_signature;
|
||||
|
||||
// need access to following data in AiBig.cpp
|
||||
extern object *Pl_objp;
|
||||
extern object *En_objp;
|
||||
extern float AI_frametime;
|
||||
|
||||
|
||||
// Return index of free AI slot.
|
||||
// Return 0 if no free slot.
|
||||
int ai_get_slot(int shipnum);
|
||||
|
||||
// Releases an AI slot to be used by someone else.
|
||||
void ai_free_slot(int ai_index);
|
||||
|
||||
// call to init one ai object.. you can pass all sorts of
|
||||
// stuff by adding new paramters.
|
||||
void ai_object_init(object * obj, int ai_index);
|
||||
|
||||
// Called once a frame
|
||||
void ai_process( object * obj, int ai_index, float frametime );
|
||||
|
||||
int get_wingnum(int objnum);
|
||||
|
||||
void set_wingnum(int objnum, int wingnum);
|
||||
char *ai_get_goal_target_name(const char *name, int *index);
|
||||
|
||||
extern void init_ai_system(void);
|
||||
extern void ai_attack_object(object *attacker, object *attacked, ship_subsys *ssp, int ship_info_index = -1);
|
||||
extern void ai_evade_object(object *evader, object *evaded);
|
||||
extern void ai_ignore_object(object *ignorer, object *ignored, int ignore_new);
|
||||
extern void ai_ignore_wing(object *ignorer, int wingnum);
|
||||
extern void ai_dock_with_object(object *docker, int docker_index, object *dockee, int dockee_index, int dock_type);
|
||||
extern void ai_stay_still(object *still_objp, vec3d *view_pos);
|
||||
extern void ai_do_default_behavior(object *obj);
|
||||
extern void ai_start_waypoints(object *objp, waypoint_list *wp_list, int wp_flags);
|
||||
extern void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hit_normal);
|
||||
extern void ai_ship_destroy(int shipnum);
|
||||
extern void ai_turn_towards_vector(vec3d *dest, object *objp, float turn_time, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec = nullptr, int sexp_flags = 0);
|
||||
extern void init_ai_object(int objnum);
|
||||
extern void ai_init(void); // Call this one to parse ai.tbl.
|
||||
extern void ai_level_init(void); // Call before each level to reset AI
|
||||
|
||||
extern int ai_set_attack_subsystem(object *objp, int subnum);
|
||||
extern int ai_issue_rearm_request(object *requester_objp); // Object requests rearm/repair.
|
||||
extern int ai_abort_rearm_request(object *requester_objp); // Object aborts rearm/repair.
|
||||
extern void ai_do_repair_frame(object *objp, ai_info *aip, float frametime); // Repair a ship object, player or AI.
|
||||
extern void ai_update_danger_weapon(int objnum, int weapon_objnum);
|
||||
|
||||
// called externally from MissionParse.cpp to position ships in wings upon arrival into the
|
||||
// mission.
|
||||
extern void get_absolute_wing_pos( vec3d *result_pos, object *leader_objp, int wing_index, int formation_object_flag);
|
||||
extern void get_absolute_wing_pos_autopilot( vec3d *result_pos, object *leader_objp, int wing_index, int formation_object_flag);
|
||||
|
||||
// Interface from goals code to AI. Set ship to guard. *objp guards *other_objp
|
||||
extern void ai_set_guard_object(object *objp, object *other_objp);
|
||||
extern void ai_set_guard_wing(object *objp, int wingnum);
|
||||
extern void ai_warp_out(object *objp, vec3d *vp);
|
||||
extern void ai_attack_wing(object *attacker, int wingnum);
|
||||
extern void ai_deathroll_start(object *ship_obj);
|
||||
extern int set_target_objnum(ai_info *aip, int objnum);
|
||||
extern void ai_form_on_wing(object *objp, object *goal_objp);
|
||||
extern void ai_do_stay_near(object *objp, object *other_obj, float dist);
|
||||
extern ship_subsys *set_targeted_subsys(ai_info *aip, ship_subsys *new_subsys, int parent_objnum);
|
||||
extern void ai_rearm_repair( object *objp, int docker_index, object *goal_objp, int dockee_index );
|
||||
extern void ai_add_rearm_goal( object *requester_objp, object *support_objp );
|
||||
extern void create_model_path(object *pl_objp, object *mobjp, int path_num, int subsys_path=0);
|
||||
extern int ai_find_goal_index( ai_goal* aigp, int mode, int submode = -1, int priority = -1 );
|
||||
|
||||
// Goober5000
|
||||
extern void ai_do_safety(object *objp);
|
||||
|
||||
// used to get path info for fighter bay emerging and departing
|
||||
int ai_acquire_emerge_path(object *pl_objp, int parent_objnum, int path_mask, vec3d *pos, vec3d *fvec);
|
||||
int ai_acquire_depart_path(object *pl_objp, int parent_objnum, int path_mask);
|
||||
|
||||
// used by AiBig.cpp
|
||||
extern void ai_set_positions(object *pl_objp, object *en_objp, ai_info *aip, vec3d *player_pos, vec3d *enemy_pos);
|
||||
extern void accelerate_ship(ai_info *aip, float accel);
|
||||
extern void turn_away_from_point(object *objp, vec3d *point, float bank_override);
|
||||
extern float ai_endangered_by_weapon(ai_info *aip);
|
||||
extern void update_aspect_lock_information(ai_info *aip, vec3d *vec_to_enemy, float dist_to_enemy, float enemy_radius);
|
||||
extern void ai_chase_ct();
|
||||
extern void ai_find_path(object *pl_objp, int objnum, int path_num, int exit_flag, int subsys_path=0);
|
||||
extern float ai_path();
|
||||
extern void evade_weapon();
|
||||
extern int might_collide_with_ship(object *obj1, object *obj2, float dot_to_enemy, float dist_to_enemy, float duration);
|
||||
extern int ai_fire_primary_weapon(object *objp); //changed to return weather it fired-Bobboau
|
||||
extern int ai_fire_secondary_weapon(object *objp);
|
||||
extern float ai_get_weapon_dist(ship_weapon *swp);
|
||||
extern void turn_towards_point(object *objp, vec3d *point, vec3d *slide_vec, float bank_override);
|
||||
extern int ai_maybe_fire_afterburner(object *objp, ai_info *aip);
|
||||
extern void set_predicted_enemy_pos(vec3d *predicted_enemy_pos, object *pobjp, vec3d *enemy_pos, vec3d *enemy_vel, ai_info *aip);
|
||||
|
||||
extern int is_instructor(object *objp);
|
||||
extern int find_enemy(int objnum, float range, int max_attackers, int ship_info_index = -1);
|
||||
|
||||
float ai_get_weapon_speed(ship_weapon *swp);
|
||||
void set_predicted_enemy_pos_turret(vec3d *predicted_enemy_pos, vec3d *gun_pos, object *pobjp, vec3d *enemy_pos, vec3d *enemy_vel, float weapon_speed, float time_enemy_in_range);
|
||||
|
||||
// function to change rearm status for ai ships (called from sexpression code)
|
||||
extern void ai_set_rearm_status( int team, int new_status );
|
||||
extern void ai_good_secondary_time( int team, int weapon_index, int num_weapons, char *shipname );
|
||||
|
||||
extern void ai_do_objects_docked_stuff(object *docker, int docker_point, object *dockee, int dockee_point, bool update_clients = true);
|
||||
extern void ai_do_objects_undocked_stuff( object *docker, object *dockee );
|
||||
extern void ai_do_objects_repairing_stuff( object *repaired_obj, object *repair_obj, int how );
|
||||
|
||||
// Goober5000
|
||||
// Move to a position relative to a dock bay using thrusters.
|
||||
extern float dock_orient_and_approach(object *docker_objp, int docker_index, object *dockee_objp, int dockee_index, int dock_mode, rotating_dockpoint_info *rdinfo = NULL);
|
||||
|
||||
void ai_set_mode_warp_out(object *objp, ai_info *aip);
|
||||
|
||||
// prototyped by Goober5000
|
||||
int get_nearest_objnum(int objnum, int enemy_team_mask, int enemy_wing, float range, int max_attackers, int ship_info_index);
|
||||
|
||||
// moved to header file by Goober5000
|
||||
void ai_announce_ship_dying(object *dying_objp);
|
||||
|
||||
// added by kazan
|
||||
void ai_start_fly_to_ship(object *objp, int shipnum);
|
||||
void ai_fly_to_ship();
|
||||
|
||||
//Moved declaration here for player ship -WMC
|
||||
void process_subobjects(int objnum);
|
||||
|
||||
//SUSHI: Setting ai_info stuff from both ai class and ai profile
|
||||
void init_aip_from_class_and_profile(ai_info *aip, ai_class *aicp, ai_profile_t *profile);
|
||||
|
||||
void ai_update_aim(ai_info *aip);
|
||||
|
||||
//SUSHI: Random evasive sidethrust
|
||||
void do_random_sidethrust(ai_info *aip, ship_info *sip);
|
||||
|
||||
#endif
|
||||
@@ -1,124 +0,0 @@
|
||||
#ifndef AI_FLAGS_H
|
||||
#define AI_FLAGS_H
|
||||
|
||||
#include "globalincs/flagset.h"
|
||||
|
||||
namespace AI {
|
||||
FLAG_LIST(AI_Flags) {
|
||||
Formation_wing, // Fly in formation as part of wing.
|
||||
Awaiting_repair, // Awaiting a repair ship.
|
||||
Being_repaired, // Currently docked with repair ship.
|
||||
Repairing, // Repairing a ship (or going to repair a ship)
|
||||
Seek_lock, // set if should focus on gaining aspect lock, not hitting with lasers
|
||||
Formation_object, // Fly in formation off a specific object.
|
||||
Temporary_ignore, // Means current ignore_objnum is only temporary, not an order from the player.
|
||||
Use_exit_path, // Used by path code, to flag path as an exit path
|
||||
Use_static_path, // Used by path code, use fixed path, don't try to recreate
|
||||
Target_collision, // Collided with aip->target_objnum last frame. Avoid that ship for half a second or so.
|
||||
Unload_secondaries, // Fire secondaries as fast as possible!
|
||||
On_subsys_path, // Current path leads to a subsystem
|
||||
Avoid_shockwave_ship, // Avoid an existing shockwave from a ship.
|
||||
Avoid_shockwave_weapon, // Avoid an expected shockwave from a weapon. shockwave_object field contains object index.
|
||||
Avoid_shockwave_started, // Already started avoiding shockwave, don't keep deciding whether to avoid.
|
||||
Attack_slowly, // Move slowly while attacking.
|
||||
Repair_obstructed, // Ship wants to be repaired, but path is obstructed.
|
||||
Kamikaze, // Crash into target
|
||||
No_dynamic, // Not allowed to get dynamic goals
|
||||
Avoiding_small_ship, // Avoiding a player ship.
|
||||
Avoiding_big_ship, // Avoiding a large ship.
|
||||
Big_ship_collide_recover_1, // Collided into a big ship. Recovering by flying away.
|
||||
Big_ship_collide_recover_2, // Collided into a big ship. Fly towards big ship sphere perimeter.
|
||||
Stealth_pursuit, // AI is trying to fight stealth ship
|
||||
Unload_primaries, // Fire primaries as fast as possible!
|
||||
Trying_unsuccessfully_to_warp, // Trying to warp, but can't warp at the moment
|
||||
Free_afterburner_use, // Use afterburners while following waypoints or flying towards objects
|
||||
|
||||
NUM_VALUES
|
||||
};
|
||||
|
||||
FLAG_LIST(Goal_Flags) {
|
||||
Docker_index_valid, // when set, index field for docker is valid
|
||||
Dockee_index_valid, // when set, index field for dockee is valid
|
||||
Goal_on_hold, // when set, this goal cannot currently be satisfied, although it could be in the future
|
||||
Subsys_needs_fixup, // when set, the subsystem index (for a destroy subsystem goal) is invalid and must be gotten from the subsys name stored in docker.name field!!
|
||||
Goal_override, // paired with AIG_TYPE_DYNAMIC to mean this goal overrides any other goal
|
||||
Purge, // purge this goal next time we process
|
||||
Goals_purged, // this goal has already caused other goals to get purged
|
||||
Depart_sound_played,// Goober5000 - replacement for AL's hack ;)
|
||||
Target_own_team,
|
||||
|
||||
NUM_VALUES
|
||||
};
|
||||
|
||||
FLAG_LIST(Maneuver_Override_Flags) {
|
||||
Full, // Full sexp control
|
||||
Roll, // Sexp forced roll maneuver
|
||||
Pitch, // Sexp forced pitch change
|
||||
Heading, // Sexp forced heading change
|
||||
Full_lat, // full control over up/side/forward movement
|
||||
Up, // vertical movement
|
||||
Sideways, // horizontal movement
|
||||
Forward, // forward movement
|
||||
|
||||
NUM_VALUES
|
||||
};
|
||||
|
||||
FLAG_LIST(Profile_Flags) {
|
||||
Advanced_turret_fov_edge_checks,
|
||||
Ai_aims_from_ship_center,
|
||||
Ai_can_slow_down_attacking_big_ships,
|
||||
Ai_guards_specific_ship_in_wing,
|
||||
All_ships_manage_shields,
|
||||
Allow_multi_event_scoring,
|
||||
Allow_primary_link_at_start,
|
||||
Allow_rapid_secondary_dumbfire,
|
||||
Allow_turrets_target_weapons_freely,
|
||||
Allow_vertical_dodge,
|
||||
Aspect_invulnerability_fix,
|
||||
Aspect_lock_countermeasure,
|
||||
Assist_scoring_scales_with_damage,
|
||||
Beams_damage_weapons,
|
||||
Big_ships_can_attack_beam_turrets_on_untargeted_ships,
|
||||
Disable_linked_fire_penalty,
|
||||
Disable_weapon_damage_scaling,
|
||||
Dont_insert_random_turret_fire_delay,
|
||||
Fix_ai_class_bug,
|
||||
Fix_ai_path_order_bug,
|
||||
Fix_heat_seeker_stealth_bug,
|
||||
Fix_linked_primary_bug,
|
||||
Force_beam_turret_fov,
|
||||
Free_afterburner_use,
|
||||
Glide_decay_requires_thrust,
|
||||
Hack_improve_non_homing_swarm_turret_fire_accuracy,
|
||||
Huge_turret_weapons_ignore_bombs,
|
||||
Include_beams_in_stat_calcs,
|
||||
Kill_scoring_scales_with_damage,
|
||||
Multi_allow_empty_primaries,
|
||||
Multi_allow_empty_secondaries,
|
||||
Navigation_subsys_governs_warp,
|
||||
No_min_dock_speed_cap,
|
||||
No_special_player_avoid,
|
||||
No_warp_camera,
|
||||
Perform_fewer_scream_checks,
|
||||
Player_weapon_scale_fix,
|
||||
Prevent_targeting_bombs_beyond_range,
|
||||
Require_turret_to_have_target_in_fov,
|
||||
Shockwaves_damage_small_ship_subsystems,
|
||||
Smart_afterburner_management,
|
||||
Smart_primary_weapon_selection,
|
||||
Smart_secondary_weapon_selection,
|
||||
Smart_shield_management,
|
||||
Smart_subsystem_targeting_for_turrets,
|
||||
Strict_turred_tagged_only_targeting,
|
||||
Support_dont_add_primaries, //Prevents support ship from equipping new primary as requested in http://scp.indiegames.us/mantis/view.php?id=3198
|
||||
Turrets_ignore_target_radius,
|
||||
Use_actual_primary_range,
|
||||
Use_additive_weapon_velocity,
|
||||
Use_newtonian_dampening,
|
||||
Use_only_single_fov_for_turrets,
|
||||
|
||||
NUM_VALUES
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,631 +0,0 @@
|
||||
/*
|
||||
* Created by Ian "Goober5000" Warfield for the FreeSpace2 Source Code Project.
|
||||
* You may not sell or otherwise commercially exploit the source or things you
|
||||
* create based on the source.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "def_files/def_files.h"
|
||||
#include "ai/ai_profiles.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "localization/localize.h"
|
||||
#include "parse/parselo.h"
|
||||
#include "ship/ship.h"
|
||||
#include "weapon/weapon.h"
|
||||
|
||||
|
||||
// global stuff
|
||||
int Num_ai_profiles;
|
||||
int Default_ai_profile;
|
||||
ai_profile_t Ai_profiles[MAX_AI_PROFILES];
|
||||
|
||||
// local to this file
|
||||
static int Ai_profiles_initted = 0;
|
||||
static char Default_profile_name[NAME_LENGTH];
|
||||
|
||||
|
||||
// utility
|
||||
void set_flag(ai_profile_t *profile, const char *name, AI::Profile_Flags flag)
|
||||
{
|
||||
if (optional_string(name))
|
||||
{
|
||||
bool val;
|
||||
stuff_boolean(&val);
|
||||
profile->flags.set(flag, val);
|
||||
}
|
||||
}
|
||||
|
||||
const char *AI_path_types[] = {
|
||||
"normal",
|
||||
"alt1",
|
||||
};
|
||||
|
||||
int Num_ai_path_types = sizeof(AI_path_types)/sizeof(char*);
|
||||
|
||||
int ai_path_type_match(char *p)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < Num_ai_path_types; i++)
|
||||
{
|
||||
if(!stricmp(AI_path_types[i], p))
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void parse_ai_profiles_tbl(const char *filename)
|
||||
{
|
||||
int i;
|
||||
char profile_name[NAME_LENGTH];
|
||||
ai_profile_t dummy_profile;
|
||||
char *saved_Mp = NULL;
|
||||
char buf[NAME_LENGTH];
|
||||
|
||||
try
|
||||
{
|
||||
if (filename == NULL)
|
||||
read_file_text_from_default(defaults_get_file("ai_profiles.tbl"));
|
||||
else
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
|
||||
reset_parse();
|
||||
|
||||
|
||||
// start parsing
|
||||
required_string("#AI Profiles");
|
||||
|
||||
// new default?
|
||||
if (optional_string("$Default Profile:"))
|
||||
stuff_string(Default_profile_name, F_NAME, NAME_LENGTH);
|
||||
|
||||
// begin reading data
|
||||
while (required_string_either("#End", "$Profile Name:"))
|
||||
{
|
||||
ai_profile_t *profile = &dummy_profile;
|
||||
ai_profile_t *previous_profile = NULL;
|
||||
bool no_create = false;
|
||||
|
||||
// get the name
|
||||
required_string("$Profile Name:");
|
||||
stuff_string(profile_name, F_NAME, NAME_LENGTH);
|
||||
|
||||
// see if it exists
|
||||
for (i = 0; i < Num_ai_profiles; i++)
|
||||
{
|
||||
if (!stricmp(Ai_profiles[i].profile_name, profile_name))
|
||||
{
|
||||
previous_profile = &Ai_profiles[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// modular table stuff
|
||||
if (optional_string("+nocreate"))
|
||||
{
|
||||
no_create = true;
|
||||
|
||||
// use the previous one if possible,
|
||||
// otherwise continue to use the dummy one
|
||||
if (previous_profile != NULL)
|
||||
profile = previous_profile;
|
||||
}
|
||||
else
|
||||
{
|
||||
// don't create multiple profiles with the same name
|
||||
if (previous_profile != NULL)
|
||||
{
|
||||
Warning(LOCATION, "An ai profile named '%s' already exists! The new one will not be created.\n", profile_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
// make sure we're under the limit
|
||||
if (Num_ai_profiles >= MAX_AI_PROFILES)
|
||||
{
|
||||
Warning(LOCATION, "Too many profiles in ai_profiles.tbl! Max is %d.\n", MAX_AI_PROFILES - 1); // -1 because one is built-in
|
||||
skip_to_string("#End", NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
profile = &Ai_profiles[Num_ai_profiles];
|
||||
Num_ai_profiles++;
|
||||
}
|
||||
}
|
||||
|
||||
// initialize profile if we're not building from a previously parsed one
|
||||
if (!no_create)
|
||||
{
|
||||
// base profile, so zero it out
|
||||
if (profile == &Ai_profiles[0])
|
||||
{
|
||||
profile->reset();
|
||||
}
|
||||
// brand new profile, so set it to the base defaults
|
||||
else
|
||||
{
|
||||
*profile = Ai_profiles[0];
|
||||
}
|
||||
}
|
||||
|
||||
// set the name
|
||||
strcpy_s(profile->profile_name, profile_name);
|
||||
|
||||
|
||||
// fill in any and all settings; they're all optional and can be in any order
|
||||
while (!check_for_string("$Profile Name:") && !check_for_string("#End"))
|
||||
{
|
||||
if (optional_string("$Player Afterburner Recharge Scale:"))
|
||||
parse_float_list(profile->afterburner_recharge_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Beam Friendly Fire Damage:"))
|
||||
parse_float_list(profile->beam_friendly_damage_cap, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Countermeasure Life Scale:"))
|
||||
parse_float_list(profile->cmeasure_life_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Countermeasure Firing Chance:"))
|
||||
parse_float_list(profile->cmeasure_fire_chance, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI In Range Time:"))
|
||||
parse_float_list(profile->in_range_time, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Always Links Ammo Weapons:"))
|
||||
parse_float_list(profile->link_ammo_levels_always, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Maybe Links Ammo Weapons:"))
|
||||
parse_float_list(profile->link_ammo_levels_maybe, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Primary Ammo Burst Multiplier:"))
|
||||
parse_float_list(profile->primary_ammo_burst_mult, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Always Links Energy Weapons:"))
|
||||
parse_float_list(profile->link_energy_levels_always, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Maybe Links Energy Weapons:"))
|
||||
parse_float_list(profile->link_energy_levels_maybe, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Missles Locked on Player:") || optional_string("$Max Missiles Locked on Player:"))
|
||||
parse_int_list(profile->max_allowed_player_homers, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Player Attackers:"))
|
||||
parse_int_list(profile->max_attackers, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Incoming Asteroids:"))
|
||||
parse_int_list(profile->max_incoming_asteroids, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Damage Factor:") || optional_string("$AI Damage Reduction to Player Hull:"))
|
||||
parse_float_list(profile->player_damage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Subsys Damage Factor:") || optional_string("$AI Damage Reduction to Player Subsys:"))
|
||||
parse_float_list(profile->subsys_damage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
// represented in fractions of F1_0
|
||||
if (optional_string("$Predict Position Delay:"))
|
||||
{
|
||||
int iLoop;
|
||||
float temp_list[NUM_SKILL_LEVELS];
|
||||
|
||||
parse_float_list(temp_list, NUM_SKILL_LEVELS);
|
||||
|
||||
for (iLoop = 0; iLoop < NUM_SKILL_LEVELS; iLoop++)
|
||||
profile->predict_position_delay[iLoop] = fl2f(temp_list[iLoop]);
|
||||
}
|
||||
|
||||
if (optional_string("$AI Shield Manage Delay:") || optional_string("$AI Shield Manage Delays:"))
|
||||
parse_float_list(profile->shield_manage_delay, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Friendly AI Fire Delay Scale:"))
|
||||
parse_float_list(profile->ship_fire_delay_scale_friendly, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Hostile AI Fire Delay Scale:"))
|
||||
parse_float_list(profile->ship_fire_delay_scale_hostile, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Friendly AI Secondary Fire Delay Scale:"))
|
||||
parse_float_list(profile->ship_fire_secondary_delay_scale_friendly, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Hostile AI Secondary Fire Delay Scale:"))
|
||||
parse_float_list(profile->ship_fire_secondary_delay_scale_hostile, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$AI Turn Time Scale:"))
|
||||
parse_float_list(profile->turn_time_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Glide Attack Percent:")) {
|
||||
parse_float_list(profile->glide_attack_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->glide_attack_percent[i] < 0.0f || profile->glide_attack_percent[i] > 100.0f) {
|
||||
Warning(LOCATION, "$Glide Attack Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->glide_attack_percent[i]);
|
||||
profile->glide_attack_percent[i] = 0.0f;
|
||||
}
|
||||
profile->glide_attack_percent[i] /= 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Circle Strafe Percent:")) {
|
||||
parse_float_list(profile->circle_strafe_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->circle_strafe_percent[i] < 0.0f || profile->circle_strafe_percent[i] > 100.0f) {
|
||||
Warning(LOCATION, "$Circle Strafe Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->circle_strafe_percent[i]);
|
||||
profile->circle_strafe_percent[i] = 0.0f;
|
||||
}
|
||||
profile->circle_strafe_percent[i] /= 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Glide Strafe Percent:")) {
|
||||
parse_float_list(profile->glide_strafe_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->glide_strafe_percent[i] < 0.0f || profile->glide_strafe_percent[i] > 100.0f) {
|
||||
Warning(LOCATION, "$Glide Strafe Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->glide_strafe_percent[i]);
|
||||
profile->glide_strafe_percent[i] = 0.0f;
|
||||
}
|
||||
profile->glide_strafe_percent[i] /= 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Random Sidethrust Percent:")) {
|
||||
parse_float_list(profile->random_sidethrust_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->random_sidethrust_percent[i] < 0.0f || profile->random_sidethrust_percent[i] > 100.0f) {
|
||||
Warning(LOCATION, "$Random Sidethrust Percent should be between 0 and 100.0 (read %f). Setting to 0.", profile->random_sidethrust_percent[i]);
|
||||
profile->random_sidethrust_percent[i] = 0.0f;
|
||||
}
|
||||
profile->random_sidethrust_percent[i] /= 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Stalemate Time Threshold:"))
|
||||
parse_float_list(profile->stalemate_time_thresh, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Stalemate Distance Threshold:"))
|
||||
parse_float_list(profile->stalemate_dist_thresh, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Shield Recharge Scale:"))
|
||||
parse_float_list(profile->shield_energy_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Weapon Recharge Scale:"))
|
||||
parse_float_list(profile->weapon_energy_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Turret Target Ownage:"))
|
||||
parse_int_list(profile->max_turret_ownage_target, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Turret Player Ownage:"))
|
||||
parse_int_list(profile->max_turret_ownage_player, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Percentage Required For Kill Scale:"))
|
||||
parse_float_list(profile->kill_percentage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Percentage Required For Assist Scale:"))
|
||||
parse_float_list(profile->assist_percentage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Percentage Awarded For Capship Assist:"))
|
||||
parse_float_list(profile->assist_award_percentage_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Repair Penalty:"))
|
||||
parse_int_list(profile->repair_penalty, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Delay Before Allowing Bombs to Be Shot Down:"))
|
||||
parse_float_list(profile->delay_bomb_arm_timer, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Chance AI Has to Fire Missiles at Player:"))
|
||||
parse_int_list(profile->chance_to_use_missiles_on_plr, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Aim Update Delay:"))
|
||||
parse_float_list(profile->max_aim_update_delay, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Turret Max Aim Update Delay:"))
|
||||
parse_float_list(profile->turret_max_aim_update_delay, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Player Autoaim FOV:"))
|
||||
{
|
||||
float fov_list[NUM_SKILL_LEVELS];
|
||||
parse_float_list(fov_list, NUM_SKILL_LEVELS);
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++)
|
||||
{
|
||||
//Enforce range
|
||||
if (fov_list[i] < 0.0f || fov_list[i] >= 360.0f)
|
||||
{
|
||||
Warning(LOCATION, "$Player Autoaim FOV should be >= 0 and < 360.0 (read %f). Setting to 0.", fov_list[i]);
|
||||
fov_list[i] = 0.0f;
|
||||
}
|
||||
|
||||
//Convert units
|
||||
profile->player_autoaim_fov[i] = fov_list[i] * PI / 180.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Detail Distance Multiplier:"))
|
||||
parse_float_list(profile->detail_distance_mult, MAX_DETAIL_LEVEL + 1);
|
||||
|
||||
set_flag(profile, "$big ships can attack beam turrets on untargeted ships:", AI::Profile_Flags::Big_ships_can_attack_beam_turrets_on_untargeted_ships);
|
||||
|
||||
set_flag(profile, "$smart primary weapon selection:", AI::Profile_Flags::Smart_primary_weapon_selection);
|
||||
|
||||
set_flag(profile, "$smart secondary weapon selection:", AI::Profile_Flags::Smart_secondary_weapon_selection);
|
||||
|
||||
set_flag(profile, "$smart shield management:", AI::Profile_Flags::Smart_shield_management);
|
||||
|
||||
set_flag(profile, "$smart afterburner management:", AI::Profile_Flags::Smart_afterburner_management);
|
||||
|
||||
set_flag(profile, "$free afterburner use:", AI::Profile_Flags::Free_afterburner_use);
|
||||
|
||||
set_flag(profile, "$allow rapid secondary dumbfire:", AI::Profile_Flags::Allow_rapid_secondary_dumbfire);
|
||||
|
||||
set_flag(profile, "$huge turret weapons ignore bombs:", AI::Profile_Flags::Huge_turret_weapons_ignore_bombs);
|
||||
|
||||
set_flag(profile, "$don't insert random turret fire delay:", AI::Profile_Flags::Dont_insert_random_turret_fire_delay);
|
||||
|
||||
set_flag(profile, "$hack improve non-homing swarm turret fire accuracy:", AI::Profile_Flags::Hack_improve_non_homing_swarm_turret_fire_accuracy);
|
||||
|
||||
set_flag(profile, "$shockwaves damage small ship subsystems:", AI::Profile_Flags::Shockwaves_damage_small_ship_subsystems);
|
||||
|
||||
set_flag(profile, "$navigation subsystem governs warpout capability:", AI::Profile_Flags::Navigation_subsys_governs_warp);
|
||||
|
||||
set_flag(profile, "$ignore lower bound for minimum speed of docked ship:", AI::Profile_Flags::No_min_dock_speed_cap);
|
||||
|
||||
set_flag(profile, "$disable linked fire penalty:", AI::Profile_Flags::Disable_linked_fire_penalty);
|
||||
|
||||
set_flag(profile, "$disable weapon damage scaling:", AI::Profile_Flags::Disable_weapon_damage_scaling);
|
||||
|
||||
set_flag(profile, "$use additive weapon velocity:", AI::Profile_Flags::Use_additive_weapon_velocity);
|
||||
|
||||
set_flag(profile, "$use newtonian dampening:", AI::Profile_Flags::Use_newtonian_dampening);
|
||||
|
||||
set_flag(profile, "$include beams for kills and assists:", AI::Profile_Flags::Include_beams_in_stat_calcs);
|
||||
|
||||
set_flag(profile, "$score kills based on damage caused:", AI::Profile_Flags::Kill_scoring_scales_with_damage);
|
||||
|
||||
set_flag(profile, "$score assists based on damage caused:", AI::Profile_Flags::Assist_scoring_scales_with_damage);
|
||||
|
||||
set_flag(profile, "$allow event and goal scoring in multiplayer:", AI::Profile_Flags::Allow_multi_event_scoring);
|
||||
|
||||
set_flag(profile, "$fix linked primary weapon decision bug:", AI::Profile_Flags::Fix_linked_primary_bug);
|
||||
|
||||
set_flag(profile, "$prevent turrets targeting too distant bombs:", AI::Profile_Flags::Prevent_targeting_bombs_beyond_range);
|
||||
|
||||
set_flag(profile, "$smart subsystem targeting for turrets:", AI::Profile_Flags::Smart_subsystem_targeting_for_turrets);
|
||||
|
||||
set_flag(profile, "$fix heat seekers homing on stealth ships bug:", AI::Profile_Flags::Fix_heat_seeker_stealth_bug);
|
||||
|
||||
set_flag(profile, "$multi allow empty primaries:", AI::Profile_Flags::Multi_allow_empty_primaries);
|
||||
|
||||
set_flag(profile, "$multi allow empty secondaries:", AI::Profile_Flags::Multi_allow_empty_secondaries);
|
||||
|
||||
set_flag(profile, "$allow turrets target weapons freely:", AI::Profile_Flags::Allow_turrets_target_weapons_freely);
|
||||
|
||||
set_flag(profile, "$use only single fov for turrets:", AI::Profile_Flags::Use_only_single_fov_for_turrets);
|
||||
|
||||
set_flag(profile, "$allow vertical dodge:", AI::Profile_Flags::Allow_vertical_dodge);
|
||||
|
||||
set_flag(profile, "$force beam turrets to use normal fov:", AI::Profile_Flags::Force_beam_turret_fov);
|
||||
|
||||
set_flag(profile, "$fix ai class bug:", AI::Profile_Flags::Fix_ai_class_bug);
|
||||
|
||||
set_flag(profile, "$turrets ignore targets radius in range checks:", AI::Profile_Flags::Turrets_ignore_target_radius);
|
||||
|
||||
set_flag(profile, "$no extra collision avoidance vs player:", AI::Profile_Flags::No_special_player_avoid);
|
||||
|
||||
set_flag(profile, "$perform fewer checks for death screams:", AI::Profile_Flags::Perform_fewer_scream_checks);
|
||||
|
||||
set_flag(profile, "$advanced turret fov edge checks:", AI::Profile_Flags::Advanced_turret_fov_edge_checks);
|
||||
|
||||
set_flag(profile, "$require turrets to have target in fov:", AI::Profile_Flags::Require_turret_to_have_target_in_fov);
|
||||
|
||||
set_flag(profile, "$all ships manage shields:", AI::Profile_Flags::All_ships_manage_shields);
|
||||
|
||||
set_flag(profile, "$ai aims from ship center:", AI::Profile_Flags::Ai_aims_from_ship_center);
|
||||
|
||||
set_flag(profile, "$allow primary link at mission start:", AI::Profile_Flags::Allow_primary_link_at_start);
|
||||
|
||||
set_flag(profile, "$allow beams to damage bombs:", AI::Profile_Flags::Beams_damage_weapons);
|
||||
|
||||
set_flag(profile, "$disable weapon damage scaling for player:", AI::Profile_Flags::Player_weapon_scale_fix);
|
||||
|
||||
set_flag(profile, "$countermeasures affect aspect seekers:", AI::Profile_Flags::Aspect_lock_countermeasure);
|
||||
|
||||
set_flag(profile, "$ai guards specific ship in wing:", AI::Profile_Flags::Ai_guards_specific_ship_in_wing);
|
||||
|
||||
set_flag(profile, "$support don't add primaries:", AI::Profile_Flags::Support_dont_add_primaries);
|
||||
|
||||
profile->ai_path_mode = AI_PATH_MODE_NORMAL;
|
||||
if (optional_string("$ai path mode:"))
|
||||
{
|
||||
stuff_string(buf, F_NAME, NAME_LENGTH);
|
||||
int j = ai_path_type_match(buf);
|
||||
if (j >= 0) {
|
||||
profile->ai_path_mode = j;
|
||||
}
|
||||
else {
|
||||
Warning(LOCATION, "Invalid ai path mode '%s' specified", buf);
|
||||
}
|
||||
}
|
||||
|
||||
set_flag(profile, "$no warp camera:", AI::Profile_Flags::No_warp_camera);
|
||||
|
||||
set_flag(profile, "$fix ai path order bug:", AI::Profile_Flags::Fix_ai_path_order_bug);
|
||||
|
||||
set_flag(profile, "$strict turret-tagged-only targeting:", AI::Profile_Flags::Strict_turred_tagged_only_targeting);
|
||||
|
||||
set_flag(profile, "$aspect bomb invulnerability fix:", AI::Profile_Flags::Aspect_invulnerability_fix);
|
||||
|
||||
set_flag(profile, "$glide decay requires thrust:", AI::Profile_Flags::Glide_decay_requires_thrust);
|
||||
|
||||
set_flag(profile, "$ai can slow down when attacking big ships:", AI::Profile_Flags::Ai_can_slow_down_attacking_big_ships);
|
||||
|
||||
set_flag(profile, "$use actual primary range:", AI::Profile_Flags::Use_actual_primary_range);
|
||||
|
||||
profile->bay_arrive_speed_mult = 1.0f;
|
||||
profile->bay_depart_speed_mult = 1.0f;
|
||||
if (optional_string("$bay arrive speed multiplier:")) {
|
||||
stuff_float(&profile->bay_arrive_speed_mult);
|
||||
}
|
||||
if (optional_string("$bay depart speed multiplier:")) {
|
||||
stuff_float(&profile->bay_depart_speed_mult);
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
// compatibility
|
||||
if (optional_string("$perform less checks for death screams:"))
|
||||
{
|
||||
mprintf(("Warning: \"$perform less checks for death screams\" flag is deprecated in favor of \"$perform fewer checks for death screams\"\n"));
|
||||
bool temp;
|
||||
stuff_boolean(&temp);
|
||||
profile->flags.set(AI::Profile_Flags::Perform_fewer_scream_checks, temp);
|
||||
}
|
||||
if (optional_string("$allow primary link delay:"))
|
||||
{
|
||||
mprintf(("Warning: \"$allow primary link delay\" flag is deprecated in favor of \"$allow primary link at mission start\"\n"));
|
||||
bool temp;
|
||||
stuff_boolean(&temp);
|
||||
profile->flags.set(AI::Profile_Flags::Allow_primary_link_at_start, !temp);
|
||||
}
|
||||
|
||||
|
||||
// if we've been through once already and are at the same place, force a move
|
||||
if (saved_Mp && (saved_Mp == Mp))
|
||||
{
|
||||
char tmp[60];
|
||||
memset(tmp, 0, 60);
|
||||
strncpy(tmp, Mp, 59);
|
||||
mprintf(("WARNING: Unrecognized parameter in ai_profiles: %s\n", tmp));
|
||||
|
||||
Mp++;
|
||||
}
|
||||
|
||||
// find next valid option
|
||||
if (!skip_to_start_of_string_either("$", "#"))
|
||||
break;
|
||||
saved_Mp = Mp;
|
||||
}
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", (filename) ? filename : "<default ai_profiles.tbl>", e.what()));
|
||||
return;
|
||||
}
|
||||
|
||||
// add tbl/tbm to multiplayer validation list
|
||||
extern void fs2netd_add_table_validation(const char *tblname);
|
||||
fs2netd_add_table_validation(filename);
|
||||
}
|
||||
|
||||
void ai_profiles_init()
|
||||
{
|
||||
int temp;
|
||||
|
||||
if (Ai_profiles_initted)
|
||||
return;
|
||||
|
||||
Num_ai_profiles = 0;
|
||||
Default_ai_profile = 0;
|
||||
Default_profile_name[0] = '\0';
|
||||
|
||||
// init retail entry first
|
||||
parse_ai_profiles_tbl(NULL);
|
||||
|
||||
// now parse the supplied table (if any)
|
||||
if (cf_exists_full("ai_profiles.tbl", CF_TYPE_TABLES))
|
||||
parse_ai_profiles_tbl("ai_profiles.tbl");
|
||||
|
||||
// parse any modular tables
|
||||
parse_modular_table("*-aip.tbm", parse_ai_profiles_tbl);
|
||||
|
||||
// set default if specified
|
||||
temp = ai_profile_lookup(Default_profile_name);
|
||||
if (temp >= 0)
|
||||
Default_ai_profile = temp;
|
||||
|
||||
Ai_profiles_initted = 1;
|
||||
}
|
||||
|
||||
int ai_profile_lookup(char *name)
|
||||
{
|
||||
for (int i = 0; i < Num_ai_profiles; i++)
|
||||
if (!stricmp(name, Ai_profiles[i].profile_name))
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ai_profile_t::reset()
|
||||
{
|
||||
memset(profile_name, 0, sizeof(profile_name));
|
||||
|
||||
flags.reset();
|
||||
|
||||
ai_path_mode = 0;
|
||||
bay_arrive_speed_mult = 0;
|
||||
bay_depart_speed_mult = 0;
|
||||
|
||||
for (int i = 0; i < NUM_SKILL_LEVELS; ++i) {
|
||||
max_incoming_asteroids[i] = 0;
|
||||
max_allowed_player_homers[i] = 0;
|
||||
max_attackers[i] = 0;
|
||||
predict_position_delay[i] = 0;
|
||||
in_range_time[i] = 0;
|
||||
shield_manage_delay[i] = 0;
|
||||
|
||||
link_energy_levels_always[i] = 0;
|
||||
link_energy_levels_maybe[i] = 0;
|
||||
|
||||
link_ammo_levels_always[i] = 0;
|
||||
link_ammo_levels_maybe[i] = 0;
|
||||
primary_ammo_burst_mult[i] = 0;
|
||||
|
||||
cmeasure_life_scale[i] = 0;
|
||||
cmeasure_fire_chance[i] = 0;
|
||||
weapon_energy_scale[i] = 0;
|
||||
shield_energy_scale[i] = 0;
|
||||
afterburner_recharge_scale[i] = 0;
|
||||
player_damage_scale[i] = 0;
|
||||
|
||||
subsys_damage_scale[i] = 0;
|
||||
beam_friendly_damage_cap[i] = 0;
|
||||
turn_time_scale[i] = 0;
|
||||
glide_attack_percent[i] = 0;
|
||||
circle_strafe_percent[i] = 0;
|
||||
glide_strafe_percent[i] = 0;
|
||||
random_sidethrust_percent[i] = 0;
|
||||
stalemate_time_thresh[i] = 0;
|
||||
stalemate_dist_thresh[i] = 0;
|
||||
max_aim_update_delay[i] = 0;
|
||||
turret_max_aim_update_delay[i] = 0;
|
||||
|
||||
ship_fire_delay_scale_hostile[i] = 0;
|
||||
ship_fire_delay_scale_friendly[i] = 0;
|
||||
|
||||
ship_fire_secondary_delay_scale_hostile[i] = 0;
|
||||
ship_fire_secondary_delay_scale_friendly[i] = 0;
|
||||
|
||||
max_turret_ownage_target[i] = 0;
|
||||
max_turret_ownage_player[i] = 0;
|
||||
|
||||
kill_percentage_scale[i] = 0;
|
||||
assist_percentage_scale[i] = 0;
|
||||
|
||||
assist_award_percentage_scale[i] = 0;
|
||||
|
||||
repair_penalty[i] = 0;
|
||||
delay_bomb_arm_timer[i] = 0;
|
||||
chance_to_use_missiles_on_plr[i] = 0;
|
||||
player_autoaim_fov[i] = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i <= MAX_DETAIL_LEVEL; ++i) {
|
||||
detail_distance_mult[i] = 0;
|
||||
}
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Created by Ian "Goober5000" Warfield for the FreeSpace2 Source Code Project.
|
||||
* You may not sell or otherwise commercially exploit the source or things you
|
||||
* create based on the source.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _AI_PROFILES_H_
|
||||
#define _AI_PROFILES_H_
|
||||
|
||||
#include "globalincs/globals.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "globalincs/systemvars.h"
|
||||
#include "ai/ai_flags.h"
|
||||
|
||||
// AI Path types
|
||||
#define AI_PATH_MODE_NORMAL 0
|
||||
#define AI_PATH_MODE_ALT1 1
|
||||
|
||||
#define MAX_AI_PROFILES 5
|
||||
|
||||
class ai_profile_t {
|
||||
public:
|
||||
char profile_name[NAME_LENGTH];
|
||||
|
||||
flagset<AI::Profile_Flags> flags;
|
||||
|
||||
// difficulty-related values
|
||||
int max_incoming_asteroids[NUM_SKILL_LEVELS]; // max number of asteroids thrown at friendlies
|
||||
int max_allowed_player_homers[NUM_SKILL_LEVELS]; // max number of simultaneous homing weapons on player
|
||||
int max_attackers[NUM_SKILL_LEVELS]; // max number of ships that can attack a ship
|
||||
fix predict_position_delay[NUM_SKILL_LEVELS]; // how long until AI predicts a ship position
|
||||
float in_range_time[NUM_SKILL_LEVELS]; // seconds to add to time it takes to get enemy in range (only for player's enemies)
|
||||
float shield_manage_delay[NUM_SKILL_LEVELS]; // how long before AI manages shields (note that the player's team always uses the average skill's delay)
|
||||
|
||||
// AI ships link primaries if energy levels greater than these percents
|
||||
float link_energy_levels_always[NUM_SKILL_LEVELS]; // always link
|
||||
float link_energy_levels_maybe[NUM_SKILL_LEVELS]; // link if hull strength low
|
||||
|
||||
// AI ships link primaries if ammunition levels greater than these percents
|
||||
float link_ammo_levels_always[NUM_SKILL_LEVELS]; // always link
|
||||
float link_ammo_levels_maybe[NUM_SKILL_LEVELS]; // link if hull strength low
|
||||
float primary_ammo_burst_mult[NUM_SKILL_LEVELS]; // SUSHI: Multiplier adjusting burst frequency for ballistic primary weapons
|
||||
|
||||
// difficulty-related scales
|
||||
float cmeasure_life_scale[NUM_SKILL_LEVELS]; // life of countermeasures
|
||||
float cmeasure_fire_chance[NUM_SKILL_LEVELS]; // chance a countermeasure will be fired based on skill level (also scaled by ai_class)
|
||||
float weapon_energy_scale[NUM_SKILL_LEVELS]; // weapon energy available
|
||||
float shield_energy_scale[NUM_SKILL_LEVELS]; // shield energy available
|
||||
float afterburner_recharge_scale[NUM_SKILL_LEVELS]; // speed of afterburner recharge
|
||||
float player_damage_scale[NUM_SKILL_LEVELS]; // damage applied to the player
|
||||
|
||||
float subsys_damage_scale[NUM_SKILL_LEVELS]; // damage applied to a player subsystem
|
||||
float beam_friendly_damage_cap[NUM_SKILL_LEVELS]; // damage cap values for friendly beam fire
|
||||
float turn_time_scale[NUM_SKILL_LEVELS]; // speed at which enemy ships turn
|
||||
float glide_attack_percent[NUM_SKILL_LEVELS]; // SUSHI: The likelihood (0.0-1.0) of the AI to use the "glide attack" move
|
||||
float circle_strafe_percent[NUM_SKILL_LEVELS]; // SUSHI: The likelihood (0.0-1.0) of the AI to use the "circle strafe" move
|
||||
float glide_strafe_percent[NUM_SKILL_LEVELS]; // SUSHI: The likelihood (0.0-1.0) of the AI to use glide when strafing capships
|
||||
float random_sidethrust_percent[NUM_SKILL_LEVELS]; // SUSHI: The likelihood (0.0-1.0) of the AI to randomly use sidethrust while dogfihthing
|
||||
float stalemate_time_thresh[NUM_SKILL_LEVELS]; // SUSHI: The amount of time required for the AI to detect (and try to break) dogfight stalemate
|
||||
float stalemate_dist_thresh[NUM_SKILL_LEVELS]; // SUSHI: The maximum distance the AI and target must be within for a stalemate
|
||||
float max_aim_update_delay[NUM_SKILL_LEVELS]; // SUSHI: The maximum delay before the AI updates their aim against small ships
|
||||
float turret_max_aim_update_delay[NUM_SKILL_LEVELS]; // SUSHI: As above, but for turrets updating their aim
|
||||
|
||||
// Multiplicative delay factors for increasing skill levels.
|
||||
float ship_fire_delay_scale_hostile[NUM_SKILL_LEVELS];
|
||||
float ship_fire_delay_scale_friendly[NUM_SKILL_LEVELS];
|
||||
|
||||
// Multiplicative secondary delay factors for increasing skill levels.
|
||||
float ship_fire_secondary_delay_scale_hostile[NUM_SKILL_LEVELS];
|
||||
float ship_fire_secondary_delay_scale_friendly[NUM_SKILL_LEVELS];
|
||||
|
||||
// Maximum turrets of one ship allowed to shoot the same target
|
||||
int max_turret_ownage_target[NUM_SKILL_LEVELS];
|
||||
int max_turret_ownage_player[NUM_SKILL_LEVELS];
|
||||
|
||||
// percentage of damage caused required for a kill/assist
|
||||
float kill_percentage_scale[NUM_SKILL_LEVELS];
|
||||
float assist_percentage_scale[NUM_SKILL_LEVELS];
|
||||
|
||||
// percentage of the capships score given to other team mates on a kill
|
||||
float assist_award_percentage_scale[NUM_SKILL_LEVELS];
|
||||
|
||||
// the number of points subtracted from score for a rearm started on a player
|
||||
int repair_penalty[NUM_SKILL_LEVELS];
|
||||
|
||||
float delay_bomb_arm_timer[NUM_SKILL_LEVELS];
|
||||
|
||||
// the chance (x/7) that ship is allowed to fire missiles at player ship.
|
||||
int chance_to_use_missiles_on_plr[NUM_SKILL_LEVELS];
|
||||
|
||||
// Player-specific autoaim FOV override
|
||||
float player_autoaim_fov[NUM_SKILL_LEVELS];
|
||||
|
||||
float detail_distance_mult[MAX_DETAIL_LEVEL + 1]; //MAX_DETAIL_LEVEL really needs to be 4
|
||||
|
||||
int ai_path_mode;
|
||||
|
||||
// Ships flying bay paths will gradually accelerate/decelerate instead of
|
||||
// flying the whole path at max speed
|
||||
float bay_arrive_speed_mult;
|
||||
float bay_depart_speed_mult;
|
||||
|
||||
void reset();
|
||||
};
|
||||
|
||||
|
||||
extern int Num_ai_profiles;
|
||||
extern int Default_ai_profile;
|
||||
extern ai_profile_t Ai_profiles[MAX_AI_PROFILES];
|
||||
|
||||
#define AI_PROFILES_INDEX(ai_p) ((int)((ai_p) - Ai_profiles))
|
||||
|
||||
void ai_profiles_init();
|
||||
|
||||
int ai_profile_lookup(char *name);
|
||||
|
||||
#endif
|
||||
-1823
File diff suppressed because it is too large.
Load diff
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef __AIBIG_H__
|
||||
#define __AIBIG_H__
|
||||
|
||||
class object;
|
||||
struct ai_info;
|
||||
struct vec3d;
|
||||
class ship_subsys;
|
||||
|
||||
void ai_big_chase();
|
||||
void ai_big_subsys_path_cleanup(ai_info *aip);
|
||||
|
||||
// strafe functions
|
||||
void ai_big_strafe();
|
||||
int ai_big_maybe_enter_strafe_mode(const object *objp, int weapon_objnum);
|
||||
void ai_big_strafe_maybe_attack_turret(const object *ship_objp, const object *weapon_objp);
|
||||
void ai_big_pick_attack_point(object *objp, object *attacker_objp, vec3d *attack_point, float fov=1.0f);
|
||||
void ai_big_pick_attack_point_turret(object *objp, ship_subsys *ssp, vec3d *gpos, vec3d *gvec, vec3d *attack_point, float weapon_travel_dist, float fov=1.0f);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
-15489
File diff suppressed because it is too large.
Load diff
-2497
File diff suppressed because it is too large.
Load diff
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _AIGOALS_H
|
||||
#define _AIGOALS_H
|
||||
|
||||
#include "globalincs/globals.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
|
||||
struct wing;
|
||||
struct ai_info;
|
||||
struct ai_goal;
|
||||
|
||||
// macros for goals which get set via sexpressions in the mission code
|
||||
|
||||
// IMPORTANT! If you add a new AI_GOAL_x define, be sure to update the functions
|
||||
// ai_update_goal_references() and query_referenced_in_ai_goals() or else risk breaking
|
||||
// Fred. If the goal you add doesn't have a target (such as chase_any), then you don't have
|
||||
// to worry about doing this. Also add it to list in Fred\Management.cpp, and let Hoffoss know!
|
||||
// WMC - Oh and add them to Ai_goal_names plz. TY! :)
|
||||
// Goober5000 - As well as Ai_goal_text and Ai_goal_list, if appropriate
|
||||
#define AI_GOAL_CHASE (1<<1) // 0x00000002
|
||||
#define AI_GOAL_DOCK (1<<2) // 0x00000004 // used for undocking as well
|
||||
#define AI_GOAL_WAYPOINTS (1<<3) // 0x00000008
|
||||
#define AI_GOAL_WAYPOINTS_ONCE (1<<4) // 0x00000010
|
||||
#define AI_GOAL_WARP (1<<5) // 0x00000020
|
||||
#define AI_GOAL_DESTROY_SUBSYSTEM (1<<6) // 0x00000040
|
||||
#define AI_GOAL_FORM_ON_WING (1<<7) // 0x00000080
|
||||
#define AI_GOAL_UNDOCK (1<<8) // 0x00000100
|
||||
#define AI_GOAL_CHASE_WING (1<<9) // 0x00000200
|
||||
#define AI_GOAL_GUARD (1<<10) // 0x00000400
|
||||
#define AI_GOAL_DISABLE_SHIP (1<<11) // 0x00000800
|
||||
#define AI_GOAL_DISARM_SHIP (1<<12) // 0x00001000
|
||||
#define AI_GOAL_CHASE_ANY (1<<13) // 0x00002000
|
||||
#define AI_GOAL_IGNORE (1<<14) // 0x00004000
|
||||
#define AI_GOAL_GUARD_WING (1<<15) // 0x00008000
|
||||
#define AI_GOAL_EVADE_SHIP (1<<16) // 0x00010000
|
||||
|
||||
// the next goals are for support ships only
|
||||
#define AI_GOAL_STAY_NEAR_SHIP (1<<17) // 0x00020000
|
||||
#define AI_GOAL_KEEP_SAFE_DISTANCE (1<<18) // 0x00040000
|
||||
#define AI_GOAL_REARM_REPAIR (1<<19) // 0x00080000
|
||||
|
||||
// resume regular goals
|
||||
#define AI_GOAL_STAY_STILL (1<<20) // 0x00100000
|
||||
#define AI_GOAL_PLAY_DEAD (1<<21) // 0x00200000
|
||||
|
||||
// added by SCP
|
||||
#define AI_GOAL_CHASE_WEAPON (1<<22) // 0x00400000
|
||||
#define AI_GOAL_FLY_TO_SHIP (1<<23) // 0x00800000
|
||||
#define AI_GOAL_IGNORE_NEW (1<<24) // 0x01000000
|
||||
#define AI_GOAL_CHASE_SHIP_CLASS (1<<25) // 0x02000000
|
||||
#define AI_GOAL_PLAY_DEAD_PERSISTENT (1<<26) // 0x03000000
|
||||
|
||||
// now the masks for ship types
|
||||
|
||||
// Goober5000: added AI_GOAL_STAY_NEAR_SHIP and AI_GOAL_KEEP_SAFE_DISTANCE as valid for fighters
|
||||
//WMC - Don't need these anymore. Whee!
|
||||
/*
|
||||
#define AI_GOAL_ACCEPT_FIGHTER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_DESTROY_SUBSYSTEM | AI_GOAL_CHASE_WING | AI_GOAL_GUARD | AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP | AI_GOAL_CHASE_ANY | AI_GOAL_IGNORE | AI_GOAL_IGNORE_NEW | AI_GOAL_GUARD_WING | AI_GOAL_EVADE_SHIP | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT | AI_GOAL_STAY_NEAR_SHIP | AI_GOAL_KEEP_SAFE_DISTANCE )
|
||||
#define AI_GOAL_ACCEPT_BOMBER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_FIGHTER | AI_GOAL_STAY_NEAR_SHIP )
|
||||
#define AI_GOAL_ACCEPT_STEALTH ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_FIGHTER | AI_GOAL_STAY_NEAR_SHIP )
|
||||
#define AI_GOAL_ACCEPT_TRANSPORT ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_DOCK | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_UNDOCK | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT | AI_GOAL_STAY_NEAR_SHIP )
|
||||
#define AI_GOAL_ACCEPT_FREIGHTER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_TRANSPORT | AI_GOAL_STAY_NEAR_SHIP )
|
||||
#define AI_GOAL_ACCEPT_CRUISER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_FREIGHTER | AI_GOAL_STAY_NEAR_SHIP )
|
||||
#define AI_GOAL_ACCEPT_CORVETTE ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_CRUISER | AI_GOAL_STAY_NEAR_SHIP )
|
||||
#define AI_GOAL_ACCEPT_GAS_MINER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_CRUISER | AI_GOAL_STAY_NEAR_SHIP )
|
||||
#define AI_GOAL_ACCEPT_AWACS ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_CRUISER | AI_GOAL_STAY_NEAR_SHIP )
|
||||
#define AI_GOAL_ACCEPT_CAPITAL ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_CRUISER & ~(AI_GOAL_DOCK | AI_GOAL_UNDOCK) | AI_GOAL_STAY_NEAR_SHIP )
|
||||
#define AI_GOAL_ACCEPT_SUPERCAP ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_CAPITAL | AI_GOAL_STAY_NEAR_SHIP )
|
||||
#define AI_GOAL_ACCEPT_SUPPORT ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_DOCK | AI_GOAL_UNDOCK | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_STAY_NEAR_SHIP | AI_GOAL_KEEP_SAFE_DISTANCE | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT )
|
||||
#define AI_GOAL_ACCEPT_ESCAPEPOD ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_TRANSPORT| AI_GOAL_STAY_NEAR_SHIP )
|
||||
*/
|
||||
|
||||
#define MAX_AI_DOCK_NAMES 25
|
||||
|
||||
typedef flag_def_list ai_goal_list;
|
||||
|
||||
extern ai_goal_list Ai_goal_names[];
|
||||
extern int Num_ai_goals;
|
||||
|
||||
extern int Num_ai_dock_names;
|
||||
extern char Ai_dock_names[MAX_AI_DOCK_NAMES][NAME_LENGTH];
|
||||
|
||||
extern const char *Ai_goal_text(int goal);
|
||||
|
||||
// extern function definitions
|
||||
extern void ai_post_process_mission();
|
||||
extern void ai_maybe_add_form_goal( wing *wingp );
|
||||
extern void ai_process_mission_orders( int objnum, ai_info *aip );
|
||||
|
||||
extern int ai_goal_num(ai_goal *goals);
|
||||
|
||||
// adds goals to ships/wing through sexpressions
|
||||
extern void ai_add_ship_goal_scripting(int mode, int submode, int priority, char *shipname, ai_info *aip);
|
||||
extern void ai_add_ship_goal_sexp( int sexp, int type, ai_info *aip );
|
||||
extern void ai_add_wing_goal_sexp( int sexp, int type, int wingnum );
|
||||
extern void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name );
|
||||
|
||||
extern int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp );
|
||||
extern void ai_remove_wing_goal_sexp(int sexp, int wingnum);
|
||||
|
||||
// adds goals to ships/sings through player orders
|
||||
extern void ai_add_ship_goal_player( int type, int mode, int submode, char *shipname, ai_info *aip );
|
||||
extern void ai_add_wing_goal_player( int type, int mode, int submode, char *shipname, int wingnum );
|
||||
|
||||
extern void ai_remove_ship_goal( ai_info *aip, int index );
|
||||
extern void ai_clear_ship_goals( ai_info *aip );
|
||||
extern void ai_clear_wing_goals( int wingnum );
|
||||
|
||||
extern void ai_copy_mission_wing_goal( ai_goal *aigp, ai_info *aip );
|
||||
|
||||
extern void ai_mission_goal_complete( ai_info *aip );
|
||||
extern void ai_mission_wing_goal_complete( int wingnum, ai_goal *remove_goalp );
|
||||
|
||||
extern void ai_update_goal_references(ai_goal *goals, int type, const char *old_name, const char *new_name);
|
||||
extern int query_referenced_in_ai_goals(ai_goal *goals, int type, const char *name);
|
||||
extern char *ai_add_dock_name(const char *str);
|
||||
|
||||
extern int ai_query_goal_valid( int ship, int ai_goal_type );
|
||||
|
||||
extern void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int docker_point, int dockee_point, int immediate = 1 );
|
||||
|
||||
#endif
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _AIINTERNAL_H
|
||||
#define _AIINTERNAL_H
|
||||
|
||||
#include "ship/ship.h"
|
||||
#include "weapon/weapon.h"
|
||||
|
||||
//Returns true if the specified object is a stealth ship, false if not
|
||||
bool is_object_stealth_ship(object* objp);
|
||||
|
||||
//Number of live turrets on the object attacking
|
||||
int num_turrets_attacking(object *turret_parent, int target_objnum);
|
||||
|
||||
//Determine whether an object is targetable within a nebula (checks for stealth)
|
||||
int object_is_targetable(object *target, ship *viewer);
|
||||
|
||||
//Returns the number of enemy fighters within threshold of pos.
|
||||
int num_nearby_fighters(int enemy_team_mask, vec3d *pos, float threshold);
|
||||
|
||||
//Returns true if OK for *aip to fire its current weapon at its current target.
|
||||
int check_ok_to_fire(int objnum, int target_objnum, weapon_info *wip);
|
||||
|
||||
//Does all the stuff needed to aim and fire a turret.
|
||||
void ai_fire_from_turret(ship *shipp, ship_subsys *ss, int parent_objnum);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,940 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "anim/animplay.h"
|
||||
#include "anim/packunpack.h"
|
||||
#include "bmpman/bmpman.h"
|
||||
#include "cfile/cfile.h"
|
||||
#include "cmdline/cmdline.h"
|
||||
#include "globalincs/linklist.h"
|
||||
#include "graphics/2d.h"
|
||||
#include "io/timer.h"
|
||||
#include "pcxutils/pcxutils.h"
|
||||
#include "render/3d.h"
|
||||
#include "graphics/material.h"
|
||||
#include "tracing/Monitor.h"
|
||||
|
||||
static color Color_xparent;
|
||||
|
||||
anim *first_anim = NULL;
|
||||
anim_instance anim_free_list;
|
||||
anim_instance anim_render_list;
|
||||
|
||||
#define MAX_ANIM_INSTANCES 25
|
||||
anim_instance anim_render_instance[MAX_ANIM_INSTANCES];
|
||||
|
||||
int Anim_paused; /// Global variable to pause the playing back of anims
|
||||
int Anim_inited = FALSE;
|
||||
|
||||
fix t1,t2;
|
||||
|
||||
int Anim_ignore_frametime=0; // flag used to ignore frametime... useful when need to avoid saturated frametimes
|
||||
|
||||
/**
|
||||
* @brief Initialise animation
|
||||
* @details Queue all the ::anim_render_instance[] elements onto the ::anim_free_list
|
||||
*/
|
||||
void anim_init()
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( Anim_inited == TRUE )
|
||||
return;
|
||||
|
||||
list_init( &anim_free_list );
|
||||
list_init( &anim_render_list );
|
||||
|
||||
// Link all anim render slots into the free list
|
||||
for (i=1; i < MAX_ANIM_INSTANCES; i++) {
|
||||
list_append(&anim_free_list, &anim_render_instance[i]);
|
||||
}
|
||||
|
||||
Anim_paused = 0;
|
||||
Anim_inited = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Display the frames for the currently playing anims
|
||||
*/
|
||||
void anim_render_all(int screen_id, float frametime)
|
||||
{
|
||||
anim_instance* A;
|
||||
anim_instance* temp;
|
||||
|
||||
A = GET_FIRST(&anim_render_list);
|
||||
while( A !=END_OF_LIST(&anim_render_list) ) {
|
||||
temp = GET_NEXT(A);
|
||||
if ( A->screen_id == screen_id ) {
|
||||
if ( Anim_ignore_frametime ) {
|
||||
frametime = 0.0f;
|
||||
Anim_ignore_frametime=0;
|
||||
}
|
||||
if ( anim_show_next_frame(A, frametime) == -1 ) {
|
||||
A->data = NULL;
|
||||
anim_release_render_instance(A);
|
||||
}
|
||||
}
|
||||
A = temp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Display the frames for the passed animation
|
||||
* @details It will ignore animations which do not have the same id as the passed screen_id
|
||||
*/
|
||||
void anim_render_one(int screen_id, anim_instance *ani, float frametime)
|
||||
{
|
||||
// make sure this guy's screen id matches the passed one
|
||||
if(screen_id != ani->screen_id){
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise render it
|
||||
if ( Anim_ignore_frametime ) {
|
||||
frametime = 0.0f;
|
||||
Anim_ignore_frametime=0;
|
||||
}
|
||||
if ( anim_show_next_frame(ani, frametime) == -1 ) {
|
||||
ani->data = NULL;
|
||||
anim_release_render_instance(ani);
|
||||
}
|
||||
}
|
||||
|
||||
MONITOR(NumANIPlayed)
|
||||
|
||||
/**
|
||||
* @brief Setup an anim_play_struct for passing into ::anim_play().
|
||||
* @details Will fill in default values, which you can then change before calling ::anim_play().
|
||||
*/
|
||||
void anim_play_init(anim_play_struct *aps, anim *a_info, int x, int y, int base_w, int base_h)
|
||||
{
|
||||
aps->anim_info = a_info;
|
||||
aps->x = x;
|
||||
aps->y = y;
|
||||
aps->base_w = base_w;
|
||||
aps->base_h = base_h;
|
||||
aps->start_at = 0;
|
||||
aps->stop_at = a_info->total_frames - 1;
|
||||
aps->screen_id = 0;
|
||||
aps->world_pos = NULL;
|
||||
aps->radius = 0.0f;
|
||||
aps->framerate_independent = 0;
|
||||
aps->color = NULL;
|
||||
aps->skip_frames = 1;
|
||||
aps->looped = 0;
|
||||
aps->ping_pong = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Will add an anim instance to the anim_render_list.
|
||||
* This will cause the anim to be played at the x,y position specified in the parameter list.
|
||||
*
|
||||
* @param aps Compressed animation that we should make an instance from
|
||||
* @return If success pointer to instance, NULL if anim anim could not be played
|
||||
*/
|
||||
anim_instance *anim_play(anim_play_struct *aps)
|
||||
{
|
||||
Assert( aps->anim_info != NULL );
|
||||
Assert( aps->start_at >= 0 );
|
||||
Assert( aps->stop_at < aps->anim_info->total_frames );
|
||||
Assert( !(aps->looped && aps->ping_pong) ); // shouldn't have these both set at once
|
||||
|
||||
MONITOR_INC(NumANIPlayed, 1);
|
||||
|
||||
anim_instance *instance;
|
||||
|
||||
// Find next free anim instance slot on queue
|
||||
instance = GET_FIRST(&anim_free_list);
|
||||
Assert( instance != &anim_free_list ); // shouldn't have the dummy element
|
||||
|
||||
// remove instance from the free list
|
||||
list_remove( &anim_free_list, instance );
|
||||
|
||||
// insert instance onto the end of anim_render_list
|
||||
list_append( &anim_render_list, instance );
|
||||
|
||||
aps->anim_info->instance_count++;
|
||||
instance->frame_num = -1;
|
||||
instance->last_frame_num = -99;
|
||||
instance->parent = aps->anim_info;
|
||||
instance->data = aps->anim_info->data;
|
||||
if ( anim_instance_is_streamed(instance) ) {
|
||||
instance->file_offset = instance->parent->file_offset;
|
||||
}
|
||||
instance->frame = (ubyte *) vm_malloc(instance->parent->width * instance->parent->height * 2);
|
||||
Assert( instance->frame != NULL );
|
||||
memset( instance->frame, 0, instance->parent->width * instance->parent->height * 2 );
|
||||
instance->time_elapsed = 0.0f;
|
||||
instance->stop_at = aps->stop_at;
|
||||
instance->x = aps->x;
|
||||
instance->y = aps->y;
|
||||
instance->world_pos = aps->world_pos;
|
||||
instance->radius = aps->radius;
|
||||
instance->framerate_independent = aps->framerate_independent;
|
||||
instance->last_bitmap = -1;
|
||||
instance->stop_now = FALSE;
|
||||
instance->screen_id = aps->screen_id;
|
||||
instance->aa_color = aps->color;
|
||||
instance->skip_frames = aps->skip_frames;
|
||||
instance->looped = aps->looped;
|
||||
instance->ping_pong = aps->ping_pong;
|
||||
instance->direction = ANIM_DIRECT_FORWARD;
|
||||
instance->paused = 0;
|
||||
instance->loop_count = 0;
|
||||
if ( aps->color == NULL ){
|
||||
instance->xlate_pal = 1;
|
||||
} else {
|
||||
instance->xlate_pal = 0;
|
||||
}
|
||||
|
||||
if(aps->base_w < 0 || aps->base_h < 0) {
|
||||
instance->base_w = gr_screen.max_w_unscaled_zoomed;
|
||||
instance->base_h = gr_screen.max_h_unscaled_zoomed;
|
||||
} else {
|
||||
instance->base_w = aps->base_w;
|
||||
instance->base_h = aps->base_h;
|
||||
}
|
||||
|
||||
// determining the start_at frame is more complicated, since it must be a key-frame.
|
||||
// Futhermore, need to subtract 1 from key-frame number, since frame number is always
|
||||
// incremented the first time anim_show_next_frame() is called
|
||||
|
||||
instance->start_at = aps->start_at;
|
||||
|
||||
if ( aps->start_at > 0 ) {
|
||||
key_frame *keyp;
|
||||
int idx;
|
||||
int key = 0;
|
||||
int offset = 0;
|
||||
int frame_num = aps->start_at;
|
||||
|
||||
keyp = instance->parent->keys;
|
||||
idx = 0;
|
||||
while (idx < instance->parent->num_keys) {
|
||||
if (key == frame_num)
|
||||
break;
|
||||
|
||||
key = keyp[idx].frame_num - 1;
|
||||
offset = keyp[idx].offset;
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (key > instance->frame_num) { // best key is closer than current position
|
||||
instance->frame_num = key;
|
||||
if ( anim_instance_is_streamed(instance) ) {
|
||||
instance->file_offset = instance->parent->file_offset + offset;
|
||||
} else {
|
||||
instance->data = instance->parent->data + offset;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
instance->frame_num--; // required
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function is called to blit the next frame of an anim instance to the screen.
|
||||
* This is normally called by the anim_render_all() function.
|
||||
*
|
||||
* @param instance Pointer to animation instance
|
||||
* @param frametime Time elapsed since last call, in seconds
|
||||
*/
|
||||
int anim_show_next_frame(anim_instance *instance, float frametime)
|
||||
{
|
||||
int bitmap_id, bitmap_flags=0, new_frame_num, frame_diff=0, i, n_frames=0,frame_save;
|
||||
float percent_through, time;
|
||||
vertex image_vertex;
|
||||
int aabitmap = 0;
|
||||
int bpp = 16;
|
||||
|
||||
Assert( instance != NULL );
|
||||
|
||||
instance->time_elapsed += frametime;
|
||||
|
||||
// Advance to the next frame, if we determine enough time has elapsed.
|
||||
if(instance->direction == ANIM_DIRECT_FORWARD)
|
||||
n_frames = instance->stop_at - instance->start_at + 1;
|
||||
else if(instance->direction == ANIM_DIRECT_REVERSE)
|
||||
n_frames = instance->start_at - instance->stop_at + 1;
|
||||
|
||||
time = n_frames / i2fl(instance->parent->fps);
|
||||
|
||||
percent_through = instance->time_elapsed / time;
|
||||
|
||||
if(instance->direction == ANIM_DIRECT_FORWARD)
|
||||
new_frame_num = instance->start_at - 1 + (int) lround(percent_through * n_frames);
|
||||
else
|
||||
new_frame_num = instance->start_at - 1 - (int) lround(percent_through * n_frames);
|
||||
|
||||
frame_save = instance->frame_num;
|
||||
|
||||
// If framerate independent, use the new_frame_num... unless instance->skip_frames is
|
||||
// FALSE, then only advance a maximum of one frame (this is needed since some big animations
|
||||
// should just play slower rather than taking the hit of decompressing multiple frames and
|
||||
// creating an even greater slowdown
|
||||
if (instance->framerate_independent) {
|
||||
if(instance->direction == ANIM_DIRECT_FORWARD){
|
||||
if ( new_frame_num > instance->last_frame_num) {
|
||||
if ( instance->skip_frames )
|
||||
instance->frame_num = new_frame_num;
|
||||
else
|
||||
instance->frame_num++;
|
||||
}
|
||||
} else if(instance->direction == ANIM_DIRECT_REVERSE){
|
||||
if( new_frame_num < instance->last_frame_num) {
|
||||
if ( instance->skip_frames )
|
||||
instance->frame_num = new_frame_num;
|
||||
else
|
||||
instance->frame_num--;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(instance->direction == ANIM_DIRECT_FORWARD){
|
||||
if ( new_frame_num > instance->last_frame_num) {
|
||||
instance->frame_num++;
|
||||
}
|
||||
} else if(instance->direction == ANIM_DIRECT_REVERSE){
|
||||
if ( new_frame_num < instance->last_frame_num) {
|
||||
instance->frame_num--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(instance->direction == ANIM_DIRECT_FORWARD){
|
||||
if ( instance->frame_num < instance->start_at ) {
|
||||
instance->frame_num = instance->start_at;
|
||||
}
|
||||
} else if(instance->direction == ANIM_DIRECT_REVERSE){
|
||||
if ( instance->frame_num > instance->start_at ) {
|
||||
instance->frame_num = instance->start_at;
|
||||
}
|
||||
}
|
||||
|
||||
if ( instance->stop_now == TRUE ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// If past the last frame, clamp to the last frame and then set the stop_now flag in the
|
||||
// anim instance. The next iteration, the animation will stop.
|
||||
if(instance->direction == ANIM_DIRECT_FORWARD){
|
||||
if (instance->frame_num >= instance->stop_at ) {
|
||||
if (instance->looped) { // looped animations
|
||||
instance->frame_num = instance->stop_at;
|
||||
instance->time_elapsed = 0.0f;
|
||||
} else if(instance->ping_pong) { // pingponged animations
|
||||
instance->frame_num = instance->stop_at;
|
||||
anim_reverse_direction(instance);
|
||||
} else { // one-shot animations
|
||||
instance->frame_num = instance->stop_at;
|
||||
instance->last_frame_num = instance->frame_num;
|
||||
instance->stop_now = TRUE;
|
||||
}
|
||||
}
|
||||
} else if(instance->direction == ANIM_DIRECT_REVERSE){
|
||||
if (instance->frame_num <= instance->stop_at ) {
|
||||
if (instance->looped) { // looped animations
|
||||
instance->frame_num = instance->stop_at;
|
||||
instance->time_elapsed = 0.0f;
|
||||
} else if(instance->ping_pong) { // pingponged animations
|
||||
instance->frame_num = instance->stop_at;
|
||||
anim_reverse_direction(instance);
|
||||
} else { // one-shot animations
|
||||
instance->frame_num = instance->stop_at+1;
|
||||
instance->last_frame_num = instance->frame_num;
|
||||
instance->stop_now = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(instance->direction == ANIM_DIRECT_FORWARD){
|
||||
if( instance->last_frame_num >= instance->start_at ) {
|
||||
frame_diff = instance->frame_num - instance->last_frame_num;
|
||||
} else {
|
||||
frame_diff = 1;
|
||||
}
|
||||
} else if(instance->direction == ANIM_DIRECT_REVERSE){
|
||||
if( instance->last_frame_num <= instance->start_at ) {
|
||||
frame_diff = instance->last_frame_num - instance->frame_num;
|
||||
} else {
|
||||
frame_diff = 1;
|
||||
}
|
||||
}
|
||||
Assert(frame_diff >= 0);
|
||||
Assert( instance->frame_num >= 0 && instance->frame_num < instance->parent->total_frames );
|
||||
|
||||
// if the anim is paused, ignore all the above changes and still display this frame
|
||||
if(instance->paused || Anim_paused){
|
||||
instance->frame_num = frame_save;
|
||||
instance->time_elapsed -= frametime;
|
||||
frame_diff = 0;
|
||||
}
|
||||
|
||||
if (instance->parent->flags & ANF_XPARENT){
|
||||
bitmap_flags = 0;
|
||||
}
|
||||
bpp = 16;
|
||||
if(instance->aa_color != NULL){
|
||||
bitmap_flags |= BMP_AABITMAP;
|
||||
aabitmap = 1;
|
||||
bpp = 8;
|
||||
}
|
||||
|
||||
if ( frame_diff > 0 ) {
|
||||
instance->last_frame_num = instance->frame_num;
|
||||
|
||||
t1 = timer_get_fixed_seconds();
|
||||
for ( i = 0; i < frame_diff; i++ ) {
|
||||
anim_check_for_palette_change(instance);
|
||||
|
||||
// if we're playing backwards, every frame must be a keyframe and we set the data ptr here
|
||||
if(instance->direction == ANIM_DIRECT_REVERSE){
|
||||
if ( anim_instance_is_streamed(instance) ) {
|
||||
instance->file_offset = instance->parent->file_offset + instance->parent->keys[instance->frame_num-1].offset;
|
||||
} else {
|
||||
instance->data = instance->parent->data + instance->parent->keys[instance->frame_num-1].offset;
|
||||
}
|
||||
}
|
||||
|
||||
ubyte *temp = NULL;
|
||||
int temp_file_offset = -1;
|
||||
|
||||
// if we're using bitmap polys
|
||||
BM_SELECT_TEX_FORMAT();
|
||||
|
||||
if ( anim_instance_is_streamed(instance) ) {
|
||||
if ( instance->xlate_pal ){
|
||||
temp_file_offset = unpack_frame_from_file(instance, instance->frame, instance->parent->width*instance->parent->height, instance->parent->palette_translation, aabitmap, bpp);
|
||||
} else {
|
||||
temp_file_offset = unpack_frame_from_file(instance, instance->frame, instance->parent->width*instance->parent->height, NULL, aabitmap, bpp);
|
||||
}
|
||||
} else {
|
||||
if ( instance->xlate_pal ){
|
||||
temp = unpack_frame(instance, instance->data, instance->frame, instance->parent->width*instance->parent->height, instance->parent->palette_translation, aabitmap, bpp);
|
||||
} else {
|
||||
temp = unpack_frame(instance, instance->data, instance->frame, instance->parent->width*instance->parent->height, NULL, aabitmap, bpp);
|
||||
}
|
||||
}
|
||||
|
||||
// always go back to screen format
|
||||
BM_SELECT_SCREEN_FORMAT();
|
||||
|
||||
// see if we had an error during decode (corrupted anim stream)
|
||||
if ( (temp == NULL) && (temp_file_offset < 0) ) {
|
||||
mprintf(("ANI: Fatal ERROR at frame %i!! Aborting playback of \"%s\"...\n", instance->frame_num, instance->parent->name));
|
||||
|
||||
// return -1 to end all playing of this anim instanc
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(instance->direction == ANIM_DIRECT_FORWARD){
|
||||
if ( anim_instance_is_streamed(instance) ) {
|
||||
instance->file_offset = temp_file_offset;
|
||||
} else {
|
||||
instance->data = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
t2 = timer_get_fixed_seconds();
|
||||
}
|
||||
else {
|
||||
t2=t1=0;
|
||||
}
|
||||
|
||||
// this only happens when the anim is being looped, we need to reset the last_frame_num
|
||||
if ( (instance->time_elapsed == 0) && (instance->looped) ) {
|
||||
instance->last_frame_num = -1;
|
||||
instance->frame_num = -1;
|
||||
instance->data = instance->parent->data;
|
||||
instance->file_offset = instance->parent->file_offset;
|
||||
instance->loop_count++;
|
||||
}
|
||||
|
||||
t1 = timer_get_fixed_seconds();
|
||||
if ( frame_diff == 0 && instance->last_bitmap != -1 ) {
|
||||
bitmap_id = instance->last_bitmap;
|
||||
}
|
||||
else {
|
||||
if ( instance->last_bitmap != -1 ){
|
||||
bm_release(instance->last_bitmap);
|
||||
}
|
||||
bitmap_id = bm_create(bpp, instance->parent->width, instance->parent->height, instance->frame, bitmap_flags);
|
||||
}
|
||||
|
||||
if ( bitmap_id == -1 ) {
|
||||
// anim has finsished playing, free the instance frame data
|
||||
anim_release_render_instance(instance);
|
||||
return -1;
|
||||
|
||||
// NOTE: there is no need to free the instance, since it was pre-allocated as
|
||||
// part of the anim_free_list
|
||||
}
|
||||
else {
|
||||
gr_set_bitmap(bitmap_id);
|
||||
|
||||
// determine x,y to display the bitmap at
|
||||
if ( instance->world_pos == NULL ) {
|
||||
int old_max_w_unscaled = gr_screen.max_w_unscaled;
|
||||
int old_max_h_unscaled = gr_screen.max_h_unscaled;
|
||||
int old_max_w_unscaled_zoomed = gr_screen.max_w_unscaled_zoomed;
|
||||
int old_max_h_unscaled_zoomed = gr_screen.max_h_unscaled_zoomed;
|
||||
gr_set_screen_scale(instance->base_w, instance->base_h);
|
||||
gr_set_clip(0, 0, instance->base_w, instance->base_h, GR_RESIZE_MENU);
|
||||
if ( instance->aa_color == NULL ) {
|
||||
gr_bitmap(instance->x, instance->y, GR_RESIZE_MENU_NO_OFFSET);
|
||||
}
|
||||
else {
|
||||
gr_set_color_fast( (color*)instance->aa_color );
|
||||
gr_aabitmap(instance->x, instance->y, GR_RESIZE_MENU_NO_OFFSET);
|
||||
}
|
||||
gr_set_screen_scale(old_max_w_unscaled, old_max_h_unscaled, old_max_w_unscaled_zoomed, old_max_h_unscaled_zoomed);
|
||||
gr_reset_clip();
|
||||
}
|
||||
else {
|
||||
g3_rotate_vertex(&image_vertex,instance->world_pos);
|
||||
Assert(instance->radius != 0.0f);
|
||||
//g3_draw_bitmap(&image_vertex, 0, instance->radius*1.5f, TMAP_FLAG_TEXTURED | TMAP_HTL_2D);
|
||||
material mat_params;
|
||||
material_set_unlit(&mat_params, bitmap_id, 1.0f, false, false);
|
||||
g3_render_rect_screen_aligned_2d(&mat_params, &image_vertex, 0, instance->radius*1.5f);
|
||||
}
|
||||
|
||||
instance->last_bitmap = bitmap_id;
|
||||
}
|
||||
|
||||
t2 = timer_get_fixed_seconds();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free a particular animation instance that is on the anim_render_list.
|
||||
* Do not call this function to free an animation instance in general (use
|
||||
* free_anim_instance() for that), only when you want to free an instance
|
||||
* that is on the anim_render_list
|
||||
*/
|
||||
void anim_release_render_instance(anim_instance* instance)
|
||||
{
|
||||
Assert( instance != NULL );
|
||||
|
||||
if (instance->frame != NULL)
|
||||
vm_free(instance->frame);
|
||||
|
||||
instance->frame = NULL;
|
||||
instance->parent->instance_count--;
|
||||
|
||||
if ( instance->last_bitmap != -1 ) {
|
||||
bm_release(instance->last_bitmap);
|
||||
instance->last_bitmap = -1;
|
||||
}
|
||||
|
||||
// remove instance from anim_render_list
|
||||
list_remove( &anim_render_list, instance );
|
||||
|
||||
// insert instance into the anim_free_list
|
||||
list_append( &anim_free_list, instance );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free all anim instances that are on the anim_render_list.
|
||||
*
|
||||
* @param screen_id Optional parameter that lets you only free a subset of the anim instances.
|
||||
* A screen_id of 0 is the default value, and this is used for animations that always play when
|
||||
* they are placed on the aim_render_list.
|
||||
*/
|
||||
void anim_release_all_instances(int screen_id)
|
||||
{
|
||||
anim_instance* A;
|
||||
anim_instance* temp;
|
||||
|
||||
if ( Anim_inited == FALSE )
|
||||
return;
|
||||
|
||||
A = GET_FIRST(&anim_render_list);
|
||||
while( A !=END_OF_LIST(&anim_render_list) ) {
|
||||
temp = GET_NEXT(A);
|
||||
if ( A->screen_id == screen_id || screen_id == 0 ) {
|
||||
anim_release_render_instance(A);
|
||||
}
|
||||
A = temp;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// anim_read_header()
|
||||
//
|
||||
// Read the header of a .ani file. Below is the format of a .ani header
|
||||
//
|
||||
// #bytes | description
|
||||
// 2 | obsolete, kept for compatibility with old versions
|
||||
// 2 | version number
|
||||
// 2 | fps
|
||||
// 1 | transparent red value
|
||||
// 1 | transparent green value
|
||||
// 1 | transparent blue value
|
||||
// 2 | width
|
||||
// 2 | height
|
||||
// 2 | number of frames
|
||||
// 1 | packer code
|
||||
// 763 | palette
|
||||
// 2 | number of key frames
|
||||
// 2 | key frame number } repeats
|
||||
// 4 | key frame offset } repeats
|
||||
// 4 | compressed data length
|
||||
//
|
||||
void anim_read_header(anim *ptr, CFILE *fp)
|
||||
{
|
||||
ptr->width = cfread_short(fp);
|
||||
// If first 2 bytes are zero, this means we are using a new format, which includes
|
||||
// a version, and fps values. This is only done since a version number was not included
|
||||
// in the original header.
|
||||
|
||||
// default
|
||||
Color_xparent.red = 0;
|
||||
Color_xparent.green = 255;
|
||||
Color_xparent.blue = 0;
|
||||
|
||||
if ( ptr->width == 0 ) {
|
||||
ptr->version = cfread_short(fp);
|
||||
ptr->fps = cfread_short(fp);
|
||||
|
||||
// version 2 added a custom transparency color
|
||||
if ( ptr->version >= 2 ) {
|
||||
cfread(&Color_xparent.red, 1, 1, fp);
|
||||
cfread(&Color_xparent.green, 1, 1, fp);
|
||||
cfread(&Color_xparent.blue, 1, 1, fp);
|
||||
}
|
||||
|
||||
ptr->width = cfread_short(fp);
|
||||
}
|
||||
else {
|
||||
ptr->version = 0;
|
||||
ptr->fps = 30;
|
||||
}
|
||||
|
||||
ptr->height = cfread_short(fp);
|
||||
|
||||
#ifndef NDEBUG
|
||||
// get size of ani compared to power of 2
|
||||
int r, floor_pow;
|
||||
r = ptr->height;
|
||||
floor_pow = 0;
|
||||
|
||||
while(r >= 2) {
|
||||
r /= 2;
|
||||
floor_pow++;
|
||||
}
|
||||
|
||||
int floor_size = (int) pow(2.0, floor_pow);
|
||||
int diff = ptr->height - floor_size;
|
||||
float waste = 100.0f * float((floor_size - diff))/(2.0f *(float)floor_size);
|
||||
|
||||
if (diff != 0) {
|
||||
if (ptr->height > 16) {
|
||||
mprintf(("ANI %s with size %dx%d (%.1f%% wasted)\n", ptr->name, ptr->width, ptr->height, waste));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ptr->total_frames = cfread_short(fp);
|
||||
ptr->packer_code = cfread_ubyte(fp);
|
||||
cfread(&ptr->palette, 256, 3, fp);
|
||||
ptr->num_keys = cfread_short(fp);
|
||||
|
||||
// store xparent colors
|
||||
ptr->xparent_r = Color_xparent.red;
|
||||
ptr->xparent_g = Color_xparent.green;
|
||||
ptr->xparent_b = Color_xparent.blue;
|
||||
|
||||
if(ptr->total_frames == ptr->num_keys){
|
||||
ptr->flags |= ANF_ALL_KEYFRAMES;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Load an animation. This stores the compressed data, which instances of the animation can reference.
|
||||
* Must be free'ed later with anim_free().
|
||||
*
|
||||
* @param real_filename Filename of animation
|
||||
* @param cf_dir_type
|
||||
* @param file_mapped Whether to use memory-mapped file or not.
|
||||
*
|
||||
* @details Memory-mapped files will page in the animation from disk as it is needed, but performance is not as good.
|
||||
* @return Pointer to anim that is loaded if sucess, NULL if failure.
|
||||
*/
|
||||
anim *anim_load(const char *real_filename, int cf_dir_type, int file_mapped)
|
||||
{
|
||||
anim *ptr;
|
||||
CFILE *fp;
|
||||
int count,idx;
|
||||
char name[_MAX_PATH];
|
||||
|
||||
Assert( real_filename != NULL );
|
||||
|
||||
strcpy_s( name, real_filename );
|
||||
char *p = strchr( name, '.' );
|
||||
if ( p ) {
|
||||
*p = 0;
|
||||
}
|
||||
strcat_s( name, ".ani" );
|
||||
|
||||
ptr = first_anim;
|
||||
while (ptr) {
|
||||
if (!stricmp(name, ptr->name))
|
||||
break;
|
||||
|
||||
ptr = ptr->next;
|
||||
}
|
||||
|
||||
if (!ptr) {
|
||||
fp = cfopen(name, "rb", CFILE_NORMAL, cf_dir_type);
|
||||
if ( !fp )
|
||||
return NULL;
|
||||
|
||||
ptr = (anim *) vm_malloc(sizeof(anim));
|
||||
Assert(ptr);
|
||||
|
||||
ptr->flags = 0;
|
||||
ptr->next = first_anim;
|
||||
first_anim = ptr;
|
||||
Assert(strlen(name) < _MAX_PATH - 1);
|
||||
strcpy_s(ptr->name, name);
|
||||
ptr->instance_count = 0;
|
||||
ptr->width = 0;
|
||||
ptr->height = 0;
|
||||
ptr->total_frames = 0;
|
||||
ptr->keys = NULL;
|
||||
ptr->ref_count=0;
|
||||
|
||||
anim_read_header(ptr, fp);
|
||||
|
||||
if (ptr->width < 0 || ptr->height < 0) {
|
||||
Error(LOCATION, "Ani file %s has a faulty header and cannot be loaded.", name);
|
||||
}
|
||||
|
||||
if(ptr->num_keys > 0){
|
||||
ptr->keys = (key_frame*)vm_malloc(sizeof(key_frame) * ptr->num_keys);
|
||||
Assert(ptr->keys != NULL);
|
||||
}
|
||||
|
||||
// store how long the anim should take on playback (in seconds)
|
||||
ptr->time = i2fl(ptr->total_frames)/ptr->fps;
|
||||
|
||||
for(idx=0;idx<ptr->num_keys;idx++){
|
||||
ptr->keys[idx].frame_num = 0;
|
||||
cfread(&ptr->keys[idx].frame_num, 2, 1, fp);
|
||||
cfread(&ptr->keys[idx].offset, 4, 1, fp);
|
||||
ptr->keys[idx].frame_num = INTEL_INT( ptr->keys[idx].frame_num ); //-V570
|
||||
ptr->keys[idx].offset = INTEL_INT( ptr->keys[idx].offset ); //-V570
|
||||
}
|
||||
|
||||
cfread(&count, 4, 1, fp); // size of compressed data
|
||||
count = INTEL_INT( count );
|
||||
|
||||
ptr->cfile_ptr = NULL;
|
||||
|
||||
if ( file_mapped == PAGE_FROM_MEM) {
|
||||
// Try mapping the file to memory
|
||||
ptr->flags |= ANF_MEM_MAPPED;
|
||||
ptr->cfile_ptr = cfopen(name, "rb", CFILE_MEMORY_MAPPED, cf_dir_type);
|
||||
}
|
||||
|
||||
// couldn't memory-map file... must be in a packfile, so stream manually
|
||||
if ( file_mapped == PAGE_FROM_MEM && !ptr->cfile_ptr ) {
|
||||
ptr->flags &= ~ANF_MEM_MAPPED;
|
||||
ptr->flags |= ANF_STREAMED;
|
||||
ptr->cfile_ptr = cfopen(name, "rb", CFILE_NORMAL, cf_dir_type);
|
||||
}
|
||||
|
||||
ptr->cache = NULL;
|
||||
|
||||
// If it opened properly as mem-mapped (or streamed)
|
||||
if (ptr->cfile_ptr != NULL) {
|
||||
// VERY IMPORTANT STEP
|
||||
// Set the data pointer to the compressed data (which is not at the start of the
|
||||
// file). Use ftell() to find out how far we've already parsed into the file
|
||||
//
|
||||
int offset;
|
||||
offset = cftell(fp);
|
||||
ptr->file_offset = offset;
|
||||
if ( ptr->flags & ANF_STREAMED ) {
|
||||
ptr->data = NULL;
|
||||
ptr->cache_file_offset = ptr->file_offset;
|
||||
ptr->cache = (ubyte*)vm_malloc(ANI_STREAM_CACHE_SIZE+2);
|
||||
Assert(ptr->cache);
|
||||
cfseek(ptr->cfile_ptr, offset, CF_SEEK_SET);
|
||||
cfread(ptr->cache, ANI_STREAM_CACHE_SIZE, 1, ptr->cfile_ptr);
|
||||
} else {
|
||||
ptr->data = (ubyte*)cf_returndata(ptr->cfile_ptr) + offset;
|
||||
}
|
||||
} else {
|
||||
// Not a memory mapped file (or streamed)
|
||||
ptr->flags &= ~ANF_MEM_MAPPED;
|
||||
ptr->flags &= ~ANF_STREAMED;
|
||||
ptr->data = (ubyte *) vm_malloc(count);
|
||||
ptr->file_offset = -1;
|
||||
cfread(ptr->data, count, 1, fp);
|
||||
}
|
||||
|
||||
cfclose(fp);
|
||||
|
||||
// store screen signature, so we can tell if palette changes
|
||||
ptr->screen_sig = gr_screen.signature;
|
||||
|
||||
anim_set_palette(ptr);
|
||||
}
|
||||
|
||||
ptr->ref_count++;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free an animation that was loaded with anim_load().
|
||||
* @details All instances referencing this animation must be free'ed or get an assert.
|
||||
*/
|
||||
int anim_free(anim *ptr)
|
||||
{
|
||||
Assert ( ptr != NULL );
|
||||
anim *list, **prev_anim;
|
||||
|
||||
list = first_anim;
|
||||
prev_anim = &first_anim;
|
||||
while (list && (list != ptr)) {
|
||||
prev_anim = &list->next;
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
if ( !list )
|
||||
return -2;
|
||||
|
||||
// only free when ref_count is 0
|
||||
ptr->ref_count--;
|
||||
if ( ptr->ref_count > 0 )
|
||||
return -1;
|
||||
|
||||
// only free if there are no playing instances
|
||||
if ( ptr->instance_count > 0 )
|
||||
return -1;
|
||||
|
||||
if(ptr->keys != NULL){
|
||||
vm_free(ptr->keys);
|
||||
ptr->keys = NULL;
|
||||
}
|
||||
|
||||
if ( ptr->flags & (ANF_MEM_MAPPED|ANF_STREAMED) ) {
|
||||
cfclose(ptr->cfile_ptr);
|
||||
if (ptr->cache != NULL) {
|
||||
vm_free(ptr->cache);
|
||||
ptr->cache = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Assert(ptr->data);
|
||||
if (ptr->data != NULL) {
|
||||
vm_free(ptr->data);
|
||||
ptr->data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
*prev_anim = ptr->next;
|
||||
vm_free(ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called at the beginning of a mission to initialize any mission dependent anim data.
|
||||
* @todo Redundant?
|
||||
*/
|
||||
void anim_level_init()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called after the end of a mission to clean up any mission dependent anim data.
|
||||
*/
|
||||
void anim_level_close()
|
||||
{
|
||||
anim_release_all_instances();
|
||||
}
|
||||
|
||||
void anim_reverse_direction(anim_instance *ai)
|
||||
{
|
||||
int temp;
|
||||
|
||||
// you're not allowed to call anim_reverse_direction(...) unless every frame is a keyframe!!!!
|
||||
// The God of Delta-RLE demands it be thus.
|
||||
Assertion( ai->parent->flags & ANF_ALL_KEYFRAMES, "Ani was set to play backwards. In order to enable this, all frames of the animation MUST be keyframes.");
|
||||
|
||||
// flip the animation direction
|
||||
if(ai->direction == ANIM_DIRECT_FORWARD){
|
||||
ai->direction = ANIM_DIRECT_REVERSE;
|
||||
} else if(ai->direction == ANIM_DIRECT_REVERSE){
|
||||
ai->direction = ANIM_DIRECT_FORWARD;
|
||||
}
|
||||
|
||||
// flip frame_num and last_frame_num
|
||||
temp = ai->frame_num;
|
||||
ai->frame_num = ai->last_frame_num;
|
||||
ai->last_frame_num = temp;
|
||||
|
||||
// flip the start and stop at frames
|
||||
temp = ai->stop_at;
|
||||
ai->stop_at = ai->start_at;
|
||||
ai->start_at = temp;
|
||||
|
||||
// make sure to sync up the time correctly
|
||||
if(ai->direction == ANIM_DIRECT_FORWARD){
|
||||
ai->time_elapsed = ((float)ai->frame_num - (float)ai->start_at - 1.0f) / (float)ai->parent->fps;
|
||||
} else if(ai->direction == ANIM_DIRECT_REVERSE) {
|
||||
ai->time_elapsed = ((float)ai->start_at - (float)ai->frame_num - 1.0f) / (float)ai->parent->fps;
|
||||
}
|
||||
}
|
||||
|
||||
void anim_ignore_next_frametime()
|
||||
{
|
||||
Anim_ignore_frametime=1;
|
||||
}
|
||||
|
||||
int anim_instance_is_streamed(anim_instance *ai)
|
||||
{
|
||||
Assert(ai);
|
||||
return ( ai->parent->flags & ANF_STREAMED );
|
||||
}
|
||||
|
||||
unsigned char anim_instance_get_byte(anim_instance *ai, int offset)
|
||||
{
|
||||
int absolute_offset;
|
||||
anim *parent;
|
||||
|
||||
Assert(ai);
|
||||
Assert(ai->parent->cfile_ptr);
|
||||
Assert(ai->parent->flags & ANF_STREAMED);
|
||||
|
||||
parent = ai->parent;
|
||||
absolute_offset = ai->file_offset + offset;
|
||||
|
||||
// maybe in cache?
|
||||
int cache_offset;
|
||||
cache_offset = absolute_offset - parent->cache_file_offset;
|
||||
if ( (cache_offset >= 0) && (cache_offset < ANI_STREAM_CACHE_SIZE) ) {
|
||||
return parent->cache[cache_offset];
|
||||
} else {
|
||||
// fill cache
|
||||
cfseek(parent->cfile_ptr, absolute_offset, CF_SEEK_SET);
|
||||
cfread(parent->cache, ANI_STREAM_CACHE_SIZE, 1, parent->cfile_ptr);
|
||||
parent->cache_file_offset = absolute_offset;
|
||||
return parent->cache[0];
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef __ANIMPLAY_H__
|
||||
#define __ANIMPLAY_H__
|
||||
|
||||
#include "cfile/cfile.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
|
||||
struct anim;
|
||||
struct anim_info;
|
||||
struct anim_instance;
|
||||
|
||||
// structure passed in when playing an anim. Talk about overkill..
|
||||
typedef struct {
|
||||
anim *anim_info;
|
||||
int x;
|
||||
int y;
|
||||
int base_w;
|
||||
int base_h;
|
||||
int start_at;
|
||||
int stop_at;
|
||||
int screen_id;
|
||||
vec3d *world_pos;
|
||||
float radius;
|
||||
int framerate_independent;
|
||||
void *color;
|
||||
int skip_frames;
|
||||
int looped;
|
||||
int ping_pong;
|
||||
} anim_play_struct;
|
||||
|
||||
enum
|
||||
{
|
||||
PAGE_FROM_DISK = 0,
|
||||
PAGE_FROM_MEM = 1
|
||||
};
|
||||
|
||||
extern int Anim_paused;
|
||||
|
||||
void anim_init();
|
||||
void anim_level_init();
|
||||
void anim_level_close();
|
||||
void anim_render_all(int screen_id, float frametime);
|
||||
void anim_render_one(int screen_id, anim_instance *ani, float frametime);
|
||||
void anim_play_init(anim_play_struct *aps, anim *a_info, int x, int y, int max_x = -1, int max_y = -1);
|
||||
anim_instance *anim_play(anim_play_struct *aps);
|
||||
void anim_ignore_next_frametime();
|
||||
int anim_show_next_frame(anim_instance *instance, float frametime);
|
||||
void anim_release_all_instances(int screen_id = 0);
|
||||
void anim_release_render_instance(anim_instance* instance);
|
||||
anim *anim_load(const char *name, int cf_dir_type = CF_TYPE_ANY, int file_mapped = PAGE_FROM_DISK);
|
||||
int anim_free(anim *ptr);
|
||||
void anim_read_header(anim *ptr, CFILE *fp);
|
||||
void anim_reverse_direction(anim_instance *ai); // called automatically for ping-ponging, and can also be called externally
|
||||
|
||||
int anim_instance_is_streamed(anim_instance *ai);
|
||||
unsigned char anim_instance_get_byte(anim_instance *ai, int offset);
|
||||
|
||||
#endif /* __ANIMPLAY_H__ */
|
||||
@@ -1,721 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "anim/animplay.h"
|
||||
#include "anim/packunpack.h"
|
||||
#include "bmpman/bmpman.h"
|
||||
#include "graphics/2d.h"
|
||||
|
||||
|
||||
const int packer_code = PACKER_CODE;
|
||||
const int transparent_code = 254;
|
||||
|
||||
void anim_check_for_palette_change(anim_instance *instance) {
|
||||
if ( instance->parent->screen_sig != gr_screen.signature ) {
|
||||
instance->parent->screen_sig = gr_screen.signature;
|
||||
anim_set_palette(instance->parent);
|
||||
}
|
||||
}
|
||||
|
||||
anim_instance *init_anim_instance(anim *ptr, int bpp)
|
||||
{
|
||||
anim_instance *inst;
|
||||
|
||||
if (!ptr) {
|
||||
Int3();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( ptr->flags & ANF_STREAMED ) {
|
||||
if ( ptr->file_offset < 0 ) {
|
||||
Int3();
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if ( !ptr->data ) {
|
||||
Int3();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ptr->instance_count++;
|
||||
inst = (anim_instance *) vm_malloc(sizeof(anim_instance));
|
||||
Assert(inst);
|
||||
memset(inst, 0, sizeof(anim_instance));
|
||||
inst->frame_num = -1;
|
||||
inst->last_frame_num = -1;
|
||||
inst->parent = ptr;
|
||||
inst->data = ptr->data;
|
||||
inst->file_offset = ptr->file_offset;
|
||||
inst->stop_now = FALSE;
|
||||
inst->aa_color = NULL;
|
||||
|
||||
inst->frame = (ubyte *) vm_malloc(inst->parent->width * inst->parent->height * (bpp >> 3));
|
||||
Assert( inst->frame != NULL );
|
||||
memset( inst->frame, 0, inst->parent->width * inst->parent->height * (bpp >> 3) );
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
void free_anim_instance(anim_instance *inst)
|
||||
{
|
||||
Assert(inst->frame);
|
||||
vm_free(inst->frame);
|
||||
inst->frame = NULL;
|
||||
inst->parent->instance_count--;
|
||||
inst->parent = NULL;
|
||||
inst->data = NULL;
|
||||
inst->file_offset = -1;
|
||||
|
||||
vm_free(inst);
|
||||
}
|
||||
|
||||
ubyte *anim_get_next_raw_buffer(anim_instance *inst, int xlate_pal, int aabitmap, int bpp)
|
||||
{
|
||||
if ( anim_instance_is_streamed(inst) ) {
|
||||
if ( inst->file_offset < 0 ) {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if (!inst->data){
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
inst->frame_num++;
|
||||
if (inst->frame_num >= inst->parent->total_frames) {
|
||||
inst->data = NULL;
|
||||
inst->file_offset = inst->parent->file_offset;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
anim_check_for_palette_change(inst);
|
||||
|
||||
if ( anim_instance_is_streamed(inst) ) {
|
||||
if ( xlate_pal ){
|
||||
inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
|
||||
} else {
|
||||
inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, NULL, aabitmap, bpp);
|
||||
}
|
||||
} else {
|
||||
if ( xlate_pal ){
|
||||
inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
|
||||
} else {
|
||||
inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, NULL, aabitmap, bpp);
|
||||
}
|
||||
}
|
||||
|
||||
return inst->frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a 24 bit value to a 16 bit value
|
||||
* @param bit_24 24 bit value
|
||||
* @param bit_16 16 bit value (output)
|
||||
*/
|
||||
void convert_24_to_16(int bit_24, ushort *bit_16)
|
||||
{
|
||||
ubyte *pixel = (ubyte*)&bit_24;
|
||||
ubyte alpha = 1;
|
||||
|
||||
bm_set_components((ubyte*)bit_16, (ubyte*)&pixel[0], (ubyte*)&pixel[1], (ubyte*)&pixel[2], &alpha);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unpack a pixel given the passed index and the anim_instance's palette
|
||||
* @return Bytes stuffed
|
||||
*/
|
||||
int unpack_pixel(anim_instance *ai, ubyte *data, ubyte pix, int aabitmap, int bpp)
|
||||
{
|
||||
int bit_24;
|
||||
ushort bit_16 = 0;
|
||||
ubyte bit_8 = 0;
|
||||
ubyte al = 0;
|
||||
ubyte r, g, b;
|
||||
int pixel_size = (bpp / 8);
|
||||
anim *a = ai->parent;
|
||||
Assert(a);
|
||||
|
||||
// if this is an aabitmap, don't run through the palette
|
||||
if(aabitmap){
|
||||
switch(bpp){
|
||||
case 16 :
|
||||
bit_16 = (ushort)pix;
|
||||
break;
|
||||
case 8:
|
||||
// 8 bit-per-pixel aa bitmaps are a bit special since they only use value in the range [0, 15] where 15 wraps
|
||||
// around back to 0. Since the rest of the code expects the value to be in the range [0, 255] the pixel value
|
||||
// needs to be adjusted here. By muliplying the value with 17 the original range [0, 15] is mapped to [0, 255]
|
||||
if (pix >= 15) {
|
||||
bit_8 = 0;
|
||||
} else {
|
||||
bit_8 = (ubyte)(pix * 17);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Int3();
|
||||
}
|
||||
} else {
|
||||
// if the pixel value is 255, or is the xparent color, make it so
|
||||
if(((a->palette[pix*3] == a->xparent_r) && (a->palette[pix*3+1] == a->xparent_g) && (a->palette[pix*3+2] == a->xparent_b)) ){
|
||||
if (pixel_size > 2) {
|
||||
bit_24 = 0;
|
||||
} else {
|
||||
r = b = 0;
|
||||
g = 255;
|
||||
|
||||
bm_set_components((ubyte*)&bit_16, &r, &g, &b, &al);
|
||||
}
|
||||
} else {
|
||||
if (pixel_size > 2) {
|
||||
ubyte pixel[4];
|
||||
pixel[0] = ai->parent->palette[pix * 3 + 2];
|
||||
pixel[1] = ai->parent->palette[pix * 3 + 1];
|
||||
pixel[2] = ai->parent->palette[pix * 3];
|
||||
pixel[3] = 255;
|
||||
memcpy(&bit_24, pixel, sizeof(int));
|
||||
|
||||
if (pixel_size == 4) {
|
||||
bit_24 = INTEL_INT(bit_24);
|
||||
}
|
||||
} else {
|
||||
// stuff the 24 bit value
|
||||
memcpy(&bit_24, &ai->parent->palette[pix * 3], 3); //-V512
|
||||
|
||||
// convert to 16 bit
|
||||
convert_24_to_16(bit_24, &bit_16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// stuff the pixel
|
||||
switch (bpp) {
|
||||
case 32:
|
||||
case 24:
|
||||
memcpy(data, &bit_24, pixel_size);
|
||||
break;
|
||||
|
||||
case 16:
|
||||
memcpy(data, &bit_16, pixel_size);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
*data = bit_8;
|
||||
break;
|
||||
|
||||
default:
|
||||
Int3();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pixel_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unpack a pixel given the passed index and the anim_instance's palette
|
||||
* @return Bytes stuffed
|
||||
*/
|
||||
int unpack_pixel_count(anim_instance *ai, ubyte *data, ubyte pix, int count = 0, int aabitmap = 0, int bpp = 8)
|
||||
{
|
||||
int bit_24;
|
||||
int idx;
|
||||
ubyte al = 0;
|
||||
ushort bit_16 = 0;
|
||||
ubyte bit_8 = 0;
|
||||
anim *a = ai->parent;
|
||||
int pixel_size = (bpp / 8);
|
||||
ubyte r, g, b;
|
||||
Assert(a);
|
||||
|
||||
// if this is an aabitmap, don't run through the palette
|
||||
if(aabitmap){
|
||||
switch(bpp){
|
||||
case 16 :
|
||||
bit_16 = (ushort)pix;
|
||||
break;
|
||||
case 8 :
|
||||
// 8 bit-per-pixel aa bitmaps are a bit special since they only use value in the range [0, 15] where 15 wraps
|
||||
// around back to 0. Since the rest of the code expects the value to be in the range [0, 255] the pixel value
|
||||
// needs to be adjusted here. By muliplying the value with 17 the original range [0, 15] is mapped to [0, 255]
|
||||
if (pix >= 15) {
|
||||
bit_8 = 0;
|
||||
} else {
|
||||
bit_8 = (ubyte)(pix * 17);
|
||||
}
|
||||
break;
|
||||
default :
|
||||
Int3();
|
||||
}
|
||||
} else {
|
||||
// if the pixel value is 255, or is the xparent color, make it so
|
||||
if(((a->palette[pix*3] == a->xparent_r) && (a->palette[pix*3+1] == a->xparent_g) && (a->palette[pix*3+2] == a->xparent_b)) ){
|
||||
if (pixel_size > 2) {
|
||||
bit_24 = 0;
|
||||
} else {
|
||||
r = b = 0;
|
||||
g = 255;
|
||||
|
||||
bm_set_components((ubyte*)&bit_16, &r, &g, &b, &al);
|
||||
}
|
||||
} else {
|
||||
if (pixel_size > 2) {
|
||||
ubyte pixel[4];
|
||||
pixel[0] = ai->parent->palette[pix * 3 + 2];
|
||||
pixel[1] = ai->parent->palette[pix * 3 + 1];
|
||||
pixel[2] = ai->parent->palette[pix * 3];
|
||||
pixel[3] = 255;
|
||||
memcpy(&bit_24, pixel, sizeof(int));
|
||||
|
||||
if (pixel_size == 4) {
|
||||
bit_24 = INTEL_INT(bit_24);
|
||||
}
|
||||
} else {
|
||||
// stuff the 24 bit value
|
||||
memcpy(&bit_24, &ai->parent->palette[pix * 3], 3); //-V512
|
||||
|
||||
// convert to 16 bit
|
||||
convert_24_to_16(bit_24, &bit_16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// stuff the pixel
|
||||
for (idx=0; idx<count; idx++) {
|
||||
switch (bpp) {
|
||||
case 32:
|
||||
case 24:
|
||||
memcpy(data + (idx * pixel_size), &bit_24, pixel_size);
|
||||
break;
|
||||
|
||||
case 16:
|
||||
memcpy(data + (idx * pixel_size), &bit_16, pixel_size);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
*(data + idx) = bit_8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (pixel_size * count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unpack frame
|
||||
*
|
||||
* @param ai Animation instance
|
||||
* @param ptr Packed data to unpack
|
||||
* @param frame Where to store unpacked data to
|
||||
* @param size Total number of unpacked pixels requested
|
||||
* @param pal_translate Color translation lookup table (NULL if no palette translation desired)
|
||||
* @param aabitmap
|
||||
* @param bpp
|
||||
*/
|
||||
ubyte *unpack_frame(anim_instance *ai, ubyte *ptr, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp)
|
||||
{
|
||||
int xlate_pal, value, count = 0;
|
||||
int stuffed;
|
||||
int pixel_size = (bpp / 8);
|
||||
|
||||
if ( pal_translate == NULL ) {
|
||||
xlate_pal = 0;
|
||||
}
|
||||
else {
|
||||
xlate_pal = 1;
|
||||
}
|
||||
|
||||
if (*ptr == PACKING_METHOD_RLE_KEY) { // key frame, Hoffoss's RLE format
|
||||
ptr++;
|
||||
while (size > 0) {
|
||||
value = *ptr++;
|
||||
if (value != packer_code) {
|
||||
if ( xlate_pal ){
|
||||
stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
|
||||
} else {
|
||||
stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
|
||||
}
|
||||
frame += stuffed;
|
||||
size--;
|
||||
} else {
|
||||
count = *ptr++;
|
||||
if (count < 2){
|
||||
value = packer_code;
|
||||
} else {
|
||||
value = *ptr++;
|
||||
}
|
||||
|
||||
if (++count > size){
|
||||
count = size;
|
||||
}
|
||||
|
||||
if ( xlate_pal ){
|
||||
stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
|
||||
} else {
|
||||
stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
|
||||
}
|
||||
|
||||
frame += stuffed;
|
||||
size -= count;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( *ptr == PACKING_METHOD_STD_RLE_KEY) { // key frame, with high bit as count
|
||||
ptr++;
|
||||
while (size > 0) {
|
||||
value = *ptr++;
|
||||
if ( !(value & STD_RLE_CODE) ) {
|
||||
if ( xlate_pal ){
|
||||
stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
|
||||
} else {
|
||||
stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
|
||||
}
|
||||
|
||||
frame += stuffed;
|
||||
size--;
|
||||
} else {
|
||||
count = value & (~STD_RLE_CODE);
|
||||
value = *ptr++;
|
||||
|
||||
if (count > size)
|
||||
count = size;
|
||||
|
||||
size -= count;
|
||||
Assert(size >= 0);
|
||||
|
||||
if ( xlate_pal ){
|
||||
stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
|
||||
} else {
|
||||
stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
|
||||
}
|
||||
|
||||
frame += stuffed;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (*ptr == PACKING_METHOD_RLE) { // normal frame, Hoffoss's RLE format
|
||||
|
||||
ptr++;
|
||||
while (size > 0) {
|
||||
value = *ptr++;
|
||||
if (value != packer_code) {
|
||||
if (value != transparent_code) {
|
||||
if ( xlate_pal ){
|
||||
stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
|
||||
} else {
|
||||
stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
|
||||
}
|
||||
} else {
|
||||
// temporary pixel
|
||||
stuffed = pixel_size;
|
||||
}
|
||||
|
||||
frame += stuffed;
|
||||
size--;
|
||||
} else {
|
||||
count = *ptr++;
|
||||
if (count < 2){
|
||||
value = packer_code;
|
||||
} else {
|
||||
value = *ptr++;
|
||||
}
|
||||
|
||||
if (++count > size){
|
||||
count = size;
|
||||
}
|
||||
|
||||
size -= count;
|
||||
Assert(size >= 0);
|
||||
|
||||
if (value != transparent_code ) {
|
||||
if ( xlate_pal ) {
|
||||
stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
|
||||
} else {
|
||||
stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
|
||||
}
|
||||
} else {
|
||||
stuffed = count * pixel_size;
|
||||
}
|
||||
|
||||
frame += stuffed;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if ( *ptr == PACKING_METHOD_STD_RLE) { // normal frame, with high bit as count
|
||||
ptr++;
|
||||
while (size > 0) {
|
||||
value = *ptr++;
|
||||
if ( !(value & STD_RLE_CODE) ) {
|
||||
if (value != transparent_code) {
|
||||
if ( xlate_pal ){
|
||||
stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
|
||||
} else {
|
||||
stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
|
||||
}
|
||||
} else {
|
||||
stuffed = pixel_size;
|
||||
}
|
||||
|
||||
frame += stuffed;
|
||||
size--;
|
||||
} else {
|
||||
count = value & (~STD_RLE_CODE);
|
||||
value = *ptr++;
|
||||
|
||||
if (count > size)
|
||||
count = size;
|
||||
|
||||
size -= count;
|
||||
Assert(size >= 0);
|
||||
|
||||
if (value != transparent_code) {
|
||||
if ( xlate_pal ){
|
||||
stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
|
||||
} else {
|
||||
stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
|
||||
}
|
||||
} else {
|
||||
stuffed = pixel_size * count;
|
||||
}
|
||||
|
||||
frame += stuffed;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// unknown packing method
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unpack frame from file
|
||||
*
|
||||
* @param ai Animation instance
|
||||
* @param frame Where to store unpacked data to
|
||||
* @param size Total number of unpacked pixels requested
|
||||
* @param pal_translate Color translation lookup table (NULL if no palette translation desired)
|
||||
* @param aabitmap
|
||||
* @param bpp
|
||||
*/
|
||||
int unpack_frame_from_file(anim_instance *ai, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp)
|
||||
{
|
||||
int xlate_pal, value, count = 0;
|
||||
int offset = 0;
|
||||
int stuffed;
|
||||
int pixel_size = (bpp / 8);
|
||||
|
||||
if ( pal_translate == NULL ) {
|
||||
xlate_pal = 0;
|
||||
}
|
||||
else {
|
||||
xlate_pal = 1;
|
||||
}
|
||||
|
||||
if (anim_instance_get_byte(ai,offset) == PACKING_METHOD_RLE_KEY) { // key frame, Hoffoss's RLE format
|
||||
offset++;
|
||||
while (size > 0) {
|
||||
value = anim_instance_get_byte(ai,offset);
|
||||
offset++;
|
||||
if (value != packer_code) {
|
||||
if ( xlate_pal ){
|
||||
stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
|
||||
} else {
|
||||
stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
|
||||
}
|
||||
|
||||
frame += stuffed;
|
||||
size--;
|
||||
} else {
|
||||
count = anim_instance_get_byte(ai,offset);
|
||||
offset++;
|
||||
if (count < 2) {
|
||||
value = packer_code;
|
||||
} else {
|
||||
value = anim_instance_get_byte(ai,offset);
|
||||
offset++;
|
||||
}
|
||||
|
||||
if (++count > size){
|
||||
count = size;
|
||||
}
|
||||
|
||||
if ( xlate_pal ){
|
||||
stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
|
||||
} else {
|
||||
stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
|
||||
}
|
||||
|
||||
frame += stuffed;
|
||||
size -= count;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( anim_instance_get_byte(ai,offset) == PACKING_METHOD_STD_RLE_KEY) { // key frame, with high bit as count
|
||||
offset++;
|
||||
while (size > 0) {
|
||||
value = anim_instance_get_byte(ai,offset);
|
||||
offset++;
|
||||
if ( !(value & STD_RLE_CODE) ) {
|
||||
if ( xlate_pal ){
|
||||
stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
|
||||
} else {
|
||||
stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
|
||||
}
|
||||
|
||||
frame += stuffed;
|
||||
size--;
|
||||
} else {
|
||||
count = value & (~STD_RLE_CODE);
|
||||
value = anim_instance_get_byte(ai,offset);
|
||||
offset++;
|
||||
|
||||
if (count > size)
|
||||
count = size;
|
||||
|
||||
size -= count;
|
||||
Assert(size >= 0);
|
||||
|
||||
if ( xlate_pal ){
|
||||
stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
|
||||
} else {
|
||||
stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
|
||||
}
|
||||
|
||||
frame += stuffed;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (anim_instance_get_byte(ai,offset) == PACKING_METHOD_RLE) { // normal frame, Hoffoss's RLE format
|
||||
|
||||
offset++;
|
||||
while (size > 0) {
|
||||
value = anim_instance_get_byte(ai,offset);
|
||||
offset++;
|
||||
if (value != packer_code) {
|
||||
if (value != transparent_code) {
|
||||
if ( xlate_pal ){
|
||||
stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
|
||||
} else {
|
||||
stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
|
||||
}
|
||||
} else {
|
||||
stuffed = pixel_size;
|
||||
}
|
||||
|
||||
frame += stuffed;
|
||||
size--;
|
||||
} else {
|
||||
count = anim_instance_get_byte(ai,offset);
|
||||
offset++;
|
||||
|
||||
if (count < 2) {
|
||||
value = packer_code;
|
||||
} else {
|
||||
value = anim_instance_get_byte(ai,offset);
|
||||
offset++;
|
||||
}
|
||||
if (++count > size){
|
||||
count = size;
|
||||
}
|
||||
|
||||
size -= count;
|
||||
Assert(size >= 0);
|
||||
|
||||
if (value != transparent_code ) {
|
||||
if ( xlate_pal ) {
|
||||
stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
|
||||
} else {
|
||||
stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
|
||||
}
|
||||
} else {
|
||||
stuffed = pixel_size * count;
|
||||
}
|
||||
|
||||
frame += stuffed;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if ( anim_instance_get_byte(ai,offset) ) { // normal frame, with high bit as count
|
||||
offset++;
|
||||
while (size > 0) {
|
||||
value = anim_instance_get_byte(ai,offset);
|
||||
offset++;
|
||||
if ( !(value & STD_RLE_CODE) ) {
|
||||
if (value != transparent_code) {
|
||||
if ( xlate_pal ){
|
||||
stuffed = unpack_pixel(ai, frame, pal_translate[value], aabitmap, bpp);
|
||||
} else {
|
||||
stuffed = unpack_pixel(ai, frame, (ubyte)value, aabitmap, bpp);
|
||||
}
|
||||
} else {
|
||||
stuffed = pixel_size;
|
||||
}
|
||||
|
||||
frame += stuffed;
|
||||
size--;
|
||||
} else {
|
||||
count = value & (~STD_RLE_CODE);
|
||||
value = anim_instance_get_byte(ai,offset);
|
||||
offset++;
|
||||
|
||||
if (count > size)
|
||||
count = size;
|
||||
|
||||
size -= count;
|
||||
Assert(size >= 0);
|
||||
|
||||
if (value != transparent_code) {
|
||||
if ( xlate_pal ){
|
||||
stuffed = unpack_pixel_count(ai, frame, pal_translate[value], count, aabitmap, bpp);
|
||||
} else {
|
||||
stuffed = unpack_pixel_count(ai, frame, (ubyte)value, count, aabitmap, bpp);
|
||||
}
|
||||
} else {
|
||||
stuffed = pixel_size * count;
|
||||
}
|
||||
|
||||
frame += stuffed;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// unknown packing method
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ai->file_offset + offset;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set animation palette
|
||||
* @todo Actually convert the frame data to correct palette at this point
|
||||
*/
|
||||
void anim_set_palette(anim *ptr)
|
||||
{
|
||||
int i, xparent_found = 0;
|
||||
|
||||
// create the palette translation look-up table
|
||||
for ( i = 0; i < 256; i++ ) {
|
||||
ptr->palette_translation[i] = (ubyte)i;
|
||||
}
|
||||
|
||||
if ( xparent_found ) {
|
||||
ptr->flags |= ANF_XPARENT;
|
||||
}
|
||||
else {
|
||||
ptr->flags &= ~ANF_XPARENT;
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef __PACKUNPACK_H__
|
||||
#define __PACKUNPACK_H__
|
||||
|
||||
#include "globalincs/pstypes.h"
|
||||
|
||||
struct CFILE;
|
||||
|
||||
#define ANI_STREAM_CACHE_SIZE 4096
|
||||
|
||||
#define PACKER_CODE 0xEE /// Used by PACKING_METHOD_RLE
|
||||
#define PACKING_METHOD_RLE 0 /// Hoffoss's RLE format
|
||||
#define PACKING_METHOD_RLE_KEY 1 /// Hoffoss's key frame RLE format
|
||||
#define PACKING_METHOD_STD_RLE 2 /// Standard RLE format (high bit is count)
|
||||
#define PACKING_METHOD_STD_RLE_KEY 3 /// Standard RLE format key frame
|
||||
|
||||
#define STD_RLE_CODE 0x80
|
||||
|
||||
typedef struct key_frame {
|
||||
int frame_num; // which frame number this key frame is
|
||||
int offset; // offset from the start of data block
|
||||
} key_frame;
|
||||
|
||||
#define ANF_MEM_MAPPED (1<<0) // animation is memory-mapped file
|
||||
#define ANF_STREAMED (1<<1)
|
||||
#define ANF_XPARENT (1<<2) // animation has transparency
|
||||
#define ANF_ALL_KEYFRAMES (1<<3) // all the frames are keyframes (this is necessary if we want to play the file backwards)
|
||||
|
||||
typedef struct anim {
|
||||
anim *next;
|
||||
char name[MAX_PATH_LEN];
|
||||
ubyte packer_code;
|
||||
int width;
|
||||
int height;
|
||||
int total_frames;
|
||||
int instance_count; // number of instances that are currently playing
|
||||
int ref_count; // number of times this anim has been loaded
|
||||
float time; // playback time in seconds
|
||||
int num_keys;
|
||||
key_frame *keys;
|
||||
ubyte palette[768];
|
||||
ubyte palette_translation[256];
|
||||
ubyte *data; // points to compressed data
|
||||
CFILE* cfile_ptr;
|
||||
int version;
|
||||
int fps;
|
||||
ubyte xparent_r; // red component for the transparent color in source image
|
||||
ubyte xparent_g; // green component for the transparent color in source image
|
||||
ubyte xparent_b; // blue component for the transparent color in source image
|
||||
int flags;
|
||||
uint screen_sig;
|
||||
int file_offset; // file offset to start of frame data
|
||||
int cache_file_offset;
|
||||
ubyte *cache;
|
||||
} anim;
|
||||
|
||||
// the direction to play the anim (forwards or backwards)
|
||||
#define ANIM_DIRECT_FORWARD 0
|
||||
#define ANIM_DIRECT_REVERSE 1
|
||||
|
||||
typedef struct anim_instance {
|
||||
anim_instance *next, *prev;
|
||||
int x,y; // coordinates anim is played at (top left corner of anim)
|
||||
int base_w, base_h; // coordinate scale this anim is played in.
|
||||
vec3d *world_pos; // world (x,y,z) position of explosion
|
||||
float radius; // radius of image, needed for scaling
|
||||
int frame_num; // current frame, or last frame if between frames (first frame is 0)
|
||||
int last_frame_num;// last frame rendered
|
||||
anim *parent; // pointer to anim structure, which holds compressed data
|
||||
ubyte *data; // pointer to next frame's compressed data
|
||||
ubyte *frame; // uncompressed frame
|
||||
float time_elapsed; // how long the anim has played for (in seconds)
|
||||
int start_at; // frame anim playing should start
|
||||
int stop_at; // frame anim playing should stop
|
||||
int framerate_independent; // animation should play back in same amount of time, regardless
|
||||
int skip_frames; // should anim skip frames during framerate independent playback
|
||||
int looped; // should anim keep playing over and over...
|
||||
int stop_now; // flag to indicate time to stop the animation
|
||||
int last_bitmap; // id of last bitmap that was rendered out from animation
|
||||
int screen_id; // 0 means all screens should render, otherwise screen specific
|
||||
void *aa_color; // anti-aliased bitmap color
|
||||
int xlate_pal;
|
||||
int direction; // playing forwards or backwards ?
|
||||
int ping_pong; // should be played ping-pong style
|
||||
int paused; // pause the anim
|
||||
int file_offset; // current offset into frame (like data, put offset into file)
|
||||
int loop_count; // starts at 0, and is incremented each time it loops
|
||||
} anim_instance;
|
||||
|
||||
ubyte *unpack_frame(anim_instance *ai, ubyte *ptr, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp);
|
||||
int unpack_frame_from_file(anim_instance *ai, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp);
|
||||
|
||||
void anim_init();
|
||||
anim_instance *init_anim_instance(anim *ptr, int bpp);
|
||||
void free_anim_instance(anim_instance *inst);
|
||||
ubyte *anim_get_next_raw_buffer(anim_instance *inst, int xlate_pal, int aabitmap, int bpp);
|
||||
void anim_set_palette(anim *a);
|
||||
void anim_check_for_palette_change(anim_instance *inst);
|
||||
|
||||
|
||||
#endif /* __PACKUNPACK_H__ */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,172 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef __ASTEROID_H__
|
||||
#define __ASTEROID_H__
|
||||
|
||||
#include "globalincs/globals.h" // for NAME_LENGTH
|
||||
#include "globalincs/pstypes.h"
|
||||
|
||||
|
||||
class object;
|
||||
class polymodel;
|
||||
struct collision_info_struct;
|
||||
class model_draw_list;
|
||||
|
||||
#define MAX_ASTEROIDS 512
|
||||
|
||||
#define NUM_DEBRIS_SIZES 3
|
||||
#define NUM_DEBRIS_POFS 3 // Number of POFs per debris size
|
||||
|
||||
#define ASTEROID_TYPE_SMALL 0
|
||||
#define ASTEROID_TYPE_MEDIUM 1
|
||||
#define ASTEROID_TYPE_LARGE 2
|
||||
|
||||
// these should always be equal for the benefit of generic asteroids (c.f. asteroid_page_in)
|
||||
#define MAX_ACTIVE_DEBRIS_TYPES NUM_DEBRIS_SIZES
|
||||
|
||||
// Goober5000 - currently same as MAX_SHIP_DETAIL_LEVELS (put here to avoid an #include)
|
||||
#define MAX_ASTEROID_DETAIL_LEVELS 5
|
||||
|
||||
|
||||
// Data structure to track the active asteroids
|
||||
typedef struct asteroid_obj {
|
||||
asteroid_obj *next, *prev;
|
||||
int flags, objnum;
|
||||
} asteroid_obj;
|
||||
extern asteroid_obj Asteroid_obj_list;
|
||||
|
||||
|
||||
// Data structure for determining a type and amount of other asteroids an
|
||||
// asteroid will split to when destroyed.
|
||||
typedef struct asteroid_split_info {
|
||||
int asteroid_type;
|
||||
int min;
|
||||
int max;
|
||||
} asteroid_split_info;
|
||||
|
||||
class asteroid_info
|
||||
{
|
||||
public:
|
||||
char name[NAME_LENGTH]; // name for the asteroid
|
||||
char pof_files[NUM_DEBRIS_POFS][MAX_FILENAME_LEN]; // POF files to load/associate with ship
|
||||
int num_detail_levels; // number of detail levels for this ship
|
||||
int detail_distance[MAX_ASTEROID_DETAIL_LEVELS]; // distance to change detail levels at
|
||||
float max_speed; // cap on speed for asteroid
|
||||
int damage_type_idx; //Damage type of the asteroid
|
||||
int damage_type_idx_sav; // stored value from table used to reset damage_type_idx
|
||||
float inner_rad; // radius within which maximum area effect damage is applied
|
||||
float outer_rad; // radius at which no area effect damage is applied
|
||||
float damage; // maximum damage applied from area effect explosion
|
||||
float blast; // maximum blast impulse from area effect explosion
|
||||
float initial_asteroid_strength; // starting strength of asteroid
|
||||
SCP_vector< asteroid_split_info > split_info;
|
||||
polymodel *modelp[NUM_DEBRIS_POFS];
|
||||
int model_num[NUM_DEBRIS_POFS];
|
||||
SCP_vector<int> explosion_bitmap_anims;
|
||||
float fireball_radius_multiplier; // the model radius is multiplied by this to determine the fireball size
|
||||
|
||||
asteroid_info( )
|
||||
: num_detail_levels( 0 ), max_speed( 0 ), damage_type_idx( 0 ),
|
||||
damage_type_idx_sav( -1 ), inner_rad( 0 ), outer_rad( 0 ),
|
||||
damage( 0 ), blast( 0 ), initial_asteroid_strength( 0 ),
|
||||
fireball_radius_multiplier( -1 )
|
||||
{
|
||||
name[ 0 ] = 0;
|
||||
memset( detail_distance, 0, sizeof( detail_distance ) );
|
||||
|
||||
for (int i = 0; i < NUM_DEBRIS_POFS; i++)
|
||||
{
|
||||
modelp[i] = NULL;
|
||||
model_num[i] = -1;
|
||||
pof_files[i][0] = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#define AF_USED (1<<0) // Set means used.
|
||||
|
||||
typedef struct asteroid {
|
||||
int flags;
|
||||
int objnum;
|
||||
int model_instance_num;
|
||||
int asteroid_type; // 0..MAX_DEBRIS_TYPES
|
||||
int asteroid_subtype; // Index in asteroid_info for modelnum and modelp
|
||||
int check_for_wrap; // timestamp to check for asteroid wrapping around field
|
||||
int check_for_collide; // timestamp to check for asteroid colliding with escort ships
|
||||
int final_death_time; // timestamp to swap in new models after explosion starts
|
||||
int collide_objnum; // set to objnum that asteroid will be impacting soon
|
||||
int collide_objsig; // object signature corresponding to collide_objnum
|
||||
vec3d death_hit_pos; // hit pos that caused death
|
||||
int target_objnum; // Yes, hah! Asteroids can have targets. See asteroid_aim_at_target().
|
||||
} asteroid;
|
||||
|
||||
|
||||
// TYPEDEF FOR DEBRIS TYPE
|
||||
typedef enum {
|
||||
DG_ASTEROID,
|
||||
DG_SHIP
|
||||
} debris_genre_t;
|
||||
|
||||
// TYPEDEF FOR FIELD TYPE
|
||||
typedef enum {
|
||||
FT_ACTIVE,
|
||||
FT_PASSIVE
|
||||
} field_type_t;
|
||||
|
||||
typedef struct asteroid_field {
|
||||
vec3d min_bound; // Minimum range of field.
|
||||
vec3d max_bound; // Maximum range of field.
|
||||
float bound_rad;
|
||||
int has_inner_bound;
|
||||
vec3d inner_min_bound;
|
||||
vec3d inner_max_bound;
|
||||
vec3d vel; // Average asteroid moves at this velocity.
|
||||
float speed; // Average speed of field
|
||||
int num_initial_asteroids; // Number of asteroids at creation.
|
||||
field_type_t field_type; // active throws and wraps, passive does not
|
||||
debris_genre_t debris_genre; // type of debris (ship or asteroid) [generic type]
|
||||
int field_debris_type[MAX_ACTIVE_DEBRIS_TYPES]; // one of the debris type defines above
|
||||
} asteroid_field;
|
||||
|
||||
extern SCP_vector< asteroid_info > Asteroid_info;
|
||||
extern asteroid Asteroids[MAX_ASTEROIDS];
|
||||
extern asteroid_field Asteroid_field;
|
||||
|
||||
extern int Num_asteroids;
|
||||
extern int Asteroids_enabled;
|
||||
extern char Asteroid_icon_closeup_model[NAME_LENGTH]; // model for asteroid field briefing icon rendering
|
||||
extern vec3d Asteroid_icon_closeup_position; // closeup position for asteroid field briefing icon rendering
|
||||
extern float Asteroid_icon_closeup_zoom; // zoom position for asteroid field briefing icon rendering
|
||||
|
||||
void asteroid_init();
|
||||
void asteroid_level_init();
|
||||
void asteroid_level_close();
|
||||
void asteroid_create_all();
|
||||
void asteroid_render(object * obj, model_draw_list *scene);
|
||||
void asteroid_delete( object *asteroid_objp );
|
||||
void asteroid_process_pre( object *asteroid_objp );
|
||||
void asteroid_process_post( object *asteroid_objp);
|
||||
int asteroid_check_collision( object *asteroid_objp, object * other_obj, vec3d * hitpos, collision_info_struct *asteroid_hit_info=NULL, vec3d* hitnormal=NULL );
|
||||
void asteroid_hit( object *pasteroid_objp, object *other_objp, vec3d *hitpos, float damage );
|
||||
int asteroid_count();
|
||||
int asteroid_collide_objnum(object *asteroid_objp);
|
||||
float asteroid_time_to_impact(object *asteroid_objp);
|
||||
void asteroid_show_brackets();
|
||||
void asteroid_target_closest_danger();
|
||||
|
||||
// need to extern for multiplayer
|
||||
void asteroid_sub_create(object *parent_objp, int asteroid_type, vec3d *relvec);
|
||||
|
||||
void asteroid_frame();
|
||||
|
||||
#endif // __ASTEROID_H__
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,161 +0,0 @@
|
||||
// Autopilot.h
|
||||
// Derek Meek
|
||||
// 4-30-2004
|
||||
|
||||
|
||||
|
||||
#if !defined(_AUTOPILOT_H_)
|
||||
#define _AUTOPILOT_H_
|
||||
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "object/object.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
// milliseconds between updates
|
||||
#define NPS_TICKRATE 125
|
||||
|
||||
#define MAX_NAVPOINTS 8
|
||||
|
||||
#define NP_WAYPOINT 0x0001 // Nav Point is bound to the position of a single node of a waypoint path
|
||||
#define NP_SHIP 0x0002 // Nav Point is bound to the position of a certain ship
|
||||
#define NP_HIDDEN 0x0004 // Nav Point doesn't show on map and isn't selectable
|
||||
#define NP_NOACCESS 0x0008 // Nav Point isn't selectable
|
||||
#define NP_VISITED 0x0100 // Whether we've been within 1,000 meters of this waypoint
|
||||
|
||||
#define NP_NOSELECT ( NP_HIDDEN | NP_NOACCESS )
|
||||
#define NP_VALIDTYPE ( NP_WAYPOINT | NP_SHIP )
|
||||
|
||||
class NavPoint
|
||||
{
|
||||
public:
|
||||
char m_NavName[32];
|
||||
int flags;
|
||||
|
||||
void *target_obj;
|
||||
int waypoint_num; //only used when flags & NP_WAYPOINT
|
||||
|
||||
vec3d *GetPosition();
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_NavName[0] = 0;
|
||||
flags = 0;
|
||||
|
||||
target_obj = NULL;
|
||||
waypoint_num = -1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#define NP_MSG_FAIL_NOSEL 0
|
||||
#define NP_MSG_FAIL_GLIDING 1
|
||||
#define NP_MSG_FAIL_TOCLOSE 2
|
||||
#define NP_MSG_FAIL_HOSTILES 3
|
||||
#define NP_MSG_MISC_LINKED 4
|
||||
#define NP_MSG_FAIL_HAZARD 5
|
||||
#define NP_MSG_FAIL_SUPPORT_PRESENT 6
|
||||
#define NP_MSG_FAIL_SUPPORT_WORKING 7
|
||||
#define NP_NUM_MESSAGES 8
|
||||
|
||||
struct NavMessage
|
||||
{
|
||||
char message[256];
|
||||
char filename[256]; // can be ""
|
||||
};
|
||||
|
||||
extern bool AutoPilotEngaged;
|
||||
extern int CurrentNav;
|
||||
extern NavPoint Navs[MAX_NAVPOINTS];
|
||||
extern NavMessage NavMsgs[NP_NUM_MESSAGES];
|
||||
extern int LockAPConv;
|
||||
extern SCP_map<int,int> autopilot_wings;
|
||||
|
||||
// Cycles through the NavPoint List
|
||||
bool Sel_NextNav();
|
||||
|
||||
|
||||
// Tell us if autopilot is allowed
|
||||
// This needs:
|
||||
// * Nav point selected
|
||||
// * No enemies within AutopilotMinEnemyDistance meters
|
||||
// * No asteroids within AutopilotMinAsteroidDistance meters
|
||||
// * Destination > 1,000 meters away
|
||||
// * Support ship not present or is actively leaving
|
||||
bool CanAutopilot(vec3d targetPos, bool send_msg=false);
|
||||
|
||||
// Check if autopilot is allowed at player's current position
|
||||
// See CanAutopilot(vec3d, bool) for more information
|
||||
inline bool CanAutopilot(bool send_msg=false) { return CanAutopilot(Player_obj->pos, send_msg); }
|
||||
|
||||
// Engages autopilot
|
||||
// This does:
|
||||
// * Checks if Autopilot is allowed. See CanAutopilot() for conditions.
|
||||
// * Control switched from player to AI
|
||||
// * Time compression to 32x
|
||||
// * Tell AI to fly to targeted Nav Point (for all nav-status wings/ships)
|
||||
// * Sets max waypoint speed to the best-speed of the slowest ship tagged
|
||||
// Returns false if autopilot cannot be started. True otherwise.
|
||||
bool StartAutopilot();
|
||||
|
||||
// Disengages autopilot
|
||||
// this does:
|
||||
// * Time compression to 1x
|
||||
// * Delete AI nav goal
|
||||
// * Control switched from AI to player
|
||||
void EndAutoPilot();
|
||||
|
||||
|
||||
// Checks for changes every NPS_TICKRATE milliseconds
|
||||
// Checks:
|
||||
// * if we've gotten close enough to a nav point for it to be counted as "Visited"
|
||||
// * If we're current AutoNavigating it checks if we need to autodisengage
|
||||
void NavSystem_Do();
|
||||
|
||||
|
||||
// Inits the Nav System
|
||||
void NavSystem_Init();
|
||||
|
||||
// parse autopilot.tbl
|
||||
void parse_autopilot_table(const char *filename);
|
||||
|
||||
// Finds a Nav point by name
|
||||
int FindNav(char *Nav);
|
||||
|
||||
// Selects a Nav point by name
|
||||
void SelectNav(char *Nav);
|
||||
|
||||
// Deselects any navpoint selected.
|
||||
void DeselectNav();
|
||||
|
||||
// Removes a Nav
|
||||
bool DelNavPoint(char *Nav);
|
||||
bool DelNavPoint(int nav);
|
||||
|
||||
// adds a Nav
|
||||
bool AddNav_Ship(char *Nav, char *TargetName, int flags);
|
||||
bool AddNav_Waypoint(char *Nav, char *WP_Path, int node, int flags);
|
||||
|
||||
// Sexp Accessors
|
||||
bool Nav_Set_Flag(char *Nav, int flag);
|
||||
bool Nav_UnSet_Flag(char *Nav, int flag);
|
||||
|
||||
bool Nav_Set_Hidden(char *Nav);
|
||||
bool Nav_Set_NoAccess(char *Nav);
|
||||
bool Nav_Set_Visited(char *Nav);
|
||||
|
||||
bool Nav_UnSet_Hidden(char *Nav);
|
||||
bool Nav_UnSet_NoAccess(char *Nav);
|
||||
bool Nav_UnSet_Visited(char *Nav);
|
||||
|
||||
// Useful functions
|
||||
unsigned int DistanceTo(char *nav);
|
||||
unsigned int DistanceTo(int nav);
|
||||
|
||||
bool IsVisited(char *nav);
|
||||
bool IsVisited(int nav);
|
||||
|
||||
void send_autopilot_msg(char *msg, char *snd=NULL);
|
||||
void send_autopilot_msgID(int msgid);
|
||||
#endif
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file bm_examples.cpp
|
||||
* This file contains example code for using bmpman.
|
||||
*/
|
||||
|
||||
#include "bmpman/bmpman.h"
|
||||
#include "graphics/2d.h"
|
||||
|
||||
void bm_create_example() {
|
||||
static int test_inited = 0;
|
||||
static int test_bmp;
|
||||
static uint test_bmp_data[128 * 64];
|
||||
|
||||
if (!test_inited) {
|
||||
test_inited = 1;
|
||||
// Create the new bitmap and fill in its data.
|
||||
// When you're done with it completely, call
|
||||
// bm_release to free up the bitmap handle
|
||||
test_bmp = bm_create(32, 128, 64, test_bmp_data);
|
||||
int i, j;
|
||||
for (i = 0; i < 64; i++) {
|
||||
for (j = 0; j < 64; j++) {
|
||||
uint r = i * 4;
|
||||
test_bmp_data[j + i * 128] = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// page out the data, so that the next bm_lock will convert the new data to
|
||||
// the correct bpp
|
||||
bm_unload(test_bmp);
|
||||
|
||||
// put in new data
|
||||
int x, y;
|
||||
gr_reset_clip();
|
||||
for (y = 0; y < 64; y++) {
|
||||
for (x = 0; x < 128; x++) {
|
||||
test_bmp_data[y * 128 + x] = 15;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the bitmap, the upper left corner is the origin (0, 0)
|
||||
gr_set_bitmap(test_bmp);
|
||||
gr_bitmap(0, 0);
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
#ifndef __BM_INTERNAL_H__
|
||||
#define __BM_INTERNAL_H__
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file bm_internal.h
|
||||
* These are functions and types used by bmpman and a few others.
|
||||
*
|
||||
* @details It is a "protected" header that requires BMPMAN_INTERNAL to be defined before it can be included. This is to
|
||||
* provide a small measure of safety since this functions can cause problems if not used correctly
|
||||
*/
|
||||
|
||||
#ifndef BMPMAN_INTERNAL
|
||||
#error The file header "bmpman/bm_internal.h" is protected. Make sure you know what you are doing!
|
||||
#endif
|
||||
|
||||
#include "bmpman/bmpman.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
/**
|
||||
* @brief Container class for graphics API specific bitmap data
|
||||
*/
|
||||
class gr_bitmap_info {
|
||||
public:
|
||||
virtual ~gr_bitmap_info() = 0;
|
||||
};
|
||||
|
||||
union bm_extra_info {
|
||||
struct {
|
||||
// Stuff needed for animations
|
||||
int first_frame; //!< used for animations -- points to index of first frame
|
||||
int num_frames; //!< used for animations -- number of frames in the animation
|
||||
int keyframe; //!< used for animations -- keyframe info
|
||||
float total_time; //!< used for animations -- total animation time (not always derived from num_frames/fps)
|
||||
ubyte fps; //!< used for animations -- frames per second
|
||||
bool is_array; //!< Flag for if all frames of an animation have the same size which means that it can be put into a texture array
|
||||
|
||||
struct {
|
||||
// stuff for static animations
|
||||
BM_TYPE type; //!< type for individual images
|
||||
char filename[MAX_FILENAME_LEN]; //!< filename for individual images
|
||||
} eff;
|
||||
struct {
|
||||
bool is_apng; //!< Is this animation an APNG?
|
||||
float frame_delay; //!< cumulative frame delay
|
||||
} apng;
|
||||
} ani;
|
||||
|
||||
struct {
|
||||
// Stuff needed for user bitmaps
|
||||
void* data; //!< For user bitmaps, this is where the data comes from
|
||||
ubyte bpp; //!< For user bitmaps, this is what format the data is
|
||||
ubyte flags; //!< For user bitmaps, Flags passed to bm_create
|
||||
} user;
|
||||
};
|
||||
|
||||
struct bitmap_entry {
|
||||
// identification
|
||||
char filename[MAX_FILENAME_LEN]; //!< filename for this bitmap
|
||||
|
||||
uint signature; //!< a unique signature identifying the data
|
||||
int handle; //!< Handle = id*MAX_BITMAPS + bitmapnum
|
||||
|
||||
BM_TYPE type; //!< PCX, USER, ANI, etc
|
||||
BM_TYPE comp_type; //!< What sort of compressed type, BM_TYPE_NONE if not compressed
|
||||
signed char ref_count; //!< Number of locks on bitmap. Can't unload unless ref_count is 0.
|
||||
|
||||
int dir_type; //!< which directory this was loaded from (to skip other locations with same name)
|
||||
|
||||
// compressed bitmap stuff (.dds) - RT please take a look at this and tell me if we really need it
|
||||
size_t mem_taken; //!< How much memory does this bitmap use? - UnknownPlayer
|
||||
int num_mipmaps; //!< number of mipmap levels, we need to read all of them
|
||||
|
||||
// Stuff to keep track of usage
|
||||
ubyte preloaded; //!< If set, then this was loaded from the lst file
|
||||
int preload_count; //!< how many times this gets used in game, for unlocking
|
||||
ubyte used_flags; //!< What flags it was accessed thru
|
||||
int load_count;
|
||||
|
||||
bitmap bm; //!< Bitmap info
|
||||
|
||||
bm_extra_info info; //!< Data for animations and user bitmaps
|
||||
|
||||
#ifdef BMPMAN_NDEBUG
|
||||
// bookeeping
|
||||
ubyte used_last_frame; // If set, then it was used last frame
|
||||
ubyte used_this_frame; // If set, then it was used this frame
|
||||
size_t data_size; // How much data this bitmap uses
|
||||
int used_count; // How many times it was accessed
|
||||
#endif
|
||||
};
|
||||
|
||||
struct bitmap_slot {
|
||||
bitmap_entry entry;
|
||||
|
||||
gr_bitmap_info* gr_info = nullptr;
|
||||
};
|
||||
|
||||
// image specific lock functions
|
||||
void bm_lock_ani( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_dds( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_png( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_apng( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_jpg( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_pcx( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_tga( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
|
||||
void bm_lock_user( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags );
|
||||
|
||||
const size_t BM_BLOCK_SIZE = 4096;
|
||||
|
||||
extern SCP_vector<std::array<bitmap_slot, BM_BLOCK_SIZE>> bm_blocks;
|
||||
|
||||
bitmap_slot* bm_get_slot(int handle, bool separate_ani_frames = true);
|
||||
|
||||
inline bitmap_entry* bm_get_entry(int handle, bool separate_ani_frames = true) {
|
||||
return &bm_get_slot(handle, separate_ani_frames)->entry;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* bm_get_gr_info(int handle, bool separate_ani_frames = true) {
|
||||
return static_cast<T*>(bm_get_slot(handle, separate_ani_frames)->gr_info);
|
||||
}
|
||||
|
||||
#endif // __BM_INTERNAL_H__
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,675 +0,0 @@
|
||||
#ifndef _BMPMAN_H
|
||||
#define _BMPMAN_H
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file bmpman.h
|
||||
* Header file for the bitmap manager (bmpman)
|
||||
*/
|
||||
|
||||
/**
|
||||
* @example bm_examples.cpp
|
||||
* @brief This containes examples of bmpman usage
|
||||
*/
|
||||
|
||||
#include "cfile/cfile.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define BMPMAN_NDEBUG //!< Enables BMPMAN debugging code
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup BMPMAN_CONSTANTS Macro constants used in/with bmpman.h
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
// Flag positions for bitmap.flags
|
||||
// ***** NOTE: bitmap.flags is an 8-bit value, no more BMP_TEX_* flags can be added unless the type is changed!! ******
|
||||
#define BMP_AABITMAP (1<<0) //!< antialiased bitmap
|
||||
#define BMP_TEX_XPARENT (1<<1) //!< transparent texture
|
||||
#define BMP_TEX_OTHER (1<<2) //!< so we can identify all "normal" textures
|
||||
#define BMP_TEX_DXT1 (1<<3) //!< dxt1 compressed 8r8g8b1a (24bit)
|
||||
#define BMP_TEX_DXT3 (1<<4) //!< dxt3 compressed 8r8g8b4a (32bit)
|
||||
#define BMP_TEX_DXT5 (1<<5) //!< dxt5 compressed 8r8g8b8a (32bit)
|
||||
#define BMP_TEX_CUBEMAP (1<<6) //!< a texture made for cubic environment map
|
||||
#define BMP_MASK_BITMAP (1<<7) //!< a bitmap that will be used for masking mouse interaction. Typically not used in render operations
|
||||
|
||||
// Combined flags
|
||||
#define BMP_TEX_COMP ( BMP_TEX_DXT1 | BMP_TEX_DXT3 | BMP_TEX_DXT5 ) //!< Compressed textures
|
||||
#define BMP_TEX_NONCOMP ( BMP_TEX_XPARENT | BMP_TEX_OTHER ) //!< Non-compressed textures
|
||||
#define BMP_TEX_ANY ( BMP_TEX_COMP | BMP_TEX_NONCOMP ) //!< Any texture
|
||||
|
||||
// Flag positions for bitmap.type
|
||||
#define BMP_FLAG_RENDER_TARGET_STATIC (1<<0) //!< Texture is a static type
|
||||
#define BMP_FLAG_RENDER_TARGET_DYNAMIC (1<<1) //!< Texture is a dynamic type (animation)
|
||||
#define BMP_FLAG_CUBEMAP (1<<2) //!< Texture is a cubemap
|
||||
|
||||
// Bitmap types
|
||||
enum BM_TYPE
|
||||
{
|
||||
BM_TYPE_NONE = 0, //!< No type
|
||||
BM_TYPE_USER, //!< in-memory
|
||||
BM_TYPE_PCX, //!< PCX
|
||||
BM_TYPE_TGA, //!< 16 or 32 bit targa
|
||||
BM_TYPE_DDS, //!< generic identifier for DDS
|
||||
BM_TYPE_PNG, //!< PNG
|
||||
BM_TYPE_JPG, //!< 32 bit jpeg
|
||||
BM_TYPE_ANI, //!< in-house ANI format
|
||||
BM_TYPE_EFF, //!< specifies any type of animated image, the EFF itself is just text
|
||||
|
||||
// special types
|
||||
BM_TYPE_RENDER_TARGET_STATIC, //!< 24/32 bit setup internally as a static render target
|
||||
BM_TYPE_RENDER_TARGET_DYNAMIC, //!< 24/32 bit setup internally as a dynamic render target
|
||||
|
||||
// Compressed types (bitmap.c_type)
|
||||
BM_TYPE_DXT1, //!< 24 bit with switchable alpha
|
||||
BM_TYPE_DXT3, //!< 32 bit with 4 bit alpha
|
||||
BM_TYPE_DXT5, //!< 32 bit with 8 bit alpha
|
||||
BM_TYPE_CUBEMAP_DDS, //!< generic DDS cubemap (uncompressed cubemap surface)
|
||||
BM_TYPE_CUBEMAP_DXT1, //!< 24-bit cubemap (compressed cubemap surface)
|
||||
BM_TYPE_CUBEMAP_DXT3, //!< 32-bit cubemap (compressed cubemap surface)
|
||||
BM_TYPE_CUBEMAP_DXT5 //!< 32-bit cubemap (compressed cubemap surface)
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
struct bitmap
|
||||
{
|
||||
short w; //!< Width, in number of pixels
|
||||
short h; //!< Height, in number of pixels
|
||||
short rowsize; //!< What you need to add to go to next row
|
||||
int bpp; //!< Requested bitdepth of each pixel. ( 7, 8, 15, 16, 24, 32)
|
||||
int true_bpp; //!< The image's actual bitdepth
|
||||
ubyte flags; //!< Various texture type flags. @see BMPMAN_CONSTANTS
|
||||
ptr_u data; //!< Pointer to data, or maybe offset into VRAM.
|
||||
ubyte *palette; /**< @brief Pointer to this bitmap's palette (if it has one).
|
||||
* @details If BMP_NO_PALETTE_MAP flag is cleared, this palette just points to the screen palette. (gr_palette)
|
||||
*/
|
||||
};
|
||||
|
||||
// Forward definition for the graphics API
|
||||
struct bitmap_entry;
|
||||
struct bitmap_slot;
|
||||
|
||||
extern size_t bm_texture_ram; //!< how many bytes of textures are used.
|
||||
|
||||
extern int Bm_paging; //!< Bool type that indicates if BMPMAN is currently paging.
|
||||
|
||||
extern const BM_TYPE bm_type_list[]; //!< List of valid bitmap types
|
||||
extern const char *bm_ext_list[]; //!< List of extensions for those types
|
||||
extern const int BM_NUM_TYPES; //!< Calculated number of bitmap types
|
||||
extern const BM_TYPE bm_ani_type_list[]; //!< List of valid bitmap animation types
|
||||
extern const char *bm_ani_ext_list[]; //!< List of extensions for those types
|
||||
extern const int BM_ANI_NUM_TYPES; //!< Calculated number of bitmap animation types
|
||||
|
||||
extern int ENVMAP; //!< References a map that is for environment mapping -Bobboau
|
||||
|
||||
/**
|
||||
* @brief Initilizes the bitmap manager
|
||||
*/
|
||||
void bm_init();
|
||||
|
||||
/**
|
||||
* @brief Closes the bitmap manager, freeing any allocated memory used by bitmaps. Is called at program close.
|
||||
*/
|
||||
void bm_close();
|
||||
|
||||
#define BMP_FLAG_RENDER_TARGET_STATIC (1<<0)
|
||||
#define BMP_FLAG_RENDER_TARGET_DYNAMIC (1<<1)
|
||||
#define BMP_FLAG_CUBEMAP (1<<2)
|
||||
#define BMP_FLAG_RENDER_TARGET_MIPMAP (1<<3)
|
||||
|
||||
/**
|
||||
* @brief Allocates memory for the given handle.
|
||||
*
|
||||
* @returns A pointer to the allocated vm if successful,
|
||||
* @returns Null, if unsuccessful
|
||||
*
|
||||
* @note z64 - This function looks fishy. Not only is handle not used in release builds, but bm_bitmaps[handle].size
|
||||
* and bm_texture_size aren't modified unless this is a debug build
|
||||
*/
|
||||
void *bm_malloc(int handle, size_t size);
|
||||
|
||||
/**
|
||||
* @brief (DEBUG) Similar to bm_malloc, but only updates how much memory is used
|
||||
*
|
||||
* @note z64 - Also fishy (see bm_malloc)
|
||||
*/
|
||||
void bm_update_memory_used(int n, size_t size);
|
||||
|
||||
class bitmap_lookup {
|
||||
ubyte *Bitmap_data;
|
||||
|
||||
int Width;
|
||||
int Height;
|
||||
int Num_channels;
|
||||
|
||||
float map_texture_address(float address);
|
||||
public:
|
||||
bitmap_lookup(int bitmap_num);
|
||||
~bitmap_lookup();
|
||||
|
||||
bool valid();
|
||||
|
||||
float get_channel_alpha(float u, float v);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Loads a bitmap so we can draw with it later.
|
||||
*
|
||||
* @param filename
|
||||
*
|
||||
* @returns The bitmap number if successful, else
|
||||
* @returns a negative value if not
|
||||
*/
|
||||
int bm_load(const char* filename);
|
||||
|
||||
/**
|
||||
* @brief Loads a bitmap so we can draw with it later. (Preferred version)
|
||||
*
|
||||
* @param filename
|
||||
*
|
||||
* @returns The bitmap number if successful, else
|
||||
* @returns a negative value if not
|
||||
*/
|
||||
int bm_load(const SCP_string& filename);
|
||||
|
||||
/**
|
||||
* @brief Reloads a bitmap as a duplicate.
|
||||
*
|
||||
* @details This function basically allows you to load a bitmap which already exists (by filename). This is useful
|
||||
* because in some cases we need to have a bitmap which is locked in screen format _and_ texture format, such as
|
||||
* the pilot pics and squad logos
|
||||
*
|
||||
* @param filename
|
||||
*
|
||||
* @returns The bitmap number if successful, else
|
||||
* @returns a negative value if not
|
||||
*/
|
||||
int bm_load_duplicate(const char *filename);
|
||||
|
||||
/**
|
||||
* Loads a bitmap which exists somewhere in the RAM.
|
||||
*
|
||||
* @param bpp The bitdepth of the bitmap
|
||||
* @param w The width of the bitmap
|
||||
* @param h The height of the bitmap
|
||||
* @param[in] data The bitmap's data glob
|
||||
* @param flags
|
||||
*
|
||||
* @note The used RAM cannot be freed until bm_release is called on the created bitmap
|
||||
*/
|
||||
int bm_create(int bpp, int w, int h, void *data = NULL, int flags = 0);
|
||||
|
||||
/**
|
||||
* @brief Unloads a bitmap's data, but not the bitmap info
|
||||
*
|
||||
* @details The bm number (n) may be reused once this function has been called on it. However, it will have to be paged
|
||||
* in the next time it is locked.
|
||||
|
||||
* @param handle The index number of the bitmap to free
|
||||
* @param clear_render_targets If true, release a render target
|
||||
* @param nodebug If true, exclude certain debug messages
|
||||
*
|
||||
* @returns 0 if not successful,
|
||||
* @returns 1 if successful
|
||||
*/
|
||||
int bm_unload(int handle, int clear_render_targets = 0, bool nodebug = false);
|
||||
|
||||
/**
|
||||
* @brief Quickly unloads a bitmap's data, ignoring the load_count
|
||||
*
|
||||
* @details Similar to bm_unload(), except that it can be safely used to free data without worrying about load_count.
|
||||
* It's safe to use in relation to bm_release() and in gr_*_texture functions
|
||||
*
|
||||
* @param handle The bm number of the bitmap to free
|
||||
* @param clear_render_targets If true, release a render target
|
||||
*
|
||||
* @note bm_free_data_fast() is used here and NOT bm_free_data()
|
||||
*/
|
||||
int bm_unload_fast(int handle, int clear_render_targets = 0);
|
||||
|
||||
/**
|
||||
* @brief Frees both a bitmap's data and it's associated slot.
|
||||
*
|
||||
* @details Once called, the bm number 'n' cannot be used until bm_load or bm_create is re-inits the slot.
|
||||
*
|
||||
* @param handle The index number of the bitmap to release
|
||||
* @param clear_render_targets If nonzero, also release render targets
|
||||
*
|
||||
* @returns 1 on success,
|
||||
* @returns 0 otherwise
|
||||
*
|
||||
* @note If the passed handle is that of an ANI, it frees EVERY frame. Be sure to only pass the handle of the first frame!
|
||||
*
|
||||
* @todo upgrade return type and clear_render_targets type to bools
|
||||
*/
|
||||
int bm_release(int handle, int clear_render_targets = 0);
|
||||
|
||||
/**
|
||||
* @brief Loads a bitmap sequance so we can draw with it.
|
||||
*
|
||||
* @param[in] filename
|
||||
* @param[out] nframes If non-null, set to the number of frames the animation has
|
||||
* @param[out] fps If non-null, set to the fps of this animation
|
||||
* @param[out] keyframe if non null, set to the keyframe index of this animation
|
||||
* @param[in] can_drop_frames If set, allows dropped frames
|
||||
* @param[in] dir_type Directory type
|
||||
*
|
||||
* @returns The bm number of the first bitmap in the sequence if successful, or
|
||||
* @returns A negative value if unsuccessful
|
||||
*/
|
||||
int bm_load_animation(const char *filename, int *nframes = nullptr, int *fps = nullptr, int *keyframe = nullptr, float *total_time = nullptr, bool can_drop_frames = 0, int dir_type = CF_TYPE_ANY);
|
||||
|
||||
/**
|
||||
* @brief Loads either animation (bm_load_animation) or still image (bm_load)
|
||||
*
|
||||
* @param[in] filename
|
||||
* @param[out] nframes If non-null and loading was successful, set to the number of frames the animation has
|
||||
* @param[out] fps If non-null and loading was successful, set to the fps of this animation
|
||||
* @param[out] keyframe if non null and loading was successful, set to the keyframe index of this animation
|
||||
* @param[in] can_drop_frames
|
||||
* @param[in] dir_type
|
||||
*
|
||||
* @returns The bm number of the first bitmap in the sequence if successful, or
|
||||
* @returns A negative value if unsuccessful
|
||||
*/
|
||||
int bm_load_either(const char *filename, int *nframes = NULL, int *fps = NULL, int *keyframe = NULL, bool can_drop_frames = false, int dir_type = CF_TYPE_ANY);
|
||||
|
||||
/**
|
||||
* @brief Locks down the bitmap indexed by bitmapnum.
|
||||
*
|
||||
* @details Also converts the bitmap to the appropriate format specified by bpp and flags. Only lock a bitmap when you
|
||||
* need it!
|
||||
*
|
||||
* @param handle The number indexing the desired bitmap
|
||||
* @param bpp The desired bpp of the bitmep
|
||||
* @param flags The desired bitmap format
|
||||
* @param nodebug
|
||||
|
||||
* @returns A pointer to the bitmap that's valid until bm_unlock is called if successful, or
|
||||
* @returns NULL if unsuccessful
|
||||
*/
|
||||
bitmap* bm_lock(int handle, int bpp, ubyte flags, bool nodebug = false);
|
||||
|
||||
/**
|
||||
* @brief Returns the image type of the given bitmap handle
|
||||
*/
|
||||
BM_TYPE bm_get_type(int handle);
|
||||
|
||||
/**
|
||||
* @brief Unlocks a bitmap
|
||||
*
|
||||
* @details Decrements the ref_count member of the bitmap_entry struct, A bitmap can only be unloaded when the
|
||||
* ref_count is 0
|
||||
*/
|
||||
void bm_unlock(int handle);
|
||||
|
||||
/**
|
||||
* @brief Checks if the bitmap indexed by handle is valid
|
||||
*
|
||||
* @details Some early known false or out of range handles (such as negative) are checked within
|
||||
* an initial routine pass, followed by a more thorough check routine to ensure the
|
||||
* series of bitmaps within the bm_bitmaps[] structure have not become invalid.
|
||||
*
|
||||
* @returns Nonzero if valid, else
|
||||
* @returns Zero otherwise
|
||||
*
|
||||
* @todo z64 - Returned value is essentially a bool type, need to check all caller functions to see if it can safely
|
||||
* be updated to reflect this
|
||||
*/
|
||||
int bm_is_valid(int handle);
|
||||
|
||||
/**
|
||||
* @brief Gets info on the bitmap indexed by handle.
|
||||
*
|
||||
* @param[out] w If non-null, gets the width
|
||||
* @param[out] h If non-null, gets the heigth
|
||||
* @param[out] flags If non-null, gets the flags
|
||||
* @param[out] nframs If non-null, gets the nframes
|
||||
* @param[out] fps If non-null, gets the fps
|
||||
*
|
||||
* @returns The handle on success, or
|
||||
* @returns The handle to the first frame on success, or
|
||||
* @returns -1 on failure
|
||||
*/
|
||||
int bm_get_info(int handle, int *w = NULL, int * h = NULL, ubyte * flags = NULL, int *nframes = NULL, int *fps = NULL);
|
||||
|
||||
/**
|
||||
* @brief Gets the filename of the bitmap indexed by handle
|
||||
*
|
||||
* @param[out] filename The filename of the bitmap, if successful. Is set to an empty string if unseccessful
|
||||
*
|
||||
* @todo z64 - maybe deprecate this in favor of an SCP_string version
|
||||
*/
|
||||
void bm_get_filename(int bitmapnum, char *filename);
|
||||
|
||||
/**
|
||||
* @brief Gets the filename of the bitmap indexed by handle, which must exist.
|
||||
*
|
||||
* @details If the bitmap does not exist (i.e. the handle is invalid), then an Assertion halts program execution.
|
||||
*
|
||||
* @returns A const char* to the filename of the bitmap
|
||||
*
|
||||
* @todo z64 - maybe deprecate this in favor of an SCP_string version.
|
||||
* @todo z64 - maybe combine this with the other bm_get_filename function like so:
|
||||
* void bm_get_filename(int handle, SCP_string *filename, bool must_exist = false);
|
||||
*/
|
||||
const char *bm_get_filename(int handle);
|
||||
|
||||
/**
|
||||
* @brief Unloads all used bitmaps, should only ever be called by game_shutdown()
|
||||
*
|
||||
* @todo Maybe move this declaration into bmpman.cpp and then extern this function within game_shutdown() to
|
||||
* ensure it only ever gets called there.
|
||||
*/
|
||||
void bm_unload_all();
|
||||
|
||||
/**
|
||||
* @brief Gets the palette for a given bitmap indexed by handle, and optionally the filename
|
||||
*
|
||||
* @param[out] pal Is set to reference the bitmap's palette
|
||||
* @param[out] name (optional) Is set to the bitmap's filename
|
||||
*
|
||||
* @todo Maybe get rid of the optional filename and have the callers call bm_get_filename. Less efficient, however.
|
||||
*/
|
||||
void bm_get_palette(int handle, ubyte *pal, char *name);
|
||||
|
||||
/**
|
||||
* @brief (DEBUG) Gets memory size, in bytes, of the locked bitmaps
|
||||
*
|
||||
* @details Both params are non-optional, and must be non-null. There's currently no safety checks on either.
|
||||
*
|
||||
* @param ntotal[out] Memory size, in bytes, of the locked bitmaps
|
||||
* @param nnew[out] Memory size, in bytes, of the bitmaps that were locked since the last frame
|
||||
*
|
||||
* @note This is a debug function, and is undefined within release builds
|
||||
*/
|
||||
void bm_get_frame_usage(int *ntotal, int *nnew);
|
||||
|
||||
/**
|
||||
* @brief Reloads an existing bmpman slot with different bitmap
|
||||
*
|
||||
* @param[in] filename The filename of the image to load
|
||||
*
|
||||
* @returns The bitmap handle on success, or
|
||||
* @returns A negative value on failure
|
||||
*
|
||||
* @note This should only be used if you are certain the new picture is the same type, has same dimensions, etc.
|
||||
*/
|
||||
int bm_reload(int bitmap_handle, const char* filename);
|
||||
|
||||
/**
|
||||
* @brief Tells bmpman to start keeping track of what bitmaps are used where
|
||||
*/
|
||||
void bm_page_in_start();
|
||||
|
||||
/**
|
||||
* @brief Tells bmpman to stop paging (?)
|
||||
*/
|
||||
void bm_page_in_stop();
|
||||
|
||||
// Paging code in a library should call these functions
|
||||
// in its page in function.
|
||||
|
||||
/**
|
||||
* @brief Marks a texture as being used for this level
|
||||
*
|
||||
* @param[in] num_frames If specified, assumes this is an animated texture
|
||||
*/
|
||||
void bm_page_in_texture(int bitmapnum, int num_frames = 0);
|
||||
|
||||
/**
|
||||
* @brief Marks a textures as being used for level and is transparant
|
||||
*
|
||||
* @param[in] num_frames If specified, assumes this is an animated texture
|
||||
*/
|
||||
void bm_page_in_xparent_texture(int bitmapnum, int num_frames = 1);
|
||||
|
||||
/**
|
||||
* @brief Marks a texture as being used for this level, and is anti-aliased
|
||||
*
|
||||
* @param[in] num_frames If specified, assumes this is an animated texture
|
||||
*/
|
||||
void bm_page_in_aabitmap(int bitmapnum, int num_frames = 1);
|
||||
|
||||
/**
|
||||
* @brief Sets BMPMAN's memory mode
|
||||
*
|
||||
* @details 0 = High memory;
|
||||
* 1 = Low memory (loads every other frame of ani's);
|
||||
* 2 = Debug low memory (only use first frame of each ani)
|
||||
*
|
||||
* @todo This should use an enum, or instead allow an arbitrary number to drop frames (like 1/2, 1/3, etc.)
|
||||
*/
|
||||
void bm_set_low_mem(int mode);
|
||||
|
||||
/**
|
||||
* @brief Sets bm_set_components and bm_get_components to reference screen format functions
|
||||
*/
|
||||
void BM_SELECT_SCREEN_FORMAT();
|
||||
|
||||
/**
|
||||
* @brief Sets bm_set_components and bm_get_components to reference texture format functions
|
||||
*/
|
||||
void BM_SELECT_TEX_FORMAT();
|
||||
|
||||
/**
|
||||
* @brief Sets bm_set_components and bm_get_components to reference texture format functions (with alpha)
|
||||
*/
|
||||
void BM_SELECT_ALPHA_TEX_FORMAT();
|
||||
|
||||
/**
|
||||
* @brief Functional pointer that references any of the bm_set_components functions.
|
||||
*
|
||||
* @details The bm_set_components functions packs the RGBA values into the ubyte array referenced by pixel, whose
|
||||
* format differs according to its bpp value and presence of an alpha channel. The RGBA values are scaled accordingly.
|
||||
*
|
||||
* @param[out] pixel The pixel to set
|
||||
* @param[in] r Red value (may not be NULL)
|
||||
* @param[in] g Green value (may not be NULL)
|
||||
* @param[in] b Blue value (may not be NULL)
|
||||
* @param[in] a Alpha value (currently ignored)
|
||||
*
|
||||
* @note z64 - These functions were made predating the introduction of C++ classes, and are basically the equivalent
|
||||
* of Pixel::set(ubyte *r, ubyte *b, ubyte *g). The original comment mentions that any of the rgba params may be
|
||||
* NULL, but this is by far _NOT_ the case, as a NULL value will cause undefined behavior (really really bad chroma
|
||||
* corruption)
|
||||
*
|
||||
* @note These functions assume the incoming bitdepth will always be >= to the outgoing bitdepth of the pixel. Should
|
||||
* the incoming bitdepth be lower, the outgoing values will appear darker than they should be
|
||||
*/
|
||||
extern void(*bm_set_components)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
/**
|
||||
* @brief Sets the 16bpp screen pixel to the specified RGBA value
|
||||
*
|
||||
* @see bm_set_components
|
||||
*/
|
||||
void bm_set_components_argb_16_screen(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
/**
|
||||
* @brief Sets the 16bpp texture pixel to the specified RGBA value
|
||||
*
|
||||
* @see bm_set_components
|
||||
*/
|
||||
void bm_set_components_argb_16_tex(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
/**
|
||||
* @brief Sets the 32bpp texture pixel to the specified RGBA value
|
||||
*
|
||||
* @see bm_set_components
|
||||
*/
|
||||
void bm_set_components_argb_32_tex(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
/**
|
||||
* @brief Gets the RGBA components of a pixel according to the selected mode
|
||||
*
|
||||
* @see BM_SELECT_SCREEN_FORMAT() BM_SELECT_TEX_FORMAT() BM_SELECT_ALPHA_TEX_FORMAT()
|
||||
*/
|
||||
void bm_get_components(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
extern int ENVMAP; //this holds a reference to a map that is for environment mapping -Bobboau
|
||||
|
||||
/**
|
||||
* @brief Returns the compression type of the bitmap indexed by handle
|
||||
*/
|
||||
int bm_is_compressed(int handle);
|
||||
|
||||
/**
|
||||
* @brief Gets the correct TCACHE_TYPE for compressed graphics (uncompressed are assumed TCACHE_TYPE_NORMAL)
|
||||
*/
|
||||
int bm_get_tcache_type(int handle);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets the number of mipmaps of the indexed texture
|
||||
*/
|
||||
int bm_get_num_mipmaps(int handle);
|
||||
|
||||
/**
|
||||
* @brief Checks to see if the indexed bitmap has an alpha channel
|
||||
*
|
||||
* @note Currently just checks if the bitmap is 32bpp and is not a .PCX
|
||||
*/
|
||||
bool bm_has_alpha_channel(int handle);
|
||||
|
||||
/**
|
||||
* @brief (DEBUG) Prints all loaded bitmaps to an outwindow
|
||||
*/
|
||||
void bm_print_bitmaps();
|
||||
|
||||
/**
|
||||
* @brief Creates a render target as close to the desired resolution as possible.
|
||||
*
|
||||
* @returns the handle of an avilable render target if successful, or
|
||||
* @returns -1 if not successful
|
||||
*
|
||||
* @note BM_FLAG_RENDER_TARGET_STATIC are drawn once/infrequently, while BM_FLAG_RENDER_TARGET_DYNAMIC are drawn roughly once every frame
|
||||
*/
|
||||
int bm_make_render_target(int width, int height, int flags);
|
||||
|
||||
/**
|
||||
* @brief Checks to see if the given bitmap indexed by handle is a render target
|
||||
*
|
||||
* @returns The render type (BM_TYPE) if it is a render target, or
|
||||
* @returns 0 if it is not
|
||||
*/
|
||||
int bm_is_render_target(int handle);
|
||||
|
||||
/**
|
||||
* @brief (GR function) Calls gr_bm_set_render target for the given bitmap indexed by handle
|
||||
*
|
||||
* @returns true if successful, or
|
||||
* @returns false if unsuccessful
|
||||
*/
|
||||
bool bm_set_render_target(int handle, int face = -1);
|
||||
|
||||
/**
|
||||
* @brief Loads and parses an .EFF
|
||||
*
|
||||
* @param[in] filename The filename of the .EFF
|
||||
* @param[in] dir_type
|
||||
* @param[out] nframes (optional) If given, is set to the number of frames this .EFF has
|
||||
* @param[out] nfps (optional) If given, is set to the fps of this .EFF
|
||||
* @param[out] key (optional) If given, is set to the keyframe index of this .EFF
|
||||
* @param[out] type (optional) If given, is set to the BM_TYPE of the .EFF
|
||||
*
|
||||
* @returns true If successful
|
||||
* @returns false If not successful
|
||||
*/
|
||||
bool bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int *nfps, int *key, BM_TYPE *type);
|
||||
|
||||
/**
|
||||
* @brief Calculates & returns the current frame of an animation
|
||||
*
|
||||
* @param[in] frame1_handle Handle of the animation
|
||||
* @param[in] elapsed_time Time in seconds since the animation started playing
|
||||
* @param[in] loop (optional) specifies if the animation should loop, default is false which causes animation to hold on the last frame
|
||||
* @param[in] divisor (optional) if greater than zero, elapsed time will be divided by this value i.e. allows "percentage complete" to be used to determine the frame instead of the animations total time derived from fps * frames
|
||||
*
|
||||
* @returns current frame of the animation (range is zero to the number of frames minus one)
|
||||
*/
|
||||
int bm_get_anim_frame(const int frame1_handle, float elapsed_time, const float divisor = 0.0f, const bool loop = false);
|
||||
|
||||
/**
|
||||
* @brief Determines if the given handle could be used in a texture array
|
||||
*
|
||||
* @param handle The handle to query the value for
|
||||
* @return @c true if all frames have the same size, @c false otherwise. Always returns @c true for single images
|
||||
*/
|
||||
bool bm_is_texture_array(const int handle);
|
||||
|
||||
/**
|
||||
* @brief Gets the base frame of the specified animation
|
||||
*
|
||||
* @details The base frame is the frame of the animation that should be used to determine if two animation frames can be
|
||||
* used in the same draw call. Use this if you want to optimize your draw calls to make use of texture arrays.
|
||||
*
|
||||
* @param handle The handle of the animation to check. This may also be a single frame bitmap
|
||||
* @param num_frames Optionally return the number of frames in the animation
|
||||
* @return The bitmap handle of the base frame or -1 on error
|
||||
*/
|
||||
int bm_get_base_frame(const int handle, int* num_frames = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Get the array index of the specified bitmap
|
||||
*
|
||||
* This should be used when passing the array index to the GPU (e.g. when building uniform structs or streaming particle
|
||||
* data)
|
||||
*
|
||||
* @param handle The handle of the bitmap
|
||||
* @return The index into the array
|
||||
*/
|
||||
int bm_get_array_index(const int handle);
|
||||
|
||||
/**
|
||||
* @brief Counts how many slots are used in bm_bitmaps
|
||||
*
|
||||
* This needs to iterate through all the slots in order to determine whether or not they're used, so shouldn't be used frivolously.
|
||||
*
|
||||
* @return The number of used slots
|
||||
*/
|
||||
int bmpman_count_bitmaps();
|
||||
|
||||
/**
|
||||
* @brief Counts how many slots are available to the bmpman system
|
||||
*
|
||||
* Since the number of slots is dynamic now, this should be used for determining the total amount of available slots at
|
||||
* the moment.
|
||||
*
|
||||
* @warning This is entirely for debugging and logging purposes. It should not be used in actual engine code.
|
||||
*
|
||||
* @return The number of available slots
|
||||
*/
|
||||
int bmpman_count_available_slots();
|
||||
|
||||
/**
|
||||
* @brief Checks if the given filename is a valid effect or texture file name
|
||||
*
|
||||
* @note At least one of @c single_frame or @c animation must be true since the result would make no sense otherwise. It
|
||||
* is also valid to set both parmeters to @c true.
|
||||
*
|
||||
* @todo This currently just tries to load the file but could be improved by not actually loading the file in the future.
|
||||
*
|
||||
* @param file The file name to check
|
||||
* @param single_frame If set to @c true then single frames are valid files
|
||||
* @param animation If set to @c true then animations are valid files
|
||||
* @return @c true if the file name is valid, @c false otherwise
|
||||
*/
|
||||
bool bm_validate_filename(const SCP_string& file, bool single_frame, bool animation);
|
||||
|
||||
SDL_Surface* bm_to_sdl_surface(int handle);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,175 +0,0 @@
|
||||
|
||||
#ifndef _CAMERA_H
|
||||
#define _CAMERA_H
|
||||
|
||||
#include "globalincs/globals.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "graphics/2d.h"
|
||||
#include "object/object.h"
|
||||
#include "physics/physics.h" //for avd
|
||||
|
||||
#include <string>
|
||||
|
||||
#define CAM_STATIONARY_FOV (1<<0)
|
||||
#define CAM_STATIONARY_ORI (1<<1)
|
||||
#define CAM_STATIONARY_POS (1<<2)
|
||||
#define CAM_DEFAULT_FLAGS 0
|
||||
|
||||
class camera
|
||||
{
|
||||
protected:
|
||||
char name[NAME_LENGTH];
|
||||
int sig;
|
||||
int flags;
|
||||
|
||||
object_h object_host;
|
||||
int object_host_submodel;
|
||||
|
||||
object_h object_target;
|
||||
int object_target_submodel;
|
||||
|
||||
void (*func_custom_position)(camera *cam, vec3d *pos);
|
||||
void (*func_custom_orientation)(camera *cam, matrix *ori);
|
||||
|
||||
avd_movement fov;
|
||||
avd_movement pos_x;
|
||||
avd_movement pos_y;
|
||||
avd_movement pos_z;
|
||||
avd_movement ori[9];
|
||||
|
||||
//Cache stuff
|
||||
float c_fov;
|
||||
vec3d c_pos;
|
||||
matrix c_ori;
|
||||
public:
|
||||
camera(const char *in_name=NULL, int in_signature=-1);
|
||||
~camera();
|
||||
void clear();
|
||||
void reset();
|
||||
|
||||
//Set
|
||||
void set_name(const char *in_name);
|
||||
|
||||
void set_object_host(object *objp, int n_object_host_submodel = -1);
|
||||
void set_object_target(object *objp, int n_object_target_submodel = -1);
|
||||
|
||||
void set_custom_position_function(void (*n_func_custom_position)(camera *cam, vec3d *pos));
|
||||
void set_custom_orientation_function(void (*n_func_custom_orientation)(camera *cam, matrix *ori));
|
||||
|
||||
void set_fov(float in_fov, float in_fov_time = 0.0f, float in_fov_acceleration_time = 0.0f, float in_deceleration_time = 0.0f);
|
||||
|
||||
void set_position(vec3d *in_position = NULL, float in_translation_time = 0.0f, float in_translation_acceleration_time = 0.0f, float in_translation_deceleration_time = 0.0f, float in_end_velocity = 0.0f);
|
||||
|
||||
void set_rotation(matrix *in_orientation = NULL, float in_rotation_time = 0.0f, float in_rotation_acceleration_time = 0.0f, float in_rotation_deceleration_time = 0.0f);
|
||||
void set_rotation(angles *in_angles, float in_rotation_time = 0.0f, float in_rotation_acceleration_time = 0.0f, float in_rotation_deceleration_time = 0.0f);
|
||||
void set_rotation_facing(vec3d *in_target, float in_rotation_time = 0.0f, float in_rotation_acceleration_time = 0.0f, float in_rotation_deceleration_time = 0.0f);
|
||||
|
||||
//Get
|
||||
const char* get_name() { return name; }
|
||||
int get_signature() {return sig;}
|
||||
object *get_object_host();
|
||||
int get_object_host_submodel();
|
||||
object *get_object_target();
|
||||
int get_object_target_submodel();
|
||||
float get_fov();
|
||||
void get_info(vec3d *position, matrix *orientation);
|
||||
|
||||
//Is
|
||||
bool is_empty(){return sig < 0;}
|
||||
|
||||
//Do
|
||||
void do_frame(float in_frametime);
|
||||
};
|
||||
|
||||
class warp_camera
|
||||
{
|
||||
private:
|
||||
float c_time;
|
||||
float c_damping;
|
||||
|
||||
vec3d c_vel;
|
||||
vec3d c_desired_vel;
|
||||
|
||||
vec3d c_pos;
|
||||
matrix c_ori;
|
||||
public:
|
||||
warp_camera();
|
||||
warp_camera(object *objp);
|
||||
void reset();
|
||||
|
||||
void set_position(vec3d *in_pos);
|
||||
void set_rotation(matrix *in_ori);
|
||||
void set_velocity(vec3d *in_vel, bool instantaneous);
|
||||
|
||||
void do_frame(float in_frametime);
|
||||
|
||||
void get_info(vec3d *position, matrix *orientation);
|
||||
};
|
||||
|
||||
extern warp_camera Warp_camera;
|
||||
|
||||
class subtitle
|
||||
{
|
||||
private:
|
||||
void clone(const subtitle &sub);
|
||||
|
||||
SCP_vector<SCP_string> text_lines;
|
||||
struct { int x; int y; } text_pos;
|
||||
|
||||
float display_time;
|
||||
float fade_time;
|
||||
color text_color;
|
||||
int text_fontnum;
|
||||
|
||||
//Done with set
|
||||
char imageanim[MAX_FILENAME_LEN];
|
||||
int image_id;
|
||||
struct { int x; int y; int w; int h; } image_pos;
|
||||
|
||||
//Time this has been displayed
|
||||
float time_displayed;
|
||||
|
||||
//When to end it
|
||||
float time_displayed_end;
|
||||
|
||||
bool post_shaded;
|
||||
public:
|
||||
subtitle(int in_x_pos, int in_y_pos, const char* in_text = NULL, const char* in_imageanim = NULL,
|
||||
float in_display_time = 0, float in_fade_time = 0.0f, const color *in_text_color = NULL, int in_text_fontnum = -1,
|
||||
bool center_x = false, bool center_y = false, int in_width = 0, int in_height = 0, bool post_shaded=false);
|
||||
~subtitle();
|
||||
|
||||
subtitle(const subtitle &sub) { clone(sub); }
|
||||
subtitle& operator=(const subtitle &sub);
|
||||
|
||||
void do_frame(float frametime);
|
||||
bool is_post_shaded( ) { return post_shaded; }
|
||||
};
|
||||
|
||||
//Some global stuff
|
||||
extern SCP_vector<subtitle> Subtitles;
|
||||
extern float VIEWER_ZOOM_DEFAULT;
|
||||
extern float Sexp_fov;
|
||||
|
||||
//Helpful functions
|
||||
void cam_init();
|
||||
void cam_close();
|
||||
void cam_do_frame(float frametime);
|
||||
camid cam_create(const char *n_name=NULL, vec3d *n_pos=NULL, matrix *n_ori=NULL, object *n_object=NULL, int n_submodel_parent=-1);
|
||||
camid cam_create(const char *n_name, vec3d *n_pos, vec3d *n_norm, object *n_object=NULL, int n_submodel_parent=-1);
|
||||
void cam_delete(camid cid);
|
||||
bool cam_set_camera(camid cid);
|
||||
void cam_reset_camera();
|
||||
camid cam_lookup(const char* name);
|
||||
camid cam_get_camera(uint index);
|
||||
camid cam_get_current();
|
||||
size_t cam_get_num();
|
||||
|
||||
void get_turret_cam_pos(camera *cam, vec3d *pos);
|
||||
void get_turret_cam_orient(camera *cam, matrix *ori);
|
||||
|
||||
void subtitles_close();
|
||||
void subtitles_do_frame(float frametime);
|
||||
void subtitles_do_frame_post_shaded(float frametime);
|
||||
|
||||
#endif // _CAMERA_H
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,488 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef __CFILE_H__
|
||||
#define __CFILE_H__
|
||||
|
||||
|
||||
#include "globalincs/pstypes.h"
|
||||
|
||||
#include <ctime>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
|
||||
#define CF_EOF (-1)
|
||||
|
||||
#define CF_SEEK_SET (0)
|
||||
#define CF_SEEK_CUR (1)
|
||||
#define CF_SEEK_END (2)
|
||||
|
||||
// Opaque file handle
|
||||
struct CFILE;
|
||||
|
||||
// extra info that can be returned when getting a file listing
|
||||
typedef struct {
|
||||
time_t write_time;
|
||||
} file_list_info;
|
||||
|
||||
|
||||
#define CF_MAX_FILENAME_LENGTH 32 // Includes null terminater, so real length is 31
|
||||
#define CF_MAX_PATHNAME_LENGTH 256 // Includes null terminater, so real length is 255
|
||||
|
||||
#define CF_TYPE_ANY -1 // Used to check in any directory
|
||||
|
||||
#define CF_TYPE_INVALID 0
|
||||
#define CF_TYPE_ROOT 1 // Root must be 1!!
|
||||
#define CF_TYPE_DATA 2
|
||||
#define CF_TYPE_MAPS 3
|
||||
#define CF_TYPE_TEXT 4
|
||||
#define CF_TYPE_MODELS 5
|
||||
#define CF_TYPE_TABLES 6
|
||||
#define CF_TYPE_SOUNDS 7
|
||||
#define CF_TYPE_SOUNDS_8B22K 8
|
||||
#define CF_TYPE_SOUNDS_16B11K 9
|
||||
#define CF_TYPE_VOICE 10
|
||||
#define CF_TYPE_VOICE_BRIEFINGS 11
|
||||
#define CF_TYPE_VOICE_CMD_BRIEF 12
|
||||
#define CF_TYPE_VOICE_DEBRIEFINGS 13
|
||||
#define CF_TYPE_VOICE_PERSONAS 14
|
||||
#define CF_TYPE_VOICE_SPECIAL 15
|
||||
#define CF_TYPE_VOICE_TRAINING 16
|
||||
#define CF_TYPE_MUSIC 17
|
||||
#define CF_TYPE_MOVIES 18
|
||||
#define CF_TYPE_INTERFACE 19
|
||||
#define CF_TYPE_FONT 20
|
||||
#define CF_TYPE_EFFECTS 21
|
||||
#define CF_TYPE_HUD 22
|
||||
#define CF_TYPE_PLAYERS 23
|
||||
#define CF_TYPE_PLAYER_IMAGES 24
|
||||
#define CF_TYPE_SQUAD_IMAGES 25
|
||||
#define CF_TYPE_SINGLE_PLAYERS 26
|
||||
#define CF_TYPE_MULTI_PLAYERS 27
|
||||
#define CF_TYPE_CACHE 28
|
||||
#define CF_TYPE_MULTI_CACHE 29
|
||||
#define CF_TYPE_MISSIONS 30
|
||||
#define CF_TYPE_CONFIG 31
|
||||
#define CF_TYPE_DEMOS 32
|
||||
#define CF_TYPE_CBANIMS 33
|
||||
#define CF_TYPE_INTEL_ANIMS 34
|
||||
#define CF_TYPE_SCRIPTS 35
|
||||
#define CF_TYPE_FICTION 36
|
||||
#define CF_TYPE_FREDDOCS 37
|
||||
#define CF_TYPE_INTERFACE_MARKUP 38
|
||||
#define CF_TYPE_INTERFACE_CSS 39
|
||||
|
||||
#define CF_MAX_PATH_TYPES \
|
||||
40 // Can be as high as you'd like //DTP; yeah but beware alot of things uses CF_MAX_PATH_TYPES
|
||||
|
||||
// TRUE if type is specified and valid
|
||||
#define CF_TYPE_SPECIFIED(path_type) (((path_type)>CF_TYPE_INVALID) && ((path_type)<CF_MAX_PATH_TYPES))
|
||||
|
||||
// #define's for the type parameter in cfopen.
|
||||
#define CFILE_NORMAL 0 // open file normally
|
||||
#define CFILE_MEMORY_MAPPED (1<<0) // open file as a memory-mapped file
|
||||
|
||||
#define CF_SORT_NONE 0
|
||||
#define CF_SORT_NAME 1
|
||||
#define CF_SORT_TIME 2
|
||||
#define CF_SORT_REVERSE 3
|
||||
|
||||
/**
|
||||
* @brief Contains a collection of flags for specifying from where a CFILE should be opened
|
||||
*
|
||||
* There are two types of flags. CF_LOCATION_GAME_ROOT and CF_LOCATION_USER_ROOT specify in which basic root directory
|
||||
* CFile should search for files.
|
||||
*
|
||||
* The remaining flags control what type of location may be used for the operation. It's possible to restrict the
|
||||
* location to the primary mod, the remaining mods or the top-level root directory.
|
||||
*/
|
||||
enum CFileLocationFlags {
|
||||
CF_LOCATION_ROOT_GAME = 1 << 0, //!< The game root location. This is the location of the game data (e.g. FS2 retail)
|
||||
/**
|
||||
* @brief The user directories.
|
||||
*
|
||||
* If the engine is in portable mode then using this flag exclusively will result in a failure to open files!
|
||||
*/
|
||||
CF_LOCATION_ROOT_USER = 1 << 1,
|
||||
|
||||
/**
|
||||
* @brief The memory root
|
||||
*
|
||||
* This contains all the built-in files available to the engine.
|
||||
*/
|
||||
CF_LOCATION_ROOT_MEMORY = 1 << 2,
|
||||
|
||||
/**
|
||||
* @brief Mask for extracting root type from a location bit field
|
||||
*/
|
||||
CF_LOCATION_ROOT_MASK = 0xFFFF,
|
||||
|
||||
CF_LOCATION_TYPE_ROOT = 1 << 16, //!< The basic, top-level root location
|
||||
/**
|
||||
* @brief The primary mod location.
|
||||
*
|
||||
* This is the mod that appears first on the command line. If there are no mods then the root location is considered
|
||||
* to be the primary mod
|
||||
*/
|
||||
CF_LOCATION_TYPE_PRIMARY_MOD = 1 << 17,
|
||||
/**
|
||||
* @brief The remaining mods.
|
||||
*
|
||||
* If there are no mods on the command line then this might not include any valid location.
|
||||
*/
|
||||
CF_LOCATION_TYPE_SECONDARY_MODS = 1 << 18,
|
||||
|
||||
/**
|
||||
* @brief Bitmask for extracting the type from a location bit field
|
||||
*/
|
||||
CF_LOCATION_TYPE_MASK = 0xFFFF0000,
|
||||
|
||||
/**
|
||||
* @brief A combination of all flags
|
||||
*
|
||||
* This should be used when the default behavior without any location filtering is desired.
|
||||
*/
|
||||
CF_LOCATION_ALL = CF_LOCATION_ROOT_MASK | CF_LOCATION_TYPE_MASK
|
||||
};
|
||||
|
||||
// callback function used for get_file_list() to filter files to be added to list. Return 1
|
||||
// to add file to list, or 0 to not add it.
|
||||
extern int (*Get_file_list_filter)(const char *filename);
|
||||
|
||||
// extra check for child directory under CF_TYPE_*
|
||||
// NOTE: if specified cf_get_file_list() will not search pack files!
|
||||
// NOTE: specified string must not contain ':' or spaces or begin with DIR_SEPARATOR!
|
||||
extern const char *Get_file_list_child;
|
||||
|
||||
// cfile directory. valid after cfile_init() returns successfully
|
||||
#define CFILE_ROOT_DIRECTORY_LEN 256
|
||||
|
||||
namespace cfile {
|
||||
enum class ModRootType { Unknown, Folder, Package };
|
||||
|
||||
enum class LocationType { Unknown, SecondaryMod, PrimaryMod, GameRoot };
|
||||
|
||||
struct ModRoot {
|
||||
ModRootType type = ModRootType::Unknown;
|
||||
SCP_string path;
|
||||
LocationType location_type = LocationType::Unknown;
|
||||
bool user_location = false;
|
||||
};
|
||||
} // namespace cfile
|
||||
|
||||
//================= LOW-LEVEL FUNCTIONS ==================
|
||||
int cfile_init(const SCP_vector<cfile::ModRoot>& modRoots);
|
||||
void cfile_close();
|
||||
|
||||
// add an extension to a filename if it doesn't already have it
|
||||
char *cf_add_ext(const char *filename, const char *ext);
|
||||
|
||||
// return CF_TYPE (directory location type) of a CFILE you called cfopen() successfully on.
|
||||
int cf_get_dir_type(CFILE *cfile);
|
||||
|
||||
// Opens the file. If no path is given, use the extension to look into the
|
||||
// default path. If mode is NULL, delete the file.
|
||||
CFILE* _cfopen(const char* source_file, int line, const char* filename, const char* mode, int type = CFILE_NORMAL,
|
||||
int dir_type = CF_TYPE_ANY, bool localize = false, uint32_t location_flags = CF_LOCATION_ALL);
|
||||
#define cfopen(...) _cfopen(LOCATION, __VA_ARGS__) // Pass source location to the function
|
||||
|
||||
// like cfopen(), but it accepts a fully qualified path only (ie, the result of a cf_find_file_location() call)
|
||||
// NOTE: only supports reading files!!
|
||||
CFILE *_cfopen_special(const char* source_file, int line, const char *file_path, const char *mode,
|
||||
const size_t size, const size_t offset, const void* data, int dir_type = CF_TYPE_ANY);
|
||||
#define cfopen_special(...) _cfopen_special(LOCATION, __VA_ARGS__) // Pass source location to the function
|
||||
|
||||
// Flush the open file buffer
|
||||
int cflush(CFILE *cfile);
|
||||
|
||||
// will throw an error if cfread*() functions read past this mark
|
||||
// converted to raw offsets when used, but gets passed actual length from current position
|
||||
// setting 'len' to zero will disable the check
|
||||
void cf_set_max_read_len(CFILE *cfile, size_t len);
|
||||
|
||||
// Deletes a file. Returns 0 on error, 1 if successful
|
||||
int cf_delete(const char *filename, int dir_type, uint32_t location_flags = CF_LOCATION_ALL);
|
||||
|
||||
// Same as _access function to read a file's access bits
|
||||
int cf_access(const char *filename, int dir_type, int mode);
|
||||
|
||||
// Returns 1 if the file exists, 0 if not.
|
||||
// Checks only the file system.
|
||||
int cf_exists(const char *filename, int dir_type);
|
||||
|
||||
// Goober5000
|
||||
// Returns 1 if the file exists, 0 if not.
|
||||
// Checks both the file system and the VPs.
|
||||
int cf_exists_full(const char *filename, int dir_type);
|
||||
// check num_ext worth of ext_list extensions
|
||||
int cf_exists_full_ext(const char *filename, int dir_type, const int num_ext, const char **ext_list);
|
||||
|
||||
// ctmpfile() opens a temporary file stream. File is deleted automatically when closed
|
||||
CFILE *ctmpfile();
|
||||
|
||||
// Closes the file
|
||||
int cfclose(CFILE *cfile);
|
||||
|
||||
//Checks if the given handle is valid
|
||||
int cf_is_valid(CFILE *cfile);
|
||||
|
||||
// Returns size of file...
|
||||
int cfilelength(CFILE *fp);
|
||||
|
||||
// Reads data
|
||||
int cfread(void *buf, int elsize, int nelem, CFILE *fp);
|
||||
|
||||
// cfwrite() writes to the file
|
||||
int cfwrite(const void *buf, int elsize, int nelem, CFILE *cfile);
|
||||
|
||||
// Moves the file pointer
|
||||
int cfseek(CFILE *fp, int offset, int where);
|
||||
|
||||
// Returns current position of file.
|
||||
int cftell(CFILE *fp);
|
||||
|
||||
// cfputc() writes a character to a file
|
||||
int cfputc(int c, CFILE *cfile);
|
||||
|
||||
// cfputs() writes a string to a file
|
||||
int cfputs(const char *str, CFILE *cfile);
|
||||
|
||||
// cfgetc() reads a character to a file
|
||||
int cfgetc(CFILE *cfile);
|
||||
|
||||
// cfgets() reads a string from a file
|
||||
char *cfgets(char *buf, int n, CFILE *cfile);
|
||||
|
||||
// cfeof() Tests for end-of-file on a stream
|
||||
int cfeof(CFILE *cfile);
|
||||
|
||||
// Return the data pointer associated with the CFILE structure (for memory mapped files)
|
||||
const void *cf_returndata(CFILE *cfile);
|
||||
|
||||
// get the 2 byte checksum of the passed filename - return 0 if operation failed, 1 if succeeded
|
||||
int cf_chksum_short(const char *filename, ushort *chksum, int max_size = -1, int cf_type = CF_TYPE_ANY );
|
||||
|
||||
// get the 2 byte checksum of the passed file - return 0 if operation failed, 1 if succeeded
|
||||
// NOTE : preserves current file position
|
||||
int cf_chksum_short(CFILE *file, ushort *chksum, int max_size = -1);
|
||||
|
||||
// get the 32 bit CRC checksum of the passed filename - return 0 if operation failed, 1 if succeeded
|
||||
int cf_chksum_long(const char *filename, uint *chksum, int max_size = -1, int cf_type = CF_TYPE_ANY );
|
||||
|
||||
// get the 32 bit CRC checksum of the passed file - return 0 if operation failed, 1 if succeeded
|
||||
// NOTE : preserves current file position
|
||||
int cf_chksum_long(CFILE *file, uint *chksum, int max_size = -1);
|
||||
|
||||
int cf_chksum_pack(const char *filename, uint *chk_long, bool full = false);
|
||||
|
||||
// convenient for misc checksumming purposes ------------------------------------------
|
||||
|
||||
// update cur_chksum with the chksum of the new_data of size new_data_size
|
||||
ushort cf_add_chksum_short(ushort seed, ubyte *buffer, int size);
|
||||
|
||||
// update cur_chksum with the chksum of the new_data of size new_data_size
|
||||
uint cf_add_chksum_long(uint seed, ubyte *buffer, size_t size);
|
||||
|
||||
// convenient for misc checksumming purposes ------------------------------------------
|
||||
|
||||
//================= HIGH LEVEL FUNCTIONS ==================
|
||||
|
||||
// rename a file, utilizing the extension to determine where file is.
|
||||
#define CF_RENAME_SUCCESS 0 // successfully renamed the file
|
||||
#define CF_RENAME_FAIL_ACCESS 1 // new name could not be created
|
||||
#define CF_RENAME_FAIL_EXIST 2 // old name does not exist
|
||||
int cf_rename(const char *old_name, const char *name, int type = CF_TYPE_ANY );
|
||||
|
||||
// changes the attributes of a file
|
||||
void cf_attrib(const char *name, int set, int clear, int type);
|
||||
|
||||
// flush (delete all files in) the passed directory (by type), return the # of files deleted
|
||||
// NOTE : WILL NOT DELETE READ-ONLY FILES
|
||||
int cfile_flush_dir(int type);
|
||||
|
||||
// functions for reading from cfile
|
||||
// These are all high level, built up from
|
||||
// cfread.
|
||||
char *cfgets(char *buf, size_t n, CFILE *fp);
|
||||
char cfread_char(CFILE* file, char deflt = 0);
|
||||
ubyte cfread_ubyte(CFILE* file, ubyte deflt = 0);
|
||||
short cfread_short(CFILE* file, short deflt = 0);
|
||||
ushort cfread_ushort(CFILE* file, ushort deflt = 0);
|
||||
int cfread_int(CFILE* file, int deflt = 0);
|
||||
uint cfread_uint(CFILE* file, uint deflt = 0);
|
||||
float cfread_float(CFILE* file, float deflt = 0.0f);
|
||||
void cfread_vector(vec3d* vec, CFILE* file, vec3d* deflt = nullptr);
|
||||
|
||||
// Reads variable length, null-termined string. Will only read up
|
||||
// to n characters.
|
||||
void cfread_string(char *buf,int n, CFILE *file);
|
||||
/**
|
||||
* @brief Read a fixed length string that is not null-terminated, with the length stored in file
|
||||
*
|
||||
* @param buf Pre-allocated array to store string
|
||||
* @param n Size of pre-allocated array
|
||||
* @param file File to read from
|
||||
*
|
||||
* @note Appends NULL character to string (buf)
|
||||
*/
|
||||
void cfread_string_len(char *buf,int n, CFILE *file);
|
||||
|
||||
/**
|
||||
* @brief Read a string from the file where the length is stored in the file
|
||||
* @param file The file to read the string from
|
||||
* @return The string that was read
|
||||
*/
|
||||
SCP_string cfread_string_len(CFILE *file);
|
||||
|
||||
// functions for writing cfiles
|
||||
int cfwrite_char(char c, CFILE *file);
|
||||
int cfwrite_float(float f, CFILE *file);
|
||||
int cfwrite_int(int i, CFILE *file);
|
||||
int cfwrite_uint(uint i, CFILE *file);
|
||||
int cfwrite_short(short s, CFILE *file);
|
||||
int cfwrite_ushort(ushort s, CFILE *file);
|
||||
int cfwrite_ubyte(ubyte u, CFILE *file);
|
||||
|
||||
// writes variable length, null-termined string.
|
||||
int cfwrite_string(const char *buf, CFILE *file);
|
||||
|
||||
/**
|
||||
* @brief Write a fixed length string (not including its null terminator), with the length stored in file
|
||||
*
|
||||
* @param buf String to write to file
|
||||
* @param file File to write to
|
||||
*/
|
||||
int cfwrite_string_len(const char *buf, CFILE *file);
|
||||
|
||||
int cf_get_file_list(SCP_vector<SCP_string>& list, int pathtype, const char* filter, int sort = CF_SORT_NONE,
|
||||
SCP_vector<file_list_info>* info = nullptr, uint32_t location_flags = CF_LOCATION_ALL);
|
||||
int cf_get_file_list(int max, char** list, int type, const char* filter, int sort = CF_SORT_NONE,
|
||||
file_list_info* info = nullptr, uint32_t location_flags = CF_LOCATION_ALL);
|
||||
int cf_get_file_list_preallocated(int max, char arr[][MAX_FILENAME_LEN], char** list, int type, const char* filter,
|
||||
int sort = CF_SORT_NONE, file_list_info* info = nullptr,
|
||||
uint32_t location_flags = CF_LOCATION_ALL);
|
||||
void cf_sort_filenames( int n, char **list, int sort, file_list_info *info = NULL );
|
||||
void cf_sort_filenames( SCP_vector<SCP_string> &list, int sort, SCP_vector<file_list_info> *info = NULL );
|
||||
|
||||
struct CFileLocation {
|
||||
bool found = false;
|
||||
SCP_string full_name;
|
||||
size_t size = 0;
|
||||
size_t offset = 0;
|
||||
const void* data_ptr = nullptr;
|
||||
|
||||
explicit CFileLocation(bool found_in = false) : found(found_in) {}
|
||||
};
|
||||
|
||||
// Searches for a file. Follows all rules and precedence and searches
|
||||
// CD's and pack files.
|
||||
// Input: filespace - Filename & extension
|
||||
// pathtype - See CF_TYPE_ defines in CFILE.H
|
||||
// max_out - Maximum string size to be stuffed into pack_filename
|
||||
// Output: pack_filename - Absolute path and filename of this file. Could be a packfile or the actual file.
|
||||
// size - File size
|
||||
// offset - Offset into pack file. 0 if not a packfile.
|
||||
// Returns: If not found returns 0.
|
||||
CFileLocation cf_find_file_location(const char* filespec, int pathtype, bool localize = false,
|
||||
uint32_t location_flags = CF_LOCATION_ALL);
|
||||
|
||||
struct CFileLocationExt : public CFileLocation {
|
||||
int extension_index = -1;
|
||||
|
||||
explicit CFileLocationExt(int extension_index_in = -1)
|
||||
: CFileLocation(extension_index_in >= 0), extension_index(extension_index_in)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// Searches for a file. Follows all rules and precedence and searches
|
||||
// CD's and pack files. Searches all locations in order for first filename using ext filter list.
|
||||
// Input: filename - Filename & extension
|
||||
// ext_num - number of extensions to look for
|
||||
// ext_list - extension filter list
|
||||
// pathtype - See CF_TYPE_ defines in CFILE.H
|
||||
// max_out - Maximum string length that should be stuffed into pack_filename
|
||||
// Output: pack_filename - Absolute path and filename of this file. Could be a packfile or the actual file.
|
||||
// size - File size
|
||||
// offset - Offset into pack file. 0 if not a packfile.
|
||||
// Returns: If not found returns -1, else returns offset into ext_list.
|
||||
// (NOTE: This function is exponentially slow, so don't use it unless truely needed!!)
|
||||
CFileLocationExt cf_find_file_location_ext(const char* filename, const int ext_num, const char** ext_list, int pathtype,
|
||||
bool localize = false);
|
||||
|
||||
// Functions to change directories
|
||||
int cfile_chdir(const char *dir);
|
||||
|
||||
#ifdef _WIN32
|
||||
int cfile_chdrive(int DriveNum, int flag);
|
||||
#endif
|
||||
|
||||
// push current directory on a 'stack' (so we can restore it) and change the directory
|
||||
int cfile_push_chdir(int type);
|
||||
|
||||
// restore directory on top of the stack
|
||||
int cfile_pop_dir();
|
||||
|
||||
int cfile_get_path_type(const SCP_string& dir);
|
||||
|
||||
namespace cfile
|
||||
{
|
||||
// exceptions and other errors
|
||||
class cfile_error : public std::exception
|
||||
{
|
||||
public:
|
||||
cfile_error() : m_excuse("CFILE Exception")
|
||||
{
|
||||
}
|
||||
|
||||
explicit cfile_error(const std::string &excuse) : m_excuse(excuse)
|
||||
{
|
||||
}
|
||||
|
||||
~cfile_error() SCP_NOEXCEPT override {}
|
||||
|
||||
const char *what() const SCP_NOEXCEPT override {
|
||||
return m_excuse.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_excuse;
|
||||
};
|
||||
|
||||
class max_read_length : public cfile_error
|
||||
{
|
||||
public:
|
||||
explicit max_read_length(const std::string &excuse) : cfile_error(excuse)
|
||||
{
|
||||
}
|
||||
|
||||
max_read_length() : cfile_error("Attempted to read beyond length limit")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// This allows to use std::unique_ptr with CFILE
|
||||
namespace std {
|
||||
template <>
|
||||
struct default_delete<CFILE> {
|
||||
void operator()(CFILE* ptr)
|
||||
{
|
||||
if (cf_is_valid(ptr)) {
|
||||
cfclose(ptr);
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
#endif /* __CFILE_H__ */
|
||||
@@ -1,269 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#define _CFILE_INTERNAL
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
#include <windows.h>
|
||||
#include <winbase.h> /* needed for memory mapping of file functions */
|
||||
#endif
|
||||
|
||||
#include "cfile/cfile.h"
|
||||
#include "cfile/cfilearchive.h"
|
||||
#include "luaconf.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <limits>
|
||||
|
||||
|
||||
#define CHECK_POSITION
|
||||
|
||||
// Called once to setup the low-level reading code.
|
||||
|
||||
void cf_init_lowlevel_read_code( CFILE * cfile, size_t lib_offset, size_t size, size_t pos )
|
||||
{
|
||||
Assert(cfile != nullptr);
|
||||
|
||||
cfile->lib_offset = lib_offset;
|
||||
cfile->raw_position = pos;
|
||||
cfile->size = size;
|
||||
|
||||
if ( cfile->fp ) {
|
||||
if ( cfile->lib_offset ) {
|
||||
fseek( cfile->fp, (long)cfile->lib_offset, SEEK_SET );
|
||||
}
|
||||
|
||||
#if defined(CHECK_POSITION) && !defined(NDEBUG)
|
||||
auto raw_position = ftell(cfile->fp) - cfile->lib_offset;
|
||||
Assert(raw_position == cfile->raw_position);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// cfeof() Tests for end-of-file on a stream
|
||||
//
|
||||
// returns a nonzero value after the first read operation that attempts to read
|
||||
// past the end of the file. It returns 0 if the current position is not end of file.
|
||||
// There is no error return.
|
||||
|
||||
int cfeof(CFILE *cfile)
|
||||
{
|
||||
Assert(cfile != NULL);
|
||||
|
||||
int result = 0;
|
||||
|
||||
#if defined(CHECK_POSITION) && !defined(NDEBUG)
|
||||
if (cfile->fp) {
|
||||
auto raw_position = ftell(cfile->fp) - cfile->lib_offset;
|
||||
Assert(raw_position == cfile->raw_position);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cfile->raw_position >= cfile->size ) {
|
||||
result = 1;
|
||||
} else {
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// cftell() returns offset into file
|
||||
//
|
||||
// returns: success ==> offset into the file
|
||||
// error ==> -1
|
||||
//
|
||||
int cftell( CFILE * cfile )
|
||||
{
|
||||
Assert(cfile != NULL);
|
||||
|
||||
#if defined(CHECK_POSITION) && !defined(NDEBUG)
|
||||
if (cfile->fp) {
|
||||
auto raw_position = ftell(cfile->fp) - cfile->lib_offset;
|
||||
Assert(raw_position == cfile->raw_position);
|
||||
}
|
||||
#endif
|
||||
|
||||
// The rest of the code still uses ints, do an overflow check to detect cases where this fails
|
||||
Assertion(cfile->raw_position <= static_cast<size_t>(std::numeric_limits<int>::max()),
|
||||
"Integer overflow in cftell, a file is probably too large (but I don't know which one).");
|
||||
return (int) cfile->raw_position;
|
||||
}
|
||||
|
||||
|
||||
// cfseek() moves the file pointer
|
||||
//
|
||||
// returns: success ==> 0
|
||||
// error ==> non-zero
|
||||
//
|
||||
int cfseek( CFILE *cfile, int offset, int where )
|
||||
{
|
||||
|
||||
Assert(cfile != NULL);
|
||||
|
||||
// TODO: seek to offset in memory mapped file
|
||||
Assert( !cfile->mem_mapped );
|
||||
|
||||
size_t goal_position;
|
||||
|
||||
switch( where ) {
|
||||
case CF_SEEK_SET:
|
||||
goal_position = offset+cfile->lib_offset;
|
||||
break;
|
||||
case CF_SEEK_CUR:
|
||||
{
|
||||
goal_position = cfile->raw_position+offset+cfile->lib_offset;
|
||||
}
|
||||
break;
|
||||
case CF_SEEK_END:
|
||||
goal_position = cfile->size+offset+cfile->lib_offset;
|
||||
break;
|
||||
default:
|
||||
Int3();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Make sure we don't seek beyond the end of the file
|
||||
CAP(goal_position, cfile->lib_offset, cfile->lib_offset + cfile->size);
|
||||
|
||||
int result = 0;
|
||||
|
||||
if (cfile->fp) {
|
||||
// If we have a file pointer we can also seek in that file
|
||||
result = fseek(cfile->fp, (long)goal_position, SEEK_SET );
|
||||
Assertion(goal_position >= cfile->lib_offset, "Invalid offset values detected while seeking! Goal was " SIZE_T_ARG ", lib_offset is " SIZE_T_ARG ".", goal_position, cfile->lib_offset);
|
||||
}
|
||||
// If we only have a data pointer this will do all the work
|
||||
cfile->raw_position = goal_position - cfile->lib_offset;
|
||||
Assertion(cfile->raw_position <= cfile->size, "Invalid raw_position value detected!");
|
||||
|
||||
#if defined(CHECK_POSITION) && !defined(NDEBUG)
|
||||
if (cfile->fp) {
|
||||
auto tmp_offset = ftell(cfile->fp) - cfile->lib_offset;
|
||||
Assert(tmp_offset == cfile->raw_position);
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// cfread() reads from a file
|
||||
//
|
||||
// returns: returns the number of full elements read
|
||||
//
|
||||
//
|
||||
int cfread(void *buf, int elsize, int nelem, CFILE *cfile)
|
||||
{
|
||||
if(!cf_is_valid(cfile))
|
||||
return 0;
|
||||
|
||||
size_t size = elsize*nelem;
|
||||
|
||||
if(buf == NULL || size <= 0)
|
||||
return 0;
|
||||
|
||||
if ( (cfile->raw_position+size) > cfile->size ) {
|
||||
Assertion(cfile->raw_position <= cfile->size, "Invalid raw_position value detected!");
|
||||
size = cfile->size - cfile->raw_position;
|
||||
if ( size < 1 ) {
|
||||
return 0;
|
||||
}
|
||||
//mprintf(( "CFILE: EOF encountered in file\n" ));
|
||||
}
|
||||
|
||||
if (cfile->max_read_len) {
|
||||
if ( cfile->raw_position+size > cfile->max_read_len ) {
|
||||
std::ostringstream s_buf;
|
||||
s_buf << "Attempted to read " << size << "-byte(s) beyond length limit";
|
||||
|
||||
throw cfile::max_read_length(s_buf.str());
|
||||
}
|
||||
}
|
||||
|
||||
size_t bytes_read;
|
||||
if (cfile->data != nullptr) {
|
||||
// This is a file from memory
|
||||
bytes_read = size;
|
||||
memcpy(buf, reinterpret_cast<const char*>(cfile->data) + cfile->raw_position, size);
|
||||
} else {
|
||||
bytes_read = fread( buf, 1, size, cfile->fp );
|
||||
}
|
||||
if ( bytes_read > 0 ) {
|
||||
cfile->raw_position += bytes_read;
|
||||
Assertion(cfile->raw_position <= cfile->size, "Invalid raw_position value detected!");
|
||||
}
|
||||
|
||||
#if defined(CHECK_POSITION) && !defined(NDEBUG)
|
||||
if (cfile->fp) {
|
||||
auto tmp_offset = ftell(cfile->fp) - cfile->lib_offset;
|
||||
Assert(tmp_offset==cfile->raw_position);
|
||||
}
|
||||
#endif
|
||||
|
||||
return (int)(bytes_read / elsize);
|
||||
|
||||
}
|
||||
|
||||
int cfread_lua_number(double *buf, CFILE *cfile)
|
||||
{
|
||||
if(!cf_is_valid(cfile))
|
||||
return 0;
|
||||
|
||||
if(buf == NULL)
|
||||
return 0;
|
||||
|
||||
// cfread() not supported for memory-mapped files
|
||||
if(cfile->data != nullptr)
|
||||
{
|
||||
Warning(LOCATION, "Writing is not supported for mem-mapped files");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t advance = 0;
|
||||
int items_read;
|
||||
if (cfile->fp) {
|
||||
long orig_pos = ftell(cfile->fp);
|
||||
items_read = fscanf(cfile->fp, LUA_NUMBER_SCAN, buf);
|
||||
advance = (size_t) (ftell(cfile->fp)-orig_pos);
|
||||
} else {
|
||||
int read;
|
||||
// %n returns the number of bytes currently read so we append that to the scan format at the end so it will return
|
||||
// how many bytes we have consumed
|
||||
items_read = sscanf(reinterpret_cast<const char*>(cfile->data), LUA_NUMBER_SCAN "%n", buf, &read);
|
||||
if (items_read == 2) {
|
||||
// We need to correct the items read counter since we read one additional item
|
||||
items_read = 1;
|
||||
}
|
||||
advance = (size_t) read;
|
||||
}
|
||||
cfile->raw_position += advance;
|
||||
Assertion(cfile->raw_position <= cfile->size, "Invalid raw_position value detected!");
|
||||
|
||||
#if defined(CHECK_POSITION) && !defined(NDEBUG)
|
||||
if (cfile->fp) {
|
||||
auto tmp_offset = ftell(cfile->fp) - cfile->lib_offset;
|
||||
Assert(tmp_offset==cfile->raw_position);
|
||||
}
|
||||
#endif
|
||||
|
||||
return items_read;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _CFILEARCHIVE_H
|
||||
#define _CFILEARCHIVE_H
|
||||
|
||||
#ifndef _CFILE_INTERNAL
|
||||
#error This file should only be included internally in CFILE!!
|
||||
#endif
|
||||
|
||||
// The following Cfile_block data is private to cfile.cpp
|
||||
// DO NOT MOVE the Cfile_block* information to cfile.h / do not extern this data
|
||||
//
|
||||
#define CFILE_BLOCK_UNUSED 0
|
||||
#define CFILE_BLOCK_USED 1
|
||||
|
||||
struct CFILE {
|
||||
int type = CFILE_BLOCK_UNUSED; // CFILE_BLOCK_UNUSED, CFILE_BLOCK_USED
|
||||
int dir_type; // directory location
|
||||
FILE* fp; // File pointer if opening an individual file
|
||||
const void* data; // Pointer for memory-mapped file access. NULL if not mem-mapped.
|
||||
bool mem_mapped; // Flag for memory mapped files (if data is not null and this is false it means that it's an embedded file)
|
||||
#ifdef _WIN32
|
||||
HANDLE hInFile; // Handle from CreateFile()
|
||||
HANDLE hMapFile; // Handle from CreateFileMapping()
|
||||
#else
|
||||
size_t data_length; // length of data for mmap
|
||||
#endif
|
||||
size_t lib_offset;
|
||||
size_t raw_position;
|
||||
size_t size; // for packed files
|
||||
|
||||
size_t max_read_len; // max read offset, for special error handling
|
||||
|
||||
const char* source_file;
|
||||
int line_num;
|
||||
};
|
||||
|
||||
#define MAX_CFILE_BLOCKS 64
|
||||
extern std::array<CFILE, MAX_CFILE_BLOCKS> Cfile_block_list;
|
||||
|
||||
// Called once to setup the low-level reading code.
|
||||
void cf_init_lowlevel_read_code( CFILE * cfile, size_t lib_offset, size_t size, size_t pos );
|
||||
|
||||
#endif
|
||||
@@ -1,203 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
#include <windows.h>
|
||||
#include <winbase.h> /* needed for memory mapping of file functions */
|
||||
#endif
|
||||
|
||||
#include "cfile/cfile.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
|
||||
|
||||
void cf_sort_filenames( SCP_vector<SCP_string> &list, int sort, SCP_vector<file_list_info> *info )
|
||||
{
|
||||
// NOTE: This really needs to be updated to C++ style sorting at some point
|
||||
|
||||
int i, j, incr;
|
||||
SCP_string t;
|
||||
file_list_info tt;
|
||||
|
||||
int n = (int)list.size();
|
||||
|
||||
if (sort == CF_SORT_NAME) {
|
||||
incr = n / 2;
|
||||
while (incr > 0) {
|
||||
for (i=incr; i<n; i++) {
|
||||
j = i - incr;
|
||||
while (j >= 0) {
|
||||
if (stricmp(list[j].c_str(), list[j + incr].c_str()) > 0) {
|
||||
t = list[j];
|
||||
list[j] = list[j + incr];
|
||||
list[j + incr] = t;
|
||||
|
||||
if (info) {
|
||||
tt = (*info)[j];
|
||||
(*info)[j] = (*info)[j + incr];
|
||||
(*info)[j + incr] = tt;
|
||||
}
|
||||
|
||||
j -= incr;
|
||||
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
incr /= 2;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
} else if (sort == CF_SORT_TIME) {
|
||||
Assert(info);
|
||||
incr = n / 2;
|
||||
while (incr > 0) {
|
||||
for (i=incr; i<n; i++) {
|
||||
j = i - incr;
|
||||
while (j >= 0) {
|
||||
if ( (*info)[j].write_time < (*info)[j + incr].write_time ) {
|
||||
t = list[j];
|
||||
list[j] = list[j + incr];
|
||||
list[j + incr] = t;
|
||||
|
||||
tt = (*info)[j];
|
||||
(*info)[j] = (*info)[j + incr];
|
||||
(*info)[j + incr] = tt;
|
||||
j -= incr;
|
||||
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
incr /= 2;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
} else if (sort == CF_SORT_REVERSE) {
|
||||
std::reverse( list.begin(), list.end() );
|
||||
|
||||
if (info) {
|
||||
std::reverse( info->begin(), info->end() );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
nprintf(("Error", "Unknown sorting method %d passed to cf_sort_filenames()\n", sort));
|
||||
}
|
||||
|
||||
// Sorts a list of filenames using the specified sorting method (CF_SORT_*).
|
||||
// n = number of filenames in list to sort
|
||||
// list = list of filenames to be sorted
|
||||
// sort = sorting method to use (one of the CF_SORT_* defines)
|
||||
// info = extra info for each file. Only required if sorting by time, however if you
|
||||
// have extra file info, you should pass it as well to get it sorted too (so an
|
||||
// index into list is the same index for info for that file
|
||||
void cf_sort_filenames( int n, char **list, int sort, file_list_info *info )
|
||||
{
|
||||
int i, j, incr;
|
||||
char *t;
|
||||
file_list_info tt;
|
||||
|
||||
if (sort == CF_SORT_NAME) {
|
||||
incr = n / 2;
|
||||
while (incr > 0) {
|
||||
for (i=incr; i<n; i++) {
|
||||
j = i - incr;
|
||||
while (j >= 0) {
|
||||
if (stricmp(list[j], list[j + incr]) > 0) {
|
||||
t = list[j];
|
||||
list[j] = list[j + incr];
|
||||
list[j + incr] = t;
|
||||
|
||||
if (info) {
|
||||
tt = info[j];
|
||||
info[j] = info[j + incr];
|
||||
info[j + incr] = tt;
|
||||
}
|
||||
|
||||
j -= incr;
|
||||
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
incr /= 2;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
} else if (sort == CF_SORT_TIME) {
|
||||
Assert(info);
|
||||
incr = n / 2;
|
||||
while (incr > 0) {
|
||||
for (i=incr; i<n; i++) {
|
||||
j = i - incr;
|
||||
while (j >= 0) {
|
||||
if (info[j].write_time < info[j + incr].write_time) {
|
||||
t = list[j];
|
||||
list[j] = list[j + incr];
|
||||
list[j + incr] = t;
|
||||
|
||||
tt = info[j];
|
||||
info[j] = info[j + incr];
|
||||
info[j + incr] = tt;
|
||||
j -= incr;
|
||||
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
incr /= 2;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
} else if (sort == CF_SORT_REVERSE) {
|
||||
incr = n / 2;
|
||||
char buffer[MAX_FILENAME_LEN];
|
||||
file_list_info tt_tmp;
|
||||
|
||||
for (i = 0; i < incr; i++) {
|
||||
t = list[n - 1 - i];
|
||||
|
||||
if (list[i] != t) {
|
||||
strcpy_s(buffer, list[i]);
|
||||
strcpy(list[i], t);
|
||||
strcpy(t, buffer);
|
||||
|
||||
if (info) {
|
||||
tt = info[n - 1 - i];
|
||||
tt_tmp = info[i];
|
||||
info[i] = tt;
|
||||
tt = tt_tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
nprintf(("Error", "Unknown sorting method %d passed to cf_sort_filenames()\n", sort));
|
||||
}
|
||||
@@ -1,266 +0,0 @@
|
||||
#define _CFILE_INTERNAL
|
||||
|
||||
#include "cfilemod.h"
|
||||
#include "cfile.h"
|
||||
#include "cmdline/cmdline.h"
|
||||
#include "osapi/osapi.h"
|
||||
#include "cfilesystem.h"
|
||||
|
||||
#ifdef SCP_UNIX
|
||||
#include <glob.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <fnmatch.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <libgen.h>
|
||||
#endif
|
||||
|
||||
namespace cfile {
|
||||
|
||||
namespace {
|
||||
|
||||
typedef struct cf_root_sort {
|
||||
SCP_string path;
|
||||
int cf_type;
|
||||
} cf_root_sort;
|
||||
|
||||
// packfile sort function
|
||||
bool cf_packfile_sort_func(const cf_root_sort& r1, const cf_root_sort& r2) {
|
||||
// if the 2 directory types are the same, do a string compare
|
||||
if (r1.cf_type == r2.cf_type) {
|
||||
return (stricmp(r1.path.c_str(), r2.path.c_str()) < 0);
|
||||
}
|
||||
|
||||
// otherwise return them in order of CF_TYPE_* precedence
|
||||
return (r1.cf_type < r2.cf_type);
|
||||
}
|
||||
|
||||
// Go through a root and look for pack files
|
||||
void build_pack_list(SCP_vector<ModRoot>& mod_roots,
|
||||
const SCP_string& search_path,
|
||||
LocationType location_type,
|
||||
bool user_location) {
|
||||
char filespec[MAX_PATH_LEN];
|
||||
|
||||
// allocate a temporary array of temporary roots so we can easily sort them
|
||||
SCP_vector<cf_root_sort> temp_roots_sort;
|
||||
|
||||
// now just setup all the root info
|
||||
for (int i = CF_TYPE_ROOT; i < CF_MAX_PATH_TYPES; i++) {
|
||||
strcpy_s(filespec, search_path.c_str());
|
||||
|
||||
if (strlen(Pathtypes[i].path)) {
|
||||
strcat_s(filespec, Pathtypes[i].path);
|
||||
|
||||
if (filespec[strlen(filespec) - 1] != DIR_SEPARATOR_CHAR)
|
||||
strcat_s(filespec, DIR_SEPARATOR_STR);
|
||||
}
|
||||
|
||||
#if defined _WIN32
|
||||
strcat_s( filespec, "*.vp" );
|
||||
|
||||
intptr_t find_handle;
|
||||
_finddata_t find;
|
||||
|
||||
find_handle = _findfirst( filespec, &find );
|
||||
|
||||
if (find_handle != -1) {
|
||||
do {
|
||||
// add the new item
|
||||
if (!(find.attrib & _A_SUBDIR)) {
|
||||
|
||||
// get a temp pointer
|
||||
rptr_sort = &temp_roots_sort[root_index++];
|
||||
|
||||
// fill in all the proper info
|
||||
strcpy_s(rptr_sort->path, root->path);
|
||||
|
||||
if(strlen(Pathtypes[i].path)) {
|
||||
|
||||
strcat_s(rptr_sort->path, Pathtypes[i].path );
|
||||
strcat_s(rptr_sort->path, DIR_SEPARATOR_STR);
|
||||
}
|
||||
|
||||
strcat_s(rptr_sort->path, find.name );
|
||||
rptr_sort->roottype = CF_ROOTTYPE_PACK;
|
||||
rptr_sort->cf_type = i;
|
||||
}
|
||||
|
||||
} while (!_findnext(find_handle, &find));
|
||||
|
||||
_findclose( find_handle );
|
||||
}
|
||||
#elif defined SCP_UNIX
|
||||
strcat_s(filespec, "*.[vV][pP]");
|
||||
glob_t globinfo;
|
||||
|
||||
memset(&globinfo, 0, sizeof(globinfo));
|
||||
|
||||
int status = glob(filespec, 0, NULL, &globinfo);
|
||||
|
||||
if (status == 0) {
|
||||
for (uint j = 0; j < globinfo.gl_pathc; j++) {
|
||||
// Determine if this is a regular file
|
||||
struct stat statbuf;
|
||||
memset(&statbuf, 0, sizeof(statbuf));
|
||||
stat(globinfo.gl_pathv[j], &statbuf);
|
||||
|
||||
if (S_ISREG(statbuf.st_mode)) {
|
||||
|
||||
cf_root_sort sort;
|
||||
|
||||
// fill in all the proper info
|
||||
sort.path = globinfo.gl_pathv[j];
|
||||
sort.cf_type = i;
|
||||
temp_roots_sort.push_back(sort);
|
||||
}
|
||||
}
|
||||
|
||||
globfree(&globinfo);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// sort the roots
|
||||
std::sort(temp_roots_sort.begin(), temp_roots_sort.end(), cf_packfile_sort_func);
|
||||
|
||||
// now insert them all into the real root list properly
|
||||
for (const auto& pack_root : temp_roots_sort) {
|
||||
ModRoot root;
|
||||
root.type = ModRootType::Package;
|
||||
root.path = pack_root.path;
|
||||
root.user_location = user_location;
|
||||
root.location_type = location_type;
|
||||
|
||||
mod_roots.push_back(root);
|
||||
}
|
||||
}
|
||||
|
||||
char normalize_directory_separator(char in) {
|
||||
if (in == '/') {
|
||||
return DIR_SEPARATOR_CHAR;
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
void
|
||||
add_mod_roots(SCP_vector<ModRoot>& mod_roots, const char* mod_cmdline, const SCP_string& rootDirectory, bool user_location) {
|
||||
if (mod_cmdline) {
|
||||
bool primary = true;
|
||||
for (const char* cur_pos = mod_cmdline; strlen(cur_pos) != 0; cur_pos += (strlen(cur_pos) + 1)) {
|
||||
SCP_stringstream ss;
|
||||
ss << rootDirectory;
|
||||
|
||||
if (rootDirectory.back() != DIR_SEPARATOR_CHAR) {
|
||||
ss << DIR_SEPARATOR_CHAR;
|
||||
}
|
||||
|
||||
ss << cur_pos << DIR_SEPARATOR_STR;
|
||||
|
||||
SCP_string rootPath = ss.str();
|
||||
|
||||
// normalize the path to the native path format
|
||||
std::transform(rootPath.begin(), rootPath.end(), rootPath.begin(), normalize_directory_separator);
|
||||
|
||||
ModRoot root;
|
||||
root.type = ModRootType::Folder;
|
||||
root.path = rootPath;
|
||||
root.user_location = user_location;
|
||||
|
||||
if (primary) {
|
||||
root.location_type = LocationType::PrimaryMod;
|
||||
} else {
|
||||
root.location_type = LocationType::SecondaryMod;
|
||||
}
|
||||
|
||||
mod_roots.push_back(root);
|
||||
|
||||
build_pack_list(mod_roots, rootPath, root.location_type, user_location);
|
||||
|
||||
primary = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SCP_vector<ModRoot> getModRootsFromModCmdline(const SCP_string& content_root, const char* mod_cmdline) {
|
||||
SCP_vector<ModRoot> mod_roots;
|
||||
|
||||
if (os_is_legacy_mode()) {
|
||||
// =========================================================================
|
||||
#ifdef WIN32
|
||||
// Nothing to do here, Windows uses the current directory as the base
|
||||
#else
|
||||
add_mod_roots(mod_roots, mod_cmdline, os_get_legacy_user_dir(), true);
|
||||
|
||||
ModRoot root;
|
||||
root.type = ModRootType::Folder;
|
||||
root.path = os_get_legacy_user_dir();
|
||||
root.user_location = true;
|
||||
root.location_type = LocationType::GameRoot;
|
||||
|
||||
// do we already have a slash? as in the case of a root directory install
|
||||
if (root.path.back() != DIR_SEPARATOR_CHAR) {
|
||||
root.path += DIR_SEPARATOR_STR; // put trailing backslash on for easier path construction
|
||||
}
|
||||
|
||||
mod_roots.push_back(root);
|
||||
|
||||
// Next, check any VP files under the current directory.
|
||||
build_pack_list(mod_roots, root.path, root.location_type, root.user_location);
|
||||
#endif
|
||||
// =========================================================================
|
||||
} else if (!Cmdline_portable_mode) {
|
||||
// =========================================================================
|
||||
// now look for mods under the users HOME directory to use before system ones
|
||||
add_mod_roots(mod_roots, mod_cmdline, os_get_config_path(), true);
|
||||
// =========================================================================
|
||||
|
||||
// =========================================================================
|
||||
// set users HOME directory as default for loading and saving files
|
||||
ModRoot root;
|
||||
root.type = ModRootType::Folder;
|
||||
root.path = os_get_config_path();
|
||||
root.user_location = true;
|
||||
root.location_type = LocationType::GameRoot;
|
||||
|
||||
// do we already have a slash? as in the case of a root directory install
|
||||
if (root.path.back() != DIR_SEPARATOR_CHAR) {
|
||||
root.path += DIR_SEPARATOR_STR; // put trailing backslash on for easier path construction
|
||||
}
|
||||
|
||||
mod_roots.push_back(root);
|
||||
|
||||
// Next, check any VP files under the current directory.
|
||||
build_pack_list(mod_roots, root.path, root.location_type, root.user_location);
|
||||
// =========================================================================
|
||||
}
|
||||
|
||||
add_mod_roots(mod_roots, mod_cmdline, content_root, false);
|
||||
|
||||
ModRoot root;
|
||||
root.type = ModRootType::Folder;
|
||||
root.path = content_root;
|
||||
root.user_location = false;
|
||||
root.location_type = LocationType::GameRoot;
|
||||
|
||||
// do we already have a slash? as in the case of a root directory install
|
||||
if (root.path.back() != DIR_SEPARATOR_CHAR) {
|
||||
root.path += DIR_SEPARATOR_STR; // put trailing backslash on for easier path construction
|
||||
}
|
||||
|
||||
mod_roots.push_back(root);
|
||||
|
||||
//======================================================
|
||||
// Next, check any VP files under the current directory.
|
||||
build_pack_list(mod_roots, root.path, root.location_type, root.user_location);
|
||||
|
||||
return mod_roots;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "cfile/cfile.h"
|
||||
|
||||
namespace cfile {
|
||||
|
||||
SCP_vector<ModRoot> getModRootsFromModCmdline(const SCP_string& content_root, const char* mod_cmdline);
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _CFILESYSTEM_H
|
||||
#define _CFILESYSTEM_H
|
||||
|
||||
#include "cfile/cfile.h"
|
||||
|
||||
// Builds a list of all the files
|
||||
void cf_build_secondary_filelist(const SCP_vector<cfile::ModRoot>& modRoots);
|
||||
void cf_free_secondary_filelist();
|
||||
|
||||
// Internal stuff
|
||||
typedef struct cf_pathtype {
|
||||
int index; // To verify that the CF_TYPE define is correctly indexed into this array
|
||||
const char* path; // Path relative to FreeSpace root, has ending backslash.
|
||||
const char* extensions; // Extensions used in this pathtype, separated by spaces
|
||||
int parent_index; // Index of this directory's parent. Used for creating directories when writing.
|
||||
} cf_pathtype;
|
||||
|
||||
// During cfile_init, verify that Pathtypes[n].index == n for each item
|
||||
extern cf_pathtype Pathtypes[CF_MAX_PATH_TYPES];
|
||||
|
||||
bool cf_check_location_flags(uint32_t check_flags, uint32_t desired_flags);
|
||||
|
||||
// Returns the default storage path for files given a
|
||||
// particular pathtype. In other words, the path to
|
||||
// the unpacked, non-cd'd, stored on hard drive path.
|
||||
// If filename isn't null it will also tack the filename
|
||||
// on the end, creating a completely valid filename.
|
||||
// Input: pathtype - CF_TYPE_??
|
||||
// path_max - Maximum characters in the path
|
||||
// filename - optional, if set, tacks the filename onto end of path.
|
||||
// Output: path - Fully qualified pathname.
|
||||
//Returns 0 if result would be too long (invalid result)
|
||||
int cf_create_default_path_string(char* path, uint path_max, int pathtype, const char* filename = nullptr,
|
||||
bool localize = false, uint32_t location_flags = CF_LOCATION_ALL);
|
||||
int cf_create_default_path_string(SCP_string& path, int pathtype, const char* filename = nullptr, bool localize = false,
|
||||
uint32_t location_flags = CF_LOCATION_ALL);
|
||||
|
||||
#endif //_CFILESYSTEM_H
|
||||
@@ -1,19 +0,0 @@
|
||||
|
||||
add_executable(cfilearchiver EXCLUDE_FROM_ALL cfilearchiver.cpp)
|
||||
|
||||
ADD_DEFINITIONS(-DNO_SAFE_STRINGS)
|
||||
include_directories(${CODE_HEADERS})
|
||||
|
||||
set_target_properties(cfilearchiver
|
||||
PROPERTIES
|
||||
FOLDER "FSOTools"
|
||||
)
|
||||
TARGET_LINK_LIBRARIES(cfilearchiver PUBLIC sdl2)
|
||||
TARGET_INCLUDE_DIRECTORIES(cfilearchiver PUBLIC ${GENERATED_SOURCE_DIR})
|
||||
TARGET_INCLUDE_DIRECTORIES(cfilearchiver PUBLIC ${GENERATED_SOURCE_DIR}/code)
|
||||
|
||||
IF(MSVC)
|
||||
set_target_properties(cfilearchiver PROPERTIES
|
||||
COMPILE_DEFINITIONS_DEBUG "_DEBUG;PDB_DEBUGGING=1"
|
||||
)
|
||||
ENDIF(MSVC)
|
||||
@@ -1,411 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
||||
*
|
||||
* All source code herein is the property of Volition, Inc. You may not sell
|
||||
* or otherwise commercially exploit the source or things you created based on the
|
||||
* source.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#include <conio.h>
|
||||
#else
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "cfile/cfile.h"
|
||||
|
||||
|
||||
static int data_error;
|
||||
static int no_dir;
|
||||
|
||||
// right out of pstypes.h but we don't want to use the INTEL_INT macro here
|
||||
// since it would require SDL which isn't used on WIN32 platforms
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define INT_SWAP(x) ( \
|
||||
(x << 24) | \
|
||||
(((ulong)x) >> 24) | \
|
||||
((x & 0x0000ff00) << 8) | \
|
||||
((x & 0x00ff0000) >> 8) \
|
||||
)
|
||||
#else
|
||||
#define INT_SWAP(x) (x)
|
||||
#endif
|
||||
|
||||
|
||||
size_t fswrite_int(int *wint, FILE *stream)
|
||||
{
|
||||
int tmp = *wint;
|
||||
tmp = INT_SWAP(tmp);
|
||||
|
||||
return fwrite(&tmp, 1, sizeof(int), stream);
|
||||
}
|
||||
|
||||
unsigned int Total_size=16; // Start with size of header
|
||||
unsigned int Num_files =0;
|
||||
FILE *fp_out = NULL;
|
||||
FILE *fp_out_hdr = NULL;
|
||||
|
||||
typedef struct vp_header {
|
||||
char id[4];
|
||||
int version;
|
||||
int index_offset;
|
||||
int num_files;
|
||||
} vp_header;
|
||||
|
||||
//vp_header Vp_header;
|
||||
|
||||
char archive_dat[1024];
|
||||
char archive_hdr[1024];
|
||||
|
||||
#define BLOCK_SIZE (1024*1024)
|
||||
#define VERSION_NUMBER 2;
|
||||
|
||||
char tmp_data[BLOCK_SIZE]; // 1 MB
|
||||
|
||||
void write_header()
|
||||
{
|
||||
int ver = VERSION_NUMBER;
|
||||
|
||||
fseek(fp_out, 0, SEEK_SET);
|
||||
fwrite("VPVP", 1, 4, fp_out);
|
||||
fswrite_int(&ver, fp_out);
|
||||
fswrite_int((int*)&Total_size, fp_out);
|
||||
fswrite_int((int*)&Num_files, fp_out);
|
||||
}
|
||||
|
||||
int write_index(char *hf, char *df)
|
||||
{
|
||||
FILE *h = NULL, *d = NULL;
|
||||
unsigned int i;
|
||||
|
||||
h = fopen(hf, "rb");
|
||||
d = fopen(df, "a+b");
|
||||
|
||||
if ( (h == NULL) || (d == NULL) )
|
||||
{
|
||||
if ( h )
|
||||
fclose( h );
|
||||
if ( d )
|
||||
fclose( d );
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < Num_files; i++) {
|
||||
fread(tmp_data, 32+4+4+4, 1, h);
|
||||
fwrite(tmp_data, 32+4+4+4, 1, d);
|
||||
}
|
||||
|
||||
fclose(h);
|
||||
fclose(d);
|
||||
|
||||
unlink(hf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void pack_file( char *filespec, char *filename, int filesize, _fs_time_t time_write )
|
||||
{
|
||||
char path[1024];
|
||||
|
||||
if ( strstr( filename, ".vp" )) {
|
||||
// Don't pack yourself!!
|
||||
return;
|
||||
}
|
||||
|
||||
if ( strstr( filename, ".hdr" )) {
|
||||
// Don't pack yourself!!
|
||||
return;
|
||||
}
|
||||
|
||||
if ( filesize == 0 ) {
|
||||
// Don't pack 0 length files, screws up directory structure!
|
||||
return;
|
||||
}
|
||||
|
||||
if ( strlen(filename) > 31 ) {
|
||||
printf( "Filename '%s' too long! Skipping...\n", filename );
|
||||
return;
|
||||
}
|
||||
|
||||
memset( path, 0, sizeof(path) );
|
||||
strcpy_s( path, filename );
|
||||
|
||||
fswrite_int( (int*)&Total_size, fp_out_hdr );
|
||||
fswrite_int( &filesize, fp_out_hdr );
|
||||
fwrite( &path, 1, 32, fp_out_hdr );
|
||||
fswrite_int( (int*)&time_write, fp_out_hdr );
|
||||
|
||||
Total_size += filesize;
|
||||
Num_files++;
|
||||
|
||||
printf( "Packing %s%s%s...", filespec, DIR_SEPARATOR_STR, filename );
|
||||
|
||||
sprintf( path, "%s%s%s", filespec, DIR_SEPARATOR_STR, filename );
|
||||
|
||||
|
||||
FILE *fp = fopen( path, "rb" );
|
||||
|
||||
if ( fp == NULL ) {
|
||||
printf( "Error opening '%s'\n", path );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int nbytes, nbytes_read=0;
|
||||
|
||||
do {
|
||||
nbytes = fread( tmp_data, 1, BLOCK_SIZE, fp );
|
||||
if ( nbytes > 0 ) {
|
||||
fwrite( tmp_data, 1, nbytes, fp_out );
|
||||
nbytes_read += nbytes;
|
||||
|
||||
}
|
||||
} while( nbytes > 0 );
|
||||
|
||||
fclose(fp);
|
||||
|
||||
printf( " %d bytes\n", nbytes_read );
|
||||
}
|
||||
|
||||
// This function adds a directory marker to the header file
|
||||
void add_directory( char * dirname)
|
||||
{
|
||||
char path[256];
|
||||
char *pathptr = path;
|
||||
char *tmpptr;
|
||||
int i = 0;
|
||||
|
||||
strcpy_s(path, dirname);
|
||||
|
||||
fswrite_int( (int*)&Total_size, fp_out_hdr);
|
||||
fswrite_int( &i, fp_out_hdr);
|
||||
|
||||
// strip out any directories that this dir is a subdir of
|
||||
while ( (tmpptr = strchr(pathptr, DIR_SEPARATOR_CHAR)) != NULL ) {
|
||||
pathptr = tmpptr+1;
|
||||
}
|
||||
|
||||
fwrite(pathptr, 1, 32, fp_out_hdr);
|
||||
fswrite_int( &i, fp_out_hdr); // timestamp = 0
|
||||
|
||||
Num_files++;
|
||||
}
|
||||
|
||||
void pack_directory( char * filespec)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
int find_handle;
|
||||
_finddata_t find;
|
||||
#endif
|
||||
char tmp[512];
|
||||
char tmp1[512];
|
||||
char *ts;
|
||||
|
||||
// strip trailing slash
|
||||
ts = filespec + (strlen(filespec) - 1);
|
||||
while ( (*ts == DIR_SEPARATOR_CHAR) && (ts > filespec) )
|
||||
*ts = '\0';
|
||||
|
||||
strcpy_s( tmp1, filespec );
|
||||
|
||||
add_directory(filespec);
|
||||
strcat( tmp1, DIR_SEPARATOR_STR"*.*" );
|
||||
|
||||
printf( "In dir '%s'\n", tmp1 );
|
||||
|
||||
#ifdef _WIN32
|
||||
find_handle = _findfirst( tmp1, &find );
|
||||
if( find_handle != -1 ) {
|
||||
if ( find.attrib & _A_SUBDIR ) {
|
||||
if (strcmp( "..", find.name) && strcmp( ".", find.name) && strcmp( ".svn", find.name)) {
|
||||
strcpy_s( tmp, filespec );
|
||||
strcat( tmp, "\\" );
|
||||
strcat( tmp, find.name );
|
||||
pack_directory(tmp);
|
||||
}
|
||||
} else {
|
||||
pack_file( filespec, find.name, find.size, find.time_write );
|
||||
}
|
||||
|
||||
while( !_findnext( find_handle, &find ) ) {
|
||||
if ( find.attrib & _A_SUBDIR ) {
|
||||
if (strcmp( "..", find.name) && strcmp( ".", find.name) && strcmp( ".svn", find.name)) {
|
||||
strcpy_s( tmp, filespec );
|
||||
strcat( tmp, "\\" );
|
||||
strcat( tmp, find.name );
|
||||
pack_directory(tmp);
|
||||
|
||||
}
|
||||
} else {
|
||||
pack_file( filespec, find.name, find.size, find.time_write );
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
DIR *dirp;
|
||||
struct dirent *dir;
|
||||
|
||||
dirp = opendir (filespec);
|
||||
if ( dirp ) {
|
||||
while ((dir = readdir(dirp)) != NULL) {
|
||||
|
||||
char fn[MAX_PATH];
|
||||
snprintf(fn, MAX_PATH-1, "%s/%s", filespec, dir->d_name);
|
||||
fn[MAX_PATH-1] = 0;
|
||||
|
||||
struct stat buf;
|
||||
if (stat(fn, &buf) == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( (strcmp(dir->d_name, ".") == 0) || (strcmp(dir->d_name, "..") == 0) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( (strcmp(dir->d_name, ".svn") == 0) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (S_ISDIR(buf.st_mode)) {
|
||||
strcpy_s( tmp, filespec );
|
||||
strcat( tmp, "/" );
|
||||
strcat( tmp, dir->d_name );
|
||||
pack_directory(tmp);
|
||||
} else {
|
||||
pack_file( filespec, dir->d_name, buf.st_size, buf.st_mtime );
|
||||
}
|
||||
}
|
||||
closedir(dirp);
|
||||
} else {
|
||||
printf("Error: Source directory does not exist!\n");
|
||||
no_dir = 1;
|
||||
}
|
||||
#endif
|
||||
add_directory("..");
|
||||
}
|
||||
|
||||
int verify_directory( char *filespec )
|
||||
{
|
||||
char *ts;
|
||||
char *dd;
|
||||
|
||||
// strip trailing '/'
|
||||
ts = filespec+(strlen(filespec)-1);
|
||||
while ( (*ts == DIR_SEPARATOR_CHAR) && (ts > filespec) )
|
||||
*ts = '\0';
|
||||
|
||||
// make sure last directory is named "data", ignoring case
|
||||
dd = filespec + (strlen(filespec) - 4);
|
||||
if ( stricmp( dd, "data" ) )
|
||||
data_error = 1;
|
||||
|
||||
return data_error;
|
||||
}
|
||||
|
||||
void print_instructions()
|
||||
{
|
||||
printf("Creates a vp archive out of a FreeSpace data tree.\n\n");
|
||||
printf("Usage: cfilearchiver archive_name src_dir\n");
|
||||
#ifdef _WIN32
|
||||
printf("Example: cfilearchiver freespace c:\\freespace\\data\n");
|
||||
#else
|
||||
printf("Example: cfilearchiver freespace /tmp/freespace/data\n\n");
|
||||
#endif
|
||||
printf("Creates an archive named freespace out of the freespace data tree\n");
|
||||
printf("For information about the FS2 directory structure, please consult\n");
|
||||
printf("http://www.hard-light.net/wiki/index.php/FS2_Data_Structure\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// we end up #include'ing SDL.h which on Windows and Mac will redefine main() which is something
|
||||
// that we don't want since we don't actually link against SDL, this solves the problem...
|
||||
#ifdef main
|
||||
#undef main
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[] )
|
||||
{
|
||||
char archive[1024];
|
||||
char *p;
|
||||
|
||||
if ( argc < 3 ) {
|
||||
print_instructions();
|
||||
}
|
||||
|
||||
strcpy_s( archive, argv[1] );
|
||||
p = strchr( archive, '.' );
|
||||
if (p) *p = 0; // remove extension
|
||||
|
||||
strcpy_s( archive_dat, archive );
|
||||
strcat( archive_dat, ".vp" );
|
||||
|
||||
strcpy_s( archive_hdr, archive );
|
||||
strcat( archive_hdr, ".hdr" );
|
||||
|
||||
fp_out = fopen( archive_dat, "wb" );
|
||||
if ( !fp_out ) {
|
||||
printf( "Couldn't open '%s'!\n", archive_dat );
|
||||
#ifdef _WIN32
|
||||
printf( "Press any key to exit...\n" );
|
||||
getch();
|
||||
return 1;
|
||||
#else
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
fp_out_hdr = fopen( archive_hdr, "wb" );
|
||||
if ( !fp_out_hdr ) {
|
||||
printf( "Couldn't open '%s'!\n", archive_hdr );
|
||||
#ifdef _WIN32
|
||||
printf( "Press any key to exit...\n" );
|
||||
getch();
|
||||
return 1;
|
||||
#else
|
||||
exit(2);
|
||||
#endif
|
||||
}
|
||||
|
||||
if ( verify_directory( argv[2] ) != 0 ) {
|
||||
printf("Warning! Last directory must be named \"data\" (not case sensitive)\n");
|
||||
exit(3);
|
||||
}
|
||||
|
||||
write_header();
|
||||
|
||||
pack_directory( argv[2] );
|
||||
|
||||
// in case the directory doesn't exist
|
||||
if ( no_dir )
|
||||
exit(4);
|
||||
|
||||
write_header();
|
||||
|
||||
fclose(fp_out);
|
||||
fclose(fp_out_hdr);
|
||||
|
||||
printf( "Data files written, appending index...\n" );
|
||||
|
||||
if (!write_index(archive_hdr, archive_dat)) {
|
||||
printf("Error appending index!\n");
|
||||
#ifdef _WIN32
|
||||
printf("Press any key to exit...\n");
|
||||
getch();
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf( "%d total KB.\n", Total_size/1024 );
|
||||
return 0;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
|
||||
add_executable(cfileextractor EXCLUDE_FROM_ALL cfileextractor.cpp)
|
||||
|
||||
ADD_DEFINITIONS(-DNO_SAFE_STRINGS)
|
||||
include_directories(${CODE_HEADERS})
|
||||
|
||||
set_target_properties(cfileextractor
|
||||
PROPERTIES
|
||||
FOLDER "FSOTools"
|
||||
)
|
||||
TARGET_LINK_LIBRARIES(cfileextractor PUBLIC sdl2)
|
||||
TARGET_INCLUDE_DIRECTORIES(cfileextractor PUBLIC ${GENERATED_SOURCE_DIR})
|
||||
TARGET_INCLUDE_DIRECTORIES(cfileextractor PUBLIC ${GENERATED_SOURCE_DIR}/code)
|
||||
|
||||
IF(MSVC)
|
||||
set_target_properties(cfileextractor PROPERTIES
|
||||
COMPILE_DEFINITIONS_DEBUG "_DEBUG;PDB_DEBUGGING=1"
|
||||
)
|
||||
ENDIF(MSVC)
|
||||
@@ -1,497 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Taylor Richards
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "cfile/cfile.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// GLOBAL FUNCTIONS AND VARIABLES
|
||||
//
|
||||
|
||||
// right out of pstypes.h but we don't want to use the INTEL_INT macro here
|
||||
// since it would require SDL which isn't used on WIN32 platforms
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define INT_SWAP(x) ( \
|
||||
(x << 24) | \
|
||||
(((ulong)x) >> 24) | \
|
||||
((x & 0x0000ff00) << 8) | \
|
||||
((x & 0x00ff0000) >> 8) \
|
||||
)
|
||||
#else
|
||||
#define INT_SWAP(x) (x)
|
||||
#endif
|
||||
|
||||
FILE *fp_in = NULL;
|
||||
FILE *fp_out = NULL;
|
||||
|
||||
#ifndef MAX_PATH
|
||||
#define MAX_PATH 255
|
||||
#endif
|
||||
|
||||
char out_dir[MAX_PATH];
|
||||
|
||||
#define BLOCK_SIZE (1024*1024)
|
||||
|
||||
char tmp_data[BLOCK_SIZE]; // 1 MB
|
||||
|
||||
static int have_index = 0;
|
||||
static int have_header = 0;
|
||||
|
||||
#define ERR_NO_FP_IN 0
|
||||
#define ERR_NO_FP_OUT 1
|
||||
#define ERR_INVALID_VP 2
|
||||
#define ERR_NO_INDEX 3
|
||||
#define ERR_NO_HEADER 4
|
||||
#define ERR_PATH_TOO_LONG 5
|
||||
|
||||
typedef struct vp_header {
|
||||
char id[4]; // 'VPVP'
|
||||
int version;
|
||||
int index_offset; // offset where the file index starts, also a total file data size count
|
||||
int num_files; // number of files, including each step in the directory structure
|
||||
} vp_header;
|
||||
|
||||
vp_header VP_Header;
|
||||
|
||||
typedef struct vp_fileinfo {
|
||||
// stuff that is actually written to the VP
|
||||
int offset; // offset of where this file is in the VP
|
||||
int file_size; // size of file
|
||||
char file_name[CF_MAX_FILENAME_LENGTH]; // filename
|
||||
_fs_time_t write_time; // date/time in _fs_time_t type (a 32-bit version of time_t)
|
||||
|
||||
// not in the VP
|
||||
char file_path[CF_MAX_PATHNAME_LENGTH]; // file path, generated here and not actually in the VP on a per file basis
|
||||
|
||||
vp_fileinfo() {
|
||||
offset = 0;
|
||||
file_size = 0;
|
||||
file_name[0] = '\0';
|
||||
file_path[0] = '\0';
|
||||
write_time = 0;
|
||||
}
|
||||
|
||||
~vp_fileinfo() {}
|
||||
} vp_fileinfo;
|
||||
|
||||
SCP_vector<vp_fileinfo> VP_FileInfo;
|
||||
|
||||
// just like strlwr() but without actually including it here
|
||||
void lowercase(char *s)
|
||||
{
|
||||
if (s == NULL)
|
||||
return;
|
||||
|
||||
while (*s) {
|
||||
*s = tolower(*s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The useful stuff...
|
||||
//
|
||||
|
||||
void print_error(int err)
|
||||
{
|
||||
switch (err) {
|
||||
case ERR_NO_FP_IN:
|
||||
printf("ERROR: The input file (fp_in) is NULL! Exiting...\n");
|
||||
break;
|
||||
case ERR_NO_FP_OUT:
|
||||
printf("ERROR: The output file (fp_out) is NULL! Exiting...\n");
|
||||
break;
|
||||
case ERR_INVALID_VP:
|
||||
printf("ERROR: The specified VP file is invalid! Exiting...\n");
|
||||
break;
|
||||
case ERR_NO_INDEX:
|
||||
printf("ERROR: No file index is available! Exiting...\n");
|
||||
break;
|
||||
case ERR_NO_HEADER:
|
||||
printf("ERROR: No file header is available! Exiting...\n");
|
||||
break;
|
||||
case ERR_PATH_TOO_LONG:
|
||||
printf("ERROR: Path to output directory is too long! Exiting...\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void read_header()
|
||||
{
|
||||
fseek(fp_in, 0, SEEK_SET);
|
||||
fread(&VP_Header.id, 1, 4, fp_in);
|
||||
fread(&VP_Header.version, 1, sizeof(int), fp_in);
|
||||
fread(&VP_Header.index_offset, 1, sizeof(int), fp_in);
|
||||
fread(&VP_Header.num_files, 1, sizeof(int), fp_in);
|
||||
|
||||
VP_Header.version = INT_SWAP(VP_Header.version);
|
||||
VP_Header.index_offset = INT_SWAP(VP_Header.index_offset);
|
||||
VP_Header.num_files = INT_SWAP(VP_Header.num_files);
|
||||
|
||||
// check for a valid id (VPVP)
|
||||
if ( (VP_Header.id[0] != 'V') && (VP_Header.id[1] != 'P') && (VP_Header.id[2] != 'V') && (VP_Header.id[3] != 'P') )
|
||||
print_error(ERR_INVALID_VP);
|
||||
|
||||
// the index_offset needs to be greater than the size of vp_header at the very least and there should be at least one file
|
||||
if ( !(VP_Header.index_offset > (int)sizeof(vp_header)) || !(VP_Header.num_files > 1) )
|
||||
print_error(ERR_INVALID_VP);
|
||||
|
||||
|
||||
have_header = 1;
|
||||
}
|
||||
|
||||
void read_index(int lc = 0)
|
||||
{
|
||||
if (fp_in == NULL)
|
||||
print_error(ERR_NO_FP_IN);
|
||||
else if (!have_header)
|
||||
print_error(ERR_NO_HEADER);
|
||||
|
||||
int i;
|
||||
char path[CF_MAX_PATHNAME_LENGTH];
|
||||
|
||||
fseek(fp_in, VP_Header.index_offset, SEEK_SET);
|
||||
|
||||
memset(path, 0, CF_MAX_PATHNAME_LENGTH);
|
||||
|
||||
for ( i = 0; i < VP_Header.num_files; i++) {
|
||||
vp_fileinfo vpinfo;
|
||||
|
||||
fread(&vpinfo.offset, 1, sizeof(int), fp_in);
|
||||
fread(&vpinfo.file_size, 1, sizeof(int), fp_in);
|
||||
fread(&vpinfo.file_name, 1, CF_MAX_FILENAME_LENGTH, fp_in);
|
||||
fread(&vpinfo.write_time, 1, sizeof(_fs_time_t), fp_in);
|
||||
|
||||
vpinfo.offset = INT_SWAP(vpinfo.offset);
|
||||
vpinfo.file_size = INT_SWAP(vpinfo.file_size);
|
||||
vpinfo.write_time = INT_SWAP(vpinfo.write_time);
|
||||
|
||||
// check if it's a directory and if so then create a path to use for files
|
||||
if (vpinfo.file_size == 0) {
|
||||
// if we get a ".." then drop down in the path
|
||||
if (!strcmp(vpinfo.file_name, "..")) {
|
||||
char *s = strrchr(path, DIR_SEPARATOR_CHAR);
|
||||
|
||||
if (s)
|
||||
*s = '\0';
|
||||
|
||||
// skip, we don't want to add the ".." to the path
|
||||
continue;
|
||||
}
|
||||
|
||||
// don't add the very first directory separator character, easier to clean later
|
||||
if (path[0] != 0)
|
||||
strcat( path, DIR_SEPARATOR_STR );
|
||||
|
||||
// always make directory names lower case for ease of use
|
||||
lowercase( vpinfo.file_name );
|
||||
|
||||
strcat( path, vpinfo.file_name );
|
||||
} // it's a file then
|
||||
else {
|
||||
// lowercase the filename if wanted
|
||||
if (lc == 1)
|
||||
lowercase( vpinfo.file_name );
|
||||
|
||||
strcpy_s( vpinfo.file_path, path );
|
||||
VP_FileInfo.push_back(vpinfo);
|
||||
}
|
||||
}
|
||||
|
||||
have_index = 1;
|
||||
}
|
||||
|
||||
void extract_all_files(char *file)
|
||||
{
|
||||
if (fp_in == NULL)
|
||||
print_error(ERR_NO_FP_IN);
|
||||
else if (!have_header)
|
||||
print_error(ERR_NO_HEADER);
|
||||
else if (!have_index)
|
||||
print_error(ERR_NO_INDEX);
|
||||
|
||||
int status, m_error, nbytes, nbytes_remaining;
|
||||
char path[CF_MAX_PATHNAME_LENGTH+CF_MAX_FILENAME_LENGTH+1]; // path length + filename length + extra NULL
|
||||
char path2[CF_MAX_PATHNAME_LENGTH+CF_MAX_FILENAME_LENGTH+1]; // path length + filename length + extra NULL
|
||||
char *c;
|
||||
ubyte have_outdir = 0;
|
||||
|
||||
int out_len = strlen(out_dir);
|
||||
|
||||
if (out_len > 0)
|
||||
have_outdir = 1;
|
||||
|
||||
printf("VP file extractor - version 0.6\n");
|
||||
printf("\n");
|
||||
|
||||
if (have_outdir) {
|
||||
printf("Output directory: \"%s\"\n", out_dir);
|
||||
}
|
||||
|
||||
printf("Extracting: %s...\n", file);
|
||||
|
||||
for (size_t i = 0; i < VP_FileInfo.size(); i++) {
|
||||
// save the file path to a temp location and recursively make the needed directories
|
||||
if (have_outdir) {
|
||||
if ( (out_len + 1 + strlen(path)) > MAX_PATH-1 )
|
||||
print_error(ERR_PATH_TOO_LONG);
|
||||
|
||||
sprintf(path, "%s%s%s%s", out_dir, DIR_SEPARATOR_STR, VP_FileInfo[i].file_path, DIR_SEPARATOR_STR);
|
||||
} else {
|
||||
sprintf(path, "%s%s", VP_FileInfo[i].file_path, DIR_SEPARATOR_STR);
|
||||
}
|
||||
|
||||
c = &path[0];
|
||||
|
||||
while (c++) {
|
||||
c = strchr(c, DIR_SEPARATOR_CHAR);
|
||||
|
||||
if (c) {
|
||||
*c = '\0'; // NULL at DIR_SEP char
|
||||
|
||||
#ifdef _WIN32
|
||||
status = _mkdir(path);
|
||||
#else
|
||||
status = mkdir(path, 0777);
|
||||
#endif
|
||||
|
||||
m_error = errno;
|
||||
|
||||
if (status && (m_error != EEXIST) ) {
|
||||
printf("Cannot mkdir %s: %s\n", VP_FileInfo[i].file_path, strerror(m_error));
|
||||
continue;
|
||||
}
|
||||
|
||||
*c = DIR_SEPARATOR_CHAR; // replace DIR_SEP char
|
||||
}
|
||||
}
|
||||
|
||||
memset( path, 0, CF_MAX_PATHNAME_LENGTH+CF_MAX_FILENAME_LENGTH+1);
|
||||
|
||||
// start writing out the file
|
||||
fseek(fp_in, VP_FileInfo[i].offset, SEEK_SET);
|
||||
|
||||
sprintf(path, "%s%s%s", VP_FileInfo[i].file_path, DIR_SEPARATOR_STR, VP_FileInfo[i].file_name);
|
||||
|
||||
// this is cheap, I know.
|
||||
if (have_outdir) {
|
||||
if ( (out_len + 1 + strlen(path)) > MAX_PATH-1 )
|
||||
print_error(ERR_PATH_TOO_LONG);
|
||||
|
||||
sprintf(path2, "%s%s%s", out_dir, DIR_SEPARATOR_STR, path);
|
||||
} else {
|
||||
strcpy_s(path2, path);
|
||||
}
|
||||
|
||||
fp_out = fopen(path2, "wb");
|
||||
|
||||
printf(" %s ... ", path);
|
||||
|
||||
if (fp_out == NULL) {
|
||||
printf("can't create file!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
nbytes_remaining = VP_FileInfo[i].file_size;
|
||||
|
||||
while ( nbytes_remaining > 0 ) {
|
||||
nbytes = fread( tmp_data, 1, MIN(BLOCK_SIZE, nbytes_remaining), fp_in );
|
||||
|
||||
if (nbytes > 0) {
|
||||
fwrite( tmp_data, 1, nbytes, fp_out );
|
||||
nbytes_remaining -= nbytes;
|
||||
}
|
||||
}
|
||||
|
||||
printf("done!\n");
|
||||
|
||||
fclose(fp_out);
|
||||
fp_out = NULL;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// TODO: the formatting of this is a bit loco but I don't care enough to make it better...
|
||||
void list_all_files(char *file)
|
||||
{
|
||||
char out_time[20];
|
||||
float one_k = 1024.0f;
|
||||
float one_m = 1048576.0f;
|
||||
char m;
|
||||
float div_by;
|
||||
time_t plat_time;
|
||||
|
||||
// if we don't have an index then bail
|
||||
if (!have_index)
|
||||
print_error(ERR_NO_INDEX);
|
||||
|
||||
|
||||
printf("VP file extractor - version 0.6\n");
|
||||
printf("\n");
|
||||
printf("%s:\n", file);
|
||||
printf("\n");
|
||||
|
||||
printf(" Name Size Offset Date/Time Path\n");
|
||||
printf("-------------------------------------------------------------------------------\n");
|
||||
for (size_t i = 0; i < VP_FileInfo.size(); i++) {
|
||||
plat_time = VP_FileInfo[i].write_time; // gets rid of some platform strangeness this way
|
||||
strftime(out_time, 32, "%F %H:%M", localtime(&plat_time)); // YYYY-mm-dd HH:mm (ISO 8601 date format, 24-hr time)
|
||||
|
||||
if (VP_FileInfo[i].file_size > (int)one_m) {
|
||||
m = 'M';
|
||||
div_by = one_m;
|
||||
} else {
|
||||
m = 'K';
|
||||
div_by = one_k;
|
||||
}
|
||||
|
||||
int len = strlen( VP_FileInfo[i].file_name );
|
||||
printf("%s %*.1f%c %10i %18s %3s%s\n", VP_FileInfo[i].file_name, 33 - len, (float)VP_FileInfo[i].file_size/div_by, m, VP_FileInfo[i].offset, out_time, DIR_SEPARATOR_STR, VP_FileInfo[i].file_path);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
// we use the vector size here since VP_Header.num_files would include each entry
|
||||
// in the directory tree as well as individual files and that artificially inflates
|
||||
// the number of files that we show or would extract
|
||||
printf("Total files: %i\n", (int)VP_FileInfo.size());
|
||||
|
||||
// yeah, I'm just that cheap
|
||||
if (VP_Header.index_offset > (int)one_m) {
|
||||
m = 'M';
|
||||
div_by = one_m;
|
||||
} else {
|
||||
m = 'K';
|
||||
div_by = one_k;
|
||||
}
|
||||
|
||||
printf("Total size: %.1f%c\n", (float)VP_Header.index_offset/div_by, m);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void help()
|
||||
{
|
||||
printf("VP file extractor - version 0.6\n");
|
||||
printf("\n");
|
||||
printf("Usage: cfileextractor [-x | -l] [-L] [-o <dir>] <vp_filename>\n");
|
||||
printf("\n");
|
||||
printf(" Commands (only one at the time):\n");
|
||||
printf(" -x | --extract Extract all files into current directory.\n");
|
||||
printf(" -l | --list List all files in VP archive.\n");
|
||||
printf(" -h | --help Show this help text.\n");
|
||||
printf("\n");
|
||||
printf(" Options:\n");
|
||||
printf(" -L | --lowercase Force all filenames to be lower case.\n");
|
||||
printf(" -o <dir> Extract files to <dir> instead of current directory.\n");
|
||||
printf(" NOTE: No spaces allowed, enclose path in \" \" if needed.\n");
|
||||
printf("\n");
|
||||
printf(" (No command specified will list all files in the VP archive.)\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// we end up #include'ing SDL.h which on Windows and Mac will redefine main() which is something
|
||||
// that we don't want since we don't actually link against SDL, this solves the problem...
|
||||
#ifdef main
|
||||
#undef main
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int extract = 0, lc = 0, list = 0;
|
||||
|
||||
if (argc < 2) {
|
||||
help();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
|
||||
help();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// the last option should always be the VP file that we want
|
||||
fp_in = fopen(argv[argc-1], "rb");
|
||||
|
||||
if (fp_in == NULL)
|
||||
print_error(ERR_NO_FP_IN);
|
||||
|
||||
// if the header is invalid then read_header() should exit us out
|
||||
read_header();
|
||||
|
||||
memset(out_dir, 0, MAX_PATH);
|
||||
|
||||
// TODO: add filter based extraction
|
||||
for (int i = 1; i < argc-1; i++) {
|
||||
if (!strcmp(argv[i], "-x") || !strcmp(argv[i], "--extract")) {
|
||||
if (list) {
|
||||
help();
|
||||
exit(0);
|
||||
}
|
||||
extract = 1;
|
||||
} else if (!strcmp(argv[i], "-L") || !strcmp(argv[i], "--lowercase")) {
|
||||
lc = 1;
|
||||
} else if (!strcmp(argv[i], "-l") || !strcmp(argv[i], "--list")) {
|
||||
if (extract) {
|
||||
help();
|
||||
exit(0);
|
||||
}
|
||||
list = 1;
|
||||
} else if ( !strcmp(argv[i], "-o") && (i+1 < argc) && (argv[i+1][0] != '-') ) {
|
||||
strncpy(out_dir, argv[i+1], MAX_PATH-1);
|
||||
i++; // have to increment "i" past the output directory
|
||||
} else {
|
||||
help();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// read the file index, make all filenames lowercase if wanted
|
||||
read_index( lc );
|
||||
|
||||
if (extract) {
|
||||
extract_all_files( argv[argc-1] );
|
||||
return 0;
|
||||
} else if (list) {
|
||||
list_all_files( argv[argc-1] );
|
||||
return 0;
|
||||
} else {
|
||||
// if only -L is specified or no command is specified then just list files
|
||||
list_all_files( argv[argc-1] );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
Loaded 100 of 2564 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user