Compare commits
5592 Commits
release_0_
...
master
Author | SHA1 | Date |
---|---|---|
![]() |
6f1a63fe89 | |
![]() |
25356b70f1 | |
![]() |
75766495f9 | |
![]() |
1091e69726 | |
![]() |
f6e0feb13e | |
![]() |
33754b706e | |
![]() |
50e39989f7 | |
![]() |
c73a7ffe53 | |
![]() |
e2379a66d6 | |
![]() |
5cd9d36bba | |
![]() |
b756ffb1e6 | |
![]() |
bec2329653 | |
![]() |
06bef8b560 | |
![]() |
dfcd482933 | |
![]() |
8a4fd0a9cb | |
![]() |
b022181a05 | |
![]() |
ee39a36f20 | |
![]() |
c1624b2b33 | |
![]() |
1192bf6f2c | |
![]() |
2c7fac57ff | |
![]() |
3b1989a9d9 | |
![]() |
f51e19b19b | |
![]() |
6f1d4e1d5c | |
![]() |
6690a8cedd | |
![]() |
7d6f0982c8 | |
![]() |
0ec9d74c39 | |
![]() |
76a6935dc8 | |
![]() |
3ddb2669a9 | |
![]() |
58bbe693e1 | |
![]() |
0a36e96f66 | |
![]() |
5d498a97c4 | |
![]() |
fff5659879 | |
![]() |
efdd938dc3 | |
![]() |
ff84815acb | |
![]() |
28f5c76035 | |
![]() |
7984eae357 | |
![]() |
2bc5b0d86b | |
![]() |
a0386e535c | |
![]() |
72315fa339 | |
![]() |
1cf7c37896 | |
![]() |
8fa0affab1 | |
![]() |
e7442cc999 | |
![]() |
fa1879f9a7 | |
![]() |
bb1b6a1c80 | |
![]() |
91196788eb | |
![]() |
8f9c6892d5 | |
![]() |
42667020d8 | |
![]() |
64132f765a | |
![]() |
00b8df1b00 | |
![]() |
f910c6197c | |
![]() |
f84a804499 | |
![]() |
8197174d69 | |
![]() |
3db6d5676c | |
![]() |
9bbfca527a | |
![]() |
04f97d5755 | |
![]() |
ea648f7110 | |
![]() |
c75c1ce2c3 | |
![]() |
2e01c0a840 | |
![]() |
b799d94762 | |
![]() |
176e38ce2f | |
![]() |
c5ab8a6ef6 | |
![]() |
de9fc5ab75 | |
![]() |
5baeb02754 | |
![]() |
d7dcc85d87 | |
![]() |
79f3f94099 | |
![]() |
9aa2ddfc88 | |
![]() |
4427b863ad | |
![]() |
15f5b169cc | |
![]() |
be51e41c04 | |
![]() |
46990f2d85 | |
![]() |
ca566eb11b | |
![]() |
0a78fa2a2b | |
![]() |
2f177d19a2 | |
![]() |
4c90c2d9ee | |
![]() |
d6532b9e91 | |
![]() |
d58c0e9331 | |
![]() |
e2a25e2412 | |
![]() |
f323dc464f | |
![]() |
8e77a8d9f1 | |
![]() |
5754425458 | |
![]() |
12ed7dd054 | |
![]() |
368cd49fb6 | |
![]() |
3ef927100b | |
![]() |
8b5ac56d66 | |
![]() |
60385bd099 | |
![]() |
811e1de45e | |
![]() |
3e650f2f73 | |
![]() |
0c7cb99d78 | |
![]() |
70fef83ded | |
![]() |
ff9231bb34 | |
![]() |
ab1d37a44f | |
![]() |
cc0b3ed00d | |
![]() |
80694cd966 | |
![]() |
586aea5310 | |
![]() |
4b0805e139 | |
![]() |
15a6e51739 | |
![]() |
de62116cc8 | |
![]() |
241ca96cf1 | |
![]() |
aaf88d9f14 | |
![]() |
d480f95d79 | |
![]() |
dd88556d53 | |
![]() |
00dd6fb97a | |
![]() |
bb3011c262 | |
![]() |
86a29d768a | |
![]() |
3a6f2f6dc5 | |
![]() |
0e88f9aa94 | |
![]() |
384854f6e7 | |
![]() |
7dbece1082 | |
![]() |
09090e93f9 | |
![]() |
c962c550e7 | |
![]() |
76fe5f758c | |
![]() |
ba56bbc7c2 | |
![]() |
3ec0b0c2e1 | |
![]() |
fc6ff8edbd | |
![]() |
fe0ae83c40 | |
![]() |
d4163a1893 | |
![]() |
086980deaf | |
![]() |
76bd1a5e35 | |
![]() |
6309a9c6a7 | |
![]() |
779606ec2f | |
![]() |
ffb8666a8f | |
![]() |
ff6c33a8d6 | |
![]() |
90d0abdae0 | |
![]() |
738298a9e8 | |
![]() |
4a53a30b91 | |
![]() |
9515af82b2 | |
![]() |
bae67e2d0c | |
![]() |
0a6eca6dce | |
![]() |
45738beb88 | |
![]() |
6508c2b115 | |
![]() |
f2cfd23ef2 | |
![]() |
b06537cf51 | |
![]() |
0b027d8cc0 | |
![]() |
8be30fe971 | |
![]() |
f3dee5d7ac | |
![]() |
0a34ef8e0b | |
![]() |
7a3b748d77 | |
![]() |
25cbcd255e | |
![]() |
3955480674 | |
![]() |
ca799e60b7 | |
![]() |
357ff8a2c5 | |
![]() |
402e9f0a31 | |
![]() |
41e3401765 | |
![]() |
751ab0255b | |
![]() |
6c5941689f | |
![]() |
35976edb5f | |
![]() |
586c7ee199 | |
![]() |
e3167110b2 | |
![]() |
4e6a7f0424 | |
![]() |
9bf090b309 | |
![]() |
d08a5dc56c | |
![]() |
6ee942ca5f | |
![]() |
0c90e8f4e3 | |
![]() |
50f02ae172 | |
![]() |
0fc3306bfc | |
![]() |
f240472f5e | |
![]() |
12347c7cd9 | |
![]() |
d00e6355da | |
![]() |
946f7df9bc | |
![]() |
4e7926eaa1 | |
![]() |
7fb5a5871b | |
![]() |
f48aee928c | |
![]() |
ba83b68b7f | |
![]() |
aeefd86f57 | |
![]() |
b468aee01a | |
![]() |
aa21454373 | |
![]() |
cedc1c9f38 | |
![]() |
8bba9dc955 | |
![]() |
5c805b2de0 | |
![]() |
7c2f281d25 | |
![]() |
941c2e39be | |
![]() |
1bde1c28ac | |
![]() |
3511e14ac6 | |
![]() |
3cefa5d78e | |
![]() |
fadd3b6e63 | |
![]() |
bf344e9a3e | |
![]() |
1dbbeba3a7 | |
![]() |
65ec088918 | |
![]() |
6b7559c71b | |
![]() |
c97ba8fb16 | |
![]() |
ab17945377 | |
![]() |
952585eaae | |
![]() |
be88a0b4c3 | |
![]() |
4e1ce23982 | |
![]() |
56251cafd1 | |
![]() |
111292ff15 | |
![]() |
90c8411cbf | |
![]() |
dcd1072800 | |
![]() |
1daebcd670 | |
![]() |
cda8cb5686 | |
![]() |
d9be9c6bf6 | |
![]() |
a7bdd1e3a9 | |
![]() |
fac70ce98b | |
![]() |
37683a708e | |
![]() |
7751b59882 | |
![]() |
e1969c470b | |
![]() |
5457932d75 | |
![]() |
cf75e26353 | |
![]() |
97848fce8c | |
![]() |
92d662cb71 | |
![]() |
86b990f68a | |
![]() |
4a95e9b8d1 | |
![]() |
d0d23cce7e | |
![]() |
5d6e8663c4 | |
![]() |
db365e849f | |
![]() |
79aa5b558e | |
![]() |
669f1b05f5 | |
![]() |
d03e4a6886 | |
![]() |
d0ed57d1b3 | |
![]() |
5831099ebc | |
![]() |
624f649acb | |
![]() |
a67e040a57 | |
![]() |
242cb63327 | |
![]() |
23400431a1 | |
![]() |
0e538b0931 | |
![]() |
d8ee3480df | |
![]() |
9554595948 | |
![]() |
628eb6596a | |
![]() |
cbbacdbf59 | |
![]() |
9273c9ab13 | |
![]() |
a3e84e28c2 | |
![]() |
5bcfd2f022 | |
![]() |
ef3f285f95 | |
![]() |
c9a4d9c4b8 | |
![]() |
5426509ede | |
![]() |
be287de623 | |
![]() |
9d2ddfa648 | |
![]() |
f0b0afe18b | |
![]() |
2b66e756da | |
![]() |
8438a5a647 | |
![]() |
29c077c165 | |
![]() |
91efef9346 | |
![]() |
b5b7f29255 | |
![]() |
739f3162d5 | |
![]() |
698139ed8e | |
![]() |
3a6c8cf9f8 | |
![]() |
3614b45a6c | |
![]() |
83396a88c0 | |
![]() |
35d7561fd7 | |
![]() |
5ab59eac86 | |
![]() |
f8a7723e86 | |
![]() |
f07cd5bae2 | |
![]() |
b7dadd1797 | |
![]() |
2664b03d93 | |
![]() |
b27b31c57d | |
![]() |
22fd8b231d | |
![]() |
16e7c126e2 | |
![]() |
a84a48dc75 | |
![]() |
d107562a16 | |
![]() |
677c6bb907 | |
![]() |
146a6ac655 | |
![]() |
640a1fdd93 | |
![]() |
d4afd4977c | |
![]() |
a95e4c57c6 | |
![]() |
24eb5ed95c | |
![]() |
a3499803ac | |
![]() |
1ccbf52246 | |
![]() |
09f7ab13c7 | |
![]() |
aa25e1dd54 | |
![]() |
589084ec74 | |
![]() |
41edf7be5e | |
![]() |
235d9efea7 | |
![]() |
b2c4d449ca | |
![]() |
6215418dc7 | |
![]() |
48f5a8289d | |
![]() |
b2ad722473 | |
![]() |
c68cc14f16 | |
![]() |
ba05516b7d | |
![]() |
416b08d6f7 | |
![]() |
bc85e0b165 | |
![]() |
b82c3d7bce | |
![]() |
3632142547 | |
![]() |
356fe47df7 | |
![]() |
d757d83b3d | |
![]() |
95b824b541 | |
![]() |
60714f6d22 | |
![]() |
d9479cd6d3 | |
![]() |
75230bfe0a | |
![]() |
aa2a5f2a34 | |
![]() |
08b6fade0b | |
![]() |
b66ac3b1db | |
![]() |
bfb693ff75 | |
![]() |
00684566dd | |
![]() |
c48583675b | |
![]() |
0193ba3b02 | |
![]() |
0140eceabd | |
![]() |
8940b33c9c | |
![]() |
669783439f | |
![]() |
f769f439dd | |
![]() |
76357662be | |
![]() |
0346f7b946 | |
![]() |
105a7f639d | |
![]() |
8c26417d49 | |
![]() |
204c58d81f | |
![]() |
0c568fd6ac | |
![]() |
a5860aae8e | |
![]() |
92aab4834b | |
![]() |
c904706a6b | |
![]() |
183dd57136 | |
![]() |
9f6ee8c55a | |
![]() |
1bbb065786 | |
![]() |
7cccf90976 | |
![]() |
07aefbd02c | |
![]() |
9ed9c0a9e4 | |
![]() |
b565073299 | |
![]() |
cdc1b5bc6d | |
![]() |
1fc64eb4fd | |
![]() |
5647303305 | |
![]() |
0f6cbffe77 | |
![]() |
6f8c085890 | |
![]() |
9a5596ce54 | |
![]() |
8fbced9c85 | |
![]() |
38634a7e5c | |
![]() |
d9c912d7fd | |
![]() |
25643e5f82 | |
![]() |
4976f57b0c | |
![]() |
069b26aa4c | |
![]() |
75e9697c5d | |
![]() |
9c3e206fed | |
![]() |
289c68fae8 | |
![]() |
3c04e8f4c7 | |
![]() |
e90ac6cc43 | |
![]() |
0a6aee6421 | |
![]() |
dce04f722f | |
![]() |
180df28ce7 | |
![]() |
6e26980d87 | |
![]() |
cc530c7a38 | |
![]() |
ccfd5a5a55 | |
![]() |
e2373bc5ff | |
![]() |
e25fd2e8c5 | |
![]() |
7239c6cfd6 | |
![]() |
0e42f772bc | |
![]() |
ba630ee278 | |
![]() |
a276d8c29c | |
![]() |
a72134539d | |
![]() |
ebc39eae64 | |
![]() |
908a53e85a | |
![]() |
88f2dfdb53 | |
![]() |
cfa75df069 | |
![]() |
2ab69da5e2 | |
![]() |
0b0bee78cc | |
![]() |
b1ee7e80d5 | |
![]() |
f12a70f4b7 | |
![]() |
2e95dda3f5 | |
![]() |
57dd000496 | |
![]() |
cd0cc31505 | |
![]() |
452c33405c | |
![]() |
4708404734 | |
![]() |
53dd630ea5 | |
![]() |
725ffb5127 | |
![]() |
ab38d17fea | |
![]() |
45a2f424e6 | |
![]() |
803c885ef2 | |
![]() |
d0d0f62d4d | |
![]() |
42da2645c1 | |
![]() |
864d419513 | |
![]() |
bd030db03f | |
![]() |
32461006d9 | |
![]() |
a758e3f0df | |
![]() |
84e98a0c49 | |
![]() |
680b3c16a3 | |
![]() |
9035c193c8 | |
![]() |
a73705bc50 | |
![]() |
02d8f0aa4d | |
![]() |
899ab48d78 | |
![]() |
965419d7ca | |
![]() |
2645a69005 | |
![]() |
efa72df171 | |
![]() |
2113af2994 | |
![]() |
7c90bc592f | |
![]() |
46a8c2385a | |
![]() |
8d1188f552 | |
![]() |
b608a62cd0 | |
![]() |
631f2a265e | |
![]() |
dec93fecfa | |
![]() |
970663bf71 | |
![]() |
53be5f6968 | |
![]() |
2e6b938378 | |
![]() |
e8de3db99c | |
![]() |
1490a19ad1 | |
![]() |
ed52d0e093 | |
![]() |
62f78f2f24 | |
![]() |
4df869c309 | |
![]() |
6833e3159d | |
![]() |
2efb260b44 | |
![]() |
7c036c1d50 | |
![]() |
31225d0ed1 | |
![]() |
28f12cf088 | |
![]() |
27a32d6262 | |
![]() |
42c59d9257 | |
![]() |
e8328eda33 | |
![]() |
c5c9e2d3a7 | |
![]() |
b1d49d14ec | |
![]() |
74cdfeea32 | |
![]() |
9ccc791e32 | |
![]() |
8a9fec431a | |
![]() |
7e85253ebb | |
![]() |
03be21608e | |
![]() |
1f377be17b | |
![]() |
a9706059e0 | |
![]() |
a677ffd168 | |
![]() |
8f20237c04 | |
![]() |
e9b3998fe8 | |
![]() |
407931288a | |
![]() |
b86a7748b1 | |
![]() |
1cec82613b | |
![]() |
599c981481 | |
![]() |
61036472b5 | |
![]() |
96b1150558 | |
![]() |
666c1ef455 | |
![]() |
95c44e389c | |
![]() |
b143ed6544 | |
![]() |
8fd322e817 | |
![]() |
bd9dcc558f | |
![]() |
0e83bd5000 | |
![]() |
9e0aed2267 | |
![]() |
f52eed131a | |
![]() |
5e48c9c44a | |
![]() |
b2c2e8f5ee | |
![]() |
1770d0a232 | |
![]() |
6f66e09d82 | |
![]() |
7e787700e7 | |
![]() |
258adbcfca | |
![]() |
747f369483 | |
![]() |
af06cc4aca | |
![]() |
81573818a9 | |
![]() |
8510948f6c | |
![]() |
3ba3821228 | |
![]() |
e344b4ce2a | |
![]() |
b4080b2cae | |
![]() |
f827be2e0f | |
![]() |
327dcd3d7b | |
![]() |
629724d865 | |
![]() |
6aa320aa0a | |
![]() |
9f19d681de | |
![]() |
0b4b58f3b4 | |
![]() |
9f82cea20b | |
![]() |
f000d1a9c0 | |
![]() |
d1d626f221 | |
![]() |
b1ffe0ae76 | |
![]() |
da75178fd6 | |
![]() |
2bd5f2804f | |
![]() |
c2d7a8a643 | |
![]() |
03e14584f6 | |
![]() |
54f3549108 | |
![]() |
f9393ab57c | |
![]() |
d5e9df3691 | |
![]() |
4cef851cbf | |
![]() |
83a3d30fa8 | |
![]() |
00ab686625 | |
![]() |
2468b1dbbe | |
![]() |
2153e53012 | |
![]() |
79abd40913 | |
![]() |
8461e2f08d | |
![]() |
021fcdd0de | |
![]() |
7db8f4fcd6 | |
![]() |
d3dee7ce9c | |
![]() |
65a280618b | |
![]() |
9f4e6992fb | |
![]() |
09506c9a19 | |
![]() |
9868c00fca | |
![]() |
90326ea1f9 | |
![]() |
b685818413 | |
![]() |
699f63d688 | |
![]() |
7e0336d57d | |
![]() |
d07bdedbd6 | |
![]() |
a2c6a789ad | |
![]() |
086112c4b5 | |
![]() |
43b00fb2a0 | |
![]() |
fe8c424c4a | |
![]() |
b8bed7082b | |
![]() |
339ea16b15 | |
![]() |
ed5ff51c0c | |
![]() |
d5693c54cf | |
![]() |
dbc1f06662 | |
![]() |
747f7b114b | |
![]() |
70a1727bd5 | |
![]() |
7fc2e4b6b6 | |
![]() |
2fb06cf4cc | |
![]() |
f42975aa4d | |
![]() |
db7bfdb185 | |
![]() |
b02dd3afaf | |
![]() |
173e2ae6e7 | |
![]() |
4afbb18eab | |
![]() |
d6e80e7864 | |
![]() |
e1cadfe112 | |
![]() |
77d38b15b1 | |
![]() |
004ec526aa | |
![]() |
4e96d07678 | |
![]() |
d626bad6bd | |
![]() |
4578728120 | |
![]() |
c082782fa9 | |
![]() |
7dd98ddb45 | |
![]() |
5b1eb55351 | |
![]() |
9ace87207d | |
![]() |
07aadb462e | |
![]() |
c6d35f9894 | |
![]() |
ff28ca6df5 | |
![]() |
4754987279 | |
![]() |
71ed1ca073 | |
![]() |
fffd574aae | |
![]() |
98a1c58db7 | |
![]() |
91b2e22894 | |
![]() |
db6e978276 | |
![]() |
19b081c8b8 | |
![]() |
d60684ce4d | |
![]() |
a948838c16 | |
![]() |
5057299fa5 | |
![]() |
7bac2ce759 | |
![]() |
8a610234c5 | |
![]() |
a5b25313f8 | |
![]() |
fffa7ebb8c | |
![]() |
ad64e73bb2 | |
![]() |
329eade565 | |
![]() |
bf71da494e | |
![]() |
3dabb10145 | |
![]() |
df18eda84f | |
![]() |
9f4f3ecf95 | |
![]() |
d9fabf6347 | |
![]() |
c0552cab6d | |
![]() |
506128760a | |
![]() |
9e79b1dcb3 | |
![]() |
8c4e42f98d | |
![]() |
f3c3228c70 | |
![]() |
037d3285a9 | |
![]() |
0db98725dc | |
![]() |
4226fa7ab2 | |
![]() |
207e93b8ae | |
![]() |
620d3b3a26 | |
![]() |
c49a480d51 | |
![]() |
92fcd1313e | |
![]() |
ef35f72172 | |
![]() |
192e0f88b2 | |
![]() |
777329a993 | |
![]() |
22801dac3c | |
![]() |
2b3a7a7e50 | |
![]() |
e775f17c87 | |
![]() |
ea02efda78 | |
![]() |
379af45813 | |
![]() |
7eabbb8ea6 | |
![]() |
0df858f2e8 | |
![]() |
67fa412144 | |
![]() |
cfe88ce0d7 | |
![]() |
3f47c4ad7d | |
![]() |
4a9c71b988 | |
![]() |
03b9481095 | |
![]() |
4f8ba2beb9 | |
![]() |
0d51b40479 | |
![]() |
3b06be0d07 | |
![]() |
479c404b60 | |
![]() |
63702ff6bd | |
![]() |
ac472c13ef | |
![]() |
9ac09387e3 | |
![]() |
b7c9b6b614 | |
![]() |
c7f85ba00a | |
![]() |
31851c2524 | |
![]() |
79437371e3 | |
![]() |
e991b16ec1 | |
![]() |
64cbba2e24 | |
![]() |
92cb90f433 | |
![]() |
e8f619c44a | |
![]() |
9d8332d671 | |
![]() |
42093b4929 | |
![]() |
4b77e9b77a | |
![]() |
84e8508520 | |
![]() |
85a2674eb5 | |
![]() |
445579b053 | |
![]() |
67f30f4023 | |
![]() |
8e7af8ada8 | |
![]() |
c135751ded | |
![]() |
37ed174621 | |
![]() |
1455b830c5 | |
![]() |
34b4fc3d72 | |
![]() |
600d159427 | |
![]() |
d3fda11a0e | |
![]() |
f62318ced4 | |
![]() |
6ef876b217 | |
![]() |
1809c0a17e | |
![]() |
6be61e4a42 | |
![]() |
3d198fcb9b | |
![]() |
4917d177cc | |
![]() |
f7bada2526 | |
![]() |
651cb53fbe | |
![]() |
b18e2058cb | |
![]() |
283f31cf87 | |
![]() |
7b3da44f5a | |
![]() |
c7426e24b7 | |
![]() |
10414b1f1d | |
![]() |
1f37dcc0a0 | |
![]() |
97d1613421 | |
![]() |
bb5849abec | |
![]() |
0942fb5c5b | |
![]() |
11fe823bbd | |
![]() |
7f035acdaa | |
![]() |
44282bc151 | |
![]() |
a04ebb8743 | |
![]() |
b873f898c0 | |
![]() |
21af401263 | |
![]() |
9836f56312 | |
![]() |
dbff32fdaa | |
![]() |
aeaf404177 | |
![]() |
ac507ebdc0 | |
![]() |
0e5dec143f | |
![]() |
b4b2781826 | |
![]() |
5e051a981d | |
![]() |
21276a5a07 | |
![]() |
b568fbc5dc | |
![]() |
02e49123da | |
![]() |
d503376558 | |
![]() |
50a24fbbd7 | |
![]() |
b138666bf6 | |
![]() |
e5a7fbe634 | |
![]() |
dc60f82ace | |
![]() |
4d86151839 | |
![]() |
baccf00674 | |
![]() |
eab1fb9583 | |
![]() |
6e35440436 | |
![]() |
91f6e4a9ef | |
![]() |
49fda66b3b | |
![]() |
48d0717f82 | |
![]() |
d319d2c6fb | |
![]() |
101fa1ef58 | |
![]() |
72386f28de | |
![]() |
a5f13edb7f | |
![]() |
c3ea512a0b | |
![]() |
02c0553977 | |
![]() |
87cb2f648f | |
![]() |
7de7d6c1c5 | |
![]() |
8708460666 | |
![]() |
19147a8457 | |
![]() |
7ec93bce63 | |
![]() |
25d7194779 | |
![]() |
a8e581dcf3 | |
![]() |
907cbf8308 | |
![]() |
7a7c1fbfc3 | |
![]() |
79515e978e | |
![]() |
b400093e3c | |
![]() |
0479afb877 | |
![]() |
df91fe9e00 | |
![]() |
cabb0eb327 | |
![]() |
cec553f4b9 | |
![]() |
64da66f37b | |
![]() |
0d65ea6050 | |
![]() |
d854909b04 | |
![]() |
cb49416952 | |
![]() |
e07e5e5db4 | |
![]() |
905de91c96 | |
![]() |
8aaabb9b05 | |
![]() |
59c2b8a990 | |
![]() |
626d5b4d36 | |
![]() |
0896b99b49 | |
![]() |
e38e98714e | |
![]() |
50abbbafa7 | |
![]() |
5552ef11c0 | |
![]() |
35c44285a8 | |
![]() |
ba92804d9f | |
![]() |
0abe38ce76 | |
![]() |
383e315b21 | |
![]() |
46c7e34439 | |
![]() |
2ac787a855 | |
![]() |
bfeff3fe66 | |
![]() |
3ecbb29863 | |
![]() |
5dd62b214b | |
![]() |
a1ea27d7f9 | |
![]() |
7435ffaefd | |
![]() |
5629855183 | |
![]() |
74cd070e61 | |
![]() |
ef0e3b3adf | |
![]() |
0c9a8a5282 | |
![]() |
3c32aeb0f5 | |
![]() |
ad9e7e8be1 | |
![]() |
2423a9bb5e | |
![]() |
96bc8977bd | |
![]() |
d680c4be51 | |
![]() |
13b5c0fd01 | |
![]() |
cc9d7a1450 | |
![]() |
c1efe4f475 | |
![]() |
eabfcb71be | |
![]() |
e4b07d2f4d | |
![]() |
5428763559 | |
![]() |
e70e065ffe | |
![]() |
917db3ecac | |
![]() |
4c53f62967 | |
![]() |
e808897c47 | |
![]() |
81f0ded5b6 | |
![]() |
89f5e50039 | |
![]() |
87c2377c6a | |
![]() |
cdbad3d05a | |
![]() |
3927aa4422 | |
![]() |
70733a55b4 | |
![]() |
6823aed6dd | |
![]() |
2a5150ff7d | |
![]() |
8e31ecd9c4 | |
![]() |
f6064006d2 | |
![]() |
79c6ab430a | |
![]() |
e654d1e7e9 | |
![]() |
7591028509 | |
![]() |
5bd5c630f1 | |
![]() |
316103d2ec | |
![]() |
5a368922c9 | |
![]() |
209dfca35f | |
![]() |
fc3d81e73a | |
![]() |
622b763bf1 | |
![]() |
ebf073e5c0 | |
![]() |
357843c543 | |
![]() |
3466c7f69a | |
![]() |
3ec927de75 | |
![]() |
f007ef655e | |
![]() |
255f5c8b91 | |
![]() |
4186c33745 | |
![]() |
1305dd1e49 | |
![]() |
a289055e1c | |
![]() |
76fafe0230 | |
![]() |
d4c17e5f8d | |
![]() |
1cc14031c9 | |
![]() |
a1791a24f0 | |
![]() |
d556c99771 | |
![]() |
55253504e3 | |
![]() |
2d1eee284c | |
![]() |
827af7a494 | |
![]() |
bf5065859b | |
![]() |
7fdf800b58 | |
![]() |
c52ee0386e | |
![]() |
5f76ba8bb3 | |
![]() |
600957a840 | |
![]() |
347a3aa833 | |
![]() |
d787b737e3 | |
![]() |
bca921ddae | |
![]() |
f814164de2 | |
![]() |
ce2c1a6774 | |
![]() |
25f7469920 | |
![]() |
7a3699aba6 | |
![]() |
3658f3c949 | |
![]() |
7df351850c | |
![]() |
0dc75ca089 | |
![]() |
46980d7732 | |
![]() |
9e6b4f128f | |
![]() |
b9317ad184 | |
![]() |
2185b6adfe | |
![]() |
07576fea31 | |
![]() |
1e0a29ee27 | |
![]() |
ac42f1d1bf | |
![]() |
de198c00a0 | |
![]() |
2d2320f4d1 | |
![]() |
8a826d4230 | |
![]() |
6cf9f1a98d | |
![]() |
79633495c4 | |
![]() |
85cb5b6c65 | |
![]() |
21df3059f4 | |
![]() |
6e5c9dbaf8 | |
![]() |
be7f22a7f9 | |
![]() |
cc9335eea6 | |
![]() |
851274b3e8 | |
![]() |
5c557440d7 | |
![]() |
463fc545b7 | |
![]() |
cc4446ab29 | |
![]() |
55c158d305 | |
![]() |
ce8275fca1 | |
![]() |
331cfa3596 | |
![]() |
96df0343f7 | |
![]() |
f0737b679f | |
![]() |
be2735b3c5 | |
![]() |
fe428fdda0 | |
![]() |
c6269ca7ff | |
![]() |
175a471e5e | |
![]() |
ac94244757 | |
![]() |
3dc7e6d70e | |
![]() |
aef0374ed8 | |
![]() |
065d9e4321 | |
![]() |
9805fe3de4 | |
![]() |
ec351f3015 | |
![]() |
72ecc8e66c | |
![]() |
ed92e1ef68 | |
![]() |
fe9541b448 | |
![]() |
8fa60fafd3 | |
![]() |
42817475c2 | |
![]() |
bb25742512 | |
![]() |
fa8cf5a6dc | |
![]() |
3c87d8b268 | |
![]() |
ee7d707acf | |
![]() |
ef3e93b4e9 | |
![]() |
fc4f12efd0 | |
![]() |
e433a6d80e | |
![]() |
242ccb26cf | |
![]() |
4f8b788e97 | |
![]() |
3e73a550e3 | |
![]() |
e4ec1d634a | |
![]() |
1c937adb9e | |
![]() |
e06d11f6df | |
![]() |
b8e85e0c9d | |
![]() |
4cd19ce522 | |
![]() |
bb93a0a365 | |
![]() |
d70bc19d9a | |
![]() |
ab3d48947a | |
![]() |
02cd950b02 | |
![]() |
0dab5917b6 | |
![]() |
d63ae63d1b | |
![]() |
c9db815171 | |
![]() |
7990e6c3f3 | |
![]() |
6ed5cf8420 | |
![]() |
3dc860b248 | |
![]() |
26504031ff | |
![]() |
0f045d430c | |
![]() |
9b1ce0efc3 | |
![]() |
066366184c | |
![]() |
f5d90a77c1 | |
![]() |
605ce35812 | |
![]() |
4a13a03f46 | |
![]() |
abc0649ad2 | |
![]() |
3890431154 | |
![]() |
0f87ada863 | |
![]() |
50f42fae55 | |
![]() |
85ee9e0ff9 | |
![]() |
40a4b3cdcf | |
![]() |
21a3fae0f3 | |
![]() |
f97c633441 | |
![]() |
39f9483034 | |
![]() |
4d6a132116 | |
![]() |
0c0bd5144e | |
![]() |
aeea0ea46a | |
![]() |
c1357c1451 | |
![]() |
062d9a65a7 | |
![]() |
022cf3c702 | |
![]() |
7bb438020b | |
![]() |
589524823b | |
![]() |
d3e4b6010c | |
![]() |
30212212b5 | |
![]() |
37afaefa2f | |
![]() |
7080e2156b | |
![]() |
ae8fb2c3bb | |
![]() |
88d930ce82 | |
![]() |
7ff5c5eece | |
![]() |
e6d6f2e10d | |
![]() |
2c6a5f9868 | |
![]() |
e604631413 | |
![]() |
8c2379f6f8 | |
![]() |
471f53e506 | |
![]() |
e56059872f | |
![]() |
b5477b608b | |
![]() |
a3eebbac21 | |
![]() |
35e834ff2c | |
![]() |
d80a84b762 | |
![]() |
9ea1b5cbda | |
![]() |
355e4a0fb4 | |
![]() |
3d573e150f | |
![]() |
df22c6e14d | |
![]() |
b9a8bafe8b | |
![]() |
fe93b70de8 | |
![]() |
157717a61f | |
![]() |
c3614a7e95 | |
![]() |
fb8d937239 | |
![]() |
37a8ca0983 | |
![]() |
6a1d9e4848 | |
![]() |
60c01bd63a | |
![]() |
9a53e8be69 | |
![]() |
2c5c2f6186 | |
![]() |
d0330fc96e | |
![]() |
3e37352bee | |
![]() |
6bcd19b3cb | |
![]() |
f6938dc80a | |
![]() |
8e9e7c4a2a | |
![]() |
6fc6ceb294 | |
![]() |
4f543aa8ca | |
![]() |
1f9b9e02a4 | |
![]() |
21f04c9ef2 | |
![]() |
b1abf50a01 | |
![]() |
a51a6d4b6d | |
![]() |
20547d38a2 | |
![]() |
7e4a270644 | |
![]() |
db1ca70f59 | |
![]() |
156c590ca4 | |
![]() |
54c6205e95 | |
![]() |
d410b5c195 | |
![]() |
30e9fb9c46 | |
![]() |
2f93fedbf8 | |
![]() |
f03a880ef9 | |
![]() |
adbbd406b1 | |
![]() |
6f8c060db6 | |
![]() |
1e18c3fb9f | |
![]() |
d81a75c867 | |
![]() |
be8d08ae87 | |
![]() |
91526e6324 | |
![]() |
71df3f4f28 | |
![]() |
e27cc87bdf | |
![]() |
5d85ac2e23 | |
![]() |
6eb1a79a71 | |
![]() |
7ae2d764b0 | |
![]() |
4affd3ca8a | |
![]() |
c8d534299f | |
![]() |
c8306de8d2 | |
![]() |
aecf153016 | |
![]() |
ef53eccb0e | |
![]() |
b6c69b031f | |
![]() |
36040e90a3 | |
![]() |
4705c3e59a | |
![]() |
c640e5c480 | |
![]() |
620048c43c | |
![]() |
9d05935696 | |
![]() |
1e9aa08f54 | |
![]() |
84e5228274 | |
![]() |
d8c0ca6f5b | |
![]() |
ad7b80ec87 | |
![]() |
56895a11aa | |
![]() |
8944328f80 | |
![]() |
44ac04df27 | |
![]() |
dab414c725 | |
![]() |
276e26c194 | |
![]() |
2000737593 | |
![]() |
1c36705fe3 | |
![]() |
26bfb66caf | |
![]() |
0beabec97c | |
![]() |
79687d3031 | |
![]() |
fb7dbca344 | |
![]() |
4735079c9a | |
![]() |
0f9f86fe61 | |
![]() |
4b28d272a7 | |
![]() |
c1eafc53f2 | |
![]() |
c3dbb920fa | |
![]() |
2e7099052d | |
![]() |
e2d60f62fd | |
![]() |
bb38022873 | |
![]() |
da3970d817 | |
![]() |
064527e24e | |
![]() |
3cc4a64b69 | |
![]() |
0965eef5b3 | |
![]() |
cfd77abaf7 | |
![]() |
65285aeb8c | |
![]() |
3fd42ae720 | |
![]() |
ff84420424 | |
![]() |
d85f140b64 | |
![]() |
0ef9543f87 | |
![]() |
5d3e53d804 | |
![]() |
68174fb31f | |
![]() |
acf49dfa01 | |
![]() |
94ddf1a467 | |
![]() |
a894000333 | |
![]() |
2dfc7866d0 | |
![]() |
bf3e1b1cf3 | |
![]() |
50755c6a45 | |
![]() |
68e91ec57f | |
![]() |
1010709de2 | |
![]() |
c65ec323ef | |
![]() |
d818155e8e | |
![]() |
faeced5c66 | |
![]() |
118b629728 | |
![]() |
c53f9632ed | |
![]() |
d045b9fa34 | |
![]() |
01225c65ee | |
![]() |
b9829ba349 | |
![]() |
8c6c2e8071 | |
![]() |
da714ea719 | |
![]() |
4e92d24b14 | |
![]() |
e3653b76ce | |
![]() |
7fda7997b2 | |
![]() |
f67154484f | |
![]() |
5ebc0ca21d | |
![]() |
af205cf582 | |
![]() |
c741f37c11 | |
![]() |
ad2dafe661 | |
![]() |
151b577cc0 | |
![]() |
43fcaf68f1 | |
![]() |
d6babce9b7 | |
![]() |
0406828da2 | |
![]() |
e6b3dfd5bd | |
![]() |
d9aa1ac31e | |
![]() |
a857e0e65c | |
![]() |
12c93232b9 | |
![]() |
1b10b39603 | |
![]() |
acb140209a | |
![]() |
7c80205a40 | |
![]() |
1767651b19 | |
![]() |
5bb4437720 | |
![]() |
1a34cfae5f | |
![]() |
0c6f18d5eb | |
![]() |
e09f269914 | |
![]() |
e828070d4d | |
![]() |
b8ebe973b9 | |
![]() |
35337a562a | |
![]() |
910661f982 | |
![]() |
39f473c590 | |
![]() |
3b310082dc | |
![]() |
0cb3bbe87d | |
![]() |
aaad5e63c5 | |
![]() |
e2d83f99fe | |
![]() |
524997e406 | |
![]() |
c9c6049892 | |
![]() |
407b01b39d | |
![]() |
4c5842d2aa | |
![]() |
2a7103ec0b | |
![]() |
e697391dfd | |
![]() |
484b062bf5 | |
![]() |
11e2448d1c | |
![]() |
3645ff4e77 | |
![]() |
80047bff91 | |
![]() |
4a844b2394 | |
![]() |
e83ec89578 | |
![]() |
bd299672a1 | |
![]() |
10dc63abca | |
![]() |
a5d843e361 | |
![]() |
491ee62754 | |
![]() |
c8ef38ad20 | |
![]() |
68d365c2f8 | |
![]() |
57bfbb1562 | |
![]() |
dee24cdbc1 | |
![]() |
bbb190a136 | |
![]() |
38b2039844 | |
![]() |
534cf2515b | |
![]() |
24cdbf0269 | |
![]() |
084a42a2f8 | |
![]() |
51303b9bc9 | |
![]() |
80cfb59c2c | |
![]() |
56477f0c5c | |
![]() |
811d9a3c18 | |
![]() |
5cc49fe417 | |
![]() |
48414b144d | |
![]() |
16ea99e78c | |
![]() |
b3a352a409 | |
![]() |
77e05eb1f8 | |
![]() |
0aa8dad199 | |
![]() |
5d384f9eae | |
![]() |
5c85bcd732 | |
![]() |
8fa3c6f9ed | |
![]() |
d671d0a888 | |
![]() |
43d79393c7 | |
![]() |
c4ea4ad879 | |
![]() |
c9b41e3c53 | |
![]() |
2c8909ed3c | |
![]() |
212f0a358f | |
![]() |
2890c4b075 | |
![]() |
17c30c48c5 | |
![]() |
89fc0a12e3 | |
![]() |
4c83ec19e9 | |
![]() |
4357ba8f47 | |
![]() |
6fa6467c5c | |
![]() |
7fa405b679 | |
![]() |
c9a405e959 | |
![]() |
9314fc2d5e | |
![]() |
208f99f4a6 | |
![]() |
8448b3ee10 | |
![]() |
775e3ae91a | |
![]() |
c9009c9302 | |
![]() |
36b97ada75 | |
![]() |
f2e43ca90b | |
![]() |
6797f00d23 | |
![]() |
5e67e9ca7c | |
![]() |
65901c77c0 | |
![]() |
36ee2477b1 | |
![]() |
c4317df76f | |
![]() |
637ad2ab18 | |
![]() |
ca6d8aaf73 | |
![]() |
07d75886bc | |
![]() |
ad7083ea98 | |
![]() |
fad678c2b3 | |
![]() |
cf5ed05cab | |
![]() |
259ca8579f | |
![]() |
09a545902d | |
![]() |
232e3d6f51 | |
![]() |
bee3fd30ce | |
![]() |
4913c0e7ae | |
![]() |
d7c347d3ae | |
![]() |
1e0e7f5e28 | |
![]() |
b0a6188902 | |
![]() |
cbd488e157 | |
![]() |
b6072287c5 | |
![]() |
fe851aa10c | |
![]() |
ad5f5c24e6 | |
![]() |
d869e6cb10 | |
![]() |
8cbdc339f2 | |
![]() |
9ccf9acea4 | |
![]() |
84e8057682 | |
![]() |
a4411086e0 | |
![]() |
842ed1b93c | |
![]() |
77c0b6e702 | |
![]() |
15957ba792 | |
![]() |
60aedec5d2 | |
![]() |
6fd23368ce | |
![]() |
43a9734ba2 | |
![]() |
d17a01d0c3 | |
![]() |
6fc7161f19 | |
![]() |
9dd7e0f451 | |
![]() |
dc41f09189 | |
![]() |
610caf0e45 | |
![]() |
5ad5e16a40 | |
![]() |
66062bca80 | |
![]() |
b95f58826e | |
![]() |
41104fd315 | |
![]() |
f79e24dba8 | |
![]() |
a17bafa652 | |
![]() |
9f7ed1aeeb | |
![]() |
1065666997 | |
![]() |
5496c8e024 | |
![]() |
5906d44c2d | |
![]() |
e4d5da97c0 | |
![]() |
cebbb262d1 | |
![]() |
696135d712 | |
![]() |
b976584451 | |
![]() |
dd8d4e6715 | |
![]() |
c64a556d82 | |
![]() |
35ddbb341d | |
![]() |
490c7e917c | |
![]() |
411bcaa15d | |
![]() |
7548294333 | |
![]() |
bd63ff1bd1 | |
![]() |
ee8fdebcf1 | |
![]() |
0e86cf128d | |
![]() |
23f4dcc009 | |
![]() |
a8fa8a44d6 | |
![]() |
35a2ca9721 | |
![]() |
8622a334a2 | |
![]() |
0f4b3ead00 | |
![]() |
022d24b5c2 | |
![]() |
932cdd6366 | |
![]() |
c024a78a43 | |
![]() |
9c128460c4 | |
![]() |
deffcaa075 | |
![]() |
24d941d02e | |
![]() |
ab3c221bf6 | |
![]() |
92924db136 | |
![]() |
42c0379cbb | |
![]() |
8d011f8344 | |
![]() |
8fb0d6ddc5 | |
![]() |
e825cddbe5 | |
![]() |
b8c006b0b5 | |
![]() |
8763a6169a | |
![]() |
db1a19ad86 | |
![]() |
cbe4717d2f | |
![]() |
c7ca122d95 | |
![]() |
c7bb41e4b1 | |
![]() |
5a61a08727 | |
![]() |
249afccfca | |
![]() |
c41a006b2a | |
![]() |
5fbaa53b46 | |
![]() |
43d3883986 | |
![]() |
ab18de05ef | |
![]() |
7509d469b9 | |
![]() |
9e3b694ace | |
![]() |
d1dcbb8218 | |
![]() |
9ee7cd8ec0 | |
![]() |
23be799a67 | |
![]() |
01c508f93a | |
![]() |
f9c32c9e79 | |
![]() |
2a58246eb5 | |
![]() |
b11bde4be4 | |
![]() |
f2f3680a7c | |
![]() |
4c01e66a8a | |
![]() |
d3b628af47 | |
![]() |
a65ceae98f | |
![]() |
1ea95cdde4 | |
![]() |
cd2f75e43a | |
![]() |
1e36b36bef | |
![]() |
cee6867bd8 | |
![]() |
bac10c7618 | |
![]() |
26ac91edd0 | |
![]() |
f9109568b8 | |
![]() |
39039f2396 | |
![]() |
b48666ea9c | |
![]() |
87335dd57a | |
![]() |
93d01f7bf5 | |
![]() |
66e8a95657 | |
![]() |
02a3b58edd | |
![]() |
c81df97a92 | |
![]() |
cd6fbcd5ea | |
![]() |
f0564cc4ac | |
![]() |
258ebfd6ea | |
![]() |
e18dd27d30 | |
![]() |
7213c6373b | |
![]() |
fa4b027dbd | |
![]() |
d5b62d3d02 | |
![]() |
010efff31b | |
![]() |
b9ada994df | |
![]() |
96bd35517b | |
![]() |
5890540007 | |
![]() |
4269925258 | |
![]() |
25eae6e1ed | |
![]() |
a7065311cc | |
![]() |
48fee8d590 | |
![]() |
24108e35e2 | |
![]() |
6680577146 | |
![]() |
e5694abd63 | |
![]() |
d0c0a5641a | |
![]() |
7202fb8d47 | |
![]() |
bc7b03c3d5 | |
![]() |
a481abebf9 | |
![]() |
d311517278 | |
![]() |
bfefaa7486 | |
![]() |
1373babe52 | |
![]() |
4457b95468 | |
![]() |
16948fe8bd | |
![]() |
6c4e951e68 | |
![]() |
63a5cb90ae | |
![]() |
0907207222 | |
![]() |
3b2a9ededc | |
![]() |
509d117f5f | |
![]() |
4abfa4466a | |
![]() |
128f9d0c96 | |
![]() |
b03a799834 | |
![]() |
109dd6f373 | |
![]() |
89a74e5c3e | |
![]() |
57f5fa0e6e | |
![]() |
d74ab529a7 | |
![]() |
0869afded6 | |
![]() |
3ca9e871e8 | |
![]() |
1be210271b | |
![]() |
4c950d2a37 | |
![]() |
8e16b618a7 | |
![]() |
858b05df79 | |
![]() |
2bc3be0711 | |
![]() |
d9394594bf | |
![]() |
97525d94d7 | |
![]() |
64d32dca0e | |
![]() |
70d6df40d6 | |
![]() |
45572fb277 | |
![]() |
711115921b | |
![]() |
15a19ba02f | |
![]() |
8be15113e2 | |
![]() |
43e740c661 | |
![]() |
f5ead86d89 | |
![]() |
e8e3200a23 | |
![]() |
ba6e8e0bab | |
![]() |
c31a5717ab | |
![]() |
7d2c70b7a8 | |
![]() |
649587fcb1 | |
![]() |
5c9fbdfb06 | |
![]() |
baef8b3fda | |
![]() |
73b5074313 | |
![]() |
9bfbaf23b8 | |
![]() |
5f0c4ecf52 | |
![]() |
8e94926072 | |
![]() |
47a71941ac | |
![]() |
2a1aaf727e | |
![]() |
c9025e81cb | |
![]() |
c6a5740665 | |
![]() |
e7d63e6cd2 | |
![]() |
f4c01c4b57 | |
![]() |
6ca2dbe6d0 | |
![]() |
addb17b660 | |
![]() |
ff4a3e0a5c | |
![]() |
a3a577f2e9 | |
![]() |
74ba49e168 | |
![]() |
174dcc11bb | |
![]() |
ecbcb3c821 | |
![]() |
3a000b68fd | |
![]() |
f5c9a36930 | |
![]() |
059ea519bc | |
![]() |
2c1360dec5 | |
![]() |
d37ef1ff95 | |
![]() |
70c69a46d3 | |
![]() |
1742114fcd | |
![]() |
f521ab1164 | |
![]() |
f8bbbec0ae | |
![]() |
4ea08792cb | |
![]() |
aa04c8f233 | |
![]() |
830dd0d78c | |
![]() |
1c59441697 | |
![]() |
c5cea732fa | |
![]() |
fda9fc2a89 | |
![]() |
8f2c85fe86 | |
![]() |
4957d7be5b | |
![]() |
759a039e25 | |
![]() |
d33faecd12 | |
![]() |
c94f353f2a | |
![]() |
d0f16193c5 | |
![]() |
cb4ecbe17e | |
![]() |
221fa5f72b | |
![]() |
17ff2b2d6e | |
![]() |
4cfa910e75 | |
![]() |
2b9bc2509a | |
![]() |
af22153f5c | |
![]() |
d1ac719b5c | |
![]() |
ccaefb18bc | |
![]() |
f67f959fe3 | |
![]() |
a86539eb1c | |
![]() |
b4650e4083 | |
![]() |
fd6ed7b518 | |
![]() |
db4982f4bc | |
![]() |
e29e825d27 | |
![]() |
abebaebdef | |
![]() |
3bf295f4ce | |
![]() |
1e9b179bf4 | |
![]() |
a05e03e2cc | |
![]() |
2379dc1e41 | |
![]() |
e58fb84707 | |
![]() |
e6d5a8fbe1 | |
![]() |
823e9edf7f | |
![]() |
11cf901336 | |
![]() |
e17e1bd0af | |
![]() |
c52b5702ed | |
![]() |
3a63db2086 | |
![]() |
2746427dd7 | |
![]() |
c7b9ecfc52 | |
![]() |
e4f935743c | |
![]() |
da6c79c6bd | |
![]() |
f02210bfdb | |
![]() |
a9f2e53c25 | |
![]() |
48f0f69929 | |
![]() |
c0a21a717d | |
![]() |
222f5d8507 | |
![]() |
bf120f3c3e | |
![]() |
51a9e2b0ab | |
![]() |
6acf7818ea | |
![]() |
3a11041ef0 | |
![]() |
7487bf2295 | |
![]() |
9a5e52a7fa | |
![]() |
623d490393 | |
![]() |
10d2776938 | |
![]() |
b9c6cd69a1 | |
![]() |
7dbe1444c3 | |
![]() |
8df7d15664 | |
![]() |
54f0e4b19b | |
![]() |
4fd39bac56 | |
![]() |
4e1bdab8c7 | |
![]() |
f377bfeb76 | |
![]() |
4473f5425d | |
![]() |
3b354a0096 | |
![]() |
d2b25360d5 | |
![]() |
eea54a753c | |
![]() |
f8ab45fc4b | |
![]() |
b442998635 | |
![]() |
5294ef1799 | |
![]() |
5aeed2112b | |
![]() |
87e52c334b | |
![]() |
1ff91b7841 | |
![]() |
600ae21668 | |
![]() |
fd5d882fe1 | |
![]() |
7a018eb9c6 | |
![]() |
aead3f4109 | |
![]() |
c0a2193290 | |
![]() |
4b8e7ceaef | |
![]() |
315320e0c1 | |
![]() |
368d785301 | |
![]() |
917475b9cd | |
![]() |
69f97b056a | |
![]() |
5deec25409 | |
![]() |
353dcef3ec | |
![]() |
ef4b203064 | |
![]() |
153b3ed61b | |
![]() |
d08dffd122 | |
![]() |
8c37d4acd6 | |
![]() |
1938dc2eed | |
![]() |
8600466498 | |
![]() |
d16785eba8 | |
![]() |
740fb66ca5 | |
![]() |
d2165f90fe | |
![]() |
5893dc78f3 | |
![]() |
1e5e47f75e | |
![]() |
db16f2f888 | |
![]() |
35e295e3dd | |
![]() |
679d5384e3 | |
![]() |
b96d2f01e1 | |
![]() |
062c0adef2 | |
![]() |
654537a4fb | |
![]() |
4ba36cbd1e | |
![]() |
5c983ede81 | |
![]() |
46c28635ef | |
![]() |
a7ec7c9581 | |
![]() |
71eb37f44e | |
![]() |
18f02cb7d3 | |
![]() |
918f45e7a4 | |
![]() |
6ced9e3942 | |
![]() |
e620b15d3c | |
![]() |
12a0c861a7 | |
![]() |
250de64ee5 | |
![]() |
301c875ecb | |
![]() |
1b483d266a | |
![]() |
624dd5788c | |
![]() |
80a4c3f071 | |
![]() |
5c6fcb0f47 | |
![]() |
c3bce87556 | |
![]() |
3b37058cbc | |
![]() |
e7f1737bdb | |
![]() |
ddac7122d3 | |
![]() |
7791f60495 | |
![]() |
68f201c3ce | |
![]() |
eaa5210fb0 | |
![]() |
0f05656a17 | |
![]() |
63b232c1b8 | |
![]() |
652af9ec71 | |
![]() |
1f60446f3f | |
![]() |
28f5c3a895 | |
![]() |
ee235d2abc | |
![]() |
c37e892090 | |
![]() |
76063a389c | |
![]() |
73c8f8af37 | |
![]() |
65bd5b565c | |
![]() |
d6872769ae | |
![]() |
50390c6f4f | |
![]() |
126db2d6de | |
![]() |
4707380746 | |
![]() |
a2527ef733 | |
![]() |
adf5151568 | |
![]() |
08e2244cea | |
![]() |
b460d76698 | |
![]() |
58b69b912a | |
![]() |
6b92b6fb2a | |
![]() |
ff2ebe400d | |
![]() |
e0945c362b | |
![]() |
09ffe3545e | |
![]() |
9357fd79e3 | |
![]() |
bc2e1d99d3 | |
![]() |
281268e05f | |
![]() |
6600a2c393 | |
![]() |
ebde061afe | |
![]() |
669515bf6e | |
![]() |
a0d42e1536 | |
![]() |
06f0bb492b | |
![]() |
751987cb90 | |
![]() |
fbad56bd14 | |
![]() |
297449caa2 | |
![]() |
c365617ff7 | |
![]() |
e332e3df26 | |
![]() |
abe2e61997 | |
![]() |
e7d7c08455 | |
![]() |
bc34bb457d | |
![]() |
d141d13705 | |
![]() |
5172e1c1f3 | |
![]() |
58b0adab4b | |
![]() |
8c1627b8c0 | |
![]() |
bb1f34c287 | |
![]() |
d82110e99b | |
![]() |
3b6a5168c2 | |
![]() |
27ffdf2ee9 | |
![]() |
199c9fb90d | |
![]() |
363424baaa | |
![]() |
e74ef8d0c5 | |
![]() |
e38246da31 | |
![]() |
5563d61f66 | |
![]() |
66b5da1cdc | |
![]() |
51163c33a1 | |
![]() |
3c48d83376 | |
![]() |
23c8955551 | |
![]() |
c1e5a56233 | |
![]() |
7c9abef399 | |
![]() |
859d47e7ff | |
![]() |
adf682eb23 | |
![]() |
9909f34a35 | |
![]() |
b5a4cf3bac | |
![]() |
1e96e738d2 | |
![]() |
5e06fbc547 | |
![]() |
8e18531784 | |
![]() |
cfae9c7674 | |
![]() |
99f68c8a51 | |
![]() |
be8530bc3d | |
![]() |
65c5cdd712 | |
![]() |
4fb55bddb9 | |
![]() |
8c8ba5e355 | |
![]() |
1f5ece6eeb | |
![]() |
2cb8ce2c4f | |
![]() |
68958a7a08 | |
![]() |
3b74861fc2 | |
![]() |
0f70654dab | |
![]() |
a2273b5eac | |
![]() |
c71da856f5 | |
![]() |
5335312704 | |
![]() |
e277fb2aed | |
![]() |
e02d134482 | |
![]() |
8dd7c9b924 | |
![]() |
7031bd9c0c | |
![]() |
093ce4b05d | |
![]() |
b553ff917b | |
![]() |
1cc22ae2aa | |
![]() |
fb2cfc4e9c | |
![]() |
60ae4c8de3 | |
![]() |
6cd42cbfe4 | |
![]() |
72fa455ca0 | |
![]() |
3799af3a01 | |
![]() |
ff2e6cb220 | |
![]() |
241f50ee7a | |
![]() |
00b5ff70d0 | |
![]() |
fc9b4831a0 | |
![]() |
a09763f8c3 | |
![]() |
d9a0c0ef00 | |
![]() |
6564827199 | |
![]() |
64d58b9b09 | |
![]() |
aff2d07146 | |
![]() |
08b8a1a62c | |
![]() |
fc3570a18a | |
![]() |
62f230ef44 | |
![]() |
53c4a27aef | |
![]() |
b9a9b8e7b2 | |
![]() |
3b0920d7f0 | |
![]() |
48bef75fd9 | |
![]() |
e79b37dcb4 | |
![]() |
c7af5cbe11 | |
![]() |
aa8069ce1a | |
![]() |
e487193545 | |
![]() |
8aa066dffc | |
![]() |
25c0232673 | |
![]() |
6756f41bdb | |
![]() |
d33f2f095c | |
![]() |
019a959702 | |
![]() |
125df2970e | |
![]() |
558cbf71d2 | |
![]() |
3af5423387 | |
![]() |
07a68dbb7a | |
![]() |
669487ff05 | |
![]() |
858d14b5fe | |
![]() |
ee306a9f07 | |
![]() |
522a4e25d1 | |
![]() |
9c573370f3 | |
![]() |
34656d977c | |
![]() |
91f2bb9ee5 | |
![]() |
a5b4df2038 | |
![]() |
f1558bf4e6 | |
![]() |
c7c472673f | |
![]() |
6eca2163f7 | |
![]() |
34df91f412 | |
![]() |
cffc343496 | |
![]() |
ce044f3700 | |
![]() |
616962f0b7 | |
![]() |
a6cb37901f | |
![]() |
eed334f999 | |
![]() |
ce494a2eaa | |
![]() |
207a3b2e9e | |
![]() |
cf8f021b30 | |
![]() |
c9d5d69c06 | |
![]() |
000efb1095 | |
![]() |
36e03fefa5 | |
![]() |
ae37e1259e | |
![]() |
1213deb102 | |
![]() |
4710cf7e37 | |
![]() |
8159da3f0c | |
![]() |
f50f9d38fd | |
![]() |
4e96cc8b6e | |
![]() |
fa971e3d63 | |
![]() |
922a7ac6f6 | |
![]() |
dfd23f6ba3 | |
![]() |
7b1350127d | |
![]() |
528513118a | |
![]() |
8fab80596b | |
![]() |
49309fb053 | |
![]() |
efcdd320f8 | |
![]() |
e6b352c73a | |
![]() |
a80fa6d4de | |
![]() |
ce4f61eaf6 | |
![]() |
0628cb5756 | |
![]() |
f230067524 | |
![]() |
de4f1c9c69 | |
![]() |
1cc8cb6fc6 | |
![]() |
5cfb407f35 | |
![]() |
1787081fca | |
![]() |
cf3758ff3f | |
![]() |
1b3825a100 | |
![]() |
60e71ce823 | |
![]() |
be11b35df9 | |
![]() |
36b192af00 | |
![]() |
7a573e75b5 | |
![]() |
6b78dc1f12 | |
![]() |
bcc7421be4 | |
![]() |
bdf580036c | |
![]() |
3b92f41b45 | |
![]() |
d2f054b5fb | |
![]() |
1d8bdd5b54 | |
![]() |
3498665e7b | |
![]() |
9564097182 | |
![]() |
7711f8288b | |
![]() |
af1a77e294 | |
![]() |
e767018e2a | |
![]() |
65d7568259 | |
![]() |
5f1e50db69 | |
![]() |
2f327c4af0 | |
![]() |
5d10b8022a | |
![]() |
444b1f67db | |
![]() |
c5678a6ba4 | |
![]() |
ac69f1e229 | |
![]() |
a0f8b7a894 | |
![]() |
8821e7b162 | |
![]() |
1368b2d5c7 | |
![]() |
032622e817 | |
![]() |
2698993805 | |
![]() |
3da9f273d2 | |
![]() |
6abf2b3454 | |
![]() |
9d6e52acac | |
![]() |
1c36704633 | |
![]() |
5b1a034aa9 | |
![]() |
1559f450fd | |
![]() |
6d1db6daae | |
![]() |
031f677486 | |
![]() |
b82f42dfde | |
![]() |
2f98c8b545 | |
![]() |
b57f2dec12 | |
![]() |
a8c8a8665b | |
![]() |
425ddecb8b | |
![]() |
9a613fb440 | |
![]() |
fb561adaad | |
![]() |
574815124a | |
![]() |
4a922b927d | |
![]() |
297721b73d | |
![]() |
3e10928bf5 | |
![]() |
0a4635eb5b | |
![]() |
41e9b1680e | |
![]() |
3612586e8b | |
![]() |
7f77037c75 | |
![]() |
2612484c54 | |
![]() |
183b41cb77 | |
![]() |
6744e162a8 | |
![]() |
ed40663b1f | |
![]() |
2144f44c67 | |
![]() |
e1d635c392 | |
![]() |
e2d9626be9 | |
![]() |
f97283e9bc | |
![]() |
1394197244 | |
![]() |
559b4ad077 | |
![]() |
81d1070d9a | |
![]() |
012b8d9e19 | |
![]() |
43d6e7f7e3 | |
![]() |
a8d04b5152 | |
![]() |
9f91a14b7f | |
![]() |
41d26c6bd7 | |
![]() |
ae64d4659b | |
![]() |
56083bcd1f | |
![]() |
57f26cb716 | |
![]() |
7a12d75529 | |
![]() |
23ae2f8a60 | |
![]() |
602da31591 | |
![]() |
b554b05b00 | |
![]() |
9d63abca3f | |
![]() |
8a23178d29 | |
![]() |
7fac2b6e11 | |
![]() |
5d52b7a0af | |
![]() |
2759834178 | |
![]() |
10b6b1e33a | |
![]() |
6c4aa4571d | |
![]() |
09879832b3 | |
![]() |
a5ab52c3fb | |
![]() |
b40ae5699c | |
![]() |
c61e44da34 | |
![]() |
1705b3eb21 | |
![]() |
84e5c98ef0 | |
![]() |
63feee1190 | |
![]() |
45d07d41de | |
![]() |
632a322be9 | |
![]() |
75c9c6f5d2 | |
![]() |
f54d68405f | |
![]() |
d1dfb067bf | |
![]() |
ff2536aa0f | |
![]() |
b646efdd55 | |
![]() |
ff3eb24e2a | |
![]() |
1303defe47 | |
![]() |
21ddbb95eb | |
![]() |
96143c293b | |
![]() |
9893afc59a | |
![]() |
be01a89164 | |
![]() |
cf185123eb | |
![]() |
aab3a7d0a6 | |
![]() |
a607264086 | |
![]() |
2d0852aaf9 | |
![]() |
3b0fc202b2 | |
![]() |
f8d129b164 | |
![]() |
629681b094 | |
![]() |
2a71c9c6fb | |
![]() |
833ac7b658 | |
![]() |
0e8265e911 | |
![]() |
6489452867 | |
![]() |
ac500c8249 | |
![]() |
02645310b4 | |
![]() |
c75b9ed62b | |
![]() |
2801ee5d19 | |
![]() |
6e0077ecb9 | |
![]() |
812cabb752 | |
![]() |
158f0c561b | |
![]() |
b0e649c9bb | |
![]() |
df60214b26 | |
![]() |
2c82d4b7b4 | |
![]() |
95db2317b9 | |
![]() |
318613e783 | |
![]() |
77918f13ee | |
![]() |
66613008f1 | |
![]() |
b9c33745c5 | |
![]() |
284119237e | |
![]() |
4af90cd902 | |
![]() |
b39f9ef9e4 | |
![]() |
59088e1ff8 | |
![]() |
14458da8f8 | |
![]() |
ebff84cd45 | |
![]() |
de91bcf369 | |
![]() |
df7f081cb5 | |
![]() |
8f6bfd2808 | |
![]() |
538442861b | |
![]() |
5d66422b94 | |
![]() |
386d9bad96 | |
![]() |
3ae591be7a | |
![]() |
212c23f30e | |
![]() |
66bc2d1d71 | |
![]() |
166365ab0d | |
![]() |
07e3612e4d | |
![]() |
a1a6c47aac | |
![]() |
fc77539bda | |
![]() |
ae92918d27 | |
![]() |
b4759f854c | |
![]() |
701bfdde80 | |
![]() |
a7a9371b3a | |
![]() |
5b2691b40e | |
![]() |
44b227d0b8 | |
![]() |
c5cae26246 | |
![]() |
84a007451a | |
![]() |
9c1f523a72 | |
![]() |
8c60f5fdf3 | |
![]() |
d8735a803b | |
![]() |
d837653b5f | |
![]() |
7abca69750 | |
![]() |
abbfa4a6b7 | |
![]() |
cc2c86cf11 | |
![]() |
d89fa0c761 | |
![]() |
17b7ebfa88 | |
![]() |
02a5944a20 | |
![]() |
a966765ae5 | |
![]() |
c7e3298b94 | |
![]() |
9ea82d913a | |
![]() |
e54a0eb3e4 | |
![]() |
cd7690730b | |
![]() |
2e2d02302b | |
![]() |
44ff1b077f | |
![]() |
b053c562d0 | |
![]() |
7dae5d2206 | |
![]() |
0ee96c0262 | |
![]() |
687ddb39c2 | |
![]() |
d6677ef42f | |
![]() |
2d143a9147 | |
![]() |
b5519378e7 | |
![]() |
cd07e14802 | |
![]() |
ebea960714 | |
![]() |
ab874d0d5e | |
![]() |
d243063c2c | |
![]() |
7d58eb9885 | |
![]() |
c5c9e14eb9 | |
![]() |
7ae811e5cf | |
![]() |
6530d35c3e | |
![]() |
3a11617bed | |
![]() |
fedef6c842 | |
![]() |
07c08f03d2 | |
![]() |
ae0023c5fd | |
![]() |
8454c93fa3 | |
![]() |
a39d104d1b | |
![]() |
11673c7a88 | |
![]() |
8e08a92b9d | |
![]() |
8be7dccdda | |
![]() |
3246953ca2 | |
![]() |
1f0ca239bb | |
![]() |
6c78aa0520 | |
![]() |
1b93208782 | |
![]() |
771ceee36b | |
![]() |
b129392683 | |
![]() |
68825ec961 | |
![]() |
cab3408049 | |
![]() |
d50c8f8e3e | |
![]() |
b314a49dee | |
![]() |
a815b1c458 | |
![]() |
2953799788 | |
![]() |
3c5461e786 | |
![]() |
9683b7e070 | |
![]() |
e6dac5ec96 | |
![]() |
a05ddab710 | |
![]() |
0d9d59455f | |
![]() |
a35edad4fc | |
![]() |
031f65fe83 | |
![]() |
bce02d9cc8 | |
![]() |
558e405511 | |
![]() |
8cfea593f8 | |
![]() |
425643bf92 | |
![]() |
edf1d305d4 | |
![]() |
d04c8eeae7 | |
![]() |
cdd5892c60 | |
![]() |
dde0da24ab | |
![]() |
3f895b85fb | |
![]() |
051e58a4fd | |
![]() |
314bb2130d | |
![]() |
0cb3bd723f | |
![]() |
4ae207fb03 | |
![]() |
03d8ee62aa | |
![]() |
4d2307538d | |
![]() |
d1a8663acb | |
![]() |
0110fe22d6 | |
![]() |
9e07cc95b4 | |
![]() |
29ff68cda9 | |
![]() |
0d162bdb9f | |
![]() |
f8e0585d26 | |
![]() |
b543e309c5 | |
![]() |
5d2b5054ba | |
![]() |
41d9061ce4 | |
![]() |
490e34f81e | |
![]() |
9a9f006397 | |
![]() |
ce5765006f | |
![]() |
d682d15142 | |
![]() |
b157132dbc | |
![]() |
d24883ee85 | |
![]() |
82904b4a74 | |
![]() |
9767f79346 | |
![]() |
9b33859c68 | |
![]() |
45b559eae6 | |
![]() |
afb63d0b2f | |
![]() |
13032f6712 | |
![]() |
caec37ef25 | |
![]() |
73f5067ebc | |
![]() |
b03347dc48 | |
![]() |
cd702e32f3 | |
![]() |
591f419ffe | |
![]() |
b0f4989230 | |
![]() |
3685c6e1f6 | |
![]() |
9a2bc94fc9 | |
![]() |
f036f26310 | |
![]() |
0ce1df58c5 | |
![]() |
549079cb95 | |
![]() |
aba30866b1 | |
![]() |
bf911bf571 | |
![]() |
f22f05959d | |
![]() |
660248816e | |
![]() |
fbb564db25 | |
![]() |
6e88f8e5dc | |
![]() |
7e43d12cc7 | |
![]() |
60ba992495 | |
![]() |
9766d2d8a6 | |
![]() |
8e7c58e11f | |
![]() |
f6d8a4a0c4 | |
![]() |
0a5f63c0f1 | |
![]() |
4a6ea70c94 | |
![]() |
08383c8195 | |
![]() |
cb2e219470 | |
![]() |
a0e0aed5a4 | |
![]() |
7f0c1276d4 | |
![]() |
655dd15cc1 | |
![]() |
6724231a2d | |
![]() |
708a2cfef5 | |
![]() |
a0ea0b258d | |
![]() |
0e346c62be | |
![]() |
60d5004d14 | |
![]() |
4d1374a675 | |
![]() |
3785435414 | |
![]() |
6851ff2737 | |
![]() |
86fe433eed | |
![]() |
a009d2ac13 | |
![]() |
2c127b73b0 | |
![]() |
c4d7e476c5 | |
![]() |
ac26660c86 | |
![]() |
da90bfec30 | |
![]() |
d8a6112049 | |
![]() |
fbf2b970a1 | |
![]() |
a0f207c66a | |
![]() |
c9ad78971c | |
![]() |
40d4d80c25 | |
![]() |
e0f8e5a82a | |
![]() |
9af7c039e4 | |
![]() |
07d9613295 | |
![]() |
344290283a | |
![]() |
e73e60cb02 | |
![]() |
a213a7aba7 | |
![]() |
485e2cc254 | |
![]() |
e0a139aeda | |
![]() |
7b84225fa4 | |
![]() |
4c9a50ae91 | |
![]() |
4f8a16d980 | |
![]() |
d4ff390287 | |
![]() |
86eff9d3f0 | |
![]() |
313dd2932f | |
![]() |
6b5aff79ad | |
![]() |
8a4813b6ff | |
![]() |
04e06869d9 | |
![]() |
34ec6bb985 | |
![]() |
2f473cd113 | |
![]() |
891fd01f82 | |
![]() |
c5f950d1aa | |
![]() |
dcb2c5fa05 | |
![]() |
ee5fcf6bd2 | |
![]() |
45f6ca71cc | |
![]() |
dc53f97d17 | |
![]() |
c98e669d74 | |
![]() |
782b60b824 | |
![]() |
3c710f33dd | |
![]() |
532f78740a | |
![]() |
8f01207e9d | |
![]() |
b849c5b1c3 | |
![]() |
d6ae36e068 | |
![]() |
9346ced34c | |
![]() |
07031ea621 | |
![]() |
f985f40ba8 | |
![]() |
607c3687ca | |
![]() |
86f84fa21c | |
![]() |
ef376a5426 | |
![]() |
549f754be2 | |
![]() |
e8f660b381 | |
![]() |
25f33c54ba | |
![]() |
a6ad4e04a8 | |
![]() |
fd4d3b19dd | |
![]() |
d565d07841 | |
![]() |
f553d50e97 | |
![]() |
65c0eec884 | |
![]() |
f68df5b976 | |
![]() |
ed1879dc8f | |
![]() |
ac07bc2639 | |
![]() |
a5c102540f | |
![]() |
f22fd97d28 | |
![]() |
fa898fcf76 | |
![]() |
2823f599ba | |
![]() |
7542718cde | |
![]() |
67989f5260 | |
![]() |
b695f1596f | |
![]() |
ea4d0960a0 | |
![]() |
0cb3bf1d2f | |
![]() |
3771d2a76d | |
![]() |
f1172fe5c8 | |
![]() |
90e9947da9 | |
![]() |
0ff9773eaf | |
![]() |
a1280789db | |
![]() |
76ba4e164d | |
![]() |
a4972abe61 | |
![]() |
abd4704711 | |
![]() |
69ee626639 | |
![]() |
bc84d6930b | |
![]() |
a738364416 | |
![]() |
4d32f051ab | |
![]() |
af00e3b3f3 | |
![]() |
dc3d1945af | |
![]() |
40fd9c2385 | |
![]() |
c40374df16 | |
![]() |
2fbd0685d1 | |
![]() |
bb6fe7d06b | |
![]() |
11403180db | |
![]() |
3c85700c5c | |
![]() |
3eb0585129 | |
![]() |
dd305b36d9 | |
![]() |
a6a1875e05 | |
![]() |
57929ed232 | |
![]() |
5b1a6e2cd9 | |
![]() |
9988ed1293 | |
![]() |
793f19d47e | |
![]() |
4eedbca3d9 | |
![]() |
21d9294697 | |
![]() |
d9cc320c4e | |
![]() |
1fc6cbdec2 | |
![]() |
18caac989b | |
![]() |
f05eb523c1 | |
![]() |
d885c383b2 | |
![]() |
f69a3738ae | |
![]() |
9cd43cc115 | |
![]() |
61e8cfb063 | |
![]() |
ec539cba02 | |
![]() |
3308d5b28e | |
![]() |
60ea6fe7d5 | |
![]() |
216d36d292 | |
![]() |
b0131342d4 | |
![]() |
15b6e7dbea | |
![]() |
6536230867 | |
![]() |
9f04d9076a | |
![]() |
f3fd4e2ebc | |
![]() |
9c5f355d00 | |
![]() |
d5cf747ce4 | |
![]() |
e4195c9277 | |
![]() |
0535b9f874 | |
![]() |
584c334c08 | |
![]() |
76ce2107fa | |
![]() |
574e6a2640 | |
![]() |
2336008f73 | |
![]() |
81d5f697c1 | |
![]() |
81dae68652 | |
![]() |
1bce1f1811 | |
![]() |
8441e6e833 | |
![]() |
fe97b5bbef | |
![]() |
444c4fcc0c | |
![]() |
c389bc7301 | |
![]() |
adc64a1c61 | |
![]() |
da132f1f1c | |
![]() |
f36f5b5627 | |
![]() |
8c00e2c676 | |
![]() |
601b86c78a | |
![]() |
386bbd6544 | |
![]() |
60f2d5d9cf | |
![]() |
74a13d55ff | |
![]() |
58732d31b4 | |
![]() |
5e8b836e83 | |
![]() |
20dc706c68 | |
![]() |
73d1a89d21 | |
![]() |
760b5a61d6 | |
![]() |
07e56b07c5 | |
![]() |
8038e559fe | |
![]() |
7e3f1d85ae | |
![]() |
ced0d3986d | |
![]() |
88006197b9 | |
![]() |
d5280f82b0 | |
![]() |
5a6590ff49 | |
![]() |
2967cd2c62 | |
![]() |
c36c379e1f | |
![]() |
e344486e8a | |
![]() |
e8cd47acf0 | |
![]() |
bccbae0df9 | |
![]() |
bf5b1505c8 | |
![]() |
7bc5aca100 | |
![]() |
be5615b477 | |
![]() |
5cfa2b4797 | |
![]() |
e1f7039f1b | |
![]() |
0fc37d2c06 | |
![]() |
76c390b17a | |
![]() |
8e3ff3c708 | |
![]() |
a30ca9e350 | |
![]() |
d9bb1f30e2 | |
![]() |
33d69b27f5 | |
![]() |
a7b62386a7 | |
![]() |
e0d2567e6c | |
![]() |
f06c81d671 | |
![]() |
761834948d | |
![]() |
96c47d6734 | |
![]() |
ee1a489dc7 | |
![]() |
8c68f22165 | |
![]() |
e41857fa82 | |
![]() |
e9d6cc3611 | |
![]() |
5a55349155 | |
![]() |
9b370cd602 | |
![]() |
3c9931b1c8 | |
![]() |
7daab3d784 | |
![]() |
47adbc5455 | |
![]() |
adae275e16 | |
![]() |
4a128f946c | |
![]() |
4d77617e3e | |
![]() |
04cbc13a6d | |
![]() |
a8ffd1e40c | |
![]() |
55516fc20e | |
![]() |
e53e289e77 | |
![]() |
fbda969347 | |
![]() |
611d0c9036 | |
![]() |
d1db3dd7ef | |
![]() |
3b332f3a12 | |
![]() |
d28e49dd2b | |
![]() |
54fc839208 | |
![]() |
d3ec1dedfb | |
![]() |
ccf2e76c32 | |
![]() |
c7cbf47472 | |
![]() |
e95c176f82 | |
![]() |
4f3990245d | |
![]() |
6673298c1e | |
![]() |
11a8221856 | |
![]() |
d2a0307431 | |
![]() |
70cb9375cc | |
![]() |
db06a04d73 | |
![]() |
12342e21cc | |
![]() |
1648b5f74d | |
![]() |
947adcd956 | |
![]() |
fec691bd26 | |
![]() |
afba637244 | |
![]() |
5215efe844 | |
![]() |
b41c194c10 | |
![]() |
28d40ffcf5 | |
![]() |
9d6f284681 | |
![]() |
dcbe28c94e | |
![]() |
c36b8cbebb | |
![]() |
0c0f968d01 | |
![]() |
f56e15da02 | |
![]() |
c5350f6247 | |
![]() |
e527ed1e37 | |
![]() |
6461b474bc | |
![]() |
42a1f7b9f5 | |
![]() |
d5bb6fd79e | |
![]() |
7dd90c9948 | |
![]() |
15f9d3ee6b | |
![]() |
80ac952e9e | |
![]() |
5c64a3858f | |
![]() |
8f38fb38e8 | |
![]() |
f48ed9fb89 | |
![]() |
d627a5b6aa | |
![]() |
e89544aa7b | |
![]() |
ecc22fb24d | |
![]() |
74dbe2efdd | |
![]() |
398cd31bf3 | |
![]() |
d652249c34 | |
![]() |
629da9c8e2 | |
![]() |
f66287d0e0 | |
![]() |
2ae84828e5 | |
![]() |
4fdcffa126 | |
![]() |
db5b63fc2e | |
![]() |
21fce2cab0 | |
![]() |
e0aa9eb56b | |
![]() |
66e314ec65 | |
![]() |
c767066858 | |
![]() |
7c7fd242c2 | |
![]() |
d1e7a1ba41 | |
![]() |
6ca691914e | |
![]() |
0b4fd3cb5e | |
![]() |
e526546bc0 | |
![]() |
4fe116b423 | |
![]() |
6af7350461 | |
![]() |
207c00df6b | |
![]() |
e973f53e52 | |
![]() |
95ba5d8a97 | |
![]() |
5bfe553a8b | |
![]() |
f6f1ba423a | |
![]() |
ccbf85ed42 | |
![]() |
d5565bad72 | |
![]() |
6697c7c0db | |
![]() |
c325eac5e3 | |
![]() |
3289a3aecc | |
![]() |
6fadb2c07f | |
![]() |
b79bd5fd33 | |
![]() |
0161ced7ff | |
![]() |
8a9295796d | |
![]() |
16bfa74d9f | |
![]() |
75bdce0942 | |
![]() |
e9b919d792 | |
![]() |
4031ee211a | |
![]() |
69ec85e624 | |
![]() |
9b2d36df0c | |
![]() |
2fc39e3c3e | |
![]() |
61df0246e6 | |
![]() |
3a747f85ce | |
![]() |
59d33fddb7 | |
![]() |
b253fc44a7 | |
![]() |
4db72d4254 | |
![]() |
f0e8760dc4 | |
![]() |
b906b233c5 | |
![]() |
3088fd581e | |
![]() |
1674170370 | |
![]() |
3331fb1890 | |
![]() |
bfe105a188 | |
![]() |
5bab1a14f3 | |
![]() |
0ac489ade1 | |
![]() |
d59ead2b51 | |
![]() |
60d0726a2a | |
![]() |
e3fdd8f7f2 | |
![]() |
2cee9a1eb9 | |
![]() |
af1c434727 | |
![]() |
76b9689bf2 | |
![]() |
e893c4eab5 | |
![]() |
fa4d2cb58f | |
![]() |
d0ec648952 | |
![]() |
381324ca09 | |
![]() |
64ea7591ab | |
![]() |
7d87434a21 | |
![]() |
df96846915 | |
![]() |
83578add74 | |
![]() |
06ece0cb07 | |
![]() |
634d1ba89b | |
![]() |
697c91d99a | |
![]() |
cfb408d63b | |
![]() |
5254d7143a | |
![]() |
d83b1a260c | |
![]() |
782447e115 | |
![]() |
afa4d57545 | |
![]() |
2ff7821e85 | |
![]() |
a8ef76f07b | |
![]() |
453baff89c | |
![]() |
baeb5313d2 | |
![]() |
f0bef635c2 | |
![]() |
928004e13e | |
![]() |
3abfa637b4 | |
![]() |
c233b1c14f | |
![]() |
1041fe8e3a | |
![]() |
9849a88269 | |
![]() |
81772f1906 | |
![]() |
d880c58f75 | |
![]() |
245586a978 | |
![]() |
6724ce53e3 | |
![]() |
e714ce9e20 | |
![]() |
0754569c17 | |
![]() |
9329a961f2 | |
![]() |
433d263b4e | |
![]() |
37ee317415 | |
![]() |
d0aeee71dd | |
![]() |
7b096b400f | |
![]() |
aef36c1949 | |
![]() |
acc22b29cb | |
![]() |
402434fe19 | |
![]() |
3e96459aea | |
![]() |
8fefb4fb7a | |
![]() |
d5ab656090 | |
![]() |
bf413dc443 | |
![]() |
9273aa58cd | |
![]() |
a987ce8ad2 | |
![]() |
c0a710fadb | |
![]() |
5b9061264b | |
![]() |
32d9abebbc | |
![]() |
b7273762fb | |
![]() |
64ce4799fd | |
![]() |
878649a0a8 | |
![]() |
f17312c91d | |
![]() |
fb2e4730e3 | |
![]() |
588744d323 | |
![]() |
16f9140960 | |
![]() |
66e6ba9497 | |
![]() |
dd13e33401 | |
![]() |
b781234576 | |
![]() |
6ab5ff5917 | |
![]() |
51e478e66a | |
![]() |
e24720f69d | |
![]() |
b95380054e | |
![]() |
204e9b46e5 | |
![]() |
bbc1517cc8 | |
![]() |
dabca07a9e | |
![]() |
0c54127f59 | |
![]() |
fca4afd7ce | |
![]() |
262fc4f14a | |
![]() |
fc6930c2e1 | |
![]() |
23955ff791 | |
![]() |
85c1c3c39d | |
![]() |
f4cf398962 | |
![]() |
03edf63c31 | |
![]() |
ce96c060f5 | |
![]() |
f02a1e83ee | |
![]() |
608b9b3986 | |
![]() |
ef212121bf | |
![]() |
a51fb22a40 | |
![]() |
2873d83de4 | |
![]() |
db358049b9 | |
![]() |
d16070ecb4 | |
![]() |
83ebb04cc2 | |
![]() |
f09b93c62a | |
![]() |
9fdb1d26bb | |
![]() |
73f44f0aeb | |
![]() |
dca852468c | |
![]() |
2b3198e392 | |
![]() |
5c3c1f14d9 | |
![]() |
84460eeb5a | |
![]() |
3f9de84fb1 | |
![]() |
8de0c23924 | |
![]() |
b7e996218b | |
![]() |
34b9cf1c0f | |
![]() |
560b23103c | |
![]() |
e23beb8630 | |
![]() |
4d50b396dd | |
![]() |
48f20e49f7 | |
![]() |
11ff936fa1 | |
![]() |
2ac5065fb4 | |
![]() |
037cf4e065 | |
![]() |
443cef56be | |
![]() |
6b8a1b979b | |
![]() |
12f5776a3f | |
![]() |
9295bb5f73 | |
![]() |
041941876d | |
![]() |
8b8e7b1648 | |
![]() |
2fe8cb330d | |
![]() |
4fec0a060e | |
![]() |
e9da2c318c | |
![]() |
4e5b6e6d6f | |
![]() |
fed37e55d3 | |
![]() |
ae36159259 | |
![]() |
513370ca21 | |
![]() |
823d99c73a | |
![]() |
76732a03ed | |
![]() |
f71fe6e108 | |
![]() |
6f91e947c3 | |
![]() |
a15e6cee10 | |
![]() |
98713caf4b | |
![]() |
def065be97 | |
![]() |
9d44ca55f6 | |
![]() |
9a642be896 | |
![]() |
d1c6c6e3ac | |
![]() |
cf109b69dd | |
![]() |
443b24cac2 | |
![]() |
fd3b89bac2 | |
![]() |
04d0faa240 | |
![]() |
249059e9c0 | |
![]() |
2a85d684eb | |
![]() |
f2cd7ad4b0 | |
![]() |
74b7993d1a | |
![]() |
675e3424b3 | |
![]() |
895be3efec | |
![]() |
0bcf4eaf59 | |
![]() |
73bc032c1c | |
![]() |
c76469cbc1 | |
![]() |
875ae2cc4b | |
![]() |
2c3db349c3 | |
![]() |
9f6f8c1cfd | |
![]() |
8e3198436b | |
![]() |
491a978f31 | |
![]() |
7fa5f7763e | |
![]() |
71c196b920 | |
![]() |
47b2b6eac6 | |
![]() |
db94b7c8a6 | |
![]() |
088495f0cd | |
![]() |
0c99529409 | |
![]() |
0983a34bd4 | |
![]() |
c88a2071a7 | |
![]() |
b93e53ac1a | |
![]() |
0ec2b21a20 | |
![]() |
ac146b26d2 | |
![]() |
e568f8c4fd | |
![]() |
38f02e0804 | |
![]() |
2b633d1cb3 | |
![]() |
dd09eb888d | |
![]() |
c95eba3901 | |
![]() |
c7c3662ed2 | |
![]() |
c2a4da43c3 | |
![]() |
76f83f2bf6 | |
![]() |
995459dc92 | |
![]() |
bc7e3bf00f | |
![]() |
a8d01255ed | |
![]() |
0445bcc9ee | |
![]() |
f94727dc1e | |
![]() |
acaa4e85d2 | |
![]() |
074c9881ae | |
![]() |
fd55e1af4d | |
![]() |
fcccf48307 | |
![]() |
6caeb38edc | |
![]() |
da4b6487e2 | |
![]() |
82f9342a5b | |
![]() |
72c34257a6 | |
![]() |
c8586c1241 | |
![]() |
285c4d567f | |
![]() |
4c8e70acd9 | |
![]() |
702879c848 | |
![]() |
d2ed4ca30e | |
![]() |
912355488e | |
![]() |
0191b680c4 | |
![]() |
dba7e21423 | |
![]() |
f9eb416311 | |
![]() |
02701e48d9 | |
![]() |
cc13d8f6d4 | |
![]() |
dbcbeedd8a | |
![]() |
ddf957fcf7 | |
![]() |
f9f6a74a72 | |
![]() |
3b0797a21d | |
![]() |
fc733b695f | |
![]() |
432a56ec95 | |
![]() |
ea6ad164db | |
![]() |
7b48e7f650 | |
![]() |
0fbe77a9a8 | |
![]() |
9815ef3cab | |
![]() |
5e5e56df87 | |
![]() |
eee29ace05 | |
![]() |
0e9766f096 | |
![]() |
50dbb2aee5 | |
![]() |
a8b27aeb66 | |
![]() |
d6db1f7e96 | |
![]() |
3d8f138874 | |
![]() |
5e3aae6b9f | |
![]() |
6db2459178 | |
![]() |
3c03def68f | |
![]() |
3a88139f99 | |
![]() |
e52511502e | |
![]() |
b85d168f9a | |
![]() |
e5eb8918d4 | |
![]() |
5f44858edd | |
![]() |
e05ef815ce | |
![]() |
bdd4f2e3f5 | |
![]() |
1fa0886fe7 | |
![]() |
9e45290c47 | |
![]() |
63406703aa | |
![]() |
b3586a0a98 | |
![]() |
b05fe32a44 | |
![]() |
ebfe8a312c | |
![]() |
c6d959ea53 | |
![]() |
b5f78e2652 | |
![]() |
88e34db3e7 | |
![]() |
6cdd10b84a | |
![]() |
2db8779e08 | |
![]() |
7e176d1998 | |
![]() |
59d8d798ef | |
![]() |
5b6d16da87 | |
![]() |
1c49c3daf5 | |
![]() |
3233bf9c86 | |
![]() |
31d2679e07 | |
![]() |
a61e91a078 | |
![]() |
ed85c3df12 | |
![]() |
429afd87f6 | |
![]() |
2f094cf11d | |
![]() |
f838938887 | |
![]() |
6ea032a191 | |
![]() |
3ee1fe0d4b | |
![]() |
b4e1286dd3 | |
![]() |
a57bf33472 | |
![]() |
b4c243fade | |
![]() |
3cd1e909fc | |
![]() |
94aac3fccd | |
![]() |
69f5f165e2 | |
![]() |
ec07d6bd55 | |
![]() |
e5b34983a9 | |
![]() |
61124f6551 | |
![]() |
2d93fc7901 | |
![]() |
41fe58e0f8 | |
![]() |
08c66df12b | |
![]() |
0cc53ad207 | |
![]() |
40b58be6ba | |
![]() |
4c50354b0e | |
![]() |
95d32bc4d2 | |
![]() |
4700d63db8 | |
![]() |
742bc11da3 | |
![]() |
0fdac4d989 | |
![]() |
5d671b8b92 | |
![]() |
b4765567ad | |
![]() |
caf8d336e7 | |
![]() |
dae13c04b1 | |
![]() |
44051ee09f | |
![]() |
589960f91b | |
![]() |
79cd1fc354 | |
![]() |
4d79e39f36 | |
![]() |
cb5e9df984 | |
![]() |
c2e9dbb126 | |
![]() |
8d4390bace | |
![]() |
11be795869 | |
![]() |
b41dd28132 | |
![]() |
e2f2bf6bb3 | |
![]() |
da29c3f483 | |
![]() |
7f88812fa9 | |
![]() |
5faea57f2c | |
![]() |
8c2fb6e44e | |
![]() |
5f1d7492cc | |
![]() |
7f8d2e4028 | |
![]() |
b2b3a14b63 | |
![]() |
79e97e339e | |
![]() |
7c62880b00 | |
![]() |
4de7a417a9 | |
![]() |
981dac038f | |
![]() |
e692e05e94 | |
![]() |
8edec83002 | |
![]() |
76de7fc3ec | |
![]() |
cc923dc444 | |
![]() |
b782e366e2 | |
![]() |
c9507d2e8e | |
![]() |
3384b93c4a | |
![]() |
4ce78d5e49 | |
![]() |
68525db6d9 | |
![]() |
f9b4229fd5 | |
![]() |
de36370a91 | |
![]() |
338077614a | |
![]() |
3dc14e59da | |
![]() |
22f814672d | |
![]() |
80547ca877 | |
![]() |
4cb1a99474 | |
![]() |
bf58a880d1 | |
![]() |
0d8fc520c4 | |
![]() |
35706cbd97 | |
![]() |
4033c0e470 | |
![]() |
960a9774e3 | |
![]() |
d0e44dbaf3 | |
![]() |
fd424a1e3a | |
![]() |
f8778ef3f2 | |
![]() |
09ea476892 | |
![]() |
b947fb3563 | |
![]() |
3acf4eb496 | |
![]() |
7b78be0382 | |
![]() |
6b8b766211 | |
![]() |
927189550a | |
![]() |
c33a11ac03 | |
![]() |
39f1b7260e | |
![]() |
bc79ca81c6 | |
![]() |
20c2810f85 | |
![]() |
04761fed6c | |
![]() |
624252bf05 | |
![]() |
36ae91938b | |
![]() |
07d60c9da1 | |
![]() |
274907e9b2 | |
![]() |
31697c68f8 | |
![]() |
eb1f462016 | |
![]() |
81c063bec9 | |
![]() |
d221b1d3d5 | |
![]() |
5ea6410107 | |
![]() |
188c53d46c | |
![]() |
fcb8551d4f | |
![]() |
7d6b1db97b | |
![]() |
1cde7d498d | |
![]() |
4d95474f92 | |
![]() |
45658d4543 | |
![]() |
e0a2a6f8a2 | |
![]() |
7a5efe8828 | |
![]() |
b39a54ab57 | |
![]() |
07a3cd6483 | |
![]() |
24c2460715 | |
![]() |
4772a0b427 | |
![]() |
baaddef970 | |
![]() |
bb40b69791 | |
![]() |
249691f817 | |
![]() |
7be35134be | |
![]() |
2c7b47be4e | |
![]() |
3cff5390f8 | |
![]() |
d9d41b5a96 | |
![]() |
5d26046bc6 | |
![]() |
e339d4c767 | |
![]() |
8d45169345 | |
![]() |
7d359a2be5 | |
![]() |
c19e4d2b94 | |
![]() |
966f44785b | |
![]() |
0794fc29fa | |
![]() |
0da83b5a4a | |
![]() |
9ac50c5b85 | |
![]() |
8dc662eb8b | |
![]() |
ddc10231ef | |
![]() |
bc61000d9a | |
![]() |
4baad291dc | |
![]() |
dd56e6c231 | |
![]() |
7555d69e9e | |
![]() |
9935052acc | |
![]() |
85675ca0ab | |
![]() |
89606483cc | |
![]() |
e62995291a | |
![]() |
7b9e626597 | |
![]() |
f237eeb0f7 | |
![]() |
b18a4af885 | |
![]() |
0ec8ea7282 | |
![]() |
d9f04eae64 | |
![]() |
2ddb2daf3c | |
![]() |
e0d02ddda2 | |
![]() |
b464ea0461 | |
![]() |
31a9cb55de | |
![]() |
04b78849b7 | |
![]() |
d5ccf2939c | |
![]() |
c739c7ab32 | |
![]() |
f95635f998 | |
![]() |
58483225d0 | |
![]() |
0924555303 | |
![]() |
4238ad7e97 | |
![]() |
8814b24a48 | |
![]() |
93b1192365 | |
![]() |
bff45b34f8 | |
![]() |
68be9026c0 | |
![]() |
3a3179a1b3 | |
![]() |
a850bc64d3 | |
![]() |
b18f284799 | |
![]() |
03bdecc899 | |
![]() |
d4bc8227a4 | |
![]() |
590acba412 | |
![]() |
5e0b720c9d | |
![]() |
8248128cde | |
![]() |
c8a4dd3037 | |
![]() |
57ae659145 | |
![]() |
44898881ca | |
![]() |
6ff5f84243 | |
![]() |
b64746f7a4 | |
![]() |
d9fd89c4f8 | |
![]() |
7a28e26a98 | |
![]() |
243cadb4cd | |
![]() |
8184770cd5 | |
![]() |
99add0a870 | |
![]() |
f8f19fd419 | |
![]() |
82cae0c168 | |
![]() |
7f1805dcc7 | |
![]() |
bce045de58 | |
![]() |
42705efde7 | |
![]() |
075131da3a | |
![]() |
0468380d12 | |
![]() |
ef6daf9c10 | |
![]() |
06a70e4b0a | |
![]() |
42f5338e56 | |
![]() |
53ff80b635 | |
![]() |
98d9290a22 | |
![]() |
e7c4293591 | |
![]() |
c97207b8d4 | |
![]() |
822cf3d289 | |
![]() |
65af9c2df5 | |
![]() |
0e7a62002c | |
![]() |
6c3b7c1762 | |
![]() |
dd36fd2d3a | |
![]() |
0a6ccebaf7 | |
![]() |
8b4b729d07 | |
![]() |
56130bec27 | |
![]() |
2469ecb419 | |
![]() |
593d82ca2b | |
![]() |
5e18fe732d | |
![]() |
cf9a25a8ba | |
![]() |
c1cfbe4556 | |
![]() |
2bd54afffb | |
![]() |
fa5d62b740 | |
![]() |
60d899b335 | |
![]() |
f1d7c895c6 | |
![]() |
392715f053 | |
![]() |
5aa87df570 | |
![]() |
0b84b68b4b | |
![]() |
0bdfe338b7 | |
![]() |
abd0aef26f | |
![]() |
d7b92c0840 | |
![]() |
0567969202 | |
![]() |
eb3831d4fe | |
![]() |
672f466fef | |
![]() |
3e0452053a | |
![]() |
98c0065807 | |
![]() |
59bac06efe | |
![]() |
65b31c7ad6 | |
![]() |
3896bf18c8 | |
![]() |
69edb2cb7f | |
![]() |
26db9ee640 | |
![]() |
8462ea6618 | |
![]() |
a093258ec2 | |
![]() |
7a160accc7 | |
![]() |
0e4e74d8f7 | |
![]() |
3835544919 | |
![]() |
bea761c04e | |
![]() |
1b5d34dedb | |
![]() |
01756f15f4 | |
![]() |
42b51f4e45 | |
![]() |
997be2f2a2 | |
![]() |
23b2f9b693 | |
![]() |
e0f7643648 | |
![]() |
0444abb7b3 | |
![]() |
be8d5288ee | |
![]() |
09c8027d69 | |
![]() |
41f4653ea0 | |
![]() |
bd55aae699 | |
![]() |
5b6ab8049e | |
![]() |
bf35d0af3f | |
![]() |
a0adb77ed5 | |
![]() |
75827a1700 | |
![]() |
61544e807e | |
![]() |
66a9a09483 | |
![]() |
faf39c8f52 | |
![]() |
2a71904419 | |
![]() |
142cd2e31a | |
![]() |
4739cf9a38 | |
![]() |
627d5122c7 | |
![]() |
69d4b84110 | |
![]() |
79ed5b8117 | |
![]() |
a9750234c9 | |
![]() |
21faaa78b4 | |
![]() |
aac5493f61 | |
![]() |
812b637aaa | |
![]() |
df4d72e055 | |
![]() |
af7ffde7e0 | |
![]() |
f63e20501f | |
![]() |
763d65ad3e | |
![]() |
5596351d8b | |
![]() |
c7846262c9 | |
![]() |
4d04bc009b | |
![]() |
86fd6238bd | |
![]() |
2dd81387c5 | |
![]() |
593dd559fc | |
![]() |
7d4983eb11 | |
![]() |
dd2942dc63 | |
![]() |
e596aa777a | |
![]() |
66ef280dde | |
![]() |
ac5191161a | |
![]() |
d18a0e1782 | |
![]() |
7d78f85f4c | |
![]() |
c3e55253d4 | |
![]() |
e7a7a38d91 | |
![]() |
0abccb098f | |
![]() |
259cb61992 | |
![]() |
7c8d40f3d1 | |
![]() |
0fd7cdf6e8 | |
![]() |
b8c21dd0ad | |
![]() |
ddb6c3dbe7 | |
![]() |
4c5793cc75 | |
![]() |
94eb1a5103 | |
![]() |
b31e692921 | |
![]() |
548aee9e83 | |
![]() |
3afdddafa0 | |
![]() |
8cd082bdde | |
![]() |
70a2ac3fed | |
![]() |
664e7391bc | |
![]() |
31b7f554b9 | |
![]() |
3982cdb90e | |
![]() |
9bfbbb1441 | |
![]() |
e5c8509ad1 | |
![]() |
982cc77111 | |
![]() |
734ed9a271 | |
![]() |
2db82d334c | |
![]() |
6989113b71 | |
![]() |
440c666545 | |
![]() |
c482d90d8a | |
![]() |
749badfd22 | |
![]() |
d6c2dfa7dc | |
![]() |
defb771f8a | |
![]() |
ae7f6c76d0 | |
![]() |
bd571202e1 | |
![]() |
cc767726aa | |
![]() |
41a4ee009f | |
![]() |
02f7b9f030 | |
![]() |
15470b2fe7 | |
![]() |
c542768e68 | |
![]() |
59ff024507 | |
![]() |
7033fcbf86 | |
![]() |
2ae5f548f9 | |
![]() |
e4d487bf14 | |
![]() |
2815eaf0af | |
![]() |
98ed8e83e6 | |
![]() |
12dc048a63 | |
![]() |
b78553cca8 | |
![]() |
a18082d29b | |
![]() |
5cd1cdef80 | |
![]() |
4577cc9c92 | |
![]() |
7f7beb6027 | |
![]() |
eb67250f71 | |
![]() |
a961a2e690 | |
![]() |
52090c2be7 | |
![]() |
7051021efc | |
![]() |
df34dec94f | |
![]() |
e60c2c5503 | |
![]() |
d65baf1245 | |
![]() |
ad46657229 | |
![]() |
7b1fe7eef0 | |
![]() |
839727664b | |
![]() |
dc661e3edb | |
![]() |
514e09a159 | |
![]() |
f00e94c64b | |
![]() |
355cf3f367 | |
![]() |
ee6501fbc0 | |
![]() |
6acaab2bf5 | |
![]() |
1055a9235f | |
![]() |
4dd70a0120 | |
![]() |
0fd5648ab6 | |
![]() |
f923c7a493 | |
![]() |
52ffa0e577 | |
![]() |
529797517c | |
![]() |
90b038f19a | |
![]() |
654b51eeb9 | |
![]() |
24647e57e0 | |
![]() |
533b810efe | |
![]() |
58d32b05c4 | |
![]() |
a08b1a3d0a | |
![]() |
006d39c3a3 | |
![]() |
78c13cc41d | |
![]() |
854c15de87 | |
![]() |
83b9722276 | |
![]() |
53756bc480 | |
![]() |
4127ce530e | |
![]() |
f57f8e00fb | |
![]() |
dfe56f909d | |
![]() |
ba1a39d2e5 | |
![]() |
98b01c43d8 | |
![]() |
0e380f908a | |
![]() |
9bd7b25aff | |
![]() |
37ebeb0682 | |
![]() |
b16f5e8c07 | |
![]() |
719e1244cc | |
![]() |
db77b2456e | |
![]() |
71345d4d20 | |
![]() |
aef86fe900 | |
![]() |
2e6ab871c1 | |
![]() |
2dc9077511 | |
![]() |
14d6e53f54 | |
![]() |
f2d177b23a | |
![]() |
98f9f0b64e | |
![]() |
f09aaa3205 | |
![]() |
5538270c1a | |
![]() |
5b215efacc | |
![]() |
d310766240 | |
![]() |
6506df3a30 | |
![]() |
a340c63734 | |
![]() |
02d131a365 | |
![]() |
6b7896cf93 | |
![]() |
ed2ef989d7 | |
![]() |
a1fbdd04a6 | |
![]() |
e751cfb9bd | |
![]() |
2914677ad6 | |
![]() |
4abb36899b | |
![]() |
f3bbcfcd63 | |
![]() |
91c53cc772 | |
![]() |
72eb5e6d12 | |
![]() |
c15911a1b1 | |
![]() |
39997cfebf | |
![]() |
fb60a9bcd8 | |
![]() |
a2f078ec81 | |
![]() |
ad65e6abf7 | |
![]() |
7e9a80c4a1 | |
![]() |
8faddbfdc8 | |
![]() |
a38920d612 | |
![]() |
34e6c5a5f5 | |
![]() |
d46f75c188 | |
![]() |
2cac9d3be3 | |
![]() |
c0181e741d | |
![]() |
9e1837dc4b | |
![]() |
a03d04a335 | |
![]() |
a2315eb314 | |
![]() |
c5a389684a | |
![]() |
c3af0b199f | |
![]() |
30ea51bce0 | |
![]() |
c7466bc4a1 | |
![]() |
effc847ee0 | |
![]() |
777fd6bc78 | |
![]() |
9ab3c45c2a | |
![]() |
bd9d8c9612 | |
![]() |
46cad337e2 | |
![]() |
1c08348f4d | |
![]() |
b3fa10446a | |
![]() |
e20037f4c7 | |
![]() |
3389e5974f | |
![]() |
86e6c34f98 | |
![]() |
d37650a8a5 | |
![]() |
6c66a740c6 | |
![]() |
a62168ccff | |
![]() |
06cd0ef7f9 | |
![]() |
c77f686f6b | |
![]() |
db96f7a0b6 | |
![]() |
a4cdf1b9a6 | |
![]() |
dcf601ebb2 | |
![]() |
887f78a0d0 | |
![]() |
97ddd12360 | |
![]() |
cb1f8af8d7 | |
![]() |
4efa980cba | |
![]() |
3ced7f5c8b | |
![]() |
fd5dc6a521 | |
![]() |
fcd5447274 | |
![]() |
9ba6873ef4 | |
![]() |
5a0c9632bb | |
![]() |
233d079b45 | |
![]() |
be3059f547 | |
![]() |
2a4b7380d3 | |
![]() |
755c63721d | |
![]() |
91ec1589a8 | |
![]() |
d43c709c33 | |
![]() |
ad1c1e6a18 | |
![]() |
27d4d5f92b | |
![]() |
b66bbd5654 | |
![]() |
1f321224b6 | |
![]() |
8dd727fc01 | |
![]() |
e841a8aa1a | |
![]() |
68fd51ac1f | |
![]() |
57eb23b97e | |
![]() |
a2fe2fdd21 | |
![]() |
e8072e0eb0 | |
![]() |
e6615d640d | |
![]() |
c87672f680 | |
![]() |
ba35ebce6a | |
![]() |
e54a1201a9 | |
![]() |
edbfa51bae | |
![]() |
54626689cf | |
![]() |
02882f9483 | |
![]() |
e6216b978a | |
![]() |
e2fcf5eadb | |
![]() |
059b396d97 | |
![]() |
b514a4b0a2 | |
![]() |
3295e71825 | |
![]() |
89aa770a82 | |
![]() |
35b6d80a62 | |
![]() |
0b689ec20d | |
![]() |
9bc148b9cc | |
![]() |
9a2eaad15c | |
![]() |
231b9dfe08 | |
![]() |
7001f8c533 | |
![]() |
1b77d8b3e3 | |
![]() |
e7b9bc7765 | |
![]() |
d65b92517d | |
![]() |
b2a81e3ea5 | |
![]() |
fe6b99a7a0 | |
![]() |
532209dd61 | |
![]() |
a6742bbe6a | |
![]() |
8ef50bfa7c | |
![]() |
1f6181db81 | |
![]() |
43020c4c3f | |
![]() |
7f8f86905a | |
![]() |
4b424e3dba | |
![]() |
38778e34e5 | |
![]() |
671b1a95f1 | |
![]() |
c1f4a60a9e | |
![]() |
0f70aa87c0 | |
![]() |
7414084aec | |
![]() |
6e9a041176 | |
![]() |
58faffaa26 | |
![]() |
1a48e36abb | |
![]() |
1a1f92877c | |
![]() |
de4922c339 | |
![]() |
1b5a49d5b1 | |
![]() |
956b6d2f89 | |
![]() |
61ae419858 | |
![]() |
8bc04ea411 | |
![]() |
9f1744e2a3 | |
![]() |
9f1a392803 | |
![]() |
2b82193674 | |
![]() |
df04471b41 | |
![]() |
874b469cf0 | |
![]() |
d960b4c061 | |
![]() |
fa17fa0554 | |
![]() |
d0c70eccb3 | |
![]() |
c148c440e1 | |
![]() |
bd1e0eec6a | |
![]() |
4f282c9499 | |
![]() |
4e7b94f75e | |
![]() |
a5a03613f1 | |
![]() |
dae7f8f2dd | |
![]() |
98329bf085 | |
![]() |
ffadf35be3 | |
![]() |
0523e85ca8 | |
![]() |
f0fe543682 | |
![]() |
ded6309e2b | |
![]() |
78e34d98f1 | |
![]() |
54538f155d | |
![]() |
738c5c3c43 | |
![]() |
eecf260b22 | |
![]() |
54fc86ced8 | |
![]() |
f5e00560a6 | |
![]() |
24acedacd5 | |
![]() |
ba5ee5e9d5 | |
![]() |
de241c139f | |
![]() |
01030efe10 | |
![]() |
2aeafe654e | |
![]() |
b3b782f810 | |
![]() |
3d33308fe7 | |
![]() |
d47e9bd2d6 | |
![]() |
49eb575ccb | |
![]() |
2e9eadd1de | |
![]() |
bdb3a756bc | |
![]() |
167234d171 | |
![]() |
1251e7cab7 | |
![]() |
4d1f041cfc | |
![]() |
0ea0e94ab4 | |
![]() |
faf986b559 | |
![]() |
22c905d9d8 | |
![]() |
1c88873788 | |
![]() |
8ca63cbb54 | |
![]() |
64073a2558 | |
![]() |
d9f13c57c0 | |
![]() |
3f320792e5 | |
![]() |
17d3c59485 | |
![]() |
b209420a38 | |
![]() |
4f2b3feee4 | |
![]() |
5cda370b9d | |
![]() |
0910dc507a | |
![]() |
a2e9667964 | |
![]() |
ffd4c5fb81 | |
![]() |
e9a12555d1 | |
![]() |
1fb288cbda | |
![]() |
ca005cc3e7 | |
![]() |
5caa5b3df4 | |
![]() |
ca68894e48 | |
![]() |
130623e6ab | |
![]() |
811b94de9b | |
![]() |
4a6c59e018 | |
![]() |
3ad7bec287 | |
![]() |
848c19f3b0 | |
![]() |
ed51d86bdc | |
![]() |
532358c562 | |
![]() |
aa1afebfc1 | |
![]() |
167c85ae4b | |
![]() |
1af87a2a68 | |
![]() |
a775c75a69 | |
![]() |
d5003c4db6 | |
![]() |
97699cd7dd | |
![]() |
c5346930fd | |
![]() |
9205cf987d | |
![]() |
0f3feb7f51 | |
![]() |
07fde97215 | |
![]() |
fa7710b3ff | |
![]() |
fcc986b068 | |
![]() |
24c859fe44 | |
![]() |
037e08f1ee | |
![]() |
15f022f90a | |
![]() |
45ff50478c | |
![]() |
afccc7226b | |
![]() |
ad1a8ee505 | |
![]() |
f74459ea46 | |
![]() |
b4462b3862 | |
![]() |
04f8434bb1 | |
![]() |
cf6345497b | |
![]() |
25b77c1b31 | |
![]() |
a67f084bbe | |
![]() |
16dd75b1e4 | |
![]() |
d546cd53c5 | |
![]() |
30f6881980 | |
![]() |
1adec8da24 | |
![]() |
b2547e767b | |
![]() |
f18e4a4df2 | |
![]() |
afc0eef0b7 | |
![]() |
8fecdad891 | |
![]() |
0093cc9648 | |
![]() |
2bcac4e190 | |
![]() |
a931324050 | |
![]() |
855a6db00f | |
![]() |
b2467a6032 | |
![]() |
d6935d07f7 | |
![]() |
4134d2556b | |
![]() |
35bde51221 | |
![]() |
a5ba9829c5 | |
![]() |
6e86aa288a | |
![]() |
7f6e9074f4 | |
![]() |
f6f1678eca | |
![]() |
7ae952f366 | |
![]() |
0fdb9308c1 | |
![]() |
86408a37ab | |
![]() |
753bb09007 | |
![]() |
45f01066c5 | |
![]() |
7ca5067856 | |
![]() |
8839973caa | |
![]() |
e214a9b6c7 | |
![]() |
5b11947f77 | |
![]() |
18a5907a1e | |
![]() |
0b00a16f4e | |
![]() |
8a7fd2445f | |
![]() |
ab53131bd8 | |
![]() |
80b775730b | |
![]() |
a537f3c166 | |
![]() |
dfb4e04a0d | |
![]() |
f864e4386c | |
![]() |
ee6ee321a4 | |
![]() |
266eccb5d5 | |
![]() |
d628ede53b | |
![]() |
a6333a2d02 | |
![]() |
d881160c03 | |
![]() |
416a5e18a1 | |
![]() |
1fdf99cf1a | |
![]() |
c7fd9f79b0 | |
![]() |
e55ad2f34e | |
![]() |
239301d405 | |
![]() |
8fd633a0c9 | |
![]() |
062f54806c | |
![]() |
d3ed81a259 | |
![]() |
21680f3c71 | |
![]() |
b1fbd863c5 | |
![]() |
b78912e1c3 | |
![]() |
8eba5500cb | |
![]() |
1487db8cdc | |
![]() |
3d2e656e83 | |
![]() |
0d4811a028 | |
![]() |
0247b86c2c | |
![]() |
4e20669538 | |
![]() |
51ac52af5c | |
![]() |
656cdca7b0 | |
![]() |
67aabb5fbc | |
![]() |
46958e2bb5 | |
![]() |
83847bf9a1 | |
![]() |
4f4704b486 | |
![]() |
09985b15a8 | |
![]() |
a164fca4c5 | |
![]() |
096baef750 | |
![]() |
46d9ab17bf | |
![]() |
2212f36cb0 | |
![]() |
5f2dd3e4c2 | |
![]() |
48a849adba | |
![]() |
a1f043ecc9 | |
![]() |
b0fef6d6af | |
![]() |
e612203da4 | |
![]() |
02acfa3fe3 | |
![]() |
0bcaded804 | |
![]() |
a46431a236 | |
![]() |
cf86f83fb0 | |
![]() |
5f0805e306 | |
![]() |
c07ba69e7e | |
![]() |
1f218e95c5 | |
![]() |
c02ffe1548 | |
![]() |
719e210de6 | |
![]() |
861308954f | |
![]() |
97b5a7ed1d | |
![]() |
07ed2680a5 | |
![]() |
b547e6bd3b | |
![]() |
55c0d8e32f | |
![]() |
e3a1c15e83 | |
![]() |
a2c7355b97 | |
![]() |
3f674a7cf6 | |
![]() |
ce4d0c9e10 | |
![]() |
2d7b42dbf2 | |
![]() |
22a69c92d8 | |
![]() |
e101b54d21 | |
![]() |
ffcca74387 | |
![]() |
c87c49c17d | |
![]() |
bfab5b230f | |
![]() |
598baf257f | |
![]() |
f26e86a77f | |
![]() |
f3d37a17a1 | |
![]() |
1aa9ff3595 | |
![]() |
d4d045f9be | |
![]() |
a51e28b3b6 | |
![]() |
68d69a6d1d | |
![]() |
9012f5426f | |
![]() |
cf621a6665 | |
![]() |
d81bfe29de | |
![]() |
4bd6b84fef | |
![]() |
b72acc0959 | |
![]() |
d6525883d9 | |
![]() |
b7ba91a0b9 | |
![]() |
236e4b3374 | |
![]() |
c73a7cb883 | |
![]() |
10cb19b39f | |
![]() |
8bd73be83f | |
![]() |
048f0c292e | |
![]() |
fb9445ffa3 | |
![]() |
f4f0c50444 | |
![]() |
0d43101548 | |
![]() |
77b692aa1b | |
![]() |
592d5e5ef7 | |
![]() |
9b241b9033 | |
![]() |
3fcb0a78d3 | |
![]() |
778f4ce0d9 | |
![]() |
47afec91fa | |
![]() |
b72ea5ee4b | |
![]() |
d5ce941e01 | |
![]() |
3bd84c2bb8 | |
![]() |
cb4e8fec9c | |
![]() |
92fe950b24 | |
![]() |
375fa0c94f | |
![]() |
14cd6b722c | |
![]() |
82ed19cc72 | |
![]() |
3a41cfdf11 | |
![]() |
e43e603ff1 | |
![]() |
1ba3dabe0d | |
![]() |
d849bf11db | |
![]() |
35b32046e9 | |
![]() |
f2dc074b40 | |
![]() |
55122bb9fa | |
![]() |
4aff5bb444 | |
![]() |
a9bba6473e | |
![]() |
ba2887e700 | |
![]() |
6f90eec593 | |
![]() |
b1bac119bb | |
![]() |
8917c70613 | |
![]() |
71a766b157 | |
![]() |
312628821f | |
![]() |
1d8ec4bb5e | |
![]() |
307e0182af | |
![]() |
4244eb69c6 | |
![]() |
57606c4aa8 | |
![]() |
651672bf7a | |
![]() |
17f9e422d3 | |
![]() |
55ae89cd4c | |
![]() |
dad016d6e5 | |
![]() |
f2c0c41bee | |
![]() |
182f81fb46 | |
![]() |
4bfd29c702 | |
![]() |
657759c3f4 | |
![]() |
25b53c7fa3 | |
![]() |
d1309e73ac | |
![]() |
1d4b33903d | |
![]() |
0364f55d14 | |
![]() |
2049720303 | |
![]() |
b9e3356bd3 | |
![]() |
91d2e0e596 | |
![]() |
af1c040eb5 | |
![]() |
7c7fa25c0a | |
![]() |
55c8021624 | |
![]() |
bbddf0bc24 | |
![]() |
b050640b95 | |
![]() |
60c3c1a91a | |
![]() |
0c7d5d796d | |
![]() |
3e29b63554 | |
![]() |
738c80d67a | |
![]() |
f165ec8b9f | |
![]() |
da92d102f4 | |
![]() |
d1e5efcda9 | |
![]() |
fcce252f50 | |
![]() |
d383d0f5aa | |
![]() |
5f92953103 | |
![]() |
8032d4dee4 | |
![]() |
93304143f9 | |
![]() |
b140005236 | |
![]() |
31027b491d | |
![]() |
4761353f94 | |
![]() |
c7e6149f1f | |
![]() |
8348f883bf | |
![]() |
2691463d4a | |
![]() |
59ec9700c6 | |
![]() |
9b2821de3a | |
![]() |
0a5a3c383c | |
![]() |
073c8844e0 | |
![]() |
4c0c82c92f | |
![]() |
fae159d2ec | |
![]() |
b7a9d5085f | |
![]() |
3503f1cc56 | |
![]() |
1d43b346fe | |
![]() |
1cbd6afa28 | |
![]() |
f8408fdab2 | |
![]() |
4c8c0e0b72 | |
![]() |
8c69f8ac3a | |
![]() |
0a40273b16 | |
![]() |
c922d67e86 | |
![]() |
8d51fdfbbe | |
![]() |
13ae3664ab | |
![]() |
10f649e843 | |
![]() |
6009d46485 | |
![]() |
3c92ad957e | |
![]() |
29fa5037bf | |
![]() |
1b1d4acdd3 | |
![]() |
0aa0b07733 | |
![]() |
64d9792067 | |
![]() |
18110b0db2 | |
![]() |
60e8ec45bd | |
![]() |
5fc80d83aa | |
![]() |
961a467f92 | |
![]() |
b1e92e6cb0 | |
![]() |
b26e760d2c | |
![]() |
9432c70bd2 | |
![]() |
2d1a6d34bf | |
![]() |
cd38ecbd34 | |
![]() |
c28b2423cc | |
![]() |
1b647bc46a | |
![]() |
88c7d5d906 | |
![]() |
3014da89b3 | |
![]() |
fb317f2717 | |
![]() |
7312b2844d | |
![]() |
625c8c270f | |
![]() |
5fa0218104 | |
![]() |
dd351a80b9 | |
![]() |
dc78778ae2 | |
![]() |
9acc466729 | |
![]() |
f6393a9210 | |
![]() |
49b5243c1a | |
![]() |
1d4977cb4b | |
![]() |
234e2b755f | |
![]() |
2c318062b7 | |
![]() |
e1c70f0ac6 | |
![]() |
a99026df03 | |
![]() |
c44819873a | |
![]() |
2c8a4603ab | |
![]() |
4d1b0b5809 | |
![]() |
713b5dc1b2 | |
![]() |
7dd20a3330 | |
![]() |
978fdfe680 | |
![]() |
e441291f32 | |
![]() |
cdfb727f8d | |
![]() |
fe4500e44e | |
![]() |
ae4a1c64e3 | |
![]() |
9a32b37048 | |
![]() |
74b8df277c | |
![]() |
79684686c3 | |
![]() |
eb3963bc37 | |
![]() |
ce73043bec | |
![]() |
e3b27ecd16 | |
![]() |
bd5cccef40 | |
![]() |
47f781d26d | |
![]() |
ea19f9cf6c | |
![]() |
40d89c77f6 | |
![]() |
42ffac8197 | |
![]() |
b3122f97ee | |
![]() |
c4c9cf60f6 | |
![]() |
9e70ebca45 | |
![]() |
a070dc091b | |
![]() |
972d9e28ea | |
![]() |
d77e3ee425 | |
![]() |
143217af2c | |
![]() |
80fd38374f | |
![]() |
8422f0ab7c | |
![]() |
3713c1ba7f | |
![]() |
18349689c8 | |
![]() |
9d0c383e93 | |
![]() |
ade66fd351 | |
![]() |
782a15da11 | |
![]() |
9897125f9a | |
![]() |
009029b15d | |
![]() |
e7064a71b6 | |
![]() |
fc0daf243a | |
![]() |
bf013a7c18 | |
![]() |
4a330878ae | |
![]() |
0a0d4fe509 | |
![]() |
8c049fc914 | |
![]() |
a8f6163bb2 | |
![]() |
d583566a3e | |
![]() |
711f5ef88c | |
![]() |
133419a1e3 | |
![]() |
20aa3cc42e | |
![]() |
1d239bce90 | |
![]() |
111476de2e | |
![]() |
cb21139402 | |
![]() |
967d00cf34 | |
![]() |
fd76bc0f6c | |
![]() |
dbcf7e675e | |
![]() |
ca6c16394e | |
![]() |
0d4763d281 | |
![]() |
de1374a445 | |
![]() |
98d5d4a597 | |
![]() |
ac8d9977ee | |
![]() |
430759d54f | |
![]() |
c3f521d09a | |
![]() |
0eb39e48c3 | |
![]() |
b6431dda83 | |
![]() |
575d87fc98 | |
![]() |
b14e6f01df | |
![]() |
1d2ceefbe9 | |
![]() |
46ecfcf7fd | |
![]() |
75dcdfd020 | |
![]() |
f502769b6c | |
![]() |
ca198d08bf | |
![]() |
bb0ceffcd5 | |
![]() |
e6ad3b5db5 | |
![]() |
d23f9f77a9 | |
![]() |
e82f680e48 | |
![]() |
5fa4217abf | |
![]() |
41d9972ec2 | |
![]() |
19f9986750 | |
![]() |
a882fd6373 | |
![]() |
4ba4419e8f | |
![]() |
b721929595 | |
![]() |
d093315786 | |
![]() |
fd6c778db0 | |
![]() |
5d68b4d98e | |
![]() |
95c40ea60a | |
![]() |
d37ac82039 | |
![]() |
e2c27f9c88 | |
![]() |
f13fabcc73 | |
![]() |
3f6e986076 | |
![]() |
8266164a60 | |
![]() |
1994e00506 | |
![]() |
0f94429bab | |
![]() |
f0d3bd7f40 | |
![]() |
d93668c4c0 | |
![]() |
be8b6906c8 | |
![]() |
fde699f8d9 | |
![]() |
da27b3e49e | |
![]() |
5c1a85e264 | |
![]() |
b50a86f560 | |
![]() |
4ffac4d2df | |
![]() |
189ea22a75 | |
![]() |
168aa1c39f | |
![]() |
04e454c8a3 | |
![]() |
ef37c65f92 | |
![]() |
4e181756da | |
![]() |
efdd1e8621 | |
![]() |
0bb93e7c8c | |
![]() |
73b9cd6503 | |
![]() |
07f8735d02 | |
![]() |
8a38d05f18 | |
![]() |
4180b540a7 | |
![]() |
5141a38ec6 | |
![]() |
95b62807e3 | |
![]() |
e901dd33a2 | |
![]() |
3562dbad63 | |
![]() |
84e9be0e29 | |
![]() |
98965bac99 | |
![]() |
e7dc68e5ce | |
![]() |
2e7f6bd52a | |
![]() |
7d31f5569b | |
![]() |
c529adf458 | |
![]() |
b691731341 | |
![]() |
98589c29bd | |
![]() |
8b01f9eb3d | |
![]() |
3cc1963129 | |
![]() |
711e0779ab | |
![]() |
834bc40a56 | |
![]() |
f841376e58 | |
![]() |
a1bd1e4872 | |
![]() |
81f72036b8 | |
![]() |
5d5d6fbf91 | |
![]() |
cee3ce6bad | |
![]() |
1a42e8103b | |
![]() |
fbd3bd438c | |
![]() |
cd024f7c69 | |
![]() |
6a35a42883 | |
![]() |
e89f37f38d | |
![]() |
8b98ed38e1 | |
![]() |
576255a0b8 | |
![]() |
2443cf866a | |
![]() |
a537003680 | |
![]() |
1533d75ea4 | |
![]() |
f06a8d5731 | |
![]() |
a41d8a4242 | |
![]() |
3795d559e0 | |
![]() |
cc1aa30e0b | |
![]() |
bb389cec2b | |
![]() |
170bc431f0 | |
![]() |
cfc5ce2335 | |
![]() |
964bc43c29 | |
![]() |
60badc15d7 | |
![]() |
ad0689009d | |
![]() |
520bd4e712 | |
![]() |
c1ad2cc5a4 | |
![]() |
5ac1ce70b5 | |
![]() |
414d661205 | |
![]() |
15ac34c397 | |
![]() |
b867a40eb7 | |
![]() |
20e02710b5 | |
![]() |
8731de6e8c | |
![]() |
053635ef55 | |
![]() |
372e35e04f | |
![]() |
2be21622ae | |
![]() |
6a33eb0cf8 | |
![]() |
ec51fa5be0 | |
![]() |
436358a51b | |
![]() |
042e584b20 | |
![]() |
7be2b0da6e | |
![]() |
4c21753dd9 | |
![]() |
0a0c1f0fe6 | |
![]() |
f8c453def5 | |
![]() |
d55eb9ba06 | |
![]() |
11afd9c97d | |
![]() |
4d201d86d2 | |
![]() |
9cf546bef3 | |
![]() |
e3cd9556cb | |
![]() |
de38a3d08e | |
![]() |
6e40d456f9 | |
![]() |
f969eedf7d | |
![]() |
af035533a0 | |
![]() |
74ff219aa9 | |
![]() |
42ffdf7c7b | |
![]() |
b1362ccb40 | |
![]() |
cf5ba963c0 | |
![]() |
b1891e35a9 | |
![]() |
ca6054c6d1 | |
![]() |
2a91ec3c9c | |
![]() |
8cf436f9f8 | |
![]() |
b68eba259b | |
![]() |
c1f2d4629a | |
![]() |
8a55bc6219 | |
![]() |
a199a91f47 | |
![]() |
e1901a2f08 | |
![]() |
d617c0141b | |
![]() |
78be544fc2 | |
![]() |
c442ae295f | |
![]() |
a77cb87edc | |
![]() |
86c9c63aed | |
![]() |
864e2664a3 | |
![]() |
cb0ce43bfc | |
![]() |
84aca05c89 | |
![]() |
541dba3a78 | |
![]() |
7fab839c75 | |
![]() |
e28f34a6d9 | |
![]() |
8c0cc33773 | |
![]() |
f00bdc7b72 | |
![]() |
b2faef8aad | |
![]() |
9248e9454b | |
![]() |
cc38aeeef8 | |
![]() |
29acd2d238 | |
![]() |
56ea49a9e3 | |
![]() |
3bfdea87a1 | |
![]() |
dbea6bfe75 | |
![]() |
8f090d0499 | |
![]() |
da36b80fdd | |
![]() |
f842340653 | |
![]() |
82db2206b0 | |
![]() |
e4fcfb08af | |
![]() |
0add4b34bf | |
![]() |
f13b137867 | |
![]() |
5e3b0bb527 | |
![]() |
522bbb7cec | |
![]() |
6bcf46190b | |
![]() |
90698769d0 | |
![]() |
f71a1ae89c | |
![]() |
384c6bca66 | |
![]() |
295ffa90b1 | |
![]() |
1f279f75af | |
![]() |
dcfe3bad86 | |
![]() |
9bf7ca718c | |
![]() |
9c750642c8 | |
![]() |
5e8fa718c6 | |
![]() |
fb7b9a2104 | |
![]() |
c5643835a1 | |
![]() |
9e40fe4435 | |
![]() |
98546fb57c | |
![]() |
97d601d2cd | |
![]() |
1adb24e67d | |
![]() |
b1df012477 | |
![]() |
e60ee3fb27 | |
![]() |
cbacd016c0 | |
![]() |
84bfa26bc7 | |
![]() |
49689be1ce | |
![]() |
68a0e791db | |
![]() |
b1db5d2080 | |
![]() |
54c80ae16e | |
![]() |
d7e32d8e8f | |
![]() |
4dbec12893 | |
![]() |
25c2789ca5 | |
![]() |
705a26cf41 | |
![]() |
9535e3cff9 | |
![]() |
6a04e0323a | |
![]() |
533c294023 | |
![]() |
b4d1199518 | |
![]() |
5d3f4e9e22 | |
![]() |
7b4b78b215 | |
![]() |
b5ff3a3111 | |
![]() |
f810403c92 | |
![]() |
ef767f03c3 | |
![]() |
cfb5940ea8 | |
![]() |
f9353eab01 | |
![]() |
90086cf357 | |
![]() |
a562c7f966 | |
![]() |
1ed8852044 | |
![]() |
423e1ad7fa | |
![]() |
d58743fd37 | |
![]() |
a81c816841 | |
![]() |
138d14b4bc | |
![]() |
b2610dfe11 | |
![]() |
60c5b06bc8 | |
![]() |
499826aab3 | |
![]() |
271fd8bfe1 | |
![]() |
5808c1d667 | |
![]() |
9804f0119a | |
![]() |
1ef7d2101c | |
![]() |
b804c2e2b1 | |
![]() |
f72ce94f8d | |
![]() |
68ffbc5ca7 | |
![]() |
4308f68535 | |
![]() |
142a66bab0 | |
![]() |
45132ba796 | |
![]() |
125ecc8cf4 | |
![]() |
24bff13260 | |
![]() |
8fd20b6b3b | |
![]() |
0d6321b491 | |
![]() |
42ffb6345a | |
![]() |
c9551b5144 | |
![]() |
7e1ec9f583 | |
![]() |
e40600564f | |
![]() |
e72cf1b901 | |
![]() |
79254b307a | |
![]() |
7535e4b8e0 | |
![]() |
0ba2839065 | |
![]() |
acb25f73a2 | |
![]() |
2008c48d04 | |
![]() |
37453c7af9 | |
![]() |
40d58e14fc | |
![]() |
b6d3c26b2b | |
![]() |
ed7b6cd6f6 | |
![]() |
0bb50b5372 | |
![]() |
9f10047113 | |
![]() |
d1e2adbbab | |
![]() |
da6af1be95 | |
![]() |
85d94c07e4 | |
![]() |
bf6392079a | |
![]() |
4885c6588b | |
![]() |
04d9bec939 | |
![]() |
a6c6f6b354 | |
![]() |
7e3c80e1d8 | |
![]() |
02b5aa97e5 | |
![]() |
c43184b77b | |
![]() |
ad1dc864fc | |
![]() |
be3000353b | |
![]() |
77024d3b82 | |
![]() |
1c31be8a5c | |
![]() |
0e61c45d5f | |
![]() |
b68eac1b42 | |
![]() |
dd77b3aeda | |
![]() |
b2af2527fe | |
![]() |
73bf5e3467 | |
![]() |
aaf0092a4a | |
![]() |
fe0f471812 | |
![]() |
960d3514be | |
![]() |
d8df35d418 | |
![]() |
9912b1b04d | |
![]() |
65151a3094 | |
![]() |
e1f7f155a2 | |
![]() |
d25ec2d119 | |
![]() |
fb7ebf22f4 | |
![]() |
a84b35c819 | |
![]() |
39692de722 | |
![]() |
20ed74f6d5 | |
![]() |
80625f4229 | |
![]() |
1ff0161d4e | |
![]() |
d6cc212f0f | |
![]() |
dae6fcbd0f | |
![]() |
8c4d4bb3a1 | |
![]() |
d6b75e99ac | |
![]() |
0ca0356432 | |
![]() |
de4ff111bb | |
![]() |
f535f9ac58 | |
![]() |
fc0c459391 | |
![]() |
ce8d525928 | |
![]() |
d2434c3bd9 | |
![]() |
7c420765a9 | |
![]() |
ed419e6a3a | |
![]() |
53a76b5be5 | |
![]() |
882d05895e | |
![]() |
bf2c15b24d | |
![]() |
c2ecb37c26 | |
![]() |
68588dd964 | |
![]() |
a9b186acb3 | |
![]() |
4069c5a517 | |
![]() |
6e4af3f8b0 | |
![]() |
e8bd687f08 | |
![]() |
6b3438925c | |
![]() |
77934940e2 | |
![]() |
d3b329ec7f | |
![]() |
fe2e22962a | |
![]() |
d727d83b5b | |
![]() |
4393a347e3 | |
![]() |
fa8b1c7483 | |
![]() |
2ac4dfe8e6 | |
![]() |
e4c49d8de9 | |
![]() |
96a47a4af9 | |
![]() |
8c80050dbe | |
![]() |
9ff4a176cf | |
![]() |
197273887f | |
![]() |
02bfeac444 | |
![]() |
df589d321a | |
![]() |
07d7d2c01d | |
![]() |
455e2c7080 | |
![]() |
cb6f0c0dfd | |
![]() |
42f9017627 | |
![]() |
5a4f5f9614 | |
![]() |
294e3e959c | |
![]() |
3587dbad50 | |
![]() |
4c0e2761e8 | |
![]() |
5f98f3906e | |
![]() |
fb0db7b5ac | |
![]() |
9dbac0c047 | |
![]() |
323db4cdf2 | |
![]() |
562eefd1b5 | |
![]() |
e72b321d29 | |
![]() |
80ba44d209 | |
![]() |
b9740ab5c7 | |
![]() |
c390f82621 | |
![]() |
012bf26764 | |
![]() |
09b06acd47 | |
![]() |
5cd32213da | |
![]() |
31f60d908a | |
![]() |
b0f2383e4c | |
![]() |
91f338a4b9 | |
![]() |
80e807c6da | |
![]() |
8d72769735 | |
![]() |
c034385553 | |
![]() |
582db02edc | |
![]() |
b9ee75878a | |
![]() |
1b8973649f | |
![]() |
a477807219 | |
![]() |
264dc80808 | |
![]() |
2f01b6c2a0 | |
![]() |
c627c6b8ad | |
![]() |
3bd57c4c95 | |
![]() |
f0ca368148 | |
![]() |
26643f18eb | |
![]() |
634c2f31d4 | |
![]() |
d0f2fdc2e8 | |
![]() |
0fffdaca01 | |
![]() |
e2dfe00574 | |
![]() |
01ef774e13 | |
![]() |
7909a3f8c2 | |
![]() |
833f4fcdb9 | |
![]() |
d2d18907c3 | |
![]() |
3eb9de4614 | |
![]() |
47bb26f093 | |
![]() |
6b88ebf513 | |
![]() |
867ac232e9 | |
![]() |
914d91da2c | |
![]() |
320fa688f1 | |
![]() |
76d9a939ed | |
![]() |
ba023fa075 | |
![]() |
168c08ae11 | |
![]() |
b12c226333 | |
![]() |
e324dc1e9a | |
![]() |
c4c8592f7f | |
![]() |
3882ebb4e7 | |
![]() |
8db331c5ff | |
![]() |
99ccf835b8 | |
![]() |
ee7244e382 | |
![]() |
61e06aea02 | |
![]() |
796364c337 | |
![]() |
4c5e700318 | |
![]() |
7bca51aa57 | |
![]() |
90ff47e8fe | |
![]() |
50c7b966e2 | |
![]() |
67465b636f | |
![]() |
1d0743861b | |
![]() |
196170a5c0 | |
![]() |
725159d943 | |
![]() |
f0b76ada6d | |
![]() |
40d342e48f | |
![]() |
a4ffedc8df | |
![]() |
61933278a4 | |
![]() |
113146e6b3 | |
![]() |
93430f6d8d | |
![]() |
78aa4a7a48 | |
![]() |
f53d6b5ee6 | |
![]() |
a4fd327ced | |
![]() |
aaa7ade12b | |
![]() |
fad6fa759f | |
![]() |
65ab7e85c5 | |
![]() |
cf0cde6108 | |
![]() |
08714ea7f2 | |
![]() |
ccff2d3149 | |
![]() |
513b3b648f | |
![]() |
3198207ee3 | |
![]() |
79d4d0c3b0 | |
![]() |
2cc4debe55 | |
![]() |
51ad58c5b1 | |
![]() |
0f04ee8a90 | |
![]() |
d7d270f52c | |
![]() |
3c57a06635 | |
![]() |
9e776c48ca | |
![]() |
68bc1d1901 | |
![]() |
5910c2f198 | |
![]() |
855be2fac3 | |
![]() |
ce47b5e87b | |
![]() |
39f549db47 | |
![]() |
4d0593d1a8 | |
![]() |
fb1921507e | |
![]() |
cbd71f0b71 | |
![]() |
643fdd4552 | |
![]() |
ae5b752001 | |
![]() |
a7e636e8b0 | |
![]() |
30a8f124f1 | |
![]() |
9d49db9111 | |
![]() |
b60c6a0cce | |
![]() |
390bc43513 | |
![]() |
2902629632 | |
![]() |
194f66e4e2 | |
![]() |
1c3bcfbaf8 | |
![]() |
fc480466b7 | |
![]() |
c448f604ad | |
![]() |
c8210b838d | |
![]() |
e068592d6b | |
![]() |
c9f278e00d | |
![]() |
edb9ebda3f | |
![]() |
dcb572a348 | |
![]() |
298c5256e3 | |
![]() |
ee66bde8a0 | |
![]() |
6a27ce1264 | |
![]() |
5916d00047 | |
![]() |
ef10848729 | |
![]() |
51d227bff5 | |
![]() |
de1c8aed5a | |
![]() |
fbe279dbdf | |
![]() |
59a8ea41ab | |
![]() |
ea6222a941 | |
![]() |
55fdb1b562 | |
![]() |
71db5c1c21 | |
![]() |
c85a15078c | |
![]() |
fb5f523f95 | |
![]() |
3ef409ba4e | |
![]() |
934fc9f777 | |
![]() |
41b6f579c9 | |
![]() |
2ecd8e296b | |
![]() |
8a083e5acb | |
![]() |
a3bc1cd1cc | |
![]() |
3f3158c3c0 | |
![]() |
e4c0154dd8 | |
![]() |
04aac479df | |
![]() |
7b768b83d8 | |
![]() |
8ebe438af2 | |
![]() |
8674c8cffe | |
![]() |
e68f2e6cf1 | |
![]() |
63e66733bd | |
![]() |
61a10c4ab6 | |
![]() |
2ed569e475 | |
![]() |
0254b5e5e2 | |
![]() |
9698f5670f | |
![]() |
f89f383f91 | |
![]() |
b171a0991a | |
![]() |
af100c36dc | |
![]() |
264b0987e8 | |
![]() |
3573ce6248 | |
![]() |
40b6351dae | |
![]() |
ecf8cf18c7 | |
![]() |
277401e4d8 | |
![]() |
f5e29556bc | |
![]() |
87124da471 | |
![]() |
15a712cc42 | |
![]() |
bc3fd907e3 | |
![]() |
721f0406c9 | |
![]() |
e48fcc9e85 | |
![]() |
fdd1c0e6e8 | |
![]() |
e48bd707f3 | |
![]() |
99401dd1f4 | |
![]() |
fbd2bceab4 | |
![]() |
ca4912c0f2 | |
![]() |
20d1adf7b4 | |
![]() |
b40dcdf3f7 | |
![]() |
7d557512be | |
![]() |
b0596ab4a2 | |
![]() |
8af1a93e77 | |
![]() |
87f110db0b | |
![]() |
5b3f629a8d | |
![]() |
1743b0b81b | |
![]() |
83aad21779 | |
![]() |
13283cdf8f | |
![]() |
fd16c41514 | |
![]() |
cb63fb4d98 | |
![]() |
ec455a15aa | |
![]() |
144d049898 | |
![]() |
4433cec8fc | |
![]() |
1721251fcb | |
![]() |
1f745442b8 | |
![]() |
7a6c1e5fd7 | |
![]() |
9ade0bd991 | |
![]() |
8875c7d302 | |
![]() |
3db430b2bf | |
![]() |
26c12949b0 | |
![]() |
a5bbd83c8e | |
![]() |
4e7172ac4a | |
![]() |
aed5f82988 | |
![]() |
69bf4a0b03 | |
![]() |
568e0548e5 | |
![]() |
bfaa92649e | |
![]() |
907889d756 | |
![]() |
06a820969c | |
![]() |
ed9c5eb8f5 | |
![]() |
541348deda | |
![]() |
66ec4060e4 | |
![]() |
7abcb201e6 | |
![]() |
d042d84840 | |
![]() |
a440388cda | |
![]() |
b18a6d62ab | |
![]() |
1cb3ae44ee | |
![]() |
5df8e5548f | |
![]() |
5a8ec614ba | |
![]() |
7d79980fb0 | |
![]() |
d5d24cbb88 | |
![]() |
950c6c7460 | |
![]() |
27484f074f | |
![]() |
9b8a0dc52c | |
![]() |
269d1940c4 | |
![]() |
9b1d5c4ef2 | |
![]() |
7fefaca661 | |
![]() |
540ad3d357 | |
![]() |
98f88f2aca | |
![]() |
22d77183f5 | |
![]() |
16e047c8e9 | |
![]() |
45e95b1a8a | |
![]() |
136f3a8642 | |
![]() |
1d7b5994ee | |
![]() |
7a96bc7c3a | |
![]() |
752a660b7d | |
![]() |
b5b2729ad0 | |
![]() |
5d6a64797f | |
![]() |
3b9af24780 | |
![]() |
6c996f8993 | |
![]() |
823030cbaf | |
![]() |
0d47349db8 | |
![]() |
ce0342e702 | |
![]() |
6f04d2be74 | |
![]() |
01aa3ccccd | |
![]() |
46c5ee5ef8 | |
![]() |
27a730b365 | |
![]() |
95163ca09a | |
![]() |
2e4fb2384c | |
![]() |
5f49036c2a | |
![]() |
01aef49125 | |
![]() |
7ab58ee5b2 | |
![]() |
2072f74f71 | |
![]() |
51497fc1a8 | |
![]() |
a841946fd8 | |
![]() |
c3bd9cd6e4 | |
![]() |
b395a819e1 | |
![]() |
12259cefcd | |
![]() |
ef6022e61e | |
![]() |
33c8717151 | |
![]() |
caaebe35e6 | |
![]() |
58d236151a | |
![]() |
b496da643d | |
![]() |
31c31675c5 | |
![]() |
d0cfc8d6be | |
![]() |
e03efa73ef | |
![]() |
c80f085444 | |
![]() |
a7032a211e | |
![]() |
f82946cd96 | |
![]() |
4306e404e4 | |
![]() |
14b1122641 | |
![]() |
685e8ef91e | |
![]() |
7874f746eb | |
![]() |
024e8b9707 | |
![]() |
16c57263de | |
![]() |
7a88e3e80d | |
![]() |
ec367f17be | |
![]() |
2ef411f641 | |
![]() |
d41862a36a | |
![]() |
4ae597c2f0 | |
![]() |
d781e65e09 | |
![]() |
dc5dbcba26 | |
![]() |
bd96da18a6 | |
![]() |
19d38dc7aa | |
![]() |
bb36f962ab | |
![]() |
87f422bf6f | |
![]() |
c1b4ad4ea2 | |
![]() |
bc53cc5a22 | |
![]() |
9cb111f927 | |
![]() |
c7fd1a9d07 | |
![]() |
e2ca4ed530 | |
![]() |
92090532b2 | |
![]() |
91be00d42e | |
![]() |
aa3cb25961 | |
![]() |
fb0b919205 | |
![]() |
21c4253efc | |
![]() |
5ba23ec012 | |
![]() |
dfbfdac140 | |
![]() |
f78409a83f | |
![]() |
0bf3a00a65 | |
![]() |
bca1dfb9ac | |
![]() |
99d2e8baa9 | |
![]() |
5e8af885e1 | |
![]() |
fb9ead56d5 | |
![]() |
ed6fd31c38 | |
![]() |
559039dc38 | |
![]() |
e60dffbc84 | |
![]() |
2f2dccee70 | |
![]() |
dcbff3f40b | |
![]() |
efc55ff761 | |
![]() |
d6ea4bf138 | |
![]() |
1d7d7df7e9 | |
![]() |
52b8847c04 | |
![]() |
0649ef51f5 | |
![]() |
3969516d0b | |
![]() |
e629f9ea7a | |
![]() |
094a1870c2 | |
![]() |
437d19fd24 | |
![]() |
7e959377ae | |
![]() |
5bcac684dd | |
![]() |
69c199b857 | |
![]() |
c762cdf95d | |
![]() |
a9d76cb8c5 | |
![]() |
9a4457e4ff | |
![]() |
7e800960ff | |
![]() |
c07b76dc86 | |
![]() |
1f58256b66 | |
![]() |
b1f426ba3f | |
![]() |
1058078891 | |
![]() |
c7baaff898 | |
![]() |
ba2ba7cca4 | |
![]() |
47c8545bee | |
![]() |
fad737ae87 | |
![]() |
539aa86231 | |
![]() |
e89cfe3a49 | |
![]() |
76c3d62147 | |
![]() |
b57aabc994 | |
![]() |
db8774bdbf | |
![]() |
5e0a1bb8d1 | |
![]() |
a11364e8d9 | |
![]() |
60e382c816 | |
![]() |
c9e117452f | |
![]() |
56c4cbc679 | |
![]() |
41297b6d8e | |
![]() |
0eae3afc27 | |
![]() |
482267cd75 | |
![]() |
ee6f3dff11 | |
![]() |
3f59a0b5d4 | |
![]() |
0490039779 | |
![]() |
8941b4aba9 | |
![]() |
bc56097041 | |
![]() |
659b0dbcb6 | |
![]() |
9d56185bc2 | |
![]() |
039e177db6 | |
![]() |
6fe8d6bdc7 | |
![]() |
f397adaf47 | |
![]() |
64cecb1b3e | |
![]() |
0888b3a5de | |
![]() |
8adec34759 | |
![]() |
ab429334f4 | |
![]() |
99ba104317 | |
![]() |
cde65de6a9 | |
![]() |
217c1d336f | |
![]() |
d96d624d6e | |
![]() |
250fca30a9 | |
![]() |
b377287bdb | |
![]() |
e91edccdbb | |
![]() |
4fbf560d7a | |
![]() |
6e496c9834 | |
![]() |
7ae6f09c1e | |
![]() |
2c59c934a8 | |
![]() |
7b7bb56ba2 | |
![]() |
55f60d5496 | |
![]() |
7b22d0b6bc | |
![]() |
d0c111ebf6 | |
![]() |
18b544b251 | |
![]() |
8b89eb1ebe | |
![]() |
16a06984bf | |
![]() |
2aa985baec | |
![]() |
2abb85a05d | |
![]() |
cea3cc3ff6 | |
![]() |
dea5e779c8 | |
![]() |
32e64e3e51 | |
![]() |
fcf244747d | |
![]() |
3bec8d8d00 | |
![]() |
aa840c41ca | |
![]() |
e484e43cfa | |
![]() |
b8cbaf2828 | |
![]() |
4f997b7dba | |
![]() |
c10af35f4d | |
![]() |
c9d1c8e467 | |
![]() |
04e3d1dafd | |
![]() |
b12a40496f | |
![]() |
f39cfd0c80 | |
![]() |
967408cbc1 | |
![]() |
cf93552f98 | |
![]() |
57c1f5caa5 | |
![]() |
92204bbe48 | |
![]() |
d37f31bf68 | |
![]() |
b3b25bcc96 | |
![]() |
df237f39d1 | |
![]() |
0e05f39b21 | |
![]() |
d5b8a5be35 | |
![]() |
fc12c385f0 | |
![]() |
a9351c7b75 | |
![]() |
e0204926c2 | |
![]() |
1944fe2931 | |
![]() |
e0040d0da9 | |
![]() |
cf04dac50f | |
![]() |
49667709bd | |
![]() |
1971cd07cb | |
![]() |
ca035407c0 | |
![]() |
1037bfa736 | |
![]() |
2e28c61837 | |
![]() |
b87032f948 | |
![]() |
c4a8559462 | |
![]() |
03068ccf1d | |
![]() |
71d73de359 | |
![]() |
19fef7e068 | |
![]() |
0b6c04c04b | |
![]() |
d248ef5cfd | |
![]() |
b3ad503d49 | |
![]() |
09689d9865 | |
![]() |
0f6b30741d | |
![]() |
6f486fc2cf | |
![]() |
56468eda49 | |
![]() |
4327d8725a | |
![]() |
6781716712 | |
![]() |
3176cf6b18 | |
![]() |
56a6d6cddd | |
![]() |
d5382702c2 | |
![]() |
ccf7dfb10c | |
![]() |
e82e1733db | |
![]() |
ed58f6e1f3 | |
![]() |
9b5bac0646 | |
![]() |
78d9f41bee | |
![]() |
73fa6826f9 | |
![]() |
c5834ad616 | |
![]() |
a9cfa9ba4c | |
![]() |
f257f61412 | |
![]() |
8a40316fe3 | |
![]() |
c90533d007 | |
![]() |
5209fd6e61 | |
![]() |
1f7f2be0a3 | |
![]() |
fe84248b05 | |
![]() |
83d8d19f39 | |
![]() |
f9e8e9c862 | |
![]() |
e5f90aaaa9 | |
![]() |
447200f537 | |
![]() |
1d41eb9ad5 | |
![]() |
3d16c5b71c | |
![]() |
0a4a6b4957 | |
![]() |
2adab7ef1a | |
![]() |
b25867dc5f | |
![]() |
8459879bed | |
![]() |
9e3ddf7fe7 | |
![]() |
9ba8f348ee | |
![]() |
7416f2a973 | |
![]() |
5bc0040f1a | |
![]() |
3e47306a26 | |
![]() |
ad8e19a9d0 | |
![]() |
6f83e98aaf | |
![]() |
3751ca21cf | |
![]() |
db8ebad34d | |
![]() |
1726035ad2 | |
![]() |
b973902023 | |
![]() |
53df785ad4 | |
![]() |
8332160bb5 | |
![]() |
a82dad9a4c | |
![]() |
8c81d6fd27 | |
![]() |
d1c1aa9f7e | |
![]() |
3b5ee1f29f | |
![]() |
8c62cc838a | |
![]() |
3b71e1d6b0 | |
![]() |
97dd427407 | |
![]() |
a6eb5c11d9 | |
![]() |
bbcda495e5 | |
![]() |
33640517af | |
![]() |
7a650d67ff | |
![]() |
5d362c9409 | |
![]() |
38a687eed8 | |
![]() |
53fb4ac616 | |
![]() |
926ac850ba | |
![]() |
3d353ce490 | |
![]() |
9c9b01cb62 | |
![]() |
03214b3848 | |
![]() |
f65d5965a5 | |
![]() |
9ce1236c21 | |
![]() |
b438ec39b7 | |
![]() |
e3276828f6 | |
![]() |
bbc0a1d6d6 | |
![]() |
c7ed3cbc8c | |
![]() |
0ce2f29016 | |
![]() |
f7111cd07a | |
![]() |
2d4c9d19e8 | |
![]() |
b971c6b4fd | |
![]() |
0771dd39cb | |
![]() |
00ef096082 | |
![]() |
e010e03b9c | |
![]() |
58c56aca0b | |
![]() |
07331b522e | |
![]() |
00b28e5807 | |
![]() |
1b7d14c178 | |
![]() |
09c69e5a2c | |
![]() |
19e82b56f8 | |
![]() |
f0a986eeef | |
![]() |
d7d3e9f21b | |
![]() |
89e4e948c3 | |
![]() |
b0895ec82f | |
![]() |
907657f63b | |
![]() |
18b7aefa78 | |
![]() |
09641d27ff | |
![]() |
829ca50a7a | |
![]() |
60534b840d | |
![]() |
5902173ae0 | |
![]() |
7d450e5a13 | |
![]() |
b8625a6f20 | |
![]() |
b117ca793d | |
![]() |
961264bd1b | |
![]() |
3411a9c9ca | |
![]() |
a9e0617180 | |
![]() |
2cdc3b828d | |
![]() |
71022e6920 | |
![]() |
2c8473e761 | |
![]() |
53e61f0ece | |
![]() |
0539d6039d | |
![]() |
04e2e8d221 | |
![]() |
4db71dcea5 | |
![]() |
2e82cbae5b | |
![]() |
35773f0c4b | |
![]() |
23e7264061 | |
![]() |
50f1d99435 | |
![]() |
d6746f7dd8 | |
![]() |
95e463ce27 | |
![]() |
9c84eb674c | |
![]() |
4915fc6978 | |
![]() |
b7daefd0f9 | |
![]() |
2789c7e495 | |
![]() |
2922015e6a | |
![]() |
7ef3df046b | |
![]() |
7d8a9d5a64 | |
![]() |
49043c097c | |
![]() |
ffb0c189e4 | |
![]() |
cf77d4398b | |
![]() |
67a9a34dfa | |
![]() |
a248e403d6 | |
![]() |
e502d5b656 | |
![]() |
e6bc023301 | |
![]() |
93186fb640 | |
![]() |
d219cccb49 | |
![]() |
8934925019 | |
![]() |
dd117dc47f | |
![]() |
44a36b7950 | |
![]() |
a3fd06019e | |
![]() |
c5e9f51523 | |
![]() |
2a46b30940 | |
![]() |
38217c032f | |
![]() |
959d551b34 | |
![]() |
ab20fa00ca | |
![]() |
ce78157274 | |
![]() |
651aa9e4a5 | |
![]() |
2db8e74050 | |
![]() |
06b13db0e5 | |
![]() |
40ea3c8435 | |
![]() |
72b3c8d375 | |
![]() |
e1424ba86c | |
![]() |
9cd9f8ab58 | |
![]() |
d4c92e2f8a | |
![]() |
583fa3089d | |
![]() |
ca086a3b85 | |
![]() |
9b7fd520cb | |
![]() |
711d596793 | |
![]() |
f8972f1772 | |
![]() |
91ced7c47f | |
![]() |
e6c0897328 | |
![]() |
ab70394898 | |
![]() |
0ebac3b4af | |
![]() |
451366ab66 | |
![]() |
715b2a0c4c | |
![]() |
53622dc5f0 | |
![]() |
16e20312dd | |
![]() |
7e1c184144 | |
![]() |
1a7bb26c39 | |
![]() |
66d36f5989 | |
![]() |
481642bc65 | |
![]() |
dd0286c96c | |
![]() |
391f277360 | |
![]() |
fd4aa08333 | |
![]() |
0589adbb56 | |
![]() |
d7e57c83bf | |
![]() |
1a4423e9c8 | |
![]() |
d8578f1f58 | |
![]() |
1fcd48722a | |
![]() |
2a0edb3c90 | |
![]() |
680c4b3b00 | |
![]() |
72108f36d2 | |
![]() |
07bc70c16f | |
![]() |
931d45d026 | |
![]() |
20a9a469f6 | |
![]() |
1f076df6ce | |
![]() |
20fe8c2e8a | |
![]() |
d3915c5f8b | |
![]() |
703a3266b2 | |
![]() |
c986a7eb1a | |
![]() |
d4c5831828 | |
![]() |
385a2cdaa8 | |
![]() |
b2341c6137 | |
![]() |
6c019ad77a | |
![]() |
7e70ed64bb | |
![]() |
953ced2c6c | |
![]() |
7bae874515 | |
![]() |
7c082ecaa3 | |
![]() |
3af6e8075b | |
![]() |
bc1d031b29 | |
![]() |
9e8a66a006 | |
![]() |
676c90a0f0 | |
![]() |
32246bac4a | |
![]() |
99473f8d9b | |
![]() |
8fd41a18a6 | |
![]() |
ecbdbf21df | |
![]() |
ce279995de | |
![]() |
bab64f3c94 | |
![]() |
a570e7a054 | |
![]() |
44ff6e97b4 | |
![]() |
e3b223d046 | |
![]() |
3a74300a72 | |
![]() |
ab8f50eae2 | |
![]() |
0accc4eaf8 | |
![]() |
6cf200b1e1 | |
![]() |
14c011d8de | |
![]() |
523d2713f9 | |
![]() |
8c6e56e679 | |
![]() |
cb1d7d2f23 | |
![]() |
f78ce4e966 | |
![]() |
47910a5264 | |
![]() |
8b7a7f9b50 | |
![]() |
1d9c7c6bc4 | |
![]() |
388c5253e3 | |
![]() |
ea3e02d098 | |
![]() |
f7e0c34ef3 | |
![]() |
c151e6983c | |
![]() |
831893aac7 | |
![]() |
2be3bc944c | |
![]() |
cc94f7abf8 | |
![]() |
f8743f1412 | |
![]() |
857fb4f7f7 | |
![]() |
084dfbf703 | |
![]() |
e524718237 | |
![]() |
49bc297032 | |
![]() |
d0bfdc0a02 | |
![]() |
96db719b0c | |
![]() |
ab61e64ac2 | |
![]() |
d3d573d777 | |
![]() |
91f19f2521 | |
![]() |
dd649aafa2 | |
![]() |
86bd06801f | |
![]() |
f7799d4b2e | |
![]() |
99483fc4f7 | |
![]() |
ce48f43c89 | |
![]() |
75b285b45c | |
![]() |
1b8eaa9501 | |
![]() |
34c2ff9e23 | |
![]() |
860ad0caa5 | |
![]() |
56403c75af | |
![]() |
6740d478b2 | |
![]() |
7f418a40e0 | |
![]() |
8e53ad6bd7 | |
![]() |
dd321a27e1 | |
![]() |
3ac9b07639 | |
![]() |
3fb9b04bfe | |
![]() |
25d84132f7 | |
![]() |
23087b4c0c | |
![]() |
c0ea64bed8 | |
![]() |
6769ec30ac | |
![]() |
b7a55e65e8 | |
![]() |
460aa6d04a | |
![]() |
c368300c05 | |
![]() |
158852cea2 | |
![]() |
d9534edf36 | |
![]() |
6828c1f746 | |
![]() |
407fa8f157 | |
![]() |
1bc975995f | |
![]() |
fbb877874f | |
![]() |
fd1b12dbc1 | |
![]() |
644e4a7b71 | |
![]() |
fd10aa872f | |
![]() |
87a167983e | |
![]() |
9828dc1ce7 | |
![]() |
8a6520e549 | |
![]() |
22e68e57a6 | |
![]() |
50f238c98c | |
![]() |
b3caff23d2 | |
![]() |
998787e921 | |
![]() |
54f771536e | |
![]() |
b14a3a592b | |
![]() |
35ed3204a7 | |
![]() |
68313ef467 | |
![]() |
0b704f27a2 | |
![]() |
4b50a9ec03 | |
![]() |
bec8aa50de | |
![]() |
b2289368a3 | |
![]() |
27b89f03ae | |
![]() |
889c449bbb | |
![]() |
04778112f6 | |
![]() |
2609e7391c | |
![]() |
8d60c75448 | |
![]() |
c24d88fa35 | |
![]() |
f710b64523 | |
![]() |
d729e8dbad | |
![]() |
5aef7a1010 | |
![]() |
359ed207fe | |
![]() |
df5bf19909 | |
![]() |
584ab583b7 | |
![]() |
ea70941994 | |
![]() |
0c671d2a4b | |
![]() |
5f4d43f738 | |
![]() |
e1d70a6f76 | |
![]() |
9c4a2dc20c | |
![]() |
5e42454cf4 | |
![]() |
60276cdf2e | |
![]() |
0a07f61db0 | |
![]() |
a9a0412a69 | |
![]() |
6e937faaf0 | |
![]() |
50665860b3 | |
![]() |
41a10c95f5 | |
![]() |
e05c17dfbb | |
![]() |
fce7cb2701 | |
![]() |
c5458e7509 | |
![]() |
489556e656 | |
![]() |
2988bb303f | |
![]() |
6e8850c903 | |
![]() |
ce8b6bc7b9 | |
![]() |
399f024fcb | |
![]() |
adeec7e38f | |
![]() |
a8ff7220cc | |
![]() |
6e36bfe1fd | |
![]() |
8167bff3c4 | |
![]() |
fd7f8f0ef6 | |
![]() |
17d4b20115 | |
![]() |
54193cc623 | |
![]() |
c20c88bdbc | |
![]() |
bb7d9f16a4 | |
![]() |
c9db2532a2 | |
![]() |
abcd172c83 | |
![]() |
8b5aa23605 | |
![]() |
dee58ee4b8 | |
![]() |
eb2b400ea8 | |
![]() |
27ad47f155 | |
![]() |
1e67b897d4 | |
![]() |
c170681139 | |
![]() |
621ebaad0d | |
![]() |
81f18cab30 | |
![]() |
d5b938452c | |
![]() |
a39c62b129 | |
![]() |
88f0549e85 | |
![]() |
c4be07bc87 | |
![]() |
5e3cb11c83 | |
![]() |
e007f422f4 | |
![]() |
7532a5d66e | |
![]() |
c2291bfee6 | |
![]() |
aa32f62368 | |
![]() |
c0ebfc43f0 | |
![]() |
07806eb836 | |
![]() |
90d57bf8ce | |
![]() |
525541d037 | |
![]() |
128305c5fd | |
![]() |
339eb9973c | |
![]() |
4029f105d8 | |
![]() |
7324afeafd | |
![]() |
e3c0aadb86 | |
![]() |
04e66de722 | |
![]() |
3043d4045e | |
![]() |
0069c02e73 | |
![]() |
d0ed6ae79c | |
![]() |
8e75d3521a | |
![]() |
00b5148274 | |
![]() |
c99e7dc2e5 | |
![]() |
fc8b2dbfc2 | |
![]() |
8bef7cfa68 | |
![]() |
6c3b1059b0 | |
![]() |
fbab1c2b5f | |
![]() |
84f637865f | |
![]() |
194723d96d | |
![]() |
52b7454046 | |
![]() |
4015411ad6 | |
![]() |
77da6267bf | |
![]() |
057703e529 | |
![]() |
ea08d4aa84 | |
![]() |
c9e2db0250 | |
![]() |
2254c143ed | |
![]() |
81cf844df6 | |
![]() |
d6fb00bb84 | |
![]() |
d1fe3e3c21 | |
![]() |
bf124165f7 | |
![]() |
64e0b8a2af | |
![]() |
07bdf7d148 | |
![]() |
13fbc2ea8e | |
![]() |
bd04d8e9bb | |
![]() |
28ff237695 | |
![]() |
a10305e786 | |
![]() |
573f321508 | |
![]() |
f1fa6973ab | |
![]() |
6dd74f9fd2 | |
![]() |
ea35450d02 | |
![]() |
71158e5081 | |
![]() |
b8694398f6 | |
![]() |
c0ea499806 | |
![]() |
131603c25b | |
![]() |
27ce7acf63 | |
![]() |
0eaef3ea53 | |
![]() |
d78cc99dab | |
![]() |
3790d1d52e | |
![]() |
14fd8ae6eb | |
![]() |
8952a9005e | |
![]() |
9bd1b7e691 | |
![]() |
517d31bae9 | |
![]() |
66b71553d0 | |
![]() |
309cb2418a | |
![]() |
ea5abf672e | |
![]() |
d9b6e86c40 | |
![]() |
146f8b43df | |
![]() |
ffeb6b97f0 | |
![]() |
74e0fabca9 | |
![]() |
2c3cef961c | |
![]() |
11e417f55a | |
![]() |
7219f88382 | |
![]() |
74702bae5a | |
![]() |
bb85744a6f | |
![]() |
642ce3a115 | |
![]() |
66c895dca4 | |
![]() |
ae940c79e1 | |
![]() |
de427321ab | |
![]() |
2ed7ef8c89 | |
![]() |
6ada678c69 | |
![]() |
e41741f457 | |
![]() |
45d7f2aef9 | |
![]() |
c6a8854e92 | |
![]() |
8339abdd71 | |
![]() |
c04caafcbf | |
![]() |
db610129bb | |
![]() |
9828895c53 | |
![]() |
c48ef684f6 | |
![]() |
ef6717c210 | |
![]() |
2f1c14fe33 | |
![]() |
1ba3351f6e | |
![]() |
b5dfdc501c | |
![]() |
aa08c20987 | |
![]() |
443fa0c50f | |
![]() |
c0b302f4e4 | |
![]() |
3856c0c5e9 | |
![]() |
9fe5205b2e | |
![]() |
2d5889eaa8 | |
![]() |
acadc2f784 | |
![]() |
c16bf09a68 | |
![]() |
188a7e54c4 | |
![]() |
c2943e28d9 | |
![]() |
908f4116a7 | |
![]() |
689d9a94df | |
![]() |
5676772a6c | |
![]() |
a88b22e547 | |
![]() |
a086c21ba7 | |
![]() |
123743fa57 | |
![]() |
359aafba57 | |
![]() |
1559e84d0d | |
![]() |
2228a8de13 | |
![]() |
3f3e086d61 | |
![]() |
f95c64cc6a | |
![]() |
0d36fecf93 | |
![]() |
3abc58ae36 | |
![]() |
17fe2472a2 | |
![]() |
6d4e256d2b | |
![]() |
81b885777c | |
![]() |
a61483d87d | |
![]() |
06e4bcfbb1 | |
![]() |
2a90946ff5 | |
![]() |
488fc951d0 | |
![]() |
c24caade3e | |
![]() |
4a19bac748 | |
![]() |
119deba104 | |
![]() |
7a2b970aff | |
![]() |
2d6477ce1b | |
![]() |
6c00a49806 | |
![]() |
e9d75ad573 | |
![]() |
f9592ea6d1 | |
![]() |
d8b3a0581d | |
![]() |
706af15ebe | |
![]() |
e96e14d8e6 | |
![]() |
305da3d38a | |
![]() |
2d9bd66224 | |
![]() |
894458bc53 | |
![]() |
a3cbf8ea01 | |
![]() |
194ee3f339 | |
![]() |
ec25feee98 | |
![]() |
062a228877 | |
![]() |
baef153e05 | |
![]() |
f71921404c | |
![]() |
087e9ae5ed | |
![]() |
ca6c0db294 | |
![]() |
dd505213be | |
![]() |
f6d2ca247e | |
![]() |
ecf5b68df6 | |
![]() |
dbe2226498 | |
![]() |
ccf3535154 | |
![]() |
b5d9628a7d | |
![]() |
bb8e239206 | |
![]() |
b4c4d55ce2 | |
![]() |
6297f00247 | |
![]() |
68cf6f1e5e | |
![]() |
3c5ad7c896 | |
![]() |
e482c772e2 | |
![]() |
24a040ef2b | |
![]() |
ffa4adfc47 | |
![]() |
3e9dd9d6c0 | |
![]() |
980a06f871 | |
![]() |
00d535f9d3 | |
![]() |
d8fde20f85 | |
![]() |
55a208d0ee | |
![]() |
3f291c8e6a | |
![]() |
3c0646c423 | |
![]() |
71441a541d | |
![]() |
646998871e | |
![]() |
da1bc169a1 | |
![]() |
9735a8a1fd | |
![]() |
aa84f1529e | |
![]() |
6275b5d746 | |
![]() |
7f13b77a78 | |
![]() |
28435d9334 | |
![]() |
b54420e5a7 | |
![]() |
2e592dca73 | |
![]() |
215a6cb6fa | |
![]() |
8ea1fc16c7 | |
![]() |
47bea83c76 | |
![]() |
cb09cf5170 | |
![]() |
633a5638a7 | |
![]() |
c0fc487be3 | |
![]() |
5c61957e10 | |
![]() |
8b4736e078 | |
![]() |
a6b05cf101 | |
![]() |
01af8a7453 | |
![]() |
f152bd98bb | |
![]() |
875d4ae2a6 | |
![]() |
048d2318a0 | |
![]() |
319f68ac68 | |
![]() |
b7ffd2a806 | |
![]() |
80a2a480c3 | |
![]() |
218319d5f9 | |
![]() |
3453ac71d4 | |
![]() |
075455d407 | |
![]() |
8f1eb173e5 | |
![]() |
4fc72bb5e2 | |
![]() |
6739397035 | |
![]() |
67010790e1 | |
![]() |
69ac706959 | |
![]() |
ff2de2bc58 | |
![]() |
e5979f2bc1 | |
![]() |
9c6426aae4 | |
![]() |
7365c9e6ea | |
![]() |
c87812a0db | |
![]() |
dd05ece216 | |
![]() |
2802c9a16f | |
![]() |
1e28d6aebe | |
![]() |
6cd699f684 | |
![]() |
64350887cc | |
![]() |
04f79fb224 | |
![]() |
71a84795b1 | |
![]() |
187bb950f3 | |
![]() |
7246a12ced | |
![]() |
2d31b5bb8d | |
![]() |
4ccb09d36d | |
![]() |
3307f91dcf | |
![]() |
0b9b7dab23 | |
![]() |
1cf0998d34 | |
![]() |
7647ebbccd | |
![]() |
073b71a46e | |
![]() |
d0200bdbcd | |
![]() |
fbc2d8e296 | |
![]() |
ba33e8aa6b | |
![]() |
fd20b10c90 | |
![]() |
f63909b1d9 | |
![]() |
b6c16bdb0c | |
![]() |
867c17d7a3 | |
![]() |
e2a29f6c3e | |
![]() |
11983ace12 | |
![]() |
f6f4719115 | |
![]() |
078ac3bea0 | |
![]() |
2288f5fdf4 | |
![]() |
0211a78a8e | |
![]() |
c2751af7f5 | |
![]() |
5d40f08ce2 | |
![]() |
09c7e4bf2c | |
![]() |
275cf18417 | |
![]() |
c0e17f2a2b | |
![]() |
b9e0eee019 | |
![]() |
082b8a1e92 | |
![]() |
7459a4a0db | |
![]() |
d4b9473034 | |
![]() |
4eb59b05c1 | |
![]() |
740fbdf6f6 | |
![]() |
24b0d4cc74 | |
![]() |
5d2a46c1ad | |
![]() |
20bbb21f56 | |
![]() |
b671d2dc37 | |
![]() |
8f2825ca2f | |
![]() |
2a9f14b516 | |
![]() |
6e05ab43a1 | |
![]() |
a0c9689b6f | |
![]() |
8495cce7d8 | |
![]() |
9fd39b42be | |
![]() |
b6e6cfd1f0 | |
![]() |
40ac90fa14 | |
![]() |
a30f22976a | |
![]() |
02915ec2d6 | |
![]() |
4c42b9ebaf | |
![]() |
52340b1f18 | |
![]() |
a266b8239d | |
![]() |
04af01a1ef | |
![]() |
fb1bde8d41 | |
![]() |
da7cb2fede | |
![]() |
1119a788ef | |
![]() |
11509592e4 | |
![]() |
4dea9cc186 | |
![]() |
321873924b | |
![]() |
9445a175fc | |
![]() |
7500bd0611 | |
![]() |
2b83987056 | |
![]() |
5a0f4d989a | |
![]() |
a57fd04002 | |
![]() |
c3d97b7854 | |
![]() |
fa63c0da88 | |
![]() |
515d4e9987 | |
![]() |
8074480ba4 | |
![]() |
0046fa5c41 | |
![]() |
845917c43b | |
![]() |
6016b74e94 | |
![]() |
572365617d | |
![]() |
ceea17083d | |
![]() |
cb75fa85fb | |
![]() |
bc91ee7d50 | |
![]() |
b194f3566b | |
![]() |
bff9cfdd5e | |
![]() |
f99e9e1456 | |
![]() |
9facabe8a1 | |
![]() |
44d89dfcc5 | |
![]() |
52f43889b3 | |
![]() |
c742ca7c82 | |
![]() |
8a099f51be | |
![]() |
d3ccd7e968 | |
![]() |
f6b07a41e8 | |
![]() |
c5e0f2500e | |
![]() |
78d17e31e8 | |
![]() |
1af7d5e9ec | |
![]() |
a18ecb3527 | |
![]() |
faa55cf1f7 | |
![]() |
20b89b2b49 | |
![]() |
918afdcb2b | |
![]() |
eac2b05c70 | |
![]() |
92464f0c84 | |
![]() |
3c184e0cfd | |
![]() |
07df6a630a | |
![]() |
bcf3b9be14 | |
![]() |
d647b9f481 | |
![]() |
fc43f75b70 | |
![]() |
8ca0cddb7c | |
![]() |
1b44158f75 | |
![]() |
d489599bc6 | |
![]() |
7789ebb3f1 | |
![]() |
263617e84b | |
![]() |
6b9f3f6b5b | |
![]() |
dd704aa865 | |
![]() |
197392788a | |
![]() |
d8cb1ea638 | |
![]() |
e9ebd7df18 | |
![]() |
af53b8e106 | |
![]() |
41a953f4a6 | |
![]() |
15b2a7cbc1 | |
![]() |
643d8f460c | |
![]() |
83d9d24747 | |
![]() |
642cbae742 | |
![]() |
4489fcd31f | |
![]() |
0340f67a5f | |
![]() |
6550d01a86 | |
![]() |
a410b2f610 | |
![]() |
7dc2c12bc8 | |
![]() |
ec3a46782a | |
![]() |
869ecc2788 | |
![]() |
c46ab0ca31 | |
![]() |
f192604d10 | |
![]() |
35b67fb337 | |
![]() |
1dcbe7b83a | |
![]() |
959207cbeb | |
![]() |
c64e50151e | |
![]() |
6cc044c496 | |
![]() |
1f0cadcfe8 | |
![]() |
e89c997958 | |
![]() |
792d1ba728 | |
![]() |
3f80c39f33 | |
![]() |
fa2afc6386 | |
![]() |
b9f520a85a | |
![]() |
6d66840326 | |
![]() |
bd0f5f9eb2 | |
![]() |
05b10e8faa | |
![]() |
8477368c41 | |
![]() |
33e735a926 | |
![]() |
8028559d84 | |
![]() |
fbf63505cf | |
![]() |
a55e58a804 | |
![]() |
a2897ac198 | |
![]() |
caf0952774 | |
![]() |
f7e9eb8598 | |
![]() |
ada3cc8c59 | |
![]() |
258f1fb2c3 | |
![]() |
c248dd4f1d | |
![]() |
f60a8de07d | |
![]() |
b481b8d5d9 | |
![]() |
dfcbea4161 | |
![]() |
8d4a505f72 | |
![]() |
7ca7824ebf | |
![]() |
a2b08efbd7 | |
![]() |
2a86619492 | |
![]() |
ff8be953a9 | |
![]() |
e2206215bf | |
![]() |
0579983459 | |
![]() |
eb05c12759 | |
![]() |
e91c8f89c1 | |
![]() |
8a020c11ba | |
![]() |
5688e953ca | |
![]() |
08628592cf | |
![]() |
b7f41c4ff1 | |
![]() |
f02500bf67 | |
![]() |
827322a013 | |
![]() |
1382b51492 | |
![]() |
5b83d55092 | |
![]() |
ae6f134406 | |
![]() |
3ed0604e12 | |
![]() |
728db76bde | |
![]() |
4175f299d3 | |
![]() |
9000a56039 | |
![]() |
8aa6cce8cb | |
![]() |
a8bed32619 | |
![]() |
99e1e3b5d5 | |
![]() |
808c6f8d3d | |
![]() |
d6532cfbe2 | |
![]() |
d6e495da98 | |
![]() |
e2e74e9b3e | |
![]() |
1019c9bb46 | |
![]() |
748c4c810b | |
![]() |
9ac2a2a48f | |
![]() |
27e9db8c6b | |
![]() |
1de4517874 | |
![]() |
63a893a277 | |
![]() |
b18e0dcb15 | |
![]() |
45f129f229 | |
![]() |
0ef0afed15 | |
![]() |
1c1dd8bb30 | |
![]() |
947356fbe1 | |
![]() |
5e3e6f8676 | |
![]() |
7d69942bbb | |
![]() |
71eac340d5 | |
![]() |
d5dc1f45b1 | |
![]() |
3cf5ec430a | |
![]() |
53aaa6850f | |
![]() |
1828745e5d | |
![]() |
28164e5bb2 | |
![]() |
333a10a655 | |
![]() |
7dbe16b4c4 | |
![]() |
952440b17d | |
![]() |
1b24d34ad2 | |
![]() |
8ff221a8fa | |
![]() |
d38623350f | |
![]() |
817e6af268 | |
![]() |
f9caa9490a | |
![]() |
d8d593d048 | |
![]() |
7d7a6c4bfa | |
![]() |
38fca0bb3c | |
![]() |
77a8d25a13 | |
![]() |
a208def471 | |
![]() |
72f363a4fb | |
![]() |
343c013385 | |
![]() |
b95d041976 | |
![]() |
7cb5d48907 | |
![]() |
20c2734317 | |
![]() |
b3a1dde141 | |
![]() |
3499207db6 | |
![]() |
cd5560b966 | |
![]() |
ad8fe45f83 | |
![]() |
d5aef7da1d | |
![]() |
f4fb58d0ff | |
![]() |
327dc2c2b9 | |
![]() |
fb6bf65dfd | |
![]() |
7f483fcab4 | |
![]() |
43b31e3f0c | |
![]() |
19fa692af8 | |
![]() |
c2f70995b4 | |
![]() |
5e51f9f1b4 | |
![]() |
37fdc95e87 | |
![]() |
84f01716a1 | |
![]() |
40d5c4a485 | |
![]() |
1ce2cb86f5 | |
![]() |
9c2369fac6 | |
![]() |
f1aa73d511 | |
![]() |
3ae63b6a0a | |
![]() |
814078f2ae | |
![]() |
a5ea4e0cc8 | |
![]() |
92ded778aa | |
![]() |
d55b3836ee | |
![]() |
26302fda39 | |
![]() |
f3a0332bc3 | |
![]() |
2d622d98e0 | |
![]() |
7b4804b878 | |
![]() |
29ac31a5a4 | |
![]() |
d8d3cd7dc0 | |
![]() |
5c7d20450f | |
![]() |
f33e81f7c3 | |
![]() |
beecc55eb0 | |
![]() |
fa588a6abb | |
![]() |
d19917f31b | |
![]() |
cc12f72058 | |
![]() |
7d670af6da | |
![]() |
e910b610dc | |
![]() |
7c2cb8223f | |
![]() |
81db33cb4a | |
![]() |
df666957da | |
![]() |
e81787b703 | |
![]() |
34a92d859f | |
![]() |
aa8baf0686 | |
![]() |
7253fe7775 | |
![]() |
aa2b5b75c8 | |
![]() |
05563cf9c7 | |
![]() |
0de92a1a4d | |
![]() |
85153d0f31 | |
![]() |
2d288f338f | |
![]() |
d963afde7f | |
![]() |
2fd1266680 | |
![]() |
eb0bc23d6e | |
![]() |
5211cea5b8 | |
![]() |
2ae4e618e5 | |
![]() |
016a543ef3 | |
![]() |
307fdf527f | |
![]() |
6a743748e4 | |
![]() |
ec89bf7ca1 | |
![]() |
6323e05bd6 | |
![]() |
698cfe1f93 | |
![]() |
4bbb85bb83 | |
![]() |
620618d22b | |
![]() |
41aa900bb7 | |
![]() |
57dbe9128d | |
![]() |
250bcd5b18 | |
![]() |
39e13e6612 | |
![]() |
eb960e1e39 | |
![]() |
8cf301fd25 | |
![]() |
ca9f2fec36 | |
![]() |
1c886d15b1 | |
![]() |
47e27cffa5 | |
![]() |
c6c2ec7137 | |
![]() |
e9537e2468 | |
![]() |
ce9523d39c | |
![]() |
0ef9b64379 | |
![]() |
3edf67ae85 | |
![]() |
4e41817906 | |
![]() |
29cc1443ac | |
![]() |
1e55bc3832 | |
![]() |
133b9866b6 | |
![]() |
522ef7db4d | |
![]() |
cbf3d47bcb | |
![]() |
3ccc9ae7dd | |
![]() |
47b2f84711 | |
![]() |
679669e1d0 | |
![]() |
e461cc9ce5 | |
![]() |
3c3b9a4a23 | |
![]() |
af0c060a7a | |
![]() |
a5218faeba | |
![]() |
1d13bcb323 | |
![]() |
4fb93568de | |
![]() |
2d9968e2eb | |
![]() |
0baa5914a5 | |
![]() |
ca1ad0bfba | |
![]() |
5e78d6a888 | |
![]() |
fec0ae896e | |
![]() |
ca540cb6b6 | |
![]() |
89df112dd8 | |
![]() |
503108cfa1 | |
![]() |
3e53a28f3c | |
![]() |
e347ab6c90 | |
![]() |
13fb9e8a2f | |
![]() |
761f9232b2 | |
![]() |
5e2b6b5582 | |
![]() |
caf05e22ea | |
![]() |
d807f08fcc | |
![]() |
86093ba19f | |
![]() |
58ea43bf2e | |
![]() |
058b218e59 | |
![]() |
ef590739da | |
![]() |
de794ec6e8 | |
![]() |
52e26afa32 | |
![]() |
6acc3e0d65 | |
![]() |
6365f26d7d | |
![]() |
1a6079ce4d | |
![]() |
6a3591bb84 | |
![]() |
95c441ea0c | |
![]() |
cf04a5e589 | |
![]() |
53ec75c9b0 | |
![]() |
4c1061b84b | |
![]() |
7904345439 | |
![]() |
67117c1280 | |
![]() |
ea8ecd9dc2 | |
![]() |
f1a573079a | |
![]() |
7fe0f62617 | |
![]() |
4fa564f062 | |
![]() |
229055cb0e | |
![]() |
305eb40c1e | |
![]() |
ffb5de877d | |
![]() |
e5f35a5f3e | |
![]() |
7bea1697c3 | |
![]() |
9fbac3e7bc | |
![]() |
7cd0426a37 | |
![]() |
ace96ce5e0 | |
![]() |
29297644ac | |
![]() |
3844e866e0 | |
![]() |
5c5be96f52 | |
![]() |
10ebeb093f | |
![]() |
2b574440ab | |
![]() |
d33cfa55a5 | |
![]() |
3bc7efc516 | |
![]() |
5428c3614a | |
![]() |
1215be45c0 | |
![]() |
7ff78b6215 | |
![]() |
0876ae03d4 | |
![]() |
756b4fd8eb | |
![]() |
113615af35 | |
![]() |
b0669283e7 | |
![]() |
a8a53aa82e | |
![]() |
9956cab1d4 | |
![]() |
1ba78a6ea3 | |
![]() |
d3bb120ebe | |
![]() |
c7bd2c7cbd | |
![]() |
7b49f8923b | |
![]() |
3b1591abe2 | |
![]() |
6047ff9c72 | |
![]() |
dd00cbd1b7 | |
![]() |
fde0833da2 | |
![]() |
ae847d37e2 | |
![]() |
e80b91bd56 | |
![]() |
ed89660799 | |
![]() |
550a71e640 | |
![]() |
3dbed90795 | |
![]() |
0c937d7f98 | |
![]() |
3fd744b810 | |
![]() |
ece807b605 | |
![]() |
dc86077865 | |
![]() |
5936de5a32 | |
![]() |
63200b09c8 | |
![]() |
f085acf680 | |
![]() |
871f7b3aee | |
![]() |
f068dfda3b | |
![]() |
7c24040c97 | |
![]() |
cd564d1a8f | |
![]() |
9ff5be6f67 | |
![]() |
edbfe3f066 | |
![]() |
821141414c | |
![]() |
e62fa0e2bb | |
![]() |
131a3a989b | |
![]() |
4485db61eb | |
![]() |
2915400b9b | |
![]() |
1f6b5a2f6d | |
![]() |
68c8951648 | |
![]() |
90b14dccfd | |
![]() |
54350d19b3 | |
![]() |
f6cf1e4ee1 | |
![]() |
832d168be0 | |
![]() |
1de5957a3e | |
![]() |
23c6438dc0 | |
![]() |
34ea5aaa5f | |
![]() |
152a7b132f | |
![]() |
300a8b996d | |
![]() |
444c3a0b0a | |
![]() |
642baafe9d | |
![]() |
7c386f0310 | |
![]() |
cec7b68614 | |
![]() |
8057953b1c | |
![]() |
cb18c55aa2 | |
![]() |
a13f65d415 | |
![]() |
4832522315 | |
![]() |
712b23d512 | |
![]() |
a30cf51c7d | |
![]() |
fbbe9da5ef | |
![]() |
2bf05b75fb | |
![]() |
0ce99ce869 | |
![]() |
ffb4ea538c | |
![]() |
cee2f02928 | |
![]() |
a71f16f390 | |
![]() |
0ed4e21eed | |
![]() |
43f7306752 | |
![]() |
1e316e7008 | |
![]() |
dc28399028 | |
![]() |
e9708f7595 | |
![]() |
5263070da5 | |
![]() |
2e4026e86d | |
![]() |
744668e821 | |
![]() |
a843ff2f22 | |
![]() |
c7bd555cc0 | |
![]() |
e8c5cffe03 | |
![]() |
54d6fad245 | |
![]() |
5317608340 | |
![]() |
af8f69ccb9 | |
![]() |
99f5c1dc0a | |
![]() |
0cc0e4739b | |
![]() |
4798e034f8 | |
![]() |
1366b34d4e | |
![]() |
90eaff428d | |
![]() |
7bfbd6b887 | |
![]() |
6a1ff20e07 | |
![]() |
4702c15820 | |
![]() |
6b0d234643 | |
![]() |
89d9ebbbd2 | |
![]() |
c52a03f95e | |
![]() |
1719e1eb41 | |
![]() |
ad388e0610 | |
![]() |
ba719bf431 | |
![]() |
f8141e77b4 | |
![]() |
8a772475f8 | |
![]() |
243f7cd58c | |
![]() |
be5cc2152c | |
![]() |
9abd38ff8e | |
![]() |
d67d0b7714 | |
![]() |
e6ad57be22 | |
![]() |
3dd9e0a27c | |
![]() |
3348cdf6e2 | |
![]() |
01cbda9a1c | |
![]() |
3dd0ee91d0 | |
![]() |
a6f99da9cf | |
![]() |
81743d139c | |
![]() |
cca48b9a34 | |
![]() |
75e749ecf9 | |
![]() |
b8aea4ffaa | |
![]() |
b2764f5bc3 | |
![]() |
69dabb3c02 | |
![]() |
7b1af20be4 | |
![]() |
28b1fcdcd6 | |
![]() |
f65e0e223c | |
![]() |
686c52b34c | |
![]() |
01daf40120 | |
![]() |
1e598f014c | |
![]() |
822552b138 | |
![]() |
cc0c3c4e26 | |
![]() |
ff59371827 | |
![]() |
7704d2fd80 | |
![]() |
ada2d9ce12 | |
![]() |
3708a80b54 | |
![]() |
18b3701693 | |
![]() |
4f887b912d | |
![]() |
594b1316a6 | |
![]() |
5f2c541ada | |
![]() |
41dc477e74 | |
![]() |
f1ea9cca7a | |
![]() |
d988ba6192 | |
![]() |
78f07fd7aa | |
![]() |
9987bd13f8 | |
![]() |
f464846c3c | |
![]() |
f6cde624f4 | |
![]() |
4c446543b4 | |
![]() |
94c9f45b88 | |
![]() |
61e4c0bddc | |
![]() |
c89f3a86bd | |
![]() |
3b7a0e79b5 | |
![]() |
e678242556 | |
![]() |
a413a17260 | |
![]() |
f6c5dce881 | |
![]() |
05d9c1b169 | |
![]() |
651ed760b7 | |
![]() |
571af5c2d7 | |
![]() |
39d123cbfc | |
![]() |
d3de70b80d | |
![]() |
57feffc70d | |
![]() |
76885cefc2 | |
![]() |
f422c236d3 | |
![]() |
b7d4a8b352 | |
![]() |
1849ac85d1 | |
![]() |
df48d9a889 | |
![]() |
e30b3fea70 | |
![]() |
b4ec5d6748 | |
![]() |
153cb5e386 | |
![]() |
7704899055 | |
![]() |
48a3dc398a | |
![]() |
5f22118a6f | |
![]() |
5abdb2faed | |
![]() |
7a266f75b2 | |
![]() |
7180336b20 | |
![]() |
823b57c6db | |
![]() |
6a03c7ff09 | |
![]() |
a05659a208 | |
![]() |
d4afa548de | |
![]() |
6b82719eb0 | |
![]() |
438800961e | |
![]() |
ea58962012 | |
![]() |
9304d34bf8 | |
![]() |
7fd9817cdb | |
![]() |
19d5e1c354 | |
![]() |
e3d3b1407f | |
![]() |
f01283e4af | |
![]() |
654952bcf8 | |
![]() |
e585142003 | |
![]() |
ee53e4c03a | |
![]() |
0e94d6ee51 | |
![]() |
6889b87605 | |
![]() |
151ebfc21f | |
![]() |
2684c683a8 | |
![]() |
df99182300 | |
![]() |
da9cfbe200 | |
![]() |
b831e49635 | |
![]() |
0e48ce4d99 | |
![]() |
8ecd2ee393 | |
![]() |
2c154a932a | |
![]() |
751825a009 | |
![]() |
62334ef6c0 | |
![]() |
563c4c5a45 | |
![]() |
6365619445 | |
![]() |
25e07dfc79 | |
![]() |
6e6e97c551 | |
![]() |
eeed006c67 | |
![]() |
7e31cf4dab | |
![]() |
813a3bbbff | |
![]() |
1704c79067 | |
![]() |
878bd69a0e | |
![]() |
6ce60f84e6 | |
![]() |
c24884c363 | |
![]() |
298b9fbabb | |
![]() |
0e88f49326 | |
![]() |
47ab70f48e | |
![]() |
08ae197fed | |
![]() |
b54baa86c6 | |
![]() |
1a5944f90c | |
![]() |
5debaa0857 | |
![]() |
96113b7ee4 | |
![]() |
2863925859 | |
![]() |
150dbbbdaf | |
![]() |
d9f5a46a6a | |
![]() |
5029f2058c | |
![]() |
caf463b302 | |
![]() |
187d9a8dbc | |
![]() |
97789af476 | |
![]() |
f054fc3da6 | |
![]() |
fc8f4f694f | |
![]() |
6aa80c44cf | |
![]() |
d8601e00a3 | |
![]() |
f1e58b3c92 | |
![]() |
2474633f79 | |
![]() |
6e3963d1ca | |
![]() |
274d8178aa | |
![]() |
d608b190dd | |
![]() |
4269612bb4 | |
![]() |
85ca9b12e3 | |
![]() |
9fa2003bc5 | |
![]() |
a2c33d0d35 | |
![]() |
8b13beb5ee | |
![]() |
c292d7d9e3 | |
![]() |
0854f57647 | |
![]() |
17fa00685f | |
![]() |
b99da6e496 | |
![]() |
a81bd98c7a | |
![]() |
dd0d05928d | |
![]() |
ba4a4b1915 | |
![]() |
88303c627d | |
![]() |
804bf0bfcf | |
![]() |
75843be9c4 | |
![]() |
37b44bfb60 | |
![]() |
dc9fd91bf6 | |
![]() |
80ebb0dcd5 | |
![]() |
30c0e56fc9 | |
![]() |
95a80303b5 | |
![]() |
167386847d | |
![]() |
c95bc1c458 | |
![]() |
30502706ee | |
![]() |
45661199e6 | |
![]() |
ed3393987f | |
![]() |
5382dab908 | |
![]() |
dd60bc24a3 | |
![]() |
07e090c224 | |
![]() |
a48b1a725d | |
![]() |
9821e2342f | |
![]() |
a165e5b1c3 | |
![]() |
dc9b05137e | |
![]() |
3d95e1061a | |
![]() |
031dde96d2 | |
![]() |
6feb15dd11 | |
![]() |
eedca01baa | |
![]() |
de49480ef5 | |
![]() |
0ab5605002 | |
![]() |
210de746fb | |
![]() |
9b96d80ecc | |
![]() |
9cd29c65bf | |
![]() |
4b2ae3ad5e | |
![]() |
d5858ba555 | |
![]() |
ba967c8fda | |
![]() |
c83531b12c | |
![]() |
12c709885b | |
![]() |
c2ddd1f83e | |
![]() |
1da5cc74ef | |
![]() |
475b4a77b2 | |
![]() |
907851c822 | |
![]() |
94717c5785 | |
![]() |
57d64f5bca | |
![]() |
ac933b2cfd | |
![]() |
1db8af1adb | |
![]() |
a5e2102033 | |
![]() |
4b7b652f47 | |
![]() |
97ac62d69f | |
![]() |
c62fe23941 | |
![]() |
ab0af7fa7e | |
![]() |
bb1e85a546 | |
![]() |
55676e4bb7 | |
![]() |
30ef5275d9 | |
![]() |
cdef916569 | |
![]() |
568682a3f0 | |
![]() |
df915330e7 | |
![]() |
64a4300ba2 | |
![]() |
7b0bddf64b | |
![]() |
f7d7b5242c | |
![]() |
2d0be6346c | |
![]() |
1230a55a4b | |
![]() |
7a5ac180de | |
![]() |
1f1507b9ef | |
![]() |
51c37da018 | |
![]() |
ae9cad072c | |
![]() |
d3bf30c646 | |
![]() |
4cb195abf8 | |
![]() |
3163f756b5 | |
![]() |
b231f48093 | |
![]() |
a077ddf472 | |
![]() |
748127d658 | |
![]() |
b8a2915c26 | |
![]() |
c3ee047c7e | |
![]() |
21f8b3fbcf | |
![]() |
c60ce7faa1 | |
![]() |
99fa5a3c76 | |
![]() |
430a6064b7 | |
![]() |
e1f77790cc | |
![]() |
fd09b81b07 | |
![]() |
4d6ac95a44 | |
![]() |
8009863daa | |
![]() |
8c7c89f036 | |
![]() |
cf92e9fcd6 | |
![]() |
85803255c3 | |
![]() |
a039a35122 | |
![]() |
32ca5e236e | |
![]() |
21e027bfa1 | |
![]() |
36a45e8cfc | |
![]() |
56f013a04c | |
![]() |
2baeab260d | |
![]() |
80296899f2 | |
![]() |
d1ccf402ad | |
![]() |
7f0616d4ba | |
![]() |
be311cbd44 | |
![]() |
928cf15312 | |
![]() |
d515af0367 | |
![]() |
f10f44b0ac | |
![]() |
1fb75500a0 | |
![]() |
443c3529d3 | |
![]() |
772d30531e | |
![]() |
6260a74e6d | |
![]() |
64dd5ac5ef | |
![]() |
2412eefa6f | |
![]() |
f588bcf10e | |
![]() |
f2918281a3 | |
![]() |
a6c84b7078 | |
![]() |
8910583330 | |
![]() |
3b866964db | |
![]() |
23a4437641 | |
![]() |
447aa2e144 | |
![]() |
3186220dfc | |
![]() |
061f375146 | |
![]() |
331c4ee269 | |
![]() |
bbae9c713e | |
![]() |
f3a0a5fd60 | |
![]() |
7c9647b954 | |
![]() |
dee9315f14 | |
![]() |
0a7e159408 | |
![]() |
9fe45a37de | |
![]() |
776d0aa72a | |
![]() |
823f0aebb2 | |
![]() |
85599d83e5 | |
![]() |
f302f00e0d | |
![]() |
c1c5ff3b0e | |
![]() |
62876b7be6 | |
![]() |
ab97b6c349 | |
![]() |
2e51fcbf1f | |
![]() |
3f4091d6fe | |
![]() |
eedb20b350 | |
![]() |
1191fafd18 | |
![]() |
5ce77db69f | |
![]() |
bc0cbc1f2e | |
![]() |
8d22c9363c | |
![]() |
7f65461438 | |
![]() |
d87ac68255 | |
![]() |
2a66e41ad5 | |
![]() |
303bf1747f | |
![]() |
1eed08c7ae | |
![]() |
3dca16b37a | |
![]() |
c3c3e48da7 | |
![]() |
962d1e5e2d | |
![]() |
4e53839385 | |
![]() |
b95a7cc921 | |
![]() |
f16052595d | |
![]() |
f955afe276 | |
![]() |
159f323068 | |
![]() |
311d723004 | |
![]() |
e974a64498 | |
![]() |
5f617ca6ef | |
![]() |
fabcf94d50 | |
![]() |
14efca22bd | |
![]() |
e51385c0bf | |
![]() |
44e6332c7b | |
![]() |
ff9f900413 | |
![]() |
ef3e819215 | |
![]() |
345cf53d4a | |
![]() |
e548c3c257 | |
![]() |
7a998d0d38 | |
![]() |
6d2ca3ee33 | |
![]() |
5ce4e91296 | |
![]() |
09448f9404 | |
![]() |
b6f31aabb4 | |
![]() |
fbd906ba8d | |
![]() |
96f784de02 | |
![]() |
964e164d2a | |
![]() |
91b27d48fa | |
![]() |
45d7d54c40 | |
![]() |
3fc3cb346f | |
![]() |
51ed1af70f | |
![]() |
222664eb8c | |
![]() |
a1ea7c6c62 | |
![]() |
e7c46f12a0 | |
![]() |
cfc4dfe53d | |
![]() |
ba617f9b7e | |
![]() |
e05df5f15f | |
![]() |
2ac6e00def | |
![]() |
b804bd6ebc | |
![]() |
33ec203f93 | |
![]() |
f0e0d21227 | |
![]() |
5c158071b8 | |
![]() |
714e2b445b | |
![]() |
127e0066f2 | |
![]() |
2e2f0428ab | |
![]() |
25a144e820 | |
![]() |
20ff3c2e0f | |
![]() |
52fc632ec7 | |
![]() |
f9c98a3202 | |
![]() |
448161a65c | |
![]() |
40eaf9f5d6 | |
![]() |
0e2532cc85 | |
![]() |
2fbf9e8d94 | |
![]() |
127f345a9c | |
![]() |
8dd437b984 | |
![]() |
842b39d1a6 | |
![]() |
7ad6fc5257 | |
![]() |
fc6cbdf03d | |
![]() |
a5cdad9ff8 | |
![]() |
d5c80e3681 | |
![]() |
096ff9dd4c | |
![]() |
017949cacb | |
![]() |
abb57abc6e | |
![]() |
1226363d5d | |
![]() |
ce7cb192ed | |
![]() |
b3d0485587 | |
![]() |
cfdc18fa53 | |
![]() |
4247b76b47 | |
![]() |
41b8605937 | |
![]() |
c9bf594a3f | |
![]() |
4b4b307f0e | |
![]() |
c73cc81494 | |
![]() |
f42c529a5a | |
![]() |
93a6318a42 | |
![]() |
7e4d70f2b8 | |
![]() |
3cb5c4a7c1 | |
![]() |
07ca5cc0a3 | |
![]() |
b24f4fe17e | |
![]() |
7dedcf1ab5 | |
![]() |
68375447ed | |
![]() |
32fd9d5ec5 | |
![]() |
a94dd4290e | |
![]() |
2a47d2bcf6 | |
![]() |
eedd91854f | |
![]() |
56eb522142 | |
![]() |
d50d5720e7 | |
![]() |
22e651884a | |
![]() |
852ede072a | |
![]() |
be2a4ba077 | |
![]() |
0653b9ec11 | |
![]() |
920be714ac | |
![]() |
650fa47468 | |
![]() |
9668f3014f | |
![]() |
b5e4481313 | |
![]() |
f6c6d12fd9 | |
![]() |
dcd2d76e96 | |
![]() |
5219aca9dd | |
![]() |
21c2b4ebfc | |
![]() |
e3f4325160 | |
![]() |
1029997586 | |
![]() |
cb70fb5af6 | |
![]() |
07055b389c | |
![]() |
410143f6b5 | |
![]() |
e2f324c466 | |
![]() |
9c622b790f | |
![]() |
30fe4c5d0d | |
![]() |
de0b2d6dc9 | |
![]() |
6118e62c10 | |
![]() |
a73e0bf6a2 | |
![]() |
a0940cad34 | |
![]() |
cd962b82e4 | |
![]() |
47fed9080a | |
![]() |
aefe74fb0e | |
![]() |
26abbe2f7f | |
![]() |
6a4cbf19c4 | |
![]() |
197d126736 | |
![]() |
228fb78696 | |
![]() |
7911585bdc | |
![]() |
e67704d5b7 | |
![]() |
eca3d75efd | |
![]() |
8b24e2c386 | |
![]() |
33be370fe6 | |
![]() |
ac68f0317f | |
![]() |
c070b10034 | |
![]() |
23f54c7d71 | |
![]() |
3d7cfba55f | |
![]() |
6a769e0bc0 | |
![]() |
107ede7375 | |
![]() |
50e13fc8c6 | |
![]() |
9d6fc8d726 | |
![]() |
856afa2116 | |
![]() |
c0606403cf | |
![]() |
a67566b01f | |
![]() |
9ba8408af9 | |
![]() |
54b392d76b | |
![]() |
a680b58121 | |
![]() |
fbff3694c6 | |
![]() |
a2548e687b | |
![]() |
a0cade405f | |
![]() |
5e90f6ae10 | |
![]() |
517a27294a | |
![]() |
0d4cf9fe49 | |
![]() |
d4604c7d81 | |
![]() |
9c99aa58c8 | |
![]() |
64feb0117c | |
![]() |
49365a2630 | |
![]() |
73b541a2c7 | |
![]() |
38d10282f4 | |
![]() |
fff695d3c1 | |
![]() |
257a138d82 | |
![]() |
3d78ca9c1c | |
![]() |
c17e0a6037 | |
![]() |
650ac714da | |
![]() |
361220ce5d | |
![]() |
2c0656a786 | |
![]() |
b068d69810 | |
![]() |
e3e45c4606 | |
![]() |
d107e7b2f4 | |
![]() |
4cb665c1e9 | |
![]() |
4bacc49da2 | |
![]() |
839f66924c | |
![]() |
75e56280c1 | |
![]() |
499adfe59c | |
![]() |
869f56bf41 | |
![]() |
d66fd4ab85 | |
![]() |
3bb392c413 | |
![]() |
0f8211ec84 | |
![]() |
9cd1ad785e | |
![]() |
61a36046d4 | |
![]() |
f9d572f07a | |
![]() |
b884832675 | |
![]() |
97b86029a6 | |
![]() |
3221fc2a88 | |
![]() |
36e1fee5fe | |
![]() |
19f9cd36fc | |
![]() |
98c68d8d89 | |
![]() |
98528a75a7 | |
![]() |
bf054c32ed | |
![]() |
2578a0a291 | |
![]() |
09229a159e | |
![]() |
e4a7588d4a | |
![]() |
8c2a951941 | |
![]() |
e661331bd1 | |
![]() |
18fa16d748 | |
![]() |
a87501a235 | |
![]() |
23cffd809c | |
![]() |
2df831cbb0 | |
![]() |
4e9176a4c0 | |
![]() |
18fed5b2ac | |
![]() |
fecd7ffd69 | |
![]() |
9689548ac8 | |
![]() |
990c2a062e | |
![]() |
1d71a7d4b7 | |
![]() |
0055130494 | |
![]() |
63605b9967 | |
![]() |
b0fbd6a919 | |
![]() |
26dc322b2c | |
![]() |
0c8e597533 | |
![]() |
1f2982fa5c | |
![]() |
82b6c5c8ea | |
![]() |
a3775a0138 | |
![]() |
577a91896b | |
![]() |
c23054364d | |
![]() |
1f68f2de4a | |
![]() |
1b10babf27 | |
![]() |
d2070ca6e5 | |
![]() |
dd167055b2 | |
![]() |
f9d81fcd0d | |
![]() |
992214a67a | |
![]() |
74a217400b | |
![]() |
3289c31d62 | |
![]() |
bfc30a659e | |
![]() |
672b8e3c8f | |
![]() |
3e57278979 | |
![]() |
a6b21e74e1 | |
![]() |
b8b16c02df | |
![]() |
c6c4871020 | |
![]() |
47785d2015 | |
![]() |
d742dd7745 | |
![]() |
fbd32a12da | |
![]() |
83fb5e2223 | |
![]() |
a5e3e92106 | |
![]() |
c92e7dca78 | |
![]() |
2affa600c1 | |
![]() |
a645bdb1d9 | |
![]() |
3dc426451e | |
![]() |
8b2ebeb2da | |
![]() |
c7188b2d48 | |
![]() |
f9acd10d94 | |
![]() |
8b80838fb8 | |
![]() |
63e9338860 | |
![]() |
8c9d99b608 | |
![]() |
e3ce9a41f4 | |
![]() |
f251df055e | |
![]() |
16eee0c416 | |
![]() |
9f6ed6db93 | |
![]() |
a0c3c02ea9 | |
![]() |
36132978f5 | |
![]() |
dd92d07548 | |
![]() |
b104d06b4f | |
![]() |
06ab1d081b | |
![]() |
6909133c5f | |
![]() |
eeb78c4086 | |
![]() |
b4a3a5ddef | |
![]() |
d652b5a0f4 | |
![]() |
15904d31de | |
![]() |
b76fc6277b | |
![]() |
f15e3c1b6a | |
![]() |
38bdc6c2f2 | |
![]() |
5b53b8c73e | |
![]() |
c4a0542ad3 | |
![]() |
45ee9f6bb5 | |
![]() |
4447955558 | |
![]() |
bf5ca69394 | |
![]() |
081a269f94 | |
![]() |
e271c6c4eb | |
![]() |
fd69a0e0aa | |
![]() |
17f285d455 | |
![]() |
f538364e3b | |
![]() |
2efd0e19e0 | |
![]() |
02b6c46751 | |
![]() |
26c2dd2ec9 | |
![]() |
f035b9d331 | |
![]() |
171b4aeeba | |
![]() |
519711e6f8 | |
![]() |
58ac31761a | |
![]() |
747cc72948 | |
![]() |
6740cc3b7d | |
![]() |
e8b3a77331 | |
![]() |
b57533998a | |
![]() |
daa2d26ff6 | |
![]() |
3b32a1cb4e | |
![]() |
c3e28a662f | |
![]() |
92fb5e378f | |
![]() |
8a9103ed33 | |
![]() |
0bdad85503 | |
![]() |
f5556d2a16 | |
![]() |
066681fce4 | |
![]() |
dd9524bd3c | |
![]() |
f49c15fdec | |
![]() |
84e4fa02d3 | |
![]() |
1d9ba5599d | |
![]() |
4ad158ce2f | |
![]() |
dc88d927bd | |
![]() |
120d8f29eb | |
![]() |
9a49138493 | |
![]() |
30eb7eb773 | |
![]() |
52b49c17e7 | |
![]() |
ec0b4547c6 | |
![]() |
3f9c4cf341 | |
![]() |
aa62c44724 | |
![]() |
af7702bb20 | |
![]() |
70a8db3231 | |
![]() |
6340db8150 | |
![]() |
fd52754682 | |
![]() |
840952a06a | |
![]() |
a28d6c1d23 | |
![]() |
0fa4b42eb4 | |
![]() |
47db86ec02 | |
![]() |
c0cb8ee700 | |
![]() |
0caab415d6 | |
![]() |
4c322a586b | |
![]() |
28a9cb1091 | |
![]() |
4cb74761c4 | |
![]() |
7ea5ecfb17 | |
![]() |
08f0a76fe2 | |
![]() |
5dfc89ca83 | |
![]() |
25c7d09e58 | |
![]() |
c54e6f000d | |
![]() |
9690913aa0 | |
![]() |
2fec8603f6 | |
![]() |
31be283ff0 | |
![]() |
8d3e0b19a4 | |
![]() |
03650f2a53 | |
![]() |
ac49e378d2 | |
![]() |
3590579579 | |
![]() |
e323960213 | |
![]() |
750bd43ce2 | |
![]() |
707121b826 | |
![]() |
974355f886 | |
![]() |
175418bb21 | |
![]() |
86aa5d9800 | |
![]() |
0e4367f2a2 | |
![]() |
d1172395c7 | |
![]() |
7a85c9e85d | |
![]() |
71b04380f1 | |
![]() |
96333a1907 | |
![]() |
9584a9b081 | |
![]() |
d10d9c6690 | |
![]() |
2941e5c05b | |
![]() |
7877dbaa9b | |
![]() |
cb7887b1ec | |
![]() |
5d3620d90f | |
![]() |
2bef4e40b8 | |
![]() |
b82970ad10 | |
![]() |
41c0169530 | |
![]() |
16b8a8f174 | |
![]() |
597570a733 | |
![]() |
1320134c19 | |
![]() |
d501721848 | |
![]() |
fb160ff827 | |
![]() |
4f4b7278c3 | |
![]() |
671ec49d8d | |
![]() |
06f0cce555 | |
![]() |
985cd76a5f | |
![]() |
47905bafea | |
![]() |
6f8eda0414 | |
![]() |
d99c069c8e | |
![]() |
9db45c8477 | |
![]() |
6eb058bba3 | |
![]() |
39083243ed | |
![]() |
68fd04ca2c | |
![]() |
7a245ef399 | |
![]() |
1411519bea | |
![]() |
b893eddd17 | |
![]() |
fc31ff0d29 | |
![]() |
0a351b29db | |
![]() |
b128934473 | |
![]() |
66a27544f3 | |
![]() |
85a9c6e87d | |
![]() |
9383c57874 | |
![]() |
564da1a23a | |
![]() |
40c3451047 | |
![]() |
c0e351339f | |
![]() |
08e8a91daf | |
![]() |
04cfc7ae66 |
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
name: New Issue, Bug report, Question
|
||||
about: New Issue, Bug report, Question
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## State your operating system:
|
||||
Windows/Mac/Linux. in case of linux, whether you use CLI, gtk2, or gtk3 version.
|
||||
|
||||
## DesMuME version
|
||||
e.g. 0.9.13 or git master
|
||||
|
||||
## Isse
|
||||
type here what's bothering you, in a detailed manner.
|
||||
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
name: DeSmuME
|
||||
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build DeSmuME (Linux)
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: install dependencies
|
||||
run: sudo apt update && sudo apt install meson libsdl2-dev libpcap-dev libgtk-3-dev
|
||||
|
||||
- name: meson
|
||||
run: |
|
||||
cd desmume/src/frontend/posix/
|
||||
meson build
|
||||
|
||||
- name: ninja
|
||||
run: ninja -C desmume/src/frontend/posix/build
|
||||
|
||||
build_gtk2:
|
||||
name: Build DeSmuME (Linux/GTK+2)
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: install dependencies
|
||||
run: sudo apt update && sudo apt install autoconf libglu1-mesa-dev libsdl2-dev libpcap-dev libgtk2.0-dev
|
||||
|
||||
- name: buildit
|
||||
run: |
|
||||
cd desmume/src/frontend/posix/
|
||||
autoreconf -i
|
||||
./configure --prefix=/usr --enable-gdb-stub --enable-wifi
|
||||
make -j8
|
||||
make DESTDIR=/tmp/DeSmuME install
|
||||
|
||||
- name: Pack artifact
|
||||
run: |
|
||||
cd /tmp
|
||||
tar cJf DeSmuME.tar.xz DeSmuME/
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: desmume-linux-gtk2-cli-x86_64
|
||||
path: /tmp/DeSmuME.tar.xz
|
||||
|
||||
build_macos:
|
||||
name: Build DeSmuME (macOS)
|
||||
runs-on: macos-14
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: xcodebuild
|
||||
run: |
|
||||
cd desmume/src/frontend/cocoa/
|
||||
xcodebuild archive -project "DeSmuME (Latest).xcodeproj" -scheme "DeSmuME (macOS App; Intel64 -- Latest Xcode)" -arch x86_64 -archivePath "$(pwd)/desmume.xcarchive" | xcpretty -c
|
||||
|
||||
- name: make zip
|
||||
run: |
|
||||
cd desmume/src/frontend/cocoa/desmume.xcarchive/Products/Applications/
|
||||
7z a DeSmuME.app.zip DeSmuME.app
|
||||
|
||||
- name: Upload artifict
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: macos
|
||||
path: desmume/src/frontend/cocoa/desmume.xcarchive/Products/Applications/DeSmuME.app.zip
|
||||
if-no-files-found: error
|
|
@ -0,0 +1,87 @@
|
|||
name: DeSmuME Interface (DLL/SO)
|
||||
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
jobs:
|
||||
build_linux:
|
||||
runs-on: ubuntu-24.04
|
||||
name: Build Linux
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: sudo apt update && sudo apt install meson libsdl2-dev libpcap-dev
|
||||
|
||||
- name: Build - Meson
|
||||
run: |
|
||||
cd desmume/src/frontend/interface/
|
||||
meson build
|
||||
|
||||
- name: Build - ninja
|
||||
run: ninja -C desmume/src/frontend/interface/build
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: linux
|
||||
path: desmume/src/frontend/interface/build/libdesmume.so
|
||||
|
||||
build_macos:
|
||||
runs-on: macos-14
|
||||
name: Build MacOS
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install MacOS build deps
|
||||
run: brew install coreutils sdl2 meson
|
||||
|
||||
- name: Build - Meson
|
||||
run: |
|
||||
cd desmume/src/frontend/interface/
|
||||
meson build
|
||||
env:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
|
||||
- name: Build - ninja
|
||||
run: ninja -C desmume/src/frontend/interface/build
|
||||
env:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: macos
|
||||
path: desmume/src/frontend/interface/build/libdesmume.dylib
|
||||
|
||||
build_windows:
|
||||
runs-on: windows-2022
|
||||
name: Build Windows
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [ 'x64', 'x86' ]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
with:
|
||||
msbuild-architecture: ${{ matrix.arch }}
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cd desmume\src\frontend\interface\windows
|
||||
MSBuild.exe DeSmuME_Interface.vcxproj /p:configuration="Release Fastbuild" /p:Platform=${{ matrix.arch }}
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: win-${{ matrix.arch }}
|
||||
path: desmume/src/frontend/interface/windows/__bins/*.dll
|
|
@ -0,0 +1,30 @@
|
|||
name: DeSmuME Windows build
|
||||
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
jobs:
|
||||
build-sln:
|
||||
runs-on: windows-2022
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup MSBuild.exe
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
with:
|
||||
msbuild-architecture: x64
|
||||
|
||||
- name: Build solution
|
||||
run: |
|
||||
SET CL=-Wno-c++11-narrowing
|
||||
msbuild 'desmume/src/frontend/windows/DeSmuME.sln' /p:configuration="Release" /p:platform=x64 /p:CL_cgthreads=1 /p:CLToolExe=clang-cl.exe
|
||||
cmd /c desmume\src\frontend\windows\ci_postbuild.bat
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: desmume-win-x64
|
||||
path: desmume/src/frontend/windows/__bins/*.exe
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
name: Generate Source Tarball
|
||||
|
||||
# Trigger whenever a release is created
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- created
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: archive
|
||||
id: archive
|
||||
run: |
|
||||
THISDIR="$PWD"
|
||||
cd desmume/src/frontend/posix
|
||||
autoreconf -i
|
||||
cd "$THISDIR"
|
||||
VERSION=$(printf "%s\n" ${{ github.event.release.tag_name }} | sed -e 's/^release_//' -e 's/_/./g')
|
||||
PKGNAME="desmume-$VERSION"
|
||||
mkdir -p /tmp/$PKGNAME
|
||||
mv * /tmp/$PKGNAME
|
||||
mv /tmp/$PKGNAME .
|
||||
TARBALL=$PKGNAME.tar.xz
|
||||
tar cJf $TARBALL $PKGNAME
|
||||
echo "::set-output name=tarball::$TARBALL"
|
||||
|
||||
- name: upload tarball
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ github.event.release.upload_url }}
|
||||
asset_path: ./${{ steps.archive.outputs.tarball }}
|
||||
asset_name: ${{ steps.archive.outputs.tarball }}
|
||||
asset_content_type: application/x-xz
|
|
@ -0,0 +1,77 @@
|
|||
/desmume/src/scmrev.h
|
||||
/desmume/src/frontend/windows/defaultconfig/scmrev.h
|
||||
/desmume/src/frontend/windows/.libs
|
||||
/desmume/src/frontend/windows/.obj
|
||||
/desmume/src/frontend/windows/__bins
|
||||
/desmume/src/frontend/windows/*.tlog
|
||||
/desmume/src/frontend/windows/*.aps
|
||||
.vs/
|
||||
*.user
|
||||
*.suo
|
||||
*.VC.db
|
||||
*.VC.opendb
|
||||
*.o
|
||||
*.ipch
|
||||
.deps
|
||||
*.dirstamp
|
||||
Makefile.in
|
||||
/desmume/src/frontend/posix/missing
|
||||
/desmume/src/frontend/posix/*.a
|
||||
/desmume/src/frontend/posix/autom4te.cache
|
||||
/desmume/src/frontend/posix/Makefile
|
||||
/desmume/src/frontend/posix/aclocal.m4
|
||||
/desmume/src/frontend/posix/configure
|
||||
/desmume/src/frontend/posix/cli/Makefile
|
||||
/desmume/src/frontend/posix/cli/desmume-cli
|
||||
/desmume/src/frontend/posix/cli/doc/Makefile
|
||||
/desmume/src/frontend/posix/compile
|
||||
/desmume/src/frontend/posix/config.guess
|
||||
/desmume/src/frontend/posix/config.log
|
||||
/desmume/src/frontend/posix/config.status
|
||||
/desmume/src/frontend/posix/config.sub
|
||||
/desmume/src/frontend/posix/depcomp
|
||||
/desmume/src/frontend/posix/gtk/Makefile
|
||||
/desmume/src/frontend/posix/gtk/desmume
|
||||
/desmume/src/frontend/posix/gtk/doc/Makefile
|
||||
/desmume/src/frontend/posix/gtk-glade/Makefile
|
||||
/desmume/src/frontend/posix/gtk-glade/desmume-glade
|
||||
/desmume/src/frontend/posix/gtk-glade/doc/Makefile
|
||||
/desmume/src/frontend/posix/install-sh
|
||||
/desmume/src/frontend/cocoa/openemu/OpenEmuBase.framework/
|
||||
/desmume/src/frontend/cocoa/OptimizationProfiles/
|
||||
|
||||
# Xcode
|
||||
|
||||
## Build generated
|
||||
build/
|
||||
DerivedData/
|
||||
|
||||
## Various settings
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata/
|
||||
.vs/ProjectSettings.json
|
||||
|
||||
## Other
|
||||
*.moved-aside
|
||||
*.xcuserstate
|
||||
*.xcscmblueprint
|
||||
|
||||
## Obj-C/Swift specific
|
||||
*.hmap
|
||||
*.ipa
|
||||
*.dSYM.zip
|
||||
*.dSYM
|
||||
|
||||
## Eclipse CDT generated files
|
||||
/.autotools
|
||||
/.cproject
|
||||
/config.log
|
||||
/.project
|
||||
.DS_Store
|
277
ChangeLog
277
ChangeLog
|
@ -1,277 +0,0 @@
|
|||
0.8 -> 0.9
|
||||
There have been so many changes that this list can hardly be considered complete.
|
||||
For this release, we have formatted the list into a high level overview of big changes and bad bugs relative to the previous release. Hopefully what you're interested in.
|
||||
This list does not include items which are solely performance boosts, for let us just say that virtually every system has been speeded up.
|
||||
|
||||
* The savestate system is totally changed and incompatible with old savestates.
|
||||
* The 3d system should be considered rewritten.
|
||||
|
||||
General/Core:
|
||||
enh: Convert to c++
|
||||
enh: Add functions for a lid open/close. Holding key (default "Backspace" in Windows port) while game is freeze/non freeze. [CrazyMax]
|
||||
enh: Add secure area decryption from ndstool [zeromus]
|
||||
enh: Change savestate code to support loosely bound chunks and more easily other parts of the emu (GE, GPU).
|
||||
The savestate format is changed, but from now on it is in principle more resilient
|
||||
(though it will continue to break as we tinker with the internals) [zeromus]
|
||||
enh: Added SSE2 optimizations for matrices. Since we now make an SSE2 build, more optimizations can be made. [CrazyMax]
|
||||
enh: Add a preliminary GUI hud system [CrazyMax,zeromus]
|
||||
|
||||
CPU/MMU:
|
||||
bug: Many fixes in IPC and GE FIFOs. Fixes freezes in NSMB, dsracing, and others. [CrazyMax,luigi__,shash]
|
||||
bug: Fix ARM instructions SBC and RSC (likewise SBC in thumb) [normatt]
|
||||
bug: Fixed Thumb LDMIA (fixes ingame Dead'n'Furious) [shash]
|
||||
bug: Fix repeating DMA (fixes NSMB parallax BG) [zeromus]
|
||||
bug: Proper handling for unaligned CPU accesses [luigi__]
|
||||
bug: Proper handling for undefined instruction exceptions [Salva Peiró]
|
||||
enh: Remove 16MB of WRAM at 0x01****** from arm9. Mapped to unused instead. Nobody knows what this was. [zeromus]
|
||||
enh: Changed instruction execution to 16 at a time blocks (tested and stable) [shash]
|
||||
|
||||
Hardware:
|
||||
bug: Newer and better sqrt and div emulation; makes SM64DS playable [luigi__,shash,zeromus]
|
||||
bug: Add preliminary RTC implementations [CrazyMax]
|
||||
enh: Add cosine interpolation in the SPU (conditionally compiled) [zeromus,luigi__]
|
||||
enh: Experimental: always one silent non-mixing SPU core at 44.1khz synched with emu, for more precision.
|
||||
The audible core runs with the host, causing music to slow down but not tear or pitch bend. [zeromus]
|
||||
|
||||
Graphics:
|
||||
- Overhaul 3d:
|
||||
. Move entire GE to core emu.
|
||||
. Move OpenGL renderer to emu core for optional use by platforms, removing ogl_collector. Now every platform shares the same 3d code.
|
||||
. Reorganize 3d code to defer rendering to after 3d vblank. Eliminates tearing, and texturing artifacts. [zeromus]
|
||||
. Move lighting model to software instead of using opengl's fixed function model [zeromus]
|
||||
. Render shadow volumes; toon shading and highlight table [zeromus, luigi__]
|
||||
. Added texture caching! big speed up. [CrazyMax]
|
||||
|
||||
bug: Many assorted tweaks and improvements to 3d and 2d precision [zeromus,CrazyMax,luigi__]
|
||||
bug: Fixes to GE: command unpacking, projection and pos-vector mode matrix handling, mult and load commands [zeromus]
|
||||
bug: Fix a bug in texture transformation mode 1 [zeromus]
|
||||
bug: Fixed GPU rendering bugs in sprites and BG [CrazyMax]
|
||||
bug: Fixes to texture conversion [CrazyMax,zeromus]
|
||||
bug: Fixes in capture display (no blinking in many games with dual 3D) [CrazyMax]
|
||||
bug: Fixes in master brightness (this fixes some games with black screens) [CrazyMax]
|
||||
bug: Fixes in screen, backdrop, and sprite blending [luigi__]
|
||||
bug: Changed clear depths and how depth initial values are calculated (fixes SM64DS skybox, Castlevania) [shash,lugi__]
|
||||
bug: Add 3d layer h-scrolling [zeromus]
|
||||
bug: Added transparency and fixed material alpha support and alpha testing on the 3D core [shash]
|
||||
bug: Rewrite VRAM mapping control and rendering (more accurate) [CrazyMax,luigi__]
|
||||
bug: convert colors to opengl better to prevent alpha=31 polys from being ever so slightly transparent [zeromus]
|
||||
enh: Add MMU->GPU signal for when vram mappings change to function as a texture cache invalidate signal [zeromus]
|
||||
enh: Make matrix 4x4 multiply routines use W-coordinate; carry w coord through pipeline [zeromus]
|
||||
|
||||
Mac OS X port:
|
||||
bug: Fixed: Filenames and paths with unicode characters now work. [Jeff]
|
||||
bug: Fixed: Load state from file button works again. [Jeff]
|
||||
enh: Save State panel now pauses emulation while the file selection box is open. [Jeff]
|
||||
bug: Fixed: Frozen video output (and/or messed 3d emulation) after loading a state. [Jeff]
|
||||
bug: Added option to load the most recent file upon launching the program. [Jeff]
|
||||
enh: Added French translation (thanks to Pierre Rudloff). [Jeff]
|
||||
enh: Added basic key mapping configuration to application preferences (thanks to Julio GorgŽ). [Jeff]
|
||||
enh: Added keyboard shortcuts for Execute, Pause and Reset command (thanks to Julio GorgŽ). [Jeff]
|
||||
enh: Default key mappings are no longer case sensitive. [Jeff]
|
||||
enh: Added ability to limit speed. [Jeff]
|
||||
enh: Fixed: Video output should work on software-only 3D renderers. [Jeff]
|
||||
|
||||
Windows port:
|
||||
bug: Fix a race condition in NDS_3D_Reset and NDS_glInit [zeromus]
|
||||
bug: Fix the buggy auto frameskip logic which made the emu slow to a crawl. Now it runs fast! [zeromus]
|
||||
bug: Fix resizing, rotate & aspect ration of main window. [CrazyMax,_zeromus]
|
||||
bug: Remove multithreading from user interface after finding several synchronization issues [zeromus]
|
||||
enh: recent roms menu [luigi_]
|
||||
enh: Changed graphics render core to DirectDraw (work faster) [CrazyMax]
|
||||
enh: Add an arm9 cpu load average calculator similar to no$. but I dont think it works right. [zeromus]
|
||||
enh: Rewrite all debug tools (autoupdate works now) [CrazyMax]
|
||||
enh: Rewrite input core & replace config input dialog [CrazyMax]
|
||||
enh: Add AVI output [zeromus]
|
||||
enh: Add pause toggle and frame advance hotkeys [adelikat]
|
||||
enh: Add frame counter display and hud messages framework [adelikat]
|
||||
enh: Main window remembers position, size, and a few other emu preferences [adelikat]
|
||||
enh: Removed directx sdk dependency for easier building. [zeromus]
|
||||
enh: Savestate doesnt unpause emu if it is already paused [adelikat]
|
||||
|
||||
0.7.3 -> 0.8
|
||||
Cocoa:
|
||||
- Save State As function now works. [Jeff B]
|
||||
- Recent Items menu now works. [Jeff B]
|
||||
- Opening NDS files from Finder now works. [Jeff B]
|
||||
- Added screenshot feature. [Jeff B]
|
||||
- Added preferences. [Jeff B]
|
||||
- Many more strings are translatable now. [Jeff B]
|
||||
- Default screen color is black (better represents being "off" and easier on eyes at night). [Jeff B]
|
||||
- Added sound. [Jeff B]
|
||||
- Now is a universal binary. [Jeff B]
|
||||
- Leopard resolution icon added. [Jeff B]
|
||||
- Added a Japanese translation. [Jeff B]
|
||||
- Added an optional status bar (resize handle no longer overlaps screen). [Jeff B]
|
||||
- New ROM Info and About DeSmuME windows have been added. [Jeff B]
|
||||
- Fixed several bugs in window resizing. [Jeff B]
|
||||
- Added FAT image support for homebrew games (thanks to TypeError). [Jeff B]
|
||||
- Key config can be changed on the command line. Save/load hotkeys changed (so expose doesn't override). [Jeff B]
|
||||
- Key bindings may work better on non-US keyboards now (needs testing). [Jeff B]
|
||||
general:
|
||||
- Encapsulate GDB debug stub to avoid certain problems [shash]
|
||||
- Fixed CPU LD*/ST* bugs [shash]
|
||||
- Fixed New SMB mini-games freeze [shash]
|
||||
- Fixed possible segfault in ROMReader on ia64 and amd64. [evilynux]
|
||||
- Fixed a crash bug with 2D background corrupting memory [shash]
|
||||
- Flag check optimization [carlo_bramini]
|
||||
- Applied some endian fixes in GPU (thanks to Phazz) [Jeff B]
|
||||
gtk-glade:
|
||||
- Added DeSmuME version in about dialog. [evilynux]
|
||||
- Updated website url in about dialog. [evilynux]
|
||||
- Added Brazilian Portuguese translation by Dreampeppers99. [evilynux]
|
||||
- Better desktop menu entry following FreeDesktop specifications. [evilynux]
|
||||
gtk:
|
||||
- Updated website url in about dialog. [evilynux]
|
||||
- Better desktop menu entry following FreeDesktop specifications. [evilynux]
|
||||
windows port:
|
||||
- Added an "about" box [shash]
|
||||
- DirectInput control interface with joystick support [CrazyMax]
|
||||
- Matrix and Light viewer [Acid Burn]
|
||||
|
||||
0.7.2 -> 0.7.3
|
||||
gtk-glade:
|
||||
- Full localization using intltool/gettext. [evilynux]
|
||||
general:
|
||||
- Added a README.TRANSLATION documenting the localization process. [evilynux]
|
||||
MacOS X:
|
||||
- Initial version of the Mac interface added. [Jeff B]
|
||||
|
||||
0.7.1 -> 0.7.2
|
||||
spu:
|
||||
- big endian fixes. [cyberwarriorx]
|
||||
gpu:
|
||||
- big endian fixes. [marcus_c]
|
||||
gtk-glade:
|
||||
- opengl improvements. [masscat]
|
||||
general:
|
||||
- Added support for setting NDS firmware language value. [masscat]
|
||||
- Function added for setting firmware language. [masscat]
|
||||
- Mac/msys compilation fixes. [cyberwarriorx]
|
||||
- Fix compilation when pkg-config macros are not available [evilynux]
|
||||
|
||||
0.7.0 -> 0.7.1
|
||||
general:
|
||||
- Added GDB debugger stub [masscat]
|
||||
- Added new/different GBAMP CFlash image reader/writer [masscat]
|
||||
gpu:
|
||||
- Major speedup to the 2D core [shash]
|
||||
gtk-glade:
|
||||
- Added command line options. [masscat]
|
||||
- Added FPS limiter [masscat]
|
||||
cli:
|
||||
- Added command line options. [masscat]
|
||||
- Added FPS limiter [masscat]
|
||||
- Added option to use OpenGl to render window (allows resizing). [masscat]
|
||||
windows port:
|
||||
- Added command line options. [masscat]
|
||||
- Added multiple language support [cyberwarriorx]
|
||||
- Added Danish language translation [thomas-2007]
|
||||
|
||||
0.6.0 -> 0.7.0
|
||||
general:
|
||||
- Added support for *.duc files [cyberwarriorx]
|
||||
gpu:
|
||||
- Added support for sprite rotation/scaling [shash]
|
||||
- Added support for the 3D core (openGL and null plugins) [shash]
|
||||
windows port:
|
||||
- A bunch of fixes [Dmitry Krutskih]
|
||||
- Fixed a bug in sound that was causing it to still not work for some
|
||||
people [cyberwarriorx]
|
||||
gtk:
|
||||
- Added 3D emulation
|
||||
- Added command line options.
|
||||
- Added option to use OpenGL to render window (allows resizing).
|
||||
gtk-glade:
|
||||
- Added 3D emulation
|
||||
|
||||
0.5.0 -> 0.6.0
|
||||
general:
|
||||
- Added zipped (based on zziplib) and gzipped (based on zlib) rom support.
|
||||
arm:
|
||||
- Added relocation interrupt vector.
|
||||
- Added region access right checks.
|
||||
- Enabled LDC/STC instructions.
|
||||
- Fixed powersave (cp15) IRQ wait.
|
||||
- Fixed MOV instructions
|
||||
gpu:
|
||||
- Added special color effects.
|
||||
- Added windowing feature.
|
||||
- Fixed transparent direct color backgrounds.
|
||||
- Fixed disabled sprites showing.
|
||||
- Fixed 8/32 bit access to gpu registers.
|
||||
- Fixed missing backgrounds
|
||||
- Support for master brightness
|
||||
wifi:
|
||||
- Added RF chip interface.
|
||||
- Added BB chip interface.
|
||||
windows port:
|
||||
- Fixed address calculation in disassembler.
|
||||
- Added Force Maintain Ratio option for window stretching
|
||||
linux port (cli, gtk and gtk-glade):
|
||||
all:
|
||||
- Added joystick support.
|
||||
- Fixed X and Y buttons.
|
||||
gtk-glade:
|
||||
- Added joystick configuration.
|
||||
- Improved I/O registers viewer tool.
|
||||
- Added save and load states support.
|
||||
|
||||
0.3.3 -> 0.5.0
|
||||
arm:
|
||||
- Fixed MSR with immediate value opcode.
|
||||
- Fixed LSR_0 thumb opcode (C flag is correctly set now).
|
||||
- Fixed LDR*/STR* opcodes.
|
||||
- Fixed unaligned memory access on THUMB Core.
|
||||
- Added relocating SWI routines.
|
||||
bios:
|
||||
- Added decompression functions.
|
||||
- Added GetPitchTable function.
|
||||
- Added GetVolumeTable function.
|
||||
- Added GetCRC16 function.
|
||||
- Added experimental SoundBias function.
|
||||
- Added GetSineTable function.
|
||||
cart:
|
||||
- Added CompactFlash/FAT emulation.
|
||||
- Added Get ROM chip ID Cartridge command.
|
||||
gpu:
|
||||
- Added framebuffer emulation.
|
||||
- Fixed a bug in GPU (xfin could be greater than LG causing a segfault).
|
||||
- Added support for Display Mode 0(Display Off).
|
||||
- Added the basic framework for Display Mode 3(Display from Main RAM).
|
||||
spu:
|
||||
- Added sound emulation.
|
||||
- Added sound core system.
|
||||
- Added WAV write core.
|
||||
- Added dummy core.
|
||||
- Added Direct Sound core.
|
||||
linux port:
|
||||
- Added GTK+ GUI.
|
||||
- Added command line interface.
|
||||
- Added stylus and arm9 keypad support in CLI version.
|
||||
- Added FPS display.
|
||||
- Added basic frameskip.
|
||||
windows port:
|
||||
- Fixed a bug when displaying a ROM's information.
|
||||
- Added key configuration.
|
||||
- Removed the debug key.
|
||||
- Added new experimental auto frameskip/frame limit code.
|
||||
- Added sound settings dialog.
|
||||
- Added a few menu options for accessing the website, forums, and for
|
||||
submitting bugs.
|
||||
general:
|
||||
- Rewrote code in C.
|
||||
- Fixed warnings.
|
||||
- Used defines and typedef's to make things more portable and easier to
|
||||
read.
|
||||
- Added autotools stuff.
|
||||
- Changes to logging system.
|
||||
- Added screenshot function.
|
||||
- Translated most french to english.
|
||||
- Added savestate support.
|
||||
- Added firmware reading support(needs work).
|
||||
- Added Backup Memory support with autodetection.
|
||||
- Fixed some endianess issues.
|
||||
- Fixed things so Visual C++ can compile code.
|
||||
- Added bsd support.
|
||||
- Reworked ROM loading so you can load a different rom without any problems.
|
||||
- Finished NDS_Reset. Now the emulation can be reset even while running.
|
237
INSTALL
237
INSTALL
|
@ -1,237 +0,0 @@
|
|||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
||||
2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is free documentation; the Free Software Foundation gives
|
||||
unlimited permission to copy, distribute and modify it.
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
Briefly, the shell commands `./configure; make; make install' should
|
||||
configure, build, and install this package. The following
|
||||
more-detailed instructions are generic; see the `README' file for
|
||||
instructions specific to this package.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
you can run in the future to recreate the current configuration, and a
|
||||
file `config.log' containing compiler output (useful mainly for
|
||||
debugging `configure').
|
||||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If you are using the cache, and at
|
||||
some point `config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You need `configure.ac' if
|
||||
you want to change it or regenerate `configure' using a newer version
|
||||
of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system.
|
||||
|
||||
Running `configure' might take a while. While running, it prints
|
||||
some messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation.
|
||||
|
||||
5. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
6. Often, you can also type `make uninstall' to remove the installed
|
||||
files again.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that the
|
||||
`configure' script does not know about. Run `./configure --help' for
|
||||
details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here
|
||||
is an example:
|
||||
|
||||
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you can use GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'.
|
||||
|
||||
With a non-GNU `make', it is safer to compile the package for one
|
||||
architecture at a time in the source code directory. After you have
|
||||
installed the package for one architecture, use `make distclean' before
|
||||
reconfiguring for another architecture.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' installs the package's commands under
|
||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||
can specify an installation prefix other than `/usr/local' by giving
|
||||
`configure' the option `--prefix=PREFIX'.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=DIR' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them.
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' cannot figure out automatically,
|
||||
but needs to determine by the type of machine the package will run on.
|
||||
Usually, assuming the package is built to be run on the _same_
|
||||
architectures, `configure' can figure that out, but if it prints a
|
||||
message saying it cannot guess the machine type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS KERNEL-OS
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the option `--target=TYPE' to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the
|
||||
"host" platform (i.e., that on which the generated programs will
|
||||
eventually be run) with `--host=TYPE'.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share, you
|
||||
can create a site shell script called `config.site' that gives default
|
||||
values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the `configure' command line, using `VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
||||
an Autoconf bug. Until the bug is fixed you can use this workaround:
|
||||
|
||||
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
|
||||
`--version'
|
||||
`-V'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||
disable caching.
|
||||
|
||||
`--config-cache'
|
||||
`-C'
|
||||
Alias for `--cache-file=config.cache'.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
EXTRA_DIST = README.LIN README.MAC README.WIN README.TRANSLATION autogen.sh \
|
||||
$(PO_FILES_IN)
|
||||
DISTCLEANFILES = $(PO_FILES)
|
||||
SUBDIRS = $(PO_DIR) src
|
||||
|
69
README
69
README
|
@ -1,69 +0,0 @@
|
|||
DeSmuME
|
||||
_________________________________________
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2006-2007 DeSmuME team
|
||||
|
||||
|
||||
1) Introduction.............................................13
|
||||
2) Staff/Thanks.............................................36
|
||||
3) Contact information......................................72
|
||||
4) Disclaimer...............................................82
|
||||
|
||||
|
||||
1 Introduction________________________________________________
|
||||
|
||||
DeSmuME is a Nintendo DS emulator under GNU GPL.
|
||||
|
||||
DeSmuME can boot homebrew and games, some of which are
|
||||
playable.
|
||||
|
||||
For installation/how to use informations, check the ports
|
||||
specific README files:
|
||||
|
||||
* README.LIN for the linux port
|
||||
* README.WIN for the windows port
|
||||
* README.MAC for the mac port
|
||||
|
||||
|
||||
2 Staff/Thanks________________________________________________
|
||||
|
||||
See the AUTHORS file for team members list.
|
||||
|
||||
Thanks to:
|
||||
|
||||
* yopyop (original author of DeSMUME),
|
||||
for releasing the source code of this great emulator.
|
||||
|
||||
* Martin Korth (author of GBATEK),
|
||||
for his well-written Gameboy Advance and Nintendo DS
|
||||
documentation.
|
||||
|
||||
|
||||
3 Contact information_________________________________________
|
||||
|
||||
E-mail: guillaume.duhamel@gmail.com
|
||||
Web: http://desmume.org
|
||||
IRC: irc://irc.freenode.net/desmume
|
||||
|
||||
Please don't ask for roms, bios files or any other
|
||||
copyrighted stuff.
|
||||
|
||||
|
||||
4 Disclaimer__________________________________________________
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be
|
||||
useful,but WITHOUT ANY WARRANTY; without even the implied
|
||||
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
MA 02111-1307 USA
|
||||
|
||||
See the GNU General Public License details in COPYING.
|
177
README.LIN
177
README.LIN
|
@ -1,177 +0,0 @@
|
|||
DeSmuME
|
||||
_________________________________________
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2006-2007 DeSmuME team
|
||||
|
||||
|
||||
1) Compiling instructions...................................13
|
||||
2) How to use DeSmuME.......................................53
|
||||
3) Contact information......................................142
|
||||
4) Disclaimer...............................................160
|
||||
|
||||
|
||||
1 Compiling instructions______________________________________
|
||||
|
||||
DeSmuME is written in C using the gtk+ and SDL libraries.
|
||||
So you need a working C compiler, such as gcc and
|
||||
the above libraries runtime and development packages:
|
||||
|
||||
* http://www.gtk.org
|
||||
|
||||
* http://www.libsdl.org/
|
||||
|
||||
Once these libraries are installed, you should be ready to
|
||||
install DeSmuME.
|
||||
|
||||
DeSmuME provides another interface based on libglade, to use
|
||||
it, you'll need glade:
|
||||
|
||||
* http://glade.gnome.org/
|
||||
|
||||
1.1 From a release archive____________________________________
|
||||
|
||||
Uncompress the DeSmuME archive, move to the newly created
|
||||
directory, type "./configure", then "make".
|
||||
It will generate three programs:
|
||||
1) "desmume" in the "src/gtk" directory;
|
||||
2) "desmume-cli" in the "src/cli" directory.
|
||||
If glade is installed on your system, you'll get a third
|
||||
binary:
|
||||
3) "desmume-glade" in the "src/gtk-glade" directory.
|
||||
|
||||
You can even type "make install" to install those programs on
|
||||
your system (in /usr/local/ by default), then uninstalling is
|
||||
done by typing "make uninstall".
|
||||
|
||||
1.2 From a CVS copy___________________________________________
|
||||
|
||||
Move to the toplevel directory (the one that contains the
|
||||
configure.ac file). Type "./autogen.sh" to generate the
|
||||
configure/install scripts and needed Makefiles. Then you can follow the
|
||||
same procedure as in 1.1 .
|
||||
|
||||
2 How to use DeSmuME__________________________________________
|
||||
|
||||
There are three versions of DeSmuME under Linux. These are a
|
||||
Gtk+ build, a Glade build and a CLI SDL build. All these builds
|
||||
have some common command line options:
|
||||
|
||||
--disable-limiter Disables the 60 fps limiter
|
||||
--soft-convert Use software colour conversion during OpenGL
|
||||
screen rendering. May produce better or worse
|
||||
frame rates depending on hardware.
|
||||
|
||||
--arm9gdb=PORT_NUM Enable the ARM9 GDB stub on the given port
|
||||
--arm7gdb=PORT_NUM Enable the ARM7 GDB stub on the given port
|
||||
|
||||
--cflash=PATH_TO_DISK_IMAGE
|
||||
Enable disk image GBAMP compact flash emulation
|
||||
|
||||
--help Display this message
|
||||
|
||||
|
||||
NOTE:
|
||||
The Gtk+ and Glade builds use gtkGLext to handle the OpenGL
|
||||
rendering and contexts. You may get improved performance by
|
||||
also passing the argument --gdk-gl-force-indirect. This has
|
||||
been seen to improve things for Nvidia based graphics cards
|
||||
under Linux.
|
||||
|
||||
|
||||
GDB Debugger Stubs:
|
||||
Source level debugging of ARM9 and/or ARM7 code is supported
|
||||
using a GDB/Insight debugger.
|
||||
The GDB stubs are enabled from the command line using the
|
||||
following options:
|
||||
|
||||
--arm9gdb=<PORT_NUM> (for the ARM9)
|
||||
--arm7gdb=<PORT_NUM> (for the ARM7)
|
||||
|
||||
The PORT_NUM is the TCP port upon which the stub will listen for
|
||||
connections. Once enabled you can connect to the stub using the
|
||||
following command at the GDB debugger prompt (assuming GDB and
|
||||
DeSmuME are running on the same machine):
|
||||
|
||||
target remote :<PORT_NUM>
|
||||
|
||||
NOTE: there are problems with the ARM support when stepping code
|
||||
with GDB versions prior to version 6.6. It is recommended that
|
||||
you use at least version 6.6 if possible.
|
||||
|
||||
|
||||
GBAMP compact flash emulation:
|
||||
|
||||
The default behaviour of DeSmumME is to attempt to emulate the
|
||||
FAT image for the contents of the directory where the running
|
||||
.nds file was located.
|
||||
This behaviour can be altered using the
|
||||
--cflash=<DISK_IMAGE_FILE> command line option. Using this
|
||||
option DeSmuME will emulation a GBAMP and read and write sectors
|
||||
from/to the disk image file.
|
||||
The disk image file must be created and populated with files
|
||||
using some external tool.
|
||||
NOTE: currently if desmume fails to open the disk image file it
|
||||
will silently continue minus a working GBAMP emulation.
|
||||
|
||||
|
||||
2.1 Gtk+ version______________________________________________
|
||||
|
||||
Type "desmume" in a shell, a window should appear, then open
|
||||
a rom file using the "open" button, next use the "run" button
|
||||
to start emulation.
|
||||
|
||||
The following command line options are specific to the Gtk+
|
||||
build:
|
||||
|
||||
--opengl-2d Enables using OpenGL for screen rendering
|
||||
--disable-sound Disables the sound emulation
|
||||
--disable-3d Disables the 3D emulation
|
||||
|
||||
|
||||
2.2 CLI SDL version_______________________________________________
|
||||
|
||||
Just type "desmume-cli path-to-a-rom" in a shell.
|
||||
|
||||
The following command line options are specific to the CLI
|
||||
build:
|
||||
|
||||
--opengl-2d Enables using OpenGL for screen rendering
|
||||
--disable-sound Disables the sound emulation
|
||||
|
||||
|
||||
3 Contact information_________________________________________
|
||||
|
||||
General inquiries should go to:
|
||||
E-mail: guillaume@desmume.org
|
||||
|
||||
Linux Port-related inquiries should go to:
|
||||
E-mail: guillaume@desmume.org
|
||||
|
||||
Web: http://desmume.org
|
||||
|
||||
Please don't ask for roms, bios files or any other copyrighted
|
||||
stuff.
|
||||
|
||||
If you want to submit a bug report, please run desmume, go into
|
||||
the "Help" menu, and click on "Submit a bug report". If you're
|
||||
having trouble with it, please feel free to email.
|
||||
|
||||
|
||||
4 Disclaimer__________________________________________________
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be
|
||||
useful,but WITHOUT ANY WARRANTY; without even the implied
|
||||
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
MA 02111-1307 USA
|
||||
|
||||
See the GNU General Public License details in COPYING.
|
107
README.MAC
107
README.MAC
|
@ -1,107 +0,0 @@
|
|||
DeSmuME
|
||||
_________________________________________
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2006-2007 DeSmuME team
|
||||
|
||||
|
||||
1) Compiling instructions...................................13
|
||||
2) How to use DeSmuME.......................................31
|
||||
3) Contact information......................................73
|
||||
4) Disclaimer...............................................90
|
||||
|
||||
|
||||
1 Compiling instructions______________________________________
|
||||
|
||||
DeSmuME is written in C, and the Cocoa interface was written
|
||||
in Objective-C. It uses the Cocoa, OpenGL, and [optionally]
|
||||
the zlib library.
|
||||
|
||||
So you need a working C and Objective-C compiler, such as
|
||||
GCC for Mac OS X.
|
||||
|
||||
* Cocoa and OpenGL come standard with Mac OS X
|
||||
|
||||
* zlib can be found at http://www.zlib.net, and may
|
||||
also come with Mac OS X.
|
||||
|
||||
DeSmuME for Mac OS X can be compiled using the XCode IDE
|
||||
or the CodeBlocks IDE. Project files are available in the
|
||||
Cocoa source folder.
|
||||
|
||||
2 How to use DeSmuME__________________________________________
|
||||
|
||||
To install DeSmuME, copy DeSmuME.app into the folder of your
|
||||
choice (Applications folder is recommended). You can also drag
|
||||
it to your dock for quicker launching.
|
||||
|
||||
Double click the application to launch DeSmuME.
|
||||
|
||||
Most options can be found in the menu bar a the top of the
|
||||
screen. On Leopard, you can use the search box under the help
|
||||
menu to find things.
|
||||
|
||||
DeSmuME for Mac OS X does not support all the features of the
|
||||
Linux and Windows versions.
|
||||
|
||||
Click the lower screen for DS touch-screen input.
|
||||
|
||||
Key mappings can be changed or viewed from the preferences
|
||||
panel. Here are the defaults (may be subject to change):
|
||||
up arrow - Up
|
||||
left arrow - Left
|
||||
down arrow - Down
|
||||
right arrow - Right
|
||||
v - A button
|
||||
b - B button
|
||||
g - X button
|
||||
h - Y button
|
||||
c - Left Trigger
|
||||
n - Right Trigger
|
||||
enter - Start button
|
||||
space - Select button
|
||||
|
||||
States can be saved with shift + number keys.
|
||||
States can be loaded with the number keys.
|
||||
|
||||
To set up a FAT disk image (for homebrew apps) you can use the
|
||||
"Emulation > Set FAT Image File" option in the menu. You can
|
||||
also set this from the command line by launching DeSmuME
|
||||
inside its app bundle:
|
||||
|
||||
DeSmuME.app/Contents/MacOS/DeSmuME -FlashFile /path/to/file.img
|
||||
|
||||
3 Contact information_________________________________________
|
||||
|
||||
General inquiries should go to:
|
||||
E-mail: guillaume.duhamel@gmail.com
|
||||
|
||||
Mac OS X Port-related inquiries should go to:
|
||||
E-mail: osx@desmume.org
|
||||
|
||||
Web: http://desmume.org
|
||||
|
||||
Please don't ask for roms, bios files or any other copyrighted
|
||||
stuff.
|
||||
|
||||
If you want to submit a bug report, please run desmume, go
|
||||
into the "Help" menu, and click on "Submit a bug report". If
|
||||
you're having trouble with it, please feel free to email.
|
||||
|
||||
4 Disclaimer__________________________________________________
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be
|
||||
useful,but WITHOUT ANY WARRANTY; without even the implied
|
||||
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
MA 02111-1307 USA
|
||||
|
||||
See the GNU General Public License details in COPYING.
|
|
@ -1,169 +0,0 @@
|
|||
__________________________ Localization of DeSmuME _____________________________
|
||||
|
||||
Users and translators:
|
||||
1) Supported UIs
|
||||
2) Starting a new translation
|
||||
3) Editors
|
||||
4) Contact Us
|
||||
|
||||
Developpers:
|
||||
5) Creating translation friendly strings (gtk-glade)
|
||||
6) Updating the template (gtk-glade)
|
||||
7) Integrating new translations
|
||||
|
||||
|
||||
1 Supported UIs ________________________________________________________________
|
||||
|
||||
Although there are 4 UIs, only 3 currently support localization:
|
||||
windows, gtk-glade, and Cocoa (Mac OS X).
|
||||
|
||||
To translate DeSmuME, see "Starting a new translation" below.
|
||||
|
||||
If you have created a new translation, or improved an existing one, please
|
||||
send us your translation by getting in touch with us: see "Contact Us" below.
|
||||
|
||||
1.1 gtk-glade UI _____________________________________________________________
|
||||
|
||||
Localization is done with gettext. gettext uses po files.
|
||||
The po files are located in the po/ folder.
|
||||
Note that there is one po file per language.
|
||||
|
||||
To use the available translations, set up your environment properly.
|
||||
e.g. under GNU/Linux you can verify that the value of your LANG variable.
|
||||
|
||||
1.2 Windows UI ______________________________________________________________
|
||||
|
||||
Localization is located in one single file: src/windows/resources.rc .
|
||||
|
||||
1.3 Mac OS X (Cocoa) UI _____________________________________________________
|
||||
|
||||
Localization files are located within the application bundle (in Finder right
|
||||
click on DeSmuME and select "Show Package Contents"). Within the
|
||||
Contents/Resources folder there is a folder for each localization.
|
||||
|
||||
2 Starting a new translation ___________________________________________________
|
||||
|
||||
2.1 gtk-glade UI _____________________________________________________________
|
||||
|
||||
Grab a copy of po/desmume.pot and rename it.
|
||||
You can use the two letter iso code of the language as the filename
|
||||
e.g. fr.po
|
||||
or you can specify the country code as well
|
||||
e.g. fr_CA.po
|
||||
|
||||
Open the newly created file with an editor: see "Editors" below.
|
||||
Translate the strings.
|
||||
|
||||
2.2 Windows UI _______________________________________________________________
|
||||
|
||||
Grab a copy of src/windows/resources.rc .
|
||||
Create a section for your language by looking at another language e.g. french.
|
||||
Translate the strings.
|
||||
|
||||
2.3 Max OS X (Cocoa) UI ______________________________________________________
|
||||
|
||||
Copy and paste one of the localization folders mentioned in 1.3.
|
||||
Rename the part before ".lproj" to the language of the translation.
|
||||
Within your newly created folder edit "Localizable.strings".
|
||||
|
||||
The MainMenu.nib opaque folder also contains localization of the Application
|
||||
menu, however since this is a standard menu in Mac OS X, for most languages
|
||||
standard strings can be generated by Apple's Interface Builder.
|
||||
|
||||
The strings file should stay in UTF-16 encoding (UTF-8 or others may work,
|
||||
but UTF-16 is preferred).
|
||||
|
||||
If your strings file has an error, no translated strings will show in DeSmuME.
|
||||
|
||||
Debugging the string file:
|
||||
If you have Mac OS X developer tools installed, from the console you can type
|
||||
"plutil FILE", replacing FILE with the name and path of the string file, and
|
||||
it will tell you if there are any errors (and on what line).
|
||||
|
||||
3 Editors ______________________________________________________________________
|
||||
|
||||
You can use plain text editors but there are many po file editors.
|
||||
Here are some recommanded po editors, in no particular order.
|
||||
|
||||
3.1 GNU/Linux ________________________________________________________________
|
||||
|
||||
- gtranslator: http://gtranslator.sourceforge.net/
|
||||
- KBabel: http://kbabel.kde.org/
|
||||
|
||||
3.2 OSX ______________________________________________________________________
|
||||
|
||||
- LocFactory Editor:
|
||||
http://www.triplespin.com/en/products/locfactoryeditor.html
|
||||
|
||||
3.3 All platforms ____________________________________________________________
|
||||
|
||||
- poEdit: http://www.poedit.net/
|
||||
- OmegaT: http://www.omegat.org/omegat/omegat.html
|
||||
- GNUEmacs/XEmacs/AquaEmacs with po-mode
|
||||
- Vim with PO ftplugin
|
||||
- Eclipse with gted
|
||||
|
||||
|
||||
4 Contact Us ___________________________________________________________________
|
||||
|
||||
As there isn't many translations so far, we're still asking you to get in touch
|
||||
via the forum located at http://forums.desmume.org/ .
|
||||
|
||||
You can upload your translation files to your favorite sharing site and paste
|
||||
the link in a post under General.
|
||||
|
||||
|
||||
5 Creating translation friendly strings (gtk-glade) ____________________________
|
||||
|
||||
5.1 In the code ______________________________________________________________
|
||||
|
||||
Make sure libintl.h is included and that _() is defined.
|
||||
e.g. see src/gtk-glade/globals.h
|
||||
Add the filename to po/POTFILES.in if it's not already there.
|
||||
|
||||
Where you would use "my text", use _("my text").
|
||||
For long strings, for translators' sanity, please do something like:
|
||||
|
||||
printf( _(" This is a\n\
|
||||
very long text\n") );
|
||||
|
||||
5.2 Glade interface __________________________________________________________
|
||||
|
||||
You have nothing special to do aside from adding the filename to
|
||||
po/POTFILES.in.
|
||||
|
||||
|
||||
6 Updating the template (gtk-glade) ____________________________________________
|
||||
|
||||
To update po/desmume.pot, move to the po/ folder and execute "make update-po".
|
||||
|
||||
|
||||
7 Integrating new translations
|
||||
|
||||
7.1 gtk-glade UI _____________________________________________________________
|
||||
|
||||
Add the new po file to po/ .
|
||||
Add the new language to ALL_LINGUAS in configure.ac .
|
||||
Regenerated the build files (./autogen.sh) and rebuild (./configure && make).
|
||||
You can also add the language to po/LINGUAS (it's a convention? it has no effect).
|
||||
|
||||
7.2 Windows UI _______________________________________________________________
|
||||
|
||||
Update the src/windows/resource.rc .
|
||||
Add the new language to to the list in src/windows/resource.h .
|
||||
Rebuild.
|
||||
|
||||
7.3 Max OS X (Cocoa) UI ______________________________________________________________
|
||||
|
||||
After following the steps in 2.3, your translation is ready to go.
|
||||
You can set the DeSmuME language one of three ways:
|
||||
|
||||
1) Set the system language (System Preferences -> International).
|
||||
|
||||
2) Right click on DeSmuME in Finder, select Get Info and disable the other translations.
|
||||
|
||||
3) From a command line, run the following line after replacing LANG with the language:
|
||||
|
||||
DeSmuME.app/Contents/MacOS/DeSmuME -AppleLanguages '<array><string>LANG</string></array>'
|
||||
|
||||
All of these methods require a restart of DeSmuME.
|
201
README.WIN
201
README.WIN
|
@ -1,201 +0,0 @@
|
|||
DeSmuME
|
||||
_________________________________________
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2006-2007 DeSmuME team
|
||||
|
||||
|
||||
1) Compiling instructions...................................13
|
||||
2) How to use DeSmuME.......................................51
|
||||
3) Contact information.....................................166
|
||||
4) Disclaimer..............................................184
|
||||
|
||||
|
||||
1 Compiling instructions______________________________________
|
||||
|
||||
DeSmuME is written in C, using the DirectX 8.0, OpenGL, zlib,
|
||||
zziplib libraries, so you need a working C compiler(such as
|
||||
mingw). Other supported compilers include Visual C++ 2005 and
|
||||
dev-cpp.
|
||||
|
||||
* You can find DirectX headers and libraries(for mingw) at
|
||||
http://alleg.sourceforge.net/wip.html as the file
|
||||
"dx80_mgw.zip". The actual runtime libraries(or
|
||||
headers/libraries for MSVC) can be gotten from
|
||||
http://www.microsoft.com/DirectX
|
||||
|
||||
* OpenGL should be included with your compiler, if it isn't,
|
||||
check on your compiler's website for links.
|
||||
|
||||
* zlib can be found at http://www.zlib.net
|
||||
|
||||
* zziplib can be found at http://zziplib.sourceforge.net
|
||||
|
||||
mingw:
|
||||
All you have to do now is go into your mingw shell
|
||||
environment, go into the directory where you extracted DeSmuME,
|
||||
and type: "./configure". Once that's done(and there was no
|
||||
errors), type: "make". It should now take some time to compile so
|
||||
go grab yourself a sandwich or beer - whatever suits your fancy
|
||||
and it should be done in a few minutes. Now all you have to do is
|
||||
type "./src/desmume" in order to run it.
|
||||
|
||||
dev-cpp:
|
||||
Load the project file DeSmuME.dev in the src/windows directory,
|
||||
compile, and you're set.
|
||||
|
||||
Visual C++:
|
||||
Load the project file DeSmuME.vcproj in the src/windows directory,
|
||||
compile, and you're set.
|
||||
|
||||
|
||||
2 How to use DeSmuME__________________________________________
|
||||
|
||||
Execute "desmume". A new window should pop up. The default
|
||||
settings should be fine for most people, but in case you need to
|
||||
adjust them, here's a brief explanation:
|
||||
|
||||
Under the "Config", there are a number of items:
|
||||
|
||||
Save Type:
|
||||
Here you can select which type of Backup Memory DeSmuME should
|
||||
emulate. By default, Autodetect works fine, but in some cases
|
||||
DeSmuME doesn't correctly detect the Backup Memory. In that
|
||||
case, you will want to select the correct one.
|
||||
|
||||
Control Config:
|
||||
Here you can change the default key mappings. For now only the
|
||||
keyboard is supported, but in the near future gamepads and
|
||||
joysticks will be supported.
|
||||
|
||||
Here are the default key mappings(they may be subject to change):
|
||||
Up arrow - Up
|
||||
Left arrow - Left
|
||||
Down arrow - Down
|
||||
right arrow - Right
|
||||
v - A button
|
||||
b - B button
|
||||
g - X button
|
||||
h - Y button
|
||||
c - Left Trigger
|
||||
n - Right Trigger
|
||||
enter - Start button
|
||||
space - Select button
|
||||
|
||||
Sound Settings:
|
||||
Here you can change the default sound settings. By default
|
||||
DeSmuME uses Direct Sound, a buffer size of 2940, and
|
||||
volume set to max. But if you want to mute the sound, you can
|
||||
set the sound core to none. Or if you want to save the sound
|
||||
to a file, you can set the sound core to WAV write. If you find
|
||||
the sound is crackling a lot, try increasing the buffer size. On
|
||||
the other hand, if you find the sound somewhat delayed or jumpy,
|
||||
try decreasing the buffer size.
|
||||
|
||||
Frame Skip:
|
||||
Here you can adjust the amount of frame draws to skip during
|
||||
emulation. Normally the emulator detects whether the emulator
|
||||
is running too fast or slow and skips a frame or more if it
|
||||
needs to speed things up. However some people don't like the
|
||||
results of it, so here you can adjust that.
|
||||
|
||||
After all the settings are set to your satisfaction, you can then
|
||||
load a ROM image by going into the "File" menu, and choosing
|
||||
"Open". Select which file you'd like to open, and the emulator
|
||||
will automatically load and start running the selected ROM.
|
||||
|
||||
You can save the current emulation state by press shift + one of
|
||||
the twelve F keys. To load, just press one of the twelve F keys
|
||||
(without shift pressed).
|
||||
|
||||
Under the View menu there's also a few additional options you may
|
||||
wish to change.
|
||||
|
||||
Rotation:
|
||||
Here you can adjust which angle of the display. Some programs
|
||||
require that you normally turn the DS on its side. You can set it
|
||||
up in that manner using this.
|
||||
|
||||
Magnify/DeMagnify:
|
||||
With these options you can increase or decrease the window size.
|
||||
|
||||
Note: You can also adjust the window size by clicking on the edge
|
||||
of the window, and dragging the mouse.
|
||||
|
||||
Force Maintain Ratio:
|
||||
Sometimes when the window size is changed it's doesn't look
|
||||
correct on the screen. This option forces the window to maintain
|
||||
a correct ratio so it looks correct.
|
||||
|
||||
|
||||
GDB Debugger Stubs:
|
||||
Source level debugging of ARM9 and/or ARM7 code is supported
|
||||
using a GDB/Insight debugger.
|
||||
The GDB stubs are enabled from the command line using the
|
||||
following options:
|
||||
|
||||
--arm9gdb=<PORT_NUM> (for the ARM9)
|
||||
--arm7gdb=<PORT_NUM> (for the ARM7)
|
||||
|
||||
The PORT_NUM is the TCP port upon which the stub will listen for
|
||||
connections. Once enabled you can connect to the stub using the
|
||||
following command at the GDB debugger prompt (assuming GDB and
|
||||
DeSmuME are running on the same machine):
|
||||
|
||||
target remote :<PORT_NUM>
|
||||
|
||||
NOTE: there are problems with the ARM support when stepping code
|
||||
with GDB versions prior to version 6.6. It is recommended that
|
||||
you use at least version 6.6 if possible.
|
||||
|
||||
|
||||
GBAMP compact flash emulation:
|
||||
|
||||
The default behaviour of DeSmumME is to attempt to emulate the
|
||||
FAT image for the contents of the directory where the running
|
||||
.nds file was located.
|
||||
This behaviour can be altered using the
|
||||
--cflash=<DISK_IMAGE_FILE> command line option. Using this
|
||||
option DeSmuME will emulation a GBAMP and read and write sectors
|
||||
from/to the disk image file.
|
||||
The disk image file must be created and populated with files
|
||||
using some external tool.
|
||||
NOTE: currently if desmume fails to open the disk image file it
|
||||
will silently continue minus a working GBAMP emulation.
|
||||
|
||||
|
||||
3 Contact information_________________________________________
|
||||
|
||||
General inquiries should go to:
|
||||
E-mail: guillaume@desmume.org
|
||||
|
||||
Windows Port-related inquiries should go to:
|
||||
E-mail:
|
||||
|
||||
Web: http://desmume.org
|
||||
|
||||
Please don't ask for roms, bios files or any other copyrighted
|
||||
stuff.
|
||||
|
||||
If you want to submit a bug report, please run desmume, go into
|
||||
the "Help" menu, and click on "Submit a bug report". If you're
|
||||
having trouble with it, please feel free to email.
|
||||
|
||||
|
||||
4 Disclaimer__________________________________________________
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be
|
||||
useful,but WITHOUT ANY WARRANTY; without even the implied
|
||||
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with this program; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
MA 02111-1307 USA
|
||||
|
||||
See the GNU General Public License details in COPYING.
|
|
@ -0,0 +1,6 @@
|
|||
# DeSmuME
|
||||
[](https://ci.appveyor.com/project/zeromus/desmume)
|
||||
|
||||
DeSmuME is a Nintendo DS emulator.
|
||||
|
||||
http://desmume.org/download
|
14
autogen.sh
14
autogen.sh
|
@ -1,14 +0,0 @@
|
|||
#!/bin/sh
|
||||
# intltoolize is optionnal as it's only required for the gtk-glade UI.
|
||||
|
||||
if test ! "x$(which intltoolize)" = "x"; then
|
||||
echo "Running intltoolize"
|
||||
intltoolize --copy --force --automake
|
||||
else
|
||||
if test ! "x$(which gintltoolize)" = "x"; then
|
||||
echo "Running gintltoolize"
|
||||
gintltoolize --copy --force --automake
|
||||
fi
|
||||
fi
|
||||
|
||||
autoreconf --install --force --verbose
|
|
@ -1,39 +0,0 @@
|
|||
# -*-shell-script-*-
|
||||
|
||||
[Meta]
|
||||
RootName: @desmume.sf.net/desmume:$SOFTWAREVERSION
|
||||
DisplayName: DeSmuME Nintendo DS Emulator
|
||||
ShortName: desmume
|
||||
Maintainer: Guillaume Duhamel <guillaume.duhamel@gmail.com>
|
||||
Packager: Guillaume Duhamel <guillaume.duhamel@gmail.com>
|
||||
Summary: DeSmuME is a Nintendo DS emulator.
|
||||
URL: http://desmume.sf.net/
|
||||
License: GNU General Public License, Version 2
|
||||
SoftwareVersion: @VERSION@
|
||||
AutopackageTarget: 1.0
|
||||
|
||||
[Description]
|
||||
This is a Nintendo DS emulator.
|
||||
|
||||
[BuildPrepare]
|
||||
prepareBuild
|
||||
|
||||
[BuildUnprepare]
|
||||
unprepareBuild
|
||||
|
||||
[Imports]
|
||||
echo '*' | import
|
||||
|
||||
[Prepare]
|
||||
# Dependency checking
|
||||
require @gtk.org/gtk 2.4
|
||||
|
||||
[Install]
|
||||
# Put your installation script here
|
||||
installExe bin/desmume
|
||||
installExe bin/desmume-cli
|
||||
installExe bin/desmume-glade
|
||||
|
||||
[Uninstall]
|
||||
# Usually just the following line is enough to uninstall everything
|
||||
uninstallFromLog
|
142
compile
142
compile
|
@ -1,142 +0,0 @@
|
|||
#! /bin/sh
|
||||
# Wrapper for compilers which do not understand `-c -o'.
|
||||
|
||||
scriptversion=2005-05-14.22
|
||||
|
||||
# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try \`$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: compile [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Wrapper for compilers which do not understand `-c -o'.
|
||||
Remove `-o dest.o' from ARGS, run PROGRAM with the remaining
|
||||
arguments, and rename the output as expected.
|
||||
|
||||
If you are trying to build a whole package this is not the
|
||||
right script to run: please start by reading the file `INSTALL'.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "compile $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
ofile=
|
||||
cfile=
|
||||
eat=
|
||||
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as `compile cc -o foo foo.c'.
|
||||
# So we strip `-o arg' only if arg is an object.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.obj)
|
||||
ofile=$2
|
||||
;;
|
||||
*)
|
||||
set x "$@" -o "$2"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*.c)
|
||||
cfile=$1
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
if test -z "$ofile" || test -z "$cfile"; then
|
||||
# If no `-o' option was seen then we might have been invoked from a
|
||||
# pattern rule where we don't need one. That is ok -- this is a
|
||||
# normal compilation that the losing compiler can handle. If no
|
||||
# `.c' file was seen then we are probably linking. That is also
|
||||
# ok.
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
# Name of file we expect compiler to create.
|
||||
cofile=`echo "$cfile" | sed -e 's|^.*/||' -e 's/\.c$/.o/'`
|
||||
|
||||
# Create the lock directory.
|
||||
# Note: use `[/.-]' here to ensure that we don't use the same name
|
||||
# that we are using for the .o file. Also, base the name on the expected
|
||||
# object file name, since that is what matters with a parallel build.
|
||||
lockdir=`echo "$cofile" | sed -e 's|[/.-]|_|g'`.d
|
||||
while true; do
|
||||
if mkdir "$lockdir" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
# FIXME: race condition here if user kills between mkdir and trap.
|
||||
trap "rmdir '$lockdir'; exit 1" 1 2 15
|
||||
|
||||
# Run the compile.
|
||||
"$@"
|
||||
ret=$?
|
||||
|
||||
if test -f "$cofile"; then
|
||||
mv "$cofile" "$ofile"
|
||||
elif test -f "${cofile}bj"; then
|
||||
mv "${cofile}bj" "$ofile"
|
||||
fi
|
||||
|
||||
rmdir "$lockdir"
|
||||
exit $ret
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
246
configure.ac
246
configure.ac
|
@ -1,246 +0,0 @@
|
|||
dnl --- Package name is first argument to AC_INIT
|
||||
dnl --- Release version is second argument to AC_INIT
|
||||
|
||||
AC_INIT(desmume, [0.9])
|
||||
|
||||
dnl -- find target architecture for some os specific libraries
|
||||
AC_CANONICAL_TARGET
|
||||
case $target in
|
||||
*linux*) desmume_arch=linux;;
|
||||
*mingw*) desmume_arch=windows;;
|
||||
*darwin*) desmume_arch=linux;;
|
||||
*bsd*) desmume_arch=linux;;
|
||||
esac
|
||||
AC_SUBST(desmume_arch)
|
||||
|
||||
AM_INIT_AUTOMAKE
|
||||
|
||||
dnl -- make sure we have a C compiler
|
||||
AC_PROG_CC
|
||||
|
||||
dnl -- make sure we have a c++ compiler
|
||||
AC_PROG_CXX
|
||||
|
||||
dnl -- use ranlib for libraries
|
||||
AC_PROG_RANLIB
|
||||
|
||||
dnl -- check for endianess
|
||||
AC_C_BIGENDIAN
|
||||
|
||||
dnl --- Other prerequisites ---
|
||||
dnl - Check for pkg-config macros
|
||||
m4_ifdef([PKG_PROG_PKG_CONFIG], [PKG_PROG_PKG_CONFIG])
|
||||
dnl - Check for intltool/gettext macros
|
||||
m4_ifdef([IT_PROG_INTLTOOL],[IT_PROG_INTLTOOL])
|
||||
|
||||
dnl - Check for zlib
|
||||
AC_CHECK_LIB(z, gzopen)
|
||||
|
||||
dnl - Check for zziplib
|
||||
AC_CHECK_LIB(zzip, zzip_open)
|
||||
|
||||
dnl - Check for SDL
|
||||
AC_PATH_PROGS(SDLCONFIG, [sdl-config sdl11-config])
|
||||
if test ! "x$SDLCONFIG" = "x" ; then
|
||||
SDL_CFLAGS=`$SDLCONFIG --cflags`
|
||||
SDL_LIBS=`$SDLCONFIG --libs`
|
||||
AC_SUBST(SDL_CFLAGS)
|
||||
AC_SUBST(SDL_LIBS)
|
||||
HAVE_SDL="yes"
|
||||
else
|
||||
HAVE_SDL="no"
|
||||
fi
|
||||
|
||||
dnl - Check for the OpenGL includes
|
||||
AC_CHECK_HEADERS([GL/gl.h])
|
||||
AC_CHECK_HEADERS([GL/glu.h])
|
||||
|
||||
dnl - Check for GTK and/or libglade
|
||||
GLIB_VER=2.8
|
||||
GTK_VER=2.6
|
||||
AC_CHECK_TOOL(HAVE_PKG, pkg-config)
|
||||
AC_PROVIDE_IFELSE([PKG_PROG_PKG_CONFIG], [
|
||||
if test ! "x$HAVE_PKG" = "x" ; then
|
||||
PKG_CHECK_MODULES(GLIB,
|
||||
glib-2.0 >= $GLIB_VER,
|
||||
HAVE_GLIB=yes,
|
||||
HAVE_GLIB=no)
|
||||
if test "$HAVE_GLIB" = "no"; then
|
||||
AC_MSG_ERROR([glib-2.0 >= $GLIB_VER is required to build desmume gtk frontend])
|
||||
fi
|
||||
|
||||
PKG_CHECK_MODULES(GTK,
|
||||
gtk+-2.0 >= $GTK_VER,
|
||||
HAVE_GTK=yes,
|
||||
HAVE_GTK=no)
|
||||
if test "$HAVE_GTK" = "no"; then
|
||||
AC_MSG_ERROR([gtk-2.0 >= $GTK_VER is required to build desmume gtk frontend])
|
||||
fi
|
||||
AC_SUBST(GTK_CFLAGS)
|
||||
AC_SUBST(GTK_LIBS)
|
||||
|
||||
PKG_CHECK_MODULES(GTKGLEXT,
|
||||
"gtkglext-1.0",
|
||||
HAVE_GTKGLEXT=yes,
|
||||
HAVE_GTKGLEXT=no)
|
||||
AC_SUBST(GTKGLEXT_CFLAGS)
|
||||
AC_SUBST(GTKGLEXT_LIBS)
|
||||
|
||||
PKG_CHECK_MODULES(GTHREAD,
|
||||
"gthread-2.0",
|
||||
HAVE_GTHREAD=yes,
|
||||
HAVE_GTHREAD=no)
|
||||
AC_SUBST(GTHREAD_CFLAGS)
|
||||
AC_SUBST(GTHREAD_LIBS)
|
||||
|
||||
|
||||
AC_CHECK_LIB(gdkglext-x11-1.0, gdk_gl_init)
|
||||
|
||||
PKG_CHECK_MODULES(LIBGLADE,
|
||||
"libglade-2.0",
|
||||
HAVE_LIBGLADE=yes,
|
||||
HAVE_LIBGLADE=no)
|
||||
AC_SUBST(LIBGLADE_CFLAGS)
|
||||
AC_SUBST(LIBGLADE_LIBS)
|
||||
|
||||
dnl uninstalled glade ui dir
|
||||
AC_DEFINE_UNQUOTED(GLADEUI_UNINSTALLED_DIR,"`pwd`/src/gtk-glade/glade/",[path to glade ui dir])
|
||||
AC_SUBST(GLADEUI_UNINSTALLED_DIR)
|
||||
fi
|
||||
],[
|
||||
echo "WARNING: pkg-config is not available therefore gtk and gtk-glade UIs are not available either."
|
||||
])
|
||||
|
||||
dnl - If the gtkGLext package is available define the corresponding C macro
|
||||
if test "x$HAVE_GTKGLEXT" = "xyes"; then
|
||||
AC_DEFINE([GTKGLEXT_AVAILABLE], [1])
|
||||
fi
|
||||
|
||||
dnl - Determine which UIs to build and if po/ should be included
|
||||
PO_DIR=""
|
||||
PO_FILES=""
|
||||
PO_FILES_IN=""
|
||||
if test "x$HAVE_SDL" = "xyes"; then
|
||||
# SDL adds just a cli
|
||||
UI_DIR="cli $UI_DIR"
|
||||
if test "x$HAVE_GTK" = "xyes"; then
|
||||
# GTK requires SDL
|
||||
UI_DIR="gtk $UI_DIR"
|
||||
fi
|
||||
|
||||
if test "x$HAVE_LIBGLADE" = "xyes"; then
|
||||
AC_PROVIDE_IFELSE([IT_PROG_INTLTOOL],[
|
||||
# libglade requires SDL too
|
||||
UI_DIR="gtk-glade $UI_DIR"
|
||||
|
||||
dnl -- localization for gtk-glade UI
|
||||
GETTEXT_PACKAGE=desmume
|
||||
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [Define to the gettext package name])
|
||||
AC_SUBST(GETTEXT_PACKAGE)
|
||||
ALL_LINGUAS="fr pt_BR"
|
||||
AM_GLIB_GNU_GETTEXT
|
||||
PO_DIR="po"
|
||||
PO_FILES="intltool-extract intltool-merge intltool-update"
|
||||
PO_FILES_IN="intltool-extract.in intltool-merge.in intltool-update.in"
|
||||
PO_MAKEFILE="po/Makefile.in"
|
||||
],[
|
||||
echo "WARNING: intltool and/or gettext are not available therefore the gtk-glade interface won't be installed. The gtk-glade UI requires intltool and gettext."
|
||||
])
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl Set compiler library flags per target.
|
||||
case $target in
|
||||
*linux* | *bsd*)
|
||||
LIBS="$LIBS -lGL -lGLU"
|
||||
;;
|
||||
*mingw*)
|
||||
LIBS="$LIBS -ldxguid -ldxerr8 -ldsound -lopengl32 -lws2_32 -mwindows"
|
||||
UI_DIR="windows"
|
||||
;;
|
||||
*darwin*)
|
||||
LIBS="$LIBS -framework OpenGL"
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_SUBST(UI_DIR)
|
||||
AC_SUBST(PO_DIR)
|
||||
AC_SUBST(PO_FILES)
|
||||
AC_SUBST(PO_FILES_IN)
|
||||
|
||||
dnl - Gdb stub
|
||||
AC_ARG_ENABLE(gdb-stub,
|
||||
[AC_HELP_STRING(--enable-gdb-stub, enable gdb stub)],
|
||||
[
|
||||
AC_DEFINE(GDB_STUB)
|
||||
wantgdbstub=yes
|
||||
])
|
||||
AM_CONDITIONAL([HAVE_GDB_STUB], [test "${wantgdbstub}" = "yes"])
|
||||
|
||||
dnl - Compiler warnings
|
||||
|
||||
# for developer use, enable lots of compile warnings,
|
||||
# but don't require this generally, because some system's
|
||||
# header files (BSD) can't handle it
|
||||
#
|
||||
# NB: must add -Werror after AC_PROG_CC, etc., so do this last
|
||||
AC_ARG_ENABLE(hardcore,
|
||||
[AC_HELP_STRING(--enable-hardcore, turn on -W -Wall -Werror)],
|
||||
[case "${enableval}" in
|
||||
yes) ENABLE_HARDCORE=1 ;;
|
||||
no) ENABLE_HARDCORE=0 ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-hardcore) ;; esac],
|
||||
[ENABLE_HARDCORE=0])
|
||||
|
||||
if test "x[$]ENABLE_HARDCORE" = "x1"; then
|
||||
AC_MSG_WARN(enable hardcore compile warnings)
|
||||
if test "x$CXX" = "x"; then
|
||||
dnl - only valid for C with newer gcc's
|
||||
CPPFLAGS="[$]CPPFLAGS -Wmissing-prototypes"
|
||||
fi
|
||||
CPPFLAGS="[$]CPPFLAGS -Wall -Wextra -Wno-missing-field-initializers -Wpointer-arith -Wcast-align -Wwrite-strings -Wno-unused-parameter -Wmissing-declarations -Wundef -Wmissing-noreturn -Wshadow"
|
||||
fi
|
||||
|
||||
dnl - Enable debug mode
|
||||
AC_ARG_ENABLE(debug,
|
||||
AC_HELP_STRING(--enable-debug, enable debug information),
|
||||
AC_DEFINE(DEBUG))
|
||||
AC_ARG_ENABLE(gpu-debug,
|
||||
AC_HELP_STRING(--enable-gpu-debug, enable gpu debug information),
|
||||
AC_DEFINE(GPUDEBUG))
|
||||
AC_ARG_ENABLE(div-debug,
|
||||
AC_HELP_STRING(--enable-div-debug, enable div debug information),
|
||||
AC_DEFINE(DIVDEBUG))
|
||||
AC_ARG_ENABLE(sqrt-debug,
|
||||
AC_HELP_STRING(--enable-sqrt-debug, enable sqrt debug information),
|
||||
AC_DEFINE(SQRTDEBUG))
|
||||
AC_ARG_ENABLE(dma-debug,
|
||||
AC_HELP_STRING(--enable-dma-debug, enable dma debug information),
|
||||
AC_DEFINE(DMADEBUG))
|
||||
|
||||
dnl - Enable memory profiling
|
||||
AC_ARG_ENABLE(memory-profiling,
|
||||
AC_HELP_STRING(--enable-memory-profiling, enable memory profiling information),
|
||||
AC_DEFINE(PROFILE_MEMORY_ACCESS))
|
||||
|
||||
dnl -- set maintainer mode
|
||||
AM_MAINTAINER_MODE
|
||||
AC_SUBST(USE_MAINTAINER_MODE)
|
||||
|
||||
|
||||
dnl --- Finally, output all the makefiles
|
||||
AC_CONFIG_FILES([Makefile
|
||||
${PO_MAKEFILE}
|
||||
src/Makefile
|
||||
src/cli/Makefile
|
||||
src/cli/doc/Makefile
|
||||
src/cocoa/Makefile
|
||||
src/gtk/Makefile
|
||||
src/gtk/doc/Makefile
|
||||
src/gtk-glade/Makefile
|
||||
src/gtk-glade/doc/Makefile
|
||||
src/windows/Makefile
|
||||
src/gdbstub/Makefile
|
||||
autopackage/default.apspec
|
||||
])
|
||||
AC_OUTPUT
|
|
@ -6,21 +6,12 @@ Current team
|
|||
------------
|
||||
Guillaume Duhamel
|
||||
Normmatt
|
||||
Bernat Muñoz (shash)
|
||||
thoduv
|
||||
Tim Seidel (Mighty Max)
|
||||
Pascal Giard (evilynux)
|
||||
Ben Jaques (masscat)
|
||||
Jeff Bland
|
||||
Andres Delikat
|
||||
Riccardo Magliocchetti
|
||||
Max Tabachenko (CrazyMax/mtabachenko)
|
||||
zeromus
|
||||
Luigi__
|
||||
adelikat
|
||||
rogerman
|
||||
|
||||
Contributors
|
||||
------------
|
||||
Bernat Muñoz (shash)
|
||||
Allustar
|
||||
amponzi
|
||||
Anthony Molinaro
|
||||
|
@ -30,3 +21,30 @@ delfare
|
|||
Romain Vallet
|
||||
snkmad
|
||||
Theo Berkau
|
||||
thoduv
|
||||
Tim Seidel (Mighty Max)
|
||||
Pascal Giard (evilynux)
|
||||
Ben Jaques (masscat)
|
||||
Jeff Bland
|
||||
Bernat Muñoz (shash)
|
||||
matusz
|
||||
nitsuja
|
||||
gocha
|
||||
pa__
|
||||
adelikat
|
||||
hi-coder
|
||||
WinterMute
|
||||
pengvado
|
||||
dormito
|
||||
ldesnogue
|
||||
mtheall
|
||||
thelemonman
|
||||
nash679
|
||||
pokefan999
|
||||
dottorleo
|
||||
yki
|
||||
Luigi__
|
||||
CrazyMax
|
||||
Riccardo Magliocchetti
|
||||
CyberWarriorX
|
||||
mic
|
|
@ -1,12 +1,12 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
|
@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
|
|||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
|
@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.
|
|||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
|
@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
|
|||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
|
@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
|
|||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
|
@ -225,7 +225,7 @@ impose that choice.
|
|||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
|
@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
|
|||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
|
@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
|||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
|
@ -303,17 +303,16 @@ the "copyright" line and a pointer to where the full notice is found.
|
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names:
|
|||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
|
@ -0,0 +1,972 @@
|
|||
0.9.12 -> 0.9.13
|
||||
|
||||
In this version we have added support for high-resolution 3D rendering. Try the new "GPU Scaling Factor" feature to
|
||||
increase the 3D resolution beyond the native resolution of 256x192 pixels. Also, the Cocoa frontend sees continued
|
||||
radical enhancements and while the Windows frontend sees some new incremental enhancements.
|
||||
|
||||
General/Core:
|
||||
bug: numerous host compatibility and accuracy improvements to OpenGL renderer, tho off-by-1 sampling bugs will remain.
|
||||
bug: fixes to 'edge marking', shadows, box tests, maths & depths precision, and some other rarer 3d rendering usecases
|
||||
bug: fixes to AR cheat processing
|
||||
bug: fixes to cheat database game identification
|
||||
bug: fix interpolation at SPU loop points, emulation of SPU half/byte size registers & others
|
||||
bug: backlight emulation added (for fade effects)
|
||||
bug: other small ongoing fixes to 2d rendering and GPU memory maps
|
||||
bug: emulate slot-1 read timings, probably for AP-related purposes
|
||||
bug: general improvement to hardware component power-off state handling, especially 3d engine
|
||||
bug: fix virtual fat (homebrew) building in environment with symlinks
|
||||
bug: fix some rarely-bugged CPU instructions
|
||||
bug: fix bugs in homebrew filesystems
|
||||
bug: fix bugs in big-endian hosts
|
||||
bug: fix loading gzipped files and some newer rars
|
||||
bug: fix inconsistencies and omissions in command-line processing
|
||||
bug: extensive improvement to wifi emulation, though wifi is still not supported.
|
||||
bug: firmware file settings/management now behaves more or less sensibly as advertised
|
||||
bug: fix movie (dsm) being bitrotted and failing to sync settings or manage sram properly
|
||||
enh: movie (dsm) add record from state feature
|
||||
enh: high-resolution 3d rendering, from 1x-16x the native resolution of 256x192 pixels
|
||||
enh: texture upscaling for 3d rendering, from 1x-4x the native texture size
|
||||
enh: texture smoothing option for OpenGL renderer
|
||||
enh: user-selectable internal GPU bpp 15/18/24 to change from accuracy to attractiveness
|
||||
enh: game-specific hacks library finally implemented internally, user-selectable.
|
||||
enh: game-specific hack for popular games that randomly corrupt their sprites when going in and out of doors
|
||||
enh: officially supported arm and arm64 jits and overall improvements on arm hosts
|
||||
enh: emulator now makes "(backups)" states on every loadstate, for in case you hit loadstate on accident
|
||||
enh: User-selectable MSAA level for OpenGL renderer.
|
||||
enh: "interface" for dll/so control of a desmume core
|
||||
enh: optimizations, cpu arch-specific, and otherwise, to all 3d and 2d rendering, ranging from SSE to AVX2
|
||||
enh: lua - Add raw joystick API and setlayermask API (windows only)
|
||||
enh: lua - Add gamecode APU for game-specific hacks in scripts and 'freelook' script functionality
|
||||
enh: add options to emulate game cards more badly, to trip AP on purpose
|
||||
enh: fix some save type / slot type autodetections and save memory import codepaths
|
||||
enh: add fake impossible debug AR code to select CPU: DFFFFFFF 77777777/99999999
|
||||
enh: add --rtc-day and --rtc-hour to specify an offset from host RTC
|
||||
enh: support newer duc files
|
||||
enh: upgrade and add some upscalers, hq3x, 6xBRZ, etc.
|
||||
enh: add "interface" frontend for use via dll/so
|
||||
|
||||
Windows:
|
||||
note: windows xp and x86 support is dropped for official builds. windows 7 support will be dropped over my dead body.
|
||||
bug: fix numerous bugs involving filenames and path with non-latin characters
|
||||
bug: fix bugs in various display layout, rotate, vsync, gaps, and display method configurations
|
||||
bug: fix bugs in user configured paths
|
||||
bug: aviout/wavout is now more robust
|
||||
bug: fix bugs in window clearing and various display method configurations which leave garbage on screen
|
||||
enh: add fullscreen display options
|
||||
enh: major revisions to mic sample feature, loaded as a bunch and rotated with hotkeys
|
||||
enh: add user-facing option to control console window visibility
|
||||
enh: add some crude capability for breakpoints to cpu debugger and memory viewer, and other bugfixes
|
||||
enh: add "screen size ratio" for smaller sub-screens, etc.
|
||||
enh: add some hotkeys
|
||||
enh: add option to kill stylus input when outside the NDS screen
|
||||
enh: improve cheat list UX
|
||||
enh: optimizations to reduce cpu usage overall and during idle especially for high resolutions, scalers, etc.
|
||||
enh: improve pen&touch support
|
||||
|
||||
Cocoa:
|
||||
bug: fix issues with v-sync causing frame rate issues under various circumstances
|
||||
bug: fix issues when running a display window in fullscreen
|
||||
enh: add native binary support for Apple Silicon CPUs
|
||||
enh: Macs with an Intel Haswell or later CPU now benefit from the new AVX2 optimizations
|
||||
enh: add support for Apple's Dark Mode user interface introduced in macOS Mojave
|
||||
enh: add some new toolbar items for the following: Frame Advance, Enable/Disable HUD, Toggle Displays
|
||||
enh: turbo inputs can now be configured with a frame-by-frame press/release pattern
|
||||
enh: display windows now run their video output using Metal, if available
|
||||
enh: display windows now support HiDPI monitors like Apple's Retina monitors
|
||||
enh: display windows have new "Hybrid" layouts for better fit on modern widescreen monitors (View > Display Layout)
|
||||
enh: display windows can now change the video source going to each individual DS screen (View > Display Video Source)
|
||||
enh: display windows can now run a Heads-Up Display for reporting useful info (View > Show HUD Settings)
|
||||
enh: add support for changing the NDS stylus pressure (Emulation > Show Stylus Settings)
|
||||
enh: screenshots can now be captured using a dedicated tool for it (Tools > Show Screenshot Capture Tool)
|
||||
enh: lots of miscellaneous stability and performance improvements
|
||||
|
||||
Linux:
|
||||
note: SDL2 now employed
|
||||
note: GTK3 port added, built with meson
|
||||
note: CLI and GTK ports improved, according to their respective niche (gaming vs functionality)
|
||||
note: CLI: added horizontal screen layout
|
||||
note: CLI: added floating-point scale factor support with HW stretching
|
||||
note: CLI/GTK2: improved gdb stub for game debugging
|
||||
note: CLI/GTK2/GTK3: various other improvements
|
||||
|
||||
0.9.11 -> 0.9.12
|
||||
|
||||
We decided to start skipping even versions to disambiguate official releases from several years of interim builds,
|
||||
and to insulate ourselves from consideration for world record of "longest time between consecutive releases" by
|
||||
creating confusion as to what constitutes a consecutive release.
|
||||
|
||||
0.9.10 -> 0.9.11 (r4908-r5146)
|
||||
|
||||
In this version, we have focused on the Cocoa frontend, but there have been some good core fixes over so long.
|
||||
Notably, the save-related issues resulting in the advice "dont use 0.9.10" have been resolved.
|
||||
|
||||
General/Core:
|
||||
bug: fix large numbers of games not being able to save anymore
|
||||
bug: fix some missing sound effects due to wrong volumes in some boot scenarios and other things
|
||||
bug: fix freezes due to tiny looping sounds
|
||||
bug: fix many big endian issues
|
||||
bug: fix some apparently rarely-used CPU instructions, no known consequences
|
||||
bug: fix (block) reading of some GPU registers
|
||||
bug: fix action replay code type 0xE
|
||||
bug: fix reading of last 4 bytes of rom
|
||||
bug: large improvements to stability of GDB stub
|
||||
bug: support w-buffer support in OpenGL renderers
|
||||
bug: fix unpredictable crashes in some 3d scenes from w=0
|
||||
enh: better loading of roms (bad patches) with wrong size info in header
|
||||
enh: warn user sometimes when 'stream rom from disk' will create malfunctions
|
||||
enh: add xBRZ filters
|
||||
enh: add "TXT Hack" for software rasterizer to improve text rendering in some games
|
||||
|
||||
Windows:
|
||||
bug: fix 5x filters
|
||||
enh: support import of action replay save files (.dss)
|
||||
enh: add antialiasing option for OpenGL renderers
|
||||
enh: don't malfunction if saveram is unavailable or read-only
|
||||
|
||||
Cocoa:
|
||||
bug: 16-bit to 32-bit color space conversions no longer darken video or images
|
||||
bug: fix intermittent issues with loading user defaults on app startup
|
||||
bug: fix rendering inaccuracies of the video preview in the app display preferences
|
||||
bug: fix various UI font rendering and text alignment issues on OS X Yosemite
|
||||
bug: fix crackly sound from N-sync and Z-sync methods
|
||||
enh: make N-sync method the default sound sync method since it has much lower latency than P-sync method
|
||||
enh: add support for gdbstub (Tools > Show GDB Stub Control) (only available on custom builds using the dev+ build target)
|
||||
enh: optimize input handling to use less CPU
|
||||
enh: add support for App Nap when the app is in an idle state (only supported on OS X Mavericks and later)
|
||||
enh: add Execution Control panel (Emulation > Show Execution Control), now with frame advance and frame jump controls
|
||||
enh: auto frame skip is now smoother
|
||||
enh: further improve execution timing accuracy
|
||||
enh: improve overall video performance
|
||||
enh: render video through a 3-stage filtering pipeline, (Video Source)-->(Pixel Scaler)-->(Video Output)
|
||||
enh: add the following video source filters - Deposterize
|
||||
enh: add the following video output filters - Bicubic B-Spline, Bicubic Mitchell-Netravali, Lanczos2, Lanczos3
|
||||
enh: add ability to run all existing pixel scalers on either the CPU or the GPU
|
||||
enh: add ability to toggle the main and touch display positions (View > Toggle All Displays)
|
||||
enh: add preliminary support for replay playback and recording
|
||||
enh: add support for turbo and autohold
|
||||
enh: add support for the entire suite of slot-2 devices (Emulation > Show SLOT-2 Manager)
|
||||
enh: add support for using the host machine's audio input device for emulating the NDS microphone (Emulation > Show Microphone Settings)
|
||||
enh: change the sine wave tone generator's range from 100Hz-5000Hz to 40Hz-4000Hz
|
||||
enh: reorganize the menu options to more logical locations
|
||||
enh: greatly improve the File Migration Assistant (now renamed Game Data Migration Assistant) and ROM Info panel with a more modern and space efficient look and feel
|
||||
enh: miscellaneous user interface improvements
|
||||
|
||||
Linux:
|
||||
bug: fix screen gap bug
|
||||
bug: workaround for std::bad_alloc exceptions compiler bugs
|
||||
enh: add experimental AV recording
|
||||
enh: generally improve main loop throttling and skipping
|
||||
enh: massive improvements to HUD and menu layout
|
||||
enh: add window sizing options and sound interpolation options
|
||||
enh: add Lid button; disallow U+D, L+R; manual option saving
|
||||
|
||||
0.9.9 -> 0.9.10 (r4623-r4908)
|
||||
|
||||
In this version, we have focused on trying to clean up some complexities in the user experience and emulator internals. Pretty unglamorous stuff, but some games are newly compatible.
|
||||
|
||||
General/Core:
|
||||
enh: break savestate back-compatibility
|
||||
bug: improve save size autodetection for some games
|
||||
bug: cpu: fix many basic jit cpu bugs
|
||||
bug: 3d: tweak softrasterizer edge marking
|
||||
bug: 3d: fix stale 4x4 texture palettes
|
||||
bug: fix some GPU sprite blending scenarios
|
||||
bug: fix bios HLE BitUnPack, UnCompHuffman
|
||||
enh: modular slot-1 device system, emulate GC bus more faithfully
|
||||
enh: support NAND slot-1 device
|
||||
enh: auto-detect appropriate slot-1 and slot-2 device
|
||||
enh: many revisions to firmware boot process for more authenticity. iQue and FlashME versions function, .dfc rewritten.
|
||||
enh: support streaming NDS file from disk (like an ISO, to avoid long initial load time)
|
||||
enh: run .dsv directly on disk, to save long flushing times. should speed backup operations.
|
||||
enh: spu synch mode and method on commandline
|
||||
|
||||
Windows:
|
||||
bug: fixes to advanscene DB import
|
||||
bug: save opengl display method filter option
|
||||
bug: general bugfixes to various screen layout modes
|
||||
enh: add option to stop non-integer scaling during fullscreen or maximize
|
||||
enh: improvements to save import dialog
|
||||
enh: improved memory viewer tool
|
||||
enh: operate better when run, against our advice, from a zipfile
|
||||
enh: add slot-1 Nitro Filesystem viewer tool
|
||||
|
||||
Cocoa:
|
||||
bug: fix slot1-R4 path saving
|
||||
bug: fix bug with mic samples < 16khz
|
||||
bug: fix bugs and enhancements in multi display windows
|
||||
bug: fix handling of some joystick analog inputs
|
||||
enh: save display windows configuration and emulation speed on app exit
|
||||
|
||||
0.9.8 -> 0.9.9 (r4228-r4623)
|
||||
|
||||
Yes, it's been a while since the last release, but we haven't been completely idle. There's a brand new jit cpu core which yields some impressive speedups!
|
||||
|
||||
General/Core:
|
||||
!!!: add optional arm cpu jit (functioning on x86 and x64 hosts only)
|
||||
bug: we're not going to list 70% of the emulation fixes, as is traditional.
|
||||
bug: savestate reliability fixes related to halt states, gxstat, firmware
|
||||
bug: lua: fix readbyterange, gdscreenshot functions
|
||||
bug: commandline slot-1 handling straightened out
|
||||
enh: fixes and additions to resize filter options
|
||||
|
||||
Graphics:
|
||||
enh: opengl 3d driver compatibility improvements
|
||||
bug: fix giant regression from 0.9.7 that left garbage from previous frames on the screen in some games
|
||||
bug: 3d: fix some single poly pixels
|
||||
bug: 3d: fix some polygon and texture coloring bugs on big-endian systems
|
||||
|
||||
Windows:
|
||||
bug: fix some full screen stretching bugs
|
||||
enh: add xaudio2 output driver
|
||||
enh: add opengl display method (as opposed to directdraw), with controllable bilinear filter
|
||||
enh: upgrade archive handling system, lzma2 supported
|
||||
enh: reorganize main menu quite a bit
|
||||
enh: add rotation hotkeys, and hotkey to control mouse cursor visibility
|
||||
enh: memory viewer improvements and fixes
|
||||
enh: improve interface for rom eject to prevent accidents and improve usefulness (hide in slot-1 config screen)
|
||||
|
||||
Cocoa:
|
||||
bug: fix missing display when running on OS X v10.8 Mountain Lion
|
||||
bug: fix possible sound crash when using Dual SPU Synch/Asynch
|
||||
bug: fix File menu items being disabled after the file migration sheet is used
|
||||
bug: fix window resizing issues
|
||||
bug: fix text rendering in About box
|
||||
enh: show the icon and name of the loaded ROM
|
||||
enh: add Support Request and Bug Report forms to the Help menu
|
||||
enh: add more detailed info to the About box
|
||||
enh: add OpenGL as a 3D rendering option
|
||||
enh: add support for MSAA when using OpenGL as the 3D rendering engine
|
||||
enh: add V-Sync option
|
||||
enh: add Display Orientation, Display Order, and Display Separation options for Combo Display mode
|
||||
enh: add HQ4xS filter
|
||||
enh: completely revamp the user interface for Input Preferences
|
||||
enh: many emulator commands may now be mapped
|
||||
enh: add ability to map an input to user-defined touch screen coordinates
|
||||
enh: add support for saving and applying input profiles
|
||||
enh: add support for using an audio file for the microphone input
|
||||
enh: add sine wave tone generator for microphone input
|
||||
enh: add support for multiple display windows (File > New Display Window)
|
||||
enh: add support for SLOT-1 devices (Emulation > Show SLOT-1 Manager)
|
||||
enh: overall performance and stability improvements
|
||||
enh: miscellaneous user interface improvements
|
||||
|
||||
0.9.7 -> 0.9.8 (r3812-r4228)
|
||||
|
||||
Yes, it's been a while since the last release, but we haven't been completely idle. There's a brand new top shelf Cocoa frontend to make life far more pleasant for OSX users, and a host of compatibility fixes.
|
||||
|
||||
General/Core:
|
||||
bug: fix more IPC FIFO errors
|
||||
bug: import more save files correctly
|
||||
bug: don't autopatch already-patched roms
|
||||
bug: fix bugs in piano and guitar grip
|
||||
bug: fix ARM7's VRAMSTAT register
|
||||
bug: fix memory leaks on compact flash emulation
|
||||
bug: fix reading of rom from low header area
|
||||
bug: spu: fix some poppy interpolation audio quality issues
|
||||
bug: improve timing of dma operations by running through normal mem cycle accounting; fixes an annoying number of games and graphical glitches
|
||||
bug: fix opcode MRC and fake bios CRC16
|
||||
enh: jitter some related register and irq events to simulate pipeline effects and stimulate some race conditions to other outcomes
|
||||
enh: fake (deterministic) some tiny jitter from human's hand holding stylus; some games were accidentally depending on this
|
||||
enh: support nocash-style prints from arm
|
||||
enh: add lua apis for accessing vram
|
||||
enh: platforms other than windows receive threading optimizations
|
||||
enh: provide diagnostics when system powers off (useful for homebrewers returning from main())
|
||||
enh: clarify handling of different console types within the family (ds,dslite,debug)
|
||||
enh: vfat support for slot-1 devices
|
||||
enh: emulate temperature register
|
||||
enh: add paddle emulation
|
||||
|
||||
Graphics:
|
||||
bug: fix occasional crash from uninitialized blending table
|
||||
bug: fix some 2d alpha blending cases resulting in white screens
|
||||
bug: fix VRAM_I B_OBJ mirroring and fix sprites rendering across the end of vram
|
||||
bug: fix rotoscaled sprites wrapping around screen
|
||||
bug: dont fix rotscaled bitmap sprites with alpha==0
|
||||
bug: opengl: fix degradation of toon rendering during loadstate
|
||||
bug: opengl: alpha blending fixes
|
||||
bug: many refinements to opengl renderer
|
||||
bug: opengl: support rear-plane/ClearImage emulation (fixes many graphics)
|
||||
bug: rasterizer: fix some rare alpha blending cases
|
||||
bug: fix bug in environment mapping introduced after 0.9.6
|
||||
bug: fix totally glitched out 3d graphics with several improvements involving matrix stack
|
||||
bug: fix memory overflows in epx filter
|
||||
bug: prevent backdrop from blending with ???
|
||||
enh: opengl: better depth buffering emulation
|
||||
enh: better support for line segment "polys" by detection and special rendering logic
|
||||
enh: opengl: support quad primitives directly
|
||||
enh: add hq4x filter
|
||||
|
||||
Windows:
|
||||
bug: fix a long-standing loadstate crash
|
||||
bug: fix lag frame accounting
|
||||
bug: fix glitches in cheat entry menu
|
||||
bug: stop compact flash emulation from accidentally scanning c:\ sometimes
|
||||
enh: add support for game database for improved save type detection
|
||||
enh: hotkey for limit framerate toggle
|
||||
enh: remove stop and reset toolbar buttons which were accidentally getting used
|
||||
enh: additional complexification to desmume's behaviour run from a console prompt. whether it's better is uncertain.
|
||||
enh: add support for cheats databases
|
||||
enh: improvements to ram search tool
|
||||
enh: preliminary support for varying stylus pressure
|
||||
enh: add [Display] Show Console=1 to ini file
|
||||
enh: more graceful cheat parsing and add some hotkeys
|
||||
enh: add 5x window size
|
||||
enh: add big endian and 20.12 toggle to memview and ramwatch
|
||||
enh: improve FPS throttle feedback and granularity
|
||||
enh: add lua menu API
|
||||
enh: hud font switching
|
||||
enh: add optional file association for .nds to path config dialog
|
||||
|
||||
Cocoa:
|
||||
enh: Big update to cocoa frontend. Pretty much entirely new. (rogerman)
|
||||
|
||||
Linux:
|
||||
bug: gtk: glitches in rom and recent rom loading
|
||||
bug: glade: normalize savestate slot to hotkey mapping
|
||||
enh: support soundtouch for use by metaspu
|
||||
enh: gtk: add SPU mode selection (Tobias Jakobi)
|
||||
enh: cli: better fps limiting (Thomas Jones)
|
||||
|
||||
Wx:
|
||||
bug: some small fixes here and there (Jan Bücken)
|
||||
enh: lot of code cleanup (Jan Bücken)
|
||||
|
||||
0.9.6 -> 0.9.7 (r3493-r3812)
|
||||
|
||||
General/Core:
|
||||
bug: fix a ton of old, broken cpu opcodes and CP15 logic
|
||||
bug: return Z1 and Z2 from TSC (fixes some touch logic)
|
||||
bug: gba slot save type detection improved
|
||||
bug: handle unusual rom headers more correctly
|
||||
bug: dont confuse motion pack commands with save memory commands
|
||||
bug: make cheat system a little less flaky and add AR 1.54 support
|
||||
bug: fix nondeterministic backup memory behaviour while rerecording
|
||||
bug: correct emulation of register accesses of wrong size and during powerdown
|
||||
bug: rewrite --cflash-path emulation
|
||||
bug: rewrite IPC/GX FIFO, IRQ flag generation, and wait-for-IRQ logics
|
||||
bug: rewrite RTC calendar handling; now supports years > 2038
|
||||
enh: auto-DLDI patching for homebrew
|
||||
enh: --gbaslot-rom=self mounts self.nds in slot2
|
||||
enh: more realistic exception handling
|
||||
enh: piano controller emulation
|
||||
enh: modular slot-1 system for exact emulation of homebrew cards
|
||||
|
||||
Graphics:
|
||||
bug: edge marking colors were wrong
|
||||
bug: handle some "invalid" vram configurations correctly
|
||||
bug: convert half of geometry engine to fixed point
|
||||
bug: fix sprite blend+fadein/fadeout
|
||||
bug: improve rasterizer shadows
|
||||
bug: fix main memory display DMA
|
||||
bug: fix some raster fx timing bugs
|
||||
enh: add a hack for improving some non-stencil shadows
|
||||
|
||||
Windows:
|
||||
bug: misc fixes and improvements to gpu viewer tools
|
||||
bug: sub screen layer display toggling fixed
|
||||
bug: fixes and improvements to ram watch, ram search, cheats list
|
||||
bug: fix start-paused commandline
|
||||
bug: fix memory leaks when sound disabled
|
||||
bug: improve load average calculators and add arm7 load average
|
||||
enh: background input support
|
||||
enh: add vsync option
|
||||
enh: support more knobs on joysticks
|
||||
enh: import cheats from R4 database
|
||||
enh: add xinput rumble for 360 pads
|
||||
|
||||
Linux/OSX:
|
||||
bug: crash less in recent roms list
|
||||
enh: Add horizontal screen layout and swap screen ability to gtk frontend (noodlebox)
|
||||
enh: Big improvement to joystick support, support complex configurations and multiple devices (noodlebox)
|
||||
|
||||
|
||||
0.9.5 -> 0.9.6 (r3075-r3493)
|
||||
|
||||
Users of gtk, cli and gtk-glade frontends please note that now we
|
||||
have a common directory in ~/.config/desmume for config file,
|
||||
saves and savestates. The old .desmume.ini will be moved
|
||||
automatically with the name config but you have to move your saves
|
||||
manually.
|
||||
|
||||
Some save files may be invalidated due to use of broken crc logic.
|
||||
Back up your DSV files before using this version of the emulator or else
|
||||
the game might wipe it.
|
||||
|
||||
General/Core:
|
||||
bug: emulate keypad interrupt
|
||||
bug: spu overhaul, add capture support
|
||||
bug: fix dma address reloading
|
||||
bug: fix rom close memory corruption
|
||||
bug: fix div and sqrt busy flag bug
|
||||
bug: fix vectest
|
||||
bug: fix lid savestate desync
|
||||
bug: fix texcache memory GB explosion when games use tons of tiny 3d sprites
|
||||
bug: fix huge rerecording movie file handle leak
|
||||
bug: fix EXXXXXXX cheat codes and some add/edit/save/load bugs
|
||||
bug: add 8MBit - 512MBit flash emulation
|
||||
bug: fix firmware booted-from-card flag
|
||||
bug: fix some failures to wake
|
||||
bug: fix some rtc calendar logic
|
||||
bug: op_bkpt emulation
|
||||
bug: correctly emulate POWCNT1 and POWCNT2 and SPI power device
|
||||
bug: corrections to bootup stack configuration
|
||||
bug: protect bios from being overwritten
|
||||
bug: initialize save data to 0xFF instead of 0x00
|
||||
bug: handle relocated irq vectors
|
||||
bug: support patched firmwares
|
||||
bug: handle 8bit auxspidata, 32bit BLDY, 32bit div regs
|
||||
bug: fix some divide by zero cases
|
||||
bug: don't print \n in ideas debug message
|
||||
bug: don't let games read off end of cart and crash emulator
|
||||
bug: fix SWI 0x0E crc16 ; some save files using wrong crc may be invalidated
|
||||
bug: fix many big endian bugs
|
||||
bug: fix CPSR.I idle wakeup
|
||||
bug: fix loadstate crashes, mostly when sound is enabled
|
||||
enh: support devkitpro argv
|
||||
enh: add gbaslot-rom commandline
|
||||
enh: add no$gba debug message
|
||||
enh: add rtc start to dsm header
|
||||
|
||||
Graphics:
|
||||
bug: fix a mistakenly rendered OBJ window and 3d blend effects
|
||||
bug: fixes to matrix stacks, fixing lots of garbled geometry
|
||||
bug: fix fog density registers
|
||||
bug: fix hblank dma to run also on scanline 262
|
||||
bug: fix w/z depth flags for broken GUIs in dual screen 3d games
|
||||
bug: fixes to poly sorting
|
||||
bug: block 8bit vram writes
|
||||
enh: improve accuracy of opengl shaders
|
||||
|
||||
Windows:
|
||||
bug: fix 16bpp display
|
||||
bug: more fixes to multi-gamepads
|
||||
bug: cheat windows robustification
|
||||
bug: fix that sticky pause state when resetting and loading roms
|
||||
bug: dont crash when no sound device is available
|
||||
bug: change F10 to be save slot 0
|
||||
bug: fix --start-paused
|
||||
enh: try not to screensave while using gamepad
|
||||
enh: add EPX and EPX1.5X resize filters
|
||||
enh: add a japanese translation which will soon be stale like the others
|
||||
enh: add fancy ctrl+printscreen with emulator info on it
|
||||
enh: add "lockdown" window mode to keep window safe from fast stylus action
|
||||
enh: add alt+enter fullscreen command
|
||||
enh: add card eject command
|
||||
enh: add ddraw software mode forcer
|
||||
enh: improve oam viewer
|
||||
enh: default 3d to rasterizer so we dont have to suggest it 1000 times a day
|
||||
enh: add dump-all-memory tool
|
||||
enh: add reload rom menu/hotkey
|
||||
|
||||
Linux/OSX:
|
||||
bug: fix building for nosse2 systems
|
||||
bug: fix --num-cores
|
||||
bug: fix occasional touchscreen failures
|
||||
bug: fix crash starting dsm record
|
||||
enh: add --nojoy=1 to fix laptops with accelerometers
|
||||
enh: add simple auto frameskip mode in the gtk frontend
|
||||
enh: add gui for configuring joystick in the gtk frontend
|
||||
enh: make the cli frontend read the ini config file too
|
||||
enh: additional OpenAL microphone backend (ncalexan)
|
||||
enh: common place for config and saves (Jan Steffens)
|
||||
enh: libagg is now optional if you don't need the hud
|
||||
|
||||
0.9.4 -> 0.9.5 (r2437-r3075)
|
||||
|
||||
0.9.5 introduces an entirely rewritten main emulation loop
|
||||
This totally changes the timing, and totally breaks old savestates.
|
||||
The OSX build is now based on the GTK port which is more up-to-date.
|
||||
|
||||
Assorted Highlights:
|
||||
* synchronous SPU mode to fix streaming sounds
|
||||
* win32: lua engine, path configuration, 7z dearchiving support
|
||||
|
||||
General/Core:
|
||||
bug: rewrite main emulation loop and cycle accounting, fixes a lot of timings
|
||||
bug: add more detailed timing emulation, removes much bogus lag
|
||||
bug: rewrite DMA,gxfifo,gxstat; fix many games and no more alternate flush mode
|
||||
bug: fix cflash directory support for non-windows and sector-writing
|
||||
bug: fix freeze in cart irq
|
||||
bug: correctly emulate dma to/from tcm
|
||||
bug: fix in thumb LSR carryflag
|
||||
bug: fix thumb BX PC switch to arm state
|
||||
bug: fix adpcm looping, remove adpcm caching (no longer necessary)
|
||||
bug: fixes to swi 3,4,5,8,0x10
|
||||
bug: fixes to exmemstat and ipc sync registers
|
||||
bug: support new backup commands
|
||||
bug: improve bootup bios/firmware emulation steps
|
||||
enh: gbaslot: add guitar grip, gbagame flash support, expansion memory pak
|
||||
enh: add more powerful antigrain-based drawing library and rewrite OSD system
|
||||
enh: ideas-style debugging prints
|
||||
enh: most optimizations now SSE instead of SSE2
|
||||
enh: more improvements to frameskipping and frame advance/speed controls
|
||||
|
||||
Graphics:
|
||||
bug: fix backdrop blending with garbage
|
||||
bug: fix 256B granularity sprite addressing for sub gpu
|
||||
bug: fix obj blending, bmp obj rendering, and some obj window cases
|
||||
bug: fix 128-wide captures
|
||||
bug: fix 16color BG line buffer overflow
|
||||
bug: fix color overflow in capture blending
|
||||
bug: fix disp fifo capture
|
||||
bug: fix simultaneous vram display and capture via same bank
|
||||
bug: fix 3d overflow acknowledge registers
|
||||
bug: fix 32bit toon table writes
|
||||
bug: change 3d cores to use 18bit color
|
||||
bug: fix boxtest (addition overflow!), move clipper to main graphics engine
|
||||
bug: fix failure in some cases of polygon clipping
|
||||
bug: fix disp3dcnt emulations
|
||||
bug: fixes to poly sorting
|
||||
bug: fix ogl renderer wireframe support
|
||||
bug: swrast: fix backface culling of nonconvex polys
|
||||
bug: swrast: add clear image and scroll emulation
|
||||
bug: swrast: add fog emulation
|
||||
bug: swrast: fixes to shadow rendering
|
||||
bug: swrast: preliminary edge marking, works decent
|
||||
enh: swrast: multicore optimization for a few fps speedup
|
||||
|
||||
Windows:
|
||||
bug: fix support for multiple gamepads and gamepad hotkeys
|
||||
bug: fix mic noise code and load wav instead of raw; effective in more cases
|
||||
bug: fix for several sticky and broken hotkeys, and f10 hotkeys
|
||||
bug: fixes in ram search, add DTCM and ITCM searching, ...
|
||||
bug: fix sound settings vol slider
|
||||
bug: recover from missing window -32000 problem
|
||||
bug: don't turn on mic unless mic input is enabled
|
||||
enh: x64 build type now supported
|
||||
enh: side-by-side and single screen view modes, many fixes to window resizing
|
||||
enh: choose any gap size by dragging bottom window edge (must be enabled)
|
||||
enh: choose a gap color
|
||||
enh: import/export no$GBA savefiles directly
|
||||
enh: multicore optimization for filters, rotation, OSD
|
||||
enh: soundview can now mute channels
|
||||
enh: new ioregview
|
||||
enh: common commandline system, many arguments shared with linux
|
||||
enh: improve map view tool to support more modes
|
||||
enh: add "FORCE AS CURRENT" recovery tool for mis-sized savefiles
|
||||
enh: add some kind of very small savestate rewinding buffer
|
||||
enh: autoframeskip works better
|
||||
enh: add Italian translation
|
||||
enh: added 2x resizing filters (hq2x, hq2xs, lq2x, lq2xs, 2xsai, supereagle)
|
||||
(scanlines, nearest2x, bilinear)
|
||||
|
||||
Linux:
|
||||
enh: alsa microphone support
|
||||
enh: hud and osd notification for gtk and cli frontends
|
||||
enh: add support for the SSE optimizations
|
||||
|
||||
0.9.2 -> 0.9.4 (r1844->r2352->r2437)
|
||||
|
||||
0.9.3 was skipped due to emu news sites sneaking it out of our staging area and
|
||||
releasing it prematurely while it still had bugs. I was going to curse them
|
||||
individually, but then I decided that they would just like the publicity.
|
||||
|
||||
Highlights:
|
||||
* New save autodetection and save file format
|
||||
* Full rerecording support
|
||||
|
||||
General/Core:
|
||||
bug: fix many 64 bit and endian issues
|
||||
bug: fix mic input, which was nearly useless before
|
||||
bug: fix failures of large dmas
|
||||
bug: fix in ipc sync which broke devkitpro touch
|
||||
bug: screenshots now exclude hud and rotation
|
||||
bug: rewritten vram mapping (fixes corrupted or missing BG)
|
||||
enh: add universal commandline system (same commandline options on every port)
|
||||
enh: cheats: added Action Replay code parser
|
||||
enh: more reliable and useful frameskipping
|
||||
enh: SPU: speedup: add adpcm caching
|
||||
enh: SPU: speedup: interpolation is now optional
|
||||
enh: print svn build number so we can identify people's svn builds from screenshots
|
||||
|
||||
Graphics:
|
||||
bug: add polygon y-sorting (fixes 3d guis)
|
||||
bug: fix texcoordgen mode 3; fixes some ortho sprites and some entirely broken games
|
||||
bug: display capture fixes
|
||||
bug: fix a number of OBJ modes
|
||||
bug: fixes to affine BG modes
|
||||
bug: better emulate some translucent OBJ
|
||||
bug: more correct handling of color effect windows and backdrop colors
|
||||
bug: fix matrix stack overrun which crashed emulator
|
||||
bug: swrast: add clear depth image emulation and other fixes to depth buffering
|
||||
bug: swrast: fix some toon and highlight cases
|
||||
bug: fix bug in matrix stack, fixes some broken models
|
||||
enh: add alternate flush mode HACK 3d config toggle, fixes some entirely broken 3d games
|
||||
|
||||
Windows:
|
||||
bug: more robust cheats engine and dialog
|
||||
enh: more solid avi and wav recording
|
||||
enh: improved tools: memory viewer
|
||||
enh: added tools: spu viewer, ram watch, ram search
|
||||
enh: change build configuration system
|
||||
enh: speedup: add gpu core disabling to hide useless screens
|
||||
enh: add background pause feature (for when emulator loses focus)
|
||||
enh: add missing autohold for L and R
|
||||
enh: add chinese translation
|
||||
|
||||
Gtk frontend:
|
||||
enh: switch all of menu/toolbar system to GtkAction + GtkUIManager
|
||||
enh: remove the gtglext 3d code
|
||||
enh: improve/speedup screen resize and final presentation logic in gtk frontend
|
||||
enh: minimal rerecording hookups
|
||||
|
||||
Cli frontend:
|
||||
enh: hooked the frameskip (szigor)
|
||||
enh: misc usability improvements: auto pause switch for pausing when focus is lost and exit on escape pressing (szigor)
|
||||
enh: hook the fake noise mic; use m to toggle
|
||||
|
||||
0.9.1 -> 0.9.2
|
||||
General/Core:
|
||||
bug: fix error in SBCS/RSCS flags; fixes many odd behaviors and crashes [zeromus]
|
||||
bug: add support for sleep mode and power registers [luigi__]
|
||||
bug: important fixes to RTC so correct time is actually told [luigi__]
|
||||
bug: fix card reads below 0x8000; fixes some game freezes [normatt]
|
||||
bug: fix 4 mbit save type; fix non-autodetect savefile dumping [zeromus, matusz]
|
||||
enh: add sram to GBA game addon emulation for importing savefiles [zeromus]
|
||||
enh: many improvements and feature hookups in linux ports [matusz, luigi__]
|
||||
|
||||
Graphics:
|
||||
bug: fix specular texture mapping mode [luigi__]
|
||||
bug: repairs to some capture modes and vram mapping [zeromus, CrazyMax]
|
||||
bug: viewports finally correctly handled [zeromus]
|
||||
enh: add software rasterizer. quirky, but on par with opengl [zeromus]
|
||||
|
||||
Windows:
|
||||
bug: mitigate bad frameskipper; default to old frameskipping mode [zeromus]
|
||||
bug: fixes with recent roms and zipfile loading [zeromus]
|
||||
bug: fix window position memory [zeromus]
|
||||
enh: bios and firmware may now be used and booted [luigi__]
|
||||
enh: many display, OSD, and input enhancements [luigi__]
|
||||
enh: brand new hotkey and controls binding system [zeromus]
|
||||
enh: configurable screen separation [luigi__]
|
||||
enh: fast forward key [pa__]
|
||||
enh: improvements to mic [luigi__]
|
||||
enh: faster updates in debug tools, up to once per frame [pa__]
|
||||
|
||||
Mac OS X Port:
|
||||
enh: added Italian translation thanks to Paolo Bernini [jeff]
|
||||
enh: resurrection of GDB stub [sigmaris]
|
||||
|
||||
0.9 -> 0.9.1
|
||||
General/Core:
|
||||
enh: GBA slot emulation [CrazyMax]
|
||||
- Rumble support (windows only)
|
||||
- GBA game
|
||||
enh: Mic support (windows only?) [luigi__]
|
||||
enh: Preliminary cheats system [CrazyMax]
|
||||
enh: Savestates invalidated, as more variables have been added.
|
||||
bug: Added PSG white noise [luigi__]
|
||||
bug: fix arm/thumb ROR [zeromus]
|
||||
bug: [ 2550645 ] Super Princess Peach: crash when starting a puzzle [zeromus]
|
||||
bug: win32: fix spu wav file writer (regression from 0.8) [zeromus,luigi__]
|
||||
bug: Much work on FIFOs, still not finished [CrazyMax]
|
||||
bug: Many fixes to dma [zeromus, CrazyMax]
|
||||
bug: bios WaitForVblank and WaitForInterrupt fixed [luigi__]
|
||||
|
||||
Graphics:
|
||||
bug: Added sprite blending [luigi__]
|
||||
bug: more correct mosaic effects, still imperfect [zeromus]
|
||||
bug: Many fixes to tile rendering; all graphics tests now pass [luigi__]
|
||||
bug: fix crashes in some affine BG [zeromus]
|
||||
bug: Implement some pos test function [luigi__]
|
||||
bug: fix texture mapping across texture and palette banks and to unmapped banks [zeromus]
|
||||
bug: fix texture handling for texels with MSB set (fixes some texture corruption) [zeromus]
|
||||
bug: fix texture coordinate generation, including environment mapping [zeromus]
|
||||
bug: texture cache invalidates when palettes change, prevents some texture corruption [zeromus]
|
||||
bug: fix display capturing from 2d+3d source when display mode is display-vram [zeromus]
|
||||
bug: [ 2488334 ].1 fixes to layer compositing [luigi__]
|
||||
bug: [ 2488334 ].3 fix bug in support for hdma affine bg parameters [zeromus]
|
||||
bug: Improvements to 3d h-scrolling [luigi__]
|
||||
bug: Fix some errors in rendering 512 tall BG [zeromus,CrazyMax] (still not fully resolved)
|
||||
bug: Add optional fragment shading pipeline (more precision) [luigi__]
|
||||
bug: Fix bug where some sprites got cut of on x=255 [zeromus]
|
||||
bug: Implement GXSTAT register [CrazyMax]
|
||||
|
||||
Windows:
|
||||
bug: resizing and rotating work in vista [luigi__]
|
||||
enh: 0 frameskip now lets emulator run at excess speed [zeromus]
|
||||
|
||||
Mac OS X Port:
|
||||
bug: left key setting no longer gets confused with the right key [jeff]
|
||||
enh: more keys can be mapped
|
||||
|
||||
0.8 -> 0.9
|
||||
There have been so many changes that this list can hardly be considered complete.
|
||||
For this release, we have formatted the list into a high level overview of big changes and bad bugs relative to the previous release. Hopefully what you're interested in.
|
||||
This list does not include items which are solely performance boosts, for let us just say that virtually every system has been speeded up.
|
||||
|
||||
* The savestate system is totally changed and incompatible with old savestates.
|
||||
* The 3d system should be considered rewritten.
|
||||
|
||||
General/Core:
|
||||
enh: Convert to c++
|
||||
enh: Add functions for a lid open/close. Holding key (default "Backspace" in Windows port) while game is freeze/non freeze. [CrazyMax]
|
||||
enh: Add secure area decryption from ndstool [zeromus]
|
||||
enh: Change savestate code to support loosely bound chunks and more easily other parts of the emu (GE, GPU).
|
||||
The savestate format is changed, but from now on it is in principle more resilient
|
||||
(though it will continue to break as we tinker with the internals) [zeromus]
|
||||
enh: Added SSE2 optimizations for matrices. Since we now make an SSE2 build, more optimizations can be made. [CrazyMax]
|
||||
enh: Add a preliminary GUI hud system [CrazyMax,zeromus]
|
||||
|
||||
CPU/MMU:
|
||||
bug: Many fixes in IPC and GE FIFOs. Fixes freezes in NSMB, dsracing, and others. [CrazyMax,luigi__,shash]
|
||||
bug: Fix ARM instructions SBC and RSC (likewise SBC in thumb) [normatt]
|
||||
bug: Fixed Thumb LDMIA (fixes ingame Dead'n'Furious) [shash]
|
||||
bug: Fix repeating DMA (fixes NSMB parallax BG) [zeromus]
|
||||
bug: Proper handling for unaligned CPU accesses [luigi__]
|
||||
bug: Proper handling for undefined instruction exceptions [Salva Peiró]
|
||||
bug: correctly return vram control register values (fixes homebrew 3d games) [zeromus]
|
||||
enh: Remove 16MB of WRAM at 0x01****** from arm9. Mapped to unused instead. Nobody knows what this was. [zeromus]
|
||||
enh: Changed instruction execution to 16 at a time blocks (tested and stable) [shash]
|
||||
|
||||
Hardware:
|
||||
bug: Newer and better sqrt and div emulation; makes SM64DS playable [luigi__,shash,zeromus]
|
||||
bug: Add preliminary RTC implementations [CrazyMax]
|
||||
enh: Add cosine interpolation in the SPU (conditionally compiled) [zeromus,luigi__]
|
||||
enh: Experimental: always one silent non-mixing SPU core at 44.1khz synched with emu, for more precision.
|
||||
The audible core runs with the host, causing music to slow down but not tear or pitch bend. [zeromus]
|
||||
|
||||
Graphics:
|
||||
- Overhaul 3d:
|
||||
. Move entire GE to core emu.
|
||||
. Move OpenGL renderer to emu core for optional use by platforms, removing ogl_collector. Now every platform shares the same 3d code.
|
||||
. Reorganize 3d code to defer rendering to after 3d vblank. Eliminates tearing, and texturing artifacts. [zeromus]
|
||||
. Add optional fragment shading pipeline (more precision) [luigi__]
|
||||
. Move lighting model to software instead of using opengl's fixed function model [zeromus]
|
||||
. Render shadow volumes; toon shading and highlight table [zeromus, luigi__]
|
||||
. Added texture caching! big speed up. [CrazyMax]
|
||||
|
||||
bug: Many assorted tweaks and improvements to 3d and 2d precision [zeromus,CrazyMax,luigi__]
|
||||
bug: Fixes to GE: command unpacking, projection and pos-vector mode matrix handling, mult and load commands [zeromus]
|
||||
bug: Fix a bug in texture transformation mode 1 [zeromus]
|
||||
bug: Fixed GPU rendering bugs in sprites and BG [CrazyMax]
|
||||
bug: Fixes to texture conversion [CrazyMax,zeromus]
|
||||
bug: Fixes in capture display (no blinking in many games with dual 3D) [CrazyMax]
|
||||
bug: Fixes in master brightness (this fixes some games with black screens) [CrazyMax]
|
||||
bug: Fixes in screen, backdrop, and sprite blending [luigi__]
|
||||
bug: Changed clear depths and how depth initial values are calculated (fixes SM64DS skybox, Castlevania) [shash,lugi__]
|
||||
bug: Add 3d layer h-scrolling [zeromus]
|
||||
bug: Added transparency and fixed material alpha support and alpha testing on the 3D core [shash]
|
||||
bug: Rewrite VRAM mapping control and rendering (more accurate) [CrazyMax,luigi__]
|
||||
|
||||
bug: convert colors to opengl better to prevent alpha=31 polys from being ever so slightly transparent [zeromus]
|
||||
enh: Add MMU->GPU signal for when vram mappings change to function as a texture cache invalidate signal [zeromus]
|
||||
enh: Make matrix 4x4 multiply routines use W-coordinate; carry w coord through pipeline [zeromus]
|
||||
|
||||
Mac OS X port:
|
||||
bug: Fixed: Filenames and paths with unicode characters now work. [Jeff]
|
||||
bug: Fixed: Load state from file button works again. [Jeff]
|
||||
enh: Save State panel now pauses emulation while the file selection box is open. [Jeff]
|
||||
bug: Fixed: Frozen video output (and/or messed 3d emulation) after loading a state. [Jeff]
|
||||
bug: Added option to load the most recent file upon launching the program. [Jeff]
|
||||
enh: Added French translation (thanks to Pierre Rudloff). [Jeff]
|
||||
enh: Added basic key mapping configuration to application preferences (thanks to Julio Gorg). [Jeff]
|
||||
enh: Added keyboard shortcuts for Execute, Pause and Reset command (thanks to Julio Gorg). [Jeff]
|
||||
enh: Default key mappings are no longer case sensitive. [Jeff]
|
||||
enh: Added ability to limit speed. [Jeff]
|
||||
enh: Fixed: Video output should work on software-only 3D renderers. [Jeff]
|
||||
|
||||
Windows port:
|
||||
bug: Fix a race condition in NDS_3D_Reset and NDS_glInit [zeromus]
|
||||
bug: Fix the buggy auto frameskip logic which made the emu slow to a crawl. Now it runs fast! [zeromus]
|
||||
bug: Fix resizing, rotate & aspect ration of main window. [CrazyMax,_zeromus]
|
||||
bug: Remove multithreading from user interface after finding several synchronization issues [zeromus]
|
||||
enh: recent roms menu [luigi_]
|
||||
enh: Changed graphics render core to DirectDraw (work faster) [CrazyMax]
|
||||
enh: Add an arm9 cpu load average calculator similar to no$. but I dont think it works right. [zeromus]
|
||||
enh: Rewrite all debug tools (autoupdate works now) [CrazyMax]
|
||||
enh: Rewrite input core & replace config input dialog [CrazyMax]
|
||||
enh: Add AVI output [zeromus]
|
||||
enh: Add pause toggle and frame advance hotkeys [adelikat]
|
||||
enh: Add frame counter display and hud messages framework [adelikat]
|
||||
enh: Main window remembers position, size, and a few other emu preferences [adelikat]
|
||||
enh: Removed directx sdk dependency for easier building. [zeromus]
|
||||
enh: Savestate doesnt unpause emu if it is already paused [adelikat]
|
||||
|
||||
0.7.3 -> 0.8
|
||||
Cocoa:
|
||||
- Save State As function now works. [Jeff B]
|
||||
- Recent Items menu now works. [Jeff B]
|
||||
- Opening NDS files from Finder now works. [Jeff B]
|
||||
- Added screenshot feature. [Jeff B]
|
||||
- Added preferences. [Jeff B]
|
||||
- Many more strings are translatable now. [Jeff B]
|
||||
- Default screen color is black (better represents being "off" and easier on eyes at night). [Jeff B]
|
||||
- Added sound. [Jeff B]
|
||||
- Now is a universal binary. [Jeff B]
|
||||
- Leopard resolution icon added. [Jeff B]
|
||||
- Added a Japanese translation. [Jeff B]
|
||||
- Added an optional status bar (resize handle no longer overlaps screen). [Jeff B]
|
||||
- New ROM Info and About DeSmuME windows have been added. [Jeff B]
|
||||
- Fixed several bugs in window resizing. [Jeff B]
|
||||
- Added FAT image support for homebrew games (thanks to TypeError). [Jeff B]
|
||||
- Key config can be changed on the command line. Save/load hotkeys changed (so expose doesn't override). [Jeff B]
|
||||
- Key bindings may work better on non-US keyboards now (needs testing). [Jeff B]
|
||||
general:
|
||||
- Encapsulate GDB debug stub to avoid certain problems [shash]
|
||||
- Fixed CPU LD*/ST* bugs [shash]
|
||||
- Fixed New SMB mini-games freeze [shash]
|
||||
- Fixed possible segfault in ROMReader on ia64 and amd64. [evilynux]
|
||||
- Fixed a crash bug with 2D background corrupting memory [shash]
|
||||
- Flag check optimization [carlo_bramini]
|
||||
- Applied some endian fixes in GPU (thanks to Phazz) [Jeff B]
|
||||
gtk-glade:
|
||||
- Added DeSmuME version in about dialog. [evilynux]
|
||||
- Updated website url in about dialog. [evilynux]
|
||||
- Added Brazilian Portuguese translation by Dreampeppers99. [evilynux]
|
||||
- Better desktop menu entry following FreeDesktop specifications. [evilynux]
|
||||
gtk:
|
||||
- Updated website url in about dialog. [evilynux]
|
||||
- Better desktop menu entry following FreeDesktop specifications. [evilynux]
|
||||
windows port:
|
||||
- Added an "about" box [shash]
|
||||
- DirectInput control interface with joystick support [CrazyMax]
|
||||
- Matrix and Light viewer [Acid Burn]
|
||||
|
||||
0.7.2 -> 0.7.3
|
||||
gtk-glade:
|
||||
- Full localization using intltool/gettext. [evilynux]
|
||||
general:
|
||||
- Added a README.TRANSLATION documenting the localization process. [evilynux]
|
||||
MacOS X:
|
||||
- Initial version of the Mac interface added. [Jeff B]
|
||||
|
||||
0.7.1 -> 0.7.2
|
||||
spu:
|
||||
- big endian fixes. [cyberwarriorx]
|
||||
gpu:
|
||||
- big endian fixes. [marcus_c]
|
||||
gtk-glade:
|
||||
- opengl improvements. [masscat]
|
||||
general:
|
||||
- Added support for setting NDS firmware language value. [masscat]
|
||||
- Function added for setting firmware language. [masscat]
|
||||
- Mac/msys compilation fixes. [cyberwarriorx]
|
||||
- Fix compilation when pkg-config macros are not available [evilynux]
|
||||
|
||||
0.7.0 -> 0.7.1
|
||||
general:
|
||||
- Added GDB debugger stub [masscat]
|
||||
- Added new/different GBAMP CFlash image reader/writer [masscat]
|
||||
gpu:
|
||||
- Major speedup to the 2D core [shash]
|
||||
gtk-glade:
|
||||
- Added command line options. [masscat]
|
||||
- Added FPS limiter [masscat]
|
||||
cli:
|
||||
- Added command line options. [masscat]
|
||||
- Added FPS limiter [masscat]
|
||||
- Added option to use OpenGl to render window (allows resizing). [masscat]
|
||||
windows port:
|
||||
- Added command line options. [masscat]
|
||||
- Added multiple language support [cyberwarriorx]
|
||||
- Added Danish language translation [thomas-2007]
|
||||
|
||||
0.6.0 -> 0.7.0
|
||||
general:
|
||||
- Added support for *.duc files [cyberwarriorx]
|
||||
gpu:
|
||||
- Added support for sprite rotation/scaling [shash]
|
||||
- Added support for the 3D core (openGL and null plugins) [shash]
|
||||
windows port:
|
||||
- A bunch of fixes [Dmitry Krutskih]
|
||||
- Fixed a bug in sound that was causing it to still not work for some
|
||||
people [cyberwarriorx]
|
||||
gtk:
|
||||
- Added 3D emulation
|
||||
- Added command line options.
|
||||
- Added option to use OpenGL to render window (allows resizing).
|
||||
gtk-glade:
|
||||
- Added 3D emulation
|
||||
|
||||
0.5.0 -> 0.6.0
|
||||
general:
|
||||
- Added zipped (based on zziplib) and gzipped (based on zlib) rom support.
|
||||
arm:
|
||||
- Added relocation interrupt vector.
|
||||
- Added region access right checks.
|
||||
- Enabled LDC/STC instructions.
|
||||
- Fixed powersave (cp15) IRQ wait.
|
||||
- Fixed MOV instructions
|
||||
gpu:
|
||||
- Added special color effects.
|
||||
- Added windowing feature.
|
||||
- Fixed transparent direct color backgrounds.
|
||||
- Fixed disabled sprites showing.
|
||||
- Fixed 8/32 bit access to gpu registers.
|
||||
- Fixed missing backgrounds
|
||||
- Support for master brightness
|
||||
wifi:
|
||||
- Added RF chip interface.
|
||||
- Added BB chip interface.
|
||||
windows port:
|
||||
- Fixed address calculation in disassembler.
|
||||
- Added Force Maintain Ratio option for window stretching
|
||||
linux port (cli, gtk and gtk-glade):
|
||||
all:
|
||||
- Added joystick support.
|
||||
- Fixed X and Y buttons.
|
||||
gtk-glade:
|
||||
- Added joystick configuration.
|
||||
- Improved I/O registers viewer tool.
|
||||
- Added save and load states support.
|
||||
|
||||
0.3.3 -> 0.5.0
|
||||
arm:
|
||||
- Fixed MSR with immediate value opcode.
|
||||
- Fixed LSR_0 thumb opcode (C flag is correctly set now).
|
||||
- Fixed LDR*/STR* opcodes.
|
||||
- Fixed unaligned memory access on THUMB Core.
|
||||
- Added relocating SWI routines.
|
||||
bios:
|
||||
- Added decompression functions.
|
||||
- Added GetPitchTable function.
|
||||
- Added GetVolumeTable function.
|
||||
- Added GetCRC16 function.
|
||||
- Added experimental SoundBias function.
|
||||
- Added GetSineTable function.
|
||||
cart:
|
||||
- Added CompactFlash/FAT emulation.
|
||||
- Added Get ROM chip ID Cartridge command.
|
||||
gpu:
|
||||
- Added framebuffer emulation.
|
||||
- Fixed a bug in GPU (xfin could be greater than LG causing a segfault).
|
||||
- Added support for Display Mode 0(Display Off).
|
||||
- Added the basic framework for Display Mode 3(Display from Main RAM).
|
||||
spu:
|
||||
- Added sound emulation.
|
||||
- Added sound core system.
|
||||
- Added WAV write core.
|
||||
- Added dummy core.
|
||||
- Added Direct Sound core.
|
||||
linux port:
|
||||
- Added GTK+ GUI.
|
||||
- Added command line interface.
|
||||
- Added stylus and arm9 keypad support in CLI version.
|
||||
- Added FPS display.
|
||||
- Added basic frameskip.
|
||||
windows port:
|
||||
- Fixed a bug when displaying a ROM's information.
|
||||
- Added key configuration.
|
||||
- Removed the debug key.
|
||||
- Added new experimental auto frameskip/frame limit code.
|
||||
- Added sound settings dialog.
|
||||
- Added a few menu options for accessing the website, forums, and for
|
||||
submitting bugs.
|
||||
general:
|
||||
- Rewrote code in C.
|
||||
- Fixed warnings.
|
||||
- Used defines and typedef's to make things more portable and easier to
|
||||
read.
|
||||
- Added autotools stuff.
|
||||
- Changes to logging system.
|
||||
- Added screenshot function.
|
||||
- Translated most french to english.
|
||||
- Added savestate support.
|
||||
- Added firmware reading support(needs work).
|
||||
- Added Backup Memory support with autodetection.
|
||||
- Fixed some endianess issues.
|
||||
- Fixed things so Visual C++ can compile code.
|
||||
- Added bsd support.
|
||||
- Reworked ROM loading so you can load a different rom without any problems.
|
||||
- Finished NDS_Reset. Now the emulation can be reset even while running.
|
|
@ -0,0 +1,97 @@
|
|||
DeSmuME
|
||||
_________________________________________
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2006-2022 DeSmuME team
|
||||
Last Updated: May 23, 2022
|
||||
|
||||
Contents:
|
||||
1) About ................................................................... 14
|
||||
2) Credits ................................................................. 59
|
||||
3) Contact Information ..................................................... 72
|
||||
4) License ................................................................. 82
|
||||
|
||||
|
||||
1) About ______________________________________________________________________
|
||||
|
||||
DeSmuME is software that allows you to emulate a Nintendo DS system. Think of
|
||||
it as a Swiss-Army knife for Nintendo DS emulation, giving you access to many
|
||||
powerful tools for testing DS features, from viewing ROM properties to managing
|
||||
Action Replay cheats. And best of all, this software is completely free and
|
||||
open-source.
|
||||
|
||||
For information on how to install or operate DeSmuME for your operating system,
|
||||
please see the README file that should be present with your installation.
|
||||
|
||||
Port-specific README files:
|
||||
* README.LIN for the Linux ports
|
||||
* README.WIN for the Windows port
|
||||
* README.MAC for the Macintosh port
|
||||
|
||||
Note that each DeSmuME port may have a different feature set from another port.
|
||||
You may see more feature parity between ports over time as we continue
|
||||
developing DeSmuME.
|
||||
|
||||
You can find our documentation on our online Wiki page. The major pages of
|
||||
interest are:
|
||||
|
||||
* Official Documentation: https://wiki.desmume.org/index.php?title=Main_Page
|
||||
|
||||
This is the main Wiki page that contains all of our official documentation.
|
||||
|
||||
* Manuals: https://wiki.desmume.org/index.php?title=Manual
|
||||
|
||||
The manuals contain detailed information about how to operate DeSmuME for each
|
||||
port.
|
||||
|
||||
* FAQ: https://wiki.desmume.org/index.php?title=Faq
|
||||
|
||||
The Frequently Asked Questions (FAQ) page has a lot of useful general
|
||||
information about DeSmuME. Do note that some of the information may be platform
|
||||
specific, and may not directly apply to your version of DeSmuME.
|
||||
|
||||
* Build Instructions:
|
||||
https://wiki.desmume.org/index.php?title=Installing_DeSmuME_from_source
|
||||
|
||||
This page contains detailed port-specific instructions about how to make your
|
||||
own build of DeSmuME directly from the source code.
|
||||
|
||||
|
||||
2) Credits ____________________________________________________________________
|
||||
|
||||
See the AUTHORS file for list of DeSmuME team members.
|
||||
|
||||
Special thanks go to:
|
||||
|
||||
* yopyop (original author of DeSmuME),
|
||||
for releasing the source code of this great emulator.
|
||||
|
||||
* Martin Korth (author of GBATEK),
|
||||
for his well-written Gameboy Advance and Nintendo DS documentation.
|
||||
|
||||
|
||||
3) Contact Information ________________________________________________________
|
||||
|
||||
Official Website: https://desmume.org
|
||||
Public Forum: https://forums.desmume.org
|
||||
Developer Chat: irc://irc.libera.chat:6697/desmume
|
||||
Source & Bug Reports: https://github.com/TASEmulators/desmume
|
||||
|
||||
Please don't ask for ROMs, BIOS files, or any other copyrighted stuff.
|
||||
|
||||
|
||||
4) License ____________________________________________________________________
|
||||
|
||||
This file is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This file is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this software. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
* See the GNU General Public License details in COPYING.
|
|
@ -0,0 +1,441 @@
|
|||
DeSmuME DLL/SO
|
||||
|
||||
DeSmuME is written in C++ using the SDL libraries.
|
||||
|
||||
* http://www.libsdl.org/
|
||||
|
||||
|
||||
Reference Usage
|
||||
===============
|
||||
A Python library using the DLL/SO interface can be found at
|
||||
`https://github.com/SkyTemple/py-desmume/blob/master/desmume/emulator.py`.
|
||||
|
||||
|
||||
Build Linux & Mac
|
||||
=================
|
||||
|
||||
DeSmuME uses the Meson build system to the shared object under Linux and MacOS:
|
||||
|
||||
* https://mesonbuild.com/
|
||||
|
||||
To build, first cd to src/frontend/interface and then run `meson build`
|
||||
|
||||
Then build the library by running `ninja -C build`
|
||||
|
||||
It will generate a shared object under `build/libdesmume.so`.
|
||||
|
||||
Build Windows
|
||||
=============
|
||||
To build open and build the Visual Studio solution at
|
||||
`src/frontend/interface/windows/DeSmuME_Interface.sln`.
|
||||
|
||||
|
||||
Interface
|
||||
=========
|
||||
The interface has the following API functions exposed in the DLL/SO.
|
||||
|
||||
|
||||
Emulator key indices
|
||||
--------------------
|
||||
Internal ID numbers for emulator keys (used for some functions):
|
||||
|
||||
#define KEY_NONE 0
|
||||
#define KEY_A 1
|
||||
#define KEY_B 2
|
||||
#define KEY_SELECT 3
|
||||
#define KEY_START 4
|
||||
#define KEY_RIGHT 5
|
||||
#define KEY_LEFT 6
|
||||
#define KEY_UP 7
|
||||
#define KEY_DOWN 8
|
||||
#define KEY_R 9
|
||||
#define KEY_L 10
|
||||
#define KEY_X 11
|
||||
#define KEY_Y 12
|
||||
#define KEY_DEBUG 13
|
||||
#define KEY_BOOST 14
|
||||
#define KEY_LID 15
|
||||
|
||||
|
||||
int desmume_init(void);
|
||||
-----------------------
|
||||
Initializes the emulator. Needs to be called before any other API functions.
|
||||
|
||||
|
||||
void desmume_free(void);
|
||||
------------------------
|
||||
Destroys the emulator, needs to be called to free memory. After this no API
|
||||
functions must be called.
|
||||
|
||||
|
||||
void desmume_set_language(unsigned char language);
|
||||
--------------------------------------------------
|
||||
Sets the firmware language. Valid values:
|
||||
0 = Japanese, 1 = English, 2 = French, 3 = German, 4 = Italian, 5 = Spanish
|
||||
|
||||
|
||||
int desmume_open(const char *filename);
|
||||
---------------------------------------
|
||||
Loads a ROM into the emulator. Returns 0 on success and another number on error.
|
||||
|
||||
|
||||
void desmume_set_savetype(int type);
|
||||
------------------------------------
|
||||
Sets the type of SRAM save. 0 for auto.
|
||||
|
||||
|
||||
void desmume_pause(void);
|
||||
-------------------------
|
||||
Pauses the emulator.
|
||||
|
||||
|
||||
void desmume_resume(void);
|
||||
--------------------------
|
||||
Resumes the emulator.
|
||||
|
||||
|
||||
void desmume_reset(void);
|
||||
-------------------------
|
||||
Resets the emulator and resumes.
|
||||
|
||||
|
||||
BOOL desmume_running(void);
|
||||
---------------------------
|
||||
Returns 0 if the emulator is not running and 1 if it is.
|
||||
|
||||
|
||||
void desmume_skip_next_frame(void);
|
||||
-----------------------------------
|
||||
Instructs the emulator to not draw the next frame.
|
||||
|
||||
|
||||
void desmume_cycle(BOOL with_joystick);
|
||||
---------------------------------------
|
||||
Runs one loop iteration (tick) of the emulation.
|
||||
The parameter must be 1 if `desmume_input_joy_init` was called before and
|
||||
joystick input should be processed
|
||||
and 0 otherwise.
|
||||
|
||||
|
||||
int desmume_sdl_get_ticks();
|
||||
----------------------------
|
||||
Get the current tick number as reported by SDL.
|
||||
|
||||
|
||||
void desmume_draw_opengl(GLuint *texture);
|
||||
------------------------------------------
|
||||
Only available if INCLUDE_OPENGL_2D was defined.
|
||||
|
||||
Draws the current tick onto the provided OpenGL texture.
|
||||
|
||||
|
||||
BOOL desmume_has_opengl();
|
||||
--------------------------
|
||||
Returns whether or not OpenGL support is available.
|
||||
|
||||
|
||||
int desmume_draw_window_init(BOOL auto_pause, BOOL use_opengl_if_possible);
|
||||
---------------------------------------------------------------------------
|
||||
Opens an SDL-powered window for drawing the emulator on and processing input.
|
||||
If `auto_pause` is >0, the emulator is paused when the window is not in focus.
|
||||
If `use_opengl_if_possible` is >0, OpenGL-based drawing is used
|
||||
if OpenGL is available.
|
||||
|
||||
|
||||
void desmume_draw_window_input();
|
||||
---------------------------------
|
||||
Process user input on the SDL window for this tick.
|
||||
Requires `desmume_draw_window_init` to be called first.
|
||||
|
||||
|
||||
void desmume_draw_window_frame();
|
||||
---------------------------------
|
||||
Draw the SDL window for this tick. Requires `desmume_draw_window_init` to be called first.
|
||||
|
||||
|
||||
BOOL desmume_draw_window_has_quit();
|
||||
------------------------------------
|
||||
Returns 1 if the SDL window was closed by the user and 0 if not.
|
||||
Requires `desmume_draw_window_init` to be called first.
|
||||
|
||||
|
||||
void desmume_draw_window_free();
|
||||
--------------------------------
|
||||
Destroys the SDL window and frees memory. Requires `desmume_draw_window_init` to be called first.
|
||||
No other SDL window functions must be called after this.
|
||||
|
||||
|
||||
unsigned short *desmume_draw_raw();
|
||||
-----------------------------------
|
||||
Returns the content of the raw framebuffer of the emulator.
|
||||
|
||||
|
||||
void desmume_draw_raw_as_rgbx(unsigned char *buffer);
|
||||
-----------------------------------------------------
|
||||
Fills the provided buffer as an RGBx formatted version of the emulator's framebuffer.
|
||||
|
||||
|
||||
void desmume_savestate_clear();
|
||||
-------------------------------
|
||||
Deletes all savestates stored on slots.
|
||||
|
||||
|
||||
BOOL desmume_savestate_load(const char *file_name);
|
||||
---------------------------------------------------
|
||||
Loads a savestate from a file. Returns 1 on success, 0 on failure.
|
||||
|
||||
|
||||
BOOL desmume_savestate_save(const char *file_name);
|
||||
---------------------------------------------------
|
||||
Saves a savestate to a file. Returns 1 on success, 0 on failure.
|
||||
|
||||
|
||||
void desmume_savestate_scan();
|
||||
------------------------------
|
||||
Scans the savestate slots for data. Required for `desmume_savestate_slot_exists` and
|
||||
`desmume_savestate_save_slot` to return the correct data.
|
||||
|
||||
|
||||
void desmume_savestate_slot_load(int index);
|
||||
--------------------------------------------
|
||||
Loads the savestate from slot `index`.
|
||||
|
||||
|
||||
void desmume_savestate_slot_save(int index);
|
||||
--------------------------------------------
|
||||
Saves the current state to the savestate in slot `index`.
|
||||
|
||||
|
||||
BOOL desmume_savestate_slot_exists(int index);
|
||||
----------------------------------------------
|
||||
Returns whether or not the savetstate at slot `index` exists.
|
||||
|
||||
|
||||
char* desmume_savestate_slot_date(int index);
|
||||
---------------------------------------------
|
||||
Returns the date (as string) that the savestate at slot `index` was saved.
|
||||
|
||||
|
||||
BOOL desmume_gpu_get_layer_main_enable_state(int layer_index);
|
||||
--------------------------------------------------------------
|
||||
Returns whether or not the layer with the given index for the main GPU is enabled.
|
||||
|
||||
|
||||
BOOL desmume_gpu_get_layer_sub_enable_state(int layer_index);
|
||||
-------------------------------------------------------------
|
||||
Returns whether or not the layer with the given index for the sub GPU is enabled.
|
||||
|
||||
|
||||
void desmume_gpu_set_layer_main_enable_state(int layer_index, BOOL the_state);
|
||||
------------------------------------------------------------------------------
|
||||
Disables or enables the layer with the given index for the main GPU.
|
||||
Disabled layers are not drawn.
|
||||
|
||||
|
||||
void desmume_gpu_set_layer_sub_enable_state(int layer_index, BOOL the_state);
|
||||
-----------------------------------------------------------------------------
|
||||
Disables or enables the layer with the given index for the sub GPU.
|
||||
Disabled layers are not drawn.
|
||||
|
||||
|
||||
int desmume_volume_get();
|
||||
-------------------------
|
||||
Returns the current emulator volume in a range from 0-100.
|
||||
|
||||
|
||||
void desmume_volume_set(int volume);
|
||||
------------------------------------
|
||||
Sets the current emulator volume in a range from 0-100.
|
||||
|
||||
|
||||
unsigned char desmume_memory_read_byte(int address);
|
||||
signed char desmume_memory_read_byte_signed(int address);
|
||||
unsigned short desmume_memory_read_short(int address);
|
||||
signed short desmume_memory_read_short_signed(int address);
|
||||
unsigned long desmume_memory_read_long(int address);
|
||||
signed long desmume_memory_read_long_signed(int address);
|
||||
-----------------------------------------------------------
|
||||
Read the emulated memory at `address` with different sizes and sign settings.
|
||||
|
||||
|
||||
void desmume_memory_write_byte(int address, unsigned char value);
|
||||
void desmume_memory_write_short(int address, unsigned short value);
|
||||
void desmume_memory_write_long(int address, unsigned long value);
|
||||
-------------------------------------------------------------------
|
||||
Write the value `value` as bytes/shorts/longs to `address` in the emulated memory.
|
||||
|
||||
|
||||
int desmume_memory_read_register(char* register_name);
|
||||
void desmume_memory_write_register(char* register_name, long value);
|
||||
--------------------------------------------------------------------
|
||||
Read or write the value of the specified register.
|
||||
|
||||
Valid register names:
|
||||
- arm9.r0 - arm9.r15 : Registers r0 - r15 on the ARM9 processor.
|
||||
- arm9.cpsr
|
||||
- arm9.spsr
|
||||
- arm7.r0 - arm7.r15 : Registers r0 - r15 on the ARM7 processor.
|
||||
- arm7.cpsr
|
||||
- arm7.spsr
|
||||
|
||||
`main` may be used as an alias for `arm9` and `sub` for `arm7`.
|
||||
If the prefix is omitted, `arm9` is used.
|
||||
|
||||
|
||||
typedef BOOL (*memory_cb_fnc)(unsigned int, int);
|
||||
void desmume_memory_register_write(int address, int size, memory_cb_fnc cb);
|
||||
void desmume_memory_register_read(int address, int size, memory_cb_fnc cb);
|
||||
void desmume_memory_register_exec(int address, int size, memory_cb_fnc cb);
|
||||
----------------------------------------------------------------------------
|
||||
Register a callback function to execute when the emulator writes/reads or executes
|
||||
an instruction at `address`. `size` is the size in bytes to monitor for that location
|
||||
(should always be 2 to exec).
|
||||
|
||||
The passed callback function gets to arguments when called. The first argument
|
||||
is the address the callback was triggered for, the second the size.
|
||||
|
||||
Only one callback can be specified per address and type (write/read/exec).
|
||||
Pass 0 instead for `cb` to unregister previously registered callbacks.
|
||||
|
||||
|
||||
void desmume_screenshot(char *screenshot_buffer);
|
||||
-------------------------------------------------
|
||||
Fills the 98304*3 bytes long `screenshot_buffer` with an RGB snapshot of
|
||||
the framebuffer.
|
||||
|
||||
|
||||
BOOL desmume_input_joy_init(void);
|
||||
----------------------------------
|
||||
Initialize SDL joypad handling. Returns 1 on success, 0 otherwise.
|
||||
Must be called before any other joypad operation.
|
||||
|
||||
void desmume_input_joy_uninit(void);
|
||||
------------------------------------
|
||||
Destroys the joypad functionality. After calling this, no other joypad
|
||||
operations must be called.
|
||||
|
||||
|
||||
unsigned short desmume_input_joy_number_connected(void);
|
||||
--------------------------------------------------------
|
||||
Returns the number of connected joypads.
|
||||
|
||||
|
||||
unsigned short desmume_input_joy_get_key(int index);
|
||||
----------------------------------------------------
|
||||
Returns the joypad key assigned to the specified emulator key.
|
||||
|
||||
|
||||
unsigned short desmume_input_joy_get_set_key(int index);
|
||||
--------------------------------------------------------
|
||||
Pause and wait for the user to press a button on a joypad.
|
||||
This button will be assigned to the specified emulator key.
|
||||
|
||||
void desmume_input_joy_set_key(int index, int joystick_key_index);
|
||||
------------------------------------------------------------------
|
||||
Sets the emulator key `index` to the specified joypad key `joystick_key_index`.
|
||||
|
||||
|
||||
void desmume_input_keypad_update(unsigned short keys);
|
||||
------------------------------------------------------
|
||||
Update the currently pressed emulator keys. This is a bitmask where each bit
|
||||
is one of the emulator's keys. See:
|
||||
|
||||
#define ADD_KEY(keypad,key) ( (keypad) |= (key) )
|
||||
#define RM_KEY(keypad,key) ( (keypad) &= ~(key) )
|
||||
#define KEYMASK_(k) (1 << (k))
|
||||
|
||||
|
||||
unsigned short desmume_input_keypad_get(void);
|
||||
----------------------------------------------
|
||||
Get the currently pressed emulator keys. This is a bitmask where each bit is
|
||||
one of the emulator's keys.
|
||||
|
||||
|
||||
void desmume_input_set_touch_pos(unsigned short x, unsigned short y);
|
||||
---------------------------------------------------------------------
|
||||
Register a touch input at the specified location on the bottom screen.
|
||||
Use `desmume_input_release_touch` to release.
|
||||
|
||||
|
||||
void desmume_input_release_touch();
|
||||
-----------------------------------
|
||||
Release the current touch.
|
||||
|
||||
|
||||
BOOL desmume_movie_is_active();
|
||||
BOOL desmume_movie_is_recording();
|
||||
BOOL desmume_movie_is_playing();
|
||||
BOOL desmume_movie_is_finished();
|
||||
----------------------------------
|
||||
Returns whether the movie system is active/recording/playing/finished.
|
||||
|
||||
|
||||
int desmume_movie_get_length();
|
||||
-------------------------------
|
||||
Returns the size of the movie records.
|
||||
|
||||
|
||||
char *desmume_movie_get_name();
|
||||
-------------------------------
|
||||
Returns the name of the movie.
|
||||
|
||||
|
||||
int desmume_movie_get_rerecord_count();
|
||||
---------------------------------------
|
||||
Returns the current rerecount counter value of the movie.
|
||||
|
||||
|
||||
void desmume_movie_set_rerecord_count(int count);
|
||||
-------------------------------------------------
|
||||
Sets the current rerecount counter value of the movie.
|
||||
|
||||
|
||||
BOOL desmume_movie_get_readonly();
|
||||
----------------------------------
|
||||
Returns 1 if the movie can only be read, 0 if it can also be modified.
|
||||
|
||||
|
||||
void desmume_movie_set_readonly(BOOL state);
|
||||
--------------------------------------------
|
||||
Change whether or not the movie is only read-only (can not be modified).
|
||||
|
||||
|
||||
// Returns NULL on success, error message otherwise.
|
||||
const char *desmume_movie_play(const char *file_name);
|
||||
------------------------------------------------------
|
||||
Play the movie from the file `file_name`. Returns NULL on success, otherwise
|
||||
an error message.
|
||||
|
||||
|
||||
enum START_FROM {START_BLANK = 0, START_SRAM, START_SAVESTATE};
|
||||
struct SimpleDate {int year; int month; int day; int hour; int minute; int second; int millisecond;};
|
||||
void desmume_movie_record_simple(const char *save_file_name, const char *author_name);
|
||||
void desmume_movie_record(const char *save_file_name, const char *author_name,
|
||||
START_FROM start_from, const char* sram_file_name);
|
||||
void desmume_movie_record_from_date(const char *save_file_name, const char *author_name,
|
||||
START_FROM start_from, const char* sram_file_name,
|
||||
SimpleDate date);
|
||||
----------------------------------------------------------------------------------------
|
||||
Record a movie.
|
||||
|
||||
- `save_file_name`: The name of the file to save the movie to.
|
||||
- `author_name`: The name of the author of the movie.
|
||||
- `start_from`: Where to start from:
|
||||
- START_BLANK (0): Reset the emulator, start without SRAM (no savefile).
|
||||
- START_SRAM (1): Reset the emulator, start using the SRAM loaded from `sram_file_name`.
|
||||
- START_SAVESTATE (2): Not supported.
|
||||
- `sram_file_name`: Name of the SRAM to load, if `start_from` == 1. NULL otherwise.
|
||||
- `date`: Date to set the emulated device's clock to.
|
||||
|
||||
|
||||
void desmume_movie_replay();
|
||||
----------------------------
|
||||
Restart playback of the current movie.
|
||||
|
||||
|
||||
void desmume_movie_stop();
|
||||
----------------------------
|
||||
Stop playback/recording of the current movie.
|
||||
|
||||
|
||||
Visit us on the web at http://www.desmume.org
|
|
@ -0,0 +1,72 @@
|
|||
DeSmuME
|
||||
|
||||
DeSmuME is written in C++ using the GTK+ and SDL2 libraries.
|
||||
|
||||
* https://gtk.org/
|
||||
* https://libsdl.org/
|
||||
|
||||
It uses the Meson build system to build the GTK+3 and SDL2 port:
|
||||
|
||||
* https://mesonbuild.com/
|
||||
|
||||
... and the autotools build system for the GTK+2 and SDL2 port.
|
||||
|
||||
to build GTK+2 or SDL2 frontend with autotools, cd to src/frontend/posix, then
|
||||
|
||||
autoreconf -i (or alternatively: ./autogen.sh)
|
||||
./configure
|
||||
make -jN (where N is the number of CPU cores to use).
|
||||
|
||||
|
||||
DeSmuME provides another interface based on libglade, to use
|
||||
, you'll need glade:
|
||||
|
||||
* http://glade.gnome.org/
|
||||
|
||||
To build, first cd to src/frontend/posix and run
|
||||
`meson build --buildtype=release`
|
||||
|
||||
Then build the program by running `ninja -C build`
|
||||
|
||||
It will generate three programs:
|
||||
1) "desmume" in the "build/gtk" directory;
|
||||
2) "desmume-cli" in the "build/cli" directory.
|
||||
|
||||
If glade is installed on your system, you'll get a third
|
||||
binary:
|
||||
|
||||
3) "desmume-glade" in the "build/gtk-glade" directory.
|
||||
|
||||
You can even type "ninja -C build install" to install those programs on
|
||||
your system (in /usr/local/ by default); then uninstalling is
|
||||
done by typing "ninja -C build uninstall".
|
||||
|
||||
For more information on the available commandline options,
|
||||
check the other README files which will be more up to date.
|
||||
|
||||
The following options specially are available on these posix ports:
|
||||
|
||||
--disable-limiter Disables the 60 fps limiter
|
||||
--soft-convert Use software colour conversion during OpenGL
|
||||
screen rendering. May produce better or worse
|
||||
frame rates depending on hardware.
|
||||
|
||||
The following options specially are available on the Gtk+ port:
|
||||
|
||||
--opengl-2d Enables using OpenGL for screen rendering
|
||||
--disable-sound Disables the sound emulation
|
||||
--disable-3d Disables the 3D emulation
|
||||
|
||||
The following options specially are available on the CLI port:
|
||||
|
||||
--opengl-2d Enables using OpenGL for screen rendering
|
||||
--disable-sound Disables the sound emulation
|
||||
|
||||
NOTE:
|
||||
The Gtk+ and Glade builds use gtkGLext to handle the OpenGL
|
||||
rendering and contexts. You may get improved performance by
|
||||
also passing the argument --gdk-gl-force-indirect. This has
|
||||
been seen to improve things for Nvidia based graphics cards
|
||||
under Linux.
|
||||
|
||||
Visit us on the web at http://www.desmume.org
|
|
@ -0,0 +1,392 @@
|
|||
DeSmuME
|
||||
_________________________________________
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2006-2022 DeSmuME team
|
||||
Last Updated: May 23, 2022
|
||||
|
||||
Contents:
|
||||
1) System Requirements ..................................................... 17
|
||||
2) Quick Start Guide for Using DeSmuME for macOS ........................... 58
|
||||
3) Improving Emulation Performance ........................................ 204
|
||||
4) Troubleshooting ........................................................ 230
|
||||
5) Additional Documentation ............................................... 245
|
||||
6) Contact Information .................................................... 275
|
||||
7) License ................................................................ 377
|
||||
|
||||
|
||||
1) System Requirements ________________________________________________________
|
||||
|
||||
Operating System: macOS v10.5 (Leopard) or later
|
||||
|
||||
CPU: Can run on any PowerPC G4, G5, or Intel processor
|
||||
Minimum Recommended: 2.4 GHz Intel Core 2 Duo
|
||||
Best Experience Recommended: 2.4 GHz Intel i5 (Haswell)
|
||||
|
||||
RAM: 512 MB (minimum)
|
||||
2 GB (recommended)
|
||||
|
||||
Before you begin, make sure that your Mac meets the listed system requirements.
|
||||
In general, any Mac with an Intel Core 2 Duo processor (from Mid-2007) should
|
||||
be sufficient for basic gaming. However, it is possible to run DeSmuME with
|
||||
even older hardware than that. In this case, you will need to use the settings
|
||||
listed in the section "Improving Emulation Performance" to make things usable.
|
||||
With this level of hardware, running any additional graphics enhancing features
|
||||
will result in a poor experience. Some frameskip will also be necessary in
|
||||
order maintain your execution speed.
|
||||
|
||||
If your Mac meets the minimum recommended requirements, then you should be able
|
||||
to run all games at full speed without any frameskip. You may need to use some
|
||||
of the settings listed in the section "Improving Emulation Performance" for
|
||||
certain games, but they should not be required for most games. You will also be
|
||||
able to use some basic graphical enhancements, such as using some of the
|
||||
display filters. However, increased 3D rendering resolution may not be possible
|
||||
for all games for this level of hardware.
|
||||
|
||||
However, if your Mac has an Intel Haswell (from late 2013) or an Apple Silicon
|
||||
processor (from 2020), you will be able to run all games with all of DeSmuME's
|
||||
features without any performance problems. Graphics enhancements, such as
|
||||
increased 3D rendering resolution, can be adjusted as needed to fit the
|
||||
performance level of your hardware.
|
||||
|
||||
Please note that running DeSmuME on a PowerPC, while possible, is not fully
|
||||
supported. The PowerPC binary exists mostly for testing and development
|
||||
purposes, and also just because we can. Most games don't work well on PowerPC,
|
||||
and so you will be limited to running only the most basic of games, such as
|
||||
"Phoenix Wright: Ace Attorney" or "Picross DS."
|
||||
|
||||
|
||||
2) Quick Start Guide for Using DeSmuME for macOS ______________________________
|
||||
|
||||
Installing DeSmuME is as easy as copying DeSmuME.app to your Applications
|
||||
folder (or other folder of your choice). Double-click the app to start DeSmuME.
|
||||
|
||||
Note that DeSmuME for macOS may have a different feature set than DeSmuME for
|
||||
Windows and DeSmuME for Linux. As of this writing, some features that are
|
||||
present in DeSmuME for Windows are not present in DeSmuME for macOS.
|
||||
|
||||
The rest of this section will be a guide to help you quickly get started using
|
||||
DeSmuME for macOS.
|
||||
|
||||
Loading a ROM and Starting the Emulator:
|
||||
Simply double-click the desired ROM from the Finder to play the game. By
|
||||
default, DeSmuME will load the ROM and start emulation. Also, there are
|
||||
additional ROM loading options that you can change in DeSmuME > Preferences if
|
||||
you need them.
|
||||
|
||||
Using the NDS Controller:
|
||||
Each NDS controller button can be mapped to a button of your choice on your
|
||||
keyboard, gamepad, or joystick. You can view the mappings by clicking on Input
|
||||
in DeSmuME > Preferences. To change a mapping, click on the NDS control that
|
||||
you want to change, then press the button on your input device to map it.
|
||||
|
||||
By default, the NDS controller is mapped to the following keys on your keyboard:
|
||||
Up - Up Arrow
|
||||
Down - Down Arrow
|
||||
Left - Left Arrow
|
||||
Right - Right Arrow
|
||||
A Button - X
|
||||
B Button - Z
|
||||
X Button - S
|
||||
Y Button - A
|
||||
L Trigger - Q
|
||||
R Trigger - W
|
||||
Start - Return
|
||||
Select - Tab
|
||||
Lid - Delete (Backspace)
|
||||
Microphone (Internal Noise Samples) - ` (Accent)
|
||||
|
||||
The NDS can support a variety of SLOT-2 devices. Some devices, such as the
|
||||
Guitar Grip, EasyPiano, and Taito Paddle have inputs, which are mapped to your
|
||||
keyboard using these defaults:
|
||||
Guitar Grip:
|
||||
Green - E
|
||||
Red - R
|
||||
Yellow - T
|
||||
Blue - Y
|
||||
|
||||
EasyPiano:
|
||||
C - C
|
||||
C# - F
|
||||
D - V
|
||||
D# - G
|
||||
E - B
|
||||
F - N
|
||||
F# - J
|
||||
G - M
|
||||
G# - K
|
||||
A - , (Comma)
|
||||
A# - L
|
||||
B - . (Period)
|
||||
High C - / (Forward Slash)
|
||||
|
||||
Paddle:
|
||||
Paddle Adjust -5 - O
|
||||
Paddle Adjust +5 - P
|
||||
|
||||
In addition, the following emulator functions are mapped to your keyboard by
|
||||
default:
|
||||
Execute/Pause - Forward Delete
|
||||
Reset - Page Down
|
||||
Rotate Display Left - [ (Left Bracket)
|
||||
Rotate Display Right - ] (Right Bracket)
|
||||
Set Speed to Half - - (Dash)
|
||||
Set Speed to Double - = (Equal)
|
||||
|
||||
Using the NDS Touch Pad:
|
||||
Touch pad input is emulated using the left mouse button by default. Simply
|
||||
click in the touch pad area of the NDS display window to use the NDS touch pad.
|
||||
|
||||
Using the NDS Microphone:
|
||||
Some games make use of the NDS microphone. DeSmuME emulates the NDS microphone
|
||||
by using the default audio input device selected in your System Preferences.
|
||||
You can choose Emulation > Show Microphone Settings to view the audio input
|
||||
device that DeSmuME is currently using, as well as setting its gain.
|
||||
|
||||
DeSmuME will track the audio input level on the meter as the NDS reads the
|
||||
microphone. The meter reflects the audio input level as seen by the NDS, not
|
||||
the host. Note that some games ignore the microphone, and therefore will not
|
||||
register on the meter. If you need to view the audio input level from the host
|
||||
machine's perspective, you can view the host's audio input level in your System
|
||||
Preferences.
|
||||
|
||||
Finally, you can generate audio samples in software by using one of DeSmuME's
|
||||
audio generators, and send those audio samples to the NDS. This is what the
|
||||
Microphone command in your Input Preferences does. As long as the Microphone
|
||||
command is engaged, the host input device will be ignored. When you disengage
|
||||
the Microphone command, DeSmuME will automatically return to reading the host
|
||||
input device.
|
||||
|
||||
The microphone icon serves to indicate the current status of the NDS
|
||||
microphone, and will change color for each status:
|
||||
Black - The microphone is inactive due to the emulation being paused.
|
||||
Dark Gray - The host audio input is inactive because the user has muted it
|
||||
or because the user never authorized its usage. The emulation
|
||||
is currently only accepting software-generated sources.
|
||||
Bright Gray - A software-generated source is being used for the microphone
|
||||
input. This overrides any host audio input.
|
||||
Dark Green - The host audio input is active. However, the input level is
|
||||
too low to be meaningful, or the game is ignoring the
|
||||
microphone.
|
||||
Bright Green - The microphone is active and the game is reading a
|
||||
meaningful input level from the host audio input.
|
||||
Bright Red - The microphone is active and the game is reading a clipped
|
||||
input level. Depending on the situation, this may or may not
|
||||
be desirable. Use the gain slider to influence the host audio
|
||||
input level if needed.
|
||||
|
||||
Rotating the NDS Display:
|
||||
Some games require that the NDS display be at a certain rotation in order to
|
||||
look correct. Rotation options can be found by choosing
|
||||
View > Display Rotation. You can also use the toolbar buttons Rotate Left and
|
||||
Rotate Right to rotate the display by 90 degrees counterclockwise or clockwise,
|
||||
respectively. Finally, you can assign inputs to Rotate Left and Rotate Right in
|
||||
your Input Preferences.
|
||||
|
||||
Freezing and Restoring the Emulation State:
|
||||
Save states are a powerful feature that allows you to freeze the emulation
|
||||
state and restore it later. However, note that save states are only a
|
||||
temporary means of saving -- more permanent saves must be done using the
|
||||
in-game save (or ROM save).
|
||||
|
||||
- To freeze the emulation state, choose File > Save State File.
|
||||
- To restore the emulation state, choose File > Open State File.
|
||||
|
||||
You can also freeze/restore emulation states without having to manage the
|
||||
Open/Save dialogs. There are ten available save state "slots" that you can
|
||||
use to quickly freeze/restore the emulation state.
|
||||
|
||||
- To quick freeze the emulation state, choose File > Save State Slot > Slot #.
|
||||
The default hotkey for this is (Shift-#).
|
||||
- To quick restore the emulation state, choose File > Load State Slot > Slot #.
|
||||
The default hotkey for this is (#).
|
||||
|
||||
|
||||
3) Improving Emulation Performance ____________________________________________
|
||||
|
||||
There are many settings you can change in order to improve DeSmuME's emulation
|
||||
performance. All of the settings listed below affect performance the most. Use
|
||||
the settings as shown for the best possible performance. All of these settings
|
||||
may be found in DeSmuME > Preferences.
|
||||
|
||||
- WARNING: Changing any Emulation setting may cause emulation glitches in
|
||||
certain ROMs. Do not change these settings unless you are willing to
|
||||
accept reduced emulation accuracy or ROM compatibility.
|
||||
|
||||
Emulation:
|
||||
Advanced Bus Level Timing - Off (May cause glitches)
|
||||
Rigorous 3D Rendering Timing - On (May cause graphical glitches)
|
||||
CPU Emulation Engine - Dynamic Recompiler (Reduces ROM compatibility)
|
||||
Dynamic Recompiler Block Size - 100 (May cause glitches)
|
||||
Use External BIOS Images - Off (May reduce ROM compatibility)
|
||||
|
||||
3D Rendering:
|
||||
3D Rendering Engine - SoftRasterizer (or OpenGL if GPU Scaling Factor
|
||||
is greater than 4)
|
||||
GPU Scaling Factor - 1
|
||||
GPU Color Depth - 15-bit (Reduces color accuracy of 3D rendering)
|
||||
Texture Scaling Factor - 1
|
||||
|
||||
|
||||
4) Troubleshooting ____________________________________________________________
|
||||
|
||||
The vast majority of problems can be resolved by simply resetting DeSmuME's
|
||||
settings back to their defaults. The easiest way to do this is to delete the
|
||||
org.desmume.DeSmuME.plist file in your ~/Library/Preferences folder. There is
|
||||
also a DeleteUserDefaults.applescript script that is included with your DeSmuME
|
||||
installation that will do this for you.
|
||||
|
||||
If you are still experiencing problems after restoring your DeSmuME settings to
|
||||
their defaults, then you may want to post your issue on our DeSmuME forum. Your
|
||||
post may gain the attention of another user, or even a DeSmuME developer, to
|
||||
help assist you with your issue. See the section "Contact Information" for how
|
||||
to contact us on the forum.
|
||||
|
||||
|
||||
5) Additional Documentation ___________________________________________________
|
||||
|
||||
The quick start guide in this Read Me is by no means a complete reference to
|
||||
everything that DeSmuME can do! If you need any additional information about
|
||||
DeSmuME, then you can reference our online Wiki pages for up-to-date
|
||||
information.
|
||||
|
||||
* Official Documentation: https://wiki.desmume.org/index.php?title=Main_Page
|
||||
|
||||
This is the main Wiki page that contains all of our official documentation.
|
||||
|
||||
* FAQ: https://wiki.desmume.org/index.php?title=Faq
|
||||
|
||||
The Frequently Asked Questions (FAQ) page has a lot of useful general
|
||||
information about DeSmuME. Do note that some of the information may be platform
|
||||
specific, and may not directly apply to the macOS version of DeSmuME.
|
||||
|
||||
* DeSmuME Manual for macOS:
|
||||
https://wiki.desmume.org/index.php?title=DeSmuME_Manual_for_the_Macintosh_port
|
||||
|
||||
This page contains complete and detailed information about how to operate
|
||||
DeSmuME for macOS.
|
||||
|
||||
* DeSmuME Build Instructions for macOS:
|
||||
https://wiki.desmume.org/index.php?title=Installing_DeSmuME_from_source_on_OS_X
|
||||
|
||||
This page contains complete and detailed instructions about how to make your
|
||||
own build of DeSmuME for macOS directly from the source code.
|
||||
|
||||
|
||||
6) Contact Information ________________________________________________________
|
||||
|
||||
Thank you for you interest in DeSmuME! If you want to tell us how useful
|
||||
DeSmuME is in your life, your love (or hate) of certain NDS games, your passion
|
||||
for NDS homebrew development, or anything else related to DeSmuME or NDS
|
||||
emulation, then there are various ways for you to contact us!
|
||||
|
||||
However, keep in mind that there are a few of rules that you need to follow:
|
||||
- Do not ask us to provide ROMs, BIOS files, or any other copyrighted stuff.
|
||||
We don't want to have to deal with any legal issues that could get us in
|
||||
trouble, or worse, completely shut down.
|
||||
|
||||
- When contacting us, please use the appropriate means to do it. For example,
|
||||
if you simply want to tell us how much you love or hate us, then use the
|
||||
comments on the official webpage. Another example: If you want to post on the
|
||||
forum, be sure to keep the topic focused on DeSmuME; questions that ask for
|
||||
things like us providing you the latest Pokemon cheats are not DeSmuME
|
||||
related, and we will instead refer you to a Pokemon cheaters forum. Finally,
|
||||
our developer chat channel is intended for furthering the development work of
|
||||
DeSmuME; questions about how to use DeSmuME should not come here, but instead
|
||||
go to the Support forum. In short, use the appropriate contact method. That's
|
||||
why the different methods exist!
|
||||
|
||||
* Official Website: https://desmume.org
|
||||
|
||||
Our official website has the latest news on DeSmuME releases, and also has a
|
||||
lot of other useful information about DeSmuME. You can comment on different
|
||||
posts telling us how you feel about DeSmuME. Is DeSmuME the best thing in your
|
||||
life? Is it making you cry? Or is it a bunch of blah? Let us know here!
|
||||
|
||||
* Public Forum: https://forums.desmume.org
|
||||
|
||||
If you have a question about DeSmuME, then this is the place to ask it. But
|
||||
before you ask it, be aware that your question may have already been answered
|
||||
before, so try the following things first:
|
||||
|
||||
- Read the manual and the FAQ. A lot of questions people have are usually
|
||||
already answered in our documentation.
|
||||
- Do a forum search about your question.
|
||||
|
||||
If you still need to ask a question, choose Help > Submit a Support Request in
|
||||
the DeSmuME application. Follow the onscreen instructions on the Support
|
||||
Request Form.
|
||||
|
||||
* Live Developer Chat Channel: irc://irc.libera.chat:6697/desmume
|
||||
|
||||
We have a live developer chatline on Libera IRC at #desmume. This channel
|
||||
is meant for discussing the development of DeSmuME, and shows the real work
|
||||
that goes on behind the scenes. If you are interested in doing any sort of
|
||||
software programming, software testing, documentation, or graphics work, then
|
||||
please join our chat channel! We would love for you to join us!
|
||||
|
||||
* Bug Reports:
|
||||
|
||||
If you believe that you have found a bug, you may submit a bug report by
|
||||
choosing Help > Submit a Bug Report in the DeSmuME application. Follow the
|
||||
onscreen instructions on the Bug Report Form.
|
||||
|
||||
When you click Go To Bug Report Webpage, you will be taken to our bug tracker
|
||||
on SourceForge. Do note that you will need a SourceForge account in order to
|
||||
submit a bug report.
|
||||
|
||||
Bug submissions are very welcome and encouraged. However, when you submit a bug
|
||||
to us, you MUST provide the following information, or else your bug submission
|
||||
may be rejected:
|
||||
|
||||
- DeSmuME app version
|
||||
- Your operating system and OS version
|
||||
- Your Mac model identifier
|
||||
- The name of the running ROM when the bug was observed (or "None", if no ROM
|
||||
was running)
|
||||
- The serial code of the running ROM when the bug was observed (or "None", if
|
||||
no ROM was running)
|
||||
- A description of the exact behavior you observed
|
||||
- A description of the behavior you expected
|
||||
|
||||
All of this information will be prepared for you if you use the Bug Report Form
|
||||
from Help > Submit a Bug Report.
|
||||
|
||||
When you write your description, make sure that they are as detailed as
|
||||
possible. The better your descriptions are, the faster we can test and fix
|
||||
bugs. For example, if you observed a bug in the game "Golden Sun: Dark Dawn,"
|
||||
then the bug report could look something like this:
|
||||
|
||||
App Version: 0.9.13
|
||||
Operating System: macOS v12.4 (21F79)
|
||||
Mac Model Identifier: MacBookPro15,1
|
||||
ROM Name: GOLDENSUN_DD
|
||||
ROM Serial: NTR-BO5E-USA
|
||||
Observed Behavior: I tried to load a save state using the
|
||||
File > Load State > Slot 3 menu option, but the game froze. If I reset, I
|
||||
can get the game working again.
|
||||
Expected Behavior: The game should continue running from the point where I
|
||||
made the save state.
|
||||
|
||||
We will try to get your bug tested as soon as possible, but any fixes may take
|
||||
longer, depending on the complexity of the bug. Also, some bugs may require us
|
||||
to ask you for certain files, such as your ROM saves, save states, or console
|
||||
logs. For the above example, we would probably ask you for your save states to
|
||||
help us track down the bug.
|
||||
|
||||
|
||||
7) License ____________________________________________________________________
|
||||
|
||||
This file is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This file is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this software. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
* See the GNU General Public License details in COPYING.
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,74 @@
|
|||
DSM is ascii plain text. It is derived from the FCEUX FM2 format.
|
||||
It consists of several key-value pairs followed by an inputlog section.
|
||||
The inputlog section can be identified by its starting with a | (pipe).
|
||||
The inputlog section terminates at eof.
|
||||
Newlines may be \r\n or \n
|
||||
|
||||
Key-value pairs consist of a key identifier, followed by a space separator, followed by the value text.
|
||||
Value text is always terminated by a newline, which the value text will not include.
|
||||
The value text is parsed differently depending on the type of the key.
|
||||
The key-value pairs may be in any order, except that the first key must be version.
|
||||
|
||||
Integer keys (also used for booleans, with a 1 or 0) will have a value that is a simple integer not to exceed 32bits
|
||||
- version (required) - the version of the movie file format; for now it is always 3
|
||||
- emuVersion (required) - the version of the emulator used to produce the movie
|
||||
- rerecordCount (optional) - the rerecord count
|
||||
- romChecksum (optional) - the CRC32 of the rom used to make the movie. should match values specified on advanscene.com
|
||||
- romSerial (optional) - a concatenation of other uniquely identifying information about the rom (name,gamecode,makercode)
|
||||
- useExtBios (optional) - were bios files was used? defaults to false.
|
||||
- swiFromBios (optional) - were swi emulated by ExtBios? (alternative is internal HLE bios). defaults to false.
|
||||
|
||||
The rom identification information may be used at a later point to warn about mismatches between movies and roms, but is not right now.
|
||||
|
||||
String keys have values that consist of the remainder of the key-value pair line. As a consequence, string values cannot contain newlines.
|
||||
- romFilename (required) - the name of the file used to record the movie
|
||||
- comment (optional) - simply a memo.
|
||||
by convention, the first token in the comment value is the subject of the comment.
|
||||
by convention, subsequent comments with the same subject will have their ordering preserved and may be used to approximate multiline comments.
|
||||
by convention, the author of the movie should be stored in comment(s) with a subject of: author
|
||||
|
||||
Hex string keys (used for binary blobs) will have a value that is like 0x0123456789ABCDEF...
|
||||
- romChecksum (required) - this is currently unused.
|
||||
|
||||
GUID keys have a value which is in the standard guid format: 452DE2C3-EF43-2FA9-77AC-0677FC51543B
|
||||
- guid (required) a unique identifier for a movie, generated when the movie is created, which is used when loading a savestate to make sure it belongs to the current movie.
|
||||
|
||||
The inputlog section consists of lines beginning and ending with a | (pipe).
|
||||
The fields are as follows, except as noted in note C.
|
||||
|c|.............XXX YYY Z|
|
||||
|
||||
'R','L','D','U','T','S','B','A','Y','X','W','E','G'
|
||||
|
||||
field c is a variable length decimal integer which is a bitfield corresponding to miscellaneous input states which are valid at the start of the frame.
|
||||
Therefore, no miscellaneous commands is represented by a value of 0.
|
||||
Here are the currently defined bit values:
|
||||
0x01 - Microphone Noise (hardcoded noise sample; to be held through duration of frame)
|
||||
0x02 - Reset
|
||||
0x04 - Lid
|
||||
|
||||
|
||||
the format of the main section is as follows:
|
||||
|
||||
the field begins with 13 characters which constitute a bitfield.
|
||||
any character other than ' ' or '.' means that the button was pressed.
|
||||
by convention, the following mnemonics will be used in a column to remind us of which button corresponds to which column:
|
||||
RLDUTSBAYXWEG (Right,Left,Down,Up,sTart,Select,B,A,Y,X,lshoulder,rshoulder,debuG)
|
||||
This ordering is based on FCEUX to a certain extent, and arbitrary after that.
|
||||
W and E were chosen for shoulders to suggest West and East for Left and Right.
|
||||
While the emulator supports a 'lid' button, and to some extent a 'blow' button, these are not supported in the movies.
|
||||
|
||||
XXX: %03d, the x position of the stylus (0,0 topleft, 255,191 bottomright)
|
||||
YYY: %03d, the y position of the stylus
|
||||
Z: %1d, 1 if the stylus is pressed pressed; 0 if not
|
||||
|
||||
Additional fields after this main section may be added later without breaking the file format.
|
||||
|
||||
* Notes *
|
||||
A. There is no key-value pair that indicates the length of the movie. This must be read by scanning the inputlog and counting the number of lines.
|
||||
|
||||
B. All movies start from power-on.
|
||||
|
||||
C. The emulator uses these framerate constants
|
||||
arm7_cycles_per_frame = 560190
|
||||
frames_per_second = 59.8261
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
The desmume save file format is merely a raw save file with a FOOTER.
|
||||
|
||||
This was chosen in order to maximize compatibility with other emulators,
|
||||
which tend load the savefile as-is and let the game read out of whatever range
|
||||
it is expecting. To assist with this, before writing the save file, desmume
|
||||
will pad the raw save file out to the next highest known length. Note that this
|
||||
may sometimes be incorrect if the savefile hasnt been written through to the end
|
||||
during initialization. This could cause other emulators to fail to recognize the
|
||||
save file.
|
||||
|
||||
Additionally, the footer makes it easier to analyze save files, because the
|
||||
game's data will be at the correct addresses starting at offset 0x0000.
|
||||
|
||||
The footer format can be identified by locating the 16Byte ascii string
|
||||
"|-DESMUME SAVE-|"
|
||||
at the end of the file. This corresponds with the following save structure:
|
||||
|
||||
struct Footer {
|
||||
u32 actually_written_size;
|
||||
u32 padded_size;
|
||||
u32 save_type; //(not currently used)
|
||||
u32 address_size; //address bus size
|
||||
u32 save_size; //size parameter of the save type (not currently used)
|
||||
u32 version_number; //should be 0
|
||||
char cookie[16];
|
||||
};
|
||||
|
||||
note that padded_size should be where you see the end of the raw save data
|
||||
and the beginning of desmume-specific information, including some junk before
|
||||
the actual footer.
|
||||
|
||||
actually_written_size is the highest address (plus one) written to by the game.
|
||||
|
||||
The new desmume savefile system tries to make as few decisions as possible,
|
||||
which is the reason for the behavior of actually_written_size and the disuse
|
||||
of save_type and save_size. If few decisions are made, then few mistakes can
|
||||
be made. That is the idea, anyway. We'll make decisions later if we need to.
|
||||
save_type and save_size are reserved in case we do.
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,8 @@
|
|||
Tips:
|
||||
* Set hotkeys for "Mic Prev Sample" and "Mic Next Sample" in the "Main" section of hotkey configuration (suggest [ and ])
|
||||
* This will rotate through all the provided desmume_N.wav. You can add your own in the series, just pick the next number.
|
||||
* Keep the microphone hotkey held down for as long as you want the noise to play! Just tapping it will make a very short sound indeed.
|
||||
|
||||
desmume_0.wav was formerly "PERFECT BLOW FOR DS EMULATORS.wav"
|
||||
desmume_1.wav was formerly "noise_loud.wav"
|
||||
desmume_4.wav came to us as "pcm0822m.wav"; these are alleged to work well for Giant Bowser fights in Bowser's Inside Story.
|
Binary file not shown.
|
@ -0,0 +1,4 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = tab
|
|
@ -0,0 +1,392 @@
|
|||
/*
|
||||
Copyright (C) 2008-2021 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "Database.h"
|
||||
#include "retro_miscellaneous.h"
|
||||
|
||||
//------------------------------------------------------------
|
||||
//large databases are first. scroll down to ENDLARGE to find the code
|
||||
|
||||
struct MAKER
|
||||
{
|
||||
u16 code;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
|
||||
static const char regions_index[] = "JPFSEODIRKHXVWUC";
|
||||
static const char *regions[] = {
|
||||
"JPN", // J
|
||||
"EUR", // P
|
||||
"FRA", // F
|
||||
"ESP", // S
|
||||
"USA", // E
|
||||
"INT", // O
|
||||
"NOE", // D
|
||||
"ITA", // I
|
||||
"RUS", // R
|
||||
"KOR", // K
|
||||
"HOL", // H
|
||||
"EUU", // X
|
||||
"EUU", // V
|
||||
"EUU", // W
|
||||
"AUS", // U
|
||||
"CHN", // C
|
||||
};
|
||||
|
||||
static MAKER makerCodes[] = {
|
||||
{ 0x3130, "Nintendo" },
|
||||
{ 0x3230, "Rocket Games, Ajinomoto" },
|
||||
{ 0x3330, "Imagineer-Zoom" },
|
||||
{ 0x3430, "Gray Matter?" },
|
||||
{ 0x3530, "Zamuse" },
|
||||
{ 0x3630, "Falcom" },
|
||||
{ 0x3730, "Enix?" },
|
||||
{ 0x3830, "Capcom" },
|
||||
{ 0x3930, "Hot B Co." },
|
||||
{ 0x4130, "Jaleco" },
|
||||
{ 0x4230, "Coconuts Japan" },
|
||||
{ 0x4330, "Coconuts Japan/G.X.Media" },
|
||||
{ 0x4430, "Micronet?" },
|
||||
{ 0x4530, "Technos" },
|
||||
{ 0x4630, "Mebio Software" },
|
||||
{ 0x4730, "Shouei System" },
|
||||
{ 0x4830, "Starfish" },
|
||||
{ 0x4A30, "Mitsui Fudosan/Dentsu" },
|
||||
{ 0x4C30, "Warashi Inc." },
|
||||
{ 0x4E30, "Nowpro" },
|
||||
{ 0x5030, "Game Village" },
|
||||
{ 0x3031, "?????????????" },
|
||||
{ 0x3231, "Infocom" },
|
||||
{ 0x3331, "Electronic Arts Japan" },
|
||||
{ 0x3531, "Cobra Team" },
|
||||
{ 0x3631, "Human/Field" },
|
||||
{ 0x3731, "KOEI" },
|
||||
{ 0x3831, "Hudson Soft" },
|
||||
{ 0x3931, "S.C.P." },
|
||||
{ 0x4131, "Yanoman" },
|
||||
{ 0x4331, "Tecmo Products" },
|
||||
{ 0x4431, "Japan Glary Business" },
|
||||
{ 0x4531, "Forum/OpenSystem" },
|
||||
{ 0x4631, "Virgin Games" },
|
||||
{ 0x4731, "SMDE" },
|
||||
{ 0x4A31, "Daikokudenki" },
|
||||
{ 0x5031, "Creatures Inc." },
|
||||
{ 0x5131, "TDK Deep Impresion" },
|
||||
{ 0x3032, "Destination Software, KSS" },
|
||||
{ 0x3132, "Sunsoft/Tokai Engineering??" },
|
||||
{ 0x3232, "POW, VR 1 Japan??" },
|
||||
{ 0x3332, "Micro World" },
|
||||
{ 0x3532, "San-X" },
|
||||
{ 0x3632, "Enix" },
|
||||
{ 0x3732, "Loriciel/Electro Brain" },
|
||||
{ 0x3832, "Kemco Japan" },
|
||||
{ 0x3932, "Seta" },
|
||||
{ 0x4132, "Culture Brain" },
|
||||
{ 0x4332, "Palsoft" },
|
||||
{ 0x4432, "Visit Co.,Ltd." },
|
||||
{ 0x4532, "Intec" },
|
||||
{ 0x4632, "System Sacom" },
|
||||
{ 0x4732, "Poppo" },
|
||||
{ 0x4832, "Ubisoft Japan" },
|
||||
{ 0x4A32, "Media Works" },
|
||||
{ 0x4B32, "NEC InterChannel" },
|
||||
{ 0x4C32, "Tam" },
|
||||
{ 0x4D32, "Jordan" },
|
||||
{ 0x4E32, "Smilesoft ???, Rocket ???" },
|
||||
{ 0x5132, "Mediakite" },
|
||||
{ 0x3033, "Viacom" },
|
||||
{ 0x3133, "Carrozzeria" },
|
||||
{ 0x3233, "Dynamic" },
|
||||
{ 0x3433, "Magifact" },
|
||||
{ 0x3533, "Hect" },
|
||||
{ 0x3633, "Codemasters" },
|
||||
{ 0x3733, "Taito/GAGA Communications" },
|
||||
{ 0x3833, "Laguna" },
|
||||
{ 0x3933, "Telstar Fun & Games, Event/Taito" },
|
||||
{ 0x4233, "Arcade Zone Ltd" },
|
||||
{ 0x4333, "Entertainment International/Empire Software?" },
|
||||
{ 0x4433, "Loriciel" },
|
||||
{ 0x4533, "Gremlin Graphics" },
|
||||
{ 0x4633, "K.Amusement Leasing Co." },
|
||||
{ 0x3034, "Seika Corp." },
|
||||
{ 0x3134, "Ubi Soft Entertainment" },
|
||||
{ 0x3234, "Sunsoft US?" },
|
||||
{ 0x3434, "Life Fitness" },
|
||||
{ 0x3634, "System 3" },
|
||||
{ 0x3734, "Spectrum Holobyte" },
|
||||
{ 0x3934, "IREM" },
|
||||
{ 0x4234, "Raya Systems" },
|
||||
{ 0x4334, "Renovation Products" },
|
||||
{ 0x4434, "Malibu Games" },
|
||||
{ 0x4634, "Eidos (was U.S. Gold <=1995)" },
|
||||
{ 0x4734, "Playmates Interactive?" },
|
||||
{ 0x4A34, "Fox Interactive" },
|
||||
{ 0x4B34, "Time Warner Interactive" },
|
||||
{ 0x5134, "Disney Interactive" },
|
||||
{ 0x5334, "Black Pearl" },
|
||||
{ 0x5534, "Advanced Productions" },
|
||||
{ 0x5834, "GT Interactive" },
|
||||
{ 0x5934, "RARE?" },
|
||||
{ 0x5A34, "Crave Entertainment" },
|
||||
{ 0x3035, "Absolute Entertainment" },
|
||||
{ 0x3135, "Acclaim" },
|
||||
{ 0x3235, "Activision" },
|
||||
{ 0x3335, "American Sammy" },
|
||||
{ 0x3435, "Take 2 Interactive (before it was GameTek)" },
|
||||
{ 0x3535, "Hi Tech" },
|
||||
{ 0x3635, "LJN LTD." },
|
||||
{ 0x3835, "Mattel" },
|
||||
{ 0x4135, "Mindscape, Red Orb Entertainment?" },
|
||||
{ 0x4235, "Romstar" },
|
||||
{ 0x4335, "Taxan" },
|
||||
{ 0x4435, "Midway (before it was Tradewest)" },
|
||||
{ 0x4635, "American Softworks" },
|
||||
{ 0x4735, "Majesco Sales Inc" },
|
||||
{ 0x4835, "3DO" },
|
||||
{ 0x4B35, "Hasbro" },
|
||||
{ 0x4C35, "NewKidCo" },
|
||||
{ 0x4D35, "Telegames" },
|
||||
{ 0x4E35, "Metro3D" },
|
||||
{ 0x5035, "Vatical Entertainment" },
|
||||
{ 0x5135, "LEGO Media" },
|
||||
{ 0x5335, "Xicat Interactive" },
|
||||
{ 0x5435, "Cryo Interactive" },
|
||||
{ 0x5735, "Red Storm Entertainment" },
|
||||
{ 0x5835, "Microids" },
|
||||
{ 0x5A35, "Conspiracy/Swing" },
|
||||
{ 0x3036, "Titus" },
|
||||
{ 0x3136, "Virgin Interactive" },
|
||||
{ 0x3236, "Maxis" },
|
||||
{ 0x3436, "LucasArts Entertainment" },
|
||||
{ 0x3736, "Ocean" },
|
||||
{ 0x3936, "Electronic Arts" },
|
||||
{ 0x4236, "Laser Beam" },
|
||||
{ 0x4536, "Elite Systems" },
|
||||
{ 0x4636, "Electro Brain" },
|
||||
{ 0x4736, "The Learning Company" },
|
||||
{ 0x4836, "BBC" },
|
||||
{ 0x4A36, "Software 2000" },
|
||||
{ 0x4C36, "BAM! Entertainment" },
|
||||
{ 0x4D36, "Studio 3" },
|
||||
{ 0x5136, "Classified Games" },
|
||||
{ 0x5336, "TDK Mediactive" },
|
||||
{ 0x5536, "DreamCatcher" },
|
||||
{ 0x5636, "JoWood Produtions" },
|
||||
{ 0x5736, "SEGA" },
|
||||
{ 0x5836, "Wannado Edition" },
|
||||
{ 0x5936, "LSP" },
|
||||
{ 0x5A36, "ITE Media" },
|
||||
{ 0x3037, "Infogrames" },
|
||||
{ 0x3137, "Interplay" },
|
||||
{ 0x3237, "JVC" },
|
||||
{ 0x3337, "Parker Brothers" },
|
||||
{ 0x3537, "Sales Curve" },
|
||||
{ 0x3837, "THQ" },
|
||||
{ 0x3937, "Accolade" },
|
||||
{ 0x4137, "Triffix Entertainment" },
|
||||
{ 0x4337, "Microprose Software" },
|
||||
{ 0x4437, "Universal Interactive, Sierra, Simon & Schuster?" },
|
||||
{ 0x4637, "Kemco" },
|
||||
{ 0x4737, "Rage Software" },
|
||||
{ 0x4837, "Encore" },
|
||||
{ 0x4A37, "Zoo" },
|
||||
{ 0x4B37, "BVM" },
|
||||
{ 0x4C37, "Simon & Schuster Interactive" },
|
||||
{ 0x4D37, "Asmik Ace Entertainment Inc./AIA" },
|
||||
{ 0x4E37, "Empire Interactive?" },
|
||||
{ 0x5137, "Jester Interactive" },
|
||||
{ 0x5437, "Scholastic" },
|
||||
{ 0x5537, "Ignition Entertainment" },
|
||||
{ 0x5737, "Stadlbauer" },
|
||||
{ 0x3038, "Misawa" },
|
||||
{ 0x3138, "Teichiku" },
|
||||
{ 0x3238, "Namco Ltd." },
|
||||
{ 0x3338, "LOZC" },
|
||||
{ 0x3438, "KOEI" },
|
||||
{ 0x3638, "Tokuma Shoten Intermedia" },
|
||||
{ 0x3738, "Tsukuda Original" },
|
||||
{ 0x3838, "DATAM-Polystar" },
|
||||
{ 0x4238, "Bulletproof Software" },
|
||||
{ 0x4338, "Vic Tokai Inc." },
|
||||
{ 0x4538, "Character Soft" },
|
||||
{ 0x4638, "I'Max" },
|
||||
{ 0x4738, "Saurus" },
|
||||
{ 0x4A38, "General Entertainment" },
|
||||
{ 0x4E38, "Success" },
|
||||
{ 0x5038, "SEGA Japan" },
|
||||
{ 0x3039, "Takara Amusement" },
|
||||
{ 0x3139, "Chun Soft" },
|
||||
{ 0x3239, "Video System, McO'River???" },
|
||||
{ 0x3339, "BEC" },
|
||||
{ 0x3539, "Varie" },
|
||||
{ 0x3639, "Yonezawa/S'pal" },
|
||||
{ 0x3739, "Kaneko" },
|
||||
{ 0x3939, "Victor Interactive Software, Pack in Video" },
|
||||
{ 0x4139, "Nichibutsu/Nihon Bussan" },
|
||||
{ 0x4239, "Tecmo" },
|
||||
{ 0x4339, "Imagineer" },
|
||||
{ 0x4639, "Nova" },
|
||||
{ 0x4739, "Den'Z" },
|
||||
{ 0x4839, "Bottom Up" },
|
||||
{ 0x4A39, "TGL" },
|
||||
{ 0x4C39, "Hasbro Japan?" },
|
||||
{ 0x4E39, "Marvelous Entertainment" },
|
||||
{ 0x5039, "Keynet Inc." },
|
||||
{ 0x5139, "Hands-On Entertainment" },
|
||||
{ 0x3041, "Telenet" },
|
||||
{ 0x3141, "Hori" },
|
||||
{ 0x3441, "Konami" },
|
||||
{ 0x3541, "K.Amusement Leasing Co." },
|
||||
{ 0x3641, "Kawada" },
|
||||
{ 0x3741, "Takara" },
|
||||
{ 0x3941, "Technos Japan Corp." },
|
||||
{ 0x4141, "JVC, Victor Musical Indutries" },
|
||||
{ 0x4341, "Toei Animation" },
|
||||
{ 0x4441, "Toho" },
|
||||
{ 0x4641, "Namco" },
|
||||
{ 0x4741, "Media Rings Corporation" },
|
||||
{ 0x4841, "J-Wing" },
|
||||
{ 0x4A41, "Pioneer LDC" },
|
||||
{ 0x4B41, "KID" },
|
||||
{ 0x4C41, "Mediafactory" },
|
||||
{ 0x5041, "Infogrames Hudson" },
|
||||
{ 0x5141, "Kiratto. Ludic Inc" },
|
||||
{ 0x3042, "Acclaim Japan" },
|
||||
{ 0x3142, "ASCII (was Nexoft?)" },
|
||||
{ 0x3242, "Bandai" },
|
||||
{ 0x3442, "Enix" },
|
||||
{ 0x3642, "HAL Laboratory" },
|
||||
{ 0x3742, "SNK" },
|
||||
{ 0x3942, "Pony Canyon" },
|
||||
{ 0x4142, "Culture Brain" },
|
||||
{ 0x4242, "Sunsoft" },
|
||||
{ 0x4342, "Toshiba EMI" },
|
||||
{ 0x4442, "Sony Imagesoft" },
|
||||
{ 0x4642, "Sammy" },
|
||||
{ 0x4742, "Magical" },
|
||||
{ 0x4842, "Visco" },
|
||||
{ 0x4A42, "Compile " },
|
||||
{ 0x4C42, "MTO Inc." },
|
||||
{ 0x4E42, "Sunrise Interactive" },
|
||||
{ 0x5042, "Global A Entertainment" },
|
||||
{ 0x5142, "Fuuki" },
|
||||
{ 0x3043, "Taito" },
|
||||
{ 0x3243, "Kemco" },
|
||||
{ 0x3343, "Square" },
|
||||
{ 0x3443, "Tokuma Shoten" },
|
||||
{ 0x3543, "Data East" },
|
||||
{ 0x3643, "Tonkin House (was Tokyo Shoseki)" },
|
||||
{ 0x3843, "Koei" },
|
||||
{ 0x4143, "Konami/Ultra/Palcom" },
|
||||
{ 0x4243, "NTVIC/VAP" },
|
||||
{ 0x4343, "Use Co.,Ltd." },
|
||||
{ 0x4443, "Meldac" },
|
||||
{ 0x4543, "Pony Canyon" },
|
||||
{ 0x4643, "Angel, Sotsu Agency/Sunrise" },
|
||||
{ 0x4A43, "Boss" },
|
||||
{ 0x4743, "Yumedia/Aroma Co., Ltd" },
|
||||
{ 0x4B43, "Axela/Crea-Tech?" },
|
||||
{ 0x4C43, "Sekaibunka-Sha, Sumire kobo?, Marigul Management Inc.?" },
|
||||
{ 0x4D43, "Konami Computer Entertainment Osaka" },
|
||||
{ 0x5043, "Enterbrain" },
|
||||
{ 0x3044, "Taito/Disco" },
|
||||
{ 0x3144, "Sofel" },
|
||||
{ 0x3244, "Quest, Bothtec" },
|
||||
{ 0x3344, "Sigma, ?????" },
|
||||
{ 0x3444, "Ask Kodansha" },
|
||||
{ 0x3644, "Naxat" },
|
||||
{ 0x3744, "Copya System" },
|
||||
{ 0x3844, "Capcom Co., Ltd." },
|
||||
{ 0x3944, "Banpresto" },
|
||||
{ 0x4144, "TOMY" },
|
||||
{ 0x4244, "LJN Japan" },
|
||||
{ 0x4444, "NCS" },
|
||||
{ 0x4544, "Human Entertainment" },
|
||||
{ 0x4644, "Altron" },
|
||||
{ 0x4744, "Jaleco???" },
|
||||
{ 0x4844, "Gaps Inc." },
|
||||
{ 0x4C44, "????" },
|
||||
{ 0x4E44, "Elf" },
|
||||
{ 0x3045, "Jaleco" },
|
||||
{ 0x3145, "????" },
|
||||
{ 0x3245, "Yutaka" },
|
||||
{ 0x3345, "Varie" },
|
||||
{ 0x3445, "T&ESoft" },
|
||||
{ 0x3545, "Epoch" },
|
||||
{ 0x3745, "Athena" },
|
||||
{ 0x3845, "Asmik" },
|
||||
{ 0x3945, "Natsume" },
|
||||
{ 0x4145, "King Records" },
|
||||
{ 0x4245, "Atlus" },
|
||||
{ 0x4345, "Epic/Sony Records" },
|
||||
{ 0x4545, "IGS" },
|
||||
{ 0x4745, "Chatnoir" },
|
||||
{ 0x4845, "Right Stuff" },
|
||||
{ 0x4C45, "Spike" },
|
||||
{ 0x4D45, "Konami Computer Entertainment Tokyo" },
|
||||
{ 0x4E45, "Alphadream Corporation" },
|
||||
{ 0x3046, "A Wave" },
|
||||
{ 0x3146, "Motown Software" },
|
||||
{ 0x3246, "Left Field Entertainment" },
|
||||
{ 0x3346, "Extreme Ent. Grp." },
|
||||
{ 0x3446, "TecMagik" },
|
||||
{ 0x3946, "Cybersoft" },
|
||||
{ 0x4246, "Psygnosis" },
|
||||
{ 0x4546, "Davidson/Western Tech." },
|
||||
{ 0x3147, "PCCW Japan" },
|
||||
{ 0x3447, "KiKi Co Ltd" },
|
||||
{ 0x3547, "Open Sesame Inc???" },
|
||||
{ 0x3647, "Sims" },
|
||||
{ 0x3747, "Broccoli" },
|
||||
{ 0x3847, "Avex" },
|
||||
{ 0x3947, "D3 Publisher" },
|
||||
{ 0x4247, "Konami Computer Entertainment Japan" },
|
||||
{ 0x4447, "Square-Enix" },
|
||||
{ 0x4849, "Yojigen" },
|
||||
};
|
||||
|
||||
//------------------------------------------------------------
|
||||
//ENDLARGE
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace Database
|
||||
{
|
||||
const char* RegionXXXForCode(char code, bool unknownAsString)
|
||||
{
|
||||
size_t regions_num = ARRAY_SIZE(regions);
|
||||
|
||||
const char* found = strchr(regions_index,code);
|
||||
if(found && found-regions_index < strlen(regions_index)) return regions[found-regions_index];
|
||||
else return unknownAsString ? "???" : NULL;
|
||||
}
|
||||
|
||||
const char *MakerNameForMakerCode(u16 id, bool unknownAsString)
|
||||
{
|
||||
//too bad these aren't sorted
|
||||
for (size_t i = 0; i < ARRAY_SIZE(makerCodes); i++)
|
||||
{
|
||||
if (makerCodes[i].code == id)
|
||||
return makerCodes[i].name;
|
||||
}
|
||||
|
||||
return unknownAsString ? "Unknown" : NULL;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef DESMUME_DATABASE_H_
|
||||
#define DESMUME_DATABASE_H_
|
||||
|
||||
namespace Database
|
||||
{
|
||||
const char* RegionXXXForCode(char code, bool unknownAsString);
|
||||
const char* MakerNameForMakerCode(u16 id, bool unknownAsString);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,549 @@
|
|||
/*
|
||||
Copyright 2006 yopyop
|
||||
Copyright 2007 shash
|
||||
Copyright 2007-2024 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "FIFO.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "armcpu.h"
|
||||
#include "debug.h"
|
||||
#include "mem.h"
|
||||
#include "MMU.h"
|
||||
#include "registers.h"
|
||||
#include "NDSSystem.h"
|
||||
#include "gfx3d.h"
|
||||
|
||||
#if defined(ENABLE_AVX512_1)
|
||||
#define USEVECTORSIZE_512
|
||||
#define VECTORSIZE 64
|
||||
#elif defined(ENABLE_AVX2)
|
||||
#define USEVECTORSIZE_256
|
||||
#define VECTORSIZE 32
|
||||
#elif defined(ENABLE_SSE2)
|
||||
#define USEVECTORSIZE_128
|
||||
#define VECTORSIZE 16
|
||||
#elif defined(ENABLE_NEON_A64)
|
||||
#define USEVECTORSIZE_128
|
||||
#define VECTORSIZE 16
|
||||
#elif defined(ENABLE_ALTIVEC)
|
||||
#define USEVECTORSIZE_128
|
||||
#define VECTORSIZE 16
|
||||
#endif
|
||||
|
||||
#if defined(USEVECTORSIZE_512) || defined(USEVECTORSIZE_256) || defined(USEVECTORSIZE_128)
|
||||
#define USEMANUALVECTORIZATION
|
||||
#endif
|
||||
|
||||
|
||||
// ========================================================= IPC FIFO
|
||||
IPC_FIFO ipc_fifo[2];
|
||||
|
||||
void IPC_FIFOinit(u8 proc)
|
||||
{
|
||||
memset(&ipc_fifo[proc], 0, sizeof(IPC_FIFO));
|
||||
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, 0x00000101);
|
||||
}
|
||||
|
||||
void IPC_FIFOsend(u8 proc, u32 val)
|
||||
{
|
||||
u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184);
|
||||
if (!(cnt_l & IPCFIFOCNT_FIFOENABLE)) return; // FIFO disabled
|
||||
u8 proc_remote = proc ^ 1;
|
||||
|
||||
if (ipc_fifo[proc].size > 15)
|
||||
{
|
||||
cnt_l |= IPCFIFOCNT_FIFOERROR;
|
||||
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l);
|
||||
return;
|
||||
}
|
||||
|
||||
u16 cnt_r = T1ReadWord(MMU.MMU_MEM[proc_remote][0x40], 0x184);
|
||||
|
||||
//LOG("IPC%s send FIFO 0x%08X size %03i (l 0x%X, tail %02i) (r 0x%X, tail %02i)\n",
|
||||
// proc?"7":"9", val, ipc_fifo[proc].size, cnt_l, ipc_fifo[proc].tail, cnt_r, ipc_fifo[proc^1].tail);
|
||||
|
||||
cnt_l &= 0xBFFC; // clear send empty bit & full
|
||||
cnt_r &= 0xBCFF; // set recv empty bit & full
|
||||
ipc_fifo[proc].buf[ipc_fifo[proc].tail] = val;
|
||||
ipc_fifo[proc].tail++;
|
||||
ipc_fifo[proc].size++;
|
||||
if (ipc_fifo[proc].tail > 15) ipc_fifo[proc].tail = 0;
|
||||
|
||||
if (ipc_fifo[proc].size > 15)
|
||||
{
|
||||
cnt_l |= IPCFIFOCNT_SENDFULL; // set send full bit
|
||||
cnt_r |= IPCFIFOCNT_RECVFULL; // set recv full bit
|
||||
}
|
||||
|
||||
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l);
|
||||
T1WriteWord(MMU.MMU_MEM[proc_remote][0x40], 0x184, cnt_r);
|
||||
|
||||
if(cnt_r&IPCFIFOCNT_RECVIRQEN)
|
||||
NDS_makeIrq(proc_remote, IRQ_BIT_IPCFIFO_RECVNONEMPTY);
|
||||
|
||||
NDS_Reschedule();
|
||||
}
|
||||
|
||||
u32 IPC_FIFOrecv(u8 proc)
|
||||
{
|
||||
u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184);
|
||||
if (!(cnt_l & IPCFIFOCNT_FIFOENABLE)) return (0); // FIFO disabled
|
||||
u8 proc_remote = proc ^ 1;
|
||||
|
||||
u32 val = 0;
|
||||
|
||||
if ( ipc_fifo[proc_remote].size == 0 ) // remote FIFO error
|
||||
{
|
||||
cnt_l |= IPCFIFOCNT_FIFOERROR;
|
||||
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l);
|
||||
return (0);
|
||||
}
|
||||
|
||||
u16 cnt_r = T1ReadWord(MMU.MMU_MEM[proc_remote][0x40], 0x184);
|
||||
|
||||
cnt_l &= 0xBCFF; // clear send full bit & empty
|
||||
cnt_r &= 0xBFFC; // set recv full bit & empty
|
||||
|
||||
val = ipc_fifo[proc_remote].buf[ipc_fifo[proc_remote].head];
|
||||
ipc_fifo[proc_remote].head++;
|
||||
ipc_fifo[proc_remote].size--;
|
||||
if (ipc_fifo[proc_remote].head > 15) ipc_fifo[proc_remote].head = 0;
|
||||
|
||||
//LOG("IPC%s recv FIFO 0x%08X size %03i (l 0x%X, tail %02i) (r 0x%X, tail %02i)\n",
|
||||
// proc?"7":"9", val, ipc_fifo[proc].size, cnt_l, ipc_fifo[proc].tail, cnt_r, ipc_fifo[proc^1].tail);
|
||||
|
||||
if ( ipc_fifo[proc_remote].size == 0 ) // FIFO empty
|
||||
{
|
||||
cnt_l |= IPCFIFOCNT_RECVEMPTY;
|
||||
cnt_r |= IPCFIFOCNT_SENDEMPTY;
|
||||
|
||||
if(cnt_r&IPCFIFOCNT_SENDIRQEN)
|
||||
NDS_makeIrq(proc_remote, IRQ_BIT_IPCFIFO_SENDEMPTY);
|
||||
}
|
||||
|
||||
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l);
|
||||
T1WriteWord(MMU.MMU_MEM[proc_remote][0x40], 0x184, cnt_r);
|
||||
|
||||
NDS_Reschedule();
|
||||
|
||||
return (val);
|
||||
}
|
||||
|
||||
void IPC_FIFOcnt(u8 proc, u16 val)
|
||||
{
|
||||
u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184);
|
||||
u16 cnt_r = T1ReadWord(MMU.MMU_MEM[proc^1][0x40], 0x184);
|
||||
|
||||
if (val & IPCFIFOCNT_FIFOERROR)
|
||||
{
|
||||
//at least SPP uses this, maybe every retail game
|
||||
cnt_l &= ~IPCFIFOCNT_FIFOERROR;
|
||||
}
|
||||
|
||||
if (val & IPCFIFOCNT_SENDCLEAR)
|
||||
{
|
||||
ipc_fifo[proc].head = 0; ipc_fifo[proc].tail = 0; ipc_fifo[proc].size = 0;
|
||||
|
||||
cnt_l |= IPCFIFOCNT_SENDEMPTY;
|
||||
cnt_r |= IPCFIFOCNT_RECVEMPTY;
|
||||
|
||||
cnt_l &= ~IPCFIFOCNT_SENDFULL;
|
||||
cnt_r &= ~IPCFIFOCNT_RECVFULL;
|
||||
|
||||
}
|
||||
cnt_l &= ~IPCFIFOCNT_WRITEABLE;
|
||||
cnt_l |= val & IPCFIFOCNT_WRITEABLE;
|
||||
|
||||
//IPCFIFOCNT_SENDIRQEN may have been set (and/or the fifo may have been cleared) so we may need to trigger this irq
|
||||
//(this approach is used by libnds fifo system on occasion in fifoInternalSend, and began happening frequently for value32 with r4326)
|
||||
if(cnt_l&IPCFIFOCNT_SENDIRQEN) if(cnt_l & IPCFIFOCNT_SENDEMPTY)
|
||||
NDS_makeIrq(proc, IRQ_BIT_IPCFIFO_SENDEMPTY);
|
||||
|
||||
//IPCFIFOCNT_RECVIRQEN may have been set so we may need to trigger this irq
|
||||
if(cnt_l&IPCFIFOCNT_RECVIRQEN) if(!(cnt_l & IPCFIFOCNT_RECVEMPTY))
|
||||
NDS_makeIrq(proc, IRQ_BIT_IPCFIFO_RECVNONEMPTY);
|
||||
|
||||
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l);
|
||||
T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, cnt_r);
|
||||
|
||||
NDS_Reschedule();
|
||||
}
|
||||
|
||||
// ========================================================= GFX FIFO
|
||||
GFX_PIPE gxPIPE;
|
||||
GFX_FIFO gxFIFO;
|
||||
|
||||
void GFX_PIPEclear()
|
||||
{
|
||||
gxPIPE.head = 0;
|
||||
gxPIPE.tail = 0;
|
||||
gxPIPE.size = 0;
|
||||
gxFIFO.matrix_stack_op_size = 0;
|
||||
}
|
||||
|
||||
void GFX_FIFOclear()
|
||||
{
|
||||
gxFIFO.head = 0;
|
||||
gxFIFO.tail = 0;
|
||||
gxFIFO.size = 0;
|
||||
gxFIFO.matrix_stack_op_size = 0;
|
||||
}
|
||||
|
||||
static void GXF_FIFO_handleEvents()
|
||||
{
|
||||
bool low = gxFIFO.size <= 127;
|
||||
bool lowchange = MMU_new.gxstat.fifo_low ^ low;
|
||||
MMU_new.gxstat.fifo_low = low;
|
||||
if(low) triggerDma(EDMAMode_GXFifo);
|
||||
|
||||
bool empty = gxFIFO.size == 0;
|
||||
bool emptychange = MMU_new.gxstat.fifo_empty ^ empty;
|
||||
MMU_new.gxstat.fifo_empty = empty;
|
||||
|
||||
|
||||
MMU_new.gxstat.sb = gxFIFO.matrix_stack_op_size != 0;
|
||||
|
||||
if(emptychange||lowchange) NDS_Reschedule();
|
||||
}
|
||||
|
||||
static bool IsMatrixStackCommand(u8 cmd)
|
||||
{
|
||||
return cmd == 0x11 || cmd == 0x12;
|
||||
}
|
||||
|
||||
void GFX_FIFOsend(u8 cmd, u32 param)
|
||||
{
|
||||
//INFO("gxFIFO: send 0x%02X = 0x%08X (size %03i/0x%02X) gxstat 0x%08X\n", cmd, param, gxFIFO.size, gxFIFO.size, gxstat);
|
||||
//printf("fifo recv: %02X: %08X upto:%d\n",cmd,param,gxFIFO.size+1);
|
||||
|
||||
//TODO - WOAH ! NOT HANDLING A TOO-BIG FIFO RIGHT NOW!
|
||||
//if (gxFIFO.size > 255)
|
||||
//{
|
||||
// GXF_FIFO_handleEvents();
|
||||
// //NEED TO HANDLE THIS!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
// //gxstat |= 0x08000000; // busy
|
||||
// NDS_RescheduleGXFIFO(1);
|
||||
// //INFO("ERROR: gxFIFO is full (cmd 0x%02X = 0x%08X) (prev cmd 0x%02X = 0x%08X)\n", cmd, param, gxFIFO.cmd[255], gxFIFO.param[255]);
|
||||
// return;
|
||||
//}
|
||||
|
||||
|
||||
gxFIFO.cmd[gxFIFO.tail] = cmd;
|
||||
gxFIFO.param[gxFIFO.tail] = param;
|
||||
gxFIFO.tail++;
|
||||
gxFIFO.size++;
|
||||
if (gxFIFO.tail > HACK_GXIFO_SIZE-1) gxFIFO.tail = 0;
|
||||
|
||||
//if a matrix op is entering the pipeline, do accounting for it
|
||||
//(this is tested by wild west, which will jam a few ops in the fifo and then wait for the matrix stack to be
|
||||
//un-busy so it can read back the current matrix stack position).
|
||||
//it is definitely only pushes and pops which set this flag.
|
||||
//seems like it would be less work in the HW to make a counter than do cmps on all the command bytes, so maybe we're even doing it right.
|
||||
if(IsMatrixStackCommand(cmd))
|
||||
gxFIFO.matrix_stack_op_size++;
|
||||
|
||||
//along the same lines:
|
||||
//american girls julie finds a way will put a bunch of stuff and then a box test into the fifo and then immediately test the busy flag
|
||||
//so we need to set the busy flag here.
|
||||
//does it expect the fifo to be running then? well, it's definitely jammed -- making it unjammed at one point did fix this bug.
|
||||
//it's still not clear whether we're handling the immediate vs fifo commands properly at all :(
|
||||
//anyway, here we go, similar treatment. consider this a hack.
|
||||
if(cmd == 0x70) MMU_new.gxstat.tb = 1; //just set the flag--youre insane if you queue more than one of these anyway
|
||||
if(cmd == 0x71) MMU_new.gxstat.tb = 1;
|
||||
|
||||
if(gxFIFO.size>=HACK_GXIFO_SIZE) {
|
||||
printf("--FIFO FULL-- : %d\n",gxFIFO.size);
|
||||
}
|
||||
|
||||
//gxstat |= 0x08000000; // set busy flag
|
||||
|
||||
GXF_FIFO_handleEvents();
|
||||
|
||||
NDS_RescheduleGXFIFO(1);
|
||||
}
|
||||
|
||||
// this function used ONLY in gxFIFO
|
||||
BOOL GFX_PIPErecv(u8 *cmd, u32 *param)
|
||||
{
|
||||
//gxstat &= 0xF7FFFFFF; // clear busy flag
|
||||
|
||||
if (gxFIFO.size == 0)
|
||||
{
|
||||
GXF_FIFO_handleEvents();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*cmd = gxFIFO.cmd[gxFIFO.head];
|
||||
*param = gxFIFO.param[gxFIFO.head];
|
||||
|
||||
//see the associated increment in another function
|
||||
if(IsMatrixStackCommand(*cmd))
|
||||
{
|
||||
gxFIFO.matrix_stack_op_size--;
|
||||
if(gxFIFO.matrix_stack_op_size>0x10000000)
|
||||
printf("bad news disaster in matrix_stack_op_size\n");
|
||||
}
|
||||
|
||||
gxFIFO.head++;
|
||||
gxFIFO.size--;
|
||||
if (gxFIFO.head > HACK_GXIFO_SIZE-1) gxFIFO.head = 0;
|
||||
|
||||
GXF_FIFO_handleEvents();
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
void GFX_FIFOcnt(u32 val)
|
||||
{
|
||||
////INFO("gxFIFO: write cnt 0x%08X (prev 0x%08X) FIFO size %03i PIPE size %03i\n", val, gxstat, gxFIFO.size, gxPIPE.size);
|
||||
|
||||
if (val & (1<<29)) // clear? (only in homebrew?)
|
||||
{
|
||||
GFX_PIPEclear();
|
||||
GFX_FIFOclear();
|
||||
return;
|
||||
}
|
||||
|
||||
//zeromus says: what happened to clear stack?
|
||||
//if (val & (1<<15)) // projection stack pointer reset
|
||||
//{
|
||||
// gfx3d_ClearStack();
|
||||
// val &= 0xFFFF5FFF; // clear reset (bit15) & stack level (bit13)
|
||||
//}
|
||||
|
||||
T1WriteLong(MMU.ARM9_REG, 0x600, val);
|
||||
}
|
||||
|
||||
// ========================================================= DISP FIFO
|
||||
DISP_FIFO disp_fifo;
|
||||
|
||||
void DISP_FIFOinit()
|
||||
{
|
||||
memset(&disp_fifo, 0, sizeof(DISP_FIFO));
|
||||
}
|
||||
|
||||
template <typename T, size_t ADDROFFSET>
|
||||
void DISP_FIFOsend(const T val)
|
||||
{
|
||||
//INFO("DISP_FIFO send value 0x%08X (head 0x%06X, tail 0x%06X)\n", val, disp_fifo.head, disp_fifo.tail);
|
||||
|
||||
const size_t numBytes = sizeof(T);
|
||||
const size_t baseWriteAddress = disp_fifo.tail * sizeof(u32);
|
||||
const size_t finalWriteAddress = baseWriteAddress + ADDROFFSET;
|
||||
|
||||
switch (numBytes)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
#ifndef MSB_FIRST
|
||||
HostWriteByte((u8 *)disp_fifo.buf, (u32)finalWriteAddress, val);
|
||||
#else
|
||||
switch (ADDROFFSET)
|
||||
{
|
||||
case 0:
|
||||
HostWriteByte((u8 *)disp_fifo.buf, (u32)baseWriteAddress + 2, val);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
HostWriteByte((u8 *)disp_fifo.buf, (u32)baseWriteAddress + 3, val);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
HostWriteByte((u8 *)disp_fifo.buf, (u32)baseWriteAddress + 0, val);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
HostWriteByte((u8 *)disp_fifo.buf, (u32)baseWriteAddress + 1, val);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef MSB_FIRST
|
||||
if (ADDROFFSET == 3)
|
||||
#else
|
||||
if (ADDROFFSET == 1)
|
||||
#endif
|
||||
{
|
||||
disp_fifo.tail++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
#ifndef MSB_FIRST
|
||||
HostWriteWord((u8 *)disp_fifo.buf, (u32)finalWriteAddress, val);
|
||||
#else
|
||||
switch (ADDROFFSET)
|
||||
{
|
||||
case 0:
|
||||
HostWriteWord((u8 *)disp_fifo.buf, (u32)baseWriteAddress + 2, val);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
HostWriteWord((u8 *)disp_fifo.buf, (u32)baseWriteAddress + 0, val);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef MSB_FIRST
|
||||
if (ADDROFFSET == 2)
|
||||
#else
|
||||
if (ADDROFFSET == 0)
|
||||
#endif
|
||||
{
|
||||
disp_fifo.tail++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
HostWriteTwoWords((u8 *)disp_fifo.buf, (u32)finalWriteAddress, val);
|
||||
disp_fifo.tail++;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (disp_fifo.tail >= 0x6000)
|
||||
{
|
||||
disp_fifo.tail = 0;
|
||||
}
|
||||
}
|
||||
|
||||
u32 DISP_FIFOrecv_u32()
|
||||
{
|
||||
//if (disp_fifo.tail == disp_fifo.head) return (0); // FIFO is empty
|
||||
u32 val = disp_fifo.buf[disp_fifo.head];
|
||||
|
||||
disp_fifo.head++;
|
||||
if (disp_fifo.head >= 0x6000)
|
||||
{
|
||||
disp_fifo.head = 0;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void _DISP_FIFOrecv_LineAdvance()
|
||||
{
|
||||
disp_fifo.head += (GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16)) / sizeof(u32);
|
||||
if (disp_fifo.head >= 0x6000)
|
||||
{
|
||||
disp_fifo.head -= 0x6000;
|
||||
}
|
||||
}
|
||||
|
||||
void DISP_FIFOrecv_Line16(u16 *__restrict dst)
|
||||
{
|
||||
#ifdef USEMANUALVECTORIZATION
|
||||
if ( (disp_fifo.head + (GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16)) / sizeof(u32) <= 0x6000) && (disp_fifo.head == (disp_fifo.head & ~(VECTORSIZE - 1))) )
|
||||
{
|
||||
buffer_copy_fast<GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16)>(dst, disp_fifo.buf + disp_fifo.head);
|
||||
_DISP_FIFOrecv_LineAdvance();
|
||||
}
|
||||
else
|
||||
#endif // USEMANUALVECTORIZATION
|
||||
{
|
||||
for (size_t i = 0; i < GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16) / sizeof(u32); i++)
|
||||
{
|
||||
const u32 src = DISP_FIFOrecv_u32();
|
||||
((u32 *)dst)[i] = src;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <NDSColorFormat OUTPUTFORMAT>
|
||||
void DISP_FIFOrecv_LineOpaque(u32 *__restrict dst)
|
||||
{
|
||||
#ifdef USEMANUALVECTORIZATION
|
||||
if ( (disp_fifo.head + (GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16)) / sizeof(u32) <= 0x6000) && (disp_fifo.head == (disp_fifo.head & ~(VECTORSIZE - 1))) )
|
||||
{
|
||||
if (OUTPUTFORMAT == NDSColorFormat_BGR555_Rev)
|
||||
{
|
||||
buffer_copy_or_constant_s16_fast<GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16), false>(dst, disp_fifo.buf + disp_fifo.head, 0x8000);
|
||||
}
|
||||
else if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev)
|
||||
{
|
||||
ColorspaceConvertBuffer555xTo6665Opaque<false, false, BESwapDst>((u16 *)(disp_fifo.buf + disp_fifo.head), dst, GPU_FRAMEBUFFER_NATIVE_WIDTH);
|
||||
}
|
||||
else if (OUTPUTFORMAT == NDSColorFormat_BGR888_Rev)
|
||||
{
|
||||
ColorspaceConvertBuffer555xTo8888Opaque<false, false, BESwapDst>((u16 *)(disp_fifo.buf + disp_fifo.head), dst, GPU_FRAMEBUFFER_NATIVE_WIDTH);
|
||||
}
|
||||
|
||||
_DISP_FIFOrecv_LineAdvance();
|
||||
}
|
||||
else
|
||||
#endif // USEMANUALVECTORIZATION
|
||||
{
|
||||
if (OUTPUTFORMAT == NDSColorFormat_BGR555_Rev)
|
||||
{
|
||||
for (size_t i = 0; i < GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16) / sizeof(u32); i++)
|
||||
{
|
||||
const u32 src = DISP_FIFOrecv_u32();
|
||||
dst[i] = src | 0x80008000;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < GPU_FRAMEBUFFER_NATIVE_WIDTH; i+=2)
|
||||
{
|
||||
const u32 src = DISP_FIFOrecv_u32();
|
||||
|
||||
if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev)
|
||||
{
|
||||
dst[i+0] = LE_TO_LOCAL_32( ColorspaceConvert555To6665Opaque<false>((src >> 0) & 0x7FFF) );
|
||||
dst[i+1] = LE_TO_LOCAL_32( ColorspaceConvert555To6665Opaque<false>((src >> 16) & 0x7FFF) );
|
||||
}
|
||||
else if (OUTPUTFORMAT == NDSColorFormat_BGR888_Rev)
|
||||
{
|
||||
dst[i+0] = LE_TO_LOCAL_32( ColorspaceConvert555To8888Opaque<false>((src >> 0) & 0x7FFF) );
|
||||
dst[i+1] = LE_TO_LOCAL_32( ColorspaceConvert555To8888Opaque<false>((src >> 16) & 0x7FFF) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DISP_FIFOreset()
|
||||
{
|
||||
disp_fifo.head = 0;
|
||||
disp_fifo.tail = 0;
|
||||
}
|
||||
|
||||
template void DISP_FIFOsend< u8, 0>(const u8 val);
|
||||
template void DISP_FIFOsend< u8, 1>(const u8 val);
|
||||
template void DISP_FIFOsend< u8, 2>(const u8 val);
|
||||
template void DISP_FIFOsend< u8, 3>(const u8 val);
|
||||
template void DISP_FIFOsend<u16, 0>(const u16 val);
|
||||
template void DISP_FIFOsend<u16, 2>(const u16 val);
|
||||
template void DISP_FIFOsend<u32, 0>(const u32 val);
|
||||
|
||||
template void DISP_FIFOrecv_LineOpaque<NDSColorFormat_BGR555_Rev>(u32 *__restrict dst);
|
||||
template void DISP_FIFOrecv_LineOpaque<NDSColorFormat_BGR666_Rev>(u32 *__restrict dst);
|
||||
template void DISP_FIFOrecv_LineOpaque<NDSColorFormat_BGR888_Rev>(u32 *__restrict dst);
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
Copyright 2006 yopyop
|
||||
Copyright 2007 shash
|
||||
Copyright 2007-2022 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FIFO_H
|
||||
#define FIFO_H
|
||||
|
||||
#include "types.h"
|
||||
#include "./utils/colorspacehandler/colorspacehandler.h"
|
||||
|
||||
//=================================================== IPC FIFO
|
||||
typedef struct
|
||||
{
|
||||
u32 buf[16];
|
||||
|
||||
u8 head;
|
||||
u8 tail;
|
||||
u8 size;
|
||||
} IPC_FIFO;
|
||||
|
||||
extern IPC_FIFO ipc_fifo[2];
|
||||
extern void IPC_FIFOinit(u8 proc);
|
||||
extern void IPC_FIFOsend(u8 proc, u32 val);
|
||||
extern u32 IPC_FIFOrecv(u8 proc);
|
||||
extern void IPC_FIFOcnt(u8 proc, u16 val);
|
||||
|
||||
//=================================================== GFX FIFO
|
||||
|
||||
//yeah, its oversize for now. thats a simpler solution
|
||||
//moon seems to overdrive the fifo with immediate dmas
|
||||
//i think this might be nintendo code too
|
||||
#define HACK_GXIFO_SIZE 200000
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 cmd[HACK_GXIFO_SIZE];
|
||||
u32 param[HACK_GXIFO_SIZE];
|
||||
|
||||
u32 head; // start position
|
||||
u32 tail; // tail
|
||||
u32 size; // size FIFO buffer
|
||||
u32 matrix_stack_op_size; //number of matrix stack items in the fifo (stack is busy when this is nonzero)
|
||||
} GFX_FIFO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 cmd[4];
|
||||
u32 param[4];
|
||||
|
||||
u8 head;
|
||||
u8 tail;
|
||||
u8 size;
|
||||
} GFX_PIPE;
|
||||
|
||||
extern GFX_PIPE gxPIPE;
|
||||
extern GFX_FIFO gxFIFO;
|
||||
void GFX_PIPEclear();
|
||||
void GFX_FIFOclear();
|
||||
void GFX_FIFOsend(u8 cmd, u32 param);
|
||||
BOOL GFX_PIPErecv(u8 *cmd, u32 *param);
|
||||
void GFX_FIFOcnt(u32 val);
|
||||
|
||||
//=================================================== Display memory FIFO
|
||||
typedef struct
|
||||
{
|
||||
CACHE_ALIGN u32 buf[0x6000]; // 256x192 32K color
|
||||
u32 head; // head
|
||||
u32 tail; // tail
|
||||
} DISP_FIFO;
|
||||
|
||||
extern DISP_FIFO disp_fifo;
|
||||
void DISP_FIFOinit();
|
||||
|
||||
template<typename T, size_t ADDROFFSET> void DISP_FIFOsend(const T val);
|
||||
u32 DISP_FIFOrecv_u32();
|
||||
|
||||
void DISP_FIFOrecv_Line16(u16 *__restrict dst);
|
||||
template<NDSColorFormat OUTPUTFORMAT> void DISP_FIFOrecv_LineOpaque(u32 *__restrict dst);
|
||||
|
||||
void DISP_FIFOreset();
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
Copyright (C) 2021-2023 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GPU_OPERATIONS_H
|
||||
#define GPU_OPERATIONS_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "./utils/colorspacehandler/colorspacehandler.h"
|
||||
|
||||
#include "GPU.h"
|
||||
|
||||
|
||||
template <s32 INTEGERSCALEHINT, bool SCALEVERTICAL, bool USELINEINDEX, bool NEEDENDIANSWAP, size_t ELEMENTSIZE>
|
||||
void CopyLineExpandHinted(const void *__restrict srcBuffer, const size_t srcLineIndex,
|
||||
void *__restrict dstBuffer, const size_t dstLineIndex, const size_t dstLineWidth, const size_t dstLineCount);
|
||||
|
||||
template <s32 INTEGERSCALEHINT, bool SCALEVERTICAL, bool USELINEINDEX, bool NEEDENDIANSWAP, size_t ELEMENTSIZE>
|
||||
void CopyLineExpandHinted(const GPUEngineLineInfo &lineInfo, const void *__restrict srcBuffer, void *__restrict dstBuffer);
|
||||
|
||||
template <s32 INTEGERSCALEHINT, bool USELINEINDEX, bool NEEDENDIANSWAP, size_t ELEMENTSIZE>
|
||||
void CopyLineReduceHinted(const void *__restrict srcBuffer, const size_t srcLineIndex, const size_t srcLineWidth,
|
||||
void *__restrict dstBuffer, const size_t dstLineIndex);
|
||||
|
||||
template <s32 INTEGERSCALEHINT, bool USELINEINDEX, bool NEEDENDIANSWAP, size_t ELEMENTSIZE>
|
||||
void CopyLineReduceHinted(const GPUEngineLineInfo &lineInfo, const void *__restrict srcBuffer, void *__restrict dstBuffer);
|
||||
|
||||
class ColorOperation
|
||||
{
|
||||
public:
|
||||
ColorOperation() {};
|
||||
|
||||
FORCEINLINE u16 blend(const u16 colA, const u16 colB, const u16 blendEVA, const u16 blendEVB) const;
|
||||
FORCEINLINE u16 blend(const u16 colA, const u16 colB, const TBlendTable *blendTable) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE Color4u8 blend(const Color4u8 colA, const Color4u8 colB, const u16 blendEVA, const u16 blendEVB) const;
|
||||
|
||||
FORCEINLINE u16 blend3D(const Color4u8 colA, const u16 colB) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE Color4u8 blend3D(const Color4u8 colA, const Color4u8 colB) const;
|
||||
|
||||
FORCEINLINE u16 increase(const u16 col, const u16 blendEVY) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE Color4u8 increase(const Color4u8 col, const u16 blendEVY) const;
|
||||
|
||||
FORCEINLINE u16 decrease(const u16 col, const u16 blendEVY) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE Color4u8 decrease(const Color4u8 col, const u16 blendEVY) const;
|
||||
};
|
||||
|
||||
class PixelOperation
|
||||
{
|
||||
private:
|
||||
template<GPULayerType LAYERTYPE> FORCEINLINE void __selectedEffect(const GPUEngineCompositorInfo &compInfo, const u8 &dstLayerID, const bool enableColorEffect, const u8 spriteAlpha, const OBJMode spriteMode, ColorEffect &selectedEffect, TBlendTable **selectedBlendTable, u8 &blendEVA, u8 &blendEVB) const;
|
||||
|
||||
protected:
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copy16(GPUEngineCompositorInfo &compInfo, const u16 srcColor16) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copy32(GPUEngineCompositorInfo &compInfo, const Color4u8 srcColor32) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUp16(GPUEngineCompositorInfo &compInfo, const u16 srcColor16) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUp32(GPUEngineCompositorInfo &compInfo, const Color4u8 srcColor32) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDown16(GPUEngineCompositorInfo &compInfo, const u16 srcColor16) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDown32(GPUEngineCompositorInfo &compInfo, const Color4u8 srcColor32) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE> FORCEINLINE void _unknownEffect16(GPUEngineCompositorInfo &compInfo, const u16 srcColor16, const bool enableColorEffect, const u8 spriteAlpha, const OBJMode spriteMode) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE> FORCEINLINE void _unknownEffect32(GPUEngineCompositorInfo &compInfo, const Color4u8 srcColor32, const bool enableColorEffect, const u8 spriteAlpha, const OBJMode spriteMode) const;
|
||||
|
||||
public:
|
||||
static CACHE_ALIGN u8 BlendTable555[17][17][32][32];
|
||||
static CACHE_ALIGN u16 BrightnessUpTable555[17][0x8000];
|
||||
static CACHE_ALIGN Color4u8 BrightnessUpTable666[17][0x8000];
|
||||
static CACHE_ALIGN Color4u8 BrightnessUpTable888[17][0x8000];
|
||||
static CACHE_ALIGN u16 BrightnessDownTable555[17][0x8000];
|
||||
static CACHE_ALIGN Color4u8 BrightnessDownTable666[17][0x8000];
|
||||
static CACHE_ALIGN Color4u8 BrightnessDownTable888[17][0x8000];
|
||||
static void InitLUTs();
|
||||
|
||||
PixelOperation() {};
|
||||
|
||||
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE> FORCEINLINE void Composite16(GPUEngineCompositorInfo &compInfo, const u16 srcColor16, const bool enableColorEffect, const u8 spriteAlpha, const u8 spriteMode) const;
|
||||
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE> FORCEINLINE void Composite32(GPUEngineCompositorInfo &compInfo, Color4u8 srcColor32, const bool enableColorEffect, const u8 spriteAlpha, const u8 spriteMode) const;
|
||||
};
|
||||
|
||||
#endif // GPU_OPERATIONS_H
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
Copyright (C) 2021 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GPU_OPERATIONS_AVX2_H
|
||||
#define GPU_OPERATIONS_AVX2_H
|
||||
|
||||
#include "GPU_Operations.h"
|
||||
|
||||
#ifndef ENABLE_AVX2
|
||||
#warning This header requires AVX2 support.
|
||||
#else
|
||||
|
||||
class ColorOperation_AVX2
|
||||
{
|
||||
public:
|
||||
ColorOperation_AVX2() {};
|
||||
|
||||
FORCEINLINE v256u16 blend(const v256u16 &colA, const v256u16 &colB, const v256u16 &blendEVA, const v256u16 &blendEVB) const;
|
||||
template<NDSColorFormat COLORFORMAT, bool USECONSTANTBLENDVALUESHINT> FORCEINLINE v256u32 blend(const v256u32 &colA, const v256u32 &colB, const v256u16 &blendEVA, const v256u16 &blendEVB) const;
|
||||
|
||||
FORCEINLINE v256u16 blend3D(const v256u32 &colA_Lo, const v256u32 &colA_Hi, const v256u16 &colB) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE v256u32 blend3D(const v256u32 &colA, const v256u32 &colB) const;
|
||||
|
||||
FORCEINLINE v256u16 increase(const v256u16 &col, const v256u16 &blendEVY) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE v256u32 increase(const v256u32 &col, const v256u16 &blendEVY) const;
|
||||
|
||||
FORCEINLINE v256u16 decrease(const v256u16 &col, const v256u16 &blendEVY) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE v256u32 decrease(const v256u32 &col, const v256u16 &blendEVY) const;
|
||||
};
|
||||
|
||||
class PixelOperation_AVX2
|
||||
{
|
||||
protected:
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copy16(GPUEngineCompositorInfo &compInfo, const v256u8 &srcLayerID, const v256u16 &src1, const v256u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copy32(GPUEngineCompositorInfo &compInfo, const v256u8 &srcLayerID, const v256u32 &src3, const v256u32 &src2, const v256u32 &src1, const v256u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copyMask16(GPUEngineCompositorInfo &compInfo, const v256u8 &passMask8, const v256u8 &srcLayerID, const v256u16 &src1, const v256u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copyMask32(GPUEngineCompositorInfo &compInfo, const v256u8 &passMask8, const v256u8 &srcLayerID, const v256u32 &src3, const v256u32 &src2, const v256u32 &src1, const v256u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUp16(GPUEngineCompositorInfo &compInfo, const v256u16 &evy16, const v256u8 &srcLayerID, const v256u16 &src1, const v256u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUp32(GPUEngineCompositorInfo &compInfo, const v256u16 &evy16, const v256u8 &srcLayerID, const v256u32 &src3, const v256u32 &src2, const v256u32 &src1, const v256u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUpMask16(GPUEngineCompositorInfo &compInfo, const v256u8 &passMask8, const v256u16 &evy16, const v256u8 &srcLayerID, const v256u16 &src1, const v256u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUpMask32(GPUEngineCompositorInfo &compInfo, const v256u8 &passMask8, const v256u16 &evy16, const v256u8 &srcLayerID, const v256u32 &src3, const v256u32 &src2, const v256u32 &src1, const v256u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDown16(GPUEngineCompositorInfo &compInfo, const v256u16 &evy16, const v256u8 &srcLayerID, const v256u16 &src1, const v256u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDown32(GPUEngineCompositorInfo &compInfo, const v256u16 &evy16, const v256u8 &srcLayerID, const v256u32 &src3, const v256u32 &src2, const v256u32 &src1, const v256u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDownMask16(GPUEngineCompositorInfo &compInfo, const v256u8 &passMask8, const v256u16 &evy16, const v256u8 &srcLayerID, const v256u16 &src1, const v256u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDownMask32(GPUEngineCompositorInfo &compInfo, const v256u8 &passMask8, const v256u16 &evy16, const v256u8 &srcLayerID, const v256u32 &src3, const v256u32 &src2, const v256u32 &src1, const v256u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE>
|
||||
FORCEINLINE void _unknownEffectMask16(GPUEngineCompositorInfo &compInfo,
|
||||
const v256u8 &passMask8,
|
||||
const v256u16 &evy16,
|
||||
const v256u8 &srcLayerID,
|
||||
const v256u16 &src1, const v256u16 &src0,
|
||||
const v256u8 &srcEffectEnableMask,
|
||||
const v256u8 &dstBlendEnableMaskLUT,
|
||||
const v256u8 &enableColorEffectMask,
|
||||
const v256u8 &spriteAlpha,
|
||||
const v256u8 &spriteMode) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE>
|
||||
FORCEINLINE void _unknownEffectMask32(GPUEngineCompositorInfo &compInfo,
|
||||
const v256u8 &passMask8,
|
||||
const v256u16 &evy16,
|
||||
const v256u8 &srcLayerID,
|
||||
const v256u32 &src3, const v256u32 &src2, const v256u32 &src1, const v256u32 &src0,
|
||||
const v256u8 &srcEffectEnableMask,
|
||||
const v256u8 &dstBlendEnableMaskLUT,
|
||||
const v256u8 &enableColorEffectMask,
|
||||
const v256u8 &spriteAlpha,
|
||||
const v256u8 &spriteMode) const;
|
||||
|
||||
public:
|
||||
PixelOperation_AVX2() {};
|
||||
|
||||
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE, bool WILLPERFORMWINDOWTEST>
|
||||
FORCEINLINE void Composite16(GPUEngineCompositorInfo &compInfo,
|
||||
const bool didAllPixelsPass,
|
||||
const v256u8 &passMask8,
|
||||
const v256u16 &evy16,
|
||||
const v256u8 &srcLayerID,
|
||||
const v256u16 &src1, const v256u16 &src0,
|
||||
const v256u8 &srcEffectEnableMask,
|
||||
const v256u8 &dstBlendEnableMaskLUT,
|
||||
const u8 *__restrict enableColorEffectPtr,
|
||||
const u8 *__restrict sprAlphaPtr,
|
||||
const u8 *__restrict sprModePtr) const;
|
||||
|
||||
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE, bool WILLPERFORMWINDOWTEST>
|
||||
FORCEINLINE void Composite32(GPUEngineCompositorInfo &compInfo,
|
||||
const bool didAllPixelsPass,
|
||||
const v256u8 &passMask8,
|
||||
const v256u16 &evy16,
|
||||
const v256u8 &srcLayerID,
|
||||
const v256u32 &src3, const v256u32 &src2, const v256u32 &src1, const v256u32 &src0,
|
||||
const v256u8 &srcEffectEnableMask,
|
||||
const v256u8 &dstBlendEnableMaskLUT,
|
||||
const u8 *__restrict enableColorEffectPtr,
|
||||
const u8 *__restrict sprAlphaPtr,
|
||||
const u8 *__restrict sprModePtr) const;
|
||||
};
|
||||
|
||||
#endif // ENABLE_AVX2
|
||||
|
||||
#endif // GPU_OPERATIONS_AVX2_H
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
Copyright (C) 2025 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GPU_OPERATIONS_NEON_H
|
||||
#define GPU_OPERATIONS_NEON_H
|
||||
|
||||
#include "GPU_Operations.h"
|
||||
|
||||
#ifndef ENABLE_NEON_A64
|
||||
#warning This header requires ARM64 NEON support.
|
||||
#else
|
||||
|
||||
class ColorOperation_NEON
|
||||
{
|
||||
public:
|
||||
ColorOperation_NEON() {};
|
||||
|
||||
FORCEINLINE v128u16 blend(const v128u16 &colA, const v128u16 &colB, const v128u16 &blendEVA, const v128u16 &blendEVB) const;
|
||||
template<NDSColorFormat COLORFORMAT, bool USECONSTANTBLENDVALUESHINT> FORCEINLINE v128u32 blend(const v128u32 &colA, const v128u32 &colB, const v128u16 &blendEVA, const v128u16 &blendEVB) const;
|
||||
|
||||
FORCEINLINE v128u16 blend3D(const v128u32 &colA_Lo, const v128u32 &colA_Hi, const v128u16 &colB) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE v128u32 blend3D(const v128u32 &colA, const v128u32 &colB) const;
|
||||
|
||||
FORCEINLINE v128u16 increase(const v128u16 &col, const v128u16 &blendEVY) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE v128u32 increase(const v128u32 &col, const v128u16 &blendEVY) const;
|
||||
|
||||
FORCEINLINE v128u16 decrease(const v128u16 &col, const v128u16 &blendEVY) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE v128u32 decrease(const v128u32 &col, const v128u16 &blendEVY) const;
|
||||
};
|
||||
|
||||
class PixelOperation_NEON
|
||||
{
|
||||
protected:
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copy16(GPUEngineCompositorInfo &compInfo, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copy32(GPUEngineCompositorInfo &compInfo, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copyMask16(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copyMask32(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUp16(GPUEngineCompositorInfo &compInfo, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUp32(GPUEngineCompositorInfo &compInfo, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUpMask16(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUpMask32(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDown16(GPUEngineCompositorInfo &compInfo, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDown32(GPUEngineCompositorInfo &compInfo, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDownMask16(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDownMask32(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE>
|
||||
FORCEINLINE void _unknownEffectMask16(GPUEngineCompositorInfo &compInfo,
|
||||
const v128u8 &passMask8,
|
||||
const v128u16 &evy16,
|
||||
const v128u8 &srcLayerID,
|
||||
const v128u16 &src1, const v128u16 &src0,
|
||||
const v128u8 &srcEffectEnableMask,
|
||||
const v128u8 &dstBlendEnableMaskLUT,
|
||||
const v128u8 &enableColorEffectMask,
|
||||
const v128u8 &spriteAlpha,
|
||||
const v128u8 &spriteMode) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE>
|
||||
FORCEINLINE void _unknownEffectMask32(GPUEngineCompositorInfo &compInfo,
|
||||
const v128u8 &passMask8,
|
||||
const v128u16 &evy16,
|
||||
const v128u8 &srcLayerID,
|
||||
const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0,
|
||||
const v128u8 &srcEffectEnableMask,
|
||||
const v128u8 &dstBlendEnableMaskLUT,
|
||||
const v128u8 &enableColorEffectMask,
|
||||
const v128u8 &spriteAlpha,
|
||||
const v128u8 &spriteMode) const;
|
||||
|
||||
public:
|
||||
PixelOperation_NEON() {};
|
||||
|
||||
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE, bool WILLPERFORMWINDOWTEST>
|
||||
FORCEINLINE void Composite16(GPUEngineCompositorInfo &compInfo,
|
||||
const bool didAllPixelsPass,
|
||||
const v128u8 &passMask8,
|
||||
const v128u16 &evy16,
|
||||
const v128u8 &srcLayerID,
|
||||
const v128u16 &src1, const v128u16 &src0,
|
||||
const v128u8 &srcEffectEnableMask,
|
||||
const v128u8 &dstBlendEnableMaskLUT,
|
||||
const u8 *__restrict enableColorEffectPtr,
|
||||
const u8 *__restrict sprAlphaPtr,
|
||||
const u8 *__restrict sprModePtr) const;
|
||||
|
||||
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE, bool WILLPERFORMWINDOWTEST>
|
||||
FORCEINLINE void Composite32(GPUEngineCompositorInfo &compInfo,
|
||||
const bool didAllPixelsPass,
|
||||
const v128u8 &passMask8,
|
||||
const v128u16 &evy16,
|
||||
const v128u8 &srcLayerID,
|
||||
const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0,
|
||||
const v128u8 &srcEffectEnableMask,
|
||||
const v128u8 &dstBlendEnableMaskLUT,
|
||||
const u8 *__restrict enableColorEffectPtr,
|
||||
const u8 *__restrict sprAlphaPtr,
|
||||
const u8 *__restrict sprModePtr) const;
|
||||
};
|
||||
|
||||
#endif // ENABLE_NEON_A64
|
||||
|
||||
#endif // GPU_OPERATIONS_NEON_H
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
Copyright (C) 2021 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GPU_OPERATIONS_SSE2_H
|
||||
#define GPU_OPERATIONS_SSE2_H
|
||||
|
||||
#include "GPU_Operations.h"
|
||||
|
||||
#ifndef ENABLE_SSE2
|
||||
#warning This header requires SSE2 support.
|
||||
#else
|
||||
|
||||
class ColorOperation_SSE2
|
||||
{
|
||||
public:
|
||||
ColorOperation_SSE2() {};
|
||||
|
||||
FORCEINLINE v128u16 blend(const v128u16 &colA, const v128u16 &colB, const v128u16 &blendEVA, const v128u16 &blendEVB) const;
|
||||
template<NDSColorFormat COLORFORMAT, bool USECONSTANTBLENDVALUESHINT> FORCEINLINE v128u32 blend(const v128u32 &colA, const v128u32 &colB, const v128u16 &blendEVA, const v128u16 &blendEVB) const;
|
||||
|
||||
FORCEINLINE v128u16 blend3D(const v128u32 &colA_Lo, const v128u32 &colA_Hi, const v128u16 &colB) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE v128u32 blend3D(const v128u32 &colA, const v128u32 &colB) const;
|
||||
|
||||
FORCEINLINE v128u16 increase(const v128u16 &col, const v128u16 &blendEVY) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE v128u32 increase(const v128u32 &col, const v128u16 &blendEVY) const;
|
||||
|
||||
FORCEINLINE v128u16 decrease(const v128u16 &col, const v128u16 &blendEVY) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE v128u32 decrease(const v128u32 &col, const v128u16 &blendEVY) const;
|
||||
};
|
||||
|
||||
class PixelOperation_SSE2
|
||||
{
|
||||
protected:
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copy16(GPUEngineCompositorInfo &compInfo, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copy32(GPUEngineCompositorInfo &compInfo, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copyMask16(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copyMask32(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUp16(GPUEngineCompositorInfo &compInfo, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUp32(GPUEngineCompositorInfo &compInfo, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUpMask16(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUpMask32(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDown16(GPUEngineCompositorInfo &compInfo, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDown32(GPUEngineCompositorInfo &compInfo, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDownMask16(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDownMask32(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE>
|
||||
FORCEINLINE void _unknownEffectMask16(GPUEngineCompositorInfo &compInfo,
|
||||
const v128u8 &passMask8,
|
||||
const v128u16 &evy16,
|
||||
const v128u8 &srcLayerID,
|
||||
const v128u16 &src1, const v128u16 &src0,
|
||||
const v128u8 &srcEffectEnableMask,
|
||||
const v128u8 &dstBlendEnableMaskLUT,
|
||||
const v128u8 &enableColorEffectMask,
|
||||
const v128u8 &spriteAlpha,
|
||||
const v128u8 &spriteMode) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE>
|
||||
FORCEINLINE void _unknownEffectMask32(GPUEngineCompositorInfo &compInfo,
|
||||
const v128u8 &passMask8,
|
||||
const v128u16 &evy16,
|
||||
const v128u8 &srcLayerID,
|
||||
const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0,
|
||||
const v128u8 &srcEffectEnableMask,
|
||||
const v128u8 &dstBlendEnableMaskLUT,
|
||||
const v128u8 &enableColorEffectMask,
|
||||
const v128u8 &spriteAlpha,
|
||||
const v128u8 &spriteMode) const;
|
||||
|
||||
public:
|
||||
PixelOperation_SSE2() {};
|
||||
|
||||
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE, bool WILLPERFORMWINDOWTEST>
|
||||
FORCEINLINE void Composite16(GPUEngineCompositorInfo &compInfo,
|
||||
const bool didAllPixelsPass,
|
||||
const v128u8 &passMask8,
|
||||
const v128u16 &evy16,
|
||||
const v128u8 &srcLayerID,
|
||||
const v128u16 &src1, const v128u16 &src0,
|
||||
const v128u8 &srcEffectEnableMask,
|
||||
const v128u8 &dstBlendEnableMaskLUT,
|
||||
const u8 *__restrict enableColorEffectPtr,
|
||||
const u8 *__restrict sprAlphaPtr,
|
||||
const u8 *__restrict sprModePtr) const;
|
||||
|
||||
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE, bool WILLPERFORMWINDOWTEST>
|
||||
FORCEINLINE void Composite32(GPUEngineCompositorInfo &compInfo,
|
||||
const bool didAllPixelsPass,
|
||||
const v128u8 &passMask8,
|
||||
const v128u16 &evy16,
|
||||
const v128u8 &srcLayerID,
|
||||
const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0,
|
||||
const v128u8 &srcEffectEnableMask,
|
||||
const v128u8 &dstBlendEnableMaskLUT,
|
||||
const u8 *__restrict enableColorEffectPtr,
|
||||
const u8 *__restrict sprAlphaPtr,
|
||||
const u8 *__restrict sprModePtr) const;
|
||||
};
|
||||
|
||||
#endif // ENABLE_SSE2
|
||||
|
||||
#endif // GPU_OPERATIONS_SSE2_H
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,460 @@
|
|||
/*
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2007 shash
|
||||
Copyright (C) 2007-2017 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// this file is split from MMU.h for the purpose of avoiding ridiculous recompile times
|
||||
// when changing it, because practically everything includes MMU.h.
|
||||
#ifndef MMUTIMING_H
|
||||
#define MMUTIMING_H
|
||||
|
||||
#include <algorithm>
|
||||
#include "MMU.h"
|
||||
#include "cp15.h"
|
||||
#include "readwrite.h"
|
||||
#include "debug.h"
|
||||
#include "NDSSystem.h"
|
||||
#include "emufile.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// MEMORY TIMING ACCURACY CONFIGURATION
|
||||
//
|
||||
// the more of these are enabled,
|
||||
// the more accurate memory access timing _should_ become.
|
||||
// they should be listed roughly in order of most to least important.
|
||||
// it's reasonable to disable some of these as a speed hack.
|
||||
// obviously, these defines don't cover all the variables or features needed,
|
||||
// and in particular, DMA or code+data access bus contention is still missing.
|
||||
|
||||
//disable this to prevent the advanced timing logic from ever running at all
|
||||
#define ENABLE_ADVANCED_TIMING
|
||||
|
||||
#ifdef ENABLE_ADVANCED_TIMING
|
||||
// makes non-sequential accesses slower than sequential ones.
|
||||
#define ACCOUNT_FOR_NON_SEQUENTIAL_ACCESS
|
||||
//(SOMETIMES THIS IS A BIG SPEED HIT!)
|
||||
|
||||
// enables emulation of code fetch waits.
|
||||
#define ACCOUNT_FOR_CODE_FETCH_CYCLES
|
||||
|
||||
// makes access to DTCM (arm9 only) fast.
|
||||
#define ACCOUNT_FOR_DATA_TCM_SPEED
|
||||
|
||||
// enables simulation of cache hits and cache misses.
|
||||
#define ENABLE_CACHE_CONTROLLER_EMULATION
|
||||
|
||||
#endif //ENABLE_ADVANCED_TIMING
|
||||
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
FORCEINLINE bool USE_TIMING() {
|
||||
#ifdef ENABLE_ADVANCED_TIMING
|
||||
return CommonSettings.advanced_timing;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
enum MMU_ACCESS_DIRECTION
|
||||
{
|
||||
MMU_AD_READ, MMU_AD_WRITE
|
||||
};
|
||||
|
||||
|
||||
// note that we don't actually emulate the cache contents here,
|
||||
// only enough to guess what would be a cache hit or a cache miss.
|
||||
// this doesn't really get used unless ENABLE_CACHE_CONTROLLER_EMULATION is defined.
|
||||
template<int SIZESHIFT, int ASSOCIATIVESHIFT, int BLOCKSIZESHIFT>
|
||||
class CacheController
|
||||
{
|
||||
public:
|
||||
template<MMU_ACCESS_DIRECTION DIR>
|
||||
FORCEINLINE bool Cached(u32 addr)
|
||||
{
|
||||
u32 blockMasked = addr & BLOCKMASK;
|
||||
if(blockMasked == m_cacheCache)
|
||||
return true;
|
||||
else
|
||||
return this->CachedInternal<DIR>(addr, blockMasked);
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
for(int blockIndex = 0; blockIndex < NUMBLOCKS; blockIndex++)
|
||||
m_blocks[blockIndex].Reset();
|
||||
m_cacheCache = ~0;
|
||||
}
|
||||
CacheController()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void savestate(EMUFILE &os, int version)
|
||||
{
|
||||
os.write_32LE(m_cacheCache);
|
||||
for (int i = 0; i < NUMBLOCKS; i++)
|
||||
{
|
||||
for (int j = 0; j < ASSOCIATIVITY; j++)
|
||||
os.write_32LE(m_blocks[i].tag[j]);
|
||||
os.write_32LE(m_blocks[i].nextWay);
|
||||
}
|
||||
}
|
||||
bool loadstate(EMUFILE &is, int version)
|
||||
{
|
||||
is.read_32LE(m_cacheCache);
|
||||
for (int i = 0; i < NUMBLOCKS; i++)
|
||||
{
|
||||
for (int j = 0; j < ASSOCIATIVITY; j++)
|
||||
is.read_32LE(m_blocks[i].tag[j]);
|
||||
is.read_32LE(m_blocks[i].nextWay);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
template<MMU_ACCESS_DIRECTION DIR>
|
||||
bool CachedInternal(u32 addr, u32 blockMasked)
|
||||
{
|
||||
u32 blockIndex = blockMasked >> BLOCKSIZESHIFT;
|
||||
CacheBlock& block = m_blocks[blockIndex];
|
||||
addr &= TAGMASK;
|
||||
|
||||
for(int way = 0; way < ASSOCIATIVITY; way++)
|
||||
if(addr == block.tag[way])
|
||||
{
|
||||
// found it, already allocated
|
||||
m_cacheCache = blockMasked;
|
||||
return true;
|
||||
}
|
||||
if(DIR == MMU_AD_READ)
|
||||
{
|
||||
// TODO: support other allocation orders?
|
||||
block.tag[block.nextWay++] = addr;
|
||||
block.nextWay %= ASSOCIATIVITY;
|
||||
m_cacheCache = blockMasked;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
enum { SIZE = 1 << SIZESHIFT };
|
||||
enum { ASSOCIATIVITY = 1 << ASSOCIATIVESHIFT };
|
||||
enum { BLOCKSIZE = 1 << BLOCKSIZESHIFT };
|
||||
enum { TAGSHIFT = SIZESHIFT - ASSOCIATIVESHIFT };
|
||||
enum { TAGMASK = (u32)(~0U << TAGSHIFT) };
|
||||
enum { BLOCKMASK = ((u32)~0U >> (32 - TAGSHIFT)) & (u32)(~0U << BLOCKSIZESHIFT) };
|
||||
enum { WORDSIZE = sizeof(u32) };
|
||||
enum { WORDSPERBLOCK = (1 << BLOCKSIZESHIFT) / WORDSIZE };
|
||||
enum { DATAPERWORD = WORDSIZE * ASSOCIATIVITY };
|
||||
enum { DATAPERBLOCK = DATAPERWORD * WORDSPERBLOCK };
|
||||
enum { NUMBLOCKS = SIZE / DATAPERBLOCK };
|
||||
|
||||
struct CacheBlock
|
||||
{
|
||||
u32 tag [ASSOCIATIVITY];
|
||||
u32 nextWay;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
nextWay = 0;
|
||||
for(int way = 0; way < ASSOCIATIVITY; way++)
|
||||
tag[way] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
u32 m_cacheCache; // optimization
|
||||
|
||||
CacheBlock m_blocks [NUMBLOCKS];
|
||||
};
|
||||
|
||||
|
||||
template<int PROCNUM, MMU_ACCESS_TYPE AT, int READSIZE, MMU_ACCESS_DIRECTION DIRECTION, bool TIMING>
|
||||
FORCEINLINE u32 _MMU_accesstime(u32 addr, bool sequential);
|
||||
|
||||
|
||||
template<int PROCNUM, MMU_ACCESS_TYPE AT>
|
||||
class FetchAccessUnit
|
||||
{
|
||||
public:
|
||||
template<int READSIZE, MMU_ACCESS_DIRECTION DIRECTION, bool TIMING>
|
||||
FORCEINLINE u32 Fetch(u32 address)
|
||||
{
|
||||
#ifdef ACCOUNT_FOR_CODE_FETCH_CYCLES
|
||||
const bool prohibit = TIMING;
|
||||
#else
|
||||
const bool prohibit = false;
|
||||
#endif
|
||||
|
||||
if(AT == MMU_AT_CODE && !prohibit)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
u32 time = _MMU_accesstime<PROCNUM, AT, READSIZE, DIRECTION,TIMING>(address,
|
||||
#ifdef ACCOUNT_FOR_NON_SEQUENTIAL_ACCESS
|
||||
(TIMING?
|
||||
(address == (m_lastAddress + (READSIZE>>3)))
|
||||
:true
|
||||
)
|
||||
#else
|
||||
true
|
||||
#endif
|
||||
);
|
||||
|
||||
#ifdef ACCOUNT_FOR_NON_SEQUENTIAL_ACCESS
|
||||
m_lastAddress = address;
|
||||
#endif
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
m_lastAddress = ~0;
|
||||
}
|
||||
FetchAccessUnit() { this->Reset(); }
|
||||
|
||||
void savestate(EMUFILE &os, int version)
|
||||
{
|
||||
os.write_32LE(m_lastAddress);
|
||||
}
|
||||
bool loadstate(EMUFILE &is, int version)
|
||||
{
|
||||
is.read_32LE(m_lastAddress);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
u32 m_lastAddress;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct MMU_struct_timing
|
||||
{
|
||||
// technically part of the cp15, but I didn't want the dereferencing penalty.
|
||||
// these template values correspond with the value of armcp15->cacheType.
|
||||
CacheController<13,2,5> arm9codeCache; // 8192 bytes, 4-way associative, 32-byte blocks
|
||||
CacheController<12,2,5> arm9dataCache; // 4096 bytes, 4-way associative, 32-byte blocks
|
||||
|
||||
// technically part of armcpu_t, but that struct isn't templated on PROCNUM
|
||||
FetchAccessUnit<0,MMU_AT_CODE> arm9codeFetch;
|
||||
FetchAccessUnit<0,MMU_AT_DATA> arm9dataFetch;
|
||||
FetchAccessUnit<1,MMU_AT_CODE> arm7codeFetch;
|
||||
FetchAccessUnit<1,MMU_AT_DATA> arm7dataFetch;
|
||||
|
||||
template<int PROCNUM> FORCEINLINE FetchAccessUnit<PROCNUM,MMU_AT_CODE>& armCodeFetch();
|
||||
template<int PROCNUM> FORCEINLINE FetchAccessUnit<PROCNUM,MMU_AT_DATA>& armDataFetch();
|
||||
};
|
||||
template<> FORCEINLINE FetchAccessUnit<0,MMU_AT_CODE>& MMU_struct_timing::armCodeFetch<0>() { return this->arm9codeFetch; }
|
||||
template<> FORCEINLINE FetchAccessUnit<1,MMU_AT_CODE>& MMU_struct_timing::armCodeFetch<1>() { return this->arm7codeFetch; }
|
||||
template<> FORCEINLINE FetchAccessUnit<0,MMU_AT_DATA>& MMU_struct_timing::armDataFetch<0>() { return this->arm9dataFetch; }
|
||||
template<> FORCEINLINE FetchAccessUnit<1,MMU_AT_DATA>& MMU_struct_timing::armDataFetch<1>() { return this->arm7dataFetch; }
|
||||
|
||||
|
||||
extern MMU_struct_timing MMU_timing;
|
||||
|
||||
|
||||
|
||||
// calculates the time a single memory access takes,
|
||||
// in units of cycles of the current processor.
|
||||
// this function replaces what used to be MMU_WAIT16 and MMU_WAIT32.
|
||||
// this may have side effects, so don't call it more than necessary.
|
||||
template<int PROCNUM, MMU_ACCESS_TYPE AT, int READSIZE, MMU_ACCESS_DIRECTION DIRECTION, bool TIMING>
|
||||
FORCEINLINE u32 _MMU_accesstime(u32 addr, bool sequential)
|
||||
{
|
||||
static const int MC = 1; // cached or tcm memory speed
|
||||
static const int M32 = (PROCNUM==ARMCPU_ARM9) ? 2 : 1; // access through 32-bit bus
|
||||
static const int M16 = M32 * ((READSIZE>16) ? 2 : 1); // access through 16-bit bus
|
||||
static const int MSLW = M16 * 8; // this needs tuning
|
||||
|
||||
if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_CODE && addr < 0x02000000)
|
||||
return MC; // ITCM
|
||||
|
||||
#ifdef ACCOUNT_FOR_DATA_TCM_SPEED
|
||||
if(TIMING && PROCNUM==ARMCPU_ARM9 && AT==MMU_AT_DATA && (addr&(~0x3FFF)) == MMU.DTCMRegion)
|
||||
return MC; // DTCM
|
||||
#endif
|
||||
|
||||
// for now, assume the cache is always enabled for all of main memory
|
||||
if(AT != MMU_AT_DMA && TIMING && PROCNUM==ARMCPU_ARM9 && (addr & 0x0F000000) == 0x02000000)
|
||||
{
|
||||
#ifdef ENABLE_CACHE_CONTROLLER_EMULATION
|
||||
bool cached = false;
|
||||
if(AT==MMU_AT_CODE)
|
||||
cached = MMU_timing.arm9codeCache.Cached<DIRECTION>(addr);
|
||||
if(AT==MMU_AT_DATA)
|
||||
cached = MMU_timing.arm9dataCache.Cached<DIRECTION>(addr);
|
||||
if(cached)
|
||||
return MC;
|
||||
u32 c;
|
||||
if(sequential && AT==MMU_AT_DATA)
|
||||
c = M16; // bonus for sequential data access
|
||||
else if(DIRECTION == MMU_AD_READ)
|
||||
c = M16 * 5;
|
||||
else
|
||||
c = M16 * 2; // should be 4, but write buffer isn't emulated yet.
|
||||
if(DIRECTION == MMU_AD_READ)
|
||||
{
|
||||
// cache miss while reading means it has to fill a whole cache line
|
||||
// by reading 32 bytes...
|
||||
c += 8 * M32*2;
|
||||
}
|
||||
|
||||
if(CheckDebugEvent(DEBUG_EVENT_CACHE_MISS))
|
||||
{
|
||||
DebugEventData.addr = addr;
|
||||
DebugEventData.size = READSIZE;
|
||||
HandleDebugEvent(DEBUG_EVENT_CACHE_MISS);
|
||||
}
|
||||
|
||||
return c;
|
||||
#elif defined(ACCOUNT_FOR_NON_SEQUENTIAL_ACCESS)
|
||||
// this is the closest approximation I could find
|
||||
// to the with-cache-controller timing
|
||||
// that doesn't do any actual caching logic.
|
||||
return sequential ? MC : M16;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const TWaitState MMU_WAIT[16*16] = {
|
||||
// ITCM, ITCM, MAIN, SWI, REG, VMEM, LCD, OAM, ROM, ROM, RAM, U, U, U, U, BIOS
|
||||
#define X MC, MC, M16, M32, M32, M16, M16, M32, MSLW, MSLW, MSLW, M32,M32,M32,M32, M32,
|
||||
// duplicate it 16 times (this was somehow faster than using a mask of 0xF)
|
||||
X X X X X X X X X X X X X X X X
|
||||
#undef X
|
||||
};
|
||||
|
||||
u32 c = MMU_WAIT[(addr >> 24)];
|
||||
|
||||
#ifdef ACCOUNT_FOR_NON_SEQUENTIAL_ACCESS
|
||||
if(TIMING && !sequential)
|
||||
{
|
||||
//if(c != MC || PROCNUM==ARMCPU_ARM7) // check not needed anymore because ITCM/DTCM return earlier
|
||||
{
|
||||
c += (PROCNUM==ARMCPU_ARM9) ? 3*2 : 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// calculates the cycle time of a single memory access in the MEM stage.
|
||||
// to be used to calculate the memCycles argument for MMU_aluMemCycles.
|
||||
// this may have side effects, so don't call it more than necessary.
|
||||
template<int PROCNUM, int READSIZE, MMU_ACCESS_DIRECTION DIRECTION, bool TIMING>
|
||||
FORCEINLINE u32 MMU_memAccessCycles(u32 addr)
|
||||
{
|
||||
if(TIMING)
|
||||
return MMU_timing.armDataFetch<PROCNUM>().template Fetch<READSIZE,DIRECTION,true>((addr)&(~((READSIZE>>3)-1)));
|
||||
else
|
||||
return MMU_timing.armDataFetch<PROCNUM>().template Fetch<READSIZE,DIRECTION,false>((addr)&(~((READSIZE>>3)-1)));
|
||||
}
|
||||
|
||||
template<int PROCNUM, int READSIZE, MMU_ACCESS_DIRECTION DIRECTION>
|
||||
FORCEINLINE u32 MMU_memAccessCycles(u32 addr)
|
||||
{
|
||||
if(USE_TIMING())
|
||||
return MMU_memAccessCycles<PROCNUM,READSIZE,DIRECTION,true>(addr);
|
||||
else
|
||||
return MMU_memAccessCycles<PROCNUM,READSIZE,DIRECTION,false>(addr);
|
||||
}
|
||||
|
||||
// calculates the cycle time of a single code fetch in the FETCH stage
|
||||
// to be used to calculate the fetchCycles argument for MMU_fetchExecuteCycles.
|
||||
// this may have side effects, so don't call it more than necessary.
|
||||
template<int PROCNUM, int READSIZE>
|
||||
FORCEINLINE u32 MMU_codeFetchCycles(u32 addr)
|
||||
{
|
||||
if(USE_TIMING())
|
||||
return MMU_timing.armCodeFetch<PROCNUM>().template Fetch<READSIZE,MMU_AD_READ,true>((addr)&(~((READSIZE>>3)-1)));
|
||||
else
|
||||
return MMU_timing.armCodeFetch<PROCNUM>().template Fetch<READSIZE,MMU_AD_READ,false>((addr)&(~((READSIZE>>3)-1)));
|
||||
}
|
||||
|
||||
// calculates the cycle contribution of ALU + MEM stages (= EXECUTE)
|
||||
// given ALU cycle time and the summation of multiple memory access cycle times.
|
||||
// this function might belong more in armcpu, but I don't think it matters.
|
||||
template<int PROCNUM>
|
||||
FORCEINLINE u32 MMU_aluMemCycles(u32 aluCycles, u32 memCycles)
|
||||
{
|
||||
if(PROCNUM==ARMCPU_ARM9)
|
||||
{
|
||||
// ALU and MEM are different stages of the 5-stage pipeline.
|
||||
// we approximate the pipeline throughput using max,
|
||||
// since simply adding the cycles of each instruction together
|
||||
// fails to take into account the parallelism of the arm pipeline
|
||||
// and would make the emulated system unnaturally slow.
|
||||
return std::max(aluCycles, memCycles);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ALU and MEM are part of the same stage of the 3-stage pipeline,
|
||||
// thus they occur in sequence and we can simply add the counts together.
|
||||
return aluCycles + memCycles;
|
||||
}
|
||||
}
|
||||
|
||||
// calculates the cycle contribution of ALU + MEM stages (= EXECUTE)
|
||||
// given ALU cycle time and the description of a single memory access.
|
||||
// this may have side effects, so don't call it more than necessary.
|
||||
template<int PROCNUM, int READSIZE, MMU_ACCESS_DIRECTION DIRECTION>
|
||||
FORCEINLINE u32 MMU_aluMemAccessCycles(u32 aluCycles, u32 addr)
|
||||
{
|
||||
u32 memCycles;
|
||||
if(USE_TIMING())
|
||||
memCycles = MMU_memAccessCycles<PROCNUM,READSIZE,DIRECTION,true>(addr);
|
||||
else memCycles = MMU_memAccessCycles<PROCNUM,READSIZE,DIRECTION,false>(addr);
|
||||
return MMU_aluMemCycles<PROCNUM>(aluCycles, memCycles);
|
||||
}
|
||||
|
||||
// calculates the cycle contribution of FETCH + EXECUTE stages
|
||||
// given executeCycles = the combined ALU+MEM cycles
|
||||
// and fetchCycles = the cycle time of the FETCH stage
|
||||
// this function might belong more in armcpu, but I don't think it matters.
|
||||
template<int PROCNUM>
|
||||
FORCEINLINE u32 MMU_fetchExecuteCycles(u32 executeCycles, u32 fetchCycles)
|
||||
{
|
||||
#ifdef ACCOUNT_FOR_CODE_FETCH_CYCLES
|
||||
const bool allow = true;
|
||||
#else
|
||||
const bool allow = false;
|
||||
#endif
|
||||
|
||||
if(USE_TIMING() && allow)
|
||||
{
|
||||
// execute and fetch are different stages of the pipeline for both arm7 and arm9.
|
||||
// again, we approximate the pipeline throughput using max.
|
||||
return std::max(executeCycles, fetchCycles);
|
||||
// TODO: add an option to support conflict between MEM and FETCH cycles
|
||||
// if they're both using the same data bus.
|
||||
// in the case of a conflict this should be:
|
||||
// return std::max(aluCycles, memCycles + fetchCycles);
|
||||
}
|
||||
return executeCycles;
|
||||
}
|
||||
|
||||
|
||||
#endif //MMUTIMING_H
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,702 @@
|
|||
/*
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2008-2022 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NDSSYSTEM_H
|
||||
#define NDSSYSTEM_H
|
||||
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "types.h"
|
||||
#include "ROMReader.h"
|
||||
#include "firmware.h"
|
||||
|
||||
class CFIRMWARE;
|
||||
class EMUFILE;
|
||||
|
||||
template<typename Type>
|
||||
struct buttonstruct {
|
||||
union {
|
||||
struct {
|
||||
// changing the order of these fields would break stuff
|
||||
//fRLDUTSBAYXWEg
|
||||
Type G; // debug
|
||||
Type E; // right shoulder
|
||||
Type W; // left shoulder
|
||||
Type X;
|
||||
Type Y;
|
||||
Type A;
|
||||
Type B;
|
||||
Type S; // start
|
||||
Type T; // select
|
||||
Type U; // up
|
||||
Type D; // down
|
||||
Type L; // left
|
||||
Type R; // right
|
||||
Type F; // lid
|
||||
};
|
||||
Type array[14];
|
||||
};
|
||||
};
|
||||
|
||||
extern buttonstruct<bool> Turbo;
|
||||
extern buttonstruct<u32> TurboTime;
|
||||
extern buttonstruct<bool> AutoHold;
|
||||
extern volatile bool execute;
|
||||
extern BOOL click;
|
||||
|
||||
/*
|
||||
* The firmware language values
|
||||
*/
|
||||
#define NDS_FW_LANG_JAP 0
|
||||
#define NDS_FW_LANG_ENG 1
|
||||
#define NDS_FW_LANG_FRE 2
|
||||
#define NDS_FW_LANG_GER 3
|
||||
#define NDS_FW_LANG_ITA 4
|
||||
#define NDS_FW_LANG_SPA 5
|
||||
#define NDS_FW_LANG_CHI 6
|
||||
#define NDS_FW_LANG_RES 7
|
||||
|
||||
extern CFIRMWARE *extFirmwareObj;
|
||||
|
||||
#define DSGBA_LOADER_SIZE 512
|
||||
enum
|
||||
{
|
||||
ROM_NDS = 0,
|
||||
ROM_DSGBA
|
||||
};
|
||||
|
||||
enum EmuHaltReasonCode
|
||||
{
|
||||
EMUHALT_REASON_USER_REQUESTED_HALT = 0,
|
||||
|
||||
EMUHALT_REASON_SYSTEM_POWERED_OFF = 1000,
|
||||
|
||||
EMUHALT_REASON_JIT_UNMAPPED_ADDRESS_EXCEPTION = 2000,
|
||||
EMUHALT_REASON_ARM_RESERVED_0X14_EXCEPTION,
|
||||
EMUHALT_REASON_ARM_UNDEFINED_INSTRUCTION_EXCEPTION,
|
||||
|
||||
EMUHALT_REASON_UNKNOWN = 10000
|
||||
};
|
||||
|
||||
enum NDSErrorCode
|
||||
{
|
||||
NDSError_NoError = 0,
|
||||
|
||||
NDSError_SystemPoweredOff = 1000,
|
||||
|
||||
NDSError_JITUnmappedAddressException = 2000,
|
||||
NDSError_ARMUndefinedInstructionException,
|
||||
|
||||
NDSError_UnknownError = 10000
|
||||
};
|
||||
|
||||
enum NDSErrorTag
|
||||
{
|
||||
NDSErrorTag_None = 0,
|
||||
NDSErrorTag_ARM9 = 1,
|
||||
NDSErrorTag_ARM7 = 2,
|
||||
NDSErrorTag_BothCPUs = 3,
|
||||
};
|
||||
|
||||
struct NDSError
|
||||
{
|
||||
NDSErrorCode code;
|
||||
NDSErrorTag tag;
|
||||
u32 programCounterARM9;
|
||||
u32 instructionARM9;
|
||||
u32 instructionAddrARM9;
|
||||
u32 programCounterARM7;
|
||||
u32 instructionARM7;
|
||||
u32 instructionAddrARM7;
|
||||
};
|
||||
typedef struct NDSError NDSError;
|
||||
|
||||
//#define LOG_ARM9
|
||||
//#define LOG_ARM7
|
||||
|
||||
#include "PACKED.h"
|
||||
struct NDS_header
|
||||
{
|
||||
char gameTile[12]; // 000 - Game Title (uppercase ASCII, padded with 00h)
|
||||
char gameCode[4]; // 00C - Gamecode (uppercase ASCII, NTR-<code>, 0=homebrew)
|
||||
u16 makerCode; // 010 - Makercode (uppercase ASCII, 0=homebrew)
|
||||
u8 unitCode; // 012 - Unitcode (00h=Nintendo DS)
|
||||
u8 deviceCode; // 013 - Encryption Seed Select (00..07h, usually 00h)
|
||||
u8 cardSize; // 014 - Devicecapacity (Chipsize = 128KB SHL nn) (eg. 7 = 16MB)
|
||||
u8 reserved1[8]; // 015 - Must be set to 0x00
|
||||
u8 region; // 01D - Specific region: 0x80 - China, 0x40 - Korea, 0x00 - Other
|
||||
u8 romversion; // 01E - ROM Version (usually 00h)
|
||||
u8 autostart; // 01F - Autostart (Bit2: Skip "Press Button" after Health and Safety)
|
||||
// (Also skips bootmenu, even in Manual mode & even Start pressed)
|
||||
u32 ARM9src; // 020 - ARM9 rom_offset (4000h and up, align 1000h)
|
||||
u32 ARM9exe; // 024 - ARM9 entry_address (2000000h..23BFE00h)
|
||||
u32 ARM9cpy; // 028 - ARM9 ram_address (2000000h..23BFE00h)
|
||||
u32 ARM9binSize; // 02C - ARM9 size (max 3BFE00h) (3839.5KB)
|
||||
|
||||
u32 ARM7src; // 030 - ARM7 rom_offset (8000h and up)
|
||||
u32 ARM7exe; // 034 - ARM7 entry_address (2000000h..23BFE00h, or 37F8000h..3807E00h)
|
||||
u32 ARM7cpy; // 038 - ARM7 ram_address (2000000h..23BFE00h, or 37F8000h..3807E00h)
|
||||
u32 ARM7binSize; // 03C - ARM7 size (max 3BFE00h, or FE00h) (3839.5KB, 63.5KB)
|
||||
|
||||
u32 FNameTblOff; // 040 - File Name Table (FNT) offset
|
||||
u32 FNameTblSize; // 044 - File Name Table (FNT) size
|
||||
|
||||
u32 FATOff; // 048 - File Allocation Table (FAT) offset
|
||||
u32 FATSize; // 04C - File Allocation Table (FAT) size
|
||||
|
||||
u32 ARM9OverlayOff; // 050 - File ARM9 overlay_offset
|
||||
u32 ARM9OverlaySize; // 054 - File ARM9 overlay_size
|
||||
u32 ARM7OverlayOff; // 058 - File ARM7 overlay_offset
|
||||
u32 ARM7OverlaySize; // 05C - File ARM7 overlay_size
|
||||
|
||||
u32 normalCmd; // 060 - Port 40001A4h setting for normal commands (usually 00586000h)
|
||||
u32 Key1Cmd; // 064 - Port 40001A4h setting for KEY1 commands (usually 001808F8h)
|
||||
|
||||
u32 IconOff; // 068 - Icon_title_offset (0=None) (8000h and up)
|
||||
u16 CRC16; // 06C - Secure Area Checksum, CRC-16 of [ [20h]..7FFFh] - Calculations with this algorithm use 0xffff as the initial value
|
||||
u16 ROMtimeout; // 06E - Secure Area Loading Timeout (usually 051Eh)
|
||||
u32 ARM9autoload; // 070 - ARM9 Auto Load List RAM Address
|
||||
u32 ARM7autoload; // 074 - ARM7 Auto Load List RAM Address
|
||||
|
||||
u8 infoResevedRegion[8]; // 078 - ROM Information Reserved Region (must be set to 0x00)
|
||||
u32 endROMoffset; // 080 - Total Used ROM size (remaining/unused bytes usually FFh-padded)
|
||||
u32 HeaderSize; // 084 - ROM Header Size (4000h)
|
||||
u32 ARM9module; // 088 - ARM9 Module Parameter Address (auto-load parameters)
|
||||
u32 ARM7module; // 08C - ARM7 Module Parameter Address (auto-load parameters)
|
||||
u8 reserved2[48]; // 090 - Must be set to 0x00 - "PASS" is contained within here?
|
||||
u8 logo[156]; // 0C0 - Nintendo Logo (compressed bitmap, same as in GBA Headers)
|
||||
u16 logoCRC16; // 15C - Nintendo Logo Checksum, CRC-16 of [0C0h-15Bh], fixed CF56h
|
||||
u16 headerCRC16; // 15E - Header Checksum, CRC-16 of [000h-15Dh]
|
||||
u8 reserved[160]; // Must be set to 0x00
|
||||
};
|
||||
#include "PACKED_END.h"
|
||||
|
||||
extern void debug();
|
||||
NDSError NDS_GetLastError();
|
||||
void emu_halt(EmuHaltReasonCode reasonCode, NDSErrorTag errorTag);
|
||||
|
||||
extern u64 nds_timer;
|
||||
void NDS_Reschedule();
|
||||
void NDS_RescheduleGXFIFO(u32 cost);
|
||||
void NDS_RescheduleDMA();
|
||||
void NDS_RescheduleReadSlot1(int procnum, int size);
|
||||
void NDS_RescheduleTimers();
|
||||
|
||||
enum ENSATA_HANDSHAKE
|
||||
{
|
||||
ENSATA_HANDSHAKE_none = 0,
|
||||
ENSATA_HANDSHAKE_query = 1,
|
||||
ENSATA_HANDSHAKE_ack = 2,
|
||||
ENSATA_HANDSHAKE_confirm = 3,
|
||||
ENSATA_HANDSHAKE_complete = 4
|
||||
};
|
||||
|
||||
enum NDS_CONSOLE_TYPE
|
||||
{
|
||||
NDS_CONSOLE_TYPE_FAT = 0xFF,
|
||||
NDS_CONSOLE_TYPE_LITE = 0x20,
|
||||
NDS_CONSOLE_TYPE_IQUE = 0x43,
|
||||
NDS_CONSOLE_TYPE_IQUE_LITE = 0x63,
|
||||
NDS_CONSOLE_TYPE_DSI = 0xFE
|
||||
};
|
||||
|
||||
struct NDSSystem
|
||||
{
|
||||
s32 wifiCycle;
|
||||
s32 cycles;
|
||||
u64 timerCycle[2][4];
|
||||
u32 VCount;
|
||||
u32 old;
|
||||
u8 overclock;
|
||||
|
||||
//raw adc touch coords for old NDS
|
||||
u16 adc_touchX;
|
||||
u16 adc_touchY;
|
||||
s32 adc_jitterctr;
|
||||
|
||||
//the DSI returns calibrated touch coords from its TSC (?), so we need to save these separately
|
||||
u16 scr_touchX;
|
||||
u16 scr_touchY;
|
||||
|
||||
//whether the console is using our faked-bootup process
|
||||
BOOL isFakeBooted;
|
||||
|
||||
BOOL isTouch;
|
||||
|
||||
u16 paddle;
|
||||
|
||||
u8 *FW_ARM9BootCode;
|
||||
u8 *FW_ARM7BootCode;
|
||||
u32 FW_ARM9BootCodeAddr;
|
||||
u32 FW_ARM7BootCodeAddr;
|
||||
u32 FW_ARM9BootCodeSize;
|
||||
u32 FW_ARM7BootCodeSize;
|
||||
|
||||
BOOL sleeping;
|
||||
BOOL cardEjected;
|
||||
u32 freezeBus;
|
||||
|
||||
//this is not essential NDS runtime state.
|
||||
//it was perhaps a mistake to put it here.
|
||||
//it is far less important than the above.
|
||||
//maybe I should move it.
|
||||
s32 idleCycles[2];
|
||||
s32 runCycleCollector[2][16];
|
||||
s32 idleFrameCounter;
|
||||
s32 cpuloopIterationCount; //counts the number of times during a frame that a reschedule happened
|
||||
|
||||
//console type must be copied in when the system boots. it can't be changed on the fly.
|
||||
int ConsoleType;
|
||||
bool Is_DSI() { return ConsoleType == NDS_CONSOLE_TYPE_DSI; }
|
||||
bool Is_DebugConsole() { return _DebugConsole!=0; }
|
||||
BOOL _DebugConsole;
|
||||
|
||||
//set if the user requests ensata emulation
|
||||
BOOL ensataEmulation;
|
||||
|
||||
//there is a hack in the ipc sync for ensata. this tracks its state
|
||||
u32 ensataIpcSyncCounter;
|
||||
|
||||
//maintains the state of the ensata handshaking protocol
|
||||
u32 ensataHandshake;
|
||||
|
||||
struct {
|
||||
u8 lcd, gpuMain, gfx3d_render, gfx3d_geometry, gpuSub, dispswap;
|
||||
} power1; //POWCNT1
|
||||
|
||||
struct {
|
||||
u8 speakers, wifi /*(initial value=0)*/;
|
||||
} power2; //POWCNT2
|
||||
|
||||
BOOL power_render, power_geometry;
|
||||
|
||||
bool isInVblank() const { return VCount >= 192; }
|
||||
bool isIn3dVblank() const { return VCount >= 192 && VCount<215; }
|
||||
};
|
||||
|
||||
extern NDSSystem nds;
|
||||
|
||||
int NDS_Init();
|
||||
|
||||
void Desmume_InitOnce();
|
||||
|
||||
void NDS_DeInit(void);
|
||||
|
||||
BOOL NDS_SetROM(u8 * rom, u32 mask);
|
||||
NDS_header * NDS_getROMHeader(void);
|
||||
|
||||
struct RomBanner
|
||||
{
|
||||
RomBanner(bool defaultInit = true);
|
||||
u16 version; //Version (0001h)
|
||||
u16 crc16; //CRC16 across entries 020h..83Fh
|
||||
u8 reserved[0x1C]; //Reserved (zero-filled)
|
||||
u8 bitmap[0x200]; //Icon Bitmap (32x32 pix) (4x4 tiles, each 4x8 bytes, 4bit depth)
|
||||
u16 palette[0x10]; //Icon Palette (16 colors, 16bit, range 0000h-7FFFh) (Color 0 is transparent, so the 1st palette entry is ignored)
|
||||
enum { NUM_TITLES = 6 };
|
||||
union {
|
||||
struct {
|
||||
u16 title_jp[0x80]; //Title 0 Japanese (128 characters, 16bit Unicode)
|
||||
u16 title_en[0x80]; //Title 1 English ("")
|
||||
u16 title_fr[0x80]; //Title 2 French ("")
|
||||
u16 title_de[0x80]; //Title 3 German ("")
|
||||
u16 title_it[0x80]; //Title 4 Italian ("")
|
||||
u16 title_es[0x80]; //Title 5 Spanish ("")
|
||||
};
|
||||
u16 titles[NUM_TITLES][0x80];
|
||||
};
|
||||
u8 end0xFF[0x1C0];
|
||||
//840h ? (Maybe newer/chinese firmware do also support chinese title?)
|
||||
//840h - End of Icon/Title structure (next 1C0h bytes usually FFh-filled)
|
||||
};
|
||||
|
||||
struct GameInfo
|
||||
{
|
||||
void *fROM;
|
||||
ROMReader_struct *reader;
|
||||
u8 *romdataForReader;
|
||||
u32 romsize;
|
||||
u32 cardSize;
|
||||
u32 mask;
|
||||
u32 crc;
|
||||
u32 crcForCheatsDb;
|
||||
u32 chipID;
|
||||
u32 romType;
|
||||
u32 headerOffset;
|
||||
char ROMserial[20];
|
||||
char ROMname[13];
|
||||
bool _isDSiEnhanced;
|
||||
NDS_header header;
|
||||
//a copy of the pristine secure area from the rom
|
||||
u8 secureArea[0x4000];
|
||||
RomBanner banner;
|
||||
const RomBanner& getRomBanner();
|
||||
|
||||
GameInfo() : fROM(NULL),
|
||||
romdataForReader(NULL),
|
||||
crc(0),
|
||||
chipID(0x00000FC2),
|
||||
romsize(0),
|
||||
cardSize(0),
|
||||
mask(0),
|
||||
romType(ROM_NDS),
|
||||
headerOffset(0),
|
||||
_isDSiEnhanced(false)
|
||||
{
|
||||
memset(&header, 0, sizeof(header));
|
||||
memset(&ROMserial[0], 0, sizeof(ROMserial));
|
||||
memset(&ROMname[0], 0, sizeof(ROMname));
|
||||
}
|
||||
|
||||
~GameInfo() { closeROM(); }
|
||||
|
||||
bool IsCode(const char* code) const;
|
||||
|
||||
bool loadROM(std::string fname, u32 type = ROM_NDS);
|
||||
void closeROM();
|
||||
u32 readROM(u32 pos);
|
||||
bool ValidateHeader();
|
||||
void populate();
|
||||
bool isDSiEnhanced();
|
||||
bool isHomebrew();
|
||||
bool hasRomBanner();
|
||||
|
||||
};
|
||||
|
||||
typedef struct TSCalInfo
|
||||
{
|
||||
struct
|
||||
{
|
||||
u16 x1, x2;
|
||||
u16 y1, y2;
|
||||
u16 width;
|
||||
u16 height;
|
||||
} adc;
|
||||
|
||||
struct
|
||||
{
|
||||
u8 x1, x2;
|
||||
u8 y1, y2;
|
||||
u16 width;
|
||||
u16 height;
|
||||
} scr;
|
||||
|
||||
} TSCalInfo;
|
||||
|
||||
extern GameInfo gameInfo;
|
||||
|
||||
extern std::vector<u32> memReadBreakPoints;
|
||||
extern std::vector<u32> memWriteBreakPoints;
|
||||
|
||||
|
||||
struct UserButtons : buttonstruct<bool>
|
||||
{
|
||||
};
|
||||
struct UserTouch
|
||||
{
|
||||
u16 touchX;
|
||||
u16 touchY;
|
||||
bool isTouch;
|
||||
};
|
||||
struct UserMicrophone
|
||||
{
|
||||
u32 micButtonPressed;
|
||||
u8 micSample;
|
||||
};
|
||||
struct UserInput
|
||||
{
|
||||
UserButtons buttons;
|
||||
UserTouch touch;
|
||||
UserMicrophone mic;
|
||||
};
|
||||
|
||||
// set physical user input
|
||||
// these functions merely request the input to be changed.
|
||||
// the actual change happens later at a specific time during the frame.
|
||||
// this is to minimize the risk of desyncs.
|
||||
void NDS_setTouchPos(u16 x, u16 y);
|
||||
void NDS_releaseTouch(void);
|
||||
void NDS_setPad(bool right,bool left,bool down,bool up,bool select,bool start,bool B,bool A,bool Y,bool X,bool leftShoulder,bool rightShoulder,bool debug, bool lid);
|
||||
void NDS_setMic(bool pressed);
|
||||
|
||||
// get physical user input
|
||||
// not including the results of autofire/etc.
|
||||
// the effects of calls to "set physical user input" functions will be immediately reflected here though.
|
||||
const UserInput& NDS_getRawUserInput();
|
||||
const UserInput& NDS_getPrevRawUserInput();
|
||||
|
||||
// get final (fully processed) user input
|
||||
// this should match whatever was or would be sent to the game
|
||||
const UserInput& NDS_getFinalUserInput();
|
||||
|
||||
// set/get to-be-processed or in-the-middle-of-being-processed user input
|
||||
// to process input, simply call this function and edit the return value.
|
||||
// (applying autofire is one example of processing the input.)
|
||||
// (movie playback is another example.)
|
||||
// this must be done after the raw user input is set
|
||||
// and before that input is sent to the game's memory.
|
||||
UserInput& NDS_getProcessingUserInput();
|
||||
bool NDS_isProcessingUserInput();
|
||||
// call once per frame to prepare input for processing
|
||||
void NDS_beginProcessingInput();
|
||||
// call once per frame to copy the processed input to the final input
|
||||
void NDS_endProcessingInput();
|
||||
|
||||
// this is in case something needs reentrancy while processing input
|
||||
void NDS_suspendProcessingInput(bool suspend);
|
||||
|
||||
|
||||
|
||||
int NDS_LoadROM(const char *filename, const char* physicalFilename=0, const char* logicalFilename=0);
|
||||
void NDS_FreeROM(void);
|
||||
void NDS_Reset();
|
||||
|
||||
bool NDS_LegitBoot();
|
||||
bool NDS_FakeBoot();
|
||||
|
||||
void nds_savestate(EMUFILE &os);
|
||||
bool nds_loadstate(EMUFILE &is, int size);
|
||||
|
||||
void NDS_Sleep();
|
||||
void NDS_TriggerCardEjectIRQ();
|
||||
|
||||
void NDS_SkipNextFrame();
|
||||
#define NDS_SkipFrame(s) if(s) NDS_SkipNext2DFrame();
|
||||
void NDS_OmitFrameSkip(int force=0);
|
||||
|
||||
void NDS_debug_break();
|
||||
void NDS_debug_continue();
|
||||
void NDS_debug_step();
|
||||
|
||||
int NDS_GetCPUCoreCount();
|
||||
void NDS_GetCPULoadAverage(u32 &outLoadAvgARM9, u32 &outLoadAvgARM7);
|
||||
void NDS_SetupDefaultFirmware();
|
||||
|
||||
//void execHardware_doAllDma(EDMAMode modeNum);
|
||||
|
||||
template<bool FORCE> void NDS_exec(s32 nb = 560190<<1);
|
||||
|
||||
extern int lagframecounter;
|
||||
|
||||
extern struct TCommonSettings
|
||||
{
|
||||
TCommonSettings()
|
||||
: GFX3D_HighResolutionInterpolateColor(true)
|
||||
, GFX3D_EdgeMark(true)
|
||||
, GFX3D_Fog(true)
|
||||
, GFX3D_Texture(true)
|
||||
, GFX3D_LineHack(true)
|
||||
, GFX3D_Renderer_MultisampleSize(0)
|
||||
, GFX3D_Renderer_TextureScalingFactor(1) // Possible values: 1, 2, 4
|
||||
, GFX3D_Renderer_TextureDeposterize(false)
|
||||
, GFX3D_Renderer_TextureSmoothing(false)
|
||||
, GFX3D_TXTHack(false)
|
||||
, OpenGL_Emulation_ShadowPolygon(true)
|
||||
, OpenGL_Emulation_SpecialZeroAlphaBlending(true)
|
||||
, OpenGL_Emulation_NDSDepthCalculation(true)
|
||||
, OpenGL_Emulation_DepthLEqualPolygonFacing(false)
|
||||
, jit_max_block_size(12)
|
||||
, loadToMemory(false)
|
||||
, UseExtBIOS(false)
|
||||
, SWIFromBIOS(false)
|
||||
, PatchSWI3(false)
|
||||
, UseExtFirmware(false)
|
||||
, UseExtFirmwareSettings(false)
|
||||
, RetailCardProtection8000(true)
|
||||
, BootFromFirmware(false)
|
||||
, DebugConsole(false)
|
||||
, EnsataEmulation(false)
|
||||
, cheatsDisable(false)
|
||||
, rigorous_timing(false)
|
||||
, advanced_timing(true)
|
||||
, micMode(InternalNoise)
|
||||
, spuInterpolationMode(2)
|
||||
, manualBackupType(0)
|
||||
, autodetectBackupMethod(0)
|
||||
, spu_captureMuted(false)
|
||||
, spu_advanced(true)
|
||||
, StylusPressure(50)
|
||||
, ConsoleType(NDS_CONSOLE_TYPE_FAT)
|
||||
, backupSave(false)
|
||||
, SPU_sync_mode(1)
|
||||
, SPU_sync_method(0)
|
||||
, WifiBridgeDeviceID(0)
|
||||
{
|
||||
strcpy(ARM9BIOS, "biosnds9.bin");
|
||||
strcpy(ARM7BIOS, "biosnds7.bin");
|
||||
strcpy(ExtFirmwarePath, "firmware.bin");
|
||||
|
||||
for(int i=0;i<16;i++)
|
||||
spu_muteChannels[i] = false;
|
||||
|
||||
for(int g=0;g<2;g++)
|
||||
for(int x=0;x<5;x++)
|
||||
dispLayers[g][x]=true;
|
||||
#ifdef HAVE_JIT
|
||||
//zero 06-sep-2012 - shouldnt be defaulting this to true for now, since the jit is buggy.
|
||||
//id rather have people discover a bonus speedhack than discover new bugs in a new version
|
||||
use_jit = false;
|
||||
#else
|
||||
use_jit = false;
|
||||
#endif
|
||||
|
||||
num_cores = NDS_GetCPUCoreCount();
|
||||
NDS_SetupDefaultFirmware();
|
||||
}
|
||||
bool GFX3D_HighResolutionInterpolateColor;
|
||||
bool GFX3D_EdgeMark;
|
||||
bool GFX3D_Fog;
|
||||
bool GFX3D_Texture;
|
||||
bool GFX3D_LineHack;
|
||||
int GFX3D_Renderer_MultisampleSize;
|
||||
int GFX3D_Renderer_TextureScalingFactor; //must be one of {1,2,4}
|
||||
bool GFX3D_Renderer_TextureDeposterize;
|
||||
bool GFX3D_Renderer_TextureSmoothing;
|
||||
bool GFX3D_TXTHack;
|
||||
|
||||
bool OpenGL_Emulation_ShadowPolygon;
|
||||
bool OpenGL_Emulation_SpecialZeroAlphaBlending;
|
||||
bool OpenGL_Emulation_NDSDepthCalculation;
|
||||
bool OpenGL_Emulation_DepthLEqualPolygonFacing;
|
||||
|
||||
bool loadToMemory;
|
||||
|
||||
bool UseExtBIOS;
|
||||
char ARM9BIOS[MAX_PATH];
|
||||
char ARM7BIOS[MAX_PATH];
|
||||
bool SWIFromBIOS;
|
||||
bool PatchSWI3;
|
||||
|
||||
bool RetailCardProtection8000;
|
||||
bool UseExtFirmware;
|
||||
bool UseExtFirmwareSettings;
|
||||
char ExtFirmwarePath[MAX_PATH];
|
||||
char ExtFirmwareUserSettingsPath[MAX_PATH];
|
||||
bool BootFromFirmware;
|
||||
FirmwareConfig fwConfig;
|
||||
|
||||
NDS_CONSOLE_TYPE ConsoleType;
|
||||
bool DebugConsole;
|
||||
bool EnsataEmulation;
|
||||
|
||||
bool cheatsDisable;
|
||||
|
||||
int num_cores;
|
||||
bool single_core() { return num_cores==1; }
|
||||
bool rigorous_timing;
|
||||
|
||||
struct GameHacks {
|
||||
GameHacks()
|
||||
: en(true)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
bool en;
|
||||
|
||||
struct {
|
||||
bool overclock;
|
||||
bool stylusjitter;
|
||||
} flags;
|
||||
|
||||
void apply();
|
||||
void clear();
|
||||
} gamehacks;
|
||||
|
||||
int StylusPressure;
|
||||
|
||||
bool dispLayers[2][5];
|
||||
|
||||
FAST_ALIGN bool advanced_timing;
|
||||
|
||||
bool use_jit;
|
||||
u32 jit_max_block_size;
|
||||
|
||||
int WifiBridgeDeviceID;
|
||||
|
||||
enum MicMode
|
||||
{
|
||||
InternalNoise = 0,
|
||||
Sample = 1,
|
||||
Random = 2,
|
||||
Physical = 3
|
||||
} micMode;
|
||||
|
||||
|
||||
int spuInterpolationMode;
|
||||
|
||||
//this is a temporary hack until we straighten out the flushing logic and/or gxfifo
|
||||
//int gfx3d_flushMode;
|
||||
|
||||
int autodetectBackupMethod;
|
||||
//this is the user's choice of manual backup type, for cases when the autodetection can't be trusted
|
||||
int manualBackupType;
|
||||
bool backupSave;
|
||||
|
||||
int SPU_sync_mode;
|
||||
int SPU_sync_method;
|
||||
|
||||
bool spu_muteChannels[16];
|
||||
bool spu_captureMuted;
|
||||
bool spu_advanced;
|
||||
|
||||
struct _ShowGpu {
|
||||
_ShowGpu() : main(true), sub(true) {}
|
||||
union {
|
||||
struct { bool main,sub; };
|
||||
bool screens[2];
|
||||
};
|
||||
} showGpu;
|
||||
|
||||
struct _Hud {
|
||||
_Hud()
|
||||
: ShowInputDisplay(false)
|
||||
, ShowGraphicalInputDisplay(false)
|
||||
, FpsDisplay(false)
|
||||
, FrameCounterDisplay(false)
|
||||
, ShowLagFrameCounter(false)
|
||||
, ShowMicrophone(false)
|
||||
, ShowRTC(false)
|
||||
{}
|
||||
bool ShowInputDisplay, ShowGraphicalInputDisplay, FpsDisplay, FrameCounterDisplay, ShowLagFrameCounter, ShowMicrophone, ShowRTC;
|
||||
} hud;
|
||||
|
||||
std::string run_advanscene_import;
|
||||
|
||||
} CommonSettings;
|
||||
|
||||
void NDS_RunAdvansceneAutoImport();
|
||||
|
||||
extern std::string InputDisplayString;
|
||||
extern int LagFrameFlag;
|
||||
extern int lastLag, TotalLagFrames;
|
||||
extern u8 MicSampleSelection;
|
||||
extern std::vector< std::vector<u8> > micSamples;
|
||||
|
||||
void MovieSRAM();
|
||||
|
||||
void ClearAutoHold(void);
|
||||
|
||||
bool ValidateSlot2Access(u32 procnum, u32 demandSRAMSpeed, u32 demand1stROMSpeed, u32 demand2ndROMSpeed, int clockbits);
|
||||
|
||||
//MUSTANG
|
||||
//extern ADVANsCEne advsc;
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2006-2007 shash
|
||||
Copyright (C) 2008-2024 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OGLRENDER_3_2_H
|
||||
#define OGLRENDER_3_2_H
|
||||
|
||||
#include "OGLRender.h"
|
||||
|
||||
#define MAX_CLIPPED_POLY_COUNT_FOR_UBO 16384
|
||||
|
||||
extern const char *GeometryVtxShader_150;
|
||||
extern const char *GeometryFragShader_150;
|
||||
extern const char *GeometryZeroDstAlphaPixelMaskVtxShader_150;
|
||||
extern const char *GeometryZeroDstAlphaPixelMaskFragShader_150;
|
||||
extern const char *MSGeometryZeroDstAlphaPixelMaskFragShader_150;
|
||||
extern const char *ClearImageVtxShader_150;
|
||||
extern const char *ClearImageFragShader_150;
|
||||
extern const char *EdgeMarkVtxShader_150;
|
||||
extern const char *EdgeMarkFragShader_150;
|
||||
extern const char *FogVtxShader_150;
|
||||
extern const char *FogFragShader_150;
|
||||
extern const char *FramebufferOutputVtxShader_150;
|
||||
extern const char *FramebufferOutput6665FragShader_150;
|
||||
|
||||
// A port that wants to use the OpenGL 3.2 renderer must assign the two following functions
|
||||
// to OGLLoadEntryPoints_3_2_Func and OGLCreateRenderer_3_2_Func, respectively.
|
||||
//
|
||||
// In addition, the port must add the following GPU3DInterface objects to core3DList:
|
||||
// - gpu3Dgl: Automatically selects the most fully featured version of standard OpenGL that
|
||||
// is available on the host system, prefering OpenGL 3.2 Core Profile.
|
||||
// - gpu3Dgl_3_2: Selects the OpenGL 3.2 Core Profile renderer, and returns an error if it
|
||||
// is not available on the host system.
|
||||
//
|
||||
// Finally, the port must call GPU->Set3DRendererByID() and pass in the index where
|
||||
// gpu3Dgl_3_2 exists in core3DList so that the emulator can create the appropriate
|
||||
// OpenGLRenderer object.
|
||||
//
|
||||
// Example code:
|
||||
// OGLLoadEntryPoints_3_2_Func = &OGLLoadEntryPoints_3_2;
|
||||
// OGLCreateRenderer_3_2_Func = &OGLCreateRenderer_3_2;
|
||||
// GPU3DInterface *core3DList[] = { &gpu3DNull, &gpu3DRasterize, &gpu3Dgl_3_2, NULL };
|
||||
// GPU->Set3DRendererByID(2);
|
||||
|
||||
void OGLLoadEntryPoints_3_2();
|
||||
void OGLCreateRenderer_3_2(OpenGLRenderer **rendererPtr);
|
||||
|
||||
class OpenGLGeometryResource : public Render3DResourceGeometry
|
||||
{
|
||||
protected:
|
||||
GLuint _vboID[3];
|
||||
GLuint _eboID[3];
|
||||
GLuint _vaoID[3];
|
||||
GLuint _uboPolyStatesID[3];
|
||||
GLuint _tboPolyStatesID[3];
|
||||
GLuint _texPolyStatesID[3];
|
||||
GLsync _syncGeometryRender[3];
|
||||
|
||||
u16 *_indexBuffer[3];
|
||||
OGLPolyStates *_polyStatesBuffer[3];
|
||||
|
||||
public:
|
||||
OpenGLGeometryResource(const OpenGLVariantID variantID);
|
||||
~OpenGLGeometryResource();
|
||||
|
||||
size_t BindWrite(const size_t rawVtxCount, const size_t clippedPolyCount);
|
||||
|
||||
size_t BindUsage();
|
||||
size_t UnbindUsage();
|
||||
size_t RebindUsage();
|
||||
|
||||
u16* GetIndexBuffer(const size_t index);
|
||||
OGLPolyStates* GetPolyStatesBuffer(const size_t index);
|
||||
bool IsPolyStatesBufferUBO();
|
||||
bool IsPolyStatesBufferTBO();
|
||||
};
|
||||
|
||||
class OpenGLRenderStatesResource : public Render3DResource
|
||||
{
|
||||
protected:
|
||||
GLsync _sync[3];
|
||||
GLuint _uboRenderStatesID[3];
|
||||
OGLRenderStates *_buffer[3];
|
||||
|
||||
public:
|
||||
OpenGLRenderStatesResource();
|
||||
~OpenGLRenderStatesResource();
|
||||
|
||||
size_t BindWrite();
|
||||
size_t BindUsage();
|
||||
size_t UnbindUsage();
|
||||
|
||||
OGLRenderStates* GetRenderStatesBuffer(const size_t index);
|
||||
};
|
||||
|
||||
class OpenGLRenderer_3_2 : public OpenGLRenderer_2_1
|
||||
{
|
||||
protected:
|
||||
bool _isShaderFixedLocationSupported;
|
||||
bool _isConservativeDepthSupported;
|
||||
bool _isConservativeDepthAMDSupported;
|
||||
|
||||
OpenGLGeometryResource *_gResource;
|
||||
OpenGLRenderStatesResource *_rsResource;
|
||||
|
||||
virtual Render3DError CreateVBOs();
|
||||
virtual Render3DError CreatePBOs();
|
||||
virtual Render3DError CreateFBOs();
|
||||
virtual void DestroyFBOs();
|
||||
virtual Render3DError CreateMultisampledFBO(GLsizei numSamples);
|
||||
virtual void DestroyMultisampledFBO();
|
||||
virtual void ResizeMultisampledFBOs(GLsizei numSamples);
|
||||
virtual Render3DError CreateVAOs();
|
||||
virtual void DestroyVAOs();
|
||||
|
||||
virtual Render3DError CreateGeometryPrograms();
|
||||
virtual Render3DError CreateClearImageProgram(const char *vsCString, const char *fsCString);
|
||||
virtual void DestroyClearImageProgram();
|
||||
virtual Render3DError CreateGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString);
|
||||
virtual Render3DError CreateMSGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString);
|
||||
virtual void DestroyMSGeometryZeroDstAlphaProgram();
|
||||
virtual Render3DError CreateEdgeMarkProgram(const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString);
|
||||
virtual Render3DError CreateFogProgram(const OGLFogProgramKey fogProgramKey, const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString);
|
||||
virtual Render3DError CreateFramebufferOutput6665Program(const char *vtxShaderCString, const char *fragShaderCString);
|
||||
virtual Render3DError CreateFramebufferOutput8888Program(const char *vtxShaderCString, const char *fragShaderCString);
|
||||
|
||||
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet);
|
||||
virtual void _SetupGeometryShaders(const OGLGeometryFlags flags);
|
||||
virtual void _RenderGeometryVertexAttribEnable();
|
||||
virtual void _RenderGeometryVertexAttribDisable();
|
||||
virtual Render3DError ZeroDstAlphaPass(const POLY *rawPolyList, const CPoly *clippedPolyList, const size_t clippedPolyCount, const size_t clippedPolyOpaqueCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr);
|
||||
virtual void _RenderGeometryLoopBegin();
|
||||
virtual void _RenderGeometryLoopEnd();
|
||||
virtual void _ResolveWorkingBackFacing();
|
||||
virtual void _ResolveGeometry();
|
||||
virtual void _ResolveFinalFramebuffer();
|
||||
virtual void _FramebufferProcessVertexAttribEnable();
|
||||
virtual void _FramebufferProcessVertexAttribDisable();
|
||||
virtual Render3DError _FramebufferConvertColorFormat();
|
||||
|
||||
virtual Render3DError BeginRender(const GFX3D_State &renderState, const GFX3D_GeometryList &renderGList);
|
||||
virtual Render3DError PostprocessFramebuffer();
|
||||
|
||||
virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 opaquePolyID);
|
||||
virtual Render3DError ClearUsingValues(const Color4u8 &clearColor6665, const FragmentAttributes &clearAttributes);
|
||||
|
||||
virtual void SetPolygonIndex(const size_t index);
|
||||
virtual Render3DError SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer, bool isBackFacing);
|
||||
virtual Render3DError SetupTexture(const POLY &thePoly, size_t polyRenderIndex);
|
||||
|
||||
public:
|
||||
OpenGLRenderer_3_2();
|
||||
~OpenGLRenderer_3_2();
|
||||
|
||||
virtual Render3DError InitExtensions();
|
||||
virtual Render3DError RenderFinish();
|
||||
virtual Render3DError RenderPowerOff();
|
||||
virtual Render3DError SetFramebufferSize(size_t w, size_t h);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,963 @@
|
|||
/*
|
||||
Copyright (C) 2024 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "OGLRender_ES3.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include "utils/bits.h"
|
||||
#include "common.h"
|
||||
#include "debug.h"
|
||||
#include "NDSSystem.h"
|
||||
|
||||
|
||||
static const GLenum GeometryDrawBuffersEnumES[8][4] = {
|
||||
{ OGL_COLOROUT_ATTACHMENT_ID, GL_NONE, GL_NONE, GL_NONE },
|
||||
{ OGL_COLOROUT_ATTACHMENT_ID, GL_NONE, GL_NONE, OGL_FOGATTRIBUTES_ATTACHMENT_ID },
|
||||
{ OGL_COLOROUT_ATTACHMENT_ID, GL_NONE, OGL_POLYID_ATTACHMENT_ID, GL_NONE },
|
||||
{ OGL_COLOROUT_ATTACHMENT_ID, GL_NONE, OGL_POLYID_ATTACHMENT_ID, OGL_FOGATTRIBUTES_ATTACHMENT_ID },
|
||||
{ OGL_COLOROUT_ATTACHMENT_ID, OGL_WORKING_ATTACHMENT_ID, GL_NONE, GL_NONE },
|
||||
{ OGL_COLOROUT_ATTACHMENT_ID, OGL_WORKING_ATTACHMENT_ID, GL_NONE, OGL_FOGATTRIBUTES_ATTACHMENT_ID },
|
||||
{ OGL_COLOROUT_ATTACHMENT_ID, OGL_WORKING_ATTACHMENT_ID, OGL_POLYID_ATTACHMENT_ID, GL_NONE },
|
||||
{ OGL_COLOROUT_ATTACHMENT_ID, OGL_WORKING_ATTACHMENT_ID, OGL_POLYID_ATTACHMENT_ID, OGL_FOGATTRIBUTES_ATTACHMENT_ID }
|
||||
};
|
||||
|
||||
static const GLint GeometryAttachmentWorkingBufferES[8] = { 1,1,1,1,1,1,1,1 };
|
||||
static const GLint GeometryAttachmentPolyIDES[8] = { 2,2,2,2,2,2,2,2 };
|
||||
static const GLint GeometryAttachmentFogAttributesES[8] = { 3,3,3,3,3,3,3,3 };
|
||||
|
||||
// Vertex shader for geometry, GLSL ES 3.00
|
||||
static const char *GeometryVtxShader_ES300 = {"\
|
||||
IN_VTX_POSITION vec4 inPosition;\n\
|
||||
IN_VTX_TEXCOORD0 vec2 inTexCoord0;\n\
|
||||
IN_VTX_COLOR vec3 inColor; \n\
|
||||
\n\
|
||||
#if IS_USING_UBO_POLY_STATES\n\
|
||||
layout (std140) uniform PolyStates\n\
|
||||
{\n\
|
||||
ivec4 value[4096];\n\
|
||||
} polyState;\n\
|
||||
#elif IS_USING_TBO_POLY_STATES\n\
|
||||
uniform highp isamplerBuffer PolyStates;\n\
|
||||
#else\n\
|
||||
uniform highp isampler2D PolyStates;\n\
|
||||
#endif\n\
|
||||
uniform mediump int polyIndex;\n\
|
||||
uniform bool polyDrawShadow;\n\
|
||||
\n\
|
||||
out vec2 vtxTexCoord;\n\
|
||||
out vec4 vtxColor;\n\
|
||||
flat out lowp int polyID;\n\
|
||||
flat out lowp int polyMode;\n\
|
||||
flat out lowp int polyIsWireframe;\n\
|
||||
flat out lowp int polyEnableFog;\n\
|
||||
flat out lowp int polySetNewDepthForTranslucent;\n\
|
||||
flat out lowp int polyEnableTexture;\n\
|
||||
flat out lowp int texSingleBitAlpha;\n\
|
||||
flat out lowp int polyIsBackFacing;\n\
|
||||
flat out lowp int isPolyDrawable;\n\
|
||||
\n\
|
||||
void main()\n\
|
||||
{\n\
|
||||
#if IS_USING_UBO_POLY_STATES\n\
|
||||
ivec4 polyStateVec = polyState.value[polyIndex >> 2];\n\
|
||||
int polyStateBits = polyStateVec[polyIndex & 0x03];\n\
|
||||
#elif IS_USING_TBO_POLY_STATES\n\
|
||||
int polyStateBits = texelFetch(PolyStates, polyIndex).r;\n\
|
||||
#else\n\
|
||||
int polyStateBits = texelFetch(PolyStates, ivec2(polyIndex & 0x00FF, (polyIndex >> 8) & 0x007F), 0).r;\n\
|
||||
#endif\n\
|
||||
int texSizeShiftS = (polyStateBits >> 18) & 0x07;\n\
|
||||
int texSizeShiftT = (polyStateBits >> 21) & 0x07;\n\
|
||||
\n\
|
||||
float polyAlpha = float((polyStateBits >> 8) & 0x1F) / 31.0;\n\
|
||||
vec2 polyTexScale = vec2(1.0 / float(8 << texSizeShiftS), 1.0 / float(8 << texSizeShiftT));\n\
|
||||
\n\
|
||||
polyID = (polyStateBits >> 0) & 0x3F;\n\
|
||||
polyMode = (polyStateBits >> 6) & 0x03;\n\
|
||||
polyIsWireframe = (polyStateBits >> 13) & 0x01;\n\
|
||||
polyEnableFog = (polyStateBits >> 14) & 0x01;\n\
|
||||
polySetNewDepthForTranslucent = (polyStateBits >> 15) & 0x01;\n\
|
||||
polyEnableTexture = (polyStateBits >> 16) & 0x01;\n\
|
||||
texSingleBitAlpha = (polyStateBits >> 17) & 0x01;\n\
|
||||
polyIsBackFacing = (polyStateBits >> 24) & 0x01;\n\
|
||||
\n\
|
||||
isPolyDrawable = int((polyMode != 3) || polyDrawShadow);\n\
|
||||
\n\
|
||||
mat2 texScaleMtx = mat2( vec2(polyTexScale.x, 0.0), \n\
|
||||
vec2( 0.0, polyTexScale.y)); \n\
|
||||
\n\
|
||||
vtxTexCoord = (texScaleMtx * inTexCoord0) / 16.0;\n\
|
||||
vtxColor = vec4(inColor / 63.0, polyAlpha);\n\
|
||||
gl_Position = vec4(inPosition.x, -inPosition.y, inPosition.z, inPosition.w) / 4096.0;\n\
|
||||
}\n\
|
||||
"};
|
||||
|
||||
// Fragment shader for geometry, GLSL ES 3.00
|
||||
static const char *GeometryFragShader_ES300 = {"\
|
||||
in vec2 vtxTexCoord;\n\
|
||||
in vec4 vtxColor;\n\
|
||||
flat in lowp int polyID;\n\
|
||||
flat in lowp int polyMode;\n\
|
||||
flat in lowp int polyIsWireframe;\n\
|
||||
flat in lowp int polyEnableFog;\n\
|
||||
flat in lowp int polySetNewDepthForTranslucent;\n\
|
||||
flat in lowp int polyEnableTexture;\n\
|
||||
flat in lowp int texSingleBitAlpha;\n\
|
||||
flat in lowp int polyIsBackFacing;\n\
|
||||
flat in lowp int isPolyDrawable;\n\
|
||||
\n\
|
||||
layout (std140) uniform RenderStates\n\
|
||||
{\n\
|
||||
bool enableAntialiasing;\n\
|
||||
bool enableFogAlphaOnly;\n\
|
||||
int clearPolyID;\n\
|
||||
float clearDepth;\n\
|
||||
float alphaTestRef;\n\
|
||||
float fogOffset;\n\
|
||||
float fogStep;\n\
|
||||
float pad_0;\n\
|
||||
vec4 fogColor;\n\
|
||||
vec4 edgeColor[8];\n\
|
||||
vec4 toonColor[32];\n\
|
||||
} state;\n\
|
||||
\n\
|
||||
uniform sampler2D texRenderObject;\n\
|
||||
uniform bool texDrawOpaque;\n\
|
||||
uniform bool drawModeDepthEqualsTest;\n\
|
||||
uniform bool polyDrawShadow;\n\
|
||||
uniform float polyDepthOffset;\n\
|
||||
\n\
|
||||
OUT_COLOR vec4 outFragColor;\n\
|
||||
\n\
|
||||
#if DRAW_MODE_OPAQUE\n\
|
||||
OUT_WORKING_BUFFER vec4 outDstBackFacing;\n\
|
||||
#elif USE_DEPTH_LEQUAL_POLYGON_FACING\n\
|
||||
uniform sampler2D inDstBackFacing;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#if ENABLE_EDGE_MARK\n\
|
||||
OUT_POLY_ID vec4 outPolyID;\n\
|
||||
#endif\n\
|
||||
#if ENABLE_FOG\n\
|
||||
OUT_FOG_ATTRIBUTES vec4 outFogAttributes;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
void main()\n\
|
||||
{\n\
|
||||
#if USE_DEPTH_LEQUAL_POLYGON_FACING && !DRAW_MODE_OPAQUE\n\
|
||||
bool isOpaqueDstBackFacing = bool( texelFetch(inDstBackFacing, ivec2(gl_FragCoord.xy), 0).r );\n\
|
||||
if ( drawModeDepthEqualsTest && (bool(polyIsBackFacing) || !isOpaqueDstBackFacing) )\n\
|
||||
{\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
vec4 mainTexColor = (ENABLE_TEXTURE_SAMPLING && bool(polyEnableTexture)) ? texture(texRenderObject, vtxTexCoord) : vec4(1.0, 1.0, 1.0, 1.0);\n\
|
||||
\n\
|
||||
if (!bool(texSingleBitAlpha))\n\
|
||||
{\n\
|
||||
if (texDrawOpaque)\n\
|
||||
{\n\
|
||||
if ( (polyMode != 1) && (mainTexColor.a <= 0.999) )\n\
|
||||
{\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
}\n\
|
||||
else\n\
|
||||
{\n\
|
||||
if ( ((polyMode != 1) && (mainTexColor.a * vtxColor.a > 0.999)) || ((polyMode == 1) && (vtxColor.a > 0.999)) )\n\
|
||||
{\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
}\n\
|
||||
}\n\
|
||||
#if USE_TEXTURE_SMOOTHING\n\
|
||||
else\n\
|
||||
{\n\
|
||||
if (mainTexColor.a < 0.500)\n\
|
||||
{\n\
|
||||
mainTexColor.a = 0.0;\n\
|
||||
}\n\
|
||||
else\n\
|
||||
{\n\
|
||||
mainTexColor.rgb = mainTexColor.rgb / mainTexColor.a;\n\
|
||||
mainTexColor.a = 1.0;\n\
|
||||
}\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
outFragColor = mainTexColor * vtxColor;\n\
|
||||
\n\
|
||||
if (polyMode == 1)\n\
|
||||
{\n\
|
||||
outFragColor.rgb = (ENABLE_TEXTURE_SAMPLING && bool(polyEnableTexture)) ? mix(vtxColor.rgb, mainTexColor.rgb, mainTexColor.a) : vtxColor.rgb;\n\
|
||||
outFragColor.a = vtxColor.a;\n\
|
||||
}\n\
|
||||
else if (polyMode == 2)\n\
|
||||
{\n\
|
||||
vec3 newToonColor = state.toonColor[int((vtxColor.r * 31.0) + 0.5)].rgb;\n\
|
||||
#if TOON_SHADING_MODE\n\
|
||||
outFragColor.rgb = min((mainTexColor.rgb * vtxColor.r) + newToonColor.rgb, 1.0);\n\
|
||||
#else\n\
|
||||
outFragColor.rgb = mainTexColor.rgb * newToonColor.rgb;\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
else if ((polyMode == 3) && polyDrawShadow)\n\
|
||||
{\n\
|
||||
outFragColor = vtxColor;\n\
|
||||
}\n\
|
||||
\n\
|
||||
if ( (isPolyDrawable != 0) && ((outFragColor.a < 0.001) || (ENABLE_ALPHA_TEST && outFragColor.a < state.alphaTestRef)) )\n\
|
||||
{\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
#if ENABLE_EDGE_MARK\n\
|
||||
outPolyID = (isPolyDrawable != 0) ? vec4( float(polyID)/63.0, float(polyIsWireframe == 1), 0.0, float(outFragColor.a > 0.999) ) : vec4(0.0, 0.0, 0.0, 0.0);\n\
|
||||
#endif\n\
|
||||
#if ENABLE_FOG\n\
|
||||
outFogAttributes = (isPolyDrawable != 0) ? vec4( float(polyEnableFog), 0.0, 0.0, float((outFragColor.a > 0.999) ? 1.0 : 0.5) ) : vec4(0.0, 0.0, 0.0, 0.0);\n\
|
||||
#endif\n\
|
||||
#if DRAW_MODE_OPAQUE\n\
|
||||
outDstBackFacing = vec4(float(polyIsBackFacing), 0.0, 0.0, 1.0);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#if USE_NDS_DEPTH_CALCULATION || ENABLE_FOG\n\
|
||||
// It is tempting to perform the NDS depth calculation in the vertex shader rather than in the fragment shader.\n\
|
||||
// Resist this temptation! It is much more reliable to do the depth calculation in the fragment shader due to\n\
|
||||
// subtle interpolation differences between various GPUs and/or drivers. If the depth calculation is not done\n\
|
||||
// here, then it is very possible for the user to experience Z-fighting in certain rendering situations.\n\
|
||||
\n\
|
||||
#if ENABLE_W_DEPTH\n\
|
||||
gl_FragDepth = clamp( ((1.0/gl_FragCoord.w) * (4096.0/16777215.0)) + polyDepthOffset, 0.0, 1.0 );\n\
|
||||
#else\n\
|
||||
// hack: when using z-depth, drop some LSBs so that the overworld map in Dragon Quest IV shows up correctly\n\
|
||||
gl_FragDepth = clamp( (floor(gl_FragCoord.z * 4194303.0) * (4.0/16777215.0)) + polyDepthOffset, 0.0, 1.0 );\n\
|
||||
#endif\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
"};
|
||||
|
||||
void OGLLoadEntryPoints_ES_3_0()
|
||||
{
|
||||
OGLLoadEntryPoints_3_2();
|
||||
}
|
||||
|
||||
void OGLCreateRenderer_ES_3_0(OpenGLRenderer **rendererPtr)
|
||||
{
|
||||
if (IsOpenGLDriverVersionSupported(3, 0, 0))
|
||||
{
|
||||
*rendererPtr = new OpenGLESRenderer_3_0;
|
||||
(*rendererPtr)->SetVersion(3, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
OpenGLESRenderer_3_0::OpenGLESRenderer_3_0()
|
||||
{
|
||||
_variantID = OpenGLVariantID_ES3_3_0;
|
||||
|
||||
_geometryDrawBuffersEnum = GeometryDrawBuffersEnumES;
|
||||
_geometryAttachmentWorkingBuffer = GeometryAttachmentWorkingBufferES;
|
||||
_geometryAttachmentPolyID = GeometryAttachmentPolyIDES;
|
||||
_geometryAttachmentFogAttributes = GeometryAttachmentFogAttributesES;
|
||||
|
||||
ref->textureSrcTypeCIColor = GL_UNSIGNED_BYTE;
|
||||
ref->textureSrcTypeCIFog = GL_UNSIGNED_BYTE;
|
||||
ref->textureSrcTypeEdgeColor = GL_UNSIGNED_BYTE;
|
||||
ref->textureSrcTypeToonTable = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
|
||||
Render3DError OpenGLESRenderer_3_0::InitExtensions()
|
||||
{
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
Render3DError error = OGLERROR_NOERR;
|
||||
|
||||
// Get OpenGL extensions
|
||||
std::set<std::string> oglExtensionSet;
|
||||
this->GetExtensionSet(&oglExtensionSet);
|
||||
|
||||
// OpenGL ES 3.0 should fully support FBOs, so we don't need the default framebuffer.
|
||||
// However, OpenGL ES has traditionally required some kind of surface buffer attached
|
||||
// to the context before using it. We don't want it, nor would we ever use it here.
|
||||
// Therefore, check if our context supports being surfaceless before doing anything else,
|
||||
// as this works as a kind of compatibility check.
|
||||
if (!this->IsExtensionPresent(&oglExtensionSet, "GL_OES_surfaceless_context"))
|
||||
{
|
||||
INFO("OpenGL ES: Client contexts are not expected to have any surfaces attached\n");
|
||||
INFO(" to the default framebuffer. The fact that the context does not\n");
|
||||
INFO(" work surfaceless may indicate an error in the context creation,\n");
|
||||
INFO(" or that your platform's context creation is too old.\n");
|
||||
error = OGLERROR_FEATURE_UNSUPPORTED;
|
||||
return error;
|
||||
}
|
||||
|
||||
// Mirrored Repeat Mode Support
|
||||
OGLRef.stateTexMirroredRepeat = GL_MIRRORED_REPEAT;
|
||||
|
||||
// Blending Support
|
||||
this->_isBlendFuncSeparateSupported = true;
|
||||
this->_isBlendEquationSeparateSupported = true;
|
||||
|
||||
// Fixed locations in shaders are supported in ES 3.0 by default.
|
||||
this->_isShaderFixedLocationSupported = true;
|
||||
|
||||
GLfloat maxAnisotropyOGL = 1.0f;
|
||||
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropyOGL);
|
||||
this->_deviceInfo.maxAnisotropy = (float)maxAnisotropyOGL;
|
||||
|
||||
// OpenGL ES 3.0 should be able to handle the GL_RGBA format in glReadPixels without any performance penalty.
|
||||
OGLRef.readPixelsBestFormat = GL_RGBA;
|
||||
OGLRef.readPixelsBestDataType = GL_UNSIGNED_BYTE;
|
||||
|
||||
this->_deviceInfo.isEdgeMarkSupported = true;
|
||||
this->_deviceInfo.isFogSupported = true;
|
||||
|
||||
// Need to generate this texture first because FBO creation needs it.
|
||||
// This texture is only required by shaders, and so if shader creation
|
||||
// fails, then we can immediately delete this texture if an error occurs.
|
||||
glGenTextures(1, &OGLRef.texFinalColorID);
|
||||
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FinalColor);
|
||||
glBindTexture(GL_TEXTURE_2D, OGLRef.texFinalColorID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
// OpenGL ES 3.0 should have all the necessary features to be able to flip and convert the framebuffer.
|
||||
this->_willConvertFramebufferOnGPU = true;
|
||||
|
||||
this->_enableTextureSmoothing = CommonSettings.GFX3D_Renderer_TextureSmoothing;
|
||||
this->_emulateShadowPolygon = CommonSettings.OpenGL_Emulation_ShadowPolygon;
|
||||
this->_emulateSpecialZeroAlphaBlending = CommonSettings.OpenGL_Emulation_SpecialZeroAlphaBlending;
|
||||
this->_emulateNDSDepthCalculation = CommonSettings.OpenGL_Emulation_NDSDepthCalculation;
|
||||
this->_emulateDepthLEqualPolygonFacing = CommonSettings.OpenGL_Emulation_DepthLEqualPolygonFacing;
|
||||
|
||||
// Load and create shaders. Return on any error, since ES 3.0 makes shaders mandatory.
|
||||
this->isShaderSupported = true;
|
||||
|
||||
this->_rsResource = new OpenGLRenderStatesResource();
|
||||
|
||||
if (IsOpenGLDriverVersionSupported(3, 2, 0))
|
||||
{
|
||||
this->_gResource = new OpenGLGeometryResource(OpenGLVariantID_ES3_3_2);
|
||||
}
|
||||
else if (IsOpenGLDriverVersionSupported(3, 1, 0))
|
||||
{
|
||||
this->_gResource = new OpenGLGeometryResource(OpenGLVariantID_ES3_3_1);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->_gResource = new OpenGLGeometryResource(OpenGLVariantID_ES3_3_0);
|
||||
}
|
||||
|
||||
error = this->CreateGeometryPrograms();
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
glUseProgram(0);
|
||||
this->DestroyGeometryPrograms();
|
||||
this->isShaderSupported = false;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
error = this->CreateClearImageProgram(ClearImageVtxShader_150, ClearImageFragShader_150);
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
glUseProgram(0);
|
||||
this->DestroyGeometryPrograms();
|
||||
this->isShaderSupported = false;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
error = this->CreateGeometryZeroDstAlphaProgram(GeometryZeroDstAlphaPixelMaskVtxShader_150, GeometryZeroDstAlphaPixelMaskFragShader_150);
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
glUseProgram(0);
|
||||
this->DestroyGeometryPrograms();
|
||||
this->DestroyClearImageProgram();
|
||||
this->isShaderSupported = false;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
INFO("OpenGL ES: Successfully created geometry shaders.\n");
|
||||
error = this->InitPostprocessingPrograms(EdgeMarkVtxShader_150,
|
||||
EdgeMarkFragShader_150,
|
||||
FramebufferOutputVtxShader_150,
|
||||
FramebufferOutput6665FragShader_150,
|
||||
NULL);
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
glUseProgram(0);
|
||||
this->DestroyGeometryPrograms();
|
||||
this->DestroyClearImageProgram();
|
||||
this->DestroyGeometryZeroDstAlphaProgram();
|
||||
this->isShaderSupported = false;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
this->isVBOSupported = true;
|
||||
this->CreateVBOs();
|
||||
|
||||
// PBOs are only used when reading back the rendered framebuffer for the emulated
|
||||
// BG0 layer. For desktop-class GPUs, doing an asynchronous glReadPixels() call
|
||||
// is always advantageous since such devices are expected to have their GPUs
|
||||
// connected to a data bus.
|
||||
//
|
||||
// However, many ARM-based mobile devices use integrated GPUs of varying degrees
|
||||
// of memory latency and implementation quality. This means that the performance
|
||||
// of an asynchronous glReadPixels() call is NOT guaranteed on such devices.
|
||||
//
|
||||
// In fact, many ARM-based devices suffer devastating performance drops when trying
|
||||
// to do asynchronous framebuffer reads. Therefore, since most OpenGL ES users will
|
||||
// be running an ARM-based iGPU, we will disable PBOs for OpenGL ES and stick with
|
||||
// a traditional synchronous glReadPixels() call instead.
|
||||
this->isPBOSupported = false;
|
||||
|
||||
this->isVAOSupported = true;
|
||||
this->CreateVAOs();
|
||||
|
||||
// Load and create FBOs. Return on any error, since OpenGL ES 3.0 includes FBOs as core functionality.
|
||||
this->isFBOSupported = true;
|
||||
error = this->CreateFBOs();
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
this->isFBOSupported = false;
|
||||
return error;
|
||||
}
|
||||
|
||||
this->_isFBOBlitSupported = true;
|
||||
this->isMultisampledFBOSupported = true;
|
||||
this->_selectedMultisampleSize = CommonSettings.GFX3D_Renderer_MultisampleSize;
|
||||
|
||||
GLint maxSamplesOGL = 0;
|
||||
glGetIntegerv(GL_MAX_SAMPLES, &maxSamplesOGL);
|
||||
this->_deviceInfo.maxSamples = (u8)maxSamplesOGL;
|
||||
|
||||
if (this->_deviceInfo.maxSamples >= 2)
|
||||
{
|
||||
// Try and initialize the multisampled FBOs with the GFX3D_Renderer_MultisampleSize.
|
||||
// However, if the client has this set to 0, then set sampleSize to 2 in order to
|
||||
// force the generation and the attachments of the buffers at a meaningful sample
|
||||
// size. If GFX3D_Renderer_MultisampleSize is 0, then we can deallocate the buffer
|
||||
// memory afterwards.
|
||||
GLsizei sampleSize = this->GetLimitedMultisampleSize();
|
||||
if (sampleSize == 0)
|
||||
{
|
||||
sampleSize = 2;
|
||||
}
|
||||
|
||||
error = this->CreateMultisampledFBO(sampleSize);
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
this->isMultisampledFBOSupported = false;
|
||||
}
|
||||
|
||||
// If GFX3D_Renderer_MultisampleSize is 0, then we can deallocate the buffers now
|
||||
// in order to save some memory.
|
||||
if (this->_selectedMultisampleSize == 0)
|
||||
{
|
||||
this->ResizeMultisampledFBOs(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->isMultisampledFBOSupported = false;
|
||||
INFO("OpenGL ES: Driver does not support at least 2x multisampled FBOs.\n");
|
||||
}
|
||||
|
||||
this->_isDepthLEqualPolygonFacingSupported = true;
|
||||
this->_enableMultisampledRendering = ((this->_selectedMultisampleSize >= 2) && this->isMultisampledFBOSupported);
|
||||
|
||||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError OpenGLESRenderer_3_0::CreateGeometryPrograms()
|
||||
{
|
||||
Render3DError error = OGLERROR_NOERR;
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
// Create shader resources.
|
||||
glGenTextures(1, &OGLRef.texFogDensityTableID);
|
||||
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_LookupTable);
|
||||
glBindTexture(GL_TEXTURE_2D, OGLRef.texFogDensityTableID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 32, 1, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
OGLGeometryFlags programFlags;
|
||||
programFlags.value = 0;
|
||||
|
||||
std::stringstream shaderHeader;
|
||||
shaderHeader << "#version 300 es\n";
|
||||
shaderHeader << "precision highp float;\n";
|
||||
shaderHeader << "precision highp int;\n";
|
||||
shaderHeader << "\n";
|
||||
|
||||
std::stringstream vsHeader;
|
||||
vsHeader << "#define IN_VTX_POSITION layout (location = " << OGLVertexAttributeID_Position << ") in\n";
|
||||
vsHeader << "#define IN_VTX_TEXCOORD0 layout (location = " << OGLVertexAttributeID_TexCoord0 << ") in\n";
|
||||
vsHeader << "#define IN_VTX_COLOR layout (location = " << OGLVertexAttributeID_Color << ") in\n";
|
||||
vsHeader << "\n";
|
||||
vsHeader << "#define IS_USING_UBO_POLY_STATES " << ((this->_gResource->IsPolyStatesBufferUBO()) ? 1 : 0) << "\n";
|
||||
vsHeader << "#define IS_USING_TBO_POLY_STATES " << ((this->_gResource->IsPolyStatesBufferTBO()) ? 1 : 0) << "\n";
|
||||
vsHeader << "#define DEPTH_EQUALS_TEST_TOLERANCE " << DEPTH_EQUALS_TEST_TOLERANCE << ".0\n";
|
||||
vsHeader << "\n";
|
||||
|
||||
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(GeometryVtxShader_ES300);
|
||||
|
||||
for (size_t flagsValue = 0; flagsValue < 128; flagsValue++, programFlags.value++)
|
||||
{
|
||||
std::stringstream shaderFlags;
|
||||
shaderFlags << "#define OUT_COLOR layout (location = 0) out\n";
|
||||
shaderFlags << "#define OUT_WORKING_BUFFER layout (location = " << (OGL_WORKING_ATTACHMENT_ID - GL_COLOR_ATTACHMENT0) << ") out\n";
|
||||
shaderFlags << "#define OUT_POLY_ID layout (location = " << (OGL_POLYID_ATTACHMENT_ID - GL_COLOR_ATTACHMENT0) << ") out\n";
|
||||
shaderFlags << "#define OUT_FOG_ATTRIBUTES layout (location = " << (OGL_FOGATTRIBUTES_ATTACHMENT_ID - GL_COLOR_ATTACHMENT0) << ") out\n";
|
||||
shaderFlags << "\n";
|
||||
shaderFlags << "#define USE_TEXTURE_SMOOTHING " << ((this->_enableTextureSmoothing) ? 1 : 0) << "\n";
|
||||
shaderFlags << "#define USE_NDS_DEPTH_CALCULATION " << ((this->_emulateNDSDepthCalculation) ? 1 : 0) << "\n";
|
||||
shaderFlags << "#define USE_DEPTH_LEQUAL_POLYGON_FACING " << ((this->_emulateDepthLEqualPolygonFacing) ? 1 : 0) << "\n";
|
||||
shaderFlags << "\n";
|
||||
shaderFlags << "#define ENABLE_W_DEPTH " << ((programFlags.EnableWDepth) ? 1 : 0) << "\n";
|
||||
shaderFlags << "#define ENABLE_ALPHA_TEST " << ((programFlags.EnableAlphaTest) ? "true\n" : "false\n");
|
||||
shaderFlags << "#define ENABLE_TEXTURE_SAMPLING " << ((programFlags.EnableTextureSampling) ? "true\n" : "false\n");
|
||||
shaderFlags << "#define TOON_SHADING_MODE " << ((programFlags.ToonShadingMode) ? 1 : 0) << "\n";
|
||||
shaderFlags << "#define ENABLE_FOG " << ((programFlags.EnableFog) ? 1 : 0) << "\n";
|
||||
shaderFlags << "#define ENABLE_EDGE_MARK " << ((programFlags.EnableEdgeMark) ? 1 : 0) << "\n";
|
||||
shaderFlags << "#define DRAW_MODE_OPAQUE " << ((programFlags.OpaqueDrawMode) ? 1 : 0) << "\n";
|
||||
shaderFlags << "\n";
|
||||
|
||||
std::string fragShaderCode = shaderHeader.str() + shaderFlags.str() + std::string(GeometryFragShader_ES300);
|
||||
|
||||
error = this->ShaderProgramCreate(OGLRef.vertexGeometryShaderID,
|
||||
OGLRef.fragmentGeometryShaderID[flagsValue],
|
||||
OGLRef.programGeometryID[flagsValue],
|
||||
vtxShaderCode.c_str(),
|
||||
fragShaderCode.c_str());
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
INFO("OpenGL ES: Failed to create the GEOMETRY shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyGeometryPrograms();
|
||||
return error;
|
||||
}
|
||||
|
||||
glLinkProgram(OGLRef.programGeometryID[flagsValue]);
|
||||
if (!this->ValidateShaderProgramLink(OGLRef.programGeometryID[flagsValue]))
|
||||
{
|
||||
INFO("OpenGL ES: Failed to link the GEOMETRY shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyGeometryPrograms();
|
||||
return OGLERROR_SHADER_CREATE_ERROR;
|
||||
}
|
||||
|
||||
glValidateProgram(OGLRef.programGeometryID[flagsValue]);
|
||||
glUseProgram(OGLRef.programGeometryID[flagsValue]);
|
||||
|
||||
// Set up render states UBO
|
||||
const GLuint uniformBlockRenderStates = glGetUniformBlockIndex(OGLRef.programGeometryID[flagsValue], "RenderStates");
|
||||
glUniformBlockBinding(OGLRef.programGeometryID[flagsValue], uniformBlockRenderStates, OGLBindingPointID_RenderStates);
|
||||
|
||||
GLint uboSize = 0;
|
||||
glGetActiveUniformBlockiv(OGLRef.programGeometryID[flagsValue], uniformBlockRenderStates, GL_UNIFORM_BLOCK_DATA_SIZE, &uboSize);
|
||||
assert(uboSize == sizeof(OGLRenderStates));
|
||||
|
||||
const GLint uniformTexRenderObject = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "texRenderObject");
|
||||
glUniform1i(uniformTexRenderObject, 0);
|
||||
|
||||
if (this->_gResource->IsPolyStatesBufferUBO())
|
||||
{
|
||||
const GLuint uniformBlockPolyStates = glGetUniformBlockIndex(OGLRef.programGeometryID[flagsValue], "PolyStates");
|
||||
glUniformBlockBinding(OGLRef.programGeometryID[flagsValue], uniformBlockPolyStates, OGLBindingPointID_PolyStates);
|
||||
}
|
||||
else
|
||||
{
|
||||
const GLint uniformTexBufferPolyStates = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "PolyStates");
|
||||
glUniform1i(uniformTexBufferPolyStates, OGLTextureUnitID_PolyStates);
|
||||
}
|
||||
|
||||
if (this->_emulateDepthLEqualPolygonFacing && !programFlags.OpaqueDrawMode)
|
||||
{
|
||||
const GLint uniformTexBackfacing = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "inDstBackFacing");
|
||||
glUniform1i(uniformTexBackfacing, OGLTextureUnitID_FinalColor);
|
||||
}
|
||||
|
||||
OGLRef.uniformTexDrawOpaque[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "texDrawOpaque");
|
||||
OGLRef.uniformDrawModeDepthEqualsTest[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "drawModeDepthEqualsTest");
|
||||
OGLRef.uniformPolyDrawShadow[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDrawShadow");
|
||||
OGLRef.uniformPolyStateIndex[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyIndex");
|
||||
OGLRef.uniformPolyDepthOffset[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDepthOffset");
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
Render3DError OpenGLESRenderer_3_0::CreateClearImageProgram(const char *vsCString, const char *fsCString)
|
||||
{
|
||||
Render3DError error = OGLERROR_NOERR;
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
std::stringstream shaderHeader;
|
||||
shaderHeader << "#version 300 es\n";
|
||||
shaderHeader << "precision highp float;\n";
|
||||
shaderHeader << "precision highp int;\n";
|
||||
shaderHeader << "\n";
|
||||
|
||||
std::stringstream vsHeader;
|
||||
if (this->_isShaderFixedLocationSupported)
|
||||
{
|
||||
vsHeader << "#define IN_VTX_POSITION layout (location = " << OGLVertexAttributeID_Position << ") in\n";
|
||||
vsHeader << "#define IN_VTX_TEXCOORD0 layout (location = " << OGLVertexAttributeID_TexCoord0 << ") in\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
vsHeader << "#define IN_VTX_POSITION in\n";
|
||||
vsHeader << "#define IN_VTX_TEXCOORD0 in\n";
|
||||
}
|
||||
vsHeader << "\n";
|
||||
|
||||
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(vsCString);
|
||||
std::stringstream fsHeader;
|
||||
if (this->_isShaderFixedLocationSupported)
|
||||
{
|
||||
fsHeader << "#define OUT_COLOR layout (location = 0) out\n";
|
||||
fsHeader << "#define OUT_FOGATTR layout (location = 1) out\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
fsHeader << "#define OUT_COLOR out\n";
|
||||
fsHeader << "#define OUT_FOGATTR out\n";
|
||||
}
|
||||
fsHeader << "\n";
|
||||
|
||||
std::string fragShaderCodeFogColor = shaderHeader.str() + fsHeader.str() + std::string(fsCString);
|
||||
error = this->ShaderProgramCreate(OGLRef.vsClearImageID,
|
||||
OGLRef.fsClearImageID,
|
||||
OGLRef.pgClearImageID,
|
||||
vtxShaderCode.c_str(),
|
||||
fragShaderCodeFogColor.c_str());
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
INFO("OpenGL ES: Failed to create the CLEAR_IMAGE shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyClearImageProgram();
|
||||
return error;
|
||||
}
|
||||
|
||||
glLinkProgram(OGLRef.pgClearImageID);
|
||||
if (!this->ValidateShaderProgramLink(OGLRef.pgClearImageID))
|
||||
{
|
||||
INFO("OpenGL ES: Failed to link the CLEAR_IMAGE shader color/fog program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyClearImageProgram();
|
||||
return OGLERROR_SHADER_CREATE_ERROR;
|
||||
}
|
||||
|
||||
glValidateProgram(OGLRef.pgClearImageID);
|
||||
glUseProgram(OGLRef.pgClearImageID);
|
||||
|
||||
const GLint uniformTexCIColor = glGetUniformLocation(OGLRef.pgClearImageID, "texCIColor");
|
||||
const GLint uniformTexCIFogAttr = glGetUniformLocation(OGLRef.pgClearImageID, "texCIFogAttr");
|
||||
const GLint uniformTexCIDepthCF = glGetUniformLocation(OGLRef.pgClearImageID, "texCIDepth");
|
||||
glUniform1i(uniformTexCIColor, OGLTextureUnitID_CIColor);
|
||||
glUniform1i(uniformTexCIFogAttr, OGLTextureUnitID_CIFogAttr);
|
||||
glUniform1i(uniformTexCIDepthCF, OGLTextureUnitID_CIDepth);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
Render3DError OpenGLESRenderer_3_0::CreateGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString)
|
||||
{
|
||||
Render3DError error = OGLERROR_NOERR;
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
if ( (vtxShaderCString == NULL) || (fragShaderCString == NULL) )
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
std::stringstream shaderHeader;
|
||||
shaderHeader << "#version 300 es\n";
|
||||
shaderHeader << "precision highp float;\n";
|
||||
shaderHeader << "precision highp int;\n";
|
||||
shaderHeader << "\n";
|
||||
|
||||
std::stringstream vsHeader;
|
||||
vsHeader << "#define IN_VTX_POSITION layout (location = " << OGLVertexAttributeID_Position << ") in\n";
|
||||
vsHeader << "#define IN_VTX_TEXCOORD0 layout (location = " << OGLVertexAttributeID_TexCoord0 << ") in\n";
|
||||
vsHeader << "#define IN_VTX_COLOR layout (location = " << OGLVertexAttributeID_Color << ") in\n";
|
||||
|
||||
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(vtxShaderCString);
|
||||
std::string fragShaderCode = shaderHeader.str() + std::string(fragShaderCString);
|
||||
|
||||
error = this->ShaderProgramCreate(OGLRef.vtxShaderGeometryZeroDstAlphaID,
|
||||
OGLRef.fragShaderGeometryZeroDstAlphaID,
|
||||
OGLRef.programGeometryZeroDstAlphaID,
|
||||
vtxShaderCode.c_str(),
|
||||
fragShaderCode.c_str());
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
INFO("OpenGL ES: Failed to create the GEOMETRY ZERO DST ALPHA shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyGeometryZeroDstAlphaProgram();
|
||||
return error;
|
||||
}
|
||||
|
||||
glLinkProgram(OGLRef.programGeometryZeroDstAlphaID);
|
||||
if (!this->ValidateShaderProgramLink(OGLRef.programGeometryZeroDstAlphaID))
|
||||
{
|
||||
INFO("OpenGL ES: Failed to link the GEOMETRY ZERO DST ALPHA shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyGeometryZeroDstAlphaProgram();
|
||||
return OGLERROR_SHADER_CREATE_ERROR;
|
||||
}
|
||||
|
||||
glValidateProgram(OGLRef.programGeometryZeroDstAlphaID);
|
||||
glUseProgram(OGLRef.programGeometryZeroDstAlphaID);
|
||||
|
||||
const GLint uniformTexGColor = glGetUniformLocation(OGLRef.programGeometryZeroDstAlphaID, "texInFragColor");
|
||||
glUniform1i(uniformTexGColor, OGLTextureUnitID_GColor);
|
||||
|
||||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError OpenGLESRenderer_3_0::CreateEdgeMarkProgram(const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString)
|
||||
{
|
||||
Render3DError error = OGLERROR_NOERR;
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
if ( (vtxShaderCString == NULL) || (fragShaderCString == NULL) )
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
std::stringstream shaderHeader;
|
||||
shaderHeader << "#version 300 es\n";
|
||||
shaderHeader << "precision highp float;\n";
|
||||
shaderHeader << "precision highp int;\n";
|
||||
shaderHeader << "\n";
|
||||
shaderHeader << "#define FRAMEBUFFER_SIZE_X " << this->_framebufferWidth << ".0 \n";
|
||||
shaderHeader << "#define FRAMEBUFFER_SIZE_Y " << this->_framebufferHeight << ".0 \n";
|
||||
shaderHeader << "\n";
|
||||
|
||||
std::stringstream vsHeader;
|
||||
vsHeader << "#define IN_VTX_POSITION layout (location = " << OGLVertexAttributeID_Position << ") in\n";
|
||||
vsHeader << "#define IN_VTX_TEXCOORD0 layout (location = " << OGLVertexAttributeID_TexCoord0 << ") in\n";
|
||||
vsHeader << "#define IN_VTX_COLOR layout (location = " << OGLVertexAttributeID_Color << ") in\n";
|
||||
|
||||
std::stringstream fsHeader;
|
||||
fsHeader << "#define OUT_COLOR layout (location = 0) out\n";
|
||||
|
||||
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(vtxShaderCString);
|
||||
std::string fragShaderCode = shaderHeader.str() + fsHeader.str() + std::string(fragShaderCString);
|
||||
|
||||
error = this->ShaderProgramCreate(OGLRef.vertexEdgeMarkShaderID,
|
||||
OGLRef.fragmentEdgeMarkShaderID,
|
||||
OGLRef.programEdgeMarkID,
|
||||
vtxShaderCode.c_str(),
|
||||
fragShaderCode.c_str());
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
INFO("OpenGL ES: Failed to create the EDGE MARK shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyEdgeMarkProgram();
|
||||
return error;
|
||||
}
|
||||
|
||||
glLinkProgram(OGLRef.programEdgeMarkID);
|
||||
if (!this->ValidateShaderProgramLink(OGLRef.programEdgeMarkID))
|
||||
{
|
||||
INFO("OpenGL ES: Failed to link the EDGE MARK shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyEdgeMarkProgram();
|
||||
return OGLERROR_SHADER_CREATE_ERROR;
|
||||
}
|
||||
|
||||
glValidateProgram(OGLRef.programEdgeMarkID);
|
||||
glUseProgram(OGLRef.programEdgeMarkID);
|
||||
|
||||
const GLuint uniformBlockRenderStates = glGetUniformBlockIndex(OGLRef.programEdgeMarkID, "RenderStates");
|
||||
glUniformBlockBinding(OGLRef.programEdgeMarkID, uniformBlockRenderStates, OGLBindingPointID_RenderStates);
|
||||
|
||||
const GLint uniformTexGDepth = glGetUniformLocation(OGLRef.programEdgeMarkID, "texInFragDepth");
|
||||
const GLint uniformTexGPolyID = glGetUniformLocation(OGLRef.programEdgeMarkID, "texInPolyID");
|
||||
glUniform1i(uniformTexGDepth, OGLTextureUnitID_DepthStencil);
|
||||
glUniform1i(uniformTexGPolyID, OGLTextureUnitID_GPolyID);
|
||||
|
||||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError OpenGLESRenderer_3_0::CreateFogProgram(const OGLFogProgramKey fogProgramKey, const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString)
|
||||
{
|
||||
Render3DError error = OGLERROR_NOERR;
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
if (vtxShaderCString == NULL)
|
||||
{
|
||||
INFO("OpenGL ES: The FOG vertex shader is unavailable.\n");
|
||||
error = OGLERROR_VERTEX_SHADER_PROGRAM_LOAD_ERROR;
|
||||
return error;
|
||||
}
|
||||
else if (fragShaderCString == NULL)
|
||||
{
|
||||
INFO("OpenGL ES: The FOG fragment shader is unavailable.\n");
|
||||
error = OGLERROR_FRAGMENT_SHADER_PROGRAM_LOAD_ERROR;
|
||||
return error;
|
||||
}
|
||||
|
||||
const s32 fogOffset = fogProgramKey.offset;
|
||||
const GLfloat fogOffsetf = (GLfloat)fogOffset / 32767.0f;
|
||||
const s32 fogStep = 0x0400 >> fogProgramKey.shift;
|
||||
|
||||
std::stringstream shaderHeader;
|
||||
shaderHeader << "#version 300 es\n";
|
||||
shaderHeader << "precision highp float;\n";
|
||||
shaderHeader << "precision highp int;\n";
|
||||
shaderHeader << "\n";
|
||||
|
||||
std::stringstream vsHeader;
|
||||
vsHeader << "#define IN_VTX_POSITION layout (location = " << OGLVertexAttributeID_Position << ") in\n";
|
||||
vsHeader << "#define IN_VTX_TEXCOORD0 layout (location = " << OGLVertexAttributeID_TexCoord0 << ") in\n";
|
||||
vsHeader << "#define IN_VTX_COLOR layout (location = " << OGLVertexAttributeID_Color << ") in\n";
|
||||
|
||||
std::stringstream fsHeader;
|
||||
fsHeader << "#define FOG_OFFSET " << fogOffset << "\n";
|
||||
fsHeader << "#define FOG_OFFSETF " << fogOffsetf << (((fogOffsetf == 0.0f) || (fogOffsetf == 1.0f)) ? ".0" : "") << "\n";
|
||||
fsHeader << "#define FOG_STEP " << fogStep << "\n";
|
||||
fsHeader << "\n";
|
||||
fsHeader << "#define OUT_COLOR layout (location = 0) out\n";
|
||||
|
||||
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(vtxShaderCString);
|
||||
std::string fragShaderCode = shaderHeader.str() + fsHeader.str() + std::string(fragShaderCString);
|
||||
|
||||
OGLFogShaderID shaderID;
|
||||
shaderID.program = 0;
|
||||
shaderID.fragShader = 0;
|
||||
|
||||
error = this->ShaderProgramCreate(OGLRef.vertexFogShaderID,
|
||||
shaderID.fragShader,
|
||||
shaderID.program,
|
||||
vtxShaderCode.c_str(),
|
||||
fragShaderCode.c_str());
|
||||
|
||||
this->_fogProgramMap[fogProgramKey.key] = shaderID;
|
||||
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
INFO("OpenGL ES: Failed to create the FOG shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyFogProgram(fogProgramKey);
|
||||
return error;
|
||||
}
|
||||
|
||||
glLinkProgram(shaderID.program);
|
||||
if (!this->ValidateShaderProgramLink(shaderID.program))
|
||||
{
|
||||
INFO("OpenGL ES: Failed to link the FOG shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyFogProgram(fogProgramKey);
|
||||
return OGLERROR_SHADER_CREATE_ERROR;
|
||||
}
|
||||
|
||||
glValidateProgram(shaderID.program);
|
||||
glUseProgram(shaderID.program);
|
||||
|
||||
const GLuint uniformBlockRenderStates = glGetUniformBlockIndex(shaderID.program, "RenderStates");
|
||||
glUniformBlockBinding(shaderID.program, uniformBlockRenderStates, OGLBindingPointID_RenderStates);
|
||||
|
||||
const GLint uniformTexGDepth = glGetUniformLocation(shaderID.program, "texInFragDepth");
|
||||
const GLint uniformTexGFog = glGetUniformLocation(shaderID.program, "texInFogAttributes");
|
||||
const GLint uniformTexFogDensityTable = glGetUniformLocation(shaderID.program, "texFogDensityTable");
|
||||
glUniform1i(uniformTexGDepth, OGLTextureUnitID_DepthStencil);
|
||||
glUniform1i(uniformTexGFog, OGLTextureUnitID_FogAttr);
|
||||
glUniform1i(uniformTexFogDensityTable, OGLTextureUnitID_LookupTable);
|
||||
|
||||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError OpenGLESRenderer_3_0::CreateFramebufferOutput6665Program(const char *vtxShaderCString, const char *fragShaderCString)
|
||||
{
|
||||
Render3DError error = OGLERROR_NOERR;
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
if ( (vtxShaderCString == NULL) || (fragShaderCString == NULL) )
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
std::stringstream shaderHeader;
|
||||
shaderHeader << "#version 300 es\n";
|
||||
shaderHeader << "precision highp float;\n";
|
||||
shaderHeader << "precision highp int;\n";
|
||||
shaderHeader << "\n";
|
||||
shaderHeader << "#define FRAMEBUFFER_SIZE_X " << this->_framebufferWidth << ".0 \n";
|
||||
shaderHeader << "#define FRAMEBUFFER_SIZE_Y " << this->_framebufferHeight << ".0 \n";
|
||||
shaderHeader << "\n";
|
||||
|
||||
std::stringstream vsHeader;
|
||||
vsHeader << "#define IN_VTX_POSITION layout (location = " << OGLVertexAttributeID_Position << ") in\n";
|
||||
vsHeader << "#define IN_VTX_TEXCOORD0 layout (location = " << OGLVertexAttributeID_TexCoord0 << ") in\n";
|
||||
vsHeader << "#define IN_VTX_COLOR layout (location = " << OGLVertexAttributeID_Color << ") in\n";
|
||||
|
||||
std::stringstream fsHeader;
|
||||
fsHeader << "#define OUT_COLOR layout (location = " << (OGL_WORKING_ATTACHMENT_ID - GL_COLOR_ATTACHMENT0) << ") out\n";
|
||||
|
||||
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(vtxShaderCString);
|
||||
std::string fragShaderCode = shaderHeader.str() + fsHeader.str() + std::string(fragShaderCString);
|
||||
|
||||
error = this->ShaderProgramCreate(OGLRef.vertexFramebufferOutput6665ShaderID,
|
||||
OGLRef.fragmentFramebufferRGBA6665OutputShaderID,
|
||||
OGLRef.programFramebufferRGBA6665OutputID,
|
||||
vtxShaderCode.c_str(),
|
||||
fragShaderCode.c_str());
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
INFO("OpenGL ES: Failed to create the FRAMEBUFFER OUTPUT RGBA6665 shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyFramebufferOutput6665Programs();
|
||||
return error;
|
||||
}
|
||||
|
||||
glLinkProgram(OGLRef.programFramebufferRGBA6665OutputID);
|
||||
if (!this->ValidateShaderProgramLink(OGLRef.programFramebufferRGBA6665OutputID))
|
||||
{
|
||||
INFO("OpenGL ES: Failed to link the FRAMEBUFFER OUTPUT RGBA6665 shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyFramebufferOutput6665Programs();
|
||||
return OGLERROR_SHADER_CREATE_ERROR;
|
||||
}
|
||||
|
||||
glValidateProgram(OGLRef.programFramebufferRGBA6665OutputID);
|
||||
glUseProgram(OGLRef.programFramebufferRGBA6665OutputID);
|
||||
|
||||
const GLint uniformTexGColor = glGetUniformLocation(OGLRef.programFramebufferRGBA6665OutputID, "texInFragColor");
|
||||
glUniform1i(uniformTexGColor, OGLTextureUnitID_GColor);
|
||||
|
||||
return OGLERROR_NOERR;
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
Copyright (C) 2024 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OGLRENDER_ES3_H
|
||||
#define OGLRENDER_ES3_H
|
||||
|
||||
#include "OGLRender_3_2.h"
|
||||
|
||||
// A port that wants to use the OpenGL ES renderer must assign the two following functions
|
||||
// to OGLLoadEntryPoints_ES_3_0_Func and OGLCreateRenderer_ES_3_0_Func, respectively.
|
||||
//
|
||||
// In addition, the port must add the following GPU3DInterface objects to core3DList:
|
||||
// - gpu3Dgl_ES_3_0: Selects the OpenGL ES 3.0 renderer, and returns an error if it is
|
||||
// not available on the host system.
|
||||
//
|
||||
// Finally, the port must call GPU->Set3DRendererByID() and pass in the index where
|
||||
// gpu3Dgl_ES_3_0 exists in core3DList so that the emulator can create the appropriate
|
||||
// OpenGLRenderer object.
|
||||
//
|
||||
// Example code:
|
||||
// OGLLoadEntryPoints_ES_3_0_Func = &OGLLoadEntryPoints_ES_3_0;
|
||||
// OGLCreateRenderer_ES_3_0_Func = &OGLCreateRenderer_ES_3_0;
|
||||
// GPU3DInterface *core3DList[] = { &gpu3DNull, &gpu3DRasterize, &gpu3Dgl_ES_3_0, NULL };
|
||||
// GPU->Set3DRendererByID(2);
|
||||
|
||||
void OGLLoadEntryPoints_ES_3_0();
|
||||
void OGLCreateRenderer_ES_3_0(OpenGLRenderer **rendererPtr);
|
||||
|
||||
class OpenGLESRenderer_3_0 : public OpenGLRenderer_3_2
|
||||
{
|
||||
protected:
|
||||
virtual Render3DError CreateGeometryPrograms();
|
||||
virtual Render3DError CreateClearImageProgram(const char *vsCString, const char *fsCString);
|
||||
virtual Render3DError CreateGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString);
|
||||
virtual Render3DError CreateEdgeMarkProgram(const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString);
|
||||
virtual Render3DError CreateFogProgram(const OGLFogProgramKey fogProgramKey, const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString);
|
||||
virtual Render3DError CreateFramebufferOutput6665Program(const char *vtxShaderCString, const char *fragShaderCString);
|
||||
|
||||
public:
|
||||
OpenGLESRenderer_3_0();
|
||||
|
||||
virtual Render3DError InitExtensions();
|
||||
};
|
||||
|
||||
#endif // OGLRENDER_ES3_H
|
|
@ -0,0 +1,3 @@
|
|||
#ifndef __GNUC__
|
||||
#pragma pack(pop)
|
||||
#endif
|
|
@ -0,0 +1,375 @@
|
|||
/*
|
||||
Copyright 2007 Guillaume Duhamel
|
||||
Copyright 2007-2017 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ROMReader.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_LIBZZIP
|
||||
#include <zzip/zzip.h>
|
||||
#endif
|
||||
|
||||
#include "utils/xstring.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define stat(...) _stat(__VA_ARGS__)
|
||||
#define S_IFMT _S_IFMT
|
||||
#define S_IFREG _S_IFREG
|
||||
#endif
|
||||
|
||||
ROMReader_struct * ROMReaderInit(char ** filename)
|
||||
{
|
||||
#ifdef HAVE_LIBZ
|
||||
if(!strcasecmp(".gz", *filename + (strlen(*filename) - 3)))
|
||||
{
|
||||
(*filename)[strlen(*filename) - 3] = '\0';
|
||||
return &GZIPROMReader;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_LIBZZIP
|
||||
if (!strcasecmp(".zip", *filename + (strlen(*filename) - 4)))
|
||||
{
|
||||
(*filename)[strlen(*filename) - 4] = '\0';
|
||||
return &ZIPROMReader;
|
||||
}
|
||||
#endif
|
||||
return &STDROMReader;
|
||||
}
|
||||
|
||||
void * STDROMReaderInit(const char * filename);
|
||||
void STDROMReaderDeInit(void *);
|
||||
u32 STDROMReaderSize(void *);
|
||||
int STDROMReaderSeek(void *, int, int);
|
||||
int STDROMReaderRead(void *, void *, u32);
|
||||
int STDROMReaderWrite(void *, void *, u32);
|
||||
|
||||
ROMReader_struct STDROMReader =
|
||||
{
|
||||
ROMREADER_STD,
|
||||
"Standard ROM Reader",
|
||||
STDROMReaderInit,
|
||||
STDROMReaderDeInit,
|
||||
STDROMReaderSize,
|
||||
STDROMReaderSeek,
|
||||
STDROMReaderRead,
|
||||
STDROMReaderWrite
|
||||
};
|
||||
|
||||
struct STDROMReaderData
|
||||
{
|
||||
FILE* file;
|
||||
long pos;
|
||||
};
|
||||
|
||||
void* STDROMReaderInit(const char* filename)
|
||||
{
|
||||
#ifndef _MSC_VER
|
||||
struct stat sb;
|
||||
if (stat(filename, &sb) == -1)
|
||||
return 0;
|
||||
|
||||
if ((sb.st_mode & S_IFMT) != S_IFREG)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
FILE* inf = _wfopen(mbstowcs((std::string)filename).c_str(),L"rb");
|
||||
#else
|
||||
FILE* inf = fopen(filename, "rb");
|
||||
#endif
|
||||
|
||||
if(!inf) return NULL;
|
||||
|
||||
STDROMReaderData* ret = new STDROMReaderData();
|
||||
ret->file = inf;
|
||||
ret->pos = 0;
|
||||
return (void*)ret;
|
||||
}
|
||||
|
||||
|
||||
void STDROMReaderDeInit(void * file)
|
||||
{
|
||||
if (!file) return ;
|
||||
fclose(((STDROMReaderData*)file)->file);
|
||||
delete ((STDROMReaderData*)file);
|
||||
}
|
||||
|
||||
u32 STDROMReaderSize(void * file)
|
||||
{
|
||||
u32 size;
|
||||
|
||||
if (!file) return 0;
|
||||
|
||||
FILE* inf = ((STDROMReaderData*)file)->file;
|
||||
|
||||
fseek(inf, 0, SEEK_END);
|
||||
size = ftell(inf);
|
||||
fseek(inf, ((STDROMReaderData*)file)->pos, SEEK_SET);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int STDROMReaderSeek(void * file, int offset, int whence)
|
||||
{
|
||||
//not normal fseek return value meanings. awesome.
|
||||
if (!file) return 0;
|
||||
if(whence == SEEK_SET && offset == ((STDROMReaderData*)file)->pos)
|
||||
return 1;
|
||||
fseek(((STDROMReaderData*)file)->file, offset, whence);
|
||||
((STDROMReaderData*)file)->pos = ftell(((STDROMReaderData*)file)->file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int STDROMReaderRead(void * file, void * buffer, u32 size)
|
||||
{
|
||||
if (!file) return 0;
|
||||
int read = fread(buffer, 1, size, ((STDROMReaderData*)file)->file);
|
||||
((STDROMReaderData*)file)->pos += read;
|
||||
return read;
|
||||
}
|
||||
|
||||
int STDROMReaderWrite(void *, void *, u32)
|
||||
{
|
||||
//not supported, for now
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
void * GZIPROMReaderInit(const char * filename);
|
||||
void GZIPROMReaderDeInit(void *);
|
||||
u32 GZIPROMReaderSize(void *);
|
||||
int GZIPROMReaderSeek(void *, int, int);
|
||||
int GZIPROMReaderRead(void *, void *, u32);
|
||||
int GZIPROMReaderWrite(void *, void *, u32);
|
||||
|
||||
ROMReader_struct GZIPROMReader =
|
||||
{
|
||||
ROMREADER_GZIP,
|
||||
"Gzip ROM Reader",
|
||||
GZIPROMReaderInit,
|
||||
GZIPROMReaderDeInit,
|
||||
GZIPROMReaderSize,
|
||||
GZIPROMReaderSeek,
|
||||
GZIPROMReaderRead,
|
||||
GZIPROMReaderWrite
|
||||
};
|
||||
|
||||
void * GZIPROMReaderInit(const char * filename)
|
||||
{
|
||||
return (void*)gzopen(filename, "rb");
|
||||
}
|
||||
|
||||
void GZIPROMReaderDeInit(void * file)
|
||||
{
|
||||
gzclose((gzFile)file);
|
||||
}
|
||||
|
||||
u32 GZIPROMReaderSize(void * file)
|
||||
{
|
||||
char useless[1024];
|
||||
u32 size = 0;
|
||||
|
||||
/* FIXME this function should first save the current
|
||||
* position and restore it after size calculation */
|
||||
gzrewind((gzFile)file);
|
||||
while (gzeof ((gzFile)file) == 0)
|
||||
size += gzread((gzFile)file, useless, 1024);
|
||||
gzrewind((gzFile)file);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int GZIPROMReaderSeek(void * file, int offset, int whence)
|
||||
{
|
||||
return gzseek((gzFile)file, offset, whence);
|
||||
}
|
||||
|
||||
int GZIPROMReaderRead(void * file, void * buffer, u32 size)
|
||||
{
|
||||
return gzread((gzFile)file, buffer, size);
|
||||
}
|
||||
|
||||
int GZIPROMReaderWrite(void *, void *, u32)
|
||||
{
|
||||
//not supported, ever
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBZZIP
|
||||
void * ZIPROMReaderInit(const char * filename);
|
||||
void ZIPROMReaderDeInit(void *);
|
||||
u32 ZIPROMReaderSize(void *);
|
||||
int ZIPROMReaderSeek(void *, int, int);
|
||||
int ZIPROMReaderRead(void *, void *, u32);
|
||||
int ZIPROMReaderWrite(void *, void *, u32);
|
||||
|
||||
ROMReader_struct ZIPROMReader =
|
||||
{
|
||||
ROMREADER_ZIP,
|
||||
"Zip ROM Reader",
|
||||
ZIPROMReaderInit,
|
||||
ZIPROMReaderDeInit,
|
||||
ZIPROMReaderSize,
|
||||
ZIPROMReaderSeek,
|
||||
ZIPROMReaderRead,
|
||||
ZIPROMReaderWrite
|
||||
};
|
||||
|
||||
void * ZIPROMReaderInit(const char * filename)
|
||||
{
|
||||
ZZIP_DIR * dir = zzip_opendir(filename);
|
||||
ZZIP_DIRENT * dirent = zzip_readdir(dir);
|
||||
if (dir != NULL)
|
||||
{
|
||||
char *tmp1;
|
||||
char tmp2[1024];
|
||||
|
||||
memset(tmp2,0,sizeof(tmp2));
|
||||
tmp1 = strndup(filename, strlen(filename) - 4);
|
||||
sprintf(tmp2, "%s/%s", tmp1, dirent->d_name);
|
||||
free(tmp1);
|
||||
return zzip_fopen(tmp2, "rb");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ZIPROMReaderDeInit(void * file)
|
||||
{
|
||||
zzip_close((ZZIP_FILE*)file);
|
||||
}
|
||||
|
||||
u32 ZIPROMReaderSize(void * file)
|
||||
{
|
||||
u32 size;
|
||||
|
||||
zzip_seek((ZZIP_FILE*)file, 0, SEEK_END);
|
||||
size = zzip_tell((ZZIP_FILE*)file);
|
||||
zzip_seek((ZZIP_FILE*)file, 0, SEEK_SET);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int ZIPROMReaderSeek(void * file, int offset, int whence)
|
||||
{
|
||||
return zzip_seek((ZZIP_FILE*)file, offset, whence);
|
||||
}
|
||||
|
||||
int ZIPROMReaderRead(void * file, void * buffer, u32 size)
|
||||
{
|
||||
#ifdef ZZIP_OLD_READ
|
||||
return zzip_read((ZZIP_FILE*)file, (char *) buffer, size);
|
||||
#else
|
||||
return zzip_read((ZZIP_FILE*)file, buffer, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
int ZIPROMReaderWrite(void *, void *, u32)
|
||||
{
|
||||
//not supported ever
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct {
|
||||
void* buf;
|
||||
int len;
|
||||
int pos;
|
||||
} mem;
|
||||
|
||||
void * MemROMReaderInit(const char * filename)
|
||||
{
|
||||
return NULL; //dummy
|
||||
}
|
||||
|
||||
void MemROMReaderDeInit(void *)
|
||||
{
|
||||
//nothing to do
|
||||
}
|
||||
u32 MemROMReaderSize(void *)
|
||||
{
|
||||
return (u32)mem.len;
|
||||
}
|
||||
int MemROMReaderSeek(void * file, int offset, int whence)
|
||||
{
|
||||
switch(whence) {
|
||||
case SEEK_SET:
|
||||
mem.pos = offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
mem.pos += offset;
|
||||
break;
|
||||
case SEEK_END:
|
||||
mem.pos = mem.len + offset;
|
||||
break;
|
||||
}
|
||||
return mem.pos;
|
||||
}
|
||||
|
||||
int MemROMReaderRead(void * file, void * buffer, u32 size)
|
||||
{
|
||||
if(mem.pos<0) return 0;
|
||||
|
||||
int todo = (int)size;
|
||||
int remain = mem.len - mem.pos;
|
||||
if(remain<todo)
|
||||
todo = remain;
|
||||
|
||||
if(todo<=0)
|
||||
return 0;
|
||||
else if(todo==1) *(u8*)buffer = ((u8*)mem.buf)[mem.pos];
|
||||
else memcpy(buffer,(u8*)mem.buf + mem.pos, todo);
|
||||
mem.pos += todo;
|
||||
return todo;
|
||||
}
|
||||
|
||||
int MemROMReaderWrite(void * file, void * buffer, u32 size)
|
||||
{
|
||||
if(mem.pos<0) return 0;
|
||||
|
||||
int todo = (int)size;
|
||||
int remain = mem.len - mem.pos;
|
||||
if(remain<todo)
|
||||
todo = remain;
|
||||
|
||||
if (todo == 1) ((u8*)mem.buf)[mem.pos] = *(u8*)buffer;
|
||||
else memcpy((u8*)mem.buf + mem.pos,buffer, todo);
|
||||
mem.pos += todo;
|
||||
return todo;
|
||||
}
|
||||
|
||||
static ROMReader_struct MemROMReader =
|
||||
{
|
||||
ROMREADER_MEM,
|
||||
"Memory ROM Reader",
|
||||
MemROMReaderInit,
|
||||
MemROMReaderDeInit,
|
||||
MemROMReaderSize,
|
||||
MemROMReaderSeek,
|
||||
MemROMReaderRead,
|
||||
MemROMReaderWrite,
|
||||
};
|
||||
|
||||
ROMReader_struct * MemROMReaderRead_TrueInit(void* buf, int length)
|
||||
{
|
||||
mem.buf = buf;
|
||||
mem.len = length;
|
||||
mem.pos = 0;
|
||||
return &MemROMReader;
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
Copyright (C) 2007 Guillaume Duhamel
|
||||
Copyright (C) 2007-2022 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _ROMREADER_H_
|
||||
#define _ROMREADER_H_
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define ROMREADER_DEFAULT -1
|
||||
#define ROMREADER_STD 0
|
||||
#define ROMREADER_GZIP 1
|
||||
#define ROMREADER_ZIP 2
|
||||
#define ROMREADER_MEM 3
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int id;
|
||||
const char * Name;
|
||||
void * (*Init)(const char * filename);
|
||||
void (*DeInit)(void * file);
|
||||
u32 (*Size)(void * file);
|
||||
int (*Seek)(void * file, int offset, int whence);
|
||||
int (*Read)(void * file, void * buffer, u32 size);
|
||||
int (*Write)(void * file, void * buffer, u32 size);
|
||||
} ROMReader_struct;
|
||||
|
||||
extern ROMReader_struct STDROMReader;
|
||||
#ifdef HAVE_LIBZ
|
||||
extern ROMReader_struct GZIPROMReader;
|
||||
#endif
|
||||
#ifdef HAVE_LIBZZIP
|
||||
extern ROMReader_struct ZIPROMReader;
|
||||
#endif
|
||||
|
||||
ROMReader_struct * ROMReaderInit(char ** filename);
|
||||
ROMReader_struct * MemROMReaderRead_TrueInit(void* buf, int length);
|
||||
|
||||
#endif // _ROMREADER_H_
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,305 @@
|
|||
/*
|
||||
Copyright 2006 Theo Berkau
|
||||
Copyright (C) 2006-2015 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SPU_H
|
||||
#define SPU_H
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "matrix.h"
|
||||
#include "metaspu/metaspu.h"
|
||||
|
||||
class EMUFILE;
|
||||
|
||||
#define SNDCORE_DEFAULT -1
|
||||
#define SNDCORE_DUMMY 0
|
||||
|
||||
#define CHANSTAT_STOPPED 0
|
||||
#define CHANSTAT_PLAY 1
|
||||
|
||||
#define SPUINTERPOLATION_TAPS 4 // Must be at least 4 for Catmull-Rom interpolation
|
||||
|
||||
//who made these static? theyre used in multiple places.
|
||||
FORCEINLINE s32 spumuldiv7(s32 val, u8 multiplier) {
|
||||
assert(multiplier <= 127);
|
||||
return (multiplier == 127) ? val : ((val * multiplier) >> 7);
|
||||
}
|
||||
|
||||
enum SPUInterpolationMode
|
||||
{
|
||||
SPUInterpolation_None = 0,
|
||||
SPUInterpolation_Linear = 1,
|
||||
SPUInterpolation_Cosine = 2,
|
||||
SPUInterpolation_CatmullRom = 3
|
||||
};
|
||||
|
||||
struct SoundInterface_struct
|
||||
{
|
||||
int id;
|
||||
const char *Name;
|
||||
int (*Init)(int buffersize);
|
||||
void (*DeInit)();
|
||||
void (*UpdateAudio)(s16 *buffer, u32 num_samples);
|
||||
u32 (*GetAudioSpace)();
|
||||
void (*MuteAudio)();
|
||||
void (*UnMuteAudio)();
|
||||
void (*SetVolume)(int volume);
|
||||
void (*ClearBuffer)();
|
||||
void (*FetchSamples)(s16 *sampleBuffer, size_t sampleCount, ESynchMode synchMode, ISynchronizingAudioBuffer *theSynchronizer);
|
||||
size_t (*PostProcessSamples)(s16 *postProcessBuffer, size_t requestedSampleCount, ESynchMode synchMode, ISynchronizingAudioBuffer *theSynchronizer);
|
||||
};
|
||||
|
||||
extern SoundInterface_struct SNDDummy;
|
||||
extern SoundInterface_struct SNDFile;
|
||||
extern int SPU_currentCoreNum;
|
||||
|
||||
struct channel_struct
|
||||
{
|
||||
channel_struct() : num(0),
|
||||
vol(0),
|
||||
volumeDiv(0),
|
||||
hold(0),
|
||||
pan(0),
|
||||
waveduty(0),
|
||||
repeat(0),
|
||||
format(0),
|
||||
keyon(0),
|
||||
status(0),
|
||||
pcm16bOffs(0),
|
||||
addr(0),
|
||||
timer(0),
|
||||
loopstart(0),
|
||||
length(0),
|
||||
totlength(0),
|
||||
totlength_shifted(0),
|
||||
sampcntFrac(0),
|
||||
sampcntInt(0),
|
||||
sampincFrac(0),
|
||||
sampincInt(0),
|
||||
loop_pcm16b(0),
|
||||
index(0),
|
||||
loop_index(0),
|
||||
x(0)
|
||||
{}
|
||||
u32 num;
|
||||
u8 vol;
|
||||
u8 volumeDiv;
|
||||
u8 hold;
|
||||
u8 pan;
|
||||
u8 waveduty;
|
||||
u8 repeat;
|
||||
u8 format;
|
||||
u8 keyon;
|
||||
u8 status;
|
||||
u8 pcm16bOffs;
|
||||
u32 addr;
|
||||
u16 timer;
|
||||
u16 loopstart;
|
||||
u32 length;
|
||||
u32 totlength;
|
||||
s32 totlength_shifted;
|
||||
u32 sampcntFrac;
|
||||
s32 sampcntInt;
|
||||
u32 sampincFrac;
|
||||
u32 sampincInt;
|
||||
s16 pcm16b[SPUINTERPOLATION_TAPS];
|
||||
// ADPCM specific
|
||||
s16 loop_pcm16b;
|
||||
s32 index;
|
||||
int loop_index;
|
||||
// PSG noise
|
||||
u16 x;
|
||||
};
|
||||
|
||||
class SPUFifo
|
||||
{
|
||||
public:
|
||||
SPUFifo();
|
||||
void enqueue(s16 val);
|
||||
s16 dequeue();
|
||||
s16 buffer[16];
|
||||
s32 head,tail,size;
|
||||
void save(EMUFILE &fp);
|
||||
bool load(EMUFILE &fp);
|
||||
void reset();
|
||||
};
|
||||
|
||||
class SPU_struct
|
||||
{
|
||||
public:
|
||||
SPU_struct(int buffersize);
|
||||
u32 bufpos;
|
||||
u32 buflength;
|
||||
s32 *sndbuf;
|
||||
s32 lastdata; //the last sample that a channel generated
|
||||
s16 *outbuf;
|
||||
u32 bufsize;
|
||||
channel_struct channels[16];
|
||||
|
||||
//registers
|
||||
struct REGS {
|
||||
REGS()
|
||||
: mastervol(0)
|
||||
, ctl_left(0)
|
||||
, ctl_right(0)
|
||||
, ctl_ch1bypass(0)
|
||||
, ctl_ch3bypass(0)
|
||||
, masteren(0)
|
||||
, soundbias(0)
|
||||
{}
|
||||
|
||||
u8 mastervol;
|
||||
u8 ctl_left, ctl_right;
|
||||
u8 ctl_ch1bypass, ctl_ch3bypass;
|
||||
u8 masteren;
|
||||
u16 soundbias;
|
||||
|
||||
enum LeftOutputMode
|
||||
{
|
||||
LOM_LEFT_MIXER=0, LOM_CH1=1, LOM_CH3=2, LOM_CH1_PLUS_CH3=3
|
||||
};
|
||||
|
||||
enum RightOutputMode
|
||||
{
|
||||
ROM_RIGHT_MIXER=0, ROM_CH1=1, ROM_CH3=2, ROM_CH1_PLUS_CH3=3
|
||||
};
|
||||
|
||||
struct CAP {
|
||||
CAP()
|
||||
: add(0), source(0), oneshot(0), bits8(0), active(0), dad(0), len(0)
|
||||
{}
|
||||
u8 add, source, oneshot, bits8, active;
|
||||
u32 dad;
|
||||
u16 len;
|
||||
struct Runtime {
|
||||
Runtime()
|
||||
: running(0), curdad(0), maxdad(0)
|
||||
{}
|
||||
u8 running;
|
||||
u32 curdad;
|
||||
u32 maxdad;
|
||||
u32 sampcntFrac;
|
||||
u32 sampcntInt;
|
||||
SPUFifo fifo;
|
||||
} runtime;
|
||||
} cap[2];
|
||||
} regs;
|
||||
|
||||
void reset();
|
||||
~SPU_struct();
|
||||
void KeyOff(int channel);
|
||||
void KeyOn(int channel);
|
||||
void KeyProbe(int channel);
|
||||
void ProbeCapture(int which);
|
||||
void WriteByte(u32 addr, u8 val);
|
||||
void WriteWord(u32 addr, u16 val);
|
||||
void WriteLong(u32 addr, u32 val);
|
||||
u8 ReadByte(u32 addr);
|
||||
u16 ReadWord(u32 addr);
|
||||
u32 ReadLong(u32 addr);
|
||||
bool isSPU(u32 addr) { return ((addr >= 0x04000400) && (addr < 0x04000520)); }
|
||||
|
||||
//kills all channels but leaves SPU otherwise running normally
|
||||
void ShutUp();
|
||||
};
|
||||
|
||||
extern SPU_struct *SPU_core, *SPU_user;
|
||||
extern int spu_core_samples;
|
||||
|
||||
int SPU_ChangeSoundCore(int coreid, int newBufferSizeBytes);
|
||||
SoundInterface_struct *SPU_SoundCore();
|
||||
|
||||
void SPU_ReInit(bool fakeBoot = false);
|
||||
int SPU_Init(int coreid, int newBufferSizeBytes);
|
||||
void SPU_Pause(int pause);
|
||||
void SPU_SetVolume(int newVolume);
|
||||
void SPU_SetSynchMode(int mode, int method);
|
||||
void SPU_ClearOutputBuffer(void);
|
||||
void SPU_Reset(void);
|
||||
void SPU_DeInit(void);
|
||||
void SPU_KeyOn(int channel);
|
||||
static FORCEINLINE void SPU_WriteByte(u32 addr, u8 val)
|
||||
{
|
||||
addr &= 0xFFF;
|
||||
|
||||
SPU_core->WriteByte(addr,val);
|
||||
if(SPU_user)
|
||||
SPU_user->WriteByte(addr,val);
|
||||
}
|
||||
static FORCEINLINE void SPU_WriteWord(u32 addr, u16 val)
|
||||
{
|
||||
addr &= 0xFFF;
|
||||
|
||||
SPU_core->WriteWord(addr,val);
|
||||
if(SPU_user)
|
||||
SPU_user->WriteWord(addr,val);
|
||||
}
|
||||
static FORCEINLINE void SPU_WriteLong(u32 addr, u32 val)
|
||||
{
|
||||
addr &= 0xFFF;
|
||||
|
||||
SPU_core->WriteLong(addr,val);
|
||||
if(SPU_user)
|
||||
SPU_user->WriteLong(addr,val);
|
||||
}
|
||||
static FORCEINLINE u8 SPU_ReadByte(u32 addr) { return SPU_core->ReadByte(addr & 0x0FFF); }
|
||||
static FORCEINLINE u16 SPU_ReadWord(u32 addr) { return SPU_core->ReadWord(addr & 0x0FFF); }
|
||||
static FORCEINLINE u32 SPU_ReadLong(u32 addr) { return SPU_core->ReadLong(addr & 0x0FFF); }
|
||||
void SPU_Emulate_core(void);
|
||||
void SPU_Emulate_user(bool mix = true);
|
||||
void SPU_DefaultFetchSamples(s16 *sampleBuffer, size_t sampleCount, ESynchMode synchMode, ISynchronizingAudioBuffer *theSynchronizer);
|
||||
size_t SPU_DefaultPostProcessSamples(s16 *postProcessBuffer, size_t requestedSampleCount, ESynchMode synchMode, ISynchronizingAudioBuffer *theSynchronizer);
|
||||
|
||||
void spu_savestate(EMUFILE &os);
|
||||
bool spu_loadstate(EMUFILE &is, int size);
|
||||
|
||||
enum WAVMode
|
||||
{
|
||||
WAVMODE_ANY = -1,
|
||||
WAVMODE_CORE = 0,
|
||||
WAVMODE_USER = 1
|
||||
};
|
||||
|
||||
class WavWriter
|
||||
{
|
||||
public:
|
||||
WavWriter();
|
||||
bool open(const std::string & fname);
|
||||
void close();
|
||||
void update(void* soundData, int numSamples);
|
||||
bool isRecording() const;
|
||||
WAVMode mode;
|
||||
private:
|
||||
FILE *spufp;
|
||||
};
|
||||
|
||||
void WAV_End();
|
||||
bool WAV_Begin(const char* fname, WAVMode mode=WAVMODE_CORE);
|
||||
bool WAV_IsRecording(WAVMode mode=WAVMODE_ANY);
|
||||
void WAV_WavSoundUpdate(void* soundData, int numSamples, WAVMode mode=WAVMODE_CORE);
|
||||
|
||||
// we should make this configurable eventually
|
||||
// but at least defining it somewhere is probably a step in the right direction
|
||||
#define DESMUME_SAMPLE_RATE 44100
|
||||
//#define DESMUME_SAMPLE_RATE 48000
|
||||
|
||||
#endif
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
Copyright (C) 2010-2015 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../slot1.h"
|
||||
|
||||
class Slot1_None : public ISlot1Interface
|
||||
{
|
||||
public:
|
||||
virtual Slot1Info const* info()
|
||||
{
|
||||
static Slot1InfoSimple info("None","Slot1 no-card emulation", 0xFF);
|
||||
return &info;
|
||||
}
|
||||
|
||||
//pretty much every access to the card should just be ignored and reading HIGH-Z off the GC bus.
|
||||
//so, nothing really to do here
|
||||
//(notably, it results in a 0xFFFFFFFF card ID)
|
||||
|
||||
};
|
||||
|
||||
ISlot1Interface* construct_Slot1_None() { return new Slot1_None(); }
|
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
Copyright (C) 2010-2021 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "slot1comp_protocol.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "../slot1.h"
|
||||
#include "../NDSSystem.h"
|
||||
#include "../emufile.h"
|
||||
|
||||
class Slot1_R4 : public ISlot1Interface, public ISlot1Comp_Protocol_Client
|
||||
{
|
||||
private:
|
||||
EMUFILE *img;
|
||||
Slot1Comp_Protocol protocol;
|
||||
u32 write_count;
|
||||
u32 write_enabled;
|
||||
|
||||
public:
|
||||
Slot1_R4()
|
||||
: img(NULL)
|
||||
, write_count(0)
|
||||
, write_enabled(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Slot1Info const* info()
|
||||
{
|
||||
static Slot1InfoSimple info("R4", "Slot1 R4 emulation", 0x03);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
img = slot1_GetFatImage();
|
||||
|
||||
if(!img)
|
||||
INFO("slot1 fat not successfully mounted\n");
|
||||
|
||||
protocol.reset(this);
|
||||
protocol.chipId = 0xFC2;
|
||||
protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0);
|
||||
}
|
||||
|
||||
//called when the emulator disconnects the device
|
||||
virtual void disconnect()
|
||||
{
|
||||
img = NULL;
|
||||
}
|
||||
|
||||
//called when the emulator shuts down, or when the device disappears from existence
|
||||
virtual void shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual void write_command(u8 PROCNUM, GC_Command command)
|
||||
{
|
||||
protocol.write_command(command);
|
||||
}
|
||||
virtual void write_GCDATAIN(u8 PROCNUM, u32 val)
|
||||
{
|
||||
protocol.write_GCDATAIN(PROCNUM, val);
|
||||
}
|
||||
virtual u32 read_GCDATAIN(u8 PROCNUM)
|
||||
{
|
||||
return protocol.read_GCDATAIN(PROCNUM);
|
||||
}
|
||||
|
||||
virtual void slot1client_startOperation(eSlot1Operation theOperation)
|
||||
{
|
||||
if (theOperation != eSlot1Operation_Unknown)
|
||||
return;
|
||||
|
||||
u32 address;
|
||||
int cmd = protocol.command.bytes[0];
|
||||
switch(cmd)
|
||||
{
|
||||
case 0xB0:
|
||||
break;
|
||||
case 0xB9:
|
||||
case 0xBA:
|
||||
address = (protocol.command.bytes[1] << 24) | (protocol.command.bytes[2] << 16) | (protocol.command.bytes[3] << 8) | protocol.command.bytes[4];
|
||||
img->fseek(address,SEEK_SET);
|
||||
break;
|
||||
case 0xBB:
|
||||
write_enabled = 1;
|
||||
write_count = 0x80;
|
||||
//passthrough on purpose?
|
||||
case 0xBC:
|
||||
address = (protocol.command.bytes[1] << 24) | (protocol.command.bytes[2] << 16) | (protocol.command.bytes[3] << 8) | protocol.command.bytes[4];
|
||||
img->fseek(address,SEEK_SET);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual u32 slot1client_read_GCDATAIN(eSlot1Operation theOperation)
|
||||
{
|
||||
if (theOperation != eSlot1Operation_Unknown)
|
||||
return 0;
|
||||
|
||||
u32 val = 0;
|
||||
int cmd = protocol.command.bytes[0];
|
||||
switch (cmd)
|
||||
{
|
||||
case 0xB0:
|
||||
val = (img != NULL) ? 0x1F4 : 0x1F2;
|
||||
break;
|
||||
case 0xB9:
|
||||
val = (rand() % 100) ? (img) ? 0x1F4 : 0x1F2 : 0;
|
||||
break;
|
||||
case 0xBB:
|
||||
case 0xBC:
|
||||
val = 0;
|
||||
break;
|
||||
case 0xBA:
|
||||
//INFO("Read from sd at sector %08X at adr %08X ",card.address/512,ftell(img));
|
||||
img->read_32LE(val);
|
||||
//INFO("val %08X\n",val);
|
||||
break;
|
||||
default:
|
||||
val = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void slot1client_write_GCDATAIN(eSlot1Operation theOperation, u32 val)
|
||||
{
|
||||
if (theOperation != eSlot1Operation_Unknown)
|
||||
return;
|
||||
|
||||
int cmd = protocol.command.bytes[0];
|
||||
switch (cmd)
|
||||
{
|
||||
case 0xBB:
|
||||
{
|
||||
if (write_count && write_enabled)
|
||||
{
|
||||
img->write_32LE(val);
|
||||
img->fflush();
|
||||
write_count--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void post_fakeboot(int PROCNUM)
|
||||
{
|
||||
// The BIOS leaves the card in NORMAL mode
|
||||
protocol.mode = eCardMode_NORMAL;
|
||||
}
|
||||
|
||||
void write32_GCDATAIN(u32 val)
|
||||
{
|
||||
//bool log = false;
|
||||
|
||||
//last_write_count = write_count;
|
||||
|
||||
//can someone tell me ... what the hell is this doing, anyway?
|
||||
//seems odd to use card.command[4] for this... isnt it part of the address?
|
||||
if (protocol.command.bytes[4])
|
||||
{
|
||||
// transfer is done
|
||||
//are you SURE this is logical? there doesnt seem to be any way for the card to signal that
|
||||
T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4,val & 0x7F7FFFFF);
|
||||
|
||||
MMU_GC_endTransfer(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int cmd = protocol.command.bytes[0];
|
||||
switch (cmd)
|
||||
{
|
||||
case 0xBB:
|
||||
{
|
||||
if (write_count && write_enabled)
|
||||
{
|
||||
img->write_32LE(val);
|
||||
img->fflush();
|
||||
write_count--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (write_count == 0)
|
||||
{
|
||||
write_enabled = 0;
|
||||
|
||||
//transfer is done
|
||||
|
||||
//are you SURE this is logical? there doesnt seem to be any way for the card to signal that
|
||||
T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4,val & 0x7F7FFFFF);
|
||||
|
||||
//but isnt this a different IRQ? IREQ_MC perhaps
|
||||
MMU_GC_endTransfer(0);
|
||||
}
|
||||
|
||||
/*if(log)
|
||||
{
|
||||
INFO("WRITE CARD command: %02X%02X%02X%02X%02X%02X%02X%02X\t",
|
||||
card.command[0], card.command[1], card.command[2], card.command[3],
|
||||
card.command[4], card.command[5], card.command[6], card.command[7]);
|
||||
INFO("FROM: %08X\t", NDS_ARM9.instruct_adr);
|
||||
INFO("VAL: %08X\n", val);
|
||||
}*/
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
ISlot1Interface* construct_Slot1_R4() { return new Slot1_R4(); }
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
Copyright (C) 2013-2015 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../slot1.h"
|
||||
#include "../NDSSystem.h"
|
||||
|
||||
class Slot1_Retail_Auto : public ISlot1Interface
|
||||
{
|
||||
private:
|
||||
ISlot1Interface *mSelectedImplementation;
|
||||
|
||||
public:
|
||||
Slot1_Retail_Auto()
|
||||
: mSelectedImplementation(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Slot1Info const* info()
|
||||
{
|
||||
static Slot1InfoSimple info("Retail (Auto)","Slot1 Retail (auto-selection) card emulation", 0xFE);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
|
||||
NDS_SLOT1_TYPE selection = NDS_SLOT1_RETAIL_MCROM;
|
||||
|
||||
//check game ID in core emulator and select right implementation
|
||||
//gamehack: definitely not a game hack, just a lazy way of selecting the right equipment for the game
|
||||
if(gameInfo.IsCode("UOR") || // WarioWare - D.I.Y. (U)(E)(EUR) / Made in Ore (J)
|
||||
gameInfo.IsCode("UXBP") || // Jam with the Band (EUR)
|
||||
gameInfo.IsCode("AXBJ") // Daigassou! Band-Brothers DX (J)
|
||||
)
|
||||
selection = NDS_SLOT1_RETAIL_NAND;
|
||||
|
||||
slot1_selected_type = selection;
|
||||
mSelectedImplementation = slot1_List[selection];
|
||||
mSelectedImplementation->connect();
|
||||
printf("Slot1 auto-selected device type: %s\n",mSelectedImplementation->info()->name());
|
||||
}
|
||||
|
||||
virtual void disconnect()
|
||||
{
|
||||
if(mSelectedImplementation) mSelectedImplementation->disconnect();
|
||||
mSelectedImplementation = NULL;
|
||||
}
|
||||
|
||||
virtual void write_command(u8 PROCNUM, GC_Command command)
|
||||
{
|
||||
mSelectedImplementation->write_command(PROCNUM, command);
|
||||
}
|
||||
|
||||
virtual void write_GCDATAIN(u8 PROCNUM, u32 val)
|
||||
{
|
||||
mSelectedImplementation->write_GCDATAIN(PROCNUM, val);
|
||||
}
|
||||
|
||||
virtual u32 read_GCDATAIN(u8 PROCNUM)
|
||||
{
|
||||
return mSelectedImplementation->read_GCDATAIN(PROCNUM);
|
||||
}
|
||||
|
||||
virtual u8 auxspi_transaction(int PROCNUM, u8 value)
|
||||
{
|
||||
return mSelectedImplementation->auxspi_transaction(PROCNUM, value);
|
||||
}
|
||||
|
||||
virtual void auxspi_reset(int PROCNUM)
|
||||
{
|
||||
mSelectedImplementation->auxspi_reset(PROCNUM);
|
||||
}
|
||||
|
||||
virtual void post_fakeboot(int PROCNUM)
|
||||
{
|
||||
mSelectedImplementation->post_fakeboot(PROCNUM);
|
||||
}
|
||||
|
||||
virtual void savestate(EMUFILE &os)
|
||||
{
|
||||
mSelectedImplementation->savestate(os);
|
||||
}
|
||||
|
||||
virtual void loadstate(EMUFILE &is)
|
||||
{
|
||||
mSelectedImplementation->loadstate(is);
|
||||
}
|
||||
};
|
||||
|
||||
ISlot1Interface* construct_Slot1_Retail_Auto() { return new Slot1_Retail_Auto(); }
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
Copyright (C) 2010-2021 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "slot1comp_mc.h"
|
||||
#include "slot1comp_rom.h"
|
||||
#include "slot1comp_protocol.h"
|
||||
|
||||
#include "../slot1.h"
|
||||
#include "../NDSSystem.h"
|
||||
|
||||
//quick architecture overview:
|
||||
//MCROM receives GC bus commands from MMU.cpp
|
||||
//those are passed on to the protocol component for parsing
|
||||
//protocol calls back into MCROM via ISlot1Comp_Protocol_Client interface for things the protocol doesnt know about (the contents of the rom, chiefly)
|
||||
//MCROM utilizes the rom component for address logic and delivering data
|
||||
|
||||
class Slot1_Retail_MCROM : public ISlot1Interface, public ISlot1Comp_Protocol_Client
|
||||
{
|
||||
private:
|
||||
Slot1Comp_Protocol protocol;
|
||||
Slot1Comp_Rom rom;
|
||||
|
||||
public:
|
||||
|
||||
virtual Slot1Info const* info()
|
||||
{
|
||||
static Slot1InfoSimple info("Retail MC+ROM", "Slot1 Retail MC+ROM (standard) card emulation", 0x01);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
protocol.reset(this);
|
||||
protocol.chipId = gameInfo.chipID;
|
||||
protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0);
|
||||
g_Slot1Comp_MC.connect();
|
||||
}
|
||||
|
||||
virtual u8 auxspi_transaction(int PROCNUM, u8 value)
|
||||
{
|
||||
return g_Slot1Comp_MC.auxspi_transaction(PROCNUM,value);
|
||||
}
|
||||
|
||||
virtual void auxspi_reset(int PROCNUM)
|
||||
{
|
||||
g_Slot1Comp_MC.auxspi_reset(PROCNUM);
|
||||
}
|
||||
|
||||
virtual void write_command(u8 PROCNUM, GC_Command command)
|
||||
{
|
||||
protocol.write_command(command);
|
||||
}
|
||||
virtual void write_GCDATAIN(u8 PROCNUM, u32 val)
|
||||
{
|
||||
protocol.write_GCDATAIN(PROCNUM, val);
|
||||
}
|
||||
virtual u32 read_GCDATAIN(u8 PROCNUM)
|
||||
{
|
||||
return protocol.read_GCDATAIN(PROCNUM);
|
||||
}
|
||||
|
||||
virtual void slot1client_startOperation(eSlot1Operation theOperation)
|
||||
{
|
||||
rom.start(theOperation,protocol.address);
|
||||
}
|
||||
|
||||
virtual void post_fakeboot(int PROCNUM)
|
||||
{
|
||||
// The BIOS leaves the card in NORMAL mode
|
||||
protocol.mode = eCardMode_NORMAL;
|
||||
}
|
||||
|
||||
virtual void savestate(EMUFILE &os)
|
||||
{
|
||||
protocol.savestate(os);
|
||||
rom.savestate(os);
|
||||
}
|
||||
|
||||
virtual void loadstate(EMUFILE &is)
|
||||
{
|
||||
protocol.loadstate(is);
|
||||
rom.loadstate(is);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
u32 slot1client_read_GCDATAIN(eSlot1Operation operation)
|
||||
{
|
||||
return rom.read();
|
||||
}
|
||||
};
|
||||
|
||||
ISlot1Interface* construct_Slot1_Retail_MCROM() { return new Slot1_Retail_MCROM(); }
|
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
Copyright (C) 2013-2021 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//This module implements a device which is capable of building a nitro FS on the fly
|
||||
//(and REBUILDING it! -- Q: under what conditions?)
|
||||
//so that you can test your homebrew games and patches without having to rebuild the ROM and restart it.
|
||||
//Q. can it handle resized files?
|
||||
|
||||
#include "slot1comp_mc.h"
|
||||
#include "slot1comp_rom.h"
|
||||
#include "slot1comp_protocol.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
#include "../slot1.h"
|
||||
#include "../path.h"
|
||||
#include "../NDSSystem.h"
|
||||
#include "../utils/fsnitro.h"
|
||||
|
||||
class Slot1_Retail_DEBUG : public ISlot1Interface, public ISlot1Comp_Protocol_Client
|
||||
{
|
||||
private:
|
||||
Slot1Comp_Protocol protocol;
|
||||
Slot1Comp_Rom rom;
|
||||
FILE *fpROM;
|
||||
FS_NITRO *fs;
|
||||
u16 curr_file_id;
|
||||
std::string pathData;
|
||||
|
||||
public:
|
||||
|
||||
virtual Slot1Info const* info()
|
||||
{
|
||||
static Slot1InfoSimple info("Retail DEBUG","Slot1 Retail (standard) card emulation + FS Nitro DEBUG", 0x04);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
protocol.reset(this);
|
||||
protocol.chipId = gameInfo.chipID;
|
||||
protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0);
|
||||
|
||||
curr_file_id = 0xFFFF;
|
||||
fpROM = NULL;
|
||||
fs = NULL;
|
||||
|
||||
pathData = path.getpath(path.SLOT1D) + path.GetRomNameWithoutExtension();
|
||||
printf("Path to Slot1 data: %s\n", pathData.c_str());
|
||||
|
||||
fs = new FS_NITRO();
|
||||
fs->rebuildFAT(pathData);
|
||||
}
|
||||
|
||||
virtual u8 auxspi_transaction(int PROCNUM, u8 value)
|
||||
{
|
||||
return g_Slot1Comp_MC.auxspi_transaction(PROCNUM,value);
|
||||
}
|
||||
|
||||
virtual void auxspi_reset(int PROCNUM)
|
||||
{
|
||||
g_Slot1Comp_MC.auxspi_reset(PROCNUM);
|
||||
}
|
||||
|
||||
virtual void write_command(u8 PROCNUM, GC_Command command)
|
||||
{
|
||||
protocol.write_command(command);
|
||||
}
|
||||
virtual void write_GCDATAIN(u8 PROCNUM, u32 val)
|
||||
{
|
||||
protocol.write_GCDATAIN(PROCNUM, val);
|
||||
}
|
||||
virtual u32 read_GCDATAIN(u8 PROCNUM)
|
||||
{
|
||||
return protocol.read_GCDATAIN(PROCNUM);
|
||||
}
|
||||
|
||||
virtual void post_fakeboot(int PROCNUM)
|
||||
{
|
||||
// The BIOS leaves the card in NORMAL mode
|
||||
protocol.mode = eCardMode_NORMAL;
|
||||
}
|
||||
|
||||
virtual void savestate(EMUFILE &os)
|
||||
{
|
||||
protocol.savestate(os);
|
||||
rom.savestate(os);
|
||||
}
|
||||
|
||||
virtual void loadstate(EMUFILE &is)
|
||||
{
|
||||
protocol.loadstate(is);
|
||||
rom.loadstate(is);
|
||||
}
|
||||
|
||||
virtual void slot1client_startOperation(eSlot1Operation theOperation)
|
||||
{
|
||||
if (protocol.operation == eSlot1Operation_B7_Read)
|
||||
{
|
||||
u16 file_id = 0xFFFF; u32 offset = 0;
|
||||
bool bFromFile = false;
|
||||
|
||||
if (fs && fs->isFAT(protocol.address))
|
||||
{
|
||||
fs->rebuildFAT(protocol.address, protocol.length, pathData);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fs && fs->getFileIdByAddr(protocol.address, file_id, offset))
|
||||
{
|
||||
if (file_id != curr_file_id)
|
||||
{
|
||||
std::string tmp = fs->getFullPathByFileID(file_id);
|
||||
printf("%04X:[%08X, ofs %08X] %s\n", file_id, protocol.address, offset, tmp.c_str());
|
||||
|
||||
if (fpROM)
|
||||
{
|
||||
fclose(fpROM);
|
||||
fpROM = NULL;
|
||||
}
|
||||
tmp = pathData + tmp;
|
||||
|
||||
fpROM = fopen(tmp.c_str(), "rb");
|
||||
if (fpROM)
|
||||
{
|
||||
bFromFile = true;
|
||||
printf("\t * found at disk, offset %08X\n", offset);
|
||||
if (fseek(fpROM, offset, SEEK_SET) != 0)
|
||||
{
|
||||
printf("\t\t - ERROR seek file position\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fpROM)
|
||||
{
|
||||
bFromFile = true;
|
||||
if (ftell(fpROM) != offset)
|
||||
{
|
||||
printf("\t * new file seek %08Xh\n", offset);
|
||||
fseek(fpROM, offset, SEEK_SET);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!bFromFile && fpROM)
|
||||
{
|
||||
fclose(fpROM);
|
||||
fpROM = NULL;
|
||||
}
|
||||
|
||||
curr_file_id = file_id;
|
||||
}
|
||||
rom.start(theOperation, protocol.address);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
u32 slot1client_read_GCDATAIN(eSlot1Operation operation)
|
||||
{
|
||||
if (protocol.operation == eSlot1Operation_B7_Read)
|
||||
{
|
||||
|
||||
u32 address = rom.getAddress();
|
||||
|
||||
if (fs && fs->isFAT(address))
|
||||
{
|
||||
u32 res = fs->getFATRecord(address);
|
||||
if (res != 0xFFFFFFFF)
|
||||
{
|
||||
rom.incAddress();
|
||||
return res;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (fpROM)
|
||||
{
|
||||
u32 data = 0;
|
||||
u32 readed = fread(&data, 1, 4, fpROM);
|
||||
if (readed)
|
||||
{
|
||||
rom.incAddress();
|
||||
if (readed < 4)
|
||||
data |= ((u32)0xFFFFFFFF << (readed * 8));
|
||||
return data;
|
||||
}
|
||||
|
||||
fclose(fpROM);
|
||||
fpROM = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return rom.read();
|
||||
}
|
||||
};
|
||||
|
||||
ISlot1Interface* construct_Slot1_Retail_DEBUG() { return new Slot1_Retail_DEBUG(); }
|
|
@ -0,0 +1,327 @@
|
|||
/*
|
||||
Copyright (C) 2010-2021 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Games with NAND Flash:
|
||||
// Ore/WarioWare D.I.Y. - chip: SAMSUNG 004
|
||||
// KLC2811ANB-P204
|
||||
// NTR-UORE-0
|
||||
// - 128Mbit
|
||||
|
||||
#include "slot1comp_rom.h"
|
||||
#include "slot1comp_protocol.h"
|
||||
|
||||
#include "../slot1.h"
|
||||
#include "../NDSSystem.h"
|
||||
#include "../emufile.h"
|
||||
|
||||
//quick architecture overview:
|
||||
//NAND receives GC bus commands from MMU.cpp
|
||||
//those are passed on to the protocol component for parsing
|
||||
//protocol calls back into NAND via ISlot1Comp_Protocol_Client interface for things the protocol doesn't know about (the contents of the rom, chiefly)
|
||||
//NAND utilizes the rom component for address logic and delivering data.
|
||||
//it also processes some commands itself which aren't rom-related (the NANDy stuff)
|
||||
|
||||
class Slot1_Retail_NAND : public ISlot1Interface, public ISlot1Comp_Protocol_Client
|
||||
{
|
||||
private:
|
||||
u32 subAdr;
|
||||
|
||||
Slot1Comp_Protocol protocol;
|
||||
Slot1Comp_Rom rom;
|
||||
|
||||
u32 mode;
|
||||
u32 handle_save;
|
||||
|
||||
//current NAND read/write start position
|
||||
//when this is changed, the read/write cursor will be reset to it
|
||||
//when it is set to the same value, the read/write cursor will NOT be reset
|
||||
//(this is since some value must necessarily come in on the protocol address, so the 'current save_start' is used as a special 'dont change' value
|
||||
u32 save_start;
|
||||
|
||||
//current NAND read/write cursor
|
||||
u32 save_adr;
|
||||
|
||||
public:
|
||||
virtual Slot1Info const* info()
|
||||
{
|
||||
static Slot1InfoSimple info("Retail NAND","Slot1 retail NAND card emulation", 0x02);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
protocol.reset(this);
|
||||
protocol.chipId = gameInfo.chipID;
|
||||
protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0);
|
||||
|
||||
save_adr = 0;
|
||||
handle_save = 0;
|
||||
mode = 0;
|
||||
subAdr = T1ReadWord(gameInfo.header.reserved2, 0x6) << 17;
|
||||
}
|
||||
|
||||
virtual void write_command(u8 PROCNUM, GC_Command command)
|
||||
{
|
||||
protocol.write_command(command);
|
||||
}
|
||||
|
||||
virtual void write_GCDATAIN(u8 PROCNUM, u32 val)
|
||||
{
|
||||
protocol.write_GCDATAIN(PROCNUM, val);
|
||||
}
|
||||
virtual u32 read_GCDATAIN(u8 PROCNUM)
|
||||
{
|
||||
return protocol.read_GCDATAIN(PROCNUM);
|
||||
}
|
||||
|
||||
virtual void slot1client_startOperation(eSlot1Operation theOperation)
|
||||
{
|
||||
//INFO("Start command: %02X%02X%02X%02X%02X%02X%02X%02X\t",
|
||||
// protocol.command.bytes[0], protocol.command.bytes[1], protocol.command.bytes[2], protocol.command.bytes[3],
|
||||
// protocol.command.bytes[4], protocol.command.bytes[5], protocol.command.bytes[6], protocol.command.bytes[7]);
|
||||
//INFO("FROM: %08X\n", NDS_ARM9.instruct_adr);
|
||||
|
||||
u32 addressFromProtocol = (protocol.command.bytes[1] << 24) | (protocol.command.bytes[2] << 16) | (protocol.command.bytes[3] << 8) | protocol.command.bytes[4];
|
||||
|
||||
//pass the normal rom operations along to the rom component
|
||||
switch (theOperation)
|
||||
{
|
||||
case eSlot1Operation_00_ReadHeader_Unencrypted:
|
||||
rom.start(theOperation, addressFromProtocol);
|
||||
return;
|
||||
|
||||
case eSlot1Operation_2x_SecureAreaLoad:
|
||||
rom.start(theOperation, protocol.address);
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//handle special commands ourselves
|
||||
int cmd = protocol.command.bytes[0];
|
||||
switch(cmd)
|
||||
{
|
||||
// Nand Init
|
||||
case 0x94:
|
||||
mode = cmd;
|
||||
break;
|
||||
|
||||
// Nand Error?
|
||||
case 0xD6:
|
||||
break;
|
||||
|
||||
//Nand Write Page
|
||||
case 0x81:
|
||||
mode = cmd;
|
||||
if(addressFromProtocol != save_start)
|
||||
{
|
||||
save_start = addressFromProtocol;
|
||||
save_adr = (addressFromProtocol & gameInfo.mask) - subAdr;
|
||||
}
|
||||
handle_save = 1;
|
||||
break;
|
||||
|
||||
case 0x84: //Write disable
|
||||
case 0x85: //Write enable
|
||||
mode = cmd;
|
||||
break;
|
||||
case 0x8B:
|
||||
mode = cmd;
|
||||
handle_save = 0;
|
||||
MMU_new.backupDevice.flushBackup();
|
||||
break;
|
||||
|
||||
//Start read mode
|
||||
case 0xB7:
|
||||
if (handle_save)
|
||||
{
|
||||
mode = cmd;
|
||||
if(addressFromProtocol != save_start)
|
||||
{
|
||||
save_start = addressFromProtocol;
|
||||
save_adr = (addressFromProtocol & gameInfo.mask) - subAdr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rom.start(theOperation, addressFromProtocol);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xB2: //Set save position
|
||||
mode = cmd;
|
||||
save_start = addressFromProtocol;
|
||||
//cursor resets regardless of whether save_start changed, that's what makes this special.
|
||||
//the cursor could be reset to the beginning of the previous save_start region
|
||||
save_adr = (addressFromProtocol & gameInfo.mask) - subAdr;
|
||||
handle_save = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual u32 slot1client_read_GCDATAIN(eSlot1Operation operation)
|
||||
{
|
||||
//pass the normal rom operations along to the rom component
|
||||
switch(operation)
|
||||
{
|
||||
case eSlot1Operation_00_ReadHeader_Unencrypted:
|
||||
case eSlot1Operation_2x_SecureAreaLoad:
|
||||
//case eSlot1Operation_B7_Read:
|
||||
return rom.read();
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//handle special commands ourselves
|
||||
int cmd = protocol.command.bytes[0];
|
||||
int val = 0;
|
||||
switch(cmd)
|
||||
{
|
||||
// Nand Init?
|
||||
case 0x94:
|
||||
val = 0;
|
||||
mode = 0;
|
||||
break;
|
||||
|
||||
//Rom/Save Read
|
||||
case 0xB7:
|
||||
{
|
||||
if(handle_save)
|
||||
{
|
||||
MMU_new.backupDevice.ensure(save_adr+4, (u8)0);
|
||||
|
||||
val = MMU_new.backupDevice.readLong(save_adr, 0);
|
||||
|
||||
save_adr += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
val = rom.read();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// Nand Status?
|
||||
case 0xD6:
|
||||
//0x80 == busy
|
||||
//0x40 == ??
|
||||
//0x20 == ready?
|
||||
//0x10 == write enabled?
|
||||
switch (mode)
|
||||
{
|
||||
case 0x84: //Write disable
|
||||
val = 0x20202020;
|
||||
break;
|
||||
case 0x85: //Write enable
|
||||
val = 0x20202020 | 0x10101010;
|
||||
break;
|
||||
case 0x8B:
|
||||
val = 0x60606060 | 0x10101010;
|
||||
break;
|
||||
case 0xB2: //Set save position
|
||||
val = 0x20202020;
|
||||
break;
|
||||
default:
|
||||
val = 0x60606060; //0x20 == ready
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
virtual void slot1client_write_GCDATAIN(eSlot1Operation operation, u32 val)
|
||||
{
|
||||
//pass the normal rom operations along to the rom component
|
||||
switch(operation)
|
||||
{
|
||||
case eSlot1Operation_00_ReadHeader_Unencrypted:
|
||||
case eSlot1Operation_B7_Read:
|
||||
case eSlot1Operation_2x_SecureAreaLoad:
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//handle special commands ourselves
|
||||
int cmd = protocol.command.bytes[0];
|
||||
u32 value = val;
|
||||
u32 adr = save_adr;
|
||||
switch(cmd)
|
||||
{
|
||||
case 0x81: //Nand Write
|
||||
|
||||
MMU_new.backupDevice.ensure(adr+4, (u8)0);
|
||||
MMU_new.backupDevice.writeLong(adr, val);
|
||||
|
||||
save_adr += 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void post_fakeboot(int PROCNUM)
|
||||
{
|
||||
// The BIOS leaves the card in NORMAL mode
|
||||
protocol.mode = eCardMode_NORMAL;
|
||||
}
|
||||
|
||||
virtual void savestate(EMUFILE &os)
|
||||
{
|
||||
s32 version = 0;
|
||||
|
||||
protocol.savestate(os);
|
||||
rom.savestate(os);
|
||||
|
||||
os.write_32LE(version);
|
||||
|
||||
os.write_32LE(mode);
|
||||
os.write_32LE(handle_save);
|
||||
os.write_32LE(save_adr);
|
||||
os.write_32LE(save_start);
|
||||
os.write_32LE(subAdr);
|
||||
}
|
||||
|
||||
virtual void loadstate(EMUFILE &is)
|
||||
{
|
||||
s32 version = 0;
|
||||
|
||||
protocol.loadstate(is);
|
||||
rom.loadstate(is);
|
||||
|
||||
is.read_32LE(version);
|
||||
|
||||
// version 0
|
||||
if (version >= 0)
|
||||
{
|
||||
is.read_32LE(mode);
|
||||
is.read_32LE(handle_save);
|
||||
is.read_32LE(save_adr);
|
||||
is.read_32LE(save_start);
|
||||
is.read_32LE(subAdr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
ISlot1Interface* construct_Slot1_Retail_NAND() { return new Slot1_Retail_NAND(); }
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
Copyright (C) 2013-2017 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//this file contains the components used for emulating standard gamecard "MC" devices (eeprom, fram, flash)
|
||||
//this is largely done by accessing the BackupDevice resources in the core emulator
|
||||
|
||||
#include "slot1comp_mc.h"
|
||||
|
||||
#include "../MMU.h"
|
||||
#include "../NDSSystem.h"
|
||||
|
||||
Slot1Comp_MC g_Slot1Comp_MC;
|
||||
|
||||
u8 Slot1Comp_MC::auxspi_transaction(int PROCNUM, u8 value)
|
||||
{
|
||||
return MMU_new.backupDevice.data_command(value, PROCNUM);
|
||||
}
|
||||
|
||||
void Slot1Comp_MC::auxspi_reset(int PROCNUM)
|
||||
{
|
||||
MMU_new.backupDevice.reset_command();
|
||||
}
|
||||
|
||||
void Slot1Comp_MC::connect()
|
||||
{
|
||||
//gamehack: not really a game hack
|
||||
if(gameInfo.IsCode("AXBJ"))
|
||||
MMU_new.backupDevice.uninitializedValue = 0x00; // Daigassou! Band Brothers DX (JP)
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
Copyright (C) 2013-2015 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//this file contains the components used for emulating standard gamecard "MC" devices (eeprom, fram, flash)
|
||||
|
||||
#ifndef _SLOT1COMP_MC_H
|
||||
#define _SLOT1COMP_MC_H
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
class Slot1Comp_MC
|
||||
{
|
||||
public:
|
||||
u8 auxspi_transaction(int PROCNUM, u8 value);
|
||||
void auxspi_reset(int PROCNUM);
|
||||
void connect();
|
||||
};
|
||||
|
||||
extern Slot1Comp_MC g_Slot1Comp_MC;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
Copyright (C) 2012-2021 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "slot1comp_protocol.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "../armcpu.h"
|
||||
#include "../encrypt.h"
|
||||
#include "../emufile.h"
|
||||
#include "../utils/decrypt/decrypt.h"
|
||||
|
||||
static _KEY1 key1((const u8*)arm7_key);
|
||||
|
||||
void Slot1Comp_Protocol::reset(ISlot1Comp_Protocol_Client* theClient)
|
||||
{
|
||||
this->client = theClient;
|
||||
|
||||
//we have to initialize this to something.. lets use dummy.
|
||||
//(need to clean this up...)
|
||||
memcpy(&command,"\x9F\0\0\0\0\0\0\0",8);
|
||||
operation = eSlot1Operation_9F_Dummy;
|
||||
|
||||
length = 0;
|
||||
delay = 0;
|
||||
mode = eCardMode_RAW;
|
||||
}
|
||||
|
||||
void Slot1Comp_Protocol::write_command_RAW(GC_Command theCommand)
|
||||
{
|
||||
int cmd = theCommand.bytes[0];
|
||||
if(cmd == 0x9F)
|
||||
{
|
||||
operation = eSlot1Operation_9F_Dummy;
|
||||
length = 0x2000;
|
||||
}
|
||||
if(cmd == 0x90)
|
||||
{
|
||||
operation = eSlot1Operation_90_ChipID;
|
||||
length = 4;
|
||||
//we handle this operation ourselves
|
||||
}
|
||||
if(cmd == 0x3C)
|
||||
{
|
||||
//switch to KEY1
|
||||
length = 0;
|
||||
mode = eCardMode_KEY1;
|
||||
|
||||
//defer initialization of KEY1 until we know we need it, just to save some CPU time.
|
||||
//TODO - some information about these parameters
|
||||
//level == 2
|
||||
//modulo == 8
|
||||
key1.init(gameCode, 2, 0x08);
|
||||
GCLOG("[GC] KEY1 ACTIVATED\n");
|
||||
}
|
||||
if(cmd == 0x00)
|
||||
{
|
||||
operation = eSlot1Operation_00_ReadHeader_Unencrypted;
|
||||
client->slot1client_startOperation(operation);
|
||||
}
|
||||
}
|
||||
|
||||
void Slot1Comp_Protocol::write_command_KEY1(GC_Command theCommand)
|
||||
{
|
||||
//decrypt the KEY1-format command
|
||||
u32 temp[2];
|
||||
theCommand.toCryptoBuffer(temp);
|
||||
key1.decrypt(temp);
|
||||
theCommand.fromCryptoBuffer(temp);
|
||||
GCLOG("[GC] (key1-decrypted):"); theCommand.print();
|
||||
|
||||
//and process it:
|
||||
int cmd = theCommand.bytes[0];
|
||||
switch(cmd&0xF0)
|
||||
{
|
||||
case 0x10:
|
||||
operation = eSlot1Operation_1x_ChipID;
|
||||
delay = 0x910, length = 4;
|
||||
//we handle this operation ourselves
|
||||
break;
|
||||
|
||||
case 0x20:
|
||||
operation = eSlot1Operation_2x_SecureAreaLoad;
|
||||
delay = 0x910, length = 0x11A8;
|
||||
|
||||
//TODO - more endian-safe way of doing this (theres examples in R4)
|
||||
{
|
||||
#ifdef MSB_FIRST
|
||||
u64 cmd64 = *(u64*)theCommand.bytes;
|
||||
#else
|
||||
u64 cmd64 = bswap64(*(u64*)theCommand.bytes);
|
||||
#endif
|
||||
//todo - parse into blocknumber
|
||||
u32 blocknumber = (cmd64>>44)&0xFFFF;
|
||||
if(blocknumber<4||blocknumber>7)
|
||||
printf("SLOT1 WARNING: INVALID BLOCKNUMBER FOR \"Get Secure Area Block\": 0x%04X\n",blocknumber);
|
||||
address = blocknumber*0x1000;
|
||||
}
|
||||
client->slot1client_startOperation(operation);
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
//switch to KEY2
|
||||
delay = 0x910, length = 0;
|
||||
//well.. not really... yet.
|
||||
GCLOG("[GC] KEY2 ACTIVATED\n");
|
||||
break;
|
||||
|
||||
case 0x60:
|
||||
//KEY2 disable? any info?
|
||||
break;
|
||||
|
||||
case 0xA0:
|
||||
delay = 0x910, length = 0;
|
||||
mode = eCardMode_NORMAL;
|
||||
GCLOG("[GC] NORMAL MODE ACTIVATED\n");
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Slot1Comp_Protocol::write_command_NORMAL(GC_Command theCommand)
|
||||
{
|
||||
switch(command.bytes[0])
|
||||
{
|
||||
case 0xB7:
|
||||
{
|
||||
operation = eSlot1Operation_B7_Read;
|
||||
|
||||
//TODO - more endian-safe way of doing this (theres examples in R4)
|
||||
#ifdef MSB_FIRST
|
||||
u64 cmd64 = *(u64*)theCommand.bytes;
|
||||
#else
|
||||
u64 cmd64 = bswap64(*(u64*)theCommand.bytes);
|
||||
#endif
|
||||
address = (u32)((cmd64 >> 24));
|
||||
length = 0x200;
|
||||
|
||||
client->slot1client_startOperation(operation);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xB8:
|
||||
operation = eSlot1Operation_B8_ChipID;
|
||||
delay = 0, length = 4;
|
||||
//we handle this operation ourselves
|
||||
break;
|
||||
|
||||
default:
|
||||
operation = eSlot1Operation_Unknown;
|
||||
client->slot1client_startOperation(operation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Slot1Comp_Protocol::write_command(GC_Command theCommand)
|
||||
{
|
||||
this->command = theCommand;
|
||||
|
||||
//unrecognized commands will do something depending on the current state of the card
|
||||
delay = 0;
|
||||
length = 0;
|
||||
address = 0;
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case eCardMode_RAW:
|
||||
write_command_RAW(theCommand);
|
||||
break;
|
||||
|
||||
case eCardMode_KEY1:
|
||||
write_command_KEY1(theCommand);
|
||||
break;
|
||||
|
||||
case eCardMode_NORMAL:
|
||||
write_command_NORMAL(theCommand);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Slot1Comp_Protocol::write_GCDATAIN(u8 PROCNUM, u32 val)
|
||||
{
|
||||
switch(operation)
|
||||
{
|
||||
case eSlot1Operation_Unknown:
|
||||
client->slot1client_write_GCDATAIN(operation,val);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
u32 Slot1Comp_Protocol::read_GCDATAIN(u8 PROCNUM)
|
||||
{
|
||||
switch(operation)
|
||||
{
|
||||
default:
|
||||
return client->slot1client_read_GCDATAIN(operation);
|
||||
|
||||
case eSlot1Operation_9F_Dummy:
|
||||
return 0xFFFFFFFF;
|
||||
|
||||
case eSlot1Operation_1x_ChipID:
|
||||
return chipId;
|
||||
|
||||
case eSlot1Operation_90_ChipID:
|
||||
case eSlot1Operation_B8_ChipID:
|
||||
|
||||
//Most games continuously compare the current chipId with the value in
|
||||
//stored in memory at boot-up, probably to know if the card was removed.
|
||||
|
||||
//staff of kings verifies this (it also uses the arm7 IRQ 20 to detect card ejects)
|
||||
return chipId;
|
||||
}
|
||||
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
void Slot1Comp_Protocol::savestate(EMUFILE &os)
|
||||
{
|
||||
s32 version = 0;
|
||||
os.write_32LE(version);
|
||||
os.write_32LE((s32)mode);
|
||||
os.write_32LE((s32)operation);
|
||||
os.fwrite(command.bytes,8);
|
||||
os.write_32LE(address);
|
||||
os.write_32LE(length);
|
||||
os.write_32LE(delay);
|
||||
os.write_32LE(chipId);
|
||||
os.write_32LE(gameCode);
|
||||
}
|
||||
|
||||
void Slot1Comp_Protocol::loadstate(EMUFILE &is)
|
||||
{
|
||||
s32 version = is.read_s32LE();
|
||||
mode = (eCardMode)is.read_s32LE();
|
||||
operation = (eSlot1Operation)is.read_s32LE();
|
||||
is.fread(command.bytes,8);
|
||||
is.read_32LE(address);
|
||||
is.read_32LE(length);
|
||||
is.read_32LE(delay);
|
||||
is.read_32LE(chipId);
|
||||
is.read_32LE(gameCode);
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
Copyright (C) 2013-2021 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//this file contains the components used for emulating standard gamecard protocol.
|
||||
//this largely means the complex boot-up process.
|
||||
//i think there's no reason why proprietary cards couldn't speak any protocol they wish, as long as they didn't mind being unbootable.
|
||||
//TODO - could this be refactored into a base class? that's probably more reasonable. but we've gone with this modular mix-in architecture so... not yet.
|
||||
|
||||
#ifndef _SLOT1COMP_PROTOCOL_H
|
||||
#define _SLOT1COMP_PROTOCOL_H
|
||||
|
||||
#include "../types.h"
|
||||
#include "../MMU.h"
|
||||
|
||||
class EMUFILE;
|
||||
|
||||
enum eSlot1Operation
|
||||
{
|
||||
//----------
|
||||
//RAW mode operations
|
||||
//before encrypted communications can be established, some values from the rom header must be read.
|
||||
//this is the only way to read the header, actually, since the only reading commands available to games (after KEY2 mode is set) are
|
||||
eSlot1Operation_00_ReadHeader_Unencrypted,
|
||||
//it's not clear why this exists
|
||||
eSlot1Operation_9F_Dummy,
|
||||
eSlot1Operation_90_ChipID,
|
||||
//----------
|
||||
|
||||
//----------
|
||||
//KEY1 mode operations
|
||||
eSlot1Operation_1x_ChipID,
|
||||
eSlot1Operation_2x_SecureAreaLoad,
|
||||
//----------
|
||||
|
||||
//----------
|
||||
//NORMAL mode operations
|
||||
//the main rom data reading command
|
||||
eSlot1Operation_B7_Read,
|
||||
eSlot1Operation_B8_ChipID,
|
||||
//----------
|
||||
|
||||
eSlot1Operation_Unknown
|
||||
};
|
||||
|
||||
class ISlot1Comp_Protocol_Client
|
||||
{
|
||||
public:
|
||||
virtual void slot1client_startOperation(eSlot1Operation theOperation) {}
|
||||
virtual u32 slot1client_read_GCDATAIN(eSlot1Operation theOperation) = 0;
|
||||
virtual void slot1client_write_GCDATAIN(eSlot1Operation theOperation, u32 val) {}
|
||||
};
|
||||
|
||||
|
||||
class Slot1Comp_Protocol
|
||||
{
|
||||
public:
|
||||
|
||||
void savestate(EMUFILE &os);
|
||||
void loadstate(EMUFILE &is);
|
||||
|
||||
//set some kind of protocol/hardware reset state
|
||||
void reset(ISlot1Comp_Protocol_Client* theClient);
|
||||
|
||||
//signals from the GC bus
|
||||
void write_command(GC_Command theCommand);
|
||||
void write_GCDATAIN(u8 PROCNUM, u32 val);
|
||||
u32 read_GCDATAIN(u8 PROCNUM);
|
||||
|
||||
//helpers for write_command()
|
||||
void write_command_RAW(GC_Command theCommand);
|
||||
void write_command_KEY1(GC_Command theCommand);
|
||||
void write_command_NORMAL(GC_Command theCommand);
|
||||
|
||||
//operations not related to obscurities of the protocol or otherwise unknown are passed through to the client here
|
||||
ISlot1Comp_Protocol_Client* client;
|
||||
|
||||
//--state--
|
||||
|
||||
//the major operational mode. the protocol shifts modes and interprets commands into operations differently depending on the mode
|
||||
eCardMode mode;
|
||||
|
||||
//the current operational state
|
||||
eSlot1Operation operation;
|
||||
|
||||
//the command we're currently crunching on
|
||||
GC_Command command;
|
||||
|
||||
//most operations are defined in terms of returning a series of bytes
|
||||
//the meaning of these varies by operation. they are provided publicly as a service to clients
|
||||
u32 address;
|
||||
s32 length, delay; //the expected length and delay of this state
|
||||
|
||||
//chipId which should be returned by the various chipId commands
|
||||
u32 chipId;
|
||||
|
||||
//gameCode used by the protocol KEY1 crypto
|
||||
u32 gameCode;
|
||||
};
|
||||
|
||||
#endif //_SLOT1COMP_PROTOCOL_H
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
Copyright (C) 2010-2021 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "slot1comp_rom.h"
|
||||
|
||||
#include "../NDSSystem.h"
|
||||
#include "../emufile.h"
|
||||
|
||||
|
||||
void Slot1Comp_Rom::start(eSlot1Operation operation, u32 addr)
|
||||
{
|
||||
this->_operation = operation;
|
||||
this->_address = addr;
|
||||
}
|
||||
|
||||
u32 Slot1Comp_Rom::read()
|
||||
{
|
||||
switch(this->_operation)
|
||||
{
|
||||
case eSlot1Operation_00_ReadHeader_Unencrypted:
|
||||
{
|
||||
u32 ret = gameInfo.readROM(this->_address);
|
||||
this->_address = (this->_address + 4) & 0xFFF;
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case eSlot1Operation_2x_SecureAreaLoad:
|
||||
{
|
||||
//see B7 for details
|
||||
|
||||
//zero 15-sep-2014 - this is meaningless. newer mask is actually reasonable
|
||||
//address &= gameInfo.mask; //sanity check
|
||||
u32 secureAreaAddress = (this->_address - 0x4000);
|
||||
secureAreaAddress &= 0x3FFF; //memory safe sanity test
|
||||
u32 ret = LE_TO_LOCAL_32(*(u32*)(gameInfo.secureArea + secureAreaAddress));
|
||||
this->_address = (this->_address&~0xFFF) + ((this->_address+4)&0xFFF);
|
||||
return ret;
|
||||
}
|
||||
|
||||
case eSlot1Operation_B7_Read:
|
||||
{
|
||||
//TODO - check about non-4-byte aligned addresses
|
||||
|
||||
//it seems that etrian odyssey 3 doesnt work unless we mask this to cart size.
|
||||
//but, a thought: does the internal rom address counter register wrap around? we may be making a mistake by keeping the extra precision
|
||||
//but there is no test case yet
|
||||
this->_address &= gameInfo.mask;
|
||||
|
||||
//feature of retail carts:
|
||||
//B7 "Can be used only for addresses 8000h and up, smaller addresses will be silently redirected to address `8000h+(addr AND 1FFh)`"
|
||||
if(CommonSettings.RetailCardProtection8000)
|
||||
if(this->_address < 0x8000)
|
||||
this->_address = (0x8000 + (this->_address & 0x1FF));
|
||||
|
||||
//1. as a sanity measure for funny-sized roms (homebrew and perhaps truncated retail roms) we need to protect ourselves by returning 0xFF for things still out of range.
|
||||
//2. this isnt right, unless someone documents otherwise:
|
||||
//if (address > gameInfo.header.endROMoffset)
|
||||
// ... the cart hardware doesnt know anything about the rom header. if it has a totally bogus endROMoffset, the cart will probably work just fine. and, the +4 is missing anyway:
|
||||
//3. this is better: it just allows us to read 0xFF anywhere we dont have rom data. forget what the header says
|
||||
//note: we allow the reading to proceed anyway, because the readROM method is built to allow jaggedy reads off the end of the rom to support trimmed roms
|
||||
if(this->_address+4 > gameInfo.romsize)
|
||||
{
|
||||
DEBUG_Notify.ReadBeyondEndOfCart(this->_address,gameInfo.romsize);
|
||||
}
|
||||
|
||||
//actually read from the ROM provider
|
||||
u32 ret = gameInfo.readROM(this->_address);
|
||||
|
||||
//"However, the datastream wraps to the begin of the current 4K block when address+length crosses a 4K boundary (1000h bytes)"
|
||||
this->_address = (this->_address&~0xFFF) + ((this->_address+4)&0xFFF);
|
||||
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
|
||||
} //switch(operation)
|
||||
} //Slot1Comp_Rom::read()
|
||||
|
||||
u32 Slot1Comp_Rom::getAddress()
|
||||
{
|
||||
return this->_address & gameInfo.mask;
|
||||
} //Slot1Comp_Rom::getAddress()
|
||||
|
||||
u32 Slot1Comp_Rom::incAddress()
|
||||
{
|
||||
this->_address &= gameInfo.mask;
|
||||
this->_address = (this->_address&~0xFFF) + ((this->_address+4)&0xFFF);
|
||||
return this->_address;
|
||||
}
|
||||
|
||||
|
||||
void Slot1Comp_Rom::savestate(EMUFILE &os)
|
||||
{
|
||||
s32 version = 0;
|
||||
os.write_32LE(version);
|
||||
os.write_32LE((s32)this->_operation);
|
||||
os.write_32LE(this->_address);
|
||||
}
|
||||
|
||||
void Slot1Comp_Rom::loadstate(EMUFILE &is)
|
||||
{
|
||||
s32 version = is.read_s32LE();
|
||||
this->_operation = (eSlot1Operation)is.read_s32LE();
|
||||
this->_address = is.read_u32LE();
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
Copyright (C) 2010-2021 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//this file contains the components used for emulating standard gamecard ROMs
|
||||
//this is largely done by accessing the rom provided in the core emulator
|
||||
|
||||
#ifndef _SLOT1COMP_ROM_H
|
||||
#define _SLOT1COMP_ROM_H
|
||||
|
||||
#include "slot1comp_protocol.h"
|
||||
#include "../types.h"
|
||||
|
||||
class EMUFILE;
|
||||
|
||||
class Slot1Comp_Rom
|
||||
{
|
||||
public:
|
||||
void start(eSlot1Operation operation, u32 addr);
|
||||
u32 read();
|
||||
u32 getAddress();
|
||||
u32 incAddress();
|
||||
|
||||
void savestate(EMUFILE &os);
|
||||
void loadstate(EMUFILE &is);
|
||||
|
||||
private:
|
||||
u32 _address;
|
||||
eSlot1Operation _operation;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
Copyright (C) 2013-2015 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../slot2.h"
|
||||
|
||||
class Slot2_Auto : public ISlot2Interface
|
||||
{
|
||||
private:
|
||||
ISlot2Interface *mSelectedImplementation;
|
||||
|
||||
public:
|
||||
Slot2_Auto()
|
||||
: mSelectedImplementation(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Slot2Info const* info()
|
||||
{
|
||||
static Slot2InfoSimple info("Auto","Slot2 (auto-selection) device emulation", 0xFE);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
slot2_selected_type = slot2_DetermineType();
|
||||
mSelectedImplementation = slot2_List[slot2_selected_type];
|
||||
mSelectedImplementation->connect();
|
||||
printf("Slot2 auto-selected device type: %s (0x%02X)\n", mSelectedImplementation->info()->name(), mSelectedImplementation->info()->id());
|
||||
}
|
||||
|
||||
virtual void disconnect()
|
||||
{
|
||||
if(mSelectedImplementation) mSelectedImplementation->disconnect();
|
||||
mSelectedImplementation = NULL;
|
||||
}
|
||||
|
||||
virtual void writeByte(u8 PROCNUM, u32 addr, u8 val) { mSelectedImplementation->writeByte(PROCNUM, addr, val); }
|
||||
virtual void writeWord(u8 PROCNUM, u32 addr, u16 val) { mSelectedImplementation->writeWord(PROCNUM, addr, val); }
|
||||
virtual void writeLong(u8 PROCNUM, u32 addr, u32 val) { mSelectedImplementation->writeLong(PROCNUM, addr, val); }
|
||||
|
||||
virtual u8 readByte(u8 PROCNUM, u32 addr) { return mSelectedImplementation->readByte(PROCNUM, addr); }
|
||||
virtual u16 readWord(u8 PROCNUM, u32 addr) { return mSelectedImplementation->readWord(PROCNUM, addr); }
|
||||
virtual u32 readLong(u8 PROCNUM, u32 addr) { return mSelectedImplementation->readLong(PROCNUM, addr); }
|
||||
|
||||
virtual void savestate(EMUFILE &os)
|
||||
{
|
||||
mSelectedImplementation->savestate(os);
|
||||
}
|
||||
|
||||
virtual void loadstate(EMUFILE &is)
|
||||
{
|
||||
mSelectedImplementation->loadstate(is);
|
||||
}
|
||||
};
|
||||
|
||||
ISlot2Interface* construct_Slot2_Auto() { return new Slot2_Auto(); }
|
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
Copyright (C) 2009 CrazyMax
|
||||
Copyright (C) 2009-2017 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../slot2.h"
|
||||
#include "../emufile.h"
|
||||
#include "../mem.h"
|
||||
|
||||
#if 0
|
||||
#define EXPINFO(...) INFO(__VA_ARGS__)
|
||||
#else
|
||||
#define EXPINFO(...)
|
||||
#endif
|
||||
|
||||
#define EXPANSION_MEMORY_SIZE (8 * 1024 * 1024)
|
||||
|
||||
static u8 header_0x00B0[] =
|
||||
{ 0xFF, 0xFF, 0x96, 0x00, //this 0x96 is strange. it can't be read from the pak when it boots, it must appear later
|
||||
0x00, 0x24, 0x24, 0x24,
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x7F
|
||||
};
|
||||
|
||||
class Slot2_ExpansionPak : public ISlot2Interface
|
||||
{
|
||||
private:
|
||||
u8 *expMemory;
|
||||
bool ext_ram_lock;
|
||||
public:
|
||||
|
||||
Slot2_ExpansionPak()
|
||||
{
|
||||
expMemory = NULL;
|
||||
ext_ram_lock = true;
|
||||
}
|
||||
|
||||
virtual Slot2Info const* info()
|
||||
{
|
||||
static Slot2InfoSimple info("Memory Expansion Pak", "Official RAM expansion for Opera browser", 0x05);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
if (expMemory == NULL)
|
||||
{
|
||||
expMemory = new u8[EXPANSION_MEMORY_SIZE];
|
||||
}
|
||||
memset(expMemory, 0xFF, EXPANSION_MEMORY_SIZE);
|
||||
ext_ram_lock = true;
|
||||
}
|
||||
|
||||
virtual void disconnect()
|
||||
{
|
||||
delete[] expMemory;
|
||||
expMemory = NULL;
|
||||
}
|
||||
|
||||
virtual void writeByte(u8 PROCNUM, u32 addr, u8 val)
|
||||
{
|
||||
if (ext_ram_lock) return;
|
||||
|
||||
if (addr >= 0x09000000)
|
||||
{
|
||||
u32 offs = (addr - 0x09000000);
|
||||
if (offs >= EXPANSION_MEMORY_SIZE) return;
|
||||
T1WriteByte(expMemory, offs, val);
|
||||
}
|
||||
EXPINFO("ExpMemory: write 08 at 0x%08X = 0x%02X\n", addr, val);
|
||||
}
|
||||
virtual void writeWord(u8 PROCNUM, u32 addr, u16 val)
|
||||
{
|
||||
if (addr == 0x08240000)
|
||||
{
|
||||
if (val == 0)
|
||||
ext_ram_lock = true;
|
||||
else
|
||||
if (val == 1)
|
||||
ext_ram_lock = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ext_ram_lock) return;
|
||||
|
||||
if (addr >= 0x09000000)
|
||||
{
|
||||
u32 offs = (addr - 0x09000000);
|
||||
if (offs >= EXPANSION_MEMORY_SIZE) return;
|
||||
T1WriteWord(expMemory, offs, val);
|
||||
}
|
||||
EXPINFO("ExpMemory: write 16 at 0x%08X = 0x%04X\n", addr, val);
|
||||
}
|
||||
virtual void writeLong(u8 PROCNUM, u32 addr, u32 val)
|
||||
{
|
||||
if (ext_ram_lock) return;
|
||||
|
||||
if (addr >= 0x09000000)
|
||||
{
|
||||
u32 offs = (addr - 0x09000000);
|
||||
if (offs >= EXPANSION_MEMORY_SIZE) return;
|
||||
T1WriteLong(expMemory, offs, val);
|
||||
}
|
||||
EXPINFO("ExpMemory: write 32 at 0x%08X = 0x%08X\n", addr, val);
|
||||
}
|
||||
|
||||
virtual u8 readByte(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
EXPINFO("ExpMemory: read 08 at 0x%08X\n", addr);
|
||||
|
||||
if ((addr >= 0x080000B0) && (addr < 0x080000C0))
|
||||
return T1ReadByte(header_0x00B0, (addr - 0x080000B0));
|
||||
|
||||
if (addr >= 0x09000000)
|
||||
{
|
||||
u32 offs = (addr - 0x09000000);
|
||||
if (offs >= EXPANSION_MEMORY_SIZE) return (0xFF);
|
||||
return T1ReadByte(expMemory, offs);
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
virtual u16 readWord(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
EXPINFO("ExpMemory: read 16 at 0x%08X\n", addr);
|
||||
|
||||
if ((addr >= 0x080000B0) && (addr < 0x080000C0))
|
||||
return T1ReadWord(header_0x00B0, (addr - 0x080000B0));
|
||||
|
||||
if (addr == 0x0801FFFC) return 0x7FFF;
|
||||
if (addr == 0x08240002) return 0; //this can't be 0xFFFF. dunno why, we just guessed 0
|
||||
|
||||
if (addr >= 0x09000000)
|
||||
{
|
||||
u32 offs = (addr - 0x09000000);
|
||||
if (offs >= EXPANSION_MEMORY_SIZE) return (0xFFFF);
|
||||
return T1ReadWord(expMemory, offs);
|
||||
}
|
||||
|
||||
return 0xFFFF;
|
||||
}
|
||||
virtual u32 readLong(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
EXPINFO("ExpMemory: read 32 at 0x%08X\n", addr);
|
||||
|
||||
if((addr >= 0x080000B0) && (addr < 0x080000C0))
|
||||
return T1ReadLong(header_0x00B0, (addr - 0x080000B0));
|
||||
|
||||
if (addr >= 0x09000000)
|
||||
{
|
||||
u32 offs = (addr - 0x09000000);
|
||||
if (offs >= EXPANSION_MEMORY_SIZE) return 0xFFFFFFFF;
|
||||
return T1ReadLong(expMemory, offs);
|
||||
}
|
||||
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
virtual void savestate(EMUFILE &os)
|
||||
{
|
||||
s32 version = 0;
|
||||
EMUFILE_MEMORY ram = EMUFILE_MEMORY(expMemory, EXPANSION_MEMORY_SIZE);
|
||||
os.write_32LE(version);
|
||||
os.write_bool32(ext_ram_lock);
|
||||
os.write_MemoryStream(ram);
|
||||
}
|
||||
|
||||
virtual void loadstate(EMUFILE &is)
|
||||
{
|
||||
EMUFILE_MEMORY ram = EMUFILE_MEMORY();
|
||||
|
||||
s32 version = is.read_s32LE();
|
||||
|
||||
if (version >= 0)
|
||||
{
|
||||
is.read_bool32(ext_ram_lock);
|
||||
is.read_MemoryStream(ram);
|
||||
memcpy(expMemory, ram.buf(), std::min(EXPANSION_MEMORY_SIZE, ram.size()));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ISlot2Interface* construct_Slot2_ExpansionPak() { return new Slot2_ExpansionPak(); }
|
|
@ -0,0 +1,466 @@
|
|||
/*
|
||||
Copyright (C) 2009 CrazyMax
|
||||
Copyright (C) 2009-2021 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../slot2.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "../debug.h"
|
||||
#include "../NDSSystem.h"
|
||||
#include "../path.h"
|
||||
#include "../emufile.h"
|
||||
|
||||
#define EEPROM 0x52504545
|
||||
#define SRAM_ 0x4D415253
|
||||
#define FLASH 0x53414C46
|
||||
#define FLASH1M_ 0x5F4D3148
|
||||
#define SIIRTC_V 0x52494953
|
||||
|
||||
static const char *saveTypes[] = {
|
||||
"EEPROM",
|
||||
"SRAM",
|
||||
"FLASH",
|
||||
"FLASH1M",
|
||||
"SIIRTC_V",
|
||||
};
|
||||
|
||||
class Slot2_GbaCart : public ISlot2Interface
|
||||
{
|
||||
private:
|
||||
EMUFILE* fROM;
|
||||
EMUFILE* fSRAM;
|
||||
u32 romSize;
|
||||
u32 sramSize;
|
||||
u32 saveType;
|
||||
|
||||
struct
|
||||
{
|
||||
u32 size;
|
||||
u8 state;
|
||||
u8 cmd;
|
||||
u8 idDevice;
|
||||
u8 idManufacturer;
|
||||
u8 bank;
|
||||
} gbaFlash;
|
||||
|
||||
u32 readRom(const u32 pos, const u8 size)
|
||||
{
|
||||
if (!fROM) return 0xFFFFFFFF;
|
||||
|
||||
fROM->fseek(pos, SEEK_SET);
|
||||
|
||||
u32 data = 0xFFFFFFFF;
|
||||
u32 readed = fROM->fread(&data, size);
|
||||
return data;
|
||||
}
|
||||
|
||||
u32 readSRAM(const u32 pos, const u8 size)
|
||||
{
|
||||
if (!fSRAM)
|
||||
return 0xFFFFFFFF;
|
||||
|
||||
fSRAM->fseek(pos, SEEK_SET);
|
||||
|
||||
u32 data = 0xFFFFFFFF;
|
||||
u32 readed = fSRAM->fread(&data, size);
|
||||
return data;
|
||||
}
|
||||
|
||||
void writeSRAM(const u32 pos, const u8 *data, u32 size)
|
||||
{
|
||||
if (!fSRAM)
|
||||
return;
|
||||
|
||||
fSRAM->fseek(pos, SEEK_SET);
|
||||
|
||||
u32 writed = size;
|
||||
fSRAM->fwrite(data, size);
|
||||
fSRAM->fflush();
|
||||
}
|
||||
|
||||
|
||||
u32 scanSaveTypeGBA()
|
||||
{
|
||||
if (!fROM) return 0xFF;
|
||||
|
||||
fROM->fseek(0, SEEK_SET);
|
||||
int size = fROM->size();
|
||||
|
||||
int lastpct=1;
|
||||
|
||||
int len = fROM->size();
|
||||
for(;;)
|
||||
{
|
||||
u32 romType = 0;
|
||||
u32 readed = fROM->fread(&romType, 4);
|
||||
|
||||
int pos = fROM->ftell();
|
||||
int currPct = pos*100/(size-1);
|
||||
for(int i=lastpct;i<currPct;i++)
|
||||
{
|
||||
if(i%10==0)
|
||||
printf(" %d%%\n",i/10*10);
|
||||
else printf(".");
|
||||
lastpct = currPct;
|
||||
}
|
||||
|
||||
if (readed < 4)
|
||||
break;
|
||||
|
||||
if(pos >= len)
|
||||
break;
|
||||
|
||||
|
||||
switch (romType)
|
||||
{
|
||||
case EEPROM:
|
||||
return 1;
|
||||
case SRAM_:
|
||||
return 2;
|
||||
case FLASH:
|
||||
{
|
||||
u32 tmp = fROM->read_u32LE();
|
||||
return ((tmp == FLASH1M_)?3:5);
|
||||
}
|
||||
case SIIRTC_V:
|
||||
return 4;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void gbaWriteFlash(u32 adr, u8 val)
|
||||
{
|
||||
if (!fSRAM) return;
|
||||
switch (gbaFlash.state)
|
||||
{
|
||||
case 0:
|
||||
if (adr == 0x0A005555)
|
||||
{
|
||||
if (val == 0xF0)
|
||||
{
|
||||
//INFO("GBAgame: Flash: reset\n");
|
||||
gbaFlash.state = 0;
|
||||
gbaFlash.cmd = 0;
|
||||
return;
|
||||
}
|
||||
if (val == 0xAA)
|
||||
{
|
||||
gbaFlash.state = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (adr == 0x0A000000)
|
||||
{
|
||||
if (gbaFlash.cmd == 0xB0)
|
||||
{
|
||||
gbaFlash.bank = val;
|
||||
gbaFlash.cmd = 0;
|
||||
//INFO("GBAgame: Flash: change bank %i\n", val);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if ( (adr == 0x0A002AAA) && (val == 0x55) )
|
||||
{
|
||||
gbaFlash.state = 2;
|
||||
return;
|
||||
}
|
||||
gbaFlash.state = 0;
|
||||
break;
|
||||
case 2:
|
||||
if (adr == 0x0A005555)
|
||||
{
|
||||
//INFO("GBAgame: Flash: send command flash 0x%02X\n", val);
|
||||
switch (val)
|
||||
{
|
||||
case 0x80: // Erase
|
||||
gbaFlash.state = 0x80;
|
||||
break;
|
||||
|
||||
case 0x90: // Chip Identification
|
||||
gbaFlash.state = 0x90;
|
||||
break;
|
||||
|
||||
case 0xA0: // Write
|
||||
gbaFlash.state = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
gbaFlash.state = 0;
|
||||
break;
|
||||
}
|
||||
gbaFlash.cmd = val;
|
||||
return;
|
||||
}
|
||||
gbaFlash.state = 0;
|
||||
break;
|
||||
|
||||
// erase
|
||||
case 0x80:
|
||||
if ( (adr == 0x0A005555) && (val == 0xAA) )
|
||||
{
|
||||
gbaFlash.state = 0x81;
|
||||
return;
|
||||
}
|
||||
gbaFlash.state = 0;
|
||||
break;
|
||||
|
||||
case 0x81:
|
||||
if ( (adr == 0x0A002AAA) && (val == 0x55) )
|
||||
{
|
||||
gbaFlash.state = 0x82;
|
||||
return;
|
||||
}
|
||||
gbaFlash.state = 0;
|
||||
break;
|
||||
|
||||
case 0x82:
|
||||
if (val == 0x30)
|
||||
{
|
||||
u32 ofs = (adr & 0x0000F000) + (0x10000 * gbaFlash.bank);
|
||||
//INFO("GBAgame: Flash: erase from 0x%08X to 0x%08X\n", ofs + 0x0A000000, ofs + 0x0A001000);
|
||||
u8 *tmp = new u8[0x1000];
|
||||
memset(tmp, 0xFF, 0x1000);
|
||||
writeSRAM(ofs, tmp, 0x1000);
|
||||
delete [] tmp;
|
||||
}
|
||||
gbaFlash.state = 0;
|
||||
gbaFlash.cmd = 0;
|
||||
return;
|
||||
|
||||
// Chip Identification
|
||||
case 0x90:
|
||||
if ( (adr == 0x0A005555) && (val == 0xAA) )
|
||||
{
|
||||
gbaFlash.state = 0x91;
|
||||
return;
|
||||
}
|
||||
gbaFlash.state = 0;
|
||||
break;
|
||||
|
||||
case 0x91:
|
||||
if ( (adr == 0x0A002AAA) && (val == 0x55) )
|
||||
{
|
||||
gbaFlash.state = 0x92;
|
||||
return;
|
||||
}
|
||||
gbaFlash.state = 0;
|
||||
break;
|
||||
|
||||
case 0x92:
|
||||
gbaFlash.state = 0;
|
||||
gbaFlash.cmd = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (gbaFlash.cmd == 0xA0) // write
|
||||
{
|
||||
writeSRAM((adr & 0x1FFFF) + (0x10000 * gbaFlash.bank), &val, 1);
|
||||
gbaFlash.state = 0;
|
||||
gbaFlash.cmd = 0;
|
||||
return;
|
||||
}
|
||||
INFO("GBAgame: Flash: write unknown atn 0x%08X = 0x%02X\n", adr, val);
|
||||
}
|
||||
|
||||
u8 gbaReadFlash(u32 adr)
|
||||
{
|
||||
if (!fSRAM) return 0xFF;
|
||||
if (gbaFlash.cmd == 0)
|
||||
return readSRAM((adr & 0x1FFFF) + (0x10000 * gbaFlash.bank), 1);
|
||||
|
||||
//INFO("GBAgame: flash read at 0x%08X\n", adr);
|
||||
|
||||
switch (gbaFlash.cmd)
|
||||
{
|
||||
case 0x90: // Chip Identification
|
||||
if (adr == 0x0A000000) return gbaFlash.idManufacturer;
|
||||
if (adr == 0x0A000001) return gbaFlash.idDevice;
|
||||
break;
|
||||
|
||||
case 0xF0: //
|
||||
gbaFlash.state = 0;
|
||||
gbaFlash.cmd = 0;
|
||||
break;
|
||||
|
||||
case 0xB0: // Bank switching
|
||||
break;
|
||||
|
||||
default:
|
||||
INFO("GBAgame: Flash: read - unknown command at 0x%08X = 0x%02X\n", adr, gbaFlash.cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
delete fROM; fROM = NULL;
|
||||
delete fSRAM; fSRAM = NULL;
|
||||
romSize = 0;
|
||||
sramSize = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
Slot2_GbaCart()
|
||||
: fROM(NULL)
|
||||
, fSRAM(NULL)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
virtual Slot2Info const* info()
|
||||
{
|
||||
static Slot2InfoSimple info("GBA Cartridge", "GBA cartridge in slot", 0x03);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
Close();
|
||||
romSize = 0;
|
||||
sramSize = 0;
|
||||
|
||||
if (gameInfo.romsize == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (GBACartridge_RomPath.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcasecmp(GBACartridge_RomPath.c_str(), "self"))
|
||||
{
|
||||
GBACartridge_RomPath = path.path;
|
||||
GBACartridge_SRAMPath = Path::GetFileNameWithoutExt(GBACartridge_RomPath) + "." + GBA_SRAM_FILE_EXT;
|
||||
}
|
||||
|
||||
printf("GBASlot opening ROM: %s\n", GBACartridge_RomPath.c_str());
|
||||
EMUFILE_FILE *inf = new EMUFILE_FILE(GBACartridge_RomPath, "rb");
|
||||
fROM = inf;
|
||||
if (fROM->fail())
|
||||
{
|
||||
printf(" - Failed\n");
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
inf->EnablePositionCache();
|
||||
|
||||
romSize = fROM->size();
|
||||
printf(" - Success (%u bytes)\n", romSize);
|
||||
|
||||
// Load the GBA cartridge SRAM.
|
||||
inf = new EMUFILE_FILE(GBACartridge_SRAMPath, "rb+");
|
||||
fSRAM = inf;
|
||||
if(fSRAM->fail())
|
||||
{
|
||||
delete fSRAM;
|
||||
fSRAM = NULL;
|
||||
printf("GBASlot did not load associated SRAM.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
inf->EnablePositionCache();
|
||||
sramSize = fSRAM->size();
|
||||
printf("Scanning GBA rom to ID save type\n");
|
||||
saveType = scanSaveTypeGBA();
|
||||
printf("\nGBASlot found SRAM (%s - %u bytes) at:\n%s\n", (saveType == 0xFF)?"Unknown":saveTypes[saveType], sramSize, GBACartridge_SRAMPath.c_str());
|
||||
gbaFlash.size = sramSize;
|
||||
if (gbaFlash.size <= (64 * 1024))
|
||||
{
|
||||
gbaFlash.idDevice = 0x1B;
|
||||
gbaFlash.idManufacturer = 0x32;
|
||||
}
|
||||
else
|
||||
{
|
||||
gbaFlash.idDevice = 0x09;
|
||||
gbaFlash.idManufacturer = 0xC2;
|
||||
}
|
||||
gbaFlash.state = 0;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void disconnect()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
virtual void writeByte(u8 PROCNUM, u32 addr, u8 val)
|
||||
{
|
||||
if ((addr >= 0x0A000000) && (addr < 0x0A010000))
|
||||
{
|
||||
switch (saveType)
|
||||
{
|
||||
case 3: // Flash
|
||||
case 5:
|
||||
gbaWriteFlash(addr, val);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual u8 readByte(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
if (addr < 0x0A000000)
|
||||
return (u8)readRom(addr - 0x08000000, 1);
|
||||
|
||||
if (addr < 0x0A010000)
|
||||
{
|
||||
if ((saveType == 3) || (saveType == 5))
|
||||
return gbaReadFlash(addr);
|
||||
|
||||
return (u8)readSRAM(addr - 0x0A000000, 1);
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
virtual u16 readWord(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
if (addr < 0x0A000000)
|
||||
return (u16)readRom(addr - 0x08000000, 2);
|
||||
|
||||
if (addr < 0x0A010000)
|
||||
return (u16)readSRAM(addr - 0x0A000000, 2);
|
||||
|
||||
return 0xFFFF;
|
||||
}
|
||||
virtual u32 readLong(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
if (addr < 0x0A000000)
|
||||
return (u32)readRom(addr - 0x08000000, 4);
|
||||
|
||||
if (addr < 0x0A010000)
|
||||
return (u32)readSRAM(addr - 0x0A000000, 4);
|
||||
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
};
|
||||
|
||||
ISlot2Interface* construct_Slot2_GbaCart() { return new Slot2_GbaCart(); }
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
Copyright (C) 2009 CrazyMax
|
||||
Copyright (C) 2009-2013 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../slot2.h"
|
||||
static u8 guitarKeyStatus;
|
||||
|
||||
class Slot2_GuitarGrip : public ISlot2Interface
|
||||
{
|
||||
private:
|
||||
|
||||
public:
|
||||
virtual Slot2Info const* info()
|
||||
{
|
||||
static Slot2InfoSimple info("Guitar Grip", "Guitar Grip for Guitar Hero games", 0x04);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
guitarKeyStatus = 0xFF;
|
||||
}
|
||||
|
||||
virtual u8 readByte(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
if (addr == 0x0A000000)
|
||||
return guitarKeyStatus;
|
||||
|
||||
return (addr & 1) ? 0xF9 : 0xFF;
|
||||
}
|
||||
|
||||
virtual u16 readWord(u8 PROCNUM, u32 addr) { return 0xF9FF; }
|
||||
virtual u32 readLong(u8 PROCNUM, u32 addr) { return 0xF9FFF9FF; }
|
||||
};
|
||||
|
||||
ISlot2Interface* construct_Slot2_GuitarGrip() { return new Slot2_GuitarGrip(); }
|
||||
|
||||
void guitarGrip_setKey(bool green, bool red, bool yellow, bool blue)
|
||||
{
|
||||
const u8 g = (green) ? (1 << 6) : 0;
|
||||
const u8 r = (red) ? (1 << 5) : 0;
|
||||
const u8 y = (yellow) ? (1 << 4) : 0;
|
||||
const u8 b = (blue) ? (1 << 3) : 0;
|
||||
|
||||
guitarKeyStatus = ~(g | r | y | b);
|
||||
}
|
||||
|
||||
void guitarGrip_setKey(u8 theKeys)
|
||||
{
|
||||
guitarKeyStatus = theKeys;
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
//HCV-1000 emulation code adapted from GBE+: https://github.com/shonumi/gbe-plus
|
||||
|
||||
/*
|
||||
Modifications Copyright (C) 2023 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "../slot2.h"
|
||||
|
||||
u8 hcv1000_cnt;
|
||||
char hcv1000_data[16];
|
||||
|
||||
class Slot2_HCV1000 : public ISlot2Interface
|
||||
{
|
||||
public:
|
||||
|
||||
virtual Slot2Info const* info()
|
||||
{
|
||||
static Slot2InfoSimple info("Sega Card Reader", "Sega Card Reader(HCV-1000) add-on", 0x09);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual bool init()
|
||||
{
|
||||
hcv1000_cnt = 0;
|
||||
memset(hcv1000_data, 0x5F, 16);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
virtual void writeByte(u8 PROCNUM, u32 addr, u8 val)
|
||||
{
|
||||
if (addr == 0xA000000) { hcv1000_cnt = (val & 0x83); }
|
||||
}
|
||||
|
||||
virtual u8 readByte(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
u8 slot_byte = 0xFF;
|
||||
//Reading these cart addresses is for detection
|
||||
if (addr < 0x8020000)
|
||||
{
|
||||
u8 data = 0xF0 | ((addr & 0x1F) >> 1);
|
||||
slot_byte = (addr & 0x1) ? 0xFD : data;
|
||||
}
|
||||
|
||||
//HCV_CNT
|
||||
else if (addr == 0xA000000) { slot_byte = hcv1000_cnt; }
|
||||
|
||||
//HCV_DATA
|
||||
else if ((addr >= 0xA000010) && (addr <= 0xA00001F))
|
||||
{
|
||||
slot_byte = (u8)hcv1000_data[addr & 0xF];
|
||||
}
|
||||
|
||||
return slot_byte;
|
||||
}
|
||||
|
||||
virtual u16 readWord(u8 PROCNUM, u32 addr) { return 0xFDFD; };
|
||||
virtual u32 readLong(u8 PROCNUM, u32 addr) { return 0xFDFDFDFD; };
|
||||
};
|
||||
|
||||
ISlot2Interface* construct_Slot2_HCV1000() { return new Slot2_HCV1000(); }
|
||||
|
||||
void HCV1000_setReady()
|
||||
{
|
||||
hcv1000_cnt &= ~0x80;
|
||||
}
|
||||
|
||||
void HCV1000_setBarcode(std::string barcode)
|
||||
{
|
||||
barcode.resize(16, '_');
|
||||
memcpy(hcv1000_data, barcode.c_str(), barcode.length());
|
||||
}
|
|
@ -0,0 +1,301 @@
|
|||
/*
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2006 Mic
|
||||
Copyright (C) 2009-2017 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../slot2.h"
|
||||
#include "../debug.h"
|
||||
#include "../emufile.h"
|
||||
#include "../path.h"
|
||||
#include "../utils/vfat.h"
|
||||
|
||||
// Set up addresses for GBAMP
|
||||
#define CF_REG_DATA 0x9000000
|
||||
#define CF_REG_ERR 0x9020000
|
||||
#define CF_REG_SEC 0x9040000
|
||||
#define CF_REG_LBA1 0x9060000
|
||||
#define CF_REG_LBA2 0x9080000
|
||||
#define CF_REG_LBA3 0x90A0000
|
||||
#define CF_REG_LBA4 0x90C0000
|
||||
#define CF_REG_CMD 0x90E0000
|
||||
#define CF_REG_STS 0x98C0000
|
||||
|
||||
// CF Card commands
|
||||
#define CF_CMD_LBA 0xE0
|
||||
#define CF_CMD_READ 0x20
|
||||
#define CF_CMD_WRITE 0x30
|
||||
|
||||
static u16 cf_reg_sts,
|
||||
cf_reg_lba1,
|
||||
cf_reg_lba2,
|
||||
cf_reg_lba3,
|
||||
cf_reg_lba4,
|
||||
cf_reg_cmd;
|
||||
static off_t currLBA;
|
||||
|
||||
static const int lfnPos[13] = {1,3,5,7,9,14,16,18,20,22,24,28,30};
|
||||
|
||||
static u32 fileStartLBA,fileEndLBA;
|
||||
static std::string sFlashPath;
|
||||
static BOOL cflashDeviceEnabled = FALSE;
|
||||
|
||||
static EMUFILE* file = NULL;
|
||||
|
||||
// ===========================
|
||||
BOOL inited;
|
||||
|
||||
enum EListCallbackArg {
|
||||
EListCallbackArg_Item, EListCallbackArg_Pop
|
||||
};
|
||||
|
||||
static BOOL cflash_init()
|
||||
{
|
||||
if (inited) return FALSE;
|
||||
BOOL init_good = FALSE;
|
||||
|
||||
CFLASHLOG("CFlash_Mode: %d\n",CFlash_Mode);
|
||||
|
||||
if (CFlash_Mode == ADDON_CFLASH_MODE_RomPath)
|
||||
{
|
||||
sFlashPath = path.RomDirectory;
|
||||
INFO("Using CFlash directory of rom: %s\n", sFlashPath.c_str());
|
||||
}
|
||||
else if(CFlash_Mode == ADDON_CFLASH_MODE_Path)
|
||||
{
|
||||
sFlashPath = CFlash_Path;
|
||||
INFO("Using CFlash directory: %s\n", sFlashPath.c_str());
|
||||
}
|
||||
else if(CFlash_Mode == ADDON_CFLASH_MODE_File)
|
||||
{
|
||||
sFlashPath = CFlash_Path;
|
||||
INFO("Using CFlash disk image file %s\n", sFlashPath.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (sFlashPath == "") return FALSE;
|
||||
|
||||
if(CFlash_IsUsingPath())
|
||||
{
|
||||
cflashDeviceEnabled = FALSE;
|
||||
currLBA = 0;
|
||||
|
||||
fileStartLBA = fileEndLBA = 0xFFFFFFFF;
|
||||
VFAT vfat;
|
||||
bool ret = vfat.build(sFlashPath.c_str(),16); //allocate 16MB extra for writing. this is probably enough for anyone, but maybe it should be configurable.
|
||||
//we could always suggest to users to add a big file to their directory to overwrite (that would cause the image to get padded)
|
||||
|
||||
if(!ret)
|
||||
{
|
||||
CFLASHLOG("FAILED cflash_build_fat\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
file = vfat.detach();
|
||||
|
||||
cf_reg_sts = 0x58; // READY
|
||||
|
||||
cflashDeviceEnabled = TRUE;
|
||||
init_good = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
file = new EMUFILE_FILE(sFlashPath.c_str(),"rb+");
|
||||
if(file->fail())
|
||||
{
|
||||
INFO("Failed to open file %s\n", sFlashPath.c_str());
|
||||
delete file;
|
||||
file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// READY
|
||||
cf_reg_sts = 0x58;
|
||||
|
||||
currLBA = 0;
|
||||
cf_reg_lba1 = cf_reg_lba2 =
|
||||
cf_reg_lba3 = cf_reg_lba4 = 0;
|
||||
|
||||
inited = TRUE;
|
||||
return init_good;
|
||||
}
|
||||
|
||||
static unsigned int cflash_read(unsigned int address)
|
||||
{
|
||||
unsigned int ret_value = 0;
|
||||
size_t elems_read = 0;
|
||||
|
||||
switch (address)
|
||||
{
|
||||
case CF_REG_STS:
|
||||
ret_value = cf_reg_sts;
|
||||
break;
|
||||
|
||||
case CF_REG_DATA:
|
||||
if (cf_reg_cmd == CF_CMD_READ)
|
||||
{
|
||||
if(file)
|
||||
{
|
||||
u8 data[2] = {0,0};
|
||||
file->fseek(currLBA, SEEK_SET);
|
||||
elems_read += file->fread(data,2);
|
||||
ret_value = data[1] << 8 | data[0];
|
||||
}
|
||||
currLBA += 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case CF_REG_CMD:
|
||||
break;
|
||||
|
||||
case CF_REG_LBA1:
|
||||
ret_value = cf_reg_lba1;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
static void cflash_write(unsigned int address,unsigned int data)
|
||||
{
|
||||
static u8 sector_data[512];
|
||||
static u32 sector_write_index = 0;
|
||||
|
||||
switch (address)
|
||||
{
|
||||
case CF_REG_STS:
|
||||
cf_reg_sts = data&0xFFFF;
|
||||
break;
|
||||
|
||||
case CF_REG_DATA:
|
||||
if (cf_reg_cmd == CF_CMD_WRITE)
|
||||
{
|
||||
{
|
||||
sector_data[sector_write_index] = (data >> 0) & 0xff;
|
||||
sector_data[sector_write_index + 1] = (data >> 8) & 0xff;
|
||||
|
||||
sector_write_index += 2;
|
||||
|
||||
if (sector_write_index == 512)
|
||||
{
|
||||
CFLASHLOG( "Write sector to %ld\n", currLBA);
|
||||
size_t written = 0;
|
||||
|
||||
if(file)
|
||||
if(currLBA + 512 < file->size())
|
||||
{
|
||||
file->fseek(currLBA,SEEK_SET);
|
||||
|
||||
while(written < 512)
|
||||
{
|
||||
size_t todo = 512-written;
|
||||
file->fwrite(§or_data[written], todo);
|
||||
size_t cur_write = todo;
|
||||
written += cur_write;
|
||||
if ( cur_write == (size_t)-1) break;
|
||||
}
|
||||
}
|
||||
|
||||
CFLASHLOG("Wrote %u bytes\n", written);
|
||||
|
||||
currLBA += 512;
|
||||
sector_write_index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CF_REG_CMD:
|
||||
cf_reg_cmd = data&0xFF;
|
||||
cf_reg_sts = 0x58; // READY
|
||||
break;
|
||||
|
||||
case CF_REG_LBA1:
|
||||
cf_reg_lba1 = data&0xFF;
|
||||
currLBA = (currLBA&0xFFFFFF00)| cf_reg_lba1;
|
||||
break;
|
||||
|
||||
case CF_REG_LBA2:
|
||||
cf_reg_lba2 = data&0xFF;
|
||||
currLBA = (currLBA&0xFFFF00FF)|(cf_reg_lba2<<8);
|
||||
break;
|
||||
|
||||
case CF_REG_LBA3:
|
||||
cf_reg_lba3 = data&0xFF;
|
||||
currLBA = (currLBA&0xFF00FFFF)|(cf_reg_lba3<<16);
|
||||
break;
|
||||
|
||||
case CF_REG_LBA4:
|
||||
cf_reg_lba4 = data&0xFF;
|
||||
|
||||
if ((cf_reg_lba4 & 0xf0) == CF_CMD_LBA)
|
||||
{
|
||||
currLBA = (currLBA&0x00FFFFFF)|((cf_reg_lba4&0x0F)<<24);
|
||||
currLBA *= 512;
|
||||
sector_write_index = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void cflash_close( void)
|
||||
{
|
||||
if (!inited) return;
|
||||
if(file) delete file;
|
||||
cflashDeviceEnabled = FALSE;
|
||||
file = NULL;
|
||||
inited = FALSE;
|
||||
}
|
||||
|
||||
class Slot2_CFlash : public ISlot2Interface
|
||||
{
|
||||
public:
|
||||
virtual Slot2Info const* info()
|
||||
{
|
||||
static Slot2InfoSimple info("MPCF Flash Card Device", "MPCF Flash Card Device", 0x01);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
cflash_close();
|
||||
cflash_init();
|
||||
}
|
||||
virtual void disconnect()
|
||||
{
|
||||
cflash_close();
|
||||
}
|
||||
|
||||
virtual void writeByte(u8 PROCNUM, u32 addr, u8 val) { cflash_write(addr, val); }
|
||||
virtual void writeWord(u8 PROCNUM, u32 addr, u16 val) { cflash_write(addr, val); }
|
||||
virtual void writeLong(u8 PROCNUM, u32 addr, u32 val) { cflash_write(addr, val); }
|
||||
|
||||
virtual u8 readByte(u8 PROCNUM, u32 addr) { return (cflash_read(addr)); }
|
||||
virtual u16 readWord(u8 PROCNUM, u32 addr) { return (cflash_read(addr)); }
|
||||
virtual u32 readLong(u8 PROCNUM, u32 addr) { return (cflash_read(addr)); }
|
||||
|
||||
};
|
||||
|
||||
ISlot2Interface* construct_Slot2_CFlash() { return new Slot2_CFlash(); }
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
Copyright (C) 2009 CrazyMax
|
||||
Copyright (C) 2009-2013 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../slot2.h"
|
||||
|
||||
class Slot2_None : public ISlot2Interface
|
||||
{
|
||||
public:
|
||||
virtual Slot2Info const* info()
|
||||
{
|
||||
static Slot2InfoSimple info("None", "Slot2 no-device emulation", 0xFF);
|
||||
return &info;
|
||||
}
|
||||
};
|
||||
|
||||
ISlot2Interface* construct_Slot2_None() { return new Slot2_None(); }
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
Copyright (C) 2011-2015 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
this device seems to have a 12bit value (like 20.12 fixed point.. get it?) located at 0x0A000000
|
||||
clockwise = right = increases.
|
||||
it returns the correct little endian bytes through byte reads.
|
||||
through halfword reads, it returns the LSB twice
|
||||
through full word reads, it returns the LSB four times.
|
||||
after that everything is 0x00.
|
||||
if the slot2 timings are wrong, then this device will return glitchy or 0xFF output.
|
||||
so this emulation code will attempt to validate that.
|
||||
arkanoid was setting REG_EXMEMCNT = 0x082F
|
||||
|
||||
the rom returns 0xEFFF for all addresses and should be used to detect this device
|
||||
|
||||
writing any byte to SRAM or writing any halfword/word to rom results in a reset or some kind of recalibrate
|
||||
the resulting value may be 0x000,0x001, or 0xFFF. seems mostly random, though once it is reset, resetting again won't change it.
|
||||
you must wait until the paddle has been moved.
|
||||
|
||||
conclusion:
|
||||
The emulation in all the handling of erroneous cases is not perfect, and some other users of the paddle (do any other games use it?)
|
||||
maybe legally configure the paddle differently, which could be rejected here; in which case this code will need finetuning
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "../slot2.h"
|
||||
#include "../NDSSystem.h"
|
||||
|
||||
class Slot2_Paddle : public ISlot2Interface
|
||||
{
|
||||
private:
|
||||
void calibrate() { nds.paddle = 0; }
|
||||
bool Validate(u32 procnum, bool rom)
|
||||
{
|
||||
if(rom)
|
||||
return ValidateSlot2Access(procnum, 0, 0, 0, -1);
|
||||
else
|
||||
return ValidateSlot2Access(procnum, 18, 0, 0, 1);
|
||||
}
|
||||
|
||||
public:
|
||||
virtual Slot2Info const* info()
|
||||
{
|
||||
static Slot2InfoSimple info("Paddle Controller", "Taito Paddle Controller", 0x07);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void writeByte(u8 PROCNUM, u32 addr, u8 val)
|
||||
{
|
||||
if (addr < 0x0A000000)
|
||||
calibrate();
|
||||
}
|
||||
virtual void writeWord(u8 PROCNUM, u32 addr, u16 val)
|
||||
{
|
||||
if (addr < 0x0A000000)
|
||||
calibrate();
|
||||
}
|
||||
virtual void writeLong(u8 PROCNUM, u32 addr, u32 val)
|
||||
{
|
||||
if (addr < 0x0A000000)
|
||||
calibrate();
|
||||
}
|
||||
|
||||
virtual u8 readByte(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
//printf("paddle: read 08 at 0x%08X\n", addr);
|
||||
if (!Validate(PROCNUM, (addr < 0x0A000000)))
|
||||
return 0xFF;
|
||||
|
||||
if (addr < 0x0A000000)
|
||||
return (addr & 1)?0xFF:0xEF;
|
||||
|
||||
if (addr == 0x0A000000)
|
||||
return (nds.paddle & 0xFF);
|
||||
|
||||
if (addr == 0x0A000001)
|
||||
return ((nds.paddle >> 8) & 0x0F);
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
virtual u16 readWord(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
//printf("paddle: read 16 at 0x%08X\n", addr);
|
||||
if (!Validate(PROCNUM, (addr < 0x0A000000)))
|
||||
return 0xFFFF;
|
||||
|
||||
if (addr < 0x0A000000)
|
||||
return 0xEFFF;
|
||||
|
||||
if (addr == 0x0A000000)
|
||||
{
|
||||
u8 val = (nds.paddle & 0xFF);
|
||||
return (val | (val << 8));
|
||||
}
|
||||
|
||||
return 0x0000;
|
||||
}
|
||||
virtual u32 readLong(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
//printf("paddle: read 32 at 0x%08X\n", addr);
|
||||
if (!Validate(PROCNUM, (addr < 0x0A000000)))
|
||||
return 0xFFFFFFFF;
|
||||
|
||||
if (addr < 0x0A000000)
|
||||
return 0xEFFFEFFF;
|
||||
|
||||
if (addr == 0x0A000000)
|
||||
{
|
||||
u8 val = (nds.paddle & 0xFF);
|
||||
return (val | (val << 8) | (val << 16) | (val << 24));
|
||||
}
|
||||
|
||||
return 0x00000000;
|
||||
}
|
||||
};
|
||||
|
||||
u16 Paddle_GetValue()
|
||||
{
|
||||
return nds.paddle;
|
||||
}
|
||||
|
||||
void Paddle_SetValue(u16 theValue)
|
||||
{
|
||||
nds.paddle = theValue;
|
||||
}
|
||||
|
||||
ISlot2Interface* construct_Slot2_Paddle() { return new Slot2_Paddle(); }
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
Copyright (C) 2013-2015 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../slot2.h"
|
||||
#include "../NDSSystem.h"
|
||||
|
||||
class Slot2_PassME : public ISlot2Interface
|
||||
{
|
||||
public:
|
||||
virtual Slot2Info const* info()
|
||||
{
|
||||
static Slot2InfoSimple info("PassME", "PassME in GBA slot", 0x08);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual u8 readByte(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
u32 tmp_addr = (addr & 0x07FFFFFF);
|
||||
if (tmp_addr < gameInfo.romsize)
|
||||
return (u8)gameInfo.readROM(tmp_addr);
|
||||
|
||||
return (0xFF);
|
||||
}
|
||||
virtual u16 readWord(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
u32 tmp_addr = (addr & 0x07FFFFFF);
|
||||
if (tmp_addr < gameInfo.romsize)
|
||||
return (u16)gameInfo.readROM(tmp_addr);
|
||||
|
||||
return (0xFFFF);
|
||||
}
|
||||
virtual u32 readLong(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
u32 tmp_addr = (addr & 0x07FFFFFF);
|
||||
if (tmp_addr < gameInfo.romsize)
|
||||
return (u32)gameInfo.readROM(tmp_addr);
|
||||
|
||||
return (0xFFFFFFFF);
|
||||
}
|
||||
};
|
||||
|
||||
ISlot2Interface* construct_Slot2_PassME() { return new Slot2_PassME(); }
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
Copyright (C) 2010-2013 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../slot2.h"
|
||||
|
||||
static u16 pianoKeyStatus = 0;
|
||||
|
||||
class Slot2_EasyPiano : public ISlot2Interface
|
||||
{
|
||||
public:
|
||||
virtual Slot2Info const* info()
|
||||
{
|
||||
static Slot2InfoSimple info("Piano", "Piano for EasyPiano", 0x06);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
pianoKeyStatus = 0xE7FF;
|
||||
}
|
||||
|
||||
virtual u8 readByte(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
//printf("piano: read 08 at 0x%08X\n", adr);
|
||||
|
||||
//the actual keyboard output
|
||||
|
||||
//byte:bit
|
||||
//0x09FFFFFE:0 = C
|
||||
//0x09FFFFFE:1 = C#
|
||||
//0x09FFFFFE:2 = D
|
||||
//0x09FFFFFE:3 = D#
|
||||
//0x09FFFFFE:4 = E
|
||||
//0x09FFFFFE:5 = F
|
||||
//0x09FFFFFE:6 = F#
|
||||
//0x09FFFFFE:7 = G
|
||||
//0x09FFFFFF:0 = G#
|
||||
//0x09FFFFFF:1 = A
|
||||
//0x09FFFFFF:2 = A#
|
||||
//0x09FFFFFF:3 = ?
|
||||
//0x09FFFFFF:4 = ?
|
||||
//0x09FFFFFF:5 = B
|
||||
//0x09FFFFFF:6 = hiC
|
||||
//0x09FFFFFF:7 = ?
|
||||
|
||||
//deassert bit if key is pressed
|
||||
|
||||
//LOG("PIANO: %04X\n",pianoKeyStatus);
|
||||
|
||||
if (addr == 0x09FFFFFE) return ((pianoKeyStatus >> 0) & 0xFF);
|
||||
if (addr == 0x09FFFFFF) return ((pianoKeyStatus >> 8) & 0xFF) & ~(0x18);
|
||||
|
||||
return (addr & 1) ? 0xE7 : 0xFF;
|
||||
}
|
||||
virtual u16 readWord(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
if (addr != 0x09FFFFFE)
|
||||
return 0xE7FF;
|
||||
|
||||
return readByte(PROCNUM, 0x09FFFFFE) | (readByte(PROCNUM,0x09FFFFFF) << 8);
|
||||
}
|
||||
virtual u32 readLong(u8 PROCNUM, u32 addr) { return 0xE7FFE7FF; }
|
||||
|
||||
};
|
||||
|
||||
ISlot2Interface* construct_Slot2_EasyPiano() { return new Slot2_EasyPiano(); }
|
||||
|
||||
void piano_setKey(bool c, bool cs, bool d, bool ds, bool e, bool f, bool fs, bool g, bool gs, bool a, bool as, bool b, bool hic)
|
||||
{
|
||||
//0x09FFFFFE:0 = C
|
||||
//0x09FFFFFE:1 = C#
|
||||
//0x09FFFFFE:2 = D
|
||||
//0x09FFFFFE:3 = D#
|
||||
//0x09FFFFFE:4 = E
|
||||
//0x09FFFFFE:5 = F
|
||||
//0x09FFFFFE:6 = F#
|
||||
//0x09FFFFFE:7 = G
|
||||
//0x09FFFFFE:0 = G#
|
||||
//0x09FFFFFE:1 = A
|
||||
//0x09FFFFFF:2 = A#
|
||||
//0x09FFFFFF:3 = ?
|
||||
//0x09FFFFFF:4 = ?
|
||||
//0x09FFFFFF:5 = B
|
||||
//0x09FFFFFF:6 = hiC
|
||||
//0x09FFFFFF:7 = ?
|
||||
|
||||
#define BIT_P(N,v) ((v)?(1<<(N)):0)
|
||||
pianoKeyStatus = ~(
|
||||
BIT_P(0,c) |
|
||||
BIT_P(1,cs) |
|
||||
BIT_P(2,d) |
|
||||
BIT_P(3,ds) |
|
||||
BIT_P(4,e) |
|
||||
BIT_P(5,f) |
|
||||
BIT_P(6,fs) |
|
||||
BIT_P(7,g) |
|
||||
BIT_P(8,gs) |
|
||||
BIT_P(9,a) |
|
||||
BIT_P(10,as) |
|
||||
BIT_P(13,b) |
|
||||
BIT_P(14,hic)
|
||||
);
|
||||
}
|
||||
|
||||
void piano_setKey(u16 theKeys)
|
||||
{
|
||||
pianoKeyStatus = theKeys;
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
Copyright (C) 2009 CrazyMax
|
||||
Copyright (C) 2009-2013 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../slot2.h"
|
||||
|
||||
void (*FeedbackON)(bool enable) = NULL;
|
||||
|
||||
class Slot2_RumblePak : public ISlot2Interface
|
||||
{
|
||||
private:
|
||||
u16 old_val_rumble;
|
||||
|
||||
public:
|
||||
virtual Slot2Info const* info()
|
||||
{
|
||||
static Slot2InfoSimple info("Rumble Pak", "NDS Rumble Pak (need joystick with Feedback)", 0x02);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
old_val_rumble = 0;
|
||||
if (!FeedbackON) return;
|
||||
FeedbackON(false);
|
||||
}
|
||||
|
||||
virtual void disconnect()
|
||||
{
|
||||
FeedbackON(false);
|
||||
}
|
||||
|
||||
virtual void writeWord(u8 PROCNUM, u32 addr, u16 val)
|
||||
{
|
||||
if (!FeedbackON) return;
|
||||
if (old_val_rumble == val) return;
|
||||
|
||||
old_val_rumble = val;
|
||||
if ((addr == 0x08000000) || (addr == 0x08001000))
|
||||
FeedbackON(val);
|
||||
}
|
||||
|
||||
virtual u8 readByte(u8 PROCNUM, u32 addr) { return (addr & 1)?0xFF:0xFD; };
|
||||
virtual u16 readWord(u8 PROCNUM, u32 addr) { return 0xFFFD; };
|
||||
virtual u32 readLong(u8 PROCNUM, u32 addr) { return 0xFFFDFFFD; };
|
||||
};
|
||||
|
||||
ISlot2Interface* construct_Slot2_RumblePak() { return new Slot2_RumblePak(); }
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,82 @@
|
|||
/* Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2011 Loren Merritt
|
||||
Copyright (C) 2012-2013 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ARM_JIT
|
||||
#define ARM_JIT
|
||||
|
||||
#include "types.h"
|
||||
#ifndef _MSC_VER
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
typedef u32 (FASTCALL* ArmOpCompiled)();
|
||||
|
||||
void arm_jit_reset(bool enable, bool suppress_msg = false);
|
||||
void arm_jit_close();
|
||||
void arm_jit_sync();
|
||||
template<int PROCNUM> u32 arm_jit_compile();
|
||||
|
||||
//#define MAPPED_JIT_FUNCS: to define or not to define?
|
||||
//* x86 windows seems faster with NON-DEFINED
|
||||
//* x64 windows seems faster with DEFINED
|
||||
//* x86 windows seems to have problems without DEFINED when desmume is built as a dll due to the
|
||||
// ~300 MB .bss section created by the 256MB non-mapped compiled_funcs table
|
||||
// (when loaded as a dll into a busy process, that much contiguous address space is hard to find. No big deal when starting up a process)
|
||||
//In principle, mapped compiled_funcs should be faster because it avoids some bit shifting logic to look it up from the memory map, right,
|
||||
//but I guess it doesn't always work out that way.
|
||||
//
|
||||
//So here's my proposed policy. NON-DEFINED is dangerous due to the huge .bss section, so it should be the default
|
||||
//The build system should #define JIT_FUNCS_FLAT to make the flat array
|
||||
#ifndef JIT_FUNCS_FLAT
|
||||
#define MAPPED_JIT_FUNCS
|
||||
#endif
|
||||
|
||||
#ifdef MAPPED_JIT_FUNCS
|
||||
struct JIT_struct
|
||||
{
|
||||
// only include the memory types that code can execute from
|
||||
uintptr_t MAIN_MEM[16*1024*1024/2];
|
||||
uintptr_t SWIRAM[0x8000/2];
|
||||
uintptr_t ARM9_ITCM[0x8000/2];
|
||||
uintptr_t ARM9_LCDC[0xA4000/2];
|
||||
uintptr_t ARM9_BIOS[0x8000/2];
|
||||
uintptr_t ARM7_BIOS[0x4000/2];
|
||||
uintptr_t ARM7_ERAM[0x10000/2];
|
||||
uintptr_t ARM7_WIRAM[0x10000/2];
|
||||
uintptr_t ARM7_WRAM[0x40000/2];
|
||||
|
||||
static uintptr_t *JIT_MEM[2][0x4000];
|
||||
};
|
||||
extern CACHE_ALIGN JIT_struct JIT;
|
||||
#define JIT_COMPILED_FUNC(adr, PROCNUM) JIT.JIT_MEM[PROCNUM][((adr)&0x0FFFC000)>>14][((adr)&0x00003FFE)>>1]
|
||||
#define JIT_COMPILED_FUNC_PREMASKED(adr, PROCNUM, ofs) JIT.JIT_MEM[PROCNUM][(adr)>>14][(((adr)&0x00003FFE)>>1)+ofs]
|
||||
#define JIT_COMPILED_FUNC_KNOWNBANK(adr, bank, mask, ofs) JIT.bank[(((adr)&(mask))>>1)+ofs]
|
||||
#define JIT_MAPPED(adr, PROCNUM) JIT.JIT_MEM[PROCNUM][(adr)>>14]
|
||||
#else
|
||||
// actually an array of function pointers, but they fit in 32bit address space, so might as well save memory
|
||||
extern uintptr_t compiled_funcs[];
|
||||
// there isn't anything mapped between 07000000 and 0EFFFFFF, so we can mask off bit 27 and get away with a smaller array
|
||||
#define JIT_COMPILED_FUNC(adr, PROCNUM) compiled_funcs[((adr) & 0x07FFFFFE) >> 1]
|
||||
#define JIT_COMPILED_FUNC_PREMASKED(adr, PROCNUM, ofs) JIT_COMPILED_FUNC(adr+(ofs<<1), PROCNUM)
|
||||
#define JIT_COMPILED_FUNC_KNOWNBANK(adr, bank, mask, ofs) JIT_COMPILED_FUNC(adr+(ofs<<1), PROCNUM)
|
||||
#define JIT_MAPPED(adr, PROCNUM) true
|
||||
#endif
|
||||
|
||||
extern u32 saveBlockSizeJIT;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,776 @@
|
|||
/*
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2009-2021 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "armcpu.h"
|
||||
#include "instructions.h"
|
||||
#include "cp15.h"
|
||||
#include "bios.h"
|
||||
#include "debug.h"
|
||||
#include "NDSSystem.h"
|
||||
#include "MMU_timing.h"
|
||||
#include "utils/bits.h"
|
||||
#ifdef HAVE_LUA
|
||||
#include "lua-engine.h"
|
||||
#endif
|
||||
#ifdef TARGET_INTERFACE
|
||||
#include "frontend/interface/interface.h"
|
||||
#endif
|
||||
#ifdef HAVE_JIT
|
||||
#include "arm_jit.h"
|
||||
#endif
|
||||
|
||||
template<u32> static u32 armcpu_prefetch();
|
||||
|
||||
FORCEINLINE u32 armcpu_prefetch(armcpu_t *armcpu) {
|
||||
if(armcpu->proc_ID==0) return armcpu_prefetch<0>();
|
||||
else return armcpu_prefetch<1>();
|
||||
}
|
||||
|
||||
armcpu_t NDS_ARM7;
|
||||
armcpu_t NDS_ARM9;
|
||||
|
||||
#define SWAP(a, b, c) do \
|
||||
{ \
|
||||
c=a; \
|
||||
a=b; \
|
||||
b=c; \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
#define STALLED_CYCLE_COUNT 10
|
||||
|
||||
static void
|
||||
stall_cpu( void *instance) {
|
||||
armcpu_t *armcpu = (armcpu_t *)instance;
|
||||
printf("STALL\n");
|
||||
armcpu->stalled = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
unstall_cpu( void *instance) {
|
||||
armcpu_t *armcpu = (armcpu_t *)instance;
|
||||
printf("UNSTALL\n");
|
||||
armcpu->stalled = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
install_post_exec_fn( void *instance,
|
||||
void (*ex_fn)( void *, u32 adr, int thumb),
|
||||
void *fn_data) {
|
||||
armcpu_t *armcpu = (armcpu_t *)instance;
|
||||
|
||||
armcpu->post_ex_fn = ex_fn;
|
||||
armcpu->post_ex_fn_data = fn_data;
|
||||
}
|
||||
|
||||
static void
|
||||
remove_post_exec_fn( void *instance) {
|
||||
armcpu_t *armcpu = (armcpu_t *)instance;
|
||||
|
||||
armcpu->post_ex_fn = NULL;
|
||||
}
|
||||
|
||||
static u32 read_cpu_reg( void *instance, u32 reg_num)
|
||||
{
|
||||
armcpu_t *armcpu = (armcpu_t *)instance;
|
||||
|
||||
if ( reg_num <= 14) {
|
||||
return armcpu->R[reg_num];
|
||||
}
|
||||
else if ( reg_num == 15) {
|
||||
return armcpu->instruct_adr;
|
||||
}
|
||||
else if ( reg_num == 16) {
|
||||
//CPSR
|
||||
return armcpu->CPSR.val;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
set_cpu_reg( void *instance, u32 reg_num, u32 value) {
|
||||
armcpu_t *armcpu = (armcpu_t *)instance;
|
||||
|
||||
if ( reg_num <= 14) {
|
||||
armcpu->R[reg_num] = value;
|
||||
}
|
||||
else if ( reg_num == 15) {
|
||||
armcpu->next_instruction = value;
|
||||
}
|
||||
else if ( reg_num == 16) {
|
||||
/* FIXME: setting the CPSR */
|
||||
}
|
||||
}
|
||||
|
||||
int armcpu_new( armcpu_t *armcpu, u32 id)
|
||||
{
|
||||
armcpu->proc_ID = id;
|
||||
armcpu->stalled = 0;
|
||||
|
||||
armcpu->base_mem_if.prefetch32 = NULL;
|
||||
armcpu->base_mem_if.prefetch16 = NULL;
|
||||
armcpu->base_mem_if.read8 = NULL;
|
||||
armcpu->base_mem_if.read16 = NULL;
|
||||
armcpu->base_mem_if.read32 = NULL;
|
||||
armcpu->base_mem_if.write8 = NULL;
|
||||
armcpu->base_mem_if.write16 = NULL;
|
||||
armcpu->base_mem_if.write32 = NULL;
|
||||
armcpu->base_mem_if.data = NULL;
|
||||
|
||||
armcpu_SetControlInterface(armcpu, &arm_default_ctrl_iface);
|
||||
armcpu_SetControlInterfaceData(armcpu, armcpu);
|
||||
armcpu_SetCurrentMemoryInterface(armcpu, NULL);
|
||||
armcpu_SetCurrentMemoryInterfaceData(armcpu, NULL);
|
||||
|
||||
armcpu->post_ex_fn = NULL;
|
||||
armcpu->post_ex_fn_data = NULL;
|
||||
|
||||
armcpu->breakPoints = new std::vector<u32>;
|
||||
|
||||
armcpu_init(armcpu, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void armcpu_SetControlInterface(armcpu_t *armcpu, const armcpu_ctrl_iface *theControlInterface)
|
||||
{
|
||||
armcpu->ctrl_iface = *theControlInterface;
|
||||
}
|
||||
|
||||
armcpu_ctrl_iface* armcpu_GetControlInterface(armcpu_t *armcpu)
|
||||
{
|
||||
return &armcpu->ctrl_iface;
|
||||
}
|
||||
|
||||
void armcpu_SetControlInterfaceData(armcpu_t *armcpu, void *theData)
|
||||
{
|
||||
armcpu->ctrl_iface.data = theData;
|
||||
}
|
||||
|
||||
void* armcpu_GetControlInterfaceData(const armcpu_t *armcpu)
|
||||
{
|
||||
return armcpu->ctrl_iface.data;
|
||||
}
|
||||
|
||||
void armcpu_SetCurrentMemoryInterface(armcpu_t *armcpu, armcpu_memory_iface *theMemoryInterface)
|
||||
{
|
||||
armcpu->mem_if = theMemoryInterface;
|
||||
}
|
||||
|
||||
armcpu_memory_iface* armcpu_GetCurrentMemoryInterface(const armcpu_t *armcpu)
|
||||
{
|
||||
return armcpu->mem_if;
|
||||
}
|
||||
|
||||
void armcpu_SetCurrentMemoryInterfaceData(armcpu_t *armcpu, void *theData)
|
||||
{
|
||||
if (armcpu->mem_if != NULL)
|
||||
{
|
||||
armcpu->mem_if->data = theData;
|
||||
}
|
||||
}
|
||||
|
||||
void* armcpu_GetCurrentMemoryInterfaceData(const armcpu_t *armcpu)
|
||||
{
|
||||
return (armcpu->mem_if != NULL) ? armcpu->mem_if->data : NULL;
|
||||
}
|
||||
|
||||
void armcpu_SetBaseMemoryInterface(armcpu_t *armcpu, const armcpu_memory_iface *theMemInterface)
|
||||
{
|
||||
armcpu->base_mem_if = *theMemInterface;
|
||||
}
|
||||
|
||||
armcpu_memory_iface* armcpu_GetBaseMemoryInterface(armcpu_t *armcpu)
|
||||
{
|
||||
return &armcpu->base_mem_if;
|
||||
}
|
||||
|
||||
void armcpu_SetBaseMemoryInterfaceData(armcpu_t *armcpu, void *theData)
|
||||
{
|
||||
armcpu->base_mem_if.data = theData;
|
||||
}
|
||||
|
||||
void* armcpu_GetBaseMemoryInterfaceData(const armcpu_t *armcpu)
|
||||
{
|
||||
return armcpu->base_mem_if.data;
|
||||
}
|
||||
|
||||
void armcpu_ResetMemoryInterfaceToBase(armcpu_t *armcpu)
|
||||
{
|
||||
armcpu_SetCurrentMemoryInterface(armcpu, armcpu_GetBaseMemoryInterface(armcpu));
|
||||
armcpu_SetCurrentMemoryInterfaceData(armcpu, armcpu_GetBaseMemoryInterfaceData(armcpu));
|
||||
}
|
||||
|
||||
//call this whenever CPSR is changed (other than CNVZQ or T flags); interrupts may need to be unleashed
|
||||
void armcpu_changeCPSR()
|
||||
{
|
||||
//but all it does is give them a chance to unleash by forcing an immediate reschedule
|
||||
//TODO - we could actually set CPSR through here and look for a change in the I bit
|
||||
//that would be a little optimization as well as a safety measure if we prevented setting CPSR directly
|
||||
NDS_Reschedule();
|
||||
}
|
||||
|
||||
void armcpu_init(armcpu_t *armcpu, u32 adr)
|
||||
{
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
memcpy(&armcpu->cond_table[0], &arm_cond_table[0], sizeof(arm_cond_table));
|
||||
#endif
|
||||
|
||||
armcpu->LDTBit = (armcpu->proc_ID==0); //set ARMv5 style bit--different for each processor
|
||||
armcpu->intVector = 0xFFFF0000 * (armcpu->proc_ID==0);
|
||||
armcpu->freeze = CPU_FREEZE_NONE;
|
||||
armcpu->intrWaitARM_state = 0;
|
||||
|
||||
//#ifdef GDB_STUB
|
||||
// armcpu->irq_flag = 0;
|
||||
//#endif
|
||||
|
||||
for(int i = 0; i < 16; ++i)
|
||||
armcpu->R[i] = 0;
|
||||
|
||||
armcpu->CPSR.val = armcpu->SPSR.val = SYS;
|
||||
|
||||
armcpu->R13_usr = armcpu->R14_usr = 0;
|
||||
armcpu->R13_svc = armcpu->R14_svc = 0;
|
||||
armcpu->R13_abt = armcpu->R14_abt = 0;
|
||||
armcpu->R13_und = armcpu->R14_und = 0;
|
||||
armcpu->R13_irq = armcpu->R14_irq = 0;
|
||||
armcpu->R8_fiq = armcpu->R9_fiq = armcpu->R10_fiq = armcpu->R11_fiq = armcpu->R12_fiq = armcpu->R13_fiq = armcpu->R14_fiq = 0;
|
||||
|
||||
armcpu->SPSR_svc.val = armcpu->SPSR_abt.val = armcpu->SPSR_und.val = armcpu->SPSR_irq.val = armcpu->SPSR_fiq.val = 0;
|
||||
|
||||
//#ifdef GDB_STUB
|
||||
// armcpu->instruct_adr = adr;
|
||||
// armcpu->R[15] = adr + 8;
|
||||
//#else
|
||||
//armcpu->R[15] = adr;
|
||||
//#endif
|
||||
|
||||
//do something sensible when booting up to a thumb address
|
||||
armcpu->next_instruction = adr & ~1;
|
||||
armcpu->CPSR.bits.T = BIT0(adr);
|
||||
|
||||
//#ifndef GDB_STUB
|
||||
armcpu_prefetch(armcpu);
|
||||
//#endif
|
||||
}
|
||||
|
||||
u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode)
|
||||
{
|
||||
u32 oldmode = armcpu->CPSR.bits.mode;
|
||||
|
||||
switch(oldmode)
|
||||
{
|
||||
case USR :
|
||||
case SYS :
|
||||
armcpu->R13_usr = armcpu->R[13];
|
||||
armcpu->R14_usr = armcpu->R[14];
|
||||
break;
|
||||
|
||||
case FIQ :
|
||||
{
|
||||
u32 tmp;
|
||||
SWAP(armcpu->R[8], armcpu->R8_fiq, tmp);
|
||||
SWAP(armcpu->R[9], armcpu->R9_fiq, tmp);
|
||||
SWAP(armcpu->R[10], armcpu->R10_fiq, tmp);
|
||||
SWAP(armcpu->R[11], armcpu->R11_fiq, tmp);
|
||||
SWAP(armcpu->R[12], armcpu->R12_fiq, tmp);
|
||||
armcpu->R13_fiq = armcpu->R[13];
|
||||
armcpu->R14_fiq = armcpu->R[14];
|
||||
armcpu->SPSR_fiq = armcpu->SPSR;
|
||||
break;
|
||||
}
|
||||
case IRQ :
|
||||
armcpu->R13_irq = armcpu->R[13];
|
||||
armcpu->R14_irq = armcpu->R[14];
|
||||
armcpu->SPSR_irq = armcpu->SPSR;
|
||||
break;
|
||||
|
||||
case SVC :
|
||||
armcpu->R13_svc = armcpu->R[13];
|
||||
armcpu->R14_svc = armcpu->R[14];
|
||||
armcpu->SPSR_svc = armcpu->SPSR;
|
||||
break;
|
||||
|
||||
case ABT :
|
||||
armcpu->R13_abt = armcpu->R[13];
|
||||
armcpu->R14_abt = armcpu->R[14];
|
||||
armcpu->SPSR_abt = armcpu->SPSR;
|
||||
break;
|
||||
|
||||
case UND :
|
||||
armcpu->R13_und = armcpu->R[13];
|
||||
armcpu->R14_und = armcpu->R[14];
|
||||
armcpu->SPSR_und = armcpu->SPSR;
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case USR :
|
||||
case SYS :
|
||||
armcpu->R[13] = armcpu->R13_usr;
|
||||
armcpu->R[14] = armcpu->R14_usr;
|
||||
//SPSR = CPSR;
|
||||
break;
|
||||
|
||||
case FIQ :
|
||||
{
|
||||
u32 tmp;
|
||||
SWAP(armcpu->R[8], armcpu->R8_fiq, tmp);
|
||||
SWAP(armcpu->R[9], armcpu->R9_fiq, tmp);
|
||||
SWAP(armcpu->R[10], armcpu->R10_fiq, tmp);
|
||||
SWAP(armcpu->R[11], armcpu->R11_fiq, tmp);
|
||||
SWAP(armcpu->R[12], armcpu->R12_fiq, tmp);
|
||||
armcpu->R[13] = armcpu->R13_fiq;
|
||||
armcpu->R[14] = armcpu->R14_fiq;
|
||||
armcpu->SPSR = armcpu->SPSR_fiq;
|
||||
break;
|
||||
}
|
||||
|
||||
case IRQ :
|
||||
armcpu->R[13] = armcpu->R13_irq;
|
||||
armcpu->R[14] = armcpu->R14_irq;
|
||||
armcpu->SPSR = armcpu->SPSR_irq;
|
||||
break;
|
||||
|
||||
case SVC :
|
||||
armcpu->R[13] = armcpu->R13_svc;
|
||||
armcpu->R[14] = armcpu->R14_svc;
|
||||
armcpu->SPSR = armcpu->SPSR_svc;
|
||||
break;
|
||||
|
||||
case ABT :
|
||||
armcpu->R[13] = armcpu->R13_abt;
|
||||
armcpu->R[14] = armcpu->R14_abt;
|
||||
armcpu->SPSR = armcpu->SPSR_abt;
|
||||
break;
|
||||
|
||||
case UND :
|
||||
armcpu->R[13] = armcpu->R13_und;
|
||||
armcpu->R[14] = armcpu->R14_und;
|
||||
armcpu->SPSR = armcpu->SPSR_und;
|
||||
break;
|
||||
|
||||
default :
|
||||
printf("switchMode: WRONG mode %02X\n",mode);
|
||||
break;
|
||||
}
|
||||
|
||||
armcpu->CPSR.bits.mode = mode & 0x1F;
|
||||
armcpu_changeCPSR();
|
||||
return oldmode;
|
||||
}
|
||||
|
||||
u32 armcpu_Wait4IRQ(armcpu_t *cpu)
|
||||
{
|
||||
cpu->freeze = (CPU_FREEZE_WAIT_IRQ | CPU_FREEZE_IE_IF);
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<u32 PROCNUM>
|
||||
FORCEINLINE static u32 armcpu_prefetch()
|
||||
{
|
||||
armcpu_t* const armcpu = &ARMPROC;
|
||||
//#ifdef GDB_STUB
|
||||
// u32 temp_instruction;
|
||||
//#endif
|
||||
u32 curInstruction = armcpu->next_instruction;
|
||||
|
||||
if(armcpu->CPSR.bits.T == 0)
|
||||
{
|
||||
//#ifdef GDB_STUB
|
||||
// temp_instruction =
|
||||
// armcpu->mem_if->prefetch32( armcpu->mem_if->data,
|
||||
// armcpu->next_instruction);
|
||||
//
|
||||
// if ( !armcpu->stalled) {
|
||||
// armcpu->instruction = temp_instruction;
|
||||
// armcpu->instruct_adr = armcpu->next_instruction;
|
||||
// armcpu->next_instruction += 4;
|
||||
// armcpu->R[15] = armcpu->next_instruction + 4;
|
||||
// }
|
||||
//#else
|
||||
curInstruction &= 0xFFFFFFFC; //please don't change this to 0x0FFFFFFC -- the NDS will happily run on 0xF******* addresses all day long
|
||||
//please note that we must setup R[15] before reading the instruction since there is a protection
|
||||
//which prevents PC > 0x3FFF from reading the bios region
|
||||
armcpu->instruct_adr = curInstruction;
|
||||
armcpu->next_instruction = curInstruction + 4;
|
||||
armcpu->R[15] = curInstruction + 8;
|
||||
armcpu->instruction = _MMU_read32<PROCNUM, MMU_AT_CODE>(curInstruction);
|
||||
//#endif
|
||||
|
||||
return MMU_codeFetchCycles<PROCNUM,32>(curInstruction);
|
||||
}
|
||||
|
||||
//#ifdef GDB_STUB
|
||||
// temp_instruction =
|
||||
// armcpu->mem_if->prefetch16( armcpu->mem_if->data,
|
||||
// armcpu->next_instruction);
|
||||
//
|
||||
// if ( !armcpu->stalled) {
|
||||
// armcpu->instruction = temp_instruction;
|
||||
// armcpu->instruct_adr = armcpu->next_instruction;
|
||||
// armcpu->next_instruction = armcpu->next_instruction + 2;
|
||||
// armcpu->R[15] = armcpu->next_instruction + 2;
|
||||
// }
|
||||
//#else
|
||||
curInstruction &= 0xFFFFFFFE; //please don't change this to 0x0FFFFFFE -- the NDS will happily run on 0xF******* addresses all day long
|
||||
//please note that we must setup R[15] before reading the instruction since there is a protection
|
||||
//which prevents PC > 0x3FFF from reading the bios region
|
||||
armcpu->instruct_adr = curInstruction;
|
||||
armcpu->next_instruction = curInstruction + 2;
|
||||
armcpu->R[15] = curInstruction + 4;
|
||||
armcpu->instruction = _MMU_read16<PROCNUM, MMU_AT_CODE>(curInstruction);
|
||||
//#endif
|
||||
|
||||
if(PROCNUM==0)
|
||||
{
|
||||
// arm9 fetches 2 instructions at a time in thumb mode
|
||||
if(!(curInstruction == armcpu->instruct_adr + 2 && (curInstruction & 2)))
|
||||
return MMU_codeFetchCycles<PROCNUM,32>(curInstruction);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
return MMU_codeFetchCycles<PROCNUM,16>(curInstruction);
|
||||
}
|
||||
|
||||
#if 0 /* not used */
|
||||
static BOOL FASTCALL test_EQ(Status_Reg CPSR) { return ( CPSR.bits.Z); }
|
||||
static BOOL FASTCALL test_NE(Status_Reg CPSR) { return (!CPSR.bits.Z); }
|
||||
static BOOL FASTCALL test_CS(Status_Reg CPSR) { return ( CPSR.bits.C); }
|
||||
static BOOL FASTCALL test_CC(Status_Reg CPSR) { return (!CPSR.bits.C); }
|
||||
static BOOL FASTCALL test_MI(Status_Reg CPSR) { return ( CPSR.bits.N); }
|
||||
static BOOL FASTCALL test_PL(Status_Reg CPSR) { return (!CPSR.bits.N); }
|
||||
static BOOL FASTCALL test_VS(Status_Reg CPSR) { return ( CPSR.bits.V); }
|
||||
static BOOL FASTCALL test_VC(Status_Reg CPSR) { return (!CPSR.bits.V); }
|
||||
static BOOL FASTCALL test_HI(Status_Reg CPSR) { return (CPSR.bits.C) && (!CPSR.bits.Z); }
|
||||
static BOOL FASTCALL test_LS(Status_Reg CPSR) { return (CPSR.bits.Z) || (!CPSR.bits.C); }
|
||||
static BOOL FASTCALL test_GE(Status_Reg CPSR) { return (CPSR.bits.N==CPSR.bits.V); }
|
||||
static BOOL FASTCALL test_LT(Status_Reg CPSR) { return (CPSR.bits.N!=CPSR.bits.V); }
|
||||
static BOOL FASTCALL test_GT(Status_Reg CPSR) { return (!CPSR.bits.Z) && (CPSR.bits.N==CPSR.bits.V); }
|
||||
static BOOL FASTCALL test_LE(Status_Reg CPSR) { return ( CPSR.bits.Z) || (CPSR.bits.N!=CPSR.bits.V); }
|
||||
static BOOL FASTCALL test_AL(Status_Reg CPSR) { return 1; }
|
||||
|
||||
static BOOL (FASTCALL* test_conditions[])(Status_Reg CPSR)= {
|
||||
test_EQ , test_NE ,
|
||||
test_CS , test_CC ,
|
||||
test_MI , test_PL ,
|
||||
test_VS , test_VC ,
|
||||
test_HI , test_LS ,
|
||||
test_GE , test_LT ,
|
||||
test_GT , test_LE ,
|
||||
test_AL
|
||||
};
|
||||
#define TEST_COND2(cond, CPSR) \
|
||||
(cond<15&&test_conditions[cond](CPSR))
|
||||
#endif
|
||||
|
||||
//TODO - merge with armcpu_irqException?
|
||||
//http://www.ethernut.de/en/documents/arm-exceptions.html
|
||||
//http://docs.google.com/viewer?a=v&q=cache:V4ht1YkxprMJ:www.cs.nctu.edu.tw/~wjtsai/EmbeddedSystemDesign/Ch3-1.pdf+arm+exception+handling&hl=en&gl=us&pid=bl&srcid=ADGEEShx9VTHbUhWdDOrTVRzLkcCsVfJiijncNDkkgkrlJkLa7D0LCpO8fQ_hhU3DTcgZh9rcZWWQq4TYhhCovJ625h41M0ZUX3WGasyzWQFxYzDCB-VS6bsUmpoJnRxAc-bdkD0qmsu&sig=AHIEtbR9VHvDOCRmZFQDUVwy53iJDjoSPQ
|
||||
void armcpu_exception(armcpu_t *cpu, u32 number)
|
||||
{
|
||||
Mode cpumode = USR;
|
||||
switch(number)
|
||||
{
|
||||
case EXCEPTION_RESET: cpumode = SVC; break;
|
||||
case EXCEPTION_UNDEFINED_INSTRUCTION: cpumode = UND; break;
|
||||
case EXCEPTION_SWI: cpumode = SVC; break;
|
||||
case EXCEPTION_PREFETCH_ABORT: cpumode = ABT; break;
|
||||
case EXCEPTION_DATA_ABORT: cpumode = ABT; break;
|
||||
case EXCEPTION_RESERVED_0x14: emu_halt(EMUHALT_REASON_ARM_RESERVED_0X14_EXCEPTION, (cpu->proc_ID == ARMCPU_ARM9) ? NDSErrorTag_ARM9 : NDSErrorTag_ARM7); break;
|
||||
case EXCEPTION_IRQ: cpumode = IRQ; break;
|
||||
case EXCEPTION_FAST_IRQ: cpumode = FIQ; break;
|
||||
}
|
||||
|
||||
Status_Reg tmp = cpu->CPSR;
|
||||
armcpu_switchMode(cpu, cpumode); //enter new mode
|
||||
cpu->R[14] = cpu->next_instruction;
|
||||
cpu->SPSR = tmp; //save old CPSR as new SPSR
|
||||
cpu->CPSR.bits.T = 0; //handle as ARM32 code
|
||||
cpu->CPSR.bits.I = 1;
|
||||
armcpu_changeCPSR();
|
||||
cpu->R[15] = cpu->intVector + number;
|
||||
cpu->next_instruction = cpu->R[15];
|
||||
printf("armcpu_exception!\n");
|
||||
//extern bool dolog;
|
||||
//dolog=true;
|
||||
|
||||
//HOW DOES THIS WORTK WITHOUT A PREFETCH, LIKE IRQ BELOW?
|
||||
//I REALLY WISH WE DIDNT PREFETCH BEFORE EXECUTING
|
||||
}
|
||||
|
||||
BOOL armcpu_irqException(armcpu_t *armcpu)
|
||||
{
|
||||
Status_Reg tmp;
|
||||
|
||||
//TODO - remove GDB specific code
|
||||
//#ifdef GDB_STUB
|
||||
// armcpu->irq_flag = 0;
|
||||
//#endif
|
||||
|
||||
tmp = armcpu->CPSR;
|
||||
armcpu_switchMode(armcpu, IRQ);
|
||||
|
||||
//TODO - remove GDB specific code
|
||||
//#ifdef GDB_STUB
|
||||
// armcpu->R[14] = armcpu->next_instruction + 4;
|
||||
//#else
|
||||
armcpu->R[14] = armcpu->instruct_adr + 4;
|
||||
//#endif
|
||||
armcpu->SPSR = tmp;
|
||||
armcpu->CPSR.bits.T = 0;
|
||||
armcpu->CPSR.bits.I = 1;
|
||||
armcpu->next_instruction = armcpu->intVector + 0x18;
|
||||
armcpu->freeze &= ~CPU_FREEZE_IRQ_IE_IF;
|
||||
|
||||
//must retain invariant of having next instruction to be executed prefetched
|
||||
//(yucky)
|
||||
armcpu_prefetch(armcpu);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//TODO - remove GDB specific code
|
||||
//BOOL
|
||||
//armcpu_flagIrq( armcpu_t *armcpu) {
|
||||
// if(armcpu->CPSR.bits.I) return FALSE;
|
||||
//
|
||||
// armcpu->waitIRQ = 0;
|
||||
//
|
||||
//#ifdef GDB_STUB
|
||||
// armcpu->irq_flag = 1;
|
||||
//#endif
|
||||
//
|
||||
// return TRUE;
|
||||
//}
|
||||
|
||||
u32 TRAPUNDEF(armcpu_t* cpu)
|
||||
{
|
||||
INFO("ARM%c: Undefined instruction: 0x%08X PC=0x%08X\n", cpu->proc_ID?'7':'9', cpu->instruction, cpu->instruct_adr);
|
||||
|
||||
if (((cpu->intVector != 0) ^ (cpu->proc_ID == ARMCPU_ARM9)))
|
||||
{
|
||||
armcpu_exception(&NDS_ARM9,EXCEPTION_UNDEFINED_INSTRUCTION);
|
||||
return 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
emu_halt(EMUHALT_REASON_ARM_UNDEFINED_INSTRUCTION_EXCEPTION, (cpu->proc_ID == ARMCPU_ARM9) ? NDSErrorTag_ARM9 : NDSErrorTag_ARM7);
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
//BOOL
|
||||
//armcpu_flagIrq( armcpu_t *armcpu) {
|
||||
// if(armcpu->CPSR.bits.I) return FALSE;
|
||||
//
|
||||
// armcpu->waitIRQ = 0;
|
||||
//
|
||||
//#ifdef GDB_STUB
|
||||
// armcpu->irq_flag = 1;
|
||||
//#endif
|
||||
//
|
||||
// return TRUE;
|
||||
//}
|
||||
|
||||
template<int PROCNUM>
|
||||
u32 armcpu_exec()
|
||||
{
|
||||
// Usually, fetching and executing are processed parallelly.
|
||||
// So this function stores the cycles of each process to
|
||||
// the variables below, and returns appropriate cycle count.
|
||||
u32 cFetch = 0;
|
||||
u32 cExecute = 0;
|
||||
|
||||
//this assert is annoying. but sometimes it is handy.
|
||||
//assert(ARMPROC.instruct_adr!=0x00000000);
|
||||
//#ifdef DEVELOPER
|
||||
#if 0
|
||||
if ((((ARMPROC.instruct_adr & 0x0F000000) == 0x0F000000) && (PROCNUM == 0)) ||
|
||||
(((ARMPROC.instruct_adr & 0x0F000000) == 0x00000000) && (PROCNUM == 1)))
|
||||
{
|
||||
switch (ARMPROC.instruct_adr & 0xFFFF)
|
||||
{
|
||||
case 0x00000000:
|
||||
printf("BIOS%c: Reset!!!\n", PROCNUM?'7':'9');
|
||||
emu_halt();
|
||||
break;
|
||||
case 0x00000004:
|
||||
printf("BIOS%c: Undefined instruction\n", PROCNUM?'7':'9');
|
||||
//emu_halt();
|
||||
break;
|
||||
case 0x00000008:
|
||||
//printf("BIOS%c: SWI\n", PROCNUM?'7':'9');
|
||||
break;
|
||||
case 0x0000000C:
|
||||
printf("BIOS%c: Prefetch Abort!!!\n", PROCNUM?'7':'9');
|
||||
//emu_halt();
|
||||
break;
|
||||
case 0x00000010:
|
||||
//printf("BIOS%c: Data Abort!!!\n", PROCNUM?'7':'9');
|
||||
//emu_halt();
|
||||
break;
|
||||
case 0x00000014:
|
||||
printf("BIOS%c: Reserved!!!\n", PROCNUM?'7':'9');
|
||||
break;
|
||||
case 0x00000018:
|
||||
//printf("BIOS%c: IRQ\n", PROCNUM?'7':'9');
|
||||
break;
|
||||
case 0x0000001C:
|
||||
printf("BIOS%c: Fast IRQ\n", PROCNUM?'7':'9');
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0 //#ifdef GDB_STUB
|
||||
if (ARMPROC.stalled) {
|
||||
return STALLED_CYCLE_COUNT;
|
||||
}
|
||||
|
||||
/* check for interrupts */
|
||||
if (ARMPROC.irq_flag) {
|
||||
armcpu_irqException(&ARMPROC);
|
||||
}
|
||||
|
||||
cFetch = armcpu_prefetch(&ARMPROC);
|
||||
|
||||
if (ARMPROC.stalled) {
|
||||
return MMU_fetchExecuteCycles<PROCNUM>(cExecute, cFetch);
|
||||
}
|
||||
#endif
|
||||
|
||||
//cFetch = armcpu_prefetch(&ARMPROC);
|
||||
|
||||
//printf("%d: %08X\n",PROCNUM,ARMPROC.instruct_adr);
|
||||
|
||||
if(ARMPROC.CPSR.bits.T == 0)
|
||||
{
|
||||
if(
|
||||
CONDITION(ARMPROC.instruction) == 0x0E //fast path for unconditional instructions
|
||||
|| (TEST_COND(CONDITION(ARMPROC.instruction), CODE(ARMPROC.instruction), ARMPROC.CPSR)) //handles any condition
|
||||
)
|
||||
{
|
||||
#ifdef HAVE_LUA
|
||||
CallRegisteredLuaMemHook(ARMPROC.instruct_adr, 4, ARMPROC.instruction, LUAMEMHOOK_EXEC); // should report even if condition=false?
|
||||
#endif
|
||||
#ifdef TARGET_INTERFACE
|
||||
call_registered_interface_mem_hook(ARMPROC.instruct_adr, 4, HOOK_EXEC);
|
||||
#endif
|
||||
#ifdef DEVELOPER
|
||||
DEBUG_statistics.instructionHits[PROCNUM].arm[INSTRUCTION_INDEX(ARMPROC.instruction)]++;
|
||||
#endif
|
||||
cExecute = arm_instructions_set[PROCNUM][INSTRUCTION_INDEX(ARMPROC.instruction)](ARMPROC.instruction);
|
||||
}
|
||||
else
|
||||
cExecute = 1; // If condition=false: 1S cycle
|
||||
#ifdef GDB_STUB
|
||||
if ( ARMPROC.post_ex_fn != NULL) {
|
||||
/* call the external post execute function */
|
||||
ARMPROC.post_ex_fn(ARMPROC.post_ex_fn_data, ARMPROC.instruct_adr, 0);
|
||||
}
|
||||
ARMPROC.mem_if->prefetch32( ARMPROC.mem_if->data, ARMPROC.next_instruction);
|
||||
#endif
|
||||
cFetch = armcpu_prefetch<PROCNUM>();
|
||||
return MMU_fetchExecuteCycles<PROCNUM>(cExecute, cFetch);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LUA
|
||||
CallRegisteredLuaMemHook(ARMPROC.instruct_adr, 2, ARMPROC.instruction, LUAMEMHOOK_EXEC);
|
||||
#endif
|
||||
#ifdef TARGET_INTERFACE
|
||||
call_registered_interface_mem_hook(ARMPROC.instruct_adr, 2, HOOK_EXEC);
|
||||
#endif
|
||||
#ifdef DEVELOPER
|
||||
DEBUG_statistics.instructionHits[PROCNUM].thumb[ARMPROC.instruction>>6]++;
|
||||
#endif
|
||||
cExecute = thumb_instructions_set[PROCNUM][ARMPROC.instruction>>6](ARMPROC.instruction);
|
||||
|
||||
#ifdef GDB_STUB
|
||||
if ( ARMPROC.post_ex_fn != NULL) {
|
||||
/* call the external post execute function */
|
||||
ARMPROC.post_ex_fn( ARMPROC.post_ex_fn_data, ARMPROC.instruct_adr, 1);
|
||||
}
|
||||
ARMPROC.mem_if->prefetch32( ARMPROC.mem_if->data, ARMPROC.next_instruction);
|
||||
#endif
|
||||
cFetch = armcpu_prefetch<PROCNUM>();
|
||||
return MMU_fetchExecuteCycles<PROCNUM>(cExecute, cFetch);
|
||||
}
|
||||
|
||||
//these templates needed to be instantiated manually
|
||||
template u32 armcpu_exec<0>();
|
||||
template u32 armcpu_exec<1>();
|
||||
|
||||
#ifdef HAVE_JIT
|
||||
void arm_jit_sync()
|
||||
{
|
||||
NDS_ARM7.next_instruction = NDS_ARM7.instruct_adr;
|
||||
NDS_ARM9.next_instruction = NDS_ARM9.instruct_adr;
|
||||
armcpu_prefetch<0>();
|
||||
armcpu_prefetch<1>();
|
||||
}
|
||||
|
||||
template<int PROCNUM, bool jit>
|
||||
u32 armcpu_exec()
|
||||
{
|
||||
if (jit)
|
||||
{
|
||||
ARMPROC.instruct_adr &= ARMPROC.CPSR.bits.T?0xFFFFFFFE:0xFFFFFFFC;
|
||||
ArmOpCompiled f = (ArmOpCompiled)JIT_COMPILED_FUNC(ARMPROC.instruct_adr, PROCNUM);
|
||||
return f ? f() : arm_jit_compile<PROCNUM>();
|
||||
}
|
||||
|
||||
return armcpu_exec<PROCNUM>();
|
||||
}
|
||||
|
||||
template u32 armcpu_exec<0,false>();
|
||||
template u32 armcpu_exec<0,true>();
|
||||
template u32 armcpu_exec<1,false>();
|
||||
template u32 armcpu_exec<1,true>();
|
||||
#endif
|
||||
|
||||
void setIF(int PROCNUM, u32 flag)
|
||||
{
|
||||
//don't set generated bits!!!
|
||||
assert(!(flag&0x00200000));
|
||||
|
||||
MMU.reg_IF_bits[PROCNUM] |= flag;
|
||||
|
||||
NDS_Reschedule();
|
||||
}
|
||||
|
||||
const armcpu_ctrl_iface arm_default_ctrl_iface = {
|
||||
stall_cpu,
|
||||
unstall_cpu,
|
||||
read_cpu_reg,
|
||||
set_cpu_reg,
|
||||
install_post_exec_fn,
|
||||
remove_post_exec_fn,
|
||||
NULL
|
||||
};
|
|
@ -0,0 +1,366 @@
|
|||
/*
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2006-2021 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DESMUME_ARMCPU_H
|
||||
#define DESMUME_ARMCPU_H
|
||||
|
||||
//half of this stuff is arm cpu internals
|
||||
//half is public API
|
||||
//really a mess
|
||||
|
||||
#include "types.h"
|
||||
#include "MMU.h"
|
||||
|
||||
#define CONDITION(i) ((i)>>28)
|
||||
#define REG_POS(i,n) (((i)>>n)&0xF)
|
||||
#define CODE(i) (((i)>>25)&0x7)
|
||||
#define OPCODE(i) (((i)>>21)&0xF)
|
||||
#define SIGNEBIT(i) (((i)>>20)&1)
|
||||
|
||||
#define EXCEPTION_RESET 0x00
|
||||
#define EXCEPTION_UNDEFINED_INSTRUCTION 0x04
|
||||
#define EXCEPTION_SWI 0x08
|
||||
#define EXCEPTION_PREFETCH_ABORT 0x0C
|
||||
#define EXCEPTION_DATA_ABORT 0x10
|
||||
#define EXCEPTION_RESERVED_0x14 0x14
|
||||
#define EXCEPTION_IRQ 0x18
|
||||
#define EXCEPTION_FAST_IRQ 0x1C
|
||||
|
||||
|
||||
#define CPU_FREEZE_NONE 0x00
|
||||
#define CPU_FREEZE_WAIT_IRQ 0x01 //waiting for some IRQ to happen, any IRQ
|
||||
#define CPU_FREEZE_IE_IF 0x02 //waiting for IE&IF to signal something (probably edge triggered on IRQ too)
|
||||
#define CPU_FREEZE_IRQ_IE_IF (CPU_FREEZE_WAIT_IRQ|CPU_FREEZE_IE_IF)
|
||||
#define CPU_FREEZE_OVERCLOCK_HACK 0x04
|
||||
|
||||
#define INSTRUCTION_INDEX(i) ((((i)>>16)&0xFF0)|(((i)>>4)&0xF))
|
||||
|
||||
inline u32 ROR(u32 i, u32 j) { return ((((u32)(i))>>(j)) | (((u32)(i))<<(32-(j)))); }
|
||||
|
||||
template<typename T>
|
||||
inline T UNSIGNED_OVERFLOW(T a,T b,T c) { return BIT31(((a)&(b)) | (((a)|(b))&(~c))); }
|
||||
|
||||
template<typename T>
|
||||
inline T UNSIGNED_UNDERFLOW(T a,T b,T c) { return BIT31(((~a)&(b)) | (((~a)|(b))&(c))); }
|
||||
|
||||
template<typename T>
|
||||
inline T SIGNED_OVERFLOW(T a,T b,T c) { return BIT31(((a)&(b)&(~c)) | ((~a)&(~(b))&(c))); }
|
||||
|
||||
template<typename T>
|
||||
inline T SIGNED_UNDERFLOW(T a,T b,T c) { return BIT31(((a)&(~(b))&(~c)) | ((~a)&(b)&(c))); }
|
||||
|
||||
#if !defined(bswap32)
|
||||
#define bswap32(val) \
|
||||
( (val << 24) & 0xFF000000) | \
|
||||
( (val << 8) & 0x00FF0000) | \
|
||||
( (val >> 8) & 0x0000FF00) | \
|
||||
( (val >> 24) & 0x000000FF)
|
||||
#endif
|
||||
|
||||
#if !defined(bswap64)
|
||||
#define bswap64(x) \
|
||||
( (x << 56) & 0xff00000000000000ULL ) | \
|
||||
( (x << 40) & 0x00ff000000000000ULL ) | \
|
||||
( (x << 24) & 0x0000ff0000000000ULL ) | \
|
||||
( (x << 8) & 0x000000ff00000000ULL ) | \
|
||||
( (x >> 8) & 0x00000000ff000000ULL ) | \
|
||||
( (x >> 24) & 0x0000000000ff0000ULL ) | \
|
||||
( (x >> 40) & 0x000000000000ff00ULL ) | \
|
||||
( (x >> 56) & 0x00000000000000ffULL )
|
||||
#endif
|
||||
|
||||
// ============================= CPRS flags funcs
|
||||
inline bool CarryFrom(s32 left, s32 right)
|
||||
{
|
||||
u32 res = (0xFFFFFFFFU - (u32)left);
|
||||
|
||||
return ((u32)right > res);
|
||||
}
|
||||
|
||||
inline bool BorrowFrom(s32 left, s32 right)
|
||||
{
|
||||
return ((u32)right > (u32)left);
|
||||
}
|
||||
|
||||
inline bool OverflowFromADD(s32 alu_out, s32 left, s32 right)
|
||||
{
|
||||
return ((left >= 0 && right >= 0) || (left < 0 && right < 0))
|
||||
&& ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
|
||||
}
|
||||
|
||||
inline bool OverflowFromSUB(s32 alu_out, s32 left, s32 right)
|
||||
{
|
||||
return ((left < 0 && right >= 0) || (left >= 0 && right < 0))
|
||||
&& ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
|
||||
}
|
||||
|
||||
//zero 15-feb-2009 - these werent getting used and they were getting in my way
|
||||
//#define EQ 0x0
|
||||
//#define NE 0x1
|
||||
//#define CS 0x2
|
||||
//#define CC 0x3
|
||||
//#define MI 0x4
|
||||
//#define PL 0x5
|
||||
//#define VS 0x6
|
||||
//#define VC 0x7
|
||||
//#define HI 0x8
|
||||
//#define LS 0x9
|
||||
//#define GE 0xA
|
||||
//#define LT 0xB
|
||||
//#define GT 0xC
|
||||
//#define LE 0xD
|
||||
//#define AL 0xE
|
||||
|
||||
static const u8 arm_cond_table[16*16] = {
|
||||
// N=0, Z=0, C=0, V=0
|
||||
0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF, // 0x00
|
||||
0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20, // 0x00
|
||||
// N=0, Z=0, C=0, V=1
|
||||
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x00, // 0x10
|
||||
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||
// N=0, Z=0, C=1, V=0
|
||||
0x00,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF, // 0x20
|
||||
0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20,
|
||||
// N=0, Z=0, C=1, V=1
|
||||
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00, // 0x30
|
||||
0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||
// N=0, Z=1, C=0, V=0
|
||||
0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF, // 0x40
|
||||
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
|
||||
// N=0, Z=1, C=0, V=1
|
||||
0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x00, // 0x50
|
||||
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||
// N=0, Z=1, C=1, V=0
|
||||
0xFF,0x00,0xFF,0x00,0x00,0xFF,0x00,0xFF, // 0x60
|
||||
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
|
||||
// N=0, Z=1, C=1, V=1
|
||||
0xFF,0x00,0xFF,0x00,0x00,0xFF,0xFF,0x00, // 0x70
|
||||
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||
// N=1, Z=0, C=0, V=0
|
||||
0x00,0xFF,0x00,0xFF,0xFF,0x00,0x00,0xFF, // 0x80
|
||||
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||
// N=1, Z=0, C=0, V=1
|
||||
0x00,0xFF,0x00,0xFF,0xFF,0x00,0xFF,0x00, // 0x90
|
||||
0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20,
|
||||
// N=1, Z=0, C=1, V=0
|
||||
0x00,0xFF,0xFF,0x00,0xFF,0x00,0x00,0xFF, // 0xA0
|
||||
0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||
// N=1, Z=0, C=1, V=1
|
||||
0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x00, // 0xB0
|
||||
0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20,
|
||||
// N=1, Z=1, C=0, V=0
|
||||
0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF, // 0xC0
|
||||
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||
// N=1, Z=1, C=0, V=1
|
||||
0xFF,0x00,0x00,0xFF,0xFF,0x00,0xFF,0x00, // 0xD0
|
||||
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
|
||||
// N=1, Z=1, C=1, V=0
|
||||
0xFF,0x00,0xFF,0x00,0xFF,0x00,0x00,0xFF, // 0xE0
|
||||
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||
// N=1, Z=1, C=1, V=1
|
||||
0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00, // 0xF0
|
||||
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20
|
||||
};
|
||||
|
||||
#define TEST_COND(cond, inst, CPSR) ((arm_cond_table[((CPSR.val >> 24) & 0xf0)|(cond)]) & (1 << (inst)))
|
||||
|
||||
|
||||
enum Mode
|
||||
{
|
||||
USR = 0x10,
|
||||
FIQ = 0x11,
|
||||
IRQ = 0x12,
|
||||
SVC = 0x13,
|
||||
ABT = 0x17,
|
||||
UND = 0x1B,
|
||||
SYS = 0x1F
|
||||
};
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
#ifdef MSB_FIRST
|
||||
u32 N : 1,
|
||||
Z : 1,
|
||||
C : 1,
|
||||
V : 1,
|
||||
Q : 1,
|
||||
RAZ : 19,
|
||||
I : 1,
|
||||
F : 1,
|
||||
T : 1,
|
||||
mode : 5;
|
||||
#else
|
||||
u32 mode : 5,
|
||||
T : 1,
|
||||
F : 1,
|
||||
I : 1,
|
||||
RAZ : 19,
|
||||
Q : 1,
|
||||
V : 1,
|
||||
C : 1,
|
||||
Z : 1,
|
||||
N : 1;
|
||||
#endif
|
||||
} bits;
|
||||
u32 val;
|
||||
} Status_Reg;
|
||||
|
||||
/**
|
||||
* The control interface to a CPU
|
||||
*/
|
||||
struct armcpu_ctrl_iface
|
||||
{
|
||||
/** stall the processor */
|
||||
void (*stall)( void *instance);
|
||||
|
||||
/** unstall the processor */
|
||||
void (*unstall)( void *instance);
|
||||
|
||||
/** read a register value */
|
||||
u32 (*read_reg)( void *instance, u32 reg_num);
|
||||
|
||||
/** set a register value */
|
||||
void (*set_reg)( void *instance, u32 reg_num, u32 value);
|
||||
|
||||
/** install the post execute function */
|
||||
void (*install_post_ex_fn)( void *instance,
|
||||
void (*fn)( void *, u32 adr, int thumb),
|
||||
void *fn_data);
|
||||
|
||||
/** remove the post execute function */
|
||||
void (*remove_post_ex_fn)( void *instance);
|
||||
|
||||
/** the private data passed to all interface functions */
|
||||
void *data;
|
||||
};
|
||||
|
||||
|
||||
typedef void* armcp_t;
|
||||
|
||||
struct armcpu_t
|
||||
{
|
||||
u32 proc_ID;
|
||||
u32 instruction; //4
|
||||
u32 instruct_adr; //8
|
||||
u32 next_instruction; //12
|
||||
|
||||
u32 R[16]; //16
|
||||
Status_Reg CPSR; //80
|
||||
Status_Reg SPSR;
|
||||
|
||||
u32 R13_usr, R14_usr;
|
||||
u32 R13_svc, R14_svc;
|
||||
u32 R13_abt, R14_abt;
|
||||
u32 R13_und, R14_und;
|
||||
u32 R13_irq, R14_irq;
|
||||
u32 R8_fiq, R9_fiq, R10_fiq, R11_fiq, R12_fiq, R13_fiq, R14_fiq;
|
||||
Status_Reg SPSR_svc, SPSR_abt, SPSR_und, SPSR_irq, SPSR_fiq;
|
||||
|
||||
u32 intVector;
|
||||
u8 LDTBit; //1 : ARMv5 style 0 : non ARMv5 (earlier)
|
||||
|
||||
u32 freeze;
|
||||
//BOOL waitIRQ;
|
||||
//BOOL halt_IE_and_IF;
|
||||
|
||||
u8 intrWaitARM_state;
|
||||
|
||||
BOOL BIOS_loaded;
|
||||
|
||||
u32 (* *swi_tab)();
|
||||
|
||||
// flag indicating if the processor is stalled (for debugging)
|
||||
int stalled;
|
||||
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
u8 cond_table[16*16];
|
||||
#endif
|
||||
|
||||
/** there is a pending irq for the cpu */
|
||||
int irq_flag;
|
||||
|
||||
/** the post executed function (if installed) */
|
||||
void (*post_ex_fn)( void *, u32 adr, int thumb);
|
||||
|
||||
/** data for the post executed function */
|
||||
void *post_ex_fn_data;
|
||||
|
||||
/** the memory interface */
|
||||
armcpu_memory_iface *mem_if; // This is the memory interface currently in use.
|
||||
armcpu_memory_iface base_mem_if; // This is the CPU's base memory interface.
|
||||
|
||||
/** the ctrl interface */
|
||||
armcpu_ctrl_iface ctrl_iface;
|
||||
|
||||
// debugging stuff
|
||||
u32 runToRetTmp;
|
||||
bool runToRet;
|
||||
u32 stepOverBreak;
|
||||
std::vector<u32> *breakPoints;
|
||||
bool debugStep;
|
||||
};
|
||||
|
||||
void armcpu_SetControlInterface(armcpu_t *armcpu, const armcpu_ctrl_iface *theCtrlInterface);
|
||||
armcpu_ctrl_iface* armcpu_GetControlInterface(armcpu_t *armcpu);
|
||||
void armcpu_SetControlInterfaceData(armcpu_t *armcpu, void *theData);
|
||||
void* armcpu_GetControlInterfaceData(const armcpu_t *armcpu);
|
||||
|
||||
void armcpu_SetCurrentMemoryInterface(armcpu_t *armcpu, armcpu_memory_iface *theMemInterface);
|
||||
armcpu_memory_iface* armcpu_GetCurrentMemoryInterface(const armcpu_t *armcpu);
|
||||
void armcpu_SetCurrentMemoryInterfaceData(armcpu_t *armcpu, void *theData);
|
||||
void* armcpu_GetCurrentMemoryInterfaceData(const armcpu_t *armcpu);
|
||||
|
||||
void armcpu_SetBaseMemoryInterface(armcpu_t *armcpu, const armcpu_memory_iface *theMemInterface);
|
||||
armcpu_memory_iface* armcpu_GetBaseMemoryInterface(armcpu_t *armcpu);
|
||||
void armcpu_SetBaseMemoryInterfaceData(armcpu_t *armcpu, void *theData);
|
||||
void* armcpu_GetBaseMemoryInterfaceData(const armcpu_t *armcpu);
|
||||
|
||||
void armcpu_ResetMemoryInterfaceToBase(armcpu_t *armcpu);
|
||||
|
||||
void armcpu_changeCPSR();
|
||||
|
||||
int armcpu_new( armcpu_t *armcpu, u32 id);
|
||||
void armcpu_init(armcpu_t *armcpu, u32 adr);
|
||||
u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode);
|
||||
|
||||
|
||||
BOOL armcpu_irqException(armcpu_t *armcpu);
|
||||
BOOL armcpu_flagIrq( armcpu_t *armcpu);
|
||||
void armcpu_exception(armcpu_t *cpu, u32 number);
|
||||
u32 TRAPUNDEF(armcpu_t* cpu);
|
||||
u32 armcpu_Wait4IRQ(armcpu_t *cpu);
|
||||
|
||||
extern armcpu_t NDS_ARM7;
|
||||
extern armcpu_t NDS_ARM9;
|
||||
extern const armcpu_ctrl_iface arm_default_ctrl_iface;
|
||||
|
||||
template<int PROCNUM> u32 armcpu_exec();
|
||||
#ifdef HAVE_JIT
|
||||
template<int PROCNUM, bool jit> u32 armcpu_exec();
|
||||
#endif
|
||||
|
||||
void setIF(int PROCNUM, u32 flag);
|
||||
|
||||
static INLINE void NDS_makeIrq(int PROCNUM, u32 num)
|
||||
{
|
||||
setIF(PROCNUM,1<<num);
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2006-2015 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef BIOS_H
|
||||
#define BIOS_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
extern u32 (* ARM_swi_tab[2][32])();
|
||||
extern const char* ARM_swi_names[2][32];
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,329 @@
|
|||
/*
|
||||
Copyright (C) 2009-2024 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "types.h"
|
||||
|
||||
#define CHEAT_VERSION_MAJOR 2
|
||||
#define CHEAT_VERSION_MINOR 0
|
||||
#define MAX_XX_CODE 1024
|
||||
#define CHEAT_FILE_MIN_FGETS_BUFFER 32768
|
||||
|
||||
#define CHEAT_TYPE_EMPTY 0xFF
|
||||
#define CHEAT_TYPE_INTERNAL 0
|
||||
#define CHEAT_TYPE_AR 1
|
||||
#define CHEAT_TYPE_CODEBREAKER 2
|
||||
|
||||
enum CheatSystemError
|
||||
{
|
||||
CheatSystemError_NoError = 0,
|
||||
CheatSystemError_FileOpenFailed = 1,
|
||||
CheatSystemError_FileFormatInvalid = 2,
|
||||
CheatSystemError_GameNotFound = 3,
|
||||
CheatSystemError_LoadEntryError = 4,
|
||||
CheatSystemError_FileSaveFailed = 5,
|
||||
CheatSystemError_FileDoesNotExist = 6
|
||||
};
|
||||
|
||||
struct CHEATS_LIST
|
||||
{
|
||||
CHEATS_LIST()
|
||||
{
|
||||
memset(this,0,sizeof(*this));
|
||||
type = CHEAT_TYPE_EMPTY;
|
||||
}
|
||||
u8 type;
|
||||
u8 enabled;
|
||||
// TODO
|
||||
u8 freezeType; // 0 - normal freeze
|
||||
// 1 - can decrease
|
||||
// 2 - can increase
|
||||
u32 code[MAX_XX_CODE][2];
|
||||
|
||||
union
|
||||
{
|
||||
char description[1024];
|
||||
|
||||
struct
|
||||
{
|
||||
char descriptionMajor[512];
|
||||
char descriptionMinor[512];
|
||||
};
|
||||
};
|
||||
|
||||
u32 num;
|
||||
u8 size;
|
||||
};
|
||||
|
||||
class CHEATS
|
||||
{
|
||||
private:
|
||||
std::vector<CHEATS_LIST> _list;
|
||||
u8 _filename[MAX_PATH];
|
||||
size_t _currentGet;
|
||||
|
||||
char *clearCode(char *s);
|
||||
|
||||
public:
|
||||
CHEATS()
|
||||
: _currentGet(0)
|
||||
{
|
||||
memset(_filename, 0, sizeof(_filename));
|
||||
}
|
||||
~CHEATS() {}
|
||||
|
||||
void clear();
|
||||
void init(const char *thePath);
|
||||
const char* getFilePath() const;
|
||||
void setFilePath(const char *thePath);
|
||||
|
||||
size_t addItem(const CHEATS_LIST &srcCheat);
|
||||
bool add(u8 size, u32 address, u32 val, char *description, bool enabled);
|
||||
bool add(u8 size, u32 address, u32 val, char *description, u8 enabled);
|
||||
|
||||
bool updateItemAtIndex(const CHEATS_LIST &srcCheat, const size_t pos);
|
||||
bool update(u8 size, u32 address, u32 val, char *description, bool enabled, const size_t pos);
|
||||
bool update(u8 size, u32 address, u32 val, char *description, u8 enabled, const size_t pos);
|
||||
|
||||
bool move(size_t srcPos, size_t dstPos);
|
||||
|
||||
size_t add_AR_Direct(const CHEATS_LIST &srcCheat);
|
||||
bool add_AR(char *code, char *description, bool enabled);
|
||||
bool add_AR(char *code, char *description, u8 enabled);
|
||||
|
||||
bool update_AR(char *code, char *description, bool enabled, const size_t pos);
|
||||
bool update_AR(char *code, char *description, u8 enabled, const size_t pos);
|
||||
|
||||
bool add_CB(char *code, char *description, bool enabled);
|
||||
bool add_CB(char *code, char *description, u8 enabled);
|
||||
|
||||
bool update_CB(char *code, char *description, bool enabled, const size_t pos);
|
||||
bool update_CB(char *code, char *description, u8 enabled, const size_t pos);
|
||||
|
||||
bool remove(const size_t pos);
|
||||
|
||||
void toggle(bool enabled, const size_t pos);
|
||||
void toggle(u8 enablbed, const size_t pos);
|
||||
|
||||
void getListReset();
|
||||
bool getList(CHEATS_LIST *cheat);
|
||||
CHEATS_LIST* getListPtr();
|
||||
bool copyItemFromIndex(const size_t pos, CHEATS_LIST &outCheatItem);
|
||||
CHEATS_LIST* getItemPtrAtIndex(const size_t pos) const;
|
||||
size_t getListSize() const;
|
||||
size_t getActiveCount() const;
|
||||
void setDescription(const char *description, const size_t pos);
|
||||
bool save();
|
||||
bool load();
|
||||
bool process(int targetType) const;
|
||||
|
||||
static void JitNeedsReset();
|
||||
static bool ResetJitIfNeeded();
|
||||
|
||||
template<size_t LENGTH> static bool DirectWrite(const int targetProc, const u32 targetAddress, u32 newValue);
|
||||
static bool DirectWrite(const size_t newValueLength, const int targetProc, const u32 targetAddress, u32 newValue);
|
||||
|
||||
static bool ARparser(const CHEATS_LIST &cheat);
|
||||
|
||||
static void StringFromXXCode(const CHEATS_LIST &srcCheatItem, char *outCStringBuffer);
|
||||
static bool XXCodeFromString(const std::string codeString, CHEATS_LIST &outCheatItem);
|
||||
static bool XXCodeFromString(const char *codeString, CHEATS_LIST &outCheatItem);
|
||||
};
|
||||
|
||||
class CHEATSEARCH
|
||||
{
|
||||
private:
|
||||
u8 *_statMem;
|
||||
u8 *_mem;
|
||||
u32 _amount;
|
||||
u32 _lastRecord;
|
||||
|
||||
u32 _type;
|
||||
u32 _size;
|
||||
u32 _sign;
|
||||
|
||||
public:
|
||||
CHEATSEARCH()
|
||||
: _statMem(0), _mem(0), _amount(0), _lastRecord(0), _type(0), _size(0), _sign(0)
|
||||
{}
|
||||
~CHEATSEARCH() { this->close(); }
|
||||
bool start(u8 type, u8 size, u8 sign);
|
||||
void close();
|
||||
u32 search(u32 val);
|
||||
u32 search(u8 comp);
|
||||
u32 getAmount();
|
||||
bool getList(u32 *address, u32 *curVal);
|
||||
void getListReset();
|
||||
};
|
||||
|
||||
#define CHEATDB_OFFSET_FILE_DESCRIPTION 0x00000010
|
||||
#define CHEATDB_FILEOFFSET_FIRST_FAT_ENTRY 0x00000100
|
||||
|
||||
enum CheatDBFileFormat
|
||||
{
|
||||
CheatDBFileFormat_Undefined = 0,
|
||||
CheatDBFileFormat_R4 = 1,
|
||||
CheatDBFileFormat_Unknown = 65535
|
||||
};
|
||||
|
||||
// This struct maps to the FAT entries in the R4 cheat database file.
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
typedef struct FAT_R4
|
||||
{
|
||||
u8 serial[4];
|
||||
u32 CRC;
|
||||
u64 addr;
|
||||
} FAT_R4;
|
||||
#pragma pack(pop)
|
||||
|
||||
// Wrapper for a single entry in a memory block that contains data read from a cheat database file.
|
||||
// This struct also maintains the hierarchical relationships between entries.
|
||||
struct CheatDBEntry
|
||||
{
|
||||
u8 *base; // Pointer to the entry's base location in memory.
|
||||
char *name; // Pointer to the entry's name string.
|
||||
char *note; // Pointer to the entry's note string.
|
||||
u32 *codeLength; // Pointer to the entry's 32-bit code length in bytes. This value is NULL if the entry is a directory.
|
||||
u32 *codeData; // Pointer to the entry's code data, provided in pairs of 32-bit values. This value is NULL if the entry is a directory.
|
||||
|
||||
CheatDBEntry *parent;
|
||||
std::vector<CheatDBEntry> child;
|
||||
};
|
||||
typedef struct CheatDBEntry CheatDBEntry;
|
||||
|
||||
class CheatDBGame
|
||||
{
|
||||
protected:
|
||||
u32 _baseOffset; // This offset is relative to the file head.
|
||||
u32 _firstEntryOffset; // This offset is relative to the file head.
|
||||
u32 _encryptOffset; // This offset is relative to the memory address of this->_entryDataRawPtr.
|
||||
|
||||
u32 _rawDataSize;
|
||||
u32 _workingDataSize;
|
||||
u32 _crc;
|
||||
u32 _entryCount;
|
||||
|
||||
std::string _title;
|
||||
char _serial[4 + 1];
|
||||
|
||||
u8 *_entryDataRawPtr;
|
||||
u8 *_entryData;
|
||||
CheatDBEntry _entryRoot;
|
||||
u32 _cheatItemCount;
|
||||
|
||||
void _UpdateDirectoryParents(CheatDBEntry &directory);
|
||||
bool _CreateCheatItemFromCheatEntry(const CheatDBEntry &inEntry, const bool isHierarchical, CHEATS_LIST &outCheatItem);
|
||||
size_t _DirectoryAddCheatsFlat(const CheatDBEntry &directory, const bool isHierarchical, size_t cheatIndex, CHEATS_LIST *outCheatsList);
|
||||
|
||||
public:
|
||||
CheatDBGame();
|
||||
CheatDBGame(const u32 encryptOffset, const FAT_R4 &fat, const u32 rawDataSize);
|
||||
CheatDBGame(FILE *fp, const bool isEncrypted, const u32 encryptOffset, const FAT_R4 &fat, const u32 rawDataSize, u8 (&workingBuffer)[1024]);
|
||||
~CheatDBGame();
|
||||
|
||||
void SetInitialProperties(const u32 rawDataSize, const u32 encryptOffset, const FAT_R4 &fat);
|
||||
void LoadPropertiesFromFile(FILE *fp, const bool isEncrypted, u8 (&workingBuffer)[1024]);
|
||||
|
||||
u32 GetBaseOffset() const;
|
||||
u32 GetFirstEntryOffset() const;
|
||||
u32 GetEncryptOffset() const;
|
||||
u32 GetRawDataSize() const;
|
||||
u32 GetWorkingDataSize() const;
|
||||
u32 GetCRC() const;
|
||||
u32 GetEntryCount() const;
|
||||
u32 GetCheatItemCount() const;
|
||||
const char* GetTitle() const;
|
||||
const char* GetSerial() const;
|
||||
|
||||
const CheatDBEntry& GetEntryRoot() const;
|
||||
const u8* GetEntryRawData() const;
|
||||
bool IsEntryDataLoaded() const;
|
||||
|
||||
u8* LoadEntryData(FILE *fp, const bool isEncrypted);
|
||||
size_t ParseEntriesToCheatsListFlat(CHEATS_LIST *outCheatsList);
|
||||
};
|
||||
|
||||
typedef std::vector<CheatDBGame> CheatDBGameList;
|
||||
|
||||
class CheatDBFile
|
||||
{
|
||||
protected:
|
||||
std::string _path;
|
||||
std::string _description;
|
||||
std::string _formatString;
|
||||
|
||||
CheatDBFileFormat _format;
|
||||
bool _isEncrypted;
|
||||
size_t _size;
|
||||
|
||||
FILE *_fp;
|
||||
|
||||
CheatDBGame _ReadGame(const u32 encryptOffset, const FAT_R4 &fat, const u32 gameDataSize, u8 (&workingBuffer)[1024]);
|
||||
|
||||
public:
|
||||
CheatDBFile();
|
||||
~CheatDBFile();
|
||||
|
||||
static void R4Decrypt(u8 *buf, const size_t len, u64 n);
|
||||
static bool ReadToBuffer(FILE *fp, const size_t fileOffset, const bool isEncrypted, const size_t encryptOffset, const size_t requestedSize, u8 *outBuffer);
|
||||
|
||||
FILE* GetFilePtr() const;
|
||||
bool IsEncrypted() const;
|
||||
const char* GetDescription() const;
|
||||
CheatDBFileFormat GetFormat() const;
|
||||
const char* GetFormatString() const;
|
||||
|
||||
CheatSystemError OpenFile(const char *filePath);
|
||||
void CloseFile();
|
||||
|
||||
u32 LoadGameList(const char *gameCode, const u32 gameDatabaseCRC, CheatDBGameList &outList);
|
||||
};
|
||||
|
||||
class CHEATSEXPORT
|
||||
{
|
||||
private:
|
||||
CheatDBFile _dbFile;
|
||||
CheatDBGameList _tempGameList;
|
||||
CheatDBGame *_selectedDbGame;
|
||||
CHEATS_LIST *_cheats;
|
||||
CheatSystemError _lastError;
|
||||
|
||||
public:
|
||||
CHEATSEXPORT();
|
||||
~CHEATSEXPORT();
|
||||
|
||||
bool load(const char *path);
|
||||
void close();
|
||||
|
||||
CHEATS_LIST *getCheats() const;
|
||||
size_t getCheatsNum() const;
|
||||
const char* getGameTitle() const;
|
||||
const char* getDescription() const;
|
||||
CheatSystemError getErrorCode() const;
|
||||
};
|
||||
|
||||
CheatDBGame* GetCheatDBGameEntryFromList(const CheatDBGameList &gameList, const char *gameCode, const u32 gameDatabaseCRC);
|
||||
void CheatItemGenerateDescriptionHierarchical(const char *itemName, const char *itemNote, CHEATS_LIST &outCheatItem);
|
||||
void CheatItemGenerateDescriptionFlat(const char *folderName, const char *folderNote, const char *itemName, const char *itemNote, CHEATS_LIST &outCheatItem);
|
||||
|
||||
extern CHEATS *cheats;
|
||||
extern CHEATSEARCH *cheatSearch;
|
|
@ -0,0 +1,634 @@
|
|||
/*
|
||||
Copyright (C) 2009-2017 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//windows note: make sure this file gets compiled with _cdecl
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdio.h>
|
||||
#include "commandline.h"
|
||||
#include "types.h"
|
||||
#include "movie.h"
|
||||
#include "rtc.h"
|
||||
#include "slot1.h"
|
||||
#include "slot2.h"
|
||||
#include "NDSSystem.h"
|
||||
#include "utils/datetime.h"
|
||||
#include "utils/xstring.h"
|
||||
#include <compat/getopt.h>
|
||||
//#include "frontend/modules/mGetOpt.h" //to test with this, make sure global `optind` is initialized to 1
|
||||
|
||||
#define printerror(...) fprintf(stderr, __VA_ARGS__)
|
||||
|
||||
int _scanline_filter_a = 0, _scanline_filter_b = 2, _scanline_filter_c = 2, _scanline_filter_d = 4;
|
||||
int _commandline_linux_nojoy = 0;
|
||||
|
||||
CommandLine::CommandLine()
|
||||
: is_cflash_configured(false)
|
||||
, _load_to_memory(-1)
|
||||
, _play_movie_file(0)
|
||||
, _record_movie_file(0)
|
||||
, _cflash_image(0)
|
||||
, _cflash_path(0)
|
||||
, _gbaslot_rom(0)
|
||||
, _bios_arm9(NULL)
|
||||
, _bios_arm7(NULL)
|
||||
, _bios_swi(0)
|
||||
, _fw_path(NULL)
|
||||
, _fw_boot(0)
|
||||
, _spu_sync_mode(-1)
|
||||
, _spu_sync_method(-1)
|
||||
, _spu_advanced(0)
|
||||
, _num_cores(-1)
|
||||
, _rigorous_timing(0)
|
||||
, _advanced_timing(-1)
|
||||
, _gamehacks(-1)
|
||||
, _texture_deposterize(-1)
|
||||
, _texture_smooth(-1)
|
||||
, _slot1(NULL)
|
||||
, _slot1_fat_dir(NULL)
|
||||
, _slot1_fat_dir_type(false)
|
||||
, _slot1_no8000prot(0)
|
||||
#ifdef HAVE_JIT
|
||||
, _cpu_mode(-1)
|
||||
, _jit_size(-1)
|
||||
#endif
|
||||
, _console_type(NULL)
|
||||
, _advanscene_import(NULL)
|
||||
, load_slot(-1)
|
||||
, arm9_gdb_port(0)
|
||||
, arm7_gdb_port(0)
|
||||
, start_paused(FALSE)
|
||||
, autodetect_method(-1)
|
||||
, render3d(COMMANDLINE_RENDER3D_DEFAULT)
|
||||
, texture_upscale(-1)
|
||||
, gpu_resolution_multiplier(-1)
|
||||
, language(1) //english by default
|
||||
, disable_sound(0)
|
||||
, disable_limiter(0)
|
||||
, windowed_fullscreen(0)
|
||||
, frameskip(0)
|
||||
, horizontal(0)
|
||||
, scale(1.0)
|
||||
, _rtc_day(-1)
|
||||
, _rtc_hour(-1)
|
||||
{
|
||||
}
|
||||
|
||||
CommandLine::~CommandLine()
|
||||
{
|
||||
}
|
||||
|
||||
static char mytoupper(char c) { return ::toupper(c); }
|
||||
|
||||
static std::string strtoupper(const std::string& str)
|
||||
{
|
||||
std::string ret = str;
|
||||
std::transform(ret.begin(), ret.end(), ret.begin(), ::mytoupper);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define ENDL "\n"
|
||||
static const char* help_string = \
|
||||
"Arguments affecting overall emulator behaviour: (`user settings`):" ENDL
|
||||
" --num-cores N Override numcores detection and use this many" ENDL
|
||||
" --spu-synch Use SPU synch (crackles; helps streams; default ON)" ENDL
|
||||
" --spu-method N Select SPU synch method: 0:N, 1:Z, 2:P; default 0" ENDL
|
||||
" --3d-render [SW|AUTOGL|GL|OLDGL]" ENDL
|
||||
" Select 3d renderer; default SW" ENDL
|
||||
" --3d-texture-deposterize-enable" ENDL
|
||||
" Enables texture deposterization." ENDL
|
||||
" --3d-texture-upscale [1|2|4]" ENDL
|
||||
" Automatically upscales textures by the specified" ENDL
|
||||
" amount; 1:No scaling (default), 2:2x upscaling," ENDL
|
||||
" 4:4x upscaling" ENDL
|
||||
" --3d-texture-smoothing-enable" ENDL
|
||||
" Enables smooth texture sampling while rendering." ENDL
|
||||
#ifdef HOST_WINDOWS
|
||||
" --gpu-resolution-multiplier N" ENDL
|
||||
" Increases the resolution of GPU rendering by this" ENDL
|
||||
" multipler; 1:256x192 (default), 2:512x384," ENDL
|
||||
" 3:768x576, 4:1024x768, 5:1280x960" ENDL
|
||||
" --windowed-fullscreen" ENDL
|
||||
" Launches in windowed fullscreen (same as alt+enter)" ENDL
|
||||
#else
|
||||
" --scale N scale factor for window; default 1.0" ENDL
|
||||
" --horizontal display touch screen to the right; default OFF" ENDL
|
||||
" --nojoy Disables joystick support" ENDL
|
||||
#endif
|
||||
" --disable-sound Disables the sound output" ENDL
|
||||
" --disable-limiter Disables the 60fps limiter" ENDL
|
||||
" --rtc-day D Override RTC day, 0=Sunday, 6=Saturday" ENDL
|
||||
" --rtc-hour H Override RTC hour, 0=midnight, 23=an hour before" ENDL
|
||||
" --frameskip N Set frameskip to N; default 0" ENDL
|
||||
ENDL
|
||||
"Arguments affecting overall emulation parameters (`sync settings`): " ENDL
|
||||
#ifdef HAVE_JIT
|
||||
" --jit-enable Formerly --cpu-mode; default OFF" ENDL
|
||||
" --jit-size N JIT block size 1-100; 1:accurate 100:fast (default)" ENDL
|
||||
#endif
|
||||
" --advanced-timing Use advanced bus-level timing; default ON" ENDL
|
||||
" --rigorous-timing Use more realistic component timings; default OFF" ENDL
|
||||
" --gamehacks Use game-specific hacks; default ON" ENDL
|
||||
" --spu-advanced Enable advanced SPU capture functions (reverb)" ENDL
|
||||
" --backupmem-db Use DB for autodetecting backup memory type" ENDL
|
||||
ENDL
|
||||
"Arguments affecting the emulated requipment:" ENDL
|
||||
" --console-type [FAT|LITE|IQUE|DEBUG|DSI]" ENDL
|
||||
" Select basic console type; default FAT" ENDL
|
||||
" --bios-arm9 BIN_FILE Uses the ARM9 BIOS provided at the specified path" ENDL
|
||||
" --bios-arm7 BIN_FILE Uses the ARM7 BIOS provided at the specified path" ENDL
|
||||
" --firmware-path BIN_FILE Uses the firmware provided at the specified path" ENDL
|
||||
" --firmware-boot 0|1 Boot from firmware" ENDL
|
||||
" --bios-swi Uses SWI from the provided bios files (else HLE)" ENDL
|
||||
" --lang N Firmware language (can affect game translations)" ENDL
|
||||
" 0 = Japanese, 1 = English (default), 2 = French" ENDL
|
||||
" 3 = German, 4 = Italian, 5 = Spanish" ENDL
|
||||
ENDL
|
||||
"Arguments affecting contents of SLOT-1:" ENDL
|
||||
" --slot1 [RETAIL|RETAILAUTO|R4|RETAILNAND|RETAILMCDROM|RETAILDEBUG]" ENDL
|
||||
" Device type to be used SLOT-1; default RETAILAUTO" ENDL
|
||||
" --preload-rom precache ROM to RAM instead of streaming from disk" ENDL
|
||||
" --slot1-fat-dir DIR Directory to mount for SLOT-1 flash cards" ENDL
|
||||
" --slot1_no8000prot Disables retail card copy protection <8000 feature" ENDL
|
||||
ENDL
|
||||
"Arguments affecting contents of SLOT-2:" ENDL
|
||||
" --cflash-image IMG_FILE Mounts cflash in SLOT-2 with specified image file" ENDL
|
||||
" --cflash-path DIR Mounts cflash in SLOT-2 with FS rooted at DIR" ENDL
|
||||
" --gbaslot-rom GBA_FILE Mounts GBA specified rom in SLOT-2" ENDL
|
||||
ENDL
|
||||
"Commands taking place after ROM is loaded: (be sure to specify a ROM!)" ENDL
|
||||
" --start-paused emulation should start paused" ENDL
|
||||
" --load-slot N loads savestate from slot N (0-9)" ENDL
|
||||
" --play-movie DSM_FILE automatically plays movie" ENDL
|
||||
" --record-movie DSM_FILE begin recording a movie" ENDL
|
||||
ENDL
|
||||
"Arguments affecting video filters:" ENDL
|
||||
" --scanline-filter-a N Fadeout intensity (N/16) (topleft) (default 0)" ENDL
|
||||
" --scanline-filter-b N Fadeout intensity (N/16) (topright) (default 2)" ENDL
|
||||
" --scanline-filter-c N Fadeout intensity (N/16) (bottomleft) (default 2)" ENDL
|
||||
" --scanline-filter-d N Fadeout intensity (N/16) (bottomright) (default 4)" ENDL
|
||||
ENDL
|
||||
#ifdef GDB_STUB
|
||||
"Arguments affecting debugging features:" ENDL
|
||||
" --arm9gdb PORTNUM Enable the ARM9 GDB stub on the given port" ENDL
|
||||
" --arm7gdb PORTNUM Enable the ARM7 GDB stub on the given port" ENDL
|
||||
ENDL
|
||||
#endif
|
||||
"Utility commands which occur in place of emulation:" ENDL
|
||||
" --advanscene-import PATH Import advanscene, dump .ddb, and exit" ENDL
|
||||
ENDL
|
||||
"These arguments may be reorganized/renamed in the future." ENDL ENDL
|
||||
;
|
||||
|
||||
//https://github.com/mono/mono/blob/b7a308f660de8174b64697a422abfc7315d07b8c/eglib/test/driver.c
|
||||
|
||||
#define OPT_NUMCORES 1
|
||||
#define OPT_SPU_METHOD 2
|
||||
#define OPT_3D_RENDER 3
|
||||
#define OPT_3D_TEXTURE_UPSCALE 81
|
||||
#define OPT_GPU_RESOLUTION_MULTIPLIER 82
|
||||
#define OPT_FRAMESKIP 83
|
||||
#define OPT_SCALE 84
|
||||
#define OPT_JIT_SIZE 100
|
||||
|
||||
#define OPT_CONSOLE_TYPE 200
|
||||
#define OPT_ARM9 201
|
||||
#define OPT_ARM7 202
|
||||
#define OPT_LANGUAGE 203
|
||||
#define OPT_FIRMPATH 204
|
||||
#define OPT_FIRMBOOT 205
|
||||
|
||||
#define OPT_SLOT1 300
|
||||
#define OPT_SLOT1_FAT_DIR 301
|
||||
|
||||
#define OPT_LOAD_SLOT 400
|
||||
#define OPT_PLAY_MOVIE 410
|
||||
#define OPT_RECORD_MOVIE 411
|
||||
|
||||
#define OPT_SLOT2_CFLASH_IMAGE 500
|
||||
#define OPT_SLOT2_CFLASH_DIR 501
|
||||
#define OPT_SLOT2_GBAGAME 502
|
||||
|
||||
#define OPT_SCANLINES_A 600
|
||||
#define OPT_SCANLINES_B 601
|
||||
#define OPT_SCANLINES_C 602
|
||||
#define OPT_SCANLINES_D 603
|
||||
|
||||
#define OPT_ARM9GDB 700
|
||||
#define OPT_ARM7GDB 701
|
||||
|
||||
#define OPT_RTC_DAY 800
|
||||
#define OPT_RTC_HOUR 801
|
||||
|
||||
#define OPT_ADVANSCENE 900
|
||||
|
||||
bool CommandLine::parse(int argc,char **argv)
|
||||
{
|
||||
//closest thing to a portable main() we have, I guess.
|
||||
srand((unsigned)time(nullptr));
|
||||
|
||||
std::string _render3d;
|
||||
|
||||
int opt_help = 0;
|
||||
int option_index = 0;
|
||||
for(;;)
|
||||
{
|
||||
//libretro-common's optional argument is not supported presently
|
||||
static struct option long_options[] =
|
||||
{
|
||||
//stuff
|
||||
{ "help", no_argument, &opt_help, 1 },
|
||||
|
||||
//user settings
|
||||
{ "num-cores", required_argument, NULL, OPT_NUMCORES },
|
||||
{ "spu-synch", no_argument, &_spu_sync_mode, 1 },
|
||||
{ "spu-method", required_argument, NULL, OPT_SPU_METHOD },
|
||||
{ "3d-render", required_argument, NULL, OPT_3D_RENDER },
|
||||
{ "3d-texture-deposterize-enable", no_argument, &_texture_deposterize, 1 },
|
||||
{ "3d-texture-upscale", required_argument, NULL, OPT_3D_TEXTURE_UPSCALE },
|
||||
{ "3d-texture-smoothing-enable", no_argument, &_texture_smooth, 1 },
|
||||
#ifdef HOST_WINDOWS
|
||||
{ "gpu-resolution-multiplier", required_argument, NULL, OPT_GPU_RESOLUTION_MULTIPLIER },
|
||||
{ "windowed-fullscreen", no_argument, &windowed_fullscreen, 1 },
|
||||
#else
|
||||
{ "nojoy", no_argument, &_commandline_linux_nojoy, 1},
|
||||
{ "horizontal", no_argument, &horizontal, 1},
|
||||
{ "scale", required_argument, NULL, OPT_SCALE},
|
||||
#endif
|
||||
{ "frameskip", required_argument, NULL, OPT_FRAMESKIP},
|
||||
{ "disable-sound", no_argument, &disable_sound, 1},
|
||||
{ "disable-limiter", no_argument, &disable_limiter, 1},
|
||||
{ "rtc-day", required_argument, NULL, OPT_RTC_DAY},
|
||||
{ "rtc-hour", required_argument, NULL, OPT_RTC_HOUR},
|
||||
|
||||
//sync settings
|
||||
#ifdef HAVE_JIT
|
||||
{ "jit-enable", no_argument, &_cpu_mode, 1},
|
||||
{ "jit-size", required_argument, NULL, OPT_JIT_SIZE },
|
||||
#endif
|
||||
{ "rigorous-timing", no_argument, &_rigorous_timing, 1},
|
||||
{ "advanced-timing", no_argument, &_advanced_timing, 1},
|
||||
{ "gamehacks", no_argument, &_gamehacks, 1},
|
||||
{ "spu-advanced", no_argument, &_spu_advanced, 1},
|
||||
{ "backupmem-db", no_argument, &autodetect_method, 1},
|
||||
|
||||
//system equipment
|
||||
{ "console-type", required_argument, NULL, OPT_CONSOLE_TYPE },
|
||||
{ "bios-arm9", required_argument, NULL, OPT_ARM9},
|
||||
{ "bios-arm7", required_argument, NULL, OPT_ARM7},
|
||||
{ "bios-swi", no_argument, &_bios_swi, 1},
|
||||
{ "firmware-path", required_argument, NULL, OPT_FIRMPATH},
|
||||
{ "firmware-boot", required_argument, NULL, OPT_FIRMBOOT},
|
||||
{ "lang", required_argument, NULL, OPT_LANGUAGE},
|
||||
|
||||
//slot-1 contents
|
||||
{ "slot1", required_argument, NULL, OPT_SLOT1},
|
||||
{ "preload-rom", no_argument, &_load_to_memory, 1},
|
||||
{ "slot1-fat-dir", required_argument, NULL, OPT_SLOT1_FAT_DIR},
|
||||
//and other slot-1 option
|
||||
{ "slot1-no8000prot", no_argument, &_slot1_no8000prot, 1},
|
||||
|
||||
//slot-2 contents
|
||||
{ "cflash-image", required_argument, NULL, OPT_SLOT2_CFLASH_IMAGE},
|
||||
{ "cflash-path", required_argument, NULL, OPT_SLOT2_CFLASH_DIR},
|
||||
{ "gbaslot-rom", required_argument, NULL, OPT_SLOT2_GBAGAME},
|
||||
|
||||
//commands
|
||||
{ "start-paused", no_argument, &start_paused, 1},
|
||||
{ "load-slot", required_argument, NULL, OPT_LOAD_SLOT},
|
||||
{ "play-movie", required_argument, NULL, OPT_PLAY_MOVIE},
|
||||
{ "record-movie", required_argument, NULL, OPT_RECORD_MOVIE},
|
||||
|
||||
//video filters
|
||||
{ "scanline-filter-a", required_argument, NULL, OPT_SCANLINES_A},
|
||||
{ "scanline-filter-b", required_argument, NULL, OPT_SCANLINES_B},
|
||||
{ "scanline-filter-c", required_argument, NULL, OPT_SCANLINES_C},
|
||||
{ "scanline-filter-d", required_argument, NULL, OPT_SCANLINES_D},
|
||||
|
||||
//debugging
|
||||
#ifdef GDB_STUB
|
||||
{ "arm9gdb", required_argument, NULL, OPT_ARM9GDB},
|
||||
{ "arm7gdb", required_argument, NULL, OPT_ARM7GDB},
|
||||
#endif
|
||||
|
||||
//utilities
|
||||
{ "advanscene-import", required_argument, NULL, OPT_ADVANSCENE},
|
||||
|
||||
{0,0,0,0}
|
||||
};
|
||||
|
||||
int c = getopt_long(argc,argv,"",long_options,&option_index);
|
||||
if(c == -1) break;
|
||||
if(c == '?')
|
||||
break;
|
||||
|
||||
switch(c)
|
||||
{
|
||||
case 0: break;
|
||||
|
||||
//user settings
|
||||
case OPT_NUMCORES: _num_cores = atoi(optarg); break;
|
||||
case OPT_SPU_METHOD: _spu_sync_method = atoi(optarg); break;
|
||||
case OPT_3D_RENDER: _render3d = optarg; break;
|
||||
case OPT_3D_TEXTURE_UPSCALE: texture_upscale = atoi(optarg); break;
|
||||
case OPT_GPU_RESOLUTION_MULTIPLIER: gpu_resolution_multiplier = atoi(optarg); break;
|
||||
case OPT_SCALE: scale = atof(optarg); break;
|
||||
case OPT_FRAMESKIP: frameskip = atoi(optarg); break;
|
||||
|
||||
//RTC settings
|
||||
case OPT_RTC_DAY: _rtc_day = atoi(optarg); break;
|
||||
case OPT_RTC_HOUR: _rtc_hour = atoi(optarg); break;
|
||||
|
||||
//sync settings
|
||||
#ifdef HAVE_JIT
|
||||
case OPT_JIT_SIZE: _jit_size = atoi(optarg); break;
|
||||
#endif
|
||||
|
||||
//system equipment
|
||||
case OPT_CONSOLE_TYPE: console_type = optarg; break;
|
||||
case OPT_ARM9: _bios_arm9 = strdup(optarg); break;
|
||||
case OPT_ARM7: _bios_arm7 = strdup(optarg); break;
|
||||
case OPT_FIRMPATH: _fw_path = strdup(optarg); break;
|
||||
case OPT_FIRMBOOT: _fw_boot = atoi(optarg); break;
|
||||
|
||||
//slot-1 contents
|
||||
case OPT_SLOT1: slot1 = strtoupper(optarg); break;
|
||||
case OPT_SLOT1_FAT_DIR: slot1_fat_dir = optarg; break;
|
||||
|
||||
//slot-2 contents
|
||||
case OPT_SLOT2_CFLASH_IMAGE: cflash_image = optarg; break;
|
||||
case OPT_SLOT2_CFLASH_DIR: _cflash_path = optarg; break;
|
||||
case OPT_SLOT2_GBAGAME: _gbaslot_rom = optarg; break;
|
||||
|
||||
//commands
|
||||
case OPT_LOAD_SLOT: load_slot = atoi(optarg); break;
|
||||
case OPT_PLAY_MOVIE: play_movie_file = optarg; break;
|
||||
case OPT_RECORD_MOVIE: record_movie_file = optarg; break;
|
||||
|
||||
//video filters
|
||||
case OPT_SCANLINES_A: _scanline_filter_a = atoi(optarg); break;
|
||||
case OPT_SCANLINES_B: _scanline_filter_b = atoi(optarg); break;
|
||||
case OPT_SCANLINES_C: _scanline_filter_c = atoi(optarg); break;
|
||||
case OPT_SCANLINES_D: _scanline_filter_d = atoi(optarg); break;
|
||||
|
||||
//debugging
|
||||
case OPT_ARM9GDB: arm9_gdb_port = atoi(optarg); break;
|
||||
case OPT_ARM7GDB: arm7_gdb_port = atoi(optarg); break;
|
||||
|
||||
//utilities
|
||||
case OPT_ADVANSCENE: CommonSettings.run_advanscene_import = optarg; break;
|
||||
case OPT_LANGUAGE: language = atoi(optarg); break;
|
||||
}
|
||||
} //arg parsing loop
|
||||
|
||||
if(opt_help)
|
||||
{
|
||||
printf("%s",help_string);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(_load_to_memory != -1) CommonSettings.loadToMemory = (_load_to_memory == 1)?true:false;
|
||||
if(_num_cores != -1) CommonSettings.num_cores = _num_cores;
|
||||
if(_rigorous_timing) CommonSettings.rigorous_timing = true;
|
||||
if(_advanced_timing != -1) CommonSettings.advanced_timing = _advanced_timing==1;
|
||||
if(_gamehacks != -1) CommonSettings.gamehacks.en = _gamehacks==1;
|
||||
|
||||
#ifdef HAVE_JIT
|
||||
if(_cpu_mode != -1) CommonSettings.use_jit = (_cpu_mode==1);
|
||||
if(_jit_size != -1)
|
||||
{
|
||||
if ((_jit_size < 1) || (_jit_size > 100))
|
||||
CommonSettings.jit_max_block_size = 100;
|
||||
else
|
||||
CommonSettings.jit_max_block_size = _jit_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
//process console type
|
||||
CommonSettings.DebugConsole = false;
|
||||
CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_FAT;
|
||||
console_type = strtoupper(console_type);
|
||||
if(console_type == "") {}
|
||||
else if(console_type == "FAT") CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_FAT;
|
||||
else if(console_type == "LITE") CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_LITE;
|
||||
else if(console_type == "IQUE") CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_IQUE;
|
||||
else if(console_type == "DSI") CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_DSI;
|
||||
else if(console_type == "DEBUG")
|
||||
{
|
||||
CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_FAT;
|
||||
CommonSettings.DebugConsole = true;
|
||||
}
|
||||
|
||||
//process 3d renderer
|
||||
_render3d = strtoupper(_render3d);
|
||||
if(_render3d == "NONE") render3d = COMMANDLINE_RENDER3D_NONE;
|
||||
else if(_render3d == "SW") render3d = COMMANDLINE_RENDER3D_SW;
|
||||
else if(_render3d == "OLDGL") render3d = COMMANDLINE_RENDER3D_OLDGL;
|
||||
else if(_render3d == "AUTOGL") render3d = COMMANDLINE_RENDER3D_AUTOGL;
|
||||
else if(_render3d == "GL") render3d = COMMANDLINE_RENDER3D_GL;
|
||||
|
||||
if (_texture_deposterize != -1) CommonSettings.GFX3D_Renderer_TextureDeposterize = (_texture_deposterize == 1);
|
||||
if (_texture_smooth != -1) CommonSettings.GFX3D_Renderer_TextureSmoothing = (_texture_smooth == 1);
|
||||
|
||||
if (autodetect_method != -1)
|
||||
CommonSettings.autodetectBackupMethod = autodetect_method;
|
||||
|
||||
//TODO NOT MAX PRIORITY! change ARM9BIOS etc to be a std::string
|
||||
if(_bios_arm9) { CommonSettings.UseExtBIOS = true; strcpy(CommonSettings.ARM9BIOS,_bios_arm9); }
|
||||
if(_bios_arm7) { CommonSettings.UseExtBIOS = true; strcpy(CommonSettings.ARM7BIOS,_bios_arm7); }
|
||||
#ifndef HOST_WINDOWS
|
||||
if(_fw_path) { CommonSettings.UseExtFirmware = true; CommonSettings.UseExtFirmwareSettings = true; strcpy(CommonSettings.ExtFirmwarePath,_fw_path); }
|
||||
#endif
|
||||
if(_fw_boot) CommonSettings.BootFromFirmware = true;
|
||||
if(_bios_swi) CommonSettings.SWIFromBIOS = true;
|
||||
if(_slot1_no8000prot) CommonSettings.RetailCardProtection8000 = false;
|
||||
if(_spu_sync_mode != -1) CommonSettings.SPU_sync_mode = _spu_sync_mode;
|
||||
if(_spu_sync_method != -1) CommonSettings.SPU_sync_method = _spu_sync_method;
|
||||
if(_spu_advanced) CommonSettings.spu_advanced = true;
|
||||
|
||||
free(_bios_arm9);
|
||||
free(_bios_arm7);
|
||||
_bios_arm9 = _bios_arm7 = NULL;
|
||||
|
||||
//remaining argument should be an NDS file, and nothing more
|
||||
int remain = argc-optind;
|
||||
if(remain==1)
|
||||
nds_file = argv[optind];
|
||||
else if(remain>1) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommandLine::validate()
|
||||
{
|
||||
if(slot1 != "")
|
||||
{
|
||||
if(slot1 != "R4" && slot1 != "RETAIL" && slot1 != "NONE" && slot1 != "RETAILNAND") {
|
||||
printerror("Invalid slot1 device specified.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (_load_to_memory < -1 || _load_to_memory > 1) {
|
||||
printerror("Invalid parameter (0 - stream from disk, 1 - from RAM)\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_spu_sync_mode < -1 || _spu_sync_mode > 1) {
|
||||
printerror("Invalid parameter\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_spu_sync_method < -1 || _spu_sync_method > 2) {
|
||||
printerror("Invalid parameter\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (load_slot < -1 || load_slot > 10) {
|
||||
printerror("I only know how to load from slots 0-10; -1 means 'do not load savegame' and is default\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(play_movie_file != "" && record_movie_file != "") {
|
||||
printerror("Cannot both play and record a movie.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(record_movie_file != "" && load_slot != -1) {
|
||||
printerror("Cannot both record a movie and load a savestate.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(cflash_path != "" && cflash_image != "") {
|
||||
printerror("Cannot specify both cflash-image and cflash-path.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if((_bios_arm9 && !_bios_arm7) || (_bios_arm7 && !_bios_arm9)) {
|
||||
printerror("If either bios-arm7 or bios-arm9 are specified, both must be.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(_bios_swi && (!_bios_arm7 || !_bios_arm9)) {
|
||||
printerror("If either bios-swi is used, bios-arm9 and bios-arm7 must be specified.\n");
|
||||
}
|
||||
|
||||
if(_fw_boot && (!_fw_path)) {
|
||||
printerror("If either firmware boot is used, firmware path must be specified.\n");
|
||||
}
|
||||
|
||||
if((_cflash_image && _gbaslot_rom) || (_cflash_path && _gbaslot_rom)) {
|
||||
printerror("Cannot specify both cflash and gbaslot rom (both occupy SLOT-2)\n");
|
||||
}
|
||||
|
||||
if (autodetect_method < -1 || autodetect_method > 1) {
|
||||
printerror("Invalid autodetect save method (0 - internal, 1 - from database)\n");
|
||||
}
|
||||
|
||||
if ( (texture_upscale != -1) && (texture_upscale != 1) && (texture_upscale != 2) && (texture_upscale != 4) ) {
|
||||
printerror("Invalid texture upscaling value [1|2|4]. Ignoring command line setting.\n");
|
||||
texture_upscale = -1;
|
||||
}
|
||||
|
||||
if ( (gpu_resolution_multiplier != -1) && ((gpu_resolution_multiplier < 1) || (gpu_resolution_multiplier > 5)) ) {
|
||||
printerror("Invalid GPU resolution multiplier [1..5]. Ignoring command line setting.\n");
|
||||
gpu_resolution_multiplier = -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_JIT
|
||||
if (_cpu_mode < -1 || _cpu_mode > 1) {
|
||||
printerror("Invalid cpu mode emulation (0 - interpreter, 1 - dynarec)\n");
|
||||
}
|
||||
if (_jit_size < -1 && (_jit_size == 0 || _jit_size > 100)) {
|
||||
printerror("Invalid jit block size [1..100]. set to 100\n");
|
||||
}
|
||||
#endif
|
||||
if (_rtc_day < -1 || _rtc_day > 6) {
|
||||
printerror("Invalid rtc day override, valid values are from 0 to 6");
|
||||
return false;
|
||||
}
|
||||
if (_rtc_hour < -1 || _rtc_hour > 23) {
|
||||
printerror("Invalid rtc day override, valid values are from 0 to 23");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CommandLine::errorHelp(const char* binName)
|
||||
{
|
||||
printerror("%s",help_string);
|
||||
}
|
||||
|
||||
void CommandLine::process_movieCommands()
|
||||
{
|
||||
if(play_movie_file != "")
|
||||
{
|
||||
FCEUI_LoadMovie(play_movie_file.c_str(),true,false,-1);
|
||||
}
|
||||
else if(record_movie_file != "")
|
||||
{
|
||||
FCEUI_SaveMovie(record_movie_file.c_str(), L"", START_BLANK, NULL, FCEUI_MovieGetRTCDefault());
|
||||
}
|
||||
}
|
||||
|
||||
void CommandLine::process_addonCommands()
|
||||
{
|
||||
if (cflash_image != "")
|
||||
{
|
||||
CFlash_Mode = ADDON_CFLASH_MODE_File;
|
||||
CFlash_Path = cflash_image;
|
||||
is_cflash_configured = true;
|
||||
}
|
||||
if (cflash_path != "")
|
||||
{
|
||||
CFlash_Mode = ADDON_CFLASH_MODE_Path;
|
||||
CFlash_Path = cflash_path;
|
||||
is_cflash_configured = true;
|
||||
}
|
||||
|
||||
if(slot1_fat_dir != "")
|
||||
slot1_SetFatDir(slot1_fat_dir);
|
||||
|
||||
if(slot1 == "RETAIL")
|
||||
slot1_Change(NDS_SLOT1_RETAIL_AUTO);
|
||||
else if(slot1 == "RETAILAUTO")
|
||||
slot1_Change(NDS_SLOT1_RETAIL_AUTO);
|
||||
else if(slot1 == "R4")
|
||||
slot1_Change(NDS_SLOT1_R4);
|
||||
else if(slot1 == "RETAILNAND")
|
||||
slot1_Change(NDS_SLOT1_RETAIL_NAND);
|
||||
else if(slot1 == "RETAILMCROM")
|
||||
slot1_Change(NDS_SLOT1_RETAIL_MCROM);
|
||||
else if(slot1 == "RETAILDEBUG")
|
||||
slot1_Change(NDS_SLOT1_RETAIL_DEBUG);
|
||||
|
||||
if (_rtc_day != -1 || _rtc_hour != -1) {
|
||||
DateTime now = DateTime::get_Now();
|
||||
int cur_day = now.get_DayOfWeek();
|
||||
int cur_hour = now.get_Hour();
|
||||
int cur_total = cur_day * 24 + cur_hour;
|
||||
int day = (_rtc_day != -1 ? _rtc_day : cur_day);
|
||||
int hour = (_rtc_hour != -1 ? _rtc_hour : cur_hour);
|
||||
int total = day * 24 + hour;
|
||||
int diff = total - cur_total;
|
||||
if (diff < 0)
|
||||
diff += 24 * 7;
|
||||
rtcHourOverride = diff;
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue