Compare commits
750 commits
0.1.0-andr
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
37b70c3f4d | ||
|
f02147d9a0 | ||
|
06b3933102 | ||
|
c087f17054 | ||
|
efc483290a | ||
|
14df62ab11 | ||
|
1e776e7d3a | ||
|
8b5406d941 | ||
|
c7160c9ea8 | ||
|
20f541d469 | ||
|
f5d729c8a1 | ||
|
2335cf0064 | ||
|
f4602687eb | ||
|
f4b5df3640 | ||
|
37aa3f36aa | ||
|
896f43dc1e | ||
|
adb7a4dff6 | ||
|
7b588f0222 | ||
|
d96f7054e3 | ||
|
5d68ea9f89 | ||
|
13e09e8679 | ||
|
2f73066d12 | ||
|
5f517e6992 | ||
|
2f1159c14f | ||
|
50ea506c53 | ||
|
8fce1cddbc | ||
|
a925c4e7e8 | ||
|
eb7bdf4313 | ||
|
36e21810df | ||
|
70611a8957 | ||
|
8d1da15cfd | ||
|
50cd0e54f5 | ||
|
6973573721 | ||
|
71452113ac | ||
|
a82a536e09 | ||
|
60cfc47a21 | ||
|
9a0fa2d0ad | ||
|
7376875151 | ||
|
deea09407b | ||
|
3ebb02be1d | ||
|
11d5212f47 | ||
|
080bb43429 | ||
|
2fc564b498 | ||
|
2214179e0e | ||
|
d9ad87323f | ||
|
8195097363 | ||
|
1c0c68ce48 | ||
|
9f8e386370 | ||
|
3ef2f652c3 | ||
|
fc1bfdcc68 | ||
|
f03401915d | ||
|
d8605f4027 | ||
|
bf8a80150d | ||
|
f7e76e09a2 | ||
|
acc365451c | ||
|
247fbf2936 | ||
|
8004e4ace3 | ||
|
4e539b73f2 | ||
|
2df21c8e8d | ||
|
ec21a22e30 | ||
|
aebf4c2d59 | ||
|
97d85aa841 | ||
|
2ef34fe6f8 | ||
|
5a1bacdba6 | ||
|
548d8cdd77 | ||
|
4d43c9c828 | ||
|
dce696282b | ||
|
44d5893a7a | ||
|
c19d0738fa | ||
|
5434e6dbf5 | ||
|
60a6c97834 | ||
|
c33d387031 | ||
|
b572fdfd47 | ||
|
94b9f930ce | ||
|
01ec93dd27 | ||
|
ca5361cc58 | ||
|
08f086bfc4 | ||
|
1f288e2a39 | ||
|
0e0cd66564 | ||
|
9c95b20f5c | ||
|
7630a9b60e | ||
|
ae909878c4 | ||
|
7785513e8b | ||
|
7f33f7b6c8 | ||
|
6c9b4d9a54 | ||
|
af9947b931 | ||
|
b275816e76 | ||
|
8e3ccea8a1 | ||
|
76ec4771b3 | ||
|
3b77cdf0c5 | ||
|
397cd8f584 | ||
|
21c255efb4 | ||
|
e1fb118910 | ||
|
c56bd2e8ae | ||
|
e09fbf5c63 | ||
|
c4cffd54a8 | ||
|
99f13a746e | ||
|
690c97e44d | ||
|
311ca8b12f | ||
|
152e31966a | ||
|
b4ede5bcad | ||
|
a5f49c07e4 | ||
|
fc66b84d8f | ||
|
87cc7f12e3 | ||
|
e9cf548cc2 | ||
|
3af1d61e5b | ||
|
3b14adf949 | ||
|
46710dd31a | ||
|
10e4d3efff | ||
|
2b1411787b | ||
|
0e33bcaaf9 | ||
|
45443dfa23 | ||
|
06ae269b7b | ||
|
12a305becb | ||
|
bd203cfddb | ||
|
c2ad3dd643 | ||
|
3468bcf5fd | ||
|
21221d80e7 | ||
|
a45c630116 | ||
|
73295a6351 | ||
|
ab87862646 | ||
|
5f24ee52b0 | ||
|
02e1763e1d | ||
|
44c6af2146 | ||
|
d1d008edda | ||
|
4d7dfd0266 | ||
|
b70f0007b1 | ||
|
f7148edd96 | ||
|
425a26b3a0 | ||
|
f6caffd624 | ||
|
b294f65656 | ||
|
a5ed1a370e | ||
|
f07228895c | ||
|
b3007c10e3 | ||
|
7caff84e04 | ||
|
dcdb4e9d39 | ||
|
596c7b8aff | ||
|
ed2c5f510a | ||
|
0ba5aad8af | ||
|
50ff888141 | ||
|
72e74e2113 | ||
|
47a43467d0 | ||
|
19e0da519f | ||
|
721a0c907a | ||
|
2a3341e3c5 | ||
|
63f903104a | ||
|
277f5d957b | ||
|
9409bb35fe | ||
|
9e09d56b76 | ||
|
40767c021b | ||
|
0e164a44df | ||
|
38338ae551 | ||
|
dbb72ff6c1 | ||
|
0a45332f3f | ||
|
aa27680baf | ||
|
67fb32499f | ||
|
5821f06928 | ||
|
5f93658f0f | ||
|
cd671cce48 | ||
|
2a162d948f | ||
|
72a2ada0b2 | ||
|
0ccbbefbed | ||
|
bc91d9f366 | ||
|
beb290dafb | ||
|
5f7bae8f4f | ||
|
11eafb8d03 | ||
|
f99b452073 | ||
|
51834be404 | ||
|
b2fb548584 | ||
|
1633eef3dd | ||
|
e57c9cdb27 | ||
|
07b1550cf4 | ||
|
a15fd4d190 | ||
|
b8af9aed25 | ||
|
8992889e94 | ||
|
f91e793062 | ||
|
3fbe94ecd1 | ||
|
5bd0dcd564 | ||
|
41b840d13f | ||
|
95e09ded99 | ||
|
6bccf59f5b | ||
|
890c0596ed | ||
|
b22ca8b35e | ||
|
e77241cd56 | ||
|
3dbe56690a | ||
|
1810bf6d5b | ||
|
d6715bccea | ||
|
30c85c2f8b | ||
|
979909faa8 | ||
|
90df8faa7a | ||
|
6d3c127912 | ||
|
515a0a7fe7 | ||
|
7fe96780de | ||
|
f1e5d11b2a | ||
|
3739e9f170 | ||
|
3c79582fed | ||
|
a187942cff | ||
|
4ae085f7e2 | ||
|
153b1b4962 | ||
|
2774eae66f | ||
|
4928ce4682 | ||
|
64290ae5a3 | ||
|
1457aa3caa | ||
|
ee58c1c8af | ||
|
a5bb130e73 | ||
|
bbd20a003b | ||
|
ef1c2a5930 | ||
|
074af609bc | ||
|
efa8a47b8d | ||
|
bc3616d073 | ||
|
510442490e | ||
|
0a7fd4dc47 | ||
|
4fa7069e82 | ||
|
212d7b915b | ||
|
cb95db1e89 | ||
|
334e64f499 | ||
|
90e58649a7 | ||
|
e845c87738 | ||
|
2cb36de715 | ||
|
c2a8bf52e9 | ||
|
e975a75ec4 | ||
|
5854735392 | ||
|
356f4230b5 | ||
|
4be3dd518b | ||
|
5ed2d40e23 | ||
|
a246d1a2f9 | ||
|
e567dd6296 | ||
|
066389a29f | ||
|
67979a03ea | ||
|
f91513edd2 | ||
|
5d92cafe67 | ||
|
d87bbf2b46 | ||
|
2860938b9a | ||
|
e74b586dd1 | ||
|
0fca898c54 | ||
|
df467e8764 | ||
|
17e1156850 | ||
|
9fd04ed47a | ||
|
c9e6dd7181 | ||
|
0330cf3b2b | ||
|
2be1c422d6 | ||
|
0f79474aae | ||
|
713e704b9b | ||
|
d42632f973 | ||
|
57b2be5211 | ||
|
3a756e0ac4 | ||
|
6607d2fc15 | ||
|
8ebe210105 | ||
|
f0949f49cf | ||
|
2b9a0198cb | ||
|
8684dd8448 | ||
|
72c268647f | ||
|
e9d2099f42 | ||
|
f7d635a3d7 | ||
|
029d6d52e4 | ||
|
dec913dd65 | ||
|
028c60157d | ||
|
3d86995feb | ||
|
670e6891c1 | ||
|
a25dc297ef | ||
|
4ed7ba66b8 | ||
|
b1b3b131e2 | ||
|
f1b3c680c9 | ||
|
ca1fa7b7c0 | ||
|
3cc9d75681 | ||
|
92bc887663 | ||
|
59da01b7b9 | ||
|
e07207b40c | ||
|
1688f4bcbc | ||
|
8c70e1a13d | ||
|
b1d578c0b4 | ||
|
290068dd37 | ||
|
7b359ae4c1 | ||
|
56631201c8 | ||
|
81755d4ad9 | ||
|
f1542246c6 | ||
|
b29c375a7a | ||
|
bfd9c8c343 | ||
|
1883045f75 | ||
|
4cfbcc50ac | ||
|
f74ec19cb5 | ||
|
c68fedaa50 | ||
|
8a4201f381 | ||
|
ffaf12cca8 | ||
|
03e9c9db0c | ||
|
c9ba05c948 | ||
|
914555eac0 | ||
|
fee63f2600 | ||
|
2a792db797 | ||
|
a598f31716 | ||
|
ef040a393c | ||
|
4a6b2c4400 | ||
|
398f610c09 | ||
|
fb4ac0dae8 | ||
|
0415f917f8 | ||
|
6f95e6109c | ||
|
cdd3a37754 | ||
|
f00f35ca2c | ||
|
eee0f9eff9 | ||
|
84d9dbf877 | ||
|
9932b1209f | ||
|
6d8e58090a | ||
|
93e567981e | ||
|
7693a4ff20 | ||
|
86f89e7522 | ||
|
3297b151ad | ||
|
aaecafcb72 | ||
|
444539405a | ||
|
2177382b5a | ||
|
a1d0f2dc63 | ||
|
75b077c772 | ||
|
d8636bc693 | ||
|
9d7c63571d | ||
|
3faf99b535 | ||
|
1440a91fba | ||
|
6d08eb716e | ||
|
69fdc7d3d2 | ||
|
18a7670248 | ||
|
d7face2544 | ||
|
987c857b1c | ||
|
3f8c66db0f | ||
|
dc2476c9dd | ||
|
8a2e9fa569 | ||
|
588b0d53dd | ||
|
7c07986b5d | ||
|
02a9cac305 | ||
|
af39130fed | ||
|
2d2e712eab | ||
|
acad65d233 | ||
|
24762a1c45 | ||
|
75f5e9f364 | ||
|
7e793e09a8 | ||
|
7dcf30f854 | ||
|
5fdd9676cb | ||
|
f672ff6f24 | ||
|
e4ec69b6dc | ||
|
934df79f85 | ||
|
c97ed04fea | ||
|
daea35381b | ||
|
28a3f160c3 | ||
|
b94b20bf76 | ||
|
b626472f10 | ||
|
0c97d554ae | ||
|
9b572190de | ||
|
90900f01e1 | ||
|
adfc768a8f | ||
|
11f335acc4 | ||
|
ca1d7a8642 | ||
|
339f822a80 | ||
|
68318e3a69 | ||
|
2d9840c901 | ||
|
858abae42d | ||
|
730d1cb5d8 | ||
|
7c8f2ac60a | ||
|
2bce0136ff | ||
|
8b31d0a9ab | ||
|
299ef053f4 | ||
|
77fdd19ec2 | ||
|
55e80b4c69 | ||
|
b0958749f6 | ||
|
a0df539b7b | ||
|
fb17edea7a | ||
|
11454183a1 | ||
|
0dbee1e854 | ||
|
890c297437 | ||
|
e27d555bc6 | ||
|
51d384aee8 | ||
|
06709ae031 | ||
|
ecdc84fba7 | ||
|
8fbab06192 | ||
|
bd00c8a372 | ||
|
d69e158b41 | ||
|
91f6f19914 | ||
|
fb253b7573 | ||
|
04fecdeee0 | ||
|
2e1188d854 | ||
|
cd8a23391a | ||
|
703413dcb6 | ||
|
f60440f877 | ||
|
42edfd7fd6 | ||
|
6408ffcf21 | ||
|
01d88c2d33 | ||
|
675e321d8f | ||
|
99d7ef67e0 | ||
|
9dba30d360 | ||
|
1e7da276ab | ||
|
7e3fef8d41 | ||
|
1795d71b37 | ||
|
500f53bebb | ||
|
ad2beacf40 | ||
|
c0efcbef71 | ||
|
2dadbdb905 | ||
|
8fd0a814e9 | ||
|
38ea01d605 | ||
|
5795015059 | ||
|
df2663d9fb | ||
|
2415d74a46 | ||
|
f50760d9c6 | ||
|
ef99809c95 | ||
|
b2ae281483 | ||
|
42f35b673d | ||
|
b079488c27 | ||
|
06b4aeead9 | ||
|
4b0b667ed5 | ||
|
d2a671e04c | ||
|
62efbf0cc3 | ||
|
465825797e | ||
|
e1f1dd4554 | ||
|
cb7b2bd402 | ||
|
067bcc5c8b | ||
|
05b9d9ebe0 | ||
|
bc56271174 | ||
|
d45e611466 | ||
|
0db6b60251 | ||
|
657be6159e | ||
|
4b5d70ea3f | ||
|
bba0313824 | ||
|
15010e54c2 | ||
|
0387a450ce | ||
|
71b39cdadc | ||
|
4055fef911 | ||
|
7a580fdf44 | ||
|
4cdadfc505 | ||
|
b6712409ab | ||
|
7f35dbf19e | ||
|
b673d5a33d | ||
|
657b73aefc | ||
|
0c33795356 | ||
|
6b7b6b7032 | ||
|
a6272476ba | ||
|
3867dd58c4 | ||
|
390cc45153 | ||
|
c5e73fac91 | ||
|
765d520d70 | ||
|
fc2f26db91 | ||
|
efd1729ce5 | ||
|
74a5cddeaf | ||
|
464ea6f194 | ||
|
e216110864 | ||
|
d61602b7bb | ||
|
287e06e24b | ||
|
b29fe87e76 | ||
|
ccd4030dc1 | ||
|
9b3e2837b7 | ||
|
7db42e86e6 | ||
|
f26f019584 | ||
|
befac5db85 | ||
|
49d14b58a3 | ||
|
39171cc9a9 | ||
|
19dad43d7a | ||
|
1c2eaae4d1 | ||
|
a2ebaaaab6 | ||
|
5909fedf33 | ||
|
5ee580cb35 | ||
|
1070e67af4 | ||
|
8a94c841c6 | ||
|
5cf63660ef | ||
|
41bf965937 | ||
|
5ed2883954 | ||
|
d49c261a17 | ||
|
0d20b1a209 | ||
|
44f478be75 | ||
|
b771005816 | ||
|
c43d822c44 | ||
|
6a8d0bfd22 | ||
|
e6632a845d | ||
|
38efa5ded9 | ||
|
d7a25f2681 | ||
|
dfcf2e2f3f | ||
|
1fe00d25c6 | ||
|
37cb574907 | ||
|
3cd95b4427 | ||
|
680294def8 | ||
|
99c4798bed | ||
|
e109db81e6 | ||
|
c82c65c39f | ||
|
c4f1c60e35 | ||
|
b457f5dd6f | ||
|
8cd22b932b | ||
|
2e3245c654 | ||
|
fe3e60ecbf | ||
|
8e2088adb4 | ||
|
c127ee4bd4 | ||
|
3374f13c2b | ||
|
e09ea37bda | ||
|
338dbe4bc8 | ||
|
7bc8e18310 | ||
|
c722582ff2 | ||
|
0369b37d10 | ||
|
e53d4c7f43 | ||
|
79d28822e8 | ||
|
693155ca6a | ||
|
2223358991 | ||
|
a359a756d0 | ||
|
32526f92f8 | ||
|
bd0762f812 | ||
|
88fdb7b0ce | ||
|
ff79957145 | ||
|
807cc305b9 | ||
|
d3d77b58e3 | ||
|
ff5cf7359b | ||
|
9f530ce6a5 | ||
|
5725948f85 | ||
|
db50f67876 | ||
|
a02284c439 | ||
|
6e7191e5d3 | ||
|
654cbfb814 | ||
|
b99cb8a34d | ||
|
7448ce0e59 | ||
|
fba36467ea | ||
|
b7f226b322 | ||
|
698d694c43 | ||
|
3b307c7c9d | ||
|
95fd91b8a0 | ||
|
6302258817 | ||
|
d32cd87532 | ||
|
7b5d4c367c | ||
|
e1b33aa0e9 | ||
|
12d7758ea7 | ||
|
a098095c13 | ||
|
59b2e9954a | ||
|
bb07919505 | ||
|
4c20234d5e | ||
|
0e06113738 | ||
|
3054d07213 | ||
|
1c7e4c9f65 | ||
|
b880fee8e7 | ||
|
dba6789b0a | ||
|
dcd33d943e | ||
|
4325dcad86 | ||
|
d6df4640ab | ||
|
bc3906e39d | ||
|
203bacb1a0 | ||
|
eadeedae6b | ||
|
af1f9f5d89 | ||
|
ce6de7c0a0 | ||
|
6226df68ca | ||
|
fb5a72c565 | ||
|
c9f11d6c9f | ||
|
b181f9293f | ||
|
c63c520553 | ||
|
53fdb890b1 | ||
|
dd8f2dcf67 | ||
|
924f23154b | ||
|
f676b73c0e | ||
|
46045c2a7e | ||
|
c8115df285 | ||
|
529a1c122d | ||
|
df297819fe | ||
|
3d1ebf76a3 | ||
|
824ba2c287 | ||
|
8786787249 | ||
|
ef1d2a320e | ||
|
4f00d439f3 | ||
|
1b702d1a5a | ||
|
58406aae71 | ||
|
1ae5ecdbbf | ||
|
87792972d0 | ||
|
87bab5fca9 | ||
|
27003f4e64 | ||
|
2fed0928d8 | ||
|
375c72cfbd | ||
|
cd049fd378 | ||
|
fa0695b546 | ||
|
e57bf29703 | ||
|
85b1b71a0f | ||
|
6cef63bd0e | ||
|
b492be2203 | ||
|
39267048c7 | ||
|
d5743ac972 | ||
|
1f8690263b | ||
|
10b7b5536d | ||
|
89771844cc | ||
|
0804fe86ce | ||
|
e27cde67c7 | ||
|
be91851952 | ||
|
c4d80eecb3 | ||
|
4c8ec46864 | ||
|
87ddcc1324 | ||
|
e7b666b4cc | ||
|
6339a612b5 | ||
|
cb52935d9f | ||
|
25a098145d | ||
|
af6e36ef3b | ||
|
7d92b55b58 | ||
|
124b2e2c82 | ||
|
d572aebe32 | ||
|
0cad0b0762 | ||
|
27b439f2cb | ||
|
3e6adbe3c1 | ||
|
7ac4346012 | ||
|
75a1b3f9f4 | ||
|
4a91448067 | ||
|
d484e8a183 | ||
|
4d6768c015 | ||
|
b80f57ae49 | ||
|
4f3312d9ca | ||
|
a10a5f138c | ||
|
94514d3b68 | ||
|
d15fd43c84 | ||
|
77fc4ca5b9 | ||
|
3d912f6fbb | ||
|
c8dc2d3443 | ||
|
d09e0f8a91 | ||
|
cdfa550110 | ||
|
ef84379b62 | ||
|
e2afafdfa3 | ||
|
ebe3c2f2af | ||
|
b7680019ee | ||
|
575dcc7a6d | ||
|
3b1a5f149e | ||
|
ac58602ed0 | ||
|
4134d4754e | ||
|
5a6f7dec59 | ||
|
00309a73f0 | ||
|
9b4fd7d1a0 | ||
|
75e05c5ca5 | ||
|
eaaa11d4f6 | ||
|
1b424f0b80 | ||
|
23f0feaae0 | ||
|
f3a87259a1 | ||
|
bdc4e7d209 | ||
|
8b5d56fe27 | ||
|
df1fbbf0d1 | ||
|
66106c7e82 | ||
|
164b2bf295 | ||
|
d147242199 | ||
|
4854d9e758 | ||
|
68cf299e96 | ||
|
01e35a09eb | ||
|
3f9ad235ce | ||
|
cd959f8f7c | ||
|
481f61a705 | ||
|
e018b53b04 | ||
|
2cb9335453 | ||
|
e80673ecb5 | ||
|
55afe1292f | ||
|
8a94f7f9d1 | ||
|
a601d6c044 | ||
|
c815c91541 | ||
|
6d9ed16668 | ||
|
a203af7e7b | ||
|
a226447a92 | ||
|
e1a05cb3fb | ||
|
7f65136f3d | ||
|
329cd9d646 | ||
|
5637bb6052 | ||
|
f44e3c298a | ||
|
79c54b09c3 | ||
|
a52d095e45 | ||
|
4f65d42881 | ||
|
e2c6ee8caf | ||
|
39ab0d8bcc | ||
|
639c296bcc | ||
|
d427651de3 | ||
|
cfbb2c3286 | ||
|
a085037fc6 | ||
|
e53944bcb5 | ||
|
3806531e34 | ||
|
47b42bcf1e | ||
|
79a6c93060 | ||
|
eeb290a6f3 | ||
|
fcf7b292b1 | ||
|
d1ca07c297 | ||
|
2b873a92a2 | ||
|
0e5d85ff05 | ||
|
5ce0e1d67d | ||
|
ba582882cc | ||
|
584df5518b | ||
|
6f3beb6e28 | ||
|
0d47a0f401 | ||
|
215ec9ed6c | ||
|
c1bd334844 | ||
|
937d12c87b | ||
|
752ecac3ee | ||
|
3fe8e132e5 | ||
|
d68a248292 | ||
|
aa625789ce | ||
|
b8b0d34406 | ||
|
b779af2c1f | ||
|
6aa10ed946 | ||
|
80a2fc024c | ||
|
4904c165ed | ||
|
d23ad6984e | ||
|
1360794264 | ||
|
aed30141b4 | ||
|
8f4aff55b2 | ||
|
ea38f54c74 | ||
|
7844a4d26f | ||
|
ecabff27a8 | ||
|
ad6a330ae0 | ||
|
d83f58fe1b | ||
|
4f34e33b57 | ||
|
0db2e02181 | ||
|
490f02f2fe | ||
|
d6316aa718 | ||
|
4d08158427 | ||
|
27b5d85da7 | ||
|
8d906536c1 | ||
|
65be03261c | ||
|
13bbf897dd | ||
|
f6426750fd | ||
|
753e7304a3 | ||
|
f0780479c2 | ||
|
6750cd7ad4 | ||
|
a0f0c7c909 | ||
|
f4c11ba326 | ||
|
0b6f9191c2 | ||
|
e7792002cb | ||
|
71577e08b7 | ||
|
edeff2b95b | ||
|
9a0009101f | ||
|
662dc2adbf | ||
|
a08ea7a86b | ||
|
8271920178 | ||
|
347cb25d8b | ||
|
9820f4b4f1 | ||
|
5efd3f3c92 | ||
|
334d1530c0 | ||
|
aa269377ab | ||
|
6a12a9082f | ||
|
af7d7ae744 | ||
|
6c74b5517c | ||
|
f5751f6651 | ||
|
8973da2840 | ||
|
fe9fb06b5a | ||
|
d1d188ac77 | ||
|
4043830e56 | ||
|
c4b32f28ae | ||
|
f6c9a03126 | ||
|
a0c8cfa26d | ||
|
b49cc83a5b | ||
|
539af32722 | ||
|
493ff3a0fb | ||
|
8a64cfc180 | ||
|
36fd5f8879 | ||
|
268ecb62bd | ||
|
211108674f | ||
|
b34422ac7f | ||
|
12b2556b40 | ||
|
361baeb20d | ||
|
ac29d35950 | ||
|
9d552eaa1a | ||
|
f87b791c87 | ||
|
ecfcf57847 | ||
|
a1d546215f | ||
|
c0c48783a9 | ||
|
4f2767c4fe | ||
|
c40f870fa5 | ||
|
319289ca67 |
|
@ -1,46 +0,0 @@
|
|||
version: "0.1.0.{build}-{branch}"
|
||||
|
||||
os: Visual Studio 2019
|
||||
|
||||
environment:
|
||||
global:
|
||||
PROJECT_NAME: doukutsu-rs
|
||||
matrix:
|
||||
- channel: stable
|
||||
target: x86_64-pc-windows-msvc
|
||||
target_name: win64
|
||||
job_name: windows-x64
|
||||
# - channel: stable
|
||||
# target: i686-pc-windows-msvc
|
||||
# target_name: win32
|
||||
# job_name: windows-x32
|
||||
|
||||
install:
|
||||
- appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
|
||||
- rustup-init -yv --default-toolchain %channel% --default-host %target%
|
||||
- set PATH=%PATH%;%USERPROFILE%\.cargo\bin
|
||||
- rustup update
|
||||
- rustup default %channel%
|
||||
- rustc -vV
|
||||
- cargo -vV
|
||||
|
||||
cache:
|
||||
- '%USERPROFILE%\.cache\sccache -> Cargo.toml'
|
||||
- '%USERPROFILE%\.cargo -> Cargo.toml'
|
||||
- 'target -> Cargo.toml'
|
||||
|
||||
#test_script:
|
||||
# - cargo build --verbose --all
|
||||
# - cargo test --verbose --all --no-fail-fast
|
||||
|
||||
build_script:
|
||||
- set DRS_BUILD_VERSION_OVERRIDE=%APPVEYOR_BUILD_VERSION%
|
||||
- cargo build --release --bin doukutsu-rs
|
||||
- mkdir release
|
||||
- copy target\release\doukutsu-rs.exe release
|
||||
- cd release
|
||||
- appveyor DownloadFile https://github.com/doukutsu-rs/game-data/archive/master.zip -FileName ../game-data.zip
|
||||
- 7z x ../game-data.zip
|
||||
- rename game-data-master data
|
||||
- 7z a ../doukutsu-rs_%target_name%.zip *
|
||||
- appveyor PushArtifact ../doukutsu-rs_%target_name%.zip
|
205
.github/ISSUE_TEMPLATE/001-bug_report.yml
vendored
Normal file
|
@ -0,0 +1,205 @@
|
|||
name: Bug Report
|
||||
description: Report a bug or issue with doukutsu-rs
|
||||
type: "Bug"
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to report a bug! Please fill out this form as completely as possible to help us reproduce and fix the issue.
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Issue description
|
||||
description: A clear and concise description of what the bug is.
|
||||
placeholder: Describe the issue you're experiencing...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: reproduction-steps
|
||||
attributes:
|
||||
label: Reproduction steps
|
||||
description: Steps to reproduce the behavior
|
||||
placeholder: |
|
||||
1. Open the game and load the attached save file
|
||||
2. Go to Mimiga Village
|
||||
3. Do ...
|
||||
4. See that ... happens
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected-behavior
|
||||
attributes:
|
||||
label: Expected behavior
|
||||
description: A clear and concise description of what you expected to happen.
|
||||
placeholder: What should have happened instead?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: What **exact** version of doukutsu-rs are you using? For example, "0.102.0-beta7", "0.102.0-733" - you can find it at bottom of the main menu
|
||||
placeholder: x.xxx.x-xxx
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: data-files
|
||||
attributes:
|
||||
label: Data files used
|
||||
description: Which Cave Story data files are you using?
|
||||
options:
|
||||
- Vanilla Cave Story (1.0.0.6), Japanese
|
||||
- Vanilla Cave Story (1.0.0.6), AGTP English translation
|
||||
- Vanilla Cave Story - Another version or translation
|
||||
- Cave Story+ - Steam version
|
||||
- Cave Story+ - Epic Games version
|
||||
- Cave Story+ - GOG version
|
||||
- Cave Story+ - Humble Bundle DRM-free
|
||||
- Cave Story+ - Mac App Store version
|
||||
- Cave Story+ - 2011 Steam version
|
||||
- Cave Story+ 1.2 - Nintendo Switch version
|
||||
- Cave Story+ 1.3 - Nintendo Switch version
|
||||
- Another version not on the list
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: version-details
|
||||
attributes:
|
||||
label: Data files details (if applicable)
|
||||
description: If you selected "Vanilla Cave Story - Another version or translation" or "Another version not on the list" above, please specify which version you're using. Also mention if you have altered data files in any way, such as installing translation mods.
|
||||
placeholder: Please specify the exact version and any modifications...
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: dropdown
|
||||
id: platform
|
||||
attributes:
|
||||
label: Platform and Operating System
|
||||
description: What platform and operating system are you using?
|
||||
options:
|
||||
- Windows
|
||||
- Linux
|
||||
- macOS
|
||||
- Android
|
||||
- iOS
|
||||
- Nintendo Switch Homebrew
|
||||
- Other (please specify in additional info)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: device-specs
|
||||
attributes:
|
||||
label: Device Model / Specs
|
||||
description: Please provide your device specifications
|
||||
placeholder: |
|
||||
Examples:
|
||||
- PC, i7-10700K, RTX 3060, 16GB RAM
|
||||
- MacBook Pro, 14-inch, M3 Pro, 36GB RAM
|
||||
- Samsung Galaxy S20
|
||||
- iPhone 15 Pro
|
||||
- Nintendo Switch OLED
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: system-info
|
||||
attributes:
|
||||
label: System Information
|
||||
description: Please see below for instructions on how to get this information.
|
||||
placeholder: |
|
||||
[paste output here, if you're uncomfortable with running commands, just specify everything manually]
|
||||
|
||||
Example output:
|
||||
--- BEGIN SYSTEM INFO ---
|
||||
OS Version: 15.5 24F74
|
||||
CPU: Apple M2
|
||||
RAM: 16384 MB
|
||||
Manufacturer/Model: Mac14,2
|
||||
GPUs:
|
||||
- Apple
|
||||
--- END SYSTEM INFO ---
|
||||
render: shell
|
||||
validations:
|
||||
required: false
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
In case of a PC or Mac, the easiest way to get this is running a command in the command prompt or terminal app and pasting the output here.
|
||||
|
||||
For Windows, run the following command in command prompt:
|
||||
```powershell
|
||||
powershell.exe -NoProfile -Command "& {Write-Host ''; Write-Host ''; Write-Host '--- BEGIN SYSTEM INFO ---'; $os = Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue; $cpu = Get-CimInstance Win32_Processor -ErrorAction SilentlyContinue; $computer = Get-CimInstance Win32_ComputerSystem -ErrorAction SilentlyContinue; $gpus = Get-CimInstance Win32_VideoController -ErrorAction SilentlyContinue; Write-Host 'OS Version: $($os.Caption) $($os.OSArchitecture) Build $($os.BuildNumber)'; Write-Host 'CPU: $($cpu.Name)'; Write-Host 'Manufacturer: $($computer.Manufacturer)'; Write-Host 'Model: $($computer.Model)'; Write-Host 'RAM: $($computer.TotalPhysicalMemory / 1MB) MB'; if ($gpus) { $i=1; foreach ($gpu in $gpus) { Write-Host "GPU $($i): $($gpu.Caption)"; $i++ } } else { Write-Host 'GPU: Unknown' }; Write-Host '--- END SYSTEM INFO ---'; Write-Host ''; Write-Host ''}"
|
||||
```
|
||||
|
||||
For Linux, run the following command in terminal and paste the output here:
|
||||
```bash
|
||||
printf "\n\n--- BEGIN SYSTEM INFO ---\n"; printf "OS Version: %s\n" "$(lsb_release -d -r -c 2>/dev/null | awk -F':\t' '{print $2}' | paste -s -d' ' || cat /etc/os-release 2>/dev/null | grep "PRETTY_NAME" | awk -F'=' '{print $2}' | tr -d '\"' || echo 'Unknown')"; printf "CPU Architecture: %s\n" "$(uname -m 2>/dev/null || echo 'Unknown')"; printf "CPU Model: %s\n" "$(lscpu 2>/dev/null | grep "Model name" | awk -F': *' '{print $2}' || echo 'Unknown')"; printf "RAM: %s MB\n" "$(grep MemTotal /proc/meminfo 2>/dev/null | awk '{print int($2 / 1024)}' || echo 'Unknown')"; printf "System Manufacturer/Model: %s\n" "$(cat /sys/class/dmi/id/board_vendor 2>/dev/null || echo 'Unknown') $(cat /sys/class/dmi/id/board_name 2>/dev/null || echo 'Unknown')"; printf "GPUs:\n%s\n" "$(lspci -vnn 2>/dev/null | grep -i 'VGA compatible controller\|3D controller' | awk -F': ' '{print " - " $2}' | sed 's/ (rev .*//' || echo ' - Unknown')"; printf "--- END SYSTEM INFO ---\n\n\n"
|
||||
```
|
||||
|
||||
For macOS, run the following command in terminal and paste the output here:
|
||||
```bash
|
||||
printf "\n\n--- BEGIN SYSTEM INFO ---\n"; printf "OS Version: %s %s\n" "$(sw_vers -productVersion 2>/dev/null || echo 'Unknown')" "$(sw_vers -buildVersion 2>/dev/null || echo 'Unknown')"; printf "CPU: %s\n" "$(sysctl -n machdep.cpu.brand_string 2>/dev/null || echo 'Unknown')"; printf "RAM: %s MB\n" "$(sysctl -n hw.memsize 2>/dev/null | awk '{print int($1 / (1024*1024))}' || echo 'Unknown')"; printf "Manufacturer/Model: %s\n" "$(system_profiler SPHardwareDataType 2>/dev/null | awk '/Model Identifier/{print $3}' || echo 'Unknown')"; printf "GPUs:\n%s\n" "$(system_profiler SPDisplaysDataType 2>/dev/null | awk '/Chipset Model/{print " - " $3}' | sed 's/ - Unknown//g' || echo ' - Unknown')"; printf "--- END SYSTEM INFO ---\n\n\n"
|
||||
```
|
||||
If you're running macOS on non-Apple hardware (Hackintosh), please manually add relevant information.
|
||||
|
||||
In case of Android, iOS or Nintendo Switch, you need to fill out it manually.
|
||||
|
||||
Android:
|
||||
```
|
||||
Android Version: 15
|
||||
[ROM / OEM UI Type and Version, as best as you can, for example:]
|
||||
System: OneUI 6.1.1
|
||||
System: MIUI Global 14.0.4.0(RKOMIXM)
|
||||
System: Xiaomi HyperOS 1.0.5.0.UNLINXM
|
||||
System: Google Pixel, Android 15, Security Update October 5, 2024
|
||||
System: LineageOS 21-20250123-NIGHTLY-marble
|
||||
```
|
||||
|
||||
iOS:
|
||||
```
|
||||
iOS Version: 18.5
|
||||
```
|
||||
|
||||
Nintendo Switch:
|
||||
```
|
||||
System Version: 20.1.5
|
||||
Atmosphere Version: 1.9.1
|
||||
```
|
||||
|
||||
- type: textarea
|
||||
id: screenshots
|
||||
attributes:
|
||||
label: Screenshots / Videos
|
||||
description: If applicable, add screenshots or videos to help explain your problem. You can drag and drop files here.
|
||||
placeholder: Drag and drop files here or click to upload...
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: additional-context
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Add any other context about the problem here, such as error messages, logs, or anything else that might be helpful.
|
||||
placeholder: Any additional information that might help us understand the issue...
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Verification
|
||||
description: Please confirm the following
|
||||
options:
|
||||
- label: "I have searched for existing issues and this is not a duplicate."
|
||||
required: true
|
||||
- label: "I understand that 3rd party ports and modifications such as the RetroArch port or Cave Story: Encore are not supported within this repository."
|
||||
required: true
|
||||
- label: "I have provided all the requested information to the best of my ability."
|
||||
required: true
|
55
.github/ISSUE_TEMPLATE/002-feature_request.yml
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
name: Feature Request
|
||||
description: Suggest a new feature or improvement for doukutsu-rs
|
||||
type: "Feature"
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for suggesting a feature! Please fill out this form to help us understand your idea and how it could improve doukutsu-rs.
|
||||
|
||||
- type: textarea
|
||||
id: feature-description
|
||||
attributes:
|
||||
label: Feature description
|
||||
description: A clear and concise description of the feature or improvement you are proposing.
|
||||
placeholder: Describe the feature you want to see...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: motivation
|
||||
attributes:
|
||||
label: Motivation
|
||||
description: Why do you want this feature? What problem does it solve or what value does it add?
|
||||
placeholder: Explain why this feature would be useful...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: Possible alternatives or workarounds
|
||||
description: Have you considered any alternative solutions or workarounds?
|
||||
placeholder: List any alternatives you've thought of, or say N/A...
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: additional-context
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Add any other context, mockups, or screenshots about the feature request here.
|
||||
placeholder: Any extra information, images, or context...
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Verification
|
||||
description: Please confirm the following
|
||||
options:
|
||||
- label: "I have searched for existing issues and feature requests and this is not a duplicate."
|
||||
required: true
|
||||
- label: "I have described the feature clearly and provided all relevant information."
|
||||
required: true
|
26
.github/ISSUE_TEMPLATE/003-todo.yml
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
name: Task
|
||||
description: This is a template for maintainers to use. Please do not submit issues using this template, unless asked by a maintainer.
|
||||
type: "Task"
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Use this template to create a TO-DO task for the doukutsu-rs project.
|
||||
|
||||
- type: textarea
|
||||
id: plan
|
||||
attributes:
|
||||
label: Plan
|
||||
description: Describe the exact plan for what needs to be implemented or fixed.
|
||||
placeholder: Describe the specific plan, implementation details, or approach...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: context
|
||||
attributes:
|
||||
label: Context
|
||||
description: Any additional context, background information, or related issues.
|
||||
placeholder: Add any relevant context, links to related issues, or background info...
|
||||
validations:
|
||||
required: false
|
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Submit a question, idea or discuss with the community
|
||||
url: https://github.com/doukutsu-rs/doukutsu-rs/discussions
|
||||
about: Get help using doukutsu-rs
|
||||
- name: Join the Discord community
|
||||
url: https://discord.gg/fbRsNNB
|
||||
about: Talk with the team
|
427
.github/workflows/ci.yml
vendored
Normal file
|
@ -0,0 +1,427 @@
|
|||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches-ignore:
|
||||
- cpp-rewrite
|
||||
- horizon-os
|
||||
- refactor
|
||||
paths-ignore:
|
||||
- ".gitignore"
|
||||
- ".github/*"
|
||||
- "**.md"
|
||||
- "LICENSE"
|
||||
- "drshorizon/**"
|
||||
- "res/**"
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types:
|
||||
- released
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
env:
|
||||
VERSION: "0.102.0"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: ${{ matrix.name }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
include:
|
||||
- name: Linux x86_64
|
||||
os: ubuntu-latest
|
||||
channel: stable
|
||||
target: x86_64-unknown-linux-gnu
|
||||
target_name: linux-x64
|
||||
arch_name: x86_64
|
||||
- name: Windows x64
|
||||
os: windows-latest
|
||||
channel: stable
|
||||
target: x86_64-pc-windows-msvc
|
||||
target_name: windows-x64
|
||||
arch_name: x86_64
|
||||
- name: Windows x32
|
||||
os: windows-latest
|
||||
channel: stable
|
||||
target: i686-pc-windows-msvc
|
||||
target_name: windows-x32
|
||||
arch_name: i686
|
||||
- name: macOS x64 (Intel Macs)
|
||||
os: macos-latest
|
||||
channel: stable
|
||||
target: x86_64-apple-darwin
|
||||
target_name: mac-x64
|
||||
arch_name: x86_64
|
||||
- name: macOS ARM64 (M1 Macs)
|
||||
os: macos-latest
|
||||
channel: stable
|
||||
target: aarch64-apple-darwin
|
||||
target_name: mac-arm64
|
||||
arch_name: arm64
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
if: ${{ matrix.os == 'ubuntu-latest' }}
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install libasound2-dev libudev-dev libgl1-mesa-dev libxext-dev
|
||||
|
||||
- name: Set version
|
||||
id: set_version
|
||||
run: |
|
||||
if [ "${{ github.ref_type }}" == "tag" ]; then
|
||||
echo "version=${{ github.ref_name }}" >> $GITHUB_OUTPUT
|
||||
echo "channel=stable" >> $GITHUB_OUTPUT
|
||||
elif [ "${{ github.ref_name }}" == "master" ]; then
|
||||
echo "version=${{ env.VERSION }}-$((${{ github.run_number }} + 654))" >> $GITHUB_OUTPUT
|
||||
echo "channel=nightly" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "version=${{ env.VERSION }}-${GITHUB_SHA:0:7}" >> $GITHUB_OUTPUT
|
||||
echo "channel=nightly" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Restore cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo
|
||||
~/.rustup
|
||||
target
|
||||
key: ${{ matrix.target_name }}-cargo
|
||||
|
||||
- name: Setup rust toolchain
|
||||
run: |
|
||||
rustup default ${{ matrix.channel }}
|
||||
rustup target add ${{ matrix.target }}
|
||||
|
||||
rustc -vV
|
||||
cargo -vV
|
||||
|
||||
if [ "${{ runner.os }}" == "macOS" ]; then
|
||||
cargo install cargo-bundle
|
||||
fi
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
if [ -z "${{ steps.set_version.outputs.version }}" ]; then
|
||||
echo "version is not set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export DRS_BUILD_VERSION_OVERRIDE="${{ steps.set_version.outputs.version }}"
|
||||
|
||||
mkdir release
|
||||
|
||||
if [ "${{ runner.os }}" == "macOS" ]; then
|
||||
CARGO_INCREMENTAL=1 cargo bundle --release --target ${{ matrix.target }}
|
||||
cp -a ./target/${{ matrix.target }}/release/bundle/osx/doukutsu-rs.app release/doukutsu-rs.app
|
||||
codesign -s - -f ./release/doukutsu-rs.app/Contents/MacOS/doukutsu-rs
|
||||
cd release
|
||||
zip -9r "doukutsu-rs_mac-${{ matrix.arch_name }}.zip" doukutsu-rs.app
|
||||
rm -rf doukutsu-rs.app
|
||||
cd ..
|
||||
elif [ "${{ runner.os }}" == "Windows" ]; then
|
||||
CARGO_INCREMENTAL=1 cargo build --release --locked --bin doukutsu-rs --target ${{ matrix.target }}
|
||||
cp ./target/${{ matrix.target }}/release/doukutsu-rs.exe release/doukutsu-rs.${{ matrix.arch_name }}.exe
|
||||
elif [ "${{ runner.os }}" == "Linux" ]; then
|
||||
RUSTFLAGS="-C link-args=-s" CARGO_INCREMENTAL=1 cargo build --release --locked --bin doukutsu-rs --target ${{ matrix.target }}
|
||||
cp -a ./target/${{ matrix.target }}/release/doukutsu-rs release/doukutsu-rs.${{ matrix.arch_name }}.elf
|
||||
fi
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: doukutsu-rs_${{ matrix.target_name }}
|
||||
path: ./release/*
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Save cache
|
||||
if: ${{ github.ref_name == 'master' || github.ref_type == 'tag' }}
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo
|
||||
~/.rustup
|
||||
target
|
||||
key: ${{ matrix.target_name }}-cargo
|
||||
|
||||
build_android:
|
||||
name: Android build
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
APP_OUTPUTS_DIR: "app/app/build/outputs/apk/release"
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
include:
|
||||
- name: Android
|
||||
os: ubuntu-latest
|
||||
channel: stable
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Restore cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cache
|
||||
~/.cargo
|
||||
~/.rustup
|
||||
~/.gradle
|
||||
app/app/.cxx
|
||||
app/app/build
|
||||
drsandroid/target
|
||||
key: android-cargo
|
||||
|
||||
- name: Setup rust toolchain
|
||||
run: |
|
||||
rustup default stable
|
||||
rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android
|
||||
rustc -vV
|
||||
cargo -vV
|
||||
cargo install cargo-ndk
|
||||
|
||||
- name: Install development kits
|
||||
run: |
|
||||
$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --install --package_file=app/app/packages.txt
|
||||
|
||||
- name: Set version
|
||||
id: set_version
|
||||
run: |
|
||||
if [ "${{ github.ref_type }}" == "tag" ]; then
|
||||
echo "version=${{ github.ref_name }}" >> $GITHUB_OUTPUT
|
||||
echo "channel=stable" >> $GITHUB_OUTPUT
|
||||
elif [ "${{ github.ref_name }}" == "master" ]; then
|
||||
echo "version=${{ env.VERSION }}-$((${{ github.run_number }} + 654))" >> $GITHUB_OUTPUT
|
||||
echo "channel=nightly" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "version=${{ env.VERSION }}-${GITHUB_SHA:0:7}" >> $GITHUB_OUTPUT
|
||||
echo "channel=nightly" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
if [ -z "${{ steps.set_version.outputs.version }}" ]; then
|
||||
echo "version is not set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export DRS_BUILD_VERSION_OVERRIDE="${{ steps.set_version.outputs.version }}"
|
||||
|
||||
cd app
|
||||
touch local.properties
|
||||
chmod +x ./gradlew
|
||||
./gradlew assembleRelease
|
||||
|
||||
- name: Sign app
|
||||
run: |
|
||||
BUILD_TOOLS=$ANDROID_HOME/build-tools/33.0.0
|
||||
|
||||
echo "${{ secrets.ANDROID_SIGNING_KEYSTORE }}" | base64 --decode > keystore.jks
|
||||
if [ "${{ secrets.ANDROID_SIGNING_KEY_PASS }}" != "" ]; then
|
||||
$BUILD_TOOLS/apksigner sign --ks ./keystore.jks --ks-key-alias "${{ secrets.ANDROID_SIGNING_ALIAS }}" --ks-pass "pass:${{ secrets.ANDROID_SIGNING_KEYSTORE_PASS }}" --key-pass "pass:${{ secrets.ANDROID_SIGNING_KEY_PASS }}" --out $APP_OUTPUTS_DIR/app-signed.apk $APP_OUTPUTS_DIR/app-release-unsigned.apk
|
||||
else
|
||||
$BUILD_TOOLS/apksigner sign --ks ./keystore.jks --ks-key-alias "${{ secrets.ANDROID_SIGNING_ALIAS }}" --ks-pass "pass:${{ secrets.ANDROID_SIGNING_KEYSTORE_PASS }}" --out $APP_OUTPUTS_DIR/app-signed.apk $APP_OUTPUTS_DIR/app-release-unsigned.apk
|
||||
fi
|
||||
|
||||
rm keystore.jks
|
||||
|
||||
- name: Prepare artifact
|
||||
run: |
|
||||
mkdir release
|
||||
mv $APP_OUTPUTS_DIR/app-signed.apk release/doukutsu-rs.apk
|
||||
cp LICENSE ./release
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: doukutsu-rs_android
|
||||
path: ./release/*
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Save cache
|
||||
if: ${{ github.ref_name == 'master' || github.ref_type == 'tag' }}
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cache
|
||||
~/.cargo
|
||||
~/.rustup
|
||||
~/.gradle
|
||||
app/app/.cxx
|
||||
app/app/build
|
||||
drsandroid/target
|
||||
key: android-cargo
|
||||
|
||||
update_metadata:
|
||||
name: Update metadata
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.ref_name == 'master' || github.ref_type == 'tag' }}
|
||||
needs: [build, build_android]
|
||||
permissions:
|
||||
contents: write
|
||||
env:
|
||||
CF_ACCESS_KEY_ID: ${{ secrets.CF_ACCESS_KEY_ID }}
|
||||
CF_SECRET_ACCESS_KEY: ${{ secrets.CF_SECRET_ACCESS_KEY }}
|
||||
CF_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}
|
||||
CF_BUCKET_NAME: "doukutsu-rs"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: doukutsu-rs/metadata
|
||||
token: ${{ secrets.METADATA_USER_TOKEN }}
|
||||
|
||||
- name: Set version
|
||||
id: set_version
|
||||
run: |
|
||||
if [ "${{ github.ref_type }}" == "tag" ]; then
|
||||
echo "version=${{ github.ref_name }}" >> $GITHUB_OUTPUT
|
||||
echo "channel=stable" >> $GITHUB_OUTPUT
|
||||
elif [ "${{ github.ref_name }}" == "master" ]; then
|
||||
echo "version=${{ env.VERSION }}-$((${{ github.run_number }} + 654))" >> $GITHUB_OUTPUT
|
||||
echo "channel=nightly" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "version=${{ env.VERSION }}-${GITHUB_SHA:0:7}" >> $GITHUB_OUTPUT
|
||||
echo "channel=nightly" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
mkdir -p releases/${{ steps.set_version.outputs.version }}
|
||||
|
||||
- name: Update metadata
|
||||
id: metadata
|
||||
run: |
|
||||
# fail early if ${{ steps.set_version.outputs.* }} is not set
|
||||
if [ -z "${{ steps.set_version.outputs.channel }}" ]; then
|
||||
echo "channel is not set"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "${{ steps.set_version.outputs.version }}" ]; then
|
||||
echo "version is not set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export FILE="./metadata/${{ steps.set_version.outputs.channel }}.json"
|
||||
export VERSION="${{ steps.set_version.outputs.version }}"
|
||||
|
||||
if [ "${{ needs.build.result }}" == "success" ]; then
|
||||
node ./metadata.js --os linux --arch x86_64 --version $VERSION --commit $GITHUB_SHA --link https://nightly.link/doukutsu-rs/doukutsu-rs/actions/runs/${{ github.run_id }}/doukutsu-rs_linux-x64.zip $FILE
|
||||
node ./metadata.js --os windows --arch x86_64 --version $VERSION --commit $GITHUB_SHA --link https://nightly.link/doukutsu-rs/doukutsu-rs/actions/runs/${{ github.run_id }}/doukutsu-rs_windows-x64.zip $FILE
|
||||
node ./metadata.js --os windows --arch i686 --version $VERSION --commit $GITHUB_SHA --link https://nightly.link/doukutsu-rs/doukutsu-rs/actions/runs/${{ github.run_id }}/doukutsu-rs_windows-x32.zip $FILE
|
||||
node ./metadata.js --os macos --arch x64 --version $VERSION --commit $GITHUB_SHA --link https://nightly.link/doukutsu-rs/doukutsu-rs/actions/runs/${{ github.run_id }}/doukutsu-rs_mac-x64.zip $FILE
|
||||
node ./metadata.js --os macos --arch arm64 --version $VERSION --commit $GITHUB_SHA --link https://nightly.link/doukutsu-rs/doukutsu-rs/actions/runs/${{ github.run_id }}/doukutsu-rs_mac-arm64.zip $FILE
|
||||
fi
|
||||
|
||||
if [ "${{ needs.build_android.result }}" == "success" ]; then
|
||||
node ./metadata.js --os android --version $VERSION --commit $GITHUB_SHA --link https://nightly.link/doukutsu-rs/doukutsu-rs/actions/runs/${{ github.run_id }}/doukutsu-rs_android.zip $FILE
|
||||
fi
|
||||
|
||||
mkdir -p release-binaries
|
||||
echo "file=$FILE" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Windows x32 build
|
||||
- name: Download Windows x32 artifact
|
||||
if: ${{ needs.build.result == 'success' }}
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: doukutsu-rs_windows-x32
|
||||
path: temp-windows-x32
|
||||
|
||||
- name: Process Windows x32 build
|
||||
if: ${{ needs.build.result == 'success' }}
|
||||
run: |
|
||||
node ./uploadBuild.js update --channel ${{ steps.set_version.outputs.channel }} --version "${{ steps.set_version.outputs.version }}" --platform windows --arch i686 --commit $GITHUB_SHA --file "temp-windows-x32/doukutsu-rs.i686.exe"
|
||||
cp ./temp-windows-x32/doukutsu-rs.i686.exe "./release-binaries/doukutsu-rs_windows_${{ steps.set_version.outputs.version }}.i686.exe"
|
||||
|
||||
# Windows x64 build
|
||||
- name: Download Windows x64 artifact
|
||||
if: ${{ needs.build.result == 'success' }}
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: doukutsu-rs_windows-x64
|
||||
path: temp-windows-x64
|
||||
|
||||
- name: Process Windows x64 build
|
||||
if: ${{ needs.build.result == 'success' }}
|
||||
run: |
|
||||
node ./uploadBuild.js update --channel ${{ steps.set_version.outputs.channel }} --version "${{ steps.set_version.outputs.version }}" --platform windows --arch x86_64 --commit $GITHUB_SHA --file "temp-windows-x64/doukutsu-rs.x86_64.exe"
|
||||
cp ./temp-windows-x64/doukutsu-rs.x86_64.exe "./release-binaries/doukutsu-rs_windows_${{ steps.set_version.outputs.version }}.x86_64.exe"
|
||||
|
||||
# Linux x64 build
|
||||
- name: Download Linux x64 artifact
|
||||
if: ${{ needs.build.result == 'success' }}
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: doukutsu-rs_linux-x64
|
||||
path: temp-linux-x64
|
||||
|
||||
- name: Process Linux x64 build
|
||||
if: ${{ needs.build.result == 'success' }}
|
||||
run: |
|
||||
node ./uploadBuild.js update --channel ${{ steps.set_version.outputs.channel }} --version "${{ steps.set_version.outputs.version }}" --platform linux --arch x86_64 --commit $GITHUB_SHA --file "temp-linux-x64/doukutsu-rs.x86_64.elf"
|
||||
cp ./temp-linux-x64/doukutsu-rs.x86_64.elf "./release-binaries/doukutsu-rs_linux_${{ steps.set_version.outputs.version }}.x86_64.elf"
|
||||
|
||||
# macOS x64 build
|
||||
- name: Download macOS x64 artifact
|
||||
if: ${{ needs.build.result == 'success' }}
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: doukutsu-rs_mac-x64
|
||||
path: temp-mac-x64
|
||||
|
||||
- name: Process macOS x64 build
|
||||
if: ${{ needs.build.result == 'success' }}
|
||||
run: |
|
||||
node ./uploadBuild.js update --channel ${{ steps.set_version.outputs.channel }} --version "${{ steps.set_version.outputs.version }}" --platform macos --arch x86_64 --commit $GITHUB_SHA --file "temp-mac-x64/doukutsu-rs_mac-x86_64.zip"
|
||||
cp ./temp-mac-x64/doukutsu-rs_mac-x86_64.zip "./release-binaries/doukutsu-rs_macos_${{ steps.set_version.outputs.version }}.x86_64.zip"
|
||||
|
||||
# macOS ARM64 build
|
||||
- name: Download macOS ARM64 artifact
|
||||
if: ${{ needs.build.result == 'success' }}
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: doukutsu-rs_mac-arm64
|
||||
path: temp-mac-arm64
|
||||
|
||||
- name: Process macOS ARM64 build
|
||||
if: ${{ needs.build.result == 'success' }}
|
||||
run: |
|
||||
node ./uploadBuild.js update --channel ${{ steps.set_version.outputs.channel }} --version "${{ steps.set_version.outputs.version }}" --platform macos --arch arm64 --commit $GITHUB_SHA --file "temp-mac-arm64/doukutsu-rs_mac-arm64.zip"
|
||||
cp ./temp-mac-arm64/doukutsu-rs_mac-arm64.zip "./release-binaries/doukutsu-rs_macos_${{ steps.set_version.outputs.version }}.arm64.zip"
|
||||
|
||||
# Android build
|
||||
- name: Download Android artifact
|
||||
if: ${{ needs.build_android.result == 'success' }}
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: doukutsu-rs_android
|
||||
path: temp-android
|
||||
|
||||
- name: Process Android build
|
||||
if: ${{ needs.build_android.result == 'success' }}
|
||||
run: |
|
||||
node ./uploadBuild.js update --channel ${{ steps.set_version.outputs.channel }} --version "${{ steps.set_version.outputs.version }}" --platform android --arch universal --commit $GITHUB_SHA --file "temp-android/doukutsu-rs.apk"
|
||||
cp ./temp-android/doukutsu-rs.apk "./release-binaries/doukutsu-rs_android_${{ steps.set_version.outputs.version }}.universal.apk"
|
||||
|
||||
- name: Upload binaries to release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
if: ${{ github.ref_type == 'tag' }}
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: release-binaries/*
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
file_glob: true
|
||||
|
||||
- name: Upload metadata
|
||||
run: |
|
||||
git config user.name ${{ vars.METADATA_USER_NAME }}
|
||||
git config user.email ${{ vars.METADATA_USER_EMAIL }}
|
||||
|
||||
git add ${{ steps.metadata.outputs.file }}
|
||||
git commit -m "Update ${{ steps.set_version.outputs.channel }} builds metadata(CI)"
|
||||
git push
|
224
.github/workflows/release.yml
vendored
|
@ -1,224 +0,0 @@
|
|||
name: Release
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build-linux-x86_64:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get install libasound2-dev libudev-dev pkg-config
|
||||
|
||||
- name: Cache Cargo registry
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cargo/registry
|
||||
key: ${{ runner.os }}-stable-cargo-registry
|
||||
restore-keys: |
|
||||
${{ runner.os }}-stable-cargo-registry-
|
||||
|
||||
- name: Cache Cargo index
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cargo/git
|
||||
key: ${{ runner.os }}-stable-cargo-index
|
||||
restore-keys: |
|
||||
${{ runner.os }}-stable-cargo-index-
|
||||
|
||||
- name: Cache Cargo build
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: target
|
||||
key: ${{ runner.os }}-stable-target
|
||||
restore-keys: |
|
||||
${{ runner.os }}-stable-target
|
||||
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Checkout data files
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: doukutsu-rs/game-data
|
||||
path: data
|
||||
|
||||
- name: Install latest stable Rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
default: true
|
||||
override: true
|
||||
|
||||
- name: Build
|
||||
run: cargo build --all --release && strip target/release/doukutsu-rs
|
||||
|
||||
- name: Copy executable to root directory
|
||||
run: cp target/release/doukutsu-rs doukutsu-rs.x86_64
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: doukutsu-rs_linux_x86_64
|
||||
path: |
|
||||
doukutsu-rs.x86_64
|
||||
data
|
||||
!data/README.md
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
files: |
|
||||
doukutsu-rs.x86_64
|
||||
data
|
||||
!data/.git
|
||||
!data/README.md
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
build-windows-x86:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: Cache Cargo registry
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cargo/registry
|
||||
key: ${{ runner.os }}-stable-cargo-registry
|
||||
restore-keys: |
|
||||
${{ runner.os }}-stable-cargo-registry-
|
||||
|
||||
- name: Cache Cargo index
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cargo/git
|
||||
key: ${{ runner.os }}-stable-cargo-index
|
||||
restore-keys: |
|
||||
${{ runner.os }}-stable-cargo-index-
|
||||
|
||||
- name: Cache Cargo build
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: target
|
||||
key: ${{ runner.os }}-stable-target
|
||||
restore-keys: |
|
||||
${{ runner.os }}-stable-target
|
||||
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Checkout data files
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: doukutsu-rs/game-data
|
||||
path: data
|
||||
|
||||
- name: Install latest stable Rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
target: i686-pc-windows-msvc
|
||||
default: true
|
||||
override: true
|
||||
|
||||
- name: Build
|
||||
run: cargo build --target i686-pc-windows-msvc --all --release
|
||||
|
||||
- name: Copy executable to root directory
|
||||
run: cp target/i686-pc-windows-msvc/release/doukutsu-rs.exe doukutsu-rs.exe
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: doukutsu-rs_windows_x86
|
||||
path: |
|
||||
doukutsu-rs.exe
|
||||
data
|
||||
!data/.git
|
||||
!data/README.md
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
files: |
|
||||
doukutsu-rs.exe
|
||||
data
|
||||
!data/README.md
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
build-windows-x64:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: Cache Cargo registry
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cargo/registry
|
||||
key: ${{ runner.os }}-stable-cargo-registry
|
||||
restore-keys: |
|
||||
${{ runner.os }}-stable-cargo-registry-
|
||||
|
||||
- name: Cache Cargo index
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cargo/git
|
||||
key: ${{ runner.os }}-stable-cargo-index
|
||||
restore-keys: |
|
||||
${{ runner.os }}-stable-cargo-index-
|
||||
|
||||
- name: Cache Cargo build
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: target
|
||||
key: ${{ runner.os }}-stable-target
|
||||
restore-keys: |
|
||||
${{ runner.os }}-stable-target
|
||||
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Checkout data files
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: doukutsu-rs/game-data
|
||||
path: data
|
||||
|
||||
- name: Install latest stable Rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
default: true
|
||||
override: true
|
||||
|
||||
- name: Build
|
||||
run: cargo build --all --release
|
||||
|
||||
- name: Copy executable to root directory
|
||||
run: cp target/release/doukutsu-rs.exe doukutsu-rs.exe
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: doukutsu-rs_windows_x64
|
||||
path: |
|
||||
doukutsu-rs.exe
|
||||
data
|
||||
!data/.git
|
||||
!data/README.md
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
files: |
|
||||
doukutsu-rs.exe
|
||||
data
|
||||
!data/README.md
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
55
.gitignore
vendored
|
@ -2,17 +2,64 @@
|
|||
.vscode/
|
||||
|
||||
# Cave Story (copyrighted) data files
|
||||
data/
|
||||
/data/
|
||||
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
debug/
|
||||
target/
|
||||
|
||||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
||||
Cargo.lock
|
||||
# Shader binary files
|
||||
*.dksh
|
||||
|
||||
# These are backup files generated by rustfmt
|
||||
**/*.rs.bk
|
||||
|
||||
# cave story saves
|
||||
Profile.dat*
|
||||
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
Thumbs.db:encryptable
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# Dump file
|
||||
*.stackdump
|
||||
|
||||
# Folder config file
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
*.log
|
||||
|
||||
3rdparty/
|
57
AUTHORS.md
Normal file
|
@ -0,0 +1,57 @@
|
|||
# doukutsu-rs Contributors
|
||||
|
||||
This file recognizes the people who have made meaningful contributions to doukutsu-rs through code, bug fixes, features, and other improvements.
|
||||
|
||||
Contributors are listed based on their level of involvement, with a focus on those who have made 5 or more commits or contributed substantial features. This list doesn't represent legal copyright - check the git log for detailed code authorship.
|
||||
|
||||
All GitHub profiles are linked for easy reference.
|
||||
|
||||
## Active Maintainers
|
||||
|
||||
These contributors actively maintain the project and review contributions:
|
||||
|
||||
**[alula](https://github.com/alula)**
|
||||
**[dawndus](https://github.com/dawndus)**
|
||||
**[jozsefsallai](https://github.com/jozsefsallai)**
|
||||
**[biroder](https://github.com/biroder)**
|
||||
|
||||
## Regular Contributors
|
||||
|
||||
Contributors with multiple commits or major feature work:
|
||||
|
||||
**[periwinkle9](https://github.com/periwinkle9)**
|
||||
**[DrGlaucous](https://github.com/DrGlaucous)**
|
||||
**[khang06](https://github.com/khang06)**
|
||||
**[mokurin000](https://github.com/mokurin000)**
|
||||
**[JakeV-1](https://github.com/JakeV-1)**
|
||||
|
||||
## Other Contributors
|
||||
|
||||
People who have made valuable contributions to the codebase:
|
||||
|
||||
**[beholdnec](https://github.com/beholdnec)**
|
||||
**[GiantBlargg](https://github.com/GiantBlargg)**
|
||||
**[tranzystorekk](https://github.com/tranzystorekk)**
|
||||
**[IruzzArcana](https://github.com/IruzzArcana)**
|
||||
**[M0REKZ](https://github.com/M0REKZ)**
|
||||
**[vrmiguel](https://github.com/vrmiguel)**
|
||||
**[tulilirockz](https://github.com/tulilirockz)**
|
||||
|
||||
## Artwork & Design
|
||||
|
||||
**[@Daedliy](https://twitter.com/Daedliy)** - Original "Crab Sue" character design and sketch-style doukutsu-rs logo
|
||||
**[AppleHair](https://github.com/AppleHair)** - New cute "Crab Sue" icon art for all platforms
|
||||
|
||||
## Built Upon
|
||||
|
||||
doukutsu-rs incorporates and builds upon these external works:
|
||||
|
||||
**[ggez](https://github.com/ggez/ggez)** - Original framework that doukutsu-rs was built on; a derivative of it's VFS implementation and other components remain in the codebase
|
||||
**[Clownacy](https://github.com/Clownacy)** - Implementation concepts from CSE2-Enhanced and Cave Story Mod Loader
|
||||
**[LunarLambda](https://github.com/doukutsu-rs/organism)** - Organism Rust Organya sound format player library, enhanced and integrated into doukutsu-rs
|
||||
**[Zoroyoshi](http://z.apps.atjp.jp/k12x10/)** - k12x10 public domain bitmap font (current built-in font)
|
||||
**[/efont/ Shinonome](http://openlab.ring.gr.jp/efont/shinonome/)** - Shinonome Public domain bitmap font family (used in early 2020 versions)
|
||||
|
||||
---
|
||||
|
||||
_See the full list of all code contributors on [GitHub](https://github.com/doukutsu-rs/doukutsu-rs/graphs/contributors)._
|
2836
Cargo.lock
generated
Normal file
144
Cargo.toml
|
@ -1,88 +1,114 @@
|
|||
[package]
|
||||
authors = ["Alula"]
|
||||
edition = "2018"
|
||||
name = "doukutsu-rs"
|
||||
version = "0.1.0"
|
||||
description = "A re-implementation of Cave Story (Doukutsu Monogatari) engine"
|
||||
version = "0.102.0"
|
||||
authors = ["Alula", "dawnDus"]
|
||||
edition = "2021"
|
||||
rust-version = "1.65"
|
||||
|
||||
#[lib]
|
||||
#crate-type = ["lib", "cdylib"]
|
||||
[lib]
|
||||
crate-type = ["lib"]
|
||||
|
||||
[package.metadata.android]
|
||||
android_version = 29
|
||||
target_sdk_version = 28
|
||||
min_sdk_version = 26
|
||||
build_targets = ["aarch64-linux-android"]
|
||||
package_name = "io.github.doukutsu_rs.android"
|
||||
apk_label = "doukutsu-rs"
|
||||
opengles_version = [3, 1]
|
||||
fullscreen = true
|
||||
orientation = "sensorLandscape"
|
||||
permission = [
|
||||
{ name = "android.permission.READ_EXTERNAL_STORAGE" },
|
||||
{ name = "android.permission.WRITE_EXTERNAL_STORAGE" }
|
||||
]
|
||||
application_metadatas = [
|
||||
{ name = "android:hardwareAccelerated", value = "true" },
|
||||
{ name = "android:requestLegacyExternalStorage", value = "true" }
|
||||
]
|
||||
[[bin]]
|
||||
name = "doukutsu-rs"
|
||||
path = "src/main.rs"
|
||||
test = false
|
||||
bench = false
|
||||
required-features = ["exe"]
|
||||
|
||||
[profile.release]
|
||||
lto = 'thin'
|
||||
panic = 'abort'
|
||||
# This is intentional. Enabling LTO inflates build times and does not provide us any significant benefits.
|
||||
lto = "off"
|
||||
panic = "abort"
|
||||
split-debuginfo = "packed"
|
||||
|
||||
[profile.dev.package."*"]
|
||||
opt-level = 3
|
||||
overflow-checks = false
|
||||
codegen-units = 256
|
||||
|
||||
[profile.dev.build-override]
|
||||
opt-level = 1
|
||||
|
||||
[profile.release.build-override]
|
||||
opt-level = 1
|
||||
[package.metadata.bundle]
|
||||
name = "doukutsu-rs"
|
||||
identifier = "io.github.doukutsu_rs"
|
||||
icon = ["res/macos/16x16.png", "res/macos/16x16@2x.png", "res/macos/32x32.png", "res/macos/32x32@2x.png", "res/macos/128x128.png", "res/macos/128x128@2x.png", "res/macos/256x256.png", "res/macos/256x256@2x.png", "res/macos/512x512.png", "res/macos/512x512@2x.png"]
|
||||
version = "0.102.0"
|
||||
resources = ["data"]
|
||||
copyright = "Copyright (c) 2020-2023 doukutsu-rs contributors"
|
||||
category = "Game"
|
||||
osx_minimum_system_version = "10.12"
|
||||
|
||||
[features]
|
||||
default = ["scripting", "backend-sdl", "ogg-playback"]
|
||||
default = ["default-base", "backend-sdl", "render-opengl", "exe", "webbrowser", "discord-rpc"]
|
||||
default-base = ["ogg-playback"]
|
||||
ogg-playback = ["lewton"]
|
||||
backend-sdl = ["sdl2"]
|
||||
backend-gfx = ["winit", "imgui-gfx-renderer", "imgui-winit-support"]
|
||||
scripting = ["lua-ffi"]
|
||||
backend-sdl = ["sdl2", "sdl2-sys"]
|
||||
backend-glutin = ["winit", "glutin", "render-opengl"]
|
||||
backend-horizon = []
|
||||
render-opengl = []
|
||||
discord-rpc = ["discord-rich-presence"]
|
||||
netplay = ["serde_cbor"]
|
||||
editor = []
|
||||
exe = []
|
||||
android = []
|
||||
|
||||
[dependencies]
|
||||
bitvec = "0.20"
|
||||
#glutin = { path = "./3rdparty/glutin/glutin", optional = true }
|
||||
#winit = { path = "./3rdparty/winit", optional = true, default_features = false, features = ["x11"] }
|
||||
#sdl2 = { path = "./3rdparty/rust-sdl2", optional = true, features = ["unsafe_textures", "bundled", "static-link"] }
|
||||
#sdl2-sys = { path = "./3rdparty/rust-sdl2/sdl2-sys", optional = true, features = ["bundled", "static-link"] }
|
||||
#cpal = { path = "./3rdparty/cpal" }
|
||||
byteorder = "1.4"
|
||||
clap = { version = "4.5.40", default_features = false, features = ["std", "help", "usage", "error-context", "cargo", "derive"] }
|
||||
case_insensitive_hashmap = "1.0.0"
|
||||
chrono = "0.4"
|
||||
cpal = "0.13"
|
||||
chrono = { version = "0.4", default-features = false, features = ["clock", "std"] }
|
||||
cpal = { git = "https://github.com/doukutsu-rs/cpal", rev = "ce731c58b7f4759a0f4007b392e2b7f4716a347c" }
|
||||
directories = "3"
|
||||
imgui = "0.7.0"
|
||||
imgui-gfx-renderer = { version = "0.7.0", optional = true }
|
||||
imgui-winit-support = { version = "0.7.0", default-features = false, features = ["winit-24"], optional = true }
|
||||
image = { version = "0.23", default-features = false, features = ["png", "bmp"] }
|
||||
discord-rich-presence = { version = "0.2", optional = true }
|
||||
downcast = "0.11"
|
||||
encoding_rs = "0.8.33"
|
||||
fern = "0.6.2"
|
||||
glutin = { git = "https://github.com/doukutsu-rs/glutin.git", rev = "2dd95f042e6e090d36f577cbea125560dd99bd27", optional = true, default_features = false, features = ["x11"] }
|
||||
imgui = { git = "https://github.com/imgui-rs/imgui-rs.git", rev = "5d771a83b82c5cc3dd58cca3f969d900369262e6" }
|
||||
image = { version = "0.24", default-features = false, features = ["png", "bmp"] }
|
||||
itertools = "0.10"
|
||||
lazy_static = "1.4.0"
|
||||
lewton = { version = "0.10.2", optional = true }
|
||||
lazy_static = "1.4"
|
||||
lewton = { version = "0.10", optional = true }
|
||||
log = "0.4"
|
||||
lua-ffi = { git = "https://github.com/doukutsu-rs/lua-ffi.git", rev = "1ef3caf772d72068297ddf75df06fd2ef8c1daab", optional = true }
|
||||
lru = "0.6.0"
|
||||
num-derive = "0.3.2"
|
||||
num-traits = "0.2.12"
|
||||
paste = "1.0.0"
|
||||
pretty_env_logger = "0.4.0"
|
||||
sdl2 = { version = "0.34", optional = true, features = ["unsafe_textures", "bundled", "static-link"] }
|
||||
num-derive = "0.3"
|
||||
num-traits = "0.2"
|
||||
open = "3.2"
|
||||
paste = "1.0"
|
||||
pelite = { version = ">=0.9.2", default-features = false, features = ["std"] }
|
||||
sdl2 = { git = "https://github.com/doukutsu-rs/rust-sdl2.git", rev = "244ae85833cff4f97ab4b58331741be20e422bd7", optional = true, features = ["unsafe_textures", "bundled", "static-link"] }
|
||||
sdl2-sys = { git = "https://github.com/doukutsu-rs/rust-sdl2.git", rev = "244ae85833cff4f97ab4b58331741be20e422bd7", optional = true, features = ["bundled", "static-link"] }
|
||||
rc-box = "1.2.0"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_derive = "1"
|
||||
serde_yaml = "0.8"
|
||||
strum = "0.20"
|
||||
strum_macros = "0.20"
|
||||
# remove and replace when drain_filter is in stable
|
||||
serde_cbor = { version = "0.11", optional = true }
|
||||
serde_json = "1.0"
|
||||
strum = "0.24"
|
||||
strum_macros = "0.24"
|
||||
# remove and replace with extract_if, when our MSRV is 1.87
|
||||
vec_mut_scan = "0.4"
|
||||
webbrowser = "0.5.5"
|
||||
winit = { version = "0.24", features = ["serde"], optional = true }
|
||||
webbrowser = { version = "0.8.6", optional = true }
|
||||
winit = { git = "https://github.com/doukutsu-rs/winit.git", rev = "878f206d19af01b0977277929eee5e32667453c0", optional = true, default_features = false, features = ["x11"] }
|
||||
xmltree = "0.10"
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
winapi = { version = "0.3", features = ["winuser"] }
|
||||
|
||||
[target.'cfg(target_os = "windows")'.build-dependencies]
|
||||
winres = "0.1"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
objc = "0.2"
|
||||
|
||||
[target.'cfg(target_os = "android")'.dependencies]
|
||||
ndk = "0.3"
|
||||
ndk-glue = "0.3"
|
||||
jni = "0.19"
|
||||
ndk = "0.7"
|
||||
ndk-glue = "0.7"
|
||||
ndk-sys = "0.4"
|
||||
jni = "0.20"
|
||||
|
||||
[target.'cfg(target_os = "horizon")'.dependencies]
|
||||
#deko3d = { path = "./3rdparty/deko3d" }
|
||||
deko3d = { git = "https://github.com/doukutsu-rs/deko3d-rs", branch = "master" }
|
||||
|
|
22
LICENSE
|
@ -1,7 +1,21 @@
|
|||
Copyright 2020 Alula
|
||||
MIT/doukutsu-rs License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
Copyright 2020 doukutsu-rs contributors.
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
The Software cannot be redistributed bundled with data files taken from any commercial port
|
||||
released by Nicalis Inc. without their explicit permission.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
248
README.md
|
@ -1,52 +1,244 @@
|
|||
# doukutsu-rs
|
||||

|
||||
|
||||

|
||||
|
||||
[Download latest Nightly builds](https://github.com/doukutsu-rs/doukutsu-rs/actions) (Requires being logged in to GitHub)
|
||||
|
||||
A re-implementation of Cave Story (Doukutsu Monogatari) engine written in [Rust](https://www.rust-lang.org/).
|
||||
|
||||
**The project is still incomplete and not fully playable yet.** [Click here to see the current status of the project](https://github.com/doukutsu-rs/doukutsu-rs/issues/10).
|
||||
A fully playable re-implementation of the Cave Story (Doukutsu Monogatari) engine written
|
||||
in [Rust](https://www.rust-lang.org/).
|
||||
|
||||
[Join the Discord server](https://discord.gg/fbRsNNB)
|
||||
|
||||
[](https://nightly.link/doukutsu-rs/doukutsu-rs/workflows/ci/master?preview)
|
||||
|
||||
- Get stable/beta builds from
|
||||
- [get.doukutsu.rs](https://get.doukutsu.rs)
|
||||
- [GitHub Releases](https://github.com/doukutsu-rs/doukutsu-rs/releases)
|
||||
- [Flatpak](https://flathub.org/apps/io.github.doukutsu_rs.doukutsu-rs) (Linux only)
|
||||
|
||||
- [Get nightly builds](https://nightly.link/doukutsu-rs/doukutsu-rs/workflows/ci/master?preview) (recommended for now, has latest fixes and improvements)
|
||||
|
||||
Permalinks to latest builds from `master` branch:
|
||||
|
||||
- [Windows (64-bit)](https://nightly.link/doukutsu-rs/doukutsu-rs/workflows/ci/master/doukutsu-rs_windows-x64.zip)
|
||||
- [Windows (32-bit)](https://nightly.link/doukutsu-rs/doukutsu-rs/workflows/ci/master/doukutsu-rs_windows-x32.zip)
|
||||
- [macOS (Intel, 64-bit, 10.14+)](https://nightly.link/doukutsu-rs/doukutsu-rs/workflows/ci/master/doukutsu-rs_mac-x64.zip)
|
||||
- [macOS (Apple M1, 11.0+)](https://nightly.link/doukutsu-rs/doukutsu-rs/workflows/ci/master/doukutsu-rs_mac-arm64.zip)
|
||||
- [Linux (64-bit)](https://nightly.link/doukutsu-rs/doukutsu-rs/workflows/ci/master/doukutsu-rs_linux-x64.zip)
|
||||
- [Android (armv7/arm64/x86)](https://nightly.link/doukutsu-rs/doukutsu-rs/workflows/ci/master/doukutsu-rs_android.zip)
|
||||
|
||||
> [!NOTE]
|
||||
> macOS note: If you get a `"doukutsu-rs" can't be opened` message, right-click doukutsu-rs.app and click open.
|
||||
|
||||
> [!NOTE]
|
||||
> If you get issues with Epic Games Store version, scroll down for instructions.
|
||||
|
||||
#### Data files
|
||||
|
||||
This repository does not contain any copyrighted files.
|
||||
In order to work doukutsu-rs needs to be paired with supported data files. This repository does not contain any data
|
||||
files.
|
||||
|
||||
For better user experience, pre-built binaries are distributed with slightly modified freeware game files.
|
||||
doukutsu-rs works fine with freeware data files or [NXEngine(-evo)](https://github.com/nxengine/nxengine-evo) or from a
|
||||
supported copy of [Cave Story+](https://www.nicalis.com/games/cavestory+).
|
||||
|
||||
*doukutsu-rs* should work fine with pre-extracted and tweaked data files from [this repository](https://github.com/doukutsu-rs/game-data), [NXEngine(-evo)](https://github.com/nxengine/nxengine-evo) extracted freeware data files and [Cave Story+](https://www.nicalis.com/games/cavestory+) data files.
|
||||
<details>
|
||||
<summary>How to set up data files on Android</summary>
|
||||
|
||||
If your phone has an app called **"Files"**:
|
||||
|
||||
Vanilla Cave Story does not work yet because some important data files have been embedded inside the executable. and we don't have a loader/extractor implemented yet.
|
||||
1. Launch this app.
|
||||
2. Press **☰** on the top left corner.
|
||||
3. Tap on **"doukutsu-rs game data"**.
|
||||
4. Copy your game data files to the opened folder.
|
||||
|
||||
##### Where to get them?
|
||||
|
||||
If your phone does not have this app:
|
||||
|
||||
1. Install the **"Material Files"** app from *Hai Zhang* and launch it([Google Play](https://play.google.com/store/apps/details?id=me.zhanghai.android.files) | [F-Droid](https://f-droid.org/en/packages/me.zhanghai.android.files/) | [Github Releases](https://github.com/zhanghai/MaterialFiles/releases)).
|
||||
2. Press **☰** on the top left corner.
|
||||
3. Press **"+ Add storage"**.
|
||||
4. In the window that pops up, press **"External storage"**.
|
||||
5. Press **☰** on the top left corner.
|
||||
6. Tap on **"doukutsu-rs game data"**.
|
||||
7. Press the large blue button at the bottom labelled **"USE THIS FOLDER"**.
|
||||
8. Then click on **☰** in the top left corner again and open.
|
||||
9. Tap on **"files"** above **"+ Add storage"**.
|
||||
10. Copy your game data files to the opened folder.
|
||||
</details>
|
||||
|
||||
#### Supported game editions and data file acquisition guides
|
||||
|
||||
**Freeware**
|
||||
|
||||
- https://github.com/doukutsu-rs/game-data - Freeware game data distributed with CI builds, based on those two below.
|
||||
- ~~https://github.com/Clownacy/CSE2/archive/enhanced.zip - copy `game_english/data` from archive to the runtime directory (place you run the executable from, usually project root)~~
|
||||
- https://github.com/nxengine/nxengine-evo/releases/download/v2.6.4/NXEngine-v2.6.4-Win32.zip - copy `NXEngine-evo-2.6.4-xxx/data` from the archive to runtime directory
|
||||
doukutsu-rs works out of the box when it's placed in the same directory as the original Doukutsu.exe executable. On the initial
|
||||
startup, doukutsu-rs will automatically extract the additional resources that are embedded in the vanilla game into the `data`
|
||||
directory. Until that is done, both doukutsu-rs and the vanilla executable have to exist in the directory.
|
||||
|
||||
<details>
|
||||
<summary>Example root directory</summary>
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
**Cave Story+**
|
||||
|
||||
- PC release (Steam) - (Tested only with Steam version, both Windows and Linux builds) Copy `data` folder from installation directory ([guide for Steam](https://steamcommunity.com/sharedfiles/filedetails/?id=760447682)) to the runtime directory.
|
||||
- PC release (EGS) - (Untested, but the game is essentially the same as Steam release) Same thing as with Steam version.
|
||||
- Switch release - (Tested once, no guarantee to work) You need a hacked Switch and physical release. Google should help you.
|
||||
doukutsu-rs can be used as drop-in replacement for `CaveStory+.exe`. No modifications to game files are needed.
|
||||
|
||||
#### Mandatory screenshots
|
||||
**Original version (first released in 2011 on Steam)** - expand for instructions
|
||||
|
||||
**Freeware data files:**
|
||||
<details>
|
||||
<summary>Steam release (Win/Mac/Linux)</summary>
|
||||
|
||||

|
||||
The `data` folder is in the same place across all platforms.
|
||||
|
||||
**Cave Story+ data files:**
|
||||
If you want to use doukutsu-rs as a substitute for Mac version of Cave Story+ (which at moment of writing doesn't work
|
||||
on 10.15+ anymore), do the following:
|
||||
|
||||

|
||||
1. Find the doukutsu-rs executable:
|
||||
- In AppVeyor builds, it's in `doukutsu-rs.app/Contents/MacOS/doukutsu-rs`
|
||||
- In your own builds, it's in `target/(release|debug)/doukutsu-rs`
|
||||
2. Open Steam Library, select `Cave Story+`, press the `Manage` button (gear icon) and select `Properties...`
|
||||
3. Select `Local Files` and press `Browse...`.
|
||||
4. Open the `Cave Story+.app` bundle and navigate to `Contents/MacOS` directory.
|
||||
5. Rename the `Cave Story+` executable to something else or delete it.
|
||||
6. Copy the doukutsu-rs executable and rename it to `Cave Story+`.
|
||||
7. Launch the game from Steam and enjoy!
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
> [!WARNING]
|
||||
> **EPIC GAMES STORE VERSION WARNING**
|
||||
>
|
||||
> Nicalis for some reason ships a stray `opengl32.dll` DLL from Windows 7 with the Epic Games Store copies of Cave Story+.
|
||||
>
|
||||
> However as the game is 32-bit and the dll is 64-bit it has no effect on the original version, but as it's a core Windows DLL and doukutsu-rs ships 64-bit builds and uses OpenGL, it's makes the game crash on startup.
|
||||
>
|
||||
> The fix is to simply delete `opengl32.dll`, as it's not used anyway.
|
||||
|
||||
<details>
|
||||
<summary>Epic Games Store</summary>
|
||||
|
||||
Check your default installation directory.
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>GOG</summary>
|
||||
|
||||
Check your default installation directory.
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Humble Bundle</summary>
|
||||
|
||||
The archive from Humble Bundle contains the necessary `data` folder, in the same folder as `CaveStory+.exe`.
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>WiiWare</summary>
|
||||
|
||||
1. [Dump Your WiiWare `.wad`](https://wii.guide/dump-wads.html)
|
||||
2. [Extract and decompress the `data` folder](https://docs.google.com/document/d/1hDNDgNl0cUDlFOQ_BUOq3QCGb7S0xfUxRoob-hfM-DY)
|
||||
Example of a [valid uncompressed `data` folder](https://user-images.githubusercontent.com/53099651/159585593-43fead24-b041-48f4-8332-be50d712310d.png)
|
||||
|
||||
</details>
|
||||
|
||||
**Remastered version (first released in 2017 on Switch)**
|
||||
|
||||
> [!NOTE]
|
||||
> This version is **incompatible** with saves from the original version.
|
||||
>
|
||||
> Interchanging the save files may result in spawning in wrong locations, softlocks, graphical glitches, or other issues.
|
||||
|
||||
<details>
|
||||
<summary>Nintendo Switch</summary>
|
||||
|
||||
Extract the `data` folder (contained in `romfs`) from your console using tool such as [nxdumptool](https://github.com/DarkMatterCore/nxdumptool).
|
||||
|
||||
**Important notes:**
|
||||
|
||||
- doukutsu-rs doesn't rely on the original ROM or executable, you just need the data files, go to `RomFS options` menu to just extract the files to SD card so you don't need to do any extra steps.
|
||||
- Ensure you're dumping the files **with update included** (`Use update/DLC` option), as 1.0 isn't supported.
|
||||
|
||||
**Nintendo Switch homebrew port specific info**
|
||||
|
||||
If you're running the homebrew port (drshorizon.nro) on your Switch, you can avoid the dumping step, doukutsu-rs will
|
||||
automatically detect and mount the data files if you run it over Cave Story+ in Title Override mode (hold `R` while starting CS+ and launch d-rs from hbmenu).
|
||||
|
||||
You can put your own data files in `/switch/doukutsu-rs/data` directory on SD Card, which will be overlayed over RomFS if
|
||||
you run it in setup described above.
|
||||
|
||||
</details>
|
||||
|
||||
#### Controls
|
||||
|
||||
Same controls as the default for freeware and Cave Story+ keyboard.
|
||||
|
||||
To change, use the control customization menu or edit `doukutsu-rs\data\settings.json` within your user directory.
|
||||
|
||||
| | P1 | P2 |
|
||||
| ------------------------- | --------- | --------- |
|
||||
| Movement | `← ↑ ↓ →` | `, L . /` |
|
||||
| Jump | `Z` | `B` |
|
||||
| Shoot | `X` | `N` |
|
||||
| Cycle Weapon | `A and S` | `G and H` |
|
||||
| Inventory / Skip cutscene | `Q` | `T` |
|
||||
| Map | `W` | `Y` |
|
||||
| Strafe | `LShift` | `RShift` |
|
||||
|
||||
- `Alt + Enter` - Toggle Fullscreen
|
||||
- `F2` (While paused) - Quick Restart
|
||||
|
||||
#### Screenshots
|
||||
|
||||
<details>
|
||||
<summary>Freeware</summary>
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Original CS+</summary>
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Remastered CS+</summary>
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
#### Credits
|
||||
|
||||
- Studio Pixel/Nicalis for Cave Story
|
||||
- [Cave Story Tribute Site](https://cavestory.org) - has lots of useful resources related to the game.
|
||||
- [CSE2](https://github.com/Clownacy/CSE2) - widescreen fixes, more readable reference for game logic, mutual help in various things.
|
||||
- [LunarLambda for organism](https://gitdab.com/LunarLambda/organism) - which is being used by us as `.org` playback engine.
|
||||
- Studio Pixel/Nicalis for Cave Story
|
||||
- [AppleHair](https://github.com/AppleHair) - icon redesign for all platforms(`crabsue-icon`).
|
||||
- [@Daedily](https://twitter.com/Daedliy) - brand artwork (Icon / Banner / Server), screenshots for this guide.
|
||||
- [ggez](https://github.com/ggez/ggez) - parts of it are used in `crate::framework`, notably the VFS code.
|
||||
- [Clownacy](https://github.com/Clownacy) - widescreen camera code.
|
||||
- [LunarLambda for organism](https://github.com/doukutsu-rs/organism) - used as basis for our Organya playback engine.
|
||||
- [Zoroyoshi](http://z.apps.atjp.jp/k12x10/) - k12x10 font we use as built-in font.
|
||||
|
|
234
app/.gitignore
vendored
Normal file
|
@ -0,0 +1,234 @@
|
|||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/androidstudio,gradle,android
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=androidstudio,gradle,android
|
||||
|
||||
### Android ###
|
||||
# Built application files
|
||||
*.apk
|
||||
*.aar
|
||||
*.ap_
|
||||
*.aab
|
||||
|
||||
# Files for the ART/Dalvik VM
|
||||
*.dex
|
||||
|
||||
# Java class files
|
||||
*.class
|
||||
|
||||
# Generated files
|
||||
bin/
|
||||
gen/
|
||||
out/
|
||||
# Uncomment the following line in case you need and you don't have the release build type files in your app
|
||||
# release/
|
||||
|
||||
# Gradle files
|
||||
.gradle/
|
||||
build/
|
||||
|
||||
# Local configuration file (sdk path, etc)
|
||||
local.properties
|
||||
|
||||
# Proguard folder generated by Eclipse
|
||||
proguard/
|
||||
|
||||
# Log Files
|
||||
*.log
|
||||
|
||||
# Android Studio Navigation editor temp files
|
||||
.navigation/
|
||||
|
||||
# Android Studio captures folder
|
||||
captures/
|
||||
|
||||
# IntelliJ
|
||||
*.iml
|
||||
.idea/workspace.xml
|
||||
.idea/tasks.xml
|
||||
.idea/gradle.xml
|
||||
.idea/assetWizardSettings.xml
|
||||
.idea/dictionaries
|
||||
.idea/libraries
|
||||
# Android Studio 3 in .gitignore file.
|
||||
.idea/caches
|
||||
.idea/modules.xml
|
||||
# Comment next line if keeping position of elements in Navigation Editor is relevant for you
|
||||
.idea/navEditor.xml
|
||||
|
||||
# Keystore files
|
||||
# Uncomment the following lines if you do not want to check your keystore files in.
|
||||
#*.jks
|
||||
#*.keystore
|
||||
|
||||
# External native build folder generated in Android Studio 2.2 and later
|
||||
.externalNativeBuild
|
||||
.cxx/
|
||||
|
||||
# Google Services (e.g. APIs or Firebase)
|
||||
# google-services.json
|
||||
|
||||
# Freeline
|
||||
freeline.py
|
||||
freeline/
|
||||
freeline_project_description.json
|
||||
|
||||
# fastlane
|
||||
fastlane/report.xml
|
||||
fastlane/Preview.html
|
||||
fastlane/screenshots
|
||||
fastlane/test_output
|
||||
fastlane/readme.md
|
||||
|
||||
# Version control
|
||||
vcs.xml
|
||||
|
||||
# lint
|
||||
lint/intermediates/
|
||||
lint/generated/
|
||||
lint/outputs/
|
||||
lint/tmp/
|
||||
# lint/reports/
|
||||
|
||||
### Android Patch ###
|
||||
gen-external-apklibs
|
||||
output.json
|
||||
|
||||
# Replacement of .externalNativeBuild directories introduced
|
||||
# with Android Studio 3.5.
|
||||
|
||||
### Gradle ###
|
||||
.gradle
|
||||
|
||||
# Ignore Gradle GUI config
|
||||
gradle-app.setting
|
||||
|
||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||
!gradle-wrapper.jar
|
||||
|
||||
# Cache of project
|
||||
.gradletasknamecache
|
||||
|
||||
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
|
||||
# gradle/wrapper/gradle-wrapper.properties
|
||||
|
||||
### Gradle Patch ###
|
||||
**/build/
|
||||
|
||||
### AndroidStudio ###
|
||||
# Covers files to be ignored for android development using Android Studio.
|
||||
|
||||
# Built application files
|
||||
|
||||
# Files for the ART/Dalvik VM
|
||||
|
||||
# Java class files
|
||||
|
||||
# Generated files
|
||||
|
||||
# Gradle files
|
||||
|
||||
# Signing files
|
||||
.signing/
|
||||
|
||||
# Local configuration file (sdk path, etc)
|
||||
|
||||
# Proguard folder generated by Eclipse
|
||||
|
||||
# Log Files
|
||||
|
||||
# Android Studio
|
||||
/*/build/
|
||||
/*/local.properties
|
||||
/*/out
|
||||
/*/*/build
|
||||
/*/*/production
|
||||
*.ipr
|
||||
*~
|
||||
*.swp
|
||||
|
||||
# Keystore files
|
||||
*.jks
|
||||
*.keystore
|
||||
|
||||
# Google Services (e.g. APIs or Firebase)
|
||||
# google-services.json
|
||||
|
||||
# Android Patch
|
||||
|
||||
# External native build folder generated in Android Studio 2.2 and later
|
||||
|
||||
# NDK
|
||||
obj/
|
||||
*.so
|
||||
|
||||
# IntelliJ IDEA
|
||||
*.iws
|
||||
/out/
|
||||
|
||||
# User-specific configurations
|
||||
.idea/caches/
|
||||
.idea/libraries/
|
||||
.idea/shelf/
|
||||
.idea/.name
|
||||
.idea/compiler.xml
|
||||
.idea/copyright/profiles_settings.xml
|
||||
.idea/encodings.xml
|
||||
.idea/misc.xml
|
||||
.idea/scopes/scope_settings.xml
|
||||
.idea/vcs.xml
|
||||
.idea/jsLibraryMappings.xml
|
||||
.idea/datasources.xml
|
||||
.idea/dataSources.ids
|
||||
.idea/sqlDataSources.xml
|
||||
.idea/dynamic.xml
|
||||
.idea/uiDesigner.xml
|
||||
.idea/jarRepositories.xml
|
||||
|
||||
# OS-specific files
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
|
||||
# Legacy Eclipse project files
|
||||
.classpath
|
||||
.project
|
||||
.cproject
|
||||
.settings/
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.war
|
||||
*.ear
|
||||
|
||||
# virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml)
|
||||
hs_err_pid*
|
||||
|
||||
## Plugin-specific files:
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/mongoSettings.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
### AndroidStudio Patch ###
|
||||
|
||||
!/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/androidstudio,gradle,android
|
||||
app/release/
|
1
app/app/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/build
|
148
app/app/build.gradle
Normal file
|
@ -0,0 +1,148 @@
|
|||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'com.github.willir.rust.cargo-ndk-android'
|
||||
}
|
||||
|
||||
android {
|
||||
namespace "io.github.doukutsu_rs"
|
||||
|
||||
/**
|
||||
* NOTE: If you want to change the versions of packages required for the build
|
||||
* (e.g. build tools, compile SDK, NDK) or add new ones,
|
||||
* make the appropriate changes in packages.txt. Otherwise CI could break.
|
||||
*/
|
||||
compileSdkVersion 33
|
||||
buildToolsVersion "33.0.0"
|
||||
ndkVersion "25.2.9519653"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "io.github.doukutsu_rs"
|
||||
minSdkVersion 24
|
||||
targetSdkVersion 33
|
||||
versionCode 3
|
||||
versionName "0.102.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
ndk {
|
||||
abiFilters 'arm64-v8a'
|
||||
stl = "c++_shared"
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments "-DANDROID_STL=c++_shared"
|
||||
}
|
||||
}
|
||||
|
||||
def documentsAuthorityValue = applicationId + ".documents"
|
||||
manifestPlaceholders = [documentsAuthority: documentsAuthorityValue]
|
||||
buildConfigField "String",
|
||||
"DOCUMENTS_AUTHORITY",
|
||||
"\"${documentsAuthorityValue}\""
|
||||
|
||||
resValue "string", "app_name", "doukutsu-rs"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
|
||||
ndk {
|
||||
abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'
|
||||
stl = "c++_shared"
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
resources {
|
||||
excludes += "**/DebugProbesKt.bin"
|
||||
}
|
||||
}
|
||||
}
|
||||
debug {
|
||||
applicationIdSuffix ".debug"
|
||||
resValue "string", "app_name", "doukutsu-rs (debug)"
|
||||
|
||||
jniDebuggable true
|
||||
renderscriptDebuggable true
|
||||
|
||||
def documentsAuthorityValue =
|
||||
android.defaultConfig.applicationId + applicationIdSuffix + ".documents"
|
||||
manifestPlaceholders = [documentsAuthority: documentsAuthorityValue]
|
||||
buildConfigField "String",
|
||||
"DOCUMENTS_AUTHORITY",
|
||||
"\"${documentsAuthorityValue}\""
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path "src/main/cpp/CMakeLists.txt"
|
||||
}
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
jniLibs {
|
||||
excludes += "**/dummy.so"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'androidx.annotation:annotation:1.5.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.6.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
|
||||
implementation 'androidx.core:core:1.9.0'
|
||||
implementation 'com.google.android.material:material:1.8.0'
|
||||
}
|
||||
|
||||
println("cargo target: ${project.buildDir.getAbsolutePath()}/rust-target")
|
||||
println("ndk dir: ${android.ndkDirectory}")
|
||||
|
||||
cargoNdk {
|
||||
librariesNames = ["libdrsandroid.so"]
|
||||
module = "../drsandroid/"
|
||||
extraCargoEnv = ["ANDROID_NDK_HOME": android.ndkDirectory]
|
||||
extraCargoBuildArguments = []
|
||||
verbose = true
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
buildType = "release"
|
||||
extraCargoBuildArguments = ["--locked"]
|
||||
targets = [
|
||||
"arm64",
|
||||
"arm",
|
||||
"x86",
|
||||
"x86_64"
|
||||
]
|
||||
}
|
||||
debug {
|
||||
buildType = "debug"
|
||||
targets = [
|
||||
"arm64"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.whenTaskAdded { task ->
|
||||
if (task.name == 'javaPreCompileDebug') {
|
||||
task.dependsOn 'buildCargoNdkDebug'
|
||||
}
|
||||
|
||||
if (task.name == 'javaPreCompileRelease') {
|
||||
task.dependsOn 'buildCargoNdkRelease'
|
||||
}
|
||||
}
|
3
app/app/packages.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
ndk;25.2.9519653
|
||||
build-tools;33.0.0
|
||||
platforms;android-33
|
21
app/app/proguard-rules.pro
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
64
app/app/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,64 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:appCategory="game"
|
||||
android:description="@string/app_description"
|
||||
android:extractNativeLibs="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:isGame="true"
|
||||
android:label="@string/app_name"
|
||||
android:resizeableActivity="false"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.Doukutsurs">
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="standard"
|
||||
android:screenOrientation="sensorLandscape"
|
||||
android:theme="@style/Theme.Doukutsurs.NoActionBar">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".DownloadActivity"
|
||||
android:label="Download"
|
||||
android:screenOrientation="sensorLandscape"
|
||||
android:theme="@style/Theme.Doukutsurs.NoActionBar" />
|
||||
|
||||
<activity
|
||||
android:name=".GameActivity"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||
android:exported="true"
|
||||
android:launchMode="standard"
|
||||
android:screenOrientation="sensorLandscape">
|
||||
<meta-data
|
||||
android:name="android.app.lib_name"
|
||||
android:value="drsandroid" />
|
||||
</activity>
|
||||
|
||||
<provider
|
||||
android:name=".DoukutsuDocumentsProvider"
|
||||
android:authorities="${applicationId}.documents"
|
||||
android:exported="true"
|
||||
android:grantUriPermissions="true"
|
||||
android:permission="android.permission.MANAGE_DOCUMENTS">
|
||||
<intent-filter>
|
||||
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
|
||||
</intent-filter>
|
||||
</provider>
|
||||
</application>
|
||||
|
||||
</manifest>
|
53
app/app/src/main/cpp/CMakeLists.txt
Normal file
|
@ -0,0 +1,53 @@
|
|||
# Sets the minimum version of CMake required to build your native library.
|
||||
# This ensures that a certain set of CMake features is available to
|
||||
# your build.
|
||||
project(doukutsu-rs)
|
||||
cmake_minimum_required(VERSION 3.18)
|
||||
|
||||
# Copy shared STL files to Android Studio output directory so they can be
|
||||
# packaged in the APK.
|
||||
# Usage:
|
||||
#
|
||||
# find_package(ndk-stl REQUIRED)
|
||||
#
|
||||
# or
|
||||
#
|
||||
# find_package(ndk-stl REQUIRED PATHS ".")
|
||||
|
||||
#if(NOT ${ANDROID_STL} MATCHES "_shared")
|
||||
# return()
|
||||
#endif()
|
||||
|
||||
function(configure_shared_stl lib_path so_base)
|
||||
message("Configuring STL ${so_base} for ${ANDROID_ABI}")
|
||||
configure_file(
|
||||
"${ANDROID_NDK}/toolchains/llvm/prebuilt/${ANDROID_HOST_TAG}/sysroot/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/lib${so_base}.so"
|
||||
"${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${so_base}.so"
|
||||
COPYONLY)
|
||||
endfunction()
|
||||
|
||||
if("${ANDROID_STL}" STREQUAL "libstdc++")
|
||||
# The default minimal system C++ runtime library.
|
||||
elseif("${ANDROID_STL}" STREQUAL "gabi++_shared")
|
||||
# The GAbi++ runtime (shared).
|
||||
message(FATAL_ERROR "gabi++_shared was not configured by ndk-stl package")
|
||||
elseif("${ANDROID_STL}" STREQUAL "stlport_shared")
|
||||
# The STLport runtime (shared).
|
||||
configure_shared_stl("stlport" "stlport_shared")
|
||||
elseif("${ANDROID_STL}" STREQUAL "gnustl_shared")
|
||||
# The GNU STL (shared).
|
||||
configure_shared_stl("gnu-libstdc++/4.9" "gnustl_shared")
|
||||
elseif("${ANDROID_STL}" STREQUAL "c++_shared")
|
||||
# The LLVM libc++ runtime (static).
|
||||
configure_shared_stl("llvm-libc++" "c++_shared")
|
||||
else()
|
||||
message(FATAL_ERROR "STL configuration ANDROID_STL=${ANDROID_STL} is not supported")
|
||||
endif()
|
||||
|
||||
# Specifies a library name, specifies whether the library is STATIC or
|
||||
# SHARED, and provides relative paths to the source code. You can
|
||||
# define multiple libraries by adding multiple add_library() commands,
|
||||
# and CMake builds them for you. When you build your app, Gradle
|
||||
# automatically packages shared libraries with your APK.
|
||||
|
||||
add_library(dummy SHARED dummy.cpp)
|
2
app/app/src/main/cpp/dummy.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
void drs_dummy_export() {
|
||||
}
|
BIN
app/app/src/main/ic_launcher-playstore.png
Normal file
After Width: | Height: | Size: 254 KiB |
|
@ -0,0 +1,16 @@
|
|||
package io.github.doukutsu_rs;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.view.Window;
|
||||
import androidx.core.view.WindowCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.core.view.WindowInsetsControllerCompat;
|
||||
|
||||
public class ActivityUtils {
|
||||
public static void hideSystemBars(Activity activity) {
|
||||
Window window = activity.getWindow();
|
||||
WindowInsetsControllerCompat windowInsetsController =
|
||||
WindowCompat.getInsetsController(window, window.getDecorView());
|
||||
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,355 @@
|
|||
package io.github.doukutsu_rs;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.database.Cursor;
|
||||
import android.database.MatrixCursor;
|
||||
import android.database.MatrixCursor.RowBuilder;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.provider.DocumentsContract;
|
||||
import android.provider.DocumentsContract.Document;
|
||||
import android.provider.DocumentsContract.Path;
|
||||
import android.provider.DocumentsContract.Root;
|
||||
import android.provider.DocumentsProvider;
|
||||
import android.util.Log;
|
||||
import android.webkit.MimeTypeMap;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
|
||||
public class DoukutsuDocumentsProvider extends DocumentsProvider {
|
||||
private final static String[] DEFAULT_ROOT_PROJECTION =
|
||||
new String[]{
|
||||
Root.COLUMN_DOCUMENT_ID,
|
||||
Root.COLUMN_ROOT_ID,
|
||||
Root.COLUMN_ICON,
|
||||
Root.COLUMN_TITLE,
|
||||
Root.COLUMN_MIME_TYPES,
|
||||
Root.COLUMN_AVAILABLE_BYTES,
|
||||
Root.COLUMN_FLAGS
|
||||
};
|
||||
|
||||
private final static String[] DEFAULT_DOCUMENT_PROJECTION =
|
||||
new String[]{
|
||||
Document.COLUMN_DOCUMENT_ID,
|
||||
Document.COLUMN_DISPLAY_NAME,
|
||||
Document.COLUMN_SIZE,
|
||||
Document.COLUMN_LAST_MODIFIED,
|
||||
Document.COLUMN_MIME_TYPE,
|
||||
Document.COLUMN_FLAGS
|
||||
};
|
||||
|
||||
@Override
|
||||
public Cursor queryRoots(String[] projection) throws FileNotFoundException {
|
||||
File file = getContext().getFilesDir();
|
||||
String id = file.getAbsolutePath();
|
||||
Log.d(DoukutsuDocumentsProvider.class.getName(), "files dir location: " + id);
|
||||
|
||||
MatrixCursor result = new MatrixCursor(projection != null ?
|
||||
projection : DEFAULT_ROOT_PROJECTION);
|
||||
|
||||
RowBuilder row = result.newRow();
|
||||
|
||||
row.add(Root.COLUMN_DOCUMENT_ID, id);
|
||||
row.add(Root.COLUMN_ROOT_ID, id);
|
||||
row.add(Root.COLUMN_ICON, R.mipmap.ic_launcher);
|
||||
row.add(Root.COLUMN_TITLE,
|
||||
getContext().getString(R.string.app_name));
|
||||
row.add(Root.COLUMN_MIME_TYPES, "*/*");
|
||||
row.add(Root.COLUMN_AVAILABLE_BYTES, file.getFreeSpace());
|
||||
row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor queryDocument(String documentId, String[] projection) throws FileNotFoundException {
|
||||
MatrixCursor result = new MatrixCursor(projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION);
|
||||
|
||||
Log.d("dupa", "queryDocument: " + documentId);
|
||||
pushFile(result, new File(documentId));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor queryChildDocuments(String parentDocumentId, String[] projection, String sortOrder) throws FileNotFoundException {
|
||||
MatrixCursor result = new MatrixCursor(projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION);
|
||||
|
||||
File root = new File(parentDocumentId);
|
||||
Log.d("dupa", "doc id:" + parentDocumentId);
|
||||
|
||||
if (!root.exists()) {
|
||||
Log.d("dupa", "no such file");
|
||||
throw new FileNotFoundException("No such file: " + root.getAbsolutePath());
|
||||
}
|
||||
|
||||
if (!root.isDirectory()) {
|
||||
Log.d("dupa", "not a directory");
|
||||
return null;
|
||||
}
|
||||
|
||||
File[] files = root.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
pushFile(result, file);
|
||||
}
|
||||
}
|
||||
|
||||
result.setNotificationUri(getContext().getContentResolver(), DocumentsContract.buildDocumentUri(BuildConfig.DOCUMENTS_AUTHORITY, parentDocumentId));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParcelFileDescriptor openDocument(String documentId, String mode, @Nullable CancellationSignal signal) throws FileNotFoundException {
|
||||
File file = new File(documentId);
|
||||
int imode = ParcelFileDescriptor.parseMode(mode);
|
||||
return ParcelFileDescriptor.open(file, imode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createDocument(String parentDocumentId, String mimeType, String displayName) throws FileNotFoundException {
|
||||
File file = new File(parentDocumentId, displayName);
|
||||
|
||||
if (file.exists()) {
|
||||
int nextId = 1;
|
||||
|
||||
while (file.exists()) {
|
||||
// maybe let's put the id before extension?
|
||||
file = new File(parentDocumentId, String.format("%s (%d)", displayName, nextId));
|
||||
|
||||
++nextId;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (mimeType != null && mimeType.equals(Document.MIME_TYPE_DIR)) {
|
||||
if (!file.mkdir()) {
|
||||
throw new FileNotFoundException("Couldn't create directory: " + file.getAbsolutePath());
|
||||
}
|
||||
} else {
|
||||
if (!file.createNewFile()) {
|
||||
throw new FileNotFoundException("Couldn't create file: " + file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new FileNotFoundException("Couldn't create file: " + e.getMessage());
|
||||
}
|
||||
|
||||
Uri uri = DocumentsContract.buildDocumentUri(BuildConfig.DOCUMENTS_AUTHORITY, file.getParent());
|
||||
|
||||
if (SDK_INT >= Build.VERSION_CODES.R) {
|
||||
getContext().getContentResolver().notifyChange(uri, null, ContentResolver.NOTIFY_INSERT);
|
||||
} else {
|
||||
getContext().getContentResolver().notifyChange(uri, null);
|
||||
}
|
||||
|
||||
|
||||
return file.getAbsolutePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteDocument(String documentId) throws FileNotFoundException {
|
||||
File file = new File(documentId);
|
||||
|
||||
if (!file.exists()) {
|
||||
throw new FileNotFoundException("Couldn't find file: " + file.getAbsolutePath());
|
||||
}
|
||||
|
||||
deleteRecursive(file);
|
||||
|
||||
|
||||
Uri uri = DocumentsContract.buildDocumentUri(BuildConfig.DOCUMENTS_AUTHORITY, file.getParent());
|
||||
|
||||
if (SDK_INT >= Build.VERSION_CODES.R) {
|
||||
getContext().getContentResolver().notifyChange(uri, null, ContentResolver.NOTIFY_DELETE);
|
||||
} else {
|
||||
getContext().getContentResolver().notifyChange(uri, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
public Path findDocumentPath(@Nullable String parentDocumentId, String childDocumentId) throws FileNotFoundException {
|
||||
if (parentDocumentId == null) {
|
||||
parentDocumentId = getContext().getFilesDir().getAbsolutePath();
|
||||
}
|
||||
|
||||
File childFile = new File(childDocumentId);
|
||||
if (!childFile.exists()) {
|
||||
throw new FileNotFoundException(childFile.getAbsolutePath()+" doesn't exist");
|
||||
} else if (!isChildDocument(parentDocumentId, childDocumentId)) {
|
||||
throw new FileNotFoundException(childDocumentId+" is not child of "+parentDocumentId);
|
||||
}
|
||||
|
||||
LinkedList<String> path = new LinkedList<>();
|
||||
while (childFile != null && isChildDocument(parentDocumentId, childFile.getAbsolutePath())) {
|
||||
path.addFirst(childFile.getAbsolutePath());
|
||||
childFile = childFile.getParentFile();
|
||||
}
|
||||
|
||||
return new Path(parentDocumentId, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDocumentType(String documentId) throws FileNotFoundException {
|
||||
File file = new File(documentId);
|
||||
|
||||
if (!file.exists()) {
|
||||
throw new FileNotFoundException("Couldn't find file: " + file.getAbsolutePath());
|
||||
} else if (file.isDirectory()) {
|
||||
return Document.MIME_TYPE_DIR;
|
||||
} else if (file.isFile()) {
|
||||
return getMimeType(file.getAbsolutePath());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChildDocument(String parentDocumentId, String documentId) {
|
||||
return documentId.startsWith(parentDocumentId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String renameDocument(String documentId, String displayName) throws FileNotFoundException {
|
||||
File file = new File(documentId);
|
||||
|
||||
if (!file.exists()) {
|
||||
throw new FileNotFoundException("Couldn't find file: " + file.getAbsolutePath());
|
||||
}
|
||||
|
||||
File newPath = new File(file.getParentFile().getAbsolutePath() + "/" + displayName);
|
||||
|
||||
try {
|
||||
if (SDK_INT >= Build.VERSION_CODES.O) {
|
||||
Files.move(file.toPath(), newPath.toPath());
|
||||
} else {
|
||||
if (!file.renameTo(newPath)) {
|
||||
throw new IOException("Couldn't rename file: " + file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new FileNotFoundException(e.getMessage());
|
||||
}
|
||||
|
||||
|
||||
Uri uri = DocumentsContract.buildDocumentUri(BuildConfig.DOCUMENTS_AUTHORITY, file.getParent());
|
||||
|
||||
if (SDK_INT >= Build.VERSION_CODES.R) {
|
||||
getContext().getContentResolver().notifyChange(uri, null, ContentResolver.NOTIFY_UPDATE);
|
||||
} else {
|
||||
getContext().getContentResolver().notifyChange(uri, null);
|
||||
}
|
||||
|
||||
return newPath.getAbsolutePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeDocument(String documentId, String parentDocumentId) throws FileNotFoundException {
|
||||
deleteDocument(documentId);
|
||||
}
|
||||
|
||||
private static void deleteRecursive(File file) {
|
||||
if (file.isDirectory()) {
|
||||
File[] files = file.listFiles();
|
||||
if (files != null) {
|
||||
for (File f : files) {
|
||||
if (SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (!Files.isSymbolicLink(f.toPath())) {
|
||||
deleteRecursive(f);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
if (!f.getAbsolutePath().equals(f.getCanonicalPath())) {
|
||||
deleteRecursive(f);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
file.delete();
|
||||
}
|
||||
|
||||
|
||||
private static String getMimeType(String url) {
|
||||
String type = null;
|
||||
String extension = MimeTypeMap.getFileExtensionFromUrl(url.toLowerCase());
|
||||
|
||||
if (extension != null) {
|
||||
switch (extension) {
|
||||
case "pbm":
|
||||
type = "image/bmp";
|
||||
break;
|
||||
case "yml":
|
||||
type = "text/x-yaml";
|
||||
break;
|
||||
default:
|
||||
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == null) {
|
||||
type = "application/octet-stream";
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
private void pushFile(MatrixCursor result, File file) throws FileNotFoundException {
|
||||
if (!file.exists()) {
|
||||
throw new FileNotFoundException("Couldn't find file: " + file.getAbsolutePath());
|
||||
}
|
||||
|
||||
String mimeType = "application/octet-stream";
|
||||
int flags = 0;
|
||||
|
||||
if (file.isDirectory()) {
|
||||
mimeType = Document.MIME_TYPE_DIR;
|
||||
|
||||
if (file.canWrite()) {
|
||||
flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
|
||||
}
|
||||
} else if (file.isFile()) {
|
||||
mimeType = getMimeType(file.getAbsolutePath());
|
||||
|
||||
if (file.canWrite()) {
|
||||
flags |= Document.FLAG_SUPPORTS_WRITE;
|
||||
}
|
||||
}
|
||||
|
||||
if (file.getParentFile().canWrite()) {
|
||||
flags |= Document.FLAG_SUPPORTS_DELETE | Document.FLAG_SUPPORTS_RENAME;
|
||||
}
|
||||
|
||||
RowBuilder row = result.newRow();
|
||||
row.add(Document.COLUMN_DOCUMENT_ID, file.getAbsolutePath());
|
||||
row.add(Document.COLUMN_DISPLAY_NAME, file.getName());
|
||||
row.add(Document.COLUMN_SIZE, file.length());
|
||||
row.add(Document.COLUMN_LAST_MODIFIED, file.lastModified());
|
||||
row.add(Document.COLUMN_FLAGS, flags);
|
||||
row.add(Document.COLUMN_MIME_TYPE, mimeType);
|
||||
row.add(Document.COLUMN_ICON, R.mipmap.ic_launcher);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
package io.github.doukutsu_rs;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
public class DownloadActivity extends AppCompatActivity {
|
||||
private TextView txtProgress;
|
||||
private ProgressBar progressBar;
|
||||
private DownloadThread downloadThread;
|
||||
private String basePath;
|
||||
private Handler handler = new Handler();
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.activity_download);
|
||||
txtProgress = findViewById(R.id.txtProgress);
|
||||
progressBar = findViewById(R.id.progressBar);
|
||||
ActivityUtils.hideSystemBars(this);
|
||||
|
||||
basePath = getFilesDir().getAbsolutePath() + "/";
|
||||
|
||||
downloadThread = new DownloadThread();
|
||||
downloadThread.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
downloadThread.interrupt();
|
||||
}
|
||||
|
||||
private class DownloadThread extends Thread {
|
||||
private final ArrayList<DownloadEntry> urls = new ArrayList<>();
|
||||
|
||||
private final ArrayList<String> filesWhitelist = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
this.filesWhitelist.add("data/");
|
||||
this.filesWhitelist.add("Doukutsu.exe");
|
||||
|
||||
// DON'T SET `true` VALUE FOR TRANSLATIONS
|
||||
this.urls.add(new DownloadEntry(R.string.download_entries_base, "https://www.cavestory.org/downloads/cavestoryen.zip", true));
|
||||
|
||||
for (DownloadEntry entry : this.urls) {
|
||||
this.download(entry);
|
||||
}
|
||||
}
|
||||
|
||||
private void download(DownloadEntry downloadEntry) {
|
||||
HttpURLConnection connection = null;
|
||||
try {
|
||||
URL url = new URL(downloadEntry.url);
|
||||
connection = (HttpURLConnection) url.openConnection();
|
||||
connection.connect();
|
||||
|
||||
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
|
||||
throw new IllegalStateException(getString(R.string.download_status_error_http, connection.getResponseCode()));
|
||||
}
|
||||
|
||||
int fileLength = connection.getContentLength();
|
||||
if (fileLength == 0) {
|
||||
handler.post(() -> progressBar.setIndeterminate(true));
|
||||
}
|
||||
|
||||
byte[] zipFile;
|
||||
{
|
||||
InputStream input = new BufferedInputStream(connection.getInputStream());
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
|
||||
int downloadedLast = 0;
|
||||
int downloaded = 0;
|
||||
byte[] buffer = new byte[4096];
|
||||
int count;
|
||||
long last = System.currentTimeMillis();
|
||||
|
||||
while ((count = input.read(buffer)) != -1) {
|
||||
downloaded += count;
|
||||
|
||||
output.write(buffer, 0, count);
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
if (last + 1000 >= now) {
|
||||
int speed = (int) ((downloaded - downloadedLast) / 1024.0);
|
||||
String text = (fileLength > 0)
|
||||
? getString(R.string.download_status_downloading, downloadEntry.name, downloaded * 100 / fileLength, downloaded / 1024, fileLength / 1024, speed)
|
||||
: getString(R.string.download_status_downloading_null, downloadEntry.name, downloaded / 1024, speed);
|
||||
|
||||
handler.post(() -> txtProgress.setText(text));
|
||||
|
||||
downloadedLast = downloaded;
|
||||
last = now;
|
||||
}
|
||||
}
|
||||
|
||||
output.flush();
|
||||
zipFile = output.toByteArray();
|
||||
output.close();
|
||||
}
|
||||
|
||||
new File(basePath).mkdirs();
|
||||
this.unpack(zipFile, downloadEntry.isBase);
|
||||
|
||||
handler.post(() -> txtProgress.setText(getString(R.string.download_status_done)));
|
||||
|
||||
handler.post(() -> {
|
||||
Intent intent = new Intent(DownloadActivity.this, GameActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
startActivity(intent);
|
||||
DownloadActivity.this.finish();
|
||||
});
|
||||
} catch (Exception e) {
|
||||
handler.post(() -> {
|
||||
if (txtProgress != null)
|
||||
txtProgress.setText(e.getMessage());
|
||||
});
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (connection != null) connection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
private void unpack(byte[] zipFile, boolean isBase) throws IOException {
|
||||
ZipInputStream in = new ZipInputStream(new ByteArrayInputStream(zipFile));
|
||||
ZipEntry entry;
|
||||
byte[] buffer = new byte[4096];
|
||||
while ((entry = in.getNextEntry()) != null) {
|
||||
String entryName = entry.getName();
|
||||
|
||||
// strip prefix
|
||||
if (entryName.startsWith("CaveStory/")) {
|
||||
entryName = entryName.substring("CaveStory/".length());
|
||||
}
|
||||
|
||||
if (!this.entryInWhitelist(entryName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
final String s = entryName;
|
||||
handler.post(() -> txtProgress.setText(
|
||||
getString(R.string.download_status_unpacking, s)
|
||||
));
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
new File(basePath + entryName).mkdirs();
|
||||
} else {
|
||||
try (FileOutputStream fos = new FileOutputStream(basePath + entryName)) {
|
||||
int count;
|
||||
while ((count = in.read(buffer)) != -1) {
|
||||
fos.write(buffer, 0, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
in.closeEntry();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean entryInWhitelist(String entry) {
|
||||
for (String file : this.filesWhitelist) {
|
||||
if (entry.startsWith(file)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private class DownloadEntry {
|
||||
public String name; //e.g. "Polish translation", "Base data files"
|
||||
public String url;
|
||||
public boolean isBase = false;
|
||||
|
||||
DownloadEntry(String name, String url, boolean isBase) {
|
||||
this.name = name;
|
||||
this.url = url;
|
||||
this.isBase = isBase;
|
||||
}
|
||||
|
||||
DownloadEntry(int name, String url, boolean isBase) {
|
||||
this.name = getString(name);
|
||||
this.url = url;
|
||||
this.isBase = isBase;
|
||||
}
|
||||
}
|
||||
}
|
118
app/app/src/main/java/io/github/doukutsu_rs/GameActivity.java
Normal file
|
@ -0,0 +1,118 @@
|
|||
package io.github.doukutsu_rs;
|
||||
|
||||
import android.app.NativeActivity;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.hardware.SensorManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.provider.DocumentsContract;
|
||||
import android.view.OrientationEventListener;
|
||||
import android.view.WindowInsets;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
|
||||
public class GameActivity extends NativeActivity {
|
||||
private int[] displayInsets = new int[]{0, 0, 0, 0};
|
||||
private OrientationEventListener listener;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
ActivityUtils.hideSystemBars(this);
|
||||
|
||||
listener = new OrientationEventListener(this, SensorManager.SENSOR_DELAY_UI) {
|
||||
@Override
|
||||
public void onOrientationChanged(int orientation) {
|
||||
GameActivity.this.updateCutouts();
|
||||
}
|
||||
};
|
||||
|
||||
if (listener.canDetectOrientation()) {
|
||||
listener.enable();
|
||||
} else {
|
||||
listener = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
if (listener != null) {
|
||||
listener.disable();
|
||||
|
||||
listener = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
|
||||
this.updateCutouts();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
|
||||
this.updateCutouts();
|
||||
}
|
||||
|
||||
private void updateCutouts() {
|
||||
this.displayInsets[0] = 0;
|
||||
this.displayInsets[1] = 0;
|
||||
this.displayInsets[2] = 0;
|
||||
this.displayInsets[3] = 0;
|
||||
|
||||
WindowInsets insets = getWindow().getDecorView().getRootWindowInsets();
|
||||
|
||||
if (insets != null) {
|
||||
this.displayInsets[0] = Math.max(this.displayInsets[0], insets.getStableInsetLeft());
|
||||
this.displayInsets[1] = Math.max(this.displayInsets[1], insets.getStableInsetTop());
|
||||
this.displayInsets[2] = Math.max(this.displayInsets[2], insets.getStableInsetRight());
|
||||
this.displayInsets[3] = Math.max(this.displayInsets[3], insets.getStableInsetBottom());
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (SDK_INT >= Build.VERSION_CODES.P) {
|
||||
android.view.DisplayCutout cutout = insets.getDisplayCutout();
|
||||
|
||||
if (cutout != null) {
|
||||
this.displayInsets[0] = Math.max(this.displayInsets[0], cutout.getSafeInsetLeft());
|
||||
this.displayInsets[1] = Math.max(this.displayInsets[0], cutout.getSafeInsetTop());
|
||||
this.displayInsets[2] = Math.max(this.displayInsets[0], cutout.getSafeInsetRight());
|
||||
this.displayInsets[3] = Math.max(this.displayInsets[0], cutout.getSafeInsetBottom());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void openDir(String path) {
|
||||
Uri uri = DocumentsContract.buildDocumentUri(BuildConfig.DOCUMENTS_AUTHORITY, path);
|
||||
|
||||
File file = new File(path);
|
||||
if (!file.isDirectory()) {
|
||||
Toast.makeText(getApplicationContext(), R.string.dir_not_found, Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.addCategory(Intent.CATEGORY_DEFAULT);
|
||||
intent.setDataAndType(uri, DocumentsContract.Document.MIME_TYPE_DIR);
|
||||
intent.setFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
|
||||
try {
|
||||
startActivity(intent);
|
||||
} catch(ActivityNotFoundException e) {
|
||||
Toast.makeText(getApplicationContext(), R.string.no_app_found_to_open_dir, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package io.github.doukutsu_rs;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
ActivityUtils.hideSystemBars(this);
|
||||
|
||||
File f = new File(getFilesDir().getAbsolutePath() + "/data/");
|
||||
String[] list = f.list();
|
||||
if (!f.exists() || (list != null && list.length == 0)) {
|
||||
messageBox(getString(R.string.missing_data_title), getString(R.string.missing_data_desc), () -> {
|
||||
Intent intent = new Intent(this, DownloadActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
startActivity(intent);
|
||||
this.finish();
|
||||
}, this::launchGame);
|
||||
} else {
|
||||
launchGame();
|
||||
}
|
||||
}
|
||||
|
||||
private void launchGame() {
|
||||
Intent intent = new Intent(this, GameActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
startActivity(intent);
|
||||
this.finish();
|
||||
}
|
||||
|
||||
private void messageBox(String title, String message, Runnable yesCallback, Runnable noCallback) {
|
||||
this.runOnUiThread(() -> {
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(this);
|
||||
alert.setTitle(title);
|
||||
alert.setMessage(message);
|
||||
alert.setPositiveButton(android.R.string.yes, (dialog, whichButton) -> yesCallback.run());
|
||||
alert.setNegativeButton(android.R.string.no, (dialog, whichButton) -> noCallback.run());
|
||||
alert.setCancelable(false);
|
||||
alert.show();
|
||||
});
|
||||
}
|
||||
}
|
30
app/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
Normal file
|
@ -0,0 +1,30 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
10
app/app/src/main/res/drawable/ic_launcher_background.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="@color/ic_launcher_background"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
</vector>
|
43
app/app/src/main/res/layout/activity_download.xml
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".DownloadActivity">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:layout_marginStart="32dp"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/download_title"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Display1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtProgress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="..."
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
9
app/app/src/main/res/layout/activity_main.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
5
app/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
5
app/app/src/main/res/mipmap-anydpi-v26/icon_sue.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/icon_sue_background"/>
|
||||
<foreground android:drawable="@mipmap/icon_sue_foreground"/>
|
||||
</adaptive-icon>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/icon_sue_background"/>
|
||||
<foreground android:drawable="@mipmap/icon_sue_foreground"/>
|
||||
</adaptive-icon>
|
BIN
app/app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 6.6 KiB |
BIN
app/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
app/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
app/app/src/main/res/mipmap-hdpi/icon_sue.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
app/app/src/main/res/mipmap-hdpi/icon_sue_foreground.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
app/app/src/main/res/mipmap-hdpi/icon_sue_round.png
Normal file
After Width: | Height: | Size: 7.9 KiB |
BIN
app/app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
app/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 8.6 KiB |
BIN
app/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
app/app/src/main/res/mipmap-mdpi/icon_sue.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
app/app/src/main/res/mipmap-mdpi/icon_sue_foreground.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
BIN
app/app/src/main/res/mipmap-mdpi/icon_sue_round.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
app/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
app/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
app/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
app/app/src/main/res/mipmap-xhdpi/icon_sue.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
app/app/src/main/res/mipmap-xhdpi/icon_sue_foreground.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
app/app/src/main/res/mipmap-xhdpi/icon_sue_round.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
app/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
app/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
app/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
app/app/src/main/res/mipmap-xxhdpi/icon_sue.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
app/app/src/main/res/mipmap-xxhdpi/icon_sue_foreground.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
app/app/src/main/res/mipmap-xxhdpi/icon_sue_round.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
app/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
app/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 91 KiB |
BIN
app/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
app/app/src/main/res/mipmap-xxxhdpi/icon_sue.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
app/app/src/main/res/mipmap-xxxhdpi/icon_sue_foreground.png
Normal file
After Width: | Height: | Size: 61 KiB |
BIN
app/app/src/main/res/mipmap-xxxhdpi/icon_sue_round.png
Normal file
After Width: | Height: | Size: 34 KiB |
8
app/app/src/main/res/values-v27/themes.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="Theme.Doukutsurs" parent="@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen">
|
||||
<item name="android:windowLayoutInDisplayCutoutMode">
|
||||
shortEdges
|
||||
</item>
|
||||
</style>
|
||||
</resources>
|
10
app/app/src/main/res/values/colors.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="purple_200">#FFBB86FC</color>
|
||||
<color name="purple_500">#FF6200EE</color>
|
||||
<color name="purple_700">#FF3700B3</color>
|
||||
<color name="teal_200">#FF03DAC5</color>
|
||||
<color name="teal_700">#FF018786</color>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
</resources>
|
3
app/app/src/main/res/values/dimens.xml
Normal file
|
@ -0,0 +1,3 @@
|
|||
<resources>
|
||||
<dimen name="fab_margin">16dp</dimen>
|
||||
</resources>
|
5
app/app/src/main/res/values/ic_launcher_background.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#FD7F44</color>
|
||||
<color name="icon_sue_background">#FD7F44</color>
|
||||
</resources>
|
20
app/app/src/main/res/values/strings.xml
Normal file
|
@ -0,0 +1,20 @@
|
|||
<resources>
|
||||
<string name="app_description">A faithful and open-source remake of Cave Story engine written in Rust.</string>
|
||||
|
||||
<string name="missing_data_title">Missing data files</string>
|
||||
<string name="missing_data_desc">No data files found, would you like to download them?</string>
|
||||
|
||||
<string name="download_title">Downloading game data</string>
|
||||
<string name="download_status_error_http">Bad HTTP response code: %d</string>
|
||||
<!-- Downloading {entry_name}… {progress}% ({downloaded_size}/{total_size} KiB, {speed} KiB/s) -->
|
||||
<string name="download_status_downloading">Downloading %1$s… %2$d%% (%3$d/%4$d KiB, %5$d KiB/s)</string>
|
||||
<string name="download_status_downloading_null">Downloading %1$s… --%% (%2$d KiB, %3$d KiB/s)</string>
|
||||
<string name="download_status_unpacking">Unpacking: %s</string>
|
||||
<string name="download_status_done">Done!</string>
|
||||
|
||||
<!-- Look {entry_name} on 9th line -->
|
||||
<string name="download_entries_base">base game files</string>
|
||||
|
||||
<string name="dir_not_found">Dir not found</string>
|
||||
<string name="no_app_found_to_open_dir">No app found to open dir</string>
|
||||
</resources>
|
15
app/app/src/main/res/values/themes.xml
Normal file
|
@ -0,0 +1,15 @@
|
|||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.Doukutsurs" parent="@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen">
|
||||
|
||||
</style>
|
||||
|
||||
<style name="Theme.Doukutsurs.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Doukutsurs.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||
|
||||
<style name="Theme.Doukutsurs.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
||||
</resources>
|
28
app/build.gradle
Normal file
|
@ -0,0 +1,28 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
maven {
|
||||
url "https://plugins.gradle.org/m2/"
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath "com.android.tools.build:gradle:7.3.1"
|
||||
classpath "gradle.plugin.com.github.willir.rust:plugin:0.3.4"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
17
app/gradle.properties
Normal file
|
@ -0,0 +1,17 @@
|
|||
# Project-wide Gradle settings.
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||
# Android operating system, and which are packaged with your app"s APK
|
||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||
android.useAndroidX=true
|
BIN
app/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
6
app/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
#Wed Feb 17 23:16:31 CET 2021
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
172
app/gradlew
vendored
Executable file
|
@ -0,0 +1,172 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
84
app/gradlew.bat
vendored
Normal file
|
@ -0,0 +1,84 @@
|
|||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
2
app/settings.gradle
Normal file
|
@ -0,0 +1,2 @@
|
|||
rootProject.name = "doukutsu-rs"
|
||||
include ':app'
|
37
build.rs
Normal file
|
@ -0,0 +1,37 @@
|
|||
use std::env;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
extern crate winres;
|
||||
|
||||
fn main() {
|
||||
// let dest = PathBuf::from(&env::var("OUT_DIR").unwrap());
|
||||
let target = env::var("TARGET").unwrap_or_else(|e| panic!("{}", e));
|
||||
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
if target.contains("windows") {
|
||||
let mut res = winres::WindowsResource::new();
|
||||
res.set_icon("res/crabsue-icon.ico");
|
||||
res.compile().unwrap();
|
||||
|
||||
if target.contains("i686") {
|
||||
// hack
|
||||
println!("cargo:rustc-link-arg=/FORCE:MULTIPLE");
|
||||
println!("cargo:rustc-link-lib=shlwapi");
|
||||
}
|
||||
}
|
||||
|
||||
if target.contains("darwin") {
|
||||
println!("cargo:rustc-env=MACOSX_DEPLOYMENT_TARGET=10.15");
|
||||
println!("cargo:rustc-link-arg=-weak_framework");
|
||||
println!("cargo:rustc-link-arg=GameController");
|
||||
println!("cargo:rustc-link-arg=-weak_framework");
|
||||
println!("cargo:rustc-link-arg=CoreHaptics");
|
||||
}
|
||||
|
||||
if target.contains("android") {
|
||||
println!("cargo:rustc-link-lib=dylib=GLESv2");
|
||||
println!("cargo:rustc-link-lib=dylib=EGL");
|
||||
}
|
||||
}
|
2756
drsandroid/Cargo.lock
generated
Normal file
20
drsandroid/Cargo.toml
Normal file
|
@ -0,0 +1,20 @@
|
|||
[package]
|
||||
name = "drsandroid"
|
||||
description = "doukutsu-rs targeted for Android"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[profile.release]
|
||||
opt-level = 3
|
||||
lto = "off"
|
||||
codegen-units = 256
|
||||
incremental = true
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
ndk = "0.7"
|
||||
ndk-glue = "0.7"
|
||||
ndk-sys = "0.4"
|
||||
doukutsu-rs = { path = "../", default-features = false, features = ["default-base", "backend-glutin", "webbrowser"] }
|
11
drsandroid/src/lib.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
#[cfg(target_os = "android")]
|
||||
#[cfg_attr(target_os = "android", ndk_glue::main())]
|
||||
pub fn android_main() {
|
||||
let resource_dir = std::path::PathBuf::from(ndk_glue::native_activity().internal_data_path().to_string_lossy().to_string());
|
||||
|
||||
std::env::set_current_dir(&resource_dir).unwrap();
|
||||
|
||||
let options = doukutsu_rs::game::LaunchOptions::default();
|
||||
|
||||
doukutsu_rs::game::init(options).unwrap();
|
||||
}
|
9
drshorizon/.cargo/config
Normal file
|
@ -0,0 +1,9 @@
|
|||
[build]
|
||||
target = ["aarch64-nintendo-switch"]
|
||||
|
||||
[target.aarch64-nintendo-switch]
|
||||
cc = {path = "/opt/devkitpro/devkitA64/bin/aarch64-none-elf-gcc"}
|
||||
cxx = {path = "/opt/devkitpro/devkitA64/bin/aarch64-none-elf-g++"}
|
||||
ar = "/opt/devkitpro/devkitA64/bin/aarch64-none-elf-ar"
|
||||
ranlib = {path = "/opt/devkitpro/devkitA64/bin/aarch64-none-elf-ranlib"}
|
||||
linker = "/opt/devkitpro/devkitA64/bin/aarch64-none-elf-gcc"
|
1674
drshorizon/Cargo.lock
generated
Normal file
31
drshorizon/Cargo.toml
Normal file
|
@ -0,0 +1,31 @@
|
|||
[package]
|
||||
name = "drshorizon"
|
||||
description = "doukutsu-rs targeted for Nintendo Switch"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[profile.release]
|
||||
opt-level = 3
|
||||
codegen-units = 256
|
||||
incremental = true
|
||||
|
||||
[profile.dev]
|
||||
opt-level = 3
|
||||
lto = "off"
|
||||
overflow-checks = false
|
||||
codegen-units = 256
|
||||
incremental = true
|
||||
|
||||
[profile.dev.package."*"]
|
||||
opt-level = 3
|
||||
overflow-checks = false
|
||||
incremental = true
|
||||
|
||||
[profile.dev.package."doukutsu-rs"]
|
||||
opt-level = 3
|
||||
overflow-checks = false
|
||||
codegen-units = 256
|
||||
incremental = true
|
||||
|
||||
[dependencies]
|
||||
doukutsu-rs = { path = "../", default-features = false, features = ["default-base", "backend-horizon"] }
|
3
drshorizon/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
Experimental.
|
||||
|
||||
ld script and .specs taken from devkitPro
|
45
drshorizon/aarch64-nintendo-switch.json
Normal file
|
@ -0,0 +1,45 @@
|
|||
{
|
||||
"arch": "aarch64",
|
||||
"data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
|
||||
"dynamic-linking": true,
|
||||
"disable-redzone": true,
|
||||
"env": "newlib",
|
||||
"executables": true,
|
||||
"exe-suffix": ".elf",
|
||||
"features": "+a57,+strict-align,+crc,+crypto",
|
||||
"has-rpath": false,
|
||||
"has-thread-local": false,
|
||||
"linker": "/opt/devkitpro/devkitA64/bin/aarch64-none-elf-gcc",
|
||||
"linker-flavor": "gcc",
|
||||
"llvm-target": "aarch64-unknown-none",
|
||||
"max-atomic-width": 128,
|
||||
"no-default-libraries": false,
|
||||
"os": "horizon",
|
||||
"panic-strategy": "abort",
|
||||
"position-independent-executables": true,
|
||||
"pre-link-args": {
|
||||
"gcc": [
|
||||
"-fPIC",
|
||||
"-specs",
|
||||
"aarch64_nintendo_switch.specs",
|
||||
"-T",
|
||||
"aarch64_nintendo_switch.ld",
|
||||
"-L",
|
||||
"/opt/devkitpro/portlibs/switch/lib",
|
||||
"-L",
|
||||
"/opt/devkitpro/libnx/lib",
|
||||
"-I",
|
||||
"/opt/devkitpro/libnx/include"
|
||||
]
|
||||
},
|
||||
"relocation-model": "pic",
|
||||
"requires-uwtable": true,
|
||||
"target-c-int-width": "32",
|
||||
"target-endian": "little",
|
||||
"target-family": [
|
||||
"unix"
|
||||
],
|
||||
"target-pointer-width": "64",
|
||||
"trap-unreachable": true,
|
||||
"vendor": "nintendo"
|
||||
}
|
200
drshorizon/aarch64_nintendo_switch.ld
Normal file
|
@ -0,0 +1,200 @@
|
|||
OUTPUT_ARCH(aarch64)
|
||||
ENTRY(_start)
|
||||
|
||||
PHDRS
|
||||
{
|
||||
code PT_LOAD FLAGS(5) /* Read | Execute */;
|
||||
rodata PT_LOAD FLAGS(4) /* Read */;
|
||||
data PT_LOAD FLAGS(6) /* Read | Write */;
|
||||
dyn PT_DYNAMIC;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* =========== CODE section =========== */
|
||||
PROVIDE(__start__ = 0x0);
|
||||
. = __start__;
|
||||
__code_start = . ;
|
||||
|
||||
.text :
|
||||
{
|
||||
HIDDEN(__text_start = .);
|
||||
KEEP (*(.crt0))
|
||||
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||
*(.text.exit .text.exit.*)
|
||||
*(.text.startup .text.startup.*)
|
||||
*(.text.hot .text.hot.*)
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
. = ALIGN(8);
|
||||
} :code
|
||||
|
||||
.init :
|
||||
{
|
||||
KEEP( *(.init) )
|
||||
. = ALIGN(8);
|
||||
} :code
|
||||
|
||||
.plt :
|
||||
{
|
||||
*(.plt)
|
||||
*(.iplt)
|
||||
. = ALIGN(8);
|
||||
} :code
|
||||
|
||||
.fini :
|
||||
{
|
||||
KEEP( *(.fini) )
|
||||
. = ALIGN(8);
|
||||
} :code
|
||||
|
||||
/* =========== RODATA section =========== */
|
||||
. = ALIGN(0x1000);
|
||||
__rodata_start = . ;
|
||||
|
||||
.nx-module-name : { KEEP (*(.nx-module-name)) } :rodata
|
||||
|
||||
.rodata :
|
||||
{
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
. = ALIGN(8);
|
||||
} :rodata
|
||||
|
||||
.eh_frame_hdr : { __eh_frame_hdr_start = .; *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) __eh_frame_hdr_end = .; } :rodata
|
||||
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } :rodata
|
||||
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } :rodata
|
||||
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } : rodata
|
||||
|
||||
HIDDEN(__dynamic_start = .);
|
||||
.dynamic : { *(.dynamic) } :rodata :dyn
|
||||
.dynsym : { *(.dynsym) } :rodata
|
||||
.dynstr : { *(.dynstr) } :rodata
|
||||
.rela.dyn : { *(.rela.*) } :rodata
|
||||
.interp : { *(.interp) } :rodata
|
||||
.hash : { *(.hash) } :rodata
|
||||
.gnu.hash : { *(.gnu.hash) } :rodata
|
||||
.gnu.version : { *(.gnu.version) } :rodata
|
||||
.gnu.version_d : { *(.gnu.version_d) } :rodata
|
||||
.gnu.version_r : { *(.gnu.version_r) } :rodata
|
||||
.note.gnu.build-id : { *(.note.gnu.build-id) } :rodata
|
||||
|
||||
/* =========== DATA section =========== */
|
||||
. = ALIGN(0x1000);
|
||||
__data_start = . ;
|
||||
|
||||
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } :data
|
||||
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } :data
|
||||
.gnu_extab : ONLY_IF_RW { *(.gnu_extab*) } : data
|
||||
.exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } :data
|
||||
|
||||
.tdata ALIGN(8) :
|
||||
{
|
||||
__tdata_lma = .;
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
. = ALIGN(8);
|
||||
__tdata_lma_end = .;
|
||||
} :data
|
||||
|
||||
.tbss ALIGN(8) :
|
||||
{
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon)
|
||||
. = ALIGN(8);
|
||||
} :data
|
||||
|
||||
.preinit_array ALIGN(8) :
|
||||
{
|
||||
PROVIDE (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE (__preinit_array_end = .);
|
||||
} :data
|
||||
|
||||
.init_array ALIGN(8) :
|
||||
{
|
||||
PROVIDE (__init_array_start = .);
|
||||
KEEP( *(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)) )
|
||||
KEEP( *(.init_array .ctors) )
|
||||
PROVIDE (__init_array_end = .);
|
||||
} :data
|
||||
|
||||
.fini_array ALIGN(8) :
|
||||
{
|
||||
PROVIDE (__fini_array_start = .);
|
||||
KEEP( *(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)) )
|
||||
KEEP( *(.fini_array .dtors) )
|
||||
PROVIDE (__fini_array_end = .);
|
||||
} :data
|
||||
|
||||
__got_start__ = .;
|
||||
|
||||
.got : { *(.got) *(.igot) } :data
|
||||
.got.plt : { *(.got.plt) *(.igot.plt) } :data
|
||||
|
||||
__got_end__ = .;
|
||||
|
||||
.data ALIGN(8) :
|
||||
{
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
SORT(CONSTRUCTORS)
|
||||
} :data
|
||||
|
||||
__bss_start__ = .;
|
||||
.bss ALIGN(8) :
|
||||
{
|
||||
HIDDEN(__bss_start = .);
|
||||
*(.dynbss)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(8);
|
||||
|
||||
/* Reserve space for the TLS segment of the main thread */
|
||||
__tls_start = .;
|
||||
. += + SIZEOF(.tdata) + SIZEOF(.tbss);
|
||||
__tls_end = .;
|
||||
HIDDEN(__bss_end = .);
|
||||
} :data
|
||||
__bss_end__ = .;
|
||||
|
||||
__end__ = ABSOLUTE(.) ;
|
||||
|
||||
. = ALIGN(0x1000);
|
||||
__argdata__ = ABSOLUTE(.) ;
|
||||
|
||||
/* ==================
|
||||
==== Metadata ====
|
||||
================== */
|
||||
|
||||
/* Discard sections that difficult post-processing */
|
||||
/DISCARD/ : { *(.group .comment .note) }
|
||||
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
|
||||
/* DWARF debug sections.
|
||||
Symbols in the DWARF debugging sections are relative to the beginning
|
||||
of the section so we begin them at 0. */
|
||||
|
||||
/* DWARF 1 */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
|
||||
/* GNU DWARF 1 extensions */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
|
||||
/* DWARF 1.1 and DWARF 2 */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
|
||||
/* DWARF 2 */
|
||||
.debug_info 0 : { *(.debug_info) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
}
|
8
drshorizon/aarch64_nintendo_switch.specs
Normal file
|
@ -0,0 +1,8 @@
|
|||
%rename link old_link
|
||||
|
||||
*link:
|
||||
%(old_link) -pie --no-dynamic-linker --spare-dynamic-tags=0 -z text -z nodynamic-undefined-weak --build-id=sha1 --nx-module-name
|
||||
|
||||
*startfile:
|
||||
crti%O%s crtbegin%O%s --require-defined=main
|
||||
|
5
drshorizon/build.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
fn main() {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
|
||||
println!("cargo:rustc-link-lib=dylib=nx");
|
||||
}
|
33
drshorizon/build_debug.sh
Executable file
|
@ -0,0 +1,33 @@
|
|||
#!/bin/bash
|
||||
|
||||
cd "$(dirname "$0")" || exit
|
||||
set -e
|
||||
|
||||
DARK_GRAY=$(tput setaf 8)
|
||||
YELLOW=$(tput bold)$(tput setaf 3)
|
||||
RESET=$(tput sgr0)
|
||||
|
||||
function message() {
|
||||
echo "${DARK_GRAY}----${RESET} ${YELLOW}$*${RESET}"
|
||||
}
|
||||
|
||||
message "Compiling shaders..."
|
||||
uam -s vert -o ../src/framework/shaders/deko3d/vertex_basic.dksh ../src/framework/shaders/deko3d/vertex_basic.glsl
|
||||
uam -s frag -o ../src/framework/shaders/deko3d/fragment_textured.dksh ../src/framework/shaders/deko3d/fragment_textured.glsl
|
||||
uam -s frag -o ../src/framework/shaders/deko3d/fragment_color.dksh ../src/framework/shaders/deko3d/fragment_color.glsl
|
||||
|
||||
message "Building crate..."
|
||||
rustup run rust-switch cargo build -Z build-std=core,alloc,std,panic_abort --target aarch64-nintendo-switch.json
|
||||
|
||||
rm -f target/aarch64-nintendo-switch/debug/drshorizon.nro
|
||||
rm -f target/aarch64-nintendo-switch/debug/drshorizon.nacp
|
||||
|
||||
message "Creating NACP..."
|
||||
nacptool --create 'doukutsu-rs' 'doukutsu-rs contributors' '0.102.0' target/aarch64-nintendo-switch/debug/drshorizon.nacp
|
||||
|
||||
message "Running elf2nro..."
|
||||
elf2nro target/aarch64-nintendo-switch/debug/drshorizon.elf target/aarch64-nintendo-switch/debug/drshorizon.nro \
|
||||
--icon=../res/crabsue-icon.jpg \
|
||||
--nacp=target/aarch64-nintendo-switch/debug/drshorizon.nacp
|
||||
|
||||
message "done!"
|
33
drshorizon/build_release.sh
Executable file
|
@ -0,0 +1,33 @@
|
|||
#!/bin/bash
|
||||
|
||||
cd "$(dirname "$0")" || exit
|
||||
set -e
|
||||
|
||||
DARK_GRAY=$(tput setaf 8)
|
||||
YELLOW=$(tput bold)$(tput setaf 3)
|
||||
RESET=$(tput sgr0)
|
||||
|
||||
function message() {
|
||||
echo "${DARK_GRAY}----${RESET} ${YELLOW}$*${RESET}"
|
||||
}
|
||||
|
||||
message "Compiling shaders..."
|
||||
uam -s vert -o ../src/framework/shaders/deko3d/vertex_basic.dksh ../src/framework/shaders/deko3d/vertex_basic.glsl
|
||||
uam -s frag -o ../src/framework/shaders/deko3d/fragment_textured.dksh ../src/framework/shaders/deko3d/fragment_textured.glsl
|
||||
uam -s frag -o ../src/framework/shaders/deko3d/fragment_color.dksh ../src/framework/shaders/deko3d/fragment_color.glsl
|
||||
|
||||
message "Building crate..."
|
||||
rustup run rust-switch cargo build -Z build-std=core,alloc,std,panic_abort --target aarch64-nintendo-switch.json --release
|
||||
|
||||
rm -f target/aarch64-nintendo-switch/release/drshorizon.nro
|
||||
rm -f target/aarch64-nintendo-switch/release/drshorizon.nacp
|
||||
|
||||
message "Creating NACP..."
|
||||
nacptool --create 'doukutsu-rs' 'doukutsu-rs contributors' '0.102.0' target/aarch64-nintendo-switch/release/drshorizon.nacp
|
||||
|
||||
message "Running elf2nro..."
|
||||
elf2nro target/aarch64-nintendo-switch/release/drshorizon.elf target/aarch64-nintendo-switch/release/drshorizon.nro \
|
||||
--icon=../res/crabsue-icon.jpg \
|
||||
--nacp=target/aarch64-nintendo-switch/release/drshorizon.nacp
|
||||
|
||||
message "done!"
|
47
drshorizon/src/main.rs
Normal file
|
@ -0,0 +1,47 @@
|
|||
//#![feature(restricted_std)]
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PrintConsole {}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
pub enum ApmCpuBoostMode {
|
||||
Normal = 0,
|
||||
FastLoad = 1,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn consoleInit(unk: *mut PrintConsole) -> *mut PrintConsole;
|
||||
fn consoleUpdate(unk: *mut PrintConsole);
|
||||
|
||||
fn socketInitialize(unk: *const std::ffi::c_void) -> u32;
|
||||
fn nxlinkConnectToHost(redir_stdout: bool, redir_stderr: bool) -> i32;
|
||||
|
||||
fn appletSetCpuBoostMode(mode: ApmCpuBoostMode) -> u32;
|
||||
|
||||
static __text_start: u32;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
// if socketInitialize(std::ptr::null()) == 0 {
|
||||
// nxlinkConnectToHost(true, true);
|
||||
// }
|
||||
|
||||
// appletSetCpuBoostMode(ApmCpuBoostMode::FastLoad);
|
||||
|
||||
std::env::set_var("RUST_BACKTRACE", "full");
|
||||
|
||||
println!("__text_start = {:#x}", (&__text_start) as *const _ as usize);
|
||||
|
||||
let options = doukutsu_rs::game::LaunchOptions::default();
|
||||
let result = doukutsu_rs::game::init(options);
|
||||
|
||||
if let Err(e) = result {
|
||||
println!("Initialization error: {}", e);
|
||||
loop {
|
||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
51
drshorizon/symbolize.js
Normal file
|
@ -0,0 +1,51 @@
|
|||
// <reference types="node" />
|
||||
|
||||
const readline = require('readline');
|
||||
const childProcess = require('child_process');
|
||||
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
terminal: false
|
||||
});
|
||||
|
||||
let textStart = 0;
|
||||
const textStartRegex = /__text_start = 0x([0-9a-f]+)/i;
|
||||
let symbolize = false;
|
||||
|
||||
if (process.argv.length <= 2) {
|
||||
console.error('Usage: node symbolize.js <path to ELF file>');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const elfPath = process.argv[2];
|
||||
|
||||
rl.on('line', (line) => {
|
||||
if (textStart === 0) {
|
||||
const match = textStartRegex.exec(line);
|
||||
if (match) {
|
||||
textStart = parseInt(match[1], 16);
|
||||
}
|
||||
}
|
||||
|
||||
if (line.includes("stack backtrace:")) {
|
||||
symbolize = true;
|
||||
}
|
||||
|
||||
if (symbolize) {
|
||||
const match = /0x([0-9a-f]+) - \<unknown\>/.exec(line);
|
||||
if (match) {
|
||||
const addr = parseInt(match[1], 16);
|
||||
const relative = addr - textStart;
|
||||
// run addr2line on the address
|
||||
const addr2line = childProcess.spawnSync('addr2line', ['-e', elfPath, '-j', '.text', '-f', '-C', '0x' + relative.toString(16)]);
|
||||
if (addr2line.status === 0) {
|
||||
const output = addr2line.stdout.toString();
|
||||
const lines = output.split('\n');
|
||||
const [func, file] = lines;
|
||||
line = line.replace(match[0], `0x${addr.toString(16)} - ${func} (${file})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(line);
|
||||
});
|
113
misc/json-schemas/skinmeta.json
Normal file
|
@ -0,0 +1,113 @@
|
|||
{
|
||||
"$schema": "https://json-schema.org/draft/2019-09/schema",
|
||||
"title": "JSON schema for doukutsu-rs .dskinmeta files.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "Name of the skin.",
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "Optional description of the skin.",
|
||||
"type": "string"
|
||||
},
|
||||
"author": {
|
||||
"description": "Optional author of the skin.",
|
||||
"type": "string"
|
||||
},
|
||||
"gunOffsetX": {
|
||||
"description": "Weapon offset from center in X axis.",
|
||||
"type": "number",
|
||||
"minimum": -32768,
|
||||
"maximum": 32767
|
||||
},
|
||||
"gunOffsetY": {
|
||||
"description": "Weapon offset from center in Y axis.",
|
||||
"type": "number",
|
||||
"minimum": -32768,
|
||||
"maximum": 32767
|
||||
},
|
||||
"frameSizeWidth": {
|
||||
"description": "Width of skin animation frame.",
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 256
|
||||
},
|
||||
"frameSizeHeight": {
|
||||
"description": "Height of skin animation frame.",
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 256
|
||||
},
|
||||
"hitBox": {
|
||||
"description": "Hit box of the skin. A [front, up, back, down] tuple specifying offsets from center in pixels (as in 1/16 of vanilla tile size, 0x200 as internal fix9 number).",
|
||||
"type": "array",
|
||||
"minItems": 4,
|
||||
"maxItems": 4,
|
||||
"items": [
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 65535
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 65535
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 65535
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 65535
|
||||
}
|
||||
]
|
||||
},
|
||||
"displayBox": {
|
||||
"description": "Display box of the skin. A [front, up, back, down] tuple specifying offsets from center in pixels (as in 1/16 of vanilla tile size, 0x200 as internal fix9 number).",
|
||||
"type": "array",
|
||||
"minItems": 4,
|
||||
"maxItems": 4,
|
||||
"items": [
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 65535
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 65535
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 65535
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 65535
|
||||
}
|
||||
]
|
||||
},
|
||||
"custom": {
|
||||
"description": "This field contains an optional object, meant for storing additional metadata not covered by this specification. Any keys with names that are unrecognized by application which is currently parsing the file must be ignored. To avoid value conflicts, we suggest attaching a prefix to every custom key eg. \"d-rs__gun_hitbox\".",
|
||||
"type": "object"
|
||||
},
|
||||
"version": {
|
||||
"type": "number",
|
||||
"enum": [
|
||||
1
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"version"
|
||||
]
|
||||
}
|
33
misc/json-schemas/texture_sizes.json
Normal file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"$schema": "https://json-schema.org/draft/2019-09/schema",
|
||||
"title": "JSON schema for texture sizes",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"sizes": {
|
||||
"description": "List of textures and their sizes to prevent accidental scaling being applied",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^.*$": {
|
||||
"description": "Location and Width/Height of texture",
|
||||
"type": "array",
|
||||
"minItems": 2,
|
||||
"maxItems": 2,
|
||||
"items": [
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 65535
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 65535
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
1
misc/update-gamecontrollerdb.sh
Executable file
|
@ -0,0 +1 @@
|
|||
curl -o ./src/data/builtin/gamecontrollerdb.txt https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/master/gamecontrollerdb.txt
|
BIN
res/crabsue-icon.bmp
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
res/crabsue-icon.ico
Normal file
After Width: | Height: | Size: 219 KiB |
BIN
res/crabsue-icon.jpg
Normal file
After Width: | Height: | Size: 71 KiB |