mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-09 17:29:21 -10:00
Compare commits
573
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de4e56ecf2 | ||
|
|
dc2f6da813 | ||
|
|
06921aebed | ||
|
|
083914aa5c | ||
|
|
80b06c37fe | ||
|
|
d7002641c3 | ||
|
|
4d367a2b59 | ||
|
|
1250ecbc46 | ||
|
|
da15bc2802 | ||
|
|
91bf7b553a | ||
|
|
55b77cb663 | ||
|
|
78e7d23c14 | ||
|
|
b6ae697fad | ||
|
|
75f94950bf | ||
|
|
8b6fe0a934 | ||
|
|
f63c11ebaf | ||
|
|
08c1c05f82 | ||
|
|
6d73de8fa7 | ||
|
|
03ce03eb81 | ||
|
|
af0e49df57 | ||
|
|
d89ab49d32 | ||
|
|
b2ef25e20f | ||
|
|
6fcf291df4 | ||
|
|
60fab1c4a1 | ||
|
|
0f85bbf32d | ||
|
|
59b79e2191 | ||
|
|
eaf2f618b5 | ||
|
|
f3ce04be0c | ||
|
|
b98b9471d9 | ||
|
|
9b00a932d5 | ||
|
|
2f88edb93f | ||
|
|
8fc14354e9 | ||
|
|
d7983f2827 | ||
|
|
8e962e495c | ||
|
|
1aa542be2d | ||
|
|
fb444f9d91 | ||
|
|
d95bc2dd54 | ||
|
|
1e31a8d5fd | ||
|
|
2feca8994d | ||
|
|
28247ba65d | ||
|
|
05b7ac47c3 | ||
|
|
780fdf721e | ||
|
|
47c850c7fd | ||
|
|
c6892d03c3 | ||
|
|
82c69995f0 | ||
|
|
4d2adee166 | ||
|
|
a18e29cc8a | ||
|
|
065fb5acee | ||
|
|
27a6210f96 | ||
|
|
c6e83d23f5 | ||
|
|
72513e29b2 | ||
|
|
6d67c16507 | ||
|
|
910a652b3c | ||
|
|
ea77410037 | ||
|
|
96ddb301b6 | ||
|
|
fc653fad90 | ||
|
|
db74d7c81b | ||
|
|
675fe72ef0 | ||
|
|
e70b3d49b7 | ||
|
|
a404689894 | ||
|
|
646b0f7209 | ||
|
|
5253e4be23 | ||
|
|
4d2178fafc | ||
|
|
492a83e6d5 | ||
|
|
b08314cf60 | ||
|
|
28145abde9 | ||
|
|
6f90b24f72 | ||
|
|
fe943a65e8 | ||
|
|
3a25e1fbc3 | ||
|
|
f3bda542d6 | ||
|
|
32b8560858 | ||
|
|
86ca2006ea | ||
|
|
284fb6baa4 | ||
|
|
1490ad18a2 | ||
|
|
596bc4e686 | ||
|
|
d675276e28 | ||
|
|
c1216fd16d | ||
|
|
d9bc8fb796 | ||
|
|
b4d9d6c5fc | ||
|
|
b094c58081 | ||
|
|
53bd6908e1 | ||
|
|
0ecaa609f9 | ||
|
|
715c054de5 | ||
|
|
c67806dbd7 | ||
|
|
3b08d63b23 | ||
|
|
8a8c2da042 | ||
|
|
249241d7cd | ||
|
|
de22e06862 | ||
|
|
4f62612044 | ||
|
|
9ed51bc528 | ||
|
|
b1f52a25ea | ||
|
|
32594e6643 | ||
|
|
1726d8acb9 | ||
|
|
9bcee062ff | ||
|
|
df553bb7f5 | ||
|
|
56f2e2f7b8 | ||
|
|
01cb10d8b3 | ||
|
|
4d112da58d | ||
|
|
c11a798467 | ||
|
|
460f5e745d | ||
|
|
97c5c269a7 | ||
|
|
4a53c6771c | ||
|
|
35312feab6 | ||
|
|
621f51394b | ||
|
|
4896832612 | ||
|
|
3e4201ed30 | ||
|
|
4c87c307cc | ||
|
|
e8e8404741 | ||
|
|
f6dc1c6d93 | ||
|
|
b74b2f9b87 | ||
|
|
0f2cb88ec6 | ||
|
|
69cf8b1795 | ||
|
|
cfd408db86 | ||
|
|
3b1d75d9cf | ||
|
|
ba0d42ceb3 | ||
|
|
6faf2fe5b9 | ||
|
|
ab65e31e09 | ||
|
|
79e4106cc8 | ||
|
|
e215f56490 | ||
|
|
2c65382d50 | ||
|
|
8739264485 | ||
|
|
e4d62a3b9f | ||
|
|
e137f2c9dc | ||
|
|
8f82bcaad9 | ||
|
|
bc756e31d9 | ||
|
|
977a7d3eb6 | ||
|
|
b697f556e5 | ||
|
|
f0d9add1b2 | ||
|
|
7768c296b9 | ||
|
|
569704fb37 | ||
|
|
ee4486068d | ||
|
|
3d08aa8e32 | ||
|
|
9b0cb0fc92 | ||
|
|
6dec52fda7 | ||
|
|
023f427856 | ||
|
|
bc02f8319e | ||
|
|
3d54d952a5 | ||
|
|
7df18ec59d | ||
|
|
644e7dce7c | ||
|
|
3ae7d19cd5 | ||
|
|
78b25b20dd | ||
|
|
5a3cd8671e | ||
|
|
d2ab5d05ee | ||
|
|
8373ef1a61 | ||
|
|
b2527b43e8 | ||
|
|
bbfcecfab0 | ||
|
|
03edf4f6a9 | ||
|
|
b0928cd0f8 | ||
|
|
f0d8af0d34 | ||
|
|
80e7e1983a | ||
|
|
e76da47b31 | ||
|
|
932c9b9926 | ||
|
|
c816cd2b61 | ||
|
|
a7b7472c34 | ||
|
|
1fe70da946 | ||
|
|
5bacf1e9be | ||
|
|
5d3654ddbb | ||
|
|
0e22b1ec73 | ||
|
|
b8242601ec | ||
|
|
538b58aa7a | ||
|
|
600a3365ea | ||
|
|
19a1dbbc85 | ||
|
|
9ec7cecb93 | ||
|
|
8093f4595c | ||
|
|
a576ee49db | ||
|
|
e71e895ad6 | ||
|
|
c97b40e900 | ||
|
|
ab8e8359a6 | ||
|
|
5d3ebd0ece | ||
|
|
504a6b9670 | ||
|
|
df1f7bffb9 | ||
|
|
2febc16e2e | ||
|
|
5bc2d42cdc | ||
|
|
412c79862c | ||
|
|
e541dd5ab1 | ||
|
|
763fcd8267 | ||
|
|
d43b99cbac | ||
|
|
37a91e1be5 | ||
|
|
42e03cae83 | ||
|
|
6f7332c8fa | ||
|
|
80cf91417c | ||
|
|
b45a192416 | ||
|
|
4bb2c14293 | ||
|
|
592f69ec69 | ||
|
|
a106dedeb6 | ||
|
|
cdc5e33953 | ||
|
|
f8c3c76e18 | ||
|
|
e301fffae3 | ||
|
|
6d5d2e722d | ||
|
|
c092fa33e1 | ||
|
|
900675ad23 | ||
|
|
a953b27614 | ||
|
|
6aa89b3723 | ||
|
|
17ccfe4004 | ||
|
|
cce04bab70 | ||
|
|
ffbbdbd256 | ||
|
|
84052ee7e1 | ||
|
|
e1352060b5 | ||
|
|
a431760829 | ||
|
|
5bd7433ac4 | ||
|
|
60eaf14afc | ||
|
|
0afdb2a0cf | ||
|
|
86cced8eab | ||
|
|
dbe0252db4 | ||
|
|
4132176ece | ||
|
|
cd74221d33 | ||
|
|
d9a4dc52c0 | ||
|
|
8511152738 | ||
|
|
84f558db0b | ||
|
|
fa213a724f | ||
|
|
dfcbde86f7 | ||
|
|
2ecb253ed4 | ||
|
|
3a67162ae2 | ||
|
|
5f2ed6c85a | ||
|
|
86b47b4859 | ||
|
|
17362e3692 | ||
|
|
6ee3c14779 | ||
|
|
a612e7f7cc | ||
|
|
6ae1270e5c | ||
|
|
2c289a6212 | ||
|
|
38e74ee3cf | ||
|
|
4e24fb3d01 | ||
|
|
948ad76b14 | ||
|
|
245101b1a1 | ||
|
|
e2848ad0d5 | ||
|
|
688e00a25b | ||
|
|
49d3a947b8 | ||
|
|
5f6fc20360 | ||
|
|
b71be7efd2 | ||
|
|
5241d3e5d6 | ||
|
|
c9d66eed46 | ||
|
|
f5a1af00eb | ||
|
|
a50bf67386 | ||
|
|
d4dbd677db | ||
|
|
a14dcfa3ba | ||
|
|
311fec15d9 | ||
|
|
cc756e4126 | ||
|
|
bacae58ea5 | ||
|
|
51ba13035d | ||
|
|
58287ad666 | ||
|
|
c50087efdc | ||
|
|
979428649a | ||
|
|
650789a570 | ||
|
|
0e77013f2f | ||
|
|
d6fda5044f | ||
|
|
2ca982691b | ||
|
|
d8d21e9947 | ||
|
|
87ce001a4a | ||
|
|
1a7e8e6628 | ||
|
|
eaf32daf25 | ||
|
|
6d6eca7a9f | ||
|
|
d3b38f45fd | ||
|
|
c4a676d756 | ||
|
|
f93548ab56 | ||
|
|
aca2b9675f | ||
|
|
209b3b76b3 | ||
|
|
4fa1443c71 | ||
|
|
a5c79e4c86 | ||
|
|
0c0d19e3f1 | ||
|
|
4331065cc0 | ||
|
|
c9a72fadab | ||
|
|
f8da64d740 | ||
|
|
2095fc53f8 | ||
|
|
f4831809f7 | ||
|
|
2f130a23e4 | ||
|
|
4dda10b86d | ||
|
|
0a1ffcd4d5 | ||
|
|
4cf1bcf70f | ||
|
|
310c43d7ad | ||
|
|
0b205c2292 | ||
|
|
fb2d600837 | ||
|
|
3e3cf904ca | ||
|
|
ad4f6176ff | ||
|
|
b3f3bf1e83 | ||
|
|
aa642e5786 | ||
|
|
176c2d1911 | ||
|
|
28f531647f | ||
|
|
ddaf3bc6cf | ||
|
|
1a228a4e78 | ||
|
|
c2df109874 | ||
|
|
87c5720988 | ||
|
|
b5504dda99 | ||
|
|
1935d217d2 | ||
|
|
4ae67b9fa4 | ||
|
|
bb948e9b81 | ||
|
|
7ca3c314f8 | ||
|
|
5b85339839 | ||
|
|
b7d77e9484 | ||
|
|
483d1f2ac7 | ||
|
|
19d05db9ae | ||
|
|
f43b19db4f | ||
|
|
d13f325216 | ||
|
|
c28df9ccef | ||
|
|
c29fd8e53a | ||
|
|
fb6dfd345f | ||
|
|
d4902b65bd | ||
|
|
a427de28eb | ||
|
|
3c388b62d4 | ||
|
|
a192064403 | ||
|
|
76fd60b15e | ||
|
|
940f7553fd | ||
|
|
be05a7e194 | ||
|
|
31342ea18f | ||
|
|
17f63e6e39 | ||
|
|
d017ce7b03 | ||
|
|
e161af4826 | ||
|
|
ee1d9f5d1b | ||
|
|
916a3fd157 | ||
|
|
18dae9ce73 | ||
|
|
a746030901 | ||
|
|
68713b46b0 | ||
|
|
5efd2a64a4 | ||
|
|
9579810579 | ||
|
|
be650a790c | ||
|
|
22df09885e | ||
|
|
26132a2330 | ||
|
|
f17deb90c7 | ||
|
|
0168fe0303 | ||
|
|
9e208198f2 | ||
|
|
98bed89d6f | ||
|
|
d056a989ee | ||
|
|
33cc889f7f | ||
|
|
6a100272a8 | ||
|
|
689057a9b2 | ||
|
|
736ab4c964 | ||
|
|
a28e226ef4 | ||
|
|
e1d144e2b8 | ||
|
|
f0392474f2 | ||
|
|
b67b93ebfe | ||
|
|
43d0fa6248 | ||
|
|
b696903162 | ||
|
|
393e42a497 | ||
|
|
c48d533950 | ||
|
|
1afbe4a326 | ||
|
|
7d52d43667 | ||
|
|
c0ed1e3367 | ||
|
|
ec97c86756 | ||
|
|
c6369b7861 | ||
|
|
c4049b9597 | ||
|
|
e0ad9f7e26 | ||
|
|
c752f9b0de | ||
|
|
f6291adf01 | ||
|
|
b9041995f0 | ||
|
|
fb6bf6023a | ||
|
|
eff6f41a38 | ||
|
|
9151326b73 | ||
|
|
b21f3964b6 | ||
|
|
9da43ad34e | ||
|
|
7ad71a4a05 | ||
|
|
07534e4a6d | ||
|
|
3d84a9960e | ||
|
|
966335e367 | ||
|
|
3f7d279acf | ||
|
|
0357b6c922 | ||
|
|
e5215d9e29 | ||
|
|
77e202fbf7 | ||
|
|
568a30380b | ||
|
|
cae793e39f | ||
|
|
58b306d651 | ||
|
|
cda66d09c3 | ||
|
|
690c802921 | ||
|
|
b7c14f61bc | ||
|
|
e5e6f343ac | ||
|
|
698ab4729a | ||
|
|
7049c6c204 | ||
|
|
8cc423e036 | ||
|
|
6ee92d8583 | ||
|
|
2c7d2bcc18 | ||
|
|
6c123dd078 | ||
|
|
cd50a51f3e | ||
|
|
45f2f74d45 | ||
|
|
4fa4260a16 | ||
|
|
71836c1055 | ||
|
|
aea8dad1ae | ||
|
|
1cd0938cc3 | ||
|
|
688c652673 | ||
|
|
1582856b43 | ||
|
|
682bbab233 | ||
|
|
430baf7c21 | ||
|
|
fd8aa7a9cc | ||
|
|
34892555ec | ||
|
|
98431a15c0 | ||
|
|
dd278dc068 | ||
|
|
62528a483f | ||
|
|
6870f0114e | ||
|
|
cb8a589b77 | ||
|
|
baa51a5a91 | ||
|
|
9ec445ab40 | ||
|
|
3b1a1ac8da | ||
|
|
39074fa55c | ||
|
|
6bbee036f4 | ||
|
|
b078d52689 | ||
|
|
e3217b4a35 | ||
|
|
e954a46b1b | ||
|
|
06a2367008 | ||
|
|
6f60ee9b6e | ||
|
|
9f01ebf0a9 | ||
|
|
fbbe351f7d | ||
|
|
bfeffb2423 | ||
|
|
a44f5bbf78 | ||
|
|
09880e92d2 | ||
|
|
bf9706395d | ||
|
|
b6695d8921 | ||
|
|
9b7270cb6a | ||
|
|
b6fef13109 | ||
|
|
69e4ea8d33 | ||
|
|
41838ef544 | ||
|
|
1fc6f759c5 | ||
|
|
ce8a3db4dc | ||
|
|
4a39630c0f | ||
|
|
1dd15ac516 | ||
|
|
121ca3a482 | ||
|
|
72e49d82d6 | ||
|
|
b4ef32cfce | ||
|
|
621c3a7b7e | ||
|
|
af4bdecef9 | ||
|
|
67eb42a8c2 | ||
|
|
a585e05a8a | ||
|
|
97f3fca139 | ||
|
|
ef8a14a968 | ||
|
|
05f95ad428 | ||
|
|
1d26ed64a5 | ||
|
|
454fddb1dc | ||
|
|
c1cbe68df7 | ||
|
|
019466e928 | ||
|
|
73b252a0d8 | ||
|
|
99a1ffdb89 | ||
|
|
339feab15b | ||
|
|
5069acd288 | ||
|
|
ecef757af9 | ||
|
|
544c8c4e29 | ||
|
|
3c4b39057f | ||
|
|
1077a6f3a8 | ||
|
|
adc325e908 | ||
|
|
bc6433e0f9 | ||
|
|
b4137915e8 | ||
|
|
0a40e1f771 | ||
|
|
8a83ebec28 | ||
|
|
e497da9cf4 | ||
|
|
d02d32fbe4 | ||
|
|
228c5b83e2 | ||
|
|
c2c36177b8 | ||
|
|
5bb4df3a42 | ||
|
|
9982452c18 | ||
|
|
2b87cd9313 | ||
|
|
8dfaf84cc9 | ||
|
|
d3d7748f92 | ||
|
|
113e9340c1 | ||
|
|
5f49899343 | ||
|
|
85a256e2cb | ||
|
|
71b30d7846 | ||
|
|
ed437fdd8e | ||
|
|
2f9a8d7b3e | ||
|
|
9e40966dce | ||
|
|
335c24a895 | ||
|
|
7a8b629746 | ||
|
|
d04dee7ee0 | ||
|
|
282c8ddc5f | ||
|
|
e7e6b9977f | ||
|
|
955bf08fcd | ||
|
|
4ffe9dc5b3 | ||
|
|
17c522bbb0 | ||
|
|
fd5c718b48 | ||
|
|
0cf437e375 | ||
|
|
44dcfb88b6 | ||
|
|
6a99832a4d | ||
|
|
efad7a7dcc | ||
|
|
a2f9273979 | ||
|
|
a60df14d81 | ||
|
|
be92517b16 | ||
|
|
0867227293 | ||
|
|
e9ca17ea41 | ||
|
|
3fa1052dad | ||
|
|
3a82485a80 | ||
|
|
11d38421df | ||
|
|
b0c859557e | ||
|
|
15596f953e | ||
|
|
2adf52a493 | ||
|
|
4faf2f82f1 | ||
|
|
a3b508f136 | ||
|
|
a410cf1377 | ||
|
|
0c45d96a99 | ||
|
|
369e175e60 | ||
|
|
86103b5cc1 | ||
|
|
5c55a74655 | ||
|
|
1eade78654 | ||
|
|
7324c0d33b | ||
|
|
d8098a5ad5 | ||
|
|
02898a4a79 | ||
|
|
b9c77a48c9 | ||
|
|
fca72f67d1 | ||
|
|
a2fa243412 | ||
|
|
680b631ad6 | ||
|
|
9e0b98cd89 | ||
|
|
a6ed23d031 | ||
|
|
efa16a8fca | ||
|
|
4025b678bf | ||
|
|
d7a8bc55a3 | ||
|
|
3b6196144f | ||
|
|
9c7a55352d | ||
|
|
62a8b13b1a | ||
|
|
9fe56d6865 | ||
|
|
753332ff18 | ||
|
|
fc460dbb9c | ||
|
|
70ee3fbca7 | ||
|
|
f015ecdc03 | ||
|
|
196cc8b33d | ||
|
|
34c374737c | ||
|
|
2d5e090eb3 | ||
|
|
109ab785ee | ||
|
|
eba1ed6d75 | ||
|
|
038a24ae34 | ||
|
|
9e55654e72 | ||
|
|
13d662d76b | ||
|
|
1d8930625a | ||
|
|
a3aed79b71 | ||
|
|
62c6d99163 | ||
|
|
dfb0e298c5 | ||
|
|
b3a1a769b9 | ||
|
|
5dd0e90fca | ||
|
|
e64cd24715 | ||
|
|
393f9bdd48 | ||
|
|
369cafe1ad | ||
|
|
82b8c0a60e | ||
|
|
1280151d13 | ||
|
|
771585f95d | ||
|
|
c93b3e7615 | ||
|
|
b6cd140528 | ||
|
|
318f153012 | ||
|
|
86f899c844 | ||
|
|
f06b9ecf06 | ||
|
|
823c54a39d | ||
|
|
deaf116d38 | ||
|
|
1fc73f11b5 | ||
|
|
cb4028fd3d | ||
|
|
0b768d0460 | ||
|
|
174ab373e4 | ||
|
|
28bef36c74 | ||
|
|
abd089e88e | ||
|
|
a4a7c3bedf | ||
|
|
318108ac82 | ||
|
|
619398bbe4 | ||
|
|
89002e6b72 | ||
|
|
8171e513aa | ||
|
|
3cfab5ab88 | ||
|
|
d6c25f153f | ||
|
|
4e1564da16 | ||
|
|
2a5751ca0e | ||
|
|
f4c5852cfa | ||
|
|
f671ce4f8c | ||
|
|
fe2c3a5310 | ||
|
|
a68b95690c | ||
|
|
1fccddc705 | ||
|
|
6a490c0383 | ||
|
|
12bab704eb | ||
|
|
d63c6b9706 | ||
|
|
2886932968 | ||
|
|
bd5295ca76 | ||
|
|
8ee025636e | ||
|
|
56e150d68f | ||
|
|
17e490c424 | ||
|
|
7c84a26563 | ||
|
|
211e7d4094 | ||
|
|
84cab492b2 | ||
|
|
fc898d016b | ||
|
|
d651c9ae02 | ||
|
|
af23c5c900 | ||
|
|
edd446929b | ||
|
|
f2bc7caad9 | ||
|
|
11de2ae1fe | ||
|
|
5c75b683af | ||
|
|
446ed5f5b3 | ||
|
|
dc8b6a93d4 |
No files matched your search
@@ -0,0 +1,38 @@
|
||||
name: CI PS2
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: git.libretro.com:5050/libretro-infrastructure/libretro-build-ps2:latest
|
||||
options: --user root
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Compile Salamander
|
||||
run: |
|
||||
make -f Makefile.ps2.salamander -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
make -f Makefile.ps2.salamander -j$(getconf _NPROCESSORS_ONLN) release
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
make -f Makefile.ps2 -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
make -f Makefile.ps2 -j$(getconf _NPROCESSORS_ONLN) HAVE_STATIC_DUMMY=1 release
|
||||
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)"
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: RA-PS2-dummy-${{ steps.slug.outputs.sha8 }}
|
||||
path: |
|
||||
raboot.elf
|
||||
retroarchps2.elf
|
||||
@@ -0,0 +1,44 @@
|
||||
name: CI PSP
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
repository_dispatch:
|
||||
types: [run_build]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: git.libretro.com:5050/libretro-infrastructure/libretro-build-psp:latest
|
||||
options: --user root
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Compile bootstrap
|
||||
run: |
|
||||
cd bootstrap/psp1/kernel_functions_prx
|
||||
make -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
make -j$(getconf _NPROCESSORS_ONLN)
|
||||
|
||||
- name: Compile Salamander
|
||||
run: |
|
||||
make -f Makefile.psp1.salamander -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
make -f Makefile.psp1.salamander -j$(getconf _NPROCESSORS_ONLN)
|
||||
|
||||
- name: Compile RA
|
||||
run: |
|
||||
make -f Makefile.psp1 -j$(getconf _NPROCESSORS_ONLN) clean
|
||||
make -f Makefile.psp1 -j$(getconf _NPROCESSORS_ONLN) HAVE_STATIC_DUMMY=1
|
||||
|
||||
- name: Get short SHA
|
||||
id: slug
|
||||
run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)"
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: RA-PSP-dummy-${{ steps.slug.outputs.sha8 }}
|
||||
path: |
|
||||
kernel_functions.prx
|
||||
EBOOT.PBP
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
CROWDIN_API_KEY: ${{ secrets.CROWDIN_API_KEY }}
|
||||
run: |
|
||||
cd intl
|
||||
python3 -m pip install requests yaml
|
||||
python3 -m pip install requests PyYAML
|
||||
python3 crowdin_sync.py "$CROWDIN_API_KEY"
|
||||
git config user.name github-actions
|
||||
git config user.email [email protected]
|
||||
|
||||
@@ -15,7 +15,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Dependencies
|
||||
run: sudo apt-get install build-essential libxkbcommon-dev libx11-xcb-dev zlib1g-dev libfreetype6-dev libegl1-mesa-dev libgles2-mesa-dev libgbm-dev nvidia-cg-toolkit nvidia-cg-dev libavcodec-dev libsdl2-dev libsdl-image1.2-dev libxml2-dev yasm
|
||||
run: |
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install build-essential libxkbcommon-dev libx11-xcb-dev zlib1g-dev libfreetype6-dev libegl1-mesa-dev libgles2-mesa-dev libgbm-dev nvidia-cg-toolkit nvidia-cg-dev libavcodec-dev libsdl2-dev libsdl-image1.2-dev libxml2-dev yasm
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Configure
|
||||
|
||||
+1
-2
@@ -198,8 +198,7 @@ retroarch_switch.nro
|
||||
retroarch_switch.nso
|
||||
|
||||
# PS2
|
||||
ps2/irx/*.c
|
||||
*.irx
|
||||
*_irx.c
|
||||
|
||||
# Wayland
|
||||
gfx/common/wayland/idle-inhibit-unstable-v1.c
|
||||
|
||||
+78
-4
@@ -363,6 +363,29 @@ build-retroarch-osx-opengl-x64:
|
||||
XCPROJECT_NAME: RetroArch
|
||||
XCCONFIG: OpenGL_GitLabCI.xcconfig
|
||||
|
||||
build-retroarch-osx-ppc:
|
||||
stage: build
|
||||
artifacts:
|
||||
paths:
|
||||
- ${XCPROJECT_NAME}.zip
|
||||
- retroarch-repo/
|
||||
expire_in: 10 min
|
||||
dependencies: []
|
||||
variables:
|
||||
XCPROJECT_NAME: RetroArch
|
||||
XCCONFIG: OpenGL_GitLabCI.xcconfig
|
||||
tags:
|
||||
- macosx-legacy
|
||||
script:
|
||||
- xcodebuild -target RetroArch -configuration Release -project pkg/apple/RetroArch_PPC.xcodeproj ONLY_ACTIVE_ARCH=NO
|
||||
- pushd pkg/apple/build/Release/
|
||||
- ditto -c -k --sequesterRsrc --keepParent RetroArch.app ${XCPROJECT_NAME}.zip
|
||||
- popd
|
||||
- mv pkg/apple/build/Release/RetroArch.zip ${XCPROJECT_NAME}.zip
|
||||
- mkdir .retroarch-repo
|
||||
- "cp -r ./* .retroarch-repo"
|
||||
- "mv .retroarch-repo/ retroarch-repo/"
|
||||
|
||||
build-retroarch-ios-arm64:
|
||||
extends: .build-retroarch-macos-xcode
|
||||
variables:
|
||||
@@ -688,6 +711,8 @@ build-static-retroarch-dummy-vita:
|
||||
build-static-retroarch-ps2:
|
||||
image: $CI_SERVER_HOST:5050/libretro-infrastructure/libretro-build-ps2:latest
|
||||
stage: prepare-for-static-cores
|
||||
before_script:
|
||||
- export NUMPROC=$(($(nproc)/3))
|
||||
artifacts:
|
||||
paths:
|
||||
- retroarch-precompiled/
|
||||
@@ -698,8 +723,7 @@ build-static-retroarch-ps2:
|
||||
- build-static-retroarch-dummy-ps2
|
||||
script:
|
||||
# Allow failure since we don't have a core
|
||||
# PS2 makefile for now doesn't allow -jX so this is why is hardcoded to -j1
|
||||
- "make -f Makefile.ps2 -j1 ||:"
|
||||
- "make -f Makefile.ps2 -j$NUMPROC ||:"
|
||||
- "mkdir .retroarch-precompiled"
|
||||
- "cp -r ./* .retroarch-precompiled/"
|
||||
- "mv .retroarch-precompiled/ retroarch-precompiled/"
|
||||
@@ -708,8 +732,7 @@ build-static-retroarch-dummy-ps2:
|
||||
image: $CI_SERVER_HOST:5050/libretro-infrastructure/libretro-build-ps2:latest
|
||||
stage: build
|
||||
before_script:
|
||||
# PS2 doesn't allow to use -jX for now
|
||||
- export NUMPROC=1
|
||||
- export NUMPROC=$(($(nproc)/3))
|
||||
artifacts:
|
||||
paths:
|
||||
- raboot.elf
|
||||
@@ -718,6 +741,39 @@ build-static-retroarch-dummy-ps2:
|
||||
script:
|
||||
- "make -f Makefile.ps2.salamander -j$NUMPROC release"
|
||||
|
||||
build-static-retroarch-psl1ght:
|
||||
image: $CI_SERVER_HOST:5050/libretro-infrastructure/libretro-build-psl1ght:latest
|
||||
stage: prepare-for-static-cores
|
||||
before_script:
|
||||
- export NUMPROC=$(($(nproc)/3))
|
||||
artifacts:
|
||||
paths:
|
||||
- retroarch-precompiled/
|
||||
expire_in: 10 min
|
||||
dependencies: []
|
||||
needs:
|
||||
# Dummy build requires no core
|
||||
- build-static-retroarch-dummy-psl1ght
|
||||
script:
|
||||
# Allow failure since we don't have a core
|
||||
- "make -f Makefile.psl1ght -j$NUMPROC ||:"
|
||||
- "mkdir .retroarch-precompiled"
|
||||
- "cp -r ./* .retroarch-precompiled/"
|
||||
- "mv .retroarch-precompiled/ retroarch-precompiled/"
|
||||
|
||||
build-static-retroarch-dummy-psl1ght:
|
||||
image: $CI_SERVER_HOST:5050/libretro-infrastructure/libretro-build-psl1ght:latest
|
||||
stage: build
|
||||
before_script:
|
||||
- export NUMPROC=$(($(nproc)/3))
|
||||
artifacts:
|
||||
paths:
|
||||
- retroarch_psl1ght_salamander.elf
|
||||
expire_in: 10 min
|
||||
dependencies: []
|
||||
script:
|
||||
- "make -f Makefile.psl1ght.salamander -j$NUMPROC create-salamander"
|
||||
|
||||
build-static-retroarch-psp:
|
||||
image: $CI_SERVER_HOST:5050/libretro-infrastructure/libretro-build-psp:latest
|
||||
stage: prepare-for-static-cores
|
||||
@@ -762,6 +818,23 @@ build-static-retroarch-dummy-psp:
|
||||
- "cp -f pkg/psp1/ICON0.PNG ${MEDIA_PATH}/${CI_PROJECT_NAME}/pkg"
|
||||
- "cp -f pkg/psp1/PIC1.PNG ${MEDIA_PATH}/${CI_PROJECT_NAME}/pkg"
|
||||
|
||||
build-static-retroarch-djgpp:
|
||||
image: $CI_SERVER_HOST:5050/libretro-infrastructure/libretro-djgpp-build-container:latest
|
||||
stage: prepare-for-static-cores
|
||||
before_script:
|
||||
- export NUMPROC=$(($(nproc)/3))
|
||||
artifacts:
|
||||
paths:
|
||||
- retroarch-precompiled/
|
||||
expire_in: 10 min
|
||||
dependencies: []
|
||||
script:
|
||||
# Allow failure since we don't have a core
|
||||
- "make -f Makefile.dos -j$NUMPROC ||:"
|
||||
- "mkdir .retroarch-precompiled"
|
||||
- "cp -r ./* .retroarch-precompiled/"
|
||||
- "mv .retroarch-precompiled/ retroarch-precompiled/"
|
||||
|
||||
build-static-retroarch-ctr:
|
||||
image: $CI_SERVER_HOST:5050/libretro-infrastructure/libretro-build-devkitpro:latest
|
||||
stage: prepare-for-static-cores
|
||||
@@ -1004,6 +1077,7 @@ trigger_static-cores:
|
||||
- build-static-retroarch-libnx-aarch64
|
||||
- build-static-retroarch-vita
|
||||
- build-static-retroarch-ps2
|
||||
- build-static-retroarch-psl1ght
|
||||
- build-static-retroarch-psp
|
||||
- build-static-retroarch-ctr
|
||||
- build-static-retroarch-ctr-legacy
|
||||
|
||||
Vendored
+1
@@ -10,6 +10,7 @@
|
||||
"editor.renderWhitespace": "all",
|
||||
"editor.insertSpaces": true,
|
||||
"editor.formatOnSave": false,
|
||||
"editor.ruler": [80],
|
||||
"files.associations": {
|
||||
"*.h": "c",
|
||||
"*.in": "c",
|
||||
|
||||
@@ -350,6 +350,7 @@ reztek
|
||||
Richard Howell (rmaz)
|
||||
rlnilsen
|
||||
Rob Loach (RobLoach)
|
||||
Roberto V. Rampim (Cthulhu)
|
||||
Robin de Rooij (rrooij)
|
||||
Romain Gay (vikbez)
|
||||
Romain Graillot (notnotme)
|
||||
|
||||
+226
-9
@@ -1,5 +1,222 @@
|
||||
# Future
|
||||
|
||||
# 1.10.2
|
||||
- 3DS: Add a menu toggle for switching between old and new 3DS speeds, located in the 'Power Management' menu. Enabled by default, hidden on old 3DS devices.
|
||||
- AUDIO/MIXER: Free audio voices properly
|
||||
- CHEEVOS: Update to rcheevos 10.3.3
|
||||
- CHEEVOS: Support for Arduboy
|
||||
- CHEEVOS: Fix tab sequences in rich presence being turned into t character
|
||||
- CHEEVOS: Fix overflow when parsing float value that has more than 9 digits after the decimal
|
||||
- CHEEVOS: Fix memory mapping when disconnect mask breaks a region into multiple blocks
|
||||
- CORES: Enable manual selection of which cores are displayed in the 'Standalone Cores' menu
|
||||
- DATABASE/EXPLORE: Added more categories to the Explore menu
|
||||
- INPUT: Fix analog stick not working with 'Unified Menu Controls'
|
||||
- INPUT/MAPPING: Add 'Manage Remap Files' submenu + automatically save input remaps when closing content
|
||||
- INPUT/MAPPING: Add 'Reset Input Mapping' option to 'Manage Remap Files' menu
|
||||
- INPUT/MAPPING: Fix keyboard device remap nulling
|
||||
- IOS/IOS13+: Support a toolbar that allows toggling of onscreen keyboard and touch mouse
|
||||
- LIBRETRO: RETRO_ENVIRONMENT_SHUTDOWN fix - ensure core is properly unloaded when RETRO_ENVIRONMENT_SHUTDOWN is called
|
||||
- LIBRETRO: RETRO_ENVIRONMENT_SHUTDOWN fix - ensure menu stack is properly flushed when RETRO_ENVIRONMENT_SHUTDOWN is called
|
||||
- LINUX/MALI FBDEV: Fix segfault switching video threaded from quickmenu
|
||||
- LOCALIZATION: Add Czech language support
|
||||
- MMAP: Handle disconnect bits on both sides of len
|
||||
- MIYOO: Improve CPU architecture and model name identification for Miyoo
|
||||
- MENU/SETTINGS: Remove 'Advanced Settings' flag from 'Settings > Core' menu
|
||||
- MENU/MATERIALUI: Add 'Gray Dark + Light' themes
|
||||
- MENU/RGUI: Add 6x10 extended ASCII and Latin Extended A and B fonts. These will enable most Latin alphabets to be displayed in RGUI.
|
||||
- MENU/RGUI: Add 'Gray Dark + Light' themes
|
||||
- MENU/XMB: Add title margin adjustment
|
||||
- MENU/XMB: Vertical fade corrections
|
||||
- MENU/OZONE: The size of the thumbnail bar can now be changed though a new option (Settings->User interface->Appearance) up to double its normal size.
|
||||
- MENU/OZONE: Add 'Gray Dark + Light' themes
|
||||
- MENU/OZONE: Add thumbnail scale option
|
||||
- HOTKEYS: Added hotkey for toggling sync to exact content framerate
|
||||
- HOTKEYS: Prevent log spam when using rewind hotkey with cores that don't support rewind, if rewind functionality itself is disabled
|
||||
- HOTKEYS: Add hotkey for toggling sync to exact content framerate
|
||||
- PS3/PSL1GHT: Add RSX graphics support
|
||||
- PS3/PSL1GHT: Add libco support
|
||||
- PS3/PSL1GHT: Add experimental PSMove support
|
||||
- RS90: Optimise layout of sdl_rs90_video
|
||||
- STEAM: Use native OSK (Onscreen Keyboard) instead of built-in RetroArch version
|
||||
- STEAM: New built-in core DLC downloader
|
||||
- STEAM: Swap OK/Cancel buttons by default
|
||||
- VIDEO/HDR: Removed redundant copy of buffer in HDR mode if the shader has already a HDR format i.e. R10G10B10A2 (updated Vulkan/D3D11/D3D12 drivers)
|
||||
- VIDEO/HDR: Fixed crash when using stock shader and HDR and previous optimisation
|
||||
- WAYLAND: Dynamically load libdecor at runtime
|
||||
- WAYLAND: Fix splash screen when using xdg_toplevel
|
||||
- WAYLAND: SHM anti-collision for the splash screen
|
||||
- WAYLAND: Skip splash screen if window is not ready
|
||||
- WII: Fix find_connection_entry(): needs unsigned int
|
||||
Otherwise the USB gamepad cannot be found, if VID/PID has leading zero. This issue happened with Retrode gamepad adapter
|
||||
- WII: Rework Retrode gamepad implementation to support multi_pad interface
|
||||
- WII: Fix - Unplugging and re-plugging now works again
|
||||
- WII: vWii- Only gamepad 1 is supported, because multi_pad is currently only relevant in the Wii U implementation
|
||||
- WIIU: Implemented the multi_pad interface according to input/connect/connect_wiiugca.c
|
||||
- WIIU: Add Optimize for Gamepad option
|
||||
- WIIU: Fix USB gamepad support
|
||||
|
||||
# 1.10.1
|
||||
- ANDROID: Add `HAVE_LANGEXTRA` back to makefile
|
||||
- ANDROID: Include adaptive launcher icons
|
||||
- ANDROID: Populate external storage devices inside the file browser on Android 11+ devices
|
||||
- CHEEVOS: add mastery placard
|
||||
- CHEEVOS: more description message for missing RetroAchievements credentials
|
||||
- CHEEVOS: prevent occasional infinite wait loading multi-disc game from secondary disc
|
||||
- CHEEVOS: stop load process if unable to retrieve achievement data
|
||||
- CHEEVOS: support for identifying Dreamcast CHDs
|
||||
- CHEEVOS: Updated to 10.3.2
|
||||
- CONTENTLESS CORES: Disable per-game and per-content-directory remaps when running contentless cores
|
||||
- CONTENTLESS CORES: Disable per-game and per-content-directory shader presets
|
||||
- CONTENTLESS CORES: Enable config overrides
|
||||
- CONTENTLESS CORES: Enable runtime logging
|
||||
- CORE INFORMATION: Show core version
|
||||
- CORE UPDATER: Add 'Core System Files Downloader'
|
||||
- CORES/SETTINGS: Add 'Standalone Cores' menu
|
||||
- D3D10/D3D11: Add Vsync swap interval
|
||||
- EMSCRIPTEN: Enable 7zip
|
||||
- GBA: New GBA filter Upscale_240x160-320x240
|
||||
- GONG: Removed now that it's a standalone core
|
||||
- HISTORY/FAVORITES: Fix default core on 'Add to Favorites'
|
||||
- INPUT/WAYLAND: Allow toggling mouse grabs
|
||||
- INPUT/WAYLAND: Release keys and mouse buttons on lost focus
|
||||
- iOS: Support for custom keyboard and touch mouse support, among other iOS 13 features
|
||||
- LIBRETRO: Fix crash when cores using RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK return false from retro_load_game()
|
||||
- LIBRETRO: Add optional frame skipping when fast-forwarding
|
||||
- LOCALIZATION: Fetch translations from Crowdin
|
||||
- LOCALIZATION: OSD fonts for Chinese, Korean, Arabic and Persian
|
||||
- LOCALIZATION: Translation fixes for various languages
|
||||
- MENU/RGUI: Add dynamic theme
|
||||
- MIYOO: Enable NEAREST audio resampler
|
||||
- MIYOO: Support battery level
|
||||
- NETPLAY: Disable savestates on stateless mode
|
||||
- NGC/Wii: Several improvements
|
||||
- OSX: Enable compilation on PPC
|
||||
- OZONE/XMB: Improve efficiency/accuracy of History/Favorites icon rendering
|
||||
- RECORDING/FFMPEG: Fix building against FFmpeg 5.0
|
||||
- RETROARCH INFORMATION: No longer report on enabled Python support, which was removed in RetroArch 1.7.8
|
||||
- SAVESTATES: Disable save states based on save state support level defined in core info files
|
||||
- UNIX/WINDOWS: Allow setting the default libretro_directory via environment variable
|
||||
- WAYLAND/VULKAN: Fix Wayland Vulkan not reacting to initial resize
|
||||
- WINDOWS/WINRAW: Enable mouse overlay control
|
||||
- Xbox/UWP: Fix CHD not working with Cheevos / Add 7zip support.
|
||||
|
||||
# 1.10.0
|
||||
- 3DS: Add Jaxe, A5200 and WASM4 cores
|
||||
- 3DS: Fix rotation
|
||||
- ARCHIVE: Allow loading files from archive subdirectory
|
||||
- AUDIO: Remove frame limit from audio batch callback. Before, if a core used the audio batch callback, there would be a hidden cap of 1024 on the number of audio frames that could be sent. If a core exceeded this value, any excess samples were silently discarded. While this is sufficient for 'normal' samplerates/framerates, it means that e.g. a core using the batch callback to send 44100 Hz audio at 30 fps with would have entirely broken sound. This has been fixed by removing the audio batch frame limit.
|
||||
- AUDIO/RESAMPLER/NEON: Implement sinc kaiser NEON function
|
||||
- CHEEVOS: Reset hardcore default to enabled; show message when trying to load state in hardcore
|
||||
- CHEEVOS: Fix memory map conversion
|
||||
- CHEEVOS: Check netplay status when unlocking achievements
|
||||
- CHEEVOS: Support for hashing buffered NDS ROMs
|
||||
- CHEEVOS: Fix hung task whe badge doesn't exist
|
||||
- CLI: Load save states from command-line or playlist
|
||||
- CORE INFO CACHE/SETTINGS: Restore missing 'Cache Core Info Files' menu entry
|
||||
- DATABASE: Serial scanning for Gamecube/MegaCD/SegaCD/Saturn/PSX/PSP/Dreamcast/Wii
|
||||
- EMSCRIPTEN: Add Jaxe, WASM4 cores
|
||||
- FILE IO: Fix incorrect file names for remap files when the content path doesn't have a preceding slash
|
||||
- INPUT/OVERLAY: Added support for showing the overlay behind the menu instead of in front. This is currently only supported on the GL, Vulkan, D3D 9/10/11/12 and 3DS drivers.
|
||||
- INPUT/UDEV: Convert abs mouse from screen to viewport coordinates; fix relative mouse coords
|
||||
- INPUT/WAYLAND: Ignore mouse clicks on window decoration
|
||||
- INPUT/WAYLAND: Add scroll wheel support
|
||||
- LINUX: Added support for Linux GameMode (https://github.com/FeralInteractive/gamemode), which can be toggled on/off in the Power Management or Latency settings menus.
|
||||
- LOCALIZATION: Fetch translations from Crowdin
|
||||
- LOCALIZATION: Add Indonesian, Swedish and Ukrainian language options
|
||||
- LOCALIZATION/MENU/RGUI: Enable Indonesian and Swedish localisations for RGUI
|
||||
- LOGGING: Logging cleanups
|
||||
- LOGGING: Stop logging FPS statistics twice on quit
|
||||
- LOGGING: Log font rendering backend only once
|
||||
- HOTKEYS: Added a hotkey toggle for the on-screen technical statistics.
|
||||
- HOTKEYS: Add delay + acceleration to volume hotkeys
|
||||
- MENU: Add option for showing notifications only in menu
|
||||
- MENU/RGUI: Add Finnish to supported languages
|
||||
- MENU/XMB: Optional vertical list item fade
|
||||
- MENU/XMB/OZONE: Category + History/Favorites icons
|
||||
- NETWORK: Fix dummy notification - no longer shows a netplay initialization failed notification when netplay is not enabled
|
||||
- NETWORK: LAN addresses only for UPnP - Some router devices might accept non-LAN addresses without raising an error.
|
||||
- NETWORK: Filter out non-connectable rooms. Add an option for filtering out non-connectable netplay rooms.
|
||||
- NETWORK: Netplay spectator notification fix. Fix double notification when the host switches to spectator.
|
||||
- NETWORK: Prevents long-term pausing from clients dishonoring allow pausing
|
||||
- NETWORK/LOBBY: Lobby Viewer: Filter out rooms that are not running RetroArch
|
||||
- NETWORK/LOBBY: Lobby Viewer: Display a non-connectable tag to non-connectable rooms
|
||||
- NETWORK/LOBBY: Host: Display warning if we are announcing to the internet but our room isn't connectable from there
|
||||
- NETWORK/RELAY: Custom relay server support - Add support for custom user-ran relay servers
|
||||
- NETWORK/RELAY: Replace Canadian relay server with Singapore relay server. Current relays: New York/USA, Madrid/Spain, Sao Paulo/Brazil, Singapore
|
||||
- NETWORK/UPNP: Various refactors/improvements, no more dependent on miniupnpc
|
||||
- NETWORK/UPNP: Various UPnP binding fixes for specific routers
|
||||
- NETWORK/UPNP: Accept IGD v2 service types
|
||||
- NETWORK/UPNP: Delay lobby server announcing - delay the announcing in order to give UPnP's port forwarding more time. Fix the remaining truncation warnings.
|
||||
- NETWORK/UPNP: Smart interface selection - Find the most suitable address for UPnP by scoring interfaces on how close their address is to the device's address
|
||||
- OPENGL1: Fix buffer overflow - RetroArch would sometimes crashes at startup when loading asset textures with GL1 driver
|
||||
- PS3: PSL1GHT port added to Gitlab CI
|
||||
- VULKAN: Double combined image sampler descriptor pool size - fix segfaults with AMD GPUs using RADV
|
||||
- VULKAN: Emulate mailbox only with Vsync enabled - otherwise have it disabled - useful for VRR/G-Sync/FreeSync
|
||||
- VULKAN/SWAPCHAIN: Vulkan max swapchain images option adjustments: removed value 1, since it won't be used - Video reinit on change, so that there is no need to restart or toggle fullscreen
|
||||
- VULKAN/HDR: HDR support - tested on Windows
|
||||
- WAYLAND: Add libdecor for client side decoration
|
||||
- WAYLAND: Use any display for initial metrics
|
||||
- WAYLAND: Fix the window closing, if RetroArch is build without libdecor
|
||||
- WAYLAND: Use checked sizes in EGL resize
|
||||
- WAYLAND: Fix window title update
|
||||
- WEBOS: Fix webOS build and run
|
||||
- WIIU: Fix rotation
|
||||
- UWP/XBOX: Fix content over 4GB (approx) failing to load, improve/speed up copy/load times
|
||||
- UWP/XBOX: Fix scanning for playlists
|
||||
- UWP/XBOX: Move content copied to LocalState to a dedicated dir and clear on startup
|
||||
- UWP/XBOX: Make content copy to a specific cache directory in the LocalState folder when it's copied
|
||||
- UWP/XBOX: Auto delete VFS cache dir on startup
|
||||
- UWP/XBOX: Make resolution switching automatic and fix angle output issues
|
||||
- UWP/XBOX: Force ANGLE to render at 1080p regardless of screensize as the output is 1080p regardless of screensize. This fixes an issue where at 4k any angle output would be zoomed into a corner.
|
||||
- UWP/XBOX: Set resolution based on display resolution (auto 4k)
|
||||
- UWP/XBOX: Set driver to D3D11 if booting with opengl
|
||||
- UWP/XBOX: Reset width and height of output on boot to match display
|
||||
- UWP/XBOX: Mitigate need for VFS cores on NTFS drives
|
||||
- UWP/XBOX: Make check for standard I/O by access rather than the just assuming based on path string
|
||||
- UWP/XBOX: Add code to auto permissions so files can be accessed by non VFS cores (no exFAT or FAT32 support yet)
|
||||
|
||||
# 1.9.14
|
||||
- ANDROID/PLAYSTORE: Implement MANAGE_EXTERNAL_STORAGE permission
|
||||
- ANDROID/PLAYSTORE: Bump up SDK level to 30 to comply with Play Store policies
|
||||
- AUDIO/MIXER: Increase sample buffer padding
|
||||
- CHEEVOS: Disallow achievements when spectating netplay
|
||||
- CHEEVOS: Fix need-to-activate achievement logic for non-hardcore
|
||||
- CHEEVOS: Don't queue rewind re-init if already on main thread
|
||||
- CHEEVOS: Ignore unofficial achievements unless setting is enabled
|
||||
- CHEEVOS: Use SSL host when available
|
||||
- CHEEVOS: Validate hashes for secondary discs in multi-disc games
|
||||
- CHEEVOS: Ensure placard is initialized on main thread when game has no achievements
|
||||
- CHEEVOS: Audit achievement settings defaults and visibility
|
||||
- CHEEVOS: Show error message when no password provided
|
||||
- CHEEVOS: Use widget for game loaded achievement progress
|
||||
- CONFIG: Honor config_save_on_exit when Reboot/Shutdown is called
|
||||
- DISK CONTROL: Focus on current content entry in Disk Control append/insert
|
||||
- FRAMEDELAY: Auto Frame Delay Improvements - swap interval handling, D3DX handling, and delay target resets also on core restart. It should now work with high refresh rates and also with Direct3D 10/11/12 drivers
|
||||
- INPUT/GYRO/ACCELEROMETER/ANDROID: Re-enable Gyroscope & Accelerometer when RetroArch resumes or regains focus
|
||||
- INPUT/HID: Fix gamepad disconnect on unrecognized HID device
|
||||
- LAKKA: Patch to fix keyboard typing
|
||||
- LAKKA: CD-ROM eject menu item
|
||||
- LAKKA/BLUETOOTH: Add option to remove pairing
|
||||
- LAKKA/SWITCH: Disable rumble gain
|
||||
- LAKKA/SWITCH: Disable cpu scaling, uses its own CPU governor
|
||||
- LOGGING: Logging cleanups. A bunch of unifications and reformattings (capitalizations, dots, quotes, prefixes etc). Also added a few missing things, such as Run-Ahead error logging and LED interface init logging when it is enabled.
|
||||
- NETPLAY: Networking - should not print country for a local lobby
|
||||
- NETPLAY: Added setting to allow/disallow players other than the host from pausing the game.
|
||||
- NETPLAY: Added a sublabel for netplay max connections.
|
||||
- NETPLAY: Fixed port override macro from not being set immediately after the port setting.
|
||||
- NETPLAY: Show passworded rooms on lobby
|
||||
- NETWORK: Make HTTP header parsing case insensitive
|
||||
- NETWORK/UPNP: Fixed memory leaks
|
||||
- NETWORK/UPNP: Added a task_queue_wait to prevent executing two nat tasks at once, so it's also thread safe now
|
||||
- NETWORK/UPNP: Switch to a permanent lease time, but request it to be removed when we do netplay_free. Switch to a permanent lease time, but request it to be removed when we do netplay_free.
|
||||
- NETWORK/UPNP: Only use a single interface for UPnP, return on the first one found instead of iterating over all of them and opening them one by one
|
||||
- OVERLAYS: Revert changes
|
||||
- RETROFW: Add OSS audio
|
||||
- VIDEO/ROTATION: Always return false if rotation can't occur. RETRO_ENVIRONMENT_SET_ROTATION should return false when rotation has been forcefully disabled in frontend, that way the core can decide if aspect ratio should be rotated or not for vertical games. Useful for FBNeo for instance.
|
||||
- VULKAN: Avoid hard crash when capturing screenshot in emulating mailbox.
|
||||
- WIIU: Make wiiu_gfx_load_texture code safer
|
||||
- WIIU: Fix keyboard support.
|
||||
|
||||
# 1.9.13
|
||||
- CHEEVOS/MSVC2010: Add Cheevos support
|
||||
- CRT/SWITCHRES: Fixes some issue where scaling is incorrect in some video modes for CRT output.
|
||||
@@ -278,7 +495,7 @@ Not that SR works on them but to fix RA compile issues
|
||||
# 1.9.5
|
||||
- ALSATHREAD: Make alsathread default for all ALSA devices with threads
|
||||
- ARCHIVE: Fix loading of archived content with file names containing '#' characters
|
||||
- CHEEVOS: Upgrade to rcheevos 10.1
|
||||
- CHEEVOS: Upgrade to rcheevos 10.1
|
||||
- CHEEVOS: Challenge indicators
|
||||
- CHEEVOS: Group achievements by category in quick menu
|
||||
- CHEEVOS: Relabel 'Start Active' with 'Encore Mode'
|
||||
@@ -293,9 +510,9 @@ Not that SR works on them but to fix RA compile issues
|
||||
- INPUT: Allow the 8 analog stick directions to be used as keys for core keyboard mappings
|
||||
- LIBRETRO: Add API extension for setting 'need_fullpath' based on content file extension and to request persistent frontend content data buffers
|
||||
- MENU/SEARCH: Add enhanced search functionality to the 'Manage Cores' menu
|
||||
- OPENDINGUX: Fix black screens when triggering gfx driver initialisation via menu actions
|
||||
- OPENDINGUX: Fix black screens when triggering gfx driver initialisation via menu actions
|
||||
- UNIX: Get better battery stats on sysfs nodes
|
||||
- VIDEO: Extend Frame Delay range to 19 to accommodate PAL land too
|
||||
- VIDEO: Extend Frame Delay range to 19 to accommodate PAL land too
|
||||
- WIFI/LAKKA: Add nmcli to wifi drivers
|
||||
- WIFI/LAKKA: Add wifi configuration menu
|
||||
- X11: fix fullscreen when swapping monitors/resolution
|
||||
@@ -328,7 +545,7 @@ Not that SR works on them but to fix RA compile issues
|
||||
- CORE INFO/FILE IO: Core Info cache; significant file I/O performance improvements on systems with slow disk file I/O
|
||||
- CORE INFO/FILE IO: Enable core info cache by default on all 'console' platforms
|
||||
- FREEBSD: FreeBSD build fix
|
||||
- LAKKA: Support for tweaking CPU governors/scaling policies
|
||||
- LAKKA: Support for tweaking CPU governors/scaling policies
|
||||
- LAKKA: This adds managed policies and settings to store them and reload them at startup
|
||||
- LIBRETRO API: Add API extension for cores to override frontend fast-forward state
|
||||
- MENU/RGUI: Fix saving of config files/overrides when 'Lock Menu Aspect Ratio' is enabled
|
||||
@@ -369,7 +586,7 @@ Not that SR works on them but to fix RA compile issues
|
||||
- MENU: Add optional menu screensaver
|
||||
- MENU: Add search filter support to cheats and overlays file browser menus
|
||||
- MENU/FILEBROWSER: Enhanced 'Load Content' file browser search functionality
|
||||
- MENU/INPUT: Block accidental diagonals in menu navigation
|
||||
- MENU/INPUT: Block accidental diagonals in menu navigation
|
||||
- MENU/RGUI: Add option to disable menu transparency
|
||||
- MENU/RGUI: Fix display of 'Video > Scaling' menu when 'Lock Menu Aspect Ratio' is enabled
|
||||
- MENU/MATERIALUI: Add icon to 'Turbo Fire' menu entry
|
||||
@@ -488,7 +705,7 @@ Having remaps for many different cores makes finding the active core files cumbe
|
||||
- MAC/UNIVERSAL: Add CoreAudio3 audio driver for Metal Universal build
|
||||
- MAC/IOS: Only extract assets once on first install
|
||||
- MENU: Add 'L2 + R2' menu toggle gamepad combo
|
||||
- MENU: Menu text improvements; clarifications, consistency, text mistakes,
|
||||
- MENU: Menu text improvements; clarifications, consistency, text mistakes,
|
||||
- MENU: Tweak menu scroll initial hold delays
|
||||
- MENU: Restrict menu acceleration to navigation buttons
|
||||
- MENU: Add 'Menu Driver' setting to 'User Interface'
|
||||
@@ -705,7 +922,7 @@ save state limit (global). Instead of wrapping around the slot counter it will s
|
||||
- FILE PATH: Various file path handling optimisations
|
||||
- FONT: Fix Arabic, Chinese and Korean font rendering
|
||||
- INPUT MAPPING/REMAPPING: Restore broken 'reset to default' functionality with RetroPad 'start' button
|
||||
- INPUT MAPPING/REMAPPING: Fix 'reset to default' action for analog sticks and undefined core inputs
|
||||
- INPUT MAPPING/REMAPPING: Fix 'reset to default' action for analog sticks and undefined core inputs
|
||||
- LOCALIZATION: Update Arabic translation
|
||||
- LOCALIZATION: Update Chinese (Simplified) translation
|
||||
- LOCALIZATION: Update Chinese (Traditional) translation
|
||||
@@ -967,7 +1184,7 @@ appear to be required in order for mouse input to work on macOS
|
||||
- VITA: Re-add Online Updater
|
||||
- VULKAN: Fix font driver 'vulkan_get_message_width()' function
|
||||
- VIDEO FILTERS: Only use threads when the number exceeds 1. Fixes race conditions with some CPU filters on Vita
|
||||
- WINDOWS: Add ANGLE support for x64, separate binary (for now?)
|
||||
- WINDOWS: Add ANGLE support for x64, separate binary (for now?)
|
||||
|
||||
# 1.8.2
|
||||
- BUG/CRASH/GLSLANG: Fix glslang crashing error - managed to reproduce an issue which has been plaguing
|
||||
@@ -1144,7 +1361,7 @@ Vulkan, so use the old onContentRectChanged callback to get notified when size c
|
||||
# (1.7.9)
|
||||
- AI SERVICE: Image mode is now much faster, it now saves the image in-memory in PNG format then passes it along to the translation service
|
||||
- BUGFIX: Touch input - When using an overlay to toggle the quick menu on touchscreen devices, we no longer get 'phantom' menu input - i.e. the old bug of hitting the toggle and instantly resuming content (or performing a save state) is fixed
|
||||
- BUGFIX: Networking - RetroArch crashed when pressing left while Relay Server Location entry was selected
|
||||
- BUGFIX: Networking - RetroArch crashed when pressing left while Relay Server Location entry was selected
|
||||
- BUGFIX: Networking - fix memory leak that could happen at exit after a network
|
||||
operation had run
|
||||
- CHEEVOS: Improve handling of line endings when calculating CD hashes for retroachievements
|
||||
|
||||
+76
-51
@@ -198,6 +198,10 @@ ifeq ($(TARGET), retroarch_3ds)
|
||||
OBJ += frontend/drivers/platform_ctr.o
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET), retroarch_ps2)
|
||||
OBJ += frontend/drivers/platform_ps2.o
|
||||
endif
|
||||
|
||||
# Git Version
|
||||
GIT_VERSION_CACHEDIR = $(if $(OBJDIR),$(OBJDIR),$(CURDIR))
|
||||
GIT_VERSION_CACHEFILE = $(GIT_VERSION_CACHEDIR)/git-version.cache
|
||||
@@ -234,6 +238,11 @@ endif
|
||||
|
||||
OBJ += frontend/frontend_driver.o \
|
||||
retroarch.o \
|
||||
runloop.o \
|
||||
driver.o \
|
||||
ui/ui_companion_driver.o \
|
||||
camera/camera_driver.o \
|
||||
record/record_driver.o \
|
||||
command.o \
|
||||
msg_hash.o \
|
||||
midi_driver.o \
|
||||
@@ -255,10 +264,11 @@ OBJ += \
|
||||
tasks/task_manual_content_scan.o \
|
||||
tasks/task_core_backup.o \
|
||||
$(LIBRETRO_COMM_DIR)/encodings/encoding_utf.o \
|
||||
$(LIBRETRO_COMM_DIR)/encodings/encoding_crc32.o
|
||||
$(LIBRETRO_COMM_DIR)/encodings/encoding_crc32.o \
|
||||
$(LIBRETRO_COMM_DIR)/encodings/encoding_base64.o
|
||||
|
||||
ifeq ($(HAVE_TRANSLATE), 1)
|
||||
OBJ += $(LIBRETRO_COMM_DIR)/encodings/encoding_base64.o
|
||||
OBJ += tasks/task_translation.o
|
||||
endif
|
||||
|
||||
OBJ += \
|
||||
@@ -329,6 +339,7 @@ endif
|
||||
OBJ += \
|
||||
gfx/drivers_font_renderer/bitmapfont.o \
|
||||
gfx/drivers_font_renderer/bitmapfont_10x10.o \
|
||||
gfx/drivers_font_renderer/bitmapfont_6x10.o \
|
||||
tasks/task_autodetect.o \
|
||||
input/input_autodetect_builtin.o \
|
||||
input/input_keymaps.o \
|
||||
@@ -372,6 +383,10 @@ DEFINES += -DHAVE_VIDEO_FILTER
|
||||
OBJ += gfx/video_filter.o
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_WINDOW_OFFSET), 1)
|
||||
DEFINES += -DHAVE_WINDOW_OFFSET
|
||||
endif
|
||||
|
||||
OBJ += $(LIBRETRO_COMM_DIR)/audio/resampler/audio_resampler.o
|
||||
|
||||
ifeq ($(HAVE_DSP_FILTER), 1)
|
||||
@@ -455,7 +470,11 @@ ifeq ($(HAVE_LANGEXTRA), 1)
|
||||
intl/msg_hash_fa.o \
|
||||
intl/msg_hash_he.o \
|
||||
intl/msg_hash_ast.o \
|
||||
intl/msg_hash_fi.o
|
||||
intl/msg_hash_fi.o \
|
||||
intl/msg_hash_id.o \
|
||||
intl/msg_hash_sv.o \
|
||||
intl/msg_hash_uk.o \
|
||||
intl/msg_hash_cs.o
|
||||
endif
|
||||
|
||||
ifneq ($(HAVE_GETOPT_LONG), 1)
|
||||
@@ -757,8 +776,12 @@ endif
|
||||
|
||||
# Miscellaneous
|
||||
|
||||
ifeq ($(HAVE_COMMAND), 1)
|
||||
DEFINES += -DHAVE_COMMAND
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_STDIN_CMD), 1)
|
||||
DEFINES += -DHAVE_COMMAND -DHAVE_STDIN_CMD
|
||||
DEFINES += -DHAVE_STDIN_CMD
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_EMSCRIPTEN), 1)
|
||||
@@ -770,22 +793,23 @@ ifeq ($(HAVE_EMSCRIPTEN), 1)
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_BLUETOOTH), 1)
|
||||
OBJ += bluetooth/bluetooth_driver.o
|
||||
OBJ += bluetooth/drivers/bluetoothctl.o
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_BLUETOOTH), 1)
|
||||
OBJ += tasks/task_bluetooth.o
|
||||
ifeq ($(HAVE_DBUS), 1)
|
||||
OBJ += bluetooth/drivers/bluez.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_LAKKA), 1)
|
||||
OBJ += wifi/drivers/connmanctl.o
|
||||
OBJ += network/drivers_wifi/connmanctl.o
|
||||
OBJ += misc/cpufreq/cpufreq.o
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_WIFI), 1)
|
||||
OBJ += wifi/drivers/nmcli.o
|
||||
OBJ += network/wifi_driver.o
|
||||
OBJ += tasks/task_wifi.o
|
||||
OBJ += network/drivers_wifi/nmcli.o
|
||||
DEFINES += -DHAVE_WIFI
|
||||
endif
|
||||
|
||||
@@ -816,6 +840,10 @@ ifeq ($(TARGET), retroarch_3ds)
|
||||
OBJ += gfx/drivers_font/ctr_font.o
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET), retroarch_ps2)
|
||||
OBJ += gfx/drivers_font/ps2_font.o
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_LIBNX), 1)
|
||||
OBJ += gfx/drivers_font/switch_font.o
|
||||
endif
|
||||
@@ -1062,7 +1090,8 @@ ifeq ($(HAVE_MENU_COMMON), 1)
|
||||
menu/cbs/menu_cbs_label.o \
|
||||
menu/cbs/menu_cbs_sublabel.o \
|
||||
menu/cbs/menu_cbs_title.o \
|
||||
menu/menu_displaylist.o
|
||||
menu/menu_displaylist.o \
|
||||
menu/menu_contentless_cores.o
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_GFX_WIDGETS), 1)
|
||||
@@ -1093,13 +1122,13 @@ endif
|
||||
ifeq ($(HAVE_VIDEO_LAYOUT), 1)
|
||||
DEFINES += -DHAVE_VIDEO_LAYOUT
|
||||
OBJ += \
|
||||
gfx/video_layout.o \
|
||||
gfx/video_layout/view.o \
|
||||
gfx/video_layout/element.o \
|
||||
gfx/video_layout/component.o \
|
||||
gfx/video_layout/internal.o \
|
||||
gfx/video_layout/scope.o \
|
||||
gfx/video_layout/load.o
|
||||
gfx/video_layout.o \
|
||||
gfx/video_layout/view.o \
|
||||
gfx/video_layout/element.o \
|
||||
gfx/video_layout/component.o \
|
||||
gfx/video_layout/internal.o \
|
||||
gfx/video_layout/scope.o \
|
||||
gfx/video_layout/load.o
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_STB_FONT), 1)
|
||||
@@ -1162,6 +1191,13 @@ ifeq ($(TARGET), retroarch_3ds)
|
||||
input/drivers_joypad/ctr_joypad.o
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET), retroarch_ps2)
|
||||
OBJ += gfx/drivers/ps2_gfx.o \
|
||||
input/drivers/ps2_input.o \
|
||||
input/drivers_joypad/ps2_joypad.o \
|
||||
audio/drivers/ps2_audio.o
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET), retroarch_orbis)
|
||||
OBJ += input/drivers/ps4_input.o \
|
||||
input/drivers_joypad/ps4_joypad.o \
|
||||
@@ -1227,6 +1263,7 @@ ifeq ($(HAVE_WAYLAND), 1)
|
||||
OBJ += gfx/drivers_context/wayland_ctx.o \
|
||||
input/common/wayland_common.o \
|
||||
input/drivers/wayland_input.o \
|
||||
gfx/common/wayland_common.o \
|
||||
gfx/common/wayland/xdg-shell.o \
|
||||
gfx/common/wayland/idle-inhibit-unstable-v1.o \
|
||||
gfx/common/wayland/xdg-decoration-unstable-v1.o
|
||||
@@ -1238,6 +1275,11 @@ ifeq ($(HAVE_WAYLAND), 1)
|
||||
DEF_FLAGS += $(WAYLAND_CFLAGS) $(WAYLAND_CURSOR_CFLAGS)
|
||||
LIBS += $(WAYLAND_LIBS) $(WAYLAND_CURSOR_LIBS)
|
||||
|
||||
ifeq ($(HAVE_LIBDECOR), 1)
|
||||
DEFINES += -DHAVE_LIBDECOR_H
|
||||
DEF_FLAGS += $(LIBDECOR_CFLAGS)
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
# XML
|
||||
@@ -1431,7 +1473,9 @@ endif
|
||||
|
||||
ifeq ($(HAVE_PLAIN_DRM), 1)
|
||||
OBJ += gfx/drivers/drm_gfx.o
|
||||
INCLUDE_DIRS += -I/usr/include/libdrm
|
||||
ifneq ($(HAVE_LAKKA), 1)
|
||||
INCLUDE_DIRS += -I/usr/include/libdrm
|
||||
endif
|
||||
LIBS += -ldrm
|
||||
endif
|
||||
|
||||
@@ -2032,12 +2076,6 @@ OBJ += $(LIBRETRO_COMM_DIR)/formats/bmp/rbmp_encode.o \
|
||||
$(LIBRETRO_COMM_DIR)/formats/image_transfer.o \
|
||||
$(LIBRETRO_COMM_DIR)/formats/m3u/m3u_file.o
|
||||
|
||||
# Gong embedded core
|
||||
ifeq ($(HAVE_GONG),1)
|
||||
DEFINES += -DHAVE_GONG
|
||||
OBJ += cores/libretro-gong/gong.o
|
||||
endif
|
||||
|
||||
# Video4Linux 2
|
||||
|
||||
ifeq ($(HAVE_V4L2),1)
|
||||
@@ -2078,9 +2116,7 @@ ifeq ($(HAVE_NETWORKING), 1)
|
||||
tasks/task_http.o \
|
||||
tasks/task_netplay_lan_scan.o \
|
||||
tasks/task_netplay_nat_traversal.o \
|
||||
tasks/task_bluetooth.o \
|
||||
tasks/task_wifi.o \
|
||||
tasks/task_pl_thumbnail_download.o \
|
||||
tasks/task_pl_thumbnail_download.o \
|
||||
tasks/task_netplay_find_content.o
|
||||
|
||||
ifeq ($(HAVE_MENU_COMMON), 1)
|
||||
@@ -2136,6 +2172,7 @@ ifeq ($(HAVE_NETWORKING), 1)
|
||||
deps/rcheevos/src/rcheevos/runtime_progress.o \
|
||||
deps/rcheevos/src/rcheevos/trigger.o \
|
||||
deps/rcheevos/src/rcheevos/value.o \
|
||||
deps/rcheevos/src/rhash/cdreader.o \
|
||||
deps/rcheevos/src/rhash/hash.o \
|
||||
deps/rcheevos/src/rapi/rc_api_common.o \
|
||||
deps/rcheevos/src/rapi/rc_api_runtime.o \
|
||||
@@ -2221,27 +2258,6 @@ ifeq ($(HAVE_NETWORKING), 1)
|
||||
ifeq ($(HAVE_NETWORKGAMEPAD), 1)
|
||||
OBJ += cores/libretro-net-retropad/net_retropad_core.o
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_BUILTINMINIUPNPC), 1)
|
||||
HAVE_MINIUPNPC = 1
|
||||
DEFINES += -DHAVE_MINIUPNPC -DHAVE_BUILTINMINIUPNPC -DMINIUPNPC_SET_SOCKET_TIMEOUT -DMINIUPNPC_GET_SRC_ADDR
|
||||
INCLUDE_DIRS += -I$(DEPS_DIR)
|
||||
OBJ += $(DEPS_DIR)/miniupnpc/igd_desc_parse.o \
|
||||
$(DEPS_DIR)/miniupnpc/upnpreplyparse.o \
|
||||
$(DEPS_DIR)/miniupnpc/upnpcommands.o \
|
||||
$(DEPS_DIR)/miniupnpc/upnperrors.o \
|
||||
$(DEPS_DIR)/miniupnpc/connecthostport.o \
|
||||
$(DEPS_DIR)/miniupnpc/portlistingparse.o \
|
||||
$(DEPS_DIR)/miniupnpc/receivedata.o \
|
||||
$(DEPS_DIR)/miniupnpc/upnpdev.o \
|
||||
$(DEPS_DIR)/miniupnpc/minissdpc.o \
|
||||
$(DEPS_DIR)/miniupnpc/miniwget.o \
|
||||
$(DEPS_DIR)/miniupnpc/miniupnpc.o \
|
||||
$(DEPS_DIR)/miniupnpc/minixml.o \
|
||||
$(DEPS_DIR)/miniupnpc/minisoap.o
|
||||
else ifeq ($(HAVE_MINIUPNPC), 1)
|
||||
LIBS += $(MINIUPNPC_LIBS)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(findstring FPGA,$(OS)),)
|
||||
@@ -2376,7 +2392,8 @@ ifeq ($(HAVE_STATIC_VIDEO_FILTERS), 1)
|
||||
gfx/video_filters/dot_matrix_4x.o \
|
||||
gfx/video_filters/upscale_1_5x.o \
|
||||
gfx/video_filters/upscale_256x_320x240.o \
|
||||
gfx/video_filters/picoscale_256x_320x240.o
|
||||
gfx/video_filters/picoscale_256x_320x240.o \
|
||||
gfx/video_filters/upscale_240x160_320x240.o
|
||||
endif
|
||||
|
||||
ifeq ($(WANT_IOSUHAX), 1)
|
||||
@@ -2441,6 +2458,13 @@ ifeq ($(ANDROID), 1)
|
||||
OBJ += play_feature_delivery/play_feature_delivery.o
|
||||
endif
|
||||
|
||||
### Steam integration using mist
|
||||
ifeq ($(HAVE_MIST), 1)
|
||||
INCLUDE_DIRS += -I$(MIST_PATH)/include
|
||||
LDFLAGS += -L$(MIST_PATH) -lmist
|
||||
OBJ += steam/steam.o tasks/task_steam.o
|
||||
endif
|
||||
|
||||
##################################
|
||||
### Classic Platform specifics ###
|
||||
###############WIP################
|
||||
@@ -2460,12 +2484,13 @@ ifeq ($(HAVE_C_A7A7), 1)
|
||||
-fmerge-all-constants -fno-math-errno \
|
||||
-marm -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard
|
||||
DEF_FLAGS += $(C_A7A7_OPT)
|
||||
ifeq ($(shell echo `$(CC) -dumpversion` "< 4.9" | bc -l), 1)
|
||||
CC_VERSION := $(shell $(CC) -dumpversion)
|
||||
ifneq (4.9,$(firstword $(sort $(CC_VERSION) 4.9))) # if version < 4.9
|
||||
DEF_FLAGS += -march=armv7-a
|
||||
else
|
||||
DEF_FLAGS += -march=armv7ve
|
||||
# If gcc is 5.0 or later
|
||||
ifeq ($(shell echo `$(CC) -dumpversion` ">= 5" | bc -l), 1)
|
||||
ifeq (5,$(firstword $(sort $(CC_VERSION) 5)))
|
||||
LDFLAGS += -static-libgcc -static-libstdc++
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -10,6 +10,7 @@ BUILD_3DS = 0
|
||||
BUILD_CIA = 1
|
||||
LIBCTRU_NO_DEPRECATION = 1
|
||||
USE_CTRULIB_2 ?= 0
|
||||
LOAD_WITHOUT_CORE_INFO ?= 0
|
||||
|
||||
APP_TITLE = RetroArch 3DS
|
||||
APP_DESCRIPTION = RetroArch 3DS
|
||||
@@ -106,6 +107,9 @@ endif
|
||||
ifeq ($(strip $(DEVKITPRO)),)
|
||||
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>devkitpro")
|
||||
endif
|
||||
ifeq ($(strip $(DEVKITARM)),)
|
||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitarm")
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(CTRULIB)),)
|
||||
CTRULIB = $(DEVKITPRO)/libctru
|
||||
@@ -115,6 +119,10 @@ ifeq ($(strip $(USE_CTRULIB_2)),1)
|
||||
CFLAGS += -DUSE_CTRULIB_2
|
||||
endif
|
||||
|
||||
ifeq ($(LOAD_WITHOUT_CORE_INFO),1)
|
||||
CFLAGS += -DLOAD_WITHOUT_CORE_INFO
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(DEVKITTOOLS)),)
|
||||
ifeq ($(strip $(USE_CTRULIB_2)),1)
|
||||
DEVKITTOOLS = $(DEVKITPRO)/tools
|
||||
|
||||
+217
@@ -0,0 +1,217 @@
|
||||
include version.all
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
|
||||
|
||||
DEBUG ?= 0
|
||||
WHOLE_ARCHIVE_LINK = 0
|
||||
GRIFFIN_BUILD = 0
|
||||
|
||||
OBJ :=
|
||||
|
||||
DEFINES := -DHAVE_DJGPP=1 -U__linux__ -U__linux -DRARCH_INTERNAL -DHAVE_STB_VORBIS
|
||||
CC := i586-pc-msdosdjgpp-gcc
|
||||
CXX := i586-pc-msdosdjgpp-g++
|
||||
TARGET := retrodos.exe
|
||||
|
||||
RARCH_CONSOLE = 0
|
||||
HAVE_SHADERPIPELINE = 1
|
||||
HAVE_SPIRV_CROSS = 0
|
||||
HAVE_PATCH = 1
|
||||
HAVE_LUA = 0
|
||||
HAVE_CONFIGFILE = 1
|
||||
HAVE_GFX_WIDGETS = 1
|
||||
HAVE_LANGEXTRA = 1
|
||||
HAVE_DR_MP3 = 1
|
||||
HAVE_TRANSLATE = 0
|
||||
HAVE_SCREENSHOTS = 1
|
||||
HAVE_REWIND = 1
|
||||
HAVE_AUDIOMIXER = 1
|
||||
HAVE_CC_RESAMPLER = 1
|
||||
HAVE_MENU_COMMON = 1
|
||||
HAVE_RTGA = 1
|
||||
HAVE_RPNG = 1
|
||||
HAVE_RJPEG = 1
|
||||
HAVE_RBMP = 1
|
||||
HAVE_7ZIP = 1
|
||||
HAVE_ZLIB = 1
|
||||
HAVE_IMAGEVIEWER = 1
|
||||
HAVE_BUILTINZLIB = 1
|
||||
HAVE_LIBRETRODB = 1
|
||||
HAVE_DSP_FILTER = 1
|
||||
HAVE_VIDEO_FILTER = 1
|
||||
HAVE_STATIC_VIDEO_FILTERS = 1
|
||||
HAVE_STATIC_AUDIO_FILTERS = 1
|
||||
HAVE_FILTERS_BUILTIN = 1
|
||||
HAVE_MENU = 1
|
||||
HAVE_CONFIGFILE = 1
|
||||
HAVE_PATCH = 1
|
||||
HAVE_CHEATS = 1
|
||||
HAVE_RUNAHEAD = 1
|
||||
HAVE_NETWORKING = 0
|
||||
HAVE_NETPLAYDISCOVERY = 1
|
||||
HAVE_OVERLAY := 1
|
||||
HAVE_STB_FONT = 1
|
||||
HAVE_COMMAND := 1
|
||||
HAVE_STDIN_CMD := 1
|
||||
HAVE_CMD := 1
|
||||
HAVE_CHEEVOS = 0
|
||||
HAVE_CHD = 0 # disabled due to static libretro-common and libchdr conflicts between different cores
|
||||
HAVE_STB_VORBIS = 1
|
||||
HAVE_IBXM = 1
|
||||
HAVE_CORE_INFO_CACHE = 1
|
||||
|
||||
HAVE_RGUI = 1
|
||||
HAVE_MATERIALUI = 0
|
||||
HAVE_XMB = 0
|
||||
HAVE_OZONE = 0
|
||||
|
||||
|
||||
OBJ := \
|
||||
frontend/drivers/platform_dos.o \
|
||||
gfx/drivers/vga_gfx.o gfx/drivers_font/vga_font.o \
|
||||
input/drivers/dos_input.o input/drivers_joypad/dos_joypad.o
|
||||
|
||||
include Makefile.common
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# DATA is a list of directories containing data files
|
||||
# INCLUDES is a list of directories containing header files
|
||||
# EXEFS_SRC is the optional input directory containing data copied into exefs, if anything this normally should only contain "main.npdm".
|
||||
# ROMFS is the directory containing data to be added to RomFS, relative to the Makefile (Optional)
|
||||
#
|
||||
# NO_ICON: if set to anything, do not use icon.
|
||||
# NO_NACP: if set to anything, no .nacp file is generated.
|
||||
# APP_TITLE is the name of the app stored in the .nacp file (Optional)
|
||||
# APP_AUTHOR is the author of the app stored in the .nacp file (Optional)
|
||||
# APP_VERSION is the version of the app stored in the .nacp file (Optional)
|
||||
# APP_TITLEID is the titleID of the app stored in the .nacp file (Optional)
|
||||
# ICON is the filename of the icon (.jpg), relative to the project folder.
|
||||
# If not set, it attempts to use one of the following (in this order):
|
||||
# - <Project name>.jpg
|
||||
# - icon.jpg
|
||||
# - <libnx folder>/default_icon.jpg
|
||||
#---------------------------------------------------------------------------------
|
||||
BUILD := build
|
||||
SOURCES := $(CURDIR)/source
|
||||
DATA := data
|
||||
INCLUDES := include
|
||||
EXEFS_SRC := exefs_src
|
||||
|
||||
APP_TITLE := RetroArch
|
||||
APP_VERSION := $(RARCH_VERSION)
|
||||
APP_AUTHOR := libretro Team
|
||||
APP_ICON := pkg/libnx/retroarch.jpg
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
ARCH :=
|
||||
|
||||
CFLAGS := -g -Wall -O3 -fcommon -ffast-math -ffunction-sections \
|
||||
$(ARCH) $(DEFINES) $(INCLUDE_DIRS)
|
||||
|
||||
CFLAGS += $(INCLUDE)
|
||||
|
||||
ifeq ($(HAVE_FILTERS_BUILTIN), 1)
|
||||
CFLAGS += -DHAVE_FILTERS_BUILTIN
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(HAVE_STATIC_DUMMY)),1)
|
||||
CFLAGS += -DHAVE_STATIC_DUMMY=1
|
||||
endif
|
||||
|
||||
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = $(ARCH) -Wl,--allow-multiple-definition -Wl,-Map,$(notdir $*.map)
|
||||
|
||||
# add things from Makefile.common
|
||||
CFLAGS += $(DEF_FLAGS)
|
||||
|
||||
LIBS := -lstdc++ -lm
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(TARGET)
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
export OFILES := $(OBJ)
|
||||
|
||||
ifeq ($(strip $(HAVE_STATIC_DUMMY)),)
|
||||
OFILES += libretro_libnx.a
|
||||
endif
|
||||
|
||||
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
export BUILD_EXEFS_SRC := $(TOPDIR)/$(EXEFS_SRC)
|
||||
|
||||
ifneq ($(APP_TITLEID),)
|
||||
export NACPFLAGS += --titleid=$(APP_TITLEID)
|
||||
endif
|
||||
|
||||
ifneq ($(ROMFS),)
|
||||
export NROFLAGS += --romfsdir=$(CURDIR)/$(ROMFS)
|
||||
endif
|
||||
|
||||
DEPENDS_TMP := $(OFILES:.o=.d)
|
||||
DEPENDS := $(filter-out libretro_libnx.a,$(DEPENDS_TMP))
|
||||
|
||||
.PHONY: clean all
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
all : $(OUTPUT)
|
||||
|
||||
$(OUTPUT): $(OBJ)
|
||||
$(CXX) -o $@ $(LDFLAGS) $(LIBDIRS) $(OBJ) $(PLATEXTRA) -L. -lretro_dos $(LIBS)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) -c -o $@ $(CFLAGS) $<
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) -c -o $@ $(CFLAGS) $<
|
||||
|
||||
clean:
|
||||
rm -f $(DEPENDS) $(OBJ) $(OUTPUT)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o %_bin.h : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
||||
@@ -43,6 +43,7 @@ HAVE_CONFIGFILE = 1
|
||||
HAVE_CHEATS = 1
|
||||
HAVE_IBXM = 1
|
||||
HAVE_CORE_INFO_CACHE = 1
|
||||
HAVE_7ZIP = 1
|
||||
|
||||
ASYNC ?= 0
|
||||
ifeq ($(LIBRETRO), mupen64plus)
|
||||
|
||||
+14
-46
@@ -66,7 +66,6 @@ SHADER_CG_DIR := media/shaders_cg
|
||||
OVERLAY_DIR := media/overlays
|
||||
SHADER_GLSL_DIR := media/shaders_glsl
|
||||
|
||||
PYTHON2 := python2$(EXE_EXT)
|
||||
PYTHON3 := python3$(EXE_EXT)
|
||||
GIT := git$(EXE_EXT)
|
||||
|
||||
@@ -122,14 +121,20 @@ else ifeq ($(libogc_platform), 1)
|
||||
CXX = $(DEVKITPPC)/bin/powerpc-eabi-g++$(EXE_EXT)
|
||||
LD = $(DEVKITPPC)/bin/powerpc-eabi-ld$(EXE_EXT)
|
||||
ELF2DOL = $(DEVKITPPC)/bin/elf2dol$(EXE_EXT)
|
||||
# Check whether ELF2DOL executable exists
|
||||
# (path has changed in more recent toolchains)
|
||||
ifeq ("$(wildcard $(ELF2DOL))","")
|
||||
ELF2DOL = $(DEVKITPRO)/tools/bin/elf2dol$(EXE_EXT)
|
||||
endif
|
||||
EXT_TARGET := $(TARGET_NAME)_$(platform).dol
|
||||
EXT_INTER_TARGET := $(TARGET_NAME)_$(platform).elf
|
||||
|
||||
INCLUDE += -I. -I$(DEVKITPRO)/libogc/include -Iwii/libogc/include
|
||||
INCLUDE += -I.
|
||||
|
||||
ifeq ($(EXTERNAL_LIBOGC), 1)
|
||||
CFLAGS += -DEXTERNAL_LIBOGC
|
||||
CXXFLAGS += -DEXTERNAL_LIBOGC
|
||||
INCLUDE += -I$(DEVKITPRO)/libogc/include
|
||||
|
||||
ifeq ($(platform), ngc)
|
||||
LIBDIRS += -L$(DEVKITPRO)/libogc/lib/cube
|
||||
@@ -140,6 +145,7 @@ else ifeq ($(libogc_platform), 1)
|
||||
else
|
||||
CFLAGS += -DINTERNAL_LIBOGC
|
||||
CXXFLAGS += -DINTERNAL_LIBOGC
|
||||
INCLUDE += -Iwii/libogc/include
|
||||
|
||||
ifeq ($(platform), ngc)
|
||||
LIBDIRS += -Lwii/libogc/libs/cube
|
||||
@@ -935,7 +941,7 @@ else ifeq (qnx,$(platform))
|
||||
LDFLAGS += -g
|
||||
endif
|
||||
|
||||
PLATCFLAGS += -DHAVE_SHADERPIPELINE -DHAVE_OPENGL -DHAVE_OPENGLES -DHAVE_OPENGLES2 -DHAVE_OZONE -DHAVE_CC_RESAMPLER -DHAVE_CHEEVOS -DRC_DISABLE_LUA -DHAVE_FBO -DHAVE_GL_SYNC -DHAVE_GLSLANG -DHAVE_BUILTINGLSLANG -DHAVE_IMAGEVIEWER -DHAVE_LANGEXTRA -DHAVE_RUNAHEAD -DHAVE_GFX_WIDGETS -DHAVE_CONFIGFILE -DHAVE_PATCH -DHAVE_SPIRV_CROSS -DHAVE_STB_FONT -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS -DHAVE_UPDATE_CORES -DHAVE_XMB -DRARCH_INTERNAL -DWANT_GLSLANG -DHAVE_XCB -DHAVE_EGL -DHAVE_BB10 -DHAVE_GLSL -DHAVE_AL -DHAVE_BSV_MOVIE -DRARCH_MOBILE
|
||||
PLATCFLAGS += -DHAVE_SHADERPIPELINE -DHAVE_OPENGL -DHAVE_OPENGLES -DHAVE_OPENGLES2 -DHAVE_OZONE -DHAVE_CC_RESAMPLER -DHAVE_CHEEVOS -DRC_DISABLE_LUA -DHAVE_GL_SYNC -DHAVE_GLSLANG -DHAVE_BUILTINGLSLANG -DHAVE_IMAGEVIEWER -DHAVE_LANGEXTRA -DHAVE_RUNAHEAD -DHAVE_GFX_WIDGETS -DHAVE_CONFIGFILE -DHAVE_PATCH -DHAVE_SPIRV_CROSS -DHAVE_STB_FONT -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS -DHAVE_UPDATE_CORES -DHAVE_XMB -DRARCH_INTERNAL -DWANT_GLSLANG -DHAVE_XCB -DHAVE_EGL -DHAVE_BB10 -DHAVE_GLSL -DHAVE_AL -DHAVE_BSV_MOVIE -DRARCH_MOBILE
|
||||
EXT_TARGET := $(TARGET_NAME)
|
||||
EXT_INTER_TARGET := $(TARGET_NAME)
|
||||
INCLUDE += -Ilibretro-common/include -Igfx/include -Ideps -Ideps/stb -Ideps/rcheevos/include -Ideps/SPIRV-Cross -Ideps/glslang -I.
|
||||
@@ -973,53 +979,11 @@ else ifneq (,$(findstring unix,$(platform)))
|
||||
HAVE_CHEATS := 1
|
||||
HAVE_CORE_INFO_CACHE := 1
|
||||
|
||||
PLATCFLAGS += -D__MMX__ -D__SSE__ -DHAVE_OPENGL -DHAVE_OPENGL1 -DHAVE_GLSL -DHAVE_SHADERPIPELINE -DHAVE_OZONE -DHAVE_CC_RESAMPLER -DHAVE_CHEEVOS -DRC_DISABLE_LUA -DHAVE_FBO -DHAVE_GL_SYNC -DHAVE_SLANG -DHAVE_GLSLANG -DHAVE_BUILTINGLSLANG -DHAVE_IMAGEVIEWER -DHAVE_LANGEXTRA -DHAVE_RUNAHEAD -DHAVE_GFX_WIDGETS -DHAVE_CONFIGFILE -DHAVE_PATCH -DHAVE_SPIRV_CROSS -DHAVE_STB_FONT -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS -DHAVE_UPDATE_CORES -DHAVE_VULKAN -DHAVE_XMB -DRARCH_INTERNAL -DWANT_GLSLANG -DHAVE_X11 -DHAVE_XCB -DHAVE_UDEV -DHAVE_BSV_MOVIE -DHAVE_PULSE
|
||||
PLATCFLAGS += -D__MMX__ -D__SSE__ -DHAVE_OPENGL -DHAVE_OPENGL1 -DHAVE_GLSL -DHAVE_SHADERPIPELINE -DHAVE_OZONE -DHAVE_CC_RESAMPLER -DHAVE_CHEEVOS -DRC_DISABLE_LUA -DHAVE_GL_SYNC -DHAVE_SLANG -DHAVE_GLSLANG -DHAVE_BUILTINGLSLANG -DHAVE_IMAGEVIEWER -DHAVE_LANGEXTRA -DHAVE_RUNAHEAD -DHAVE_GFX_WIDGETS -DHAVE_CONFIGFILE -DHAVE_PATCH -DHAVE_SPIRV_CROSS -DHAVE_STB_FONT -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS -DHAVE_UPDATE_CORES -DHAVE_VULKAN -DHAVE_XMB -DRARCH_INTERNAL -DWANT_GLSLANG -DHAVE_X11 -DHAVE_XCB -DHAVE_UDEV -DHAVE_BSV_MOVIE -DHAVE_PULSE
|
||||
EXT_TARGET := $(TARGET_NAME)
|
||||
EXT_INTER_TARGET := $(TARGET_NAME)
|
||||
INCLUDE += -Ilibretro-common/include -Igfx/include -Ideps -Ideps/stb -Ideps/rcheevos/include -Ideps/SPIRV-Cross -Ideps/glslang -I.
|
||||
LIBS += -ldl -lm -lpthread -lGL -ludev -lpulse -lX11 -lX11-xcb -lXxf86vm
|
||||
else ifeq (dos,$(platform))
|
||||
HAVE_RPNG := 1
|
||||
HAVE_RJPEG := 1
|
||||
HAVE_RBMP := 1
|
||||
HAVE_RTGA := 1
|
||||
HAVE_ZLIB := 1
|
||||
HAVE_7ZIP := 1
|
||||
HAVE_NETWORKING := 0
|
||||
HAVE_NETWORK_CMD := 0
|
||||
HAVE_NETPLAYDISCOVERY := 0
|
||||
HAVE_OVERLAY := 1
|
||||
HAVE_VIDEO_LAYOUT := 0
|
||||
HAVE_MATERIALUI := 0
|
||||
HAVE_XMB := 0
|
||||
HAVE_STB_FONT := 1
|
||||
HAVE_THREADS := 0
|
||||
HAVE_LIBRETRODB := 1
|
||||
HAVE_COMMAND := 1
|
||||
HAVE_STDIN_CMD := 1
|
||||
HAVE_CMD := 1
|
||||
HAVE_DYLIB := 0
|
||||
HAVE_DYNAMIC := 0
|
||||
HAVE_GRIFFIN_CPP := 0
|
||||
WANT_GLSLANG := 0
|
||||
HAVE_CONFIGFILE := 1
|
||||
HAVE_PATCH := 0
|
||||
HAVE_CHEATS := 0
|
||||
HAVE_CORE_INFO_CACHE := 1
|
||||
CC=i586-pc-msdosdjgpp-gcc
|
||||
CXX=i586-pc-msdosdjgpp-g++
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
LDFLAGS += -g
|
||||
endif
|
||||
|
||||
PLATCFLAGS += -DHAVE_SHADERPIPELINE -DHAVE_CC_RESAMPLER -DRC_DISABLE_LUA -DHAVE_FBO -DHAVE_IMAGEVIEWER -DHAVE_LANGEXTRA -DHAVE_GFX_WIDGETS -DHAVE_CONFIGFILE -DHAVE_PATCH -DHAVE_SPIRV_CROSS -DHAVE_STB_FONT -DRARCH_INTERNAL -DHAVE_XCB
|
||||
TARGET_NAME := retrodos
|
||||
EXT_TARGET := $(TARGET_NAME).exe
|
||||
EXT_INTER_TARGET := $(TARGET_NAME).exe
|
||||
INCLUDE += -Ilibretro-common/include -Igfx/include -Ideps -Ideps/stb -Ideps/SPIRV-Cross -Ideps/glslang -I.
|
||||
LIBS += -lm
|
||||
LIBDIRS += -L.
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring msvc,$(platform)))
|
||||
@@ -1197,6 +1161,10 @@ ifeq ($(HAVE_FILTERS_BUILTIN), 1)
|
||||
CFLAGS += -DHAVE_FILTERS_BUILTIN
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_WINDOW_OFFSET), 1)
|
||||
CFLAGS += -DHAVE_WINDOW_OFFSET
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_THREADS), 1)
|
||||
CFLAGS += -DHAVE_THREADS
|
||||
|
||||
|
||||
+1
-1
@@ -111,7 +111,7 @@ HAVE_CHEEVOS = 0
|
||||
HAVE_LIBSHAKE = 0
|
||||
HAVE_CORE_INFO_CACHE = 1
|
||||
#HAVE_TINYALSA = 1
|
||||
#HAVE_NEAREST_RESAMPLER = 1
|
||||
HAVE_NEAREST_RESAMPLER = 1
|
||||
|
||||
OS = Linux
|
||||
TARGET = retroarch
|
||||
|
||||
+20
-125
@@ -63,16 +63,18 @@ ifeq ("$(wildcard $(ELF2DOL))","")
|
||||
ELF2DOL = $(DEVKITPRO)/tools/bin/elf2dol$(EXE_EXT)
|
||||
endif
|
||||
|
||||
INCLUDE += -I. -I$(DEVKITPRO)/libogc/include -Iwii/libogc/include
|
||||
INCLUDE += -I.
|
||||
|
||||
ifeq ($(EXTERNAL_LIBOGC), 1)
|
||||
CFLAGS += -DEXTERNAL_LIBOGC
|
||||
CXXFLAGS += -DEXTERNAL_LIBOGC
|
||||
LIBDIRS += -L$(DEVKITPRO)/libogc/lib/cube
|
||||
INCLUDE += -I$(DEVKITPRO)/libogc/include
|
||||
else
|
||||
CFLAGS += -DINTERNAL_LIBOGC
|
||||
CXXFLAGS += -DINTERNAL_LIBOGC
|
||||
LIBDIRS += -Lwii/libogc/libs/cube
|
||||
INCLUDE += -Iwii/libogc/include
|
||||
endif
|
||||
|
||||
ifeq ($(GX_PTHREAD_LEGACY), 1)
|
||||
@@ -127,18 +129,31 @@ HAVE_RWAV := 1
|
||||
RARCH_CONSOLE = 1
|
||||
HAVE_CHEATS := 1
|
||||
HAVE_CORE_INFO_CACHE := 1
|
||||
HAVE_MENU_COMMON := 1
|
||||
HAVE_MENU := 1
|
||||
HAVE_BUILTINZLIB := 1
|
||||
HAVE_STATIC_AUDIO_FILTERS := 1
|
||||
HAVE_STATIC_VIDEO_FILTERS := 1
|
||||
HAVE_XMB := 0
|
||||
HAVE_OZONE := 0
|
||||
HAVE_RGUI := 1
|
||||
HAVE_MATERIALUI := 0
|
||||
|
||||
CFLAGS += -Wall -std=gnu99 $(MACHDEP) $(PLATCFLAGS) $(INCLUDE)
|
||||
INCLUDE += -I./libretro-common/include \
|
||||
-Ideps \
|
||||
-Ideps/stb
|
||||
CFLAGS += -Wall -std=gnu99 $(MACHDEP) $(PLATCFLAGS) $(INCLUDE)
|
||||
|
||||
OBJ = griffin/griffin.o $(PLATOBJS)
|
||||
OBJ = $(PLATOBJS) audio/drivers/gx_audio.o gfx/drivers/gx_gfx.o input/drivers/gx_input.o frontend/drivers/platform_gx.o input/drivers_joypad/gx_joypad.o
|
||||
|
||||
ifeq ($(HAVE_GRIFFIN_CPP), 1)
|
||||
OBJ += griffin/griffin_cpp.o
|
||||
ifeq ($(EXTERNAL_LIBOGC), 0)
|
||||
OBJ += wii/libogc/libfat/libfat.o wii/libogc/libfat/fatfile.o wii/libogc/libfat/file_allocation_table.o wii/libogc/libfat/cache.o wii/libogc/libfat/fatdir.o wii/libogc/libfat/partition.o wii/libogc/libfat/directory.o wii/libogc/libfat/filetime.o wii/libogc/libfat/disc.o
|
||||
endif
|
||||
|
||||
include Makefile.common
|
||||
|
||||
CFLAGS += $(DEFINES)
|
||||
|
||||
ifeq ($(WANT_GLSLANG), 1)
|
||||
OBJ += griffin/griffin_glslang.o
|
||||
endif
|
||||
@@ -156,18 +171,10 @@ ifeq ($(HAVE_WIIUSB_HID), 1)
|
||||
CFLAGS += -DHAVE_WIIUSB_HID -DHAVE_HID
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_LIBRETRODB), 1)
|
||||
CFLAGS += -DHAVE_LIBRETRODB
|
||||
endif
|
||||
|
||||
ifeq ($(BIG_STACK),1)
|
||||
CFLAGS += -DBIG_STACK
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_RJPEG), 1)
|
||||
CFLAGS += -DHAVE_RJPEG
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_FILE_LOGGER), 1)
|
||||
CFLAGS += -DHAVE_FILE_LOGGER
|
||||
endif
|
||||
@@ -181,66 +188,10 @@ ifeq ($(HAVE_ZLIB), 1)
|
||||
CFLAGS += -I./libretro-common/include/compat/zlib
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_RPNG), 1)
|
||||
CFLAGS += -DHAVE_RPNG
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_RBMP), 1)
|
||||
CFLAGS += -DHAVE_RBMP
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_RTGA), 1)
|
||||
CFLAGS += -DHAVE_RTGA
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_IMAGEVIEWER), 1)
|
||||
CFLAGS += -DHAVE_IMAGEVIEWER
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_BSV_MOVIE), 1)
|
||||
CFLAGS += -DHAVE_BSV_MOVIE
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_RUNAHEAD), 1)
|
||||
CFLAGS += -DHAVE_RUNAHEAD
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_7ZIP), 1)
|
||||
CFLAGS += -DHAVE_7ZIP -D_7ZIP_ST
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_SCREENSHOTS), 1)
|
||||
CFLAGS += -DHAVE_SCREENSHOTS
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_REWIND), 1)
|
||||
CFLAGS += -DHAVE_REWIND
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_AUDIOMIXER), 1)
|
||||
CFLAGS += -DHAVE_AUDIOMIXER
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_RWAV), 1)
|
||||
CFLAGS += -DHAVE_RWAV
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_OVERLAY), 1)
|
||||
CFLAGS += -DHAVE_OVERLAY
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_VIDEO_LAYOUT), 1)
|
||||
CFLAGS += -DHAVE_VIDEO_LAYOUT
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_NETWORKING), 1)
|
||||
CFLAGS += -DHAVE_NETWORKING
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_NETPLAYDISCOVERY), 1)
|
||||
CFLAGS += -DHAVE_NETPLAYDISCOVERY
|
||||
endif
|
||||
|
||||
ifeq ($(RARCH_CONSOLE), 1)
|
||||
CFLAGS += -DRARCH_CONSOLE
|
||||
endif
|
||||
@@ -251,50 +202,10 @@ endif
|
||||
|
||||
CFLAGS += -std=gnu99 -DHAVE_RGUI -DHAVE_MENU -DHAVE_GRIFFIN=1 -Wno-char-subscripts -DRARCH_INTERNAL
|
||||
|
||||
ifeq ($(HAVE_MATERIALUI), 1)
|
||||
CFLAGS += -DHAVE_MATERIALUI
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_XMB), 1)
|
||||
CFLAGS += -DHAVE_XMB
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_STB_FONT), 1)
|
||||
CFLAGS += -DHAVE_STB_FONT
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_LANGEXTRA), 1)
|
||||
CFLAGS += -DHAVE_LANGEXTRA
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_DSP_FILTER), 1)
|
||||
CFLAGS += -DHAVE_DSP_FILTER
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_VIDEO_FILTER), 1)
|
||||
CFLAGS += -DHAVE_VIDEO_FILTER
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_FILTERS_BUILTIN), 1)
|
||||
CFLAGS += -DHAVE_FILTERS_BUILTIN
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_THREADS), 1)
|
||||
CFLAGS += -DHAVE_THREADS
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_CONFIGFILE), 1)
|
||||
CFLAGS += -DHAVE_CONFIGFILE
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_PATCH), 1)
|
||||
CFLAGS += -DHAVE_PATCH
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_CHEATS), 1)
|
||||
CFLAGS += -DHAVE_CHEATS
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_RSOUND), 1)
|
||||
CFLAGS += -DHAVE_RSOUND
|
||||
endif
|
||||
@@ -303,30 +214,14 @@ ifeq ($(HAVE_GETOPT_LONG), 1)
|
||||
CFLAGS += -DHAVE_GETOPT_LONG=1
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_DYLIB), 1)
|
||||
CFLAGS += -DHAVE_DYLIB
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_NETWORK_CMD), 1)
|
||||
CFLAGS += -DHAVE_NETWORK_CMD
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_COMMAND), 1)
|
||||
CFLAGS += -DHAVE_COMMAND
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_STDIN_CMD), 1)
|
||||
CFLAGS += -DHAVE_STDIN_CMD
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_DYNAMIC), 1)
|
||||
CFLAGS += -DHAVE_DYNAMIC
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_CORE_INFO_CACHE), 1)
|
||||
CFLAGS += -DHAVE_CORE_INFO_CACHE
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
CFLAGS += -O0 -g -DDEBUG
|
||||
else
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ pnd: retroarch.pnd
|
||||
install: all $(BINDIR)/retroarch-joyconfig $(BINDIR)/retroarch-zip $(PNDDIR)/readme.html
|
||||
|
||||
retroarch:
|
||||
./configure --prefix=$PND_BASEDIR/$PRJ --disable-ffmpeg --disable-cg --disable-python --disable-libpng --disable-pulse --disable-jack --enable-gles --enable-xml
|
||||
./configure --prefix=$PND_BASEDIR/$PRJ --disable-ffmpeg --disable-cg --disable-pulse --disable-jack --enable-opengles
|
||||
make -f Makefile
|
||||
|
||||
$(BINDIR)/retroarch: retroarch
|
||||
|
||||
+84
-63
@@ -1,90 +1,113 @@
|
||||
TARGET := retroarch_ps2
|
||||
TARGET_RELEASE = retroarchps2.elf
|
||||
|
||||
BUILD_FOR_PCSX2 = 0
|
||||
DEBUG = 0
|
||||
SCREEN_DEBUG = 0
|
||||
GRIFFIN_BUILD = 0
|
||||
HAVE_THREADS = 0
|
||||
MUTE_WARNINGS = 1
|
||||
WHOLE_ARCHIVE_LINK = 0
|
||||
HAVE_STATIC_DUMMY ?= 0
|
||||
PS2_IP = 192.168.1.10
|
||||
|
||||
TARGET = retroarchps2-debug.elf
|
||||
TARGET_RELEASE = retroarchps2.elf
|
||||
|
||||
# Compile the IRXs first
|
||||
IRX_DIR = ps2/irx
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
OPTIMIZE_LV := -O0 -g
|
||||
RARCH_DEFINES += -DDEBUG
|
||||
DEFINES += -DDEBUG
|
||||
else
|
||||
OPTIMIZE_LV := -O3
|
||||
LDFLAGS := -s
|
||||
# LDFLAGS := -s
|
||||
endif
|
||||
|
||||
ifeq ($(MUTE_WARNINGS), 1)
|
||||
DISABLE_WARNINGS := -Wno-unused -Wno-format -Wno-format-truncation
|
||||
endif
|
||||
|
||||
INCDIR = -I$(PS2DEV)/gsKit/include -I$(PS2SDK)/ports/include
|
||||
INCDIR += -Ips2/include -Ilibretro-common/include -Ideps -Ideps/stb -Ideps/7zip
|
||||
CFLAGS = $(OPTIMIZE_LV) $(DISABLE_WARNINGS) -ffast-math -fsingle-precision-constant
|
||||
ASFLAGS = $(CFLAGS)
|
||||
|
||||
RARCH_DEFINES += -DPS2 \
|
||||
-DHAVE_GRIFFIN=1 \
|
||||
-DRARCH_INTERNAL \
|
||||
-DHAVE_SCREENSHOTS \
|
||||
-DHAVE_REWIND \
|
||||
-DRARCH_CONSOLE \
|
||||
-DHAVE_MENU \
|
||||
-DHAVE_CONFIGFILE \
|
||||
-DHAVE_PATCH \
|
||||
-DHAVE_CHEATS \
|
||||
-DHAVE_ZLIB \
|
||||
-DHAVE_NO_BUILTINZLIB \
|
||||
-DHAVE_RPNG \
|
||||
-DHAVE_RJPEG \
|
||||
-DHAVE_FILTERS_BUILTIN \
|
||||
-DHAVE_7ZIP \
|
||||
-D_7ZIP_ST \
|
||||
-DHAVE_CC_RESAMPLER \
|
||||
-DHAVE_AUDIOMIXER \
|
||||
-DHAVE_WINDOW_OFFSET \
|
||||
-DHAVE_VIDEO_FILTER \
|
||||
-DHAVE_RGUI \
|
||||
-DHAVE_DSP_FILTER \
|
||||
-DHAVE_CORE_INFO_CACHE
|
||||
|
||||
LDFLAGS += -L$(PS2DEV)/gsKit/lib -L$(PS2SDK)/ports/lib -L.
|
||||
# Lib cdvd is needed to get proper time
|
||||
LIBS += -lretro_ps2 -lpatches -lgskit -ldmakit -laudsrv -lmtap -lpadx -lz -lcdvd -lelf-loader -lfileXio -lpoweroff
|
||||
ifeq ($(HAVE_STATIC_DUMMY),1)
|
||||
DEFINES += -DHAVE_STATIC_DUMMY
|
||||
else
|
||||
LIBS += -lretro_ps2
|
||||
endif
|
||||
|
||||
ifeq ($(SCREEN_DEBUG), 1)
|
||||
LIBS += -ldebug
|
||||
RARCH_DEFINES += -DSCREEN_DEBUG
|
||||
DEFINES += -DSCREEN_DEBUG
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_FOR_PCSX2), 1)
|
||||
RARCH_DEFINES += -DBUILD_FOR_PCSX2
|
||||
DEFINES += -DBUILD_FOR_PCSX2
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_THREADS), 1)
|
||||
RARCH_DEFINES += -DHAVE_THREADS
|
||||
DEFINES += -DRARCH_INTERNAL -DRARCH_CONSOLE
|
||||
|
||||
ifeq ($(GRIFFIN_BUILD), 1)
|
||||
OBJ += griffin/griffin.o
|
||||
DEFINES += -DHAVE_GRIFFIN=1 -DHAVE_SCREENSHOTS -DHAVE_REWIND -DHAVE_MENU -DHAVE_CONFIGFILE -DHAVE_PATCH -DHAVE_CHEATS
|
||||
DEFINES += -DHAVE_ZLIB -DHAVE_NO_BUILTINZLIB -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_FILTERS_BUILTIN -DHAVE_7ZIP -D_7ZIP_ST -DHAVE_CC_RESAMPLER -DHAVE_AUDIOMIXER
|
||||
DEFINES += -DHAVE_VIDEO_FILTER -DHAVE_RGUI -DHAVE_WINDOW_OFFSET
|
||||
DEFINES += -DHAVE_DSP_FILTER
|
||||
else
|
||||
HAVE_CC_RESAMPLER = 1
|
||||
HAVE_MENU_COMMON = 1
|
||||
HAVE_RPNG = 1
|
||||
HAVE_RJPEG = 1
|
||||
HAVE_RBMP = 1
|
||||
HAVE_MENU = 1
|
||||
HAVE_CONFIGFILE = 1
|
||||
HAVE_PATCH = 1
|
||||
HAVE_CHEATS = 1
|
||||
HAVE_RGUI = 1
|
||||
HAVE_MATERIALUI = 0
|
||||
HAVE_XMB = 0
|
||||
HAVE_OZONE = 0
|
||||
HAVE_ZLIB = 1
|
||||
HAVE_NO_BUILTINZLIB = 1
|
||||
HAVE_7ZIP = 1
|
||||
HAVE_SCREENSHOTS = 1
|
||||
HAVE_REWIND = 1
|
||||
HAVE_AUDIOMIXER = 1
|
||||
HAVE_RWAV = 1
|
||||
HAVE_DSP_FILTER = 1
|
||||
HAVE_VIDEO_FILTER = 1
|
||||
HAVE_FILTERS_BUILTIN = 1
|
||||
HAVE_WINDOW_OFFSET = 1
|
||||
|
||||
include Makefile.common
|
||||
CFLAGS += $(DEF_FLAGS)
|
||||
BLACKLIST :=
|
||||
OBJ := $(filter-out $(BLACKLIST),$(OBJ))
|
||||
INCDIRS += $(INCLUDE_DIRS)
|
||||
endif
|
||||
|
||||
CFLAGS += $(RARCH_DEFINES)
|
||||
ifeq ($(strip $(PS2SDK)),)
|
||||
$(error "Please set PS2SDK in your environment. export PS2SDK=<path to>ps2sdk")
|
||||
endif
|
||||
|
||||
# All the IRX objects
|
||||
EE_OBJS += $(IRX_DIR)/sio2man_irx.o $ $(IRX_DIR)/iomanX_irx.o $(IRX_DIR)/fileXio_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/mcman_irx.o $(IRX_DIR)/mcserv_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/usbd_irx.o $(IRX_DIR)/bdm_irx.o $(IRX_DIR)/bdmfs_vfat_irx.o $(IRX_DIR)/usbmass_bd_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/libsd_irx.o $(IRX_DIR)/audsrv_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/cdfs_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/ps2dev9_irx.o $(IRX_DIR)/ps2atad_irx.o $(IRX_DIR)/ps2hdd_irx.o $(IRX_DIR)/ps2fs_irx.o $(IRX_DIR)/poweroff_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/mtapman_irx.o $(IRX_DIR)/padman_irx.o
|
||||
INCDIR = -I$(PS2DEV)/gsKit/include -I$(PS2SDK)/ports/include
|
||||
INCDIR += -Ips2/include -Ilibretro-common/include -Ideps -Ideps/stb -Ideps/7zip
|
||||
|
||||
LDFLAGS += -L$(PS2DEV)/gsKit/lib -L$(PS2SDK)/ports/lib -L.
|
||||
# Lib cdvd is needed to get proper time
|
||||
LIBS += -lpatches -lgskit -ldmakit -laudsrv -lmtap -lpadx -lz -lcdvd -lelf-loader -lfileXio -lpoweroff
|
||||
|
||||
|
||||
CFLAGS = $(OPTIMIZE_LV) $(DISABLE_WARNINGS) $(DEFINES) -DPS2 -ffast-math -fsingle-precision-constant
|
||||
ASFLAGS = $(CFLAGS)
|
||||
|
||||
# IRX libs
|
||||
IRX_FILES += sio2man.irx iomanX.irx fileXio.irx
|
||||
IRX_FILES += mcman.irx mcserv.irx
|
||||
IRX_FILES += usbd.irx bdm.irx bdmfs_vfat.irx usbmass_bd.irx
|
||||
IRX_FILES += libsd.irx audsrv.irx
|
||||
IRX_FILES += cdfs.irx
|
||||
IRX_FILES += ps2dev9.irx ps2atad.irx ps2hdd.irx ps2fs.irx poweroff.irx
|
||||
IRX_FILES += mtapman.irx padman.irx
|
||||
EE_OBJS += $(IRX_FILES:.irx=_irx.o)
|
||||
|
||||
# Missing objecst on the PS2SDK
|
||||
EE_OBJS += ps2/compat_files/ps2_devices.o
|
||||
|
||||
EE_OBJS += griffin/griffin.o
|
||||
EE_OBJS += $(OBJ)
|
||||
|
||||
EE_CFLAGS = $(CFLAGS)
|
||||
EE_CXXFLAGS = $(CFLAGS)
|
||||
@@ -92,18 +115,14 @@ EE_LDFLAGS = $(LDFLAGS)
|
||||
EE_LIBS = $(LIBS)
|
||||
EE_ASFLAGS = $(ASFLAGS)
|
||||
EE_INCS = $(INCDIR)
|
||||
EE_BIN = $(TARGET)
|
||||
EE_BIN = $(TARGET).elf
|
||||
EE_GPVAL = $(GPVAL)
|
||||
|
||||
|
||||
all: irxdir $(EE_BIN)
|
||||
|
||||
irxdir:
|
||||
$(MAKE) -C $(IRX_DIR)
|
||||
all: $(EE_BIN)
|
||||
|
||||
clean:
|
||||
rm -f $(EE_BIN) $(EE_OBJS)
|
||||
$(MAKE) -C $(IRX_DIR) clean
|
||||
|
||||
prepare:
|
||||
ps2client -h $(PS2_IP) reset
|
||||
@@ -117,10 +136,12 @@ sim:
|
||||
|
||||
debug: clean all run
|
||||
|
||||
package:
|
||||
release: all
|
||||
ps2-packer $(EE_BIN) $(TARGET_RELEASE)
|
||||
|
||||
release: clean all package
|
||||
# IRX files
|
||||
%_irx.c:
|
||||
$(PS2SDK)/bin/bin2c $(PS2SDK)/iop/irx/$*.irx $@ $*_irx
|
||||
|
||||
#Include preferences
|
||||
include $(PS2SDK)/samples/Makefile.pref
|
||||
|
||||
+14
-18
@@ -7,9 +7,6 @@ PS2_IP = 192.168.1.150
|
||||
TARGET = raboot-debug.elf
|
||||
TARGET_RELEASE = raboot.elf
|
||||
|
||||
# Compile the IRXs first
|
||||
IRX_DIR = ps2/irx
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
OPTIMIZE_LV := -O0 -g
|
||||
RARCH_DEFINES += -DDEBUG
|
||||
@@ -19,7 +16,7 @@ else
|
||||
endif
|
||||
|
||||
ifeq ($(MUTE_WARNINGS), 1)
|
||||
DISABLE_WARNINGS := -Wno-sign-compare -Wno-unused -Wno-parentheses
|
||||
DISABLE_WARNINGS := -Wno-unused -Wno-format -Wno-format-truncation
|
||||
endif
|
||||
|
||||
INCDIR = -Ilibretro-common/include
|
||||
@@ -63,14 +60,15 @@ EE_OBJS = frontend/frontend_salamander.o \
|
||||
libretro-common/hash/lrc_hash.o \
|
||||
libretro-common/time/rtime.o \
|
||||
verbosity.o \
|
||||
ps2/compat_files/ps2_devices.o
|
||||
ps2/compat_files/ps2_devices.o
|
||||
|
||||
# Needed IRX objects
|
||||
EE_OBJS += $(IRX_DIR)/sio2man_irx.o $ $(IRX_DIR)/iomanX_irx.o $(IRX_DIR)/fileXio_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/mcman_irx.o $(IRX_DIR)/mcserv_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/usbd_irx.o $(IRX_DIR)/bdm_irx.o $(IRX_DIR)/bdmfs_vfat_irx.o $(IRX_DIR)/usbmass_bd_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/cdfs_irx.o
|
||||
EE_OBJS += $(IRX_DIR)/ps2dev9_irx.o $(IRX_DIR)/ps2atad_irx.o $(IRX_DIR)/ps2hdd_irx.o $(IRX_DIR)/ps2fs_irx.o $(IRX_DIR)/poweroff_irx.o
|
||||
# IRX libs
|
||||
IRX_FILES += sio2man.irx iomanX.irx fileXio.irx
|
||||
IRX_FILES += mcman.irx mcserv.irx
|
||||
IRX_FILES += usbd.irx bdm.irx bdmfs_vfat.irx usbmass_bd.irx
|
||||
IRX_FILES += cdfs.irx
|
||||
IRX_FILES += ps2dev9.irx ps2atad.irx ps2hdd.irx ps2fs.irx poweroff.irx
|
||||
EE_OBJS += $(IRX_FILES:.irx=_irx.o)
|
||||
|
||||
EE_CFLAGS = $(CFLAGS)
|
||||
EE_CXXFLAGS = $(CFLAGS)
|
||||
@@ -81,24 +79,22 @@ EE_INCS = $(INCDIR)
|
||||
EE_BIN = $(TARGET)
|
||||
EE_GPVAL = $(GPVAL)
|
||||
|
||||
all: irxdir $(EE_BIN)
|
||||
|
||||
irxdir:
|
||||
$(MAKE) -C $(IRX_DIR)
|
||||
all: $(EE_BIN)
|
||||
|
||||
clean:
|
||||
rm -f $(EE_BIN) $(EE_OBJS)
|
||||
$(MAKE) -C $(IRX_DIR) clean
|
||||
|
||||
debug: clean all run
|
||||
|
||||
run:
|
||||
ps2client -h $(PS2_IP) execee host:$(EE_BIN)
|
||||
|
||||
package:
|
||||
release: all
|
||||
ps2-packer $(EE_BIN) $(TARGET_RELEASE)
|
||||
|
||||
release: clean all package
|
||||
# IRX files
|
||||
%_irx.c:
|
||||
$(PS2SDK)/bin/bin2c $(PS2SDK)/iop/irx/$*.irx $@ $*_irx
|
||||
|
||||
#Include preferences
|
||||
include $(PS2SDK)/samples/Makefile.pref
|
||||
|
||||
+9
-2
@@ -33,7 +33,7 @@ LIBDIRS += -L.
|
||||
MACHDEP := -D__PSL1GHT__ -D__PS3__ -mcpu=cell
|
||||
CFLAGS += -Wall $(MACHDEP) $(INCLUDE)
|
||||
LDFLAGS := $(MACHDEP)
|
||||
LIBS := -lretro_psl1ght -laudio -lrsx -lgcm_sys -lnet -lio -lsysutil -lsysmodule -lm -ljpgdec -lpngdec -llv2 -lnet -lnetctl -lsysfs
|
||||
LIBS := -lretro_psl1ght -laudio -lrsx -lgcm_sys -lnet -lio -lsysutil -lsysmodule -lm -ljpgdec -lpngdec -llv2 -lnet -lnetctl -lsysfs -lfreetype -lcamera -lgem -lspurs
|
||||
|
||||
# system platform
|
||||
system_platform = unix
|
||||
@@ -53,7 +53,12 @@ else
|
||||
GIT = git.exe
|
||||
endif
|
||||
|
||||
OBJ = griffin/griffin.o
|
||||
SHADER_OBJS = gfx/drivers/rsx_shaders/vpshader_basic.vpo.o \
|
||||
gfx/drivers/rsx_shaders/fpshader_basic.fpo.o
|
||||
|
||||
LIBCO_OBJ = libretro-common/libco/ps3.o
|
||||
|
||||
OBJ = $(SHADER_OBJS) $(LIBCO_OBJ) griffin/griffin.o
|
||||
|
||||
ifeq ($(HAVE_LOGGER), 1)
|
||||
CFLAGS += -DHAVE_LOGGER
|
||||
@@ -92,7 +97,9 @@ SHARED_FLAGS += -DHAVE_MENU \
|
||||
-DHAVE_SCREENSHOTS \
|
||||
-DHAVE_REWIND \
|
||||
-DHAVE_MULTIMAN \
|
||||
-DHAVE_MEMINFO \
|
||||
-DHAVE_RGUI \
|
||||
-DHAVE_FREETYPE \
|
||||
-DHAVE_CORE_INFO_CACHE
|
||||
CFLAGS += -std=gnu99 $(SHARED_FLAGS)
|
||||
CXXFLAGS += $(SHARED_FLAGS)
|
||||
|
||||
+26
-18
@@ -1,10 +1,11 @@
|
||||
BUILD_PRX = 0
|
||||
PSP_LARGE_MEMORY = 1
|
||||
DEBUG = 0
|
||||
HAVE_KERNEL_PRX = 1
|
||||
HAVE_THREADS = 1
|
||||
BIG_STACK = 0
|
||||
WHOLE_ARCHIVE_LINK = 0
|
||||
BUILD_PRX ?= 0
|
||||
PSP_LARGE_MEMORY ?= 1
|
||||
DEBUG ?= 0
|
||||
HAVE_KERNEL_PRX ?= 1
|
||||
HAVE_THREADS ?= 1
|
||||
BIG_STACK ?= 0
|
||||
LOAD_WITHOUT_CORE_INFO ?= 0
|
||||
HAVE_STATIC_DUMMY ?= 0
|
||||
|
||||
TARGET = retroarchpsp
|
||||
|
||||
@@ -14,13 +15,8 @@ else
|
||||
OPTIMIZE_LV := -O3
|
||||
endif
|
||||
|
||||
ifeq ($(WHOLE_ARCHIVE_LINK), 1)
|
||||
WHOLE_START := -Wl,--whole-archive
|
||||
WHOLE_END := -Wl,--no-whole-archive
|
||||
endif
|
||||
|
||||
INCDIR = deps deps/stb deps/7zip libretro-common/include libretro-common/include/compat/zlib
|
||||
CFLAGS = $(OPTIMIZE_LV) -G0 -std=gnu99 -ffast-math -fsingle-precision-constant
|
||||
CFLAGS = $(OPTIMIZE_LV) -ffast-math -fsingle-precision-constant
|
||||
ASFLAGS = $(CFLAGS)
|
||||
|
||||
RARCH_DEFINES = -DPSP \
|
||||
@@ -50,14 +46,21 @@ RARCH_DEFINES = -DPSP \
|
||||
-DHAVE_CORE_INFO_CACHE
|
||||
|
||||
LIBDIR =
|
||||
LDFLAGS =
|
||||
LIBS = $(WHOLE_START) -lretro_psp1 $(WHOLE_END) -lstdc++ -lpspgu -lpspgum -lm -lpspaudio -lpspfpu -lpsppower -lpsprtc -lpthread-psp
|
||||
LDFLAGS = -L$(shell psp-config --psp-prefix)
|
||||
|
||||
ifeq ($(HAVE_STATIC_DUMMY),1)
|
||||
RARCH_DEFINES += -DHAVE_STATIC_DUMMY
|
||||
else
|
||||
LIBS += -lretro_psp1
|
||||
endif
|
||||
LIBS += -lstdc++ -lpspgu -lpspgum -lpspaudio -lpspfpu -lpsppower -lpsprtc -lpthread
|
||||
|
||||
ifeq ($(HAVE_THREADS), 1)
|
||||
RARCH_DEFINES += -DHAVE_THREADS
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_KERNEL_PRX), 1)
|
||||
OBJS += bootstrap/psp1/kernel_functions.o
|
||||
CFLAGS += -DHAVE_KERNEL_PRX
|
||||
endif
|
||||
|
||||
@@ -65,14 +68,16 @@ ifeq ($(BIG_STACK), 1)
|
||||
CFLAGS += -DBIG_STACK
|
||||
endif
|
||||
|
||||
ifeq ($(LOAD_WITHOUT_CORE_INFO),1)
|
||||
RARCH_DEFINES += -DLOAD_WITHOUT_CORE_INFO
|
||||
endif
|
||||
|
||||
CFLAGS += $(RARCH_DEFINES)
|
||||
|
||||
EXTRA_TARGETS = EBOOT.PBP
|
||||
PSP_EBOOT_TITLE = RetroArch PSP1
|
||||
|
||||
PSP_OBJECTS = griffin/griffin.o bootstrap/psp1/kernel_functions.o
|
||||
|
||||
OBJS = $(PSP_OBJECTS)
|
||||
OBJS += griffin/griffin.o
|
||||
|
||||
PSPSDK=$(shell psp-config --pspsdk-path)
|
||||
include $(PSPSDK)/lib/build.mak
|
||||
@@ -91,3 +96,6 @@ pspsh-run:
|
||||
debug: clean all pspsh-debug
|
||||
|
||||
run: clean all pspsh-run
|
||||
|
||||
sim:
|
||||
/Applications/PPSSPPSDL.app/Contents/MacOS/PPSSPPSDL $(shell pwd)/EBOOT.PBP
|
||||
@@ -1,5 +1,6 @@
|
||||
BUILD_PRX = 0
|
||||
PSP_LARGE_MEMORY = 1
|
||||
HAVE_KERNEL_PRX = 1
|
||||
DEBUG = 0
|
||||
|
||||
TARGET = retroarchpsp_salamander
|
||||
@@ -7,18 +8,18 @@ TARGET = retroarchpsp_salamander
|
||||
ifeq ($(DEBUG), 1)
|
||||
OPTIMIZE_LV := -O0 -g
|
||||
else
|
||||
OPTIMIZE_LV := -O2
|
||||
OPTIMIZE_LV := -O3
|
||||
endif
|
||||
|
||||
INCDIR = $(PSPPATH)/include libretro-common/include
|
||||
CFLAGS = $(OPTIMIZE_LV) -G0 -std=gnu99 -ffast-math
|
||||
CFLAGS = $(OPTIMIZE_LV) -ffast-math -fsingle-precision-constant
|
||||
ASFLAGS = $(CFLAGS)
|
||||
|
||||
RARCH_DEFINES = -DPSP -DIS_SALAMANDER -DRARCH_CONSOLE
|
||||
|
||||
LIBDIR =
|
||||
LDFLAGS =
|
||||
LIBS = -lstdc++ -lm -lpsppower
|
||||
LIBS = -lstdc++ -lpsppower
|
||||
|
||||
CFLAGS += $(RARCH_DEFINES)
|
||||
|
||||
@@ -45,8 +46,12 @@ OBJS = frontend/frontend_salamander.o \
|
||||
libretro-common/vfs/vfs_implementation.o \
|
||||
libretro-common/hash/lrc_hash.o \
|
||||
libretro-common/time/rtime.o \
|
||||
verbosity.o \
|
||||
bootstrap/psp1/kernel_functions.o
|
||||
verbosity.o
|
||||
|
||||
ifeq ($(HAVE_KERNEL_PRX), 1)
|
||||
OBJS += bootstrap/psp1/kernel_functions.o
|
||||
CFLAGS += -DHAVE_KERNEL_PRX
|
||||
endif
|
||||
|
||||
PSPSDK=$(shell psp-config --pspsdk-path)
|
||||
include $(PSPSDK)/lib/build.mak
|
||||
+2
-4
@@ -111,10 +111,7 @@ HAVE_CHEATS = 1
|
||||
HAVE_CHEEVOS = 0
|
||||
HAVE_LIBSHAKE = 0
|
||||
HAVE_CORE_INFO_CACHE = 1
|
||||
|
||||
#comment out for now not working
|
||||
#HAVE_OSS =1
|
||||
#HAVE_OSS_LIB =1
|
||||
HAVE_OSS =1
|
||||
|
||||
OS = Linux
|
||||
TARGET = retroarch
|
||||
@@ -139,6 +136,7 @@ DEFINES := -DRARCH_INTERNAL -D_FILE_OFFSET_BITS=64 -UHAVE_STATIC_DUMMY
|
||||
DEFINES += -DHAVE_C99=1 -DHAVE_CXX=1
|
||||
DEFINES += -DHAVE_GETOPT_LONG=1 -DHAVE_STRCASESTR=1 -DHAVE_DYNAMIC=1
|
||||
DEFINES += -DHAVE_FILTERS_BUILTIN
|
||||
DEFINES += -DHAVE_OSS=1
|
||||
|
||||
SDL_DINGUX_CFLAGS := $(shell $(GCW0_SDL_CONFIG) --cflags)
|
||||
SDL_DINGUX_LIBS := $(shell $(GCW0_SDL_CONFIG) --libs)
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@ PACKAGE_VERSION := $(patsubst "%",%,$(RARCH_VERSION))
|
||||
|
||||
DEBUG ?= 0
|
||||
|
||||
HAVE_SCREENSHOTS = 0
|
||||
HAVE_SCREENSHOTS = 1
|
||||
HAVE_REWIND = 1
|
||||
HAVE_7ZIP = 1
|
||||
HAVE_ACCESSIBILITY = 1
|
||||
@@ -97,7 +97,7 @@ HAVE_SHADERPIPELINE = 1
|
||||
HAVE_STB_FONT = 1
|
||||
HAVE_STB_IMAGE = 1
|
||||
HAVE_STB_VORBIS = 1
|
||||
HAVE_STDIN_CMD = 0
|
||||
HAVE_STDIN_CMD = 1
|
||||
HAVE_STRCASESTR = 1
|
||||
HAVE_THREADS = 1
|
||||
HAVE_UDEV = 0
|
||||
|
||||
+33
-127
@@ -6,6 +6,7 @@ HAVE_FILE_LOGGER = 0
|
||||
HAVE_CC_RESAMPLER = 1
|
||||
WHOLE_ARCHIVE_LINK = 0
|
||||
BIG_STACK = 1
|
||||
HAVE_NETWORKING = 1
|
||||
PC_DEVELOPMENT_IP_ADDRESS = 255.255.255.255
|
||||
PC_DEVELOPMENT_UDP_PORT = 3490
|
||||
RARCH_CONSOLE = 0
|
||||
@@ -63,16 +64,18 @@ ifeq ("$(wildcard $(ELF2DOL))","")
|
||||
ELF2DOL = $(DEVKITPRO)/tools/bin/elf2dol$(EXE_EXT)
|
||||
endif
|
||||
|
||||
INCLUDE += -I. -I$(DEVKITPRO)/libogc/include -Iwii/libogc/include
|
||||
INCLUDE += -I.
|
||||
|
||||
ifeq ($(EXTERNAL_LIBOGC), 1)
|
||||
CFLAGS += -DEXTERNAL_LIBOGC
|
||||
CXXFLAGS += -DEXTERNAL_LIBOGC
|
||||
LIBDIRS += -L$(DEVKITPRO)/libogc/lib/wii
|
||||
INCLUDE += -I$(DEVKITPRO)/libogc/include
|
||||
else
|
||||
CFLAGS += -DINTERNAL_LIBOGC
|
||||
CXXFLAGS += -DINTERNAL_LIBOGC
|
||||
LIBDIRS += -Lwii/libogc/libs/wii
|
||||
INCLUDE += -Iwii/libogc/include
|
||||
endif
|
||||
|
||||
ifeq ($(GX_PTHREAD_LEGACY), 1)
|
||||
@@ -100,6 +103,10 @@ LIBS += -lwiiuse -lbte
|
||||
ifeq ($(USBGECKO), 1)
|
||||
LIBS += -ldb
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_LOGGER), 1)
|
||||
LIBS += -lbba
|
||||
endif
|
||||
|
||||
LIBS += -logc
|
||||
|
||||
@@ -127,12 +134,25 @@ HAVE_REWIND := 1
|
||||
HAVE_AUDIOMIXER := 1
|
||||
HAVE_RWAV := 1
|
||||
RARCH_CONSOLE = 1
|
||||
HAVE_CHEATS := 1
|
||||
HAVE_CORE_INFO_CACHE := 1
|
||||
HAVE_MENU_COMMON := 1
|
||||
HAVE_MENU := 1
|
||||
HAVE_BUILTINZLIB := 1
|
||||
HAVE_STATIC_AUDIO_FILTERS := 1
|
||||
HAVE_STATIC_VIDEO_FILTERS := 1
|
||||
|
||||
#HAVE_LANGEXTRA := 1
|
||||
HAVE_WIIUSB_HID := 1
|
||||
HAVE_HID := 1
|
||||
HAVE_RARCH_EXEC := 1
|
||||
HAVE_CORE_INFO_CACHE := 1
|
||||
HAVE_RSOUND := 0
|
||||
HAVE_XMB := 0
|
||||
HAVE_OZONE := 0
|
||||
HAVE_RGUI := 1
|
||||
HAVE_MATERIALUI := 0
|
||||
|
||||
CFLAGS += -DHAVE_SOCKET_LEGACY
|
||||
|
||||
APP_BOOTER_DIR = wii/app_booter
|
||||
PLATOBJS := $(APP_BOOTER_DIR)/app_booter.binobj
|
||||
@@ -141,19 +161,23 @@ ifeq ($(USBGECKO), 1)
|
||||
CFLAGS += -DUSBGECKO
|
||||
endif
|
||||
|
||||
HAVE_CHEATS := 1
|
||||
|
||||
CFLAGS += -Wall -std=gnu99 $(MACHDEP) $(PLATCFLAGS) $(INCLUDE)
|
||||
INCLUDE += -I./libretro-common/include \
|
||||
-Ideps \
|
||||
-Ideps/stb
|
||||
CFLAGS += -Wall -std=gnu99 $(MACHDEP) $(PLATCFLAGS) $(INCLUDE)
|
||||
|
||||
OBJ = griffin/griffin.o $(PLATOBJS)
|
||||
OBJ = $(PLATOBJS) audio/drivers/gx_audio.o gfx/drivers/gx_gfx.o input/drivers/gx_input.o frontend/drivers/platform_gx.o input/drivers_joypad/gx_joypad.o memory/wii/mem2_manager.o gfx/drivers/gx_gfx_vi_encoder.o frontend/drivers/platform_wii.o input/drivers_hid/wiiusb_hid.o
|
||||
|
||||
ifeq ($(HAVE_GRIFFIN_CPP), 1)
|
||||
OBJ += griffin/griffin_cpp.o
|
||||
ifeq ($(EXTERNAL_LIBOGC), 0)
|
||||
OBJ += wii/libogc/libfat/libfat.o wii/libogc/libfat/fatfile.o wii/libogc/libfat/file_allocation_table.o wii/libogc/libfat/cache.o wii/libogc/libfat/fatdir.o wii/libogc/libfat/partition.o wii/libogc/libfat/directory.o wii/libogc/libfat/filetime.o wii/libogc/libfat/disc.o
|
||||
endif
|
||||
|
||||
include Makefile.common
|
||||
|
||||
CFLAGS += $(DEFINES) -DPC_DEVELOPMENT_IP_ADDRESS=\"$(PC_DEVELOPMENT_IP_ADDRESS)\" \
|
||||
-DPC_DEVELOPMENT_UDP_PORT=$(PC_DEVELOPMENT_UDP_PORT) \
|
||||
|
||||
|
||||
ifeq ($(WANT_GLSLANG), 1)
|
||||
OBJ += griffin/griffin_glslang.o
|
||||
endif
|
||||
@@ -163,28 +187,18 @@ ifeq ($(HAVE_LOGGER), 1)
|
||||
CFLAGS += -DPC_DEVELOPMENT_IP_ADDRESS=\"$(PC_DEVELOPMENT_IP_ADDRESS)\" -DPC_DEVELOPMENT_UDP_PORT=$(PC_DEVELOPMENT_UDP_PORT)
|
||||
endif
|
||||
|
||||
CFLAGS += -DHAVE_SOCKET_LEGACY
|
||||
|
||||
ifeq ($(HAVE_KERNEL_PRX), 1)
|
||||
CFLAGS += -DHAVE_KERNEL_PRX
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_WIIUSB_HID), 1)
|
||||
CFLAGS += -DHAVE_WIIUSB_HID -DHAVE_HID
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_LIBRETRODB), 1)
|
||||
CFLAGS += -DHAVE_LIBRETRODB
|
||||
CFLAGS += -DHAVE_WIIUSB_HID
|
||||
endif
|
||||
|
||||
ifeq ($(BIG_STACK),1)
|
||||
CFLAGS += -DBIG_STACK
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_RJPEG), 1)
|
||||
CFLAGS += -DHAVE_RJPEG
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_FILE_LOGGER), 1)
|
||||
CFLAGS += -DHAVE_FILE_LOGGER
|
||||
endif
|
||||
@@ -198,66 +212,10 @@ ifeq ($(HAVE_ZLIB), 1)
|
||||
CFLAGS += -I./libretro-common/include/compat/zlib
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_RPNG), 1)
|
||||
CFLAGS += -DHAVE_RPNG
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_RBMP), 1)
|
||||
CFLAGS += -DHAVE_RBMP
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_RTGA), 1)
|
||||
CFLAGS += -DHAVE_RTGA
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_IMAGEVIEWER), 1)
|
||||
CFLAGS += -DHAVE_IMAGEVIEWER
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_BSV_MOVIE), 1)
|
||||
CFLAGS += -DHAVE_BSV_MOVIE
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_RUNAHEAD), 1)
|
||||
CFLAGS += -DHAVE_RUNAHEAD
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_7ZIP), 1)
|
||||
CFLAGS += -DHAVE_7ZIP -D_7ZIP_ST
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_SCREENSHOTS), 1)
|
||||
CFLAGS += -DHAVE_SCREENSHOTS
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_REWIND), 1)
|
||||
CFLAGS += -DHAVE_REWIND
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_AUDIOMIXER), 1)
|
||||
CFLAGS += -DHAVE_AUDIOMIXER
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_RWAV), 1)
|
||||
CFLAGS += -DHAVE_RWAV
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_OVERLAY), 1)
|
||||
CFLAGS += -DHAVE_OVERLAY
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_VIDEO_LAYOUT), 1)
|
||||
CFLAGS += -DHAVE_VIDEO_LAYOUT
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_NETWORKING), 1)
|
||||
CFLAGS += -DHAVE_NETWORKING
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_NETPLAYDISCOVERY), 1)
|
||||
CFLAGS += -DHAVE_NETPLAYDISCOVERY
|
||||
endif
|
||||
|
||||
ifeq ($(RARCH_CONSOLE), 1)
|
||||
CFLAGS += -DRARCH_CONSOLE
|
||||
endif
|
||||
@@ -268,50 +226,10 @@ endif
|
||||
|
||||
CFLAGS += -std=gnu99 -DHAVE_RGUI -DHAVE_MENU -DHAVE_GRIFFIN=1 -Wno-char-subscripts -DRARCH_INTERNAL
|
||||
|
||||
ifeq ($(HAVE_MATERIALUI), 1)
|
||||
CFLAGS += -DHAVE_MATERIALUI
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_XMB), 1)
|
||||
CFLAGS += -DHAVE_XMB
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_STB_FONT), 1)
|
||||
CFLAGS += -DHAVE_STB_FONT
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_LANGEXTRA), 1)
|
||||
CFLAGS += -DHAVE_LANGEXTRA
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_DSP_FILTER), 1)
|
||||
CFLAGS += -DHAVE_DSP_FILTER
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_VIDEO_FILTER), 1)
|
||||
CFLAGS += -DHAVE_VIDEO_FILTER
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_FILTERS_BUILTIN), 1)
|
||||
CFLAGS += -DHAVE_FILTERS_BUILTIN
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_THREADS), 1)
|
||||
CFLAGS += -DHAVE_THREADS
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_CONFIGFILE), 1)
|
||||
CFLAGS += -DHAVE_CONFIGFILE
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_PATCH), 1)
|
||||
CFLAGS += -DHAVE_PATCH
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_CHEATS), 1)
|
||||
CFLAGS += -DHAVE_CHEATS
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_RSOUND), 1)
|
||||
CFLAGS += -DHAVE_RSOUND
|
||||
endif
|
||||
@@ -320,22 +238,10 @@ ifeq ($(HAVE_GETOPT_LONG), 1)
|
||||
CFLAGS += -DHAVE_GETOPT_LONG=1
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_DYLIB), 1)
|
||||
CFLAGS += -DHAVE_DYLIB
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_NETWORK_CMD), 1)
|
||||
CFLAGS += -DHAVE_NETWORK_CMD
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_COMMAND), 1)
|
||||
CFLAGS += -DHAVE_COMMAND
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_STDIN_CMD), 1)
|
||||
CFLAGS += -DHAVE_STDIN_CMD
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_DYNAMIC), 1)
|
||||
CFLAGS += -DHAVE_DYNAMIC
|
||||
endif
|
||||
|
||||
@@ -25,7 +25,6 @@ HAVE_MATERIALUI = 1
|
||||
HAVE_DSP_FILTER = 1
|
||||
HAVE_VIDEO_FILTER = 1
|
||||
HAVE_7ZIP = 1
|
||||
HAVE_PYTHON = 0
|
||||
DYNAMIC = 1
|
||||
HAVE_CORE_INFO_CACHE = 1
|
||||
|
||||
@@ -35,7 +34,6 @@ HAVE_WINMM = 1
|
||||
HAVE_SDL := 0
|
||||
HAVE_SDL2 := 0
|
||||
HAVE_RSOUND := 0
|
||||
HAVE_PYTHON := 0
|
||||
|
||||
HAVE_STB_FONT := 1
|
||||
HAVE_FREETYPE := 1
|
||||
@@ -84,11 +82,6 @@ RSOUND_CFLAGS := -DHAVE_RSOUND
|
||||
RSOUND_LIBS := -lrsound
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_PYTHON), 1)
|
||||
PYTHON_LIBS := -lpython32
|
||||
PYTHON_CFLAGS := -DHAVE_PYTHON -Ipython
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_FFMPEG), 1)
|
||||
AVCODEC_LIBS := -lavcodec
|
||||
AVUTIL_LIBS := -lavutil
|
||||
|
||||
@@ -76,11 +76,11 @@ In the end you should have this on your system:
|
||||
gl3.h
|
||||
gl3platform.h
|
||||
|
||||
To enable mali_fbdev you must configure RetroArch with --enable-gles and --enable-mali_fbdev.
|
||||
To enable mali_fbdev you must configure RetroArch with --enable-opengles and --enable-mali_fbdev.
|
||||
|
||||
This is an example of what you would use on a CubieBoard2 for a lightweight RetroArch:
|
||||
|
||||
./configure --enable-gles --enable-mali_fbdev --disable-x11 --disable-sdl2 --enable-floathard --disable-ffmpeg --disable-netplay --enable-udev --disable-sdl --disable-pulse --disable-oss --disable-freetype --disable-7zip
|
||||
./configure --enable-opengles --enable-mali_fbdev --disable-x11 --disable-sdl2 --enable-floathard --disable-ffmpeg --disable-netplay --enable-udev --disable-sdl --disable-pulse --disable-oss --disable-freetype --disable-7zip
|
||||
|
||||
NOTE: A TTY hack is used to auto-clean the console on exit, and the fbdev ioctls are used to retrieve
|
||||
current video mode. Both things work good, but they are not exactly ideal solutions.
|
||||
|
||||
+69
-28
@@ -45,12 +45,17 @@
|
||||
#include "../menu/menu_driver.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETWORKING
|
||||
#include "../network/netplay/netplay.h"
|
||||
#endif
|
||||
|
||||
#include "../configuration.h"
|
||||
#include "../driver.h"
|
||||
#include "../frontend/frontend_driver.h"
|
||||
#include "../retroarch.h"
|
||||
#include "../list_special.h"
|
||||
#include "../file_path_special.h"
|
||||
#include "../record/record_driver.h"
|
||||
#include "../tasks/task_content.h"
|
||||
#include "../verbosity.h"
|
||||
|
||||
@@ -176,6 +181,18 @@ audio_driver_state_t *audio_state_get_ptr(void)
|
||||
return &audio_driver_st;
|
||||
}
|
||||
|
||||
/**
|
||||
* config_get_audio_driver_options:
|
||||
*
|
||||
* Get an enumerated list of all audio driver names, separated by '|'.
|
||||
*
|
||||
* Returns: string listing of all audio driver names, separated by '|'.
|
||||
**/
|
||||
const char *config_get_audio_driver_options(void)
|
||||
{
|
||||
return char_list_new_special(STRING_LIST_AUDIO_DRIVERS, NULL);
|
||||
}
|
||||
|
||||
#ifdef HAVE_TRANSLATE
|
||||
/* TODO/FIXME - Doesn't currently work. Fix this. */
|
||||
bool audio_driver_is_ai_service_speech_running(void)
|
||||
@@ -805,38 +822,53 @@ void audio_driver_sample(int16_t left, int16_t right)
|
||||
|
||||
size_t audio_driver_sample_batch(const int16_t *data, size_t frames)
|
||||
{
|
||||
recording_state_t *record_st = recording_state_get_ptr();
|
||||
runloop_state_t *runloop_st = runloop_state_get_ptr();
|
||||
audio_driver_state_t *audio_st = &audio_driver_st;
|
||||
size_t frames_remaining = frames;
|
||||
recording_state_t *record_st = recording_state_get_ptr();
|
||||
runloop_state_t *runloop_st = runloop_state_get_ptr();
|
||||
audio_driver_state_t *audio_st = &audio_driver_st;
|
||||
|
||||
if (frames > (AUDIO_CHUNK_SIZE_NONBLOCKING >> 1))
|
||||
frames = AUDIO_CHUNK_SIZE_NONBLOCKING >> 1;
|
||||
if (audio_st->suspended)
|
||||
if (audio_st->suspended || (frames < 1))
|
||||
return frames;
|
||||
|
||||
if ( record_st->data
|
||||
&& record_st->driver
|
||||
&& record_st->driver->push_audio)
|
||||
/* We want to run this loop at least once, so use a
|
||||
* do...while (do...while has only a single conditional
|
||||
* jump, as opposed to for and while which have a
|
||||
* conditional jump and an unconditional jump). Note,
|
||||
* however, that this is only relevant for compilers
|
||||
* that are poor at optimisation... */
|
||||
do
|
||||
{
|
||||
struct record_audio_data ffemu_data;
|
||||
size_t frames_to_write =
|
||||
(frames_remaining > (AUDIO_CHUNK_SIZE_NONBLOCKING >> 1)) ?
|
||||
(AUDIO_CHUNK_SIZE_NONBLOCKING >> 1) : frames_remaining;
|
||||
|
||||
ffemu_data.data = data;
|
||||
ffemu_data.frames = (frames << 1) / 2;
|
||||
if ( record_st->data
|
||||
&& record_st->driver
|
||||
&& record_st->driver->push_audio)
|
||||
{
|
||||
struct record_audio_data ffemu_data;
|
||||
|
||||
record_st->driver->push_audio(record_st->data, &ffemu_data);
|
||||
ffemu_data.data = data;
|
||||
ffemu_data.frames = frames_to_write;
|
||||
|
||||
record_st->driver->push_audio(record_st->data, &ffemu_data);
|
||||
}
|
||||
|
||||
if (!( runloop_st->paused
|
||||
|| !audio_st->active
|
||||
|| !audio_st->output_samples_buf))
|
||||
audio_driver_flush(audio_st,
|
||||
config_get_ptr()->floats.slowmotion_ratio,
|
||||
config_get_ptr()->bools.audio_fastforward_mute,
|
||||
data,
|
||||
frames_to_write << 1,
|
||||
runloop_st->slowmotion,
|
||||
runloop_st->fastmotion);
|
||||
|
||||
frames_remaining -= frames_to_write;
|
||||
data += frames_to_write << 1;
|
||||
}
|
||||
|
||||
if (!(
|
||||
runloop_st->paused
|
||||
|| !audio_st->active
|
||||
|| !audio_st->output_samples_buf))
|
||||
audio_driver_flush(audio_st,
|
||||
config_get_ptr()->floats.slowmotion_ratio,
|
||||
config_get_ptr()->bools.audio_fastforward_mute,
|
||||
data,
|
||||
frames << 1,
|
||||
runloop_st->slowmotion,
|
||||
runloop_st->fastmotion);
|
||||
while (frames_remaining > 0);
|
||||
|
||||
return frames;
|
||||
}
|
||||
@@ -861,8 +893,10 @@ size_t audio_driver_sample_batch_rewind(
|
||||
|
||||
for (i = 0; i < samples; i++)
|
||||
{
|
||||
if (audio_st->rewind_ptr > 0)
|
||||
audio_st->rewind_buf[--audio_st->rewind_ptr] = data[i];
|
||||
if (audio_st->rewind_ptr < 1)
|
||||
break;
|
||||
|
||||
audio_st->rewind_buf[--audio_st->rewind_ptr] = data[i];
|
||||
}
|
||||
|
||||
return frames;
|
||||
@@ -1574,7 +1608,14 @@ bool audio_driver_callback(void)
|
||||
settings_t *settings = config_get_ptr();
|
||||
bool runloop_paused = runloop_state_get_ptr()->paused;
|
||||
#ifdef HAVE_MENU
|
||||
bool core_paused = runloop_paused || (settings->bools.menu_pause_libretro && menu_state_get_ptr()->alive);
|
||||
#ifdef HAVE_NETWORKING
|
||||
bool core_paused = runloop_paused ||
|
||||
(settings->bools.menu_pause_libretro && menu_state_get_ptr()->alive &&
|
||||
netplay_driver_ctl(RARCH_NETPLAY_CTL_ALLOW_PAUSE, NULL));
|
||||
#else
|
||||
bool core_paused = runloop_paused ||
|
||||
(settings->bools.menu_pause_libretro && menu_state_get_ptr()->alive);
|
||||
#endif
|
||||
#else
|
||||
bool core_paused = runloop_paused;
|
||||
#endif
|
||||
|
||||
@@ -374,8 +374,7 @@ void audio_driver_sample(int16_t left, int16_t right);
|
||||
*
|
||||
* Batched audio sample render callback function.
|
||||
*
|
||||
* Returns: amount of frames sampled. Will be equal to @frames
|
||||
* unless @frames exceeds (AUDIO_CHUNK_SIZE_NONBLOCKING / 2).
|
||||
* Returns: amount of frames sampled.
|
||||
**/
|
||||
size_t audio_driver_sample_batch(const int16_t *data, size_t frames);
|
||||
|
||||
@@ -401,8 +400,7 @@ void audio_driver_sample_rewind(int16_t left, int16_t right);
|
||||
* This callback function will be used instead of
|
||||
* audio_driver_sample_batch when rewinding is activated.
|
||||
*
|
||||
* Returns: amount of frames sampled. Will be equal to @frames
|
||||
* unless @frames exceeds (AUDIO_CHUNK_SIZE_NONBLOCKING / 2).
|
||||
* Returns: amount of frames sampled.
|
||||
**/
|
||||
size_t audio_driver_sample_batch_rewind(
|
||||
const int16_t *data, size_t frames);
|
||||
|
||||
@@ -33,12 +33,13 @@
|
||||
|
||||
#include "../audio_driver.h"
|
||||
#include "../../verbosity.h"
|
||||
#include "defines/cocoa_defines.h"
|
||||
|
||||
typedef struct coreaudio
|
||||
{
|
||||
slock_t *lock;
|
||||
scond_t *cond;
|
||||
#if (defined(__MACH__) && (defined(__ppc__) || defined(__ppc64__)))
|
||||
#if !HAS_MACOSX_10_12
|
||||
ComponentInstance dev;
|
||||
#else
|
||||
AudioComponentInstance dev;
|
||||
@@ -64,7 +65,7 @@ static void coreaudio_free(void *data)
|
||||
if (dev->dev_alive)
|
||||
{
|
||||
AudioOutputUnitStop(dev->dev);
|
||||
#if (defined(__MACH__) && (defined(__ppc__) || defined(__ppc64__)))
|
||||
#if !HAS_MACOSX_10_12
|
||||
CloseComponent(dev->dev);
|
||||
#else
|
||||
AudioComponentInstanceDispose(dev->dev);
|
||||
@@ -139,7 +140,7 @@ static void choose_output_device(coreaudio_t *dev, const char* device)
|
||||
UInt32 size = 0;
|
||||
|
||||
propaddr.mSelector = kAudioHardwarePropertyDevices;
|
||||
#if MAC_OS_X_VERSION_10_12
|
||||
#if HAS_MACOSX_10_12
|
||||
propaddr.mScope = kAudioObjectPropertyScopeOutput;
|
||||
#else
|
||||
propaddr.mScope = kAudioObjectPropertyScopeGlobal;
|
||||
@@ -157,7 +158,7 @@ static void choose_output_device(coreaudio_t *dev, const char* device)
|
||||
&propaddr, 0, 0, &size, devices) != noErr)
|
||||
goto done;
|
||||
|
||||
#if MAC_OS_X_VERSION_10_12
|
||||
#if HAS_MACOSX_10_12
|
||||
#else
|
||||
propaddr.mScope = kAudioDevicePropertyScopeOutput;
|
||||
#endif
|
||||
@@ -192,7 +193,7 @@ static void *coreaudio_init(const char *device,
|
||||
size_t fifo_size;
|
||||
UInt32 i_size;
|
||||
AudioStreamBasicDescription real_desc;
|
||||
#if (defined(__MACH__) && (defined(__ppc__) || defined(__ppc64__)))
|
||||
#if !HAS_MACOSX_10_12
|
||||
Component comp;
|
||||
#else
|
||||
AudioComponent comp;
|
||||
@@ -204,7 +205,7 @@ static void *coreaudio_init(const char *device,
|
||||
AudioStreamBasicDescription stream_desc = {0};
|
||||
bool component_unavailable = false;
|
||||
static bool session_initialized = false;
|
||||
#if (defined(__MACH__) && (defined(__ppc__) || defined(__ppc64__)))
|
||||
#if !HAS_MACOSX_10_12
|
||||
ComponentDescription desc = {0};
|
||||
#else
|
||||
AudioComponentDescription desc = {0};
|
||||
@@ -238,7 +239,7 @@ static void *coreaudio_init(const char *device,
|
||||
#endif
|
||||
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
|
||||
#if (defined(__MACH__) && (defined(__ppc__) || defined(__ppc64__)))
|
||||
#if !HAS_MACOSX_10_12
|
||||
comp = FindNextComponent(NULL, &desc);
|
||||
#else
|
||||
comp = AudioComponentFindNext(NULL, &desc);
|
||||
@@ -246,7 +247,7 @@ static void *coreaudio_init(const char *device,
|
||||
if (!comp)
|
||||
goto error;
|
||||
|
||||
#if (defined(__MACH__) && (defined(__ppc__) || defined(__ppc64__)))
|
||||
#if !HAS_MACOSX_10_12
|
||||
component_unavailable = (OpenAComponent(comp, &dev->dev) != noErr);
|
||||
#else
|
||||
component_unavailable = (AudioComponentInstanceNew(comp, &dev->dev) != noErr);
|
||||
|
||||
+14
-9
@@ -136,8 +136,8 @@ static void dsound_thread(void *data)
|
||||
static DWORD CALLBACK dsound_thread(PVOID data)
|
||||
#endif
|
||||
{
|
||||
DWORD write_ptr;
|
||||
dsound_t *ds = (dsound_t*)data;
|
||||
DWORD write_ptr = 0;
|
||||
dsound_t *ds = (dsound_t*)data;
|
||||
|
||||
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
|
||||
|
||||
@@ -315,15 +315,20 @@ static BOOL CALLBACK enumerate_cb(LPGUID guid,
|
||||
|
||||
if (guid)
|
||||
{
|
||||
unsigned i;
|
||||
LPGUID guid_copy = (LPGUID)malloc(sizeof(GUID) * 1);
|
||||
guid_copy->Data1 = guid->Data1;
|
||||
guid_copy->Data2 = guid->Data2;
|
||||
guid_copy->Data3 = guid->Data3;
|
||||
for (i = 0; i < 8; i++)
|
||||
guid_copy->Data4[i] = guid->Data4[i];
|
||||
|
||||
list->elems[list->size-1].userdata = guid_copy;
|
||||
if (guid_copy)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
guid_copy->Data1 = guid->Data1;
|
||||
guid_copy->Data2 = guid->Data2;
|
||||
guid_copy->Data3 = guid->Data3;
|
||||
for (i = 0; i < 8; i++)
|
||||
guid_copy->Data4[i] = guid->Data4[i];
|
||||
|
||||
list->elems[list->size - 1].userdata = guid_copy;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
@@ -126,8 +126,10 @@ static bool oss_stop(void *data)
|
||||
{
|
||||
oss_audio_t *ossaudio = (oss_audio_t*)data;
|
||||
|
||||
#if !defined(RETROFW)
|
||||
if (ioctl(ossaudio->fd, SNDCTL_DSP_RESET, 0) < 0)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
ossaudio->is_paused = true;
|
||||
return true;
|
||||
@@ -167,8 +169,11 @@ static void oss_free(void *data)
|
||||
{
|
||||
oss_audio_t *ossaudio = (oss_audio_t*)data;
|
||||
|
||||
/*RETROFW IOCTL always returns EINVAL*/
|
||||
#if !defined(RETROFW)
|
||||
if (ioctl(ossaudio->fd, SNDCTL_DSP_RESET, 0) < 0)
|
||||
return;
|
||||
#endif
|
||||
|
||||
close(ossaudio->fd);
|
||||
free(data);
|
||||
|
||||
+33
-25
@@ -54,7 +54,7 @@ typedef struct psp_audio
|
||||
|
||||
SceUID thread;
|
||||
|
||||
int rate;
|
||||
int port;
|
||||
|
||||
volatile uint16_t read_pos;
|
||||
volatile uint16_t write_pos;
|
||||
@@ -67,22 +67,27 @@ typedef struct psp_audio
|
||||
#define AUDIO_BUFFER_SIZE (1u<<13u)
|
||||
#define AUDIO_BUFFER_SIZE_MASK (AUDIO_BUFFER_SIZE-1)
|
||||
|
||||
/* Return port used */
|
||||
static int configureAudio(unsigned rate) {
|
||||
int port;
|
||||
#if defined(VITA)
|
||||
port = sceAudioOutOpenPort(
|
||||
SCE_AUDIO_OUT_PORT_TYPE_MAIN, AUDIO_OUT_COUNT,
|
||||
rate, SCE_AUDIO_OUT_MODE_STEREO);
|
||||
#elif defined(ORBIS)
|
||||
port = sceAudioOutOpen(0xff,
|
||||
SCE_AUDIO_OUT_PORT_TYPE_MAIN, 0, AUDIO_OUT_COUNT,
|
||||
rate, SCE_AUDIO_OUT_MODE_STEREO);
|
||||
#else
|
||||
port = sceAudioSRCChReserve(AUDIO_OUT_COUNT, rate, 2);
|
||||
#endif
|
||||
return port;
|
||||
}
|
||||
|
||||
static void audioMainLoop(void *data)
|
||||
{
|
||||
psp_audio_t* psp = (psp_audio_t*)data;
|
||||
|
||||
#if defined(VITA)
|
||||
int port = sceAudioOutOpenPort(
|
||||
SCE_AUDIO_OUT_PORT_TYPE_MAIN, AUDIO_OUT_COUNT,
|
||||
psp->rate, SCE_AUDIO_OUT_MODE_STEREO);
|
||||
#elif defined(ORBIS)
|
||||
int port = sceAudioOutOpen(0xff,
|
||||
SCE_AUDIO_OUT_PORT_TYPE_MAIN, 0, AUDIO_OUT_COUNT,
|
||||
psp->rate, SCE_AUDIO_OUT_MODE_STEREO);
|
||||
#else
|
||||
sceAudioSRCChReserve(AUDIO_OUT_COUNT, psp->rate, 2);
|
||||
#endif
|
||||
|
||||
while (psp->running)
|
||||
{
|
||||
bool cond = false;
|
||||
@@ -107,7 +112,7 @@ static void audioMainLoop(void *data)
|
||||
slock_unlock(psp->cond_lock);
|
||||
|
||||
#if defined(VITA) || defined(ORBIS)
|
||||
sceAudioOutOutput(port,
|
||||
sceAudioOutOutput(psp->port,
|
||||
cond ? (psp->zeroBuffer)
|
||||
: (psp->buffer + read_pos_2));
|
||||
#else
|
||||
@@ -116,14 +121,6 @@ static void audioMainLoop(void *data)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(VITA)
|
||||
sceAudioOutReleasePort(port);
|
||||
#elif defined(ORBIS)
|
||||
sceAudioOutClose(port);
|
||||
#else
|
||||
sceAudioSRCChRelease();
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -137,8 +134,9 @@ static void *psp_audio_init(const char *device,
|
||||
if (!psp)
|
||||
return NULL;
|
||||
|
||||
(void)device;
|
||||
(void)latency;
|
||||
int port = configureAudio(rate);
|
||||
if (port < 0)
|
||||
return NULL;
|
||||
|
||||
#ifdef ORBIS
|
||||
psp->buffer = (uint32_t*)
|
||||
@@ -161,7 +159,7 @@ static void *psp_audio_init(const char *device,
|
||||
|
||||
psp->read_pos = 0;
|
||||
psp->write_pos = 0;
|
||||
psp->rate = rate;
|
||||
psp->port = port;
|
||||
|
||||
psp->fifo_lock = slock_new();
|
||||
psp->cond_lock = slock_new();
|
||||
@@ -197,7 +195,17 @@ static void psp_audio_free(void *data)
|
||||
free(psp->buffer);
|
||||
psp->worker_thread = NULL;
|
||||
free(psp->zeroBuffer);
|
||||
|
||||
#if defined(VITA)
|
||||
sceAudioOutReleasePort(psp->port);
|
||||
#elif defined(ORBIS)
|
||||
sceAudioOutClose(psp->port);
|
||||
#else
|
||||
sceAudioSRCChRelease();
|
||||
#endif
|
||||
|
||||
free(psp);
|
||||
|
||||
}
|
||||
|
||||
static ssize_t psp_audio_write(void *data, const void *buf, size_t size)
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2021 - Daniel De Matteis
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#include "../driver.h"
|
||||
#include "../list_special.h"
|
||||
#include "../retroarch.h"
|
||||
#include "../runloop.h"
|
||||
#include "../verbosity.h"
|
||||
|
||||
#include "bluetooth_driver.h"
|
||||
|
||||
static bluetooth_driver_t bluetooth_null = {
|
||||
NULL, /* init */
|
||||
NULL, /* free */
|
||||
NULL, /* scan */
|
||||
NULL, /* get_devices */
|
||||
NULL, /* device_is_connected */
|
||||
NULL, /* device_get_sublabel */
|
||||
NULL, /* connect_device */
|
||||
NULL, /* remove_device */
|
||||
"null",
|
||||
};
|
||||
|
||||
const bluetooth_driver_t *bluetooth_drivers[] = {
|
||||
#ifdef HAVE_BLUETOOTH
|
||||
&bluetooth_bluetoothctl,
|
||||
#ifdef HAVE_DBUS
|
||||
&bluetooth_bluez,
|
||||
#endif
|
||||
#endif
|
||||
&bluetooth_null,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static bluetooth_driver_state_t bluetooth_driver_st = {0};
|
||||
|
||||
bluetooth_driver_state_t *bluetooth_state_get_ptr(void)
|
||||
{
|
||||
return &bluetooth_driver_st;
|
||||
}
|
||||
|
||||
/**
|
||||
* config_get_bluetooth_driver_options:
|
||||
*
|
||||
* Get an enumerated list of all bluetooth driver names,
|
||||
* separated by '|'.
|
||||
*
|
||||
* Returns: string listing of all bluetooth driver names,
|
||||
* separated by '|'.
|
||||
**/
|
||||
const char* config_get_bluetooth_driver_options(void)
|
||||
{
|
||||
return char_list_new_special(STRING_LIST_BLUETOOTH_DRIVERS, NULL);
|
||||
}
|
||||
|
||||
void driver_bluetooth_scan(void)
|
||||
{
|
||||
bluetooth_driver_state_t *bt_st = &bluetooth_driver_st;
|
||||
if ( bt_st
|
||||
&& bt_st->active
|
||||
&& bt_st->drv->scan )
|
||||
bt_st->drv->scan(bt_st->data);
|
||||
}
|
||||
|
||||
void driver_bluetooth_get_devices(struct string_list* devices)
|
||||
{
|
||||
bluetooth_driver_state_t *bt_st = &bluetooth_driver_st;
|
||||
if ( bt_st
|
||||
&& bt_st->active
|
||||
&& bt_st->drv->get_devices )
|
||||
bt_st->drv->get_devices(bt_st->data, devices);
|
||||
}
|
||||
|
||||
bool driver_bluetooth_device_is_connected(unsigned i)
|
||||
{
|
||||
bluetooth_driver_state_t *bt_st = &bluetooth_driver_st;
|
||||
if ( bt_st
|
||||
&& bt_st->active
|
||||
&& bt_st->drv->device_is_connected )
|
||||
return bt_st->drv->device_is_connected(bt_st->data, i);
|
||||
return false;
|
||||
}
|
||||
|
||||
void driver_bluetooth_device_get_sublabel(char *s, unsigned i, size_t len)
|
||||
{
|
||||
bluetooth_driver_state_t *bt_st = &bluetooth_driver_st;
|
||||
if ( bt_st
|
||||
&& bt_st->active
|
||||
&& bt_st->drv->device_get_sublabel )
|
||||
bt_st->drv->device_get_sublabel(bt_st->data, s, i, len);
|
||||
}
|
||||
|
||||
bool driver_bluetooth_connect_device(unsigned i)
|
||||
{
|
||||
bluetooth_driver_state_t *bt_st = &bluetooth_driver_st;
|
||||
if (bt_st->active)
|
||||
return bt_st->drv->connect_device(bt_st->data, i);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool driver_bluetooth_remove_device(unsigned i)
|
||||
{
|
||||
bluetooth_driver_state_t *bt_st = &bluetooth_driver_st;
|
||||
if (bt_st->active)
|
||||
return bt_st->drv->remove_device(bt_st->data, i);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bluetooth_driver_ctl(enum rarch_bluetooth_ctl_state state, void *data)
|
||||
{
|
||||
bluetooth_driver_state_t *bt_st = &bluetooth_driver_st;
|
||||
settings_t *settings = config_get_ptr();
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case RARCH_BLUETOOTH_CTL_DESTROY:
|
||||
bt_st->drv = NULL;
|
||||
bt_st->data = NULL;
|
||||
bt_st->active = false;
|
||||
break;
|
||||
case RARCH_BLUETOOTH_CTL_FIND_DRIVER:
|
||||
{
|
||||
const char *prefix = "bluetooth driver";
|
||||
int i = (int)driver_find_index(
|
||||
"bluetooth_driver",
|
||||
settings->arrays.bluetooth_driver);
|
||||
|
||||
if (i >= 0)
|
||||
bt_st->drv = (const bluetooth_driver_t*)bluetooth_drivers[i];
|
||||
else
|
||||
{
|
||||
if (verbosity_is_enabled())
|
||||
{
|
||||
unsigned d;
|
||||
RARCH_ERR("Couldn't find any %s named \"%s\"\n", prefix,
|
||||
settings->arrays.bluetooth_driver);
|
||||
RARCH_LOG_OUTPUT("Available %ss are:\n", prefix);
|
||||
for (d = 0; bluetooth_drivers[d]; d++)
|
||||
RARCH_LOG_OUTPUT("\t%s\n", bluetooth_drivers[d]->ident);
|
||||
|
||||
RARCH_WARN("Going to default to first %s...\n", prefix);
|
||||
}
|
||||
|
||||
bt_st->drv = (const bluetooth_driver_t*)bluetooth_drivers[0];
|
||||
|
||||
if (!bt_st->drv)
|
||||
retroarch_fail(1, "find_bluetooth_driver()");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RARCH_BLUETOOTH_CTL_DEINIT:
|
||||
if (bt_st->data && bt_st->drv)
|
||||
{
|
||||
if (bt_st->drv->free)
|
||||
bt_st->drv->free(bt_st->data);
|
||||
}
|
||||
|
||||
bt_st->data = NULL;
|
||||
bt_st->active = false;
|
||||
break;
|
||||
case RARCH_BLUETOOTH_CTL_INIT:
|
||||
/* Resource leaks will follow if bluetooth is initialized twice. */
|
||||
if (bt_st->data)
|
||||
return false;
|
||||
|
||||
bluetooth_driver_ctl(RARCH_BLUETOOTH_CTL_FIND_DRIVER, NULL);
|
||||
|
||||
if (bt_st->drv && bt_st->drv->init)
|
||||
{
|
||||
bt_st->active = true;
|
||||
bt_st->data = bt_st->drv->init();
|
||||
|
||||
if (!bt_st->data)
|
||||
{
|
||||
RARCH_ERR("Failed to initialize bluetooth driver. Will continue without bluetooth.\n");
|
||||
bt_st->active = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
bt_st->active = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -43,6 +43,7 @@ typedef struct bluetooth_driver
|
||||
bool (*device_is_connected)(void *data, unsigned i);
|
||||
void (*device_get_sublabel)(void *data, char *s, unsigned i, size_t len);
|
||||
bool (*connect_device)(void *data, unsigned i);
|
||||
bool (*remove_device)(void *data, unsigned i);
|
||||
|
||||
const char *ident;
|
||||
} bluetooth_driver_t;
|
||||
@@ -50,6 +51,13 @@ typedef struct bluetooth_driver
|
||||
extern bluetooth_driver_t bluetooth_bluetoothctl;
|
||||
extern bluetooth_driver_t bluetooth_bluez;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const bluetooth_driver_t *drv;
|
||||
void *data;
|
||||
bool active;
|
||||
} bluetooth_driver_state_t;
|
||||
|
||||
/**
|
||||
* config_get_bluetooth_driver_options:
|
||||
*
|
||||
@@ -71,8 +79,14 @@ void driver_bluetooth_device_get_sublabel(char *s, unsigned i, size_t len);
|
||||
|
||||
bool driver_bluetooth_connect_device(unsigned i);
|
||||
|
||||
bool driver_bluetooth_remove_device(unsigned i);
|
||||
|
||||
bool bluetooth_driver_ctl(enum rarch_bluetooth_ctl_state state, void *data);
|
||||
|
||||
bluetooth_driver_state_t *bluetooth_state_get_ptr(void);
|
||||
|
||||
extern const bluetooth_driver_t *bluetooth_drivers[];
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
@@ -191,6 +191,45 @@ static bool bluetoothctl_connect_device(void *data, unsigned idx)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool bluetoothctl_remove_device(void *data, unsigned idx)
|
||||
{
|
||||
unsigned i;
|
||||
bluetoothctl_t *btctl = (bluetoothctl_t*) data;
|
||||
char device[18] = {0};
|
||||
const char *line = btctl->lines->elems[idx].data;
|
||||
static struct string_list* list = NULL;
|
||||
|
||||
/* bluetoothctl devices outputs lines of the format:
|
||||
* $ bluetoothctl devices
|
||||
* 'Device (mac address) (device name)'
|
||||
*/
|
||||
list = string_split(line, " ");
|
||||
if (!list)
|
||||
return false;
|
||||
|
||||
if (list->size == 0)
|
||||
{
|
||||
string_list_free(list);
|
||||
return false;
|
||||
}
|
||||
|
||||
strlcpy(device, list->elems[1].data, sizeof(device));
|
||||
string_list_free(list);
|
||||
|
||||
snprintf(btctl->command, sizeof(btctl->command), "\
|
||||
echo -e \"disconnect %s\\nremove %s\\n\" | bluetoothctl",
|
||||
device, device);
|
||||
|
||||
pclose(popen(btctl->command, "r"));
|
||||
|
||||
runloop_msg_queue_push(msg_hash_to_str(MSG_BLUETOOTH_PAIRING_REMOVED),
|
||||
1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT,
|
||||
MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
|
||||
btctl->bluetoothctl_counter[idx] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void bluetoothctl_device_get_sublabel(
|
||||
void *data, char *s, unsigned i, size_t len)
|
||||
{
|
||||
@@ -211,5 +250,6 @@ bluetooth_driver_t bluetooth_bluetoothctl = {
|
||||
bluetoothctl_device_is_connected,
|
||||
bluetoothctl_device_get_sublabel,
|
||||
bluetoothctl_connect_device,
|
||||
bluetoothctl_remove_device,
|
||||
"bluetoothctl",
|
||||
};
|
||||
@@ -604,6 +604,27 @@ static bool bluez_connect_device(void *data, unsigned i)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool bluez_remove_device(void *data, unsigned i)
|
||||
{
|
||||
bluez_t *bluez = (bluez_t*)data;
|
||||
bluez_dbus_connect(bluez);
|
||||
|
||||
/* Disconnect the device */
|
||||
device_method(bluez, bluez->devices->data[i].path, "Disconnect");
|
||||
|
||||
/* Remove the device */
|
||||
if (device_method(bluez, bluez->devices->data[i].path, "RemoveDevice"))
|
||||
return false;
|
||||
|
||||
runloop_msg_queue_push(msg_hash_to_str(MSG_BLUETOOTH_PAIRING_REMOVED),
|
||||
1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT,
|
||||
MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
|
||||
bluez_dbus_disconnect(bluez);
|
||||
bluez->bluez_cache_counter[i] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bluetooth_driver_t bluetooth_bluez = {
|
||||
bluez_init,
|
||||
bluez_free,
|
||||
@@ -612,5 +633,6 @@ bluetooth_driver_t bluetooth_bluez = {
|
||||
bluez_device_is_connected,
|
||||
bluez_device_get_sublabel,
|
||||
bluez_connect_device,
|
||||
bluez_remove_device,
|
||||
"bluez",
|
||||
};
|
||||
@@ -9,7 +9,6 @@ PSP_EXPORT_VAR_HASH(module_info)
|
||||
PSP_EXPORT_END
|
||||
|
||||
PSP_EXPORT_START(kernel_functions, 0, 0x4001)
|
||||
PSP_EXPORT_FUNC(read_system_buttons)
|
||||
PSP_EXPORT_FUNC(exitspawn_kernel)
|
||||
PSP_EXPORT_END
|
||||
|
||||
|
||||
@@ -1,49 +1,17 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <pspdebug.h>
|
||||
#include <pspsdk.h>
|
||||
#include <pspctrl.h>
|
||||
#include <psploadexec_kernel.h>
|
||||
#include <pspthreadman_kernel.h>
|
||||
|
||||
PSP_MODULE_INFO("kernel_functions", PSP_MODULE_KERNEL, 0, 0);
|
||||
PSP_MAIN_THREAD_ATTR(0);
|
||||
|
||||
static volatile int thread_active;
|
||||
static unsigned int buttons;
|
||||
static SceUID main_thread_id;
|
||||
|
||||
static int main_thread(SceSize args, void *argp)
|
||||
{
|
||||
SceCtrlData paddata;
|
||||
|
||||
thread_active = 1;
|
||||
|
||||
while (thread_active)
|
||||
{
|
||||
sceCtrlPeekBufferPositive(&paddata, 1);
|
||||
buttons = paddata.Buttons;
|
||||
sceKernelDelayThread(1000000/60);
|
||||
}
|
||||
|
||||
sceKernelExitThread(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int read_system_buttons(void)
|
||||
{
|
||||
return buttons;
|
||||
}
|
||||
|
||||
void exitspawn_kernel(const char *fileName, SceSize args, void *argp)
|
||||
{
|
||||
int k1;
|
||||
struct SceKernelLoadExecVSHParam game_param;
|
||||
|
||||
thread_active = 0;
|
||||
|
||||
memset(&game_param,0,sizeof(game_param));
|
||||
|
||||
game_param.size = sizeof(game_param);
|
||||
@@ -57,34 +25,16 @@ void exitspawn_kernel(const char *fileName, SceSize args, void *argp)
|
||||
game_param.unk5 = 0x10000;
|
||||
|
||||
k1 = pspSdkSetK1(0);
|
||||
#if 0
|
||||
sceKernelSuspendAllUserThreads();
|
||||
#endif
|
||||
sceKernelLoadExecVSHMs2(fileName, &game_param);
|
||||
pspSdkSetK1(k1);
|
||||
}
|
||||
|
||||
int module_start(SceSize args, void *argp)
|
||||
{
|
||||
(void)args;
|
||||
(void)argp;
|
||||
|
||||
buttons = 0;
|
||||
thread_active = 0;
|
||||
main_thread_id = sceKernelCreateThread("main Thread", main_thread, 0x11, 0x200, 0, NULL);
|
||||
|
||||
if (main_thread >= 0)
|
||||
sceKernelStartThread(main_thread_id, 0, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int module_stop(void)
|
||||
{
|
||||
if (main_thread_id >= 0)
|
||||
{
|
||||
thread_active = 0;
|
||||
sceKernelWaitThreadEnd(main_thread_id, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -43,7 +43,6 @@ void _init_vita_heap(void) {
|
||||
|
||||
if (_newlib_vm_memblock < 0){
|
||||
//sceClibPrintf("sceKernelAllocMemBlockForVM failed\n");
|
||||
goto failure;
|
||||
}
|
||||
}else{
|
||||
_newlib_vm_memblock = 0;
|
||||
@@ -99,8 +98,8 @@ void _free_vita_heap(void) {
|
||||
// Free the heap memblock to avoid memory leakage.
|
||||
sceKernelFreeMemBlock(_newlib_heap_memblock);
|
||||
|
||||
if(_newlib_vm_memblock)
|
||||
sceKernelFreeMemBlock(_newlib_vm_memblock);
|
||||
if (_newlib_vm_memblock > 0)
|
||||
sceKernelFreeMemBlock(_newlib_vm_memblock);
|
||||
|
||||
_newlib_vm_memblock = 0;
|
||||
_newlib_heap_memblock = 0;
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2021 - Daniel De Matteis
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <libretro.h>
|
||||
|
||||
#include "../configuration.h"
|
||||
#include "../driver.h"
|
||||
#include "../list_special.h"
|
||||
#include "../runloop.h"
|
||||
#include "../verbosity.h"
|
||||
|
||||
#include "camera_driver.h"
|
||||
|
||||
static void *nullcamera_init(const char *device, uint64_t caps,
|
||||
unsigned width, unsigned height) { return (void*)-1; }
|
||||
static void nullcamera_free(void *data) { }
|
||||
static void nullcamera_stop(void *data) { }
|
||||
static bool nullcamera_start(void *data) { return true; }
|
||||
static bool nullcamera_poll(void *a,
|
||||
retro_camera_frame_raw_framebuffer_t b,
|
||||
retro_camera_frame_opengl_texture_t c) { return true; }
|
||||
|
||||
static camera_driver_t camera_null = {
|
||||
nullcamera_init,
|
||||
nullcamera_free,
|
||||
nullcamera_start,
|
||||
nullcamera_stop,
|
||||
nullcamera_poll,
|
||||
"null",
|
||||
};
|
||||
|
||||
const camera_driver_t *camera_drivers[] = {
|
||||
#ifdef HAVE_V4L2
|
||||
&camera_v4l2,
|
||||
#endif
|
||||
#ifdef EMSCRIPTEN
|
||||
&camera_rwebcam,
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
&camera_android,
|
||||
#endif
|
||||
&camera_null,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static camera_driver_state_t camera_driver_st = {0};
|
||||
|
||||
camera_driver_state_t *camera_state_get_ptr(void)
|
||||
{
|
||||
return &camera_driver_st;
|
||||
}
|
||||
|
||||
/**
|
||||
* config_get_camera_driver_options:
|
||||
*
|
||||
* Get an enumerated list of all camera driver names,
|
||||
* separated by '|'.
|
||||
*
|
||||
* Returns: string listing of all camera driver names,
|
||||
* separated by '|'.
|
||||
**/
|
||||
const char *config_get_camera_driver_options(void)
|
||||
{
|
||||
return char_list_new_special(STRING_LIST_CAMERA_DRIVERS, NULL);
|
||||
}
|
||||
|
||||
bool driver_camera_start(void)
|
||||
{
|
||||
camera_driver_state_t *camera_st = &camera_driver_st;
|
||||
if ( camera_st
|
||||
&& camera_st->data
|
||||
&& camera_st->driver
|
||||
&& camera_st->driver->start)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
bool camera_allow = settings->bools.camera_allow;
|
||||
if (camera_allow)
|
||||
return camera_st->driver->start(camera_st->data);
|
||||
|
||||
runloop_msg_queue_push(
|
||||
"Camera is explicitly disabled.\n", 1, 180, false,
|
||||
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void driver_camera_stop(void)
|
||||
{
|
||||
camera_driver_state_t *camera_st = &camera_driver_st;
|
||||
if ( camera_st->driver
|
||||
&& camera_st->driver->stop
|
||||
&& camera_st->data)
|
||||
camera_st->driver->stop(camera_st->data);
|
||||
}
|
||||
|
||||
bool camera_driver_find_driver(const char *prefix,
|
||||
bool verbosity_enabled)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
camera_driver_state_t
|
||||
*camera_st = &camera_driver_st;
|
||||
int i = (int)driver_find_index(
|
||||
"camera_driver",
|
||||
settings->arrays.camera_driver);
|
||||
|
||||
if (i >= 0)
|
||||
camera_st->driver = (const camera_driver_t*)camera_drivers[i];
|
||||
else
|
||||
{
|
||||
if (verbosity_enabled)
|
||||
{
|
||||
unsigned d;
|
||||
RARCH_ERR("Couldn't find any %s named \"%s\"\n", prefix,
|
||||
settings->arrays.camera_driver);
|
||||
RARCH_LOG_OUTPUT("Available %ss are:\n", prefix);
|
||||
for (d = 0; camera_drivers[d]; d++)
|
||||
{
|
||||
if (camera_drivers[d])
|
||||
{
|
||||
RARCH_LOG_OUTPUT("\t%s\n", camera_drivers[d]->ident);
|
||||
}
|
||||
}
|
||||
|
||||
RARCH_WARN("Going to default to first %s...\n", prefix);
|
||||
}
|
||||
|
||||
if (!(camera_st->driver = (const camera_driver_t*)camera_drivers[0]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2021 - Daniel De Matteis
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _CAMERA_DRIVER_H
|
||||
#define _CAMERA_DRIVER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <boolean.h>
|
||||
#include <retro_common_api.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
typedef struct camera_driver
|
||||
{
|
||||
/* FIXME: params for initialization - queries for resolution,
|
||||
* framerate, color format which might or might not be honored. */
|
||||
void *(*init)(const char *device, uint64_t buffer_types,
|
||||
unsigned width, unsigned height);
|
||||
|
||||
void (*free)(void *data);
|
||||
|
||||
bool (*start)(void *data);
|
||||
void (*stop)(void *data);
|
||||
|
||||
/* Polls the camera driver.
|
||||
* Will call the appropriate callback if a new frame is ready.
|
||||
* Returns true if a new frame was handled. */
|
||||
bool (*poll)(void *data,
|
||||
retro_camera_frame_raw_framebuffer_t frame_raw_cb,
|
||||
retro_camera_frame_opengl_texture_t frame_gl_cb);
|
||||
|
||||
const char *ident;
|
||||
} camera_driver_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct retro_camera_callback cb; /* uint64_t alignment */
|
||||
const camera_driver_t *driver;
|
||||
void *data;
|
||||
bool active;
|
||||
} camera_driver_state_t;
|
||||
|
||||
extern const camera_driver_t *camera_drivers[];
|
||||
|
||||
|
||||
extern camera_driver_t camera_v4l2;
|
||||
extern camera_driver_t camera_android;
|
||||
extern camera_driver_t camera_rwebcam;
|
||||
extern camera_driver_t camera_avfoundation;
|
||||
|
||||
/**
|
||||
* config_get_camera_driver_options:
|
||||
*
|
||||
* Get an enumerated list of all camera driver names,
|
||||
* separated by '|'.
|
||||
*
|
||||
* Returns: string listing of all camera driver names,
|
||||
* separated by '|'.
|
||||
**/
|
||||
const char* config_get_camera_driver_options(void);
|
||||
|
||||
bool driver_camera_start(void);
|
||||
|
||||
void driver_camera_stop(void);
|
||||
|
||||
bool camera_driver_find_driver(const char *prefix,
|
||||
bool verbosity_enabled);
|
||||
|
||||
camera_driver_state_t *camera_state_get_ptr(void);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
@@ -15,8 +15,10 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <libretro.h>
|
||||
#include <glsym/glsym.h>
|
||||
|
||||
#include "../camera_driver.h"
|
||||
#include "../../retroarch.h"
|
||||
|
||||
typedef struct android_camera
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include <boolean.h>
|
||||
#include <libretro.h>
|
||||
|
||||
#include "../camera_driver.h"
|
||||
#include "../../retroarch.h"
|
||||
|
||||
/* forward declarations */
|
||||
|
||||
@@ -42,9 +42,11 @@
|
||||
#include <gfx/scaler/scaler.h>
|
||||
#include <gfx/video_frame.h>
|
||||
#include <file/file_path.h>
|
||||
#include <libretro.h>
|
||||
|
||||
#include <compat/strl.h>
|
||||
|
||||
#include "../camera_driver.h"
|
||||
#include "../../retroarch.h"
|
||||
#include "../../verbosity.h"
|
||||
|
||||
|
||||
+11
-6
@@ -45,6 +45,7 @@
|
||||
#include "msg_hash.h"
|
||||
#include "configuration.h"
|
||||
#include "retroarch.h"
|
||||
#include "runloop.h"
|
||||
#include "dynamic.h"
|
||||
#include "core.h"
|
||||
#include "verbosity.h"
|
||||
@@ -303,6 +304,8 @@ static void cheat_manager_free(void)
|
||||
free(cheat_st->cheats[i].desc);
|
||||
if (cheat_st->cheats[i].code)
|
||||
free(cheat_st->cheats[i].code);
|
||||
cheat_st->cheats[i].desc = NULL;
|
||||
cheat_st->cheats[i].code = NULL;
|
||||
}
|
||||
|
||||
free(cheat_st->cheats);
|
||||
@@ -559,6 +562,8 @@ bool cheat_manager_realloc(unsigned new_size, unsigned default_handler)
|
||||
free(cheat_st->cheats[i].code);
|
||||
if (cheat_st->cheats[i].desc)
|
||||
free(cheat_st->cheats[i].desc);
|
||||
cheat_st->cheats[i].code = NULL;
|
||||
cheat_st->cheats[i].desc = NULL;
|
||||
}
|
||||
|
||||
val = (struct item_cheat*)
|
||||
@@ -693,17 +698,17 @@ static bool cheat_manager_get_game_specific_filename(
|
||||
{
|
||||
char s1[PATH_MAX_LENGTH];
|
||||
struct retro_system_info system_info;
|
||||
global_t *global = global_get_ptr();
|
||||
const char *core_name = NULL;
|
||||
const char *game_name = NULL;
|
||||
runloop_state_t *runloop_st = runloop_state_get_ptr();
|
||||
const char *core_name = NULL;
|
||||
const char *game_name = NULL;
|
||||
|
||||
s1[0] = '\0';
|
||||
s1[0] = '\0';
|
||||
|
||||
if (!global || !core_get_system_info(&system_info))
|
||||
if (!core_get_system_info(&system_info))
|
||||
return false;
|
||||
|
||||
core_name = system_info.library_name;
|
||||
game_name = path_basename_nocompression(global->name.cheatfile);
|
||||
game_name = path_basename_nocompression(runloop_st->name.cheatfile);
|
||||
|
||||
if (string_is_empty(path_cheat_database) ||
|
||||
string_is_empty(core_name) ||
|
||||
|
||||
+626
-172
File diff suppressed because it is too large.
Load diff
@@ -26,6 +26,8 @@
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
bool rcheevos_load(const void *data);
|
||||
void rcheevos_change_disc(const char* new_disc_path, bool initial_disc);
|
||||
|
||||
size_t rcheevos_get_serialize_size(void);
|
||||
bool rcheevos_get_serialized_data(void* buffer);
|
||||
bool rcheevos_set_serialized_data(void* buffer);
|
||||
|
||||
+284
-68
@@ -99,6 +99,32 @@ typedef struct rcheevos_async_io_request
|
||||
char type;
|
||||
} rcheevos_async_io_request;
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
#define RCHEEVOS_CONCURRENT_BADGE_DOWNLOADS 2
|
||||
#else
|
||||
#define RCHEEVOS_CONCURRENT_BADGE_DOWNLOADS 1
|
||||
#endif
|
||||
|
||||
typedef struct rcheevos_fetch_badge_state
|
||||
{
|
||||
unsigned badge_fetch_index;
|
||||
unsigned locked_badge_fetch_index;
|
||||
const char* badge_directory;
|
||||
rcheevos_client_callback callback;
|
||||
void* callback_data;
|
||||
char requested_badges[
|
||||
RCHEEVOS_CONCURRENT_BADGE_DOWNLOADS][32];
|
||||
} rcheevos_fetch_badge_state;
|
||||
|
||||
typedef struct rcheevos_fetch_badge_data
|
||||
{
|
||||
rcheevos_fetch_badge_state* state;
|
||||
int request_index;
|
||||
void* data;
|
||||
size_t data_len;
|
||||
rcheevos_client_callback callback;
|
||||
} rcheevos_fetch_badge_data;
|
||||
|
||||
|
||||
/****************************
|
||||
* forward declarations *
|
||||
@@ -109,6 +135,11 @@ static retro_time_t rcheevos_client_prepare_ping(rcheevos_async_io_request* requ
|
||||
static void rcheevos_async_http_task_callback(
|
||||
retro_task_t* task, void* task_data, void* user_data, const char* error);
|
||||
|
||||
static void rcheevos_async_end_request(rcheevos_async_io_request* request);
|
||||
|
||||
static void rcheevos_async_fetch_badge_callback(
|
||||
struct rcheevos_async_io_request* request,
|
||||
http_transfer_data_t* data, char buffer[], size_t buffer_size);
|
||||
|
||||
/****************************
|
||||
* user agent construction *
|
||||
@@ -374,7 +405,7 @@ static void rcheevos_async_http_task_callback(
|
||||
else if (error)
|
||||
{
|
||||
/* there was a communication error */
|
||||
/* automatically requeued, don't process any further */
|
||||
/* if automatically requeued, don't process any further */
|
||||
if (rcheevos_async_request_failed(request, error))
|
||||
return;
|
||||
|
||||
@@ -397,7 +428,16 @@ static void rcheevos_async_http_task_callback(
|
||||
}
|
||||
|
||||
if (data->status != 200) /* Server returned error via status code. */
|
||||
{
|
||||
snprintf(buffer, sizeof(buffer), "HTTP error code %d", data->status);
|
||||
|
||||
if (request->type == CHEEVOS_ASYNC_FETCH_BADGE)
|
||||
{
|
||||
/* This isn't a JSON request. An empty response with a status code is a valid response. */
|
||||
if (request->handler)
|
||||
request->handler(request, data, buffer, sizeof(buffer));
|
||||
}
|
||||
}
|
||||
else /* Server sent empty response without error status code */
|
||||
strlcpy(buffer, "No response from server", sizeof(buffer));
|
||||
}
|
||||
@@ -484,9 +524,14 @@ static void rcheevos_async_http_task_callback(
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "%s\n", errbuf);
|
||||
}
|
||||
|
||||
rcheevos_async_end_request(request);
|
||||
}
|
||||
|
||||
static void rcheevos_async_end_request(rcheevos_async_io_request* request)
|
||||
{
|
||||
rc_api_destroy_request(&request->request);
|
||||
|
||||
if (request->callback && !aborted)
|
||||
if (request->callback && !rcheevos_load_aborted())
|
||||
request->callback(request->callback_data);
|
||||
|
||||
/* rich presence request will be reused on next ping - reset the attempt
|
||||
@@ -498,10 +543,28 @@ static void rcheevos_async_http_task_callback(
|
||||
}
|
||||
|
||||
static void rcheevos_async_begin_request(
|
||||
rcheevos_async_io_request* request,
|
||||
rcheevos_async_io_request* request, int init_result,
|
||||
rcheevos_async_handler handler, char type, int id,
|
||||
const char* success_message, const char* failure_message)
|
||||
{
|
||||
if (init_result != RC_OK)
|
||||
{
|
||||
char errbuf[256];
|
||||
if (id)
|
||||
snprintf(errbuf, sizeof(errbuf), "%s %u: %s",
|
||||
failure_message, id, rc_error_str(init_result));
|
||||
else
|
||||
snprintf(errbuf, sizeof(errbuf), "%s: %s",
|
||||
failure_message, rc_error_str(init_result));
|
||||
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "%s\n", errbuf);
|
||||
runloop_msg_queue_push(errbuf, 0, 5 * 60, false, NULL,
|
||||
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_ERROR);
|
||||
|
||||
rcheevos_async_end_request(request);
|
||||
return;
|
||||
}
|
||||
|
||||
request->handler = handler;
|
||||
request->type = type;
|
||||
request->id = id;
|
||||
@@ -537,8 +600,25 @@ static bool rcheevos_async_succeeded(int result,
|
||||
|
||||
void rcheevos_client_initialize(void)
|
||||
{
|
||||
/* force non-HTTPS until everything uses RAPI */
|
||||
rc_api_set_host("http://retroachievements.org");
|
||||
const settings_t* settings = config_get_ptr();
|
||||
const char* host = settings->arrays.cheevos_custom_host;
|
||||
if (!host[0])
|
||||
{
|
||||
#ifdef HAVE_SSL
|
||||
host = "https://retroachievements.org";
|
||||
#else
|
||||
host = "http://retroachievements.org";
|
||||
#endif
|
||||
}
|
||||
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Using host: %s\n", host);
|
||||
if (!string_is_equal(host, "https://retroachievements.org"))
|
||||
{
|
||||
rc_api_set_host(host);
|
||||
|
||||
if (!string_is_equal(host, "http://retroachievements.org"))
|
||||
rc_api_set_image_host(host);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************
|
||||
@@ -556,8 +636,16 @@ static void rcheevos_async_login_callback(
|
||||
if (rcheevos_async_succeeded(result, &api_response.response,
|
||||
buffer, buffer_size))
|
||||
{
|
||||
/* save the token to the config and clear the password on success */
|
||||
settings_t* settings = config_get_ptr();
|
||||
strlcpy(settings->arrays.cheevos_token, api_response.api_token,
|
||||
sizeof(settings->arrays.cheevos_token));
|
||||
settings->arrays.cheevos_password[0] = '\0';
|
||||
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "%s logged in successfully\n",
|
||||
api_response.username);
|
||||
api_response.display_name);
|
||||
strlcpy(rcheevos_locals->displayname, api_response.display_name,
|
||||
sizeof(rcheevos_locals->displayname));
|
||||
strlcpy(rcheevos_locals->username, api_response.username,
|
||||
sizeof(rcheevos_locals->username));
|
||||
strlcpy(rcheevos_locals->token, api_response.api_token,
|
||||
@@ -582,18 +670,19 @@ static void rcheevos_client_login(const char* username,
|
||||
else
|
||||
{
|
||||
rc_api_login_request_t api_params;
|
||||
int result;
|
||||
|
||||
memset(&api_params, 0, sizeof(api_params));
|
||||
api_params.username = username;
|
||||
api_params.password = password;
|
||||
api_params.api_token = token;
|
||||
|
||||
rc_api_init_login_request(&request->request, &api_params);
|
||||
result = rc_api_init_login_request(&request->request, &api_params);
|
||||
|
||||
request->callback = callback;
|
||||
request->callback_data = userdata;
|
||||
|
||||
rcheevos_async_begin_request(request,
|
||||
rcheevos_async_begin_request(request, result,
|
||||
rcheevos_async_login_callback,
|
||||
CHEEVOS_ASYNC_LOGIN, 0,
|
||||
NULL,
|
||||
@@ -649,19 +738,17 @@ void rcheevos_client_identify_game(const char* hash,
|
||||
else
|
||||
{
|
||||
rc_api_resolve_hash_request_t api_params;
|
||||
int result;
|
||||
|
||||
memset(&api_params, 0, sizeof(api_params));
|
||||
api_params.username = "unused"; /* TODO: don't set this after upgrading to rcheevos 10.2 */
|
||||
api_params.api_token = "unused"; /* TODO: don't set this after upgrading to rcheevos 10.2 */
|
||||
api_params.game_hash = hash;
|
||||
|
||||
rc_api_init_resolve_hash_request(&request->request, &api_params);
|
||||
result = rc_api_init_resolve_hash_request(&request->request, &api_params);
|
||||
|
||||
request->callback = callback;
|
||||
request->callback_data = userdata;
|
||||
|
||||
rcheevos_begin_load_state(RCHEEVOS_LOAD_STATE_IDENTIFYING_GAME);
|
||||
rcheevos_async_begin_request(request,
|
||||
rcheevos_async_begin_request(request, result,
|
||||
rcheevos_async_resolve_hash_callback,
|
||||
CHEEVOS_ASYNC_RESOLVE_HASH, 0,
|
||||
NULL,
|
||||
@@ -720,15 +807,16 @@ static void rcheevos_client_copy_achievements(
|
||||
|
||||
if (definition->category != 3)
|
||||
{
|
||||
achievement->active = RCHEEVOS_ACTIVE_UNOFFICIAL;
|
||||
if (!settings->bools.cheevos_test_unofficial)
|
||||
continue;
|
||||
|
||||
if (settings->bools.cheevos_test_unofficial)
|
||||
achievement->active |= RCHEEVOS_ACTIVE_SOFTCORE
|
||||
| RCHEEVOS_ACTIVE_HARDCORE;
|
||||
achievement->active = RCHEEVOS_ACTIVE_UNOFFICIAL
|
||||
| RCHEEVOS_ACTIVE_SOFTCORE
|
||||
| RCHEEVOS_ACTIVE_HARDCORE;
|
||||
}
|
||||
else
|
||||
{
|
||||
achievement->active = RCHEEVOS_ACTIVE_SOFTCORE
|
||||
achievement->active = RCHEEVOS_ACTIVE_SOFTCORE
|
||||
| RCHEEVOS_ACTIVE_HARDCORE;
|
||||
|
||||
for (j = 0; j <
|
||||
@@ -868,6 +956,98 @@ static void rcheevos_client_initialize_runtime_callback(void* userdata)
|
||||
free(runtime_data);
|
||||
}
|
||||
|
||||
static void rcheevos_client_fetch_game_badge_callback(void* userdata)
|
||||
{
|
||||
rcheevos_fetch_badge_data* data = (rcheevos_fetch_badge_data*)userdata;
|
||||
rcheevos_async_initialize_runtime_data_t* runtime_data =
|
||||
(rcheevos_async_initialize_runtime_data_t*)data->state->callback_data;
|
||||
|
||||
free((void*)data->state->badge_directory);
|
||||
free(data->state);
|
||||
free(data);
|
||||
|
||||
rcheevos_client_initialize_runtime_callback(runtime_data);
|
||||
}
|
||||
|
||||
static void rcheevos_client_fetch_game_badge(const char* badge_name, rcheevos_async_initialize_runtime_data_t* runtime_data)
|
||||
{
|
||||
#if defined(HAVE_GFX_WIDGETS) /* don't need game badge unless widgets are enabled */
|
||||
char badge_fullpath[PATH_MAX_LENGTH] = "";
|
||||
char* badge_fullname = NULL;
|
||||
size_t badge_fullname_size = 0;
|
||||
|
||||
/* make sure the directory exists */
|
||||
fill_pathname_application_special(badge_fullpath,
|
||||
sizeof(badge_fullpath),
|
||||
APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_CHEEVOS_BADGES);
|
||||
|
||||
if (!path_is_directory(badge_fullpath))
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Creating %s\n", badge_fullpath);
|
||||
path_mkdir(badge_fullpath);
|
||||
}
|
||||
|
||||
fill_pathname_slash(badge_fullpath, sizeof(badge_fullpath));
|
||||
badge_fullname = badge_fullpath + strlen(badge_fullpath);
|
||||
badge_fullname_size = sizeof(badge_fullpath) -
|
||||
(badge_fullname - badge_fullpath);
|
||||
|
||||
snprintf(badge_fullname,
|
||||
badge_fullname_size, "i%s" FILE_PATH_PNG_EXTENSION, badge_name);
|
||||
|
||||
/* check if it's already available */
|
||||
if (path_is_valid(badge_fullpath))
|
||||
return;
|
||||
|
||||
#ifdef CHEEVOS_LOG_BADGES
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Downloading game badge %s\n", badge_name);
|
||||
#endif
|
||||
|
||||
{
|
||||
rcheevos_async_io_request* request = (rcheevos_async_io_request*)
|
||||
calloc(1, sizeof(rcheevos_async_io_request));
|
||||
rcheevos_fetch_badge_data* data = (rcheevos_fetch_badge_data*)
|
||||
calloc(1, sizeof(rcheevos_fetch_badge_data));
|
||||
rcheevos_fetch_badge_state* state = (rcheevos_fetch_badge_state*)
|
||||
calloc(1, sizeof(rcheevos_fetch_badge_state));
|
||||
|
||||
if (!request || !data || !state)
|
||||
{
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG
|
||||
"Failed to allocate fetch badge request\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
rc_api_fetch_image_request_t api_params;
|
||||
int result;
|
||||
|
||||
memset(&api_params, 0, sizeof(api_params));
|
||||
api_params.image_name = badge_name;
|
||||
api_params.image_type = RC_IMAGE_TYPE_GAME;
|
||||
|
||||
result = rc_api_init_fetch_image_request(&request->request, &api_params);
|
||||
|
||||
strlcpy(state->requested_badges[0], badge_fullname, sizeof(state->requested_badges[0]));
|
||||
*badge_fullname = '\0';
|
||||
state->badge_directory = strdup(badge_fullpath);
|
||||
state->callback_data = runtime_data;
|
||||
|
||||
data->state = state;
|
||||
data->request_index = 0;
|
||||
data->callback = rcheevos_client_fetch_game_badge_callback;
|
||||
|
||||
request->callback_data = data;
|
||||
|
||||
rcheevos_begin_load_state(RCHEEVOS_LOAD_STATE_FETCHING_GAME_DATA);
|
||||
rcheevos_async_begin_request(request, result,
|
||||
rcheevos_async_fetch_badge_callback,
|
||||
CHEEVOS_ASYNC_FETCH_BADGE, atoi(badge_name), NULL,
|
||||
"Error fetching game badge");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void rcheevos_async_fetch_user_unlocks_callback(
|
||||
struct rcheevos_async_io_request* request,
|
||||
http_transfer_data_t* data, char buffer[], size_t buffer_size)
|
||||
@@ -914,6 +1094,14 @@ static void rcheevos_async_fetch_game_data_callback(
|
||||
runtime_data->game_data.title);
|
||||
rcheevos_locals->game.console_id =
|
||||
runtime_data->game_data.console_id;
|
||||
|
||||
snprintf(rcheevos_locals->game.badge_name, sizeof(rcheevos_locals->game.badge_name),
|
||||
"i%s", runtime_data->game_data.image_name);
|
||||
rcheevos_client_fetch_game_badge(runtime_data->game_data.image_name, runtime_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
rcheevos_unload();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -971,19 +1159,20 @@ void rcheevos_client_initialize_runtime(unsigned game_id,
|
||||
free(contents);
|
||||
#else
|
||||
rc_api_fetch_game_data_request_t api_params;
|
||||
int result;
|
||||
|
||||
memset(&api_params, 0, sizeof(api_params));
|
||||
api_params.username = rcheevos_locals->username;
|
||||
api_params.api_token = rcheevos_locals->token;
|
||||
api_params.game_id = rcheevos_locals->game.id;
|
||||
|
||||
rc_api_init_fetch_game_data_request(&request->request, &api_params);
|
||||
result = rc_api_init_fetch_game_data_request(&request->request, &api_params);
|
||||
|
||||
request->callback = rcheevos_client_initialize_runtime_callback;
|
||||
request->callback_data = data;
|
||||
|
||||
rcheevos_begin_load_state(RCHEEVOS_LOAD_STATE_FETCHING_GAME_DATA);
|
||||
rcheevos_async_begin_request(request,
|
||||
rcheevos_async_begin_request(request, result,
|
||||
rcheevos_async_fetch_game_data_callback,
|
||||
CHEEVOS_ASYNC_FETCH_GAME_DATA, rcheevos_locals->game.id,
|
||||
"Fetched game data",
|
||||
@@ -1012,6 +1201,7 @@ void rcheevos_client_initialize_runtime(unsigned game_id,
|
||||
else
|
||||
{
|
||||
rc_api_fetch_user_unlocks_request_t api_params;
|
||||
int result;
|
||||
|
||||
memset(&api_params, 0, sizeof(api_params));
|
||||
api_params.username = rcheevos_locals->username;
|
||||
@@ -1019,7 +1209,7 @@ void rcheevos_client_initialize_runtime(unsigned game_id,
|
||||
api_params.game_id = rcheevos_locals->game.id;
|
||||
api_params.hardcore = i;
|
||||
|
||||
rc_api_init_fetch_user_unlocks_request(&request->request, &api_params);
|
||||
result = rc_api_init_fetch_user_unlocks_request(&request->request, &api_params);
|
||||
|
||||
request->callback = rcheevos_client_initialize_runtime_callback;
|
||||
request->callback_data = data;
|
||||
@@ -1027,7 +1217,7 @@ void rcheevos_client_initialize_runtime(unsigned game_id,
|
||||
rcheevos_begin_load_state(RCHEEVOS_LOAD_STATE_FETCHING_GAME_DATA);
|
||||
if (i == 0)
|
||||
{
|
||||
rcheevos_async_begin_request(request,
|
||||
rcheevos_async_begin_request(request, result,
|
||||
rcheevos_async_fetch_user_unlocks_callback,
|
||||
CHEEVOS_ASYNC_FETCH_USER_UNLOCKS,
|
||||
rcheevos_locals->game.id,
|
||||
@@ -1036,7 +1226,7 @@ void rcheevos_client_initialize_runtime(unsigned game_id,
|
||||
}
|
||||
else
|
||||
{
|
||||
rcheevos_async_begin_request(request,
|
||||
rcheevos_async_begin_request(request, result,
|
||||
rcheevos_async_fetch_user_unlocks_callback,
|
||||
CHEEVOS_ASYNC_FETCH_HARDCORE_USER_UNLOCKS,
|
||||
rcheevos_locals->game.id,
|
||||
@@ -1187,16 +1377,17 @@ void rcheevos_client_start_session(unsigned game_id)
|
||||
else
|
||||
{
|
||||
rc_api_start_session_request_t api_params;
|
||||
int result;
|
||||
|
||||
memset(&api_params, 0, sizeof(api_params));
|
||||
api_params.username = rcheevos_locals->username;
|
||||
api_params.api_token = rcheevos_locals->token;
|
||||
api_params.game_id = game_id;
|
||||
|
||||
rc_api_init_start_session_request(
|
||||
result = rc_api_init_start_session_request(
|
||||
&request->request, &api_params);
|
||||
|
||||
rcheevos_async_begin_request(request,
|
||||
rcheevos_async_begin_request(request, result,
|
||||
rcheevos_async_start_session_callback,
|
||||
CHEEVOS_ASYNC_START_SESSION, game_id,
|
||||
"Started session for game",
|
||||
@@ -1210,30 +1401,6 @@ void rcheevos_client_start_session(unsigned game_id)
|
||||
* fetch badge *
|
||||
****************************/
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
#define RCHEEVOS_CONCURRENT_BADGE_DOWNLOADS 2
|
||||
#else
|
||||
#define RCHEEVOS_CONCURRENT_BADGE_DOWNLOADS 1
|
||||
#endif
|
||||
|
||||
typedef struct rcheevos_fetch_badge_state
|
||||
{
|
||||
unsigned badge_fetch_index;
|
||||
unsigned locked_badge_fetch_index;
|
||||
const char* badge_directory;
|
||||
rcheevos_client_callback callback;
|
||||
void* callback_data;
|
||||
char requested_badges[
|
||||
RCHEEVOS_CONCURRENT_BADGE_DOWNLOADS][32];
|
||||
} rcheevos_fetch_badge_state;
|
||||
|
||||
typedef struct rcheevos_fetch_badge_data
|
||||
{
|
||||
rcheevos_fetch_badge_state* state;
|
||||
int request_index;
|
||||
} rcheevos_fetch_badge_data;
|
||||
|
||||
|
||||
static bool rcheevos_fetch_next_badge(rcheevos_fetch_badge_state* state);
|
||||
|
||||
static void rcheevos_end_fetch_badges(rcheevos_fetch_badge_state* state)
|
||||
@@ -1257,26 +1424,69 @@ static void rcheevos_async_download_next_badge(void* userdata)
|
||||
free(badge_data);
|
||||
}
|
||||
|
||||
static void rcheevos_async_fetch_badge_callback(
|
||||
struct rcheevos_async_io_request* request,
|
||||
http_transfer_data_t* data, char buffer[], size_t buffer_size)
|
||||
static void rcheevos_async_fetch_badge_complete(rcheevos_fetch_badge_data* badge_data)
|
||||
{
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
|
||||
CHEEVOS_LOCK(rcheevos_locals->load_info.request_lock);
|
||||
badge_data->state->requested_badges[badge_data->request_index][0] = '\0';
|
||||
CHEEVOS_UNLOCK(rcheevos_locals->load_info.request_lock);
|
||||
|
||||
if (badge_data->callback)
|
||||
badge_data->callback(badge_data);
|
||||
}
|
||||
|
||||
static void rcheevos_async_write_badge(retro_task_t* task)
|
||||
{
|
||||
char badge_fullpath[PATH_MAX_LENGTH];
|
||||
rcheevos_fetch_badge_data* badge_data =
|
||||
(rcheevos_fetch_badge_data*)request->callback_data;
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
rcheevos_fetch_badge_data* badge_data =
|
||||
(rcheevos_fetch_badge_data*)task->user_data;
|
||||
|
||||
fill_pathname_join(badge_fullpath, badge_data->state->badge_directory,
|
||||
badge_data->state->requested_badges[badge_data->request_index],
|
||||
sizeof(badge_fullpath));
|
||||
|
||||
if (!filestream_write_file(badge_fullpath, data->data, data->len))
|
||||
if (!filestream_write_file(badge_fullpath, badge_data->data, badge_data->data_len))
|
||||
{
|
||||
CHEEVOS_ERR(RCHEEVOS_TAG "Error writing badge %s\n",
|
||||
badge_fullpath);
|
||||
badge_fullpath);
|
||||
}
|
||||
|
||||
CHEEVOS_LOCK(rcheevos_locals->load_info.request_lock);
|
||||
badge_data->state->requested_badges[badge_data->request_index][0] = '\0';
|
||||
CHEEVOS_UNLOCK(rcheevos_locals->load_info.request_lock);
|
||||
free(badge_data->data);
|
||||
badge_data->data = NULL;
|
||||
badge_data->data_len = 0;
|
||||
|
||||
task_set_finished(task, true);
|
||||
|
||||
rcheevos_async_fetch_badge_complete(badge_data);
|
||||
}
|
||||
|
||||
static void rcheevos_async_fetch_badge_callback(
|
||||
struct rcheevos_async_io_request* request,
|
||||
http_transfer_data_t* data, char buffer[], size_t buffer_size)
|
||||
{
|
||||
rcheevos_fetch_badge_data* badge_data =
|
||||
(rcheevos_fetch_badge_data*)request->callback_data;
|
||||
retro_task_t* task;
|
||||
|
||||
if (!data->data)
|
||||
{
|
||||
/* error retrieving badge, nothing to write. just call the callback */
|
||||
rcheevos_async_fetch_badge_complete(badge_data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* take ownership of the file data */
|
||||
badge_data->data = data->data;
|
||||
badge_data->data_len = data->len;
|
||||
data->data = NULL;
|
||||
data->len = 0;
|
||||
|
||||
/* this is called on the primary thread. use a task to write the file from a background thread */
|
||||
task = task_init();
|
||||
task->handler = rcheevos_async_write_badge;
|
||||
task->user_data = badge_data;
|
||||
task_queue_push(task);
|
||||
}
|
||||
|
||||
static bool rcheevos_client_fetch_badge(
|
||||
@@ -1362,6 +1572,7 @@ static bool rcheevos_client_fetch_badge(
|
||||
else
|
||||
{
|
||||
rc_api_fetch_image_request_t api_params;
|
||||
int result;
|
||||
|
||||
memset(&api_params, 0, sizeof(api_params));
|
||||
api_params.image_name = badge_name;
|
||||
@@ -1369,16 +1580,16 @@ static bool rcheevos_client_fetch_badge(
|
||||
? RC_IMAGE_TYPE_ACHIEVEMENT_LOCKED
|
||||
: RC_IMAGE_TYPE_ACHIEVEMENT;
|
||||
|
||||
rc_api_init_fetch_image_request(&request->request, &api_params);
|
||||
result = rc_api_init_fetch_image_request(&request->request, &api_params);
|
||||
|
||||
data->state = state;
|
||||
data->request_index = request_index;
|
||||
data->callback = rcheevos_async_download_next_badge;
|
||||
|
||||
request->callback = rcheevos_async_download_next_badge;
|
||||
request->callback_data = data;
|
||||
|
||||
rcheevos_begin_load_state(RCHEEVOS_LOAD_STATE_FETCHING_BADGES);
|
||||
rcheevos_async_begin_request(request,
|
||||
rcheevos_async_begin_request(request, result,
|
||||
rcheevos_async_fetch_badge_callback,
|
||||
CHEEVOS_ASYNC_FETCH_BADGE, atoi(badge_name), NULL,
|
||||
"Error fetching badge");
|
||||
@@ -1536,6 +1747,9 @@ static void rcheevos_async_award_achievement_callback(
|
||||
CHEEVOS_LOG(RCHEEVOS_TAG "Achievement %u: %s\n",
|
||||
request->id, api_response.response.error_message);
|
||||
}
|
||||
|
||||
if (api_response.achievements_remaining == 0)
|
||||
rcheevos_show_mastery_placard();
|
||||
}
|
||||
|
||||
rc_api_destroy_award_achievement_response(&api_response);
|
||||
@@ -1552,8 +1766,9 @@ void rcheevos_client_award_achievement(unsigned achievement_id)
|
||||
}
|
||||
else
|
||||
{
|
||||
rc_api_award_achievement_request_t api_params;
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
rc_api_award_achievement_request_t api_params;
|
||||
int result;
|
||||
|
||||
memset(&api_params, 0, sizeof(api_params));
|
||||
api_params.username = rcheevos_locals->username;
|
||||
@@ -1562,10 +1777,10 @@ void rcheevos_client_award_achievement(unsigned achievement_id)
|
||||
api_params.hardcore = rcheevos_locals->hardcore_active ? 1 : 0;
|
||||
api_params.game_hash = rcheevos_locals->game.hash;
|
||||
|
||||
rc_api_init_award_achievement_request(&request->request,
|
||||
result = rc_api_init_award_achievement_request(&request->request,
|
||||
&api_params);
|
||||
|
||||
rcheevos_async_begin_request(request,
|
||||
rcheevos_async_begin_request(request, result,
|
||||
rcheevos_async_award_achievement_callback,
|
||||
CHEEVOS_ASYNC_AWARD_ACHIEVEMENT, achievement_id,
|
||||
"Awarded achievement",
|
||||
@@ -1608,6 +1823,7 @@ void rcheevos_client_submit_lboard_entry(unsigned leaderboard_id,
|
||||
{
|
||||
const rcheevos_locals_t* rcheevos_locals = get_rcheevos_locals();
|
||||
rc_api_submit_lboard_entry_request_t api_params;
|
||||
int result;
|
||||
|
||||
memset(&api_params, 0, sizeof(api_params));
|
||||
api_params.username = rcheevos_locals->username;
|
||||
@@ -1616,10 +1832,10 @@ void rcheevos_client_submit_lboard_entry(unsigned leaderboard_id,
|
||||
api_params.score = value;
|
||||
api_params.game_hash = rcheevos_locals->game.hash;
|
||||
|
||||
rc_api_init_submit_lboard_entry_request(&request->request,
|
||||
result = rc_api_init_submit_lboard_entry_request(&request->request,
|
||||
&api_params);
|
||||
|
||||
rcheevos_async_begin_request(request,
|
||||
rcheevos_async_begin_request(request, result,
|
||||
rcheevos_async_submit_lboard_entry_callback,
|
||||
CHEEVOS_ASYNC_SUBMIT_LBOARD, leaderboard_id,
|
||||
"Submitted leaderboard",
|
||||
|
||||
@@ -18,11 +18,8 @@
|
||||
#define __RARCH_CHEEVOS_LOCALS_H
|
||||
|
||||
#include "../deps/rcheevos/include/rc_runtime.h"
|
||||
|
||||
#include "../deps/rcheevos/src/rcheevos/rc_libretro.h"
|
||||
|
||||
#include <../command.h>
|
||||
#include <../verbosity.h>
|
||||
#include <boolean.h>
|
||||
#include <queues/task_queue.h>
|
||||
|
||||
@@ -32,6 +29,9 @@
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
#include "../command.h"
|
||||
#include "../verbosity.h"
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
/************************************************************************
|
||||
@@ -120,12 +120,24 @@ typedef struct rcheevos_load_info_t
|
||||
#endif
|
||||
} rcheevos_load_info_t;
|
||||
|
||||
typedef struct rcheevos_hash_entry_t
|
||||
{
|
||||
uint32_t path_djb2;
|
||||
int game_id;
|
||||
struct rcheevos_hash_entry_t* next;
|
||||
char hash[33];
|
||||
} rcheevos_hash_entry_t;
|
||||
|
||||
typedef struct rcheevos_game_info_t
|
||||
{
|
||||
int id;
|
||||
int console_id;
|
||||
char* title;
|
||||
char hash[33];
|
||||
char badge_name[16];
|
||||
char* hash;
|
||||
bool mastery_placard_shown;
|
||||
|
||||
rcheevos_hash_entry_t* hashes;
|
||||
|
||||
rcheevos_racheevo_t* achievements;
|
||||
rcheevos_ralboard_t* leaderboards;
|
||||
@@ -157,6 +169,7 @@ typedef struct rcheevos_locals_t
|
||||
enum event_command queued_command; /* action queued by background thread to be run on main thread */
|
||||
#endif
|
||||
|
||||
char displayname[32]; /* name to display in messages */
|
||||
char username[32]; /* case-corrected username */
|
||||
char token[32]; /* user's session token */
|
||||
char user_agent_prefix[128]; /* RetroArch/OS version information */
|
||||
@@ -183,6 +196,8 @@ void rcheevos_begin_load_state(enum rcheevos_load_state state);
|
||||
int rcheevos_end_load_state(void);
|
||||
bool rcheevos_load_aborted(void);
|
||||
|
||||
void rcheevos_show_mastery_placard(void);
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
#define CHEEVOS_LOCK(l) do { slock_lock(l); } while (0)
|
||||
#define CHEEVOS_UNLOCK(l) do { slock_unlock(l); } while (0)
|
||||
|
||||
+22
-11
@@ -28,6 +28,7 @@
|
||||
#include "../menu/menu_entries.h"
|
||||
|
||||
#include <features/features_cpu.h>
|
||||
#include <retro_assert.h>
|
||||
|
||||
enum rcheevos_menuitem_bucket
|
||||
{
|
||||
@@ -115,9 +116,12 @@ bool rcheevos_menu_get_state(unsigned menu_offset, char *buffer, size_t len)
|
||||
if (cheevo)
|
||||
{
|
||||
if (cheevo->menu_progress)
|
||||
snprintf(buffer, len, "%s - %d%%",
|
||||
msg_hash_to_str(menuitem->state_label_idx),
|
||||
cheevo->menu_progress);
|
||||
{
|
||||
const int written = snprintf(buffer, len, "%s - ",
|
||||
msg_hash_to_str(menuitem->state_label_idx));
|
||||
if (len - written > 0)
|
||||
rc_runtime_format_achievement_measured(&rcheevos_locals->runtime, cheevo->id, buffer + written, len - written);
|
||||
}
|
||||
else
|
||||
strlcpy(buffer, msg_hash_to_str(menuitem->state_label_idx), len);
|
||||
|
||||
@@ -271,7 +275,6 @@ static void rcheevos_menu_update_badge(rcheevos_racheevo_t* cheevo)
|
||||
static void rcheevos_menu_append_items(rcheevos_locals_t* rcheevos_locals,
|
||||
enum rcheevos_menuitem_bucket bucket)
|
||||
{
|
||||
const settings_t *settings = config_get_ptr();
|
||||
rcheevos_racheevo_t* cheevo = rcheevos_locals->game.achievements;
|
||||
rcheevos_racheevo_t* stop = cheevo + rcheevos_locals->game.achievement_count;
|
||||
const unsigned first_index = rcheevos_locals->menuitem_count;
|
||||
@@ -345,9 +348,14 @@ static void rcheevos_menu_append_items(rcheevos_locals_t* rcheevos_locals,
|
||||
break;
|
||||
}
|
||||
|
||||
if (cheevo->badge && cheevo->badge[0] && settings &&
|
||||
settings->bools.cheevos_badges_enable)
|
||||
rcheevos_menu_update_badge(cheevo);
|
||||
if (cheevo->badge && cheevo->badge[0])
|
||||
{
|
||||
#ifndef HAVE_GFX_WIDGETS
|
||||
const settings_t* settings = config_get_ptr();
|
||||
if (settings && settings->bools.cheevos_badges_enable)
|
||||
#endif
|
||||
rcheevos_menu_update_badge(cheevo);
|
||||
}
|
||||
}
|
||||
|
||||
++cheevo;
|
||||
@@ -393,7 +401,7 @@ void rcheevos_menu_populate_hardcore_pause_submenu(void* data)
|
||||
{
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_PAUSE_CANCEL),
|
||||
msg_hash_to_str(MENU_ENUM_SUBLABEL_ACHIEVEMENT_PAUSE_CANCEL),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE_CANCEL),
|
||||
MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE_CANCEL,
|
||||
MENU_SETTING_ACTION_CLOSE, 0, 0);
|
||||
menu_entries_append_enum(info->list,
|
||||
@@ -406,7 +414,7 @@ void rcheevos_menu_populate_hardcore_pause_submenu(void* data)
|
||||
{
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_RESUME_CANCEL),
|
||||
msg_hash_to_str(MENU_ENUM_SUBLABEL_ACHIEVEMENT_RESUME_CANCEL),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_ACHIEVEMENT_RESUME_CANCEL),
|
||||
MENU_ENUM_LABEL_ACHIEVEMENT_RESUME_CANCEL,
|
||||
MENU_SETTING_ACTION_CLOSE, 0, 0);
|
||||
menu_entries_append_enum(info->list,
|
||||
@@ -443,13 +451,13 @@ void rcheevos_menu_populate(void* data)
|
||||
if (rcheevos_locals->hardcore_active)
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_PAUSE),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_PAUSE_MENU),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE_MENU),
|
||||
MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE_MENU,
|
||||
MENU_SETTING_ACTION_PAUSE_ACHIEVEMENTS, 0, 0);
|
||||
else
|
||||
menu_entries_append_enum(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_RESUME),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_PAUSE_MENU),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE_MENU),
|
||||
MENU_ENUM_LABEL_ACHIEVEMENT_PAUSE_MENU,
|
||||
MENU_SETTING_ACTION_RESUME_ACHIEVEMENTS, 0, 0);
|
||||
}
|
||||
@@ -653,6 +661,9 @@ uintptr_t rcheevos_get_badge_texture(const char *badge, bool locked)
|
||||
if (!badge)
|
||||
return 0;
|
||||
|
||||
/* OpenGL driver crashes if gfx_display_reset_textures_list is called on a background thread */
|
||||
retro_assert(task_is_on_main_thread());
|
||||
|
||||
snprintf(badge_file, sizeof(badge_file), "%s%s%s", badge,
|
||||
locked ? "_lock" : "", FILE_PATH_PNG_EXTENSION);
|
||||
|
||||
|
||||
@@ -96,6 +96,8 @@ static bool command_get_arg(const char *tok,
|
||||
if (str == tok)
|
||||
{
|
||||
const char *argument = str + strlen(action_map[i].str);
|
||||
if (!argument)
|
||||
return false;
|
||||
if (*argument != ' ' && *argument != '\0')
|
||||
return false;
|
||||
|
||||
@@ -223,7 +225,7 @@ command_t* command_network_new(uint16_t port)
|
||||
int fd = socket_init(
|
||||
(void**)&res, port, NULL, SOCKET_TYPE_DATAGRAM);
|
||||
|
||||
RARCH_LOG("%s %hu.\n",
|
||||
RARCH_LOG("[NetCMD]: %s %hu.\n",
|
||||
msg_hash_to_str(MSG_BRINGING_UP_COMMAND_INTERFACE_ON_PORT),
|
||||
(unsigned short)port);
|
||||
|
||||
@@ -241,7 +243,7 @@ command_t* command_network_new(uint16_t port)
|
||||
|
||||
if (!socket_bind(netcmd->net_fd, (void*)res))
|
||||
{
|
||||
RARCH_ERR("%s.\n",
|
||||
RARCH_ERR("[NetCMD]: %s.\n",
|
||||
msg_hash_to_str(MSG_FAILED_TO_BIND_SOCKET));
|
||||
goto error;
|
||||
}
|
||||
@@ -258,7 +260,6 @@ error:
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(HAVE_STDIN_CMD)
|
||||
typedef struct
|
||||
{
|
||||
@@ -335,6 +336,14 @@ command_t* command_stdin_new(void)
|
||||
|
||||
cmd = (command_t*)calloc(1, sizeof(command_t));
|
||||
stdincmd = (command_stdin_t*)calloc(1, sizeof(command_stdin_t));
|
||||
|
||||
if (!cmd)
|
||||
return NULL;
|
||||
if (!stdincmd)
|
||||
{
|
||||
free(cmd);
|
||||
return NULL;
|
||||
}
|
||||
cmd->userptr = stdincmd;
|
||||
cmd->poll = command_stdin_poll;
|
||||
cmd->replier = stdin_command_reply;
|
||||
@@ -344,6 +353,46 @@ command_t* command_stdin_new(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
bool command_get_config_param(command_t *cmd, const char* arg)
|
||||
{
|
||||
char reply[8192] = {0};
|
||||
const char *value = "unsupported";
|
||||
settings_t *settings = config_get_ptr();
|
||||
bool video_fullscreen = settings->bools.video_fullscreen;
|
||||
const char *dir_runtime_log = settings->paths.directory_runtime_log;
|
||||
const char *log_dir = settings->paths.log_dir;
|
||||
const char *directory_cache = settings->paths.directory_cache;
|
||||
const char *directory_system = settings->paths.directory_system;
|
||||
const char *path_username = settings->paths.username;
|
||||
|
||||
if (string_is_equal(arg, "video_fullscreen"))
|
||||
{
|
||||
if (video_fullscreen)
|
||||
value = "true";
|
||||
else
|
||||
value = "false";
|
||||
}
|
||||
else if (string_is_equal(arg, "savefile_directory"))
|
||||
value = dir_get_ptr(RARCH_DIR_SAVEFILE);
|
||||
else if (string_is_equal(arg, "savestate_directory"))
|
||||
value = dir_get_ptr(RARCH_DIR_SAVESTATE);
|
||||
else if (string_is_equal(arg, "runtime_log_directory"))
|
||||
value = dir_runtime_log;
|
||||
else if (string_is_equal(arg, "log_dir"))
|
||||
value = log_dir;
|
||||
else if (string_is_equal(arg, "cache_directory"))
|
||||
value = directory_cache;
|
||||
else if (string_is_equal(arg, "system_directory"))
|
||||
value = directory_system;
|
||||
else if (string_is_equal(arg, "netplay_nickname"))
|
||||
value = path_username;
|
||||
/* TODO: query any string */
|
||||
|
||||
snprintf(reply, sizeof(reply), "GET_CONFIG_PARAM %s %s\n", arg, value);
|
||||
cmd->replier(cmd, reply, strlen(reply));
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(HAVE_LAKKA)
|
||||
#include <sys/un.h>
|
||||
#define MAX_USER_CONNECTIONS 4
|
||||
@@ -507,8 +556,8 @@ static bool command_verify(const char *cmd)
|
||||
if (command_get_arg(cmd, NULL, NULL))
|
||||
return true;
|
||||
|
||||
RARCH_ERR("Command \"%s\" is not recognized by the program.\n", cmd);
|
||||
RARCH_ERR("\tValid commands:\n");
|
||||
RARCH_ERR("[NetCMD]: Command \"%s\" is not recognized by the program.\n", cmd);
|
||||
RARCH_ERR("[NetCMD]: \tValid commands:\n");
|
||||
for (i = 0; i < ARRAY_SIZE(map); i++)
|
||||
RARCH_ERR("\t\t%s\n", map[i].str);
|
||||
|
||||
@@ -550,7 +599,7 @@ bool command_network_send(const char *cmd_)
|
||||
if (port_)
|
||||
port = strtoul(port_, NULL, 0);
|
||||
|
||||
RARCH_LOG("%s: \"%s\" to %s:%hu\n",
|
||||
RARCH_LOG("[NetCMD]: %s: \"%s\" to %s:%hu\n",
|
||||
msg_hash_to_str(MSG_SENDING_COMMAND),
|
||||
cmd, host, (unsigned short)port);
|
||||
|
||||
@@ -621,7 +670,7 @@ bool command_write_ram(command_t *cmd, const char *arg)
|
||||
|
||||
if (rcheevos_hardcore_active())
|
||||
{
|
||||
RARCH_LOG("Achievements hardcore mode disabled by WRITE_CORE_RAM\n");
|
||||
RARCH_LOG("[Command]: Achievements hardcore mode disabled by WRITE_CORE_RAM.\n");
|
||||
rcheevos_pause_hardcore();
|
||||
}
|
||||
|
||||
@@ -644,7 +693,7 @@ bool command_version(command_t *cmd, const char* arg)
|
||||
return true;
|
||||
}
|
||||
|
||||
static const rarch_memory_descriptor_t* command_memory_get_descriptor(const rarch_memory_map_t* mmap, unsigned address)
|
||||
static const rarch_memory_descriptor_t* command_memory_get_descriptor(const rarch_memory_map_t* mmap, unsigned address, size_t* offset)
|
||||
{
|
||||
const rarch_memory_descriptor_t* desc = mmap->descriptors;
|
||||
const rarch_memory_descriptor_t* end = desc + mmap->num_descriptors;
|
||||
@@ -655,15 +704,37 @@ static const rarch_memory_descriptor_t* command_memory_get_descriptor(const rarc
|
||||
{
|
||||
/* if select is 0, attempt to explicitly match the address */
|
||||
if (address >= desc->core.start && address < desc->core.start + desc->core.len)
|
||||
{
|
||||
*offset = address - desc->core.start;
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* otherwise, attempt to match the address by matching the select bits */
|
||||
if (((desc->core.start ^ address) & desc->core.select) == 0)
|
||||
{
|
||||
/* adjust the address to the start of the descriptor */
|
||||
unsigned desc_offset = address - (unsigned)desc->core.start;
|
||||
|
||||
/* address is unsigned. we only need that much of the disconnect mask */
|
||||
unsigned mask = (unsigned)desc->core.disconnect;
|
||||
|
||||
/* this magic logic is copied from mmap_reduce. it removes any bits from
|
||||
* address that are non-zero in the disconnect field. bits above the
|
||||
* removed bits are shifted down to fill the gap. */
|
||||
while (mask)
|
||||
{
|
||||
const unsigned tmp = (mask - 1) & ~mask;
|
||||
desc_offset = (desc_offset & tmp) | ((desc_offset >> 1) & ~tmp);
|
||||
mask = (mask & (mask - 1)) >> 1;
|
||||
}
|
||||
|
||||
/* we've calculated the actual offset of the data within the descriptor */
|
||||
*offset = desc_offset;
|
||||
|
||||
/* sanity check - make sure the descriptor is large enough to hold the target address */
|
||||
if (address - desc->core.start < desc->core.len)
|
||||
if (desc_offset < desc->core.len)
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
@@ -684,7 +755,8 @@ uint8_t *command_memory_get_pointer(
|
||||
strlcpy(reply_at, " -1 no memory map defined\n", len);
|
||||
else
|
||||
{
|
||||
const rarch_memory_descriptor_t* desc = command_memory_get_descriptor(&system->mmaps, address);
|
||||
size_t offset;
|
||||
const rarch_memory_descriptor_t* desc = command_memory_get_descriptor(&system->mmaps, address, &offset);
|
||||
if (!desc)
|
||||
strlcpy(reply_at, " -1 no descriptor for address\n", len);
|
||||
else if (!desc->core.ptr)
|
||||
@@ -693,7 +765,6 @@ uint8_t *command_memory_get_pointer(
|
||||
strlcpy(reply_at, " -1 descriptor data is readonly\n", len);
|
||||
else
|
||||
{
|
||||
const size_t offset = address - desc->core.start;
|
||||
*max_bytes = (desc->core.len - offset);
|
||||
return (uint8_t*)desc->core.ptr + desc->core.offset + offset;
|
||||
}
|
||||
@@ -810,7 +881,7 @@ bool command_write_memory(command_t *cmd, const char *arg)
|
||||
#ifdef HAVE_CHEEVOS
|
||||
if (rcheevos_hardcore_active())
|
||||
{
|
||||
RARCH_LOG("Achievements hardcore mode disabled by WRITE_CORE_MEMORY\n");
|
||||
RARCH_LOG("[Command]: Achievements hardcore mode disabled by WRITE_CORE_MEMORY.\n");
|
||||
rcheevos_pause_hardcore();
|
||||
}
|
||||
#endif
|
||||
@@ -1037,16 +1108,20 @@ bool command_event_resize_windowed_scale(settings_t *settings,
|
||||
|
||||
bool command_event_save_auto_state(
|
||||
bool savestate_auto_save,
|
||||
global_t *global,
|
||||
const enum rarch_core_type current_core_type)
|
||||
{
|
||||
runloop_state_t *runloop_st = runloop_state_get_ptr();
|
||||
bool ret = false;
|
||||
char savestate_name_auto[PATH_MAX_LENGTH];
|
||||
|
||||
if (!global || !savestate_auto_save)
|
||||
if (runloop_st->entry_state_slot)
|
||||
return false;
|
||||
if (!savestate_auto_save)
|
||||
return false;
|
||||
if (current_core_type == CORE_TYPE_DUMMY)
|
||||
return false;
|
||||
if (!core_info_current_supports_savestate())
|
||||
return false;
|
||||
|
||||
if (string_is_empty(path_basename(path_get(RARCH_PATH_BASENAME))))
|
||||
return false;
|
||||
@@ -1058,7 +1133,8 @@ bool command_event_save_auto_state(
|
||||
|
||||
savestate_name_auto[0] = '\0';
|
||||
|
||||
fill_pathname_noext(savestate_name_auto, global->name.savestate,
|
||||
fill_pathname_noext(savestate_name_auto,
|
||||
runloop_st->name.savestate,
|
||||
".auto", sizeof(savestate_name_auto));
|
||||
|
||||
ret = content_save_state((const char*)savestate_name_auto, true, true);
|
||||
@@ -1099,10 +1175,59 @@ void command_event_init_cheats(
|
||||
}
|
||||
#endif
|
||||
|
||||
void command_event_load_auto_state(global_t *global)
|
||||
bool command_event_load_entry_state(void)
|
||||
{
|
||||
char entry_state_path[PATH_MAX_LENGTH];
|
||||
int entry_path_stats;
|
||||
runloop_state_t *runloop_st = runloop_state_get_ptr();
|
||||
bool ret = false;
|
||||
|
||||
if (!core_info_current_supports_savestate())
|
||||
return false;
|
||||
|
||||
#ifdef HAVE_CHEEVOS
|
||||
if (rcheevos_hardcore_active())
|
||||
return false;
|
||||
#endif
|
||||
#ifdef HAVE_NETWORKING
|
||||
if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_ENABLED, NULL))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
entry_state_path[0] = '\0';
|
||||
|
||||
if (!retroarch_get_entry_state_path(entry_state_path, sizeof(entry_state_path),
|
||||
runloop_st->entry_state_slot))
|
||||
return false;
|
||||
|
||||
entry_path_stats = path_stat(entry_state_path);
|
||||
|
||||
if ((entry_path_stats & RETRO_VFS_STAT_IS_VALID) == 0
|
||||
|| (entry_path_stats & RETRO_VFS_STAT_IS_DIRECTORY) != 0)
|
||||
return false;
|
||||
|
||||
ret = content_load_state(entry_state_path, false, true);
|
||||
|
||||
RARCH_LOG("[State]: %s \"%s\".\n",
|
||||
msg_hash_to_str(MSG_FOUND_ENTRY_STATE_IN),
|
||||
entry_state_path);
|
||||
RARCH_LOG("[State]: %s \"%s\" %s.\n",
|
||||
msg_hash_to_str(MSG_LOADING_ENTRY_STATE_FROM),
|
||||
entry_state_path, ret ? "succeeded" : "failed"
|
||||
);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void command_event_load_auto_state(void)
|
||||
{
|
||||
char savestate_name_auto[PATH_MAX_LENGTH];
|
||||
runloop_state_t *runloop_st = runloop_state_get_ptr();
|
||||
bool ret = false;
|
||||
|
||||
if (!core_info_current_supports_savestate())
|
||||
return;
|
||||
|
||||
#ifdef HAVE_CHEEVOS
|
||||
if (rcheevos_hardcore_active())
|
||||
return;
|
||||
@@ -1114,7 +1239,7 @@ void command_event_load_auto_state(global_t *global)
|
||||
|
||||
savestate_name_auto[0] = '\0';
|
||||
|
||||
fill_pathname_noext(savestate_name_auto, global->name.savestate,
|
||||
fill_pathname_noext(savestate_name_auto, runloop_st->name.savestate,
|
||||
".auto", sizeof(savestate_name_auto));
|
||||
|
||||
if (!path_is_valid(savestate_name_auto))
|
||||
@@ -1122,17 +1247,16 @@ void command_event_load_auto_state(global_t *global)
|
||||
|
||||
ret = content_load_state(savestate_name_auto, false, true);
|
||||
|
||||
RARCH_LOG("%s: %s\n%s \"%s\" %s.\n",
|
||||
RARCH_LOG("[State]: %s \"%s\".\n",
|
||||
msg_hash_to_str(MSG_FOUND_AUTO_SAVESTATE_IN),
|
||||
savestate_name_auto,
|
||||
savestate_name_auto);
|
||||
RARCH_LOG("[State]: %s \"%s\" %s.\n",
|
||||
msg_hash_to_str(MSG_AUTOLOADING_SAVESTATE_FROM),
|
||||
savestate_name_auto, ret ? "succeeded" : "failed"
|
||||
);
|
||||
}
|
||||
|
||||
void command_event_set_savestate_auto_index(
|
||||
settings_t *settings,
|
||||
const global_t *global)
|
||||
void command_event_set_savestate_auto_index(settings_t *settings)
|
||||
{
|
||||
size_t i;
|
||||
char state_dir[PATH_MAX_LENGTH];
|
||||
@@ -1140,21 +1264,22 @@ void command_event_set_savestate_auto_index(
|
||||
|
||||
struct string_list *dir_list = NULL;
|
||||
unsigned max_idx = 0;
|
||||
runloop_state_t *runloop_st = runloop_state_get_ptr();
|
||||
bool savestate_auto_index = settings->bools.savestate_auto_index;
|
||||
bool show_hidden_files = settings->bools.show_hidden_files;
|
||||
|
||||
if (!global || !savestate_auto_index)
|
||||
if (!savestate_auto_index)
|
||||
return;
|
||||
|
||||
state_dir[0] = state_base[0] = '\0';
|
||||
|
||||
/* Find the file in the same directory as global->savestate_name
|
||||
/* Find the file in the same directory as runloop_st->savestate_name
|
||||
* with the largest numeral suffix.
|
||||
*
|
||||
* E.g. /foo/path/content.state, will try to find
|
||||
* /foo/path/content.state%d, where %d is the largest number available.
|
||||
*/
|
||||
fill_pathname_basedir(state_dir, global->name.savestate,
|
||||
fill_pathname_basedir(state_dir, runloop_st->name.savestate,
|
||||
sizeof(state_dir));
|
||||
|
||||
dir_list = dir_list_new_special(state_dir, DIR_LIST_PLAIN, NULL,
|
||||
@@ -1163,7 +1288,7 @@ void command_event_set_savestate_auto_index(
|
||||
if (!dir_list)
|
||||
return;
|
||||
|
||||
fill_pathname_base(state_base, global->name.savestate,
|
||||
fill_pathname_base(state_base, runloop_st->name.savestate,
|
||||
sizeof(state_base));
|
||||
|
||||
for (i = 0; i < dir_list->size; i++)
|
||||
@@ -1191,13 +1316,12 @@ void command_event_set_savestate_auto_index(
|
||||
|
||||
configuration_set_int(settings, settings->ints.state_slot, max_idx);
|
||||
|
||||
RARCH_LOG("%s: #%d\n",
|
||||
RARCH_LOG("[State]: %s: #%d\n",
|
||||
msg_hash_to_str(MSG_FOUND_LAST_STATE_SLOT),
|
||||
max_idx);
|
||||
}
|
||||
|
||||
void command_event_set_savestate_garbage_collect(
|
||||
const global_t *global,
|
||||
unsigned max_to_keep,
|
||||
bool show_hidden_files
|
||||
)
|
||||
@@ -1205,6 +1329,7 @@ void command_event_set_savestate_garbage_collect(
|
||||
size_t i, cnt = 0;
|
||||
char state_dir[PATH_MAX_LENGTH];
|
||||
char state_base[PATH_MAX_LENGTH];
|
||||
runloop_state_t *runloop_st = runloop_state_get_ptr();
|
||||
|
||||
struct string_list *dir_list = NULL;
|
||||
unsigned min_idx = UINT_MAX;
|
||||
@@ -1215,7 +1340,7 @@ void command_event_set_savestate_garbage_collect(
|
||||
|
||||
/* Similar to command_event_set_savestate_auto_index(),
|
||||
* this will find the lowest numbered save-state */
|
||||
fill_pathname_basedir(state_dir, global->name.savestate,
|
||||
fill_pathname_basedir(state_dir, runloop_st->name.savestate,
|
||||
sizeof(state_dir));
|
||||
|
||||
dir_list = dir_list_new_special(state_dir, DIR_LIST_PLAIN, NULL,
|
||||
@@ -1224,7 +1349,7 @@ void command_event_set_savestate_garbage_collect(
|
||||
if (!dir_list)
|
||||
return;
|
||||
|
||||
fill_pathname_base(state_base, global->name.savestate,
|
||||
fill_pathname_base(state_base, runloop_st->name.savestate,
|
||||
sizeof(state_base));
|
||||
|
||||
for (i = 0; i < dir_list->size; i++)
|
||||
@@ -1349,7 +1474,7 @@ bool command_event_save_core_config(
|
||||
if (path_is_valid(core_path))
|
||||
{
|
||||
unsigned i;
|
||||
RARCH_LOG("%s\n", msg_hash_to_str(MSG_USING_CORE_NAME_FOR_NEW_CONFIG));
|
||||
RARCH_LOG("[Config]: %s\n", msg_hash_to_str(MSG_USING_CORE_NAME_FOR_NEW_CONFIG));
|
||||
|
||||
/* In case of collision, find an alternative name. */
|
||||
for (i = 0; i < 16; i++)
|
||||
@@ -1453,7 +1578,7 @@ void command_event_save_current_config(enum override_type type)
|
||||
}
|
||||
else
|
||||
strlcpy(msg, msg_hash_to_str(MSG_OVERRIDES_ERROR_SAVING), sizeof(msg));
|
||||
RARCH_LOG("[Config - Overrides]: %s\n", msg);
|
||||
RARCH_LOG("[Overrides]: %s\n", msg);
|
||||
runloop_msg_queue_push(msg, 1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
}
|
||||
break;
|
||||
@@ -1466,18 +1591,23 @@ bool command_event_main_state(unsigned cmd)
|
||||
retro_ctx_size_info_t info;
|
||||
char msg[128];
|
||||
char state_path[16384];
|
||||
const global_t *global = global_get_ptr();
|
||||
settings_t *settings = config_get_ptr();
|
||||
bool savestates_enabled = core_info_current_supports_savestate();
|
||||
bool ret = false;
|
||||
bool push_msg = true;
|
||||
|
||||
state_path[0] = msg[0] = '\0';
|
||||
|
||||
retroarch_get_current_savestate_path(state_path, sizeof(state_path));
|
||||
if (savestates_enabled)
|
||||
{
|
||||
retroarch_get_current_savestate_path(state_path,
|
||||
sizeof(state_path));
|
||||
|
||||
core_serialize_size(&info);
|
||||
core_serialize_size(&info);
|
||||
savestates_enabled = (info.size > 0);
|
||||
}
|
||||
|
||||
if (info.size)
|
||||
if (savestates_enabled)
|
||||
{
|
||||
switch (cmd)
|
||||
{
|
||||
@@ -1500,7 +1630,7 @@ bool command_event_main_state(unsigned cmd)
|
||||
|
||||
/* Clean up excess savestates if necessary */
|
||||
if (savestate_auto_index && (savestate_max_keep > 0))
|
||||
command_event_set_savestate_garbage_collect(global,
|
||||
command_event_set_savestate_garbage_collect(
|
||||
settings->uints.savestate_max_keep,
|
||||
settings->bools.show_hidden_files
|
||||
);
|
||||
@@ -1565,7 +1695,7 @@ bool command_event_main_state(unsigned cmd)
|
||||
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||
|
||||
if (!string_is_empty(msg))
|
||||
RARCH_LOG("%s\n", msg);
|
||||
RARCH_LOG("[State]: %s\n", msg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -74,6 +74,7 @@ enum event_command
|
||||
CMD_EVENT_RESET,
|
||||
CMD_EVENT_SET_PER_GAME_RESOLUTION,
|
||||
CMD_EVENT_SET_FRAME_LIMIT,
|
||||
CMD_EVENT_VRR_RUNLOOP_TOGGLE,
|
||||
/* Loads core. */
|
||||
CMD_EVENT_LOAD_CORE,
|
||||
CMD_EVENT_LOAD_CORE_PERSIST,
|
||||
@@ -119,6 +120,10 @@ enum event_command
|
||||
CMD_EVENT_AUDIO_MUTE_TOGGLE,
|
||||
/* Toggles FPS counter. */
|
||||
CMD_EVENT_FPS_TOGGLE,
|
||||
/* Toggles statistics display. */
|
||||
CMD_EVENT_STATISTICS_TOGGLE,
|
||||
/* Toggle ping counter. */
|
||||
CMD_EVENT_NETPLAY_PING_TOGGLE,
|
||||
/* Gathers diagnostic info about the system and RetroArch configuration, then sends it to our servers. */
|
||||
CMD_EVENT_SEND_DEBUG_INFO,
|
||||
/* Toggles netplay hosting. */
|
||||
@@ -202,6 +207,10 @@ enum event_command
|
||||
CMD_EVENT_NETPLAY_DEINIT,
|
||||
/* Switch between netplay gaming and watching. */
|
||||
CMD_EVENT_NETPLAY_GAME_WATCH,
|
||||
/* Open a netplay chat input menu. */
|
||||
CMD_EVENT_NETPLAY_PLAYER_CHAT,
|
||||
/* Toggle chat fading. */
|
||||
CMD_EVENT_NETPLAY_FADE_CHAT_TOGGLE,
|
||||
/* Start hosting netplay. */
|
||||
CMD_EVENT_NETPLAY_ENABLE_HOST,
|
||||
/* Disconnect from the netplay host. */
|
||||
@@ -339,7 +348,6 @@ bool command_event_resize_windowed_scale(settings_t *settings,
|
||||
|
||||
bool command_event_save_auto_state(
|
||||
bool savestate_auto_save,
|
||||
global_t *global,
|
||||
const enum rarch_core_type current_core_type);
|
||||
|
||||
/**
|
||||
@@ -363,14 +371,14 @@ void command_event_set_volume(
|
||||
void command_event_init_controllers(rarch_system_info_t *info,
|
||||
settings_t *settings, unsigned num_active_users);
|
||||
|
||||
void command_event_load_auto_state(global_t *global);
|
||||
bool command_event_load_entry_state(void);
|
||||
|
||||
void command_event_load_auto_state(void);
|
||||
|
||||
void command_event_set_savestate_auto_index(
|
||||
settings_t *settings,
|
||||
const global_t *global);
|
||||
settings_t *settings);
|
||||
|
||||
void command_event_set_savestate_garbage_collect(
|
||||
const global_t *global,
|
||||
unsigned max_to_keep,
|
||||
bool show_hidden_files
|
||||
);
|
||||
@@ -435,6 +443,7 @@ static const struct cmd_map map[] = {
|
||||
{ "FAST_FORWARD_HOLD", RARCH_FAST_FORWARD_HOLD_KEY },
|
||||
{ "SLOWMOTION", RARCH_SLOWMOTION_KEY },
|
||||
{ "SLOWMOTION_HOLD", RARCH_SLOWMOTION_HOLD_KEY },
|
||||
{ "VRR_RUNLOOP_TOGGLE", RARCH_VRR_RUNLOOP_TOGGLE },
|
||||
{ "LOAD_STATE", RARCH_LOAD_STATE_KEY },
|
||||
{ "SAVE_STATE", RARCH_SAVE_STATE_KEY },
|
||||
{ "FULLSCREEN_TOGGLE", RARCH_FULLSCREEN_TOGGLE_KEY },
|
||||
@@ -456,6 +465,7 @@ static const struct cmd_map map[] = {
|
||||
{ "MUTE", RARCH_MUTE },
|
||||
{ "OSK", RARCH_OSK },
|
||||
{ "FPS_TOGGLE", RARCH_FPS_TOGGLE },
|
||||
{ "STATISTICS_TOGGLE", RARCH_STATISTICS_TOGGLE },
|
||||
{ "SEND_DEBUG_INFO", RARCH_SEND_DEBUG_INFO },
|
||||
{ "NETPLAY_HOST_TOGGLE", RARCH_NETPLAY_HOST_TOGGLE },
|
||||
{ "NETPLAY_GAME_WATCH", RARCH_NETPLAY_GAME_WATCH },
|
||||
|
||||
+51
-6
@@ -173,6 +173,8 @@
|
||||
|
||||
#define DEFAULT_USER_LANGUAGE 0
|
||||
|
||||
#define DEFAULT_GAMEMODE_ENABLE true
|
||||
|
||||
#if (defined(_WIN32) && !defined(_XBOX)) || (defined(__linux) && !defined(ANDROID) && !defined(HAVE_LAKKA)) || (defined(__MACH__) && !defined(IOS)) || defined(EMSCRIPTEN)
|
||||
#define DEFAULT_MOUSE_ENABLE true
|
||||
#else
|
||||
@@ -495,6 +497,8 @@
|
||||
/* Initialise file browser with the last used start directory */
|
||||
#define DEFAULT_USE_LAST_START_DIRECTORY false
|
||||
|
||||
#define DEFAULT_OVERLAY_BEHIND_MENU false
|
||||
|
||||
#define DEFAULT_OVERLAY_HIDE_IN_MENU true
|
||||
|
||||
/* Automatically disable overlays when a
|
||||
@@ -554,6 +558,7 @@
|
||||
#define DEFAULT_OZONE_TRUNCATE_PLAYLIST_NAME true
|
||||
#define DEFAULT_OZONE_SORT_AFTER_TRUNCATE_PLAYLIST_NAME true
|
||||
#define DEFAULT_OZONE_SCROLL_CONTENT_METADATA false
|
||||
#define DEFAULT_OZONE_THUMBNAIL_SCALE_FACTOR 1.0f
|
||||
#endif
|
||||
|
||||
#define DEFAULT_SETTINGS_SHOW_DRIVERS true
|
||||
@@ -646,6 +651,9 @@ static const bool menu_show_load_content = true;
|
||||
#ifdef HAVE_CDROM
|
||||
static const bool menu_show_load_disc = true;
|
||||
static const bool menu_show_dump_disc = true;
|
||||
#ifdef HAVE_LAKKA
|
||||
static const bool menu_show_eject_disc = true;
|
||||
#endif /* HAVE_LAKKA */
|
||||
#endif
|
||||
static const bool menu_show_information = true;
|
||||
static const bool menu_show_configurations = true;
|
||||
@@ -659,6 +667,9 @@ static const bool menu_show_core_updater = false;
|
||||
#else
|
||||
static const bool menu_show_core_updater = true;
|
||||
#endif
|
||||
#ifdef HAVE_MIST
|
||||
static const bool menu_show_core_manager_steam = true;
|
||||
#endif
|
||||
static const bool menu_show_legacy_thumbnail_updater = false;
|
||||
static const bool menu_show_sublabels = true;
|
||||
static const bool menu_dynamic_wallpaper_enable = true;
|
||||
@@ -723,9 +734,12 @@ static const bool content_show_playlists = true;
|
||||
#if defined(HAVE_LIBRETRODB)
|
||||
#define DEFAULT_MENU_CONTENT_SHOW_EXPLORE true
|
||||
#endif
|
||||
#define DEFAULT_MENU_CONTENT_SHOW_CONTENTLESS_CORES MENU_CONTENTLESS_CORES_DISPLAY_SINGLE_PURPOSE
|
||||
|
||||
#ifdef HAVE_XMB
|
||||
#define DEFAULT_XMB_ANIMATION 0
|
||||
#define DEFAULT_XMB_VERTICAL_FADE_FACTOR 100
|
||||
#define DEFAULT_XMB_TITLE_MARGIN 5
|
||||
|
||||
static const unsigned xmb_alpha_factor = 75;
|
||||
static const unsigned menu_font_color_red = 255;
|
||||
@@ -754,7 +768,7 @@ static const float menu_footer_opacity = 1.000;
|
||||
|
||||
static const float menu_header_opacity = 1.000;
|
||||
|
||||
#if defined(HAVE_OPENGLES2) || (defined(__MACH__) && (defined(__ppc__) || defined(__ppc64__)))
|
||||
#if defined(HAVE_OPENGLES2) || (defined(__MACH__) && defined(MAC_OS_X_VERSION_MAX_ALLOWED) && (MAC_OS_X_VERSION_MAX_ALLOWED < 101200))
|
||||
#define DEFAULT_MENU_SHADER_PIPELINE 1
|
||||
#else
|
||||
#define DEFAULT_MENU_SHADER_PIPELINE 2
|
||||
@@ -842,7 +856,7 @@ static const unsigned input_backtouch_toggle = false;
|
||||
|
||||
#define DEFAULT_OVERLAY_SHOW_INPUTS_PORT 0
|
||||
|
||||
#if defined(ANDROID) || defined(_WIN32)
|
||||
#if defined(ANDROID) || defined(_WIN32) || defined(HAVE_STEAM)
|
||||
#define DEFAULT_MENU_SWAP_OK_CANCEL_BUTTONS true
|
||||
#else
|
||||
#define DEFAULT_MENU_SWAP_OK_CANCEL_BUTTONS false
|
||||
@@ -936,12 +950,20 @@ static const float message_bgcolor_opacity = 1.0f;
|
||||
#define DEFAULT_ALLOW_ROTATE true
|
||||
|
||||
#if defined(_3DS)
|
||||
/* Enable New3DS clock and L2 cache */
|
||||
static const bool new3ds_speedup_enable = true;
|
||||
/* Enable bottom LCD screen */
|
||||
static const bool video_3ds_lcd_bottom = true;
|
||||
static const bool video_3ds_lcd_bottom = true;
|
||||
/* Sets video display mode (3D, 2D, etc.) */
|
||||
static const unsigned video_3ds_display_mode = CTR_VIDEO_MODE_3D;
|
||||
#endif
|
||||
|
||||
#ifdef WIIU
|
||||
/* On Wii U, whether to optimize for the native TV resolution
|
||||
* or exactly 2x the Wii U GamePad resolution. */
|
||||
#define DEFAULT_WIIU_PREFER_DRC false
|
||||
#endif
|
||||
|
||||
/* AUDIO */
|
||||
|
||||
/* Will enable audio or not. */
|
||||
@@ -1024,6 +1046,10 @@ static const bool audio_enable_menu_bgm = false;
|
||||
#define DEFAULT_NOTIFICATION_SHOW_NETPLAY_EXTRA false
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
#define DEFAULT_NOTIFICATION_SHOW_WHEN_MENU_IS_ALIVE false
|
||||
#endif
|
||||
|
||||
/* Output samplerate. */
|
||||
#ifdef GEKKO
|
||||
#define DEFAULT_OUTPUT_RATE 32000
|
||||
@@ -1101,6 +1127,9 @@ static const bool audio_enable_menu_bgm = false;
|
||||
/* Enables displaying various timing statistics. */
|
||||
#define DEFAULT_STATISTICS_SHOW false
|
||||
|
||||
/* Enables displaying the current netplay room ping. */
|
||||
#define DEFAULT_NETPLAY_PING_SHOW false
|
||||
|
||||
/* Enables use of rewind. This will incur some memory footprint
|
||||
* depending on the save state buffer. */
|
||||
#define DEFAULT_REWIND_ENABLE false
|
||||
@@ -1129,7 +1158,7 @@ static const bool audio_enable_menu_bgm = false;
|
||||
#define DEFAULT_REWIND_GRANULARITY 1
|
||||
#endif
|
||||
/* Pause gameplay when gameplay loses focus. */
|
||||
#if defined(EMSCRIPTEN) || defined(WEBOS)
|
||||
#if defined(EMSCRIPTEN)
|
||||
#define DEFAULT_PAUSE_NONACTIVE false
|
||||
#else
|
||||
#define DEFAULT_PAUSE_NONACTIVE true
|
||||
@@ -1145,12 +1174,21 @@ static const bool audio_enable_menu_bgm = false;
|
||||
#define DEFAULT_AUTOSAVE_INTERVAL 0
|
||||
#endif
|
||||
|
||||
/* Show only connectable rooms */
|
||||
#define DEFAULT_NETPLAY_SHOW_ONLY_CONNECTABLE true
|
||||
|
||||
/* Publicly announce netplay */
|
||||
#define DEFAULT_NETPLAY_PUBLIC_ANNOUNCE true
|
||||
|
||||
/* Start netplay in spectator mode */
|
||||
static const bool netplay_start_as_spectator = false;
|
||||
|
||||
/* Netplay chat fading toggle */
|
||||
static const bool netplay_fade_chat = true;
|
||||
|
||||
/* Allow players to pause */
|
||||
static const bool netplay_allow_pausing = false;
|
||||
|
||||
/* Allow connections in slave mode */
|
||||
static const bool netplay_allow_slaves = true;
|
||||
|
||||
@@ -1176,9 +1214,10 @@ static const bool netplay_use_mitm_server = false;
|
||||
|
||||
#ifdef HAVE_NETWORKING
|
||||
static const unsigned netplay_max_connections = 3;
|
||||
static const unsigned netplay_share_digital = RARCH_NETPLAY_SHARE_DIGITAL_NO_PREFERENCE;
|
||||
static const unsigned netplay_max_ping = 0;
|
||||
|
||||
static const unsigned netplay_share_analog = RARCH_NETPLAY_SHARE_ANALOG_NO_PREFERENCE;
|
||||
static const unsigned netplay_share_digital = RARCH_NETPLAY_SHARE_DIGITAL_NO_PREFERENCE;
|
||||
static const unsigned netplay_share_analog = RARCH_NETPLAY_SHARE_ANALOG_NO_PREFERENCE;
|
||||
#endif
|
||||
|
||||
/* On save state load, block SRAM from being overwritten.
|
||||
@@ -1227,6 +1266,10 @@ static const bool savestate_thumbnail_enable = false;
|
||||
|
||||
/* Maximum fast forward ratio. */
|
||||
#define DEFAULT_FASTFORWARD_RATIO 0.0
|
||||
#define MAXIMUM_FASTFORWARD_RATIO 50.0
|
||||
|
||||
/* Skip frames when fast forwarding. */
|
||||
#define DEFAULT_FASTFORWARD_FRAMESKIP true
|
||||
|
||||
/* Enable runloop for variable refresh rate screens. Force x1 speed while handling fast forward too. */
|
||||
#define DEFAULT_VRR_RUNLOOP_ENABLE false
|
||||
@@ -1309,6 +1352,8 @@ static const int default_content_favorites_size = 200;
|
||||
#define DEFAULT_PLAYLIST_SHOW_SUBLABELS true
|
||||
#endif
|
||||
|
||||
#define DEFAULT_PLAYLIST_SHOW_HISTORY_ICONS PLAYLIST_SHOW_HISTORY_ICONS_DEFAULT
|
||||
|
||||
/* Show the indices of playlist entries in
|
||||
* a menu-driver-specific fashion */
|
||||
#define DEFAULT_PLAYLIST_SHOW_ENTRY_IDX true
|
||||
|
||||
@@ -304,6 +304,13 @@ static const struct retro_keybind retro_keybinds_1[] = {
|
||||
RARCH_SLOWMOTION_HOLD_KEY, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_VRR_RUNLOOP_TOGGLE, RETROK_UNKNOWN,
|
||||
RARCH_VRR_RUNLOOP_TOGGLE, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
@@ -451,6 +458,20 @@ static const struct retro_keybind retro_keybinds_1[] = {
|
||||
RARCH_FPS_TOGGLE, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_STATISTICS_TOGGLE, RETROK_UNKNOWN,
|
||||
RARCH_STATISTICS_TOGGLE, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_PING_TOGGLE, RETROK_UNKNOWN,
|
||||
RARCH_NETPLAY_PING_TOGGLE, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
@@ -472,6 +493,20 @@ static const struct retro_keybind retro_keybinds_1[] = {
|
||||
RARCH_NETPLAY_GAME_WATCH, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_PLAYER_CHAT, RETROK_UNKNOWN,
|
||||
RARCH_NETPLAY_PLAYER_CHAT, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FADE_CHAT_TOGGLE, RETROK_UNKNOWN,
|
||||
RARCH_NETPLAY_FADE_CHAT_TOGGLE, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
@@ -858,6 +893,13 @@ static const struct retro_keybind retro_keybinds_1[] = {
|
||||
RARCH_SLOWMOTION_HOLD_KEY, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_VRR_RUNLOOP_TOGGLE, RETROK_UNKNOWN,
|
||||
RARCH_VRR_RUNLOOP_TOGGLE, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
@@ -1005,6 +1047,20 @@ static const struct retro_keybind retro_keybinds_1[] = {
|
||||
RARCH_FPS_TOGGLE, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_STATISTICS_TOGGLE, RETROK_UNKNOWN,
|
||||
RARCH_STATISTICS_TOGGLE, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_PING_TOGGLE, RETROK_UNKNOWN,
|
||||
RARCH_NETPLAY_PING_TOGGLE, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
@@ -1026,6 +1082,20 @@ static const struct retro_keybind retro_keybinds_1[] = {
|
||||
RARCH_NETPLAY_GAME_WATCH, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_PLAYER_CHAT, RETROK_UNKNOWN,
|
||||
RARCH_NETPLAY_PLAYER_CHAT, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FADE_CHAT_TOGGLE, RETROK_UNKNOWN,
|
||||
RARCH_NETPLAY_FADE_CHAT_TOGGLE, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
@@ -1412,6 +1482,13 @@ static const struct retro_keybind retro_keybinds_1[] = {
|
||||
RARCH_SLOWMOTION_HOLD_KEY, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_VRR_RUNLOOP_TOGGLE, RETROK_UNKNOWN,
|
||||
RARCH_VRR_RUNLOOP_TOGGLE, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
@@ -1569,6 +1646,20 @@ static const struct retro_keybind retro_keybinds_1[] = {
|
||||
RARCH_FPS_TOGGLE, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_STATISTICS_TOGGLE, RETROK_UNKNOWN,
|
||||
RARCH_STATISTICS_TOGGLE, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_PING_TOGGLE, RETROK_UNKNOWN,
|
||||
RARCH_NETPLAY_PING_TOGGLE, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
@@ -1590,6 +1681,20 @@ static const struct retro_keybind retro_keybinds_1[] = {
|
||||
RARCH_NETPLAY_GAME_WATCH, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_PLAYER_CHAT, RETROK_BACKQUOTE,
|
||||
RARCH_NETPLAY_PLAYER_CHAT, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FADE_CHAT_TOGGLE, RETROK_UNKNOWN,
|
||||
RARCH_NETPLAY_FADE_CHAT_TOGGLE, NO_BTN, NO_BTN, 0,
|
||||
true
|
||||
},
|
||||
{
|
||||
NULL, NULL,
|
||||
AXIS_NONE, AXIS_NONE, AXIS_NONE,
|
||||
|
||||
@@ -302,12 +302,6 @@
|
||||
#define SUPPORTS_NETPLAY false
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
#define SUPPORTS_PYTHON true
|
||||
#else
|
||||
#define SUPPORTS_PYTHON false
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH) || defined(HAVE_COCOA_METAL)
|
||||
#define SUPPORTS_COCOA true
|
||||
#else
|
||||
|
||||
+336
-260
File diff suppressed because it is too large.
Load diff
+32
-4
@@ -156,8 +156,7 @@ typedef struct settings
|
||||
unsigned input_joypad_index[MAX_USERS];
|
||||
unsigned input_device[MAX_USERS];
|
||||
unsigned input_mouse_index[MAX_USERS];
|
||||
/* Set by autoconfiguration in joypad_autoconfig_dir.
|
||||
* Does not override main binds. */
|
||||
|
||||
unsigned input_libretro_device[MAX_USERS];
|
||||
unsigned input_analog_dpad_mode[MAX_USERS];
|
||||
|
||||
@@ -201,6 +200,7 @@ typedef struct settings
|
||||
|
||||
unsigned netplay_port;
|
||||
unsigned netplay_max_connections;
|
||||
unsigned netplay_max_ping;
|
||||
unsigned netplay_input_latency_frames_min;
|
||||
unsigned netplay_input_latency_frames_range;
|
||||
unsigned netplay_share_digital;
|
||||
@@ -277,6 +277,8 @@ typedef struct settings
|
||||
unsigned menu_xmb_theme;
|
||||
unsigned menu_xmb_color_theme;
|
||||
unsigned menu_xmb_thumbnail_scale_factor;
|
||||
unsigned menu_xmb_vertical_fade_factor;
|
||||
unsigned menu_xmb_title_margin;
|
||||
unsigned menu_materialui_color_theme;
|
||||
unsigned menu_materialui_transition_animation;
|
||||
unsigned menu_materialui_thumbnail_view_portrait;
|
||||
@@ -293,11 +295,13 @@ typedef struct settings
|
||||
unsigned menu_ticker_type;
|
||||
unsigned menu_scroll_delay;
|
||||
unsigned menu_content_show_add_entry;
|
||||
unsigned menu_content_show_contentless_cores;
|
||||
unsigned menu_screensaver_timeout;
|
||||
unsigned menu_screensaver_animation;
|
||||
|
||||
unsigned playlist_entry_remove_enable;
|
||||
unsigned playlist_show_inline_core_name;
|
||||
unsigned playlist_show_history_icons;
|
||||
unsigned playlist_sublabel_runtime_type;
|
||||
unsigned playlist_sublabel_last_played_style;
|
||||
|
||||
@@ -365,6 +369,7 @@ typedef struct settings
|
||||
float menu_ticker_speed;
|
||||
float menu_rgui_particle_effect_speed;
|
||||
float menu_screensaver_animation_speed;
|
||||
float ozone_thumbnail_scale_factor;
|
||||
|
||||
float audio_max_timing_skew;
|
||||
float audio_volume; /* dB scale. */
|
||||
@@ -409,6 +414,7 @@ typedef struct settings
|
||||
char cheevos_password[256];
|
||||
char cheevos_token[32];
|
||||
char cheevos_leaderboards_enable[32];
|
||||
char cheevos_custom_host[64];
|
||||
char video_context_driver[32];
|
||||
char audio_driver[32];
|
||||
char audio_resampler[32];
|
||||
@@ -453,6 +459,7 @@ typedef struct settings
|
||||
char netplay_spectate_password[128];
|
||||
|
||||
char netplay_server[255];
|
||||
char netplay_custom_mitm_server[255];
|
||||
char network_buildbot_url[255];
|
||||
char network_buildbot_assets_url[255];
|
||||
|
||||
@@ -559,6 +566,7 @@ typedef struct settings
|
||||
bool video_memory_show;
|
||||
bool video_msg_bgcolor_enable;
|
||||
bool video_3ds_lcd_bottom;
|
||||
bool video_wiiu_prefer_drc;
|
||||
bool video_notch_write_over_enable;
|
||||
#ifdef HAVE_VIDEO_LAYOUT
|
||||
bool video_layout_enable;
|
||||
@@ -588,6 +596,7 @@ typedef struct settings
|
||||
bool input_sensors_enable;
|
||||
bool input_overlay_enable;
|
||||
bool input_overlay_enable_autopreferred;
|
||||
bool input_overlay_behind_menu;
|
||||
bool input_overlay_hide_in_menu;
|
||||
bool input_overlay_hide_when_gamepad_connected;
|
||||
bool input_overlay_show_mouse_cursor;
|
||||
@@ -627,6 +636,9 @@ typedef struct settings
|
||||
#endif
|
||||
bool notification_show_refresh_rate;
|
||||
bool notification_show_netplay_extra;
|
||||
#ifdef HAVE_MENU
|
||||
bool notification_show_when_menu_is_alive;
|
||||
#endif
|
||||
bool menu_widget_scale_auto;
|
||||
bool menu_show_start_screen;
|
||||
bool menu_pause_libretro;
|
||||
@@ -648,11 +660,17 @@ typedef struct settings
|
||||
bool menu_horizontal_animation;
|
||||
bool menu_scroll_fast;
|
||||
bool menu_show_online_updater;
|
||||
#ifdef HAVE_MIST
|
||||
bool menu_show_core_manager_steam;
|
||||
#endif
|
||||
bool menu_show_core_updater;
|
||||
bool menu_show_load_core;
|
||||
bool menu_show_load_content;
|
||||
bool menu_show_load_disc;
|
||||
bool menu_show_dump_disc;
|
||||
#ifdef HAVE_LAKKA
|
||||
bool menu_show_eject_disc;
|
||||
#endif
|
||||
bool menu_show_information;
|
||||
bool menu_show_configurations;
|
||||
bool menu_show_help;
|
||||
@@ -751,14 +769,18 @@ typedef struct settings
|
||||
bool crt_switch_hires_menu;
|
||||
|
||||
/* Netplay */
|
||||
bool netplay_show_only_connectable;
|
||||
bool netplay_public_announce;
|
||||
bool netplay_start_as_spectator;
|
||||
bool netplay_fade_chat;
|
||||
bool netplay_allow_pausing;
|
||||
bool netplay_allow_slaves;
|
||||
bool netplay_require_slaves;
|
||||
bool netplay_stateless_mode;
|
||||
bool netplay_nat_traversal;
|
||||
bool netplay_use_mitm_server;
|
||||
bool netplay_request_devices[MAX_USERS];
|
||||
bool netplay_ping_show;
|
||||
|
||||
/* Network */
|
||||
bool network_buildbot_auto_extract_archive;
|
||||
@@ -818,6 +840,7 @@ typedef struct settings
|
||||
bool history_list_enable;
|
||||
bool playlist_entry_rename;
|
||||
bool rewind_enable;
|
||||
bool fastforward_frameskip;
|
||||
bool vrr_runloop_enable;
|
||||
bool apply_cheats_after_toggle;
|
||||
bool apply_cheats_after_load;
|
||||
@@ -900,6 +923,11 @@ typedef struct settings
|
||||
|
||||
bool ai_service_enable;
|
||||
bool ai_service_pause;
|
||||
|
||||
bool gamemode_enable;
|
||||
#ifdef _3DS
|
||||
bool new3ds_speedup_enable;
|
||||
#endif
|
||||
} bools;
|
||||
|
||||
} settings_t;
|
||||
@@ -1083,9 +1111,9 @@ void config_load_file_salamander(void);
|
||||
void config_save_file_salamander(void);
|
||||
#endif
|
||||
|
||||
void config_init(void);
|
||||
void rarch_config_init(void);
|
||||
|
||||
void config_deinit(void);
|
||||
void rarch_config_deinit(void);
|
||||
|
||||
settings_t *config_get_ptr(void);
|
||||
|
||||
|
||||
@@ -27,10 +27,6 @@
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
#ifdef HAVE_REWIND
|
||||
bool core_set_rewind_callbacks(void);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETWORKING
|
||||
bool core_set_netplay_callbacks(void);
|
||||
|
||||
|
||||
+623
-190
File diff suppressed because it is too large.
Load diff
+46
@@ -25,6 +25,23 @@
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
/* Defines the levels of savestate support
|
||||
* that may be offered by a core:
|
||||
* - serialized: rewind
|
||||
* - deterministic: netplay/runahead
|
||||
* Thus:
|
||||
* (level < CORE_INFO_SAVESTATE_BASIC)
|
||||
* -> no savestate support
|
||||
* (level < CORE_INFO_SAVESTATE_SERIALIZED)
|
||||
* -> no rewind/netplay/runahead
|
||||
* (level < CORE_INFO_SAVESTATE_DETERMINISTIC)
|
||||
* -> no netplay/runahead
|
||||
*/
|
||||
#define CORE_INFO_SAVESTATE_DISABLED 0
|
||||
#define CORE_INFO_SAVESTATE_BASIC 1
|
||||
#define CORE_INFO_SAVESTATE_SERIALIZED 2
|
||||
#define CORE_INFO_SAVESTATE_DETERMINISTIC 3
|
||||
|
||||
enum core_info_list_qsort_type
|
||||
{
|
||||
CORE_INFO_LIST_SORT_PATH = 0,
|
||||
@@ -84,11 +101,14 @@ typedef struct
|
||||
core_info_firmware_t *firmware;
|
||||
core_file_id_t core_file_id; /* ptr alignment */
|
||||
size_t firmware_count;
|
||||
uint32_t savestate_support_level;
|
||||
bool has_info;
|
||||
bool supports_no_game;
|
||||
bool single_purpose;
|
||||
bool database_match_archive_member;
|
||||
bool is_experimental;
|
||||
bool is_locked;
|
||||
bool is_standalone_exempt;
|
||||
bool is_installed;
|
||||
} core_info_t;
|
||||
|
||||
@@ -184,6 +204,16 @@ bool core_info_list_get_info(core_info_list_t *core_info_list,
|
||||
|
||||
bool core_info_hw_api_supported(core_info_t *info);
|
||||
|
||||
/* Convenience wrapper functions used to interpret
|
||||
* the 'savestate_support_level' parameter of
|
||||
* the currently loaded core. If no core is
|
||||
* loaded, will return 'true' (since full
|
||||
* savestate functionality is assumed by default) */
|
||||
bool core_info_current_supports_savestate(void);
|
||||
bool core_info_current_supports_rewind(void);
|
||||
bool core_info_current_supports_netplay(void);
|
||||
bool core_info_current_supports_runahead(void);
|
||||
|
||||
/* Sets 'locked' status of specified core
|
||||
* > Returns true if successful
|
||||
* > Like all functions that access the cached
|
||||
@@ -200,6 +230,22 @@ bool core_info_set_core_lock(const char *core_path, bool lock);
|
||||
* must be checked externally */
|
||||
bool core_info_get_core_lock(const char *core_path, bool validate_path);
|
||||
|
||||
/* Sets 'standalone exempt' status of specified core
|
||||
* > A 'standalone exempt' core will not be shown
|
||||
* in the contentless cores menu when display type
|
||||
* is set to 'custom'
|
||||
* > Returns true if successful
|
||||
* > Returns false if core does not support
|
||||
* contentless operation
|
||||
* > *Not* thread safe */
|
||||
bool core_info_set_core_standalone_exempt(const char *core_path, bool exempt);
|
||||
/* Fetches 'standalone exempt' status of specified core
|
||||
* > Returns true if core should be excluded from
|
||||
* the contentless cores menu when display type is
|
||||
* set to 'custom'
|
||||
* > *Not* thread safe */
|
||||
bool core_info_get_core_standalone_exempt(const char *core_path);
|
||||
|
||||
bool core_info_core_file_id_is_equal(const char *core_path_a, const char *core_path_b);
|
||||
|
||||
/* When called, generates a temporary file
|
||||
|
||||
@@ -737,7 +737,7 @@ static bool core_option_manager_parse_variable(
|
||||
value, NULL);
|
||||
|
||||
/* Set value hash */
|
||||
*value_hash = core_option_manager_hash_string(value);
|
||||
*value_hash = core_option_manager_hash_string(value);
|
||||
option->vals->elems[i].userdata = (void*)value_hash;
|
||||
|
||||
/* Redundant safely check... */
|
||||
|
||||
@@ -34,13 +34,13 @@ static uint16_t *dummy_frame_buf;
|
||||
static uint16_t frame_buf_width;
|
||||
static uint16_t frame_buf_height;
|
||||
|
||||
#if defined(HAVE_LIBNX) && defined(HAVE_STATIC_DUMMY)
|
||||
#if defined(HAVE_STATIC_DUMMY)
|
||||
void retro_init(void) { libretro_dummy_retro_init(); }
|
||||
void retro_deinit(void) { libretro_dummy_retro_deinit(); }
|
||||
unsigned retro_api_version(void) { return libretro_dummy_retro_api_version(); }
|
||||
void retro_set_controller_port_device(unsigned port, unsigned device) { libretro_dummy_retro_set_controller_port_device(port, device); }
|
||||
void retro_get_system_info(struct retro_system_info *info) { libretro_dummy_retro_get_system_info(info); }
|
||||
void retro_get_system_av_info(struct retro_system_av_info *info) { retro_get_system_av_info(info); }
|
||||
void retro_get_system_av_info(struct retro_system_av_info *info) { libretro_dummy_retro_get_system_av_info(info); }
|
||||
void retro_set_environment(retro_environment_t cb) { libretro_dummy_retro_set_environment(cb); }
|
||||
void retro_set_audio_sample(retro_audio_sample_t cb) { libretro_dummy_retro_set_audio_sample(cb); }
|
||||
void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) { libretro_dummy_retro_set_audio_sample_batch(cb); }
|
||||
|
||||
@@ -360,62 +360,6 @@ size_t libretro_videoprocessor_retro_get_memory_size(unsigned id);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GONG
|
||||
/* Internal gong core. */
|
||||
|
||||
void libretro_gong_retro_init(void);
|
||||
|
||||
void libretro_gong_retro_deinit(void);
|
||||
|
||||
unsigned libretro_gong_retro_api_version(void);
|
||||
|
||||
void libretro_gong_retro_get_system_info(struct retro_system_info *info);
|
||||
|
||||
void libretro_gong_retro_get_system_av_info(struct retro_system_av_info *info);
|
||||
|
||||
void libretro_gong_retro_set_environment(retro_environment_t cb);
|
||||
|
||||
void libretro_gong_retro_set_video_refresh(retro_video_refresh_t cb);
|
||||
|
||||
void libretro_gong_retro_set_audio_sample(retro_audio_sample_t cb);
|
||||
|
||||
void libretro_gong_retro_set_audio_sample_batch(retro_audio_sample_batch_t cb);
|
||||
|
||||
void libretro_gong_retro_set_input_poll(retro_input_poll_t cb);
|
||||
|
||||
void libretro_gong_retro_set_input_state(retro_input_state_t cb);
|
||||
|
||||
void libretro_gong_retro_set_controller_port_device(unsigned port, unsigned device);
|
||||
|
||||
void libretro_gong_retro_reset(void);
|
||||
|
||||
void libretro_gong_retro_run(void);
|
||||
|
||||
size_t libretro_gong_retro_serialize_size(void);
|
||||
|
||||
bool libretro_gong_retro_serialize(void *data, size_t size);
|
||||
|
||||
bool libretro_gong_retro_unserialize(const void *data, size_t size);
|
||||
|
||||
void libretro_gong_retro_cheat_reset(void);
|
||||
|
||||
void libretro_gong_retro_cheat_set(unsigned index, bool enabled, const char *code);
|
||||
|
||||
bool libretro_gong_retro_load_game(const struct retro_game_info *game);
|
||||
|
||||
bool libretro_gong_retro_load_game_special(unsigned game_type,
|
||||
const struct retro_game_info *info, size_t num_info);
|
||||
|
||||
void libretro_gong_retro_unload_game(void);
|
||||
|
||||
unsigned libretro_gong_retro_get_region(void);
|
||||
|
||||
void *libretro_gong_retro_get_memory_data(unsigned id);
|
||||
|
||||
size_t libretro_gong_retro_get_memory_size(unsigned id);
|
||||
|
||||
#endif
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
@@ -96,11 +96,8 @@ static unsigned sw_sws_threads;
|
||||
static video_buffer_t *video_buffer;
|
||||
static tpool_t *tpool;
|
||||
|
||||
/* If libavutil is at least version 55 or higher,
|
||||
* and if libavcodec is at least version 57.80.100 or higher,
|
||||
* enable hardware acceleration */
|
||||
#define ENABLE_HW_ACCEL ((LIBAVUTIL_VERSION_MAJOR > 55) && ENABLE_HW_ACCEL_CHECK2())
|
||||
#define ENABLE_HW_ACCEL_CHECK2() ((LIBAVCODEC_VERSION_MAJOR == 57 && LIBAVCODEC_VERSION_MINOR >= 80 && LIBAVCODEC_VERSION_MICRO >= 100) || (LIBAVCODEC_VERSION_MAJOR > 57))
|
||||
#define FFMPEG3 ((LIBAVUTIL_VERSION_INT < (56, 6, 100)) || \
|
||||
(LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100)))
|
||||
|
||||
#if ENABLE_HW_ACCEL
|
||||
static enum AVHWDeviceType hw_decoder;
|
||||
@@ -240,7 +237,9 @@ void CORE_PREFIX(retro_init)(void)
|
||||
{
|
||||
reset_triggered = false;
|
||||
|
||||
#if FFMPEG3
|
||||
av_register_all();
|
||||
#endif
|
||||
|
||||
if (CORE_PREFIX(environ_cb)(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, NULL))
|
||||
libretro_supports_bitmasks = true;
|
||||
@@ -462,10 +461,12 @@ static void check_variables(bool firststart)
|
||||
hw_decoder = AV_HWDEVICE_TYPE_DRM;
|
||||
else if (string_is_equal(hw_var.value, "dxva2"))
|
||||
hw_decoder = AV_HWDEVICE_TYPE_DXVA2;
|
||||
#if !FFMPEG3
|
||||
else if (string_is_equal(hw_var.value, "mediacodec"))
|
||||
hw_decoder = AV_HWDEVICE_TYPE_MEDIACODEC;
|
||||
else if (string_is_equal(hw_var.value, "opencl"))
|
||||
hw_decoder = AV_HWDEVICE_TYPE_OPENCL;
|
||||
#endif
|
||||
else if (string_is_equal(hw_var.value, "qsv"))
|
||||
hw_decoder = AV_HWDEVICE_TYPE_QSV;
|
||||
else if (string_is_equal(hw_var.value, "vaapi"))
|
||||
@@ -988,8 +989,9 @@ static enum AVPixelFormat init_hw_decoder(struct AVCodecContext *ctx,
|
||||
{
|
||||
int ret = 0;
|
||||
enum AVPixelFormat decoder_pix_fmt = AV_PIX_FMT_NONE;
|
||||
struct AVCodec *codec = avcodec_find_decoder(fctx->streams[video_stream_index]->codec->codec_id);
|
||||
const AVCodec *codec = avcodec_find_decoder(fctx->streams[video_stream_index]->codecpar->codec_id);
|
||||
|
||||
#if !FFMPEG3
|
||||
for (int i = 0;; i++)
|
||||
{
|
||||
const AVCodecHWConfig *config = avcodec_get_hw_config(codec, i);
|
||||
@@ -1002,12 +1004,15 @@ static enum AVPixelFormat init_hw_decoder(struct AVCodecContext *ctx,
|
||||
if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX &&
|
||||
config->device_type == type)
|
||||
{
|
||||
enum AVPixelFormat device_pix_fmt = config->pix_fmt;
|
||||
#else
|
||||
enum AVPixelFormat device_pix_fmt =
|
||||
pix_fmts ? ctx->get_format(ctx, pix_fmts) : decoder_pix_fmt;
|
||||
#endif
|
||||
log_cb(RETRO_LOG_INFO, "[FFMPEG] Selected HW decoder %s.\n",
|
||||
av_hwdevice_get_type_name(type));
|
||||
log_cb(RETRO_LOG_INFO, "[FFMPEG] Selected HW pixel format %s.\n",
|
||||
av_get_pix_fmt_name(config->pix_fmt));
|
||||
|
||||
enum AVPixelFormat device_pix_fmt = config->pix_fmt;
|
||||
av_get_pix_fmt_name(device_pix_fmt));
|
||||
|
||||
if (pix_fmts != NULL)
|
||||
{
|
||||
@@ -1019,16 +1024,17 @@ static enum AVPixelFormat init_hw_decoder(struct AVCodecContext *ctx,
|
||||
goto exit;
|
||||
}
|
||||
log_cb(RETRO_LOG_ERROR, "[FFMPEG] Codec %s does not support device pixel format %s.\n",
|
||||
codec->name, av_get_pix_fmt_name(config->pix_fmt));
|
||||
codec->name, av_get_pix_fmt_name(device_pix_fmt));
|
||||
}
|
||||
else
|
||||
{
|
||||
decoder_pix_fmt = device_pix_fmt;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#if !FFMPEG3
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
exit:
|
||||
if (decoder_pix_fmt != AV_PIX_FMT_NONE)
|
||||
@@ -1070,7 +1076,6 @@ static enum AVPixelFormat auto_hw_decoder(AVCodecContext *ctx,
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static enum AVPixelFormat select_decoder(AVCodecContext *ctx,
|
||||
const enum AVPixelFormat *pix_fmts)
|
||||
{
|
||||
@@ -1098,7 +1103,7 @@ static enum AVPixelFormat select_decoder(AVCodecContext *ctx,
|
||||
ctx->thread_count = sw_decoder_threads;
|
||||
log_cb(RETRO_LOG_INFO, "[FFMPEG] Configured software decoding threads: %d\n", sw_decoder_threads);
|
||||
|
||||
format = fctx->streams[video_stream_index]->codec->pix_fmt;
|
||||
format = fctx->streams[video_stream_index]->codecpar->format;
|
||||
|
||||
#if ENABLE_HW_ACCEL
|
||||
hw_decoding_enabled = false;
|
||||
@@ -1132,14 +1137,15 @@ static bool open_codec(AVCodecContext **ctx, enum AVMediaType type, unsigned ind
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
AVCodec *codec = avcodec_find_decoder(fctx->streams[index]->codec->codec_id);
|
||||
const AVCodec *codec = avcodec_find_decoder(fctx->streams[index]->codecpar->codec_id);
|
||||
if (!codec)
|
||||
{
|
||||
log_cb(RETRO_LOG_ERROR, "[FFMPEG] Couldn't find suitable decoder\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*ctx = fctx->streams[index]->codec;
|
||||
*ctx = avcodec_alloc_context3(codec);
|
||||
avcodec_parameters_to_context((*ctx), fctx->streams[index]->codecpar);
|
||||
|
||||
if (type == AVMEDIA_TYPE_VIDEO)
|
||||
{
|
||||
@@ -1230,7 +1236,7 @@ static bool open_codecs(void)
|
||||
|
||||
for (i = 0; i < fctx->nb_streams; i++)
|
||||
{
|
||||
enum AVMediaType type = fctx->streams[i]->codec->codec_type;
|
||||
enum AVMediaType type = fctx->streams[i]->codecpar->codec_type;
|
||||
switch (type)
|
||||
{
|
||||
case AVMEDIA_TYPE_AUDIO:
|
||||
@@ -1245,7 +1251,7 @@ static bool open_codecs(void)
|
||||
|
||||
case AVMEDIA_TYPE_VIDEO:
|
||||
if (!vctx
|
||||
&& !codec_is_image(fctx->streams[i]->codec->codec_id))
|
||||
&& !codec_is_image(fctx->streams[i]->codecpar->codec_id))
|
||||
{
|
||||
if (!open_codec(&vctx, type, i))
|
||||
return false;
|
||||
@@ -1255,7 +1261,7 @@ static bool open_codecs(void)
|
||||
case AVMEDIA_TYPE_SUBTITLE:
|
||||
#ifdef HAVE_SSA
|
||||
if (subtitle_streams_num < MAX_STREAMS
|
||||
&& codec_id_is_ass(fctx->streams[i]->codec->codec_id))
|
||||
&& codec_id_is_ass(fctx->streams[i]->codecpar->codec_id))
|
||||
{
|
||||
int size;
|
||||
AVCodecContext **s = &sctx[subtitle_streams_num];
|
||||
@@ -1280,9 +1286,9 @@ static bool open_codecs(void)
|
||||
|
||||
case AVMEDIA_TYPE_ATTACHMENT:
|
||||
{
|
||||
AVCodecContext *ctx = fctx->streams[i]->codec;
|
||||
if (codec_id_is_ttf(ctx->codec_id))
|
||||
append_attachment(ctx->extradata, ctx->extradata_size);
|
||||
AVCodecParameters *params = fctx->streams[i]->codecpar;
|
||||
if (codec_id_is_ttf(params->codec_id))
|
||||
append_attachment(params->extradata, params->extradata_size);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1464,12 +1470,12 @@ static void sws_worker_thread(void *arg)
|
||||
|
||||
ctx->sws = sws_getCachedContext(ctx->sws,
|
||||
media.width, media.height, (enum AVPixelFormat)tmp_frame->format,
|
||||
media.width, media.height, PIX_FMT_RGB32,
|
||||
media.width, media.height, AV_PIX_FMT_RGB32,
|
||||
SWS_POINT, NULL, NULL, NULL);
|
||||
|
||||
set_colorspace(ctx->sws, media.width, media.height,
|
||||
av_frame_get_colorspace(tmp_frame),
|
||||
av_frame_get_color_range(tmp_frame));
|
||||
tmp_frame->colorspace,
|
||||
tmp_frame->color_range);
|
||||
|
||||
if ((ret = sws_scale(ctx->sws, (const uint8_t *const*)tmp_frame->data,
|
||||
tmp_frame->linesize, 0, media.height,
|
||||
@@ -1620,7 +1626,7 @@ static int16_t *decode_audio(AVCodecContext *ctx, AVPacket *pkt,
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
required_buffer = frame->nb_samples * sizeof(int16_t) * 2;
|
||||
if (required_buffer > *buffer_cap)
|
||||
{
|
||||
@@ -1637,7 +1643,7 @@ static int16_t *decode_audio(AVCodecContext *ctx, AVPacket *pkt,
|
||||
pts = frame->best_effort_timestamp;
|
||||
slock_lock(fifo_lock);
|
||||
|
||||
while (!decode_thread_dead &&
|
||||
while (!decode_thread_dead &&
|
||||
FIFO_WRITE_AVAIL(audio_decode_fifo) < required_buffer)
|
||||
{
|
||||
if (!main_sleeping)
|
||||
@@ -1740,7 +1746,7 @@ static void decode_thread(void *data)
|
||||
|
||||
if (video_stream_index >= 0)
|
||||
{
|
||||
frame_size = avpicture_get_size(PIX_FMT_RGB32, media.width, media.height);
|
||||
frame_size = av_image_get_buffer_size(AV_PIX_FMT_RGB32, media.width, media.height, 1);
|
||||
video_buffer = video_buffer_create(4, frame_size, media.width, media.height);
|
||||
tpool = tpool_create(sw_sws_threads);
|
||||
log_cb(RETRO_LOG_INFO, "[FFMPEG] Configured worker threads: %d\n", sw_sws_threads);
|
||||
@@ -1813,7 +1819,7 @@ static void decode_thread(void *data)
|
||||
if (!packet_buffer_empty(video_packet_buffer))
|
||||
next_video_end = video_timebase * packet_buffer_peek_end_pts(video_packet_buffer);
|
||||
|
||||
/*
|
||||
/*
|
||||
* Decode audio packet if:
|
||||
* 1. it's the start of file or it's audio only media
|
||||
* 2. there is a video packet for in the buffer
|
||||
@@ -1835,7 +1841,7 @@ static void decode_thread(void *data)
|
||||
av_packet_unref(pkt);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* Decode video packet if:
|
||||
* 1. we already decoded an audio packet
|
||||
* 2. there is no audio stream to play
|
||||
@@ -1865,7 +1871,7 @@ static void decode_thread(void *data)
|
||||
av_packet_free(&pkt);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Read the next frame and stage it in case of audio or video frame.
|
||||
if (av_read_frame(fctx, pkt) < 0)
|
||||
eof = true;
|
||||
@@ -1878,7 +1884,7 @@ static void decode_thread(void *data)
|
||||
/**
|
||||
* Decode subtitle packets right away, since SSA/ASS can operate this way.
|
||||
* If we ever support other subtitles, we need to handle this with a
|
||||
* buffer too
|
||||
* buffer too
|
||||
**/
|
||||
AVSubtitle sub;
|
||||
int finished = 0;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/imgutils.h>
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -69,17 +70,18 @@ video_buffer_t *video_buffer_create(
|
||||
b->buffer[i].pts = 0;
|
||||
b->buffer[i].sws = sws_alloc_context();
|
||||
b->buffer[i].source = av_frame_alloc();
|
||||
#if LIBAVUTIL_VERSION_MAJOR > 55
|
||||
#if ENABLE_HW_ACCEL
|
||||
b->buffer[i].hw_source = av_frame_alloc();
|
||||
#endif
|
||||
b->buffer[i].target = av_frame_alloc();
|
||||
|
||||
avpicture_alloc((AVPicture*)b->buffer[i].target,
|
||||
PIX_FMT_RGB32, width, height);
|
||||
AVFrame* frame = b->buffer[i].target;
|
||||
av_image_alloc(frame->data, frame->linesize,
|
||||
width, height, AV_PIX_FMT_RGB32, 1);
|
||||
|
||||
if (!b->buffer[i].sws ||
|
||||
!b->buffer[i].source ||
|
||||
#if LIBAVUTIL_VERSION_MAJOR > 55
|
||||
#if ENABLE_HW_ACCEL
|
||||
!b->buffer[i].hw_source ||
|
||||
#endif
|
||||
!b->buffer[i].target)
|
||||
@@ -106,11 +108,11 @@ void video_buffer_destroy(video_buffer_t *video_buffer)
|
||||
{
|
||||
for (i = 0; i < video_buffer->capacity; i++)
|
||||
{
|
||||
#if LIBAVUTIL_VERSION_MAJOR > 55
|
||||
#if ENABLE_HW_ACCEL
|
||||
av_frame_free(&video_buffer->buffer[i].hw_source);
|
||||
#endif
|
||||
av_frame_free(&video_buffer->buffer[i].source);
|
||||
avpicture_free((AVPicture*)video_buffer->buffer[i].target);
|
||||
av_freep((AVFrame*)video_buffer->buffer[i].target);
|
||||
av_frame_free(&video_buffer->buffer[i].target);
|
||||
sws_freeContext(video_buffer->buffer[i].sws);
|
||||
}
|
||||
|
||||
@@ -31,22 +31,24 @@ extern "C" {
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
#ifndef PIX_FMT_RGB32
|
||||
#define PIX_FMT_RGB32 AV_PIX_FMT_RGB32
|
||||
#endif
|
||||
/* If libavutil is at least version 55,
|
||||
* and if libavcodec is at least version 57.80.100,
|
||||
* enable hardware acceleration */
|
||||
#define ENABLE_HW_ACCEL ((LIBAVUTIL_VERSION_MAJOR >= 55) && \
|
||||
(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 80, 100)))
|
||||
|
||||
/**
|
||||
* video_decoder_context
|
||||
*
|
||||
*
|
||||
* Context object for the sws worker threads.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct video_decoder_context
|
||||
{
|
||||
int64_t pts;
|
||||
struct SwsContext *sws;
|
||||
AVFrame *source;
|
||||
#if LIBAVUTIL_VERSION_MAJOR > 55
|
||||
#if ENABLE_HW_ACCEL
|
||||
AVFrame *hw_source;
|
||||
#endif
|
||||
AVFrame *target;
|
||||
@@ -60,15 +62,15 @@ typedef struct video_decoder_context video_decoder_context_t;
|
||||
|
||||
/**
|
||||
* video_buffer
|
||||
*
|
||||
* The video buffer is a ring buffer, that can be used as a
|
||||
*
|
||||
* The video buffer is a ring buffer, that can be used as a
|
||||
* buffer for many workers while keeping the order.
|
||||
*
|
||||
*
|
||||
* It is thread safe in a sensem that it is designed to work
|
||||
* with one work coordinator, that allocates work slots for
|
||||
* workers threads to work on and later collect the work
|
||||
* product in the same order, as the slots were allocated.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct video_buffer;
|
||||
typedef struct video_buffer video_buffer_t;
|
||||
@@ -81,38 +83,38 @@ typedef struct video_buffer video_buffer_t;
|
||||
* @height : Height of the target frame.
|
||||
*
|
||||
* Create a video buffer.
|
||||
*
|
||||
*
|
||||
* Returns: A video buffer.
|
||||
*/
|
||||
video_buffer_t *video_buffer_create(size_t capacity, int frame_size, int width, int height);
|
||||
|
||||
/**
|
||||
/**
|
||||
* video_buffer_destroy:
|
||||
* @video_buffer : video buffer.
|
||||
*
|
||||
*
|
||||
* Destroys a video buffer.
|
||||
*
|
||||
*
|
||||
* Does also free the buffer allocated with video_buffer_create().
|
||||
* User has to shut down any external worker threads that may have
|
||||
* a reference to this video buffer.
|
||||
*
|
||||
*
|
||||
**/
|
||||
void video_buffer_destroy(video_buffer_t *video_buffer);
|
||||
|
||||
/**
|
||||
/**
|
||||
* video_buffer_clear:
|
||||
* @video_buffer : video buffer.
|
||||
*
|
||||
*
|
||||
* Clears a video buffer.
|
||||
*
|
||||
*
|
||||
**/
|
||||
void video_buffer_clear(video_buffer_t *video_buffer);
|
||||
|
||||
/**
|
||||
/**
|
||||
* video_buffer_get_open_slot:
|
||||
* @video_buffer : video buffer.
|
||||
* @context : sws context.
|
||||
*
|
||||
*
|
||||
* Returns the next open context inside the ring buffer
|
||||
* and it's index. The status of the slot will be marked as
|
||||
* 'in progress' until slot is marked as finished with
|
||||
@@ -121,21 +123,21 @@ void video_buffer_clear(video_buffer_t *video_buffer);
|
||||
**/
|
||||
void video_buffer_get_open_slot(video_buffer_t *video_buffer, video_decoder_context_t **context);
|
||||
|
||||
/**
|
||||
/**
|
||||
* video_buffer_return_open_slot:
|
||||
* @video_buffer : video buffer.
|
||||
* @context : sws context.
|
||||
*
|
||||
*
|
||||
* Marks the given sws context that is "in progress" as "open" again.
|
||||
*
|
||||
**/
|
||||
void video_buffer_return_open_slot(video_buffer_t *video_buffer, video_decoder_context_t *context);
|
||||
|
||||
/**
|
||||
/**
|
||||
* video_buffer_open_slot:
|
||||
* @video_buffer : video buffer.
|
||||
* @context : sws context.
|
||||
*
|
||||
*
|
||||
* Sets the status of the given context from "finished" to "open".
|
||||
* The slot is then available for producers to claim again with video_buffer_get_open_slot().
|
||||
**/
|
||||
@@ -145,7 +147,7 @@ void video_buffer_open_slot(video_buffer_t *video_buffer, video_decoder_context_
|
||||
* video_buffer_get_finished_slot:
|
||||
* @video_buffer : video buffer.
|
||||
* @context : sws context.
|
||||
*
|
||||
*
|
||||
* Returns a reference for the next context inside
|
||||
* the ring buffer. User needs to use video_buffer_open_slot()
|
||||
* to open the slot in the ringbuffer for the next
|
||||
@@ -158,7 +160,7 @@ void video_buffer_get_finished_slot(video_buffer_t *video_buffer, video_decoder_
|
||||
* video_buffer_finish_slot:
|
||||
* @video_buffer : video buffer.
|
||||
* @context : sws context.
|
||||
*
|
||||
*
|
||||
* Sets the status of the given context from "in progress" to "finished".
|
||||
* This is normally done by a producer. User can then retrieve the finished work
|
||||
* context by calling video_buffer_get_finished_slot().
|
||||
@@ -168,9 +170,9 @@ void video_buffer_finish_slot(video_buffer_t *video_buffer, video_decoder_contex
|
||||
/**
|
||||
* video_buffer_wait_for_open_slot:
|
||||
* @video_buffer : video buffer.
|
||||
*
|
||||
*
|
||||
* Blocks until open slot is available.
|
||||
*
|
||||
*
|
||||
* Returns true if the buffer has a open slot available.
|
||||
*/
|
||||
bool video_buffer_wait_for_open_slot(video_buffer_t *video_buffer);
|
||||
@@ -180,7 +182,7 @@ bool video_buffer_wait_for_open_slot(video_buffer_t *video_buffer);
|
||||
* @video_buffer : video buffer.
|
||||
*
|
||||
* Blocks until finished slot is available.
|
||||
*
|
||||
*
|
||||
* Returns true if the buffers next slot is finished and a
|
||||
* context available.
|
||||
*/
|
||||
@@ -190,7 +192,7 @@ bool video_buffer_wait_for_finished_slot(video_buffer_t *video_buffer);
|
||||
* bool video_buffer_has_open_slot(video_buffer_t *video_buffer)
|
||||
:
|
||||
* @video_buffer : video buffer.
|
||||
*
|
||||
*
|
||||
* Returns true if the buffer has a open slot available.
|
||||
*/
|
||||
bool video_buffer_has_open_slot(video_buffer_t *video_buffer);
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
gong.so: gong.c
|
||||
gcc \
|
||||
-std=c89 \
|
||||
-pedantic \
|
||||
-Wall \
|
||||
-Wno-unused-variable \
|
||||
-g \
|
||||
gong.c \
|
||||
-I../../libretro-common/include/ \
|
||||
-shared \
|
||||
-fPIC \
|
||||
-Wl,--no-undefined \
|
||||
-lm \
|
||||
-o gong.so
|
||||
|
||||
clean:
|
||||
rm -f gong.so
|
||||
@@ -1,939 +0,0 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2017 - Daniel De Matteis
|
||||
* Copyright (C) 2016-2019 - Brad Parker
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Libretro port by Brad Parker,
|
||||
Original source code by Dan Zaidan: https://danzaidan.itch.io/
|
||||
Original license:
|
||||
"You can do whatever you want with the code, but I am providing it as is without any warranty whatsoever."
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <libretro.h>
|
||||
#include <retro_math.h>
|
||||
#include <retro_inline.h>
|
||||
#include <retro_endianness.h>
|
||||
|
||||
#ifdef RARCH_INTERNAL
|
||||
#include "internal_cores.h"
|
||||
#define GONG_CORE_PREFIX(s) libretro_gong_##s
|
||||
#else
|
||||
#define GONG_CORE_PREFIX(s) s
|
||||
#endif
|
||||
|
||||
#define WIDTH 356
|
||||
#define HEIGHT 200
|
||||
#define MAX_PLAYERS 2
|
||||
#define STATE_SIZE 4096 /* can be anything as long as it's large enough to hold everything */
|
||||
|
||||
static retro_log_printf_t GONG_CORE_PREFIX(log_cb);
|
||||
static retro_video_refresh_t GONG_CORE_PREFIX(video_cb);
|
||||
static retro_input_poll_t GONG_CORE_PREFIX(input_poll_cb);
|
||||
static retro_input_state_t GONG_CORE_PREFIX(input_state_cb);
|
||||
static retro_audio_sample_t GONG_CORE_PREFIX(audio_cb);
|
||||
static retro_audio_sample_batch_t GONG_CORE_PREFIX(audio_batch_cb);
|
||||
static retro_environment_t GONG_CORE_PREFIX(environ_cb);
|
||||
|
||||
static const char *GONG_CORE_PREFIX(valid_extensions) = "gong";
|
||||
|
||||
static unsigned char *video_buf = NULL;
|
||||
|
||||
enum
|
||||
{
|
||||
B_MOVE_UP,
|
||||
B_MOVE_DOWN,
|
||||
B_SPEED_UP,
|
||||
B_COUNT /* This should always be in the bottom */
|
||||
};
|
||||
|
||||
/* any changes here must be handled in serialization code too */
|
||||
typedef struct
|
||||
{
|
||||
union { float f; unsigned u; } py;
|
||||
union { float f; unsigned u; } dpy;
|
||||
} Player;
|
||||
|
||||
/* any changes here must be handled in serialization code too */
|
||||
typedef struct
|
||||
{
|
||||
int half_transition_count;
|
||||
bool ended_down;
|
||||
} Game_Button_State;
|
||||
|
||||
/* any changes here must be handled in serialization code too */
|
||||
typedef struct
|
||||
{
|
||||
Game_Button_State buttons[B_COUNT];
|
||||
float last_dt; /* not in savestate */
|
||||
} Game_Input;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t input;
|
||||
uint16_t not_input;
|
||||
uint16_t realinput;
|
||||
int16_t analogYLeft;
|
||||
int16_t analogYRight;
|
||||
} retro_inputs;
|
||||
|
||||
/* any changes here must be handled in serialization code too */
|
||||
typedef struct
|
||||
{
|
||||
unsigned version;
|
||||
unsigned player1_score;
|
||||
unsigned player2_score;
|
||||
union { float f; unsigned u; } player2_speed;
|
||||
union { float f; unsigned u; } ball_px;
|
||||
union { float f; unsigned u; } ball_py;
|
||||
union { float f; unsigned u; } ball_dpx;
|
||||
union { float f; unsigned u; } ball_dpy;
|
||||
union { float f; unsigned u; } ball_speed;
|
||||
union { float f; unsigned u; } current_play_points;
|
||||
float refresh; /* not in savestate */
|
||||
bool is_initialized;
|
||||
bool player2_human;
|
||||
uint16_t previnput[MAX_PLAYERS];
|
||||
Game_Input g_input[MAX_PLAYERS];
|
||||
Player player[MAX_PLAYERS];
|
||||
} State;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Pixels are always 32-bit wide, memory order XX BB GG RR */
|
||||
int width;
|
||||
int height;
|
||||
int pitch;
|
||||
void *memory;
|
||||
} Game_Offscreen_Buffer;
|
||||
|
||||
static State *g_state = NULL;
|
||||
static Game_Offscreen_Buffer game_buffer = {0};
|
||||
static void game_update_and_render(Game_Input *input, Game_Offscreen_Buffer *draw_buffer);
|
||||
|
||||
static const struct retro_controller_description pads1[] = {
|
||||
{ "Joypad", RETRO_DEVICE_JOYPAD },
|
||||
{ NULL, 0 },
|
||||
};
|
||||
|
||||
static const struct retro_controller_description pads2[] = {
|
||||
{ "Joypad", RETRO_DEVICE_JOYPAD },
|
||||
{ NULL, 0 },
|
||||
};
|
||||
|
||||
static const struct retro_controller_info ports[] = {
|
||||
{ pads1, 1 },
|
||||
{ pads2, 1 },
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
struct retro_input_descriptor desc[] = {
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" },
|
||||
{ 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" },
|
||||
{ 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Analog Y" },
|
||||
{ 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right Analog Y" },
|
||||
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
static void check_variables(void)
|
||||
{
|
||||
struct retro_variable var = {0};
|
||||
|
||||
var.key = "gong_refresh";
|
||||
if (GONG_CORE_PREFIX(environ_cb)(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||
{
|
||||
int i;
|
||||
g_state->refresh = atoi(var.value);
|
||||
|
||||
for (i = 0; i < (int)(sizeof(g_state->g_input) / sizeof(g_state->g_input[0])); i++)
|
||||
g_state->g_input[i].last_dt = 1.0f / g_state->refresh;
|
||||
}
|
||||
|
||||
var.key = "gong_player2";
|
||||
if (GONG_CORE_PREFIX(environ_cb)(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||
{
|
||||
if (!strncmp(var.value, "CPU", 3))
|
||||
g_state->player2_human = false;
|
||||
else if (!strncmp(var.value, "Human", 5))
|
||||
g_state->player2_human = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void save_state(void *data, size_t size)
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
unsigned char *buf = (unsigned char*)data;
|
||||
unsigned version = swap_if_little32(g_state->version);
|
||||
unsigned player1_score = swap_if_little32(g_state->player1_score);
|
||||
unsigned player2_score = swap_if_little32(g_state->player2_score);
|
||||
unsigned player2_speed = swap_if_little32(g_state->player2_speed.u);
|
||||
unsigned ball_px = swap_if_little32(g_state->ball_px.u);
|
||||
unsigned ball_py = swap_if_little32(g_state->ball_py.u);
|
||||
unsigned ball_dpx = swap_if_little32(g_state->ball_dpx.u);
|
||||
unsigned ball_dpy = swap_if_little32(g_state->ball_dpy.u);
|
||||
unsigned ball_speed = swap_if_little32(g_state->ball_speed.u);
|
||||
unsigned current_play_points = swap_if_little32(g_state->current_play_points.u);
|
||||
unsigned is_initialized = g_state->is_initialized;
|
||||
unsigned player2_human = g_state->player2_human;
|
||||
|
||||
(void)size;
|
||||
|
||||
memcpy(buf, &version, sizeof(unsigned));
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
memcpy(buf, &player1_score, sizeof(unsigned));
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
memcpy(buf, &player2_score, sizeof(unsigned));
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
memcpy(buf, &player2_speed, sizeof(unsigned));
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
memcpy(buf, &ball_px, sizeof(unsigned));
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
memcpy(buf, &ball_py, sizeof(unsigned));
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
memcpy(buf, &ball_dpx, sizeof(unsigned));
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
memcpy(buf, &ball_dpy, sizeof(unsigned));
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
memcpy(buf, &ball_speed, sizeof(unsigned));
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
memcpy(buf, ¤t_play_points, sizeof(unsigned));
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
memcpy(buf, &is_initialized, sizeof(unsigned));
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
memcpy(buf, &player2_human, sizeof(unsigned));
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
/* previnput */
|
||||
for (i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
uint16_t previnput = swap_if_little16(g_state->previnput[i]);
|
||||
memcpy(buf, &previnput, sizeof(uint16_t));
|
||||
buf += sizeof(uint16_t);
|
||||
}
|
||||
|
||||
/* g_input */
|
||||
for (i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
for (j = 0; j < B_COUNT; j++)
|
||||
{
|
||||
int half_transition_count = swap_if_little32(g_state->g_input[i].buttons[j].half_transition_count);
|
||||
unsigned ended_down = g_state->g_input[i].buttons[j].ended_down;
|
||||
|
||||
memcpy(buf, &half_transition_count, sizeof(int));
|
||||
buf += sizeof(int);
|
||||
|
||||
memcpy(buf, &ended_down, sizeof(unsigned));
|
||||
buf += sizeof(unsigned);
|
||||
}
|
||||
}
|
||||
|
||||
/* player */
|
||||
for (i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
unsigned py = swap_if_little32((unsigned)g_state->player[i].py.u);
|
||||
|
||||
memcpy(buf, &py, sizeof(unsigned));
|
||||
buf += sizeof(uint16_t);
|
||||
}
|
||||
}
|
||||
|
||||
static void load_state(const void *data, size_t size)
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
const unsigned char *buf = (const unsigned char*)data;
|
||||
|
||||
(void)size;
|
||||
|
||||
memset(g_state, 0, sizeof(*g_state));
|
||||
|
||||
g_state->version = swap_if_little32(*(unsigned*)buf);
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
g_state->player1_score = swap_if_little32(*(unsigned*)buf);
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
g_state->player2_score = swap_if_little32(*(unsigned*)buf);
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
g_state->player2_speed.u = swap_if_little32(*(unsigned*)buf);
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
g_state->ball_px.u = swap_if_little32(*(unsigned*)buf);
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
g_state->ball_py.u = swap_if_little32(*(unsigned*)buf);
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
g_state->ball_dpx.u = swap_if_little32(*(unsigned*)buf);
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
g_state->ball_dpy.u = swap_if_little32(*(unsigned*)buf);
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
g_state->ball_speed.u = swap_if_little32(*(unsigned*)buf);
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
g_state->current_play_points.u = swap_if_little32(*(unsigned*)buf);
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
g_state->is_initialized = (bool)swap_if_little32(*(unsigned*)buf);
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
g_state->player2_human = (bool)swap_if_little32(*(unsigned*)buf);
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
/* previnput */
|
||||
for (i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
uint16_t previnput = swap_if_little16(*(uint16_t*)buf);
|
||||
g_state->previnput[i] = previnput;
|
||||
buf += sizeof(uint16_t);
|
||||
}
|
||||
|
||||
/* g_input */
|
||||
for (i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
for (j = 0; j < B_COUNT; j++)
|
||||
{
|
||||
int half_transition_count;
|
||||
bool ended_down;
|
||||
|
||||
half_transition_count = (int)swap_if_little32(*(unsigned*)buf);
|
||||
|
||||
g_state->g_input[i].buttons[j].half_transition_count = half_transition_count;
|
||||
buf += sizeof(int);
|
||||
|
||||
ended_down = (bool)swap_if_little32(*(unsigned*)buf);
|
||||
|
||||
g_state->g_input[i].buttons[j].ended_down = ended_down;
|
||||
buf += sizeof(unsigned);
|
||||
}
|
||||
}
|
||||
|
||||
/* player */
|
||||
for (i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
g_state->player[i].py.u = swap_if_little32(*(unsigned*)buf);
|
||||
buf += sizeof(unsigned);
|
||||
|
||||
g_state->player[i].dpy.u = swap_if_little32(*(unsigned*)buf);
|
||||
buf += sizeof(unsigned);
|
||||
}
|
||||
|
||||
check_variables();
|
||||
}
|
||||
|
||||
static INLINE bool is_down(Game_Button_State state)
|
||||
{
|
||||
return state.ended_down;
|
||||
}
|
||||
|
||||
void GONG_CORE_PREFIX(retro_get_system_info)(struct retro_system_info *info)
|
||||
{
|
||||
info->library_name = "gong";
|
||||
info->library_version = "v1.0";
|
||||
info->need_fullpath = false;
|
||||
info->block_extract = false;
|
||||
info->valid_extensions = GONG_CORE_PREFIX(valid_extensions);
|
||||
}
|
||||
|
||||
void GONG_CORE_PREFIX(retro_get_system_av_info)(struct retro_system_av_info *info)
|
||||
{
|
||||
info->geometry.base_width = WIDTH;
|
||||
info->geometry.base_height = HEIGHT;
|
||||
info->geometry.max_width = WIDTH;
|
||||
info->geometry.max_height = HEIGHT;
|
||||
info->geometry.aspect_ratio = 16.0f / 9.0f;
|
||||
info->timing.fps = g_state->refresh;
|
||||
info->timing.sample_rate = 44100.0;
|
||||
}
|
||||
|
||||
void GONG_CORE_PREFIX(retro_init)(void)
|
||||
{
|
||||
struct retro_log_callback log;
|
||||
|
||||
g_state = (State*)calloc(1, sizeof(*g_state));
|
||||
|
||||
if (GONG_CORE_PREFIX(environ_cb)(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log))
|
||||
GONG_CORE_PREFIX(log_cb) = log.log;
|
||||
else
|
||||
GONG_CORE_PREFIX(log_cb) = NULL;
|
||||
|
||||
video_buf = (unsigned char*)calloc(1, WIDTH * HEIGHT * sizeof(unsigned));
|
||||
|
||||
game_buffer.width = WIDTH;
|
||||
game_buffer.height = HEIGHT;
|
||||
game_buffer.pitch = WIDTH * sizeof(unsigned);
|
||||
game_buffer.memory = video_buf;
|
||||
}
|
||||
|
||||
void GONG_CORE_PREFIX(retro_deinit)(void)
|
||||
{
|
||||
if (video_buf)
|
||||
free(video_buf);
|
||||
|
||||
video_buf = NULL;
|
||||
game_buffer.memory = NULL;
|
||||
|
||||
if (g_state)
|
||||
free(g_state);
|
||||
}
|
||||
|
||||
void GONG_CORE_PREFIX(retro_set_environment)(retro_environment_t cb)
|
||||
{
|
||||
bool no_content = true;
|
||||
|
||||
static const struct retro_variable vars[] = {
|
||||
{ "gong_player2", "Player 2; CPU|Human" },
|
||||
{ "gong_refresh", "Video Refresh Rate (restart); 60|70|72|75|100|119|120|140|144" },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
GONG_CORE_PREFIX(environ_cb) = cb;
|
||||
|
||||
cb(RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME, &no_content);
|
||||
cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)vars);
|
||||
cb(RETRO_ENVIRONMENT_SET_CONTROLLER_INFO, (void*)ports);
|
||||
}
|
||||
|
||||
void GONG_CORE_PREFIX(retro_set_video_refresh)(retro_video_refresh_t cb)
|
||||
{
|
||||
GONG_CORE_PREFIX(video_cb) = cb;
|
||||
}
|
||||
|
||||
void GONG_CORE_PREFIX(retro_set_audio_sample)(retro_audio_sample_t cb)
|
||||
{
|
||||
GONG_CORE_PREFIX(audio_cb) = cb;
|
||||
}
|
||||
|
||||
void GONG_CORE_PREFIX(retro_set_audio_sample_batch)(retro_audio_sample_batch_t cb)
|
||||
{
|
||||
GONG_CORE_PREFIX(audio_batch_cb) = cb;
|
||||
}
|
||||
|
||||
void GONG_CORE_PREFIX(retro_set_input_poll)(retro_input_poll_t cb)
|
||||
{
|
||||
GONG_CORE_PREFIX(input_poll_cb) = cb;
|
||||
}
|
||||
|
||||
void GONG_CORE_PREFIX(retro_set_input_state)(retro_input_state_t cb)
|
||||
{
|
||||
GONG_CORE_PREFIX(input_state_cb) = cb;
|
||||
}
|
||||
|
||||
void GONG_CORE_PREFIX(retro_set_controller_port_device)(unsigned a, unsigned b)
|
||||
{
|
||||
}
|
||||
|
||||
void GONG_CORE_PREFIX(retro_reset)(void)
|
||||
{
|
||||
memset(g_state, 0, sizeof(*g_state));
|
||||
check_variables();
|
||||
}
|
||||
|
||||
size_t GONG_CORE_PREFIX(retro_serialize_size)(void)
|
||||
{
|
||||
return STATE_SIZE;
|
||||
}
|
||||
|
||||
bool GONG_CORE_PREFIX(retro_serialize)(void *data, size_t size)
|
||||
{
|
||||
if (size != STATE_SIZE)
|
||||
return false;
|
||||
|
||||
save_state(data, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GONG_CORE_PREFIX(retro_unserialize)(const void *data, size_t size)
|
||||
{
|
||||
if (size != STATE_SIZE)
|
||||
return false;
|
||||
|
||||
load_state(data, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
void GONG_CORE_PREFIX(retro_cheat_reset)(void)
|
||||
{
|
||||
}
|
||||
|
||||
void GONG_CORE_PREFIX(retro_cheat_set)(unsigned a, bool b, const char * c)
|
||||
{
|
||||
}
|
||||
|
||||
bool GONG_CORE_PREFIX(retro_load_game)(const struct retro_game_info *info)
|
||||
{
|
||||
enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_XRGB8888;
|
||||
|
||||
check_variables();
|
||||
|
||||
if (!GONG_CORE_PREFIX(environ_cb)(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt))
|
||||
{
|
||||
if (GONG_CORE_PREFIX(log_cb))
|
||||
GONG_CORE_PREFIX(log_cb)(RETRO_LOG_INFO, "XRGB8888 is not supported.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GONG_CORE_PREFIX(retro_load_game_special)(unsigned a, const struct retro_game_info *b, size_t c)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void GONG_CORE_PREFIX(retro_unload_game)(void)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned GONG_CORE_PREFIX(retro_get_region)(void)
|
||||
{
|
||||
return RETRO_REGION_NTSC;
|
||||
}
|
||||
|
||||
void* GONG_CORE_PREFIX(retro_get_memory_data)(unsigned id)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t GONG_CORE_PREFIX(retro_get_memory_size)(unsigned id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void process_joypad(Game_Button_State *new_state, bool is_down)
|
||||
{
|
||||
if (new_state->ended_down != is_down)
|
||||
{
|
||||
new_state->ended_down = is_down;
|
||||
new_state->half_transition_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_key_up_or_down(int16_t input, int16_t not_input, int key)
|
||||
{
|
||||
if (input & (1 << key) || not_input & (1 << key))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void GONG_CORE_PREFIX(retro_run)(void)
|
||||
{
|
||||
int i = 0;
|
||||
int port = 0;
|
||||
bool updated = false;
|
||||
retro_inputs inputs[MAX_PLAYERS] = {{0}};
|
||||
|
||||
if (GONG_CORE_PREFIX(environ_cb)(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated)
|
||||
check_variables();
|
||||
|
||||
GONG_CORE_PREFIX(input_poll_cb)();
|
||||
|
||||
for (port = 0; port < MAX_PLAYERS; port++)
|
||||
{
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
if (GONG_CORE_PREFIX(input_state_cb)(port, RETRO_DEVICE_JOYPAD, 0, i))
|
||||
{
|
||||
inputs[port].realinput |= 1 << i;
|
||||
}
|
||||
}
|
||||
|
||||
inputs[port].analogYLeft = GONG_CORE_PREFIX(input_state_cb)(port, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y) / 5000.0f;
|
||||
inputs[port].analogYRight = GONG_CORE_PREFIX(input_state_cb)(port, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y) / 5000.0f;
|
||||
|
||||
if (inputs[port].analogYLeft > 0)
|
||||
inputs[port].realinput |= (1 << RETRO_DEVICE_ID_JOYPAD_DOWN);
|
||||
else if (inputs[port].analogYRight > 0)
|
||||
inputs[port].realinput |= (1 << RETRO_DEVICE_ID_JOYPAD_DOWN);
|
||||
|
||||
if (inputs[port].analogYLeft < 0)
|
||||
inputs[port].realinput |= (1 << RETRO_DEVICE_ID_JOYPAD_UP);
|
||||
else if (inputs[port].analogYRight < 0)
|
||||
inputs[port].realinput |= (1 << RETRO_DEVICE_ID_JOYPAD_UP);
|
||||
|
||||
inputs[port].input = inputs[port].realinput & ~g_state->previnput[port];
|
||||
inputs[port].not_input = g_state->previnput[port] & ~inputs[port].realinput;
|
||||
|
||||
if (is_key_up_or_down(inputs[port].input, inputs[port].not_input, RETRO_DEVICE_ID_JOYPAD_UP))
|
||||
process_joypad(&g_state->g_input[port].buttons[B_MOVE_UP], inputs[port].realinput & (1 << RETRO_DEVICE_ID_JOYPAD_UP));
|
||||
else if (is_key_up_or_down(inputs[port].input, inputs[port].not_input, RETRO_DEVICE_ID_JOYPAD_DOWN))
|
||||
process_joypad(&g_state->g_input[port].buttons[B_MOVE_DOWN], inputs[port].realinput & (1 << RETRO_DEVICE_ID_JOYPAD_DOWN));
|
||||
else if (is_key_up_or_down(inputs[port].input, inputs[port].not_input, RETRO_DEVICE_ID_JOYPAD_DOWN))
|
||||
process_joypad(&g_state->g_input[port].buttons[B_MOVE_DOWN], inputs[port].realinput & (1 << RETRO_DEVICE_ID_JOYPAD_DOWN));
|
||||
|
||||
if (is_key_up_or_down(inputs[port].input, inputs[port].not_input, RETRO_DEVICE_ID_JOYPAD_A))
|
||||
process_joypad(&g_state->g_input[port].buttons[B_SPEED_UP], inputs[port].realinput & (1 << RETRO_DEVICE_ID_JOYPAD_A));
|
||||
else if (is_key_up_or_down(inputs[port].input, inputs[port].not_input, RETRO_DEVICE_ID_JOYPAD_B))
|
||||
process_joypad(&g_state->g_input[port].buttons[B_SPEED_UP], inputs[port].realinput & (1 << RETRO_DEVICE_ID_JOYPAD_B));
|
||||
else if (is_key_up_or_down(inputs[port].input, inputs[port].not_input, RETRO_DEVICE_ID_JOYPAD_X))
|
||||
process_joypad(&g_state->g_input[port].buttons[B_SPEED_UP], inputs[port].realinput & (1 << RETRO_DEVICE_ID_JOYPAD_X));
|
||||
else if (is_key_up_or_down(inputs[port].input, inputs[port].not_input, RETRO_DEVICE_ID_JOYPAD_Y))
|
||||
process_joypad(&g_state->g_input[port].buttons[B_SPEED_UP], inputs[port].realinput & (1 << RETRO_DEVICE_ID_JOYPAD_Y));
|
||||
|
||||
g_state->previnput[port] = inputs[port].realinput;
|
||||
}
|
||||
|
||||
game_update_and_render(g_state->g_input, &game_buffer);
|
||||
|
||||
GONG_CORE_PREFIX(video_cb)(video_buf, WIDTH, HEIGHT, WIDTH * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
unsigned GONG_CORE_PREFIX(retro_api_version)(void)
|
||||
{
|
||||
return RETRO_API_VERSION;
|
||||
}
|
||||
|
||||
static void draw_rect_in_pixels(Game_Offscreen_Buffer *buffer, unsigned color, int min_x, int min_y, int max_x, int max_y)
|
||||
{
|
||||
int y;
|
||||
|
||||
min_x = MAX(min_x, 0);
|
||||
min_y = MAX(min_y, 0);
|
||||
max_x = MIN(max_x, buffer->width);
|
||||
max_y = MIN(max_y, buffer->height);
|
||||
|
||||
for (y = min_y; y < max_y; y++)
|
||||
{
|
||||
int x;
|
||||
|
||||
for (x = min_x; x < max_x; x++)
|
||||
{
|
||||
unsigned *pixel = (unsigned*)((unsigned char*)buffer->memory + ((buffer->width * (buffer->height - y - 1) + x) * sizeof(unsigned)));
|
||||
|
||||
*pixel++ = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void clear(Game_Offscreen_Buffer *buffer, unsigned color)
|
||||
{
|
||||
draw_rect_in_pixels(buffer, color, 0, 0, buffer->width, buffer->height);
|
||||
}
|
||||
|
||||
static void draw_rect(Game_Offscreen_Buffer *buffer, unsigned color, float x, float y, float half_size_x, float half_size_y)
|
||||
{
|
||||
/* @Hardcoded to always keep the playing field area on screen, no matter the aspect ratio */
|
||||
float scale = .01f;
|
||||
float relative_axis = (float)buffer->height;
|
||||
int min_x, min_y, max_x, max_y;
|
||||
|
||||
if ((float)buffer->width / (float)buffer->height < 1.77f)
|
||||
{
|
||||
relative_axis = (float)buffer->width;
|
||||
scale = .0056f;
|
||||
}
|
||||
|
||||
half_size_x *= relative_axis * scale;
|
||||
half_size_y *= relative_axis * scale;
|
||||
x *= relative_axis * scale;
|
||||
y *= relative_axis * scale;
|
||||
|
||||
x = x + buffer->width / 2;
|
||||
y = y + buffer->height / 2;
|
||||
|
||||
min_x = (unsigned)(x - half_size_x);
|
||||
min_y = (unsigned)(y - half_size_y);
|
||||
max_x = (unsigned)(x + half_size_x);
|
||||
max_y = (unsigned)(y + half_size_y);
|
||||
|
||||
draw_rect_in_pixels(buffer, color, min_x, min_y, max_x, max_y);
|
||||
}
|
||||
|
||||
static void draw_number(Game_Offscreen_Buffer *buffer, unsigned number, unsigned color, float x, float y)
|
||||
{
|
||||
float at_x = x;
|
||||
|
||||
do {
|
||||
unsigned alg = number % 10;
|
||||
|
||||
number /= 10;
|
||||
|
||||
switch (alg)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
draw_rect(buffer, color, at_x - 2.f, y, .5f, 4.f);
|
||||
draw_rect(buffer, color, at_x + 2.f, y, .5f, 4.f);
|
||||
draw_rect(buffer, color, at_x, y + 4.f, 2.5f, .5f);
|
||||
draw_rect(buffer, color, at_x, y - 4.f, 2.5f, .5f);
|
||||
break;
|
||||
}
|
||||
|
||||
case 1:
|
||||
{
|
||||
draw_rect(buffer, color, at_x + 2.f, y, .5f, 4.5f);
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
draw_rect(buffer, color, at_x - 2.f, y - 2.f, .5f, 2.f);
|
||||
draw_rect(buffer, color, at_x + 2.f, y + 2.f, .5f, 2.f);
|
||||
draw_rect(buffer, color, at_x, y + 4.f, 2.5f, .5f);
|
||||
draw_rect(buffer, color, at_x, y, 2.5f, .5f);
|
||||
draw_rect(buffer, color, at_x, y - 4.f, 2.5f, .5f);
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
draw_rect(buffer, color, at_x + 2.f, y, .5f, 4.f);
|
||||
draw_rect(buffer, color, at_x, y + 4.f, 2.5f, .5f);
|
||||
draw_rect(buffer, color, at_x, y, 2.5f, .5f);
|
||||
draw_rect(buffer, color, at_x, y - 4.f, 2.5f, .5f);
|
||||
break;
|
||||
};
|
||||
|
||||
case 4:
|
||||
{
|
||||
draw_rect(buffer, color, at_x, y, 2.5f, .5f);
|
||||
draw_rect(buffer, color, at_x + 2.f, y, .5f, 4.5f);
|
||||
draw_rect(buffer, color, at_x - 2.f, y+2.5f, .5f, 2.f);
|
||||
break;
|
||||
};
|
||||
|
||||
case 5:
|
||||
{
|
||||
draw_rect(buffer, color, at_x + 2.f, y-2.f, .5f, 2.f);
|
||||
draw_rect(buffer, color, at_x - 2.f, y+2.f, .5f, 2.f);
|
||||
draw_rect(buffer, color, at_x, y + 4.f, 2.5f, .5f);
|
||||
draw_rect(buffer, color, at_x, y, 2.5f, .5f);
|
||||
draw_rect(buffer, color, at_x, y - 4.f, 2.5f, .5f);
|
||||
break;
|
||||
};
|
||||
|
||||
case 6:
|
||||
{
|
||||
draw_rect(buffer, color, at_x + 2.f, y-2.f, .5f, 2.f);
|
||||
draw_rect(buffer, color, at_x - 2.f, y, .5f, 4.f);
|
||||
draw_rect(buffer, color, at_x, y + 4.f, 2.5f, .5f);
|
||||
draw_rect(buffer, color, at_x, y, 2.5f, .5f);
|
||||
draw_rect(buffer, color, at_x, y - 4.f, 2.5f, .5f);
|
||||
break;
|
||||
};
|
||||
|
||||
case 7:
|
||||
{
|
||||
draw_rect(buffer, color, at_x + 2.f, y, .5f, 4.5f);
|
||||
draw_rect(buffer, color, at_x, y + 4.f, 2.5f, .5f);
|
||||
break;
|
||||
};
|
||||
|
||||
case 8:
|
||||
{
|
||||
draw_rect(buffer, color, at_x - 2.f, y, .5f, 4.f);
|
||||
draw_rect(buffer, color, at_x + 2.f, y, .5f, 4.f);
|
||||
draw_rect(buffer, color, at_x, y + 4.f, 2.5f, .5f);
|
||||
draw_rect(buffer, color, at_x, y - 4.f, 2.5f, .5f);
|
||||
draw_rect(buffer, color, at_x, y, 2.5f, .5f);
|
||||
break;
|
||||
};
|
||||
|
||||
case 9:
|
||||
{
|
||||
draw_rect(buffer, color, at_x - 2.f, y + 2.f, .5f, 2.f);
|
||||
draw_rect(buffer, color, at_x + 2.f, y, .5f, 4.f);
|
||||
draw_rect(buffer, color, at_x, y + 4.f, 2.5f, .5f);
|
||||
draw_rect(buffer, color, at_x, y, 2.5f, .5f);
|
||||
draw_rect(buffer, color, at_x, y - 4.f, 2.5f, .5f);
|
||||
break;
|
||||
};
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
at_x -= 7.f;
|
||||
} while(number > 0);
|
||||
}
|
||||
|
||||
static void game_update_and_render(Game_Input *input, Game_Offscreen_Buffer *draw_buffer)
|
||||
{
|
||||
const float initial_ball_speed = 80.f;
|
||||
float playing_field_x = 85.f;
|
||||
float playing_field_y = 48.f;
|
||||
float player_size_x = 2.5f;
|
||||
float player_size_y = 10.f;
|
||||
int i;
|
||||
|
||||
if (!g_state->is_initialized)
|
||||
{
|
||||
g_state->is_initialized = 1;
|
||||
g_state->ball_px.f = 0;
|
||||
g_state->ball_py.f = 0;
|
||||
g_state->ball_dpx.f = initial_ball_speed;
|
||||
g_state->ball_dpy.f = 0;
|
||||
g_state->current_play_points.f = 10.f;
|
||||
g_state->player2_speed.f = 80.f;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
float speed = 80.f;
|
||||
|
||||
if (i == 1 && !g_state->player2_human)
|
||||
break;
|
||||
|
||||
g_state->player[i].dpy.f = 0.f;
|
||||
|
||||
if (is_down(input[i].buttons[B_SPEED_UP]))
|
||||
speed = 150.f;
|
||||
|
||||
if (is_down(input[i].buttons[B_MOVE_UP]))
|
||||
{
|
||||
if (g_state->player[i].py.f < playing_field_y - player_size_y)
|
||||
{
|
||||
g_state->player[i].dpy.f = speed;
|
||||
}
|
||||
|
||||
if (g_state->player[i].py.f < -playing_field_y + player_size_y)
|
||||
{
|
||||
g_state->player[i].py.f = -playing_field_y + player_size_y;
|
||||
g_state->player[i].dpy.f = 0.f;
|
||||
}
|
||||
}
|
||||
if (is_down(input[i].buttons[B_MOVE_DOWN]))
|
||||
{
|
||||
if (g_state->player[i].py.f > -playing_field_y + player_size_y)
|
||||
{
|
||||
g_state->player[i].dpy.f = -speed;
|
||||
}
|
||||
|
||||
if (g_state->player[i].py.f < -playing_field_y + player_size_y)
|
||||
{
|
||||
g_state->player[i].py.f = -playing_field_y + player_size_y;
|
||||
g_state->player[i].dpy.f = 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
g_state->player[i].py.f += g_state->player[i].dpy.f * input->last_dt;
|
||||
}
|
||||
|
||||
if (!g_state->player2_human)
|
||||
{
|
||||
g_state->player[1].dpy.f = (g_state->ball_py.f - g_state->player[1].py.f) * 100.f;
|
||||
g_state->player[1].dpy.f = MIN(g_state->player[1].dpy.f, g_state->player2_speed.f);
|
||||
g_state->player[1].dpy.f = MAX(g_state->player[1].dpy.f, -g_state->player2_speed.f);
|
||||
g_state->player[1].py.f += g_state->player[1].dpy.f * input->last_dt;
|
||||
|
||||
if (g_state->player[1].py.f < -playing_field_y + player_size_y)
|
||||
{
|
||||
g_state->player[1].py.f = -playing_field_y + player_size_y;
|
||||
g_state->player[1].dpy.f = 0.f;
|
||||
}
|
||||
|
||||
if (g_state->player[1].py.f > playing_field_y - player_size_y)
|
||||
{
|
||||
g_state->player[1].py.f = playing_field_y - player_size_y;
|
||||
g_state->player[1].dpy.f = 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
g_state->ball_px.f += g_state->ball_dpx.f * input->last_dt;
|
||||
|
||||
if (g_state->ball_dpx.f > 0)
|
||||
{
|
||||
g_state->ball_dpx.f += 10.f * input->last_dt;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_state->ball_dpx.f -= 10.f * input->last_dt;
|
||||
}
|
||||
|
||||
g_state->ball_py.f += g_state->ball_dpy.f * input->last_dt;
|
||||
|
||||
if (g_state->ball_py.f > playing_field_y - 1.f)
|
||||
{
|
||||
g_state->ball_py.f = playing_field_y - 1.f;
|
||||
g_state->ball_dpy.f *= -1.f;
|
||||
}
|
||||
else if (g_state->ball_py.f < -playing_field_y + 1)
|
||||
{
|
||||
g_state->ball_py.f = -playing_field_y + 1.f;
|
||||
g_state->ball_dpy.f *= -1;
|
||||
}
|
||||
|
||||
if (g_state->ball_px.f > 80.f - 2.5f - 1.f) /* @Hardcoded */
|
||||
{
|
||||
if ((g_state->ball_py.f >= (g_state->player[1].py.f - 10.f)) && (g_state->ball_py.f <= (g_state->player[1].py.f + 10.f)))
|
||||
{
|
||||
g_state->ball_dpx.f *= -1.f;
|
||||
g_state->ball_px.f = 80.f - 2.5f - 1.f; /* @Hardcoded */
|
||||
g_state->ball_dpy.f = (g_state->ball_py.f - g_state->player[1].py.f) + g_state->player[1].dpy.f;
|
||||
++g_state->current_play_points.f;
|
||||
}
|
||||
else if (g_state->ball_px.f >= playing_field_x - 1)
|
||||
{
|
||||
g_state->ball_px.f = 0;
|
||||
g_state->ball_py.f = 0;
|
||||
g_state->ball_dpy.f = 0;
|
||||
g_state->ball_dpx.f = -initial_ball_speed;
|
||||
g_state->player2_score += (unsigned)g_state->current_play_points.f;
|
||||
g_state->current_play_points.f = 10.f;
|
||||
}
|
||||
}
|
||||
else if (g_state->ball_px.f < -80 + 2.5f + 1.f) /* @Hardcoded */
|
||||
{
|
||||
if ((g_state->ball_py.f >= (g_state->player[0].py.f - 10.f)) && (g_state->ball_py.f <= (g_state->player[0].py.f + 10.f)))
|
||||
{
|
||||
g_state->ball_dpx.f *= -1.f;
|
||||
g_state->ball_px.f = -80 + 2.5f + 1.f; /* @Hardcoded */
|
||||
g_state->ball_dpy.f = (g_state->ball_py.f - g_state->player[0].py.f) + g_state->player[0].dpy.f;
|
||||
++g_state->current_play_points.f;
|
||||
}
|
||||
else if (g_state->ball_px.f <= -playing_field_x + 1)
|
||||
{
|
||||
g_state->ball_px.f = 0;
|
||||
g_state->ball_py.f = 0;
|
||||
g_state->ball_dpy.f = 0;
|
||||
g_state->ball_dpx.f = initial_ball_speed;
|
||||
g_state->player1_score += (unsigned)g_state->current_play_points.f;
|
||||
g_state->current_play_points.f = 10.f;
|
||||
|
||||
if (!g_state->player2_human)
|
||||
g_state->player2_speed.f += g_state->current_play_points.f * 0.01f;
|
||||
}
|
||||
}
|
||||
|
||||
clear(draw_buffer, 0x021077);
|
||||
draw_rect(draw_buffer, 0x000530, 0.f, 0.f, playing_field_x, playing_field_y);
|
||||
|
||||
draw_rect(draw_buffer, 0x00ffff, -80.f, g_state->player[0].py.f, player_size_x, player_size_y);
|
||||
draw_rect(draw_buffer, 0x00ffff, 80.f, g_state->player[1].py.f, player_size_x, player_size_y);
|
||||
|
||||
draw_rect(draw_buffer, 0xffff00, g_state->ball_px.f, g_state->ball_py.f, 1.f, 1.f);
|
||||
|
||||
draw_number(draw_buffer, (unsigned)g_state->current_play_points.f, 0xaaaaaa, 0.f, 38.f);
|
||||
draw_number(draw_buffer, g_state->player1_score, 0xff6611, 20.f, 38.f);
|
||||
draw_number(draw_buffer, g_state->player2_score, 0xff6611, -20.f, 38.f);
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
#include "../internal_cores.h"
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
global: retro_*;
|
||||
local: *;
|
||||
};
|
||||
+171
-1
@@ -209,6 +209,76 @@ static int database_cursor_iterate(libretrodb_cursor_t *cur,
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->genre = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "category"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->category = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "language"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->language = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "region"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->region = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "score"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->score = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "media"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->media = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "controls"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->controls = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "artstyle"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->artstyle = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "gameplay"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->gameplay = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "narrative"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->narrative = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "pacing"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->pacing = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "perspective"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->perspective = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "setting"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->setting = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "visual"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->visual = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "vehicular"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
db_info->vehicular = strdup(val_string);
|
||||
}
|
||||
else if (string_is_equal(str, "origin"))
|
||||
{
|
||||
if (!string_is_empty(val_string))
|
||||
@@ -274,6 +344,12 @@ static int database_cursor_iterate(libretrodb_cursor_t *cur,
|
||||
db_info->releaseyear = (unsigned)val->val.uint_;
|
||||
else if (string_is_equal(str, "rumble"))
|
||||
db_info->rumble_supported = (int)val->val.uint_;
|
||||
else if (string_is_equal(str, "achievements"))
|
||||
db_info->achievements = (int)val->val.uint_;
|
||||
else if (string_is_equal(str, "console_exclusive"))
|
||||
db_info->console_exclusive = (int)val->val.uint_;
|
||||
else if (string_is_equal(str, "platform_exclusive"))
|
||||
db_info->platform_exclusive = (int)val->val.uint_;
|
||||
else if (string_is_equal(str, "coop"))
|
||||
db_info->coop_supported = (int)val->val.uint_;
|
||||
else if (string_is_equal(str, "analog"))
|
||||
@@ -504,6 +580,34 @@ database_info_list_t *database_info_list_new(
|
||||
free(db_info.franchise);
|
||||
if (db_info.genre)
|
||||
free(db_info.genre);
|
||||
if (db_info.category)
|
||||
free(db_info.category);
|
||||
if (db_info.language)
|
||||
free(db_info.language);
|
||||
if (db_info.region)
|
||||
free(db_info.region);
|
||||
if (db_info.score)
|
||||
free(db_info.score);
|
||||
if (db_info.media)
|
||||
free(db_info.media);
|
||||
if (db_info.controls)
|
||||
free(db_info.controls);
|
||||
if (db_info.artstyle)
|
||||
free(db_info.artstyle);
|
||||
if (db_info.gameplay)
|
||||
free(db_info.gameplay);
|
||||
if (db_info.narrative)
|
||||
free(db_info.narrative);
|
||||
if (db_info.pacing)
|
||||
free(db_info.pacing);
|
||||
if (db_info.perspective)
|
||||
free(db_info.perspective);
|
||||
if (db_info.setting)
|
||||
free(db_info.setting);
|
||||
if (db_info.visual)
|
||||
free(db_info.visual);
|
||||
if (db_info.vehicular)
|
||||
free(db_info.vehicular);
|
||||
if (db_info.name)
|
||||
free(db_info.name);
|
||||
if (db_info.origin)
|
||||
@@ -520,6 +624,26 @@ database_info_list_t *database_info_list_new(
|
||||
free(db_info.md5);
|
||||
if (db_info.sha1)
|
||||
free(db_info.sha1);
|
||||
|
||||
db_info.name = NULL;
|
||||
db_info.rom_name = NULL;
|
||||
db_info.serial = NULL;
|
||||
db_info.genre = NULL;
|
||||
db_info.description = NULL;
|
||||
db_info.publisher = NULL;
|
||||
db_info.developer = NULL;
|
||||
db_info.origin = NULL;
|
||||
db_info.franchise = NULL;
|
||||
db_info.edge_magazine_review = NULL;
|
||||
db_info.cero_rating = NULL;
|
||||
db_info.pegi_rating = NULL;
|
||||
db_info.enhancement_hw = NULL;
|
||||
db_info.elspa_rating = NULL;
|
||||
db_info.esrb_rating = NULL;
|
||||
db_info.bbfc_rating = NULL;
|
||||
db_info.sha1 = NULL;
|
||||
db_info.md5 = NULL;
|
||||
|
||||
database_info_list_free(database_info_list);
|
||||
free(database_info);
|
||||
free(database_info_list);
|
||||
@@ -570,13 +694,40 @@ void database_info_list_free(database_info_list_t *database_info_list)
|
||||
free(info->serial);
|
||||
if (info->genre)
|
||||
free(info->genre);
|
||||
if (info->category)
|
||||
free(info->category);
|
||||
if (info->language)
|
||||
free(info->language);
|
||||
if (info->region)
|
||||
free(info->region);
|
||||
if (info->score)
|
||||
free(info->score);
|
||||
if (info->media)
|
||||
free(info->media);
|
||||
if (info->controls)
|
||||
free(info->controls);
|
||||
if (info->artstyle)
|
||||
free(info->artstyle);
|
||||
if (info->gameplay)
|
||||
free(info->gameplay);
|
||||
if (info->narrative)
|
||||
free(info->narrative);
|
||||
if (info->pacing)
|
||||
free(info->pacing);
|
||||
if (info->perspective)
|
||||
free(info->perspective);
|
||||
if (info->setting)
|
||||
free(info->setting);
|
||||
if (info->visual)
|
||||
free(info->visual);
|
||||
if (info->vehicular)
|
||||
free(info->vehicular);
|
||||
if (info->description)
|
||||
free(info->description);
|
||||
if (info->publisher)
|
||||
free(info->publisher);
|
||||
if (info->developer)
|
||||
string_list_free(info->developer);
|
||||
info->developer = NULL;
|
||||
if (info->origin)
|
||||
free(info->origin);
|
||||
if (info->franchise)
|
||||
@@ -600,6 +751,25 @@ void database_info_list_free(database_info_list_t *database_info_list)
|
||||
free(info->sha1);
|
||||
if (info->md5)
|
||||
free(info->md5);
|
||||
|
||||
info->name = NULL;
|
||||
info->rom_name = NULL;
|
||||
info->serial = NULL;
|
||||
info->genre = NULL;
|
||||
info->description = NULL;
|
||||
info->publisher = NULL;
|
||||
info->developer = NULL;
|
||||
info->origin = NULL;
|
||||
info->franchise = NULL;
|
||||
info->edge_magazine_review = NULL;
|
||||
info->cero_rating = NULL;
|
||||
info->pegi_rating = NULL;
|
||||
info->enhancement_hw = NULL;
|
||||
info->elspa_rating = NULL;
|
||||
info->esrb_rating = NULL;
|
||||
info->bbfc_rating = NULL;
|
||||
info->sha1 = NULL;
|
||||
info->md5 = NULL;
|
||||
}
|
||||
|
||||
free(database_info_list->list);
|
||||
|
||||
@@ -85,6 +85,23 @@ typedef struct
|
||||
char *serial;
|
||||
char *description;
|
||||
char *genre;
|
||||
int achievements;
|
||||
char *category;
|
||||
char *language;
|
||||
char *region;
|
||||
int console_exclusive;
|
||||
int platform_exclusive;
|
||||
char *score;
|
||||
char *media;
|
||||
char *controls;
|
||||
char *artstyle;
|
||||
char *gameplay;
|
||||
char *narrative;
|
||||
char *pacing;
|
||||
char *perspective;
|
||||
char *setting;
|
||||
char *visual;
|
||||
char *vehicular;
|
||||
char *publisher;
|
||||
struct string_list *developer;
|
||||
char *origin;
|
||||
|
||||
Vendored
+2
-3
@@ -212,9 +212,8 @@ WRes File_Seek(CSzFile *p, int64_t *pos, ESzSeek origin)
|
||||
WRes File_GetLength(CSzFile *p, uint64_t *length)
|
||||
{
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
|
||||
DWORD sizeHigh;
|
||||
DWORD sizeLow = GetFileSize(p->handle, &sizeHigh);
|
||||
DWORD sizeHigh = 0;
|
||||
DWORD sizeLow = GetFileSize(p->handle, &sizeHigh);
|
||||
if (sizeLow == 0xFFFFFFFF)
|
||||
{
|
||||
DWORD res = GetLastError();
|
||||
|
||||
Vendored
+365
@@ -0,0 +1,365 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2017-2019, Feral Interactive
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Feral Interactive nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#ifndef CLIENT_GAMEMODE_H
|
||||
#define CLIENT_GAMEMODE_H
|
||||
/*
|
||||
* GameMode supports the following client functions
|
||||
* Requests are refcounted in the daemon
|
||||
*
|
||||
* int gamemode_request_start() - Request gamemode starts
|
||||
* 0 if the request was sent successfully
|
||||
* -1 if the request failed
|
||||
*
|
||||
* int gamemode_request_end() - Request gamemode ends
|
||||
* 0 if the request was sent successfully
|
||||
* -1 if the request failed
|
||||
*
|
||||
* GAMEMODE_AUTO can be defined to make the above two functions apply during static init and
|
||||
* destruction, as appropriate. In this configuration, errors will be printed to stderr
|
||||
*
|
||||
* int gamemode_query_status() - Query the current status of gamemode
|
||||
* 0 if gamemode is inactive
|
||||
* 1 if gamemode is active
|
||||
* 2 if gamemode is active and this client is registered
|
||||
* -1 if the query failed
|
||||
*
|
||||
* int gamemode_request_start_for(pid_t pid) - Request gamemode starts for another process
|
||||
* 0 if the request was sent successfully
|
||||
* -1 if the request failed
|
||||
* -2 if the request was rejected
|
||||
*
|
||||
* int gamemode_request_end_for(pid_t pid) - Request gamemode ends for another process
|
||||
* 0 if the request was sent successfully
|
||||
* -1 if the request failed
|
||||
* -2 if the request was rejected
|
||||
*
|
||||
* int gamemode_query_status_for(pid_t pid) - Query status of gamemode for another process
|
||||
* 0 if gamemode is inactive
|
||||
* 1 if gamemode is active
|
||||
* 2 if gamemode is active and this client is registered
|
||||
* -1 if the query failed
|
||||
*
|
||||
* const char* gamemode_error_string() - Get an error string
|
||||
* returns a string describing any of the above errors
|
||||
*
|
||||
* Note: All the above requests can be blocking - dbus requests can and will block while the daemon
|
||||
* handles the request. It is not recommended to make these calls in performance critical code
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
static char internal_gamemode_client_error_string[512] = { 0 };
|
||||
|
||||
/**
|
||||
* Load libgamemode dynamically to dislodge us from most dependencies.
|
||||
* This allows clients to link and/or use this regardless of runtime.
|
||||
* See SDL2 for an example of the reasoning behind this in terms of
|
||||
* dynamic versioning as well.
|
||||
*/
|
||||
static volatile int internal_libgamemode_loaded = 1;
|
||||
|
||||
/* Typedefs for the functions to load */
|
||||
typedef int (*api_call_return_int)(void);
|
||||
typedef const char *(*api_call_return_cstring)(void);
|
||||
typedef int (*api_call_pid_return_int)(pid_t);
|
||||
|
||||
/* Storage for functors */
|
||||
static api_call_return_int REAL_internal_gamemode_request_start = NULL;
|
||||
static api_call_return_int REAL_internal_gamemode_request_end = NULL;
|
||||
static api_call_return_int REAL_internal_gamemode_query_status = NULL;
|
||||
static api_call_return_cstring REAL_internal_gamemode_error_string = NULL;
|
||||
static api_call_pid_return_int REAL_internal_gamemode_request_start_for = NULL;
|
||||
static api_call_pid_return_int REAL_internal_gamemode_request_end_for = NULL;
|
||||
static api_call_pid_return_int REAL_internal_gamemode_query_status_for = NULL;
|
||||
|
||||
/**
|
||||
* Internal helper to perform the symbol binding safely.
|
||||
*
|
||||
* Returns 0 on success and -1 on failure
|
||||
*/
|
||||
__attribute__((always_inline)) static inline int internal_bind_libgamemode_symbol(
|
||||
void *handle, const char *name, void **out_func, size_t func_size, bool required)
|
||||
{
|
||||
void *symbol_lookup = NULL;
|
||||
char *dl_error = NULL;
|
||||
|
||||
/* Safely look up the symbol */
|
||||
symbol_lookup = dlsym(handle, name);
|
||||
dl_error = dlerror();
|
||||
if (required && (dl_error || !symbol_lookup)) {
|
||||
snprintf(internal_gamemode_client_error_string,
|
||||
sizeof(internal_gamemode_client_error_string),
|
||||
"dlsym failed - %s",
|
||||
dl_error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Have the symbol correctly, copy it to make it usable */
|
||||
memcpy(out_func, &symbol_lookup, func_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads libgamemode and needed functions
|
||||
*
|
||||
* Returns 0 on success and -1 on failure
|
||||
*/
|
||||
__attribute__((always_inline)) static inline int internal_load_libgamemode(void)
|
||||
{
|
||||
/* We start at 1, 0 is a success and -1 is a fail */
|
||||
if (internal_libgamemode_loaded != 1) {
|
||||
return internal_libgamemode_loaded;
|
||||
}
|
||||
|
||||
/* Anonymous struct type to define our bindings */
|
||||
struct binding {
|
||||
const char *name;
|
||||
void **functor;
|
||||
size_t func_size;
|
||||
bool required;
|
||||
} bindings[] = {
|
||||
{ "real_gamemode_request_start",
|
||||
(void **)&REAL_internal_gamemode_request_start,
|
||||
sizeof(REAL_internal_gamemode_request_start),
|
||||
true },
|
||||
{ "real_gamemode_request_end",
|
||||
(void **)&REAL_internal_gamemode_request_end,
|
||||
sizeof(REAL_internal_gamemode_request_end),
|
||||
true },
|
||||
{ "real_gamemode_query_status",
|
||||
(void **)&REAL_internal_gamemode_query_status,
|
||||
sizeof(REAL_internal_gamemode_query_status),
|
||||
false },
|
||||
{ "real_gamemode_error_string",
|
||||
(void **)&REAL_internal_gamemode_error_string,
|
||||
sizeof(REAL_internal_gamemode_error_string),
|
||||
true },
|
||||
{ "real_gamemode_request_start_for",
|
||||
(void **)&REAL_internal_gamemode_request_start_for,
|
||||
sizeof(REAL_internal_gamemode_request_start_for),
|
||||
false },
|
||||
{ "real_gamemode_request_end_for",
|
||||
(void **)&REAL_internal_gamemode_request_end_for,
|
||||
sizeof(REAL_internal_gamemode_request_end_for),
|
||||
false },
|
||||
{ "real_gamemode_query_status_for",
|
||||
(void **)&REAL_internal_gamemode_query_status_for,
|
||||
sizeof(REAL_internal_gamemode_query_status_for),
|
||||
false },
|
||||
};
|
||||
|
||||
void *libgamemode = NULL;
|
||||
|
||||
/* Try and load libgamemode */
|
||||
libgamemode = dlopen("libgamemode.so.0", RTLD_NOW);
|
||||
if (!libgamemode) {
|
||||
/* Attempt to load unversioned library for compatibility with older
|
||||
* versions (as of writing, there are no ABI changes between the two -
|
||||
* this may need to change if ever ABI-breaking changes are made) */
|
||||
libgamemode = dlopen("libgamemode.so", RTLD_NOW);
|
||||
if (!libgamemode) {
|
||||
snprintf(internal_gamemode_client_error_string,
|
||||
sizeof(internal_gamemode_client_error_string),
|
||||
"dlopen failed - %s",
|
||||
dlerror());
|
||||
internal_libgamemode_loaded = -1;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Attempt to bind all symbols */
|
||||
for (size_t i = 0; i < sizeof(bindings) / sizeof(bindings[0]); i++) {
|
||||
struct binding *binder = &bindings[i];
|
||||
|
||||
if (internal_bind_libgamemode_symbol(libgamemode,
|
||||
binder->name,
|
||||
binder->functor,
|
||||
binder->func_size,
|
||||
binder->required)) {
|
||||
internal_libgamemode_loaded = -1;
|
||||
return -1;
|
||||
};
|
||||
}
|
||||
|
||||
/* Success */
|
||||
internal_libgamemode_loaded = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect to the real libgamemode
|
||||
*/
|
||||
__attribute__((always_inline)) static inline const char *gamemode_error_string(void)
|
||||
{
|
||||
/* If we fail to load the system gamemode, or we have an error string already, return our error
|
||||
* string instead of diverting to the system version */
|
||||
if (internal_load_libgamemode() < 0 || internal_gamemode_client_error_string[0] != '\0') {
|
||||
return internal_gamemode_client_error_string;
|
||||
}
|
||||
|
||||
return REAL_internal_gamemode_error_string();
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect to the real libgamemode
|
||||
* Allow automatically requesting game mode
|
||||
* Also prints errors as they happen.
|
||||
*/
|
||||
#ifdef GAMEMODE_AUTO
|
||||
__attribute__((constructor))
|
||||
#else
|
||||
__attribute__((always_inline)) static inline
|
||||
#endif
|
||||
int gamemode_request_start(void)
|
||||
{
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
#ifdef GAMEMODE_AUTO
|
||||
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (REAL_internal_gamemode_request_start() < 0) {
|
||||
#ifdef GAMEMODE_AUTO
|
||||
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Redirect to the real libgamemode */
|
||||
#ifdef GAMEMODE_AUTO
|
||||
__attribute__((destructor))
|
||||
#else
|
||||
__attribute__((always_inline)) static inline
|
||||
#endif
|
||||
int gamemode_request_end(void)
|
||||
{
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
#ifdef GAMEMODE_AUTO
|
||||
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (REAL_internal_gamemode_request_end() < 0) {
|
||||
#ifdef GAMEMODE_AUTO
|
||||
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Redirect to the real libgamemode */
|
||||
__attribute__((always_inline)) static inline int gamemode_query_status(void)
|
||||
{
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (REAL_internal_gamemode_query_status == NULL) {
|
||||
snprintf(internal_gamemode_client_error_string,
|
||||
sizeof(internal_gamemode_client_error_string),
|
||||
"gamemode_query_status missing (older host?)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return REAL_internal_gamemode_query_status();
|
||||
}
|
||||
|
||||
/* Redirect to the real libgamemode */
|
||||
__attribute__((always_inline)) static inline int gamemode_request_start_for(pid_t pid)
|
||||
{
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (REAL_internal_gamemode_request_start_for == NULL) {
|
||||
snprintf(internal_gamemode_client_error_string,
|
||||
sizeof(internal_gamemode_client_error_string),
|
||||
"gamemode_request_start_for missing (older host?)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return REAL_internal_gamemode_request_start_for(pid);
|
||||
}
|
||||
|
||||
/* Redirect to the real libgamemode */
|
||||
__attribute__((always_inline)) static inline int gamemode_request_end_for(pid_t pid)
|
||||
{
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (REAL_internal_gamemode_request_end_for == NULL) {
|
||||
snprintf(internal_gamemode_client_error_string,
|
||||
sizeof(internal_gamemode_client_error_string),
|
||||
"gamemode_request_end_for missing (older host?)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return REAL_internal_gamemode_request_end_for(pid);
|
||||
}
|
||||
|
||||
/* Redirect to the real libgamemode */
|
||||
__attribute__((always_inline)) static inline int gamemode_query_status_for(pid_t pid)
|
||||
{
|
||||
/* Need to load gamemode */
|
||||
if (internal_load_libgamemode() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (REAL_internal_gamemode_query_status_for == NULL) {
|
||||
snprintf(internal_gamemode_client_error_string,
|
||||
sizeof(internal_gamemode_client_error_string),
|
||||
"gamemode_query_status_for missing (older host?)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return REAL_internal_gamemode_query_status_for(pid);
|
||||
}
|
||||
|
||||
#endif // CLIENT_GAMEMODE_H
|
||||
Vendored
-684
@@ -1,684 +0,0 @@
|
||||
$Id: Changelog.txt,v 1.226 2016/12/16 08:57:19 nanard Exp $
|
||||
miniUPnP client Changelog.
|
||||
|
||||
2016/11/11:
|
||||
check strlen before memcmp in XML parsing portlistingparse.c
|
||||
fix build under SOLARIS and CYGWIN
|
||||
|
||||
2016/10/11:
|
||||
Add python 3 compatibility to IGD test
|
||||
|
||||
VERSION 2.0 : released 2016/04/19
|
||||
|
||||
2016/01/24:
|
||||
change miniwget to return HTTP status code
|
||||
increments API_VERSION to 16
|
||||
|
||||
2016/01/22:
|
||||
Improve UPNPIGD_IsConnected() to check if WAN address is not private.
|
||||
parse HTTP response status line in miniwget.c
|
||||
|
||||
2015/10/26:
|
||||
snprintf() overflow check. check overflow in simpleUPnPcommand2()
|
||||
|
||||
2015/10/25:
|
||||
fix compilation with old macs
|
||||
fix compilation with mingw32 (for Appveyor)
|
||||
fix python module for python <= 2.3
|
||||
|
||||
2015/10/08:
|
||||
Change sameport to localport
|
||||
see https://github.com/miniupnp/miniupnp/pull/120
|
||||
increments API_VERSION to 15
|
||||
|
||||
2015/09/15:
|
||||
Fix buffer overflow in igd_desc_parse.c/IGDstartelt()
|
||||
Discovered by Aleksandar Nikolic of Cisco Talos
|
||||
|
||||
2015/08/28:
|
||||
move ssdpDiscoverDevices() to minissdpc.c
|
||||
|
||||
2015/08/27:
|
||||
avoid unix socket leak in getDevicesFromMiniSSDPD()
|
||||
|
||||
2015/08/16:
|
||||
Also accept "Up" as ConnectionStatus value
|
||||
|
||||
2015/07/23:
|
||||
split getDevicesFromMiniSSDPD
|
||||
add ttl argument to upnpDiscover() functions
|
||||
increments API_VERSION to 14
|
||||
|
||||
2015/07/22:
|
||||
Read USN from SSDP messages.
|
||||
|
||||
2015/07/15:
|
||||
Check malloc/calloc
|
||||
|
||||
2015/06/16:
|
||||
update getDevicesFromMiniSSDPD() to process longer minissdpd
|
||||
responses
|
||||
|
||||
2015/05/22:
|
||||
add searchalltypes param to upnpDiscoverDevices()
|
||||
increments API_VERSION to 13
|
||||
|
||||
2015/04/30:
|
||||
upnpc: output version on the terminal
|
||||
|
||||
2015/04/27:
|
||||
_BSD_SOURCE is deprecated in favor of _DEFAULT_SOURCE
|
||||
fix CMakeLists.txt COMPILE_DEFINITIONS
|
||||
fix getDevicesFromMiniSSDPD() not setting scope_id
|
||||
improve -r command of upnpc command line tool
|
||||
|
||||
2014/11/17:
|
||||
search all :
|
||||
upnpDiscoverDevices() / upnpDiscoverAll() functions
|
||||
listdevices executable
|
||||
increment API_VERSION to 12
|
||||
validate igd_desc_parse
|
||||
|
||||
2014/11/13:
|
||||
increment API_VERSION to 11
|
||||
|
||||
2014/11/05:
|
||||
simplified function GetUPNPUrls()
|
||||
|
||||
2014/09/11:
|
||||
use remoteHost arg of DeletePortMapping
|
||||
|
||||
2014/09/06:
|
||||
Fix python3 build
|
||||
|
||||
2014/07/01:
|
||||
Fix parsing of IGD2 root descriptions
|
||||
|
||||
2014/06/10:
|
||||
rename LIBSPEC to MINIUPNP_LIBSPEC
|
||||
|
||||
2014/05/15:
|
||||
Add support for IGD2 AddAnyPortMapping and DeletePortMappingRange
|
||||
|
||||
2014/02/05:
|
||||
handle EINPROGRESS after connect()
|
||||
|
||||
2014/02/03:
|
||||
minixml now handle XML comments
|
||||
|
||||
VERSION 1.9 : released 2014/01/31
|
||||
|
||||
2014/01/31:
|
||||
added argument remoteHost to UPNP_GetSpecificPortMappingEntry()
|
||||
increment API_VERSION to 10
|
||||
|
||||
2013/12/09:
|
||||
--help and -h arguments in upnpc.c
|
||||
|
||||
2013/10/07:
|
||||
fixed potential buffer overrun in miniwget.c
|
||||
Modified UPNP_GetValidIGD() to check for ExternalIpAddress
|
||||
|
||||
2013/08/01:
|
||||
define MAXHOSTNAMELEN if not already done
|
||||
|
||||
2013/06/06:
|
||||
update upnpreplyparse to allow larger values (128 chars instead of 64)
|
||||
|
||||
2013/05/14:
|
||||
Update upnpreplyparse to take into account "empty" elements
|
||||
validate upnpreplyparse.c code with "make check"
|
||||
|
||||
2013/05/03:
|
||||
Fix Solaris build thanks to Maciej Małecki
|
||||
|
||||
2013/04/27:
|
||||
Fix testminiwget.sh for BSD
|
||||
|
||||
2013/03/23:
|
||||
Fixed Makefile for *BSD
|
||||
|
||||
2013/03/11:
|
||||
Update Makefile to use JNAerator version 0.11
|
||||
|
||||
2013/02/11:
|
||||
Fix testminiwget.sh for use with dash
|
||||
Use $(DESTDIR) in Makefile
|
||||
|
||||
VERSION 1.8 : released 2013/02/06
|
||||
|
||||
2012/10/16:
|
||||
fix testminiwget with no IPv6 support
|
||||
|
||||
2012/09/27:
|
||||
Rename all include guards to not clash with C99
|
||||
(7.1.3 Reserved identifiers).
|
||||
|
||||
2012/08/30:
|
||||
Added -e option to upnpc program (set description for port mappings)
|
||||
|
||||
2012/08/29:
|
||||
Python 3 support (thanks to Christopher Foo)
|
||||
|
||||
2012/08/11:
|
||||
Fix a memory link in UPNP_GetValidIGD()
|
||||
Try to handle scope id in link local IPv6 URL under MS Windows
|
||||
|
||||
2012/07/20:
|
||||
Disable HAS_IP_MREQN on DragonFly BSD
|
||||
|
||||
2012/06/28:
|
||||
GetUPNPUrls() now inserts scope into link-local IPv6 addresses
|
||||
|
||||
2012/06/23:
|
||||
More error return checks in upnpc.c
|
||||
#define MINIUPNPC_GET_SRC_ADDR enables receivedata() to get scope_id
|
||||
parseURL() now parses IPv6 addresses scope
|
||||
new parameter for miniwget() : IPv6 address scope
|
||||
increment API_VERSION to 9
|
||||
|
||||
2012/06/20:
|
||||
fixed CMakeLists.txt
|
||||
|
||||
2012/05/29
|
||||
Improvements in testminiwget.sh
|
||||
|
||||
VERSION 1.7 : released 2012/05/24
|
||||
|
||||
2012/05/01:
|
||||
Cleanup settings of CFLAGS in Makefile
|
||||
Fix signed/unsigned integer comparaisons
|
||||
|
||||
2012/04/20:
|
||||
Allow to specify protocol with TCP or UDP for -A option
|
||||
|
||||
2012/04/09:
|
||||
Only try to fetch XML description once in UPNP_GetValidIGD()
|
||||
Added -ansi flag to compilation, and fixed C++ comments to ANSI C comments.
|
||||
|
||||
2012/04/05:
|
||||
minor improvements to minihttptestserver.c
|
||||
|
||||
2012/03/15:
|
||||
upnperrors.c returns valid error string for unrecognized error codes
|
||||
|
||||
2012/03/08:
|
||||
make minihttptestserver listen on loopback interface instead of 0.0.0.0
|
||||
|
||||
2012/01/25:
|
||||
Maven installation thanks to Alexey Kuznetsov
|
||||
|
||||
2012/01/21:
|
||||
Replace WIN32 macro by _WIN32
|
||||
|
||||
2012/01/19:
|
||||
Fixes in java wrappers thanks to Alexey Kuznetsov :
|
||||
https://github.com/axet/miniupnp/tree/fix-javatest/miniupnpc
|
||||
Make and install .deb packages (python) thanks to Alexey Kuznetsov :
|
||||
https://github.com/axet/miniupnp/tree/feature-debbuild/miniupnpc
|
||||
|
||||
2012/01/07:
|
||||
The multicast interface can now be specified by name with IPv4.
|
||||
|
||||
2012/01/02:
|
||||
Install man page
|
||||
|
||||
2011/11/25:
|
||||
added header to Port Mappings list in upnpc.c
|
||||
|
||||
2011/10/09:
|
||||
Makefile : make clean now removes jnaerator generated files.
|
||||
MINIUPNPC_VERSION in miniupnpc.h (updated by make)
|
||||
|
||||
2011/09/12:
|
||||
added rootdescURL to UPNPUrls structure.
|
||||
|
||||
VERSION 1.6 : released 2011/07/25
|
||||
|
||||
2011/07/25:
|
||||
Update doc for version 1.6 release
|
||||
|
||||
2011/06/18:
|
||||
Fix for windows in miniwget.c
|
||||
|
||||
2011/06/04:
|
||||
display remote host in port mapping listing
|
||||
|
||||
2011/06/03:
|
||||
Fix in make install : there were missing headers
|
||||
|
||||
2011/05/26:
|
||||
Fix the socket leak in miniwget thanks to Richard Marsh.
|
||||
Permit to add leaseduration in -a command. Display lease duration.
|
||||
|
||||
2011/05/15:
|
||||
Try both LinkLocal and SiteLocal multicast address for SSDP in IPv6
|
||||
|
||||
2011/05/09:
|
||||
add a test in testminiwget.sh.
|
||||
more error checking in miniwget.c
|
||||
|
||||
2011/05/06:
|
||||
Adding some tool to test and validate miniwget.c
|
||||
simplified and debugged miniwget.c
|
||||
|
||||
2011/04/11:
|
||||
moving ReceiveData() to a receivedata.c file.
|
||||
parsing presentation url
|
||||
adding IGD v2 WANIPv6FirewallControl commands
|
||||
|
||||
2011/04/10:
|
||||
update of miniupnpcmodule.c
|
||||
comments in miniwget.c, update in testminiwget
|
||||
Adding errors codes from IGD v2
|
||||
new functions in upnpc.c for IGD v2
|
||||
|
||||
2011/04/09:
|
||||
Support for litteral ip v6 address in miniwget
|
||||
|
||||
2011/04/08:
|
||||
Adding support for urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
|
||||
Updating APIVERSION
|
||||
Supporting IPV6 in upnpDiscover()
|
||||
Adding a -6 option to upnpc command line tool
|
||||
|
||||
2011/03/18:
|
||||
miniwget/parseURL() : return an error when url param is null.
|
||||
fixing GetListOfPortMappings()
|
||||
|
||||
2011/03/14:
|
||||
upnpDiscover() now reporting an error code.
|
||||
improvements in comments.
|
||||
|
||||
2011/03/11:
|
||||
adding miniupnpcstrings.h.cmake and CMakeLists.txt files.
|
||||
|
||||
2011/02/15:
|
||||
Implementation of GetListOfPortMappings()
|
||||
|
||||
2011/02/07:
|
||||
updates to minixml to support character data starting with spaces
|
||||
minixml now support CDATA
|
||||
upnpreplyparse treats <NewPortListing> specificaly
|
||||
change in simpleUPnPcommand to return the buffer (simplification)
|
||||
|
||||
2011/02/06:
|
||||
Added leaseDuration argument to AddPortMapping()
|
||||
Starting to implement GetListOfPortMappings()
|
||||
|
||||
2011/01/11:
|
||||
updating wingenminiupnpcstrings.c
|
||||
|
||||
2011/01/04:
|
||||
improving updateminiupnpcstrings.sh
|
||||
|
||||
VERSION 1.5 : released 2011/01/01
|
||||
|
||||
2010/12/21:
|
||||
use NO_GETADDRINFO macro to disable the use of getaddrinfo/freeaddrinfo
|
||||
|
||||
2010/12/11:
|
||||
Improvements on getHTTPResponse() code.
|
||||
|
||||
2010/12/09:
|
||||
new code for miniwget that handle Chunked transfer encoding
|
||||
using getHTTPResponse() in SOAP call code
|
||||
Adding MANIFEST.in for 'python setup.py bdist_rpm'
|
||||
|
||||
2010/11/25:
|
||||
changes to minissdpc.c to compile under Win32.
|
||||
see http://miniupnp.tuxfamily.org/forum/viewtopic.php?t=729
|
||||
|
||||
2010/09/17:
|
||||
Various improvement to Makefile from Michał Górny
|
||||
|
||||
2010/08/05:
|
||||
Adding the script "external-ip.sh" from Reuben Hawkins
|
||||
|
||||
2010/06/09:
|
||||
update to python module to match modification made on 2010/04/05
|
||||
update to Java test code to match modification made on 2010/04/05
|
||||
all UPNP_* function now return an error if the SOAP request failed
|
||||
at HTTP level.
|
||||
|
||||
2010/04/17:
|
||||
Using GetBestRoute() under win32 in order to find the
|
||||
right interface to use.
|
||||
|
||||
2010/04/12:
|
||||
Retrying with HTTP/1.1 if HTTP/1.0 failed. see
|
||||
http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1703
|
||||
|
||||
2010/04/07:
|
||||
avoid returning duplicates in upnpDiscover()
|
||||
|
||||
2010/04/05:
|
||||
Create a connecthostport.h/.c with connecthostport() function
|
||||
and use it in miniwget and miniupnpc.
|
||||
Use getnameinfo() instead of inet_ntop or inet_ntoa
|
||||
Work to make miniupnpc IPV6 compatible...
|
||||
Add java test code.
|
||||
Big changes in order to support device having both WANIPConnection
|
||||
and WANPPPConnection.
|
||||
|
||||
2010/04/04:
|
||||
Use getaddrinfo() instead of gethostbyname() in miniwget.
|
||||
|
||||
2010/01/06:
|
||||
#define _DARWIN_C_SOURCE for Mac OS X
|
||||
|
||||
2009/12/19:
|
||||
Improve MinGW32 build
|
||||
|
||||
2009/12/11:
|
||||
adding a MSVC9 project to build the static library and executable
|
||||
|
||||
2009/12/10:
|
||||
Fixing some compilation stuff for Windows/MinGW
|
||||
|
||||
2009/12/07:
|
||||
adaptations in Makefile and updateminiupnpcstring.sh for AmigaOS
|
||||
some fixes for Windows when using virtual ethernet adapters (it is the
|
||||
case with VMWare installed).
|
||||
|
||||
2009/12/04:
|
||||
some fixes for AmigaOS compilation
|
||||
Changed HTTP version to HTTP/1.0 for Soap too (to prevent chunked
|
||||
transfer encoding)
|
||||
|
||||
2009/12/03:
|
||||
updating printIDG and testigddescparse.c for debug.
|
||||
modifications to compile under AmigaOS
|
||||
adding a testminiwget program
|
||||
Changed miniwget to advertise itself as HTTP/1.0 to prevent chunked
|
||||
transfer encoding
|
||||
|
||||
2009/11/26:
|
||||
fixing updateminiupnpcstrings.sh to take into account
|
||||
which command that does not return an error code.
|
||||
|
||||
VERSION 1.4 : released 2009/10/30
|
||||
|
||||
2009/10/16:
|
||||
using Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS in python module.
|
||||
|
||||
2009/10/10:
|
||||
Some fixes for compilation under Solaris
|
||||
compilation fixes : http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1464
|
||||
|
||||
2009/09/21:
|
||||
fixing the code to ignore EINTR during connect() calls.
|
||||
|
||||
2009/08/07:
|
||||
Set socket timeout for connect()
|
||||
Some cleanup in miniwget.c
|
||||
|
||||
2009/08/04:
|
||||
remove multiple redirections with -d in upnpc.c
|
||||
Print textual error code in upnpc.c
|
||||
Ignore EINTR during the connect() and poll() calls.
|
||||
|
||||
2009/07/29:
|
||||
fix in updateminiupnpcstrings.sh if OS name contains "/"
|
||||
Sending a correct value for MX: field in SSDP request
|
||||
|
||||
2009/07/20:
|
||||
Change the Makefile to compile under Mac OS X
|
||||
Fixed a stackoverflow in getDevicesFromMiniSSDPD()
|
||||
|
||||
2009/07/09:
|
||||
Compile under Haiku
|
||||
generate miniupnpcstrings.h.in from miniupnpcstrings.h
|
||||
|
||||
2009/06/04:
|
||||
patching to compile under CygWin and cross compile for minGW
|
||||
|
||||
VERSION 1.3 :
|
||||
|
||||
2009/04/17:
|
||||
updating python module
|
||||
Use strtoull() when using C99
|
||||
|
||||
2009/02/28:
|
||||
Fixed miniwget.c for compiling under sun
|
||||
|
||||
2008/12/18:
|
||||
cleanup in Makefile (thanks to Paul de Weerd)
|
||||
minissdpc.c : win32 compatibility
|
||||
miniupnpc.c : changed xmlns prefix from 'm' to 'u'
|
||||
Removed NDEBUG (using DEBUG)
|
||||
|
||||
2008/10/14:
|
||||
Added the ExternalHost argument to DeletePortMapping()
|
||||
|
||||
2008/10/11:
|
||||
Added the ExternalHost argument to AddPortMapping()
|
||||
Put a correct User-Agent: header in HTTP requests.
|
||||
|
||||
VERSION 1.2 :
|
||||
|
||||
2008/10/07:
|
||||
Update docs
|
||||
|
||||
2008/09/25:
|
||||
Integrated sameport patch from Dario Meloni : Added a "sameport"
|
||||
argument to upnpDiscover().
|
||||
|
||||
2008/07/18:
|
||||
small modif to make Clang happy :)
|
||||
|
||||
2008/07/17:
|
||||
#define SOAPPREFIX "s" in miniupnpc.c in order to remove SOAP-ENV...
|
||||
|
||||
2008/07/14:
|
||||
include declspec.h in installation (to /usr/include/miniupnpc)
|
||||
|
||||
VERSION 1.1 :
|
||||
|
||||
2008/07/04:
|
||||
standard options for install/ln instead of gnu-specific stuff.
|
||||
|
||||
2008/07/03:
|
||||
now builds a .dll and .lib with win32. (mingw32)
|
||||
|
||||
2008/04/28:
|
||||
make install now install the binary of the upnpc tool
|
||||
|
||||
2008/04/27:
|
||||
added testupnpigd.py
|
||||
added error strings for miniupnpc "internal" errors
|
||||
improved python module error/exception reporting.
|
||||
|
||||
2008/04/23:
|
||||
Completely rewrite igd_desc_parse.c in order to be compatible with
|
||||
Linksys WAG200G
|
||||
Added testigddescparse
|
||||
updated python module
|
||||
|
||||
VERSION 1.0 :
|
||||
|
||||
2008/02/21:
|
||||
put some #ifdef DEBUG around DisplayNameValueList()
|
||||
|
||||
2008/02/18:
|
||||
Improved error reporting in upnpcommands.c
|
||||
UPNP_GetStatusInfo() returns LastConnectionError
|
||||
|
||||
2008/02/16:
|
||||
better error handling in minisoap.c
|
||||
improving display of "valid IGD found" in upnpc.c
|
||||
|
||||
2008/02/03:
|
||||
Fixing UPNP_GetValidIGD()
|
||||
improved make install :)
|
||||
|
||||
2007/12/22:
|
||||
Adding upnperrors.c/h to provide a strupnperror() function
|
||||
used to translate UPnP error codes to string.
|
||||
|
||||
2007/12/19:
|
||||
Fixing getDevicesFromMiniSSDPD()
|
||||
improved error reporting of UPnP functions
|
||||
|
||||
2007/12/18:
|
||||
It is now possible to specify a different location for MiniSSDPd socket.
|
||||
working with MiniSSDPd is now more efficient.
|
||||
python module improved.
|
||||
|
||||
2007/12/16:
|
||||
improving error reporting
|
||||
|
||||
2007/12/13:
|
||||
Try to improve compatibility by using HTTP/1.0 instead of 1.1 and
|
||||
XML a bit different for SOAP.
|
||||
|
||||
2007/11/25:
|
||||
fixed select() call for linux
|
||||
|
||||
2007/11/15:
|
||||
Added -fPIC to CFLAG for better shared library code.
|
||||
|
||||
2007/11/02:
|
||||
Fixed a potential socket leak in miniwget2()
|
||||
|
||||
2007/10/16:
|
||||
added a parameter to upnpDiscover() in order to allow the use of another
|
||||
interface than the default multicast interface.
|
||||
|
||||
2007/10/12:
|
||||
Fixed the creation of symbolic link in Makefile
|
||||
|
||||
2007/10/08:
|
||||
Added man page
|
||||
|
||||
2007/10/02:
|
||||
fixed memory bug in GetUPNPUrls()
|
||||
|
||||
2007/10/01:
|
||||
fixes in the Makefile
|
||||
Added UPNP_GetIGDFromUrl() and adapted the sample program accordingly.
|
||||
Added SONAME in the shared library to please debian :)
|
||||
fixed MS Windows compilation (minissdpd is not available under MS Windows).
|
||||
|
||||
2007/09/25:
|
||||
small change to Makefile to be able to install in a different location
|
||||
(default is /usr)
|
||||
|
||||
2007/09/24:
|
||||
now compiling both shared and static library
|
||||
|
||||
2007/09/19:
|
||||
Cosmetic changes on upnpc.c
|
||||
|
||||
2007/09/02:
|
||||
adapting to new miniSSDPd (release version ?)
|
||||
|
||||
2007/08/31:
|
||||
Usage of miniSSDPd to skip discovery process.
|
||||
|
||||
2007/08/27:
|
||||
fixed python module to allow compilation with Python older than Python 2.4
|
||||
|
||||
2007/06/12:
|
||||
Added a python module.
|
||||
|
||||
2007/05/19:
|
||||
Fixed compilation under MinGW
|
||||
|
||||
2007/05/15:
|
||||
fixed a memory leak in AddPortMapping()
|
||||
Added testupnpreplyparse executable to check the parsing of
|
||||
upnp soap messages
|
||||
minixml now ignore namespace prefixes.
|
||||
|
||||
2007/04/26:
|
||||
upnpc now displays external ip address with -s or -l
|
||||
|
||||
2007/04/11:
|
||||
changed MINIUPNPC_URL_MAXSIZE to 128 to accomodate the "BT Voyager 210"
|
||||
|
||||
2007/03/19:
|
||||
cleanup in miniwget.c
|
||||
|
||||
2007/03/01:
|
||||
Small typo fix...
|
||||
|
||||
2007/01/30:
|
||||
Now parsing the HTTP header from SOAP responses in order to
|
||||
get content-length value.
|
||||
|
||||
2007/01/29:
|
||||
Fixed the Soap Query to speedup the HTTP request.
|
||||
added some Win32 DLL stuff...
|
||||
|
||||
2007/01/27:
|
||||
Fixed some WIN32 compatibility issues
|
||||
|
||||
2006/12/14:
|
||||
Added UPNPIGD_IsConnected() function in miniupnp.c/.h
|
||||
Added UPNP_GetValidIGD() in miniupnp.c/.h
|
||||
cleaned upnpc.c main(). now using UPNP_GetValidIGD()
|
||||
|
||||
2006/12/07:
|
||||
Version 1.0-RC1 released
|
||||
|
||||
2006/12/03:
|
||||
Minor changes to compile under SunOS/Solaris
|
||||
|
||||
2006/11/30:
|
||||
made a minixml parser validator program
|
||||
updated minixml to handle attributes correctly
|
||||
|
||||
2006/11/22:
|
||||
Added a -r option to the upnpc sample thanks to Alexander Hubmann.
|
||||
|
||||
2006/11/19:
|
||||
Cleanup code to make it more ANSI C compliant
|
||||
|
||||
2006/11/10:
|
||||
detect and display local lan address.
|
||||
|
||||
2006/11/04:
|
||||
Packets and Bytes Sent/Received are now unsigned int.
|
||||
|
||||
2006/11/01:
|
||||
Bug fix thanks to Giuseppe D'Angelo
|
||||
|
||||
2006/10/31:
|
||||
C++ compatibility for .h files.
|
||||
Added a way to get ip Address on the LAN used to reach the IGD.
|
||||
|
||||
2006/10/25:
|
||||
Added M-SEARCH to the services in the discovery process.
|
||||
|
||||
2006/10/22:
|
||||
updated the Makefile to use makedepend, added a "make install"
|
||||
update Makefile
|
||||
|
||||
2006/10/20:
|
||||
fixing the description url parsing thanks to patch sent by
|
||||
Wayne Dawe.
|
||||
Fixed/translated some comments.
|
||||
Implemented a better discover process, first looking
|
||||
for IGD then for root devices (as some devices only reply to
|
||||
M-SEARCH for root devices).
|
||||
|
||||
2006/09/02:
|
||||
added freeUPNPDevlist() function.
|
||||
|
||||
2006/08/04:
|
||||
More command line arguments checking
|
||||
|
||||
2006/08/01:
|
||||
Added the .bat file to compile under Win32 with minGW32
|
||||
|
||||
2006/07/31:
|
||||
Fixed the rootdesc parser (igd_desc_parse.c)
|
||||
|
||||
2006/07/20:
|
||||
parseMSEARCHReply() is now returning the ST: line as well
|
||||
starting changes to detect several UPnP devices on the network
|
||||
|
||||
2006/07/19:
|
||||
using GetCommonLinkProperties to get down/upload bitrate
|
||||
|
||||
Vendored
-27
@@ -1,27 +0,0 @@
|
||||
MiniUPnPc
|
||||
Copyright (c) 2005-2016, Thomas BERNARD
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Vendored
-5
@@ -1,5 +0,0 @@
|
||||
include README
|
||||
include miniupnpcmodule.c
|
||||
include setup.py
|
||||
include *.h
|
||||
include libminiupnpc.a
|
||||
Vendored
-274
@@ -1,274 +0,0 @@
|
||||
# $Id: Makefile,v 1.134 2016/10/07 09:04:36 nanard Exp $
|
||||
# MiniUPnP Project
|
||||
# http://miniupnp.free.fr/
|
||||
# http://miniupnp.tuxfamily.org/
|
||||
# https://github.com/miniupnp/miniupnp
|
||||
# (c) 2005-2016 Thomas Bernard
|
||||
# to install use :
|
||||
# $ make DESTDIR=/tmp/dummylocation install
|
||||
# or
|
||||
# $ INSTALLPREFIX=/usr/local make install
|
||||
# or
|
||||
# $ make install (default INSTALLPREFIX is /usr)
|
||||
OS = $(shell uname -s)
|
||||
VERSION = $(shell cat VERSION)
|
||||
|
||||
ifeq ($(OS), Darwin)
|
||||
JARSUFFIX=mac
|
||||
LIBTOOL ?= $(shell which libtool)
|
||||
endif
|
||||
ifeq ($(OS), Linux)
|
||||
JARSUFFIX=linux
|
||||
endif
|
||||
ifneq (,$(findstring NT-5.1,$(OS)))
|
||||
JARSUFFIX=win32
|
||||
endif
|
||||
|
||||
HAVE_IPV6 ?= yes
|
||||
export HAVE_IPV6
|
||||
|
||||
CC ?= gcc
|
||||
#AR = gar
|
||||
#CFLAGS = -O -g -DDEBUG
|
||||
CFLAGS ?= -O
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -W -Wstrict-prototypes
|
||||
CFLAGS += -fno-common
|
||||
CFLAGS += -DMINIUPNPC_SET_SOCKET_TIMEOUT
|
||||
CFLAGS += -DMINIUPNPC_GET_SRC_ADDR
|
||||
CFLAGS += -D_BSD_SOURCE
|
||||
CFLAGS += -D_DEFAULT_SOURCE
|
||||
ifeq ($(OS), NetBSD)
|
||||
CFLAGS += -D_NETBSD_SOURCE
|
||||
endif
|
||||
ifneq ($(OS), FreeBSD)
|
||||
ifneq ($(OS), Darwin)
|
||||
#CFLAGS += -D_POSIX_C_SOURCE=200112L
|
||||
CFLAGS += -D_XOPEN_SOURCE=600
|
||||
endif
|
||||
endif
|
||||
#CFLAGS += -ansi
|
||||
# -DNO_GETADDRINFO
|
||||
INSTALL = install
|
||||
SH = /bin/sh
|
||||
|
||||
ifeq (SunOS, $(OS))
|
||||
LDLIBS=-lsocket -lnsl -lresolv
|
||||
CFLAGS += -D__EXTENSIONS__
|
||||
CFLAGS += -std=c99
|
||||
endif
|
||||
|
||||
# APIVERSION is used to build SONAME
|
||||
APIVERSION = 16
|
||||
|
||||
SRCS = igd_desc_parse.c miniupnpc.c minixml.c minisoap.c miniwget.c \
|
||||
upnpcommands.c upnpreplyparse.c \
|
||||
minixmlvalid.c minissdpc.c \
|
||||
upnperrors.c \
|
||||
connecthostport.c portlistingparse.c receivedata.c \
|
||||
upnpdev.c miniupnpcmodule.c
|
||||
|
||||
LIBOBJS = miniwget.o minixml.o igd_desc_parse.o minisoap.o \
|
||||
miniupnpc.o upnpreplyparse.o upnpcommands.o upnperrors.o \
|
||||
connecthostport.o portlistingparse.o receivedata.o upnpdev.o
|
||||
|
||||
ifneq ($(OS), AmigaOS)
|
||||
ifeq (,$(findstring CYGWIN,$(OS)))
|
||||
CFLAGS := -fPIC $(CFLAGS)
|
||||
endif
|
||||
LIBOBJS := $(LIBOBJS) minissdpc.o
|
||||
endif
|
||||
|
||||
OBJS = $(patsubst %.c,%.o,$(SRCS))
|
||||
|
||||
# HEADERS to install
|
||||
HEADERS = miniupnpc.h miniwget.h upnpcommands.h igd_desc_parse.h \
|
||||
upnpreplyparse.h upnperrors.h miniupnpctypes.h \
|
||||
portlistingparse.h \
|
||||
upnpdev.h \
|
||||
miniupnpc_declspec.h
|
||||
|
||||
# library names
|
||||
LIBRARY = libminiupnpc.a
|
||||
ifeq ($(OS), Darwin)
|
||||
SHAREDLIBRARY = libminiupnpc.dylib
|
||||
SONAME = $(basename $(SHAREDLIBRARY)).$(APIVERSION).dylib
|
||||
CFLAGS := -D_DARWIN_C_SOURCE $(CFLAGS)
|
||||
else
|
||||
ifeq ($(JARSUFFIX), win32)
|
||||
SHAREDLIBRARY = miniupnpc.dll
|
||||
else
|
||||
# Linux/BSD/etc.
|
||||
SHAREDLIBRARY = libminiupnpc.so
|
||||
SONAME = $(SHAREDLIBRARY).$(APIVERSION)
|
||||
endif
|
||||
endif
|
||||
|
||||
EXECUTABLES = upnpc-static
|
||||
|
||||
ifneq ($(OS), AmigaOS)
|
||||
EXECUTABLES := $(EXECUTABLES) upnpc-shared
|
||||
endif
|
||||
|
||||
LIBDIR ?= lib
|
||||
# install directories
|
||||
ifeq ($(strip $(PREFIX)),)
|
||||
INSTALLPREFIX ?= /usr
|
||||
else
|
||||
INSTALLPREFIX ?= $(PREFIX)
|
||||
endif
|
||||
INSTALLDIRINC = $(INSTALLPREFIX)/include/miniupnpc
|
||||
INSTALLDIRLIB = $(INSTALLPREFIX)/$(LIBDIR)
|
||||
INSTALLDIRBIN = $(INSTALLPREFIX)/bin
|
||||
INSTALLDIRMAN = $(INSTALLPREFIX)/share/man
|
||||
|
||||
FILESTOINSTALL = $(LIBRARY) $(EXECUTABLES)
|
||||
ifneq ($(OS), AmigaOS)
|
||||
FILESTOINSTALL := $(FILESTOINSTALL) $(SHAREDLIBRARY)
|
||||
endif
|
||||
|
||||
|
||||
.PHONY: install clean depend all check test everything \
|
||||
updateversion
|
||||
# validateminixml validateminiwget
|
||||
|
||||
all: $(LIBRARY) $(EXECUTABLES)
|
||||
|
||||
test: check
|
||||
|
||||
check: validateminixml validateminiwget validateupnpreplyparse \
|
||||
validateportlistingparse validateigddescparse
|
||||
|
||||
everything: all
|
||||
|
||||
validateminixml: minixmlvalid
|
||||
@echo "minixml validation test"
|
||||
./minixmlvalid
|
||||
touch $@
|
||||
|
||||
validateminiwget: testminiwget minihttptestserver testminiwget.sh
|
||||
@echo "miniwget validation test"
|
||||
./testminiwget.sh
|
||||
touch $@
|
||||
|
||||
validateupnpreplyparse: testupnpreplyparse testupnpreplyparse.sh
|
||||
@echo "upnpreplyparse validation test"
|
||||
./testupnpreplyparse.sh
|
||||
touch $@
|
||||
|
||||
validateportlistingparse: testportlistingparse
|
||||
@echo "portlistingparse validation test"
|
||||
./testportlistingparse
|
||||
touch $@
|
||||
|
||||
validateigddescparse: testigddescparse
|
||||
@echo "igd desc parse validation test"
|
||||
./testigddescparse testdesc/new_LiveBox_desc.xml testdesc/new_LiveBox_desc.values
|
||||
./testigddescparse testdesc/linksys_WAG200G_desc.xml testdesc/linksys_WAG200G_desc.values
|
||||
touch $@
|
||||
|
||||
clean:
|
||||
$(RM) $(LIBRARY) $(SHAREDLIBRARY) $(EXECUTABLES) $(OBJS) miniupnpcstrings.h
|
||||
|
||||
distclean: clean
|
||||
|
||||
updateversion: miniupnpc.h
|
||||
cp miniupnpc.h miniupnpc.h.bak
|
||||
sed 's/\(.*MINIUPNPC_API_VERSION\s\+\)[0-9]\+/\1$(APIVERSION)/' < miniupnpc.h.bak > miniupnpc.h
|
||||
|
||||
install: updateversion $(FILESTOINSTALL)
|
||||
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRINC)
|
||||
$(INSTALL) -m 644 $(HEADERS) $(DESTDIR)$(INSTALLDIRINC)
|
||||
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRLIB)
|
||||
$(INSTALL) -m 644 $(LIBRARY) $(DESTDIR)$(INSTALLDIRLIB)
|
||||
ifneq ($(OS), AmigaOS)
|
||||
$(INSTALL) -m 644 $(SHAREDLIBRARY) $(DESTDIR)$(INSTALLDIRLIB)/$(SONAME)
|
||||
ln -fs $(SONAME) $(DESTDIR)$(INSTALLDIRLIB)/$(SHAREDLIBRARY)
|
||||
endif
|
||||
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRBIN)
|
||||
ifeq ($(OS), AmigaOS)
|
||||
$(INSTALL) -m 755 upnpc-static $(DESTDIR)$(INSTALLDIRBIN)/upnpc
|
||||
else
|
||||
$(INSTALL) -m 755 upnpc-shared $(DESTDIR)$(INSTALLDIRBIN)/upnpc
|
||||
endif
|
||||
$(INSTALL) -m 755 external-ip.sh $(DESTDIR)$(INSTALLDIRBIN)/external-ip
|
||||
ifneq ($(OS), AmigaOS)
|
||||
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRMAN)/man3
|
||||
$(INSTALL) -m 644 man3/miniupnpc.3 $(DESTDIR)$(INSTALLDIRMAN)/man3/miniupnpc.3
|
||||
ifeq ($(OS), Linux)
|
||||
gzip -f $(DESTDIR)$(INSTALLDIRMAN)/man3/miniupnpc.3
|
||||
endif
|
||||
endif
|
||||
|
||||
install-static: updateversion $(FILESTOINSTALL)
|
||||
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRINC)
|
||||
$(INSTALL) -m 644 $(HEADERS) $(DESTDIR)$(INSTALLDIRINC)
|
||||
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRLIB)
|
||||
$(INSTALL) -m 644 $(LIBRARY) $(DESTDIR)$(INSTALLDIRLIB)
|
||||
$(INSTALL) -d $(DESTDIR)$(INSTALLDIRBIN)
|
||||
$(INSTALL) -m 755 external-ip.sh $(DESTDIR)$(INSTALLDIRBIN)/external-ip
|
||||
|
||||
cleaninstall:
|
||||
$(RM) -r $(DESTDIR)$(INSTALLDIRINC)
|
||||
$(RM) $(DESTDIR)$(INSTALLDIRLIB)/$(LIBRARY)
|
||||
$(RM) $(DESTDIR)$(INSTALLDIRLIB)/$(SHAREDLIBRARY)
|
||||
|
||||
depend:
|
||||
makedepend -Y -- $(CFLAGS) -- $(SRCS) 2>/dev/null
|
||||
|
||||
$(LIBRARY): $(LIBOBJS)
|
||||
ifeq ($(OS), Darwin)
|
||||
$(LIBTOOL) -static -o $@ $?
|
||||
else
|
||||
$(AR) crs $@ $?
|
||||
endif
|
||||
|
||||
$(SHAREDLIBRARY): $(LIBOBJS)
|
||||
ifeq ($(OS), Darwin)
|
||||
# $(CC) -dynamiclib $(LDFLAGS) -Wl,-install_name,$(SONAME) -o $@ $^
|
||||
$(CC) -dynamiclib $(LDFLAGS) -Wl,-install_name,$(INSTALLDIRLIB)/$(SONAME) -o $@ $^
|
||||
else
|
||||
$(CC) -shared $(LDFLAGS) -Wl,-soname,$(SONAME) -o $@ $^
|
||||
endif
|
||||
|
||||
upnpc-static: $(LIBRARY)
|
||||
$(CC) $(LDFLAGS) -o $@ $^ $(LOADLIBES) $(LDLIBS)
|
||||
|
||||
upnpc-shared: $(SHAREDLIBRARY)
|
||||
$(CC) $(LDFLAGS) -o $@ $^ $(LOADLIBES) $(LDLIBS)
|
||||
|
||||
minixmlvalid: minixml.o minixmlvalid.o
|
||||
|
||||
miniupnpcstrings.h: miniupnpcstrings.h.in updateminiupnpcstrings.sh VERSION
|
||||
$(SH) updateminiupnpcstrings.sh
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
igd_desc_parse.o: igd_desc_parse.h
|
||||
miniupnpc.o: miniupnpc.h miniupnpc_declspec.h igd_desc_parse.h upnpdev.h
|
||||
miniupnpc.o: minissdpc.h miniwget.h minisoap.h minixml.h upnpcommands.h
|
||||
miniupnpc.o: upnpreplyparse.h portlistingparse.h miniupnpctypes.h
|
||||
miniupnpc.o: connecthostport.h
|
||||
minixml.o: minixml.h
|
||||
minisoap.o: minisoap.h miniupnpcstrings.h
|
||||
miniwget.o: miniupnpcstrings.h miniwget.h miniupnpc_declspec.h
|
||||
miniwget.o: connecthostport.h receivedata.h
|
||||
upnpcommands.o: upnpcommands.h upnpreplyparse.h portlistingparse.h
|
||||
upnpcommands.o: miniupnpc_declspec.h miniupnpctypes.h miniupnpc.h
|
||||
upnpcommands.o: igd_desc_parse.h upnpdev.h
|
||||
upnpreplyparse.o: upnpreplyparse.h minixml.h
|
||||
minixmlvalid.o: minixml.h
|
||||
minissdpc.o: minissdpc.h miniupnpc_declspec.h upnpdev.h miniupnpc.h
|
||||
minissdpc.o: igd_desc_parse.h receivedata.h codelength.h
|
||||
upnperrors.o: upnperrors.h miniupnpc_declspec.h upnpcommands.h
|
||||
upnperrors.o: upnpreplyparse.h portlistingparse.h miniupnpctypes.h
|
||||
upnperrors.o: miniupnpc.h igd_desc_parse.h upnpdev.h
|
||||
connecthostport.o: connecthostport.h
|
||||
portlistingparse.o: portlistingparse.h miniupnpc_declspec.h miniupnpctypes.h
|
||||
portlistingparse.o: minixml.h
|
||||
receivedata.o: receivedata.h
|
||||
upnpdev.o: upnpdev.h miniupnpc_declspec.h
|
||||
testportlistingparse.o: miniupnpctypes.h
|
||||
miniupnpcmodule.o: miniupnpc.h miniupnpc_declspec.h igd_desc_parse.h
|
||||
miniupnpcmodule.o: upnpdev.h upnpcommands.h upnpreplyparse.h
|
||||
miniupnpcmodule.o: portlistingparse.h miniupnpctypes.h upnperrors.h
|
||||
Vendored
-64
@@ -1,64 +0,0 @@
|
||||
Project: miniupnp
|
||||
Project web page: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
github: https://github.com/miniupnp/miniupnp
|
||||
freecode: http://freecode.com/projects/miniupnp
|
||||
Author: Thomas Bernard
|
||||
Copyright (c) 2005-2016 Thomas Bernard
|
||||
This software is subject to the conditions detailed in the
|
||||
LICENSE file provided within this distribution.
|
||||
|
||||
|
||||
* miniUPnP Client - miniUPnPc *
|
||||
|
||||
To compile, simply run 'gmake' (could be 'make' on your system).
|
||||
Under win32, to compile with MinGW, type "mingw32make.bat".
|
||||
MS Visual C solution and project files are supplied in the msvc/ subdirectory.
|
||||
|
||||
The compilation is known to work under linux, FreeBSD,
|
||||
OpenBSD, MacOS X, AmigaOS and cygwin.
|
||||
The official AmigaOS4.1 SDK was used for AmigaOS4 and GeekGadgets for AmigaOS3.
|
||||
upx (http://upx.sourceforge.net) is used to compress the win32 .exe files.
|
||||
|
||||
To install the library and headers on the system use :
|
||||
> su
|
||||
> make install
|
||||
> exit
|
||||
|
||||
alternatively, to install into a specific location, use :
|
||||
> INSTALLPREFIX=/usr/local make install
|
||||
|
||||
upnpc.c is a sample client using the libminiupnpc.
|
||||
To use the libminiupnpc in your application, link it with
|
||||
libminiupnpc.a (or .so) and use the following functions found in miniupnpc.h,
|
||||
upnpcommands.h and miniwget.h :
|
||||
- upnpDiscover()
|
||||
- UPNP_GetValidIGD()
|
||||
- miniwget()
|
||||
- parserootdesc()
|
||||
- GetUPNPUrls()
|
||||
- UPNP_* (calling UPNP methods)
|
||||
|
||||
Note : use #include <miniupnpc/miniupnpc.h> etc... for the includes
|
||||
and -lminiupnpc for the link
|
||||
|
||||
Discovery process is speeded up when MiniSSDPd is running on the machine.
|
||||
|
||||
|
||||
* Python module *
|
||||
|
||||
you can build a python module with 'make pythonmodule'
|
||||
and install it with 'make installpythonmodule'.
|
||||
setup.py (and setupmingw32.py) are included in the distribution.
|
||||
|
||||
|
||||
Feel free to contact me if you have any problem :
|
||||
e-mail : [email protected]
|
||||
|
||||
If you are using libminiupnpc in your application, please
|
||||
send me an email !
|
||||
|
||||
For any question, you can use the web forum :
|
||||
http://miniupnp.tuxfamily.org/forum/
|
||||
|
||||
Bugs should be reported on github :
|
||||
https://github.com/miniupnp/miniupnp/issues
|
||||
Vendored
-1
@@ -1 +0,0 @@
|
||||
2.0
|
||||
Vendored
-172
@@ -1,172 +0,0 @@
|
||||
$Id: apiversions.txt,v 1.9 2016/01/24 17:24:36 nanard Exp $
|
||||
|
||||
Differences in API between miniUPnPc versions
|
||||
|
||||
API version 16
|
||||
added "status_code" argument to getHTTPResponse(), miniwget() and miniwget_getaddr()
|
||||
updated macro :
|
||||
#define MINIUPNPC_API_VERSION 16
|
||||
|
||||
API version 15
|
||||
changed "sameport" argument of upnpDiscover() upnpDiscoverAll() upnpDiscoverDevice()
|
||||
to "localport". When 0 or 1, behaviour is not changed, but it can take
|
||||
any other value between 2 and 65535
|
||||
Existing programs should be compatible
|
||||
updated macro :
|
||||
#define MINIUPNPC_API_VERSION 15
|
||||
|
||||
API version 14
|
||||
miniupnpc.h
|
||||
add ttl argument to upnpDiscover() upnpDiscoverAll() upnpDiscoverDevice()
|
||||
upnpDiscoverDevices()
|
||||
getDevicesFromMiniSSDPD() :
|
||||
connectToMiniSSDPD() / disconnectFromMiniSSDPD()
|
||||
requestDevicesFromMiniSSDPD() / receiveDevicesFromMiniSSDPD()
|
||||
updated macro :
|
||||
#define MINIUPNPC_API_VERSION 14
|
||||
|
||||
API version 13
|
||||
miniupnpc.h:
|
||||
add searchalltype param to upnpDiscoverDevices() function
|
||||
updated macro :
|
||||
#define MINIUPNPC_API_VERSION 13
|
||||
|
||||
API version 12
|
||||
miniupnpc.h :
|
||||
add upnpDiscoverAll() / upnpDiscoverDevice() / upnpDiscoverDevices()
|
||||
functions
|
||||
updated macros :
|
||||
#define MINIUPNPC_API_VERSION 12
|
||||
|
||||
API version 11
|
||||
|
||||
upnpreplyparse.h / portlistingparse.h :
|
||||
removed usage of sys/queue.h / bsdqueue.h
|
||||
|
||||
miniupnpc.h:
|
||||
updated macros :
|
||||
#define MINIUPNPC_API_VERSION 11
|
||||
|
||||
====================== miniUPnPc version 1.9 ======================
|
||||
API version 10
|
||||
|
||||
upnpcommands.h:
|
||||
added argument remoteHost to UPNP_GetSpecificPortMappingEntry()
|
||||
|
||||
miniupnpc.h:
|
||||
updated macros :
|
||||
#define MINIUPNPC_VERSION "1.9"
|
||||
#define MINIUPNPC_API_VERSION 10
|
||||
|
||||
====================== miniUPnPc version 1.8 ======================
|
||||
API version 9
|
||||
|
||||
miniupnpc.h:
|
||||
updated macros :
|
||||
#define MINIUPNPC_VERSION "1.8"
|
||||
#define MINIUPNPC_API_VERSION 9
|
||||
added "unsigned int scope_id;" to struct UPNPDev
|
||||
added scope_id argument to GetUPNPUrls()
|
||||
|
||||
|
||||
|
||||
====================== miniUPnPc version 1.7 ======================
|
||||
API version 8
|
||||
|
||||
miniupnpc.h :
|
||||
add new macros :
|
||||
#define MINIUPNPC_VERSION "1.7"
|
||||
#define MINIUPNPC_API_VERSION 8
|
||||
add rootdescURL to struct UPNPUrls
|
||||
|
||||
|
||||
|
||||
====================== miniUPnPc version 1.6 ======================
|
||||
API version 8
|
||||
|
||||
Adding support for IPv6.
|
||||
igd_desc_parse.h :
|
||||
struct IGDdatas_service :
|
||||
add char presentationurl[MINIUPNPC_URL_MAXSIZE];
|
||||
struct IGDdatas :
|
||||
add struct IGDdatas_service IPv6FC;
|
||||
miniupnpc.h :
|
||||
new macros :
|
||||
#define UPNPDISCOVER_SUCCESS (0)
|
||||
#define UPNPDISCOVER_UNKNOWN_ERROR (-1)
|
||||
#define UPNPDISCOVER_SOCKET_ERROR (-101)
|
||||
#define UPNPDISCOVER_MEMORY_ERROR (-102)
|
||||
simpleUPnPcommand() prototype changed (but is normaly not used by API users)
|
||||
add arguments ipv6 and error to upnpDiscover() :
|
||||
struct UPNPDev *
|
||||
upnpDiscover(int delay, const char * multicastif,
|
||||
const char * minissdpdsock, int sameport,
|
||||
int ipv6,
|
||||
int * error);
|
||||
add controlURL_6FC member to struct UPNPUrls :
|
||||
struct UPNPUrls {
|
||||
char * controlURL;
|
||||
char * ipcondescURL;
|
||||
char * controlURL_CIF;
|
||||
char * controlURL_6FC;
|
||||
};
|
||||
|
||||
upnpcommands.h :
|
||||
add leaseDuration argument to UPNP_AddPortMapping()
|
||||
add desc, enabled and leaseDuration arguments to UPNP_GetSpecificPortMappingEntry()
|
||||
add UPNP_GetListOfPortMappings() function (IGDv2)
|
||||
add IGDv2 IPv6 related functions :
|
||||
UPNP_GetFirewallStatus()
|
||||
UPNP_GetOutboundPinholeTimeout()
|
||||
UPNP_AddPinhole()
|
||||
UPNP_UpdatePinhole()
|
||||
UPNP_DeletePinhole()
|
||||
UPNP_CheckPinholeWorking()
|
||||
UPNP_GetPinholePackets()
|
||||
|
||||
|
||||
|
||||
====================== miniUPnPc version 1.5 ======================
|
||||
API version 5
|
||||
|
||||
new function :
|
||||
int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *);
|
||||
new macro in upnpcommands.h :
|
||||
#define UPNPCOMMAND_HTTP_ERROR
|
||||
|
||||
====================== miniUPnPc version 1.4 ======================
|
||||
Same API as version 1.3
|
||||
|
||||
====================== miniUPnPc version 1.3 ======================
|
||||
API version 4
|
||||
|
||||
Use UNSIGNED_INTEGER type for
|
||||
UPNP_GetTotalBytesSent(), UPNP_GetTotalBytesReceived(),
|
||||
UPNP_GetTotalPacketsSent(), UPNP_GetTotalPacketsReceived()
|
||||
Add remoteHost argument to UPNP_AddPortMapping() and UPNP_DeletePortMapping()
|
||||
|
||||
====================== miniUPnPc version 1.2 ======================
|
||||
API version 3
|
||||
|
||||
added sameport argument to upnpDiscover()
|
||||
struct UPNPDev *
|
||||
upnpDiscover(int delay, const char * multicastif,
|
||||
const char * minissdpdsock, int sameport);
|
||||
|
||||
====================== miniUPnPc Version 1.1 ======================
|
||||
Same API as 1.0
|
||||
|
||||
|
||||
====================== miniUPnPc Version 1.0 ======================
|
||||
API version 2
|
||||
|
||||
|
||||
struct UPNPDev {
|
||||
struct UPNPDev * pNext;
|
||||
char * descURL;
|
||||
char * st;
|
||||
char buffer[2];
|
||||
};
|
||||
struct UPNPDev * upnpDiscover(int delay, const char * multicastif,
|
||||
const char * minissdpdsock);
|
||||
|
||||
Vendored
-54
@@ -1,54 +0,0 @@
|
||||
/* $Id: codelength.h,v 1.3 2011/07/30 13:10:05 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Author : Thomas BERNARD
|
||||
* copyright (c) 2005-2015 Thomas Bernard
|
||||
* This software is subjet to the conditions detailed in the
|
||||
* provided LICENCE file. */
|
||||
#ifndef CODELENGTH_H_INCLUDED
|
||||
#define CODELENGTH_H_INCLUDED
|
||||
|
||||
/* Encode length by using 7bit per Byte :
|
||||
* Most significant bit of each byte specifies that the
|
||||
* following byte is part of the code */
|
||||
|
||||
/* n : unsigned
|
||||
* p : unsigned char *
|
||||
*/
|
||||
#define DECODELENGTH(n, p) n = 0; \
|
||||
do { n = (n << 7) | (*p & 0x7f); } \
|
||||
while((*(p++)&0x80) && (n<(1<<25)));
|
||||
|
||||
/* n : unsigned
|
||||
* READ : function/macro to read one byte (unsigned char)
|
||||
*/
|
||||
#define DECODELENGTH_READ(n, READ) \
|
||||
n = 0; \
|
||||
do { \
|
||||
unsigned char c; \
|
||||
READ(c); \
|
||||
n = (n << 7) | (c & 0x07f); \
|
||||
if(!(c&0x80)) break; \
|
||||
} while(n<(1<<25));
|
||||
|
||||
/* n : unsigned
|
||||
* p : unsigned char *
|
||||
* p_limit : unsigned char *
|
||||
*/
|
||||
#define DECODELENGTH_CHECKLIMIT(n, p, p_limit) \
|
||||
n = 0; \
|
||||
do { \
|
||||
if((p) >= (p_limit)) break; \
|
||||
n = (n << 7) | (*(p) & 0x7f); \
|
||||
} while((*((p)++)&0x80) && (n<(1<<25)));
|
||||
|
||||
|
||||
/* n : unsigned
|
||||
* p : unsigned char *
|
||||
*/
|
||||
#define CODELENGTH(n, p) if(n>=268435456) *(p++) = (n >> 28) | 0x80; \
|
||||
if(n>=2097152) *(p++) = (n >> 21) | 0x80; \
|
||||
if(n>=16384) *(p++) = (n >> 14) | 0x80; \
|
||||
if(n>=128) *(p++) = (n >> 7) | 0x80; \
|
||||
*(p++) = n & 0x7f;
|
||||
|
||||
#endif /* CODELENGTH_H_INCLUDED */
|
||||
Vendored
-245
@@ -1,245 +0,0 @@
|
||||
/* $Id: connecthostport.c,v 1.15 2015/10/09 16:26:19 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2010-2016 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution. */
|
||||
|
||||
/* use getaddrinfo() or gethostbyname()
|
||||
* uncomment the following line in order to use gethostbyname() */
|
||||
#ifdef NO_GETADDRINFO
|
||||
#define USE_GETHOSTBYNAME
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <io.h>
|
||||
#define MAXHOSTNAMELEN 64
|
||||
#define snprintf _snprintf
|
||||
#define herror
|
||||
#define socklen_t int
|
||||
#else /* #ifdef _WIN32 */
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
|
||||
#include <sys/time.h>
|
||||
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
|
||||
#include <sys/param.h>
|
||||
#include <sys/select.h>
|
||||
#include <errno.h>
|
||||
#ifndef closesocket
|
||||
#define closesocket close
|
||||
#endif
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions
|
||||
* during the connect() call */
|
||||
#define MINIUPNPC_IGNORE_EINTR
|
||||
#ifndef USE_GETHOSTBYNAME
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
#endif /* #ifndef USE_GETHOSTBYNAME */
|
||||
#endif /* #else _WIN32 */
|
||||
|
||||
#if defined(__amigaos__) || defined(__amigaos4__)
|
||||
#define herror(A) printf("%s\n", A)
|
||||
#endif
|
||||
|
||||
#include <net/net_compat.h>
|
||||
|
||||
#include "connecthostport.h"
|
||||
|
||||
#ifndef MAXHOSTNAMELEN
|
||||
#define MAXHOSTNAMELEN 64
|
||||
#endif
|
||||
|
||||
/* connecthostport()
|
||||
* return a socket connected (TCP) to the host and port
|
||||
* or -1 in case of error */
|
||||
int connecthostport(const char * host, unsigned short port,
|
||||
unsigned int scope_id)
|
||||
{
|
||||
int s, n;
|
||||
#ifdef USE_GETHOSTBYNAME
|
||||
struct sockaddr_in dest;
|
||||
struct hostent *hp;
|
||||
#else /* #ifdef USE_GETHOSTBYNAME */
|
||||
char tmp_host[MAXHOSTNAMELEN+1];
|
||||
char port_str[8];
|
||||
struct addrinfo *ai, *p;
|
||||
struct addrinfo hints;
|
||||
#endif /* #ifdef USE_GETHOSTBYNAME */
|
||||
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
|
||||
struct timeval timeout;
|
||||
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
|
||||
|
||||
#ifdef USE_GETHOSTBYNAME
|
||||
hp = gethostbyname(host);
|
||||
if(hp == NULL)
|
||||
{
|
||||
herror(host);
|
||||
return -1;
|
||||
}
|
||||
memcpy(&dest.sin_addr, hp->h_addr, sizeof(dest.sin_addr));
|
||||
memset(dest.sin_zero, 0, sizeof(dest.sin_zero));
|
||||
s = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if(s < 0)
|
||||
return -1;
|
||||
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
|
||||
/* setting a 3 seconds timeout for the connect() call */
|
||||
timeout.tv_sec = 3;
|
||||
timeout.tv_usec = 0;
|
||||
if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0)
|
||||
{
|
||||
}
|
||||
timeout.tv_sec = 3;
|
||||
timeout.tv_usec = 0;
|
||||
if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0)
|
||||
{
|
||||
}
|
||||
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
|
||||
dest.sin_family = AF_INET;
|
||||
dest.sin_port = htons(port);
|
||||
n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in));
|
||||
#ifdef MINIUPNPC_IGNORE_EINTR
|
||||
/* EINTR The system call was interrupted by a signal that was caught
|
||||
* EINPROGRESS The socket is nonblocking and the connection cannot
|
||||
* be completed immediately. */
|
||||
while(n < 0 && (errno == EINTR || errno == EINPROGRESS))
|
||||
{
|
||||
socklen_t len;
|
||||
fd_set wset;
|
||||
int err;
|
||||
FD_ZERO(&wset);
|
||||
FD_SET(s, &wset);
|
||||
if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR)
|
||||
continue;
|
||||
/*len = 0;*/
|
||||
/*n = getpeername(s, NULL, &len);*/
|
||||
len = sizeof(err);
|
||||
if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) {
|
||||
closesocket(s);
|
||||
return -1;
|
||||
}
|
||||
if(err != 0) {
|
||||
errno = err;
|
||||
n = -1;
|
||||
}
|
||||
}
|
||||
#endif /* #ifdef MINIUPNPC_IGNORE_EINTR */
|
||||
if(n<0)
|
||||
{
|
||||
closesocket(s);
|
||||
return -1;
|
||||
}
|
||||
#else /* #ifdef USE_GETHOSTBYNAME */
|
||||
/* use getaddrinfo() instead of gethostbyname() */
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
/* hints.ai_flags = AI_ADDRCONFIG; */
|
||||
#ifdef AI_NUMERICSERV
|
||||
hints.ai_flags = AI_NUMERICSERV;
|
||||
#endif
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_family = AF_UNSPEC; /* AF_INET, AF_INET6 or AF_UNSPEC */
|
||||
/* hints.ai_protocol = IPPROTO_TCP; */
|
||||
snprintf(port_str, sizeof(port_str), "%hu", port);
|
||||
if(host[0] == '[')
|
||||
{
|
||||
/* literal ip v6 address */
|
||||
int i, j;
|
||||
for(i = 0, j = 1; host[j] && (host[j] != ']') && i < MAXHOSTNAMELEN; i++, j++)
|
||||
{
|
||||
tmp_host[i] = host[j];
|
||||
if(0 == memcmp(host+j, "%25", 3)) /* %25 is just url encoding for '%' */
|
||||
j+=2; /* skip "25" */
|
||||
}
|
||||
tmp_host[i] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(tmp_host, host, MAXHOSTNAMELEN);
|
||||
}
|
||||
tmp_host[MAXHOSTNAMELEN] = '\0';
|
||||
n = getaddrinfo_retro(tmp_host, port_str, &hints, &ai);
|
||||
if(n != 0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
fprintf(stderr, "getaddrinfo() error : %d\n", n);
|
||||
#else
|
||||
fprintf(stderr, "getaddrinfo() error : %s\n", gai_strerror(n));
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
s = -1;
|
||||
for(p = ai; p; p = p->ai_next)
|
||||
{
|
||||
s = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
|
||||
if(s < 0)
|
||||
continue;
|
||||
if(p->ai_addr->sa_family == AF_INET6 && scope_id > 0) {
|
||||
struct sockaddr_in6 * addr6 = (struct sockaddr_in6 *)p->ai_addr;
|
||||
addr6->sin6_scope_id = scope_id;
|
||||
}
|
||||
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
|
||||
/* setting a 3 seconds timeout for the connect() call */
|
||||
timeout.tv_sec = 3;
|
||||
timeout.tv_usec = 0;
|
||||
if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(struct timeval)) < 0)
|
||||
{
|
||||
}
|
||||
timeout.tv_sec = 3;
|
||||
timeout.tv_usec = 0;
|
||||
if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(struct timeval)) < 0)
|
||||
{
|
||||
}
|
||||
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
|
||||
n = connect(s, p->ai_addr, p->ai_addrlen);
|
||||
#ifdef MINIUPNPC_IGNORE_EINTR
|
||||
/* EINTR The system call was interrupted by a signal that was caught
|
||||
* EINPROGRESS The socket is nonblocking and the connection cannot
|
||||
* be completed immediately. */
|
||||
while(n < 0 && (errno == EINTR || errno == EINPROGRESS))
|
||||
{
|
||||
socklen_t len;
|
||||
fd_set wset;
|
||||
int err;
|
||||
FD_ZERO(&wset);
|
||||
FD_SET(s, &wset);
|
||||
if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR)
|
||||
continue;
|
||||
/*len = 0;*/
|
||||
/*n = getpeername(s, NULL, &len);*/
|
||||
len = sizeof(err);
|
||||
if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) {
|
||||
closesocket(s);
|
||||
freeaddrinfo(ai);
|
||||
return -1;
|
||||
}
|
||||
if(err != 0) {
|
||||
errno = err;
|
||||
n = -1;
|
||||
}
|
||||
}
|
||||
#endif /* #ifdef MINIUPNPC_IGNORE_EINTR */
|
||||
if(n < 0)
|
||||
{
|
||||
closesocket(s);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
freeaddrinfo(ai);
|
||||
if(s < 0)
|
||||
return -1;
|
||||
if(n < 0)
|
||||
return -1;
|
||||
#endif /* #ifdef USE_GETHOSTBYNAME */
|
||||
return s;
|
||||
}
|
||||
|
||||
Vendored
-18
@@ -1,18 +0,0 @@
|
||||
/* $Id: connecthostport.h,v 1.2 2012/06/23 22:32:33 nanard Exp $ */
|
||||
/* Project: miniupnp
|
||||
* http://miniupnp.free.fr/
|
||||
* Author: Thomas Bernard
|
||||
* Copyright (c) 2010-2012 Thomas Bernard
|
||||
* This software is subjects to the conditions detailed
|
||||
* in the LICENCE file provided within this distribution */
|
||||
#ifndef CONNECTHOSTPORT_H_INCLUDED
|
||||
#define CONNECTHOSTPORT_H_INCLUDED
|
||||
|
||||
/* connecthostport()
|
||||
* return a socket connected (TCP) to the host and port
|
||||
* or -1 in case of error */
|
||||
int connecthostport(const char * host, unsigned short port,
|
||||
unsigned int scope_id);
|
||||
|
||||
#endif
|
||||
|
||||
Vendored
-123
@@ -1,123 +0,0 @@
|
||||
/* $Id: igd_desc_parse.c,v 1.17 2015/09/15 13:30:04 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* http://miniupnp.free.fr/
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005-2015 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution. */
|
||||
|
||||
#include "igd_desc_parse.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Start element handler :
|
||||
* update nesting level counter and copy element name */
|
||||
void IGDstartelt(void * d, const char * name, int l)
|
||||
{
|
||||
struct IGDdatas * datas = (struct IGDdatas *)d;
|
||||
if(l >= MINIUPNPC_URL_MAXSIZE)
|
||||
l = MINIUPNPC_URL_MAXSIZE-1;
|
||||
memcpy(datas->cureltname, name, l);
|
||||
datas->cureltname[l] = '\0';
|
||||
datas->level++;
|
||||
if( (l==7) && !memcmp(name, "service", l) ) {
|
||||
datas->tmp.controlurl[0] = '\0';
|
||||
datas->tmp.eventsuburl[0] = '\0';
|
||||
datas->tmp.scpdurl[0] = '\0';
|
||||
datas->tmp.servicetype[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
#define COMPARE(str, cstr) (0==memcmp(str, cstr, sizeof(cstr) - 1))
|
||||
|
||||
/* End element handler :
|
||||
* update nesting level counter and update parser state if
|
||||
* service element is parsed */
|
||||
void IGDendelt(void * d, const char * name, int l)
|
||||
{
|
||||
struct IGDdatas * datas = (struct IGDdatas *)d;
|
||||
datas->level--;
|
||||
/*printf("endelt %2d %.*s\n", datas->level, l, name);*/
|
||||
if( (l==7) && !memcmp(name, "service", l) )
|
||||
{
|
||||
if(COMPARE(datas->tmp.servicetype,
|
||||
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:")) {
|
||||
memcpy(&datas->CIF, &datas->tmp, sizeof(struct IGDdatas_service));
|
||||
} else if(COMPARE(datas->tmp.servicetype,
|
||||
"urn:schemas-upnp-org:service:WANIPv6FirewallControl:")) {
|
||||
memcpy(&datas->IPv6FC, &datas->tmp, sizeof(struct IGDdatas_service));
|
||||
} else if(COMPARE(datas->tmp.servicetype,
|
||||
"urn:schemas-upnp-org:service:WANIPConnection:")
|
||||
|| COMPARE(datas->tmp.servicetype,
|
||||
"urn:schemas-upnp-org:service:WANPPPConnection:") ) {
|
||||
if(datas->first.servicetype[0] == '\0') {
|
||||
memcpy(&datas->first, &datas->tmp, sizeof(struct IGDdatas_service));
|
||||
} else {
|
||||
memcpy(&datas->second, &datas->tmp, sizeof(struct IGDdatas_service));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Data handler :
|
||||
* copy data depending on the current element name and state */
|
||||
void IGDdata(void * d, const char * data, int l)
|
||||
{
|
||||
struct IGDdatas * datas = (struct IGDdatas *)d;
|
||||
char * dstmember = 0;
|
||||
/*printf("%2d %s : %.*s\n",
|
||||
datas->level, datas->cureltname, l, data); */
|
||||
if( !strcmp(datas->cureltname, "URLBase") )
|
||||
dstmember = datas->urlbase;
|
||||
else if( !strcmp(datas->cureltname, "presentationURL") )
|
||||
dstmember = datas->presentationurl;
|
||||
else if( !strcmp(datas->cureltname, "serviceType") )
|
||||
dstmember = datas->tmp.servicetype;
|
||||
else if( !strcmp(datas->cureltname, "controlURL") )
|
||||
dstmember = datas->tmp.controlurl;
|
||||
else if( !strcmp(datas->cureltname, "eventSubURL") )
|
||||
dstmember = datas->tmp.eventsuburl;
|
||||
else if( !strcmp(datas->cureltname, "SCPDURL") )
|
||||
dstmember = datas->tmp.scpdurl;
|
||||
/* else if( !strcmp(datas->cureltname, "deviceType") )
|
||||
dstmember = datas->devicetype_tmp;*/
|
||||
if(dstmember)
|
||||
{
|
||||
if(l>=MINIUPNPC_URL_MAXSIZE)
|
||||
l = MINIUPNPC_URL_MAXSIZE-1;
|
||||
memcpy(dstmember, data, l);
|
||||
dstmember[l] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void printIGD(struct IGDdatas * d)
|
||||
{
|
||||
printf("urlbase = '%s'\n", d->urlbase);
|
||||
printf("WAN Device (Common interface config) :\n");
|
||||
/*printf(" deviceType = '%s'\n", d->CIF.devicetype);*/
|
||||
printf(" serviceType = '%s'\n", d->CIF.servicetype);
|
||||
printf(" controlURL = '%s'\n", d->CIF.controlurl);
|
||||
printf(" eventSubURL = '%s'\n", d->CIF.eventsuburl);
|
||||
printf(" SCPDURL = '%s'\n", d->CIF.scpdurl);
|
||||
printf("primary WAN Connection Device (IP or PPP Connection):\n");
|
||||
/*printf(" deviceType = '%s'\n", d->first.devicetype);*/
|
||||
printf(" servicetype = '%s'\n", d->first.servicetype);
|
||||
printf(" controlURL = '%s'\n", d->first.controlurl);
|
||||
printf(" eventSubURL = '%s'\n", d->first.eventsuburl);
|
||||
printf(" SCPDURL = '%s'\n", d->first.scpdurl);
|
||||
printf("secondary WAN Connection Device (IP or PPP Connection):\n");
|
||||
/*printf(" deviceType = '%s'\n", d->second.devicetype);*/
|
||||
printf(" servicetype = '%s'\n", d->second.servicetype);
|
||||
printf(" controlURL = '%s'\n", d->second.controlurl);
|
||||
printf(" eventSubURL = '%s'\n", d->second.eventsuburl);
|
||||
printf(" SCPDURL = '%s'\n", d->second.scpdurl);
|
||||
printf("WAN IPv6 Firewall Control :\n");
|
||||
/*printf(" deviceType = '%s'\n", d->IPv6FC.devicetype);*/
|
||||
printf(" servicetype = '%s'\n", d->IPv6FC.servicetype);
|
||||
printf(" controlURL = '%s'\n", d->IPv6FC.controlurl);
|
||||
printf(" eventSubURL = '%s'\n", d->IPv6FC.eventsuburl);
|
||||
printf(" SCPDURL = '%s'\n", d->IPv6FC.scpdurl);
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
Vendored
-49
@@ -1,49 +0,0 @@
|
||||
/* $Id: igd_desc_parse.h,v 1.12 2014/11/17 17:19:13 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* http://miniupnp.free.fr/
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005-2014 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution.
|
||||
* */
|
||||
#ifndef IGD_DESC_PARSE_H_INCLUDED
|
||||
#define IGD_DESC_PARSE_H_INCLUDED
|
||||
|
||||
/* Structure to store the result of the parsing of UPnP
|
||||
* descriptions of Internet Gateway Devices */
|
||||
#define MINIUPNPC_URL_MAXSIZE (128)
|
||||
struct IGDdatas_service {
|
||||
char controlurl[MINIUPNPC_URL_MAXSIZE];
|
||||
char eventsuburl[MINIUPNPC_URL_MAXSIZE];
|
||||
char scpdurl[MINIUPNPC_URL_MAXSIZE];
|
||||
char servicetype[MINIUPNPC_URL_MAXSIZE];
|
||||
/*char devicetype[MINIUPNPC_URL_MAXSIZE];*/
|
||||
};
|
||||
|
||||
struct IGDdatas {
|
||||
char cureltname[MINIUPNPC_URL_MAXSIZE];
|
||||
char urlbase[MINIUPNPC_URL_MAXSIZE];
|
||||
char presentationurl[MINIUPNPC_URL_MAXSIZE];
|
||||
int level;
|
||||
/*int state;*/
|
||||
/* "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" */
|
||||
struct IGDdatas_service CIF;
|
||||
/* "urn:schemas-upnp-org:service:WANIPConnection:1"
|
||||
* "urn:schemas-upnp-org:service:WANPPPConnection:1" */
|
||||
struct IGDdatas_service first;
|
||||
/* if both WANIPConnection and WANPPPConnection are present */
|
||||
struct IGDdatas_service second;
|
||||
/* "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1" */
|
||||
struct IGDdatas_service IPv6FC;
|
||||
/* tmp */
|
||||
struct IGDdatas_service tmp;
|
||||
};
|
||||
|
||||
void IGDstartelt(void *, const char *, int);
|
||||
void IGDendelt(void *, const char *, int);
|
||||
void IGDdata(void *, const char *, int);
|
||||
#ifdef DEBUG
|
||||
void printIGD(struct IGDdatas *);
|
||||
#endif /* DEBUG */
|
||||
|
||||
#endif /* IGD_DESC_PARSE_H_INCLUDED */
|
||||
Vendored
-105
@@ -1,105 +0,0 @@
|
||||
/* $Id: minisoap.c,v 1.23 2014/11/04 22:31:55 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005-2015 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution.
|
||||
*
|
||||
* Minimal SOAP implementation for UPnP protocol.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#include <winsock2.h>
|
||||
#define snprintf _snprintf
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include "minisoap.h"
|
||||
#include "miniupnpcstrings.h"
|
||||
|
||||
/* only for malloc */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* httpWrite sends the headers and the body to the socket
|
||||
* and returns the number of bytes sent */
|
||||
static int
|
||||
httpWrite(int fd, const char * body, int bodysize,
|
||||
const char * headers, int headerssize)
|
||||
{
|
||||
int n = 0;
|
||||
/*n = write(fd, headers, headerssize);*/
|
||||
/*if(bodysize>0)
|
||||
n += write(fd, body, bodysize);*/
|
||||
/* Note : my old linksys router only took into account
|
||||
* soap request that are sent into only one packet */
|
||||
char * p;
|
||||
/* TODO: AVOID MALLOC, we could use writev() for that */
|
||||
p = (char*)malloc(headerssize+bodysize);
|
||||
if(!p)
|
||||
return -1;
|
||||
memcpy(p, headers, headerssize);
|
||||
memcpy(p+headerssize, body, bodysize);
|
||||
/*n = write(fd, p, headerssize+bodysize);*/
|
||||
n = (int)send(fd, p, headerssize+bodysize, 0);
|
||||
/* disable send on the socket */
|
||||
/* draytek routers dont seems to like that... */
|
||||
free(p);
|
||||
return n;
|
||||
}
|
||||
|
||||
/* self explanatory */
|
||||
int soapPostSubmit(int fd,
|
||||
const char * url,
|
||||
const char * host,
|
||||
unsigned short port,
|
||||
const char * action,
|
||||
const char * body,
|
||||
const char * httpversion)
|
||||
{
|
||||
int bodysize;
|
||||
char headerbuf[512];
|
||||
int headerssize;
|
||||
char portstr[8];
|
||||
bodysize = (int)strlen(body);
|
||||
/* We are not using keep-alive HTTP connections.
|
||||
* HTTP/1.1 needs the header Connection: close to do that.
|
||||
* This is the default with HTTP/1.0
|
||||
* Using HTTP/1.1 means we need to support chunked transfer-encoding :
|
||||
* When using HTTP/1.1, the router "BiPAC 7404VNOX" always use chunked
|
||||
* transfer encoding. */
|
||||
/* Connection: Close is normally there only in HTTP/1.1 but who knows */
|
||||
portstr[0] = '\0';
|
||||
if(port != 80)
|
||||
snprintf(portstr, sizeof(portstr), ":%hu", port);
|
||||
headerssize = snprintf(headerbuf, sizeof(headerbuf),
|
||||
"POST %s HTTP/%s\r\n"
|
||||
"Host: %s%s\r\n"
|
||||
"User-Agent: " OS_STRING ", " UPNP_VERSION_STRING ", MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
|
||||
"Content-Length: %d\r\n"
|
||||
"Content-Type: text/xml\r\n"
|
||||
"SOAPAction: \"%s\"\r\n"
|
||||
"Connection: Close\r\n"
|
||||
"Cache-Control: no-cache\r\n" /* ??? */
|
||||
"Pragma: no-cache\r\n"
|
||||
"\r\n",
|
||||
url, httpversion, host, portstr, bodysize, action);
|
||||
if ((unsigned int)headerssize >= sizeof(headerbuf))
|
||||
return -1;
|
||||
#ifdef DEBUG
|
||||
/*printf("SOAP request : headersize=%d bodysize=%d\n",
|
||||
headerssize, bodysize);
|
||||
*/
|
||||
printf("SOAP request : POST %s HTTP/%s - Host: %s%s\n",
|
||||
url, httpversion, host, portstr);
|
||||
printf("SOAPAction: \"%s\" - Content-Length: %d\n", action, bodysize);
|
||||
printf("Headers :\n%s", headerbuf);
|
||||
printf("Body :\n%s\n", body);
|
||||
#endif
|
||||
return httpWrite(fd, body, bodysize, headerbuf, headerssize);
|
||||
}
|
||||
|
||||
|
||||
Vendored
-15
@@ -1,15 +0,0 @@
|
||||
/* $Id: minisoap.h,v 1.4 2010/04/12 20:39:41 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution. */
|
||||
#ifndef MINISOAP_H_INCLUDED
|
||||
#define MINISOAP_H_INCLUDED
|
||||
|
||||
/*int httpWrite(int, const char *, int, const char *);*/
|
||||
int soapPostSubmit(int, const char *, const char *, unsigned short,
|
||||
const char *, const char *, const char *);
|
||||
|
||||
#endif
|
||||
|
||||
Vendored
-864
@@ -1,864 +0,0 @@
|
||||
/* $Id: minissdpc.c,v 1.32 2016/10/07 09:04:36 nanard Exp $ */
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* Project : miniupnp
|
||||
* Web : http://miniupnp.free.fr/
|
||||
* Author : Thomas BERNARD
|
||||
* copyright (c) 2005-2017 Thomas Bernard
|
||||
* This software is subjet to the conditions detailed in the
|
||||
* provided LICENCE file. */
|
||||
/*#include <syslog.h>*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#if defined (__NetBSD__)
|
||||
#include <net/if.h>
|
||||
#endif
|
||||
#if defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <io.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <winsock.h>
|
||||
#define snprintf _snprintf
|
||||
#if !defined(_MSC_VER)
|
||||
#include <stdint.h>
|
||||
#else /* !defined(_MSC_VER) */
|
||||
typedef unsigned short uint16_t;
|
||||
#endif /* !defined(_MSC_VER) */
|
||||
#ifndef strncasecmp
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||
#define strncasecmp _memicmp
|
||||
#else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
|
||||
#define strncasecmp memicmp
|
||||
#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
|
||||
#endif /* #ifndef strncasecmp */
|
||||
#endif /* _WIN32 */
|
||||
#if defined(__amigaos__) || defined(__amigaos4__)
|
||||
#include <sys/socket.h>
|
||||
#endif /* defined(__amigaos__) || defined(__amigaos4__) */
|
||||
#if defined(__amigaos__)
|
||||
#define uint16_t unsigned short
|
||||
#endif /* defined(__amigaos__) */
|
||||
/* Hack */
|
||||
#define UNIX_PATH_LEN 108
|
||||
struct sockaddr_un {
|
||||
uint16_t sun_family;
|
||||
char sun_path[UNIX_PATH_LEN];
|
||||
};
|
||||
#else /* defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__) */
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/un.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <net/if.h>
|
||||
#ifndef closesocket
|
||||
#define closesocket close
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(__DragonFly__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__APPLE__) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__sun) && !defined(__GNU__) && !defined(__FreeBSD_kernel__) && !defined(__HAIKU__)
|
||||
#define HAS_IP_MREQN
|
||||
#endif
|
||||
|
||||
#if !defined(HAS_IP_MREQN) && !defined(_WIN32)
|
||||
#include <sys/ioctl.h>
|
||||
#if defined(__sun) || defined(__HAIKU__)
|
||||
#include <sys/sockio.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(HAS_IP_MREQN) && defined(NEED_STRUCT_IP_MREQN)
|
||||
/* Several versions of glibc don't define this structure,
|
||||
* define it here and compile with CFLAGS NEED_STRUCT_IP_MREQN */
|
||||
struct ip_mreqn
|
||||
{
|
||||
struct in_addr imr_multiaddr; /* IP multicast address of group */
|
||||
struct in_addr imr_address; /* local IP address of interface */
|
||||
int imr_ifindex; /* Interface index */
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(__amigaos__) || defined(__amigaos4__)
|
||||
/* Amiga OS specific stuff */
|
||||
#define TIMEVAL struct timeval
|
||||
#endif
|
||||
|
||||
#include "minissdpc.h"
|
||||
#include "miniupnpc.h"
|
||||
#include "receivedata.h"
|
||||
|
||||
#include <net/net_compat.h>
|
||||
|
||||
#if !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__))
|
||||
|
||||
#include "codelength.h"
|
||||
|
||||
struct UPNPDev *
|
||||
getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath, int * error)
|
||||
{
|
||||
struct UPNPDev * devlist = NULL;
|
||||
int s;
|
||||
int res;
|
||||
|
||||
s = connectToMiniSSDPD(socketpath);
|
||||
if (s < 0) {
|
||||
if (error)
|
||||
*error = s;
|
||||
return NULL;
|
||||
}
|
||||
res = requestDevicesFromMiniSSDPD(s, devtype);
|
||||
if (res < 0) {
|
||||
if (error)
|
||||
*error = res;
|
||||
} else {
|
||||
devlist = receiveDevicesFromMiniSSDPD(s, error);
|
||||
}
|
||||
disconnectFromMiniSSDPD(s);
|
||||
return devlist;
|
||||
}
|
||||
|
||||
/* macros used to read from unix socket */
|
||||
#define READ_BYTE_BUFFER(c) \
|
||||
if((int)bufferindex >= n) { \
|
||||
n = read(s, buffer, sizeof(buffer)); \
|
||||
if(n<=0) break; \
|
||||
bufferindex = 0; \
|
||||
} \
|
||||
c = buffer[bufferindex++];
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#endif /* MIN */
|
||||
|
||||
#define READ_COPY_BUFFER(dst, len) \
|
||||
for(l = len, p = (unsigned char *)dst; l > 0; ) { \
|
||||
unsigned int lcopy; \
|
||||
if((int)bufferindex >= n) { \
|
||||
n = read(s, buffer, sizeof(buffer)); \
|
||||
if(n<=0) break; \
|
||||
bufferindex = 0; \
|
||||
} \
|
||||
lcopy = (unsigned int)MIN(l, (n - bufferindex)); \
|
||||
memcpy(p, buffer + bufferindex, lcopy); \
|
||||
l -= lcopy; \
|
||||
p += lcopy; \
|
||||
bufferindex += lcopy; \
|
||||
}
|
||||
|
||||
#define READ_DISCARD_BUFFER(len) \
|
||||
for(l = len; l > 0; ) { \
|
||||
unsigned int lcopy; \
|
||||
if(bufferindex >= n) { \
|
||||
n = read(s, buffer, sizeof(buffer)); \
|
||||
if(n<=0) break; \
|
||||
bufferindex = 0; \
|
||||
} \
|
||||
lcopy = MIN(l, (n - bufferindex)); \
|
||||
l -= lcopy; \
|
||||
bufferindex += lcopy; \
|
||||
}
|
||||
|
||||
int
|
||||
connectToMiniSSDPD(const char * socketpath)
|
||||
{
|
||||
int s;
|
||||
struct sockaddr_un addr;
|
||||
#if defined(MINIUPNPC_SET_SOCKET_TIMEOUT) && !defined(__sun)
|
||||
struct timeval timeout;
|
||||
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
|
||||
|
||||
s = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if(s < 0)
|
||||
{
|
||||
/*syslog(LOG_ERR, "socket(unix): %m");*/
|
||||
perror("socket(unix)");
|
||||
return MINISSDPC_SOCKET_ERROR;
|
||||
}
|
||||
#if defined(MINIUPNPC_SET_SOCKET_TIMEOUT) && !defined(__sun)
|
||||
/* setting a 3 seconds timeout */
|
||||
/* not supported for AF_UNIX sockets under Solaris */
|
||||
timeout.tv_sec = 3;
|
||||
timeout.tv_usec = 0;
|
||||
if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0)
|
||||
{
|
||||
perror("setsockopt SO_RCVTIMEO unix");
|
||||
}
|
||||
timeout.tv_sec = 3;
|
||||
timeout.tv_usec = 0;
|
||||
if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0)
|
||||
{
|
||||
perror("setsockopt SO_SNDTIMEO unix");
|
||||
}
|
||||
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
|
||||
if(!socketpath)
|
||||
socketpath = "/var/run/minissdpd.sock";
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy(addr.sun_path, socketpath, sizeof(addr.sun_path));
|
||||
/* TODO : check if we need to handle the EINTR */
|
||||
if(connect(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0)
|
||||
{
|
||||
/*syslog(LOG_WARNING, "connect(\"%s\"): %m", socketpath);*/
|
||||
close(s);
|
||||
return MINISSDPC_SOCKET_ERROR;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
int
|
||||
disconnectFromMiniSSDPD(int s)
|
||||
{
|
||||
if (close(s) < 0)
|
||||
return MINISSDPC_SOCKET_ERROR;
|
||||
return MINISSDPC_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
requestDevicesFromMiniSSDPD(int s, const char * devtype)
|
||||
{
|
||||
unsigned char buffer[256];
|
||||
unsigned char * p;
|
||||
unsigned int l;
|
||||
unsigned stsize = (unsigned)strlen(devtype);
|
||||
if(stsize == 8 && 0 == memcmp(devtype, "ssdp:all", 8))
|
||||
{
|
||||
buffer[0] = 3; /* request type 3 : everything */
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[0] = 1; /* request type 1 : request devices/services by type */
|
||||
}
|
||||
p = buffer + 1;
|
||||
l = stsize; CODELENGTH(l, p);
|
||||
if(p + stsize > buffer + sizeof(buffer))
|
||||
{
|
||||
/* devtype is too long ! */
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "devtype is too long ! stsize=%u sizeof(buffer)=%u\n",
|
||||
stsize, (unsigned)sizeof(buffer));
|
||||
#endif /* DEBUG */
|
||||
return MINISSDPC_INVALID_INPUT;
|
||||
}
|
||||
memcpy(p, devtype, stsize);
|
||||
p += stsize;
|
||||
if(write(s, buffer, p - buffer) < 0)
|
||||
{
|
||||
/*syslog(LOG_ERR, "write(): %m");*/
|
||||
perror("minissdpc.c: write()");
|
||||
return MINISSDPC_SOCKET_ERROR;
|
||||
}
|
||||
return MINISSDPC_SUCCESS;
|
||||
}
|
||||
|
||||
struct UPNPDev *
|
||||
receiveDevicesFromMiniSSDPD(int s, int * error)
|
||||
{
|
||||
struct UPNPDev * tmp;
|
||||
struct UPNPDev * devlist = NULL;
|
||||
unsigned char buffer[256];
|
||||
ssize_t n;
|
||||
unsigned char * p;
|
||||
unsigned char * url;
|
||||
unsigned char * st;
|
||||
unsigned int bufferindex;
|
||||
unsigned int i, ndev;
|
||||
unsigned int urlsize, stsize, usnsize, l;
|
||||
|
||||
n = read(s, buffer, sizeof(buffer));
|
||||
if(n<=0)
|
||||
{
|
||||
perror("minissdpc.c: read()");
|
||||
if (error)
|
||||
*error = MINISSDPC_SOCKET_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
ndev = buffer[0];
|
||||
bufferindex = 1;
|
||||
for(i = 0; i < ndev; i++)
|
||||
{
|
||||
DECODELENGTH_READ(urlsize, READ_BYTE_BUFFER);
|
||||
if(n<=0) {
|
||||
if (error)
|
||||
*error = MINISSDPC_INVALID_SERVER_REPLY;
|
||||
return devlist;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf(" urlsize=%u", urlsize);
|
||||
#endif /* DEBUG */
|
||||
url = (unsigned char*)malloc(urlsize);
|
||||
if(url == NULL)
|
||||
{
|
||||
if (error)
|
||||
*error = MINISSDPC_MEMORY_ERROR;
|
||||
return devlist;
|
||||
}
|
||||
READ_COPY_BUFFER(url, urlsize);
|
||||
if(n<=0)
|
||||
{
|
||||
if (error)
|
||||
*error = MINISSDPC_INVALID_SERVER_REPLY;
|
||||
goto free_url_and_return;
|
||||
}
|
||||
DECODELENGTH_READ(stsize, READ_BYTE_BUFFER);
|
||||
if(n<=0)
|
||||
{
|
||||
if (error)
|
||||
*error = MINISSDPC_INVALID_SERVER_REPLY;
|
||||
goto free_url_and_return;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf(" stsize=%u", stsize);
|
||||
#endif /* DEBUG */
|
||||
st = (unsigned char*)malloc(stsize);
|
||||
if (st == NULL) {
|
||||
if (error)
|
||||
*error = MINISSDPC_MEMORY_ERROR;
|
||||
goto free_url_and_return;
|
||||
}
|
||||
READ_COPY_BUFFER(st, stsize);
|
||||
if(n<=0) {
|
||||
if (error)
|
||||
*error = MINISSDPC_INVALID_SERVER_REPLY;
|
||||
goto free_url_and_st_and_return;
|
||||
}
|
||||
DECODELENGTH_READ(usnsize, READ_BYTE_BUFFER);
|
||||
if(n<=0) {
|
||||
if (error)
|
||||
*error = MINISSDPC_INVALID_SERVER_REPLY;
|
||||
goto free_url_and_st_and_return;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf(" usnsize=%u\n", usnsize);
|
||||
#endif /* DEBUG */
|
||||
tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize);
|
||||
if(tmp == NULL) {
|
||||
if (error)
|
||||
*error = MINISSDPC_MEMORY_ERROR;
|
||||
goto free_url_and_st_and_return;
|
||||
}
|
||||
tmp->pNext = devlist;
|
||||
tmp->descURL = tmp->buffer;
|
||||
tmp->st = tmp->buffer + 1 + urlsize;
|
||||
memcpy(tmp->buffer, url, urlsize);
|
||||
tmp->buffer[urlsize] = '\0';
|
||||
memcpy(tmp->st, st, stsize);
|
||||
tmp->buffer[urlsize+1+stsize] = '\0';
|
||||
free(url);
|
||||
free(st);
|
||||
url = NULL;
|
||||
st = NULL;
|
||||
tmp->usn = tmp->buffer + 1 + urlsize + 1 + stsize;
|
||||
READ_COPY_BUFFER(tmp->usn, usnsize);
|
||||
if(n<=0) {
|
||||
if (error)
|
||||
*error = MINISSDPC_INVALID_SERVER_REPLY;
|
||||
goto free_tmp_and_return;
|
||||
}
|
||||
tmp->buffer[urlsize+1+stsize+1+usnsize] = '\0';
|
||||
tmp->scope_id = 0; /* default value. scope_id is not available with MiniSSDPd */
|
||||
devlist = tmp;
|
||||
}
|
||||
if (error)
|
||||
*error = MINISSDPC_SUCCESS;
|
||||
return devlist;
|
||||
|
||||
free_url_and_st_and_return:
|
||||
free(st);
|
||||
free_url_and_return:
|
||||
free(url);
|
||||
return devlist;
|
||||
|
||||
free_tmp_and_return:
|
||||
free(tmp);
|
||||
return devlist;
|
||||
}
|
||||
|
||||
#endif /* !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)) */
|
||||
|
||||
/* parseMSEARCHReply()
|
||||
* the last 4 arguments are filled during the parsing :
|
||||
* - location/locationsize : "location:" field of the SSDP reply packet
|
||||
* - st/stsize : "st:" field of the SSDP reply packet.
|
||||
* The strings are NOT null terminated */
|
||||
static void
|
||||
parseMSEARCHReply(const char * reply, int size,
|
||||
const char * * location, int * locationsize,
|
||||
const char * * st, int * stsize,
|
||||
const char * * usn, int * usnsize)
|
||||
{
|
||||
int a, b, i;
|
||||
i = 0;
|
||||
a = i; /* start of the line */
|
||||
b = 0; /* end of the "header" (position of the colon) */
|
||||
while(i<size)
|
||||
{
|
||||
switch(reply[i])
|
||||
{
|
||||
case ':':
|
||||
if(b==0)
|
||||
{
|
||||
b = i; /* end of the "header" */
|
||||
/*for(j=a; j<b; j++)
|
||||
{
|
||||
putchar(reply[j]);
|
||||
}
|
||||
*/
|
||||
}
|
||||
break;
|
||||
case '\x0a':
|
||||
case '\x0d':
|
||||
if(b!=0)
|
||||
{
|
||||
/*for(j=b+1; j<i; j++)
|
||||
{
|
||||
putchar(reply[j]);
|
||||
}
|
||||
putchar('\n');*/
|
||||
/* skip the colon and white spaces */
|
||||
do { b++; } while(reply[b]==' ');
|
||||
if(0==strncasecmp(reply+a, "location", 8))
|
||||
{
|
||||
*location = reply+b;
|
||||
*locationsize = i-b;
|
||||
}
|
||||
else if(0==strncasecmp(reply+a, "st", 2))
|
||||
{
|
||||
*st = reply+b;
|
||||
*stsize = i-b;
|
||||
}
|
||||
else if(0==strncasecmp(reply+a, "usn", 3))
|
||||
{
|
||||
*usn = reply+b;
|
||||
*usnsize = i-b;
|
||||
}
|
||||
b = 0;
|
||||
}
|
||||
a = i+1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/* port upnp discover : SSDP protocol */
|
||||
#define SSDP_PORT 1900
|
||||
#define XSTR(s) MINISSDPC_STR(s)
|
||||
#define MINISSDPC_STR(s) #s
|
||||
#define UPNP_MCAST_ADDR "239.255.255.250"
|
||||
/* for IPv6 */
|
||||
#define UPNP_MCAST_LL_ADDR "FF02::C" /* link-local */
|
||||
#define UPNP_MCAST_SL_ADDR "FF05::C" /* site-local */
|
||||
|
||||
/* direct discovery if minissdpd responses are not sufficient */
|
||||
/* ssdpDiscoverDevices() :
|
||||
* return a chained list of all devices found or NULL if
|
||||
* no devices was found.
|
||||
* It is up to the caller to free the chained list
|
||||
* delay is in millisecond (poll).
|
||||
* UDA v1.1 says :
|
||||
* The TTL for the IP packet SHOULD default to 2 and
|
||||
* SHOULD be configurable. */
|
||||
struct UPNPDev *
|
||||
ssdpDiscoverDevices(const char * const deviceTypes[],
|
||||
int delay, const char * multicastif,
|
||||
int localport,
|
||||
int ipv6, unsigned char ttl,
|
||||
int * error,
|
||||
int searchalltypes)
|
||||
{
|
||||
struct UPNPDev * tmp;
|
||||
struct UPNPDev * devlist = 0;
|
||||
unsigned int scope_id = 0;
|
||||
int opt = 1;
|
||||
static const char MSearchMsgFmt[] =
|
||||
"M-SEARCH * HTTP/1.1\r\n"
|
||||
"HOST: %s:" XSTR(SSDP_PORT) "\r\n"
|
||||
"ST: %s\r\n"
|
||||
"MAN: \"ssdp:discover\"\r\n"
|
||||
"MX: %u\r\n"
|
||||
"\r\n";
|
||||
int deviceIndex;
|
||||
char bufr[1536]; /* reception and emission buffer */
|
||||
int sudp;
|
||||
int n;
|
||||
struct sockaddr_storage sockudp_r;
|
||||
unsigned int mx;
|
||||
#ifdef NO_GETADDRINFO
|
||||
struct sockaddr_storage sockudp_w;
|
||||
#else
|
||||
int rv;
|
||||
struct addrinfo hints, *servinfo, *p;
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
MIB_IPFORWARDROW ip_forward;
|
||||
unsigned long _ttl = (unsigned long)ttl;
|
||||
#endif
|
||||
int linklocal = 1;
|
||||
|
||||
if(error)
|
||||
*error = MINISSDPC_UNKNOWN_ERROR;
|
||||
|
||||
if(localport==UPNP_LOCAL_PORT_SAME)
|
||||
localport = SSDP_PORT;
|
||||
|
||||
#ifdef _WIN32
|
||||
sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
#else
|
||||
sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, 0);
|
||||
#endif
|
||||
if(sudp < 0)
|
||||
{
|
||||
if(error)
|
||||
*error = MINISSDPC_SOCKET_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
/* reception */
|
||||
memset(&sockudp_r, 0, sizeof(struct sockaddr_storage));
|
||||
if(ipv6) {
|
||||
struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_r;
|
||||
p->sin6_family = AF_INET6;
|
||||
if(localport > 0 && localport < 65536)
|
||||
p->sin6_port = htons((unsigned short)localport);
|
||||
p->sin6_addr = in6addr_any; /* in6addr_any is not available with MinGW32 3.4.2 */
|
||||
} else {
|
||||
struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_r;
|
||||
p->sin_family = AF_INET;
|
||||
if(localport > 0 && localport < 65536)
|
||||
p->sin_port = htons((unsigned short)localport);
|
||||
p->sin_addr.s_addr = INADDR_ANY;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
/* This code could help us to use the right Network interface for
|
||||
* SSDP multicast traffic */
|
||||
/* Get IP associated with the index given in the ip_forward struct
|
||||
* in order to give this ip to setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF) */
|
||||
if(!ipv6
|
||||
&& (GetBestRoute(inet_addr("223.255.255.255"), 0, &ip_forward) == NO_ERROR)) {
|
||||
DWORD dwRetVal = 0;
|
||||
PMIB_IPADDRTABLE pIPAddrTable;
|
||||
DWORD dwSize = 0;
|
||||
#ifdef DEBUG
|
||||
IN_ADDR IPAddr;
|
||||
#endif
|
||||
int i;
|
||||
#ifdef DEBUG
|
||||
printf("ifIndex=%lu nextHop=%lx \n", ip_forward.dwForwardIfIndex, ip_forward.dwForwardNextHop);
|
||||
#endif
|
||||
pIPAddrTable = (MIB_IPADDRTABLE *) malloc(sizeof (MIB_IPADDRTABLE));
|
||||
if(pIPAddrTable) {
|
||||
if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) {
|
||||
free(pIPAddrTable);
|
||||
pIPAddrTable = (MIB_IPADDRTABLE *) malloc(dwSize);
|
||||
}
|
||||
}
|
||||
if(pIPAddrTable) {
|
||||
dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 );
|
||||
if (dwRetVal == NO_ERROR) {
|
||||
#ifdef DEBUG
|
||||
printf("\tNum Entries: %ld\n", pIPAddrTable->dwNumEntries);
|
||||
#endif
|
||||
for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) {
|
||||
#ifdef DEBUG
|
||||
printf("\n\tInterface Index[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwIndex);
|
||||
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr;
|
||||
printf("\tIP Address[%d]: \t%s\n", i, inet_ntoa(IPAddr) );
|
||||
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwMask;
|
||||
printf("\tSubnet Mask[%d]: \t%s\n", i, inet_ntoa(IPAddr) );
|
||||
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwBCastAddr;
|
||||
printf("\tBroadCast[%d]: \t%s (%ld)\n", i, inet_ntoa(IPAddr), pIPAddrTable->table[i].dwBCastAddr);
|
||||
printf("\tReassembly size[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwReasmSize);
|
||||
printf("\tType and State[%d]:", i);
|
||||
printf("\n");
|
||||
#endif
|
||||
if (pIPAddrTable->table[i].dwIndex == ip_forward.dwForwardIfIndex) {
|
||||
/* Set the address of this interface to be used */
|
||||
struct in_addr mc_if;
|
||||
memset(&mc_if, 0, sizeof(mc_if));
|
||||
mc_if.s_addr = pIPAddrTable->table[i].dwAddr;
|
||||
setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if));
|
||||
((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = pIPAddrTable->table[i].dwAddr;
|
||||
#ifndef DEBUG
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
free(pIPAddrTable);
|
||||
pIPAddrTable = NULL;
|
||||
}
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#ifdef _WIN32
|
||||
if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof (opt)) < 0)
|
||||
#else
|
||||
if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0)
|
||||
#endif
|
||||
{
|
||||
if(error)
|
||||
*error = MINISSDPC_SOCKET_ERROR;
|
||||
closesocket(sudp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&_ttl, sizeof(_ttl)) < 0)
|
||||
#else /* _WIN32 */
|
||||
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
|
||||
#endif /* _WIN32 */
|
||||
{
|
||||
/* not a fatal error */
|
||||
}
|
||||
|
||||
if(multicastif)
|
||||
{
|
||||
if(ipv6) {
|
||||
#if !defined(_WIN32)
|
||||
/* according to MSDN, if_nametoindex() is supported since
|
||||
* MS Windows Vista and MS Windows Server 2008.
|
||||
* http://msdn.microsoft.com/en-us/library/bb408409%28v=vs.85%29.aspx */
|
||||
unsigned int ifindex = if_nametoindex(multicastif); /* eth0, etc. */
|
||||
if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)) < 0)
|
||||
{
|
||||
}
|
||||
#else
|
||||
#ifdef DEBUG
|
||||
printf("Setting of multicast interface not supported in IPv6 under Windows.\n");
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
struct in_addr mc_if;
|
||||
mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */
|
||||
if(mc_if.s_addr != INADDR_NONE)
|
||||
{
|
||||
((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr;
|
||||
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0)
|
||||
{
|
||||
}
|
||||
} else {
|
||||
#ifdef HAS_IP_MREQN
|
||||
/* was not an ip address, try with an interface name */
|
||||
struct ip_mreqn reqn; /* only defined with -D_BSD_SOURCE or -D_GNU_SOURCE */
|
||||
memset(&reqn, 0, sizeof(struct ip_mreqn));
|
||||
reqn.imr_ifindex = if_nametoindex(multicastif);
|
||||
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&reqn, sizeof(reqn)) < 0)
|
||||
{
|
||||
}
|
||||
#elif !defined(_WIN32)
|
||||
struct ifreq ifr;
|
||||
int ifrlen = sizeof(ifr);
|
||||
strncpy(ifr.ifr_name, multicastif, IFNAMSIZ);
|
||||
ifr.ifr_name[IFNAMSIZ-1] = '\0';
|
||||
if(ioctl(sudp, SIOCGIFADDR, &ifr, &ifrlen) < 0)
|
||||
{
|
||||
}
|
||||
mc_if.s_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
|
||||
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0)
|
||||
{
|
||||
}
|
||||
#else /* _WIN32 */
|
||||
#ifdef DEBUG
|
||||
printf("Setting of multicast interface not supported with interface name.\n");
|
||||
#endif
|
||||
#endif /* #ifdef HAS_IP_MREQN / !defined(_WIN32) */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Before sending the packed, we first "bind" in order to be able
|
||||
* to receive the response */
|
||||
if (bind(sudp, (const struct sockaddr *)&sockudp_r,
|
||||
ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) != 0)
|
||||
{
|
||||
if(error)
|
||||
*error = MINISSDPC_SOCKET_ERROR;
|
||||
closesocket(sudp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(error)
|
||||
*error = MINISSDPC_SUCCESS;
|
||||
/* Calculating maximum response time in seconds */
|
||||
mx = ((unsigned int)delay) / 1000u;
|
||||
if(mx == 0) {
|
||||
mx = 1;
|
||||
delay = 1000;
|
||||
}
|
||||
/* receiving SSDP response packet */
|
||||
for(deviceIndex = 0; deviceTypes[deviceIndex]; deviceIndex++) {
|
||||
/* sending the SSDP M-SEARCH packet */
|
||||
n = snprintf(bufr, sizeof(bufr),
|
||||
MSearchMsgFmt,
|
||||
ipv6 ?
|
||||
(linklocal ? "[" UPNP_MCAST_LL_ADDR "]" : "[" UPNP_MCAST_SL_ADDR "]")
|
||||
: UPNP_MCAST_ADDR,
|
||||
deviceTypes[deviceIndex], mx);
|
||||
if ((unsigned int)n >= sizeof(bufr)) {
|
||||
if(error)
|
||||
*error = MINISSDPC_MEMORY_ERROR;
|
||||
goto error;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
/*printf("Sending %s", bufr);*/
|
||||
printf("Sending M-SEARCH request to %s with ST: %s\n",
|
||||
ipv6 ?
|
||||
(linklocal ? "[" UPNP_MCAST_LL_ADDR "]" : "[" UPNP_MCAST_SL_ADDR "]")
|
||||
: UPNP_MCAST_ADDR,
|
||||
deviceTypes[deviceIndex]);
|
||||
#endif
|
||||
#ifdef NO_GETADDRINFO
|
||||
/* the following code is not using getaddrinfo */
|
||||
/* emission */
|
||||
memset(&sockudp_w, 0, sizeof(struct sockaddr_storage));
|
||||
if(ipv6) {
|
||||
struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_w;
|
||||
p->sin6_family = AF_INET6;
|
||||
p->sin6_port = htons(SSDP_PORT);
|
||||
inet_pton(AF_INET6,
|
||||
linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR,
|
||||
&(p->sin6_addr));
|
||||
} else {
|
||||
struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_w;
|
||||
p->sin_family = AF_INET;
|
||||
p->sin_port = htons(SSDP_PORT);
|
||||
p->sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR);
|
||||
}
|
||||
n = sendto(sudp, bufr, n, 0, &sockudp_w,
|
||||
ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
|
||||
if (n < 0) {
|
||||
if(error)
|
||||
*error = MINISSDPC_SOCKET_ERROR;
|
||||
break;
|
||||
}
|
||||
#else /* #ifdef NO_GETADDRINFO */
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC; /* AF_INET6 or AF_INET */
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
/*hints.ai_flags = */
|
||||
if ((rv = getaddrinfo_retro(ipv6
|
||||
? (linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR)
|
||||
: UPNP_MCAST_ADDR,
|
||||
XSTR(SSDP_PORT), &hints, &servinfo)) != 0) {
|
||||
if(error)
|
||||
*error = MINISSDPC_SOCKET_ERROR;
|
||||
#ifdef _WIN32
|
||||
fprintf(stderr, "getaddrinfo() failed: %d\n", rv);
|
||||
#else
|
||||
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
for(p = servinfo; p; p = p->ai_next) {
|
||||
n = (int)sendto(sudp, bufr, n, 0, p->ai_addr, p->ai_addrlen);
|
||||
if (n < 0) {
|
||||
#ifdef DEBUG
|
||||
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
|
||||
if (getnameinfo(p->ai_addr, p->ai_addrlen, hbuf, sizeof(hbuf), sbuf,
|
||||
sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
|
||||
fprintf(stderr, "host:%s port:%s\n", hbuf, sbuf);
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
}
|
||||
freeaddrinfo(servinfo);
|
||||
if(n < 0) {
|
||||
if(error)
|
||||
*error = MINISSDPC_SOCKET_ERROR;
|
||||
break;
|
||||
}
|
||||
#endif /* #ifdef NO_GETADDRINFO */
|
||||
/* Waiting for SSDP REPLY packet to M-SEARCH
|
||||
* if searchalltypes is set, enter the loop only
|
||||
* when the last deviceType is reached */
|
||||
if(!searchalltypes || !deviceTypes[deviceIndex + 1]) do {
|
||||
n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id);
|
||||
if (n < 0) {
|
||||
/* error */
|
||||
if(error)
|
||||
*error = MINISSDPC_SOCKET_ERROR;
|
||||
goto error;
|
||||
} else if (n == 0) {
|
||||
/* no data or Time Out */
|
||||
#ifdef DEBUG
|
||||
printf("NODATA or TIMEOUT\n");
|
||||
#endif /* DEBUG */
|
||||
if (devlist && !searchalltypes) {
|
||||
/* found some devices, stop now*/
|
||||
if(error)
|
||||
*error = MINISSDPC_SUCCESS;
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
const char * descURL=NULL;
|
||||
int urlsize=0;
|
||||
const char * st=NULL;
|
||||
int stsize=0;
|
||||
const char * usn=NULL;
|
||||
int usnsize=0;
|
||||
parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize, &usn, &usnsize);
|
||||
if(st&&descURL) {
|
||||
#ifdef DEBUG
|
||||
printf("M-SEARCH Reply:\n ST: %.*s\n USN: %.*s\n Location: %.*s\n",
|
||||
stsize, st, usnsize, (usn?usn:""), urlsize, descURL);
|
||||
#endif /* DEBUG */
|
||||
for(tmp=devlist; tmp; tmp = tmp->pNext) {
|
||||
if(memcmp(tmp->descURL, descURL, urlsize) == 0 &&
|
||||
tmp->descURL[urlsize] == '\0' &&
|
||||
memcmp(tmp->st, st, stsize) == 0 &&
|
||||
tmp->st[stsize] == '\0' &&
|
||||
(usnsize == 0 || memcmp(tmp->usn, usn, usnsize) == 0) &&
|
||||
tmp->usn[usnsize] == '\0')
|
||||
break;
|
||||
}
|
||||
/* at the exit of the loop above, tmp is null if
|
||||
* no duplicate device was found */
|
||||
if(tmp)
|
||||
continue;
|
||||
tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize);
|
||||
if(!tmp) {
|
||||
/* memory allocation error */
|
||||
if(error)
|
||||
*error = MINISSDPC_MEMORY_ERROR;
|
||||
goto error;
|
||||
}
|
||||
tmp->pNext = devlist;
|
||||
tmp->descURL = tmp->buffer;
|
||||
tmp->st = tmp->buffer + 1 + urlsize;
|
||||
tmp->usn = tmp->st + 1 + stsize;
|
||||
memcpy(tmp->buffer, descURL, urlsize);
|
||||
tmp->buffer[urlsize] = '\0';
|
||||
memcpy(tmp->st, st, stsize);
|
||||
tmp->buffer[urlsize+1+stsize] = '\0';
|
||||
if(usn != NULL)
|
||||
memcpy(tmp->usn, usn, usnsize);
|
||||
tmp->buffer[urlsize+1+stsize+1+usnsize] = '\0';
|
||||
tmp->scope_id = scope_id;
|
||||
devlist = tmp;
|
||||
}
|
||||
}
|
||||
} while(n > 0);
|
||||
if(ipv6) {
|
||||
/* switch linklocal flag */
|
||||
if(linklocal) {
|
||||
linklocal = 0;
|
||||
--deviceIndex;
|
||||
} else {
|
||||
linklocal = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
error:
|
||||
closesocket(sudp);
|
||||
return devlist;
|
||||
}
|
||||
|
||||
Vendored
-58
@@ -1,58 +0,0 @@
|
||||
/* $Id: minissdpc.h,v 1.6 2015/09/18 12:45:16 nanard Exp $ */
|
||||
/* Project: miniupnp
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* Author: Thomas Bernard
|
||||
* Copyright (c) 2005-2015 Thomas Bernard
|
||||
* This software is subjects to the conditions detailed
|
||||
* in the LICENCE file provided within this distribution */
|
||||
#ifndef MINISSDPC_H_INCLUDED
|
||||
#define MINISSDPC_H_INCLUDED
|
||||
|
||||
#include "miniupnpc_declspec.h"
|
||||
#include "upnpdev.h"
|
||||
|
||||
/* error codes : */
|
||||
#define MINISSDPC_SUCCESS (0)
|
||||
#define MINISSDPC_UNKNOWN_ERROR (-1)
|
||||
#define MINISSDPC_SOCKET_ERROR (-101)
|
||||
#define MINISSDPC_MEMORY_ERROR (-102)
|
||||
#define MINISSDPC_INVALID_INPUT (-103)
|
||||
#define MINISSDPC_INVALID_SERVER_REPLY (-104)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__))
|
||||
|
||||
MINIUPNP_LIBSPEC struct UPNPDev *
|
||||
getDevicesFromMiniSSDPD(const char * devtype, const char * socketpath, int * error);
|
||||
|
||||
MINIUPNP_LIBSPEC int
|
||||
connectToMiniSSDPD(const char * socketpath);
|
||||
|
||||
MINIUPNP_LIBSPEC int
|
||||
disconnectFromMiniSSDPD(int fd);
|
||||
|
||||
MINIUPNP_LIBSPEC int
|
||||
requestDevicesFromMiniSSDPD(int fd, const char * devtype);
|
||||
|
||||
MINIUPNP_LIBSPEC struct UPNPDev *
|
||||
receiveDevicesFromMiniSSDPD(int fd, int * error);
|
||||
|
||||
#endif /* !(defined(_WIN32) || defined(__amigaos__) || defined(__amigaos4__)) */
|
||||
|
||||
MINIUPNP_LIBSPEC struct UPNPDev *
|
||||
ssdpDiscoverDevices(const char * const deviceTypes[],
|
||||
int delay, const char * multicastif,
|
||||
int localport,
|
||||
int ipv6, unsigned char ttl,
|
||||
int * error,
|
||||
int searchalltypes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Vendored
-724
@@ -1,724 +0,0 @@
|
||||
/* $Id: miniupnpc.c,v 1.148 2016/01/24 17:24:36 nanard Exp $ */
|
||||
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
||||
* Project : miniupnp
|
||||
* Web : http://miniupnp.free.fr/
|
||||
* Author : Thomas BERNARD
|
||||
* copyright (c) 2005-2016 Thomas Bernard
|
||||
* This software is subjet to the conditions detailed in the
|
||||
* provided LICENSE file. */
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef _WIN32
|
||||
/* Win32 Specific includes and defines */
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <io.h>
|
||||
#include <iphlpapi.h>
|
||||
#define snprintf _snprintf
|
||||
#define strdup _strdup
|
||||
#ifndef strncasecmp
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||
#define strncasecmp _memicmp
|
||||
#else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
|
||||
#define strncasecmp memicmp
|
||||
#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
|
||||
#endif /* #ifndef strncasecmp */
|
||||
#define MAXHOSTNAMELEN 64
|
||||
#else /* #ifdef _WIN32 */
|
||||
/* Standard POSIX includes */
|
||||
#include <unistd.h>
|
||||
#if defined(__amigaos__) && !defined(__amigaos4__)
|
||||
/* Amiga OS 3 specific stuff */
|
||||
#define socklen_t int
|
||||
#else
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <net/if.h>
|
||||
#if !defined(__amigaos__) && !defined(__amigaos4__)
|
||||
#include <poll.h>
|
||||
#endif
|
||||
#include <strings.h>
|
||||
#include <errno.h>
|
||||
#ifndef closesocket
|
||||
#define closesocket close
|
||||
#endif
|
||||
#endif /* #else _WIN32 */
|
||||
#ifdef __GNU__
|
||||
#define MAXHOSTNAMELEN 64
|
||||
#endif
|
||||
|
||||
|
||||
#include "miniupnpc.h"
|
||||
#include "minissdpc.h"
|
||||
#include "miniwget.h"
|
||||
#include "minisoap.h"
|
||||
#include "minixml.h"
|
||||
#include "upnpcommands.h"
|
||||
#include "connecthostport.h"
|
||||
|
||||
/* compare the begining of a string with a constant string */
|
||||
#define COMPARE(str, cstr) (0==memcmp(str, cstr, sizeof(cstr) - 1))
|
||||
|
||||
#ifndef MAXHOSTNAMELEN
|
||||
#define MAXHOSTNAMELEN 64
|
||||
#endif
|
||||
|
||||
#define SOAPPREFIX "s"
|
||||
#define SERVICEPREFIX "u"
|
||||
#define SERVICEPREFIX2 'u'
|
||||
|
||||
/* check if an ip address is a private (LAN) address
|
||||
* see https://tools.ietf.org/html/rfc1918 */
|
||||
static int is_rfc1918addr(const char * addr)
|
||||
{
|
||||
/* 192.168.0.0 - 192.168.255.255 (192.168/16 prefix) */
|
||||
if(COMPARE(addr, "192.168."))
|
||||
return 1;
|
||||
/* 10.0.0.0 - 10.255.255.255 (10/8 prefix) */
|
||||
if(COMPARE(addr, "10."))
|
||||
return 1;
|
||||
/* 172.16.0.0 - 172.31.255.255 (172.16/12 prefix) */
|
||||
if(COMPARE(addr, "172.")) {
|
||||
int i = atoi(addr + 4);
|
||||
if((16 <= i) && (i <= 31))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* root description parsing */
|
||||
MINIUPNP_LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * data)
|
||||
{
|
||||
struct xmlparser parser;
|
||||
/* xmlparser object */
|
||||
parser.xmlstart = buffer;
|
||||
parser.xmlsize = bufsize;
|
||||
parser.data = data;
|
||||
parser.starteltfunc = IGDstartelt;
|
||||
parser.endeltfunc = IGDendelt;
|
||||
parser.datafunc = IGDdata;
|
||||
parser.attfunc = 0;
|
||||
parsexml(&parser);
|
||||
#ifdef DEBUG
|
||||
printIGD(data);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* simpleUPnPcommand2 :
|
||||
* not so simple !
|
||||
* return values :
|
||||
* pointer - OK
|
||||
* NULL - error */
|
||||
char * simpleUPnPcommand2(int s, const char * url, const char * service,
|
||||
const char * action, struct UPNParg * args,
|
||||
int * bufsize, const char * httpversion)
|
||||
{
|
||||
char hostname[MAXHOSTNAMELEN+1];
|
||||
unsigned short port = 0;
|
||||
char * path;
|
||||
char soapact[128];
|
||||
char soapbody[2048];
|
||||
int soapbodylen;
|
||||
char * buf;
|
||||
int n;
|
||||
int status_code;
|
||||
|
||||
*bufsize = 0;
|
||||
snprintf(soapact, sizeof(soapact), "%s#%s", service, action);
|
||||
if(args==NULL)
|
||||
{
|
||||
soapbodylen = snprintf(soapbody, sizeof(soapbody),
|
||||
"<?xml version=\"1.0\"?>\r\n"
|
||||
"<" SOAPPREFIX ":Envelope "
|
||||
"xmlns:" SOAPPREFIX "=\"http://schemas.xmlsoap.org/soap/envelope/\" "
|
||||
SOAPPREFIX ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
|
||||
"<" SOAPPREFIX ":Body>"
|
||||
"<" SERVICEPREFIX ":%s xmlns:" SERVICEPREFIX "=\"%s\">"
|
||||
"</" SERVICEPREFIX ":%s>"
|
||||
"</" SOAPPREFIX ":Body></" SOAPPREFIX ":Envelope>"
|
||||
"\r\n", action, service, action);
|
||||
if ((unsigned int)soapbodylen >= sizeof(soapbody))
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
char * p;
|
||||
const char * pe, * pv;
|
||||
const char * const pend = soapbody + sizeof(soapbody);
|
||||
soapbodylen = snprintf(soapbody, sizeof(soapbody),
|
||||
"<?xml version=\"1.0\"?>\r\n"
|
||||
"<" SOAPPREFIX ":Envelope "
|
||||
"xmlns:" SOAPPREFIX "=\"http://schemas.xmlsoap.org/soap/envelope/\" "
|
||||
SOAPPREFIX ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
|
||||
"<" SOAPPREFIX ":Body>"
|
||||
"<" SERVICEPREFIX ":%s xmlns:" SERVICEPREFIX "=\"%s\">",
|
||||
action, service);
|
||||
if ((unsigned int)soapbodylen >= sizeof(soapbody))
|
||||
return NULL;
|
||||
p = soapbody + soapbodylen;
|
||||
while(args->elt)
|
||||
{
|
||||
if(p >= pend) /* check for space to write next byte */
|
||||
return NULL;
|
||||
*(p++) = '<';
|
||||
|
||||
pe = args->elt;
|
||||
while(p < pend && *pe)
|
||||
*(p++) = *(pe++);
|
||||
|
||||
if(p >= pend) /* check for space to write next byte */
|
||||
return NULL;
|
||||
*(p++) = '>';
|
||||
|
||||
if((pv = args->val))
|
||||
{
|
||||
while(p < pend && *pv)
|
||||
*(p++) = *(pv++);
|
||||
}
|
||||
|
||||
if((p+2) > pend) /* check for space to write next 2 bytes */
|
||||
return NULL;
|
||||
*(p++) = '<';
|
||||
*(p++) = '/';
|
||||
|
||||
pe = args->elt;
|
||||
while(p < pend && *pe)
|
||||
*(p++) = *(pe++);
|
||||
|
||||
if(p >= pend) /* check for space to write next byte */
|
||||
return NULL;
|
||||
*(p++) = '>';
|
||||
|
||||
args++;
|
||||
}
|
||||
if((p+4) > pend) /* check for space to write next 4 bytes */
|
||||
return NULL;
|
||||
*(p++) = '<';
|
||||
*(p++) = '/';
|
||||
*(p++) = SERVICEPREFIX2;
|
||||
*(p++) = ':';
|
||||
|
||||
pe = action;
|
||||
while(p < pend && *pe)
|
||||
*(p++) = *(pe++);
|
||||
|
||||
strncpy(p, "></" SOAPPREFIX ":Body></" SOAPPREFIX ":Envelope>\r\n",
|
||||
pend - p);
|
||||
if(soapbody[sizeof(soapbody)-1]) /* strncpy pads buffer with 0s, so if it doesn't end in 0, could not fit full string */
|
||||
return NULL;
|
||||
}
|
||||
if(!parseURL(url, hostname, &port, &path, NULL)) return NULL;
|
||||
if(s < 0) {
|
||||
s = connecthostport(hostname, port, 0);
|
||||
if(s < 0) {
|
||||
/* failed to connect */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
n = soapPostSubmit(s, path, hostname, port, soapact, soapbody, httpversion);
|
||||
if(n<=0) {
|
||||
#ifdef DEBUG
|
||||
printf("Error sending SOAP request\n");
|
||||
#endif
|
||||
closesocket(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf = (char*)getHTTPResponse(s, bufsize, &status_code);
|
||||
#ifdef DEBUG
|
||||
if(*bufsize > 0 && buf)
|
||||
{
|
||||
printf("HTTP %d SOAP Response :\n%.*s\n", status_code, *bufsize, buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("HTTP %d, empty SOAP response. size=%d\n", status_code, *bufsize);
|
||||
}
|
||||
#endif
|
||||
closesocket(s);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* simpleUPnPcommand :
|
||||
* not so simple !
|
||||
* return values :
|
||||
* pointer - OK
|
||||
* NULL - error */
|
||||
char * simpleUPnPcommand(int s, const char * url, const char * service,
|
||||
const char * action, struct UPNParg * args,
|
||||
int * bufsize)
|
||||
{
|
||||
char * buf;
|
||||
|
||||
#if 1
|
||||
buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.1");
|
||||
#else
|
||||
buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.0");
|
||||
if (!buf || *bufsize == 0)
|
||||
{
|
||||
#if DEBUG
|
||||
printf("Error or no result from SOAP request; retrying with HTTP/1.1\n");
|
||||
#endif
|
||||
buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.1");
|
||||
}
|
||||
#endif
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* upnpDiscoverDevices() :
|
||||
* return a chained list of all devices found or NULL if
|
||||
* no devices was found.
|
||||
* It is up to the caller to free the chained list
|
||||
* delay is in millisecond (poll).
|
||||
* UDA v1.1 says :
|
||||
* The TTL for the IP packet SHOULD default to 2 and
|
||||
* SHOULD be configurable. */
|
||||
MINIUPNP_LIBSPEC struct UPNPDev *
|
||||
upnpDiscoverDevices(const char * const deviceTypes[],
|
||||
int delay, const char * multicastif,
|
||||
const char * minissdpdsock, int localport,
|
||||
int ipv6, unsigned char ttl,
|
||||
int * error,
|
||||
int searchalltypes)
|
||||
{
|
||||
struct UPNPDev * tmp;
|
||||
struct UPNPDev * devlist = 0;
|
||||
#if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__)
|
||||
int deviceIndex;
|
||||
#endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
|
||||
|
||||
if(error)
|
||||
*error = UPNPDISCOVER_UNKNOWN_ERROR;
|
||||
#if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__)
|
||||
/* first try to get infos from minissdpd ! */
|
||||
if(!minissdpdsock)
|
||||
minissdpdsock = "/var/run/minissdpd.sock";
|
||||
for(deviceIndex = 0; deviceTypes[deviceIndex]; deviceIndex++) {
|
||||
struct UPNPDev * minissdpd_devlist;
|
||||
int only_rootdevice = 1;
|
||||
minissdpd_devlist = getDevicesFromMiniSSDPD(deviceTypes[deviceIndex],
|
||||
minissdpdsock, 0);
|
||||
if(minissdpd_devlist) {
|
||||
#ifdef DEBUG
|
||||
printf("returned by MiniSSDPD: %s\t%s\n",
|
||||
minissdpd_devlist->st, minissdpd_devlist->descURL);
|
||||
#endif /* DEBUG */
|
||||
if(!strstr(minissdpd_devlist->st, "rootdevice"))
|
||||
only_rootdevice = 0;
|
||||
for(tmp = minissdpd_devlist; tmp->pNext != NULL; tmp = tmp->pNext) {
|
||||
#ifdef DEBUG
|
||||
printf("returned by MiniSSDPD: %s\t%s\n",
|
||||
tmp->pNext->st, tmp->pNext->descURL);
|
||||
#endif /* DEBUG */
|
||||
if(!strstr(tmp->st, "rootdevice"))
|
||||
only_rootdevice = 0;
|
||||
}
|
||||
tmp->pNext = devlist;
|
||||
devlist = minissdpd_devlist;
|
||||
if(!searchalltypes && !only_rootdevice)
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(tmp = devlist; tmp != NULL; tmp = tmp->pNext) {
|
||||
/* We return what we have found if it was not only a rootdevice */
|
||||
if(!strstr(tmp->st, "rootdevice")) {
|
||||
if(error)
|
||||
*error = UPNPDISCOVER_SUCCESS;
|
||||
return devlist;
|
||||
}
|
||||
}
|
||||
#endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
|
||||
|
||||
/* direct discovery if minissdpd responses are not sufficient */
|
||||
{
|
||||
struct UPNPDev * discovered_devlist;
|
||||
discovered_devlist = ssdpDiscoverDevices(deviceTypes, delay, multicastif, localport,
|
||||
ipv6, ttl, error, searchalltypes);
|
||||
if(devlist == NULL)
|
||||
devlist = discovered_devlist;
|
||||
else {
|
||||
for(tmp = devlist; tmp->pNext != NULL; tmp = tmp->pNext);
|
||||
tmp->pNext = discovered_devlist;
|
||||
}
|
||||
}
|
||||
return devlist;
|
||||
}
|
||||
|
||||
/* upnpDiscover() Discover IGD device */
|
||||
MINIUPNP_LIBSPEC struct UPNPDev *
|
||||
upnpDiscover(int delay, const char * multicastif,
|
||||
const char * minissdpdsock, int localport,
|
||||
int ipv6, unsigned char ttl,
|
||||
int * error)
|
||||
{
|
||||
static const char * const deviceList[] = {
|
||||
#if 0
|
||||
"urn:schemas-upnp-org:device:InternetGatewayDevice:2",
|
||||
"urn:schemas-upnp-org:service:WANIPConnection:2",
|
||||
#endif
|
||||
"urn:schemas-upnp-org:device:InternetGatewayDevice:1",
|
||||
"urn:schemas-upnp-org:service:WANIPConnection:1",
|
||||
"urn:schemas-upnp-org:service:WANPPPConnection:1",
|
||||
"upnp:rootdevice",
|
||||
/*"ssdp:all",*/
|
||||
0
|
||||
};
|
||||
return upnpDiscoverDevices(deviceList,
|
||||
delay, multicastif, minissdpdsock, localport,
|
||||
ipv6, ttl, error, 0);
|
||||
}
|
||||
|
||||
/* upnpDiscoverAll() Discover all UPnP devices */
|
||||
MINIUPNP_LIBSPEC struct UPNPDev *
|
||||
upnpDiscoverAll(int delay, const char * multicastif,
|
||||
const char * minissdpdsock, int localport,
|
||||
int ipv6, unsigned char ttl,
|
||||
int * error)
|
||||
{
|
||||
static const char * const deviceList[] = {
|
||||
/*"upnp:rootdevice",*/
|
||||
"ssdp:all",
|
||||
0
|
||||
};
|
||||
return upnpDiscoverDevices(deviceList,
|
||||
delay, multicastif, minissdpdsock, localport,
|
||||
ipv6, ttl, error, 0);
|
||||
}
|
||||
|
||||
/* upnpDiscoverDevice() Discover a specific device */
|
||||
MINIUPNP_LIBSPEC struct UPNPDev *
|
||||
upnpDiscoverDevice(const char * device, int delay, const char * multicastif,
|
||||
const char * minissdpdsock, int localport,
|
||||
int ipv6, unsigned char ttl,
|
||||
int * error)
|
||||
{
|
||||
const char * const deviceList[] = {
|
||||
device,
|
||||
0
|
||||
};
|
||||
return upnpDiscoverDevices(deviceList,
|
||||
delay, multicastif, minissdpdsock, localport,
|
||||
ipv6, ttl, error, 0);
|
||||
}
|
||||
|
||||
static char *
|
||||
build_absolute_url(const char * baseurl, const char * descURL,
|
||||
const char * url, unsigned int scope_id)
|
||||
{
|
||||
int l, n;
|
||||
char * s;
|
||||
const char * base;
|
||||
char * p;
|
||||
#if defined(IF_NAMESIZE) && !defined(_WIN32)
|
||||
char ifname[IF_NAMESIZE];
|
||||
#else /* defined(IF_NAMESIZE) && !defined(_WIN32) */
|
||||
char scope_str[8];
|
||||
#endif /* defined(IF_NAMESIZE) && !defined(_WIN32) */
|
||||
|
||||
if( (url[0] == 'h')
|
||||
&&(url[1] == 't')
|
||||
&&(url[2] == 't')
|
||||
&&(url[3] == 'p')
|
||||
&&(url[4] == ':')
|
||||
&&(url[5] == '/')
|
||||
&&(url[6] == '/'))
|
||||
return strdup(url);
|
||||
base = (baseurl[0] == '\0') ? descURL : baseurl;
|
||||
n = (int)strlen(base);
|
||||
if(n > 7) {
|
||||
p = (char*)strchr(base + 7, '/');
|
||||
if(p)
|
||||
n = (int)(p - base);
|
||||
}
|
||||
l = (int)(n + strlen(url) + 1);
|
||||
if(url[0] != '/')
|
||||
l++;
|
||||
if(scope_id != 0) {
|
||||
#if defined(IF_NAMESIZE) && !defined(_WIN32)
|
||||
if(if_indextoname(scope_id, ifname)) {
|
||||
l += 3 + strlen(ifname); /* 3 == strlen(%25) */
|
||||
}
|
||||
#else /* defined(IF_NAMESIZE) && !defined(_WIN32) */
|
||||
/* under windows, scope is numerical */
|
||||
l += 3 + snprintf(scope_str, sizeof(scope_str), "%u", scope_id);
|
||||
#endif /* defined(IF_NAMESIZE) && !defined(_WIN32) */
|
||||
}
|
||||
s = (char*)malloc(l);
|
||||
if(s == NULL) return NULL;
|
||||
memcpy(s, base, n);
|
||||
if(scope_id != 0) {
|
||||
s[n] = '\0';
|
||||
if(0 == memcmp(s, "http://[fe80:", 13)) {
|
||||
/* this is a linklocal IPv6 address */
|
||||
p = strchr(s, ']');
|
||||
if(p) {
|
||||
/* insert %25<scope> into URL */
|
||||
#if defined(IF_NAMESIZE) && !defined(_WIN32)
|
||||
memmove(p + 3 + strlen(ifname), p, strlen(p) + 1);
|
||||
memcpy(p, "%25", 3);
|
||||
memcpy(p + 3, ifname, strlen(ifname));
|
||||
n += 3 + strlen(ifname);
|
||||
#else /* defined(IF_NAMESIZE) && !defined(_WIN32) */
|
||||
memmove(p + 3 + strlen(scope_str), p, strlen(p) + 1);
|
||||
memcpy(p, "%25", 3);
|
||||
memcpy(p + 3, scope_str, strlen(scope_str));
|
||||
n += 3 + strlen(scope_str);
|
||||
#endif /* defined(IF_NAMESIZE) && !defined(_WIN32) */
|
||||
}
|
||||
}
|
||||
}
|
||||
if(url[0] != '/')
|
||||
s[n++] = '/';
|
||||
memcpy(s + n, url, l - n);
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Prepare the Urls for usage...
|
||||
*/
|
||||
MINIUPNP_LIBSPEC void
|
||||
GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data,
|
||||
const char * descURL, unsigned int scope_id)
|
||||
{
|
||||
/* strdup descURL */
|
||||
urls->rootdescURL = strdup(descURL);
|
||||
|
||||
/* get description of WANIPConnection */
|
||||
urls->ipcondescURL = build_absolute_url(data->urlbase, descURL,
|
||||
data->first.scpdurl, scope_id);
|
||||
urls->controlURL = build_absolute_url(data->urlbase, descURL,
|
||||
data->first.controlurl, scope_id);
|
||||
urls->controlURL_CIF = build_absolute_url(data->urlbase, descURL,
|
||||
data->CIF.controlurl, scope_id);
|
||||
urls->controlURL_6FC = build_absolute_url(data->urlbase, descURL,
|
||||
data->IPv6FC.controlurl, scope_id);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("urls->ipcondescURL='%s'\n", urls->ipcondescURL);
|
||||
printf("urls->controlURL='%s'\n", urls->controlURL);
|
||||
printf("urls->controlURL_CIF='%s'\n", urls->controlURL_CIF);
|
||||
printf("urls->controlURL_6FC='%s'\n", urls->controlURL_6FC);
|
||||
#endif
|
||||
}
|
||||
|
||||
MINIUPNP_LIBSPEC void
|
||||
FreeUPNPUrls(struct UPNPUrls * urls)
|
||||
{
|
||||
if(!urls)
|
||||
return;
|
||||
free(urls->controlURL);
|
||||
urls->controlURL = 0;
|
||||
free(urls->ipcondescURL);
|
||||
urls->ipcondescURL = 0;
|
||||
free(urls->controlURL_CIF);
|
||||
urls->controlURL_CIF = 0;
|
||||
free(urls->controlURL_6FC);
|
||||
urls->controlURL_6FC = 0;
|
||||
free(urls->rootdescURL);
|
||||
urls->rootdescURL = 0;
|
||||
}
|
||||
|
||||
int
|
||||
UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data)
|
||||
{
|
||||
char status[64];
|
||||
unsigned int uptime;
|
||||
status[0] = '\0';
|
||||
UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype,
|
||||
status, &uptime, NULL);
|
||||
if(0 == strcmp("Connected", status))
|
||||
return 1;
|
||||
else if(0 == strcmp("Up", status)) /* Also accept "Up" */
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* UPNP_GetValidIGD() :
|
||||
* return values :
|
||||
* -1 = Internal error
|
||||
* 0 = NO IGD found
|
||||
* 1 = A valid connected IGD has been found
|
||||
* 2 = A valid IGD has been found but it reported as
|
||||
* not connected
|
||||
* 3 = an UPnP device has been found but was not recognized as an IGD
|
||||
*
|
||||
* In any positive non zero return case, the urls and data structures
|
||||
* passed as parameters are set. Dont forget to call FreeUPNPUrls(urls) to
|
||||
* free allocated memory.
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetValidIGD(struct UPNPDev * devlist,
|
||||
struct UPNPUrls * urls,
|
||||
struct IGDdatas * data,
|
||||
char * lanaddr, int lanaddrlen)
|
||||
{
|
||||
struct xml_desc {
|
||||
char * xml;
|
||||
int size;
|
||||
int is_igd;
|
||||
} * desc = NULL;
|
||||
struct UPNPDev * dev;
|
||||
int ndev = 0;
|
||||
int i;
|
||||
int state = -1; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */
|
||||
int n_igd = 0;
|
||||
char extIpAddr[16];
|
||||
char myLanAddr[40];
|
||||
int status_code = -1;
|
||||
|
||||
if(!devlist)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Empty devlist\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
/* counting total number of devices in the list */
|
||||
for(dev = devlist; dev; dev = dev->pNext)
|
||||
ndev++;
|
||||
if(ndev > 0)
|
||||
{
|
||||
desc = (struct xml_desc*)calloc(ndev, sizeof(struct xml_desc));
|
||||
if(!desc)
|
||||
return -1; /* memory allocation error */
|
||||
}
|
||||
/* Step 1 : downloading descriptions and testing type */
|
||||
for(dev = devlist, i = 0; dev; dev = dev->pNext, i++)
|
||||
{
|
||||
/* we should choose an internet gateway device.
|
||||
* with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */
|
||||
desc[i].xml = (char*)miniwget_getaddr(dev->descURL, &(desc[i].size),
|
||||
myLanAddr, sizeof(myLanAddr),
|
||||
dev->scope_id, &status_code);
|
||||
#ifdef DEBUG
|
||||
if(!desc[i].xml)
|
||||
{
|
||||
printf("error getting XML description %s\n", dev->descURL);
|
||||
}
|
||||
#endif
|
||||
if(desc[i].xml)
|
||||
{
|
||||
memset(data, 0, sizeof(struct IGDdatas));
|
||||
memset(urls, 0, sizeof(struct UPNPUrls));
|
||||
parserootdesc(desc[i].xml, desc[i].size, data);
|
||||
if(COMPARE(data->CIF.servicetype,
|
||||
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:"))
|
||||
{
|
||||
desc[i].is_igd = 1;
|
||||
n_igd++;
|
||||
if(lanaddr)
|
||||
strncpy(lanaddr, myLanAddr, lanaddrlen);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* iterate the list to find a device depending on state */
|
||||
for(state = 1; state <= 3; state++)
|
||||
{
|
||||
for(dev = devlist, i = 0; dev; dev = dev->pNext, i++)
|
||||
{
|
||||
if(desc[i].xml)
|
||||
{
|
||||
memset(data, 0, sizeof(struct IGDdatas));
|
||||
memset(urls, 0, sizeof(struct UPNPUrls));
|
||||
parserootdesc(desc[i].xml, desc[i].size, data);
|
||||
if(desc[i].is_igd || state >= 3 )
|
||||
{
|
||||
int is_connected;
|
||||
|
||||
GetUPNPUrls(urls, data, dev->descURL, dev->scope_id);
|
||||
|
||||
/* in state 2 and 3 we dont test if device is connected ! */
|
||||
if(state >= 2)
|
||||
goto free_and_return;
|
||||
is_connected = UPNPIGD_IsConnected(urls, data);
|
||||
#ifdef DEBUG
|
||||
printf("UPNPIGD_IsConnected(%s) = %d\n",
|
||||
urls->controlURL, is_connected);
|
||||
#endif
|
||||
/* checks that status is connected AND there is a external IP address assigned */
|
||||
if(is_connected &&
|
||||
(UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) {
|
||||
if(!is_rfc1918addr(extIpAddr) && (extIpAddr[0] != '\0')
|
||||
&& (0 != strcmp(extIpAddr, "0.0.0.0")))
|
||||
goto free_and_return;
|
||||
}
|
||||
FreeUPNPUrls(urls);
|
||||
if(data->second.servicetype[0] != '\0') {
|
||||
#ifdef DEBUG
|
||||
printf("We tried %s, now we try %s !\n",
|
||||
data->first.servicetype, data->second.servicetype);
|
||||
#endif
|
||||
/* swaping WANPPPConnection and WANIPConnection ! */
|
||||
memcpy(&data->tmp, &data->first, sizeof(struct IGDdatas_service));
|
||||
memcpy(&data->first, &data->second, sizeof(struct IGDdatas_service));
|
||||
memcpy(&data->second, &data->tmp, sizeof(struct IGDdatas_service));
|
||||
GetUPNPUrls(urls, data, dev->descURL, dev->scope_id);
|
||||
is_connected = UPNPIGD_IsConnected(urls, data);
|
||||
#ifdef DEBUG
|
||||
printf("UPNPIGD_IsConnected(%s) = %d\n",
|
||||
urls->controlURL, is_connected);
|
||||
#endif
|
||||
if(is_connected &&
|
||||
(UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) {
|
||||
if(!is_rfc1918addr(extIpAddr) && (extIpAddr[0] != '\0')
|
||||
&& (0 != strcmp(extIpAddr, "0.0.0.0")))
|
||||
goto free_and_return;
|
||||
}
|
||||
FreeUPNPUrls(urls);
|
||||
}
|
||||
}
|
||||
memset(data, 0, sizeof(struct IGDdatas));
|
||||
}
|
||||
}
|
||||
}
|
||||
state = 0;
|
||||
free_and_return:
|
||||
if(desc) {
|
||||
for(i = 0; i < ndev; i++) {
|
||||
if(desc[i].xml) {
|
||||
free(desc[i].xml);
|
||||
}
|
||||
}
|
||||
free(desc);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
/* UPNP_GetIGDFromUrl()
|
||||
* Used when skipping the discovery process.
|
||||
* return value :
|
||||
* 0 - Not ok
|
||||
* 1 - OK */
|
||||
int
|
||||
UPNP_GetIGDFromUrl(const char * rootdescurl,
|
||||
struct UPNPUrls * urls,
|
||||
struct IGDdatas * data,
|
||||
char * lanaddr, int lanaddrlen)
|
||||
{
|
||||
char * descXML;
|
||||
int descXMLsize = 0;
|
||||
|
||||
descXML = (char*)miniwget_getaddr(rootdescurl, &descXMLsize,
|
||||
lanaddr, lanaddrlen, 0, NULL);
|
||||
if(descXML) {
|
||||
memset(data, 0, sizeof(struct IGDdatas));
|
||||
memset(urls, 0, sizeof(struct UPNPUrls));
|
||||
parserootdesc(descXML, descXMLsize, data);
|
||||
free(descXML);
|
||||
descXML = NULL;
|
||||
GetUPNPUrls(urls, data, rootdescurl, 0);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
-45
@@ -1,45 +0,0 @@
|
||||
LIBRARY
|
||||
; miniupnpc library
|
||||
miniupnpc
|
||||
|
||||
EXPORTS
|
||||
; miniupnpc
|
||||
upnpDiscover
|
||||
freeUPNPDevlist
|
||||
parserootdesc
|
||||
UPNP_GetValidIGD
|
||||
UPNP_GetIGDFromUrl
|
||||
GetUPNPUrls
|
||||
FreeUPNPUrls
|
||||
; miniwget
|
||||
miniwget
|
||||
miniwget_getaddr
|
||||
; upnpcommands
|
||||
UPNP_GetTotalBytesSent
|
||||
UPNP_GetTotalBytesReceived
|
||||
UPNP_GetTotalPacketsSent
|
||||
UPNP_GetTotalPacketsReceived
|
||||
UPNP_GetStatusInfo
|
||||
UPNP_GetConnectionTypeInfo
|
||||
UPNP_GetExternalIPAddress
|
||||
UPNP_GetLinkLayerMaxBitRates
|
||||
UPNP_AddPortMapping
|
||||
UPNP_AddAnyPortMapping
|
||||
UPNP_DeletePortMapping
|
||||
UPNP_DeletePortMappingRange
|
||||
UPNP_GetPortMappingNumberOfEntries
|
||||
UPNP_GetSpecificPortMappingEntry
|
||||
UPNP_GetGenericPortMappingEntry
|
||||
UPNP_GetListOfPortMappings
|
||||
UPNP_AddPinhole
|
||||
UPNP_CheckPinholeWorking
|
||||
UPNP_UpdatePinhole
|
||||
UPNP_GetPinholePackets
|
||||
UPNP_DeletePinhole
|
||||
UPNP_GetFirewallStatus
|
||||
UPNP_GetOutboundPinholeTimeout
|
||||
; upnperrors
|
||||
strupnperror
|
||||
; portlistingparse
|
||||
ParsePortListing
|
||||
FreePortListing
|
||||
Vendored
-152
@@ -1,152 +0,0 @@
|
||||
/* $Id: miniupnpc.h,v 1.50 2016/04/19 21:06:21 nanard Exp $ */
|
||||
/* Project: miniupnp
|
||||
* http://miniupnp.free.fr/
|
||||
* Author: Thomas Bernard
|
||||
* Copyright (c) 2005-2016 Thomas Bernard
|
||||
* This software is subjects to the conditions detailed
|
||||
* in the LICENCE file provided within this distribution */
|
||||
#ifndef MINIUPNPC_H_INCLUDED
|
||||
#define MINIUPNPC_H_INCLUDED
|
||||
|
||||
#include "miniupnpc_declspec.h"
|
||||
#include "igd_desc_parse.h"
|
||||
#include "upnpdev.h"
|
||||
|
||||
/* error codes : */
|
||||
#define UPNPDISCOVER_SUCCESS (0)
|
||||
#define UPNPDISCOVER_UNKNOWN_ERROR (-1)
|
||||
#define UPNPDISCOVER_SOCKET_ERROR (-101)
|
||||
#define UPNPDISCOVER_MEMORY_ERROR (-102)
|
||||
|
||||
/* versions : */
|
||||
#define MINIUPNPC_VERSION "2.0"
|
||||
#define MINIUPNPC_API_VERSION 16
|
||||
|
||||
/* Source port:
|
||||
Using "1" as an alias for 1900 for backwards compatability
|
||||
(presuming one would have used that for the "sameport" parameter) */
|
||||
#define UPNP_LOCAL_PORT_ANY 0
|
||||
#define UPNP_LOCAL_PORT_SAME 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Structures definitions : */
|
||||
struct UPNParg { const char * elt; const char * val; };
|
||||
|
||||
char *
|
||||
simpleUPnPcommand(int, const char *, const char *,
|
||||
const char *, struct UPNParg *,
|
||||
int *);
|
||||
|
||||
/* upnpDiscover()
|
||||
* discover UPnP devices on the network.
|
||||
* The discovered devices are returned as a chained list.
|
||||
* It is up to the caller to free the list with freeUPNPDevlist().
|
||||
* delay (in millisecond) is the maximum time for waiting any device
|
||||
* response.
|
||||
* If available, device list will be obtained from MiniSSDPd.
|
||||
* Default path for minissdpd socket will be used if minissdpdsock argument
|
||||
* is NULL.
|
||||
* If multicastif is not NULL, it will be used instead of the default
|
||||
* multicast interface for sending SSDP discover packets.
|
||||
* If localport is set to UPNP_LOCAL_PORT_SAME(1) SSDP packets will be sent
|
||||
* from the source port 1900 (same as destination port), if set to
|
||||
* UPNP_LOCAL_PORT_ANY(0) system assign a source port, any other value will
|
||||
* be attempted as the source port.
|
||||
* "searchalltypes" parameter is useful when searching several types,
|
||||
* if 0, the discovery will stop with the first type returning results.
|
||||
* TTL should default to 2. */
|
||||
MINIUPNP_LIBSPEC struct UPNPDev *
|
||||
upnpDiscover(int delay, const char * multicastif,
|
||||
const char * minissdpdsock, int localport,
|
||||
int ipv6, unsigned char ttl,
|
||||
int * error);
|
||||
|
||||
MINIUPNP_LIBSPEC struct UPNPDev *
|
||||
upnpDiscoverAll(int delay, const char * multicastif,
|
||||
const char * minissdpdsock, int localport,
|
||||
int ipv6, unsigned char ttl,
|
||||
int * error);
|
||||
|
||||
MINIUPNP_LIBSPEC struct UPNPDev *
|
||||
upnpDiscoverDevice(const char * device, int delay, const char * multicastif,
|
||||
const char * minissdpdsock, int localport,
|
||||
int ipv6, unsigned char ttl,
|
||||
int * error);
|
||||
|
||||
MINIUPNP_LIBSPEC struct UPNPDev *
|
||||
upnpDiscoverDevices(const char * const deviceTypes[],
|
||||
int delay, const char * multicastif,
|
||||
const char * minissdpdsock, int localport,
|
||||
int ipv6, unsigned char ttl,
|
||||
int * error,
|
||||
int searchalltypes);
|
||||
|
||||
/* parserootdesc() :
|
||||
* parse root XML description of a UPnP device and fill the IGDdatas
|
||||
* structure. */
|
||||
MINIUPNP_LIBSPEC void parserootdesc(const char *, int, struct IGDdatas *);
|
||||
|
||||
/* structure used to get fast access to urls
|
||||
* controlURL: controlURL of the WANIPConnection
|
||||
* ipcondescURL: url of the description of the WANIPConnection
|
||||
* controlURL_CIF: controlURL of the WANCommonInterfaceConfig
|
||||
* controlURL_6FC: controlURL of the WANIPv6FirewallControl
|
||||
*/
|
||||
struct UPNPUrls {
|
||||
char * controlURL;
|
||||
char * ipcondescURL;
|
||||
char * controlURL_CIF;
|
||||
char * controlURL_6FC;
|
||||
char * rootdescURL;
|
||||
};
|
||||
|
||||
/* UPNP_GetValidIGD() :
|
||||
* return values :
|
||||
* 0 = NO IGD found
|
||||
* 1 = A valid connected IGD has been found
|
||||
* 2 = A valid IGD has been found but it reported as
|
||||
* not connected
|
||||
* 3 = an UPnP device has been found but was not recognized as an IGD
|
||||
*
|
||||
* In any non zero return case, the urls and data structures
|
||||
* passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to
|
||||
* free allocated memory.
|
||||
*/
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetValidIGD(struct UPNPDev * devlist,
|
||||
struct UPNPUrls * urls,
|
||||
struct IGDdatas * data,
|
||||
char * lanaddr, int lanaddrlen);
|
||||
|
||||
/* UPNP_GetIGDFromUrl()
|
||||
* Used when skipping the discovery process.
|
||||
* When succeding, urls, data, and lanaddr arguments are set.
|
||||
* return value :
|
||||
* 0 - Not ok
|
||||
* 1 - OK */
|
||||
MINIUPNP_LIBSPEC int
|
||||
UPNP_GetIGDFromUrl(const char * rootdescurl,
|
||||
struct UPNPUrls * urls,
|
||||
struct IGDdatas * data,
|
||||
char * lanaddr, int lanaddrlen);
|
||||
|
||||
MINIUPNP_LIBSPEC void
|
||||
GetUPNPUrls(struct UPNPUrls *, struct IGDdatas *,
|
||||
const char *, unsigned int);
|
||||
|
||||
MINIUPNP_LIBSPEC void
|
||||
FreeUPNPUrls(struct UPNPUrls *);
|
||||
|
||||
/* return 0 or 1 */
|
||||
MINIUPNP_LIBSPEC int UPNPIGD_IsConnected(struct UPNPUrls *, struct IGDdatas *);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Vendored
-12
@@ -1,12 +0,0 @@
|
||||
#ifndef MINIUPNPC_DECLSPEC_H_INCLUDED
|
||||
#define MINIUPNPC_DECLSPEC_H_INCLUDED
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 4
|
||||
/* fix dynlib for OS X 10.9.2 and Apple LLVM version 5.0 */
|
||||
#define MINIUPNP_LIBSPEC __attribute__ ((visibility ("default")))
|
||||
#else
|
||||
#define MINIUPNP_LIBSPEC
|
||||
#endif
|
||||
|
||||
#endif /* MINIUPNPC_DECLSPEC_H_INCLUDED */
|
||||
|
||||
Vendored
-23
@@ -1,23 +0,0 @@
|
||||
/* $Id: miniupnpcstrings.h.in,v 1.6 2014/11/04 22:31:55 nanard Exp $ */
|
||||
/* Project: miniupnp
|
||||
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* Author: Thomas Bernard
|
||||
* Copyright (c) 2005-2014 Thomas Bernard
|
||||
* This software is subjects to the conditions detailed
|
||||
* in the LICENCE file provided within this distribution */
|
||||
#ifndef MINIUPNPCSTRINGS_H_INCLUDED
|
||||
#define MINIUPNPCSTRINGS_H_INCLUDED
|
||||
|
||||
#define OS_STRING "OS/version"
|
||||
#define MINIUPNPC_VERSION_STRING "version"
|
||||
|
||||
#if 0
|
||||
/* according to "UPnP Device Architecture 1.0" */
|
||||
#define UPNP_VERSION_STRING "UPnP/1.0"
|
||||
#else
|
||||
/* according to "UPnP Device Architecture 1.1" */
|
||||
#define UPNP_VERSION_STRING "UPnP/1.1"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Vendored
-19
@@ -1,19 +0,0 @@
|
||||
/* $Id: miniupnpctypes.h,v 1.1 2011/02/15 11:10:40 nanard Exp $ */
|
||||
/* Miniupnp project : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2011 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided within this distribution */
|
||||
#ifndef MINIUPNPCTYPES_H_INCLUDED
|
||||
#define MINIUPNPCTYPES_H_INCLUDED
|
||||
|
||||
#if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
|
||||
#define UNSIGNED_INTEGER unsigned long long
|
||||
#define STRTOUI strtoull
|
||||
#else
|
||||
#define UNSIGNED_INTEGER unsigned int
|
||||
#define STRTOUI strtoul
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Vendored
-663
@@ -1,663 +0,0 @@
|
||||
/* $Id: miniwget.c,v 1.75 2016/01/24 17:24:36 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Website : http://miniupnp.free.fr/
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005-2016 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <io.h>
|
||||
#define MAXHOSTNAMELEN 64
|
||||
#define snprintf _snprintf
|
||||
#define socklen_t int
|
||||
#ifndef strncasecmp
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||
#define strncasecmp _memicmp
|
||||
#else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
|
||||
#define strncasecmp memicmp
|
||||
#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
|
||||
#endif /* #ifndef strncasecmp */
|
||||
#else /* #ifdef _WIN32 */
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
#if defined(__amigaos__) && !defined(__amigaos4__)
|
||||
#define socklen_t int
|
||||
#else /* #if defined(__amigaos__) && !defined(__amigaos4__) */
|
||||
#include <sys/select.h>
|
||||
#endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
#include <netdb.h>
|
||||
#ifndef closesocket
|
||||
#define closesocket close
|
||||
#endif
|
||||
#include <strings.h>
|
||||
#endif /* #else _WIN32 */
|
||||
#ifdef __GNU__
|
||||
#define MAXHOSTNAMELEN 64
|
||||
#endif /* __GNU__ */
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(x,y) (((x)<(y))?(x):(y))
|
||||
#endif /* MIN */
|
||||
|
||||
|
||||
#include "miniupnpcstrings.h"
|
||||
#include "miniwget.h"
|
||||
#include "connecthostport.h"
|
||||
#include "receivedata.h"
|
||||
|
||||
#ifndef MAXHOSTNAMELEN
|
||||
#define MAXHOSTNAMELEN 64
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Read a HTTP response from a socket.
|
||||
* Process Content-Length and Transfer-encoding headers.
|
||||
* return a pointer to the content buffer, which length is saved
|
||||
* to the length parameter.
|
||||
*/
|
||||
void *
|
||||
getHTTPResponse(int s, int * size, int * status_code)
|
||||
{
|
||||
char buf[2048];
|
||||
int n;
|
||||
int endofheaders = 0;
|
||||
int chunked = 0;
|
||||
int content_length = -1;
|
||||
unsigned int chunksize = 0;
|
||||
unsigned int bytestocopy = 0;
|
||||
/* buffers : */
|
||||
char * header_buf;
|
||||
unsigned int header_buf_len = 2048;
|
||||
unsigned int header_buf_used = 0;
|
||||
char * content_buf;
|
||||
unsigned int content_buf_len = 2048;
|
||||
unsigned int content_buf_used = 0;
|
||||
char chunksize_buf[32];
|
||||
unsigned int chunksize_buf_index;
|
||||
#ifdef DEBUG
|
||||
char * reason_phrase = NULL;
|
||||
int reason_phrase_len = 0;
|
||||
#endif
|
||||
|
||||
if(status_code) *status_code = -1;
|
||||
header_buf = (char*)malloc(header_buf_len);
|
||||
if(header_buf == NULL)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "%s: Memory allocation error\n", "getHTTPResponse");
|
||||
#endif /* DEBUG */
|
||||
*size = -1;
|
||||
return NULL;
|
||||
}
|
||||
content_buf = (char*)malloc(content_buf_len);
|
||||
if(content_buf == NULL)
|
||||
{
|
||||
free(header_buf);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "%s: Memory allocation error\n", "getHTTPResponse");
|
||||
#endif /* DEBUG */
|
||||
*size = -1;
|
||||
return NULL;
|
||||
}
|
||||
chunksize_buf[0] = '\0';
|
||||
chunksize_buf_index = 0;
|
||||
|
||||
while((n = receivedata(s, buf, 2048, 5000, NULL)) > 0)
|
||||
{
|
||||
if(endofheaders == 0)
|
||||
{
|
||||
int i;
|
||||
int linestart=0;
|
||||
int colon=0;
|
||||
int valuestart=0;
|
||||
if(header_buf_used + n > header_buf_len) {
|
||||
char * tmp = (char*)realloc(header_buf, header_buf_used + n);
|
||||
if(tmp == NULL) {
|
||||
/* memory allocation error */
|
||||
free(header_buf);
|
||||
free(content_buf);
|
||||
*size = -1;
|
||||
return NULL;
|
||||
}
|
||||
header_buf = tmp;
|
||||
header_buf_len = header_buf_used + n;
|
||||
}
|
||||
memcpy(header_buf + header_buf_used, buf, n);
|
||||
header_buf_used += n;
|
||||
/* search for CR LF CR LF (end of headers)
|
||||
* recognize also LF LF */
|
||||
i = 0;
|
||||
while(i < ((int)header_buf_used-1) && (endofheaders == 0)) {
|
||||
if(header_buf[i] == '\r') {
|
||||
i++;
|
||||
if(header_buf[i] == '\n') {
|
||||
i++;
|
||||
if(i < (int)header_buf_used && header_buf[i] == '\r') {
|
||||
i++;
|
||||
if(i < (int)header_buf_used && header_buf[i] == '\n') {
|
||||
endofheaders = i+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(header_buf[i] == '\n') {
|
||||
i++;
|
||||
if(header_buf[i] == '\n') {
|
||||
endofheaders = i+1;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if(endofheaders == 0)
|
||||
continue;
|
||||
/* parse header lines */
|
||||
for(i = 0; i < endofheaders - 1; i++) {
|
||||
if(linestart > 0 && colon <= linestart && header_buf[i]==':')
|
||||
{
|
||||
colon = i;
|
||||
while(i < (endofheaders-1)
|
||||
&& (header_buf[i+1] == ' ' || header_buf[i+1] == '\t'))
|
||||
i++;
|
||||
valuestart = i + 1;
|
||||
}
|
||||
/* detecting end of line */
|
||||
else if(header_buf[i]=='\r' || header_buf[i]=='\n')
|
||||
{
|
||||
if(linestart == 0 && status_code)
|
||||
{
|
||||
/* Status line
|
||||
* HTTP-Version SP Status-Code SP Reason-Phrase CRLF */
|
||||
int sp;
|
||||
for(sp = 0; sp < i; sp++)
|
||||
if(header_buf[sp] == ' ')
|
||||
{
|
||||
if(*status_code < 0)
|
||||
*status_code = atoi(header_buf + sp + 1);
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
reason_phrase = header_buf + sp + 1;
|
||||
reason_phrase_len = i - sp - 1;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("HTTP status code = %d, Reason phrase = %.*s\n",
|
||||
*status_code, reason_phrase_len, reason_phrase);
|
||||
#endif
|
||||
}
|
||||
else if(colon > linestart && valuestart > colon)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("header='%.*s', value='%.*s'\n",
|
||||
colon-linestart, header_buf+linestart,
|
||||
i-valuestart, header_buf+valuestart);
|
||||
#endif
|
||||
if(0==strncasecmp(header_buf+linestart, "content-length", colon-linestart))
|
||||
{
|
||||
content_length = atoi(header_buf+valuestart);
|
||||
#ifdef DEBUG
|
||||
printf("Content-Length: %d\n", content_length);
|
||||
#endif
|
||||
}
|
||||
else if(0==strncasecmp(header_buf+linestart, "transfer-encoding", colon-linestart)
|
||||
&& 0==strncasecmp(header_buf+valuestart, "chunked", 7))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("chunked transfer-encoding!\n");
|
||||
#endif
|
||||
chunked = 1;
|
||||
}
|
||||
}
|
||||
while((i < (int)header_buf_used) && (header_buf[i]=='\r' || header_buf[i] == '\n'))
|
||||
i++;
|
||||
linestart = i;
|
||||
colon = linestart;
|
||||
valuestart = 0;
|
||||
}
|
||||
}
|
||||
/* copy the remaining of the received data back to buf */
|
||||
n = header_buf_used - endofheaders;
|
||||
memcpy(buf, header_buf + endofheaders, n);
|
||||
/* if(headers) */
|
||||
}
|
||||
if(endofheaders)
|
||||
{
|
||||
/* content */
|
||||
if(chunked)
|
||||
{
|
||||
int i = 0;
|
||||
while(i < n)
|
||||
{
|
||||
if(chunksize == 0)
|
||||
{
|
||||
/* reading chunk size */
|
||||
if(chunksize_buf_index == 0) {
|
||||
/* skipping any leading CR LF */
|
||||
if(i<n && buf[i] == '\r') i++;
|
||||
if(i<n && buf[i] == '\n') i++;
|
||||
}
|
||||
while(i<n && isxdigit(buf[i])
|
||||
&& chunksize_buf_index < (sizeof(chunksize_buf)-1))
|
||||
{
|
||||
chunksize_buf[chunksize_buf_index++] = buf[i];
|
||||
chunksize_buf[chunksize_buf_index] = '\0';
|
||||
i++;
|
||||
}
|
||||
while(i<n && buf[i] != '\r' && buf[i] != '\n')
|
||||
i++; /* discarding chunk-extension */
|
||||
if(i<n && buf[i] == '\r') i++;
|
||||
if(i<n && buf[i] == '\n') {
|
||||
unsigned int j;
|
||||
for(j = 0; j < chunksize_buf_index; j++) {
|
||||
if(chunksize_buf[j] >= '0'
|
||||
&& chunksize_buf[j] <= '9')
|
||||
chunksize = (chunksize << 4) + (chunksize_buf[j] - '0');
|
||||
else
|
||||
chunksize = (chunksize << 4) + ((chunksize_buf[j] | 32) - 'a' + 10);
|
||||
}
|
||||
chunksize_buf[0] = '\0';
|
||||
chunksize_buf_index = 0;
|
||||
i++;
|
||||
} else {
|
||||
/* not finished to get chunksize */
|
||||
continue;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("chunksize = %u (%x)\n", chunksize, chunksize);
|
||||
#endif
|
||||
if(chunksize == 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("end of HTTP content - %d %d\n", i, n);
|
||||
/*printf("'%.*s'\n", n-i, buf+i);*/
|
||||
#endif
|
||||
goto end_of_stream;
|
||||
}
|
||||
}
|
||||
bytestocopy = ((int)chunksize < (n - i))?chunksize:(unsigned int)(n - i);
|
||||
if((content_buf_used + bytestocopy) > content_buf_len)
|
||||
{
|
||||
char * tmp;
|
||||
if(content_length >= (int)(content_buf_used + bytestocopy)) {
|
||||
content_buf_len = content_length;
|
||||
} else {
|
||||
content_buf_len = content_buf_used + bytestocopy;
|
||||
}
|
||||
tmp = (char*)realloc(content_buf, content_buf_len);
|
||||
if(tmp == NULL) {
|
||||
/* memory allocation error */
|
||||
free(content_buf);
|
||||
free(header_buf);
|
||||
*size = -1;
|
||||
return NULL;
|
||||
}
|
||||
content_buf = tmp;
|
||||
}
|
||||
memcpy(content_buf + content_buf_used, buf + i, bytestocopy);
|
||||
content_buf_used += bytestocopy;
|
||||
i += bytestocopy;
|
||||
chunksize -= bytestocopy;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* not chunked */
|
||||
if(content_length > 0
|
||||
&& (int)(content_buf_used + n) > content_length) {
|
||||
/* skipping additional bytes */
|
||||
n = content_length - content_buf_used;
|
||||
}
|
||||
if(content_buf_used + n > content_buf_len)
|
||||
{
|
||||
char * tmp;
|
||||
if(content_length >= (int)(content_buf_used + n)) {
|
||||
content_buf_len = content_length;
|
||||
} else {
|
||||
content_buf_len = content_buf_used + n;
|
||||
}
|
||||
tmp = (char*)realloc(content_buf, content_buf_len);
|
||||
if(tmp == NULL) {
|
||||
/* memory allocation error */
|
||||
free(content_buf);
|
||||
free(header_buf);
|
||||
*size = -1;
|
||||
return NULL;
|
||||
}
|
||||
content_buf = tmp;
|
||||
}
|
||||
memcpy(content_buf + content_buf_used, buf, n);
|
||||
content_buf_used += n;
|
||||
}
|
||||
}
|
||||
/* use the Content-Length header value if available */
|
||||
if(content_length > 0 && (int)content_buf_used >= content_length)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("End of HTTP content\n");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
end_of_stream:
|
||||
free(header_buf); header_buf = NULL;
|
||||
*size = content_buf_used;
|
||||
if(content_buf_used == 0)
|
||||
{
|
||||
free(content_buf);
|
||||
content_buf = NULL;
|
||||
}
|
||||
return content_buf;
|
||||
}
|
||||
|
||||
/* miniwget3() :
|
||||
* do all the work.
|
||||
* Return NULL if something failed. */
|
||||
static void *
|
||||
miniwget3(const char * host,
|
||||
unsigned short port, const char * path,
|
||||
int * size, char * addr_str, int addr_str_len,
|
||||
const char * httpversion, unsigned int scope_id,
|
||||
int * status_code)
|
||||
{
|
||||
char buf[2048];
|
||||
int s;
|
||||
int n;
|
||||
int len;
|
||||
int sent;
|
||||
void * content;
|
||||
|
||||
*size = 0;
|
||||
s = connecthostport(host, port, scope_id);
|
||||
if(s < 0)
|
||||
return NULL;
|
||||
|
||||
/* get address for caller ! */
|
||||
if(addr_str)
|
||||
{
|
||||
struct sockaddr_storage saddr;
|
||||
socklen_t saddrlen;
|
||||
|
||||
saddrlen = sizeof(saddr);
|
||||
if(getsockname(s, (struct sockaddr *)&saddr, &saddrlen) < 0)
|
||||
{
|
||||
perror("getsockname");
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(__amigaos__) && !defined(__amigaos4__)
|
||||
/* using INT WINAPI WSAAddressToStringA(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD);
|
||||
* But his function make a string with the port : nn.nn.nn.nn:port */
|
||||
/* if(WSAAddressToStringA((SOCKADDR *)&saddr, sizeof(saddr),
|
||||
NULL, addr_str, (DWORD *)&addr_str_len))
|
||||
{
|
||||
printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError());
|
||||
}*/
|
||||
/* the following code is only compatible with ip v4 addresses */
|
||||
strncpy(addr_str, inet_ntoa(((struct sockaddr_in *)&saddr)->sin_addr), addr_str_len);
|
||||
#else
|
||||
#if 0
|
||||
if(saddr.sa_family == AF_INET6) {
|
||||
inet_ntop(AF_INET6,
|
||||
&(((struct sockaddr_in6 *)&saddr)->sin6_addr),
|
||||
addr_str, addr_str_len);
|
||||
} else {
|
||||
inet_ntop(AF_INET,
|
||||
&(((struct sockaddr_in *)&saddr)->sin_addr),
|
||||
addr_str, addr_str_len);
|
||||
}
|
||||
#endif
|
||||
/* getnameinfo return ip v6 address with the scope identifier
|
||||
* such as : 2a01:e35:8b2b:7330::%4281128194 */
|
||||
n = getnameinfo((const struct sockaddr *)&saddr, saddrlen,
|
||||
addr_str, addr_str_len,
|
||||
NULL, 0,
|
||||
NI_NUMERICHOST | NI_NUMERICSERV);
|
||||
if(n != 0) {
|
||||
#ifdef _WIN32
|
||||
fprintf(stderr, "getnameinfo() failed : %d\n", n);
|
||||
#else
|
||||
fprintf(stderr, "getnameinfo() failed : %s\n", gai_strerror(n));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("address miniwget : %s\n", addr_str);
|
||||
#endif
|
||||
}
|
||||
|
||||
len = snprintf(buf, sizeof(buf),
|
||||
"GET %s HTTP/%s\r\n"
|
||||
"Host: %s:%d\r\n"
|
||||
"Connection: Close\r\n"
|
||||
"User-Agent: " OS_STRING ", " UPNP_VERSION_STRING ", MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
|
||||
|
||||
"\r\n",
|
||||
path, httpversion, host, port);
|
||||
if ((unsigned int)len >= sizeof(buf))
|
||||
{
|
||||
closesocket(s);
|
||||
return NULL;
|
||||
}
|
||||
sent = 0;
|
||||
/* sending the HTTP request */
|
||||
while(sent < len)
|
||||
{
|
||||
n = (int)send(s, buf+sent, len-sent, 0);
|
||||
if(n < 0)
|
||||
{
|
||||
perror("send");
|
||||
closesocket(s);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
sent += n;
|
||||
}
|
||||
}
|
||||
content = getHTTPResponse(s, size, status_code);
|
||||
closesocket(s);
|
||||
return content;
|
||||
}
|
||||
|
||||
/* miniwget2() :
|
||||
* Call miniwget3(); retry with HTTP/1.1 if 1.0 fails. */
|
||||
static void *
|
||||
miniwget2(const char * host,
|
||||
unsigned short port, const char * path,
|
||||
int * size, char * addr_str, int addr_str_len,
|
||||
unsigned int scope_id, int * status_code)
|
||||
{
|
||||
char * respbuffer;
|
||||
|
||||
#if 1
|
||||
respbuffer = (char*)miniwget3(host, port, path, size,
|
||||
addr_str, addr_str_len, "1.1",
|
||||
scope_id, status_code);
|
||||
#else
|
||||
respbuffer = (char*)miniwget3(host, port, path, size,
|
||||
addr_str, addr_str_len, "1.0",
|
||||
scope_id, status_code);
|
||||
if (*size == 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Retrying with HTTP/1.1\n");
|
||||
#endif
|
||||
free(respbuffer);
|
||||
respbuffer = miniwget3(host, port, path, size,
|
||||
addr_str, addr_str_len, "1.1",
|
||||
scope_id, status_code);
|
||||
}
|
||||
#endif
|
||||
return respbuffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* parseURL()
|
||||
* arguments :
|
||||
* url : source string not modified
|
||||
* hostname : hostname destination string (size of MAXHOSTNAMELEN+1)
|
||||
* port : port (destination)
|
||||
* path : pointer to the path part of the URL
|
||||
*
|
||||
* Return values :
|
||||
* 0 - Failure
|
||||
* 1 - Success */
|
||||
int
|
||||
parseURL(const char * url,
|
||||
char * hostname, unsigned short * port,
|
||||
char * * path, unsigned int * scope_id)
|
||||
{
|
||||
char * p1, *p2, *p3;
|
||||
if(!url)
|
||||
return 0;
|
||||
p1 = (char*)strstr(url, "://");
|
||||
if(!p1)
|
||||
return 0;
|
||||
p1 += 3;
|
||||
if( (url[0]!='h') || (url[1]!='t')
|
||||
||(url[2]!='t') || (url[3]!='p'))
|
||||
return 0;
|
||||
memset(hostname, 0, MAXHOSTNAMELEN + 1);
|
||||
if(*p1 == '[')
|
||||
{
|
||||
/* IP v6 : http://[2a00:1450:8002::6a]/path/abc */
|
||||
char * scope;
|
||||
scope = strchr(p1, '%');
|
||||
p2 = strchr(p1, ']');
|
||||
if(p2 && scope && scope < p2 && scope_id) {
|
||||
/* parse scope */
|
||||
#ifdef IF_NAMESIZE
|
||||
char tmp[IF_NAMESIZE];
|
||||
int l;
|
||||
scope++;
|
||||
/* "%25" is just '%' in URL encoding */
|
||||
if(scope[0] == '2' && scope[1] == '5')
|
||||
scope += 2; /* skip "25" */
|
||||
l = (int)(p2 - scope);
|
||||
if(l >= IF_NAMESIZE)
|
||||
l = IF_NAMESIZE - 1;
|
||||
memcpy(tmp, scope, l);
|
||||
tmp[l] = '\0';
|
||||
*scope_id = if_nametoindex(tmp);
|
||||
if(*scope_id == 0) {
|
||||
*scope_id = (unsigned int)strtoul(tmp, NULL, 10);
|
||||
}
|
||||
#else
|
||||
/* under windows, scope is numerical */
|
||||
char tmp[8];
|
||||
int l;
|
||||
scope++;
|
||||
/* "%25" is just '%' in URL encoding */
|
||||
if(scope[0] == '2' && scope[1] == '5')
|
||||
scope += 2; /* skip "25" */
|
||||
l = p2 - scope;
|
||||
if(l >= sizeof(tmp))
|
||||
l = sizeof(tmp) - 1;
|
||||
memcpy(tmp, scope, l);
|
||||
tmp[l] = '\0';
|
||||
*scope_id = (unsigned int)strtoul(tmp, NULL, 10);
|
||||
#endif
|
||||
}
|
||||
p3 = strchr(p1, '/');
|
||||
if(p2 && p3)
|
||||
{
|
||||
p2++;
|
||||
strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1)));
|
||||
if(*p2 == ':')
|
||||
{
|
||||
*port = 0;
|
||||
p2++;
|
||||
while( (*p2 >= '0') && (*p2 <= '9'))
|
||||
{
|
||||
*port *= 10;
|
||||
*port += (unsigned short)(*p2 - '0');
|
||||
p2++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*port = 80;
|
||||
}
|
||||
*path = p3;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
p2 = strchr(p1, ':');
|
||||
p3 = strchr(p1, '/');
|
||||
if(!p3)
|
||||
return 0;
|
||||
if(!p2 || (p2>p3))
|
||||
{
|
||||
strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p3-p1)));
|
||||
*port = 80;
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1)));
|
||||
*port = 0;
|
||||
p2++;
|
||||
while( (*p2 >= '0') && (*p2 <= '9'))
|
||||
{
|
||||
*port *= 10;
|
||||
*port += (unsigned short)(*p2 - '0');
|
||||
p2++;
|
||||
}
|
||||
}
|
||||
*path = p3;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *
|
||||
miniwget(const char * url, int * size,
|
||||
unsigned int scope_id, int * status_code)
|
||||
{
|
||||
unsigned short port;
|
||||
char * path;
|
||||
/* protocol://host:port/chemin */
|
||||
char hostname[MAXHOSTNAMELEN+1];
|
||||
*size = 0;
|
||||
if(!parseURL(url, hostname, &port, &path, &scope_id))
|
||||
return NULL;
|
||||
#ifdef DEBUG
|
||||
printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n",
|
||||
hostname, port, path, scope_id);
|
||||
#endif
|
||||
return miniwget2(hostname, port, path, size, 0, 0, scope_id, status_code);
|
||||
}
|
||||
|
||||
void *
|
||||
miniwget_getaddr(const char * url, int * size,
|
||||
char * addr, int addrlen, unsigned int scope_id,
|
||||
int * status_code)
|
||||
{
|
||||
unsigned short port;
|
||||
char * path;
|
||||
/* protocol://host:port/path */
|
||||
char hostname[MAXHOSTNAMELEN+1];
|
||||
*size = 0;
|
||||
if(addr)
|
||||
addr[0] = '\0';
|
||||
if(!parseURL(url, hostname, &port, &path, &scope_id))
|
||||
return NULL;
|
||||
#ifdef DEBUG
|
||||
printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n",
|
||||
hostname, port, path, scope_id);
|
||||
#endif
|
||||
return miniwget2(hostname, port, path, size, addr, addrlen, scope_id, status_code);
|
||||
}
|
||||
|
||||
Vendored
-30
@@ -1,30 +0,0 @@
|
||||
/* $Id: miniwget.h,v 1.12 2016/01/24 17:24:36 nanard Exp $ */
|
||||
/* Project : miniupnp
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005-2016 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution.
|
||||
* */
|
||||
#ifndef MINIWGET_H_INCLUDED
|
||||
#define MINIWGET_H_INCLUDED
|
||||
|
||||
#include "miniupnpc_declspec.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
MINIUPNP_LIBSPEC void * getHTTPResponse(int s, int * size, int * status_code);
|
||||
|
||||
MINIUPNP_LIBSPEC void * miniwget(const char *, int *, unsigned int, int *);
|
||||
|
||||
MINIUPNP_LIBSPEC void * miniwget_getaddr(const char *, int *, char *, int, unsigned int, int *);
|
||||
|
||||
int parseURL(const char *, char *, unsigned short *, char * *, unsigned int *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Vendored
-229
@@ -1,229 +0,0 @@
|
||||
/* $Id: minixml.c,v 1.10 2012/03/05 19:42:47 nanard Exp $ */
|
||||
/* minixml.c : the minimum size a xml parser can be ! */
|
||||
/* Project : miniupnp
|
||||
* webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* Author : Thomas Bernard
|
||||
|
||||
Copyright (c) 2005-2014, Thomas BERNARD
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "minixml.h"
|
||||
|
||||
/* parseatt : used to parse the argument list
|
||||
* return 0 (false) in case of success and -1 (true) if the end
|
||||
* of the xmlbuffer is reached. */
|
||||
static int parseatt(struct xmlparser * p)
|
||||
{
|
||||
const char * attname;
|
||||
int attnamelen;
|
||||
const char * attvalue;
|
||||
int attvaluelen;
|
||||
while(p->xml < p->xmlend)
|
||||
{
|
||||
if(*p->xml=='/' || *p->xml=='>')
|
||||
return 0;
|
||||
if( !IS_WHITE_SPACE(*p->xml) )
|
||||
{
|
||||
char sep;
|
||||
attname = p->xml;
|
||||
attnamelen = 0;
|
||||
while(*p->xml!='=' && !IS_WHITE_SPACE(*p->xml) )
|
||||
{
|
||||
attnamelen++; p->xml++;
|
||||
if(p->xml >= p->xmlend)
|
||||
return -1;
|
||||
}
|
||||
while(*(p->xml++) != '=')
|
||||
{
|
||||
if(p->xml >= p->xmlend)
|
||||
return -1;
|
||||
}
|
||||
while(IS_WHITE_SPACE(*p->xml))
|
||||
{
|
||||
p->xml++;
|
||||
if(p->xml >= p->xmlend)
|
||||
return -1;
|
||||
}
|
||||
sep = *p->xml;
|
||||
if(sep=='\'' || sep=='\"')
|
||||
{
|
||||
p->xml++;
|
||||
if(p->xml >= p->xmlend)
|
||||
return -1;
|
||||
attvalue = p->xml;
|
||||
attvaluelen = 0;
|
||||
while(*p->xml != sep)
|
||||
{
|
||||
attvaluelen++; p->xml++;
|
||||
if(p->xml >= p->xmlend)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
attvalue = p->xml;
|
||||
attvaluelen = 0;
|
||||
while( !IS_WHITE_SPACE(*p->xml)
|
||||
&& *p->xml != '>' && *p->xml != '/')
|
||||
{
|
||||
attvaluelen++; p->xml++;
|
||||
if(p->xml >= p->xmlend)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/*printf("%.*s='%.*s'\n",
|
||||
attnamelen, attname, attvaluelen, attvalue);*/
|
||||
if(p->attfunc)
|
||||
p->attfunc(p->data, attname, attnamelen, attvalue, attvaluelen);
|
||||
}
|
||||
p->xml++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* parseelt parse the xml stream and
|
||||
* call the callback functions when needed... */
|
||||
static void parseelt(struct xmlparser * p)
|
||||
{
|
||||
int i;
|
||||
const char * elementname;
|
||||
while(p->xml < (p->xmlend - 1))
|
||||
{
|
||||
if((p->xml + 4) <= p->xmlend && (0 == memcmp(p->xml, "<!--", 4)))
|
||||
{
|
||||
p->xml += 3;
|
||||
/* ignore comments */
|
||||
do
|
||||
{
|
||||
p->xml++;
|
||||
if ((p->xml + 3) >= p->xmlend)
|
||||
return;
|
||||
}
|
||||
while(memcmp(p->xml, "-->", 3) != 0);
|
||||
p->xml += 3;
|
||||
}
|
||||
else if((p->xml)[0]=='<' && (p->xml)[1]!='?')
|
||||
{
|
||||
i = 0; elementname = ++p->xml;
|
||||
while( !IS_WHITE_SPACE(*p->xml)
|
||||
&& (*p->xml!='>') && (*p->xml!='/')
|
||||
)
|
||||
{
|
||||
i++; p->xml++;
|
||||
if (p->xml >= p->xmlend)
|
||||
return;
|
||||
/* to ignore namespace : */
|
||||
if(*p->xml==':')
|
||||
{
|
||||
i = 0;
|
||||
elementname = ++p->xml;
|
||||
}
|
||||
}
|
||||
if(i>0)
|
||||
{
|
||||
if(p->starteltfunc)
|
||||
p->starteltfunc(p->data, elementname, i);
|
||||
if(parseatt(p))
|
||||
return;
|
||||
if(*p->xml!='/')
|
||||
{
|
||||
const char * data;
|
||||
i = 0; data = ++p->xml;
|
||||
if (p->xml >= p->xmlend)
|
||||
return;
|
||||
while( IS_WHITE_SPACE(*p->xml) )
|
||||
{
|
||||
i++; p->xml++;
|
||||
if (p->xml >= p->xmlend)
|
||||
return;
|
||||
}
|
||||
if(memcmp(p->xml, "<![CDATA[", 9) == 0)
|
||||
{
|
||||
/* CDATA handling */
|
||||
p->xml += 9;
|
||||
data = p->xml;
|
||||
i = 0;
|
||||
while(memcmp(p->xml, "]]>", 3) != 0)
|
||||
{
|
||||
i++; p->xml++;
|
||||
if ((p->xml + 3) >= p->xmlend)
|
||||
return;
|
||||
}
|
||||
if(i>0 && p->datafunc)
|
||||
p->datafunc(p->data, data, i);
|
||||
while(*p->xml!='<')
|
||||
{
|
||||
p->xml++;
|
||||
if (p->xml >= p->xmlend)
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while(*p->xml!='<')
|
||||
{
|
||||
i++; p->xml++;
|
||||
if ((p->xml + 1) >= p->xmlend)
|
||||
return;
|
||||
}
|
||||
if(i>0 && p->datafunc && *(p->xml + 1) == '/')
|
||||
p->datafunc(p->data, data, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(*p->xml == '/')
|
||||
{
|
||||
i = 0; elementname = ++p->xml;
|
||||
if (p->xml >= p->xmlend)
|
||||
return;
|
||||
while((*p->xml != '>'))
|
||||
{
|
||||
i++; p->xml++;
|
||||
if (p->xml >= p->xmlend)
|
||||
return;
|
||||
}
|
||||
if(p->endeltfunc)
|
||||
p->endeltfunc(p->data, elementname, i);
|
||||
p->xml++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p->xml++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* the parser must be initialized before calling this function */
|
||||
void parsexml(struct xmlparser * parser)
|
||||
{
|
||||
parser->xml = parser->xmlstart;
|
||||
parser->xmlend = parser->xmlstart + parser->xmlsize;
|
||||
parseelt(parser);
|
||||
}
|
||||
|
||||
|
||||
Loaded 100 of 723 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user