mirror of
https://github.com/libretro/mame2003-plus-libretro.git
synced 2026-11-07 04:16:07 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dff0ba6365 | ||
|
|
1035485897 | ||
|
|
a0e0e75905 | ||
|
|
a45b70e19e | ||
|
|
ea291bf560 | ||
|
|
0dd483f4c0 | ||
|
|
7f35678403 | ||
|
|
888122871c | ||
|
|
d41198a39d | ||
|
|
34988bc120 | ||
|
|
af0f783b1e | ||
|
|
b8afd2ddde | ||
|
|
00e1f93fc6 | ||
|
|
ae8299f57c | ||
|
|
11b6dd20a8 | ||
|
|
b6b9bae087 | ||
|
|
9f568e318b | ||
|
|
5a0269a6fd | ||
|
|
91f2f15e15 | ||
|
|
b974d670cc | ||
|
|
ab52620ee4 | ||
|
|
7ed1af5370 | ||
|
|
35fee378f5 | ||
|
|
40dab5fe44 | ||
|
|
cc4bfcdf71 | ||
|
|
93b073496c | ||
|
|
4930bf5be7 | ||
|
|
6d162f313c | ||
|
|
e455f1783a | ||
|
|
9275a6a775 | ||
|
|
4d5e7f3e17 | ||
|
|
b168882c39 | ||
|
|
4125e63480 | ||
|
|
90149e76d2 | ||
|
|
273f904d7d | ||
|
|
df60f6466d | ||
|
|
b47967f1f2 | ||
|
|
a1fb5c7993 | ||
|
|
d7117cdcdc | ||
|
|
0ad96d5104 | ||
|
|
f80f7223f4 | ||
|
|
ff5f1bd024 | ||
|
|
dfc61f1689 | ||
|
|
c6a2aa4700 | ||
|
|
6266128ce8 | ||
|
|
9649c81834 | ||
|
|
0e919473ca | ||
|
|
fa9eea238c | ||
|
|
ad755f06ad | ||
|
|
5b5d6f8a23 | ||
|
|
faa5ddf4e9 | ||
|
|
46f354464a | ||
|
|
3b41adc749 | ||
|
|
bdfdc977c2 | ||
|
|
5e593b6462 | ||
|
|
da7b539232 | ||
|
|
eb11c10f08 | ||
|
|
b3328713bb | ||
|
|
7ec7d077f2 | ||
|
|
5c6f346782 | ||
|
|
51e87e8a46 | ||
|
|
6926b424a6 | ||
|
|
122405bb79 | ||
|
|
f51acae279 | ||
|
|
02beadf6c1 | ||
|
|
c542bf7d24 | ||
|
|
4d19fd28b8 | ||
|
|
34bf3c28c6 | ||
|
|
ca185b19ad | ||
|
|
a2960b3fca | ||
|
|
7d3a3547e3 | ||
|
|
993403d033 | ||
|
|
64b3c38ac6 | ||
|
|
42176a69d1 | ||
|
|
bbb49d84d7 | ||
|
|
79a4e690a4 | ||
|
|
75f4dbb1d9 | ||
|
|
fd95cd4b28 | ||
|
|
e0815b5b43 | ||
|
|
f584d820f6 | ||
|
|
d373dcb4b1 | ||
|
|
0c777d48e6 | ||
|
|
8a0a74c79f | ||
|
|
4060e4c8e1 | ||
|
|
1f8b8b71b1 | ||
|
|
ae45f94fc9 | ||
|
|
e7b2e2706c | ||
|
|
cf8d7da002 | ||
|
|
bbf2784396 | ||
|
|
7a361d0dad | ||
|
|
ce9db6e3cc | ||
|
|
0742497860 | ||
|
|
02cbb28183 | ||
|
|
aca3960858 | ||
|
|
daf2acebc9 | ||
|
|
f8aebaebbc | ||
|
|
9dcf3f94ed | ||
|
|
ccdf3afc6a | ||
|
|
e764a06a04 | ||
|
|
0c9afd4989 | ||
|
|
127a425837 | ||
|
|
eedb4b5ce0 | ||
|
|
65456ae709 | ||
|
|
ff31c50883 | ||
|
|
650346ec75 | ||
|
|
3a553e7fb4 | ||
|
|
cc7b0dd9a1 | ||
|
|
d57fdfe4ee | ||
|
|
4c70822b8f | ||
|
|
ef0071b1bd | ||
|
|
9e2bb67fe4 | ||
|
|
30ed1cd5ad | ||
|
|
3e2c0db497 | ||
|
|
38d906cb98 | ||
|
|
084b3535b3 | ||
|
|
e49db47d7d | ||
|
|
d87508ce4f | ||
|
|
4fd1c76422 | ||
|
|
c262d4a4b6 | ||
|
|
c47cda1f40 | ||
|
|
bc75df8087 | ||
|
|
ea58c97b57 | ||
|
|
14e3abc89f | ||
|
|
ac620b3686 | ||
|
|
bd64b9de5e | ||
|
|
196f1d69d3 | ||
|
|
2173c6021d | ||
|
|
ab56912e49 | ||
|
|
bf0dc9c8c0 | ||
|
|
03fc843ad8 | ||
|
|
652fd97a6d | ||
|
|
b79eb3e9fa | ||
|
|
c0de8d54ba | ||
|
|
ce92716fca | ||
|
|
453b679c80 | ||
|
|
ffc68e38d9 | ||
|
|
080e2f8916 | ||
|
|
65d2272c9b | ||
|
|
db6bffdae0 | ||
|
|
c6a547a379 | ||
|
|
17c28f93c1 | ||
|
|
da65b34feb | ||
|
|
d53b244990 | ||
|
|
5865842962 | ||
|
|
9525caa7e8 | ||
|
|
483d854518 | ||
|
|
4e96962446 | ||
|
|
67e99574d4 | ||
|
|
ca0dc1a147 | ||
|
|
45d3576576 | ||
|
|
8ff668596c | ||
|
|
1c23227c79 | ||
|
|
39fcb104e2 | ||
|
|
d8ddd5b9f5 | ||
|
|
a514e1f0ac | ||
|
|
d0dd053834 | ||
|
|
73fcfe418d | ||
|
|
e36928faac | ||
|
|
7d9da4e99a | ||
|
|
0f2695d091 | ||
|
|
b96cd8c43a | ||
|
|
76a64e85dd | ||
|
|
d9ef30cf14 | ||
|
|
1a3ae77e39 | ||
|
|
d483d33314 | ||
|
|
3c9fe3a43b | ||
|
|
81fac8a81a | ||
|
|
b3cf0a37d2 | ||
|
|
4f83ca25f1 | ||
|
|
a275f8dfc4 | ||
|
|
2df7f7b29d | ||
|
|
8ed414a1f5 | ||
|
|
d708f399f7 | ||
|
|
dc3148e25a | ||
|
|
ee687592a7 | ||
|
|
5e0aeb4cb4 | ||
|
|
620c7ba7d1 | ||
|
|
4a9ed46a7b | ||
|
|
969075a5ae | ||
|
|
440a6dc232 | ||
|
|
3234504360 | ||
|
|
7ebb758a6a | ||
|
|
ffc7666884 | ||
|
|
da3a90f659 | ||
|
|
0f88b8feae | ||
|
|
1624990be3 | ||
|
|
25900bae57 | ||
|
|
8343ab6b0e | ||
|
|
38a7da6eac | ||
|
|
f1abec1d1a | ||
|
|
59f7ca7c30 | ||
|
|
9aece938b6 | ||
|
|
505733a2df | ||
|
|
23a56e6afe | ||
|
|
28bb883273 | ||
|
|
149c6e2640 | ||
|
|
5bd572a2b8 | ||
|
|
5262c77700 | ||
|
|
a27a08f661 | ||
|
|
2a14d0c3f8 | ||
|
|
f32b6d8a95 | ||
|
|
0aaf055d11 | ||
|
|
c53f2b4206 | ||
|
|
0b06ca52dc | ||
|
|
7b46a717d8 | ||
|
|
ce908de1c1 | ||
|
|
fbd9882765 | ||
|
|
1d96012a6f | ||
|
|
a6087d4e1a | ||
|
|
fdb7a57451 | ||
|
|
b2855ef3b1 | ||
|
|
98ea5e6469 | ||
|
|
6b20b595a4 | ||
|
|
804b9baabc | ||
|
|
5443426940 | ||
|
|
94ee7d65ee | ||
|
|
f61aa3a0b5 | ||
|
|
c797619396 | ||
|
|
9029a8abec | ||
|
|
5563d70290 | ||
|
|
23c1680f56 | ||
|
|
f518b40918 | ||
|
|
521a327dd9 | ||
|
|
8a9224a9a6 | ||
|
|
cfac240042 | ||
|
|
c5233bcb58 | ||
|
|
a5e5261093 | ||
|
|
92c7b8e475 | ||
|
|
62eca3b507 | ||
|
|
b8df278931 | ||
|
|
d3d8defb48 | ||
|
|
bf6a7455d7 | ||
|
|
89a47488e9 | ||
|
|
b12d6012b5 | ||
|
|
2decddc0b5 | ||
|
|
fd01c495ad | ||
|
|
eb611beff8 | ||
|
|
4a79de6337 | ||
|
|
7b1ad60b94 | ||
|
|
b5ca65f5fd | ||
|
|
5f39e722a5 | ||
|
|
74a1af5baf | ||
|
|
ccaebab82e | ||
|
|
aa2b32f913 | ||
|
|
b0068b501e | ||
|
|
3277597377 | ||
|
|
da8c86f159 | ||
|
|
e05caba0aa | ||
|
|
9d9d1ed901 | ||
|
|
155d68254c | ||
|
|
0fe5665808 | ||
|
|
97cb277199 | ||
|
|
d73ba22c26 | ||
|
|
64de9b21ed | ||
|
|
1104e225f9 | ||
|
|
21c9f8ffd4 | ||
|
|
10315f744e | ||
|
|
b52156ee5d | ||
|
|
a0ab0427b9 | ||
|
|
c620bfebef | ||
|
|
f073a5af73 | ||
|
|
0d9a325c96 | ||
|
|
31419303cb | ||
|
|
0077ef7e41 | ||
|
|
546424f3cd | ||
|
|
8393e124af | ||
|
|
0f72193fcc | ||
|
|
5da0428c7f | ||
|
|
e059bb0fe8 | ||
|
|
6e6f19aa43 | ||
|
|
9bbb94cf6d | ||
|
|
d3ac6c95f2 | ||
|
|
3a2f7f39b1 | ||
|
|
07a41088de | ||
|
|
21256d2412 | ||
|
|
a045126dad | ||
|
|
6c514a3242 | ||
|
|
dc1f391a83 | ||
|
|
93159c0ce9 | ||
|
|
5bbb84086c | ||
|
|
e9cebbf19d | ||
|
|
9125fe0fa7 | ||
|
|
80a84d2df0 | ||
|
|
d6bf36f65f | ||
|
|
bcd9192749 | ||
|
|
2cca444170 | ||
|
|
5d2f4a740b | ||
|
|
f183f9862b | ||
|
|
31c9da911c | ||
|
|
0191984c9e | ||
|
|
45f7a7f89f | ||
|
|
30f9b3fad9 | ||
|
|
eb164a5d84 | ||
|
|
4c5d7fb8bc | ||
|
|
fba48d2b5a | ||
|
|
d9a26ac7e8 | ||
|
|
a4a02f8f26 | ||
|
|
5373e38e10 | ||
|
|
9b296d7990 | ||
|
|
ab58a72ccf | ||
|
|
87a1286dfa | ||
|
|
7d7fc6d9d6 | ||
|
|
872b935cef | ||
|
|
3da943f4bc | ||
|
|
e7e9738f10 | ||
|
|
5bffa186b7 | ||
|
|
b22393988e | ||
|
|
b36d10e1a9 | ||
|
|
6702ed3e8c | ||
|
|
9041a9e6ac | ||
|
|
6db645cab6 | ||
|
|
53453e5767 | ||
|
|
a8af95df1d | ||
|
|
01f5a03bb3 | ||
|
|
3a69de934a | ||
|
|
e9249b97a8 | ||
|
|
95c5640969 | ||
|
|
b9b7bfaa2d | ||
|
|
92f3b5de84 | ||
|
|
00b9562d8b | ||
|
|
9e119625ae | ||
|
|
e784df7e3c | ||
|
|
bd5c1e12e3 | ||
|
|
f1d057d593 | ||
|
|
f6c6d9d3e4 | ||
|
|
4bba6ed207 | ||
|
|
5065fd21cf | ||
|
|
bcf5a63230 | ||
|
|
65314e3431 | ||
|
|
b235c48df0 | ||
|
|
93f5620304 | ||
|
|
731fe1119c | ||
|
|
ef7ac656f4 | ||
|
|
a0fbe9244f | ||
|
|
d035ea07d0 | ||
|
|
26cc26baf1 | ||
|
|
ddfdc07803 | ||
|
|
b426945e65 | ||
|
|
25fba78bcb | ||
|
|
0e8de267b7 | ||
|
|
f970c1ceba | ||
|
|
1b67618d3c | ||
|
|
8a37a04db6 | ||
|
|
e58d3285f4 | ||
|
|
0486855fed | ||
|
|
826e3630f4 | ||
|
|
db27e4e4ff | ||
|
|
198f6aa08c | ||
|
|
62c7089644 | ||
|
|
e2e9f71ae7 | ||
|
|
dbd33ad168 | ||
|
|
7e2d046e91 | ||
|
|
870e8ba3fa | ||
|
|
59b8a9fb06 | ||
|
|
48114cea1c | ||
|
|
a4239124d4 | ||
|
|
eb6fd2ada2 | ||
|
|
95803f09cd | ||
|
|
1e2be66646 | ||
|
|
1a97128775 | ||
|
|
5af62b9ed8 | ||
|
|
798e3c88aa | ||
|
|
28cd83e14c | ||
|
|
03b6f6862e | ||
|
|
c15a7890ce | ||
|
|
250d22b0cb | ||
|
|
7cd497bf48 | ||
|
|
0cc00a2d7d | ||
|
|
3f778c3a06 | ||
|
|
2761fabad1 | ||
|
|
0cd66be68c | ||
|
|
c29b4eabe8 | ||
|
|
d69dd909bc | ||
|
|
04fb75e4f1 | ||
|
|
145a8ef321 | ||
|
|
45b4158fbd | ||
|
|
933050f39a | ||
|
|
a29811e60e | ||
|
|
f4f2ba3f76 | ||
|
|
ada3b0c61f | ||
|
|
2ddba63b3e | ||
|
|
c369a8a8fd | ||
|
|
73d01a5dbb | ||
|
|
8def4b0202 | ||
|
|
09e84fe557 | ||
|
|
57af2900d6 | ||
|
|
c478eae748 | ||
|
|
caecdc1151 | ||
|
|
a3f85258e1 | ||
|
|
d3e5487008 | ||
|
|
decf81ee5d | ||
|
|
c557dee176 | ||
|
|
aa8c681b15 | ||
|
|
e7d1a6ecc1 | ||
|
|
b3a1d08946 | ||
|
|
c1de17eb54 | ||
|
|
925e165981 | ||
|
|
c39cef083b | ||
|
|
c7cb4c4af9 | ||
|
|
04fa16be53 | ||
|
|
53fca33a3b | ||
|
|
f307165454 | ||
|
|
69ea4c48ae | ||
|
|
ac2e805b22 | ||
|
|
d11a112920 | ||
|
|
0de5b2f6fa | ||
|
|
c58dedb458 | ||
|
|
c2128c3e82 | ||
|
|
7b705ae172 | ||
|
|
3d12f13318 | ||
|
|
a2edd51b13 | ||
|
|
a2b81fa548 | ||
|
|
666803b277 | ||
|
|
d76b3b7c40 | ||
|
|
0afd3c56c9 | ||
|
|
605eaa0dbe | ||
|
|
2e9c416450 | ||
|
|
4d0b821825 | ||
|
|
2b5fc26ee6 | ||
|
|
f8ca33c3fb | ||
|
|
fa5277dd98 | ||
|
|
5cd24817c9 | ||
|
|
1fa8c3ebcf | ||
|
|
4659e0ec0f | ||
|
|
fea2b1091a | ||
|
|
f4782d9cbb | ||
|
|
60b18093f8 | ||
|
|
58764e9840 | ||
|
|
5b1af7ead8 | ||
|
|
a9e700649e | ||
|
|
0244587c0a | ||
|
|
2e3cc1d434 | ||
|
|
da2832c302 | ||
|
|
bac1626f65 | ||
|
|
12d25f3872 | ||
|
|
5aaeebb791 | ||
|
|
6580600e3a | ||
|
|
5bb27497c5 | ||
|
|
d4cbcad0a0 | ||
|
|
8c9d48347c | ||
|
|
4df08f4096 | ||
|
|
c0f2066ae3 | ||
|
|
af6022eba8 | ||
|
|
93d38a487e | ||
|
|
4e1cc83e73 | ||
|
|
7908a5eaf0 | ||
|
|
1112627984 | ||
|
|
a5bb1f4425 | ||
|
|
ea05ce215a | ||
|
|
5529775a36 | ||
|
|
e590112a6a | ||
|
|
95b69c731b | ||
|
|
38d400c11e | ||
|
|
0ce322f784 | ||
|
|
f40e11ed06 | ||
|
|
2a1b904154 | ||
|
|
936133fa31 | ||
|
|
fd6c469d7f | ||
|
|
1225d5cab1 | ||
|
|
40476ed855 | ||
|
|
5f14197c94 | ||
|
|
50b963e8f3 | ||
|
|
aa7ce81f6e | ||
|
|
4893b3f744 | ||
|
|
86009afa16 | ||
|
|
558ef7258f | ||
|
|
ec335d3a61 | ||
|
|
989e6c14bc | ||
|
|
e3197d28cc | ||
|
|
bc53de2590 | ||
|
|
656c4c4341 | ||
|
|
9efe0b7af8 | ||
|
|
0b630c106a | ||
|
|
bbf93723ac | ||
|
|
3cd3740515 | ||
|
|
82c214ba5e | ||
|
|
191b588dff | ||
|
|
b10f326a72 | ||
|
|
7c239b1429 | ||
|
|
ef52c07615 | ||
|
|
1bf1aff46e | ||
|
|
a2a0b4faa3 | ||
|
|
d58829ab3b | ||
|
|
2b709bcf70 | ||
|
|
beb3b9f226 | ||
|
|
2cbe2659ad | ||
|
|
90ae4b521b | ||
|
|
dfc557cbad | ||
|
|
f691beea3b | ||
|
|
100b135223 | ||
|
|
fa588eea44 | ||
|
|
cea00d3aa5 | ||
|
|
e8d87e9db1 | ||
|
|
ece4dea4fd | ||
|
|
e70655ce44 | ||
|
|
cbe5872688 | ||
|
|
48d8b87c9a | ||
|
|
3989fc7e1c | ||
|
|
ac1346d264 | ||
|
|
90cdced290 | ||
|
|
98b21c864e | ||
|
|
fc802d496d | ||
|
|
084885f9aa | ||
|
|
23928f5e4a | ||
|
|
5b2782e5b7 | ||
|
|
0fcccae96e | ||
|
|
61305d6032 | ||
|
|
aee3dac97c | ||
|
|
dd6a6e5041 | ||
|
|
ab4c818d75 | ||
|
|
38a426d27d | ||
|
|
79a094df21 | ||
|
|
aaf1a95728 | ||
|
|
564b73c513 | ||
|
|
61c9d71fa1 | ||
|
|
1fe0821faa | ||
|
|
5ca1a2d01f | ||
|
|
4eb7f7cbce | ||
|
|
75853b49e6 | ||
|
|
0b461178ad | ||
|
|
445fa5fec6 | ||
|
|
ac4fe980fa | ||
|
|
4089958aeb | ||
|
|
689fa63dc8 | ||
|
|
206a22a875 | ||
|
|
465e91a8d3 | ||
|
|
3251db24cf | ||
|
|
3448ee617b | ||
|
|
664e176cb0 | ||
|
|
bd51bc81b8 | ||
|
|
47d6b272b8 | ||
|
|
7283fb9ab7 | ||
|
|
3fc99dfd31 | ||
|
|
4a9aec73e5 | ||
|
|
f9919eee24 | ||
|
|
1d144fc476 | ||
|
|
8781823ff8 | ||
|
|
ab1276f90d | ||
|
|
5dba741f7a | ||
|
|
6d469936e2 | ||
|
|
0ef78a9a4e | ||
|
|
329f28e34b | ||
|
|
19fac219f3 | ||
|
|
63614309dd | ||
|
|
b73691f933 | ||
|
|
1650537bf6 | ||
|
|
2063e86f23 | ||
|
|
74f4296b0f | ||
|
|
b79faa11ef | ||
|
|
b340ce492d | ||
|
|
fd4932189d | ||
|
|
f903e2e110 | ||
|
|
b00ea1c957 | ||
|
|
523f6bc471 | ||
|
|
b7596f26f2 | ||
|
|
fda76d238d | ||
|
|
3b8fd05b7f | ||
|
|
3545ffa17d | ||
|
|
2f8ebc37ad | ||
|
|
627eb92a58 | ||
|
|
8df15d2726 | ||
|
|
59329d99c2 | ||
|
|
d290c6573f | ||
|
|
7bc63c35e0 | ||
|
|
e97cd0d6e2 | ||
|
|
c86232158c | ||
|
|
90f5941078 | ||
|
|
ba1a04bfef | ||
|
|
7a8876bba7 | ||
|
|
8daf4bcd9b | ||
|
|
44062887a6 | ||
|
|
5ff6e11472 | ||
|
|
2fbb6b7230 | ||
|
|
83eb31b093 | ||
|
|
094f896dbd | ||
|
|
9965d14d88 | ||
|
|
4b0a347a56 | ||
|
|
fb9550dc7c | ||
|
|
34ebf55a63 | ||
|
|
fa5877d00f | ||
|
|
3352d872b1 | ||
|
|
cfb86a37f3 | ||
|
|
883b14f2b7 | ||
|
|
b3caefeed3 | ||
|
|
e915f1ed77 | ||
|
|
e6802571c6 | ||
|
|
8338ca7626 | ||
|
|
5cd6c6a192 | ||
|
|
81333f3e52 | ||
|
|
4c2e4460bb | ||
|
|
76db9b75c3 | ||
|
|
9717fc0f2b | ||
|
|
6052f9e4d3 | ||
|
|
9511d7fa8f | ||
|
|
0da03f2489 | ||
|
|
505010fe51 | ||
|
|
96bf3d2d73 | ||
|
|
dd862a8b54 | ||
|
|
c994b0584d | ||
|
|
6009a8ed48 | ||
|
|
5304594287 | ||
|
|
63d5c26b58 | ||
|
|
8db6d05653 | ||
|
|
c9428ec1c1 | ||
|
|
b6f99029dd | ||
|
|
9221b2f66d | ||
|
|
3aa773e2a4 | ||
|
|
76830b0644 | ||
|
|
404be42674 | ||
|
|
3988b35060 | ||
|
|
4092d12132 | ||
|
|
c6250585b8 | ||
|
|
c90157bdc0 | ||
|
|
5f5e325987 | ||
|
|
c24656582d | ||
|
|
6135089740 | ||
|
|
9b359c8a21 | ||
|
|
1b448cefe8 | ||
|
|
27f6fd58d0 | ||
|
|
03f92aa4e2 | ||
|
|
647045487e | ||
|
|
4e37a655f3 | ||
|
|
7d4e2ccc01 | ||
|
|
8e504dda18 | ||
|
|
28a3bcc3db | ||
|
|
4986bd37b3 | ||
|
|
77808fade3 | ||
|
|
8297da7659 | ||
|
|
f6c88f7391 | ||
|
|
1ad788fe88 | ||
|
|
cf2f727441 | ||
|
|
eccf3f5a1c | ||
|
|
931741d4ba | ||
|
|
9234555754 | ||
|
|
994829d390 | ||
|
|
446d248d73 | ||
|
|
59ec9ae9a9 | ||
|
|
04af4c8ecb | ||
|
|
17cd76a4d1 | ||
|
|
3d41dd63ec | ||
|
|
7d863fe55b | ||
|
|
20f53256b1 | ||
|
|
7a3745c91b | ||
|
|
6c7587ab08 | ||
|
|
2e126b09b6 | ||
|
|
d9f7c75d0f | ||
|
|
9094949e68 | ||
|
|
7c91c55083 | ||
|
|
d22b80aafa | ||
|
|
8455198aa0 | ||
|
|
5f60a36894 | ||
|
|
6b2291d140 | ||
|
|
c39dc96a47 | ||
|
|
7e3f5c55d7 | ||
|
|
42daae9497 | ||
|
|
93e5fbe660 | ||
|
|
e4830a0f5b | ||
|
|
8b23d0f1c3 | ||
|
|
107d488712 | ||
|
|
bac6ff86fc | ||
|
|
bd371b5c70 | ||
|
|
33ac7ce4c8 | ||
|
|
555c824944 | ||
|
|
2f6b79b8cd | ||
|
|
2227597ff7 | ||
|
|
354384a08e | ||
|
|
b16dbc66e0 | ||
|
|
95806c35f7 | ||
|
|
f38ab5903e | ||
|
|
91279be5ea | ||
|
|
f8f0f8100c | ||
|
|
c107ff4821 | ||
|
|
2b9c96b8f3 | ||
|
|
da281a6845 | ||
|
|
00aab4a06a | ||
|
|
3cad29367f | ||
|
|
f0983d56c8 | ||
|
|
dae678270e | ||
|
|
20ca69a61a | ||
|
|
7c1d241f98 | ||
|
|
192492c28d | ||
|
|
00656ef605 | ||
|
|
064f99db63 | ||
|
|
9f52be61b4 | ||
|
|
95969cb409 | ||
|
|
dd43fddb29 | ||
|
|
99dfc6d319 | ||
|
|
87e9241898 | ||
|
|
0ad38d26f5 | ||
|
|
e8f7ade377 | ||
|
|
1e1aee8b01 | ||
|
|
4e4a80bf07 | ||
|
|
5120c554cf | ||
|
|
957856360c | ||
|
|
3c3f5d2018 | ||
|
|
081f2fc388 | ||
|
|
eb5d8b6d91 | ||
|
|
68081252a6 | ||
|
|
7f6cc6f289 | ||
|
|
93ed77caac | ||
|
|
cfe38c91c9 | ||
|
|
cbfdd3cfac | ||
|
|
8ed99f0665 | ||
|
|
5f98dc3cf1 | ||
|
|
3807c39bcd | ||
|
|
4adf11f0eb | ||
|
|
444bc10c2a | ||
|
|
fe1ede7f5d | ||
|
|
2fd4b574c4 | ||
|
|
ae63a9992d | ||
|
|
765f054e02 | ||
|
|
8ffa3c7736 | ||
|
|
4b1655566a | ||
|
|
48bf0c6576 | ||
|
|
12e98d3825 | ||
|
|
fbec48de26 | ||
|
|
3ff70f1049 | ||
|
|
6a35683078 | ||
|
|
7623e02f22 | ||
|
|
ff9a89de8d | ||
|
|
244018ddec | ||
|
|
3da9f7be18 | ||
|
|
10e5792459 | ||
|
|
ba480f9240 | ||
|
|
5ad53fe043 | ||
|
|
5d37a2a958 | ||
|
|
f5adc67bf3 | ||
|
|
bc5668c328 | ||
|
|
dae79e6881 | ||
|
|
1845ee2d95 | ||
|
|
944d73bad6 | ||
|
|
250b08ed78 | ||
|
|
ddbf2ac634 | ||
|
|
3ca57f4a5f | ||
|
|
a548b52061 | ||
|
|
65c195b90a | ||
|
|
c12965bea4 | ||
|
|
1035dfb264 | ||
|
|
3feca60b07 | ||
|
|
49596a7797 | ||
|
|
eb6295935f | ||
|
|
3a0e3d8426 | ||
|
|
d2b68cced4 | ||
|
|
389511ca3a | ||
|
|
a01198fd90 | ||
|
|
2dbcd8a014 | ||
|
|
4af6b905b9 | ||
|
|
a2ca0fc5ef | ||
|
|
174bdd15b7 | ||
|
|
abaf52d4ec | ||
|
|
6e32442172 | ||
|
|
e04cf9cba9 | ||
|
|
d8fbbeb585 | ||
|
|
5cb2e3756a | ||
|
|
1ae2425549 | ||
|
|
82d079d86c | ||
|
|
48b565393f | ||
|
|
0997277c7c | ||
|
|
cd4a083788 | ||
|
|
2ac37bb5f2 | ||
|
|
e57f1dc31c | ||
|
|
0720293e22 | ||
|
|
61dc29213d | ||
|
|
820b214bb7 | ||
|
|
4db726c6b8 | ||
|
|
358f5c012a | ||
|
|
d1ea797420 | ||
|
|
720ef0c5d9 | ||
|
|
62bf8afca9 | ||
|
|
85edcf5588 | ||
|
|
29def6ac5b | ||
|
|
333a6d550e | ||
|
|
655690dc68 | ||
|
|
a52de11944 | ||
|
|
cfc1a05064 | ||
|
|
bdf262379f | ||
|
|
98944d3c0a | ||
|
|
643c9bcf73 | ||
|
|
0fe6f58200 | ||
|
|
edc216ffa0 | ||
|
|
1b5869c510 | ||
|
|
d6fdae0a80 | ||
|
|
52cc561a4c | ||
|
|
81819b43b5 | ||
|
|
015fbd88bf | ||
|
|
efaec4f28e | ||
|
|
73e2aeed93 | ||
|
|
d4a5bf4581 | ||
|
|
00679d3b78 | ||
|
|
df1d09749d | ||
|
|
ffe307aaa4 | ||
|
|
c81ea394a6 | ||
|
|
34e265745f | ||
|
|
e6c5af4d79 | ||
|
|
da3548f3c9 | ||
|
|
fffb0665cd | ||
|
|
69e4b68a07 | ||
|
|
48e8458483 | ||
|
|
7a18e6289a | ||
|
|
686b8976ff | ||
|
|
ab6a8d9d31 | ||
|
|
88784633bc | ||
|
|
0422413bbb | ||
|
|
3233570240 | ||
|
|
f3bbd6284a | ||
|
|
1337ed4d1e | ||
|
|
f01f6c68c8 | ||
|
|
4bbd426645 | ||
|
|
a3e1bdecc2 | ||
|
|
6cfb3b4039 | ||
|
|
a510183a53 | ||
|
|
96034b6efe | ||
|
|
b6aac3b869 | ||
|
|
20522a26c6 | ||
|
|
f0294304be | ||
|
|
148188345e | ||
|
|
d399fb0434 | ||
|
|
3baee8fd74 | ||
|
|
3206819c48 | ||
|
|
418fe399ad | ||
|
|
be073fe1c5 | ||
|
|
c729e24b83 | ||
|
|
3e74766852 | ||
|
|
88061f4328 | ||
|
|
ecd00b1818 | ||
|
|
6f006b90a0 | ||
|
|
e49d9946a3 | ||
|
|
b37ce12303 | ||
|
|
7e0673fb35 | ||
|
|
00f12f2da7 | ||
|
|
4e47c2409b | ||
|
|
2a2ba583af | ||
|
|
b0bd7ab4a2 | ||
|
|
fa04706178 | ||
|
|
a5646f7531 | ||
|
|
929ebe9e4f | ||
|
|
5f0dff3012 | ||
|
|
97dfe652db | ||
|
|
b40699ea65 | ||
|
|
1b56b20cd6 | ||
|
|
38ec1ab42b | ||
|
|
4cc15fa4a1 | ||
|
|
a9cfcedc65 | ||
|
|
5abffa8e29 | ||
|
|
3bb111a8cd | ||
|
|
f0135f7f61 | ||
|
|
ad1eeb8b08 | ||
|
|
b7ed1be7b3 | ||
|
|
d67bd2534a | ||
|
|
2154d31e62 | ||
|
|
a663899c7d | ||
|
|
ab725a7f30 | ||
|
|
95165d5638 | ||
|
|
32f28b41c1 | ||
|
|
71c6b8ca36 | ||
|
|
11fad92fae | ||
|
|
6c1d0f0a0a | ||
|
|
80d41e0245 | ||
|
|
73d72aea18 | ||
|
|
f0a37ce4ba | ||
|
|
f581919cac | ||
|
|
7603522cb4 | ||
|
|
d6732ad36a | ||
|
|
0fe764272f | ||
|
|
e637995d2c | ||
|
|
c275c79fe5 | ||
|
|
bb864ca20b | ||
|
|
3d88790f03 | ||
|
|
d3b616a590 | ||
|
|
2d10f9a22a | ||
|
|
b3982cb1a4 | ||
|
|
453f715014 | ||
|
|
32784c7879 | ||
|
|
8f5c5db523 | ||
|
|
b81e4dd719 | ||
|
|
fd902427ef | ||
|
|
7ca870c416 | ||
|
|
21268ea8c7 | ||
|
|
5c52291ec4 | ||
|
|
bf25033136 | ||
|
|
c31cf77a12 | ||
|
|
bc10b807b1 | ||
|
|
113f8fe342 | ||
|
|
0ed70a12f1 | ||
|
|
847393a71d | ||
|
|
6473d053aa | ||
|
|
f6ef16f4fb | ||
|
|
d688f4fd49 | ||
|
|
e4c17d5277 | ||
|
|
2df4978081 | ||
|
|
d43251da46 | ||
|
|
859476acf9 | ||
|
|
2a358de827 | ||
|
|
cbafc60d5f | ||
|
|
f03f865af9 | ||
|
|
0d7dfa721f | ||
|
|
aafe295d5b | ||
|
|
ee777f235b | ||
|
|
8e60ed0217 | ||
|
|
f0f77bee45 | ||
|
|
f8b0565fd3 | ||
|
|
a7cb863de4 | ||
|
|
3bfa9f89ab | ||
|
|
eaaf94a351 | ||
|
|
5ccce74b43 | ||
|
|
d3bc97daaf | ||
|
|
9270cf4827 | ||
|
|
1a5b4b75e1 | ||
|
|
a5582a4f76 | ||
|
|
c3b9159216 | ||
|
|
fc987f1913 | ||
|
|
ce562d9348 | ||
|
|
e15cd2be08 | ||
|
|
0ead99edaf | ||
|
|
7f7ead9766 | ||
|
|
b75cb35726 | ||
|
|
a4d62997d3 | ||
|
|
2f135b9efb | ||
|
|
a33e5c0a18 | ||
|
|
5373f31ca3 | ||
|
|
89c8b2f4f9 | ||
|
|
2ad90f22d7 | ||
|
|
75a6289408 | ||
|
|
3f0bb3c930 | ||
|
|
8646ec13f6 | ||
|
|
ac64834ea6 | ||
|
|
fc6bd6b640 | ||
|
|
3a1a18e780 | ||
|
|
debcb547ea | ||
|
|
2823e46675 | ||
|
|
42c6e1bc88 | ||
|
|
fb90c4b9d2 | ||
|
|
e1679b2a6e | ||
|
|
cbe2d591bd | ||
|
|
53c6083a20 | ||
|
|
4924228dd5 | ||
|
|
52b0100473 | ||
|
|
692c1f9823 | ||
|
|
283a78420c | ||
|
|
8ba9cc0f03 | ||
|
|
fb653702f0 | ||
|
|
ff664cf8ec | ||
|
|
61b0f3a590 | ||
|
|
517e2896ad | ||
|
|
25f3e82011 | ||
|
|
c7bcc47d11 | ||
|
|
0d0461201d | ||
|
|
ee4c13520c | ||
|
|
84f35d3af0 | ||
|
|
d850ce5788 | ||
|
|
aed76b26cc | ||
|
|
b0bb203aef | ||
|
|
06a353b6bc | ||
|
|
9ae3c01cf0 | ||
|
|
9a45ce9b9b | ||
|
|
d032999421 | ||
|
|
f1b1412f1b | ||
|
|
ea3919785d | ||
|
|
4523c667ca | ||
|
|
55f2f22d3e | ||
|
|
cc8e6844c0 | ||
|
|
a536089b07 | ||
|
|
5d4212664d | ||
|
|
8c7797066d | ||
|
|
bf07e0f409 | ||
|
|
3e69da17a8 | ||
|
|
00ceb5fffe | ||
|
|
fb65e590ca | ||
|
|
32fa606e82 | ||
|
|
b61da7548e | ||
|
|
b9654b8b02 | ||
|
|
c3e15ebd51 | ||
|
|
99644ccca8 | ||
|
|
7af5e18c3c | ||
|
|
3934ad7f6a | ||
|
|
3d03cc4bc2 | ||
|
|
b4b8587904 | ||
|
|
f93c2f282f | ||
|
|
43b5d1f40e | ||
|
|
70c76b9cdc | ||
|
|
fe73badfd0 | ||
|
|
f7e4b68db4 | ||
|
|
0fecaf751c | ||
|
|
d2025b36e1 | ||
|
|
323d05b90d | ||
|
|
45129616ec | ||
|
|
380fa9092e | ||
|
|
dbc6abe094 | ||
|
|
f65ef6d39a | ||
|
|
e69f753722 | ||
|
|
59e49400fa | ||
|
|
eddec6d603 | ||
|
|
c05ce28cba | ||
|
|
3523655080 | ||
|
|
23db610f65 | ||
|
|
156b3873fb | ||
|
|
a34654262c | ||
|
|
b320a1ffc5 | ||
|
|
a477a49a26 | ||
|
|
bd41eb7547 | ||
|
|
40c457994d | ||
|
|
a9eab878c4 | ||
|
|
cbe887d64d | ||
|
|
c711a0d870 | ||
|
|
7bdf57b5de | ||
|
|
a6e6e44e55 | ||
|
|
79aee414b6 | ||
|
|
c0afa9cf2f | ||
|
|
419021fc00 | ||
|
|
912f435b61 | ||
|
|
48f1c5bbb4 | ||
|
|
e4935d64a8 | ||
|
|
bb7d918fa9 | ||
|
|
3cb60f8a87 | ||
|
|
695df35cf6 | ||
|
|
e1719ffa2e | ||
|
|
0335c8926e | ||
|
|
619c8b94f1 | ||
|
|
ae56d31289 | ||
|
|
ea78a50a2f | ||
|
|
b13e614093 | ||
|
|
cb3386c2dc | ||
|
|
7710d0c3eb | ||
|
|
1dece012e7 | ||
|
|
090df601be | ||
|
|
31e47d03f7 | ||
|
|
bec7506023 | ||
|
|
2e712d1650 | ||
|
|
ab1ce8f1df | ||
|
|
0053ae45a0 | ||
|
|
e8bd2db9db | ||
|
|
442a839ad7 | ||
|
|
cc6a2b0391 | ||
|
|
0a8c91ea27 | ||
|
|
9c7137f8a9 | ||
|
|
c76d6ea5bb | ||
|
|
63d624c17f | ||
|
|
e28af780b8 | ||
|
|
bdce39527e | ||
|
|
7c543ef481 | ||
|
|
93f7845200 | ||
|
|
bdd9abedde | ||
|
|
a1ff7485de | ||
|
|
d4cc36cb28 | ||
|
|
09c04473e9 | ||
|
|
222b32bc6f | ||
|
|
a009e4fa43 | ||
|
|
ce04eda93b | ||
|
|
5bb0cc4268 | ||
|
|
441c431362 | ||
|
|
fa55e30ad1 | ||
|
|
f9eed30e9d | ||
|
|
94c3496b1e | ||
|
|
0294852719 | ||
|
|
e1557a79bd | ||
|
|
6c413c298f | ||
|
|
b72133ac05 | ||
|
|
a146f060eb | ||
|
|
cf23344e52 | ||
|
|
1d6b85fee5 | ||
|
|
7dab4451cc | ||
|
|
e0a82be141 | ||
|
|
36f3d061e7 | ||
|
|
5f335470f4 | ||
|
|
b0d18750ed | ||
|
|
e0f4c66ec4 | ||
|
|
3091ddb45f | ||
|
|
671d3e481d | ||
|
|
b3a143706d | ||
|
|
e7048e4170 | ||
|
|
7a6d119048 | ||
|
|
f3c893e2cd | ||
|
|
aac6c20c8f | ||
|
|
0f7a9b8355 | ||
|
|
5a4eb1e4da | ||
|
|
138893e6f2 | ||
|
|
4406607dca | ||
|
|
ed20b64b07 | ||
|
|
89298ff123 | ||
|
|
b4b499aacd | ||
|
|
423f536a18 | ||
|
|
af2a85078f | ||
|
|
020efc01b4 | ||
|
|
6c37b976df | ||
|
|
9c7d3344bd | ||
|
|
aa9483fb32 | ||
|
|
41e7d82106 | ||
|
|
c5bba9e35c | ||
|
|
5f3068d39c | ||
|
|
04eb7a1b1f | ||
|
|
3af552873f | ||
|
|
bdc942211f | ||
|
|
3a02e0dc17 | ||
|
|
d08c7a5eb2 | ||
|
|
71766e8f0c | ||
|
|
891264bca3 | ||
|
|
5caabb169f | ||
|
|
87ae927539 | ||
|
|
2ec0caa3bb | ||
|
|
5e1b4bbc08 | ||
|
|
bae5a79322 | ||
|
|
1df09d273c | ||
|
|
7198ad2fba | ||
|
|
56be1182df | ||
|
|
1af4b556f7 | ||
|
|
966c10ed34 | ||
|
|
33b20043b8 | ||
|
|
f71f0abcb5 | ||
|
|
cd49b89ede | ||
|
|
f40335e800 | ||
|
|
4061b719fe | ||
|
|
16f6c696d9 | ||
|
|
13e588ec3b | ||
|
|
40a0a2e392 | ||
|
|
4ca349c84f | ||
|
|
bcb814002c | ||
|
|
21e8f8ac0b | ||
|
|
00ead5d666 | ||
|
|
d71dbc1b57 | ||
|
|
d013fdf977 | ||
|
|
d8f12a0220 | ||
|
|
e460eb1a29 | ||
|
|
e940e1a16f | ||
|
|
1c1e9b7687 | ||
|
|
a2f76b2c4e | ||
|
|
c2053dd23b | ||
|
|
cc2e1fe5bb | ||
|
|
b9966def4e | ||
|
|
471ea5ac1b | ||
|
|
756ccb779c | ||
|
|
48b7cd0522 | ||
|
|
c6a799c425 | ||
|
|
77826515fb | ||
|
|
dd704f41f3 | ||
|
|
d44ef2350b | ||
|
|
f52a75644d | ||
|
|
c0b4997051 | ||
|
|
cb5043777a | ||
|
|
7f357c5e06 | ||
|
|
ae4e3ecac1 | ||
|
|
7454b53f05 | ||
|
|
7bbcf469b1 | ||
|
|
ba41a3defe | ||
|
|
26437fde9b | ||
|
|
f47cba8b11 | ||
|
|
379d50b456 | ||
|
|
07485ae940 | ||
|
|
9af3976990 | ||
|
|
cafc5561fe | ||
|
|
89fb66229c | ||
|
|
bd51a0b1fe | ||
|
|
c58084c51a | ||
|
|
7f6ac8455a | ||
|
|
7400d8290b | ||
|
|
a9d71ca339 | ||
|
|
f992c9a035 | ||
|
|
b8a0db71ff | ||
|
|
42c09141c4 | ||
|
|
03464271d6 | ||
|
|
27823d7192 | ||
|
|
8f4e0ecf34 | ||
|
|
0497f72daf | ||
|
|
0b030b9e9d | ||
|
|
d5e42aa060 | ||
|
|
f2018dfc2d | ||
|
|
f146ea961e | ||
|
|
0208cc9924 | ||
|
|
83e4f7d40d | ||
|
|
4eea3d4d1c | ||
|
|
50e97e91b1 | ||
|
|
edf18a8809 | ||
|
|
700bea86f6 | ||
|
|
aa0bc2d268 | ||
|
|
02bbcf6f86 | ||
|
|
0b9309d9d8 | ||
|
|
acd45da2ec | ||
|
|
5a6db85846 | ||
|
|
db769cc0ca | ||
|
|
b0f3b7bd10 | ||
|
|
cc2ddd5458 | ||
|
|
ecc722cb5f | ||
|
|
f5ce5d301c | ||
|
|
981fe9b338 | ||
|
|
2bd4ba1be0 | ||
|
|
8337a2ad73 | ||
|
|
0db1cbe704 | ||
|
|
d757c21d0f | ||
|
|
9f2dffe5ff | ||
|
|
41d8e2e425 | ||
|
|
62408bb3c4 | ||
|
|
92d1f6e814 | ||
|
|
90d84caf9e | ||
|
|
02a3d2a000 | ||
|
|
e0d4ece3b2 | ||
|
|
d3d07b2eb7 | ||
|
|
a9613c5b11 | ||
|
|
bf4f26f6fd | ||
|
|
3ed410ea73 | ||
|
|
c4b556fdb5 | ||
|
|
995cee485e | ||
|
|
7cc1688669 | ||
|
|
fd3820efef | ||
|
|
3f377aeba3 | ||
|
|
b8213ff599 | ||
|
|
e877ace351 | ||
|
|
8a0ef0f493 | ||
|
|
2af7f3ca9d | ||
|
|
7d2f5c21c9 | ||
|
|
ef14861d8e | ||
|
|
609e8c43dd | ||
|
|
c48d49e706 | ||
|
|
2b38212664 | ||
|
|
6b795e0243 | ||
|
|
758a3a573b | ||
|
|
e9a6173d05 | ||
|
|
030e54907f | ||
|
|
6a475f7399 | ||
|
|
86b4abf6b2 | ||
|
|
6ec15145e8 | ||
|
|
57c5796c48 | ||
|
|
fb230aad1e | ||
|
|
a3c987880c | ||
|
|
926d85c940 | ||
|
|
d491ec4ad9 | ||
|
|
f34453af7f | ||
|
|
ec4bb7b7e5 | ||
|
|
b30ebee2d9 | ||
|
|
1dd0eba80c | ||
|
|
281acd239f | ||
|
|
6726ad759d | ||
|
|
fffe8d17ab | ||
|
|
3e666d814f | ||
|
|
a9672c4bf8 | ||
|
|
8d61636bd2 | ||
|
|
85b55f2b92 | ||
|
|
847832af18 | ||
|
|
40bd18a356 | ||
|
|
e31c8116ca | ||
|
|
20ead953b4 | ||
|
|
77eb396fd4 | ||
|
|
8c1b19c61f | ||
|
|
3a12fda068 | ||
|
|
f4cf2dd027 | ||
|
|
fc34ab6986 | ||
|
|
44d02349a2 | ||
|
|
f81297eb63 | ||
|
|
efcb9caf8a | ||
|
|
37c1ce2394 | ||
|
|
3631d8d370 | ||
|
|
c8a3a254cd | ||
|
|
1177518a15 | ||
|
|
fe9dae3453 | ||
|
|
62e8f31f3f | ||
|
|
60bfb60bdc | ||
|
|
b8c90d9b3c | ||
|
|
b3c0d6db39 | ||
|
|
eba3d6144e | ||
|
|
918f94a52b | ||
|
|
f873e768ee | ||
|
|
de117504ea | ||
|
|
d26ef91553 | ||
|
|
bd02bf2ef7 | ||
|
|
6c9dd2cd48 | ||
|
|
92154f8c2e | ||
|
|
2510e857b0 | ||
|
|
e5be46e100 | ||
|
|
b0f22e6c8d | ||
|
|
8641b827ab | ||
|
|
3249de7cea | ||
|
|
cb4049518f | ||
|
|
a84a95c961 | ||
|
|
b6019e6867 | ||
|
|
d7579d7c3c | ||
|
|
6493fe876a | ||
|
|
8f689fd8c9 | ||
|
|
c7eb9822d6 | ||
|
|
71cb57025c | ||
|
|
4d47ebefb8 | ||
|
|
dc90a6ad07 | ||
|
|
c3cc141d53 | ||
|
|
214770c2a1 | ||
|
|
bc8034c428 | ||
|
|
8e722788c1 | ||
|
|
cf9d8aafae | ||
|
|
8aafa9d05c | ||
|
|
8838c7d7a8 | ||
|
|
93f136337b | ||
|
|
c9567f29cb | ||
|
|
0b5d8d9a1e | ||
|
|
c674416dd1 | ||
|
|
6746febb7e | ||
|
|
51568444a5 | ||
|
|
d384a6a0d8 | ||
|
|
76e7239615 | ||
|
|
2a89bca81e | ||
|
|
00302ae29c | ||
|
|
1557b859cc | ||
|
|
a92d40e016 | ||
|
|
7036b95ae5 | ||
|
|
f5d2d70430 | ||
|
|
5269c0c448 | ||
|
|
92c0885b22 | ||
|
|
12b4c90b91 | ||
|
|
1584977db1 | ||
|
|
231842c171 | ||
|
|
75f3092886 | ||
|
|
d22f343163 | ||
|
|
2a84481f03 | ||
|
|
decbfe79a8 | ||
|
|
d9c151c4d6 | ||
|
|
15d060afeb | ||
|
|
4537e24549 | ||
|
|
8dd631bcb2 | ||
|
|
5dd4a30500 | ||
|
|
b0525f6bfc | ||
|
|
1654a0c039 | ||
|
|
6bdb7be5ec | ||
|
|
36871ff63d | ||
|
|
b2b642c517 | ||
|
|
369dd20a68 | ||
|
|
89c43d62c0 | ||
|
|
58cd144b11 | ||
|
|
ae88d3a4c9 | ||
|
|
522c5b0601 | ||
|
|
1a84070cc4 | ||
|
|
7478b34302 | ||
|
|
b5e55c9820 | ||
|
|
9831bccec4 | ||
|
|
8df01583bf | ||
|
|
cb8dbb62f5 | ||
|
|
cf1d3a9eca | ||
|
|
7836cc7720 | ||
|
|
b9acd0a714 | ||
|
|
4f92cd7ed5 | ||
|
|
aecfaf27c3 | ||
|
|
bc2bd4ddf8 | ||
|
|
4bf97d5a49 | ||
|
|
4bdef31591 | ||
|
|
c0e13731eb | ||
|
|
b31d1ac0dd | ||
|
|
52e8fd474a | ||
|
|
7b276db014 | ||
|
|
062c22a249 | ||
|
|
d5a70f9bf9 | ||
|
|
0d94558f53 | ||
|
|
533bf97d22 | ||
|
|
a6aedcc66c | ||
|
|
de97cc4bfe | ||
|
|
a16eb6d24d | ||
|
|
5fbf6ce577 | ||
|
|
e41903d6bc | ||
|
|
e2fa73fa75 | ||
|
|
b3fe591f9f | ||
|
|
87ec1eab73 | ||
|
|
d88d5c118e | ||
|
|
2eb26d64a1 | ||
|
|
ca2223574f | ||
|
|
75401fee25 | ||
|
|
873e5751fc | ||
|
|
dc57125243 | ||
|
|
8581c7d83a | ||
|
|
843b9475c0 | ||
|
|
e7c5e866f2 | ||
|
|
8d842197cc | ||
|
|
f1ff259775 | ||
|
|
f78baa9e6c | ||
|
|
36d6eb427d | ||
|
|
982db57b32 | ||
|
|
5d09a38282 | ||
|
|
0383ad2c57 | ||
|
|
fa46714923 | ||
|
|
aa0a8682ef | ||
|
|
6bd286e297 | ||
|
|
d65b98f4b5 | ||
|
|
7b2607e059 | ||
|
|
58dff874ec | ||
|
|
15349c4529 | ||
|
|
3f2785447b | ||
|
|
a3aec9be50 | ||
|
|
b2fe08afd2 | ||
|
|
4bab1ffc43 | ||
|
|
94cf80b829 | ||
|
|
e7c575a8fe | ||
|
|
2070ecc640 | ||
|
|
20cd2a38fa | ||
|
|
afb32e592b | ||
|
|
922df51837 | ||
|
|
df23da8827 | ||
|
|
c58894e0c6 | ||
|
|
52ae0968ce | ||
|
|
839db58c41 | ||
|
|
dd4c8ebc6f | ||
|
|
3686446132 | ||
|
|
2d51266fa6 | ||
|
|
1865122b58 | ||
|
|
ee203e3922 | ||
|
|
d0a3f1b46f | ||
|
|
e1802ffb73 | ||
|
|
5beccdc8e8 | ||
|
|
daab00d69c | ||
|
|
13e41517ab | ||
|
|
b09b06a4f4 | ||
|
|
f58c4e190b | ||
|
|
4e9f777cd4 | ||
|
|
f81421eb9a | ||
|
|
46bfbb2a91 | ||
|
|
e03d6bf74b | ||
|
|
26b145f0e0 | ||
|
|
e0b28e73c6 | ||
|
|
3e36be0646 | ||
|
|
05054e294e | ||
|
|
52a8cb60a8 | ||
|
|
bba8558618 | ||
|
|
0e52288cb2 | ||
|
|
ab455c7515 | ||
|
|
6fca6b8811 | ||
|
|
bdf96e5905 | ||
|
|
78bf492f69 | ||
|
|
55c1297356 | ||
|
|
6d0c845d71 | ||
|
|
080345ea0b | ||
|
|
638c9479ab | ||
|
|
973723e7d3 | ||
|
|
e0dbe3049e | ||
|
|
22db76a273 | ||
|
|
f53fe6f227 | ||
|
|
615cd22e93 | ||
|
|
a05c01bb7e | ||
|
|
fc1530a166 | ||
|
|
8c73745835 | ||
|
|
c3685fcbcd | ||
|
|
bf8a170147 | ||
|
|
a9215e45d5 | ||
|
|
e7013bd828 | ||
|
|
9cfa3c15ff | ||
|
|
7b4b84cfe2 | ||
|
|
bc6b1c9fdd | ||
|
|
73bd6791f8 | ||
|
|
d3e1992150 | ||
|
|
2524d27313 | ||
|
|
b8600d2c2f | ||
|
|
d2dd2e6688 | ||
|
|
d601e59092 | ||
|
|
e27d8760e4 | ||
|
|
4a0a89925d | ||
|
|
b535de4355 | ||
|
|
06f0a08381 | ||
|
|
e9da71ccd8 | ||
|
|
f9772d2710 | ||
|
|
12b524efd5 | ||
|
|
0f3dbde66d | ||
|
|
d2f9710778 | ||
|
|
99e2e59686 | ||
|
|
6cfa08e13d | ||
|
|
5ca05e9735 | ||
|
|
d52595fd5e | ||
|
|
08207c1d1a | ||
|
|
5aa09b427b | ||
|
|
fa72185179 | ||
|
|
67013fe1ed | ||
|
|
666660455a | ||
|
|
bd536204b5 | ||
|
|
c476e46b46 | ||
|
|
e1d1bcdad8 | ||
|
|
effb03c933 | ||
|
|
2f9d3e4420 | ||
|
|
5fb09fdc55 | ||
|
|
808ec51028 | ||
|
|
83a442d615 | ||
|
|
4da27c29f9 | ||
|
|
bc7bdb6bdf | ||
|
|
3ab83328b0 | ||
|
|
ed407edda9 | ||
|
|
bc2ca4e61b | ||
|
|
b28c8ddd85 | ||
|
|
b47319a191 | ||
|
|
6903d25749 | ||
|
|
6e61a4b8a0 | ||
|
|
c3a3c187a7 | ||
|
|
af3c4de98b | ||
|
|
4e5b6a9124 | ||
|
|
7df5e0a180 | ||
|
|
cccc44ff64 | ||
|
|
0daa495158 | ||
|
|
2866616fbf | ||
|
|
9fdb450bb3 | ||
|
|
d780e6c724 | ||
|
|
426a19314d | ||
|
|
31a0186862 | ||
|
|
02ebfbe1f1 | ||
|
|
fb2c27ab14 | ||
|
|
a41e0905be | ||
|
|
58ecbbb74e | ||
|
|
b648f8cdc4 | ||
|
|
f6fe4a800f | ||
|
|
98bc30c5ce | ||
|
|
401fc7a495 | ||
|
|
430661a5c3 | ||
|
|
52cc8a635b | ||
|
|
409626e72e | ||
|
|
fcaa5dfa82 | ||
|
|
0b1cc70680 | ||
|
|
6372bbe902 | ||
|
|
ea813452bf | ||
|
|
a93c67bb75 | ||
|
|
f150e1f35c | ||
|
|
cbbb20e3f0 | ||
|
|
d88eb3a455 | ||
|
|
bf76263a40 | ||
|
|
23b95c6f57 | ||
|
|
2b223bf898 | ||
|
|
c0c1abeb6b | ||
|
|
e34f5b4221 | ||
|
|
4bba11d28d | ||
|
|
2ecb71fcb1 | ||
|
|
6aef8b4a4e | ||
|
|
445fee730c | ||
|
|
d03f97c8b3 | ||
|
|
d5da4f6826 | ||
|
|
6ea13f3a47 | ||
|
|
a6aef0a640 | ||
|
|
8884d7088f | ||
|
|
5eeba98b34 | ||
|
|
ae4ed00621 | ||
|
|
e77aaf9cc2 | ||
|
|
21aa171662 | ||
|
|
7ff51a1524 | ||
|
|
81dfb550b3 | ||
|
|
48b019dab8 | ||
|
|
5f89a46c2e | ||
|
|
a7a2782c0e | ||
|
|
f481abe0b0 | ||
|
|
5838f2e83e | ||
|
|
0dc377060f | ||
|
|
df36e0e2cf | ||
|
|
04eee935ff | ||
|
|
b7b94d42d6 | ||
|
|
c34e689d2d | ||
|
|
0513aeef33 | ||
|
|
915911b4b5 | ||
|
|
bed90331a7 | ||
|
|
5d91ee7879 | ||
|
|
b2a22711f7 | ||
|
|
3e910d5f59 | ||
|
|
1a3d3603f6 | ||
|
|
2779c96006 | ||
|
|
70089f16ef | ||
|
|
1eee578672 | ||
|
|
6f485085b7 | ||
|
|
f7d36b7c18 | ||
|
|
4ea44e8eaa | ||
|
|
6a64dcfa7b | ||
|
|
260bc0262c | ||
|
|
bf185ef305 | ||
|
|
0183ab5f3c | ||
|
|
d17083ecb0 | ||
|
|
77187a3974 | ||
|
|
693e575e09 | ||
|
|
f70b8f8018 | ||
|
|
4a9b28537d | ||
|
|
b2c1c04b24 | ||
|
|
a2e387fbc3 | ||
|
|
fecf11dfbd | ||
|
|
d4d9bd8aeb | ||
|
|
36032c4a0b | ||
|
|
6de44ee0a3 | ||
|
|
fd63f561b5 | ||
|
|
de9f768db7 | ||
|
|
8da6d3ca12 | ||
|
|
6f3b18c941 | ||
|
|
863389ff7e | ||
|
|
9c9d542719 | ||
|
|
8c8e9c6917 | ||
|
|
e5ee29ecb8 | ||
|
|
9ab273f3d0 | ||
|
|
0f70a07dfc | ||
|
|
0c7cbc60d9 | ||
|
|
f21d0af52a | ||
|
|
8f1498fff4 | ||
|
|
13210d01c3 | ||
|
|
c82ce094c2 | ||
|
|
411ff45f10 | ||
|
|
886bfb3cfe | ||
|
|
9557ea82d7 | ||
|
|
7470fca163 | ||
|
|
063b7a752d | ||
|
|
bb8d16eeb1 | ||
|
|
9300ccaccd | ||
|
|
a7a40ef748 | ||
|
|
20367b706d | ||
|
|
6fbec5afba | ||
|
|
6edf97587f | ||
|
|
6147fc1c8b | ||
|
|
29ac9a3092 | ||
|
|
7be0706eae | ||
|
|
afefbe4455 | ||
|
|
24e5516206 | ||
|
|
91547c9892 | ||
|
|
6d43b44d81 | ||
|
|
713b74c1f9 | ||
|
|
ad738c2ed0 | ||
|
|
03ee05187d | ||
|
|
a5fc09cf82 | ||
|
|
0bea0ad8dd | ||
|
|
71233c3ee6 | ||
|
|
d25447d3ce | ||
|
|
8cfefb91fc | ||
|
|
6b8ac2910c | ||
|
|
5123462863 | ||
|
|
6a48b344ed | ||
|
|
2030fd6212 | ||
|
|
5760e8f190 | ||
|
|
42ff49fb51 | ||
|
|
8ca29ff29d | ||
|
|
37a43c2a98 | ||
|
|
63bc14c30b | ||
|
|
3f608e361f | ||
|
|
a496fc0304 | ||
|
|
c9a5f01578 | ||
|
|
9528328121 | ||
|
|
b25d57b6fa | ||
|
|
51b9b5e1e5 | ||
|
|
d2914bf635 | ||
|
|
7034237eed | ||
|
|
36cfc3ec93 | ||
|
|
b99b378c55 |
No files matched your search
@@ -4,5 +4,6 @@
|
||||
*.exe
|
||||
*.dll
|
||||
*.so
|
||||
*.d
|
||||
package.json
|
||||
.npmignore
|
||||
+64
-9
@@ -41,6 +41,10 @@ include:
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/linux-i686.yml'
|
||||
|
||||
# Linux 64-bit (ARM)
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/linux-aarch64.yml'
|
||||
|
||||
# MacOS 64-bit
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/osx-x64.yml'
|
||||
@@ -50,8 +54,8 @@ include:
|
||||
file: '/osx-arm64.yml'
|
||||
|
||||
# MacOS PowerPC 32-bit
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/osx-ppc.yml'
|
||||
# - project: 'libretro-infrastructure/ci-templates'
|
||||
# file: '/osx-ppc.yml'
|
||||
|
||||
################################## CELLULAR ################################
|
||||
# Android
|
||||
@@ -67,6 +71,10 @@ include:
|
||||
file: '/ios9.yml'
|
||||
|
||||
################################## CONSOLES ################################
|
||||
# PlayStation3
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/psl1ght-static.yml'
|
||||
|
||||
# PlayStation Portable
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/psp-static.yml'
|
||||
@@ -79,6 +87,10 @@ include:
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/ctr-legacy-static.yml'
|
||||
|
||||
# Nintendo Wii
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/wii-static.yml'
|
||||
|
||||
# Nintendo WiiU
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/wiiu-static.yml'
|
||||
@@ -104,6 +116,10 @@ include:
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/emscripten-static.yml'
|
||||
|
||||
# webOS 32-bit (LGTV)
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/webos-make.yml'
|
||||
|
||||
# Stages for building
|
||||
stages:
|
||||
- build-prepare
|
||||
@@ -171,12 +187,20 @@ libretro-build-linux-i686:
|
||||
only:
|
||||
- master
|
||||
|
||||
# Linux 64-bit (ARM)
|
||||
libretro-build-linux-aarch64:
|
||||
extends:
|
||||
- .libretro-linux-aarch64-make-default
|
||||
- .core-defs
|
||||
only:
|
||||
- master
|
||||
|
||||
# MacOS 64-bit
|
||||
libretro-build-osx-x64:
|
||||
tags:
|
||||
- macosx-packaging
|
||||
extends:
|
||||
- .libretro-osx-x64-make-default
|
||||
- .libretro-osx-x64-make-10-7
|
||||
- .core-defs
|
||||
only:
|
||||
- master
|
||||
@@ -192,12 +216,12 @@ libretro-build-osx-arm64:
|
||||
- master
|
||||
|
||||
# MacOS PowerPC 32-bit
|
||||
libretro-build-osx-ppc:
|
||||
extends:
|
||||
- .libretro-osx-ppc-make-default
|
||||
- .core-defs
|
||||
only:
|
||||
- master
|
||||
#libretro-build-osx-ppc:
|
||||
# extends:
|
||||
# - .libretro-osx-ppc-make-default
|
||||
# - .core-defs
|
||||
# only:
|
||||
# - master
|
||||
|
||||
################################### CELLULAR #################################
|
||||
# Android ARMv7a
|
||||
@@ -257,6 +281,14 @@ libretro-build-tvos-arm64:
|
||||
- master
|
||||
|
||||
################################### CONSOLES #################################
|
||||
# PlayStation3
|
||||
libretro-build-psl1ght:
|
||||
extends:
|
||||
- .libretro-psl1ght-static-retroarch-master
|
||||
- .core-defs
|
||||
only:
|
||||
- master
|
||||
|
||||
# PlayStation Portable
|
||||
libretro-build-psp:
|
||||
extends:
|
||||
@@ -281,6 +313,21 @@ libretro-build-ctr:
|
||||
only:
|
||||
- master
|
||||
|
||||
# Nintendo Wii
|
||||
.core-defs-wii:
|
||||
extends:
|
||||
- .libretro-wii-static-retroarch-master
|
||||
- .core-defs
|
||||
only:
|
||||
- master
|
||||
|
||||
#libretro-build-wii-core:
|
||||
# extends:
|
||||
# - .core-defs-wii
|
||||
# variables:
|
||||
# INCLUDE_DRV: drv_?
|
||||
# CORENAME: mame2003_plus_drv_?
|
||||
|
||||
# Nintendo WiiU
|
||||
libretro-build-wiiu:
|
||||
extends:
|
||||
@@ -345,3 +392,11 @@ libretro-build-emscripten:
|
||||
- .core-defs
|
||||
only:
|
||||
- master
|
||||
|
||||
# webOS 32-bit
|
||||
libretro-build-webos-armv7a:
|
||||
extends:
|
||||
- .libretro-webos-armv7a-make-default
|
||||
- .core-defs
|
||||
only:
|
||||
- master
|
||||
+480
-14
@@ -2,7 +2,8 @@
|
||||
|
||||
* Current repository maintainers: arcadez, mahoneyt944, markwkidd, twinaphex
|
||||
* Past repository maintiners: arnoldsecret, grant2258
|
||||
* Significant code contributors to this project: AMadvanceMAME, BritneysPAIRS, dink, FBN Dev, grant2258, iq_132, MAME Dev, ShmupMAME
|
||||
* Significant code contributors to this project: AMadvanceMAME, BritneysPAIRS, dink,
|
||||
* FBN Dev, grant2258, iq_132, MAME Dev, Mistydreams, ShmupMAME, Zanac, AI agent claude
|
||||
|
||||
The list of direct contributors to the MAME 2003-Plus github repository can be found at https://github.com/libretro/mame2003-plus-libretro/graphs/contributors. Additional contributor credits can be found in LICENSE.md, CHANGELOG.old, and in the individual driver source files.
|
||||
|
||||
@@ -10,48 +11,76 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
|
||||
* 96 Flag Rally
|
||||
* 1943 - The Battle Of Midway Mark II
|
||||
* 19XX: The War Against Destiny (All Sets)
|
||||
* 1945k III
|
||||
* A.B. COP
|
||||
* Action Fighter (Unprotected)
|
||||
* Action Hollywood
|
||||
* Adventure Canoe
|
||||
* Air Attack
|
||||
* Air Rescue
|
||||
* Akka Arrh (prototype)
|
||||
* Aladdin (bootleg of Megadrive version)
|
||||
* Angler Dangler (Deco Cassette)
|
||||
* Argus (Gottlieb, prototype)
|
||||
* Astropal
|
||||
* Asura Buster
|
||||
* Backfire!
|
||||
* Back Fire (Tecmo)
|
||||
* Bang Bang Busters
|
||||
* Bare Knuckle (scrambled bootleg of Mega Drive version) - Romset `barekch` - 6 button pads
|
||||
* Bare Knuckle II (bootleg of Mega Drive version) - Romset `barek2mb` - its PIC16C57 emulated
|
||||
* Bare Knuckle II (chinese bootleg of Megadrive version)
|
||||
* Bare Knuckle III (bootleg of Megadrive version)
|
||||
* Baryon: Future Assault
|
||||
* Beastie Feastie (Epos Tristar 9000) - Romset `beastf`; the Pac-Man conversion is now `beastfp`, as in current MAME
|
||||
* Big Fight - Big Trouble In The Atlantic Ocean
|
||||
* Bio-Hazard Battle (scrambled bootleg of Mega Drive version) - Romset `biohzdmb`
|
||||
* Bomb Kick
|
||||
* Boogie Wings
|
||||
* Born To Fight
|
||||
* Botanic (English / Spanish set 1)
|
||||
* Bronx (Cycle Shooting bootleg)
|
||||
* Bubble Bobble 2 - The Return Of Super Drunk (prototype)
|
||||
* Bubble Buster
|
||||
* Buccaneers
|
||||
* Buggy Boy/Speed Buggy (cockpit, rev. D and B), Buggy Boy Junior/Speed Buggy (upright)
|
||||
* Bullet (unprotected of FD1094 317-0041 set)" )
|
||||
* Cabal (World, Joystick version)
|
||||
* Calorie Kun vs Moguranian
|
||||
* Center Court
|
||||
* Chain Reaction
|
||||
* Charlie Ninja
|
||||
* Chase Bombers
|
||||
* Choky! Choky!
|
||||
* Choutetsu Brikin'ger - iron clad
|
||||
* Clockwork Aquario
|
||||
* Columns II: The Voyage Through Time (World) - Romset `columns2`; the old `columns2` (Japan) is now its clone `column2j`, as in current MAME
|
||||
* Combat Hawk
|
||||
* Come Back Toto
|
||||
* Cookie & Bibi
|
||||
* Cookie & Bibi 3
|
||||
* Command War - Super Special Battle & War Game (prototype)
|
||||
* Cosmic Monsters II
|
||||
* Cotton (set 4, World) (unprotected of FD1094 317-0181a set)
|
||||
* Counter Run (Bootleg, Set 1)
|
||||
* Counter Run (Bootleg, Set 3)
|
||||
* Crossed Swords 2
|
||||
* Cute Fighter
|
||||
* Cycle Warriors
|
||||
* Daikaiju no Gyakushu
|
||||
* Danger Express (prototype)
|
||||
* Deathsmiles - Romset `deathsml`
|
||||
* Deathsmiles MegaBlack Label - Romset `dsmbl`
|
||||
* Deluxe 5
|
||||
* Denjin Makai
|
||||
* Deer Hunting
|
||||
* Deroon DeroDero
|
||||
* Dice - The Dice Game
|
||||
* Diet Go Go
|
||||
* Digger (CVS)
|
||||
* DoDonPachi Dai-Fukkatsu (Ver 1.5 and 1.0) - Romsets `ddpdfk`, `ddpdfk10`
|
||||
* DoDonPachi Dai-Fukkatsu Black Label - Romset `dfkbl`
|
||||
* Dolmen
|
||||
* Dodge Man
|
||||
* DoDonPachi Dai-Ou-Jou
|
||||
@@ -59,17 +88,23 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Double Wings
|
||||
* Dragon Bowl
|
||||
* Dream World
|
||||
* Dunk shot all sets
|
||||
* Dyna Gear
|
||||
* Eeekk!
|
||||
* ESPGaluda
|
||||
* Espgaluda II (all sets) - Romsets `espgal2`, `espgal2a`, `espgal2b`
|
||||
* F1 Super Lap (World)
|
||||
* Fantasy Zone II - The Tears of Opa-Opa (System 16C version)
|
||||
* Fever SOS
|
||||
* Final Tetris
|
||||
* Fire Hawk
|
||||
* FixEight (bootleg)
|
||||
* Flying Tiger
|
||||
* Frog & Spiders (bootleg)
|
||||
* Gaia: The Last Choice Of Earth
|
||||
* Galactica - Batalha Espacial
|
||||
* Ghostlop
|
||||
* Gladmort (NeoGeo Final Release)
|
||||
* Glass (Ver 1.1, Break Edition, Checksum D419AB69, Version 1994) (censored, unprotected)
|
||||
* Golden Par Golf
|
||||
* Golden Tee 3D Golf (v1.93N)
|
||||
@@ -81,68 +116,115 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Gulun.Pa!
|
||||
* Gunbarich
|
||||
* GunMaster
|
||||
* Gut's N' Glory (Atari Prototype)
|
||||
* Hammer Away
|
||||
* Hang Zo
|
||||
* Hard Times
|
||||
* Head On Channel (Japan, Prototype)
|
||||
* Heavy Smash
|
||||
* Heavy Unit
|
||||
* Hoops '96
|
||||
* Hypernoid
|
||||
* Hyper Crash
|
||||
* Hyper Street Fighter II (Asia)
|
||||
* Hyper Street Fighter II (All Sets)
|
||||
* Ibara (all sets) - Romsets `ibara`, `ibarao`
|
||||
* Ibara Kuro Black Label (all sets) - Romsets `ibarablk`, `ibarablka`
|
||||
* In Your Face
|
||||
* Inca * Mature *
|
||||
* Indian Battle
|
||||
* Invasion
|
||||
* Jammin (Atari Prototype)
|
||||
* Jingling Jiazu Genie 2000 - Romset `jingling`
|
||||
* Joe & Mac Returns
|
||||
* Jolly Jogger
|
||||
* Jurassic Park (Bootleg Of Megadrive Version)
|
||||
* Juezhan Tianhuang
|
||||
* Jump Kun
|
||||
* Kabuki-Z (World)
|
||||
* Ketsui: Kizuna Jigoku Tachi
|
||||
* Ketsui: Kizuna Jigoku Tachi - IKD 2007 Special Version
|
||||
* Knightmare
|
||||
* Knights Chance (NeoGeo)
|
||||
* Last Hope
|
||||
* Led Storm Rally 2011
|
||||
* Lethal Enforcers
|
||||
* Line Of Fire
|
||||
* Mad Alien
|
||||
* Mad Ball V2.0 * Mature * - Romset `madballn`
|
||||
* Magic Purple
|
||||
* Magic Purple
|
||||
* Manhattan (Deco Cassette)
|
||||
* Marble Madness II (prototype)
|
||||
* Master's Fury
|
||||
* Match It II * Mature *
|
||||
* Maze Invaders
|
||||
* Megumi Rescue
|
||||
* Metal Slug 4
|
||||
* Metal Slug 5
|
||||
* Mighty Pang (All Sets)
|
||||
* Mighty Warriors
|
||||
* Mirax
|
||||
* Mobile Suit Gundam Final Shooting
|
||||
* Monsters World (Bootleg Of Super Pang)
|
||||
* Monster Maulers
|
||||
* More More
|
||||
* Mortal Kombat 3 (scrambled bootleg of Mega Drive version) - Romset `mk3mdb` - 6 button pads
|
||||
* Mortal Race
|
||||
* Mouse Shooter GoGo
|
||||
* Ms. Pacman Twin
|
||||
* Mrs. Dynamite
|
||||
* Muchi Muchi Pork! - Romset `mmpork`
|
||||
* Multi Champ Deluxe * Mature *
|
||||
* Mushihime-Sama (all sets) - Romsets `mushisam`, `mushisama`, `mushisamb`
|
||||
* Mushihime-Sama Futari Black Label (all sets) - Romsets `futaribl`, `futariblj`
|
||||
* Mushihime-Sama Futari Ver 1.5 and 1.0 (all sets) - Romsets `futari15`, `futari15a`, `futari10`
|
||||
* New Zero Team
|
||||
* Ninja Kazan
|
||||
* Oo Parts (Japan, Prototype)
|
||||
* Opa Opa (Rev A Unprotected)
|
||||
* Oriental Legend Special
|
||||
* Oriental Legend Special - Xi You Shi E Zhuan Super (ver. 101, Korean Board)
|
||||
* Oriental Legend Special - Xi You Shi E Zhuan Super (ver. 103, China, Tencent) (unprotected)
|
||||
* Osman
|
||||
* Oozumou - The Grand Sumo (Deco Cassette)
|
||||
* Pack'n Bang Bang
|
||||
* Parallel Turn
|
||||
* Party Time: Gonta the Diver II / Ganbare! Gonta!! 2 * Mature *
|
||||
* Passing Shot (Japan 2 players)
|
||||
* Penky
|
||||
* Photo Y2K 2
|
||||
* Pink Sweets: Ibara Sorekara (all sets) - Romsets `pinkswts`, `pinkswtsa`, `pinkswtsb`, `pinkswtsx`
|
||||
* Pirate Treasure
|
||||
* Planet Probe
|
||||
* Pochi & Nyaa
|
||||
* Pocket Gal Deluxe * Mature *
|
||||
* Power Balls
|
||||
* Power Instinct Legends
|
||||
* Power Instinct Matrimelee
|
||||
* Power Up Baseball
|
||||
* Progear
|
||||
* Puzz Loop 2
|
||||
* Puckman Pockimon Genie 2000 - Romset `puckpkmn` - the set of current MAME; the old `puckpkmn` set is now its clone `puckpkmnb`, as in current MAME
|
||||
* Puyo Puyo (World) - Romset `puyo`; the old `puyopuyo`, `puyopuya` and `puyopuyb` are now its clones `puyoj`, `puyoja` and `puyobl`, as in current MAME
|
||||
* Puzz Loop 2 (All Sets)
|
||||
* Puzzle Break
|
||||
* Puzzle Star
|
||||
* Puzzle! Mushihime-Tama (all sets) - Romsets `mushitam`, `mushitama`
|
||||
* Puzzli 2
|
||||
* Puzzli 2 Super
|
||||
* Quick Shots (Clone Of Target Hits)
|
||||
* Racing Beat
|
||||
* Racing Hero
|
||||
* Rage Of The Dragons
|
||||
* Raiden II
|
||||
* Raiden DX
|
||||
* Raiden II / Raiden DX New
|
||||
* Recalhorn (prototype)
|
||||
* Revenger '84 (newer) - Romset `revngr84`; the older set `revenger` is a bad dump and stays not working
|
||||
* Riot
|
||||
* Rolling Crush
|
||||
* Round Up 5 - Super Delta Force
|
||||
* Rumba Lumber
|
||||
* Samurai Shodown V
|
||||
* Samurai Shodown V Special
|
||||
* Saurian Front (Williams Prototype)
|
||||
* SD Fighters
|
||||
* Sega Megaplay : Bio Hazard Battle
|
||||
* Sega Megaplay : Columns III
|
||||
@@ -151,22 +233,40 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Sega Megaplay : Streets Of Rage II
|
||||
* Sega Megaplay : Tecmo World Cup
|
||||
* Sega Sonic Bros (Japan, Prototype)
|
||||
* SegaSonic Cosmo Fighter (World and Japan) - Romsets `sonicfgt`, `sonicfgtj`
|
||||
* SegaSonic Popcorn Shop (Rev B) - Romset `sonicpop` - the popcorn machine itself isn't emulated, as in current MAME
|
||||
* Sengoku 3
|
||||
* Shuihu Feng Yun Zhuan
|
||||
* Skater (Deco Cassette)
|
||||
* Skull Fang
|
||||
* Sky Robo / Tatakae! Big Fighter
|
||||
* Slap Shooter
|
||||
* Snow Brothers 3 - Magical Adventure
|
||||
* Snk Vs Capcom : Svc Chaos (MVS)
|
||||
* Snapper
|
||||
* Sonic Boom
|
||||
* Sonic The Hedgehog 2 (Bootleg Of Megadrive Version)
|
||||
* Sonic The Hedgehog 3 (Bootleg Of Megadrive Version)
|
||||
* Soreike! Anpanman Popcorn Koujou (Rev B and Rev A) - Romsets `anpanman`, `anpanmana` - the popcorn machine itself isn't emulated, as in current MAME
|
||||
* Space Fever High Splitter
|
||||
* Space Launcher
|
||||
* Space Raider
|
||||
* Spectrum 2000 (Euro)
|
||||
* Squash
|
||||
* Stack Columns (World) - Romset `stkclmns`; the old `stkclmns` (Japan) is now its clone `stkclmnsj`, as in current MAME
|
||||
* Stadium Cross (World, linkable) and (US) - Romsets `scrossa`, `scrossu`; `scross` now uses the ROM names of current MAME
|
||||
* Star Fire 2
|
||||
* Steel Worker
|
||||
* Street Fighter III 3rd Strike: Fight for the Future (Widescreen 20220908, Bank Bank hack) - Romset `sfiii3ws`
|
||||
* Street Fighter Zero 3 Mix v0.32 (Zero800 hack, CPS2Turbo) - Romset `sfz3mix`, optional music samples `sfz3mix.zip`
|
||||
* Success Joe
|
||||
* Super Bishi Bashi Championship (ver JAA, 2 Players)
|
||||
* Super Bubble Bobble (Sun Mixing, Megadrive clone hardware)
|
||||
* Super Doubles Tennis (Deco Cassette)
|
||||
* Sunset Riders (scrambled bootleg of Mega Drive version) - Romset `srmdb`
|
||||
* Super Monaco GP
|
||||
* Super Rider
|
||||
* Super Street Fighter II - The New Challengers (scrambled bootleg of Mega Drive version) - Romset `ssf2mdb` - 6 button pads
|
||||
* Super Trio
|
||||
* SWAT Police
|
||||
* Tang Tang
|
||||
@@ -179,52 +279,91 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* The King of Fighters 2002
|
||||
* The King of Fighters 2003
|
||||
* The Lost Castle In Darkmist
|
||||
* ThunderForce AC (Japan, prototype, bootleg)
|
||||
* Top Driving
|
||||
* Top Roller
|
||||
* Top Shooter - Romset `topshoot`
|
||||
* Toppy & Rappy
|
||||
* Torus * Mature *
|
||||
* Touch & Go (Korea, unprotected)
|
||||
* Thunder Heroes
|
||||
* Thunder Hoop
|
||||
* Title Fight
|
||||
* Touki Denshou -Angel Eyes
|
||||
* Trophy Hunting Bear & Moose
|
||||
* Turkey Hunting
|
||||
* Twin Cobra 2
|
||||
* Twin Action
|
||||
* Twin Squash - Romset `twinsqua`
|
||||
* Twinkle
|
||||
* Twinkle Tale (Bootleg Of Megadrive Version)
|
||||
* TX-1 (World, Japan rev. B and C)
|
||||
* Tylz
|
||||
* Ufo Senshi Yohko Chan
|
||||
* Varia Metal
|
||||
* Vasara 2
|
||||
* Virtua Bowling
|
||||
* Virtua Fighter
|
||||
* Waku Waku Anpanman (Rev A and original) - Romsets `wwanpanm`, `wwanpanmo`
|
||||
* Waku Waku Jumbo (Rev A) - Romset `wwjumbo`
|
||||
* Waku Waku Marine - Romset `wwmarine`
|
||||
* Waku Waku Pajero - Romset `wwpajero`
|
||||
* Waku Waku Sonic Patrol Car - Romset `soniccar`
|
||||
* Wheels Runner
|
||||
* Wing Force
|
||||
* Wing Shooting Championship
|
||||
* Wiz Warz
|
||||
* Wonderboy In Monsterland (English Virtual Console Version)
|
||||
* Woodpecker
|
||||
* World Cup Volley 95
|
||||
* Xeno Crisis
|
||||
* Zero Team 2000
|
||||
* Zintrick
|
||||
* Zupapa
|
||||
|
||||
## New Clones
|
||||
|
||||
* 800 Fathoms (older), Knock Out!! (bootleg, set 2 and set 3), Triple Punch (set 2) - Romsets `800fatha`, `knockoutb`, `knockoutc`, `triplepa`
|
||||
* Alien Storm (bootlegs of the 3 players and Japan sets) - Romsets `astorm3d`, `astormud`, `astormjd`
|
||||
* Asura Buster - Eternal Warriors (USA), (Japan, set 2) and (Japan) (ARCADIA review build) - Romsets `asurabus`, `asurabusja`, `asurabusjr`; the Japan set 1 is now `asurabusj`, as in current MAME
|
||||
* Bare Knuckle III (bootleg of Mega Drive version, alt set, the PIC simulated) - Romset `barek3mba` - not working, as in current MAME
|
||||
* Bare Knuckle III / Sunset Riders (scrambled bootleg of Mega Drive versions) - Romset `bk3ssrmb` - not working, as in current MAME (only Bare Knuckle III boots)
|
||||
* Bloxeed (US, C System, Rev A) - Romset `bloxeedu`
|
||||
* Borench (set 2) and (Japan) - Romsets `borencha`, `borenchj`
|
||||
* Columns (US, cocktail, Rev A) - Romset `columnsu`
|
||||
* Print Club (World) and (Japan Vol.3) - Romsets `pclub`, `pclubjv3` - not working (camera and printer), as in current MAME
|
||||
* Puzzle & Action: Ichidant-R (World) (bootleg) - Romset `ichirbl`
|
||||
* Puzzle & Action: Tant-R (Japan) (bootleg set 3 and set 4) - Romsets `tantrbl3`, `tantrbl4`
|
||||
* Ribbit! (Japan) - Romset `ribbitj`
|
||||
* Sunset Riders / Super Street Fighter II - The New Challengers (scrambled bootleg of Mega Drive versions) - Romset `srssf2mb` - not working, as in current MAME (the order of the ROMs is not known)
|
||||
* Battle Shark (Japan, Joystick)
|
||||
* Bloxeed (bootleg) - Romset `bloxeedd`
|
||||
* Botanic (French version)
|
||||
* Bubble Bobble (prototype on tokio hardware)
|
||||
* Calorie Kun vs Moguranian (bootleg)
|
||||
* Cannon Dancer
|
||||
* Clutch Hitter (bootlegs) - Romsets `cltchitrd`, `cltchitrjd`
|
||||
* Competition Golf Final Round (old version) - `compglfo`
|
||||
* Cotton (bootlegs of the US and Japan sets) - Romsets `cottonud`, `cottonjd`, `cottonjad`
|
||||
* Crouching Tiger Hidden Dragon 2003
|
||||
* Crouching Tiger Hidden Dragon 2003 Super Plus
|
||||
* Crystal Castles (Joystick Version)
|
||||
* D. D. Crew (bootlegs of the six FD1094 sets) - Romsets `ddcrewd`, `ddcrewud`, `ddcrew1d`, `ddcrew2d`, `ddcrewjd`, `ddcrewj2d`
|
||||
* Desert Breaker (bootlegs) - Romsets `desertbrd`, `desertbrjd`
|
||||
* DJ Boy (Japan)
|
||||
* DoDonPachi Dai-Ou-Jou (Black Label)
|
||||
* Double Dragon 3 - The Rosetta Stone (Japan)
|
||||
* Dunk Dream '95
|
||||
* Dogyuun (8/25/1992 location test)
|
||||
* E.D.F. : Earth Defense Force (North America)
|
||||
* Escape Kids (Asia 4 Players)
|
||||
* Fishing
|
||||
* Flower (bootleg)
|
||||
* Fujiyama Buster
|
||||
* Gals Panic DX * Mature *
|
||||
* Ghox (Joystick)
|
||||
* Ganbare! Gonta!! 2 / Party Time: Gonta the Diver II * Mature *
|
||||
* Golden Axe II (Mega Play, original revision) - Romset `mp_gaxe2a`
|
||||
* GunNail (Location Test)
|
||||
* Guwange Special Version
|
||||
* Hacha Mecha Fighter (bootleg)
|
||||
@@ -237,6 +376,7 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* King of Gladiator
|
||||
* Knuckle Bash 2
|
||||
* Kyukyoku Tiger (Japan, 2 Players)
|
||||
* Laser Ghost (bootlegs) - Romsets `lghostd`, `lghostud`
|
||||
* Mad Ball V2.0 * Mature * - Romset `madball`
|
||||
* Magical Drop
|
||||
* Magical Drop Plus 1
|
||||
@@ -245,6 +385,7 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Renegade (US, Bootleg)
|
||||
* Safari Rally (World) - safarir
|
||||
* Sexy Parodius (Ver AAA) * Mature *
|
||||
* Shadow Dancer (World, Japan and US) - Romsets `shdancer`, `shdancerj`, `shdancer1` (were `shdancer`, `shdancrj`, `shdancrb`), now on the System 18 memory mapper and video as in current MAME
|
||||
* Snk Vs Capcom : Svc Chaos (bootleg)
|
||||
* Super Bishi Bashi Championship (ver KAA, 3 Players)
|
||||
* Target Ball * Mature * (Romset `tgtballa`)
|
||||
@@ -277,10 +418,15 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
|
||||
* Bubble Bobble Lost Cave
|
||||
* Bubble Bobble Ultra
|
||||
* Captain Barrel
|
||||
* Cyborg Force
|
||||
* Do DonPachi (Arrange Ver. 1.1) (trap15, hack)
|
||||
* Dogou Souken / Victory Road (joystick hack bootleg)
|
||||
* Donkey Kong II Jumpman Returns
|
||||
* Donkey Kong Remix
|
||||
* Donkey Kong Christmas Remix
|
||||
* Dottori-Man Jr. (Hack by Chris Covell)
|
||||
* Double Dragon One (Beta 7)
|
||||
* DownTown (joystick hack)
|
||||
* Final Fight 30th Anniversary Edition (Grego And Rotwang)
|
||||
* Food Fight - Live Center Rev 5 w/ debounce delay position hack
|
||||
@@ -289,15 +435,19 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Metal Slug 2 - Turbo (Trap15, Hack)
|
||||
* Midnight Resistance (joystick hack bootleg)
|
||||
* Mortal Kombat 2 Plus Beta 2
|
||||
* Pink Sweets: Suicide Club (2017 hack of Pink Sweets) - Romset `pinkswtssc`
|
||||
* TANK III (joystick hack bootleg)
|
||||
* The Eye Of The Typhoon (Beta 7)
|
||||
* Tron freeplay custom rom
|
||||
* Ultimate Mortal Kombat 3 Plus Beta 1
|
||||
* Ultimate Mortal Kombat 3 Plus Beta 2
|
||||
|
||||
|
||||
## Games fixed and now working
|
||||
|
||||
* Agent Super Bond - Romset `superbon` - colors fixed
|
||||
* Alcon - Romset: `alcon`
|
||||
* Alien Storm (World and Japan 2 players, World and US 3 players) - Romsets `astorm`, `astormj`, `astorm3`, `astormu` - FD1094 encrypted 68000, Sega System 18
|
||||
* Bloxeed (Japan, two sets) - Romsets `bloxeed`, `bloxeeda` - FD1094 encrypted 68000, Sega System 18
|
||||
* Arch Rivals - Romset: `archrivl`
|
||||
* Avengers In Galactic Storm US - Romset: `avengrgs`
|
||||
* Avengers In Galactic Storm Japan - Romset: `avengrgsj`
|
||||
@@ -315,12 +465,19 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Cheeky Mouse - Romset `cheekyms` - colors fixed
|
||||
* Chouji Meikyuu Legion (ver 1.05) - Romset `legiono`
|
||||
* Competition Golf Final Round (revision 3) - `compgolf`
|
||||
* Cotton (World, US, Japan Rev A and Rev B) - Romsets `cotton`, `cottonu`, `cottonj`, `cottonja` - FD1094 encrypted 68000
|
||||
* Clutch Hitter (US and Japan) - Romsets `cltchitr`, `cltchitrj` - FD1094 encrypted 68000, Sega System 18
|
||||
* Crater Raider - Romset `crater`
|
||||
* Crazy Climber 2 - Romset `cclimbr2`
|
||||
* Dark Edge - Romset `darkedge`
|
||||
* DD Crew - Romset `ddcrew`
|
||||
* D. D. Crew (all FD1094 sets: World 2, 3 and 4 players, US, Japan 2 and 4 players) - Romsets `ddcrew`, `ddcrew1`, `ddcrew2`, `ddcrewu`, `ddcrewj`, `ddcrewj2` - Sega System 18, as in current MAME
|
||||
* Desert Breaker (World and Japan) - Romsets `desertbr`, `desertbrj` - FD1094 encrypted 68000, Sega System 18
|
||||
* Demolition Derby - Romset `demoderb`
|
||||
* Die Hard Arcade - Romset `diehard` - Requires a fast system; video and sound issues remain
|
||||
* Discs Of Tron - Romsets `dotron` and `dotrone`
|
||||
* DJ Boy - Romset `djboy`
|
||||
* Dragon Ball Z V.R.V.S. - Romset `dbzvrvs`
|
||||
* Driving Force (galaxian hardware) - Romset `drivfrcg` - colors fixed
|
||||
* Domino Man - Romset `domino`
|
||||
* Dragon World - Romset `drgnwrld`
|
||||
@@ -329,18 +486,24 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Eight Ball Action (Pacman conversion) - Romset `8bpm` - colors fixed
|
||||
* F-1 Grand Prix Star II - Romset `f1gpstr2`
|
||||
* F1 Super Lap (Japan) - Romset `f1lapj`
|
||||
* Fantastic Journey - Romset `fanjour`
|
||||
* Fighters History - Romsets `fghthist`, `fghthsta`, and `fghthstw` - Playable with minor remaining unemulated protection
|
||||
* Find Out - Romset `findout` - colors fixed
|
||||
* Fire Barrel - Romset `firebarr`
|
||||
* Final Lap 2 - Romsets `finalap2` and `finalp2j`
|
||||
* Final Lap 3 - Romsets `finalap3` and `finalp3a`
|
||||
* Flower - Romset `flower`
|
||||
* Free Kick - Romset `freekick`
|
||||
* Funky Jet - Romset `funkyjet`
|
||||
* Gardia - Romset `gardia`
|
||||
* Get Star / Guardian - Romsets `getstar` and `getstarj`
|
||||
* Great 1000 Miles Rally - Romsets `gtmr`, `gtmr2`, `gtmre`, and `gtmrusa`
|
||||
* Green Beret - Romset `greenber`
|
||||
* Gussun Oyoyo - Romset `gussun`
|
||||
* Hacha Mecha Figher - Romsets `hachamf` and `hachamfb` - `hachamf` is playable but has remaining unemulated protection
|
||||
* Hang-On - Romset `hangon`
|
||||
* Hard Head 2 - Romset `hardhea2`
|
||||
* Highway Chase - Romset `chwy`
|
||||
* Hyper Duel - Romsets `hyprduel`, and `hyprdelj`
|
||||
* IGMO - Romset `igmo` color fixed
|
||||
* Imago - Romsets `imago` and `imagoa`
|
||||
@@ -351,6 +514,7 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Kick - Romset `kick`
|
||||
* Kick'N Run- Romset `kicknrun`
|
||||
* Kozmik Kroozr - Romset `kroozr`
|
||||
* Laser Ghost (World, US and Japan) - Romsets `lghost`, `lghostu`, `lghostj` - FD1094 encrypted 68000, Sega System 18, light guns
|
||||
* Legion (ver 2.03) - Romset `legion`
|
||||
* Macho Mouse - Romset `machomou` - colors fixed
|
||||
* Mario's Open Golf (Playchoice 10) - Romset `pc_moglf`
|
||||
@@ -363,14 +527,19 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* New Sinbad 7 - Romset `newsin7` - colors fixed
|
||||
* Night Slashers - Romset `nslasher`
|
||||
* Off Road Challenge - Romset `offroadc` - Requires a fast system
|
||||
* Passing Shot 4 player bootleg - Romset `passht4b`
|
||||
* Phantasm - Romset `phantasm`
|
||||
* Photo Y2k - Romset `photoy2k`
|
||||
* Pigskin 621AD - Romset `pigskin`
|
||||
* Princess Clara Daisakusen - Romset `prikura`
|
||||
* Power Drive - Romset `powerdrv`
|
||||
* Prebillian - `pbillian`
|
||||
* Pro Baseball Skill Tryout - `tryout`
|
||||
* Puzzle King (PacMan 2 with Tetris & HyperMan 2 & Snow Bros - `4in1boot`
|
||||
* Rabbit - Romset `rabbit` - no sound
|
||||
* Raiden II - Romset `raiden2`
|
||||
* Rampage - Romsets `rampage` and `rampage2`
|
||||
* Risky Challenge - Romset `riskchal` - Playable but dont press any buttons during the score calc screen between the levels
|
||||
* Risky Challenge - Romset `riskchal`
|
||||
* Rohga Armor Force - Romsets `rohga`, `rohgah`, `rohgau`
|
||||
* Run And Gun - Romset `rungun`
|
||||
* Rush'N Attack - Romset `rushatck`
|
||||
@@ -379,14 +548,26 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Satan's Hollow - Romset `shollow`
|
||||
* Sega Megaplay : Golden Axe II - Romset `mp_gaxe2`
|
||||
* Sega Megaplay : Sonic The Hedgehog - Romset `mp_sonic`
|
||||
* Sega Mega-Tech : After Burner - Romset `mt_aftrb` - SMS based
|
||||
* Sega Mega-Tech : Astro Warrior - Romset `mt_astro` - SMS based
|
||||
* Sega Mega-Tech : Bonanza Bros. - Romset `mt_bbros` - the good dump of current MAME
|
||||
* Sega Mega-Tech : Ghouls'n Ghosts - Romset `mt_gng` - the good dump of current MAME
|
||||
* Sega Mega-Tech : Golden Axe II - Romset `mt_gaxe2`
|
||||
* Sega Mega-Tech : Great Golf - Romset `mt_ggolf` - SMS based, the good dump of current MAME
|
||||
* Sega Mega-Tech : Parlour Games - Romset `mt_parlg` - SMS based
|
||||
* Sega Mega-Tech : Shinobi - Romset `mt_shnbi` - SMS based
|
||||
* Sega Mega-Tech : Tetris - Romset `mt_tetri` - the good dump of current MAME
|
||||
* Shisensho II * Mature * - Romset `shisen2`
|
||||
* Shogun Warriors - Romset `shogwarr`
|
||||
* Shrike Avenger - Romset `shrike`
|
||||
* Sky Army - Romset `skyarmy`
|
||||
* Slap Fight (Official Version) - Romset `slapfigh`
|
||||
* Slipstream - Romset `slipstrm`
|
||||
* Snowboard Championship - Romset `snowboar`
|
||||
* Solar Fox - Romset `solarfox`
|
||||
* Songjiangyanyi Final - Romset `songjang` - the Mega Drive board of current MAME, the HBLANK status it waits for
|
||||
* Space Position - Romset `spcpostn`
|
||||
* Space Seeker - Romset `spaceskr`
|
||||
* Speed Spin - Romset `speedspn` - gfx glitches
|
||||
* Spy Hunter - Romset `spyhunt`
|
||||
* Spy Hunter 2 - Romset `spyhunt2`
|
||||
@@ -397,10 +578,13 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Tapper - Romset `tapper`
|
||||
* Target Ball (Nude) - Romset `tgtball`
|
||||
* Task Force Harrier - Romsets `tharrier` and `tharierj`
|
||||
* The Dealer - Romset `dealer` - Epos Tristar 9000 board from current MAME
|
||||
* Thunder Blade - Romsets `thndrbld` and `thndrbld1`
|
||||
* Thunder Dragon - Romset `tdragon` - Minor sound issues remaining
|
||||
* Thunder Strike - Romset `tstrike`
|
||||
* Timber - Romset `timber`
|
||||
* Time Limit - Romset `timelimt` - colors fixed
|
||||
* Thunder Dragon - Romset `tdragon` - Minor sound issues remaining
|
||||
* Thunder Strike - Romset `tstrike`
|
||||
* Tokio / Scramble Formation (US) - Romset `tokio`
|
||||
* Tri-Sports - Romset `trisport`
|
||||
* Tron - Romset `tron`
|
||||
* Turbo Out Run - Romsets `toutrun` and `toutrun3`
|
||||
@@ -409,12 +593,15 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Two Tigers - Romset `twotiger`
|
||||
* Under Fire - Romset `undrfire`
|
||||
* U.S. Classic - Romset `usclssic` - colors fixed
|
||||
* VS. Hot Smash - `hotsmash`
|
||||
* Wally wo Sagase! (rev A and B, 2 and 3 players) - Romsets `wwallyj`, `wwallyja`, `wwallyja3p` - FD1094 encrypted 68000, Sega System 18, trackballs
|
||||
* Wonder Boy in Monster Land (Japan New Ver.) - Romset `wbml`
|
||||
* Wonder Boy in Monster Land (Japan Old Ver.) - Romset `wbmljo`
|
||||
* Xenophobe - Romset `xenophob`
|
||||
* X-men (6 players) - Romset `xmen6p` and `xmen6pu`
|
||||
* Wacko - Romset `wacko`
|
||||
* Whizz - Romset `whizz`
|
||||
* Zeroize - Romset `czeroize`
|
||||
* Zwackery - Romset `zwackery`
|
||||
|
||||
## Games now with sound
|
||||
@@ -422,6 +609,7 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Acrobat Mission
|
||||
* Altered Beast (version 2)
|
||||
* Asura Blade
|
||||
* Atomic Boy / Wily Tower
|
||||
* Balloon Bomber
|
||||
* Batsugun (Partial)
|
||||
* Bio-ship Paladin
|
||||
@@ -429,6 +617,7 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Cross Pang
|
||||
* Daitoride
|
||||
* Dharma Doujou
|
||||
* Dogyuun (8/25/1992 location test)
|
||||
* Fire Shark
|
||||
* Ghox
|
||||
* GunNail
|
||||
@@ -457,6 +646,8 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Sky Alert
|
||||
* Sky Diver
|
||||
* Space Chaser (CV version)
|
||||
* Special Forces
|
||||
* Special Forces II
|
||||
* Super Slam
|
||||
* Super Spacefortress Macross
|
||||
* Teki Paki
|
||||
@@ -473,11 +664,18 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
|
||||
## Games now with improved sound
|
||||
|
||||
* 800 Fathoms, Knock Out!!, Mariner, Triple Punch: AY-8910 clock of current MAME (1.536 MHz, verified on hardware), the sound was 16% too high and too fast
|
||||
* 1945kIII
|
||||
* Air Buster
|
||||
* Ashita no Joe
|
||||
* Asterix
|
||||
* Asura Blade, Asura Buster (no more repeated voices and sound effects)
|
||||
* Athena
|
||||
* Bandito
|
||||
* Big Event Golf
|
||||
* Bosconian
|
||||
* Burgler X
|
||||
* Congo Bongo
|
||||
* Cookie & Bibi 2
|
||||
* Crazy Balloon
|
||||
* Destination Earth - (Added lrescue.zip sample support)
|
||||
@@ -492,9 +690,11 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Galaga 3
|
||||
* Galaxy Rescue - (Added lrescue.zip sample support)
|
||||
* Gaplus
|
||||
* Go Go! Mile Smile / Susume! Mile Smile
|
||||
* Grobda
|
||||
* Hit The Ice
|
||||
* Horizon
|
||||
* Inferno (Williams)
|
||||
* Journey (Added sepways.wav sample)
|
||||
* Kaiketsu Yanchamaru
|
||||
* Kid Niki - Radical Ninja (US)
|
||||
@@ -512,13 +712,18 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Nibbler
|
||||
* Open Ice
|
||||
* Out Run - Added ost soundtrack (via KMFDManic)
|
||||
* Pack 'n Bang Bang
|
||||
* Pacman & Chomp Chomp
|
||||
* Pac & Pal
|
||||
* Passing Shot (4 Player Bootleg)
|
||||
* Performan
|
||||
* Pole Position
|
||||
* Pole Position II
|
||||
* Rampage World Tour
|
||||
* Revolution X
|
||||
* Rim Rockin Basketball (commentary voices)
|
||||
* Rohga Armor Force
|
||||
* R-Type Leo
|
||||
* Shark Attack
|
||||
* Sheriff
|
||||
* Space Fever
|
||||
@@ -532,7 +737,10 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Super Spacefortress Macross II
|
||||
* Super Xevious
|
||||
* Tecmo Bowl
|
||||
* The Legend OF Silkroad
|
||||
* Thief
|
||||
* Title Fight
|
||||
* Tough Turf (Japan)
|
||||
* Tower Of Druaga
|
||||
* Toypop
|
||||
* Trojan / Tatakai No Banka
|
||||
@@ -541,6 +749,7 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Two Tigers - `twotigra` romset
|
||||
* WWF Wrestlemania
|
||||
* Xevious
|
||||
* Zero Point
|
||||
|
||||
|
||||
## Games now with sound sample support
|
||||
@@ -549,7 +758,6 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Destination Earth - lrescue
|
||||
* Frogs
|
||||
* Galaxy Rescue - lrescue
|
||||
* Ghox (Toaplan Samples)
|
||||
* Journey
|
||||
* Lunar Rescue - lrescue
|
||||
* NATO Defense
|
||||
@@ -558,12 +766,15 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Sea Wolf II
|
||||
* Shark Attack
|
||||
* Space Firebird
|
||||
* Tailgunner
|
||||
* Thief
|
||||
* Two Tigers - `twotigra` romset
|
||||
* Zero Hour
|
||||
|
||||
|
||||
## Games supporting new and improved samples
|
||||
|
||||
* Congo Bongo
|
||||
* Destination Earth
|
||||
* Donkey Kong
|
||||
* Donkey Kong JR
|
||||
@@ -574,7 +785,101 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Vanguard
|
||||
|
||||
|
||||
## Changes
|
||||
## New and/or Recommended Input Options and Settings
|
||||
|
||||
* Ikari (joystick hack bootleg): dual stick aiming. Set the 'Aim with Right Stick' DIP switch to On (Tab menu, Dip Switches): the player walks with the left stick and aims and fires with the right stick; with the right stick released he fires where he walks, as before. Off by default.
|
||||
|
||||
* Added 'X-Way Joystick' Option to Analog Controls Menu only for IPT_DIAL and IPT_DIAL_V devices. This option is for use with x-way rotary joysticks (where the joystick can rotate X discrete steps, 8 or 12 appears to be most common). The joystick can still move up, down, left, right and diagonally. The most famous game to use this control scheme is Ikari Warriors.
|
||||
Notes on this option:
|
||||
- When on, prevents the character from rotating two discrete steps sometimes when the rotary joystick is just rotated one step.
|
||||
- When on, the character will only rotate up to half the frame rate instead of the frame rate, so up to 30 times per second instead of 60 times a second if the game is running at 60Hz.
|
||||
|
||||
* Recommended analog control settings for known games that use an x-way rotary joystick to give the intended rotary control of the character. (Note: Settings will work best if the game is running at its native 60Hz, and the time the rotary joystick "holds" down the virtual IPT_DIAL or IPT_DIAL_V button is longer than 1/60th of a second, but less than 2/60ths of a second.):
|
||||
- Bermuda Triangle
|
||||
Key/Joy Speed: 16
|
||||
Sensitivity: 100%
|
||||
X-Way Joystick: On
|
||||
- Caliber 50
|
||||
Key/Joy Speed: 4
|
||||
Sensitivity: 100%
|
||||
X-Way Joystick: On
|
||||
- DownTown
|
||||
Key/Joy Speed: 21
|
||||
Sensitivity: 100%
|
||||
X-Way Joystick: On
|
||||
- Forgotten Worlds (arcade version used "roll" button, not rotary joystick)
|
||||
Key/Joy Speed: 65
|
||||
Sensitivity: 100%
|
||||
X-Way Joystick: On
|
||||
- Gondomania
|
||||
Key/Joy Speed: 21
|
||||
Sensitivity: 100%
|
||||
X-Way Joystick: On
|
||||
- Guerrilla War
|
||||
Key/Joy Speed: 16
|
||||
Sensitivity: 100%
|
||||
X-Way Joystick: On
|
||||
- Heavy Barrel
|
||||
Key/Joy Speed: 21
|
||||
Sensitivity: 100%
|
||||
X-Way Joystick: On
|
||||
- Ikari Warriors
|
||||
Key/Joy Speed: 16
|
||||
Sensitivity: 100%
|
||||
X-Way Joystick: On
|
||||
- Victory Road (kind of Ikari Warriors II)
|
||||
Key/Joy Speed: 16
|
||||
Sensitivity: 100%
|
||||
X-Way Joystick: On
|
||||
- Ikari III - The Rescue
|
||||
Key/Joy Speed: 21
|
||||
Sensitivity: 100%
|
||||
X-Way Joystick: On
|
||||
- Midnight Resistance
|
||||
Key/Joy Speed: 21
|
||||
Sensitivity: 100%
|
||||
X-Way Joystick: On
|
||||
- SAR - Search and Rescue
|
||||
Key/Joy Speed: 21
|
||||
Sensitivity: 100%
|
||||
X-Way Joystick: On
|
||||
- T.A.N.K
|
||||
Key/Joy Speed: 16
|
||||
Sensitivity: 100%
|
||||
X-Way Joystick: On
|
||||
- Time Soldiers
|
||||
Key/Joy Speed: 21
|
||||
Sensitivity: 100%
|
||||
X-Way Joystick: On
|
||||
- Touchdown Fever
|
||||
Key/Joy Speed: 2
|
||||
Sensitivity: 100%
|
||||
X-Way Joystick: On
|
||||
- Touchdown Fever 2
|
||||
Key/Joy Speed: 2
|
||||
Sensitivity: 100%
|
||||
X-Way Joystick: On
|
||||
|
||||
|
||||
## Misc Changes
|
||||
* Save states (RunAhead, netplay) of the Galaxian/Scramble/Frogger hardware: Galaxian video (stars, flip, banks, background), the 7474 flip-flops, the Scramble sound RAM and timer, the RC filters of the sound streams, the global sound enable
|
||||
* Sega System 18: all the games on the 315-5195 memory mapper, the segaic16 video and the VDP layer as in current MAME (171-5874, 171-5987 and Shadow Dancer ROM boards, FD1094 sets, Laser Ghost light guns, Wally wo Sagase! trackballs); the old `astorm` and `astorm2p` are now `astormj` and `astorm`
|
||||
* Sega Mega Drive VDP (315-5313): now a module of its own (`vidhrdw/segavdp.c`), started with its own configuration by System C/C2, Mega-Tech, Mega Play, the Mega Drive bootlegs and System 18, so a change for one board no longer reaches the others; a game loaded after a Mega Play game in the same session no longer inherits its interrupt mode (e.g. Columns attract out of sync), and the VDP window position and VBLANK flag are in the save states
|
||||
* Sega Mega Play: its own driver (`drivers/megaplay.c`, as in current MAME), the Mega Drive part shared with the other Mega Drive based boards; Tecmo World Cup is now `mp_twcup` and the BIOS version 2 ROM `epr-a15294.ic2`, as in current MAME
|
||||
* Sega Mega-Tech: its own driver (`drivers/megatech.c`, as in current MAME), sets, ROMs and names as in current MAME (good dumps of `mt_bbros`, `mt_ggolf`, `mt_gng`, `mt_tetri`, the instruction ROMs in the cart at 0x300000); the Master System carts now run, on the Mega Drive in Mark III mode as in current MAME (the VDP in mode 4, the Z80 with the Sega mapper); the BIOS cart slots as in current MAME (the menu lists the one cart in slot 1, the slot RAM, the window into the cart), the BIOS display in its 224 line mode (the MENU title was cut) and drawn line by line; the Mega Drive VDP line timing and partial updates now count its own lines below the BIOS screen (they used the scanlines of the double screen); the 68000 writes to 0xa02000 of the boards without the Mega Play BIOS no longer go through a NULL pointer (Great Golf and Great Soccer crashed)
|
||||
* Sega Mega Play: the BIOS overlay is transparent on colour 0 of both its palettes and covers its borders, as in current MAME (the boot logo screen was hidden behind a green background)
|
||||
* Sega Mega Drive based bootlegs: their own driver (`drivers/megadriv_acbl.c`, as in current MAME), with the board variants of current MAME (the 6 button pads, the DIP switches at 0x770070 of the scrambled boards, the 3rd I/O port coins, the PIC16C57 of `barek2mb`); the new sets take their V-INT / H-INT through the VDP interrupt enables as on the real hardware (Mortal Kombat 3 crashed at boot), the descrambling of the bootlegs and the PIC of `barek2mb` now also work on big-endian hosts
|
||||
* Genie / Y-BOX and Sun Mixing boards: their own drivers (`drivers/megadriv_ybox.c`, `drivers/megadriv_sunmix.c`, as in current MAME); the Y-BOX games run on the Mega Drive machine as in MAME (Z80, I/O, the VDP interrupts and HBLANK as on the real hardware), with the protection read back latches and the ROM address remapping of Shuihu Feng Yun Zhuan of current MAME
|
||||
* Sega System C/C2: `drivers/segac2.c` now has only System C/C2, the Mega Drive part shared by the other boards is in `machine/megadriv.c` (as `megadriv.cpp` in current MAME); the sets, ROMs, titles, inputs and DIP switches as in current MAME; the protection chip as the EPM5032 logic of each game of current MAME (no more Ribbit! and Puyo Puyo 2 workarounds and fake tables, Print Club Vol.2, 4 and 5 now get past the protection); the alternate palette mode of Ribbit! and Twin Squash (instead of the palette address watching of Ribbit!); the 68000 at 8.95 MHz and the 59.92 Hz refresh as in current MAME (it ran at 7.67 MHz and 60 Hz: the games now follow the timing of MAME frame for frame), the V-INT and H-INT held until the 68000 takes them as on the board, the address mirrors, the battery-backed work RAM (high scores kept, as in current MAME) and the coin meters on the I/O chip
|
||||
* YM2612 / YM3438: the busy flag after a data write (192 clocks, as in current MAME), and a timer started long after its last overflow runs a whole period instead of firing at once (Thunder Force AC, Bloxeed and the other System C2 games follow MAME again)
|
||||
* Sega Mega Play: the V-INT of the BIOS VDP comes about 12 lines after the Mega Drive VBLANK, as in current MAME (it came ~80 lines early, and the BIOS/game handshake on port C could miss: Tecmo World Cup stayed on a black screen)
|
||||
* Sega Mega Play / System E: the tiles of the SMS-type VDP are read byte by byte, so they are drawn right on big-endian hosts (the Mega Play BIOS screen had the wrong colours)
|
||||
* Sega Mega Drive VDP: in H32 mode the sprite table base uses bit 0 of register 5, as on the real VDP (the fighters of Super Street Fighter II were missing, the sprites of Bonanza Bros. on Mega-Tech were garbled)
|
||||
* PIC16C5x CPU core: the program counter wraps at the end of the program memory (the 2K parts start at 0x7ff and ran past the ROM), and the save states no longer register the ports and STATUS through a NULL pointer (the save of a game with a PIC crashed); these are in the data RAM, saved with the CPU memory
|
||||
* Save states (netplay, RunAhead with a second instance) of the Mega Drive based boards: the Z80 RAM and bus state and the Mega-Tech / Mega Play BIOS registers and RAM are saved (Gunstar Heroes and Mazin Wars Mega Play went out of sync after loading a state in a new instance); the SN76496 PSG is saved, and the YM2612 DAC enable is restored from its own register (0x2b, it was read from 0x2d)
|
||||
* Sega System 18 (also Moonwalker): the VDP palette writes no longer overflow the System 16 palette RAM (they corrupted the memory after it, e.g. garbled graphics in Shadow Dancer), and the sprite shadows over the VDP layer no longer index past the palette
|
||||
* Save states (RunAhead, netplay) of the Sega System 18 hardware: the RF5C68 PCM, the YM2612/YM3438 envelope, LFO, frequency and timer state, the VDP layer, the sound ROM bank
|
||||
* Save states (RunAhead, netplay) of the Sega System 16B hardware: the uPD7759 ADPCM chip, the sound CPU ROM bank, the segaic16 tilemap and sprite banks, flip, scroll latches and display enable
|
||||
* Added HD647180 MCU sound support for Fire Shark and Vimana [arcadez]
|
||||
* Added sound sample support for Cosmic Alien [BritneysPAIRS, arcadez]
|
||||
* Updated sample support for Donkey Kong and Donkey kong JR to MAME87 [BritneysPAIRS, arcadez]
|
||||
@@ -652,7 +957,6 @@ Gun & Fronter, Metal Black, Ninja Kids, and Pulirula [arcadez]
|
||||
* Ported Mamesick's fix for the sound in Super Spacefortress Macross II level 2 onwards [arcadez]
|
||||
* Backported Kale's Taito F3 sound fixes for Riding Fight and Ring Rage from MAME 144 [arcadez]
|
||||
* Backported Stefan Jokisch's graphical and sound improvemnets for the Nintendo 8080 based games from MAME81 [arcadez]
|
||||
* Added Bryan McPhail's C-Chip simulation code for Operation Wolf from MAME98 and MAME176 respectively [arcadez]
|
||||
* Fixed graphical problems in GunNail and better balanced the sound for the games using the NMK004 [arcadez]
|
||||
* Removed imperfect MCU simulation code and hooked the proper M68705 MCU's for Renegade and Nekketsu Kouha Kunio-kun [dink, arcadez]
|
||||
* Hooked up the sepways.wav sample for journey in mcr2.c [mahoneyt944, grant2258, arcadez]
|
||||
@@ -676,7 +980,7 @@ Gun & Fronter, Metal Black, Ninja Kids, and Pulirula [arcadez]
|
||||
* Hooked up x-men 6 players [arcadez, mahoneyt944, KMFDManic]
|
||||
* Removed gauntlet entry from highscore dat to fix game glitches [mahoneyt944]
|
||||
* Set flag in Ost drivers to allow them to be fully bypassed [mahoneyt944]
|
||||
* Hooked up mk2p and umk3p romsets [Zoltan45, mahoneyt944]
|
||||
* Hooked up mk2p and umk3p romsets [Zoltan45, palmerj, mahoneyt944]
|
||||
* Ashita no Joe sound fixes / CPU clock frequencies [arcadez]
|
||||
* Success Joe new game support added [mahoneyt944]
|
||||
* Fixed directory and file creation for WiiU - should be working for all platforms now [mahoneyt944]
|
||||
@@ -700,7 +1004,7 @@ Gun & Fronter, Metal Black, Ninja Kids, and Pulirula [arcadez]
|
||||
* Added support for 1943 - The Battle Of Midway Mark II to 1943.c [arcadez]
|
||||
* Updated the legionnaire driver and video code to MAME142 added seicop protection Denjin Makai now playable [arcadez]
|
||||
* Added a small hack to the seibu soundcore to fix music and sfx in Denjin Makai [arcadez]
|
||||
* Added a working bootleg of Counter Run to freekick.c [BritneysPAIRS]
|
||||
* Added two working bootlegs of Counter Run to freekick.c [BritneysPAIRS, arcadez]
|
||||
* Updated the rohga.c driver to support the rare prototype Hang-Zo [arcadez]
|
||||
* Added support for Hyper Crash to nemesis.c [arcadez]
|
||||
* Added support for In Your Face a rare basketball prototype to the megasys1.c driver [arcadez]
|
||||
@@ -824,3 +1128,165 @@ Gun & Fronter, Metal Black, Ninja Kids, and Pulirula [arcadez]
|
||||
* Fixed sound in Dolmen and Twin Action then sorted an mcu simulation issue in Task Force Harrier [grant2258]
|
||||
* Improved road vs scenery priorities meaning you dont see things that should be hidden behind the hills appearing all over the road in Jaleco's Big Run [arcadez]
|
||||
* Updated the snowbros.c driver fixing three games and adding support for eight new games this also sorted the sound from cutting out in Cookie & Bibi 2 [arcadez]
|
||||
* Fixed some graphical problems where the colours were wrong on level 3 and half the screen was missing eg rendered black in Buggy Challenge [arcadez]
|
||||
* Added support for Dice - The Dice Game a bootleg of the undumped DiceDiceDice by IREM to the M90 driver [arcadez]
|
||||
* Added a new protection simulation to pgm.c so that Oriental Legend Special - Xi You Shi E Zhuan Super (ver. 101, Korean Board) now works in this core [arcadez]
|
||||
* Hooked up the M68705 protection MCU for the official Taito USA version of Tokio / Scramble Formation game now playable [arcadez]
|
||||
* Fixed some graphical priority and screen display area niggles which affected The Legend Of Kage [arcadez]
|
||||
* Added Bryan McPhail's C-Chip sim code for Operation Wolf from MAME98 and modded it slightly so the final end boss and enemy has located you mini levels can now be played [arcadez]
|
||||
* Added new sample support in cinemat drivers for tailgunner - tailg [mahoneyt944]
|
||||
* Fixed missing adpcm sound effects in Pack 'n Bang Bang and hooked up the sound correctly for Blood Warrior [arcadez]
|
||||
* Added support for a special sprite effect to kaneko16 video used by Magical Crystals on the first boss [arcadez]
|
||||
* Added a missing graphical sprite effect which handles enemy damage flashes and improved the sound for 1945k III [arcadez]
|
||||
* Added support for Angler Dangler and the clone japanese set Fishing to the decocass.c driver [arcadez]
|
||||
* Better balanced the music and Sfx levels in Kaneko's Air Buster and added the Japan version of DJ Boy [arcadez]
|
||||
* Fixed Deco Cassette game Zeroize in the decocass.c driver game now playable [arcadez]
|
||||
* Disabled palette banking for R-Type leo - fixes invincibiliy flashing [Haze, arcadez]
|
||||
* Fixed some serious graphical problems in R-Type Leo by disabling a gfx based speedup which caused issues throughout the game [arcadez]
|
||||
* Updated the Irem GRA20 soundcore to MAME 81 which fixes missing voices and improves the sound more generally for R-Type Leo [arcadez]
|
||||
* Added support for Hypernoid to the neogeo driver [arcadez, mahoneyt944]
|
||||
* Added Megumi Rescue to the Sega System E driver [Haze, arcadez]
|
||||
* Added Marble Madness II (prototype) to the batman driver [Haze, MistyDreams, dink, iq_132, arcadez, mahoneyt944]
|
||||
* Added Fantasy Zone II - The Tears of Opa-Opa (fantzn2x) to system16 driver [MistyDreams, mahoneyt944, arcadez]
|
||||
* Added Action Fighter Sega System A unprotected set to the system16 driver hooked up the inputs and sound plus some new gfx calls game now playable [arcadez, mahoneyt944]
|
||||
* Added support for Snapper to the system16 driver and hooked up the sound and music [mahoneyt944, arcadez]
|
||||
* Added and integrated a new segas16b driver to support decrypted versions of Bullet, Cotton and now Fantasy Zone II also [MistyDreams]
|
||||
* Added new Sega system16 graphical drawing routines and updated the UPD7759 soundcore plus all related drivers to MAME92 as per the above [MistyDreams]
|
||||
* Fixed some graphical niggles in Body Slam, Major League, Shinobi (bootleg), Tough Turf and Wrestlewar by switching them over to use the new Sega drawing routines [mahoneyt944]
|
||||
* Fixed missing speech samples in Tough Turf and some broken graphics in Passing Shot 4 player bootleg making the game now playable [mahoneyt944]
|
||||
* Added partial sound to Passing Shot 4 player bootleg [arcadez, mahoneyt944]
|
||||
* Fixed collisions in Golden Axe (Version 2) and improved the irq timers for Body Slam [mahoneyt944]
|
||||
* Added Hard Times and Power Balls to the playmark driver, no sound in Hard Times as yet [arcadez]
|
||||
* Added Penky to paradise.c plus Fire Hawk and Spectrum 2000 to afega.c [arcadez]
|
||||
* Added new style MAME cps2 decryption many more Capcom Play System 2 sets are now supported and more games are now playable [MistyDreams]
|
||||
* Fixed some missing graphics in Beast Busters and Mechanized Attack then sorted sprite priorities on level 2 in Beast Busters [bmcphail, dink, arcadez]
|
||||
* Added a new hack to fix the lights dont go out when shot in Elevator Action Returns and clones which doesn't break the gfx on the game ending [dink, arcadez]
|
||||
* Fixed some serious graphical issues on the final level in Double Dragon 3 and the third level in The Combat Tribes [Pierpaolo Prazzoli, arcadez, Cibomatto2002]
|
||||
* Added missing dac sounds speech and crowd cheers etc etc to Taito's Big Event Golf [arcadez]
|
||||
* Fixed broken sound for the classic Williams game Inferno by backporting a sound cpu hack from later MAME [Aaron Giles, arcadez]
|
||||
* Prevented The Electric Yo-Yo from hanging during the attract mode by interleaving the CPU's [MAME Dev, arcadez]
|
||||
* Updated some parts of the Taito SJ code to MAME 103 vastly improving the emulation for Elevator Action, Jungle Hunt, Sea Fighter Poseidon and more [MAME Dev, arcadez]
|
||||
* Fixed an issue where Space Seeker would not coin up and start due to a previous commit which added an invalid input game now playable again [arcadez]
|
||||
* Stopped Space Cruiser from crashing on the asteroids level and added the dedicated button for the continue mode [MAMEDev, arcadez]
|
||||
* Fixed Jungle Hunt / Jungle King / Pirate Pete from crashing on the last level [MEMEDev, arcadez]
|
||||
* Sorted a gfx niggle with Mario Bros where the screen would shake incorrectly left/right rather than up/down when you hit the POW box [MAMEDEv, arcadez]
|
||||
* Added support for Woodpecker to the pacman.c driver [MAMEDEv, arcadez, mahoneyt944]
|
||||
* Added sound banking to the OKIM6295 in silkroad.c fixing missing Sfx and Speech in The Legend Of Silkroad [MAMEDev, arcadez]
|
||||
* Added the Prom dump for Taxi Driver and hooked up the palette init fixing colours in the game [MAMEDev, arcadez]
|
||||
* Improved the sound for Congo Bongo by adding new samples and reclocking the 2nd SN76496 channel to fix the drums tempo [MAMEDev, arcadez]
|
||||
* Added support for Back Fire to the Tecmo driver [MAMEDev, arcadez]
|
||||
* Fix broken attract mode and likely other problems with the japan sets of Undercover Cops due to incorrect speedup addresses [Bryan Mcphail, Scandy]
|
||||
* Added support for a bootleg version of Sonic The Hedgehog 2 to the segac2 driver and made Lode Runner The Dig Fight default to the English World Region [MAMEDev, arcadez]
|
||||
* Added Deco Cassette Type A bios fixed Highway Chase sorted colours for all games then updated some parts of the machine and video code to MAME146 [MAMEDev, arcadez]
|
||||
* Added support for Angler Dangler, Manhattan, Oozumou - The Grand Sumo, Skater, and Super Doubles Tennis to the Deco Cassette driver [MAMEDev, arcadez]
|
||||
* Added support for resnet dkong and dkong3 machines are hooked up atm [MistyDreams]
|
||||
* Fixed Dragon Gun from locking up on the final boss and sorted an issue with the energy bar being missing also on the final boss [MAMEDev, arcadez]
|
||||
* Added support for the USA version of Night Slashers to the deco32.c driver [arcadez]
|
||||
* Sorted broken dip switches in Mr Do's Castle, Do! Run Run and Mr Do's Wild Ride plus fixed the sound for Indoor Soccer [MAMEDev, arcadez, SapphireDrew]
|
||||
* Fixed broken sound in Hachoo and Kick Goal plus sorted some graphical priority issues for 64th. Street - A Detective Story [MAMEDev, arcadez]
|
||||
* Added sprite buffering to the megasys1 driver improving the gfx for 64th. Street - A Detective Story, Avenging Spirit, Chimera Beast, Cybattler
|
||||
* E.D.F. : Earth Defense Force, Hachoo, In Your Face, Legend of Makai, P-47 - The Phantom Fighter, Ninja Kazan, Plus Alpha, Rod-Land, Saint Dragon
|
||||
* Shingen Samurai-Fighter, The Astyanax + more also added missing prio prom dumps for the games that did not have em already [MAMEDev, arcadez]
|
||||
* Added support for Ninja Kazan the English version of Iga Ninjyutsuden and E.D.F. : Earth Defense Force (North America) to megasys1.c [arcadez]
|
||||
* Fixed some serious graphical problems affecting Zero Hour wrong colours bullet width tilemaps etc etc Red Clash will also benefit from this [Hap, dink, arcadez]
|
||||
* Added sound sample support for Zero Hour which was totally silent previously [dink, Otto_Pylotte, MistyDreams, arcadez]
|
||||
* Added sega fd089 added all dunkshot sets and aurail sets, also added sdib,destroyer sets [mamedev backports]
|
||||
* Improved mario palette we now use resnet mamedev backports]
|
||||
* Fixed the official andparent romset for Free Kick and hooked up missing button 2 for Free kick. Gigas and Giga Mark II [MAMEDev, arcadez]
|
||||
* Added a previously missing graphical effect for Mega Blast in taito_f2.c now when you get the green pickup the shield orb on your ship can be seen [HAZE, arcadez]
|
||||
* Added support for the Tatsumi driver supporting Big Fight - Big Trouble In The Atlantic Ocean, Cycle Warriors and Round Up 5 - Super Delta Force [Mame2003 Dev Team]
|
||||
* Updated the Tecmo Sys driver to MAME126 both Deroon DeroDero and Touki Denshou - Angel Eyes are now playable [Haze, Arcadez, dink]
|
||||
* Hooked up the missing SN76496 sound for Special Forces and Special Forces II in the dkong.c driver both games now have Sfx and music [arcadez]
|
||||
* Fixed sound popping on B-Rap Boys and some sound banking niggles with The Great Thousand Mile Rally games [Mistydreams, arcadez]
|
||||
* Added support for Top Driving to the kickgoal.c driver [HAZE, arcadez]
|
||||
* Added a rare Atari Prototype Gut's N' Glory to the eprom.c driver [arcadez, mahoneyt944]
|
||||
* Updated the stlforce driver adding support for Mortal Race then backported some video fixes for it and Steel Force from later MAME [Mistydreams]
|
||||
* Added support for Dogyuun (8/25/1992 location test) to toaplan2 this version has full sound and music [arcadez, grant2258]
|
||||
* Added Photo Y2K 2 Puzzli 2 and Puzzli 2 Super to the pgm driver [arcadez, IQ_132, Haze]
|
||||
* Switched Contra to use the HD6309 for the main CPU to get rid of slowdowns and fix a crash after 2nd enemy base [arcadez]
|
||||
* Backported a fix from later MAME which gets rid of sprites sticking on the screen in Contra [Kale, mahoneyt944]
|
||||
* Fixed sprite prios and some bullets being hidden behind the bosses in Flak Attack / MX5000 [dink, KALE, arcadez]
|
||||
* Fixed missing commentary voices and correctly hooked up player 3 and 4 inputs for Rim Rockin Basketball [arcadez]
|
||||
* Fixed some graphical niggles and hooked up full sound and music for IREM's Atomic Boy / Wily Tower [MAMEDev, arcadez]
|
||||
* Fixed WWF Superstars bad sprites with some of Randy Macho Man Savage moves eg back suplex etc etc [MAMEDev, arcadez]
|
||||
* Hacked around some game breaking protection calls in Solomon's Key which could make levels unplayable [MAMEDEv, arcadez]
|
||||
* Added Maze Invaders Atari prototype to the centipede driver [MAMEDEv, arcadez]
|
||||
* Fixed Dragonball Z VRVS in the system32.c driver and Fantastic Journey in the konamigx.c driver [grant2258, arcadez]
|
||||
* Updated the romset for Pack N' Bang Bang to use the final released version rather than the unfinished prototype [arcadez]
|
||||
* Added the English language version of Dragon Might to the konamigx.c driver [arcadez, grant2258]
|
||||
* Added support for Monsters World (Bootleg Of Super Pang) to the mitchell.c driver [arcadez]
|
||||
* Fixed some graphical niggles in Cannon Dancer / Osman such as some objects didn't move previously eg trucks on final level [FBN Dev, MAMEDev, arcadez]
|
||||
* Added shadow support to the SSV video greatly improving the graphical effects in Storm Blade [MAMEDev, arcadez]
|
||||
* Fixed graphical corruption on left side of screen stage 3 onwards in Storm Blade and all stages in Ultra X Weapons [MAMEDev, arcadez]
|
||||
* Added some alt sprite drawing to the ssv video to prevent performance drops in some SSV games after the above updates [BritneysPAIRS]
|
||||
* Hooked up the M6801 Protection MCU for Kiki Kai Kai fixing many gameplay issues this game can now be considered 100% in the emulation dept [arcadez]
|
||||
* Updated Sega system 16/c2 gfx to support the system18 VDP gfx then added Clockwork Aquario to the system18 driver[grant2258, arcadez, mistydreams]
|
||||
* Fixed DD Crew so it is now playable in this core added support for Hammer Away and fixed the sound banking for games in system18.c [grant2258, arcadez, mistydreams]
|
||||
* Added screen flipping and fixed the cocktail mode for Asteroids, Asteroids Deluxe and Tempest [mahoneyt944]
|
||||
* Backported a graphical fix from latest MAME to fix missing shadows in Atari's Shuuz [MAMEdev, arcadez]
|
||||
* Added Donkey Kong Remix and Donkey Kong Christmas Remix hacks to dkong.c [grant2258, arcadez]
|
||||
* Emulated a missing graphical effect for Wild Fang / Tecmo Knight the screen now shakes when enemies break through walls and you land after a big jump [arcadez]
|
||||
* Fixed Player 2 Start Button for Namco's Tinkle Pit [MAMEDev, arcadez]
|
||||
* Updated the rabbit driver to MAME88 and bootstrapped the rom loading to prevent the game from hanging, Rabbit is now playable but without sound
|
||||
* as we dont have the I5000 soundcore this game would require [arcadez, mahoneyt944]
|
||||
* Added missing button 3 inputs for Strike Gunner S.T.G used to combine both ships into one during a two player game [MAMEDEv, arcadez]
|
||||
* Updated the protection code for Exerion to prevent the game from ending should you die at anytime after the first bonus round [MAMEDev, arcadez]
|
||||
* Added a new game Top Roller to the yamato.c driver and reworked the cpu encryption making it compatable with the MAME78 codebase [grant2258, arcadez]
|
||||
* Fixed some graphical niggles with Chinese Hero on level 7 [MAMEDev, arcadez]
|
||||
* Improved the sound for Go Go! Mile Smile / Susume! Mile Smile by adding sound banking and reclocking the sound and CPU speeds [MAMEDev, arcadez]
|
||||
* Fixed some grahical niggles throughout the game and with the cocktail mode for Orca's Sky Lancer [MAMEDev, arcadez]
|
||||
* Added support for Cyborg Force to the NeoGeo driver [arcadez]
|
||||
* Fixed broken sound and incorrect background graphics in Performan [MAMEDev, arcadez]
|
||||
* Improved the sound for Burgler X and Zero Point by reclocking the YM3812 sound call [MAMEDev, arcadez]
|
||||
* Added support for Buccaneers to vigilant.c and ThunderForce AC (Japan, prototype, bootleg) to the segac2.c drivers [MAMEDev, arcadez]
|
||||
* Fixed sound clipping in Karate Champ [MAMEDev, arcadez]
|
||||
* Fixed sound samples not playing in two versions of Bomber Man namely Bomber Man World (World) and New Atomic Punk - Global Quest (US) [MAMEDev, arcadez]
|
||||
* Added two sets of Twin Cobra 2 to the taito_f3.c driver and the international version of Dangun Feveron namely Fever SOS to cave.c [arcadez]
|
||||
* Fixed up Dark Edge and Slipstream by hooking up the inputs adding the protection then fixing the graphics and sound both games now playable [mahoneyt944, grant2258, arcadez]
|
||||
* Backported segas32 video driver, interrupt controllers for v60 and sound, general cleanup and merger of multi32 and system32 drivers. [mahoneyt944]
|
||||
* Backported the segaxbd driver and video code from later MAME A.B. COP, Line Of Fire, Racing Hero, Super Monaco GP
|
||||
* and Thunder Blade are now fully playable [grant2258]
|
||||
* Added support for Knights Chance to the NeoGeo driver [arcadez]
|
||||
* Fixed dip switches for Super Pac-man added new sound roms for Pac & Pal and new graphical roms which fix bad colours in Pac-man & Chomp Chomp [MAMEDev, arcadez]
|
||||
* Added the proper sprite roms for Final Lap 2 game now playable and hooked up the road colour clut proms for the Final Lap games and Suzuka 8 Hours [arcadez]
|
||||
* Fixed some missing line scrolling graphical effects in Magical Cat Adventure and Nostradamus [MAMEDev, arcadez]
|
||||
* Added three more Megadrive arcade bootlegs to segac2 namely Jurassic Park, Sonic 3 and Twinkle Tale [MAMEDev, arcadez, mahoneyt944]
|
||||
* Improved the gfx significantly for Sega's Title Fight [mahoneyt944]
|
||||
* Fixed missing and or incorrect sounds with a two player game in Title Fight [arcadez]
|
||||
* Added support for a decrypted version of Passing Shot and a rare prototype of the same game called Center Court to segas16b driver [grant2258]
|
||||
* Added Captain Barrel by Neobyteforce to the neogeo driver [arcadez]
|
||||
* Backported some graphical fixes for SNK's Joyful Road / Munch Mobile from later MAME [arcadez]
|
||||
* Added RNG protection which handles random events during boss battles improving the emulation
|
||||
* for Data East's Secret Agent / Sly Spy [arcadez, Mahoneyt944]
|
||||
* Improved the protection for Data East's Express Raider to prevent the game stalling on level 2 [MAMEDev, arcadez]
|
||||
* Added support for Bubble Buster a unique version of Puzzle Bobble with totally different gameplay and music [arcadez, FBNDev]
|
||||
* Fixed the attract mode for 64th Street, Chimera Beast, pengo, updated the pengo sets and fixed the gameover annimation for Vapor Trail [grant2258]
|
||||
* Added reset playfield dip switch option in Space Wars [mahoneyt944]
|
||||
* Merged pbillian.c and superqix.c updating to MAME90 which improves the emulation and sound for Prebillian and VS. Hot Smash both games now playable [arcadez, grant2258]
|
||||
* Ported across from advancemame a proper fix For Risky Challenge / Gussun Oyoyo the protection is now fully cracked fixing an issuemwhere the game
|
||||
could crash on the score calc between levels is sorted [amadvance, arcadez]
|
||||
* Added Taito's Victorious Nine to flstory.c and hooked up the M68705 protection MCU for Taito's Field Day [arcadez]
|
||||
* Added support for Gladmort to the NeoGeo driver [arcadez]
|
||||
* Added Quick Shots an unprotected version of Target Hits to the targeth.c driver then updated the gfx and configured the gun sights [arcadez, grant2258]
|
||||
* Added Shuihu Feng Yun Zhuan and Songjiangyanyi Final to the segac2.c driver grant2258 fixed Shuihu Feng Yun Zhuan game now playable [grant2258, arcadez]
|
||||
* Supported Double Dragon One and The Eve Of The Typhoon in neogeo.c [arcadez]
|
||||
* Added Double Wings (Asia) to the dblewing.c driver as unlike the original version this one doen't have checkpoints [arcadez]
|
||||
* Ported across from FBL dink's fix for the broken text gfx layer in the Japanese version Of Cameltry [dink, arcadez]
|
||||
* Added support for Jammin a rare Atari prototype music game to the Donkey Kong driver [arcadez]
|
||||
* Added Saurian Front a super rare Williams prototype of Midway's Strike Force to the midyunit driver [arcadez]
|
||||
* Added Adventure Canoe to the taitosj driver [arcadez, jackphilippi, dink]
|
||||
* Added support for Ketsui: Kizuna Jigoku Tachi - IKD 2007 Special Version to pgm.c [arcadez]
|
||||
* Fixed a protection related problem with powerups in Burning Force [MAMEDev, arcadez]
|
||||
* Extended IREM Drum sample support to Lode Runner 3 and 4 [dink, arcadez]
|
||||
* Improved the dip switch options for Data East's Break Thru [arcadez]
|
||||
* Fixed BG GFX colours for Crater Raider [MAMEDev, arcadez]
|
||||
* Fixed multiple sound sample issues in TAD CORP's Toki [MAMEDev, arcadez]
|
||||
* Fixed sound sample playing for SEGA's Zaxxon [MAMEDev, arcadez]
|
||||
* Fixed Palette banking problems for Pleiads [MAMEDev, arcadez]
|
||||
* Added fixes from later MAME so that Princess Clara Daisakusen now works [MAMEDev, arcadez]
|
||||
* Ported a new raiden2.c driver Raiden II Raiden DX and Zero Team etc etc now playable [Salvia, MAMEDev, FBN, vanni and claude, arcadez]
|
||||
* Ported the Cave CV1000 driver from current MAME: SH-3 CPU (interpreter and a recompiler with the same results), the blitter, the YMZ770 sound chip, the NAND flash and the RTC9701 [MAMEDev, vanni and claude]
|
||||
* Added support for the hvyunit.c driver ported across from my xbox project [arcadez, mistydreams, vanni and claude]
|
||||
* Added Sky Robo / Tatakae! Big Fighter to armedf.c and hooked it up to the new mcs51 cpu
|
||||
[arcadez, grant2258, AdvanceMAME, Zanac]
|
||||
* Ported a driver for Atari's Akka Arrh across from AdvanceMAME [arcadez, AdvanceMAME]
|
||||
@@ -1,10 +1,12 @@
|
||||
TARGET_NAME := mame2003_plus
|
||||
CORE_DIR := src
|
||||
INCLUDE_DRV ?= all
|
||||
|
||||
DEBUG ?= 0
|
||||
DEBUGGER ?= 0
|
||||
SPLIT_UP_LINK ?= 0
|
||||
ARM ?= 0 # set to 0 or 1 to indicate ARM or not
|
||||
HAVE_ARMv6 ?= 0
|
||||
CPU_ARCH ?= 0 # as of November 2018 this flag doesn't seem to be used but is being set to either arm or arm64 for some platforms
|
||||
|
||||
LIBS ?=
|
||||
@@ -98,7 +100,9 @@ endif
|
||||
ifeq ($(platform), unix)
|
||||
TARGET = $(TARGET_NAME)_libretro.so
|
||||
fpic = -fPIC
|
||||
CFLAGS += $(fpic)
|
||||
# only the retro_* entry points (RETRO_API) leave the library: the rest is
|
||||
# reached directly instead of through the GOT and PLT
|
||||
CFLAGS += $(fpic) -fvisibility=hidden
|
||||
LDFLAGS += $(fpic) -shared -Wl,--version-script=link.T
|
||||
|
||||
# Linux Portable
|
||||
@@ -179,6 +183,7 @@ else ifeq ($(platform), rpi0)
|
||||
CXXFLAGS = $(CFLAGS) -fno-rtti -fno-exceptions
|
||||
CPU_ARCH := arm
|
||||
ARM = 1
|
||||
HAVE_ARMv6 = 1
|
||||
|
||||
# Raspberry Pi 1
|
||||
else ifeq ($(platform), rpi1)
|
||||
@@ -191,6 +196,7 @@ else ifeq ($(platform), rpi1)
|
||||
CXXFLAGS = $(CFLAGS) -fno-rtti -fno-exceptions
|
||||
CPU_ARCH := arm
|
||||
ARM = 1
|
||||
HAVE_ARMv6 = 1
|
||||
|
||||
# Raspberry Pi 2
|
||||
else ifeq ($(platform), rpi2)
|
||||
@@ -203,6 +209,7 @@ else ifeq ($(platform), rpi2)
|
||||
CXXFLAGS = $(CFLAGS) -fno-rtti -fno-exceptions
|
||||
CPU_ARCH := arm
|
||||
ARM = 1
|
||||
HAVE_ARMv6 = 1
|
||||
|
||||
# Raspberry Pi 3
|
||||
else ifeq ($(platform), rpi3)
|
||||
@@ -215,6 +222,7 @@ else ifeq ($(platform), rpi3)
|
||||
CXXFLAGS = $(CFLAGS) -fno-rtti -fno-exceptions
|
||||
CPU_ARCH := arm
|
||||
ARM = 1
|
||||
HAVE_ARMv6 = 1
|
||||
|
||||
# Raspberry Pi 3 (AArch64)
|
||||
else ifeq ($(platform), rpi3_64)
|
||||
@@ -238,6 +246,7 @@ else ifeq ($(platform), rpi4)
|
||||
CXXFLAGS = $(CFLAGS) -fno-rtti -fno-exceptions
|
||||
CPU_ARCH := arm
|
||||
ARM = 1
|
||||
HAVE_ARMv6 = 1
|
||||
|
||||
# Raspberry Pi 4 (AArch64)
|
||||
else ifeq ($(platform), rpi4_64)
|
||||
@@ -270,6 +279,7 @@ else ifeq ($(platform), classic_armv7_a7)
|
||||
ARCH = arm
|
||||
CPU_ARCH := arm
|
||||
ARM = 1
|
||||
HAVE_ARMv6 = 1
|
||||
ifeq ($(shell echo `$(CC) -dumpversion` "< 4.9" | bc -l), 1)
|
||||
CFLAGS += -march=armv7-a
|
||||
else
|
||||
@@ -300,6 +310,7 @@ else ifeq ($(platform), s812)
|
||||
ARCH = arm
|
||||
CPU_ARCH := arm
|
||||
ARM = 1
|
||||
HAVE_ARMv6 = 1
|
||||
|
||||
# Playstation Classic
|
||||
else ifeq ($(platform), classic_armv8_a35)
|
||||
@@ -321,6 +332,7 @@ else ifeq ($(platform), classic_armv8_a35)
|
||||
ARCH = arm
|
||||
CPU_ARCH := arm
|
||||
ARM = 1
|
||||
HAVE_ARMv6 = 1
|
||||
CFLAGS += -march=armv8-a
|
||||
LDFLAGS += -static-libgcc -static-libstdc++
|
||||
|
||||
@@ -378,13 +390,15 @@ else ifeq ($(platform), ngc)
|
||||
|
||||
# Nintendo Wii
|
||||
else ifeq ($(platform), wii)
|
||||
TARGET = $(TARGET_NAME)_libretro_$(platform).a
|
||||
TARGET = $(TARGET_NAME)_$(INCLUDE_DRV)_libretro_$(platform).a
|
||||
BIGENDIAN = 1
|
||||
CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT)
|
||||
AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT)
|
||||
PLATCFLAGS += -DGEKKO -mrvl -mcpu=750 -meabi -mhard-float -D__ppc__ -D__POWERPC__
|
||||
PLATCFLAGS += -U__INT32_TYPE__ -U __UINT32_TYPE__ -D__INT32_TYPE__=int
|
||||
PLATCFLAGS += -D$(INCLUDE_DRV) -DSPLIT_CORE
|
||||
STATIC_LINKING = 1
|
||||
ZLIB_UNCOMPRESS = 1
|
||||
|
||||
# Nintendo WiiU
|
||||
else ifeq ($(platform), wiiu)
|
||||
@@ -393,7 +407,7 @@ else ifeq ($(platform), wiiu)
|
||||
CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT)
|
||||
AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT)
|
||||
PLATCFLAGS += -DGEKKO -DWIIU -mcpu=750 -meabi -mhard-float -D__ppc__ -D__POWERPC__
|
||||
PLATCFLAGS += -U__INT32_TYPE__ -U __UINT32_TYPE__ -D__INT32_TYPE__=int
|
||||
PLATCFLAGS += -ffunction-sections -fdata-sections -D__wiiu__ -D__wut__
|
||||
STATIC_LINKING = 1
|
||||
|
||||
# Nintendo Switch (libnx)
|
||||
@@ -450,6 +464,7 @@ else ifeq ($(platform), psp1)
|
||||
AR = psp-ar$(EXE_EXT)
|
||||
PLATCFLAGS += -DPSP
|
||||
CFLAGS += -G0
|
||||
CFLAGS += -Wno-incompatible-pointer-types
|
||||
STATIC_LINKING = 1
|
||||
|
||||
# Vita
|
||||
@@ -467,6 +482,7 @@ else ifeq ($(platform), vita)
|
||||
CXXFLAGS = $(CFLAGS) -fno-rtti -fno-exceptions
|
||||
HAVE_RZLIB := 1
|
||||
ARM = 1
|
||||
HAVE_ARMv6 = 1
|
||||
STATIC_LINKING := 1
|
||||
USE_CYCLONE := 1
|
||||
USE_DRZ80 := 1
|
||||
@@ -519,11 +535,14 @@ else ifeq ($(platform), miyoo)
|
||||
CC = /opt/miyoo/usr/bin/arm-linux-gcc
|
||||
CXX = /opt/miyoo/usr/bin/arm-linux-g++
|
||||
AR = /opt/miyoo/usr/bin/arm-linux-ar
|
||||
fpic := -fPIC
|
||||
fpic := -fno-PIC
|
||||
LDFLAGS += -shared -Wl,--version-script=link.T -Wl,-no-undefined
|
||||
PLATCFLAGS := -DNO_UNALIGNED_ACCESS
|
||||
PLATCFLAGS += -fomit-frame-pointer -march=armv5te -mtune=arm926ej-s -ffast-math
|
||||
CXXFLAGS += -fno-rtti -fno-exceptions
|
||||
ARM = 1
|
||||
USE_CYCLONE := 1
|
||||
USE_DRZ80 := 1
|
||||
|
||||
# Emscripten
|
||||
else ifeq ($(platform), emscripten)
|
||||
@@ -752,7 +771,11 @@ else ifneq (,$(findstring windows_msvc2017,$(platform)))
|
||||
else
|
||||
TARGET := $(TARGET_NAME)_libretro.dll
|
||||
CC ?= gcc
|
||||
LDFLAGS += -shared -static-libgcc -static-libstdc++ -s -Wl,--version-script=link.T
|
||||
LDFLAGS += -shared -static-libgcc -static-libstdc++
|
||||
ifneq ($(DEBUG), 1)
|
||||
LDFLAGS += -s
|
||||
endif
|
||||
LDFLAGS += -Wl,--version-script=link.T
|
||||
CFLAGS += -D__WIN32__
|
||||
endif
|
||||
|
||||
@@ -802,6 +825,19 @@ CFLAGS += -DHAVE_SOCKLEN_T
|
||||
CFLAGS += -D_LARGEFILE_SOURCE
|
||||
CFLAGS += -D_FILE_OFFSET_BITS=64
|
||||
|
||||
# make gcc fail like msvc does
|
||||
ifeq (,$(findstring msvc,$(platform)))
|
||||
CFLAGS += -Werror=vla -Werror=declaration-after-statement
|
||||
endif
|
||||
|
||||
# no fused multiply-add: a*b+c rounded once (FMA) on AArch64, ARMv7 VFPv4
|
||||
# and PowerPC gives other results than x86, where it is rounded twice;
|
||||
# with it off the floating point results are the same on every host
|
||||
# (netplay between them, save states and RunAhead)
|
||||
ifeq (,$(findstring msvc,$(platform)))
|
||||
CFLAGS += -ffp-contract=off
|
||||
endif
|
||||
|
||||
# Required for RZIP support in cheat.c
|
||||
CFLAGS += -DHAVE_ZLIB
|
||||
|
||||
@@ -834,8 +870,34 @@ else
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_ARMv6),1)
|
||||
CFLAGS += -DHAVE_ARMv6
|
||||
endif
|
||||
|
||||
# threads (libretro-common rthreads), as the other libretro cores do (beetle-psx):
|
||||
# on by default, off where there is no thread library, and on the MSVC builds
|
||||
# (the ST-V threaded video needs MSVC 2015's thread-local storage, the
|
||||
# buildbot's MSVC lanes are 2005 and 2010: nothing would use the threads)
|
||||
HAVE_THREADS ?= 1
|
||||
ifneq (,$(filter $(platform), emscripten linux-portable ngc wii wiiu ps2 ps3 psl1ght psp1 ctr vita))
|
||||
HAVE_THREADS = 0
|
||||
endif
|
||||
ifneq (,$(findstring msvc,$(platform)))
|
||||
HAVE_THREADS = 0
|
||||
endif
|
||||
ifeq ($(HAVE_THREADS),1)
|
||||
# pthreads are in the C library on Darwin and Android, Windows uses its own threads
|
||||
ifeq (,$(findstring msvc,$(platform))$(findstring android,$(platform))$(findstring ios,$(platform))$(findstring tvos,$(platform))$(filter osx win,$(platform)))
|
||||
LIBS += -lpthread
|
||||
endif
|
||||
endif
|
||||
|
||||
# include the various .mak files
|
||||
include Makefile.common
|
||||
ifneq (,$(filter $(INCLUDE_DRV),all))
|
||||
include Makefile.common
|
||||
else
|
||||
include Makefile.split
|
||||
endif
|
||||
|
||||
# build the targets in different object dirs, since mess changes
|
||||
# some structures and thus they can't be linked against each other.
|
||||
@@ -844,9 +906,9 @@ DEFS = $(COREDEFINES) -Dasm=__asm__
|
||||
CFLAGS += $(INCFLAGS) $(INCFLAGS_PLATFORM)
|
||||
|
||||
# combine the various definitions to one
|
||||
CDEFS = $(DEFS) $(COREDEFS) $(CPUDEFS) $(SOUNDDEFS) $(ASMDEFS) $(DBGDEFS)
|
||||
CDEFS = $(DEFS) $(CPUDEFS) $(SOUNDDEFS) $(ASMDEFS) $(DBGDEFS)
|
||||
|
||||
OBJECTS := $(SOURCES_C:.c=.o) $(SOURCES_ASM:.s=.o)
|
||||
OBJECTS := $(SOURCES_C:.c=.o) $(SOURCES_ASM:.s=.o) $(SOURCES_ASM_PP:.S=.o)
|
||||
|
||||
OBJOUT = -o
|
||||
LINKOUT = -o
|
||||
@@ -914,3 +976,18 @@ ifeq ($(SPLIT_UP_LINK), 1)
|
||||
@rm $@.in
|
||||
endif
|
||||
$(HIDE)rm -f $(OBJECTS) $(TARGET)
|
||||
# 1. Map object files to dependency trackers
|
||||
DEPFILES := $(OBJECTS:.o=.d)
|
||||
|
||||
# 2. ONLY read or handle dependencies if we are NOT running a clean command
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
-include $(DEPFILES)
|
||||
|
||||
# 3. FIXED: Generate a pure, clean dependency file directly using the -MM flag
|
||||
%.d: %.c
|
||||
@echo "Generating dependency tracker for $<..."
|
||||
$(HIDE)$(CC) -MM -MP -MT $(@:.d=.o) -MF $@ $< $(CFLAGS)
|
||||
|
||||
# 4. Fallback stub to prevent build errors if a header file is deleted
|
||||
$(DEPFILES):
|
||||
endif
|
||||
+216
-26
@@ -68,6 +68,8 @@ SOURCES_C += \
|
||||
$(CORE_DIR)/x86drc.c
|
||||
|
||||
SOURCES_C += \
|
||||
$(CORE_DIR)/machine/fd1089.c \
|
||||
$(CORE_DIR)/machine/fd1094.c \
|
||||
$(CORE_DIR)/machine/6522via.c \
|
||||
$(CORE_DIR)/machine/6532riot.c \
|
||||
$(CORE_DIR)/machine/6821pia.c \
|
||||
@@ -78,6 +80,9 @@ SOURCES_C += \
|
||||
$(CORE_DIR)/machine/8255ppi.c \
|
||||
$(CORE_DIR)/machine/eeprom.c \
|
||||
$(CORE_DIR)/machine/idectrl.c \
|
||||
$(CORE_DIR)/machine/intelfsh.c \
|
||||
$(CORE_DIR)/machine/ds2404.c \
|
||||
$(CORE_DIR)/machine/ataflash.c \
|
||||
$(CORE_DIR)/machine/mathbox.c \
|
||||
$(CORE_DIR)/machine/mb87078.c \
|
||||
$(CORE_DIR)/machine/random.c \
|
||||
@@ -94,7 +99,8 @@ SOURCES_C += \
|
||||
$(CORE_DIR)/vidhrdw/matrix3d.c \
|
||||
$(CORE_DIR)/vidhrdw/poly.c \
|
||||
$(CORE_DIR)/vidhrdw/tlc34076.c \
|
||||
$(CORE_DIR)/vidhrdw/vector.c
|
||||
$(CORE_DIR)/vidhrdw/vector.c \
|
||||
$(CORE_DIR)/vidhrdw/resnet.c
|
||||
|
||||
# the core object files (without target specific objects;
|
||||
# those are added in the target.mak files)
|
||||
@@ -125,6 +131,7 @@ CPUS+=I186@
|
||||
CPUS+=V20@
|
||||
CPUS+=V30@
|
||||
CPUS+=V33@
|
||||
CPUS+=V25@
|
||||
CPUS+=V60@
|
||||
CPUS+=V70@
|
||||
CPUS+=I8035@
|
||||
@@ -132,6 +139,7 @@ CPUS+=I8039@
|
||||
CPUS+=I8048@
|
||||
CPUS+=N7751@
|
||||
CPUS+=I8X41@
|
||||
CPUS+=I8051@
|
||||
CPUS+=M6800@
|
||||
CPUS+=M6801@
|
||||
CPUS+=M6802@
|
||||
@@ -164,23 +172,35 @@ CPUS+=TMS9995@
|
||||
CPUS+=Z8000@
|
||||
CPUS+=TMS32010@
|
||||
CPUS+=TMS32025@
|
||||
CPUS+=NAMCOC71@
|
||||
CPUS+=TMS32031@
|
||||
CPUS+=I960@
|
||||
CPUS+=MB86233@
|
||||
CPUS+=MB86235@
|
||||
CPUS+=ADSP21062@
|
||||
CPUS+=CCPU@
|
||||
CPUS+=ADSP2100@
|
||||
CPUS+=ADSP2101@
|
||||
CPUS+=ADSP2104@
|
||||
CPUS+=ADSP2105@
|
||||
CPUS+=ADSP2115@
|
||||
CPUS+=ADSP2181@
|
||||
CPUS+=PSXCPU@
|
||||
CPUS+=H83002@
|
||||
CPUS+=I386@
|
||||
CPUS+=MN10200@
|
||||
CPUS+=M37702@
|
||||
CPUS+=ASAP@
|
||||
CPUS+=UPD7810@
|
||||
CPUS+=UPD7807@
|
||||
CPUS+=ARM@
|
||||
CPUS+=ARM7@
|
||||
CPUS+=JAGUAR@
|
||||
CPUS+=R3000@
|
||||
CPUS+=R4600@
|
||||
CPUS+=R5000@
|
||||
CPUS+=SH2@
|
||||
CPUS+=SH3@
|
||||
CPUS+=DSP32C@
|
||||
#CPUS+=PIC16C54@
|
||||
CPUS+=PIC16C55@
|
||||
@@ -241,6 +261,7 @@ SOUNDS+=SEGAPCM@
|
||||
SOUNDS+=RF5C68@
|
||||
SOUNDS+=CEM3394@
|
||||
SOUNDS+=C140@
|
||||
SOUNDS+=C352@
|
||||
SOUNDS+=QSOUND@
|
||||
SOUNDS+=SAA1099@
|
||||
SOUNDS+=IREMGA20@
|
||||
@@ -365,7 +386,7 @@ SOURCES_C += \
|
||||
$(CORE_DIR)/vidhrdw/gridlee_vidhrdw.c $(CORE_DIR)/sndhrdw/gridlee_sndhrdw.c $(CORE_DIR)/drivers/gridlee.c \
|
||||
$(CORE_DIR)/drivers/seattle.c $(CORE_DIR)/vidhrdw/voodoo_vidhrdw.c \
|
||||
$(CORE_DIR)/vidhrdw/exterm_vidhrdw.c $(CORE_DIR)/drivers/exterm.c \
|
||||
$(CORE_DIR)/machine/midwayic.c $(CORE_DIR)/sndhrdw/dcs.c \
|
||||
$(CORE_DIR)/machine/midwayic.c $(CORE_DIR)/machine/smc91c9x.c $(CORE_DIR)/sndhrdw/dcs.c \
|
||||
$(CORE_DIR)/machine/midyunit_machine.c $(CORE_DIR)/vidhrdw/midyunit_vidhrdw.c $(CORE_DIR)/drivers/midyunit.c \
|
||||
$(CORE_DIR)/drivers/midxunit.c \
|
||||
$(CORE_DIR)/machine/midwunit_machine.c $(CORE_DIR)/drivers/midwunit.c \
|
||||
@@ -422,7 +443,6 @@ SOURCES_C += \
|
||||
$(CORE_DIR)/vidhrdw/topspeed_vidhrdw.c $(CORE_DIR)/drivers/topspeed.c \
|
||||
$(CORE_DIR)/machine/arkanoid_machine.c $(CORE_DIR)/vidhrdw/arkanoid_vidhrdw.c $(CORE_DIR)/drivers/arkanoid.c \
|
||||
$(CORE_DIR)/vidhrdw/superqix_vidhrdw.c $(CORE_DIR)/drivers/superqix.c \
|
||||
$(CORE_DIR)/vidhrdw/pbillian_vidhrdw.c $(CORE_DIR)/drivers/pbillian.c $(CORE_DIR)/sndhrdw/pbillian_sndhrdw.c \
|
||||
$(CORE_DIR)/vidhrdw/exzisus_vidhrdw.c $(CORE_DIR)/drivers/exzisus.c \
|
||||
$(CORE_DIR)/drivers/taito_x.c $(CORE_DIR)/machine/cchip.c \
|
||||
$(CORE_DIR)/vidhrdw/minivadr_vidhrdw.c $(CORE_DIR)/drivers/minivadr.c \
|
||||
@@ -479,8 +499,9 @@ SOURCES_C += \
|
||||
$(CORE_DIR)/machine/kabuki.c \
|
||||
$(CORE_DIR)/vidhrdw/mitchell_vidhrdw.c $(CORE_DIR)/drivers/mitchell.c \
|
||||
$(CORE_DIR)/vidhrdw/cbasebal_vidhrdw.c $(CORE_DIR)/drivers/cbasebal.c \
|
||||
$(CORE_DIR)/vidhrdw/cps1_vidhrdw.c $(CORE_DIR)/drivers/cps1.c $(CORE_DIR)/drivers/cps2.c \
|
||||
$(CORE_DIR)/drivers/zn.c \
|
||||
$(CORE_DIR)/vidhrdw/cps1_vidhrdw.c $(CORE_DIR)/drivers/cps1.c $(CORE_DIR)/drivers/cps2.c $(CORE_DIR)/machine/cps2crypt.c\
|
||||
$(CORE_DIR)/drivers/zn.c $(CORE_DIR)/sndhrdw/acclaim_rax.c $(CORE_DIR)/sndhrdw/taitozoom.c $(CORE_DIR)/sound/zsg2.c $(CORE_DIR)/cpu/tms57002/tms57002.c \
|
||||
$(CORE_DIR)/drivers/cps3.c $(CORE_DIR)/sndhrdw/cps3_sndhrdw.c \
|
||||
$(CORE_DIR)/vidhrdw/tms34061_vidhrdw.c \
|
||||
$(CORE_DIR)/machine/capbowl_machine.c $(CORE_DIR)/vidhrdw/capbowl_vidhrdw.c $(CORE_DIR)/drivers/capbowl.c \
|
||||
$(CORE_DIR)/vidhrdw/itech8_vidhrdw.c $(CORE_DIR)/drivers/itech8.c \
|
||||
@@ -502,16 +523,17 @@ SOURCES_C += \
|
||||
$(CORE_DIR)/vidhrdw/system1_vidhrdw.c $(CORE_DIR)/drivers/system1.c \
|
||||
$(CORE_DIR)/vidhrdw/segasyse_vidhrdw.c $(CORE_DIR)/drivers/segasyse.c \
|
||||
$(CORE_DIR)/machine/system16_machine.c $(CORE_DIR)/vidhrdw/system16_vidhrdw.c $(CORE_DIR)/vidhrdw/sys16spr.c \
|
||||
$(CORE_DIR)/sndhrdw/system16_sndhrdw.c \
|
||||
$(CORE_DIR)/drivers/system16.c $(CORE_DIR)/drivers/aburner.c $(CORE_DIR)/drivers/outrun.c \
|
||||
$(CORE_DIR)/vidhrdw/segaic16.c $(CORE_DIR)/vidhrdw/segas16b.c $(CORE_DIR)/vidhrdw/segaorun.c $(CORE_DIR)/drivers/segas16b.c \
|
||||
$(CORE_DIR)/sndhrdw/system16_sndhrdw.c $(CORE_DIR)/machine/segaic16.c $(CORE_DIR)/vidhrdw/segaxbd.c\
|
||||
$(CORE_DIR)/drivers/system16.c $(CORE_DIR)/drivers/aburner.c $(CORE_DIR)/drivers/outrun.c $(CORE_DIR)/drivers/segaxbd.c \
|
||||
$(CORE_DIR)/drivers/sharrier.c $(CORE_DIR)/drivers/system18.c \
|
||||
$(CORE_DIR)/drivers/system24.c $(CORE_DIR)/machine/system24_machine.c $(CORE_DIR)/vidhrdw/system24_vidhrdw.c \
|
||||
$(CORE_DIR)/vidhrdw/segaic24.c \
|
||||
$(CORE_DIR)/drivers/system32.c $(CORE_DIR)/drivers/multi32.c $(CORE_DIR)/vidhrdw/system32_vidhrdw.c \
|
||||
$(CORE_DIR)/vidhrdw/segac2_vidhrdw.c $(CORE_DIR)/drivers/segac2.c \
|
||||
$(CORE_DIR)/vidhrdw/segaic24.c $(CORE_DIR)/vidhrdw/segas18.c \
|
||||
$(CORE_DIR)/drivers/segas32.c $(CORE_DIR)/machine/segas32.c $(CORE_DIR)/vidhrdw/segas32.c \
|
||||
$(CORE_DIR)/vidhrdw/segavdp.c $(CORE_DIR)/vidhrdw/segac2_vidhrdw.c $(CORE_DIR)/machine/megadriv.c $(CORE_DIR)/drivers/segac2.c $(CORE_DIR)/drivers/megaplay.c $(CORE_DIR)/drivers/megatech.c $(CORE_DIR)/drivers/megadriv_acbl.c $(CORE_DIR)/drivers/megadriv_ybox.c $(CORE_DIR)/drivers/megadriv_sunmix.c \
|
||||
$(CORE_DIR)/drivers/stv.c $(CORE_DIR)/drivers/stvhacks.c $(CORE_DIR)/machine/stvcd.c \
|
||||
$(CORE_DIR)/machine/scudsp.c \
|
||||
$(CORE_DIR)/vidhrdw/stvvdp1_vidhrdw.c $(CORE_DIR)/vidhrdw/stvvdp2_vidhrdw.c \
|
||||
$(CORE_DIR)/vidhrdw/stvvid.c \
|
||||
$(CORE_DIR)/vidhrdw/deniam_vidhrdw.c $(CORE_DIR)/drivers/deniam.c \
|
||||
$(CORE_DIR)/machine/btime_machine.c $(CORE_DIR)/vidhrdw/btime_vidhrdw.c $(CORE_DIR)/drivers/btime.c \
|
||||
$(CORE_DIR)/machine/decocass_machine.c $(CORE_DIR)/vidhrdw/decocass_vidhrdw.c $(CORE_DIR)/drivers/decocass.c \
|
||||
@@ -803,6 +825,7 @@ SOURCES_C += \
|
||||
$(CORE_DIR)/vidhrdw/raiden_vidhrdw.c $(CORE_DIR)/drivers/raiden.c $(CORE_DIR)/drivers/raiden2.c \
|
||||
$(CORE_DIR)/vidhrdw/dcon_vidhrdw.c $(CORE_DIR)/drivers/dcon.c \
|
||||
$(CORE_DIR)/vidhrdw/sengokmj_vidhrdw.c $(CORE_DIR)/drivers/sengokmj.c \
|
||||
$(CORE_DIR)/machine/seibuspi_machine.c $(CORE_DIR)/vidhrdw/seibuspi_vidhrdw.c $(CORE_DIR)/drivers/seibuspi.c \
|
||||
$(CORE_DIR)/sndhrdw/t5182.c \
|
||||
$(CORE_DIR)/vidhrdw/mustache_vidhrdw.c $(CORE_DIR)/drivers/mustache.c \
|
||||
$(CORE_DIR)/vidhrdw/darkmist_vidhrdw.c $(CORE_DIR)/drivers/darkmist.c \
|
||||
@@ -1040,9 +1063,17 @@ SOURCES_C += \
|
||||
$(CORE_DIR)/drivers/n8080.c \
|
||||
$(CORE_DIR)/drivers/mirax.c \
|
||||
$(CORE_DIR)/machine/model1_machine.c $(CORE_DIR)/vidhrdw/model1_vidhrdw.c $(CORE_DIR)/drivers/model1.c \
|
||||
$(CORE_DIR)/machine/model2_machine.c $(CORE_DIR)/vidhrdw/model2_vidhrdw.c $(CORE_DIR)/drivers/model2.c \
|
||||
$(CORE_DIR)/sndhrdw/segadsb.c $(CORE_DIR)/sound/mpeg_audio.c \
|
||||
$(CORE_DIR)/drivers/cv1k.c $(CORE_DIR)/vidhrdw/cv1k_vidhrdw.c $(CORE_DIR)/sound/ymz770.c \
|
||||
$(CORE_DIR)/machine/sega315_5881.c $(CORE_DIR)/machine/sega315_5838.c \
|
||||
$(CORE_DIR)/drivers/calorie.c \
|
||||
$(CORE_DIR)/drivers/hvyunit.c \
|
||||
$(CORE_DIR)/drivers/akkaarrh.c \
|
||||
$(CORE_DIR)/machine/mc8123.c \
|
||||
$(CORE_DIR)/machine/namcoio_machine.c
|
||||
$(CORE_DIR)/machine/namcoio_machine.c \
|
||||
$(CORE_DIR)/drivers/tatsumi.c $(CORE_DIR)/vidhrdw/tatsumi.c $(CORE_DIR)/machine/tatsumi.c \
|
||||
$(CORE_DIR)/drivers/tx1.c $(CORE_DIR)/vidhrdw/tx1_vidhrdw.c $(CORE_DIR)/machine/tx1_machine.c $(CORE_DIR)/sndhrdw/tx1_sndhrdw.c
|
||||
|
||||
|
||||
|
||||
@@ -1089,6 +1120,14 @@ else
|
||||
CPUDEFS += -DHAS_ADSP2115=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring ADSP2181@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
CPUDEFS += -DHAS_ADSP2181=1
|
||||
HAS_ADSP2100 = 1
|
||||
else
|
||||
CPUDEFS += -DHAS_ADSP2181=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring Z80@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
CPUDEFS += -DHAS_Z80=1
|
||||
@@ -1345,6 +1384,15 @@ else
|
||||
CPUDEFS += -DHAS_V33=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring V25@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/nec
|
||||
CPUDEFS += -DHAS_V25=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/nec/v25.c
|
||||
else
|
||||
CPUDEFS += -DHAS_V25=0
|
||||
endif
|
||||
|
||||
ifeq ($(HAS_V30),1)
|
||||
SOURCES_C += $(CORE_DIR)/cpu/nec/nec.c
|
||||
ifeq ($(DEBUGGER),1)
|
||||
@@ -1429,6 +1477,15 @@ else
|
||||
CPUDEFS += -DHAS_I8X41=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring I8051@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/i8051
|
||||
CPUDEFS += -DHAS_I8051=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/i8051/i8051.c
|
||||
else
|
||||
CPUDEFS += -DHAS_I8051=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring M6800@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/m6800
|
||||
@@ -1810,6 +1867,15 @@ else
|
||||
CPUDEFS += -DHAS_TMS32010=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring NAMCOC71@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/namcoc71
|
||||
CPUDEFS += -DHAS_NAMCOC71=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/namcoc71/c71.c
|
||||
else
|
||||
CPUDEFS += -DHAS_NAMCOC71=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring TMS32025@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/tms32025
|
||||
@@ -1822,6 +1888,42 @@ else
|
||||
CPUDEFS += -DHAS_TMS32025=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring MB86233@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/mb86233
|
||||
CPUDEFS += -DHAS_MB86233=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/mb86233/mb86233.c
|
||||
else
|
||||
CPUDEFS += -DHAS_MB86233=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring MB86235@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/mb86235
|
||||
CPUDEFS += -DHAS_MB86235=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/mb86235/mb86235.c
|
||||
else
|
||||
CPUDEFS += -DHAS_MB86235=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring ADSP21062@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/sharc
|
||||
CPUDEFS += -DHAS_ADSP21062=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/sharc/sharc.c
|
||||
else
|
||||
CPUDEFS += -DHAS_ADSP21062=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring I960@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/i960
|
||||
CPUDEFS += -DHAS_I960=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/i960/i960.c
|
||||
else
|
||||
CPUDEFS += -DHAS_I960=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring TMS32031@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/tms32031
|
||||
@@ -1859,6 +1961,42 @@ else
|
||||
CPUDEFS += -DHAS_PSXCPU=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring H83002@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/h83002
|
||||
CPUDEFS += -DHAS_H83002=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/h83002/h83002.c
|
||||
else
|
||||
CPUDEFS += -DHAS_H83002=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring I386@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/i386
|
||||
CPUDEFS += -DHAS_I386=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/i386/i386.c
|
||||
else
|
||||
CPUDEFS += -DHAS_I386=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring MN10200@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/mn10200
|
||||
CPUDEFS += -DHAS_MN10200=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/mn10200/mn10200.c
|
||||
else
|
||||
CPUDEFS += -DHAS_MN10200=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring M37702@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/m37710
|
||||
CPUDEFS += -DHAS_M37702=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/m37710/m37710.c $(CORE_DIR)/cpu/m37710/m37710o0.c $(CORE_DIR)/cpu/m37710/m37710o1.c $(CORE_DIR)/cpu/m37710/m37710o2.c $(CORE_DIR)/cpu/m37710/m37710o3.c
|
||||
else
|
||||
CPUDEFS += -DHAS_M37702=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring ASAP@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/asap
|
||||
@@ -1908,6 +2046,15 @@ else
|
||||
CPUDEFS += -DHAS_ARM=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring ARM7@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/arm7
|
||||
CPUDEFS += -DHAS_ARM7=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/arm7/arm7.c
|
||||
else
|
||||
CPUDEFS += -DHAS_ARM7=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring JAGUAR@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/jaguar
|
||||
@@ -1972,6 +2119,15 @@ else
|
||||
CPUDEFS += -DHAS_SH2=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring SH3@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/sh3
|
||||
CPUDEFS += -DHAS_SH3=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/sh3/sh3.c
|
||||
else
|
||||
CPUDEFS += -DHAS_SH3=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring DSP32C@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/dsp32
|
||||
@@ -2504,6 +2660,14 @@ else
|
||||
SOUNDDEFS += -DHAS_C140=0
|
||||
endif
|
||||
|
||||
SOUND=$(strip $(findstring C352@,$(SOUNDS)))
|
||||
ifneq ($(SOUND),)
|
||||
SOUNDDEFS += -DHAS_C352=1
|
||||
SOURCES_C += $(CORE_DIR)/sound/c352.c
|
||||
else
|
||||
SOUNDDEFS += -DHAS_C352=0
|
||||
endif
|
||||
|
||||
SOUND=$(strip $(findstring QSOUND@,$(SOUNDS)))
|
||||
ifneq ($(SOUND),)
|
||||
SOUNDDEFS += -DHAS_QSOUND=1
|
||||
@@ -2657,9 +2821,19 @@ SOUNDDEFS += -DHAS_ICS2115=0
|
||||
endif
|
||||
|
||||
SOURCES_C += \
|
||||
$(CORE_DIR)/lib/mame-chd/chd.c \
|
||||
$(CORE_DIR)/lib/mame-chd/mame_sha1.c
|
||||
|
||||
# libchdr: reads the hard disk CHDs (every version, zlib/LZMA/Huffman/FLAC)
|
||||
SOURCES_C += \
|
||||
$(CORE_DIR)/lib/libchdr/src/libchdr_bitstream.c \
|
||||
$(CORE_DIR)/lib/libchdr/src/libchdr_cdrom.c \
|
||||
$(CORE_DIR)/lib/libchdr/src/libchdr_chd.c \
|
||||
$(CORE_DIR)/lib/libchdr/src/libchdr_flac.c \
|
||||
$(CORE_DIR)/lib/libchdr/src/libchdr_huffman.c \
|
||||
$(CORE_DIR)/lib/libchdr/deps/lzma/LzFind.c \
|
||||
$(CORE_DIR)/lib/libchdr/deps/lzma/LzmaDec.c \
|
||||
$(CORE_DIR)/lib/libchdr/deps/lzma/LzmaEnc.c
|
||||
|
||||
SOURCES_C += \
|
||||
$(CORE_DIR)/libretro-deps/libFLAC/bitreader.c \
|
||||
$(CORE_DIR)/libretro-deps/libFLAC/cpu.c \
|
||||
@@ -2673,6 +2847,28 @@ SOURCES_C += \
|
||||
$(CORE_DIR)/libretro-deps/libFLAC/stream_decoder.c \
|
||||
$(CORE_DIR)/libretro-deps/libFLAC/window.c
|
||||
|
||||
SOURCES_C += \
|
||||
$(CORE_DIR)/lib/zlib/adler32.c \
|
||||
$(CORE_DIR)/lib/zlib/crc32.c \
|
||||
$(CORE_DIR)/lib/zlib/deflate.c \
|
||||
$(CORE_DIR)/lib/zlib/inffast.c \
|
||||
$(CORE_DIR)/lib/zlib/inflate.c \
|
||||
$(CORE_DIR)/lib/zlib/inftrees.c \
|
||||
$(CORE_DIR)/lib/zlib/ioapi.c \
|
||||
$(CORE_DIR)/lib/zlib/trees.c \
|
||||
$(CORE_DIR)/lib/zlib/uncompr.c \
|
||||
$(CORE_DIR)/lib/zlib/unzip.c \
|
||||
$(CORE_DIR)/lib/zlib/zutil.c
|
||||
|
||||
# sljit: run-time code generator of the MIPS recompilers (empty where they are not supported)
|
||||
SOURCES_C += $(CORE_DIR)/lib/sljit/sljit_mame.c
|
||||
|
||||
# threads (libretro-common rthreads, set by the platform: see Makefile): the ST-V threaded video option
|
||||
ifeq ($(HAVE_THREADS),1)
|
||||
COREDEFINES += -DHAVE_THREADS
|
||||
SOURCES_C += $(LIBRETRO_COMM_DIR)/rthreads/rthreads.c
|
||||
endif
|
||||
|
||||
ifeq ($(STATIC_LINKING),1)
|
||||
else
|
||||
SOURCES_C += \
|
||||
@@ -2697,23 +2893,17 @@ SOURCES_C += \
|
||||
$(LIBRETRO_COMM_DIR)/string/stdstring.c \
|
||||
$(LIBRETRO_COMM_DIR)/utils/md5.c \
|
||||
$(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.c \
|
||||
$(LIBRETRO_COMM_DIR)/time/rtime.c \
|
||||
$(CORE_DIR)/lib/zlib/adler32.c \
|
||||
$(CORE_DIR)/lib/zlib/crc32.c \
|
||||
$(CORE_DIR)/lib/zlib/deflate.c \
|
||||
$(CORE_DIR)/lib/zlib/inffast.c \
|
||||
$(CORE_DIR)/lib/zlib/inflate.c \
|
||||
$(CORE_DIR)/lib/zlib/inftrees.c \
|
||||
$(CORE_DIR)/lib/zlib/ioapi.c \
|
||||
$(CORE_DIR)/lib/zlib/trees.c \
|
||||
$(CORE_DIR)/lib/zlib/uncompr.c \
|
||||
$(CORE_DIR)/lib/zlib/unzip.c \
|
||||
$(CORE_DIR)/lib/zlib/zutil.c
|
||||
$(LIBRETRO_COMM_DIR)/time/rtime.c
|
||||
endif
|
||||
|
||||
ifeq ($(ZLIB_UNCOMPRESS), 1)
|
||||
SOURCES_C += \
|
||||
$(CORE_DIR)/lib/zlib/uncompr.c
|
||||
endif
|
||||
|
||||
ifeq ($(USE_CYCLONE), 1)
|
||||
CPUDEFS += -DHAS_CYCLONE=1
|
||||
SOURCES_ASM += $(CORE_DIR)/cpu/m68000_cyclone/cyclone.s
|
||||
SOURCES_ASM_PP += $(CORE_DIR)/cpu/m68000_cyclone/cyclone.S
|
||||
SOURCES_C += $(CORE_DIR)/cpu/m68000_cyclone/c68000.c
|
||||
endif
|
||||
|
||||
|
||||
+2806
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,115 @@
|
||||
# Capcom CPS-3: how the driver works and where it differs from the hardware
|
||||
|
||||
Sets: `redearth`, `warzard`, `sfiii`, `sfiii2`, `jojo`, `sfiii3`, `jojoba`
|
||||
and their clones (53 in all, MAME's list without the multi-game bootlegs),
|
||||
plus `sfiii4n`, the "4rd Arrange Edition 2013" hack of 3rd Strike that
|
||||
FBNeo has and MAME does not.
|
||||
|
||||
Files: `src/drivers/cps3.c` (memory map, flash SIMMs, video, DMA, sets),
|
||||
`src/sndhrdw/cps3_sndhrdw.c` (the 16 voice sample chip). A C89 port of
|
||||
current MAME's `cps3.cpp` and `cps3_a.cpp`.
|
||||
|
||||
## The board
|
||||
|
||||
- A custom Hitachi SH-2 at 25 MHz that decrypts what it reads from the BIOS,
|
||||
the program SIMMs and its cache RAM, with a per-game key stored in the
|
||||
cartridge.
|
||||
- The game in flash SIMMs: two SIMMs of 4 Fujitsu 29F016A chips (2 MB each)
|
||||
for the program, up to four SIMMs of 8 chips for graphics and samples.
|
||||
- 2D video: sprites with zoom, tilemaps drawn as sprites, a text layer,
|
||||
palette DMA with fades, character DMA with RLE decompression.
|
||||
- 16 voices of 8-bit samples read from the graphics SIMMs.
|
||||
- A SCSI CD-ROM drive: the BIOS writes the game from the CD into the SIMMs.
|
||||
|
||||
## No CD drive
|
||||
|
||||
The CD drive is not emulated. All sets run from SIMMs already written:
|
||||
|
||||
- The "NO CD" sets come with their SIMMs and a BIOS that does not look for a
|
||||
drive, as in MAME.
|
||||
- The CD sets (Europe, USA, Japan, Asia, Hispanic versions) get the SIMM data
|
||||
of their version, the same as the NO CD set of that date (the SIMM
|
||||
contents do not depend on the region, the BIOS does). As in FBNeo, which
|
||||
plays them the same way. MAME needs the CD image instead.
|
||||
- The CD BIOSes would stop on the missing drive. The BIOS has a flag the
|
||||
no-CD BIOSes have set (byte 0x1fecc, bit 0); the driver sets it, and the
|
||||
game runs from the SIMMs.
|
||||
- The Red Earth / Warzard CD BIOSes have no such flag: the driver starts the
|
||||
game from the SIMMs as the BIOS would (PC and SP from the program's vector
|
||||
table, VBR on it), as FBNeo does.
|
||||
|
||||
The flash chips answer the Fujitsu command set (ID, program, erase), but
|
||||
what is written to them is not saved: no set writes them while playing.
|
||||
|
||||
## Region
|
||||
|
||||
The region is not a switch on the board: it is a byte in the cart's flash
|
||||
(the low nibble of the BIOS byte 0x1fecb, 0x1fedb on Red Earth / Warzard),
|
||||
which the BIOS and the games read. A fake DIP switch, "Region", patches it at
|
||||
reset, as in FBNeo: Japan, Asia, Europe, USA, Hispanic, Brazil, Oceania or
|
||||
the second Asia code, or "As BIOS" to keep the dumped value. The default is
|
||||
Europe for every set, whatever region its BIOS has; 2nd Impact, which had no
|
||||
European release, defaults to USA. It changes the boot screen colour, the
|
||||
warnings, the coin settings, the language and the title (Warzard in Japan,
|
||||
Red Earth elsewhere). Change it, then reset.
|
||||
|
||||
The game options (coins, difficulty, monitor flip, language...) are in the
|
||||
games' own test menu (F2) and kept in the cart's EEPROM, saved as NVRAM.
|
||||
|
||||
## Encryption
|
||||
|
||||
The BIOS is decrypted at load. The program SIMMs are kept as dumped and also
|
||||
decrypted into a copy the CPU fetches opcodes from; data reads come out
|
||||
decrypted, as the custom CPU reads them. Two hooks in the SH-2 core (both
|
||||
optional, unused by the other SH-2 drivers) do this:
|
||||
|
||||
- `opcode_read`: the opcode fetch, from the BIOS, the decrypted program copy
|
||||
or the decrypted copy of the cache RAM.
|
||||
- `dma_read_hook`: the SH-2 DMA bypasses the decryption on the real board;
|
||||
the hook re-encrypts what the handlers decrypted.
|
||||
|
||||
`sfiii2` runs off a "dead" cartridge: the key is gone and its program is
|
||||
stored with code encrypted and data not, as in MAME.
|
||||
|
||||
## Video
|
||||
|
||||
The renderer is MAME's: sprites and tilemaps go to a render buffer of
|
||||
palette indexes (with the shadow/highlight blend bits), which is copied to the
|
||||
screen through the full screen zoom; the text layer is drawn on top. Tiles
|
||||
are read straight from the character RAM (no gfx elements to keep dirty).
|
||||
Colours are 15-bit with no extension of the low bits, as on the board (its
|
||||
video DAC has them grounded). The screen width follows the CRTC registers, as
|
||||
in MAME (384 pixels in the games checked).
|
||||
|
||||
## Idle loop
|
||||
|
||||
Each game waits for the vblank interrupt by reading a word of the main RAM
|
||||
in a loop. When the loop reads it, the CPU skips to the next event (the
|
||||
addresses are FBNeo's, one per game and version). Speed goes from about
|
||||
4.5x to 12-16x real time on an x86 core. The games run the same; only the
|
||||
attract mode can pick other fighters, since the games draw random numbers
|
||||
from the time spent in that loop.
|
||||
|
||||
## Sound
|
||||
|
||||
MAME's sound device: 16 voices, signed 8-bit samples, the board clock / 3 /
|
||||
384 (37.3 kHz), loop and end addresses, a volume per side. Levels checked
|
||||
against MAME's WAV output of the same attract mode.
|
||||
|
||||
## ROM loading of merged sets
|
||||
|
||||
Merged sets keep the files of the clones in subfolders of the parent's zip,
|
||||
with the same names (`sfiii3n/sfiii3-simm1.0`, `sfiii3nr1/sfiii3-simm1.0`).
|
||||
The ROM loader of this core matched by name only and took the first one.
|
||||
It now looks for the expected CRC first, then for the name, so merged,
|
||||
split and non-merged sets all load.
|
||||
|
||||
## Checked
|
||||
|
||||
- Attract mode of `sfiii3n`, `jojoba`, `sfiii2n`, `jojon`, `sfiiin`,
|
||||
`redearthn` against MAME 0.264 at the same frames: the same screens.
|
||||
- A game of 3rd Strike (coin, character select, fight).
|
||||
- CD sets: the regional warning screens, then the game (`sfiii3`, `sfiii3u`,
|
||||
`sfiiih`, `sfiii2`, `jojor2`, `jojobaner2`, `warzard`).
|
||||
- Save states: loaded in a new process, the game goes on frame for frame.
|
||||
- Big-endian: the PowerPC build renders as x86.
|
||||
@@ -0,0 +1,119 @@
|
||||
# Cave CV1000: how the driver works and where it differs from MAME
|
||||
|
||||
Sets (MAME's list without the touch screen mahjong game `mmmbanc`):
|
||||
|
||||
| Board | Sets |
|
||||
|---|---|
|
||||
| CV1000-B (8 MB RAM) | `mushisam`, `mushisama`, `mushisamb`, `ibara`, `ibarao`, `ibarablk`, `ibarablka`, `espgal2`, `espgal2a`, `espgal2b`, `mushitam`, `mushitama`, `pinkswts`, `pinkswtsa`, `pinkswtsb`, `pinkswtsx`, `pinkswtssc`, `futari15`, `futari15a`, `futari10`, `futaribl`, `futariblj`, `mmpork`, `deathsml` |
|
||||
| CV1000-D (16 MB RAM) | `dsmbl`, `ddpdfk`, `ddpdfk10`, `dfkbl` |
|
||||
|
||||
`futaribl` is the World / English set; the others are Japanese.
|
||||
|
||||
Files:
|
||||
|
||||
- `src/cpu/sh3/sh3.c`: the SH-3 (SH7709S) CPU and its peripherals.
|
||||
- `src/cpu/sh3/sh3jit.c`: the SH-3 recompiler, included by `sh3.c`.
|
||||
- `src/drivers/cv1k.c`: memory maps, NAND flash, RTC9701, inputs, sets.
|
||||
- `src/vidhrdw/cv1k_vidhrdw.c`: the blitter (Cave's EPIC12 FPGA).
|
||||
- `src/sound/ymz770.c`: the Yamaha YMZ770 ("AMM"), on `src/sound/mpeg_audio.c`.
|
||||
|
||||
All are C89 ports of current MAME (`sh.cpp`, `sh3comn.cpp`, `sh4*.cpp`,
|
||||
`cv1k.cpp`, `epic12*.cpp`, `ymz770.cpp`).
|
||||
|
||||
## The board
|
||||
|
||||
- Hitachi SH7709S, an SH-3 at 102.4 MHz, big-endian, no FPU. The boot code
|
||||
copies the game from the NAND flash to work RAM and runs it from there.
|
||||
- The blitter: copies sprites from an 8192 x 4096 VRAM to the screen with
|
||||
flips, tint, transparency and 8 source and 8 destination blend modes, and
|
||||
uploads graphics to VRAM. The games wait on it.
|
||||
- The YMZ770: 16 channels of compressed audio from two 4 MB flash chips,
|
||||
and a sequencer.
|
||||
- 128 MB NAND flash with the graphics and data, a NOR flash with the boot
|
||||
code, the RTC9701 with its EEPROM (settings and high scores).
|
||||
|
||||
## CPU
|
||||
|
||||
The interpreter follows current MAME's SH-3 instruction by instruction,
|
||||
with the cycle counts of MAME's recompiler (MAME only runs the SH-3 with its
|
||||
recompiler) and MAME's SH7709S cache and bus timing model: every data access
|
||||
goes through a model of the 16 KB cache, the write-back, the burst fills and
|
||||
the wait states of each bus area. The games' speed (and their slowdowns)
|
||||
depends on it.
|
||||
|
||||
Peripherals: the interrupt controller, the three timers (TMU), the DMA
|
||||
controller (the transfer at once, the end interrupt after the transfer
|
||||
time, as MAME), the I/O ports (inputs, NAND control, RTC serial line), the
|
||||
cache address array. The timers run on the machine time, as in MAME.
|
||||
|
||||
## Recompiler
|
||||
|
||||
Core option "SH-3 Dynarec" (enabled by default; offered for these games
|
||||
only, on the hosts where it runs: x86, x86-64, ARMv7, AArch64, except the
|
||||
systems that forbid run-time code generation). Big-endian hosts use the
|
||||
interpreter.
|
||||
|
||||
It gives the same results as the interpreter, cycle for cycle: a saved
|
||||
state is the same with and without it, so netplay, save states and RunAhead
|
||||
don't depend on it.
|
||||
|
||||
- Straight runs of instructions, up to an unconditional branch and its
|
||||
delay slot, become native code (sljit, as the MIPS and ADSP recompilers
|
||||
of this core). Conditional branches leave the block or loop inside it.
|
||||
- The timeslice is checked before every instruction, as the interpreter's
|
||||
loop does; the cycles are taken in the interpreter's order around the
|
||||
memory accesses and the bus timing.
|
||||
- Loads and stores compute their address natively and call the
|
||||
interpreter's accessors (memory handlers, cache and bus timing). The
|
||||
instructions without native code call the interpreter for that
|
||||
instruction.
|
||||
- The block leaves when an interrupt becomes pending or a write touches
|
||||
translated code. Writes over translated code (CPU stores, DMA) and state
|
||||
loads flush the translations.
|
||||
|
||||
## Speedups
|
||||
|
||||
As in MAME, each game has an idle loop speedup: the read of the variable the
|
||||
game polls in its wait loop skips 10 us of CPU time. The loop reads it in
|
||||
the delay slot of its branch; MAME's recompiler reports there the PC it
|
||||
stored two bytes after the loop start, so it skips on every pass; this
|
||||
driver does the same with the delay slot's own PC.
|
||||
|
||||
MAME suspends the CPU for those 10 us. This core's scheduler doesn't give
|
||||
the time back to a CPU resumed in the timeslice that suspended it, so the
|
||||
CPU would fall further behind on every pass: the 10 us are eaten from the
|
||||
timeslice instead (1024 cycles), with the same effect.
|
||||
|
||||
## Video
|
||||
|
||||
The VRAM is kept as 16-bit pixels (the 5-5-5 colour and the transparency
|
||||
bit), 64 MB instead of MAME's 128 MB of 32-bit pixels; the blits work on
|
||||
the same values as MAME's. The blitter runs at once when started, and is
|
||||
busy for the time MAME computes for that blit (the games read the busy
|
||||
flag). MAME can run it in a separate thread; this core doesn't.
|
||||
|
||||
## Sound
|
||||
|
||||
The YMZ770 decodes MAME's AMM variant of MPEG audio, added to
|
||||
`mpeg_audio.c` next to layers I and II (used by the Sega DSB), which are
|
||||
unchanged.
|
||||
|
||||
## NAND flash, RTC, NVRAM
|
||||
|
||||
- The NAND is read with its spare area and bad block table through the
|
||||
flash interface and port E (busy for 25 us after a page read).
|
||||
- The RTC9701 is set from the host clock at start, as MAME does.
|
||||
- NVRAM: the RTC EEPROM, and the NAND blocks the game erased or programmed
|
||||
(only those, not the 128 MB).
|
||||
|
||||
## Save states
|
||||
|
||||
Every part has its state saved (CPU, peripherals, cache model, blitter
|
||||
and VRAM, YMZ770, NAND, RTC). A state is about 77 MB with the VRAM (85 MB on
|
||||
CV1000-D). Tested: a save and load on every frame (RunAhead-like) gives the
|
||||
same frames, audio and state as a run without them.
|
||||
|
||||
## Not done
|
||||
|
||||
- `mmmbanc` (Medal Mahjong Moukari Bancho), a touch screen game.
|
||||
- Akai Katana and DoDonPachi SaiDaiOuJou: commented out in MAME too.
|
||||
@@ -0,0 +1,203 @@
|
||||
# Sega Model 1: how the driver works and where it differs from the hardware
|
||||
|
||||
Sets: `vr`, `vformula`, `vf`, `swa`, `swaj`, `wingwar`, `wingwaru`,
|
||||
`wingwarj`, `wingwar360`, `netmerc`.
|
||||
|
||||
Files: `src/drivers/model1.c` (boards, maps, ROMs), `src/machine/model1_machine.c`
|
||||
(the TGP), `src/vidhrdw/model1_vidhrdw.c` (the renderer, ported from current
|
||||
MAME), `src/sndhrdw/segadsb.c` (the Digital Sound Board of Star Wars Arcade).
|
||||
|
||||
## The TGP (geometry coprocessor)
|
||||
|
||||
The TGP is a Fujitsu MB86233 DSP running a program from a 315-xxxx ROM:
|
||||
315-5573 (Virtua Racing, Virtua Formula), 315-5724 (Virtua Fighter), 315-5711
|
||||
(Star Wars Arcade, Wing War, NetMerc). The V60 sends it commands (a function
|
||||
number and its arguments) through a FIFO and reads the results back.
|
||||
|
||||
The driver runs the TGP functions in C (high level emulation, HLE), started
|
||||
from MAME 0.215, the last MAME with an HLE TGP. In MAME 0.215 Virtua Racing had
|
||||
no HLE at all and Star Wars Arcade and Wing War did not work.
|
||||
|
||||
### Checked against the real program
|
||||
|
||||
The core also contains the MB86233 (from the Model 2 work), so the real TGP
|
||||
program can run next to the HLE. A development build (`-DMODEL1_TGP_DEV`)
|
||||
reads `MODEL1_TGP` from the environment:
|
||||
|
||||
- `lle`: the game runs on the real TGP program only.
|
||||
- `oracle`: the game runs on the real TGP program, the HLE gets the same
|
||||
input, and every call is compared: function, arguments, the results of
|
||||
both. The pairing follows the input stream (a call ends when the DSP takes
|
||||
the next function word), so a function giving a wrong number of results
|
||||
does not shift the others. The TGP RAM both sides keep is compared every
|
||||
frame. Every 600 frames it prints, for each function, the calls that were
|
||||
exact, near (rounding), wrong, or gave a wrong number of results.
|
||||
|
||||
With this, every function the games call was rewritten from the DSP program
|
||||
until the results match bit for bit: same table lookups (sine, 1/x, 1/sqrt,
|
||||
atan come from the TGP's table ROM through its I/O ports, with one
|
||||
multiply-subtract step), same order of the sums, same comparisons (the ALU's
|
||||
`-0` is neither negative nor positive). Checked on attract and play of
|
||||
`vr` (three tracks), `vformula`, `vf`, `swa`, `wingwar`, `wingwar360` and
|
||||
`netmerc`: no call differs and the TGP RAM stays identical.
|
||||
|
||||
Virtua Fighter's program (315-5724) is marked as a bad dump in MAME, but it
|
||||
runs the game on the MB86233 core, so it is checked the same way. About half
|
||||
of its functions differ from 315-5573 (matrix stack and saved matrices at
|
||||
other addresses, the camera, collision bitmaps, ground box test, list walks
|
||||
in the copro RAM), so it has its own table. MAME 0.215 used the Virtua Racing
|
||||
table for it, with guessed camera functions (one returned random numbers),
|
||||
which put the camera far from the fighters. For Virtua Fighter the oracle
|
||||
also compares the TGP's internal RAM after every call. Over 9000 frames of
|
||||
attract and fights, 55 functions and 3.8 million calls give the same results
|
||||
and the same RAM.
|
||||
|
||||
The table lookups, the copro RAM (0x2000 words; with address bit 0x40000 set
|
||||
the address steps by 4) and the list functions follow current MAME.
|
||||
|
||||
### Program bugs reproduced
|
||||
|
||||
The HLE reproduces what the real programs do, bugs included, because the
|
||||
games run with them on the real boards:
|
||||
|
||||
- 315-5711 `roty` starts its first sum from the DSP's `d` register, which
|
||||
still holds the dispatch address (a denormal): the first matrix element
|
||||
gets `0x6c` added to it.
|
||||
- 315-5711 `normalize` never loads y; it uses whatever the scratch word at
|
||||
`$71` holds from an earlier function (tracked by the HLE).
|
||||
- 315-5711 `f47` starts its sum of squares from the z difference.
|
||||
- 315-5711 `fsqrt` skips the mantissa step and does not return a square root.
|
||||
- The matrix stack keeps 7 levels; past them the depth only counts (315-5711
|
||||
pushes again past 8, while its pops past 7 only count). The matrix slots
|
||||
and the 315-5711 accumulator stack sit in the same TGP RAM, as on the
|
||||
board.
|
||||
- 315-5711 `f52` (0x34, matrix inverse; Star Wars Arcade calls it) works
|
||||
by cofactors, never reads the first element, ORs two elements where a
|
||||
subtract is expected, and adds in the second element the scratch word
|
||||
`$11` an earlier function left (push, multiply and read leave a matrix
|
||||
element or argument there; tracked by the HLE).
|
||||
- 315-5711 `f56` (0x38, segment against a polygon list) stops at the first
|
||||
polygon hit, not the nearest one.
|
||||
- The 315-5711 games use the current matrix before setting it: the HLE starts
|
||||
from what the TGP RAM holds at power on (zeros in the emulated TGP).
|
||||
|
||||
### What is not emulated
|
||||
|
||||
- Table entries a program leaves empty (it returns at once) take no
|
||||
arguments and give no results; 315-5724 functions no game was seen calling
|
||||
are not emulated, except the simple ones (normalize, divide, set the
|
||||
translation).
|
||||
- 315-5711 functions no game was seen calling: self tests 0x04, 0x3d, 0x3e
|
||||
(results 0), 0x42 (matrix stack pop and multiply, with bugs overwriting the
|
||||
stack), 0x21 (the program jumps into the middle of another function). They
|
||||
take and give the right number of words so the command stream stays in step.
|
||||
|
||||
### ROMs
|
||||
|
||||
The TGP program ROM stays in the sets as in current MAME. For Star Wars
|
||||
Arcade, Wing War and NetMerc the HLE follows 315-5711 with CRC 6a21f304, as
|
||||
current MAME. An older dump (CRC c5ddb8fc) differs in two words: the entry
|
||||
of `f52` (which then reads the wrong RAM and gives NaNs) and the end test
|
||||
of `f56`. It loads with a checksum warning; the HLE does not use the ROM.
|
||||
|
||||
The V60 reaches the TGP in its I/O space as well as in memory, with the
|
||||
same mirrors as current MAME: Wing War sends its boot command (8, clear the
|
||||
matrix stack) with an OUT to a mirror of the FIFO, and the real program
|
||||
waits for it before taking any other command.
|
||||
|
||||
## I/O board
|
||||
|
||||
The Model 1 I/O board (model1io, model1io2: a Z80 with its own BIOS) is
|
||||
simulated: inputs, DIP switches, analog channels and the backup are put where
|
||||
the games read them in the 2 KB dual port RAM:
|
||||
|
||||
00-07 analog channels
|
||||
08-0a IN0 - IN2 (active low)
|
||||
0b-0d DSW1 - DSW3 (active low, all off)
|
||||
0e board switches
|
||||
0f outputs (lamps, coin counters)
|
||||
11 drive board / motion base output
|
||||
20 command (2 store the backup 0x100-0x1ff, 3 load it), 21 status
|
||||
|
||||
The DIP switches must read as off: 0 turned on the debug displays of Virtua
|
||||
Racing and NetMerc. The backup is saved in the NVRAM file.
|
||||
|
||||
## Sound
|
||||
|
||||
Model 1 sound board (68000, two MultiPCM, YM3438) behind an i8251 UART at
|
||||
31250 baud, as current MAME. Star Wars Arcade also has the Digital Sound
|
||||
Board (Z80 + MPEG audio), which listens to the sound board's UART.
|
||||
|
||||
The simulated I/O board answers at once, so the V60 sends its first sound
|
||||
commands before the 68000 has finished its init. The real UART holds one byte
|
||||
and would lose the others; Virtua Fighter then stayed silent. The bytes for
|
||||
the 68000 are kept in a queue.
|
||||
|
||||
Virtua Racing and Virtua Fighter play no sound in attract mode with their
|
||||
default settings, as on the board.
|
||||
|
||||
## Save states
|
||||
|
||||
Besides the RAMs and registers, a save state keeps what MAME 0.78 does not
|
||||
save by itself and what a game sets only once: the TGP FIFOs (a state can
|
||||
fall between the words of a command, or before the V60 read the results),
|
||||
the data ROM bank, the time left of the interval and UART timers, and the
|
||||
renderer's view (viewport, light, light parameters: Virtua Fighter sends
|
||||
them only when a stage starts, and without them a loaded state drew the
|
||||
fighters black). Checked by loading in a new process: Virtua Fighter and
|
||||
Virtua Racing's attract mode go on frame for frame as in a straight run
|
||||
(analog controls: see Open questions).
|
||||
|
||||
## Other boards
|
||||
|
||||
- Link board (Virtua Racing, Virtua Formula, Wing War): not emulated; the
|
||||
games see it with its CPU in reset and run stand-alone.
|
||||
- R360 motion base (`wingwar360`): the game states it sends are answered as
|
||||
the real base does, so a game starts. No motion.
|
||||
- Polhemus tracker (`netmerc`): the board (a 386 with its own program) that
|
||||
tracks the visor is not emulated. As in current MAME, the visor pose the
|
||||
game reads at dual port RAM 0x80-0x8b (x, y, z, then three angles in
|
||||
radians * 8192) is set once at reset, looking ahead. The gun on its mount
|
||||
is not tracked: it uses the stick (analog channels 0 and 2), and moving
|
||||
goes where the gun points.
|
||||
- NetMerc gun mount calibration: the ends of both axes are kept in the
|
||||
backup RAM (0x38 / 0x3c horizontal, 0x40 / 0x44 vertical). At boot the
|
||||
game sets its factory calibration (0x46-0xc4, 0x21-0x69) only when one of
|
||||
them is zero, so a new NetMerc backup RAM is 0-filled (the other games
|
||||
get 1s, which Virtua Fighter needs): with 1s it kept them, divided by
|
||||
zero, spun the gun, failed its checksum and stayed on one attract
|
||||
screen. The stick covers the same range as the factory calibration.
|
||||
- NetMerc sound: `mpr-18134` (the first sample ROM of the first MultiPCM)
|
||||
is a bad dump, all 0xff, in the only set known (MAME has the same one).
|
||||
That MultiPCM has no sample table, so the music it plays is silent; the
|
||||
effects, on the second MultiPCM, play.
|
||||
- NetMerc defaults (test menu, GAME ASSIGNMENTS): country Japan, attract
|
||||
sound off, so attract mode is silent and starts with the Japan warning.
|
||||
|
||||
## Video
|
||||
|
||||
`model1_vidhrdw.c` is a C port of current MAME's `model1_v.cpp`. Two choices
|
||||
keep the output the same on every CPU: float to int conversions follow x86
|
||||
(out of range gives `INT_MIN`, other CPUs saturate), and the files of the TGP
|
||||
and the renderer are compiled without fused multiply-add (GCC and clang fuse
|
||||
`a*b+c` on PowerPC and ARM64). Big-endian PowerPC renders pixel for pixel as
|
||||
x86.
|
||||
|
||||
Polygons with the moire flag (Virtua Fighter's shadows) are drawn as a
|
||||
checkerboard, every other pixel, as in current MAME; a 720p capture of a
|
||||
real Virtua Fighter board shows the same pattern.
|
||||
|
||||
Compared with captures of real boards: Virtua Fighter (the stages up to
|
||||
Akira's: backgrounds, floors, colours, lighting, camera, shadows), Virtua
|
||||
Racing (Bay Bridge: start grid, bridge, HUD), Star Wars Arcade (attract:
|
||||
Star Destroyer, cockpit battle, hangar), Wing War and NetMerc.
|
||||
|
||||
## Open questions
|
||||
|
||||
- Virtua Fighter: the eight stages up to Akira's were compared with a
|
||||
capture of a real board (backgrounds, floors, colours, camera); Dural's
|
||||
stage and the bonus stage were not.
|
||||
- After loading a state during play, an analog control (Virtua Racing's
|
||||
accelerator) starts again from its rest position: the core's input
|
||||
system does not save it. Digital inputs and attract mode go on as in a
|
||||
straight run.
|
||||
@@ -0,0 +1,517 @@
|
||||
# Sega Model 2: choices that differ from the hardware
|
||||
|
||||
The Model 2 driver (`src/drivers/model2.c`) emulates the boards as the games
|
||||
see them. In a few places the hardware is not available or not emulated, and
|
||||
the driver does something simpler. Each of those choices is listed here, with
|
||||
the reason and its consequences.
|
||||
|
||||
## Communication board (network link)
|
||||
|
||||
The communication board links cabinets for multi-player games over a network.
|
||||
It is not emulated: there is no network.
|
||||
|
||||
For most games the board reads as **absent** (the CN register reads 0xff).
|
||||
The games that look for it then run as single machines.
|
||||
|
||||
### Virtual-On: board present, link always stand-alone
|
||||
|
||||
Sets: `von`, `vonu`, `vonj`.
|
||||
|
||||
**Why.** Virtual-On does not start a game without the board, even on a
|
||||
machine set to stand-alone. At boot (addresses from `von`):
|
||||
|
||||
1. `0x185d0` sets the defaults: role stand-alone, link mode 0.
|
||||
2. `0x18920` reads the link ID from the backup RAM (byte `0x1d00028`:
|
||||
0 slave, 1 master, other values stand-alone; the factory setting is 2).
|
||||
3. `0xc6480` initialises the link. It reads the board's CN register first.
|
||||
Without a board it prints "THERE IS NO COMMUNICATION BOARD!", sets the
|
||||
link mode to 0xff and returns, without looking at the link ID.
|
||||
|
||||
With link mode 0xff the game never leaves the attract mode: after a coin the
|
||||
screen stays black and silent (game mode 4, sub-state 0 waits on a status
|
||||
word that stays 0xff).
|
||||
|
||||
With a board present, step 3 enables it (CN=1) and waits for the board's
|
||||
firmware to report ready (ZFG=1, read as bit 7 of the FG register going to
|
||||
0). With the link ID on stand-alone it then returns at once and the game never
|
||||
uses the link. A board that is present but never ready stops the game at boot;
|
||||
this is also what the current MAME device does without its network
|
||||
simulation, and MAME lists these sets as not working.
|
||||
|
||||
**What the driver does.**
|
||||
|
||||
- The board reads as present and reports ready as soon as the game enables
|
||||
it (`m2comm_ctrl_w`, CN=1 sets ZFG=1). Its shared RAM is plain RAM.
|
||||
- The link ID always reads as stand-alone (`von_linkid_r`, installed over the
|
||||
backup RAM dword at `0x1d00028`). Writes still go to the backup RAM.
|
||||
|
||||
**Consequences.**
|
||||
|
||||
- Master and slave are not available. The test menu always shows
|
||||
stand-alone, whatever is chosen there.
|
||||
- The game computes the backup RAM checksum by reading through the same
|
||||
handler, so the checksum stays valid and the other settings are kept.
|
||||
- An NVRAM from another emulator with the link set to master or slave fails
|
||||
the checksum once: the game then restores its factory settings.
|
||||
|
||||
**How it was checked.** A valid NVRAM with the link ID on slave (checksum
|
||||
recomputed with the game's own CRC, table at `0x2f20` in `von`) stops at boot
|
||||
on "THIS IS SLAVE SITE" without the override. With the override, the same
|
||||
NVRAM boots, plays a game, and keeps its other settings.
|
||||
|
||||
**Not added: `vonr` (Virtual-On Relay).** That version always sets its role
|
||||
to relay (`0xf1cf0` writes 0) before the link is initialised, and then waits
|
||||
for the network. It cannot run as a single machine.
|
||||
|
||||
### Daytona USA: factory link ID forced to single at start-up
|
||||
|
||||
Sets: `daytona`, `daytonase`, `daytona93`, `daytonas`.
|
||||
|
||||
**Why.** Daytona USA runs without the board, but its factory settings in the
|
||||
program ROM set the link ID to master. On a new NVRAM (or after a factory
|
||||
reset) the game uses those settings and keeps looking for the other cabinets
|
||||
("NETWORK CHECKING"), so a game never starts.
|
||||
|
||||
**What the driver does.** When the game is loaded, `DRIVER_INIT( daytona )`
|
||||
finds the factory settings table in the program ROM (it starts with
|
||||
`SEGA@\x82`) and changes the link ID at offset 0x0b from 1 (master) to
|
||||
0 (single). The board reads as absent.
|
||||
|
||||
| Set | Table | Factory link ID | Patched |
|
||||
|---|---|---|---|
|
||||
| `daytona` | `0x39d60` | 1 (master) | yes |
|
||||
| `daytonase` | `0x3ab20` | 1 (master) | yes |
|
||||
| `daytonas` | `0x3c570` | 1 (master) | yes |
|
||||
| `daytona93` | `0x3c150` | 0 (single) | no, already single |
|
||||
|
||||
**Consequences.**
|
||||
|
||||
- Only the factory value changes. A link ID already saved in the NVRAM is
|
||||
kept, and the setting can still be changed in the test menu. Set to master
|
||||
or slave, the game waits for the network as on the real hardware; set it
|
||||
back to single to play.
|
||||
- Restoring the factory settings from the test menu gives single, not
|
||||
master.
|
||||
|
||||
### Motor Raid
|
||||
|
||||
Sets: `motoraid`.
|
||||
|
||||
The game has link code ("Network Check"), but with the board absent it
|
||||
starts and plays with its factory settings. Nothing is changed.
|
||||
|
||||
## Model 1 I/O board (original Model 2)
|
||||
|
||||
Sets: `daytona` and clones, `vcop`, `vcopa`.
|
||||
|
||||
The original Model 2 reads its inputs through a Model 1 I/O board: a Z80
|
||||
with its own BIOS, behind a dual-port RAM at `0x1c00000`.
|
||||
|
||||
- With the BIOS (`model1io.zip` for Daytona USA, `model1io2.zip` for Virtua
|
||||
Cop), the board runs its own firmware on an emulated Z80.
|
||||
- Without it, the board's firmware is simulated: the driver writes the
|
||||
inputs, the analog channels and the light guns where the games read them,
|
||||
and handles the backup commands. Both BIOS files are optional ROMs.
|
||||
|
||||
## INDY 500 and Over Rev (Model 2B, `indy500` machine)
|
||||
|
||||
Sets: `indy500`, `indy500d`, `indy500to`, `overrevb`, `overrevba`.
|
||||
|
||||
- **Drive board (force feedback).** The games write their commands to it
|
||||
through port E of the 315-5649 and never wait for an answer. It is not
|
||||
emulated: the writes are ignored, as in MAME when no drive board program
|
||||
is loaded.
|
||||
- **Communication board program.** The Over Rev sets list the communication
|
||||
board program (`epr-18643.7`) as in MAME. Its CPU is not run, so the ROM
|
||||
is optional: the sets load with or without it.
|
||||
- **Over Rev parent.** As in MAME, the parent `overrev` is the Model 2C
|
||||
version (see the Model 2C sections), so `overrevb` and `overrevba` load
|
||||
from `overrev.zip`. The I/O board BIOS entries (`model1io`, `model1io2`),
|
||||
like the other BIOS sets of the core, are not in the game list: loading
|
||||
their zip reports that there is no such game instead of starting a
|
||||
machine without a program.
|
||||
- **Inverted pedals.** Over Rev reads its pedals inverted (0xff released), as
|
||||
`PORT_REVERSE` in MAME. The driver inverts those channels itself.
|
||||
|
||||
Super GT 24h (`sgt24h`) runs on the same machine. Its pedals are read
|
||||
inverted too, and it uses the same driver init as Over Rev.
|
||||
|
||||
## Sound link (MIDI input of the SCSP)
|
||||
|
||||
On Model 2A and later the i960 sends its sound commands through a UART to the
|
||||
MIDI input of the SCSP. The driver sends a byte only when the SCSP input
|
||||
queue has room, so no command is lost; while the queue is full the UART
|
||||
reports itself busy and the game waits.
|
||||
|
||||
The SCSP input queue holds 32 bytes, as in current MAME (the original MAME
|
||||
0.78 code had 8). With 8 bytes Super GT 24h hung at the end of its boot: the
|
||||
sound program does not read the queue for a while, and the game sends sound
|
||||
commands from its vertical blank interrupt, so it waited there for several
|
||||
frames. Its frame timer (same interrupt priority) expired meanwhile; the
|
||||
i960 records such an interrupt in its interrupt table, which this game keeps
|
||||
in ROM, so the interrupt was lost and the main loop waited for the timer
|
||||
forever (black screen after "STAND ALONE"). With 32 bytes the commands fit
|
||||
and the game plays.
|
||||
|
||||
**The MIDI interrupt.** The sound program reads one byte from the queue per
|
||||
MIDI interrupt (level 3 on these boards). The interrupt is now dropped when
|
||||
the program reads the byte, and raised again only while the queue still has
|
||||
bytes, as in current MAME. Before, it could stay raised on an empty queue:
|
||||
the sound program then took it again and read a stale byte as part of a
|
||||
command. This corrupted the music commands of Dead or Alive (61 extra reads
|
||||
in the attract mode) and Manx TT (189), whose music then played wrong or
|
||||
stopped. The SCSP timers are now real timers, as in MAME, and each interrupt
|
||||
source has its own level, which stays raised until the program acknowledges
|
||||
it.
|
||||
|
||||
**How it was checked.** Each sound command the i960 sends is read once, with
|
||||
no extra reads, in `doa`, `fvipers`, `hotd`, `manxtt`, `rchase2`, `srallyc`
|
||||
and `vf2`. In Dead or Alive the sound commands and every slot register write
|
||||
between 15 and 25 s of the attract mode are the same as in MAME 0.264.
|
||||
|
||||
## Rail Chase 2: mirrored sample ROMs
|
||||
|
||||
Sets: `rchase2`.
|
||||
|
||||
The sound board takes either four 16 Mbit sample ROMs (IC32, IC33, IC34,
|
||||
IC35) or two 32 Mbit ones (IC32, IC34). Rail Chase 2 has two 16 Mbit ROMs in
|
||||
the 32 Mbit positions IC32 and IC34. A 16 Mbit ROM there ignores the top
|
||||
address line, so it shows up twice: the region at 0x200000 mirrors IC32 and
|
||||
the one at 0x600000 mirrors IC34.
|
||||
|
||||
The sound program streams some effects through the 68000 into ring buffers
|
||||
in sound RAM, reading them from those mirrors (the title screen animation
|
||||
reads its stream from 0xa1e97c, inside the mirror of IC32). MAME loads the
|
||||
ROMs at 0x000000 and 0x400000 and leaves the mirrors empty, so those effects
|
||||
play silence: the title animation is silent and some in-game effects are
|
||||
missing, as reported for MAME (mametesters 09393).
|
||||
|
||||
The ROM definition loads each ROM a second time into its mirror (`ROM_RELOAD`), as the same fix proposed to MAME.
|
||||
|
||||
**How it was checked.** Current MAME (built from source, October 2026), with
|
||||
no input, plays nothing during the title animation (22-30 s, 56-62 s and
|
||||
90-96 s of the attract mode), as this core did before the change. With the
|
||||
same mirroring added to MAME's `init_rchase2`, MAME plays the title
|
||||
animation sound at the same points as this core. The billboard ROM
|
||||
(`segabill`), not dumped here, was an empty placeholder in that MAME test; it
|
||||
drives the score display only. With it the title
|
||||
animation has its sound and the in-game sound is about a third louder (the
|
||||
effects that were missing). The video is unchanged. The other Model 2 sets
|
||||
fill every ROM position they use, or (`dynabb`) use the four-ROM layout, where
|
||||
an empty socket is not a mirror.
|
||||
|
||||
## Sound: the SCSP effect DSP
|
||||
|
||||
Sets: every SCSP game that loads a DSP program (Dead or Alive among them).
|
||||
|
||||
The SCSP has a small DSP for effects (reverb, echo). The slots send their
|
||||
output to it (ISEL, IMXL), it runs its microprogram once per sample with its
|
||||
delay lines in the sound RAM (RBP, RBL), and its 16 outputs are mixed with
|
||||
the EFSDL and EFPAN of slots 0-15. The SCSP of this core did not emulate it,
|
||||
so those effects were missing, and the sounds a game sends only to the DSP
|
||||
were silent. The DSP is now the one of current MAME (`src/sound/scspdsp.c`),
|
||||
compared with MAME's on the Dead or Alive program and on random programs:
|
||||
same outputs, registers and delay RAM, sample by sample.
|
||||
|
||||
**Dead or Alive and the MADRS registers.** The DSP reads its delay line
|
||||
addresses from the MADRS registers (`0x780-0x7bf`). MAME also writes the
|
||||
range `0x7c0-0x7ff` to MADRS, as a mirror. Dead or Alive loads MADRS and then
|
||||
clears `0x7c0-0x7ff`, so in MAME every delay line address becomes 0: the
|
||||
reverb feeds back into one word, its output drifts to a DC level and
|
||||
saturates, and the sound breaks up and then goes silent (listed in MAME's
|
||||
known issues for `doa`). The mirror is not from the hardware: it replaced an
|
||||
out-of-bounds write in 2014, and Mednafen (checked on Saturn hardware) maps
|
||||
MADRS at `0x780-0x7bf` only. Here `0x7c0-0x7ff` is ignored and reads as 0.
|
||||
|
||||
**Master volume.** The SCSP master volume (MVOL) now scales the output once
|
||||
the game has written it, as in MAME. Dead or Alive keeps it at 0 for the
|
||||
first seconds while its DSP starts on an uninitialised delay RAM; without
|
||||
MVOL that start was audible as a burst of noise. The games that use 15 (the
|
||||
maximum) sound exactly as before.
|
||||
|
||||
**How it was checked.** MAME with the mirror removed plays the Dead or Alive
|
||||
attract mode for over 11 minutes without the DC drift (it saturated within
|
||||
the first minute before). In this core the games that do not start the DSP
|
||||
produce exactly the same audio as before.
|
||||
|
||||
## Video: tile layers and polygons
|
||||
|
||||
The tile layers (System 24 tilemaps A and B) are mixed among themselves
|
||||
first, A over B whatever their priority bits; the priority bit of the
|
||||
pixel that wins then puts it behind or in front of the polygons. MAME draws
|
||||
each priority on its own (the low tiles of A and B, the polygons, the high
|
||||
tiles of A and B), so a high tile of B covers a low tile of A: on the
|
||||
Virtua Cop 2 stage select the city map (tilemap B, priority set) hid
|
||||
"SHOOT TO SELECT" (tilemap A), as listed in MAME's known issues for
|
||||
`vcop2`. The other Model 2 games checked look the same as before.
|
||||
|
||||
## Video: black polygon pixels
|
||||
|
||||
The polygons are drawn into their own buffer, then laid over the tile
|
||||
layers. MAME's buffer holds `rgb_t` pixels, whose alpha byte makes a drawn
|
||||
black pixel (0xff000000) different from an empty one (0). This core stored
|
||||
plain RGB and took every black pixel as empty, so wherever a polygon was
|
||||
pure black the layer behind showed through: blue car shadows and missing
|
||||
dust in Sega Rally, blue tyres and shadows in INDY 500 and Super GT, the
|
||||
sky behind black clothes in Dead or Alive, the attract backgrounds of Motor
|
||||
Raid. Drawn pixels now carry the same opaque marker in the top byte. All the
|
||||
Model 2 games were compared before and after; the changed pixels are the
|
||||
black ones, and they now match MAME.
|
||||
|
||||
## Sega Rally Championship (Model 2A)
|
||||
|
||||
Sets: `srallyc`, `srallycb`, `srallycc`, `srallycdx`, `srallycdxa`.
|
||||
|
||||
- **Gear lever.** The H-pattern lever is read on port C bits 4-6. As for
|
||||
Daytona USA it is built from two buttons, shift up and shift down.
|
||||
- **Drive board.** The force feedback board is written to through port E and
|
||||
never answers; it is not emulated. Its program (`epr-17891`) and the
|
||||
communication board program (`epr-16726`) are not listed.
|
||||
- **Start grid.** MAME lists the initial placement of a few opponent cars as
|
||||
slightly wrong, depending on the i960 clock. Here, with the i960 at half
|
||||
and at double its clock, only one of the 8 start grid objects moves, by
|
||||
about 0.3 units (it is still settling when the race starts). Compared with
|
||||
a video of a real Model 2A-CRX, aligned on the race clock (chase view,
|
||||
full throttle): same speed (220 km/h at 0'04"0), same course, and the
|
||||
first opponent appears at the end of the village at 0'05"0 in both, at the
|
||||
same distance up to 0'06"0. Nothing is changed.
|
||||
|
||||
## Manx TT Superbike (Model 2A)
|
||||
|
||||
Sets: `manxtt` (DX/Twin, Revision D), `manxttc` (DX/Twin, Revision C),
|
||||
`manxttdx` (DX).
|
||||
|
||||
- **Cabinet type.** The MAME sets include an EEPROM image that sets the
|
||||
cabinet type: DX for `manxtt`, Twin for `manxttc`. A new NVRAM starts from
|
||||
it (`REGION_PROMS`, 16-bit little-endian as in MAME). The type can still be
|
||||
changed in the test menu.
|
||||
- **Motion slider (DX).** The DX bike moves; its drive board takes commands
|
||||
on port E of the 315-5649 and answers on port D. At boot the game shows
|
||||
"ACTIVE MOTION SLIDER / NOW CHECKING SYSTEM" (code at `0x5f580` in
|
||||
`manxtt`): after command `0x3d` it waits up to 846 frames for status
|
||||
`0xce`, sends the bike center value, then waits for `0xcd`. Without an
|
||||
answer it shows "Error! ... Not Respond" and never starts; MAME stops
|
||||
there (its known issue "no escape from active motion slider tutorial").
|
||||
The board is simulated with those two answers: `0xce` while the command is
|
||||
`0x3d`, `0xcd` otherwise. The board's error codes (`0xb0`-`0xb7`: first
|
||||
setting, encoder, overcurrent, overheat, bank volume, ROM, RAM, centering)
|
||||
are never sent. The bike does not move, of course.
|
||||
- **Model 1 sound board (DX).** The DX cabinet has a Model 1 sound board
|
||||
(68000, YM3438, two MultiPCM) next to the SCSP, for extra sounds. It runs as
|
||||
a fourth CPU (`REGION_CPU4`, samples in `REGION_SOUND2`/`REGION_SOUND3`)
|
||||
and gets the same sound commands from the i960 UART, as in MAME. Its replies
|
||||
are not passed back: the i960 reads the SCSP's.
|
||||
- **Communication board.** Its program (`epr-18643a`) is not listed; the
|
||||
board is not emulated and the game runs as a single machine.
|
||||
|
||||
## Sky Target (Model 2A)
|
||||
|
||||
Sets: `skytargt`.
|
||||
|
||||
The stick is on analog channels 0 (Y) and 2 (X, reversed), as in MAME.
|
||||
Machine gun, missile and view change are buttons 1-3.
|
||||
|
||||
## Air Walkers (Model 2A)
|
||||
|
||||
Sets: `airwlkrs`.
|
||||
|
||||
Up to four players on two input ports: port F bit 7 selects players 1-2 or
|
||||
3-4 on ports C and D, and the matching start buttons on IN0 bits 4-5, as in
|
||||
MAME.
|
||||
|
||||
## Hanguk Pro Yagu 98 (Model 2A)
|
||||
|
||||
Sets: `hpyagu98`.
|
||||
|
||||
The game stops with "Error #1" unless the NVRAM holds what its boot code
|
||||
checks: EEPROM words 4-5, the string "98KOREA PRO B.B." at the start of the
|
||||
backup RAM, a magic dword at `0x398` (`v * 3 + 0x3e82 == 0xf0c891a2`), and the
|
||||
settings block at `0x10` with its CRC (a copy at `0x1d4` restores it when
|
||||
only one is valid). MAME lists two hand-made images, EEPROM and backup RAM,
|
||||
with the settings of Dynamite Baseball 97. A new NVRAM starts from them, as in
|
||||
MAME (`REGION_PROMS` and `REGION_GFX1`); older sets without these two files
|
||||
stop on "Error #1".
|
||||
|
||||
## Desert Tank (original Model 2)
|
||||
|
||||
Sets: `desert`.
|
||||
|
||||
Model 1 I/O board as Daytona USA (its BIOS runs when `model1io.zip` is
|
||||
present). Steering, accelerator and brake on the I/O board analog inputs,
|
||||
the shift lever as a toggle, as in MAME.
|
||||
|
||||
## Model 2C: the TGPx4 (MB86235)
|
||||
|
||||
The Model 2C boards replace the TGP with a Fujitsu MB86235 "TGPx4". Its
|
||||
interpreter comes from current MAME (`src/cpu/mb86235`, in C89), with the
|
||||
program memory, the external bus (buffer RAM at `0x400000`, the copro data
|
||||
ROM at `0x800000`) and the two FIFOs as driver callbacks. As in MAME, the
|
||||
CPU waits in halt until the i960 has sent its program, and a read from the
|
||||
empty input FIFO repeats the instruction once the i960 pushes a value. Two
|
||||
places differ from MAME, where its code is plainly a slip:
|
||||
|
||||
- **FEA/FES** (exponent add/subtract) keep the sign and the mantissa and
|
||||
change only the exponent field; MAME keeps only the exponent field.
|
||||
- **EBL** (the low 14 bits of the external base register) is written as the
|
||||
low bits; MAME shifts the value up as for EBU.
|
||||
|
||||
None of the games checked showed a difference from either change.
|
||||
|
||||
The 2C games run faster than real time here, where MAME runs them at about
|
||||
70%.
|
||||
|
||||
## Video: polygon clipping
|
||||
|
||||
A polygon is clipped against four planes, and a convex one gains at most one
|
||||
vertex for each, so MAME's buffers hold 8. A bad polygon (self-crossing, or
|
||||
with NaN coordinates) can double its vertices at each plane: Top Skater's
|
||||
models drawn with the standard object format overflowed the buffers and
|
||||
crashed the core. The buffers now hold 64 vertices and only polygons that
|
||||
still fit in 8 are kept.
|
||||
|
||||
## Top Skater (Model 2C)
|
||||
|
||||
Sets: `topskatr`, `topskatru`, `topskatruo`, `topskatrj`.
|
||||
|
||||
The game uploads its own geometrizer program (MAME's notes: "a slightly
|
||||
different geometry code"), and MAME shows no 3D. Its object data command
|
||||
(`0x11`, the second bank of command numbers) reads a compact polygon list:
|
||||
the attribute word, then only the points, three words for a triangle and
|
||||
six for a quad. The standard format (no normals) also has three unused
|
||||
normal words and, for triangles, an unused point. Read with the standard
|
||||
format, every polygon after the first was garbage. The driver reads the
|
||||
compact format for command `0x11` in this game only; the skaters, the
|
||||
board, the ramps and the crowd are all drawn. The command word also carries the
|
||||
center select in bits 6-7, as the rasterizer command does: the speed meter
|
||||
is drawn around the window's second vanishing point, in the bottom left
|
||||
corner. Compared with a video of the arcade game: the course, the HUD and
|
||||
the speed meter are in the same places.
|
||||
|
||||
The program's command `0x1b` loads a second matrix and `0x1c` copies the
|
||||
first matrix's translation into it; a vertex whose x has the lowest bit set
|
||||
goes through the second matrix (the skinned joints of the skaters). MAME
|
||||
pull request #16444 (jkind73, open) found the compact format and the second
|
||||
matrix too.
|
||||
|
||||
The board has two foot sensors (front and tail), on while a foot stands on
|
||||
it. MAME reads them active low, so with no input both feet are off the
|
||||
board: the skater always jumps, floats 16 units above the ground with the
|
||||
camera close behind, and its shadow (which the game puts on the ground
|
||||
under the light) is far below, off screen. Here they are on at rest and a
|
||||
button lifts a foot. Compared with a video of the arcade game at the same
|
||||
race time, the skater now rides crouched, the camera is at the same
|
||||
distance and the shadow is under the board. The attract demos, played by
|
||||
the game, matched the video before already (shadows included).
|
||||
|
||||
The analog inputs are curving (channel 0, stick X) and slide (channel 1);
|
||||
MAME puts both on the same axis, here slide is on stick Y so a pad can
|
||||
reach both.
|
||||
|
||||
The music is on the DSB2 MPEG board (see the music board section).
|
||||
|
||||
## Sega Ski Super G (Model 2C)
|
||||
|
||||
Sets: `skisuprg`.
|
||||
|
||||
The drive board answers on port D to the commands on port E. At boot the
|
||||
game shows "CHECK DRIVE BOARD" (code at `0x88b10`): it clears port E and
|
||||
waits for `0xce` (ready), sends the inclining center and waits for `0xff`
|
||||
(taken), within 479 frames; without an answer it stops on "DRIVE BOARD
|
||||
TROUBLE CODE: FF", as in MAME. In game, `0xb0`-`0xb7` are board errors
|
||||
(init, encoder, overload, overheat, bank volume, ROM...). The board is
|
||||
simulated: `0xce` while port E is 0, `0xff` otherwise. The game then runs
|
||||
through the World Series and the races.
|
||||
|
||||
Swing is on analog channel 0 (stick Y), inclining on channel 1 (stick X),
|
||||
the foot sensors on port D are not read (port D is the drive board).
|
||||
|
||||
## Sega Touring Car Championship and Top Skater: music board (DSB)
|
||||
|
||||
Sets: `stcc`, `stccb`, `stcca`, `stcco` (DSB, Z80) and the Top Skater sets
|
||||
(DSB2, 68000).
|
||||
|
||||
Their music is MPEG audio (layer II, 32 kHz stereo) on a Digital Sound
|
||||
Board, from current MAME (`dsbz80.cpp`, `dsb2.cpp` and the decoder
|
||||
`mpeg_audio.cpp`, in C89: `src/sndhrdw/segadsb.c`, `src/sound/mpeg_audio.c`).
|
||||
The board's CPU gets the game's sound commands on its i8251, from the same
|
||||
line as the SCSP (each byte the i960 sends goes to both), and drives the
|
||||
decoder: start and end addresses, play, loop, stop, volume and stereo mode
|
||||
for the DSB; a command FIFO and a 1 kHz timer interrupt for the DSB2. The
|
||||
decoded audio is its own stream, mixed 9 dB under the SCSP's full level
|
||||
(MAME mixes both at full level). The level was measured on two recordings
|
||||
of Top Skater cabinets: with the music and the sound effects of the core as
|
||||
separate tracks of the same run, aligned on the attract mode, the
|
||||
recordings came out with the music 9 dB lower against the effects (within
|
||||
1 dB, both recordings); at full level the music also clipped. The decoded
|
||||
music itself matches the recordings (spectral correlation 0.9-0.97). The
|
||||
recordings play the music about 0.45% faster than the core's 32 kHz
|
||||
(emulated time); not changed, it may be the recordings. Touring Car's DSB
|
||||
uses the same level (no recording checked).
|
||||
|
||||
The decoder never reads past the MPEG ROM (MAME guards this on the DSB2
|
||||
only). The drive board and the communication board programs are not
|
||||
listed.
|
||||
|
||||
## The House of the Dead (Model 2C)
|
||||
|
||||
Sets: `hotd`, `hotdo`.
|
||||
|
||||
The guns work as in Virtua Cop 2 (the 315-5649 serial channel), with the
|
||||
ranges of MAME's `hotd` ports. MAME's prototype `hotdp` is not listed: one
|
||||
of its texture ROMs was never dumped.
|
||||
|
||||
## Other Model 2C sets
|
||||
|
||||
`waverunr`, `bel`, `segawski`, `dynamcopc` and `overrev` (now the Model 2C
|
||||
parent of the Model 2B sets) run with the inputs of MAME.
|
||||
|
||||
## Motor Raid - Twin/DX (Model 2A)
|
||||
|
||||
Sets: `motoraiddx`.
|
||||
|
||||
The DX cabinet has a moving bike, run by a drive board on the 315-5649
|
||||
ports: the game writes commands to port E (inverted) and reads the board's
|
||||
status on port D. The drive board's program is not dumped and MAME lists the
|
||||
set as not working: the game stops at "DRIVEBOARD NOT RESPONSE ERROR".
|
||||
|
||||
The board is simulated, as for Manx TT DX. From the cabinet check (code
|
||||
copied to RAM at `0x2158d0`, ROM `0xc58d0`):
|
||||
|
||||
- port D reads `0xcd` when the board is ready; the check then skips the
|
||||
initialisation and centring steps (which wait for `0xcf` and `0xce`);
|
||||
- the wire test sends commands `0xe0`-`0xef` and expects bit `n & 7`
|
||||
cleared (table at ROM `0xc5720`); the simulation answers the same.
|
||||
|
||||
The bike does not move, the game runs as on a working cabinet.
|
||||
|
||||
## Rail Chase 2 (`rchase2a`)
|
||||
|
||||
A second program for Rail Chase 2 that reads the guns the other way round
|
||||
(maybe a factory conversion). The guns are centred at `0x80` over the full
|
||||
range, as MAME's `rchase2a` ports.
|
||||
|
||||
## Daytona USA hacks
|
||||
|
||||
Sets: `daytonat`, `daytonata` (Turbo hack), `daytonam` (To The MAXX),
|
||||
`daytonagtx` (GTX 2004 Edition). Hacks by Kyle Hodgetts, listed by MAME as
|
||||
not working; here they play.
|
||||
|
||||
- **To The MAXX**: the kit has a PIC 16F84 in socket IC15. It answers at
|
||||
`0x240000`, where the third program ROM (`maxx.14`) is seen. As MAME:
|
||||
16-bit reads of the first 32 bytes step a 4-bit counter and return the
|
||||
PIC's answer.
|
||||
- **GTX 2004**: a banked ROM over the data ROMs at `0x2c00000`. Reads of
|
||||
some bytes switch the bank, as MAME (`0xff00c` and `0xf0003` bank 0,
|
||||
`0xff000` bank 1, `0xffffc` the empty bank 2).
|
||||
|
||||
## Not added
|
||||
|
||||
- **Royal Ascot II** (`rascot2`): a horse racing terminal made for the
|
||||
SegaNet network. It waits for the network ("SegaNet Wait Status" in MAME)
|
||||
and never starts a race as a single machine.
|
||||
|
||||
- **Power Sled** (`powsled`, `powsledr`, `powsledm`): a network of
|
||||
cabinets run by a Main unit, whose program was never dumped (MAME's
|
||||
`powsledm` is a hack of the Relay program). Every version waits on the
|
||||
network ("NETWORK: NG") in MAME, and would need the whole network to be
|
||||
simulated.
|
||||
+6
-2
@@ -3,9 +3,12 @@ LOCAL_PATH := $(call my-dir)
|
||||
ROOT_DIR := $(LOCAL_PATH)/..
|
||||
CORE_DIR := $(ROOT_DIR)/src
|
||||
|
||||
# threads: in bionic's C library
|
||||
HAVE_THREADS := 1
|
||||
|
||||
include $(ROOT_DIR)/Makefile.common
|
||||
|
||||
COREFLAGS := $(DEFS) $(COREDEFS) $(CPUDEFS) $(SOUNDDEFS) $(ASMDEFS) $(DBGDEFS) -ffast-math -funroll-loops -DANDROID -DHAVE_ZLIB $(INCFLAGS)
|
||||
COREFLAGS := $(DEFS) $(COREDEFINES) $(CPUDEFS) $(SOUNDDEFS) $(ASMDEFS) $(DBGDEFS) -ffast-math -funroll-loops -DANDROID -DHAVE_ZLIB $(INCFLAGS)
|
||||
|
||||
GIT_VERSION := " $(shell git rev-parse --short HEAD || echo unknown)"
|
||||
ifneq ($(GIT_VERSION)," unknown")
|
||||
@@ -16,7 +19,8 @@ include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := retro
|
||||
LOCAL_SRC_FILES := $(SOURCES_C)
|
||||
LOCAL_CFLAGS := -std=gnu90 $(COREFLAGS) -fsigned-char
|
||||
LOCAL_LDFLAGS := -Wl,-version-script=$(ROOT_DIR)/link.T
|
||||
LOCAL_LDFLAGS := -Wl,-version-script=$(ROOT_DIR)/link.T,-z,max-page-size=16384
|
||||
LOCAL_SHORT_COMMANDS := true
|
||||
|
||||
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||
LOCAL_ARM_NEON := true
|
||||
|
||||
Binary file not shown.
+5495
-5045
File diff suppressed because it is too large.
Load diff
+1061
-509
File diff suppressed because it is too large.
Load diff
@@ -1688,6 +1688,7 @@ batriderhk:
|
||||
|
||||
mrdrillrj:
|
||||
mrdrillr:
|
||||
mrdrillrja2:
|
||||
0:201038:288:76:76
|
||||
|
||||
sfiii3:
|
||||
@@ -1829,6 +1830,7 @@ spf2xjd:
|
||||
spf2ta:
|
||||
spf2th:
|
||||
spf2td:
|
||||
spf2xpri:
|
||||
0:ffd7aa:4e:00:02
|
||||
0:ff8081:1:01:01
|
||||
|
||||
@@ -2775,7 +2777,9 @@ chinhero3:
|
||||
0:e12a:1:03:03
|
||||
|
||||
asurabus:
|
||||
asurabusa:
|
||||
asurabusj:
|
||||
asurabusja:
|
||||
asurabusjr:
|
||||
0:40326d:132:05:14
|
||||
|
||||
dynabomb:
|
||||
@@ -3270,7 +3274,7 @@ theglob2:
|
||||
0:7c4b:1:01:01
|
||||
0:7c51:1:80:80
|
||||
|
||||
beastf:
|
||||
beastfp:
|
||||
0:4c46:3c:4d:00
|
||||
0:4c8a:1:01:01
|
||||
0:4cb0:1:15:15
|
||||
@@ -5932,6 +5936,7 @@ offtwallc:
|
||||
0:3fee2e:37:00:49
|
||||
|
||||
bublbobl:
|
||||
bublbobr:
|
||||
bub68705:
|
||||
bublboblr:
|
||||
bublboblr1:
|
||||
|
||||
+31
-31
@@ -18291,7 +18291,7 @@ F.A.Q. by Kevin Butler A.K.A. War Doc
|
||||
$end
|
||||
|
||||
|
||||
$info=batsugun,batugnsp,batsugna,
|
||||
$info=batsugun,batsuguna,batsugunc,batsugunb,batsugunsp,
|
||||
$bio
|
||||
|
||||
Batsugun (c) 02/1993 Toaplan.
|
||||
@@ -20586,7 +20586,7 @@ Commodore Amiga (1990)
|
||||
$end
|
||||
|
||||
|
||||
$info=beastf,
|
||||
$info=beastf,beastfp,
|
||||
$bio
|
||||
|
||||
Beastie Feastie (c) 1984 Epos Corporation.
|
||||
@@ -39674,7 +39674,7 @@ Graphic : Kim Eun Ae, Hong Young Joo, Whang O-Sik, Hong Dae Hyun
|
||||
$end
|
||||
|
||||
|
||||
$info=chplft,chplftb,chplftbl,
|
||||
$info=choplift,chopliftu,chopliftbl,
|
||||
$bio
|
||||
|
||||
Choplifter (c) 1985 Sega.
|
||||
@@ -49927,7 +49927,7 @@ The title of this game translates from Japanese as 'Hanafuda at the Apartments'.
|
||||
$end
|
||||
|
||||
|
||||
$info=danceyes,
|
||||
$info=danceyes,danceyesu,danceyesj,
|
||||
$bio
|
||||
|
||||
Dancing Eyes (c) 08/1996 Namco.
|
||||
@@ -57433,7 +57433,7 @@ Nintendo Famicom (1988, "Ikari 2 - Dogosoken")
|
||||
$end
|
||||
|
||||
|
||||
$info=dogyuun,
|
||||
$info=dogyuun,dogyuuna,dogyuunb,dogyuunt,
|
||||
$bio
|
||||
|
||||
Dogyuun (c) 10/1992 Toaplan.
|
||||
@@ -63256,7 +63256,7 @@ This game is also known as "Dataeast's Hoops".
|
||||
$end
|
||||
|
||||
|
||||
$info=dunkmnia,dunkmnic,
|
||||
$info=dunkmnia,dunkmniajc,
|
||||
$bio
|
||||
|
||||
Dunk Mania (c) 1995 Namco.
|
||||
@@ -68525,7 +68525,7 @@ Designed by : Luis Sanchez
|
||||
$end
|
||||
|
||||
|
||||
$info=ehrgeiz,ehrgeiza,
|
||||
$info=ehrgeiz,ehrgeizua,ehrgeizja,
|
||||
$bio
|
||||
|
||||
EZ : Ehrgeiz - God Bless The Ring (c) 1998 Square / Namco.
|
||||
@@ -71900,7 +71900,7 @@ Buttons : 2
|
||||
$end
|
||||
|
||||
|
||||
$info=fgtlayer,
|
||||
$info=fgtlayer,fgtlayerja,
|
||||
$bio
|
||||
|
||||
Fighting Layer (c) 12/1998 Arika.
|
||||
@@ -74054,7 +74054,7 @@ This game is also known as "Round-Up".
|
||||
$end
|
||||
|
||||
|
||||
$info=fixeight,fixeighb,
|
||||
$info=fixeight,fixeightk,fixeighth,fixeighttw,fixeighta,fixeightu,fixeightj,fixeightt,fixeightkt,fixeightht,fixeighttwt,fixeightat,fixeightut,fixeightjt,fixeightbl,
|
||||
$bio
|
||||
|
||||
Fixeight (c) 1992 Toaplan.
|
||||
@@ -84877,7 +84877,7 @@ The US version has the "Recycle It, Don't Trash It!" screen.
|
||||
$end
|
||||
|
||||
|
||||
$info=mp_gaxe2,
|
||||
$info=mp_gaxe2,mp_gaxe2a,
|
||||
$bio
|
||||
|
||||
Golden Axe II (c) 1993 Sega.
|
||||
@@ -89643,7 +89643,7 @@ F.A.Q. by Kevin Butler A.K.A. War Doc
|
||||
$end
|
||||
|
||||
|
||||
$info=grindstm,grindsta,
|
||||
$info=grindstm,grindstma,
|
||||
$bio
|
||||
|
||||
Grind Stormer (c) 1992 Toaplan.
|
||||
@@ -95537,7 +95537,7 @@ King Records released a limited-edition soundtrack album for this game (Konami G
|
||||
$end
|
||||
|
||||
|
||||
$info=hayaosi1,
|
||||
$info=hayaosi2,
|
||||
$bio
|
||||
|
||||
Hayaoshi Quiz Ouza Ketteisen (c) 1994 Jaleco.
|
||||
@@ -100624,7 +100624,7 @@ Sega Saturn (1996, "Sega Ages : Rouka ni Ichidant-R")
|
||||
$end
|
||||
|
||||
|
||||
$info=47pie2,47pie2o,
|
||||
$info=suchie2,suchie2o,
|
||||
$bio
|
||||
|
||||
Idol Janshi Suchi-Pai II (c) 1994 Jaleco.
|
||||
@@ -115022,7 +115022,7 @@ You can also get points by punching out enemies. If you can punch out an enemy w
|
||||
$end
|
||||
|
||||
|
||||
$info=kbash,
|
||||
$info=kbash,kbashk,kbashp,
|
||||
$bio
|
||||
|
||||
Knuckle Bash (c) 1993 Toaplan.
|
||||
@@ -146695,7 +146695,7 @@ MSX (1985)
|
||||
$end
|
||||
|
||||
|
||||
$info=mrdrillr,
|
||||
$info=mrdrillr,mrdrillrja2,
|
||||
$bio
|
||||
|
||||
Mr. Driller (c) 1999 Namco.
|
||||
@@ -153222,7 +153222,7 @@ PC [MS Windows] (2005, "Taito Legends")
|
||||
$end
|
||||
|
||||
|
||||
$info=nzerotea,
|
||||
$info=nzeroteam,nzeroteama,nzeroteamb,zerotm2k,
|
||||
$bio
|
||||
|
||||
New Zero Team (c) 1993 Seibu Kaihatsu.
|
||||
@@ -168550,7 +168550,7 @@ Sony PlayStation 2 (2002, "Gunvari Collection + Time Crisis")
|
||||
$end
|
||||
|
||||
|
||||
$info=ptblank2,
|
||||
$info=ptblank2,ptblank2a,ptblank2b,ptblank2c,ptblank2ua,gunbarla,
|
||||
$bio
|
||||
|
||||
Point Blank 2 (c) 1999 Namco.
|
||||
@@ -182610,7 +182610,7 @@ PC [MS-DOS, CD-ROM]
|
||||
$end
|
||||
|
||||
|
||||
$info=raidndx,raidndxa,raidndxb,raidndxj,raidndxm,
|
||||
$info=raidendx,raidendxg,raidendxpt,raidendxa1,raidendxa2,raidendxk,raidendxu,raidendxnl,raidendxj,raidendxja,raidendxch,r2dx_v33,r2dx_v33_r2,
|
||||
$bio
|
||||
|
||||
Raiden DX (c) 1994 Seibu Kaihatsu.
|
||||
@@ -183143,7 +183143,7 @@ Level 15 : Before the boss appears, do not shoot any small tanks. Two small tank
|
||||
$end
|
||||
|
||||
|
||||
$info=raiden2,raiden2a,raiden2b,raiden2c,raiden2e,
|
||||
$info=raiden2,raiden2g,raiden2gb,raiden2hk,raiden2j,raiden2sw,raiden2u,raiden2f,raiden2nl,raiden2es,raiden2i,raiden2au,raiden2e,raiden2eub,raiden2eua,raiden2eg,raiden2eup,raiden2ea,raiden2eu,raiden2k,raiden2dx,
|
||||
$bio
|
||||
|
||||
Raiden II (c) 1993 Seibu Kaihatsu.
|
||||
@@ -187724,7 +187724,7 @@ Total planner / Total cordinator : The Alive
|
||||
$end
|
||||
|
||||
|
||||
$info=revenger,
|
||||
$info=revenger,revngr84,
|
||||
$bio
|
||||
|
||||
Revenger (c) 1984 Epos.
|
||||
@@ -210976,7 +210976,7 @@ Sega Saturn (1997)
|
||||
$end
|
||||
|
||||
|
||||
$info=soulclbr,soulclba,soulclbb,
|
||||
$info=soulclbr,soulclbrab,soulclbrac,soulclbrub,soulclbruc,soulclbrja2,soulclbrjb,soulclbrjc,
|
||||
$bio
|
||||
|
||||
Soul Calibur (c) 07/1998 Namco.
|
||||
@@ -211061,7 +211061,7 @@ Sega Dreamcast (1999) : The new Weapon Master mode made it's debut in this versi
|
||||
$end
|
||||
|
||||
|
||||
$info=souledga,souledgb,souledgc,
|
||||
$info=souledgea,souledgeua,souledgeja,
|
||||
$bio
|
||||
|
||||
Soul Edge (c) 1995 Namco.
|
||||
@@ -211188,7 +211188,7 @@ Sony PlayStation (1996)
|
||||
$end
|
||||
|
||||
|
||||
$info=souledge,
|
||||
$info=souledge,souledgeuc,
|
||||
$bio
|
||||
|
||||
Soul Edge Ver. II (c) 1996 Namco.
|
||||
@@ -219296,7 +219296,7 @@ Sega Saturn (1997, "Sega Memorial Selection Vol.2")
|
||||
$end
|
||||
|
||||
|
||||
$info=starswep,
|
||||
$info=starswep,starswepj,
|
||||
$bio
|
||||
|
||||
Star Sweep (c) 07/1997 Axela.
|
||||
@@ -242217,7 +242217,7 @@ Directed by : Strong Shima
|
||||
$end
|
||||
|
||||
|
||||
$info=mp_twc,
|
||||
$info=mp_twcup,
|
||||
$bio
|
||||
|
||||
Tecmo World Cup (c) 1993 Sega.
|
||||
@@ -243474,7 +243474,7 @@ Music composed by : Tomoaki Takanohashi
|
||||
$end
|
||||
|
||||
|
||||
$info=tekken,tekkena,tekkenb,tekkenc,
|
||||
$info=tekken,tekkenac,tekkenb,tekkenjb,
|
||||
$bio
|
||||
|
||||
Tekken (c) 12/1994 Namco.
|
||||
@@ -243635,7 +243635,7 @@ Sony PlayStation 2 (2005, "NamCollection") : Japan release only.
|
||||
$end
|
||||
|
||||
|
||||
$info=tekken2,tekken2a,tekken2b,
|
||||
$info=tekken2,tekken2b,tekken2ud,tekken2ub,tekken2jc,tekken2jb,tekken2a,tekken2ua,
|
||||
$bio
|
||||
|
||||
Tekken 2 (c) 08/1995 Namco.
|
||||
@@ -243867,7 +243867,7 @@ Sony PlayStation 2 (2005, "Tekken 5 Ultimate Collectors Edition")
|
||||
$end
|
||||
|
||||
|
||||
$info=tekken3,tekken3a,
|
||||
$info=tekken3,tekken3je1,
|
||||
$bio
|
||||
|
||||
Tekken 3 (c) 1996 Namco.
|
||||
@@ -244067,7 +244067,7 @@ Sony PlayStation 2 (2005, "Tekken 5 Ultimate Collectors Edition")
|
||||
$end
|
||||
|
||||
|
||||
$info=tektagt,tektagta,
|
||||
$info=tektagt,tektagtub,tektagtuc1,tektagtjc1,
|
||||
$bio
|
||||
|
||||
Tekken Tag Tournament (c) 1999 Namco.
|
||||
@@ -275757,7 +275757,7 @@ F.A.Q. by Kevin Butler A.K.A. War Doc
|
||||
$end
|
||||
|
||||
|
||||
$info=xevi3dg,
|
||||
$info=xevi3dg,xevi3dga,xevi3dgj,
|
||||
$bio
|
||||
|
||||
Xevious 3D/G (c) 04/1995 Namco.
|
||||
@@ -278372,7 +278372,7 @@ This game is known in Japan as "Gekitsui Oh".
|
||||
$end
|
||||
|
||||
|
||||
$info=zeroteam,zeroteaa,zeroteab,
|
||||
$info=zeroteam,zeroteama,zeroteamb,zeroteamc,zeroteamd,zeroteame,zeroteams,zeroteamsr,
|
||||
$bio
|
||||
|
||||
Zero Team (c) 1993 Seibu Kaihatsu.
|
||||
|
||||
+67825
-10670
File diff suppressed because it is too large.
Load diff
+124
-37
@@ -377,6 +377,7 @@ struct artwork_piece
|
||||
struct mame_bitmap * yrgbbitmap;
|
||||
UINT32 * scanlinehint;
|
||||
UINT8 blendflags;
|
||||
const struct overlay_piece *overlay_data; /* a driver's overlay: drawn again on a resize */
|
||||
|
||||
/* derived/dynamic data */
|
||||
int intersects_game;
|
||||
@@ -408,6 +409,9 @@ static int gamescale;
|
||||
static struct mame_bitmap *uioverlay;
|
||||
static UINT32 *uioverlayhint;
|
||||
static struct rectangle uibounds, last_uibounds;
|
||||
static struct rectangle ui_changed_bounds;
|
||||
static int ui_changed;
|
||||
static int full_render_pending; /* after a resize: draw the whole game, not the vector dirty pixels */
|
||||
|
||||
static UINT32 *palette_lookup;
|
||||
|
||||
@@ -446,6 +450,7 @@ static void alpha_blend_intersecting_rect(struct mame_bitmap *dstbitmap, const s
|
||||
static void add_intersecting_rect(struct mame_bitmap *dstbitmap, const struct rectangle *dstbounds, struct mame_bitmap *srcbitmap, const struct rectangle *srcbounds);
|
||||
static void cmy_blend_intersecting_rect(struct mame_bitmap *dstbitmap, struct mame_bitmap *dstyrgbbitmap, const struct rectangle *dstbounds, struct mame_bitmap *srcbitmap, struct mame_bitmap *srcyrgbbitmap, const struct rectangle *srcbounds, UINT8 blendflags);
|
||||
static int generate_overlay(const struct overlay_piece *list, int width, int height);
|
||||
static int generate_overlay_bitmap(struct artwork_piece *piece, int width, int height);
|
||||
static void add_range_to_hint(UINT32 *hintbase, int scanline, int startx, int endx);
|
||||
|
||||
|
||||
@@ -596,7 +601,89 @@ static INLINE UINT32 blend_over(UINT32 game, UINT32 pre, UINT32 yrgb)
|
||||
to osd_create_display
|
||||
-------------------------------------------------*/
|
||||
|
||||
static int artwork_setup_display(struct osd_create_params *params, UINT32 *rgb_components);
|
||||
|
||||
int artwork_create_display(struct osd_create_params *params, UINT32 *rgb_components, const struct artwork_callbacks *callbacks)
|
||||
{
|
||||
/* reset UI */
|
||||
uioverlay = NULL;
|
||||
uioverlayhint = NULL;
|
||||
palette_lookup = NULL;
|
||||
|
||||
/* first load the artwork; if none, quit now */
|
||||
artwork_list = NULL;
|
||||
if (!artwork_load(Machine->gamedrv, params->width, params->height, callbacks))
|
||||
return 1;
|
||||
if (!artwork_list && (!callbacks->activate_artwork || !callbacks->activate_artwork(params)))
|
||||
return osd_create_display(params, rgb_components);
|
||||
|
||||
return artwork_setup_display(params, rgb_components);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
artwork_resize_display - the game's display
|
||||
changes size while it runs (the vector
|
||||
resolution): the loaded artwork is kept, the
|
||||
bitmaps that depend on the size are made again
|
||||
-------------------------------------------------*/
|
||||
|
||||
int artwork_resize_display(struct osd_create_params *params, UINT32 *rgb_components)
|
||||
{
|
||||
struct artwork_piece *piece;
|
||||
|
||||
if (!artwork_list && !uioverlay)
|
||||
{
|
||||
osd_close_display();
|
||||
return osd_create_display(params, rgb_components);
|
||||
}
|
||||
|
||||
/* free what was made for the old size */
|
||||
auto_bitmap_free(underlay);
|
||||
auto_bitmap_free(overlay);
|
||||
auto_bitmap_free(overlay_yrgb);
|
||||
auto_bitmap_free(bezel);
|
||||
auto_bitmap_free(final);
|
||||
auto_bitmap_free(uioverlay);
|
||||
auto_free_ptr(uioverlayhint);
|
||||
underlay = overlay = overlay_yrgb = bezel = final = uioverlay = NULL;
|
||||
uioverlayhint = NULL;
|
||||
for (piece = artwork_list; piece; piece = piece->next)
|
||||
{
|
||||
auto_bitmap_free(piece->prebitmap);
|
||||
auto_bitmap_free(piece->yrgbbitmap);
|
||||
auto_free_ptr(piece->scanlinehint);
|
||||
piece->prebitmap = piece->yrgbbitmap = NULL;
|
||||
piece->scanlinehint = NULL;
|
||||
|
||||
/* a driver's overlay is drawn at the game's size: draw it again */
|
||||
if (piece->overlay_data)
|
||||
{
|
||||
auto_bitmap_free(piece->rawbitmap);
|
||||
piece->rawbitmap = NULL;
|
||||
if (!generate_overlay_bitmap(piece, params->width, params->height))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* the UI areas were on the old size */
|
||||
memset(&uibounds, 0, sizeof(uibounds));
|
||||
memset(&last_uibounds, 0, sizeof(last_uibounds));
|
||||
memset(&ui_changed_bounds, 0, sizeof(ui_changed_bounds));
|
||||
ui_changed = 0;
|
||||
full_render_pending = 1;
|
||||
|
||||
osd_close_display();
|
||||
return artwork_setup_display(params, rgb_components);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
artwork_setup_display - size the artwork
|
||||
bitmaps for the display and create it
|
||||
-------------------------------------------------*/
|
||||
|
||||
static int artwork_setup_display(struct osd_create_params *params, UINT32 *rgb_components)
|
||||
{
|
||||
int original_width = params->width;
|
||||
int original_height = params->height;
|
||||
@@ -605,17 +692,6 @@ int artwork_create_display(struct osd_create_params *params, UINT32 *rgb_compone
|
||||
UINT32 rgb32_components[3];
|
||||
struct artwork_piece *piece;
|
||||
|
||||
/* reset UI */
|
||||
uioverlay = NULL;
|
||||
uioverlayhint = NULL;
|
||||
|
||||
/* first load the artwork; if none, quit now */
|
||||
artwork_list = NULL;
|
||||
if (!artwork_load(Machine->gamedrv, original_width, original_height, callbacks))
|
||||
return 1;
|
||||
if (!artwork_list && (!callbacks->activate_artwork || !callbacks->activate_artwork(params)))
|
||||
return osd_create_display(params, rgb_components);
|
||||
|
||||
/* determine the game bitmap scale factor */
|
||||
gamescale = options.artwork_res;
|
||||
if (gamescale < 1 || (params->video_attributes & VIDEO_TYPE_VECTOR))
|
||||
@@ -798,8 +874,6 @@ void artwork_update_visible_area(struct mame_display *display)
|
||||
|
||||
void artwork_update_video_and_audio(struct mame_display *display)
|
||||
{
|
||||
static struct rectangle ui_changed_bounds;
|
||||
static int ui_changed;
|
||||
int artwork_changed = 0, ui_visible = 0;
|
||||
|
||||
/* do nothing if no artwork */
|
||||
@@ -824,6 +898,13 @@ void artwork_update_video_and_audio(struct mame_display *display)
|
||||
/* process the artwork and UI only if we're not frameskipping */
|
||||
if (display->changed_flags & GAME_BITMAP_CHANGED)
|
||||
{
|
||||
if (full_render_pending)
|
||||
{
|
||||
display->changed_flags &= ~VECTOR_PIXELS_CHANGED;
|
||||
display->vector_dirty_pixels = NULL;
|
||||
full_render_pending = 0;
|
||||
}
|
||||
|
||||
/* see if there's any UI to display this frame */
|
||||
ui_visible = (uibounds.max_x != 0);
|
||||
|
||||
@@ -2295,10 +2376,10 @@ static int artwork_load(const struct GameDriver *driver, int width, int height,
|
||||
/* A negative values will use the default opacity for the overlay. */
|
||||
opacity = options.overlay_opacity;
|
||||
if (opacity != 0 && list) {
|
||||
if (opacity < 0) { // Default overlay opacity
|
||||
if (opacity < 0) { /* Default overlay opacity */
|
||||
if (!generate_overlay(list, width, height))
|
||||
return 0;
|
||||
} else { // Opacity is > 0
|
||||
} else { /* Opacity is > 0 */
|
||||
struct overlay_piece *newlist;
|
||||
/* Count elements in list */
|
||||
int count = 0;
|
||||
@@ -2312,8 +2393,8 @@ static int artwork_load(const struct GameDriver *driver, int width, int height,
|
||||
/* Modify opacity as set to user defined value */
|
||||
tmp = newlist;
|
||||
while (tmp->type != OVERLAY_TYPE_END) {
|
||||
tmp->color = tmp->color & ~(0xff << 24); // Clear
|
||||
tmp->color = tmp->color | (((opacity) & 0xff) << 24); // Set
|
||||
tmp->color = tmp->color & ~(0xff << 24); /* Clear */
|
||||
tmp->color = tmp->color | (((opacity) & 0xff) << 24); /* Set */
|
||||
tmp++;
|
||||
}
|
||||
if (!generate_overlay(newlist, width, height))
|
||||
@@ -3349,6 +3430,25 @@ static int generate_right_triangle_piece(struct artwork_piece *piece, const stru
|
||||
the given pieces
|
||||
-------------------------------------------------*/
|
||||
|
||||
static int generate_overlay_bitmap(struct artwork_piece *piece, int width, int height)
|
||||
{
|
||||
const struct overlay_piece *list = piece->overlay_data;
|
||||
|
||||
/* switch off the type */
|
||||
switch (list->type & ~OVERLAY_FLAG_MASK)
|
||||
{
|
||||
case OVERLAY_TYPE_RECTANGLE:
|
||||
return generate_rect_piece(piece, list, width, height);
|
||||
|
||||
case OVERLAY_TYPE_DISK:
|
||||
return generate_disk_piece(piece, list, width, height);
|
||||
|
||||
case OVERLAY_TYPE_RIGHT_TRIANGLE:
|
||||
return generate_right_triangle_piece(piece, list, width, height);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int generate_overlay(const struct overlay_piece *list, int width, int height)
|
||||
{
|
||||
struct artwork_piece *piece;
|
||||
@@ -3367,25 +3467,11 @@ static int generate_overlay(const struct overlay_piece *list, int width, int hei
|
||||
piece->layer = LAYER_OVERLAY;
|
||||
piece->priority = priority++;
|
||||
piece->blendflags = list->type & OVERLAY_FLAG_MASK;
|
||||
piece->tag = list->tag; // Handle someone using a different tag, for example, cocktail mode
|
||||
piece->tag = list->tag; /* Handle someone using a different tag, for example, cocktail mode */
|
||||
piece->overlay_data = list;
|
||||
|
||||
/* switch off the type */
|
||||
switch (list->type & ~OVERLAY_FLAG_MASK)
|
||||
{
|
||||
case OVERLAY_TYPE_RECTANGLE:
|
||||
if (!generate_rect_piece(piece, list, width, height))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case OVERLAY_TYPE_DISK:
|
||||
if (!generate_disk_piece(piece, list, width, height))
|
||||
return 0;
|
||||
break;
|
||||
case OVERLAY_TYPE_RIGHT_TRIANGLE:
|
||||
if (!generate_right_triangle_piece(piece, list, width, height))
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
if (!generate_overlay_bitmap(piece, width, height))
|
||||
return 0;
|
||||
|
||||
/* next */
|
||||
list++;
|
||||
@@ -3582,8 +3668,9 @@ static int compute_rgb_components(int depth, UINT32 rgb_components[3], UINT32 rg
|
||||
/* compute a transparent color; this is in the premultiplied space, so alpha is inverted */
|
||||
transparent_color = ASSEMBLE_ARGB(0xff,0x00,0x00,0x00);
|
||||
|
||||
/* allocate a palette lookup */
|
||||
palette_lookup = auto_malloc(65536 * sizeof(palette_lookup[0]));
|
||||
/* allocate a palette lookup (once per game: a resize keeps it, as the depth and palette stay) */
|
||||
if (!palette_lookup)
|
||||
palette_lookup = auto_malloc(65536 * sizeof(palette_lookup[0]));
|
||||
|
||||
|
||||
/* switch off the depth */
|
||||
|
||||
+2
-1
@@ -148,7 +148,7 @@ struct artwork_callbacks
|
||||
|
||||
struct overlay_piece
|
||||
{
|
||||
char *tag; // Usually set to OVERLAY_TAG
|
||||
char *tag; /* Usually set to OVERLAY_TAG */
|
||||
UINT8 type;
|
||||
rgb_t color;
|
||||
float left, top, right, bottom;
|
||||
@@ -163,6 +163,7 @@ struct overlay_piece
|
||||
***************************************************************************/
|
||||
|
||||
int artwork_create_display(struct osd_create_params *params, UINT32 *rgb_components, const struct artwork_callbacks *callbacks);
|
||||
int artwork_resize_display(struct osd_create_params *params, UINT32 *rgb_components);
|
||||
void artwork_update_video_and_audio(struct mame_display *display);
|
||||
void artwork_override_screenshot_params(struct mame_bitmap **bitmap, struct rectangle *rect, UINT32 *rgb_components);
|
||||
|
||||
|
||||
+44
-30
@@ -13077,7 +13077,7 @@ const struct bin2cFILE ddsoma_bootstrap = {
|
||||
0, 0, 0, 0, 68, 38, 68, 50, 32, 65, 83, 73, 0, 11, 1, 0, 1, 1,
|
||||
1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,150, 2, 1, 6, 0, 0, 0, 0, 68, 38,
|
||||
68, 50, 32, 65, 83, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
68, 50, 32, 65, 83, 73, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0,
|
||||
}
|
||||
@@ -39040,14 +39040,14 @@ const struct bin2cFILE nbamaxht_bootstrap = {
|
||||
const struct bin2cFILE nslashers_bootstrap = {
|
||||
128,
|
||||
{
|
||||
196, 2, 0, 3, 0, 0, 0, 0, 80, 1, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
198, 2, 0, 3, 1, 0, 0, 0, 80, 1, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 50, 88, 77,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 31, 4,251,224,196, 2, 0, 3, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 34, 4,251,221,198, 2, 0, 3, 1, 0, 0, 0,
|
||||
80, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 48, 50, 88, 77, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 4,
|
||||
251,224,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 4,
|
||||
251,221,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -43679,6 +43679,20 @@ const struct bin2cFILE qix_bootstrap = {
|
||||
}
|
||||
};
|
||||
|
||||
const struct bin2cFILE rabbit_bootstrap = {
|
||||
128,
|
||||
{
|
||||
2, 52,255,255, 69,104,255,255,205,239,255,255,152,118,255,255, 0, 0,
|
||||
255,255, 0, 0,255,255, 0, 0,255,255, 0, 8,255,255, 0, 0,255,255,
|
||||
0, 0,255,255, 0, 0,255,255, 1, 0,255,255, 1, 3,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||
255,255,
|
||||
}
|
||||
};
|
||||
|
||||
/* used for revx */
|
||||
const struct bin2cFILE revx_bootstrap = {
|
||||
32768,
|
||||
@@ -81551,8 +81565,8 @@ const struct bin2cFILE umk3_bootstrap = {
|
||||
0, 0,255, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 0,255, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,255, 0,255, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0,255, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 0,255, 0,
|
||||
0, 0, 0, 0, 0, 0, 65, 0,255, 0,190, 0, 0, 0, 0, 0, 0, 0,
|
||||
65, 0,255, 0,190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 54, 0,255, 0,201, 0, 0, 0, 0, 0, 0, 0,
|
||||
54, 0,255, 0,201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@@ -81739,20 +81753,20 @@ const struct bin2cFILE umk3_bootstrap = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0,
|
||||
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
|
||||
0, 0, 3, 0, 0, 0, 0, 0, 0, 0,217, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 3, 0, 0, 0, 0, 0, 0, 0,220, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 4, 0, 0, 0, 0, 0,237, 0,176, 0, 0, 0, 0, 0,
|
||||
237, 0,176, 0, 0, 0, 0, 0,237, 0,176, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0,250, 0, 18, 0, 82, 0, 69, 0, 86, 0, 73, 0, 83, 0, 73, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0,254, 0,230, 0, 82, 0, 69, 0, 86, 0, 73, 0, 83, 0, 73, 0,
|
||||
79, 0, 78, 0, 32, 0, 49, 0, 46, 0, 50, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@@ -84273,8 +84287,6 @@ const struct bin2cFILE umk3p_bootstrap = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,255, 0,255, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0,255, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 0,255, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,255, 0,255, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0,255, 0,255, 0, 0, 0, 0, 0, 0, 0, 1, 0,255, 0,254, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,255, 0,255, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0,255, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 0,255, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,255, 0,255, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0,255, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 0,255, 0,
|
||||
@@ -84288,8 +84300,10 @@ const struct bin2cFILE umk3p_bootstrap = {
|
||||
0, 0,255, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 0,255, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,255, 0,255, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0,255, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 0,255, 0,
|
||||
0, 0, 0, 0, 0, 0,105, 0,255, 0,150, 0, 0, 0, 0, 0, 0, 0,
|
||||
105, 0,255, 0,150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 5, 0,255, 0,250, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0,255, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 0,255, 0,
|
||||
0, 0, 0, 0, 0, 0,160, 0,255, 0, 95, 0, 0, 0, 0, 0, 0, 0,
|
||||
160, 0,255, 0, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@@ -84483,26 +84497,26 @@ const struct bin2cFILE umk3p_bootstrap = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 4, 0, 0, 0, 0, 0,237, 0,176, 0, 0, 0, 0, 0,
|
||||
237, 0,176, 0, 0, 0, 0, 0,237, 0,176, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0,254, 0,218, 0, 32, 0, 77, 0, 79, 0, 82, 0, 84, 0, 65, 0,
|
||||
76, 0, 75, 0, 79, 0, 77, 0, 66, 0, 65, 0, 84, 0, 80, 0, 76, 0,
|
||||
85, 0, 83, 0, 46, 0, 67, 0, 79, 0, 77, 0, 32, 0, 66, 0, 69, 0,
|
||||
84, 0, 65, 0, 32, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0,250, 0, 13, 0, 77, 0, 79, 0, 82, 0, 84, 0, 65, 0, 76, 0,
|
||||
75, 0, 79, 0, 77, 0, 66, 0, 65, 0, 84, 0, 80, 0, 76, 0, 85, 0,
|
||||
83, 0, 46, 0, 67, 0, 79, 0, 77, 0, 32, 0, 66, 0, 69, 0, 84, 0,
|
||||
65, 0, 32, 0, 73, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@@ -87025,8 +87039,8 @@ const struct bin2cFILE umk3r11_bootstrap = {
|
||||
0, 0,255, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 0,255, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,255, 0,255, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0,255, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 0,255, 0,
|
||||
0, 0, 0, 0, 0, 0, 41, 0,255, 0,214, 0, 0, 0, 0, 0, 0, 0,
|
||||
41, 0,255, 0,214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 54, 0,255, 0,201, 0, 0, 0, 0, 0, 0, 0,
|
||||
54, 0,255, 0,201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@@ -87213,20 +87227,20 @@ const struct bin2cFILE umk3r11_bootstrap = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0,
|
||||
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
|
||||
0, 0, 3, 0, 0, 0, 0, 0, 0, 0,215, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 3, 0, 0, 0, 0, 0, 0, 0,218, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 4, 0, 0, 0, 0, 0,237, 0,176, 0, 0, 0, 0, 0,
|
||||
237, 0,176, 0, 0, 0, 0, 0,237, 0,176, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0,250, 0, 20, 0, 82, 0, 69, 0, 86, 0, 73, 0, 83, 0, 73, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0,254, 0,232, 0, 82, 0, 69, 0, 86, 0, 73, 0, 83, 0, 73, 0,
|
||||
79, 0, 78, 0, 32, 0, 49, 0, 46, 0, 49, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
@@ -59,6 +59,7 @@ extern const struct bin2cFILE nslashers_bootstrap;
|
||||
extern const struct bin2cFILE offroadc_bootstrap;
|
||||
extern const struct bin2cFILE openice_bootstrap;
|
||||
extern const struct bin2cFILE qix_bootstrap;
|
||||
extern const struct bin2cFILE rabbit_bootstrap;
|
||||
extern const struct bin2cFILE revx_bootstrap;
|
||||
extern const struct bin2cFILE rmpgwt11_bootstrap;
|
||||
extern const struct bin2cFILE rmpgwt_bootstrap;
|
||||
|
||||
+55
-47
@@ -385,6 +385,11 @@ is selected
|
||||
|
||||
#define OSD_READKEY_KLUDGE 1
|
||||
|
||||
#define NAME_MAX_LENGTH 255
|
||||
#define DESC_MAX_LENGTH 255
|
||||
#define STR_(X) #X
|
||||
#define STR(X) STR_(X)
|
||||
|
||||
/**** Macros *****************************************************************/
|
||||
|
||||
/* easy bitfield extraction and setting */
|
||||
@@ -1986,23 +1991,23 @@ static void RebuildStringTables(void)
|
||||
(!menuStrings.subStrings && menuStrings.numStrings) ||
|
||||
(!menuStrings.buf && storageNeeded))
|
||||
{
|
||||
logerror( "cheat: memory allocation error\n"
|
||||
" length = %.8X\n"
|
||||
" numStrings = %.8X\n"
|
||||
" mainStringLength = %.8X\n"
|
||||
" subStringLength = %.8X\n"
|
||||
"%.8X %.8X %.8X %.8X %.8X %.8X\n",
|
||||
menuStrings.length,
|
||||
menuStrings.numStrings,
|
||||
menuStrings.mainStringLength,
|
||||
menuStrings.subStringLength,
|
||||
|
||||
(int)menuStrings.mainList,
|
||||
(int)menuStrings.subList,
|
||||
(int)menuStrings.flagList,
|
||||
(int)menuStrings.mainStrings,
|
||||
(int)menuStrings.subStrings,
|
||||
(int)menuStrings.buf);
|
||||
logerror(
|
||||
"cheat: memory allocation error\n"
|
||||
"length = %.8X\n"
|
||||
"numStrings = %.8X\n"
|
||||
"mainStringLength = %.8X\n"
|
||||
"subStringLength = %.8X\n"
|
||||
"%08lX %08lX %08lX %08lX %08lX %08lX\n",
|
||||
menuStrings.length,
|
||||
menuStrings.numStrings,
|
||||
menuStrings.mainStringLength,
|
||||
menuStrings.subStringLength,
|
||||
(unsigned long)(FPTR)menuStrings.mainList,
|
||||
(unsigned long)(FPTR)menuStrings.subList,
|
||||
(unsigned long)(FPTR)menuStrings.flagList,
|
||||
(unsigned long)(FPTR)menuStrings.mainStrings,
|
||||
(unsigned long)(FPTR)menuStrings.subStrings,
|
||||
(unsigned long)(FPTR)menuStrings.buf);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
@@ -7080,7 +7085,7 @@ static void ResizeCheatListNoDispose(UINT32 newLength)
|
||||
|
||||
if(newLength > cheatListLength)
|
||||
{
|
||||
int i;
|
||||
UINT32 i;
|
||||
|
||||
memset(&cheatList[cheatListLength], 0, (newLength - cheatListLength) * sizeof(CheatEntry));
|
||||
|
||||
@@ -7312,9 +7317,18 @@ static void ResizeWatchListNoDispose(UINT32 newLength)
|
||||
|
||||
if(newLength > watchListLength)
|
||||
{
|
||||
int i;
|
||||
UINT32 i;
|
||||
size_t count = newLength - watchListLength;
|
||||
|
||||
memset(&watchList[watchListLength], 0, (newLength - watchListLength) * sizeof(WatchInfo));
|
||||
WatchInfo* newWatchList = realloc(watchList, newLength * sizeof(WatchInfo));
|
||||
if (!newWatchList)
|
||||
{
|
||||
logerror("cheat: Failed to realloc watchList to size %u\n", newLength);
|
||||
return; //we should probably bail if this happens
|
||||
}
|
||||
watchList = newWatchList;
|
||||
|
||||
memset(&watchList[watchListLength], 0, count * sizeof(WatchInfo));
|
||||
|
||||
for(i = watchListLength; i < newLength; i++)
|
||||
{
|
||||
@@ -7687,7 +7701,7 @@ static void RestoreRegionBackup(SearchRegion * region)
|
||||
static UINT8 DefaultEnableRegion(SearchRegion * region, SearchInfo * info)
|
||||
{
|
||||
mem_write_handler handler = region->writeHandler->handler;
|
||||
UINT32 handlerAddress = (UINT32)handler;
|
||||
FPTR handlerAddress = (FPTR)handler;
|
||||
|
||||
switch(info->searchSpeed)
|
||||
{
|
||||
@@ -7705,21 +7719,15 @@ static UINT8 DefaultEnableRegion(SearchRegion * region, SearchInfo * info)
|
||||
}
|
||||
#endif
|
||||
|
||||
if( (handler == MWA_RAM) &&
|
||||
(!region->writeHandler->base))
|
||||
if( (handler == MWA_RAM) && (!region->writeHandler->base))
|
||||
return 1;
|
||||
|
||||
{
|
||||
extern struct GameDriver driver_neogeo;
|
||||
|
||||
/* for neogeo, search bank one*/
|
||||
if( (Machine->gamedrv->clone_of == &driver_neogeo) &&
|
||||
(info->targetType == kRegionType_CPU) &&
|
||||
(info->targetIdx == 0) &&
|
||||
(handler == MWA_BANK1))
|
||||
/* for neogeo, search bank one*/
|
||||
if( (options.content_flags[CONTENT_NEOGEO]) &&
|
||||
(info->targetType == kRegionType_CPU) &&
|
||||
(info->targetIdx == 0) &&
|
||||
(handler == MWA_BANK1))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#if HAS_TMS34010
|
||||
|
||||
@@ -7742,8 +7750,8 @@ static UINT8 DefaultEnableRegion(SearchRegion * region, SearchInfo * info)
|
||||
return 0;
|
||||
|
||||
case kSearchSpeed_Medium:
|
||||
if( (handlerAddress >= ((UINT32)MWA_BANK1)) &&
|
||||
(handlerAddress <= ((UINT32)MWA_BANK24)))
|
||||
if ((handlerAddress >= (FPTR)MWA_BANK1) &&
|
||||
(handlerAddress <= (FPTR)MWA_BANK24))
|
||||
return 1;
|
||||
|
||||
if(handler == MWA_RAM)
|
||||
@@ -7784,21 +7792,21 @@ static void SetSearchRegionDefaultName(SearchRegion * region)
|
||||
if(region->writeHandler)
|
||||
{
|
||||
mem_write_handler handler = region->writeHandler->handler;
|
||||
UINT32 handlerAddress = (UINT32)handler;
|
||||
FPTR handlerAddress = (FPTR)handler;
|
||||
|
||||
if( (handlerAddress >= ((UINT32)MWA_BANK1)) &&
|
||||
(handlerAddress <= ((UINT32)MWA_BANK24)))
|
||||
if ((handlerAddress >= (FPTR)MWA_BANK1) &&
|
||||
(handlerAddress <= (FPTR)MWA_BANK24))
|
||||
{
|
||||
sprintf(desc, "BANK%.2d", (handlerAddress - ((UINT32)MWA_BANK1)) + 1);
|
||||
sprintf(desc, "BANK%.2d", (int)((handlerAddress - (FPTR)MWA_BANK1) + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(handlerAddress)
|
||||
{
|
||||
case (UINT32)MWA_NOP: strcpy(desc, "NOP "); break;
|
||||
case (UINT32)MWA_RAM: strcpy(desc, "RAM "); break;
|
||||
case (UINT32)MWA_ROM: strcpy(desc, "ROM "); break;
|
||||
case (UINT32)MWA_RAMROM: strcpy(desc, "RAMROM"); break;
|
||||
case (FPTR)MWA_NOP: strcpy(desc, "NOP "); break;
|
||||
case (FPTR)MWA_RAM: strcpy(desc, "RAM "); break;
|
||||
case (FPTR)MWA_ROM: strcpy(desc, "ROM "); break;
|
||||
case (FPTR)MWA_RAMROM: strcpy(desc, "RAMROM"); break;
|
||||
default: strcpy(desc, "CUSTOM"); break;
|
||||
}
|
||||
}
|
||||
@@ -8302,8 +8310,8 @@ static void LoadCheatDatabase()
|
||||
foundCheatDatabase = 1;
|
||||
|
||||
/* make the format strings*/
|
||||
sprintf(formatString, ":%s:%s", Machine->gamedrv->name, "%x:%x:%x:%x:%[^:\n\r]:%[^:\n\r]");
|
||||
sprintf(oldFormatString, "%s:%s", Machine->gamedrv->name, "%d:%x:%x:%d:%[^:\n\r]:%[^:\n\r]");
|
||||
sprintf(formatString, ":%s:%s", Machine->gamedrv->name, "%x:%x:%x:%x:%" STR(NAME_MAX_LENGTH) "[^:\n\r]:%" STR(DESC_MAX_LENGTH) "[^:\n\r]");
|
||||
sprintf(oldFormatString, "%s:%s", Machine->gamedrv->name, "%d:%x:%x:%d:%" STR(NAME_MAX_LENGTH) "[^:\n\r]:%" STR(DESC_MAX_LENGTH) "[^:\n\r]");
|
||||
|
||||
while(intfstream_gets(in_file, buf, 2048))
|
||||
{
|
||||
@@ -8311,8 +8319,8 @@ static void LoadCheatDatabase()
|
||||
int address;
|
||||
int data;
|
||||
int extendData;
|
||||
char name[256];
|
||||
char description[256];
|
||||
char name[NAME_MAX_LENGTH+1];
|
||||
char description[DESC_MAX_LENGTH+1];
|
||||
|
||||
int argumentsMatched;
|
||||
|
||||
|
||||
+205
-159
@@ -13,41 +13,16 @@
|
||||
#include <string/stdstring.h>
|
||||
#include "libretro-deps/libFLAC/include/FLAC/all.h"
|
||||
#include "log.h"
|
||||
//#define LOG_LOAD
|
||||
/*#define LOG_LOAD */
|
||||
|
||||
|
||||
char *chd_error_text[] =
|
||||
{
|
||||
"CHDERR_NONE",
|
||||
"CHDERR_NO_INTERFACE",
|
||||
"CHDERR_OUT_OF_MEMORY",
|
||||
"CHDERR_INVALID_FILE",
|
||||
"CHDERR_INVALID_PARAMETER",
|
||||
"CHDERR_INVALID_DATA",
|
||||
"CHDERR_FILE_NOT_FOUND",
|
||||
"CHDERR_REQUIRES_PARENT",
|
||||
"CHDERR_FILE_NOT_WRITEABLE",
|
||||
"CHDERR_READ_ERROR",
|
||||
"CHDERR_WRITE_ERROR",
|
||||
"CHDERR_CODEC_ERROR",
|
||||
"CHDERR_INVALID_PARENT",
|
||||
"CHDERR_HUNK_OUT_OF_RANGE",
|
||||
"CHDERR_DECOMPRESSION_ERROR",
|
||||
"CHDERR_COMPRESSION_ERROR",
|
||||
"CHDERR_CANT_CREATE_FILE",
|
||||
"CHDERR_CANT_VERIFY",
|
||||
"CHDERR_NOT_SUPPORTED",
|
||||
"CHDERR_METADATA_NOT_FOUND",
|
||||
"CHDERR_INVALID_METADATA_SIZE",
|
||||
"CHDERR_UNSUPPORTED_VERSION"
|
||||
};
|
||||
/***************************************************************************
|
||||
Constants
|
||||
***************************************************************************/
|
||||
|
||||
// VERY IMPORTANT: osd_alloc_bitmap must allocate also a "safety area" 16 pixels wide all
|
||||
// around the bitmap. This is required because, for performance reasons, some graphic
|
||||
// routines don't clip at boundaries of the bitmap.
|
||||
/* VERY IMPORTANT: osd_alloc_bitmap must allocate also a "safety area" 16 pixels wide all */
|
||||
/* around the bitmap. This is required because, for performance reasons, some graphic */
|
||||
/* routines don't clip at boundaries of the bitmap. */
|
||||
#define BITMAP_SAFETY 16
|
||||
|
||||
#define MAX_MALLOCS 4096
|
||||
@@ -182,7 +157,7 @@ size_t generic_nvram_size;
|
||||
data8_t *generic_nvram;
|
||||
|
||||
/* disks */
|
||||
static struct chd_file *disk_handle[4];
|
||||
static struct hard_disk_file *disk_handle[4];
|
||||
|
||||
/* system BIOS */
|
||||
static int system_bios;
|
||||
@@ -237,13 +212,13 @@ static struct GameSample *read_wav_sample(mame_file *f, const char *gamename, co
|
||||
return NULL;
|
||||
|
||||
if (memcmp(&buf[0], "RIFF", 4) == 0)
|
||||
f_type = 1; // WAV
|
||||
f_type = 1; /* WAV */
|
||||
else if (memcmp(&buf[0], "fLaC", 4) == 0)
|
||||
f_type = 2; // FLAC
|
||||
f_type = 2; /* FLAC */
|
||||
else
|
||||
return NULL; // No idea what file this is.
|
||||
return NULL; /* No idea what file this is. */
|
||||
|
||||
// Load WAV file.
|
||||
/* Load WAV file. */
|
||||
if(f_type == 1) {
|
||||
/* get the total size */
|
||||
offset += mame_fread(f, &filesize, 4);
|
||||
@@ -316,13 +291,13 @@ static struct GameSample *read_wav_sample(mame_file *f, const char *gamename, co
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// For small samples, lets force them to pre load into memory.
|
||||
/* For small samples, lets force them to pre load into memory. */
|
||||
if(length <= GAME_SAMPLE_LARGE)
|
||||
b_data = 1;
|
||||
|
||||
/* allocate the game sample */
|
||||
if(b_data == 1)
|
||||
result = auto_malloc(sizeof(struct GameSample) + length);
|
||||
result = malloc(sizeof(struct GameSample) + length);
|
||||
else
|
||||
result = malloc(sizeof(struct GameSample));
|
||||
|
||||
@@ -339,18 +314,18 @@ static struct GameSample *read_wav_sample(mame_file *f, const char *gamename, co
|
||||
result->resolution = bits;
|
||||
|
||||
if(b_data == 1) {
|
||||
// read the data in
|
||||
/* read the data in */
|
||||
if (bits == 8)
|
||||
{
|
||||
mame_fread(f, result->data, length);
|
||||
|
||||
// convert 8-bit data to signed samples
|
||||
/* convert 8-bit data to signed samples */
|
||||
for (temp32 = 0; temp32 < length; temp32++)
|
||||
result->data[temp32] ^= 0x80;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 16-bit data is fine as-is
|
||||
/* 16-bit data is fine as-is */
|
||||
mame_fread_lsbfirst(f, result->data, length);
|
||||
}
|
||||
|
||||
@@ -361,7 +336,7 @@ static struct GameSample *read_wav_sample(mame_file *f, const char *gamename, co
|
||||
|
||||
return result;
|
||||
}
|
||||
else if(f_type == 2) { // Load FLAC file.
|
||||
else if(f_type == 2) { /* Load FLAC file. */
|
||||
int f_length;
|
||||
flac_reader flac_file;
|
||||
FLAC__StreamDecoder *decoder;
|
||||
@@ -370,7 +345,7 @@ static struct GameSample *read_wav_sample(mame_file *f, const char *gamename, co
|
||||
f_length = mame_ftell(f);
|
||||
mame_fseek(f, 0, 0);
|
||||
|
||||
// For small samples, lets force them to pre load into memory.
|
||||
/* For small samples, lets force them to pre load into memory. */
|
||||
if (f_length <= GAME_SAMPLE_LARGE)
|
||||
b_data = 1;
|
||||
|
||||
@@ -378,10 +353,10 @@ static struct GameSample *read_wav_sample(mame_file *f, const char *gamename, co
|
||||
flac_file.position = 0;
|
||||
flac_file.decoded_size = 0;
|
||||
|
||||
// Allocate space for the data.
|
||||
/* Allocate space for the data. */
|
||||
flac_file.rawdata = malloc(f_length);
|
||||
|
||||
// Read the sample data in.
|
||||
/* Read the sample data in. */
|
||||
mame_fread(f, flac_file.rawdata, f_length);
|
||||
decoder = FLAC__stream_decoder_new();
|
||||
|
||||
@@ -391,12 +366,12 @@ static struct GameSample *read_wav_sample(mame_file *f, const char *gamename, co
|
||||
}
|
||||
|
||||
if(FLAC__stream_decoder_init_stream(decoder, my_read_callback,
|
||||
NULL, //my_seek_callback, // or NULL
|
||||
NULL, //my_tell_callback, // or NULL
|
||||
NULL, //my_length_callback, // or NULL
|
||||
NULL, //my_eof_callback, // or NULL
|
||||
NULL, /*my_seek_callback, // or NULL */
|
||||
NULL, /*my_tell_callback, // or NULL */
|
||||
NULL, /*my_length_callback, // or NULL */
|
||||
NULL, /*my_eof_callback, // or NULL */
|
||||
my_write_callback,
|
||||
my_metadata_callback, //my_metadata_callback, // or NULL
|
||||
my_metadata_callback, /*my_metadata_callback, // or NULL */
|
||||
my_error_callback,
|
||||
(void*)&flac_file) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
|
||||
return NULL;
|
||||
@@ -407,14 +382,14 @@ static struct GameSample *read_wav_sample(mame_file *f, const char *gamename, co
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// only Mono supported
|
||||
/* only Mono supported */
|
||||
if (flac_file.channels != 1) {
|
||||
free(flac_file.rawdata);
|
||||
FLAC__stream_decoder_delete(decoder);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// only support 16 bit.
|
||||
/* only support 16 bit. */
|
||||
if (flac_file.bits_per_sample != 16) {
|
||||
free(flac_file.rawdata);
|
||||
FLAC__stream_decoder_delete(decoder);
|
||||
@@ -422,7 +397,7 @@ static struct GameSample *read_wav_sample(mame_file *f, const char *gamename, co
|
||||
}
|
||||
|
||||
if (b_data == 1)
|
||||
result = auto_malloc(sizeof(struct GameSample) + (flac_file.total_samples * (flac_file.bits_per_sample / 8)));
|
||||
result = malloc(sizeof(struct GameSample) + (flac_file.total_samples * (flac_file.bits_per_sample / 8)));
|
||||
else
|
||||
result = malloc(sizeof(struct GameSample));
|
||||
|
||||
@@ -436,7 +411,7 @@ static struct GameSample *read_wav_sample(mame_file *f, const char *gamename, co
|
||||
flac_file.write_position = 0;
|
||||
|
||||
if (b_data == 1) {
|
||||
flac_file.write_data = result->data;
|
||||
flac_file.write_data = (INT16 *)result->data;
|
||||
|
||||
if (FLAC__stream_decoder_process_until_end_of_stream (decoder) != FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM) {
|
||||
free(flac_file.rawdata);
|
||||
@@ -472,7 +447,7 @@ void readsample(struct GameSample *SampleInfo, int channel, struct GameSamples *
|
||||
mame_file *f;
|
||||
struct GameSample *SampleFile;
|
||||
|
||||
// Try opening the file.
|
||||
/* Try opening the file. */
|
||||
f = mame_fopen(SampleInfo->gamename,SampleInfo->filename,SampleInfo->filetype,0);
|
||||
|
||||
if (f != 0) {
|
||||
@@ -483,10 +458,10 @@ void readsample(struct GameSample *SampleInfo, int channel, struct GameSamples *
|
||||
strcpy(gamename, SampleInfo->gamename);
|
||||
strcpy(filename, SampleInfo->filename);
|
||||
|
||||
// Free up some memory.
|
||||
/* Free up some memory. */
|
||||
free(SamplesData->sample[channel]);
|
||||
|
||||
// Reload or load a sample into memory.
|
||||
/* Reload or load a sample into memory. */
|
||||
SamplesData->sample[channel] = read_wav_sample(f, gamename, filename, filetype, load);
|
||||
|
||||
mame_fclose(f);
|
||||
@@ -520,7 +495,7 @@ struct GameSamples *readsamples(const char **samplenames,const char *basename)
|
||||
|
||||
if (!i) return 0;
|
||||
|
||||
if ((samples = auto_malloc(sizeof(struct GameSamples) + (i-1)*sizeof(struct GameSample))) == 0)
|
||||
if ((samples = malloc(sizeof(struct GameSamples) + (i-1)*sizeof(struct GameSample))) == 0)
|
||||
return 0;
|
||||
|
||||
samples->total = i;
|
||||
@@ -535,7 +510,7 @@ struct GameSamples *readsamples(const char **samplenames,const char *basename)
|
||||
|
||||
if (samplenames[i+skipfirst][0])
|
||||
{
|
||||
// Try opening FLAC samples first.
|
||||
/* Try opening FLAC samples first. */
|
||||
if ((f = mame_fopen(basename,samplenames[i+skipfirst],FILETYPE_SAMPLE_FLAC,0)) == 0)
|
||||
{
|
||||
if (skipfirst) {
|
||||
@@ -543,7 +518,7 @@ struct GameSamples *readsamples(const char **samplenames,const char *basename)
|
||||
f_skip = 1;
|
||||
}
|
||||
|
||||
// Fall back to WAV if it exists.
|
||||
/* Fall back to WAV if it exists. */
|
||||
if (!f)
|
||||
{
|
||||
f_type = 1;
|
||||
@@ -557,17 +532,17 @@ struct GameSamples *readsamples(const char **samplenames,const char *basename)
|
||||
}
|
||||
}
|
||||
|
||||
// Get sample info. Small sample files will pre load into memory at this point.
|
||||
/* Get sample info. Small sample files will pre load into memory at this point. */
|
||||
if (f != 0)
|
||||
{
|
||||
// Open FLAC.
|
||||
/* Open FLAC. */
|
||||
if(f_type == 0) {
|
||||
if (f_skip == 1)
|
||||
samples->sample[i] = read_wav_sample(f, samplenames[0]+1, samplenames[i+skipfirst], FILETYPE_SAMPLE_FLAC, 0);
|
||||
else
|
||||
samples->sample[i] = read_wav_sample(f, basename, samplenames[i+skipfirst], FILETYPE_SAMPLE_FLAC, 0);
|
||||
}
|
||||
else { // Open WAV.
|
||||
else { /* Open WAV. */
|
||||
if (f_skip == 1)
|
||||
samples->sample[i] = read_wav_sample(f, samplenames[0]+1, samplenames[i+skipfirst], FILETYPE_SAMPLE, 0);
|
||||
else
|
||||
@@ -996,6 +971,47 @@ void auto_free(void)
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
auto_free_ptr - free one auto_malloc block
|
||||
before its tag ends, and stop tracking it
|
||||
(for the buffers that are reallocated while
|
||||
a game runs, as the vector bitmap)
|
||||
-------------------------------------------------*/
|
||||
|
||||
void auto_free_ptr(void *ptr)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!ptr)
|
||||
return;
|
||||
|
||||
for (i = malloc_list_index - 1; i >= 0; i--)
|
||||
if (malloc_list[i].ptr == ptr)
|
||||
{
|
||||
free(ptr);
|
||||
memmove(&malloc_list[i], &malloc_list[i + 1], (malloc_list_index - i - 1) * sizeof(malloc_list[0]));
|
||||
malloc_list_index--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
auto_bitmap_free - free an auto_bitmap_alloc
|
||||
bitmap before its tag ends
|
||||
-------------------------------------------------*/
|
||||
|
||||
void auto_bitmap_free(struct mame_bitmap *bitmap)
|
||||
{
|
||||
if (!bitmap)
|
||||
return;
|
||||
|
||||
/* the line array was allocated before the safety rows were skipped */
|
||||
auto_free_ptr(bitmap->line - BITMAP_SAFETY);
|
||||
auto_free_ptr(bitmap);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
bitmap_alloc - allocate a bitmap at the
|
||||
current screen depth
|
||||
@@ -1051,7 +1067,7 @@ void end_resource_tracking(void)
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
struct chd_file *get_disk_handle(int diskindex)
|
||||
struct hard_disk_file *get_disk_handle(int diskindex)
|
||||
{
|
||||
return disk_handle[diskindex];
|
||||
}
|
||||
@@ -1136,7 +1152,7 @@ const struct RomModule *rom_first_chunk(const struct RomModule *romp)
|
||||
const struct RomModule *rom_next_chunk(const struct RomModule *romp)
|
||||
{
|
||||
romp++;
|
||||
return (ROMENTRY_ISCONTINUE(romp)) ? romp : NULL;
|
||||
return (ROMENTRY_ISCONTINUE(romp) || ROMENTRY_ISIGNORE(romp)) ? romp : NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -1153,46 +1169,26 @@ const struct RomModule *rom_next_chunk(const struct RomModule *romp)
|
||||
|
||||
int determine_bios_rom(const struct SystemBios *bios)
|
||||
{
|
||||
const struct SystemBios *firstbios = bios;
|
||||
|
||||
/* set to default */
|
||||
int bios_no = 0;
|
||||
|
||||
/* Not system_bios_0 and options.bios is set */
|
||||
if(bios && (options.bios != NULL))
|
||||
{
|
||||
|
||||
/* Allow '-bios n' to still be used */
|
||||
/* no actually in mame2003 we don't use the old numerical bios index
|
||||
we use the core option & option.bios string */
|
||||
/*
|
||||
while(!BIOSENTRY_ISEND(bios))
|
||||
{
|
||||
char bios_number[3];
|
||||
|
||||
if(!strcmp(bios_number, options.bios))
|
||||
bios_no = bios->value;
|
||||
|
||||
bios++;
|
||||
}
|
||||
|
||||
bios = firstbios;
|
||||
*/
|
||||
|
||||
/* Test for bios short names */
|
||||
while(!BIOSENTRY_ISEND(bios))
|
||||
{
|
||||
if(strcmp(bios->_name, options.bios) == 0)
|
||||
{
|
||||
log_cb(RETRO_LOG_INFO, LOGPRE "Using BIOS: %s\n", options.bios);
|
||||
{
|
||||
log_cb(RETRO_LOG_INFO, LOGPRE "Using BIOS: %s\n", options.bios);
|
||||
bios_no = bios->value;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
bios++;
|
||||
}
|
||||
if(string_is_empty(options.bios))
|
||||
log_cb(RETRO_LOG_INFO, LOGPRE "No matching BIOS found. Using default system BIOS.");
|
||||
|
||||
if(string_is_empty(options.bios))
|
||||
log_cb(RETRO_LOG_INFO, LOGPRE "No matching BIOS found. Using default system BIOS.");
|
||||
}
|
||||
|
||||
return bios_no;
|
||||
@@ -1231,7 +1227,7 @@ static int count_roms(const struct RomModule *romp)
|
||||
static void fill_random(UINT8 *base, UINT32 length)
|
||||
{
|
||||
while (length--)
|
||||
*base++ = rand();
|
||||
*base++ = mame_rand_int();
|
||||
}
|
||||
|
||||
|
||||
@@ -1473,10 +1469,10 @@ static int open_rom_file(struct rom_load_data *romdata, const struct RomModule *
|
||||
attempts any kind of load by checksum supported by the archives. */
|
||||
romdata->file = NULL;
|
||||
for (drv = Machine->gamedrv; !romdata->file && drv; drv = drv->clone_of)
|
||||
{
|
||||
|
||||
if (drv->name && *drv->name)
|
||||
romdata->file = mame_fopen_rom(drv->name, ROM_GETNAME(romp), ROM_GETHASHDATA(romp));
|
||||
}
|
||||
|
||||
|
||||
/* return the result */
|
||||
return (romdata->file != NULL);
|
||||
@@ -1559,7 +1555,7 @@ static int read_rom_data(struct rom_load_data *romdata, const struct RomModule *
|
||||
return 0;
|
||||
numbytes -= bytesleft;
|
||||
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE " Copying to %08X\n", (int)base);
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE " Copying to %08lX\n", (FPTR)base);
|
||||
|
||||
/* unmasked cases */
|
||||
if (datamask == 0xff)
|
||||
@@ -1644,7 +1640,7 @@ static int fill_rom_data(struct rom_load_data *romdata, const struct RomModule *
|
||||
}
|
||||
|
||||
/* fill the data (filling value is stored in place of the hashdata) */
|
||||
memset(base, (UINT32)ROM_GETHASHDATA(romp) & 0xff, numbytes);
|
||||
memset(base, (FPTR)ROM_GETHASHDATA(romp) & 0xff, numbytes);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1658,7 +1654,7 @@ static int copy_rom_data(struct rom_load_data *romdata, const struct RomModule *
|
||||
UINT8 *base = romdata->regionbase + ROM_GETOFFSET(romp);
|
||||
int srcregion = ROM_GETFLAGS(romp) >> 24;
|
||||
UINT32 numbytes = ROM_GETLENGTH(romp);
|
||||
UINT32 srcoffs = (UINT32)ROM_GETHASHDATA(romp); /* srcoffset in place of hashdata */
|
||||
UINT32 srcoffs = (UINT32)(FPTR)ROM_GETHASHDATA(romp);
|
||||
UINT8 *srcbase;
|
||||
|
||||
/* make sure we copy within the region space */
|
||||
@@ -1704,6 +1700,7 @@ static int copy_rom_data(struct rom_load_data *romdata, const struct RomModule *
|
||||
static int process_rom_entries(struct rom_load_data *romdata, const struct RomModule *romp)
|
||||
{
|
||||
UINT32 lastflags = 0;
|
||||
const struct RomModule *fallback_romp = romp;
|
||||
|
||||
/* loop until we hit the end of this region */
|
||||
while (!ROMENTRY_ISREGIONEND(romp))
|
||||
@@ -1714,6 +1711,9 @@ static int process_rom_entries(struct rom_load_data *romdata, const struct RomMo
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "Error in RomModule definition: ROM_CONTINUE not preceded by ROM_LOAD\n");
|
||||
goto fatalerror;
|
||||
}
|
||||
/* if this is an ignore entry, it's invalid */
|
||||
if (ROMENTRY_ISIGNORE(romp))
|
||||
fatalerror("Error in RomModule definition: ROM_IGNORE not preceded by ROM_LOAD\n");
|
||||
|
||||
/* if this is a reload entry, it's invalid */
|
||||
if (ROMENTRY_ISRELOAD(romp))
|
||||
@@ -1747,7 +1747,16 @@ static int process_rom_entries(struct rom_load_data *romdata, const struct RomMo
|
||||
/* open the file */
|
||||
log_cb(RETRO_LOG_INFO, LOGPRE "Opening ROM file: %s\n", ROM_GETNAME(romp));
|
||||
if (!open_rom_file(romdata, romp))
|
||||
handle_missing_file(romdata, romp);
|
||||
{
|
||||
if (ROM_GETBIOSFLAGS(romp) == (system_bios+1))
|
||||
{
|
||||
log_cb(RETRO_LOG_WARN, LOGPRE "%s NOT FOUND! Attempt fallback to default bios.\n", ROM_GETNAME(romp));
|
||||
if (!open_rom_file(romdata, &fallback_romp[0])) /* try default bios instead */
|
||||
handle_missing_file(romdata, romp);
|
||||
}
|
||||
else
|
||||
handle_missing_file(romdata, romp);
|
||||
}
|
||||
|
||||
/* loop until we run out of reloads */
|
||||
do
|
||||
@@ -1767,17 +1776,20 @@ static int process_rom_entries(struct rom_load_data *romdata, const struct RomMo
|
||||
explength += ROM_GETLENGTH(&modified_romp);
|
||||
|
||||
/* attempt to read using the modified entry */
|
||||
if (!ROMENTRY_ISIGNORE(&modified_romp))
|
||||
{
|
||||
readresult = read_rom_data(romdata, &modified_romp);
|
||||
if (readresult == -1)
|
||||
goto fatalerror;
|
||||
}
|
||||
while (ROMENTRY_ISCONTINUE(romp));
|
||||
}
|
||||
while (ROMENTRY_ISCONTINUE(romp) || ROMENTRY_ISIGNORE(romp));
|
||||
|
||||
/* if this was the first use of this file, verify the length and CRC */
|
||||
if (baserom)
|
||||
{
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Verifying length (%X) and checksums\n", explength);
|
||||
verify_length_and_hash(romdata, ROM_GETNAME(baserom), explength, ROM_GETHASHDATA(baserom));
|
||||
verify_length_and_hash(romdata, ROM_GETNAME(baserom), explength, ROM_GETHASHDATA(baserom));
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Length and checksum verify finished\n");
|
||||
}
|
||||
|
||||
@@ -1828,11 +1840,14 @@ static int process_disk_entries(struct rom_load_data *romdata, const struct RomM
|
||||
/* handle files */
|
||||
if (ROMENTRY_ISFILE(romp))
|
||||
{
|
||||
struct chd_file *source, *diff = NULL;
|
||||
struct chd_header header;
|
||||
const struct GameDriver *drv;
|
||||
struct hard_disk_file *disk;
|
||||
mame_file *source = NULL, *diff = NULL;
|
||||
UINT8 *legacydata = NULL;
|
||||
UINT32 legacysize = 0;
|
||||
char filename[1024], *c;
|
||||
char acthash[HASH_BUF_SIZE];
|
||||
int err;
|
||||
char datahash[HASH_BUF_SIZE], imagehash[HASH_BUF_SIZE];
|
||||
const char *error;
|
||||
|
||||
/* make the filename of the source */
|
||||
strcpy(filename, ROM_GETNAME(romp));
|
||||
@@ -1842,83 +1857,114 @@ static int process_disk_entries(struct rom_load_data *romdata, const struct RomM
|
||||
else
|
||||
strcat(filename, ".chd");
|
||||
|
||||
/* first open the source drive */
|
||||
/* look for it in the ROM path, up the chain through the parents */
|
||||
log_cb(RETRO_LOG_INFO, LOGPRE "Opening disk image: %s\n", filename);
|
||||
source = chd_open(filename, 0, NULL);
|
||||
for (drv = Machine->gamedrv; drv != NULL && source == NULL; drv = drv->clone_of)
|
||||
source = mame_fopen(drv->name, filename, FILETYPE_IMAGE, 0);
|
||||
if (!source)
|
||||
{
|
||||
if (chd_get_last_error() == CHDERR_UNSUPPORTED_VERSION)
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%-12s UNSUPPORTED CHD VERSION\n", filename);
|
||||
else
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%-12s NOT FOUND\n", filename);
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%-12s NOT FOUND\n", filename);
|
||||
romdata->errors++;
|
||||
romp++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* get the header and extract the MD5/SHA1 */
|
||||
header = *chd_get_header(source);
|
||||
hash_data_clear(acthash);
|
||||
hash_data_insert_binary_checksum(acthash, HASH_MD5, header.md5);
|
||||
hash_data_insert_binary_checksum(acthash, HASH_SHA1, header.sha1);
|
||||
|
||||
/* verify the MD5 */
|
||||
if (!hash_data_is_equal(ROM_GETHASHDATA(romp), acthash, 0))
|
||||
{
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%-12s WRONG CHECKSUMS:\n", filename);
|
||||
dump_wrong_and_correct_checksums(romdata, ROM_GETHASHDATA(romp), acthash);
|
||||
romdata->warnings++;
|
||||
}
|
||||
|
||||
/* if not read-only, make the diff file */
|
||||
/* if not read-only, open or create the differencing file */
|
||||
if (!DISK_ISREADONLY(romp))
|
||||
{
|
||||
/* make the filename of the diff */
|
||||
strcpy(filename, ROM_GETNAME(romp));
|
||||
c = strrchr(filename, '.');
|
||||
char diffname[1024];
|
||||
|
||||
strcpy(diffname, ROM_GETNAME(romp));
|
||||
c = strrchr(diffname, '.');
|
||||
if (c)
|
||||
strcpy(c, ".dif");
|
||||
else
|
||||
strcat(filename, ".dif");
|
||||
strcat(diffname, ".dif");
|
||||
|
||||
log_cb(RETRO_LOG_INFO, LOGPRE "Opening differencing image: %s\n", diffname);
|
||||
diff = mame_fopen(NULL, diffname, FILETYPE_IMAGE_DIFF, 1);
|
||||
|
||||
/* one made by older versions of the core (a CHD v3): keep its */
|
||||
/* contents to import them, and the file itself as <name>.dif.old */
|
||||
if (diff)
|
||||
{
|
||||
UINT8 tag[8];
|
||||
UINT64 size = mame_fsize(diff);
|
||||
|
||||
mame_fseek(diff, 0, SEEK_SET);
|
||||
if (size >= sizeof(tag) && size < 0x80000000 &&
|
||||
mame_fread(diff, tag, sizeof(tag)) == sizeof(tag) && memcmp(tag, "MComprHD", 8) == 0)
|
||||
{
|
||||
char oldname[1024 + 4];
|
||||
|
||||
legacydata = malloc((size_t)size);
|
||||
if (legacydata)
|
||||
{
|
||||
mame_fseek(diff, 0, SEEK_SET);
|
||||
if (mame_fread(diff, legacydata, (UINT32)size) == size)
|
||||
legacysize = (UINT32)size;
|
||||
else
|
||||
{
|
||||
free(legacydata);
|
||||
legacydata = NULL;
|
||||
}
|
||||
}
|
||||
mame_fclose(diff);
|
||||
|
||||
/* keep the file even if it could not be read, so nothing is lost */
|
||||
sprintf(oldname, "%s.old", diffname);
|
||||
if (osd_rename(FILETYPE_IMAGE_DIFF, diffname, oldname))
|
||||
log_cb(RETRO_LOG_INFO, LOGPRE "Old-format differencing image kept as %s\n", oldname);
|
||||
else
|
||||
log_cb(RETRO_LOG_WARN, LOGPRE "Old-format differencing image could not be kept as %s\n", oldname);
|
||||
diff = mame_fopen(NULL, diffname, FILETYPE_IMAGE_DIFF, 1);
|
||||
}
|
||||
mame_fseek(diff, 0, SEEK_SET);
|
||||
}
|
||||
|
||||
/* try to open the diff */
|
||||
log_cb(RETRO_LOG_INFO, LOGPRE "Opening differencing image: %s\n", filename);
|
||||
diff = chd_open(filename, 1, source);
|
||||
if (!diff)
|
||||
{
|
||||
/* didn't work; try creating it instead */
|
||||
log_cb(RETRO_LOG_INFO, LOGPRE "Creating differencing image: %s\n", filename);
|
||||
err = chd_create(filename, 0, 0, CHDCOMPRESSION_NONE, source);
|
||||
if (err != CHDERR_NONE)
|
||||
{
|
||||
if (chd_get_last_error() == CHDERR_UNSUPPORTED_VERSION)
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%-12s UNSUPPORTED CHD VERSION\n", filename);
|
||||
else
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%-12s: CAN'T CREATE DIFF FILE Error code %s\n", filename, chd_error_text[err]);
|
||||
romdata->errors++;
|
||||
romp++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* open the newly-created diff file */
|
||||
log_cb(RETRO_LOG_INFO, LOGPRE "Opening new differencing image: %s\n", filename);
|
||||
diff = chd_open(filename, 1, source);
|
||||
if (!diff)
|
||||
{
|
||||
if (chd_get_last_error() == CHDERR_UNSUPPORTED_VERSION)
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%-12s UNSUPPORTED CHD VERSION\n", filename);
|
||||
else
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%-12s: CAN'T OPEN DIFF FILE Error code %s\n", filename, chd_error_text[err]);
|
||||
romdata->errors++;
|
||||
romp++;
|
||||
continue;
|
||||
}
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%-12s: CAN'T OPEN OR CREATE DIFF FILE\n", diffname);
|
||||
free(legacydata);
|
||||
mame_fclose(source);
|
||||
romdata->errors++;
|
||||
romp++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* open the disk */
|
||||
disk = hard_disk_open(source, diff, &error);
|
||||
if (!disk)
|
||||
{
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%-12s: CAN'T OPEN DISK IMAGE (%s)\n", filename, error);
|
||||
free(legacydata);
|
||||
romdata->errors++;
|
||||
romp++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* bring over what the game wrote with older versions of the core */
|
||||
if (legacydata)
|
||||
{
|
||||
hard_disk_import_legacy_diff(disk, legacydata, legacysize);
|
||||
free(legacydata);
|
||||
}
|
||||
|
||||
/* verify the checksums: older sets list those of the data (the same for */
|
||||
/* every CHD version of a dump), current MAME the one of a v5 image */
|
||||
hard_disk_get_hashes(disk, datahash, imagehash);
|
||||
if (!hash_data_is_equal(ROM_GETHASHDATA(romp), datahash, 0) &&
|
||||
!hash_data_is_equal(ROM_GETHASHDATA(romp), imagehash, 0))
|
||||
{
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%-12s WRONG CHECKSUMS:\n", filename);
|
||||
dump_wrong_and_correct_checksums(romdata, ROM_GETHASHDATA(romp), datahash);
|
||||
romdata->warnings++;
|
||||
}
|
||||
|
||||
/* we're okay, set the handle */
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Assigning to handle %d\n", DISK_GETINDEX(romp));
|
||||
disk_handle[DISK_GETINDEX(romp)] = DISK_ISREADONLY(romp) ? source : diff;
|
||||
disk_handle[DISK_GETINDEX(romp)] = disk;
|
||||
romp++;
|
||||
}
|
||||
}
|
||||
@@ -1980,7 +2026,7 @@ int rom_load(const struct RomModule *romp)
|
||||
/* remember the base and length */
|
||||
romdata.regionlength = memory_region_length(regiontype);
|
||||
romdata.regionbase = memory_region(regiontype);
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Allocated %X bytes @ %08X\n", romdata.regionlength, (int)romdata.regionbase);
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Allocated %X bytes @ %08lX\n", romdata.regionlength, (FPTR)romdata.regionbase);
|
||||
|
||||
/* clear the region if it's requested */
|
||||
if (ROMREGION_ISERASE(region))
|
||||
|
||||
+33
-5
@@ -40,6 +40,12 @@ struct mame_bitmap
|
||||
void (*plot_box)(struct mame_bitmap *bitmap,int x,int y,int width,int height,pen_t pen);
|
||||
};
|
||||
|
||||
#define BITMAP_ADDR(bitmap, type, y, x) \
|
||||
((type *)(bitmap)->base + (y) * (bitmap)->rowpixels + (x))
|
||||
|
||||
#define BITMAP_ADDR8(bitmap, y, x) BITMAP_ADDR(bitmap, UINT8, y, x)
|
||||
#define BITMAP_ADDR16(bitmap, y, x) BITMAP_ADDR(bitmap, UINT16, y, x)
|
||||
#define BITMAP_ADDR32(bitmap, y, x) BITMAP_ADDR(bitmap, UINT32, y, x)
|
||||
|
||||
struct RomModule
|
||||
{
|
||||
@@ -97,7 +103,7 @@ struct GameSamples
|
||||
struct GameSample *sample[1]; /* extendable */
|
||||
};
|
||||
|
||||
#define GAME_SAMPLE_LARGE 10000000 // 10MB
|
||||
#define GAME_SAMPLE_LARGE 10000000 /* 10MB */
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
@@ -165,7 +171,8 @@ enum
|
||||
#define ROMENTRYTYPE_CONTINUE 4 /* this entry continues loading the previous ROM */
|
||||
#define ROMENTRYTYPE_FILL 5 /* this entry fills an area with a constant value */
|
||||
#define ROMENTRYTYPE_COPY 6 /* this entry copies data from another region/offset */
|
||||
#define ROMENTRYTYPE_COUNT 7
|
||||
#define ROMENTRYTYPE_IGNORE 7 /* this entry continues loading the previous ROM but throws the data away */
|
||||
#define ROMENTRYTYPE_COUNT 8
|
||||
|
||||
#define ROMENTRY_REGION ((const char *)ROMENTRYTYPE_REGION)
|
||||
#define ROMENTRY_END ((const char *)ROMENTRYTYPE_END)
|
||||
@@ -173,9 +180,10 @@ enum
|
||||
#define ROMENTRY_CONTINUE ((const char *)ROMENTRYTYPE_CONTINUE)
|
||||
#define ROMENTRY_FILL ((const char *)ROMENTRYTYPE_FILL)
|
||||
#define ROMENTRY_COPY ((const char *)ROMENTRYTYPE_COPY)
|
||||
#define ROMENTRY_IGNORE ((const char *)ROMENTRYTYPE_IGNORE)
|
||||
|
||||
/* ----- per-entry macros ----- */
|
||||
#define ROMENTRY_GETTYPE(r) ((FPTR)(r)->_name)
|
||||
#define ROMENTRY_GETTYPE(r) ((FPTR)(r)->_name)
|
||||
#define ROMENTRY_ISSPECIAL(r) (ROMENTRY_GETTYPE(r) < ROMENTRYTYPE_COUNT)
|
||||
#define ROMENTRY_ISFILE(r) (!ROMENTRY_ISSPECIAL(r))
|
||||
#define ROMENTRY_ISREGION(r) ((r)->_name == ROMENTRY_REGION)
|
||||
@@ -184,6 +192,7 @@ enum
|
||||
#define ROMENTRY_ISCONTINUE(r) ((r)->_name == ROMENTRY_CONTINUE)
|
||||
#define ROMENTRY_ISFILL(r) ((r)->_name == ROMENTRY_FILL)
|
||||
#define ROMENTRY_ISCOPY(r) ((r)->_name == ROMENTRY_COPY)
|
||||
#define ROMENTRY_ISIGNORE(r) ((r)->_name == ROMENTRY_IGNORE)
|
||||
#define ROMENTRY_ISREGIONEND(r) (ROMENTRY_ISREGION(r) || ROMENTRY_ISEND(r))
|
||||
|
||||
|
||||
@@ -228,7 +237,7 @@ enum
|
||||
#define ROMREGION_DATATYPEDISK 0x00010000
|
||||
|
||||
/* ----- per-region macros ----- */
|
||||
#define ROMREGION_GETTYPE(r) ((UINT32)(r)->_hashdata)
|
||||
#define ROMREGION_GETTYPE(r) ((FPTR)(r)->_hashdata)
|
||||
#define ROMREGION_GETLENGTH(r) ((r)->_length)
|
||||
#define ROMREGION_GETFLAGS(r) ((r)->_flags)
|
||||
#define ROMREGION_GETWIDTH(r) (8 << (ROMREGION_GETFLAGS(r) & ROMREGION_WIDTHMASK))
|
||||
@@ -336,6 +345,7 @@ enum
|
||||
#define ROM_RELOAD(offset,length) ROMX_LOAD(ROMENTRY_RELOAD, offset, length, 0, ROM_INHERITFLAGS)
|
||||
#define ROM_FILL(offset,length,value) ROM_LOAD(ROMENTRY_FILL, offset, length, (const char*)value)
|
||||
#define ROM_COPY(rgn,srcoffset,offset,length) ROMX_LOAD(ROMENTRY_COPY, offset, length, (const char*)srcoffset, (rgn) << 24)
|
||||
#define ROM_IGNORE(length) ROMX_LOAD(ROMENTRY_IGNORE, 0, length, 0, ROM_INHERITFLAGS)
|
||||
|
||||
/* ----- nibble loading macros ----- */
|
||||
#define ROM_LOAD_NIB_HIGH(name,offset,length,hash) ROMX_LOAD(name, offset, length, hash, ROM_NIBBLE | ROM_SHIFT_NIBBLE_HI)
|
||||
@@ -352,6 +362,12 @@ enum
|
||||
#define ROM_LOAD32_WORD_SWAP(name,offset,length,hash)ROMX_LOAD(name, offset, length, hash, ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(2))
|
||||
#define ROM_LOAD32_DWORD(name,offset,length,hash) ROMX_LOAD(name, offset, length, hash, ROM_GROUPDWORD)
|
||||
|
||||
/* ----- new-style 64-bit loading macros ----- */
|
||||
#define ROM_LOAD64_BYTE(name,offset,length,hash) ROMX_LOAD(name, offset, length, hash, ROM_SKIP(7))
|
||||
#define ROM_LOAD64_WORD(name,offset,length,hash) ROMX_LOAD(name, offset, length, hash, ROM_GROUPWORD | ROM_SKIP(6))
|
||||
#define ROM_LOAD64_WORD_SWAP(name,offset,length,hash) ROMX_LOAD(name, offset, length, hash, ROM_GROUPWORD | ROM_REVERSE | ROM_SKIP(6))
|
||||
#define ROM_LOAD64_DWORD_SWAP(name,offset,length,hash) ROMX_LOAD(name, offset, length, hash, ROM_GROUPDWORD | ROM_REVERSE | ROM_SKIP(4))
|
||||
|
||||
/* ----- disk loading macros ----- */
|
||||
#define DISK_REGION(type) ROM_REGION(1, type, ROMREGION_DATATYPEDISK)
|
||||
#define DISK_IMAGE(name,idx,hash) ROMMD5_LOAD(name, idx, 0, hash, DISK_READWRITE)
|
||||
@@ -436,12 +452,16 @@ static INLINE int get_resource_tag(void)
|
||||
|
||||
/* automatically-freeing memory */
|
||||
void *auto_malloc(size_t size);
|
||||
|
||||
/* free one auto_malloc block (or auto bitmap) before its tag ends */
|
||||
void auto_free_ptr(void *ptr);
|
||||
void auto_bitmap_free(struct mame_bitmap *bitmap);
|
||||
char *auto_strdup(const char *str);
|
||||
struct mame_bitmap *auto_bitmap_alloc(int width,int height);
|
||||
struct mame_bitmap *auto_bitmap_alloc_depth(int width,int height,int depth);
|
||||
|
||||
/* disk handling */
|
||||
struct chd_file *get_disk_handle(int diskindex);
|
||||
struct hard_disk_file *get_disk_handle(int diskindex);
|
||||
|
||||
/* ROM processing */
|
||||
int rom_load(const struct RomModule *romp);
|
||||
@@ -552,6 +572,14 @@ void printromlist(const struct RomModule *romp,const char *name);
|
||||
(BIT(val, B1) << 1) | \
|
||||
(BIT(val, B0) << 0))
|
||||
|
||||
/* Standard MIN/MAX macros */
|
||||
#ifndef MIN
|
||||
#define MIN(x,y) ((x) < (y) ? (x) : (y))
|
||||
#endif
|
||||
#ifndef MAX
|
||||
#define MAX(x,y) ((x) > (y) ? (x) : (y))
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
+54
-21
@@ -10508,11 +10508,12 @@ const char *mk_get_ctrl_name(int type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case IPT_BUTTON1: return BTN1 "High Punch";
|
||||
case IPT_BUTTON2: return BTN2 "Block";
|
||||
case IPT_BUTTON3: return BTN3 "High Kick";
|
||||
case IPT_BUTTON4: return BTN4 "Low Punch";
|
||||
case IPT_BUTTON5: return BTN5 "Low Kick";
|
||||
case IPT_BUTTON1: return BTN1 "Low Punch";
|
||||
case IPT_BUTTON2: return BTN2 "Low Kick";
|
||||
case IPT_BUTTON3: return BTN3 "High Punch";
|
||||
case IPT_BUTTON4: return BTN4 "High Kick";
|
||||
case IPT_BUTTON5: return BTN5 "Block";
|
||||
case IPT_BUTTON6: return BTN6 "Block 2";
|
||||
case IPT_JOYSTICK_UP: return "Jump";
|
||||
case IPT_JOYSTICK_DOWN: return "Duck";
|
||||
case IPT_JOYSTICK_LEFT: return "Move Left";
|
||||
@@ -10535,11 +10536,11 @@ const char *mk3_get_ctrl_name(int type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case IPT_BUTTON1: return BTN1 "High Punch";
|
||||
case IPT_BUTTON2: return BTN2 "Block";
|
||||
case IPT_BUTTON3: return BTN3 "High Kick";
|
||||
case IPT_BUTTON4: return BTN4 "Low Punch";
|
||||
case IPT_BUTTON5: return BTN5 "Low Kick";
|
||||
case IPT_BUTTON1: return BTN1 "Low Punch";
|
||||
case IPT_BUTTON2: return BTN2 "Low Kick";
|
||||
case IPT_BUTTON3: return BTN3 "High Punch";
|
||||
case IPT_BUTTON4: return BTN4 "High Kick";
|
||||
case IPT_BUTTON5: return BTN5 "Block";
|
||||
case IPT_BUTTON6: return BTN6 "Run";
|
||||
case IPT_JOYSTICK_UP: return "Jump";
|
||||
case IPT_JOYSTICK_DOWN: return "Duck";
|
||||
@@ -10563,11 +10564,11 @@ const char *mk4_get_ctrl_name(int type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case IPT_BUTTON1: return BTN1 "High Punch";
|
||||
case IPT_BUTTON2: return BTN2 "Block";
|
||||
case IPT_BUTTON3: return BTN3 "High Kick";
|
||||
case IPT_BUTTON4: return BTN4 "Low Punch";
|
||||
case IPT_BUTTON5: return BTN5 "Low Kick";
|
||||
case IPT_BUTTON1: return BTN1 "Low Punch";
|
||||
case IPT_BUTTON2: return BTN2 "Low Kick";
|
||||
case IPT_BUTTON3: return BTN3 "High Punch";
|
||||
case IPT_BUTTON4: return BTN4 "High Kick";
|
||||
case IPT_BUTTON5: return BTN5 "Block";
|
||||
case IPT_BUTTON6: return BTN6 "Run";
|
||||
case IPT_JOYSTICK_UP: return "Jump";
|
||||
case IPT_JOYSTICK_DOWN: return "Duck";
|
||||
@@ -10591,11 +10592,12 @@ const char *mk2_get_ctrl_name(int type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case IPT_BUTTON1: return BTN1 "High Punch";
|
||||
case IPT_BUTTON2: return BTN2 "Block";
|
||||
case IPT_BUTTON3: return BTN3 "High Kick";
|
||||
case IPT_BUTTON4: return BTN4 "Low Punch";
|
||||
case IPT_BUTTON5: return BTN5 "Low Kick";
|
||||
case IPT_BUTTON1: return BTN1 "Low Punch";
|
||||
case IPT_BUTTON2: return BTN2 "Low Kick";
|
||||
case IPT_BUTTON3: return BTN3 "High Punch";
|
||||
case IPT_BUTTON4: return BTN4 "High Kick";
|
||||
case IPT_BUTTON5: return BTN5 "Block";
|
||||
case IPT_BUTTON6: return BTN6 "Block 2";
|
||||
case IPT_JOYSTICK_UP: return "Jump";
|
||||
case IPT_JOYSTICK_DOWN: return "Duck";
|
||||
case IPT_JOYSTICK_LEFT: return "Move Left";
|
||||
@@ -11781,7 +11783,7 @@ const struct ControlInfo polepos2_ctrl =
|
||||
false, /* 45_degree_rotation for joystick(s) */
|
||||
false, /* alternating_controls */
|
||||
false, /* mirrored_controls */
|
||||
"Button1 is actually spacbar by default in this game to avoid conflicts with the pedals. The high / low shifter is emulated in mame by a single button toggle. The upright cab only uses the gas pedal while the cockpit uses both. This is a dipswitch setting that you can alter if you wish to better suit your layout.", /* control_details */
|
||||
"Button 1 is actually the spacebar by default to avoid conflicts with the pedals. The high / low shifter is emulated in mame by a single button toggle. The upright cab only uses the gas pedal while the cockpit uses both. This is a dipswitch setting that you can alter if you wish to better suit your layout.", /* control_details */
|
||||
&polepos2_get_ctrl_name
|
||||
};
|
||||
|
||||
@@ -14697,6 +14699,37 @@ const char *sf_get_ctrl_name(int type)
|
||||
return "";
|
||||
}
|
||||
|
||||
const struct ControlInfo sfrush_ctrl =
|
||||
{
|
||||
false, /* 45_degree_rotation for joystick(s) */
|
||||
false, /* alternating_controls */
|
||||
false, /* mirrored_controls */
|
||||
"Wheel, accelerator and brake on player 1 (the shifter stays in the last gear chosen). Clutch, music and the four track buttons are on player 2.", /* control_details */
|
||||
&sfrush_get_ctrl_name
|
||||
};
|
||||
|
||||
const char *sfrush_get_ctrl_name(int type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case IPT_BUTTON1: return BTN1 "1st Gear / Music";
|
||||
case IPT_BUTTON2: return BTN2 "2nd Gear / Track 1";
|
||||
case IPT_BUTTON3: return BTN3 "3rd Gear / Track 2";
|
||||
case IPT_BUTTON4: return BTN4 "4th Gear / Track 3";
|
||||
case IPT_BUTTON5: return BTN5 "Track 4";
|
||||
case IPT_BUTTON7: return BTN7 "View 1";
|
||||
case IPT_BUTTON8: return BTN8 "View 2";
|
||||
case IPT_BUTTON9: return "B9: View 3";
|
||||
case IPT_BUTTON10: return "B10: Reverse";
|
||||
case IPT_PEDAL: return "Accelerator / Clutch";
|
||||
case IPT_PEDAL2: return "Brake";
|
||||
case IPT_PADDLE: return "Steer Left";
|
||||
case (IPT_PADDLE + IPT_EXTENSION): return "Steer Right";
|
||||
} /* end of switch */
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
const struct ControlInfo sfa2_ctrl =
|
||||
{
|
||||
false, /* 45_degree_rotation for joystick(s) */
|
||||
|
||||
+4
-1
@@ -2440,6 +2440,9 @@ const char *stratgyx_get_ctrl_name(int type);
|
||||
extern const struct ControlInfo sf_ctrl;
|
||||
const char *sf_get_ctrl_name(int type);
|
||||
|
||||
extern const struct ControlInfo sfrush_ctrl;
|
||||
const char *sfrush_get_ctrl_name(int type);
|
||||
|
||||
extern const struct ControlInfo sfa2_ctrl;
|
||||
const char *sfa2_get_ctrl_name(int type);
|
||||
|
||||
@@ -3226,4 +3229,4 @@ const char *zwackery_get_ctrl_name(int type);
|
||||
extern const struct ControlInfo zzyzzyxx_ctrl;
|
||||
const char *zzyzzyxx_get_ctrl_name(int type);
|
||||
|
||||
#endif /* CONTROLS_H */
|
||||
#endif /* CONTROLS_H */
|
||||
+789
-45
@@ -368,6 +368,27 @@ static void wr_px(INT32 val) { adsp2100.px = val; }
|
||||
static void wr_ifc(INT32 val)
|
||||
{
|
||||
adsp2100.ifc = val;
|
||||
#if (HAS_ADSP2181)
|
||||
if (chip_type == CHIP_TYPE_ADSP2181)
|
||||
{
|
||||
if (val & 0x0002) adsp2100.irq_latch[ADSP2181_IRQ0] = 0;
|
||||
if (val & 0x0004) adsp2100.irq_latch[ADSP2181_IRQ1] = 0;
|
||||
if (val & 0x0008) adsp2100.irq_latch[ADSP2181_BDMA] = 0;
|
||||
if (val & 0x0010) adsp2100.irq_latch[ADSP2181_IRQE] = 0;
|
||||
if (val & 0x0020) adsp2100.irq_latch[ADSP2181_SPORT0_RX] = 0;
|
||||
if (val & 0x0040) adsp2100.irq_latch[ADSP2181_SPORT0_TX] = 0;
|
||||
if (val & 0x0080) adsp2100.irq_latch[ADSP2181_IRQ2] = 0;
|
||||
if (val & 0x0200) adsp2100.irq_latch[ADSP2181_IRQ0] = 1;
|
||||
if (val & 0x0400) adsp2100.irq_latch[ADSP2181_IRQ1] = 1;
|
||||
if (val & 0x0800) adsp2100.irq_latch[ADSP2181_BDMA] = 1;
|
||||
if (val & 0x1000) adsp2100.irq_latch[ADSP2181_IRQE] = 1;
|
||||
if (val & 0x2000) adsp2100.irq_latch[ADSP2181_SPORT0_RX] = 1;
|
||||
if (val & 0x4000) adsp2100.irq_latch[ADSP2181_SPORT0_TX] = 1;
|
||||
if (val & 0x8000) adsp2100.irq_latch[ADSP2181_IRQ2] = 1;
|
||||
check_irqs();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (val & 0x002) adsp2100.irq_latch[ADSP2101_IRQ0] = 0;
|
||||
if (val & 0x004) adsp2100.irq_latch[ADSP2101_IRQ1] = 0;
|
||||
if (val & 0x008) adsp2100.irq_latch[ADSP2101_SPORT0_RX] = 0;
|
||||
@@ -384,6 +405,25 @@ static void wr_tx0(INT32 val) { if (sport_tx_callback) (*sport_tx_callback)(0, v
|
||||
static void wr_tx1(INT32 val) { if (sport_tx_callback) (*sport_tx_callback)(1, val); }
|
||||
static void wr_owrctr(INT32 val) { adsp2100.cntr = val & 0x3fff; }
|
||||
static void wr_topstack(INT32 val) { pc_stack_push_val(val & 0x3fff); }
|
||||
/* ADSP-2181: the memory overlay registers (group 1, 14 and 15) */
|
||||
static void wr_pmovlay(INT32 val)
|
||||
{
|
||||
#if (HAS_ADSP2181)
|
||||
if (chip_type == CHIP_TYPE_ADSP2181)
|
||||
adsp2100.pmovlay = val & 0x3fff;
|
||||
#endif
|
||||
}
|
||||
static void wr_dmovlay(INT32 val)
|
||||
{
|
||||
#if (HAS_ADSP2181)
|
||||
if (chip_type == CHIP_TYPE_ADSP2181)
|
||||
{
|
||||
adsp2100.dmovlay = val & 0x3fff;
|
||||
if (dmovlay_callback)
|
||||
(*dmovlay_callback)(adsp2100.dmovlay);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#define WRITE_REG(grp,reg,val) ((*wr_reg[grp][reg])(val))
|
||||
|
||||
@@ -395,7 +435,7 @@ static void (*wr_reg[4][16])(INT32) =
|
||||
},
|
||||
{
|
||||
wr_i0, wr_i1, wr_i2, wr_i3, wr_m0, wr_m1, wr_m2, wr_m3,
|
||||
wr_l0, wr_l1, wr_l2, wr_l3, wr_inval, wr_inval, wr_inval, wr_inval
|
||||
wr_l0, wr_l1, wr_l2, wr_l3, wr_inval, wr_inval, wr_pmovlay, wr_dmovlay
|
||||
},
|
||||
{
|
||||
wr_i4, wr_i5, wr_i6, wr_i7, wr_m4, wr_m5, wr_m6, wr_m7,
|
||||
@@ -469,6 +509,13 @@ static INT32 rd_px(void) { return adsp2100.px; }
|
||||
static INT32 rd_rx0(void) { if (sport_rx_callback) return (*sport_rx_callback)(0); else return 0; }
|
||||
static INT32 rd_rx1(void) { if (sport_rx_callback) return (*sport_rx_callback)(1); else return 0; }
|
||||
static INT32 rd_stacktop(void) { return pc_stack_pop_val(); }
|
||||
#if (HAS_ADSP2181)
|
||||
static INT32 rd_pmovlay(void) { return (chip_type == CHIP_TYPE_ADSP2181) ? adsp2100.pmovlay : 0; }
|
||||
static INT32 rd_dmovlay(void) { return (chip_type == CHIP_TYPE_ADSP2181) ? adsp2100.dmovlay : 0; }
|
||||
#else
|
||||
#define rd_pmovlay rd_inval
|
||||
#define rd_dmovlay rd_inval
|
||||
#endif
|
||||
|
||||
#define READ_REG(grp,reg) ((*rd_reg[grp][reg])())
|
||||
|
||||
@@ -480,7 +527,7 @@ static INT32 (*rd_reg[4][16])(void) =
|
||||
},
|
||||
{
|
||||
rd_i0, rd_i1, rd_i2, rd_i3, rd_m0, rd_m1, rd_m2, rd_m3,
|
||||
rd_l0, rd_l1, rd_l2, rd_l3, rd_inval, rd_inval, rd_inval, rd_inval
|
||||
rd_l0, rd_l1, rd_l2, rd_l3, rd_inval, rd_inval, rd_pmovlay, rd_dmovlay
|
||||
},
|
||||
{
|
||||
rd_i4, rd_i5, rd_i6, rd_i7, rd_m4, rd_m5, rd_m6, rd_m7,
|
||||
@@ -498,16 +545,23 @@ static INT32 (*rd_reg[4][16])(void) =
|
||||
Modulus addressing logic
|
||||
===========================================================================*/
|
||||
|
||||
static INLINE void modify_address(UINT32 ireg, UINT32 mreg)
|
||||
/* index register 'i' plus 'm', kept in its circular buffer; 'wrap14' (a
|
||||
constant, set only in the ADSP-2181 interpreter loop) first keeps the
|
||||
sum to 14 bits, as in current MAME: an index that steps below 0 wraps
|
||||
to the top of memory instead of going out of the address space */
|
||||
static INLINE ADSP_ALWAYS_INLINE UINT32 dag_step(UINT32 i, INT32 m, UINT32 base, UINT32 l, int wrap14)
|
||||
{
|
||||
UINT32 base = adsp2100.base[ireg];
|
||||
UINT32 i = adsp2100.i[ireg];
|
||||
UINT32 l = adsp2100.l[ireg];
|
||||
|
||||
i += adsp2100.m[mreg];
|
||||
i += m;
|
||||
if (wrap14)
|
||||
i &= 0x3fff;
|
||||
if (i < base) i += l;
|
||||
else if (i >= base + l) i -= l;
|
||||
adsp2100.i[ireg] = i;
|
||||
return i;
|
||||
}
|
||||
|
||||
static INLINE ADSP_ALWAYS_INLINE void modify_address(UINT32 ireg, UINT32 mreg, int wrap14)
|
||||
{
|
||||
adsp2100.i[ireg] = dag_step(adsp2100.i[ireg], adsp2100.m[mreg], adsp2100.base[ireg], adsp2100.l[ireg], wrap14);
|
||||
}
|
||||
|
||||
|
||||
@@ -516,7 +570,7 @@ static INLINE void modify_address(UINT32 ireg, UINT32 mreg)
|
||||
Data memory accessors
|
||||
===========================================================================*/
|
||||
|
||||
static INLINE void data_write_dag1(UINT32 op, INT32 val)
|
||||
static INLINE ADSP_ALWAYS_INLINE void data_write_dag1_f(UINT32 op, INT32 val, int fast)
|
||||
{
|
||||
UINT32 ireg = (op >> 2) & 3;
|
||||
UINT32 mreg = op & 3;
|
||||
@@ -527,19 +581,16 @@ static INLINE void data_write_dag1(UINT32 op, INT32 val)
|
||||
if ( adsp2100.mstat & MSTAT_REVERSE )
|
||||
{
|
||||
UINT32 ir = reverse_table[ i & 0x3fff ];
|
||||
WWORD_DATA(ir, val);
|
||||
WWORD_DATA_F(ir, val, fast);
|
||||
}
|
||||
else
|
||||
WWORD_DATA(i, val);
|
||||
WWORD_DATA_F(i, val, fast);
|
||||
|
||||
i += adsp2100.m[mreg];
|
||||
if (i < base) i += l;
|
||||
else if (i >= base + l) i -= l;
|
||||
adsp2100.i[ireg] = i;
|
||||
adsp2100.i[ireg] = dag_step(i, adsp2100.m[mreg], base, l, fast & 2);
|
||||
}
|
||||
|
||||
|
||||
static INLINE UINT32 data_read_dag1(UINT32 op)
|
||||
static INLINE ADSP_ALWAYS_INLINE UINT32 data_read_dag1_f(UINT32 op, int fast)
|
||||
{
|
||||
UINT32 ireg = (op >> 2) & 3;
|
||||
UINT32 mreg = op & 3;
|
||||
@@ -551,20 +602,17 @@ static INLINE UINT32 data_read_dag1(UINT32 op)
|
||||
if (adsp2100.mstat & MSTAT_REVERSE)
|
||||
{
|
||||
UINT32 ir = reverse_table[i & 0x3fff];
|
||||
res = RWORD_DATA(ir);
|
||||
res = RWORD_DATA_F(ir, fast);
|
||||
}
|
||||
else
|
||||
res = RWORD_DATA(i);
|
||||
res = RWORD_DATA_F(i, fast);
|
||||
|
||||
i += adsp2100.m[mreg];
|
||||
if (i < base) i += l;
|
||||
else if (i >= base + l) i -= l;
|
||||
adsp2100.i[ireg] = i;
|
||||
adsp2100.i[ireg] = dag_step(i, adsp2100.m[mreg], base, l, fast & 2);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static INLINE void data_write_dag2(UINT32 op, INT32 val)
|
||||
static INLINE ADSP_ALWAYS_INLINE void data_write_dag2_f(UINT32 op, INT32 val, int fast)
|
||||
{
|
||||
UINT32 ireg = 4 + ((op >> 2) & 3);
|
||||
UINT32 mreg = 4 + (op & 3);
|
||||
@@ -572,16 +620,13 @@ static INLINE void data_write_dag2(UINT32 op, INT32 val)
|
||||
UINT32 i = adsp2100.i[ireg];
|
||||
UINT32 l = adsp2100.l[ireg];
|
||||
|
||||
WWORD_DATA(i, val);
|
||||
WWORD_DATA_F(i, val, fast);
|
||||
|
||||
i += adsp2100.m[mreg];
|
||||
if (i < base) i += l;
|
||||
else if (i >= base + l) i -= l;
|
||||
adsp2100.i[ireg] = i;
|
||||
adsp2100.i[ireg] = dag_step(i, adsp2100.m[mreg], base, l, fast & 2);
|
||||
}
|
||||
|
||||
|
||||
static INLINE UINT32 data_read_dag2(UINT32 op)
|
||||
static INLINE ADSP_ALWAYS_INLINE UINT32 data_read_dag2_f(UINT32 op, int fast)
|
||||
{
|
||||
UINT32 ireg = 4 + ((op >> 2) & 3);
|
||||
UINT32 mreg = 4 + (op & 3);
|
||||
@@ -589,21 +634,25 @@ static INLINE UINT32 data_read_dag2(UINT32 op)
|
||||
UINT32 i = adsp2100.i[ireg];
|
||||
UINT32 l = adsp2100.l[ireg];
|
||||
|
||||
UINT32 res = RWORD_DATA(i);
|
||||
UINT32 res = RWORD_DATA_F(i, fast);
|
||||
|
||||
i += adsp2100.m[mreg];
|
||||
if (i < base) i += l;
|
||||
else if (i >= base + l) i -= l;
|
||||
adsp2100.i[ireg] = i;
|
||||
adsp2100.i[ireg] = dag_step(i, adsp2100.m[mreg], base, l, fast & 2);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* the interpreter's accessors; 'fast': bit 0 for the recompiler (direct
|
||||
pointers), bit 1 for the ADSP-2181 (14-bit index wrap) */
|
||||
#define data_write_dag1(op, val) data_write_dag1_f(op, val, 0)
|
||||
#define data_read_dag1(op) data_read_dag1_f(op, 0)
|
||||
#define data_write_dag2(op, val) data_write_dag2_f(op, val, 0)
|
||||
#define data_read_dag2(op) data_read_dag2_f(op, 0)
|
||||
|
||||
/*===========================================================================
|
||||
Program memory accessors
|
||||
===========================================================================*/
|
||||
|
||||
static INLINE void pgm_write_dag2(UINT32 op, INT32 val)
|
||||
static INLINE ADSP_ALWAYS_INLINE void pgm_write_dag2(UINT32 op, INT32 val, int wrap14)
|
||||
{
|
||||
UINT32 ireg = 4 + ((op >> 2) & 3);
|
||||
UINT32 mreg = 4 + (op & 3);
|
||||
@@ -613,14 +662,11 @@ static INLINE void pgm_write_dag2(UINT32 op, INT32 val)
|
||||
|
||||
WWORD_PGM(i, (val << 8) | adsp2100.px);
|
||||
|
||||
i += adsp2100.m[mreg];
|
||||
if (i < base) i += l;
|
||||
else if (i >= base + l) i -= l;
|
||||
adsp2100.i[ireg] = i;
|
||||
adsp2100.i[ireg] = dag_step(i, adsp2100.m[mreg], base, l, wrap14);
|
||||
}
|
||||
|
||||
|
||||
static INLINE UINT32 pgm_read_dag2(UINT32 op)
|
||||
static INLINE ADSP_ALWAYS_INLINE UINT32 pgm_read_dag2(UINT32 op, int wrap14)
|
||||
{
|
||||
UINT32 ireg = 4 + ((op >> 2) & 3);
|
||||
UINT32 mreg = 4 + (op & 3);
|
||||
@@ -633,10 +679,7 @@ static INLINE UINT32 pgm_read_dag2(UINT32 op)
|
||||
adsp2100.px = res;
|
||||
res >>= 8;
|
||||
|
||||
i += adsp2100.m[mreg];
|
||||
if (i < base) i += l;
|
||||
else if (i >= base + l) i -= l;
|
||||
adsp2100.i[ireg] = i;
|
||||
adsp2100.i[ireg] = dag_step(i, adsp2100.m[mreg], base, l, wrap14);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -1326,6 +1369,707 @@ void mac_op_mf(int op)
|
||||
|
||||
|
||||
|
||||
#if (HAS_ADSP2181)
|
||||
|
||||
/*===========================================================================
|
||||
ADSP-2181 only: ALU with a constant as Y, ALU with no result (NONE =),
|
||||
MAC with X as both operands (X * X); the operations above, with
|
||||
the other operand
|
||||
===========================================================================*/
|
||||
|
||||
static const INT32 alu_constants[32] =
|
||||
{
|
||||
0x0001, 0xfffe, 0x0002, 0xfffd, 0x0004, 0xfffb, 0x0008, 0xfff7,
|
||||
0x0010, 0xffef, 0x0020, 0xffdf, 0x0040, 0xffbf, 0x0080, 0xff7f,
|
||||
0x0100, 0xfeff, 0x0200, 0xfdff, 0x0400, 0xfbff, 0x0800, 0xf7ff,
|
||||
0x1000, 0xefff, 0x2000, 0xdfff, 0x4000, 0xbfff, 0x8000, 0x7fff
|
||||
};
|
||||
|
||||
static void alu_op_ar_const(int op)
|
||||
{
|
||||
INT32 xop = (op >> 8) & 7;
|
||||
INT32 yop = alu_constants[((op >> 5) & 7) | (((op >> 11) & 3) << 3)];
|
||||
INT32 res;
|
||||
|
||||
/*switch ((op >> 13) & 15)*/
|
||||
switch (op & (15<<13)) /*JB*/
|
||||
{
|
||||
case 0x00<<13:
|
||||
/* Y Clear when y = 0 */
|
||||
res = yop;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x01<<13:
|
||||
/* Y + 1 PASS 1 when y = 0 */
|
||||
res = yop + 1;
|
||||
CALC_NZ(res);
|
||||
if (yop == 0x7fff) SET_V;
|
||||
else if (yop == 0xffff) SET_C;
|
||||
break;
|
||||
case 0x02<<13:
|
||||
/* X + Y + C */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
yop += GET_C >> 3;
|
||||
res = xop + yop;
|
||||
CALC_NZVC(xop, yop, res);
|
||||
break;
|
||||
case 0x03<<13:
|
||||
/* X + Y X when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop + yop;
|
||||
CALC_NZVC(xop, yop, res);
|
||||
break;
|
||||
case 0x04<<13:
|
||||
/* NOT Y */
|
||||
res = yop ^ 0xffff;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x05<<13:
|
||||
/* -Y */
|
||||
res = -yop;
|
||||
CALC_NZ(res);
|
||||
if (yop == 0x8000) SET_V;
|
||||
if (yop == 0x0000) SET_C;
|
||||
break;
|
||||
case 0x06<<13:
|
||||
/* X - Y + C - 1 X + C - 1 when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop - yop + (GET_C >> 3) - 1;
|
||||
CALC_NZVC_SUB(xop, yop, res);
|
||||
break;
|
||||
case 0x07<<13:
|
||||
/* X - Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop - yop;
|
||||
CALC_NZVC_SUB(xop, yop, res);
|
||||
break;
|
||||
case 0x08<<13:
|
||||
/* Y - 1 PASS -1 when y = 0 */
|
||||
res = yop - 1;
|
||||
CALC_NZ(res);
|
||||
if (yop == 0x8000) SET_V;
|
||||
else if (yop == 0x0000) SET_C;
|
||||
break;
|
||||
case 0x09<<13:
|
||||
/* Y - X -X when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = yop - xop;
|
||||
CALC_NZVC_SUB(yop, xop, res);
|
||||
break;
|
||||
case 0x0a<<13:
|
||||
/* Y - X + C - 1 -X + C - 1 when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = yop - xop + (GET_C >> 3) - 1;
|
||||
CALC_NZVC_SUB(yop, xop, res);
|
||||
break;
|
||||
case 0x0b<<13:
|
||||
/* NOT X */
|
||||
res = ALU_GETXREG_UNSIGNED(xop) ^ 0xffff;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0c<<13:
|
||||
/* X AND Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop & yop;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0d<<13:
|
||||
/* X OR Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop | yop;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0e<<13:
|
||||
/* X XOR Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop ^ yop;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0f<<13:
|
||||
/* ABS X */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = (xop & 0x8000) ? -xop : xop;
|
||||
if (xop == 0) SET_Z;
|
||||
if (xop == 0x8000) SET_N, SET_V;
|
||||
CLR_S;
|
||||
if (xop & 0x8000) SET_S;
|
||||
break;
|
||||
default:
|
||||
res = 0; /* just to keep the compiler happy */
|
||||
break;
|
||||
}
|
||||
|
||||
/* saturate */
|
||||
if ((adsp2100.mstat & MSTAT_SATURATE) && GET_V) res = GET_C ? -32768 : 32767;
|
||||
|
||||
/* set the final value */
|
||||
adsp2100.core.ar.u = res;
|
||||
}
|
||||
|
||||
static void alu_op_af_const(int op)
|
||||
{
|
||||
INT32 xop = (op >> 8) & 7;
|
||||
INT32 yop = alu_constants[((op >> 5) & 7) | (((op >> 11) & 3) << 3)];
|
||||
INT32 res;
|
||||
|
||||
/* switch ((op >> 13) & 15)*/
|
||||
switch (op & (15<<13)) /*JB*/
|
||||
{
|
||||
case 0x00<<13:
|
||||
/* Y Clear when y = 0 */
|
||||
res = yop;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x01<<13:
|
||||
/* Y + 1 PASS 1 when y = 0 */
|
||||
res = yop + 1;
|
||||
CALC_NZ(res);
|
||||
if (yop == 0x7fff) SET_V;
|
||||
else if (yop == 0xffff) SET_C;
|
||||
break;
|
||||
case 0x02<<13:
|
||||
/* X + Y + C */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
yop += GET_C >> 3;
|
||||
res = xop + yop;
|
||||
CALC_NZVC(xop, yop, res);
|
||||
break;
|
||||
case 0x03<<13:
|
||||
/* X + Y X when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop + yop;
|
||||
CALC_NZVC(xop, yop, res);
|
||||
break;
|
||||
case 0x04<<13:
|
||||
/* NOT Y */
|
||||
res = yop ^ 0xffff;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x05<<13:
|
||||
/* -Y */
|
||||
res = -yop;
|
||||
CALC_NZ(res);
|
||||
if (yop == 0x8000) SET_V;
|
||||
if (yop == 0x0000) SET_C;
|
||||
break;
|
||||
case 0x06<<13:
|
||||
/* X - Y + C - 1 X + C - 1 when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop - yop + (GET_C >> 3) - 1;
|
||||
CALC_NZVC_SUB(xop, yop, res);
|
||||
break;
|
||||
case 0x07<<13:
|
||||
/* X - Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop - yop;
|
||||
CALC_NZVC_SUB(xop, yop, res);
|
||||
break;
|
||||
case 0x08<<13:
|
||||
/* Y - 1 PASS -1 when y = 0 */
|
||||
res = yop - 1;
|
||||
CALC_NZ(res);
|
||||
if (yop == 0x8000) SET_V;
|
||||
else if (yop == 0x0000) SET_C;
|
||||
break;
|
||||
case 0x09<<13:
|
||||
/* Y - X -X when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = yop - xop;
|
||||
CALC_NZVC_SUB(yop, xop, res);
|
||||
break;
|
||||
case 0x0a<<13:
|
||||
/* Y - X + C - 1 -X + C - 1 when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = yop - xop + (GET_C >> 3) - 1;
|
||||
CALC_NZVC_SUB(yop, xop, res);
|
||||
break;
|
||||
case 0x0b<<13:
|
||||
/* NOT X */
|
||||
res = ALU_GETXREG_UNSIGNED(xop) ^ 0xffff;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0c<<13:
|
||||
/* X AND Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop & yop;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0d<<13:
|
||||
/* X OR Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop | yop;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0e<<13:
|
||||
/* X XOR Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop ^ yop;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0f<<13:
|
||||
/* ABS X */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = (xop & 0x8000) ? -xop : xop;
|
||||
if (xop == 0) SET_Z;
|
||||
if (xop == 0x8000) SET_N, SET_V;
|
||||
CLR_S;
|
||||
if (xop & 0x8000) SET_S;
|
||||
break;
|
||||
default:
|
||||
res = 0; /* just to keep the compiler happy */
|
||||
break;
|
||||
}
|
||||
|
||||
/* set the final value */
|
||||
adsp2100.core.af.u = res;
|
||||
}
|
||||
|
||||
static void alu_op_none(int op)
|
||||
{
|
||||
INT32 xop = (op >> 8) & 7;
|
||||
INT32 yop = (op >> 11) & 3;
|
||||
INT32 res;
|
||||
|
||||
/*switch ((op >> 13) & 15)*/
|
||||
switch (op & (15<<13)) /*JB*/
|
||||
{
|
||||
case 0x00<<13:
|
||||
/* Y Clear when y = 0 */
|
||||
res = ALU_GETYREG_UNSIGNED(yop);
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x01<<13:
|
||||
/* Y + 1 PASS 1 when y = 0 */
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
res = yop + 1;
|
||||
CALC_NZ(res);
|
||||
if (yop == 0x7fff) SET_V;
|
||||
else if (yop == 0xffff) SET_C;
|
||||
break;
|
||||
case 0x02<<13:
|
||||
/* X + Y + C */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
yop += GET_C >> 3;
|
||||
res = xop + yop;
|
||||
CALC_NZVC(xop, yop, res);
|
||||
break;
|
||||
case 0x03<<13:
|
||||
/* X + Y X when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
res = xop + yop;
|
||||
CALC_NZVC(xop, yop, res);
|
||||
break;
|
||||
case 0x04<<13:
|
||||
/* NOT Y */
|
||||
res = ALU_GETYREG_UNSIGNED(yop) ^ 0xffff;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x05<<13:
|
||||
/* -Y */
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
res = -yop;
|
||||
CALC_NZ(res);
|
||||
if (yop == 0x8000) SET_V;
|
||||
if (yop == 0x0000) SET_C;
|
||||
break;
|
||||
case 0x06<<13:
|
||||
/* X - Y + C - 1 X + C - 1 when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
res = xop - yop + (GET_C >> 3) - 1;
|
||||
CALC_NZVC_SUB(xop, yop, res);
|
||||
break;
|
||||
case 0x07<<13:
|
||||
/* X - Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
res = xop - yop;
|
||||
CALC_NZVC_SUB(xop, yop, res);
|
||||
break;
|
||||
case 0x08<<13:
|
||||
/* Y - 1 PASS -1 when y = 0 */
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
res = yop - 1;
|
||||
CALC_NZ(res);
|
||||
if (yop == 0x8000) SET_V;
|
||||
else if (yop == 0x0000) SET_C;
|
||||
break;
|
||||
case 0x09<<13:
|
||||
/* Y - X -X when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
res = yop - xop;
|
||||
CALC_NZVC_SUB(yop, xop, res);
|
||||
break;
|
||||
case 0x0a<<13:
|
||||
/* Y - X + C - 1 -X + C - 1 when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
res = yop - xop + (GET_C >> 3) - 1;
|
||||
CALC_NZVC_SUB(yop, xop, res);
|
||||
break;
|
||||
case 0x0b<<13:
|
||||
/* NOT X */
|
||||
res = ALU_GETXREG_UNSIGNED(xop) ^ 0xffff;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0c<<13:
|
||||
/* X AND Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
res = xop & yop;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0d<<13:
|
||||
/* X OR Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
res = xop | yop;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0e<<13:
|
||||
/* X XOR Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
res = xop ^ yop;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0f<<13:
|
||||
/* ABS X */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = (xop & 0x8000) ? -xop : xop;
|
||||
if (xop == 0) SET_Z;
|
||||
if (xop == 0x8000) SET_N, SET_V;
|
||||
CLR_S;
|
||||
if (xop & 0x8000) SET_S;
|
||||
break;
|
||||
default:
|
||||
res = 0; /* just to keep the compiler happy */
|
||||
break;
|
||||
}
|
||||
|
||||
/* no result: only the flags */
|
||||
(void)res;
|
||||
}
|
||||
|
||||
static void mac_op_mr_xop(int op)
|
||||
{
|
||||
INT8 shift = ((adsp2100.mstat & MSTAT_INTEGER) >> 4) ^ 1;
|
||||
INT32 xop = (op >> 8) & 7;
|
||||
INT32 yop;
|
||||
INT32 temp;
|
||||
INT64 res;
|
||||
|
||||
/* switch ((op >> 13) & 15)*/
|
||||
switch (op & (15<<13)) /*JB*/
|
||||
{
|
||||
case 0x00<<13:
|
||||
/* no-op */
|
||||
return;
|
||||
case 0x01<<13:
|
||||
/* X * Y (RND) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = (INT64)temp;
|
||||
#ifdef ADSP_TWEAK
|
||||
if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
|
||||
else res += (res & 0x8000) << 1;
|
||||
#else
|
||||
temp &= 0xffff;
|
||||
res += 0x8000;
|
||||
if ( temp == 0x8000 )
|
||||
res &= ~((UINT64)0x10000);
|
||||
#endif
|
||||
break;
|
||||
case 0x02<<13:
|
||||
/* MR + X * Y (RND) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr + (INT64)temp;
|
||||
#ifdef ADSP_TWEAK
|
||||
if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
|
||||
else res += (res & 0x8000) << 1;
|
||||
#else
|
||||
temp &= 0xffff;
|
||||
res += 0x8000;
|
||||
if ( temp == 0x8000 )
|
||||
res &= ~((UINT64)0x10000);
|
||||
#endif
|
||||
break;
|
||||
case 0x03<<13:
|
||||
/* MR - X * Y (RND) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr - (INT64)temp;
|
||||
#ifdef ADSP_TWEAK
|
||||
if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
|
||||
else res += (res & 0x8000) << 1;
|
||||
#else
|
||||
temp &= 0xffff;
|
||||
res += 0x8000;
|
||||
if ( temp == 0x8000 )
|
||||
res &= ~((UINT64)0x10000);
|
||||
#endif
|
||||
break;
|
||||
case 0x04<<13:
|
||||
/* X * Y (SS) Clear when y = 0 */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = (INT64)temp;
|
||||
break;
|
||||
case 0x05<<13:
|
||||
/* X * Y (SU) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = (INT64)temp;
|
||||
break;
|
||||
case 0x06<<13:
|
||||
/* X * Y (US) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = (INT64)temp;
|
||||
break;
|
||||
case 0x07<<13:
|
||||
/* X * Y (UU) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = (INT64)temp;
|
||||
break;
|
||||
case 0x08<<13:
|
||||
/* MR + X * Y (SS) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr + (INT64)temp;
|
||||
break;
|
||||
case 0x09<<13:
|
||||
/* MR + X * Y (SU) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr + (INT64)temp;
|
||||
break;
|
||||
case 0x0a<<13:
|
||||
/* MR + X * Y (US) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr + (INT64)temp;
|
||||
break;
|
||||
case 0x0b<<13:
|
||||
/* MR + X * Y (UU) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr + (INT64)temp;
|
||||
break;
|
||||
case 0x0c<<13:
|
||||
/* MR - X * Y (SS) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr - (INT64)temp;
|
||||
break;
|
||||
case 0x0d<<13:
|
||||
/* MR - X * Y (SU) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr - (INT64)temp;
|
||||
break;
|
||||
case 0x0e<<13:
|
||||
/* MR - X * Y (US) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr - (INT64)temp;
|
||||
break;
|
||||
case 0x0f<<13:
|
||||
/* MR - X * Y (UU) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr - (INT64)temp;
|
||||
break;
|
||||
default:
|
||||
res = 0; /* just to keep the compiler happy */
|
||||
break;
|
||||
}
|
||||
|
||||
/* set the final value */
|
||||
temp = (res >> 31) & 0x1ff;
|
||||
CLR_MV;
|
||||
if (temp != 0x000 && temp != 0x1ff) SET_MV;
|
||||
adsp2100.core.mr.mr = res;
|
||||
}
|
||||
|
||||
static void mac_op_mf_xop(int op)
|
||||
{
|
||||
INT8 shift = ((adsp2100.mstat & MSTAT_INTEGER) >> 4) ^ 1;
|
||||
INT32 xop = (op >> 8) & 7;
|
||||
INT32 yop;
|
||||
INT32 temp;
|
||||
INT64 res;
|
||||
|
||||
/* switch ((op >> 13) & 15)*/
|
||||
switch (op & (15<<13)) /*JB*/
|
||||
{
|
||||
case 0x00<<13:
|
||||
/* no-op */
|
||||
return;
|
||||
case 0x01<<13:
|
||||
/* X * Y (RND) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = (INT64)temp;
|
||||
#ifdef ADSP_TWEAK
|
||||
if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
|
||||
else res += (res & 0x8000) << 1;
|
||||
#else
|
||||
temp &= 0xffff;
|
||||
res += 0x8000;
|
||||
if ( temp == 0x8000 )
|
||||
res &= ~((UINT64)0x10000);
|
||||
#endif
|
||||
break;
|
||||
case 0x02<<13:
|
||||
/* MR + X * Y (RND) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr + (INT64)temp;
|
||||
#ifdef ADSP_TWEAK
|
||||
if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
|
||||
else res += (res & 0x8000) << 1;
|
||||
#else
|
||||
temp &= 0xffff;
|
||||
res += 0x8000;
|
||||
if ( temp == 0x8000 )
|
||||
res &= ~((UINT64)0x10000);
|
||||
#endif
|
||||
break;
|
||||
case 0x03<<13:
|
||||
/* MR - X * Y (RND) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr - (INT64)temp;
|
||||
#ifdef ADSP_TWEAK
|
||||
if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
|
||||
else res += (res & 0x8000) << 1;
|
||||
#else
|
||||
temp &= 0xffff;
|
||||
res += 0x8000;
|
||||
if ( temp == 0x8000 )
|
||||
res &= ~((UINT64)0x10000);
|
||||
#endif
|
||||
break;
|
||||
case 0x04<<13:
|
||||
/* X * Y (SS) Clear when y = 0 */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = (INT64)temp;
|
||||
break;
|
||||
case 0x05<<13:
|
||||
/* X * Y (SU) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = (INT64)temp;
|
||||
break;
|
||||
case 0x06<<13:
|
||||
/* X * Y (US) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = (INT64)temp;
|
||||
break;
|
||||
case 0x07<<13:
|
||||
/* X * Y (UU) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = (INT64)temp;
|
||||
break;
|
||||
case 0x08<<13:
|
||||
/* MR + X * Y (SS) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr + (INT64)temp;
|
||||
break;
|
||||
case 0x09<<13:
|
||||
/* MR + X * Y (SU) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr + (INT64)temp;
|
||||
break;
|
||||
case 0x0a<<13:
|
||||
/* MR + X * Y (US) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr + (INT64)temp;
|
||||
break;
|
||||
case 0x0b<<13:
|
||||
/* MR + X * Y (UU) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr + (INT64)temp;
|
||||
break;
|
||||
case 0x0c<<13:
|
||||
/* MR - X * Y (SS) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr - (INT64)temp;
|
||||
break;
|
||||
case 0x0d<<13:
|
||||
/* MR - X * Y (SU) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr - (INT64)temp;
|
||||
break;
|
||||
case 0x0e<<13:
|
||||
/* MR - X * Y (US) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr - (INT64)temp;
|
||||
break;
|
||||
case 0x0f<<13:
|
||||
/* MR - X * Y (UU) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr - (INT64)temp;
|
||||
break;
|
||||
default:
|
||||
res = 0; /* just to keep the compiler happy */
|
||||
break;
|
||||
}
|
||||
|
||||
/* set the final value */
|
||||
adsp2100.core.mf.u = (UINT32)res >> 16;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*===========================================================================
|
||||
SHIFT operations (result in SR/SE/SB)
|
||||
===========================================================================*/
|
||||
|
||||
+1201
-686
File diff suppressed because it is too large.
Load diff
@@ -92,6 +92,13 @@ extern unsigned adsp2100_get_reg(int regnum);
|
||||
extern void adsp2100_set_reg(int regnum, unsigned val);
|
||||
extern void adsp2100_set_irq_line(int irqline, int state);
|
||||
extern void adsp2100_set_irq_callback(int (*callback)(int irqline));
|
||||
/* exact skip of one-instruction NOP delay loops: off unless a driver enables it */
|
||||
extern void adsp2100_set_nop_loop_skip(int enable);
|
||||
/* optional recompiler (adsp2100jit.c): off unless a driver enables it */
|
||||
extern int adsp2100_jit_available(void);
|
||||
extern void adsp2100_set_jit(int enable);
|
||||
/* data memory words [start, end] read through a handler with no side effects */
|
||||
extern void adsp2100_jit_pure_read(UINT32 start, UINT32 end);
|
||||
extern const char *adsp2100_info(void *context, int regnum);
|
||||
extern unsigned adsp2100_dasm(char *buffer, unsigned pc);
|
||||
|
||||
@@ -262,4 +269,56 @@ extern void adsp2115_set_tx_callback( TX_CALLBACK cb );
|
||||
extern void adsp2115_load_boot_data(data8_t *srcdata, data32_t *dstdata);
|
||||
#endif
|
||||
|
||||
#if (HAS_ADSP2181)
|
||||
/**************************************************************************
|
||||
* ADSP2181 section
|
||||
*
|
||||
* 16K words of program RAM and 16K words of data RAM on the chip: the
|
||||
* driver maps them (program memory at ADSP2181_PGM_OFFSET, data memory
|
||||
* at ADSP2181_DATA_OFFSET), with its control registers at 0x3fe0-0x3fff
|
||||
* of data memory. The I/O space (IO(x) instructions) and the data memory
|
||||
* overlay (DMOVLAY) go through the callbacks below
|
||||
**************************************************************************/
|
||||
|
||||
#define ADSP2181_DATA_OFFSET ADSP2100_DATA_OFFSET
|
||||
#define ADSP2181_PGM_OFFSET ADSP2100_PGM_OFFSET
|
||||
#define ADSP2181_SIZE ADSP2100_SIZE
|
||||
|
||||
#define adsp2181_icount adsp2100_icount
|
||||
|
||||
#define ADSP2181_IRQ0 0 /* IRQ0 */
|
||||
#define ADSP2181_SPORT1_RX 0 /* SPORT1 receive IRQ */
|
||||
#define ADSP2181_IRQ1 1 /* IRQ1 */
|
||||
#define ADSP2181_SPORT1_TX 1 /* SPORT1 transmit IRQ */
|
||||
#define ADSP2181_IRQ2 2 /* IRQ2 */
|
||||
#define ADSP2181_SPORT0_RX 3 /* SPORT0 receive IRQ */
|
||||
#define ADSP2181_SPORT0_TX 4 /* SPORT0 transmit IRQ */
|
||||
#define ADSP2181_TIMER 5 /* internal timer IRQ */
|
||||
#define ADSP2181_IRQE 6 /* IRQE */
|
||||
#define ADSP2181_BDMA 7 /* BDMA */
|
||||
#define ADSP2181_IRQL1 8 /* IRQL1 */
|
||||
#define ADSP2181_IRQL0 9 /* IRQL0 */
|
||||
|
||||
typedef UINT16 (*ADSP2181_IO_READ)( UINT32 offset );
|
||||
typedef void (*ADSP2181_IO_WRITE)( UINT32 offset, UINT16 data );
|
||||
typedef void (*ADSP2181_DMOVLAY)( UINT32 dmovlay );
|
||||
|
||||
extern void adsp2181_init(void);
|
||||
extern void adsp2181_reset(void *param);
|
||||
extern void adsp2181_exit(void);
|
||||
extern int adsp2181_execute(int cycles);
|
||||
extern unsigned adsp2181_get_context(void *dst);
|
||||
extern void adsp2181_set_context(void *src);
|
||||
extern unsigned adsp2181_get_reg(int regnum);
|
||||
extern void adsp2181_set_reg(int regnum, unsigned val);
|
||||
extern void adsp2181_set_irq_line(int irqline, int state);
|
||||
extern void adsp2181_set_irq_callback(int (*callback)(int irqline));
|
||||
extern const char *adsp2181_info(void *context, int regnum);
|
||||
extern unsigned adsp2181_dasm(char *buffer, unsigned pc);
|
||||
extern void adsp2181_set_rx_callback( RX_CALLBACK cb );
|
||||
extern void adsp2181_set_tx_callback( TX_CALLBACK cb );
|
||||
extern void adsp2181_set_io_callbacks( ADSP2181_IO_READ rd, ADSP2181_IO_WRITE wr );
|
||||
extern void adsp2181_set_dmovlay_callback( ADSP2181_DMOVLAY cb );
|
||||
#endif
|
||||
|
||||
#endif /* _ADSP2100_H */
|
||||
File diff suppressed because it is too large.
Load diff
+4
-1
@@ -894,6 +894,9 @@ static void HandleMemSingle( data32_t insn )
|
||||
|
||||
} /* HandleMemSingle */
|
||||
|
||||
#define IsNeg(i) ((i) >> 31)
|
||||
#define IsPos(i) ((~(i)) >> 31)
|
||||
|
||||
/* Set NZCV flags for ADDS / SUBS */
|
||||
|
||||
#define HandleALUAddFlags(rd, rn, op2) \
|
||||
@@ -902,7 +905,7 @@ static void HandleMemSingle( data32_t insn )
|
||||
((R15 &~ (N_MASK | Z_MASK | V_MASK | C_MASK)) \
|
||||
| (((!SIGN_BITS_DIFFER(rn, op2)) && SIGN_BITS_DIFFER(rn, rd)) \
|
||||
<< V_BIT) \
|
||||
| (((~(rn)) < (op2)) << C_BIT) \
|
||||
| (((IsNeg(rn) & IsPos(op2)) | (IsNeg(rn) & IsPos(rd)) | (IsPos(op2) & IsPos(rd))) ? C_MASK : 0) \
|
||||
| HandleALUNZFlags(rd)) \
|
||||
+ 4; \
|
||||
else R15 += 4;
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* arm7.c
|
||||
* Portable CPU Emulator for 32-bit ARM v3/4/5/6
|
||||
*
|
||||
* Copyright Steve Ellenoff, all rights reserved.
|
||||
* Thumb, DSP, and MMU support and many bugfixes by R. Belmont and Ryan Holtz.
|
||||
*
|
||||
* - This source code is released as freeware for non-commercial purposes.
|
||||
* - You are free to use and redistribute this code in modified or
|
||||
* unmodified form, provided you list me in the credits.
|
||||
* - If you modify this source code, you must add a notice to each modified
|
||||
* source file that it has been changed. If you're a nice person, you
|
||||
* will clearly mark each change too. :)
|
||||
* - If you wish to use this for commercial purposes, please contact me at
|
||||
* sellenoff@hotmail.com
|
||||
* - The author of this copywritten work reserves the right to change the
|
||||
* terms of its usage and license at any time, including retroactively
|
||||
* - This entire notice must remain in the source code.
|
||||
*
|
||||
* This work is based on:
|
||||
* #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999'
|
||||
* #2) Arm 2/3/6 emulator By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino (MAME CORE 0.76)
|
||||
*
|
||||
*****************************************************************************
|
||||
|
||||
mame2003-plus: modified. The core files (arm7core.c/h, arm7exec.c) are
|
||||
those of MAME 0.139, with the memory accesses going through this
|
||||
version's 32-bit little endian memory system (cpu_readmem32ledw...) and
|
||||
the state in one static structure; this file is the cpu interface of
|
||||
this version. ARMv4T (ARM7TDMI): no MMU, no coprocessors.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "driver.h"
|
||||
#include "state.h"
|
||||
#include "arm7.h"
|
||||
#include "arm7core.h"
|
||||
|
||||
#define LOG(x) logerror x
|
||||
#define fatalerror logerror
|
||||
#define ENDIANNESS_BIG 1
|
||||
|
||||
/* the memory handlers of the core (arm7core.c) */
|
||||
#define READ8(addr) arm7_cpu_read8(cpustate, addr)
|
||||
#define WRITE8(addr,data) arm7_cpu_write8(cpustate, addr,data)
|
||||
#define READ16(addr) arm7_cpu_read16(cpustate, addr)
|
||||
#define WRITE16(addr,data) arm7_cpu_write16(cpustate, addr,data)
|
||||
#define READ32(addr) arm7_cpu_read32(cpustate, addr)
|
||||
#define WRITE32(addr,data) arm7_cpu_write32(cpustate, addr,data)
|
||||
#define PTR_READ32 &arm7_cpu_read32
|
||||
#define PTR_WRITE32 &arm7_cpu_write32
|
||||
|
||||
#define ARM7REG(reg) cpustate->sArmRegister[reg]
|
||||
#define ARM7_ICOUNT arm7_ICount
|
||||
|
||||
static arm_state arm7_state;
|
||||
int arm7_ICount;
|
||||
|
||||
/* the core's inline functions are local to this file */
|
||||
#undef INLINE
|
||||
#if defined( _MSC_VER )
|
||||
#define INLINE static __inline
|
||||
#elif defined( __GNUC__ )
|
||||
#define INLINE static __inline__
|
||||
#else
|
||||
#define INLINE static
|
||||
#endif
|
||||
|
||||
/* ARMv5 helpers the core refers to (CLZ, QADD...): not reached on the ARMv4T */
|
||||
INLINE UINT32 count_leading_zeros(UINT32 val)
|
||||
{
|
||||
UINT32 count = 0;
|
||||
if (val == 0)
|
||||
return 32;
|
||||
while (!(val & 0x80000000))
|
||||
{
|
||||
count++;
|
||||
val <<= 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
INLINE INT64 saturate_qbit_overflow(arm_state *cpustate, INT64 res)
|
||||
{
|
||||
if (res > 2147483647) /* INT32_MAX */
|
||||
{
|
||||
res = 2147483647;
|
||||
SET_CPSR(GET_CPSR | Q_MASK);
|
||||
}
|
||||
else if (res < (-2147483647-1)) /* INT32_MIN */
|
||||
{
|
||||
res = (-2147483647-1);
|
||||
SET_CPSR(GET_CPSR | Q_MASK);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* no MMU on the ARM7TDMI: the core only calls this when one is enabled */
|
||||
INLINE UINT32 arm7_tlb_translate(arm_state *cpustate, UINT32 vaddr)
|
||||
{
|
||||
return vaddr;
|
||||
}
|
||||
|
||||
#include "arm7core.c"
|
||||
|
||||
void arm7_init(void)
|
||||
{
|
||||
arm_state *cpustate = &arm7_state;
|
||||
|
||||
memset(cpustate, 0, sizeof(*cpustate));
|
||||
cpustate->archRev = 4;
|
||||
cpustate->archFlags = eARM_ARCHFLAGS_T;
|
||||
arm7_core_init(cpustate, "arm7", cpu_getactivecpu());
|
||||
}
|
||||
|
||||
void arm7_reset(void *param)
|
||||
{
|
||||
arm7_core_reset(&arm7_state);
|
||||
}
|
||||
|
||||
void arm7_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
int arm7_execute(int cycles)
|
||||
{
|
||||
arm7_ICount = cycles;
|
||||
#include "arm7exec.c"
|
||||
return cycles - arm7_ICount;
|
||||
}
|
||||
|
||||
unsigned arm7_get_context(void *dst)
|
||||
{
|
||||
if (dst)
|
||||
memcpy(dst, &arm7_state, sizeof(arm7_state));
|
||||
return sizeof(arm7_state);
|
||||
}
|
||||
|
||||
void arm7_set_context(void *src)
|
||||
{
|
||||
if (src)
|
||||
memcpy(&arm7_state, src, sizeof(arm7_state));
|
||||
}
|
||||
|
||||
unsigned arm7_get_reg(int regnum)
|
||||
{
|
||||
arm_state *cpustate = &arm7_state;
|
||||
|
||||
switch (regnum)
|
||||
{
|
||||
case REG_PC:
|
||||
case ARM7_PC: return R15;
|
||||
case REG_SP: return GetRegister(cpustate, 13);
|
||||
case REG_PREVIOUSPC: return 0;
|
||||
case ARM7_CPSR: return GET_CPSR;
|
||||
}
|
||||
if (regnum >= ARM7_R0 && regnum <= ARM7_R15)
|
||||
return GetRegister(cpustate, regnum - ARM7_R0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void arm7_set_reg(int regnum, unsigned val)
|
||||
{
|
||||
arm_state *cpustate = &arm7_state;
|
||||
|
||||
switch (regnum)
|
||||
{
|
||||
case REG_PC:
|
||||
case ARM7_PC: R15 = val; return;
|
||||
case REG_SP: SetRegister(cpustate, 13, val); return;
|
||||
case ARM7_CPSR: SET_CPSR(val); return;
|
||||
}
|
||||
if (regnum >= ARM7_R0 && regnum <= ARM7_R15)
|
||||
SetRegister(cpustate, regnum - ARM7_R0, val);
|
||||
}
|
||||
|
||||
void arm7_set_irq_line(int irqline, int state)
|
||||
{
|
||||
arm7_core_set_irq_line(&arm7_state, irqline, state);
|
||||
}
|
||||
|
||||
void arm7_set_irq_callback(int (*callback)(int irqline))
|
||||
{
|
||||
arm7_state.irq_callback = callback;
|
||||
}
|
||||
|
||||
const char *arm7_info(void *context, int regnum)
|
||||
{
|
||||
static char buffer[16][64];
|
||||
static int which = 0;
|
||||
arm_state *cpustate = context ? (arm_state *)context : &arm7_state;
|
||||
|
||||
which = (which + 1) % 16;
|
||||
buffer[which][0] = '\0';
|
||||
|
||||
if (regnum >= CPU_INFO_REG + ARM7_R0 && regnum <= CPU_INFO_REG + ARM7_R15)
|
||||
{
|
||||
sprintf(buffer[which], "R%-3d:%08x", regnum - CPU_INFO_REG - ARM7_R0, GetRegister(cpustate, regnum - CPU_INFO_REG - ARM7_R0));
|
||||
return buffer[which];
|
||||
}
|
||||
switch (regnum)
|
||||
{
|
||||
case CPU_INFO_REG + ARM7_PC: sprintf(buffer[which], "PC :%08x", R15); break;
|
||||
case CPU_INFO_REG + ARM7_CPSR: sprintf(buffer[which], "CPSR:%08x", GET_CPSR); break;
|
||||
case CPU_INFO_FLAGS:
|
||||
sprintf(buffer[which], "%c%c%c%c%c%c%c %s",
|
||||
(GET_CPSR & N_MASK) ? 'N' : '-',
|
||||
(GET_CPSR & Z_MASK) ? 'Z' : '-',
|
||||
(GET_CPSR & C_MASK) ? 'C' : '-',
|
||||
(GET_CPSR & V_MASK) ? 'V' : '-',
|
||||
(GET_CPSR & I_MASK) ? 'I' : '-',
|
||||
(GET_CPSR & F_MASK) ? 'F' : '-',
|
||||
(GET_CPSR & T_MASK) ? 'T' : '-',
|
||||
GetModeText(GET_CPSR));
|
||||
break;
|
||||
case CPU_INFO_NAME: return "ARM7";
|
||||
case CPU_INFO_FAMILY: return "Acorn Risc Machine";
|
||||
case CPU_INFO_VERSION: return "2.0 (MAME 0.139 core)";
|
||||
case CPU_INFO_FILE: return __FILE__;
|
||||
case CPU_INFO_CREDITS: return "Copyright Steve Ellenoff, [email protected]";
|
||||
}
|
||||
return buffer[which];
|
||||
}
|
||||
|
||||
unsigned arm7_dasm(char *buffer, unsigned pc)
|
||||
{
|
||||
if (T_IS_SET(arm7_state.sArmRegister[eCPSR]))
|
||||
{
|
||||
sprintf(buffer, "$%04x", cpu_readmem32ledw_word(pc & ~1));
|
||||
return 2;
|
||||
}
|
||||
sprintf(buffer, "$%08x", cpu_readmem32ledw_dword(pc & ~3));
|
||||
return 4;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* arm7.h
|
||||
* Portable ARM7TDMI CPU Emulator
|
||||
*
|
||||
* Copyright Steve Ellenoff, all rights reserved.
|
||||
* Thumb, DSP, and MMU support and many bugfixes by R. Belmont and Ryan Holtz.
|
||||
* (see arm7core.c for the full notice)
|
||||
*
|
||||
* mame2003-plus: the MAME 0.139 core with the cpu interface of this
|
||||
* version (one ARM7 at a time, 32-bit little endian bus).
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ARM7_H
|
||||
#define ARM7_H
|
||||
|
||||
#include "driver.h"
|
||||
|
||||
/* interrupt lines and exceptions */
|
||||
#define ARM7_IRQ_LINE 0
|
||||
#define ARM7_FIRQ_LINE 1
|
||||
#define ARM7_ABORT_EXCEPTION 2
|
||||
#define ARM7_ABORT_PREFETCH_EXCEPTION 3
|
||||
#define ARM7_UNDEFINE_EXCEPTION 4
|
||||
|
||||
|
||||
extern int arm7_ICount;
|
||||
|
||||
extern void arm7_init(void);
|
||||
extern void arm7_reset(void *param);
|
||||
extern void arm7_exit(void);
|
||||
extern int arm7_execute(int cycles);
|
||||
extern unsigned arm7_get_context(void *dst);
|
||||
extern void arm7_set_context(void *src);
|
||||
extern unsigned arm7_get_reg(int regnum);
|
||||
extern void arm7_set_reg(int regnum, unsigned val);
|
||||
extern void arm7_set_irq_line(int irqline, int state);
|
||||
extern void arm7_set_irq_callback(int (*callback)(int irqline));
|
||||
extern const char *arm7_info(void *context, int regnum);
|
||||
extern unsigned arm7_dasm(char *buffer, unsigned pc);
|
||||
|
||||
#endif /* ARM7_H */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,488 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* arm7core.h
|
||||
* Portable ARM7TDMI Core Emulator
|
||||
*
|
||||
* Copyright Steve Ellenoff, all rights reserved.
|
||||
*
|
||||
* - This source code is released as freeware for non-commercial purposes.
|
||||
* - You are free to use and redistribute this code in modified or
|
||||
* unmodified form, provided you list me in the credits.
|
||||
* - If you modify this source code, you must add a notice to each modified
|
||||
* source file that it has been changed. If you're a nice person, you
|
||||
* will clearly mark each change too. :)
|
||||
* - If you wish to use this for commercial purposes, please contact me at
|
||||
* sellenoff@hotmail.com
|
||||
* - The author of this copywritten work reserves the right to change the
|
||||
* terms of its usage and license at any time, including retroactively
|
||||
* - This entire notice must remain in the source code.
|
||||
*
|
||||
* This work is based on:
|
||||
* #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999'
|
||||
* #2) Arm 2/3/6 emulator By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino (MAME CORE 0.76)
|
||||
*
|
||||
*****************************************************************************
|
||||
|
||||
This file contains everything related to the arm7 core itself, and is presumed
|
||||
to be cpu implementation non-specific, ie, applies to only the core.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#ifndef __ARM7CORE_H__
|
||||
#define __ARM7CORE_H__
|
||||
|
||||
|
||||
/****************************************************************************************************
|
||||
* INTERRUPT LINES/EXCEPTIONS
|
||||
***************************************************************************************************/
|
||||
/* ARM7_IRQ_LINE .. ARM7_UNDEFINE_EXCEPTION: in arm7.h */
|
||||
#define ARM7_NUM_LINES 5
|
||||
/* Really there's only 1 ABORT Line.. and cpu decides whether it's during data fetch or prefetch, but we let the user specify */
|
||||
|
||||
/****************************************************************************************************
|
||||
* ARM7 CORE REGISTERS
|
||||
***************************************************************************************************/
|
||||
enum
|
||||
{
|
||||
ARM7_PC = 0,
|
||||
ARM7_R0, ARM7_R1, ARM7_R2, ARM7_R3, ARM7_R4, ARM7_R5, ARM7_R6, ARM7_R7,
|
||||
ARM7_R8, ARM7_R9, ARM7_R10, ARM7_R11, ARM7_R12, ARM7_R13, ARM7_R14, ARM7_R15,
|
||||
ARM7_FR8, ARM7_FR9, ARM7_FR10, ARM7_FR11, ARM7_FR12, ARM7_FR13, ARM7_FR14,
|
||||
ARM7_IR13, ARM7_IR14, ARM7_SR13, ARM7_SR14, ARM7_FSPSR, ARM7_ISPSR, ARM7_SSPSR,
|
||||
ARM7_CPSR, ARM7_AR13, ARM7_AR14, ARM7_ASPSR, ARM7_UR13, ARM7_UR14, ARM7_USPSR
|
||||
};
|
||||
|
||||
/* There are 36 Unique - 32 bit processor registers */
|
||||
/* Each mode has 17 registers (except user & system, which have 16) */
|
||||
/* This is a list of each *unique* register */
|
||||
enum
|
||||
{
|
||||
/* All modes have the following */
|
||||
eR0 = 0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
|
||||
eR8, eR9, eR10, eR11, eR12,
|
||||
eR13, /* Stack Pointer */
|
||||
eR14, /* Link Register (holds return address) */
|
||||
eR15, /* Program Counter */
|
||||
eCPSR, /* Current Status Program Register */
|
||||
|
||||
/* Fast Interrupt - Bank switched registers */
|
||||
eR8_FIQ, eR9_FIQ, eR10_FIQ, eR11_FIQ, eR12_FIQ, eR13_FIQ, eR14_FIQ, eSPSR_FIQ,
|
||||
|
||||
/* IRQ - Bank switched registers */
|
||||
eR13_IRQ, eR14_IRQ, eSPSR_IRQ,
|
||||
|
||||
/* Supervisor/Service Mode - Bank switched registers */
|
||||
eR13_SVC, eR14_SVC, eSPSR_SVC,
|
||||
|
||||
/* Abort Mode - Bank switched registers */
|
||||
eR13_ABT, eR14_ABT, eSPSR_ABT,
|
||||
|
||||
/* Undefined Mode - Bank switched registers */
|
||||
eR13_UND, eR14_UND, eSPSR_UND,
|
||||
|
||||
kNumRegisters
|
||||
};
|
||||
|
||||
/* Coprocessor-related macros */
|
||||
#define COPRO_TLB_BASE cpustate->tlbBase
|
||||
#define COPRO_TLB_BASE_MASK 0xffffc000
|
||||
#define COPRO_TLB_VADDR_FLTI_MASK 0xfff00000
|
||||
#define COPRO_TLB_VADDR_FLTI_MASK_SHIFT 18
|
||||
#define COPRO_TLB_VADDR_CSLTI_MASK 0x000ff000
|
||||
#define COPRO_TLB_VADDR_CSLTI_MASK_SHIFT 10
|
||||
#define COPRO_TLB_VADDR_FSLTI_MASK 0x000ffc00
|
||||
#define COPRO_TLB_VADDR_FSLTI_MASK_SHIFT 8
|
||||
#define COPRO_TLB_CFLD_ADDR_MASK 0xfffffc00
|
||||
#define COPRO_TLB_CFLD_ADDR_MASK_SHIFT 10
|
||||
#define COPRO_TLB_SECTION_PAGE_MASK 0xfff00000
|
||||
#define COPRO_TLB_LARGE_PAGE_MASK 0xffff0000
|
||||
#define COPRO_TLB_SMALL_PAGE_MASK 0xfffff000
|
||||
#define COPRO_TLB_TINY_PAGE_MASK 0xfffffc00
|
||||
#define COPRO_TLB_UNMAPPED 0
|
||||
#define COPRO_TLB_LARGE_PAGE 1
|
||||
#define COPRO_TLB_SMALL_PAGE 2
|
||||
#define COPRO_TLB_TINY_PAGE 3
|
||||
#define COPRO_TLB_COARSE_TABLE 1
|
||||
#define COPRO_TLB_SECTION_TABLE 2
|
||||
#define COPRO_TLB_FINE_TABLE 3
|
||||
|
||||
#define COPRO_CTRL cpustate->control
|
||||
#define COPRO_CTRL_MMU_EN 0x00000001
|
||||
#define COPRO_CTRL_ADDRFAULT_EN 0x00000002
|
||||
#define COPRO_CTRL_DCACHE_EN 0x00000004
|
||||
#define COPRO_CTRL_WRITEBUF_EN 0x00000008
|
||||
#define COPRO_CTRL_ENDIAN 0x00000080
|
||||
#define COPRO_CTRL_SYSTEM 0x00000100
|
||||
#define COPRO_CTRL_ROM 0x00000200
|
||||
#define COPRO_CTRL_ICACHE_EN 0x00001000
|
||||
#define COPRO_CTRL_INTVEC_ADJUST 0x00002000
|
||||
#define COPRO_CTRL_ADDRFAULT_EN_SHIFT 1
|
||||
#define COPRO_CTRL_DCACHE_EN_SHIFT 2
|
||||
#define COPRO_CTRL_WRITEBUF_EN_SHIFT 3
|
||||
#define COPRO_CTRL_ENDIAN_SHIFT 7
|
||||
#define COPRO_CTRL_SYSTEM_SHIFT 8
|
||||
#define COPRO_CTRL_ROM_SHIFT 9
|
||||
#define COPRO_CTRL_ICACHE_EN_SHIFT 12
|
||||
#define COPRO_CTRL_INTVEC_ADJUST_SHIFT 13
|
||||
#define COPRO_CTRL_LITTLE_ENDIAN 0
|
||||
#define COPRO_CTRL_BIG_ENDIAN 1
|
||||
#define COPRO_CTRL_INTVEC_0 0
|
||||
#define COPRO_CTRL_INTVEC_F 1
|
||||
#define COPRO_CTRL_MASK 0x0000338f
|
||||
|
||||
/* Coprocessor Registers */
|
||||
#define ARM7COPRO_REGS \
|
||||
UINT32 control; \
|
||||
UINT32 tlbBase;
|
||||
|
||||
enum
|
||||
{
|
||||
eARM_ARCHFLAGS_T = 1, /* Thumb present */
|
||||
eARM_ARCHFLAGS_E = 2, /* extended DSP operations present (only for v5+) */
|
||||
eARM_ARCHFLAGS_J = 4, /* "Jazelle" (direct execution of Java bytecode) */
|
||||
eARM_ARCHFLAGS_MMU = 8, /* has on-board MMU (traditional ARM style like the SA1110) */
|
||||
eARM_ARCHFLAGS_SA = 16, /* StrongARM extensions (enhanced TLB) */
|
||||
eARM_ARCHFLAGS_XSCALE = 32 /* XScale extensions (CP14, enhanced TLB) */
|
||||
};
|
||||
|
||||
#define ARM7CORE_REGS \
|
||||
UINT32 sArmRegister[kNumRegisters]; \
|
||||
UINT8 pendingIrq; \
|
||||
UINT8 pendingFiq; \
|
||||
UINT8 pendingAbtD; \
|
||||
UINT8 pendingAbtP; \
|
||||
UINT8 pendingUnd; \
|
||||
UINT8 pendingSwi; \
|
||||
INT32 iCount; \
|
||||
int endian; \
|
||||
int (*irq_callback)(int irqline);
|
||||
|
||||
|
||||
/* CPU state struct */
|
||||
typedef struct
|
||||
{
|
||||
ARM7CORE_REGS /* these must be included in your cpu specific register implementation */
|
||||
ARM7COPRO_REGS
|
||||
|
||||
UINT8 archRev; /* ARM architecture revision (3, 4, and 5 are valid) */
|
||||
UINT8 archFlags; /* architecture flags */
|
||||
|
||||
} arm_state;
|
||||
|
||||
/****************************************************************************************************
|
||||
* VARIOUS INTERNAL STRUCS/DEFINES/ETC..
|
||||
***************************************************************************************************/
|
||||
/* Mode values come from bit 4-0 of CPSR, but we are ignoring bit 4 here, since bit 4 always = 1 for valid modes */
|
||||
enum
|
||||
{
|
||||
eARM7_MODE_USER = 0x0, /* Bit: 4-0 = 10000 */
|
||||
eARM7_MODE_FIQ = 0x1, /* Bit: 4-0 = 10001 */
|
||||
eARM7_MODE_IRQ = 0x2, /* Bit: 4-0 = 10010 */
|
||||
eARM7_MODE_SVC = 0x3, /* Bit: 4-0 = 10011 */
|
||||
eARM7_MODE_ABT = 0x7, /* Bit: 4-0 = 10111 */
|
||||
eARM7_MODE_UND = 0xb, /* Bit: 4-0 = 11011 */
|
||||
eARM7_MODE_SYS = 0xf /* Bit: 4-0 = 11111 */
|
||||
};
|
||||
|
||||
#define ARM7_NUM_MODES 0x10
|
||||
|
||||
static const int thumbCycles[256] =
|
||||
{
|
||||
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0 */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 1 */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 2 */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 3 */
|
||||
1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 4 */
|
||||
2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 5 */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, /* 6 */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, /* 7 */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, /* 8 */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, /* 9 */
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* a */
|
||||
1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 4, 1, 1, /* b */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* c */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, /* d */
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* e */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 /* f */
|
||||
};
|
||||
|
||||
/* 17 processor registers are visible at any given time,
|
||||
* banked depending on processor mode.
|
||||
*/
|
||||
|
||||
static const int sRegisterTable[ARM7_NUM_MODES][18] =
|
||||
{
|
||||
{ /* USR */
|
||||
eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
|
||||
eR8, eR9, eR10, eR11, eR12,
|
||||
eR13, eR14,
|
||||
eR15, eCPSR /* No SPSR in this mode */
|
||||
},
|
||||
{ /* FIQ */
|
||||
eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
|
||||
eR8_FIQ, eR9_FIQ, eR10_FIQ, eR11_FIQ, eR12_FIQ,
|
||||
eR13_FIQ, eR14_FIQ,
|
||||
eR15, eCPSR, eSPSR_FIQ
|
||||
},
|
||||
{ /* IRQ */
|
||||
eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
|
||||
eR8, eR9, eR10, eR11, eR12,
|
||||
eR13_IRQ, eR14_IRQ,
|
||||
eR15, eCPSR, eSPSR_IRQ
|
||||
},
|
||||
{ /* SVC */
|
||||
eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
|
||||
eR8, eR9, eR10, eR11, eR12,
|
||||
eR13_SVC, eR14_SVC,
|
||||
eR15, eCPSR, eSPSR_SVC
|
||||
},
|
||||
{0}, {0}, {0}, /* values for modes 4,5,6 are not valid */
|
||||
{ /* ABT */
|
||||
eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
|
||||
eR8, eR9, eR10, eR11, eR12,
|
||||
eR13_ABT, eR14_ABT,
|
||||
eR15, eCPSR, eSPSR_ABT
|
||||
},
|
||||
{0}, {0}, {0}, /* values for modes 8,9,a are not valid! */
|
||||
{ /* UND */
|
||||
eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
|
||||
eR8, eR9, eR10, eR11, eR12,
|
||||
eR13_UND, eR14_UND,
|
||||
eR15, eCPSR, eSPSR_UND
|
||||
},
|
||||
{0}, {0}, {0}, /* values for modes c,d, e are not valid! */
|
||||
{ /* SYS */
|
||||
eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
|
||||
eR8, eR9, eR10, eR11, eR12,
|
||||
eR13, eR14,
|
||||
eR15, eCPSR /* No SPSR in this mode */
|
||||
}
|
||||
};
|
||||
|
||||
#define N_BIT 31
|
||||
#define Z_BIT 30
|
||||
#define C_BIT 29
|
||||
#define V_BIT 28
|
||||
#define Q_BIT 27
|
||||
#define I_BIT 7
|
||||
#define F_BIT 6
|
||||
#define T_BIT 5 /* Thumb mode */
|
||||
|
||||
#define N_MASK ((UINT32)(1 << N_BIT)) /* Negative flag */
|
||||
#define Z_MASK ((UINT32)(1 << Z_BIT)) /* Zero flag */
|
||||
#define C_MASK ((UINT32)(1 << C_BIT)) /* Carry flag */
|
||||
#define V_MASK ((UINT32)(1 << V_BIT)) /* oVerflow flag */
|
||||
#define Q_MASK ((UINT32)(1 << Q_BIT)) /* signed overflow for QADD, MAC */
|
||||
#define I_MASK ((UINT32)(1 << I_BIT)) /* Interrupt request disable */
|
||||
#define F_MASK ((UINT32)(1 << F_BIT)) /* Fast interrupt request disable */
|
||||
#define T_MASK ((UINT32)(1 << T_BIT)) /* Thumb Mode flag */
|
||||
|
||||
#define N_IS_SET(pc) ((pc) & N_MASK)
|
||||
#define Z_IS_SET(pc) ((pc) & Z_MASK)
|
||||
#define C_IS_SET(pc) ((pc) & C_MASK)
|
||||
#define V_IS_SET(pc) ((pc) & V_MASK)
|
||||
#define Q_IS_SET(pc) ((pc) & Q_MASK)
|
||||
#define I_IS_SET(pc) ((pc) & I_MASK)
|
||||
#define F_IS_SET(pc) ((pc) & F_MASK)
|
||||
#define T_IS_SET(pc) ((pc) & T_MASK)
|
||||
|
||||
#define N_IS_CLEAR(pc) (!N_IS_SET(pc))
|
||||
#define Z_IS_CLEAR(pc) (!Z_IS_SET(pc))
|
||||
#define C_IS_CLEAR(pc) (!C_IS_SET(pc))
|
||||
#define V_IS_CLEAR(pc) (!V_IS_SET(pc))
|
||||
#define Q_IS_CLEAR(pc) (!Q_IS_SET(pc))
|
||||
#define I_IS_CLEAR(pc) (!I_IS_SET(pc))
|
||||
#define F_IS_CLEAR(pc) (!F_IS_SET(pc))
|
||||
#define T_IS_CLEAR(pc) (!T_IS_SET(pc))
|
||||
|
||||
/* Deconstructing an instruction */
|
||||
/* todo: use these in all places (including dasm file) */
|
||||
#define INSN_COND ((UINT32)0xf0000000u)
|
||||
#define INSN_SDT_L ((UINT32)0x00100000u)
|
||||
#define INSN_SDT_W ((UINT32)0x00200000u)
|
||||
#define INSN_SDT_B ((UINT32)0x00400000u)
|
||||
#define INSN_SDT_U ((UINT32)0x00800000u)
|
||||
#define INSN_SDT_P ((UINT32)0x01000000u)
|
||||
#define INSN_BDT_L ((UINT32)0x00100000u)
|
||||
#define INSN_BDT_W ((UINT32)0x00200000u)
|
||||
#define INSN_BDT_S ((UINT32)0x00400000u)
|
||||
#define INSN_BDT_U ((UINT32)0x00800000u)
|
||||
#define INSN_BDT_P ((UINT32)0x01000000u)
|
||||
#define INSN_BDT_REGS ((UINT32)0x0000ffffu)
|
||||
#define INSN_SDT_IMM ((UINT32)0x00000fffu)
|
||||
#define INSN_MUL_A ((UINT32)0x00200000u)
|
||||
#define INSN_MUL_RM ((UINT32)0x0000000fu)
|
||||
#define INSN_MUL_RS ((UINT32)0x00000f00u)
|
||||
#define INSN_MUL_RN ((UINT32)0x0000f000u)
|
||||
#define INSN_MUL_RD ((UINT32)0x000f0000u)
|
||||
#define INSN_I ((UINT32)0x02000000u)
|
||||
#define INSN_OPCODE ((UINT32)0x01e00000u)
|
||||
#define INSN_S ((UINT32)0x00100000u)
|
||||
#define INSN_BL ((UINT32)0x01000000u)
|
||||
#define INSN_BRANCH ((UINT32)0x00ffffffu)
|
||||
#define INSN_SWI ((UINT32)0x00ffffffu)
|
||||
#define INSN_RN ((UINT32)0x000f0000u)
|
||||
#define INSN_RD ((UINT32)0x0000f000u)
|
||||
#define INSN_OP2 ((UINT32)0x00000fffu)
|
||||
#define INSN_OP2_SHIFT ((UINT32)0x00000f80u)
|
||||
#define INSN_OP2_SHIFT_TYPE ((UINT32)0x00000070u)
|
||||
#define INSN_OP2_RM ((UINT32)0x0000000fu)
|
||||
#define INSN_OP2_ROTATE ((UINT32)0x00000f00u)
|
||||
#define INSN_OP2_IMM ((UINT32)0x000000ffu)
|
||||
#define INSN_OP2_SHIFT_TYPE_SHIFT 4
|
||||
#define INSN_OP2_SHIFT_SHIFT 7
|
||||
#define INSN_OP2_ROTATE_SHIFT 8
|
||||
#define INSN_MUL_RS_SHIFT 8
|
||||
#define INSN_MUL_RN_SHIFT 12
|
||||
#define INSN_MUL_RD_SHIFT 16
|
||||
#define INSN_OPCODE_SHIFT 21
|
||||
#define INSN_RN_SHIFT 16
|
||||
#define INSN_RD_SHIFT 12
|
||||
#define INSN_COND_SHIFT 28
|
||||
|
||||
#define INSN_COPRO_N ((UINT32) 0x00100000u)
|
||||
#define INSN_COPRO_CREG ((UINT32) 0x000f0000u)
|
||||
#define INSN_COPRO_AREG ((UINT32) 0x0000f000u)
|
||||
#define INSN_COPRO_CPNUM ((UINT32) 0x00000f00u)
|
||||
#define INSN_COPRO_OP2 ((UINT32) 0x000000e0u)
|
||||
#define INSN_COPRO_OP3 ((UINT32) 0x0000000fu)
|
||||
#define INSN_COPRO_N_SHIFT 20
|
||||
#define INSN_COPRO_CREG_SHIFT 16
|
||||
#define INSN_COPRO_AREG_SHIFT 12
|
||||
#define INSN_COPRO_CPNUM_SHIFT 8
|
||||
#define INSN_COPRO_OP2_SHIFT 5
|
||||
|
||||
#define THUMB_INSN_TYPE ((UINT16)0xf000)
|
||||
#define THUMB_COND_TYPE ((UINT16)0x0f00)
|
||||
#define THUMB_GROUP4_TYPE ((UINT16)0x0c00)
|
||||
#define THUMB_GROUP5_TYPE ((UINT16)0x0e00)
|
||||
#define THUMB_GROUP5_RM ((UINT16)0x01c0)
|
||||
#define THUMB_GROUP5_RN ((UINT16)0x0038)
|
||||
#define THUMB_GROUP5_RD ((UINT16)0x0007)
|
||||
#define THUMB_ADDSUB_RNIMM ((UINT16)0x01c0)
|
||||
#define THUMB_ADDSUB_RS ((UINT16)0x0038)
|
||||
#define THUMB_ADDSUB_RD ((UINT16)0x0007)
|
||||
#define THUMB_INSN_ADDSUB ((UINT16)0x0800)
|
||||
#define THUMB_INSN_CMP ((UINT16)0x0800)
|
||||
#define THUMB_INSN_SUB ((UINT16)0x0800)
|
||||
#define THUMB_INSN_IMM_RD ((UINT16)0x0700)
|
||||
#define THUMB_INSN_IMM_S ((UINT16)0x0080)
|
||||
#define THUMB_INSN_IMM ((UINT16)0x00ff)
|
||||
#define THUMB_ADDSUB_TYPE ((UINT16)0x0600)
|
||||
#define THUMB_HIREG_OP ((UINT16)0x0300)
|
||||
#define THUMB_HIREG_H ((UINT16)0x00c0)
|
||||
#define THUMB_HIREG_RS ((UINT16)0x0038)
|
||||
#define THUMB_HIREG_RD ((UINT16)0x0007)
|
||||
#define THUMB_STACKOP_TYPE ((UINT16)0x0f00)
|
||||
#define THUMB_STACKOP_L ((UINT16)0x0800)
|
||||
#define THUMB_STACKOP_RD ((UINT16)0x0700)
|
||||
#define THUMB_ALUOP_TYPE ((UINT16)0x03c0)
|
||||
#define THUMB_BLOP_LO ((UINT16)0x0800)
|
||||
#define THUMB_BLOP_OFFS ((UINT16)0x07ff)
|
||||
#define THUMB_SHIFT_R ((UINT16)0x0800)
|
||||
#define THUMB_SHIFT_AMT ((UINT16)0x07c0)
|
||||
#define THUMB_HALFOP_L ((UINT16)0x0800)
|
||||
#define THUMB_HALFOP_OFFS ((UINT16)0x07c0)
|
||||
#define THUMB_BRANCH_OFFS ((UINT16)0x07ff)
|
||||
#define THUMB_LSOP_L ((UINT16)0x0800)
|
||||
#define THUMB_LSOP_OFFS ((UINT16)0x07c0)
|
||||
#define THUMB_MULTLS ((UINT16)0x0800)
|
||||
#define THUMB_MULTLS_BASE ((UINT16)0x0700)
|
||||
#define THUMB_RELADDR_SP ((UINT16)0x0800)
|
||||
#define THUMB_RELADDR_RD ((UINT16)0x0700)
|
||||
#define THUMB_INSN_TYPE_SHIFT 12
|
||||
#define THUMB_COND_TYPE_SHIFT 8
|
||||
#define THUMB_GROUP4_TYPE_SHIFT 10
|
||||
#define THUMB_GROUP5_TYPE_SHIFT 9
|
||||
#define THUMB_ADDSUB_TYPE_SHIFT 9
|
||||
#define THUMB_INSN_IMM_RD_SHIFT 8
|
||||
#define THUMB_STACKOP_TYPE_SHIFT 8
|
||||
#define THUMB_HIREG_OP_SHIFT 8
|
||||
#define THUMB_STACKOP_RD_SHIFT 8
|
||||
#define THUMB_MULTLS_BASE_SHIFT 8
|
||||
#define THUMB_RELADDR_RD_SHIFT 8
|
||||
#define THUMB_HIREG_H_SHIFT 6
|
||||
#define THUMB_HIREG_RS_SHIFT 3
|
||||
#define THUMB_ALUOP_TYPE_SHIFT 6
|
||||
#define THUMB_SHIFT_AMT_SHIFT 6
|
||||
#define THUMB_HALFOP_OFFS_SHIFT 6
|
||||
#define THUMB_LSOP_OFFS_SHIFT 6
|
||||
#define THUMB_GROUP5_RM_SHIFT 6
|
||||
#define THUMB_GROUP5_RN_SHIFT 3
|
||||
#define THUMB_GROUP5_RD_SHIFT 0
|
||||
#define THUMB_ADDSUB_RNIMM_SHIFT 6
|
||||
#define THUMB_ADDSUB_RS_SHIFT 3
|
||||
#define THUMB_ADDSUB_RD_SHIFT 0
|
||||
|
||||
enum
|
||||
{
|
||||
OPCODE_AND, /* 0000 */
|
||||
OPCODE_EOR, /* 0001 */
|
||||
OPCODE_SUB, /* 0010 */
|
||||
OPCODE_RSB, /* 0011 */
|
||||
OPCODE_ADD, /* 0100 */
|
||||
OPCODE_ADC, /* 0101 */
|
||||
OPCODE_SBC, /* 0110 */
|
||||
OPCODE_RSC, /* 0111 */
|
||||
OPCODE_TST, /* 1000 */
|
||||
OPCODE_TEQ, /* 1001 */
|
||||
OPCODE_CMP, /* 1010 */
|
||||
OPCODE_CMN, /* 1011 */
|
||||
OPCODE_ORR, /* 1100 */
|
||||
OPCODE_MOV, /* 1101 */
|
||||
OPCODE_BIC, /* 1110 */
|
||||
OPCODE_MVN /* 1111 */
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
COND_EQ = 0, /* Z equal */
|
||||
COND_NE, /* ~Z not equal */
|
||||
COND_CS, COND_HS = 2, /* C unsigned higher or same */
|
||||
COND_CC, COND_LO = 3, /* ~C unsigned lower */
|
||||
COND_MI, /* N negative */
|
||||
COND_PL, /* ~N positive or zero */
|
||||
COND_VS, /* V overflow */
|
||||
COND_VC, /* ~V no overflow */
|
||||
COND_HI, /* C && ~Z unsigned higher */
|
||||
COND_LS, /* ~C || Z unsigned lower or same */
|
||||
COND_GE, /* N == V greater or equal */
|
||||
COND_LT, /* N != V less than */
|
||||
COND_GT, /* ~Z && N == V greater than */
|
||||
COND_LE, /* Z || N != V less than or equal */
|
||||
COND_AL, /* 1 always */
|
||||
COND_NV /* 0 never */
|
||||
};
|
||||
|
||||
#define LSL(v, s) ((v) << (s))
|
||||
#define LSR(v, s) ((v) >> (s))
|
||||
#define ROL(v, s) (LSL((v), (s)) | (LSR((v), 32u - (s))))
|
||||
#define ROR(v, s) (LSR((v), (s)) | (LSL((v), 32u - (s))))
|
||||
|
||||
/* Convenience Macros */
|
||||
#define R15 ARM7REG(eR15)
|
||||
#define SPSR 17 /* SPSR is always the 18th register in our 0 based array sRegisterTable[][18] */
|
||||
#define GET_CPSR ARM7REG(eCPSR)
|
||||
#define SET_CPSR(v) (GET_CPSR = (v))
|
||||
#define MODE_FLAG 0xF /* Mode bits are 4:0 of CPSR, but we ignore bit 4. */
|
||||
#define GET_MODE (GET_CPSR & MODE_FLAG)
|
||||
#define SIGN_BIT ((UINT32)(1 << 31))
|
||||
#define SIGN_BITS_DIFFER(a, b) (((a) ^ (b)) >> 31)
|
||||
/* I really don't know why these were set to 16-bit, the thumb registers are still 32-bit ... */
|
||||
#define THUMB_SIGN_BIT ((UINT32)(1 << 31))
|
||||
#define THUMB_SIGN_BITS_DIFFER(a, b) (((a)^(b)) >> 31)
|
||||
|
||||
/* At one point I thought these needed to be cpu implementation specific, but they don't.. */
|
||||
#define GET_REGISTER(state, reg) GetRegister(state, reg)
|
||||
#define SET_REGISTER(state, reg, val) SetRegister(state, reg, val)
|
||||
#define ARM7_CHECKIRQ arm7_check_irq_state(cpustate)
|
||||
|
||||
#ifdef UNUSED_DEFINITION
|
||||
extern char *(*arm7_dasm_cop_dt_callback)(arm_state *cpustate, char *pBuf, UINT32 opcode, char *pConditionCode, char *pBuf0);
|
||||
extern char *(*arm7_dasm_cop_rt_callback)(arm_state *cpustate, char *pBuf, UINT32 opcode, char *pConditionCode, char *pBuf0);
|
||||
extern char *(*arm7_dasm_cop_do_callback)(arm_state *cpustate, char *pBuf, UINT32 opcode, char *pConditionCode, char *pBuf0);
|
||||
#endif
|
||||
|
||||
#endif /* __ARM7CORE_H__ */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -60,6 +60,7 @@
|
||||
|
||||
#include "memory.h"
|
||||
#include "cpuintrf.h"
|
||||
#include "state.h"
|
||||
#include "mamedbg.h"
|
||||
#include "h6280.h"
|
||||
|
||||
@@ -138,6 +139,31 @@ UINT8 H6280_debug_mmr[8];
|
||||
/*****************************************************************************/
|
||||
void h6280_init(void)
|
||||
{
|
||||
int cpu = cpu_getactivecpu();
|
||||
|
||||
state_save_register_UINT32("h6280", cpu, "PPC", &h6280.ppc.d, 1);
|
||||
state_save_register_UINT32("h6280", cpu, "PC", &h6280.pc.d, 1);
|
||||
state_save_register_UINT32("h6280", cpu, "SP", &h6280.sp.d, 1);
|
||||
state_save_register_UINT32("h6280", cpu, "ZP", &h6280.zp.d, 1);
|
||||
state_save_register_UINT32("h6280", cpu, "EA", &h6280.ea.d, 1);
|
||||
state_save_register_UINT8("h6280", cpu, "A", &h6280.a, 1);
|
||||
state_save_register_UINT8("h6280", cpu, "X", &h6280.x, 1);
|
||||
state_save_register_UINT8("h6280", cpu, "Y", &h6280.y, 1);
|
||||
state_save_register_UINT8("h6280", cpu, "P", &h6280.p, 1);
|
||||
state_save_register_UINT8("h6280", cpu, "MMR", h6280.mmr, 8);
|
||||
state_save_register_UINT8("h6280", cpu, "IRQ_MASK", &h6280.irq_mask, 1);
|
||||
state_save_register_UINT8("h6280", cpu, "TIMER_STATUS", &h6280.timer_status, 1);
|
||||
state_save_register_UINT8("h6280", cpu, "TIMER_ACK", &h6280.timer_ack, 1);
|
||||
state_save_register_int("h6280", cpu, "TIMER_VALUE", &h6280.timer_value);
|
||||
state_save_register_int("h6280", cpu, "TIMER_LOAD", &h6280.timer_load);
|
||||
state_save_register_int("h6280", cpu, "EXTRA_CYCLES", &h6280.extra_cycles);
|
||||
state_save_register_int("h6280", cpu, "NMI_STATE", &h6280.nmi_state);
|
||||
state_save_register_int("h6280", cpu, "IRQ1_STATE", &h6280.irq_state[0]);
|
||||
state_save_register_int("h6280", cpu, "IRQ2_STATE", &h6280.irq_state[1]);
|
||||
state_save_register_int("h6280", cpu, "IRQT_STATE", &h6280.irq_state[2]);
|
||||
#if LAZY_FLAGS
|
||||
state_save_register_int("h6280", cpu, "NZ", &h6280.NZ);
|
||||
#endif
|
||||
}
|
||||
|
||||
void h6280_reset(void *param)
|
||||
|
||||
@@ -0,0 +1,930 @@
|
||||
/***************************************************************************
|
||||
|
||||
h83002.c: Hitachi H8/3002 microcontroller emulator
|
||||
|
||||
Original by The_Author & DynaChicken for the ZiNc emulator.
|
||||
MAME changes by R. Belmont, Luca Elia, and Tomasz Slanina.
|
||||
|
||||
TS 20060412 Added exts.l, sub.l, divxs.w (buggy), jsr @reg, rotxl.l reg, mov.l @(adr, reg), reg
|
||||
LE 20070903 Added divxu.b shal.l extu.w dec.l #Imm,Rd subx.b
|
||||
LE 20080202 Separated 3002/3044/3007, Added or.l shal.l rotl.l not.l neg.l exts.w
|
||||
sub/or/xor.l #Imm:32,ERd bset/bnot/bclr.b Rn,@ERd bst/bist.b #Imm:3,@ERd bnot.b #Imm:3,@ERd
|
||||
LE 20090128 Added mov.l ers,@aa:16; bild #xx:3,rd; eepmov.b; bnot #xx:3,@aa:8
|
||||
|
||||
mame2003-plus: backported from the legacy H8/3xx core of MAME 0.152
|
||||
(h8_16.c, h8ops.h, h8periph.c) to the MAME 0.78 CPU interface.
|
||||
Only the H8/3002 model is kept. The on-chip RAM and peripheral
|
||||
registers are handled inside the core, the on-chip I/O ports are
|
||||
routed to the driver through h8_3002_set_io_handlers().
|
||||
|
||||
This core keeps a single global context: get/set_context are no-ops,
|
||||
so only one H8/3002 can exist in a machine (System 12 uses one).
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "cpuintrf.h"
|
||||
#include "memory.h"
|
||||
#include "mamedbg.h"
|
||||
#include "state.h"
|
||||
#include "timer.h"
|
||||
#include "mame.h"
|
||||
#include "driver.h"
|
||||
#include "h83002.h"
|
||||
|
||||
/* H8_LOG((fmt, ...)): debug log, compiled out */
|
||||
#define H8_LOG(x) do { } while (0)
|
||||
|
||||
#define H8_SP (7)
|
||||
|
||||
/* on-chip resources of the H8/3002 */
|
||||
#define H8_IRAM_START 0xfffd10
|
||||
#define H8_IRAM_END 0xffff0f
|
||||
#define H8_REG_START 0xffff10
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* main CPU stuff */
|
||||
UINT32 h8err;
|
||||
UINT32 regs[8];
|
||||
UINT32 pc, ppc;
|
||||
|
||||
UINT32 irq_req[3];
|
||||
|
||||
UINT8 ccr, exr;
|
||||
UINT8 h8nflag, h8vflag, h8cflag, h8zflag, h8iflag, h8hflag;
|
||||
UINT8 h8uflag, h8uiflag;
|
||||
UINT8 incheckirqs;
|
||||
|
||||
UINT8 has_exr;
|
||||
int mode_8bit;
|
||||
|
||||
int (*irq_cb)(int irqline);
|
||||
|
||||
/* onboard peripherals stuff */
|
||||
UINT8 per_regs[0x100];
|
||||
UINT8 iram[H8_IRAM_END - H8_IRAM_START + 1];
|
||||
|
||||
UINT16 h8TCNT[5];
|
||||
UINT8 h8TSTR;
|
||||
|
||||
mame_timer *timer[5];
|
||||
int timer_running[5]; /* timer[] armed (not TIME_NEVER / disabled) */
|
||||
UINT16 tcnt_start[5]; /* TCNT when the timer was last armed */
|
||||
double tcnt_offset[5]; /* time counted before the timer was last armed by a state load */
|
||||
double save_left[5], save_elapsed[5]; /* saved timer state (time left < 0: not armed) */
|
||||
int clock;
|
||||
} h83xx_state;
|
||||
|
||||
static h83xx_state h8state;
|
||||
|
||||
/* cycles left in the timeslice: cpuexec reads and adjusts it (abort,
|
||||
cycles run), so the core counts down this very variable */
|
||||
int h8_3002_ICount;
|
||||
|
||||
static h8_io_read_func h8_io_read = NULL;
|
||||
static h8_io_write_func h8_io_write = NULL;
|
||||
|
||||
void h8_3002_set_io_handlers(h8_io_read_func readfn, h8_io_write_func writefn)
|
||||
{
|
||||
h8_io_read = readfn;
|
||||
h8_io_write = writefn;
|
||||
}
|
||||
|
||||
static data8_t h8_io_read_byte(int port)
|
||||
{
|
||||
return h8_io_read ? h8_io_read(port) : 0;
|
||||
}
|
||||
|
||||
static void h8_io_write_byte(int port, data8_t data)
|
||||
{
|
||||
if (h8_io_write)
|
||||
h8_io_write(port, data);
|
||||
}
|
||||
|
||||
static UINT8 h8_register_read8(h83xx_state *h8, UINT32 address);
|
||||
static void h8_register_write8(h83xx_state *h8, UINT32 address, UINT8 val);
|
||||
void h8_3002_InterruptRequest(h83xx_state *h8, UINT8 source, UINT8 state);
|
||||
|
||||
/***************************************************************************
|
||||
memory access (external bus via the 0.78 memory system, on-chip
|
||||
RAM/registers handled here)
|
||||
***************************************************************************/
|
||||
|
||||
static UINT8 h8_read8(h83xx_state *h8, UINT32 address)
|
||||
{
|
||||
address &= 0xffffff;
|
||||
if (address >= H8_IRAM_START)
|
||||
{
|
||||
if (address <= H8_IRAM_END)
|
||||
return h8->iram[address - H8_IRAM_START];
|
||||
return h8_register_read8(h8, address);
|
||||
}
|
||||
return cpu_readmem24bew(address);
|
||||
}
|
||||
|
||||
static void h8_write8(h83xx_state *h8, UINT32 address, UINT8 data)
|
||||
{
|
||||
address &= 0xffffff;
|
||||
if (address >= H8_IRAM_START)
|
||||
{
|
||||
if (address <= H8_IRAM_END)
|
||||
h8->iram[address - H8_IRAM_START] = data;
|
||||
else
|
||||
h8_register_write8(h8, address, data);
|
||||
return;
|
||||
}
|
||||
cpu_writemem24bew(address, data);
|
||||
}
|
||||
|
||||
static UINT16 h8_read16(h83xx_state *h8, UINT32 address)
|
||||
{
|
||||
address &= 0xfffffe;
|
||||
if (address >= H8_IRAM_START)
|
||||
return (h8_read8(h8, address) << 8) | h8_read8(h8, address + 1);
|
||||
return cpu_readmem24bew_word(address);
|
||||
}
|
||||
|
||||
static void h8_write16(h83xx_state *h8, UINT32 address, UINT16 data)
|
||||
{
|
||||
address &= 0xfffffe;
|
||||
if (address >= H8_IRAM_START)
|
||||
{
|
||||
h8_write8(h8, address, data >> 8);
|
||||
h8_write8(h8, address + 1, data & 0xff);
|
||||
return;
|
||||
}
|
||||
cpu_writemem24bew_word(address, data);
|
||||
}
|
||||
|
||||
static UINT16 h8_readop16(h83xx_state *h8, UINT32 address)
|
||||
{
|
||||
address &= 0xfffffe;
|
||||
if (address >= H8_IRAM_START)
|
||||
return h8_read16(h8, address);
|
||||
return cpu_readop16(address);
|
||||
}
|
||||
|
||||
#define h8_mem_read8(x) h8_read8(h8, x)
|
||||
#define h8_mem_read16(z, x) h8_read16(h8, x)
|
||||
#define h8_mem_write8(x, y) h8_write8(h8, x, y)
|
||||
#define h8_mem_write16(z, x, y) h8_write16(h8, x, y)
|
||||
|
||||
/* timing macros
|
||||
note: we assume a system 12 - type setup where external access is 3+1 states
|
||||
timing will be off somewhat for other configurations. */
|
||||
#define H8_IFETCH_TIMING(x) h8_3002_ICount -= (x) * 4;
|
||||
#define H8_BRANCH_TIMING(x) h8_3002_ICount -= (x) * 4;
|
||||
#define H8_STACK_TIMING(x) h8_3002_ICount -= (x) * 4;
|
||||
#define H8_BYTE_TIMING(x, adr) if (address24 >= 0xffff10) h8_3002_ICount -= (x) * 3; else h8_3002_ICount -= (x) * 4;
|
||||
#define H8_WORD_TIMING(x, adr) if (address24 >= 0xffff10) h8_3002_ICount -= (x) * 3; else h8_3002_ICount -= (x) * 4;
|
||||
#define H8_IOP_TIMING(x) h8_3002_ICount -= (x);
|
||||
|
||||
static UINT32 h8_mem_read32(h83xx_state *h8, UINT32 address)
|
||||
{
|
||||
UINT32 result = h8_read16(h8, address) << 16;
|
||||
return result | h8_read16(h8, address + 2);
|
||||
}
|
||||
|
||||
static void h8_mem_write32(h83xx_state *h8, UINT32 address, UINT32 data)
|
||||
{
|
||||
h8_write16(h8, address, data >> 16);
|
||||
h8_write16(h8, address + 2, data);
|
||||
}
|
||||
|
||||
static void h8_check_irqs(h83xx_state *h8);
|
||||
|
||||
/***************************************************************************
|
||||
implementation
|
||||
***************************************************************************/
|
||||
|
||||
void h8_3002_InterruptRequest(h83xx_state *h8, UINT8 source, UINT8 state)
|
||||
{
|
||||
int request = source / 32;
|
||||
int bit = source % 32;
|
||||
|
||||
/* don't allow clear on external interrupts */
|
||||
if ((source <= 17) && (state == 0)) return;
|
||||
|
||||
if (state)
|
||||
h8->irq_req[request] |= (1<<bit);
|
||||
else
|
||||
h8->irq_req[request] &= ~(1<<bit);
|
||||
}
|
||||
|
||||
static UINT8 h8_get_ccr(h83xx_state *h8)
|
||||
{
|
||||
h8->ccr = 0;
|
||||
if(h8->h8nflag)h8->ccr |= H8_NFLAG;
|
||||
if(h8->h8zflag)h8->ccr |= H8_ZFLAG;
|
||||
if(h8->h8vflag)h8->ccr |= H8_VFLAG;
|
||||
if(h8->h8cflag)h8->ccr |= H8_CFLAG;
|
||||
if(h8->h8uflag)h8->ccr |= H8_UFLAG;
|
||||
if(h8->h8hflag)h8->ccr |= H8_HFLAG;
|
||||
if(h8->h8uiflag)h8->ccr |= H8_UIFLAG;
|
||||
if(h8->h8iflag)h8->ccr |= H8_IFLAG;
|
||||
return h8->ccr;
|
||||
}
|
||||
|
||||
static UINT8 h8_get_exr(h83xx_state *h8)
|
||||
{
|
||||
return h8->exr;
|
||||
}
|
||||
|
||||
/* CCR into the flag bytes, without taking interrupts */
|
||||
static void h8_unpack_ccr(h83xx_state *h8, UINT8 data)
|
||||
{
|
||||
h8->ccr = data;
|
||||
|
||||
h8->h8nflag = (data & H8_NFLAG) ? 1 : 0;
|
||||
h8->h8zflag = (data & H8_ZFLAG) ? 1 : 0;
|
||||
h8->h8vflag = (data & H8_VFLAG) ? 1 : 0;
|
||||
h8->h8cflag = (data & H8_CFLAG) ? 1 : 0;
|
||||
h8->h8hflag = (data & H8_HFLAG) ? 1 : 0;
|
||||
h8->h8iflag = (data & H8_IFLAG) ? 1 : 0;
|
||||
h8->h8uflag = (data & H8_UFLAG) ? 1 : 0;
|
||||
h8->h8uiflag = (data & H8_UIFLAG) ? 1 : 0;
|
||||
}
|
||||
|
||||
static void h8_set_ccr(h83xx_state *h8, UINT8 data)
|
||||
{
|
||||
h8_unpack_ccr(h8, data);
|
||||
|
||||
if (!h8->incheckirqs) h8_check_irqs(h8);
|
||||
}
|
||||
|
||||
static void h8_set_exr(h83xx_state *h8, UINT8 data)
|
||||
{
|
||||
h8->exr = data;
|
||||
}
|
||||
|
||||
/* register numbers come from opcode bits: keep them inside regs[] */
|
||||
static INT16 h8_getreg16(h83xx_state *h8, UINT8 reg)
|
||||
{
|
||||
reg &= 15;
|
||||
if(reg > 7)
|
||||
return h8->regs[reg-8]>>16;
|
||||
else
|
||||
return h8->regs[reg];
|
||||
}
|
||||
|
||||
static void h8_setreg16(h83xx_state *h8, UINT8 reg, UINT16 data)
|
||||
{
|
||||
reg &= 15;
|
||||
if(reg > 7)
|
||||
{
|
||||
h8->regs[reg-8] &= 0xffff;
|
||||
h8->regs[reg-8] |= data<<16;
|
||||
}
|
||||
else
|
||||
{
|
||||
h8->regs[reg] &= 0xffff0000;
|
||||
h8->regs[reg] |= data;
|
||||
}
|
||||
}
|
||||
|
||||
static UINT8 h8_getreg8(h83xx_state *h8, UINT8 reg)
|
||||
{
|
||||
reg &= 15;
|
||||
if(reg > 7)
|
||||
return h8->regs[reg-8];
|
||||
else
|
||||
return h8->regs[reg]>>8;
|
||||
}
|
||||
|
||||
static void h8_setreg8(h83xx_state *h8, UINT8 reg, UINT8 data)
|
||||
{
|
||||
reg &= 15;
|
||||
if(reg > 7)
|
||||
{
|
||||
h8->regs[reg-8] &= 0xffffff00;
|
||||
h8->regs[reg-8] |= data;
|
||||
}
|
||||
else
|
||||
{
|
||||
h8->regs[reg] &= 0xffff00ff;
|
||||
h8->regs[reg] |= data<<8;
|
||||
}
|
||||
}
|
||||
|
||||
static UINT32 h8_getreg32(h83xx_state *h8, UINT8 reg)
|
||||
{
|
||||
return h8->regs[reg & 7];
|
||||
}
|
||||
|
||||
static void h8_setreg32(h83xx_state *h8, UINT8 reg, UINT32 data)
|
||||
{
|
||||
h8->regs[reg & 7] = data;
|
||||
}
|
||||
|
||||
static void h8_GenException(h83xx_state *h8, UINT8 vectornr)
|
||||
{
|
||||
/* push PC on stack (extended mode stack push!) */
|
||||
h8_setreg32(h8, H8_SP, h8_getreg32(h8, H8_SP)-4);
|
||||
h8_mem_write32(h8, h8_getreg32(h8, H8_SP), h8->pc | (h8_get_ccr(h8)<<24));
|
||||
|
||||
/* generate address from vector */
|
||||
h8_set_ccr(h8, h8_get_ccr(h8) | 0x80);
|
||||
if (h8->h8uiflag == 0)
|
||||
h8_set_ccr(h8, h8_get_ccr(h8) | 0x40);
|
||||
h8->pc = h8_mem_read32(h8, vectornr * 4) & 0xffffff;
|
||||
|
||||
/* I couldn't find timing info for exceptions, so this is a guess (based on JSR/BSR) */
|
||||
H8_IFETCH_TIMING(2);
|
||||
H8_STACK_TIMING(2);
|
||||
}
|
||||
|
||||
static int h8_get_priority(h83xx_state *h8, UINT8 bit)
|
||||
{
|
||||
int res = 0;
|
||||
switch(bit)
|
||||
{
|
||||
case 12: /* IRQ0 */
|
||||
if (h8->per_regs[0xF8]&0x80) res = 1;
|
||||
break;
|
||||
case 13: /* IRQ1 */
|
||||
if (h8->per_regs[0xF8]&0x40) res = 1;
|
||||
break;
|
||||
case 14: /* IRQ2 */
|
||||
case 15: /* IRQ3 */
|
||||
if (h8->per_regs[0xF8]&0x20) res = 1;
|
||||
break;
|
||||
case 16: /* IRQ4 */
|
||||
case 17: /* IRQ5 */
|
||||
if (h8->per_regs[0xF8]&0x10) res = 1;
|
||||
break;
|
||||
case 53: /* SCI0 Rx */
|
||||
if (!(h8->per_regs[0xB2]&0x40)) res = -2;
|
||||
else if (h8->per_regs[0xF9]&0x08) res = 1;
|
||||
break;
|
||||
case 54: /* SCI0 Tx Empty */
|
||||
if (!(h8->per_regs[0xB2]&0x80)) res = -2;
|
||||
else if (h8->per_regs[0xF9]&0x08) res = 1;
|
||||
break;
|
||||
case 55: /* SCI0 Tx End */
|
||||
if (!(h8->per_regs[0xB2]&0x04)) res = -2;
|
||||
else if (h8->per_regs[0xF9]&0x08) res = 1;
|
||||
break;
|
||||
case 57: /* SCI1 Rx */
|
||||
if (!(h8->per_regs[0xBA]&0x40)) res = -2;
|
||||
else if (h8->per_regs[0xF9]&0x04) res = 1;
|
||||
break;
|
||||
case 58: /* SCI1 Tx Empty */
|
||||
if (!(h8->per_regs[0xBA]&0x80)) res = -2;
|
||||
else if (h8->per_regs[0xF9]&0x04) res = 1;
|
||||
break;
|
||||
case 59: /* SCI1 Tx End */
|
||||
if (!(h8->per_regs[0xBA]&0x04)) res = -2;
|
||||
else if (h8->per_regs[0xF9]&0x04) res = 1;
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void h8_check_irqs(h83xx_state *h8)
|
||||
{
|
||||
int lv = -1;
|
||||
|
||||
h8->incheckirqs = 1;
|
||||
|
||||
if (h8->has_exr)
|
||||
{
|
||||
lv = (h8->exr & 7);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (h8->h8iflag == 0)
|
||||
{
|
||||
lv = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((h8->per_regs[0xF2]&0x08)/*SYSCR*/ == 0)
|
||||
{
|
||||
if (h8->h8uiflag == 0)
|
||||
lv = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* any interrupts wanted and can accept ? */
|
||||
if(((h8->irq_req[0] != 0) || (h8->irq_req[1]!= 0) || (h8->irq_req[2] != 0)) && (lv >= 0))
|
||||
{
|
||||
UINT8 bit, source;
|
||||
/* which one ? */
|
||||
for(bit = 0, source = 0xff; source == 0xff && bit < 32; bit++)
|
||||
{
|
||||
if( h8->irq_req[0] & (1<<bit) )
|
||||
{
|
||||
if (h8_get_priority(h8, bit) >= lv)
|
||||
{
|
||||
h8->irq_req[0] &= ~(1<<bit);
|
||||
source = bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(bit = 0; source == 0xff && bit < 32; bit++)
|
||||
{
|
||||
if( h8->irq_req[1] & (1<<bit) )
|
||||
{
|
||||
if (h8_get_priority(h8, bit + 32) >= lv)
|
||||
{
|
||||
h8->irq_req[1] &= ~(1<<bit);
|
||||
source = bit + 32;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(bit = 0; source == 0xff && bit < 32; bit++)
|
||||
{
|
||||
if( h8->irq_req[2] & (1<<bit) )
|
||||
{
|
||||
if (h8_get_priority(h8, bit + 64) >= lv)
|
||||
{
|
||||
h8->irq_req[2] &= ~(1<<bit);
|
||||
source = bit + 64;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* call the MAME callback if it's one of the 6 external IRQs */
|
||||
if (source >= 12 && source <= 17)
|
||||
{
|
||||
if (h8->irq_cb)
|
||||
(*h8->irq_cb)(source - 12 + H8_IRQ0);
|
||||
}
|
||||
|
||||
if (source != 0xff)
|
||||
h8_GenException(h8, source);
|
||||
}
|
||||
|
||||
h8->incheckirqs = 0;
|
||||
}
|
||||
|
||||
#define H8_ADDR_MASK 0xffffff
|
||||
static UINT32 h8_idle_start, h8_idle_end; /* polled memory (end 0 = off) */
|
||||
static UINT32 h8_idle_pc; /* loop start last reached */
|
||||
static int h8_idle_since; /* instructions since then */
|
||||
static int h8_idle_cycles; /* h8_3002_ICount then */
|
||||
|
||||
void h8_3002_set_idle_poll(UINT32 start, UINT32 end)
|
||||
{
|
||||
h8_idle_start = start;
|
||||
h8_idle_end = end;
|
||||
}
|
||||
|
||||
/* at "mov.b @aa:24, Rd": the start of a polling loop? skip passes */
|
||||
static void h8_idle_check(h83xx_state *h8)
|
||||
{
|
||||
UINT32 address = ((UINT32)h8_readop16(h8, h8->pc + 2) << 16) | h8_readop16(h8, h8->pc + 4);
|
||||
UINT16 branch = h8_readop16(h8, h8->pc + 6);
|
||||
|
||||
address &= 0xffffff;
|
||||
if (address < h8_idle_start || address > h8_idle_end || (branch != 0x46f8 && branch != 0x47f8))
|
||||
{
|
||||
h8_idle_since = -1;
|
||||
return;
|
||||
}
|
||||
/* one whole pass just ran: skip the passes that still fit */
|
||||
if (h8->pc == h8_idle_pc && h8_idle_since == 2)
|
||||
{
|
||||
int pass = h8_idle_cycles - h8_3002_ICount;
|
||||
if (pass > 0 && h8_3002_ICount > pass)
|
||||
h8_3002_ICount -= ((h8_3002_ICount - 1) / pass) * pass;
|
||||
}
|
||||
h8_idle_pc = h8->pc;
|
||||
h8_idle_since = 0;
|
||||
h8_idle_cycles = h8_3002_ICount;
|
||||
}
|
||||
|
||||
#include "h8ops.h"
|
||||
|
||||
/***************************************************************************
|
||||
on-chip peripherals (ITU timers, ports, serial, ADC)
|
||||
***************************************************************************/
|
||||
|
||||
/* timer registers */
|
||||
#define TSTR (0x60)
|
||||
#define TIER0 (0x66)
|
||||
#define TIER1 (0x70)
|
||||
#define TIER2 (0x7a)
|
||||
#define TIER3 (0x84)
|
||||
#define TIER4 (0x94)
|
||||
#define TSR0 (0x67)
|
||||
#define TSR1 (0x71)
|
||||
#define TSR2 (0x7b)
|
||||
#define TSR3 (0x85)
|
||||
#define TSR4 (0x95)
|
||||
#define TCR0 (0x64)
|
||||
#define TCR1 (0x6e)
|
||||
#define TCR2 (0x78)
|
||||
#define TCR3 (0x82)
|
||||
#define TCR4 (0x92)
|
||||
|
||||
static const UINT8 tsr[5] = { TSR0, TSR1, TSR2, TSR3, TSR4 };
|
||||
static const UINT8 tier[5] = { TIER0, TIER1, TIER2, TIER3, TIER4 };
|
||||
static const UINT8 tcr[5] = { TCR0, TCR1, TCR2, TCR3, TCR4 };
|
||||
static const int tscales[4] = { 1, 2, 4, 8 };
|
||||
|
||||
static void h8itu_timer_expire(int which)
|
||||
{
|
||||
h83xx_state *h8 = &h8state;
|
||||
|
||||
timer_adjust(h8->timer[which], TIME_NEVER, 0, 0);
|
||||
h8->timer_running[which] = 0;
|
||||
h8->tcnt_offset[which] = 0;
|
||||
h8->tcnt_start[which] = 0;
|
||||
h8->h8TCNT[which] = 0;
|
||||
h8->per_regs[tsr[which]] |= 4;
|
||||
/* interrupt on overflow ? */
|
||||
if(h8->per_regs[tier[which]] & 4)
|
||||
{
|
||||
h8_3002_InterruptRequest(h8, 26 + 4*which, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void h8_itu_refresh_timer(h83xx_state *h8, int tnum)
|
||||
{
|
||||
int ourTCR = h8->per_regs[tcr[tnum]];
|
||||
int ourTVAL = h8->h8TCNT[tnum];
|
||||
double period;
|
||||
|
||||
period = TIME_IN_HZ(h8->clock) * tscales[ourTCR & 3] * (65536 - ourTVAL);
|
||||
|
||||
if (ourTCR & 4)
|
||||
H8_LOG(("H8/3002: Timer %d is using an external clock. Unsupported!\n", tnum));
|
||||
|
||||
timer_adjust(h8->timer[tnum], period, tnum, 0);
|
||||
h8->timer_running[tnum] = 1;
|
||||
h8->tcnt_start[tnum] = ourTVAL;
|
||||
h8->tcnt_offset[tnum] = 0;
|
||||
}
|
||||
|
||||
static void h8_itu_sync_timers(h83xx_state *h8, int tnum)
|
||||
{
|
||||
int ourTCR = h8->per_regs[tcr[tnum]];
|
||||
double cycle_time, cur;
|
||||
|
||||
/* get the time per unit */
|
||||
cycle_time = TIME_IN_HZ(h8->clock) * tscales[ourTCR & 3];
|
||||
cur = timer_timeelapsed(h8->timer[tnum]) + h8->tcnt_offset[tnum];
|
||||
|
||||
/* counted from the TCNT value the timer was armed with */
|
||||
h8->h8TCNT[tnum] = (UINT16)(h8->tcnt_start[tnum] + (UINT32)(cur / cycle_time));
|
||||
}
|
||||
|
||||
static UINT8 h8_itu_read8(h83xx_state *h8, UINT8 reg)
|
||||
{
|
||||
switch(reg)
|
||||
{
|
||||
case 0x60: return h8->h8TSTR;
|
||||
case 0x68: h8_itu_sync_timers(h8, 0); return h8->h8TCNT[0]>>8;
|
||||
case 0x69: h8_itu_sync_timers(h8, 0); return h8->h8TCNT[0]&0xff;
|
||||
case 0x72: h8_itu_sync_timers(h8, 1); return h8->h8TCNT[1]>>8;
|
||||
case 0x73: h8_itu_sync_timers(h8, 1); return h8->h8TCNT[1]&0xff;
|
||||
case 0x7c: h8_itu_sync_timers(h8, 2); return h8->h8TCNT[2]>>8;
|
||||
case 0x7d: h8_itu_sync_timers(h8, 2); return h8->h8TCNT[2]&0xff;
|
||||
case 0x86: h8_itu_sync_timers(h8, 3); return h8->h8TCNT[3]>>8;
|
||||
case 0x87: h8_itu_sync_timers(h8, 3); return h8->h8TCNT[3]&0xff;
|
||||
default: return h8->per_regs[reg];
|
||||
}
|
||||
}
|
||||
|
||||
static void h8_itu_write8(h83xx_state *h8, UINT8 reg, UINT8 val)
|
||||
{
|
||||
int t;
|
||||
|
||||
h8->per_regs[reg] = val;
|
||||
switch(reg)
|
||||
{
|
||||
case 0x60:
|
||||
for (t = 0; t < 5; t++)
|
||||
if ((val & (1 << t)) && !(h8->h8TSTR & (1 << t)))
|
||||
h8_itu_refresh_timer(h8, t);
|
||||
h8->h8TSTR = val;
|
||||
break;
|
||||
case 0x68: h8->h8TCNT[0] = (val<<8) | (h8->h8TCNT[0] & 0xff); if (h8->h8TSTR & 0x01) h8_itu_refresh_timer(h8, 0); break;
|
||||
case 0x69: h8->h8TCNT[0] = (val) | (h8->h8TCNT[0] & 0xff00); if (h8->h8TSTR & 0x01) h8_itu_refresh_timer(h8, 0); break;
|
||||
case 0x72: h8->h8TCNT[1] = (val<<8) | (h8->h8TCNT[1] & 0xff); if (h8->h8TSTR & 0x02) h8_itu_refresh_timer(h8, 1); break;
|
||||
case 0x73: h8->h8TCNT[1] = (val) | (h8->h8TCNT[1] & 0xff00); if (h8->h8TSTR & 0x02) h8_itu_refresh_timer(h8, 1); break;
|
||||
case 0x7c: h8->h8TCNT[2] = (val<<8) | (h8->h8TCNT[2] & 0xff); if (h8->h8TSTR & 0x04) h8_itu_refresh_timer(h8, 2); break;
|
||||
case 0x7d: h8->h8TCNT[2] = (val) | (h8->h8TCNT[2] & 0xff00); if (h8->h8TSTR & 0x04) h8_itu_refresh_timer(h8, 2); break;
|
||||
case 0x86: h8->h8TCNT[3] = (val<<8) | (h8->h8TCNT[3] & 0xff); if (h8->h8TSTR & 0x08) h8_itu_refresh_timer(h8, 3); break;
|
||||
case 0x87: h8->h8TCNT[3] = (val) | (h8->h8TCNT[3] & 0xff00); if (h8->h8TSTR & 0x08) h8_itu_refresh_timer(h8, 3); break;
|
||||
case 0x96: h8->h8TCNT[4] = (val<<8) | (h8->h8TCNT[4] & 0xff); if (h8->h8TSTR & 0x10) h8_itu_refresh_timer(h8, 4); break;
|
||||
case 0x97: h8->h8TCNT[4] = (val) | (h8->h8TCNT[4] & 0xff00); if (h8->h8TSTR & 0x10) h8_itu_refresh_timer(h8, 4); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
static UINT8 h8_ISR_r(h83xx_state *h8)
|
||||
{
|
||||
UINT8 res = 0;
|
||||
int i;
|
||||
for (i = 0; i < 6; i++)
|
||||
if (h8->irq_req[0] & (1 << (12+i))) res |= (1 << i);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void h8_ISR_w(h83xx_state *h8, UINT8 val)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 6; i++)
|
||||
if ((~val) & (1 << i)) h8->irq_req[0] &= ~(1 << (12+i));
|
||||
}
|
||||
|
||||
static UINT8 h8_register_read8(h83xx_state *h8, UINT32 address)
|
||||
{
|
||||
UINT8 val;
|
||||
UINT8 reg = address & 0xff;
|
||||
|
||||
if(reg >= 0x60 && reg <= 0x9f)
|
||||
return h8_itu_read8(h8, reg);
|
||||
|
||||
switch(reg)
|
||||
{
|
||||
case 0xb4: /* serial port A status */
|
||||
val = h8->per_regs[reg];
|
||||
val |= 0xc4; /* transmit finished, receive ready, no errors */
|
||||
break;
|
||||
case 0xb5: val = h8_io_read_byte(H8_SERIAL_0); break; /* serial port A receive */
|
||||
case 0xbc: /* serial port B status */
|
||||
val = h8->per_regs[reg];
|
||||
val |= 0xc4; /* transmit finished, receive ready, no errors */
|
||||
break;
|
||||
case 0xbd: val = h8_io_read_byte(H8_SERIAL_1); break; /* serial port B receive */
|
||||
case 0xe0: val = h8_io_read_byte(H8_ADC_0_H); break;
|
||||
case 0xe1: val = h8_io_read_byte(H8_ADC_0_L); break;
|
||||
case 0xe2: val = h8_io_read_byte(H8_ADC_1_H); break;
|
||||
case 0xe3: val = h8_io_read_byte(H8_ADC_1_L); break;
|
||||
case 0xe4: val = h8_io_read_byte(H8_ADC_2_H); break;
|
||||
case 0xe5: val = h8_io_read_byte(H8_ADC_2_L); break;
|
||||
case 0xe6: val = h8_io_read_byte(H8_ADC_3_H); break;
|
||||
case 0xe7: val = h8_io_read_byte(H8_ADC_3_L); break;
|
||||
case 0xe8: val = 0x80; break; /* adc status */
|
||||
case 0xc7: val = h8_io_read_byte(H8_PORT_4); break; /* port 4 data */
|
||||
case 0xcb: val = h8_io_read_byte(H8_PORT_6); break; /* port 6 data */
|
||||
case 0xce: val = h8_io_read_byte(H8_PORT_7); break; /* port 7 data */
|
||||
case 0xcf: val = h8_io_read_byte(H8_PORT_8); break; /* port 8 data */
|
||||
case 0xd2: val = h8_io_read_byte(H8_PORT_9); break; /* port 9 data */
|
||||
case 0xd3: val = h8_io_read_byte(H8_PORT_A); break; /* port a data */
|
||||
case 0xd6: val = h8_io_read_byte(H8_PORT_B); break; /* port b data */
|
||||
case 0xf6: val = h8_ISR_r(h8); break;
|
||||
default: val = h8->per_regs[reg]; break;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void h8_register_write8(h83xx_state *h8, UINT32 address, UINT8 val)
|
||||
{
|
||||
UINT8 reg = address & 0xff;
|
||||
|
||||
if(reg >= 0x60 && reg <= 0x9f)
|
||||
h8_itu_write8(h8, reg, val);
|
||||
|
||||
switch (reg)
|
||||
{
|
||||
case 0xb3: /* serial 0 send */
|
||||
h8_io_write_byte(H8_SERIAL_0, val);
|
||||
h8_3002_InterruptRequest(h8, 54, 1);
|
||||
h8_3002_InterruptRequest(h8, 55, 1);
|
||||
break;
|
||||
case 0xbb: /* serial 1 send */
|
||||
h8_io_write_byte(H8_SERIAL_1, val);
|
||||
h8_3002_InterruptRequest(h8, 58, 1);
|
||||
h8_3002_InterruptRequest(h8, 59, 1);
|
||||
break;
|
||||
case 0xc7: h8_io_write_byte(H8_PORT_4, val); break;
|
||||
case 0xcb: h8_io_write_byte(H8_PORT_6, val); break;
|
||||
case 0xce: h8_io_write_byte(H8_PORT_7, val); break;
|
||||
case 0xcf: h8_io_write_byte(H8_PORT_8, val); break;
|
||||
case 0xd2: h8_io_write_byte(H8_PORT_9, val); break;
|
||||
case 0xd3: h8_io_write_byte(H8_PORT_A, val); break;
|
||||
case 0xd6: h8_io_write_byte(H8_PORT_B, val); break;
|
||||
case 0xf6: h8_ISR_w(h8, val); break;
|
||||
}
|
||||
|
||||
h8->per_regs[reg] = val;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
MAME 0.78 interface
|
||||
***************************************************************************/
|
||||
|
||||
/* the ITU timers are MAME timers, which a state does not hold: save how
|
||||
long each one has run and how long it has left, and re-arm them on load */
|
||||
static void h8_onstatesave(void)
|
||||
{
|
||||
h83xx_state *h8 = &h8state;
|
||||
int i;
|
||||
|
||||
/* the live flags are the flag bytes: ccr holds them in the state */
|
||||
h8_get_ccr(h8);
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
h8->save_left[i] = h8->timer_running[i] ? timer_timeleft(h8->timer[i]) : -1;
|
||||
h8->save_elapsed[i] = timer_timeelapsed(h8->timer[i]) + h8->tcnt_offset[i];
|
||||
}
|
||||
}
|
||||
|
||||
static void h8_onstateload(void)
|
||||
{
|
||||
h83xx_state *h8 = &h8state;
|
||||
int i;
|
||||
|
||||
/* flags only: a load must not take an interrupt */
|
||||
h8_unpack_ccr(h8, h8->ccr);
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
if (h8->save_left[i] >= 0)
|
||||
{
|
||||
timer_adjust(h8->timer[i], h8->save_left[i], i, 0);
|
||||
h8->timer_running[i] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
timer_adjust(h8->timer[i], TIME_NEVER, 0, 0);
|
||||
timer_enable(h8->timer[i], 0);
|
||||
h8->timer_running[i] = 0;
|
||||
}
|
||||
h8->tcnt_offset[i] = h8->save_elapsed[i];
|
||||
}
|
||||
}
|
||||
|
||||
void h8_3002_init(void)
|
||||
{
|
||||
h83xx_state *h8 = &h8state;
|
||||
int cpu = cpu_getactivecpu();
|
||||
int i;
|
||||
|
||||
memset(h8, 0, sizeof(*h8));
|
||||
h8->h8iflag = 1;
|
||||
h8->mode_8bit = 0;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
h8->timer[i] = timer_alloc(h8itu_timer_expire);
|
||||
|
||||
state_save_register_UINT32("h8_3002", cpu, "h8err", &h8->h8err, 1);
|
||||
state_save_register_UINT32("h8_3002", cpu, "regs", h8->regs, 8);
|
||||
state_save_register_UINT32("h8_3002", cpu, "pc", &h8->pc, 1);
|
||||
state_save_register_UINT32("h8_3002", cpu, "ppc", &h8->ppc, 1);
|
||||
state_save_register_UINT32("h8_3002", cpu, "irq_req", h8->irq_req, 3);
|
||||
state_save_register_UINT8 ("h8_3002", cpu, "ccr", &h8->ccr, 1);
|
||||
state_save_register_UINT8 ("h8_3002", cpu, "per_regs", h8->per_regs, 0x100);
|
||||
state_save_register_UINT8 ("h8_3002", cpu, "iram", h8->iram, sizeof(h8->iram));
|
||||
state_save_register_UINT8 ("h8_3002", cpu, "h8TSTR", &h8->h8TSTR, 1);
|
||||
state_save_register_UINT16("h8_3002", cpu, "h8TCNT", h8->h8TCNT, 5);
|
||||
state_save_register_UINT16("h8_3002", cpu, "tcnt_start", h8->tcnt_start, 5);
|
||||
state_save_register_double("h8_3002", cpu, "timer_left", h8->save_left, 5);
|
||||
state_save_register_double("h8_3002", cpu, "timer_elapsed", h8->save_elapsed, 5);
|
||||
state_save_register_func_presave(h8_onstatesave);
|
||||
state_save_register_func_postload(h8_onstateload);
|
||||
}
|
||||
|
||||
void h8_3002_reset(void *param)
|
||||
{
|
||||
h83xx_state *h8 = &h8state;
|
||||
int i;
|
||||
|
||||
h8->clock = Machine->drv->cpu[cpu_getactivecpu()].cpu_clock;
|
||||
|
||||
h8->h8err = 0;
|
||||
memset(h8->regs, 0, sizeof(h8->regs));
|
||||
memset(h8->irq_req, 0, sizeof(h8->irq_req));
|
||||
memset(h8->per_regs, 0, sizeof(h8->per_regs));
|
||||
h8->incheckirqs = 0;
|
||||
h8->exr = 0;
|
||||
h8->has_exr = 0;
|
||||
h8_set_ccr(h8, H8_IFLAG);
|
||||
|
||||
h8->pc = h8_mem_read32(h8, 0) & 0xffffff;
|
||||
h8->ppc = h8->pc;
|
||||
|
||||
/* disable timers */
|
||||
h8->h8TSTR = 0;
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
h8->h8TCNT[i] = 0;
|
||||
timer_adjust(h8->timer[i], TIME_NEVER, 0, 0);
|
||||
h8->timer_running[i] = 0;
|
||||
h8->tcnt_start[i] = 0;
|
||||
h8->tcnt_offset[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void h8_3002_exit(void)
|
||||
{
|
||||
h8_idle_end = 0;
|
||||
}
|
||||
|
||||
/* single instance (one H8/3002 per machine): the state lives in h8state,
|
||||
contexts are not swapped */
|
||||
unsigned h8_3002_get_context(void *dst)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void h8_3002_set_context(void *src)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned h8_3002_get_reg(int regnum)
|
||||
{
|
||||
h83xx_state *h8 = &h8state;
|
||||
|
||||
switch (regnum)
|
||||
{
|
||||
case REG_PC:
|
||||
case H8_PC: return h8->pc;
|
||||
case REG_PREVIOUSPC: return h8->ppc;
|
||||
case REG_SP: return h8->regs[7];
|
||||
case H8_CCR: return h8_get_ccr(h8);
|
||||
case H8_E0: case H8_E1: case H8_E2: case H8_E3:
|
||||
case H8_E4: case H8_E5: case H8_E6: case H8_E7:
|
||||
return h8->regs[regnum - H8_E0];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void h8_3002_set_reg(int regnum, unsigned val)
|
||||
{
|
||||
h83xx_state *h8 = &h8state;
|
||||
|
||||
switch (regnum)
|
||||
{
|
||||
case REG_PC:
|
||||
case H8_PC: h8->pc = val & 0xffffff; break;
|
||||
case REG_SP: h8->regs[7] = val; break;
|
||||
case H8_CCR: h8_set_ccr(h8, val); break;
|
||||
case H8_E0: case H8_E1: case H8_E2: case H8_E3:
|
||||
case H8_E4: case H8_E5: case H8_E6: case H8_E7:
|
||||
h8->regs[regnum - H8_E0] = val; break;
|
||||
}
|
||||
}
|
||||
|
||||
void h8_3002_set_irq_line(int irqline, int state)
|
||||
{
|
||||
h83xx_state *h8 = &h8state;
|
||||
int asserted = (state != CLEAR_LINE && state != INTERNAL_CLEAR_LINE);
|
||||
|
||||
switch (irqline)
|
||||
{
|
||||
case H8_IRQ0: case H8_IRQ1: case H8_IRQ2:
|
||||
case H8_IRQ3: case H8_IRQ4: case H8_IRQ5:
|
||||
h8_3002_InterruptRequest(h8, 12 + irqline - H8_IRQ0, asserted);
|
||||
break;
|
||||
case H8_SCI_0_RX: h8_3002_InterruptRequest(h8, 53, asserted); break;
|
||||
case H8_SCI_1_RX: h8_3002_InterruptRequest(h8, 57, asserted); break;
|
||||
}
|
||||
}
|
||||
|
||||
void h8_3002_set_irq_callback(int (*callback)(int irqline))
|
||||
{
|
||||
h8state.irq_cb = callback;
|
||||
}
|
||||
|
||||
const char *h8_3002_info(void *context, int regnum)
|
||||
{
|
||||
static char buffer[16][47+1];
|
||||
static int which = 0;
|
||||
h83xx_state *h8 = &h8state;
|
||||
|
||||
which = (which+1) % 16;
|
||||
buffer[which][0] = '\0';
|
||||
|
||||
switch (regnum)
|
||||
{
|
||||
case CPU_INFO_REG+H8_PC: sprintf(buffer[which], "PC :%06X", h8->pc); break;
|
||||
case CPU_INFO_REG+H8_CCR: sprintf(buffer[which], "CCR :%02X", h8_get_ccr(h8)); break;
|
||||
case CPU_INFO_REG+H8_E0: sprintf(buffer[which], "ER0 :%08X", h8->regs[0]); break;
|
||||
case CPU_INFO_REG+H8_E1: sprintf(buffer[which], "ER1 :%08X", h8->regs[1]); break;
|
||||
case CPU_INFO_REG+H8_E2: sprintf(buffer[which], "ER2 :%08X", h8->regs[2]); break;
|
||||
case CPU_INFO_REG+H8_E3: sprintf(buffer[which], "ER3 :%08X", h8->regs[3]); break;
|
||||
case CPU_INFO_REG+H8_E4: sprintf(buffer[which], "ER4 :%08X", h8->regs[4]); break;
|
||||
case CPU_INFO_REG+H8_E5: sprintf(buffer[which], "ER5 :%08X", h8->regs[5]); break;
|
||||
case CPU_INFO_REG+H8_E6: sprintf(buffer[which], "ER6 :%08X", h8->regs[6]); break;
|
||||
case CPU_INFO_REG+H8_E7: sprintf(buffer[which], " SP :%08X", h8->regs[7]); break;
|
||||
case CPU_INFO_FLAGS:
|
||||
sprintf(buffer[which], "%c%c%c%c%c%c%c%c",
|
||||
h8->h8iflag ? 'I':'i', h8->h8uiflag ? 'U':'u',
|
||||
h8->h8hflag ? 'H':'h', h8->h8uflag ? 'U':'u',
|
||||
h8->h8nflag ? 'N':'n', h8->h8zflag ? 'Z':'z',
|
||||
h8->h8vflag ? 'V':'v', h8->h8cflag ? 'C':'c');
|
||||
break;
|
||||
case CPU_INFO_NAME: return "H8/3002";
|
||||
case CPU_INFO_FAMILY: return "Hitachi H8/300";
|
||||
case CPU_INFO_VERSION: return "1.0";
|
||||
case CPU_INFO_FILE: return __FILE__;
|
||||
case CPU_INFO_CREDITS: return "The_Author & DynaChicken (ZiNc), R. Belmont, Luca Elia, Tomasz Slanina";
|
||||
}
|
||||
return buffer[which];
|
||||
}
|
||||
|
||||
unsigned h8_3002_dasm(char *buffer, unsigned pc)
|
||||
{
|
||||
sprintf(buffer, "$%04X", h8_read16(&h8state, pc));
|
||||
return 2;
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/***************************************************************************
|
||||
|
||||
h83002.h : Public constants and function defs for the H8/3002 emulator.
|
||||
|
||||
Backported to the MAME 0.78 CPU interface (mame2003-plus) from the legacy
|
||||
H8/3xx core of MAME 0.152 (original by The_Author & DynaChicken for ZiNc,
|
||||
MAME changes by R. Belmont, Luca Elia, Tomasz Slanina, Tim Schuerewegen,
|
||||
O. Galibert).
|
||||
|
||||
Only the H8/3002 (16-bit, advanced mode, 24-bit address space) is
|
||||
supported. On-chip RAM (0xfffd10-0xffff0f) and the on-chip peripheral
|
||||
registers (0xffff10-0xffffff) are handled inside the core.
|
||||
|
||||
The 0.78 I/O port space is sized after the data bus (16 bit), so the
|
||||
H8 on-chip ports, ADC and serial channels are routed to the driver
|
||||
through the callbacks below instead of a PORT map.
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _H83002_H_
|
||||
#define _H83002_H_
|
||||
|
||||
#include "osd_cpu.h"
|
||||
|
||||
#define H8_IFLAG 0x80
|
||||
#define H8_UIFLAG 0x40
|
||||
#define H8_HFLAG 0x20
|
||||
#define H8_UFLAG 0x10
|
||||
#define H8_NFLAG 0x08
|
||||
#define H8_ZFLAG 0x04
|
||||
#define H8_VFLAG 0x02
|
||||
#define H8_CFLAG 0x01
|
||||
|
||||
/* registers */
|
||||
enum
|
||||
{
|
||||
H8_E0 = 1,
|
||||
H8_E1,
|
||||
H8_E2,
|
||||
H8_E3,
|
||||
H8_E4,
|
||||
H8_E5,
|
||||
H8_E6,
|
||||
H8_E7,
|
||||
|
||||
H8_PC,
|
||||
H8_CCR
|
||||
};
|
||||
|
||||
/* external interrupt lines */
|
||||
enum
|
||||
{
|
||||
H8_IRQ0 = 0,
|
||||
H8_IRQ1,
|
||||
H8_IRQ2,
|
||||
H8_IRQ3,
|
||||
H8_IRQ4,
|
||||
H8_IRQ5,
|
||||
|
||||
H8_SCI_0_RX, /* incoming character on SCI 0 */
|
||||
H8_SCI_1_RX /* incoming character on SCI 1 */
|
||||
};
|
||||
|
||||
/* I/O "ports" passed to the driver callbacks */
|
||||
enum
|
||||
{
|
||||
/* digital I/O ports */
|
||||
H8_PORT_4 = 3,
|
||||
H8_PORT_6 = 5,
|
||||
H8_PORT_7,
|
||||
H8_PORT_8,
|
||||
H8_PORT_9,
|
||||
H8_PORT_A,
|
||||
H8_PORT_B,
|
||||
|
||||
/* analog inputs */
|
||||
H8_ADC_0_H = 0x20,
|
||||
H8_ADC_0_L,
|
||||
H8_ADC_1_H,
|
||||
H8_ADC_1_L,
|
||||
H8_ADC_2_H,
|
||||
H8_ADC_2_L,
|
||||
H8_ADC_3_H,
|
||||
H8_ADC_3_L,
|
||||
|
||||
/* serial ports */
|
||||
H8_SERIAL_0 = 0x30,
|
||||
H8_SERIAL_1
|
||||
};
|
||||
|
||||
typedef data8_t (*h8_io_read_func)(int port);
|
||||
typedef void (*h8_io_write_func)(int port, data8_t data);
|
||||
|
||||
/* hook the on-chip ports/ADC/serial to the driver (call before reset) */
|
||||
void h8_3002_set_io_handlers(h8_io_read_func readfn, h8_io_write_func writefn);
|
||||
/*
|
||||
Speedup (end 0 = off): memory in start-end only changes outside the
|
||||
H8's timeslice (other CPUs, the H8's own interrupts) and reading it has
|
||||
no side effects. A polling loop on it, "mov.b @aa:24, Rd / bne (or
|
||||
beq) back", leaves the same state on every pass, so once one pass has
|
||||
run in a timeslice the whole passes that still fit are skipped:
|
||||
registers, memory and cycles end up exactly as if they had run.
|
||||
*/
|
||||
void h8_3002_set_idle_poll(UINT32 start, UINT32 end);
|
||||
|
||||
extern int h8_3002_ICount;
|
||||
|
||||
void h8_3002_init(void);
|
||||
void h8_3002_reset(void *param);
|
||||
void h8_3002_exit(void);
|
||||
int h8_3002_execute(int cycles);
|
||||
unsigned h8_3002_get_context(void *dst);
|
||||
void h8_3002_set_context(void *src);
|
||||
unsigned h8_3002_get_reg(int regnum);
|
||||
void h8_3002_set_reg(int regnum, unsigned val);
|
||||
void h8_3002_set_irq_line(int irqline, int state);
|
||||
void h8_3002_set_irq_callback(int (*callback)(int irqline));
|
||||
const char *h8_3002_info(void *context, int regnum);
|
||||
unsigned h8_3002_dasm(char *buffer, unsigned pc);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -587,6 +587,8 @@ void hd6309_init(void)
|
||||
state_save_register_UINT16("hd6309", cpu, "X", &X, 1);
|
||||
state_save_register_UINT16("hd6309", cpu, "Y", &Y, 1);
|
||||
state_save_register_UINT16("hd6309", cpu, "V", &V, 1);
|
||||
state_save_register_UINT16("hd6309", cpu, "D", &D, 1); /* the accumulators A and B */
|
||||
state_save_register_UINT16("hd6309", cpu, "W", &W, 1); /* the accumulators E and F */
|
||||
state_save_register_UINT8("hd6309", cpu, "DP", &DP, 1);
|
||||
state_save_register_UINT8("hd6309", cpu, "CC", &CC, 1);
|
||||
state_save_register_UINT8("hd6309", cpu, "MD", &MD, 1);
|
||||
@@ -595,6 +597,7 @@ void hd6309_init(void)
|
||||
state_save_register_UINT8("hd6309", cpu, "NMI", &hd6309.nmi_state, 1);
|
||||
state_save_register_UINT8("hd6309", cpu, "IRQ", &hd6309.irq_state[0], 1);
|
||||
state_save_register_UINT8("hd6309", cpu, "FIRQ", &hd6309.irq_state[1], 1);
|
||||
state_save_register_int("hd6309", cpu, "extra_cycles", &hd6309.extra_cycles); /* the cycles of an interrupt taken outside the execute loop */
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
@@ -0,0 +1,674 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef __CYCLES_H__
|
||||
#define __CYCLES_H__
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CYCLES_MOV_REG_REG,
|
||||
CYCLES_MOV_REG_MEM,
|
||||
CYCLES_MOV_MEM_REG,
|
||||
CYCLES_MOV_IMM_REG,
|
||||
CYCLES_MOV_IMM_MEM,
|
||||
CYCLES_MOV_ACC_MEM,
|
||||
CYCLES_MOV_MEM_ACC,
|
||||
CYCLES_MOV_REG_SREG,
|
||||
CYCLES_MOV_MEM_SREG,
|
||||
CYCLES_MOV_SREG_REG,
|
||||
CYCLES_MOV_SREG_MEM,
|
||||
CYCLES_MOVSX_REG_REG,
|
||||
CYCLES_MOVSX_MEM_REG,
|
||||
CYCLES_MOVZX_REG_REG,
|
||||
CYCLES_MOVZX_MEM_REG,
|
||||
CYCLES_PUSH_RM,
|
||||
CYCLES_PUSH_REG_SHORT,
|
||||
CYCLES_PUSH_SREG,
|
||||
CYCLES_PUSH_IMM,
|
||||
CYCLES_PUSHA,
|
||||
CYCLES_POP_RM,
|
||||
CYCLES_POP_REG_SHORT,
|
||||
CYCLES_POP_SREG,
|
||||
CYCLES_POPA,
|
||||
CYCLES_XCHG_REG_REG,
|
||||
CYCLES_XCHG_REG_MEM,
|
||||
CYCLES_IN,
|
||||
CYCLES_IN_VAR,
|
||||
CYCLES_OUT,
|
||||
CYCLES_OUT_VAR,
|
||||
CYCLES_LEA,
|
||||
CYCLES_LDS,
|
||||
CYCLES_LES,
|
||||
CYCLES_LFS,
|
||||
CYCLES_LGS,
|
||||
CYCLES_LSS,
|
||||
CYCLES_CLC,
|
||||
CYCLES_CLD,
|
||||
CYCLES_CLI,
|
||||
CYCLES_CLTS,
|
||||
CYCLES_CMC,
|
||||
CYCLES_LAHF,
|
||||
CYCLES_POPF,
|
||||
CYCLES_PUSHF,
|
||||
CYCLES_SAHF,
|
||||
CYCLES_STC,
|
||||
CYCLES_STD,
|
||||
CYCLES_STI,
|
||||
CYCLES_ALU_REG_REG,
|
||||
CYCLES_ALU_REG_MEM,
|
||||
CYCLES_ALU_MEM_REG,
|
||||
CYCLES_ALU_IMM_REG,
|
||||
CYCLES_ALU_IMM_MEM,
|
||||
CYCLES_ALU_IMM_ACC,
|
||||
CYCLES_INC_REG,
|
||||
CYCLES_INC_MEM,
|
||||
CYCLES_DEC_REG,
|
||||
CYCLES_DEC_MEM,
|
||||
CYCLES_CMP_REG_REG,
|
||||
CYCLES_CMP_REG_MEM,
|
||||
CYCLES_CMP_MEM_REG,
|
||||
CYCLES_CMP_IMM_REG,
|
||||
CYCLES_CMP_IMM_MEM,
|
||||
CYCLES_CMP_IMM_ACC,
|
||||
CYCLES_TEST_REG_REG,
|
||||
CYCLES_TEST_REG_MEM,
|
||||
CYCLES_TEST_IMM_REG,
|
||||
CYCLES_TEST_IMM_MEM,
|
||||
CYCLES_TEST_IMM_ACC,
|
||||
CYCLES_NEG_REG,
|
||||
CYCLES_NEG_MEM,
|
||||
CYCLES_AAA,
|
||||
CYCLES_AAS,
|
||||
CYCLES_DAA,
|
||||
CYCLES_DAS,
|
||||
CYCLES_MUL8_ACC_REG,
|
||||
CYCLES_MUL8_ACC_MEM,
|
||||
CYCLES_MUL16_ACC_REG,
|
||||
CYCLES_MUL16_ACC_MEM,
|
||||
CYCLES_MUL32_ACC_REG,
|
||||
CYCLES_MUL32_ACC_MEM,
|
||||
CYCLES_IMUL8_ACC_REG,
|
||||
CYCLES_IMUL8_ACC_MEM,
|
||||
CYCLES_IMUL16_ACC_REG,
|
||||
CYCLES_IMUL16_ACC_MEM,
|
||||
CYCLES_IMUL32_ACC_REG,
|
||||
CYCLES_IMUL32_ACC_MEM,
|
||||
CYCLES_IMUL8_REG_REG,
|
||||
CYCLES_IMUL8_REG_MEM,
|
||||
CYCLES_IMUL16_REG_REG,
|
||||
CYCLES_IMUL16_REG_MEM,
|
||||
CYCLES_IMUL32_REG_REG,
|
||||
CYCLES_IMUL32_REG_MEM,
|
||||
CYCLES_IMUL16_REG_IMM_REG,
|
||||
CYCLES_IMUL16_MEM_IMM_REG,
|
||||
CYCLES_IMUL32_REG_IMM_REG,
|
||||
CYCLES_IMUL32_MEM_IMM_REG,
|
||||
CYCLES_DIV8_ACC_REG,
|
||||
CYCLES_DIV8_ACC_MEM,
|
||||
CYCLES_DIV16_ACC_REG,
|
||||
CYCLES_DIV16_ACC_MEM,
|
||||
CYCLES_DIV32_ACC_REG,
|
||||
CYCLES_DIV32_ACC_MEM,
|
||||
CYCLES_IDIV8_ACC_REG,
|
||||
CYCLES_IDIV8_ACC_MEM,
|
||||
CYCLES_IDIV16_ACC_REG,
|
||||
CYCLES_IDIV16_ACC_MEM,
|
||||
CYCLES_IDIV32_ACC_REG,
|
||||
CYCLES_IDIV32_ACC_MEM,
|
||||
CYCLES_AAD,
|
||||
CYCLES_AAM,
|
||||
CYCLES_CBW,
|
||||
CYCLES_CWD,
|
||||
CYCLES_ROTATE_REG,
|
||||
CYCLES_ROTATE_MEM,
|
||||
CYCLES_ROTATE_CARRY_REG,
|
||||
CYCLES_ROTATE_CARRY_MEM,
|
||||
CYCLES_SHLD_REG,
|
||||
CYCLES_SHLD_MEM,
|
||||
CYCLES_SHRD_REG,
|
||||
CYCLES_SHRD_MEM,
|
||||
CYCLES_NOT_REG,
|
||||
CYCLES_NOT_MEM,
|
||||
CYCLES_CMPS,
|
||||
CYCLES_INS,
|
||||
CYCLES_LODS,
|
||||
CYCLES_MOVS,
|
||||
CYCLES_OUTS,
|
||||
CYCLES_SCAS,
|
||||
CYCLES_STOS,
|
||||
CYCLES_XLAT,
|
||||
CYCLES_REP_CMPS_BASE,
|
||||
CYCLES_REP_INS_BASE,
|
||||
CYCLES_REP_LODS_BASE,
|
||||
CYCLES_REP_MOVS_BASE,
|
||||
CYCLES_REP_OUTS_BASE,
|
||||
CYCLES_REP_SCAS_BASE,
|
||||
CYCLES_REP_STOS_BASE,
|
||||
CYCLES_REP_CMPS,
|
||||
CYCLES_REP_INS,
|
||||
CYCLES_REP_LODS,
|
||||
CYCLES_REP_MOVS,
|
||||
CYCLES_REP_OUTS,
|
||||
CYCLES_REP_SCAS,
|
||||
CYCLES_REP_STOS,
|
||||
CYCLES_BSF_BASE,
|
||||
CYCLES_BSF,
|
||||
CYCLES_BSR_BASE,
|
||||
CYCLES_BSR,
|
||||
CYCLES_BT_IMM_REG,
|
||||
CYCLES_BT_IMM_MEM,
|
||||
CYCLES_BT_REG_REG,
|
||||
CYCLES_BT_REG_MEM,
|
||||
CYCLES_BTC_IMM_REG,
|
||||
CYCLES_BTC_IMM_MEM,
|
||||
CYCLES_BTC_REG_REG,
|
||||
CYCLES_BTC_REG_MEM,
|
||||
CYCLES_BTR_IMM_REG,
|
||||
CYCLES_BTR_IMM_MEM,
|
||||
CYCLES_BTR_REG_REG,
|
||||
CYCLES_BTR_REG_MEM,
|
||||
CYCLES_BTS_IMM_REG,
|
||||
CYCLES_BTS_IMM_MEM,
|
||||
CYCLES_BTS_REG_REG,
|
||||
CYCLES_BTS_REG_MEM,
|
||||
CYCLES_CALL, /* E8 */
|
||||
CYCLES_CALL_REG, /* FF /2 */
|
||||
CYCLES_CALL_MEM, /* FF /2 */
|
||||
CYCLES_CALL_INTERSEG, /* 9A */
|
||||
CYCLES_CALL_REG_INTERSEG, /* FF /3 */
|
||||
CYCLES_CALL_MEM_INTERSEG, /* FF /3 */
|
||||
CYCLES_JMP_SHORT, /* EB */
|
||||
CYCLES_JMP, /* E9 */
|
||||
CYCLES_JMP_REG, /* FF /4 */
|
||||
CYCLES_JMP_MEM, /* FF /4 */
|
||||
CYCLES_JMP_INTERSEG, /* EA */
|
||||
CYCLES_JMP_REG_INTERSEG, /* FF /5 */
|
||||
CYCLES_JMP_MEM_INTERSEG, /* FF /5 */
|
||||
CYCLES_RET, /* C3 */
|
||||
CYCLES_RET_IMM, /* C2 */
|
||||
CYCLES_RET_INTERSEG, /* CB */
|
||||
CYCLES_RET_IMM_INTERSEG, /* CA */
|
||||
CYCLES_JCC_DISP8,
|
||||
CYCLES_JCC_FULL_DISP,
|
||||
CYCLES_JCC_DISP8_NOBRANCH,
|
||||
CYCLES_JCC_FULL_DISP_NOBRANCH,
|
||||
CYCLES_JCXZ,
|
||||
CYCLES_JCXZ_NOBRANCH,
|
||||
CYCLES_LOOP,
|
||||
CYCLES_LOOPZ,
|
||||
CYCLES_LOOPNZ,
|
||||
CYCLES_SETCC_REG,
|
||||
CYCLES_SETCC_MEM,
|
||||
CYCLES_ENTER,
|
||||
CYCLES_LEAVE,
|
||||
CYCLES_INT,
|
||||
CYCLES_INT3,
|
||||
CYCLES_INTO_OF1,
|
||||
CYCLES_INTO_OF0,
|
||||
CYCLES_BOUND_IN_RANGE,
|
||||
CYCLES_BOUND_OUT_RANGE,
|
||||
CYCLES_IRET,
|
||||
CYCLES_HLT,
|
||||
CYCLES_MOV_REG_CR0,
|
||||
CYCLES_MOV_REG_CR2,
|
||||
CYCLES_MOV_REG_CR3,
|
||||
CYCLES_MOV_CR_REG,
|
||||
CYCLES_MOV_REG_DR0_3,
|
||||
CYCLES_MOV_REG_DR6_7,
|
||||
CYCLES_MOV_DR6_7_REG,
|
||||
CYCLES_MOV_DR0_3_REG,
|
||||
CYCLES_MOV_REG_TR6_7,
|
||||
CYCLES_MOV_TR6_7_REG,
|
||||
CYCLES_NOP,
|
||||
CYCLES_WAIT,
|
||||
CYCLES_ARPL_REG,
|
||||
CYCLES_ARPL_MEM,
|
||||
CYCLES_LAR_REG,
|
||||
CYCLES_LAR_MEM,
|
||||
CYCLES_LGDT,
|
||||
CYCLES_LIDT,
|
||||
CYCLES_LLDT_REG,
|
||||
CYCLES_LLDT_MEM,
|
||||
CYCLES_LMSW_REG,
|
||||
CYCLES_LMSW_MEM,
|
||||
CYCLES_LSL_REG,
|
||||
CYCLES_LSL_MEM,
|
||||
CYCLES_LTR_REG,
|
||||
CYCLES_LTR_MEM,
|
||||
CYCLES_SGDT,
|
||||
CYCLES_SIDT,
|
||||
CYCLES_SLDT_REG,
|
||||
CYCLES_SLDT_MEM,
|
||||
CYCLES_SMSW_REG,
|
||||
CYCLES_SMSW_MEM,
|
||||
CYCLES_STR_REG,
|
||||
CYCLES_STR_MEM,
|
||||
CYCLES_VERR_REG,
|
||||
CYCLES_VERR_MEM,
|
||||
CYCLES_VERW_REG,
|
||||
CYCLES_VERW_MEM,
|
||||
CYCLES_LOCK,
|
||||
|
||||
CYCLES_BSWAP,
|
||||
CYCLES_CMPXCHG8B,
|
||||
CYCLES_CMPXCHG,
|
||||
CYCLES_CPUID,
|
||||
CYCLES_CPUID_EAX1,
|
||||
CYCLES_INVD,
|
||||
CYCLES_XADD,
|
||||
CYCLES_RDTSC,
|
||||
CYCLES_RSM,
|
||||
CYCLES_RDMSR,
|
||||
|
||||
CYCLES_FABS,
|
||||
CYCLES_FADD,
|
||||
CYCLES_FBLD,
|
||||
CYCLES_FBSTP,
|
||||
CYCLES_FCHS,
|
||||
CYCLES_FCLEX,
|
||||
CYCLES_FCOM,
|
||||
CYCLES_FCOS,
|
||||
CYCLES_FDECSTP,
|
||||
CYCLES_FDISI,
|
||||
CYCLES_FDIV,
|
||||
CYCLES_FDIVR,
|
||||
CYCLES_FENI,
|
||||
CYCLES_FFREE,
|
||||
CYCLES_FIADD,
|
||||
CYCLES_FICOM,
|
||||
CYCLES_FIDIV,
|
||||
CYCLES_FILD,
|
||||
CYCLES_FIMUL,
|
||||
CYCLES_FINCSTP,
|
||||
CYCLES_FINIT,
|
||||
CYCLES_FIST,
|
||||
CYCLES_FISUB,
|
||||
CYCLES_FLD,
|
||||
CYCLES_FLDZ,
|
||||
CYCLES_FLD1,
|
||||
CYCLES_FLDL2E,
|
||||
CYCLES_FLDL2T,
|
||||
CYCLES_FLDLG2,
|
||||
CYCLES_FLDLN2,
|
||||
CYCLES_FLDPI,
|
||||
CYCLES_FLDCW,
|
||||
CYCLES_FLDENV,
|
||||
CYCLES_FMUL,
|
||||
CYCLES_FNOP,
|
||||
CYCLES_FPATAN,
|
||||
CYCLES_FPREM,
|
||||
CYCLES_FPREM1,
|
||||
CYCLES_FPTAN,
|
||||
CYCLES_FRNDINT,
|
||||
CYCLES_FRSTOR,
|
||||
CYCLES_FSAVE,
|
||||
CYCLES_FSCALE,
|
||||
CYCLES_FSETPM,
|
||||
CYCLES_FSIN,
|
||||
CYCLES_FSINCOS,
|
||||
CYCLES_FSQRT,
|
||||
CYCLES_FST,
|
||||
CYCLES_FSTCW,
|
||||
CYCLES_FSTENV,
|
||||
CYCLES_FSTSW,
|
||||
CYCLES_FSUB,
|
||||
CYCLES_FSUBR,
|
||||
CYCLES_FTST,
|
||||
CYCLES_FUCOM,
|
||||
CYCLES_FXAM,
|
||||
CYCLES_FXCH,
|
||||
CYCLES_FXTRACT,
|
||||
CYCLES_FYL2X,
|
||||
CYCLES_FYL2XPI,
|
||||
CYCLES_CMPXCHG_REG_REG_T,
|
||||
CYCLES_CMPXCHG_REG_REG_F,
|
||||
CYCLES_CMPXCHG_REG_MEM_T,
|
||||
CYCLES_CMPXCHG_REG_MEM_F,
|
||||
CYCLES_XADD_REG_REG,
|
||||
CYCLES_XADD_REG_MEM,
|
||||
|
||||
CYCLES_NUM_OPCODES
|
||||
} X86_CYCLES;
|
||||
|
||||
|
||||
#define X86_NUM_CPUS 4
|
||||
#define CPU_CYCLES_I386 0
|
||||
#define CPU_CYCLES_I486 1
|
||||
#define CPU_CYCLES_PENTIUM 2
|
||||
#define CPU_CYCLES_MEDIAGX 3
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
X86_CYCLES op;
|
||||
UINT8 cpu_cycles[X86_NUM_CPUS][2];
|
||||
} X86_CYCLE_TABLE;
|
||||
|
||||
static const X86_CYCLE_TABLE x86_cycle_table[] =
|
||||
{
|
||||
/* opcode rm/pmode */
|
||||
/* i386 i486 pentium mediagx */
|
||||
{ CYCLES_MOV_REG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_MOV_REG_MEM, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_MOV_MEM_REG, { { 4, 4 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_MOV_IMM_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_MOV_IMM_MEM, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_MOV_ACC_MEM, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_MOV_MEM_ACC, { { 4, 4 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_MOV_REG_SREG, { { 2, 18 }, { 3, 3 }, { 2, 2 }, { 1, 6 } } },
|
||||
{ CYCLES_MOV_MEM_SREG, { { 5, 19 }, { 9, 9 }, { 3, 3 }, { 1, 6 } } },
|
||||
{ CYCLES_MOV_SREG_REG, { { 2, 2 }, { 3, 3 }, { 1, 1 }, { 1, 6 } } },
|
||||
{ CYCLES_MOV_SREG_MEM, { { 2, 2 }, { 3, 3 }, { 1, 1 }, { 1, 6 } } },
|
||||
{ CYCLES_MOVSX_REG_REG, { { 3, 3 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_MOVSX_MEM_REG, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_MOVZX_REG_REG, { { 3, 3 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_MOVZX_MEM_REG, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_PUSH_RM, { { 5, 5 }, { 4, 4 }, { 2, 2 }, { 3, 3 } } },
|
||||
{ CYCLES_PUSH_REG_SHORT, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_PUSH_SREG, { { 2, 2 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_PUSH_IMM, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_PUSHA, { { 18, 18 }, { 11, 11 }, { 5, 5 }, { 11, 11 } } },
|
||||
{ CYCLES_POP_RM, { { 5, 5 }, { 4, 4 }, { 3, 3 }, { 4, 4 } } },
|
||||
{ CYCLES_POP_REG_SHORT, { { 4, 4 }, { 4, 4 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_POP_SREG, { { 7, 21 }, { 3, 3 }, { 3, 3 }, { 1, 6 } } },
|
||||
{ CYCLES_POPA, { { 24, 24 }, { 9, 9 }, { 5, 5 }, { 9, 9 } } },
|
||||
{ CYCLES_XCHG_REG_REG, { { 3, 3 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_XCHG_REG_MEM, { { 5, 5 }, { 5, 5 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_IN, { { 12, 26 }, { 14, 27 }, { 7, 19 }, { 8, 8 } } },
|
||||
{ CYCLES_IN_VAR, { { 13, 27 }, { 14, 27 }, { 7, 19 }, { 8, 8 } } },
|
||||
{ CYCLES_OUT, { { 10, 24 }, { 16, 29 }, { 12, 24 }, { 14, 14 } } },
|
||||
{ CYCLES_OUT_VAR, { { 11, 25 }, { 16, 29 }, { 12, 24 }, { 14, 14 } } },
|
||||
{ CYCLES_LEA, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_LDS, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 9 } } },
|
||||
{ CYCLES_LES, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 9 } } },
|
||||
{ CYCLES_LFS, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 9 } } },
|
||||
{ CYCLES_LGS, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 9 } } },
|
||||
{ CYCLES_LSS, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 10 } } },
|
||||
{ CYCLES_CLC, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_CLD, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 4, 4 } } },
|
||||
{ CYCLES_CLI, { { 8, 8 }, { 5, 5 }, { 7, 7 }, { 6, 6 } } },
|
||||
{ CYCLES_CLTS, { { 6, 6 }, { 7, 7 }, { 10, 10 }, { 7, 7 } } },
|
||||
{ CYCLES_CMC, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 3, 3 } } },
|
||||
{ CYCLES_LAHF, { { 2, 2 }, { 3, 3 }, { 2, 2 }, { 2, 2 } } },
|
||||
{ CYCLES_POPF, { { 5, 5 }, { 9, 9 }, { 6, 6 }, { 8, 8 } } },
|
||||
{ CYCLES_PUSHF, { { 4, 4 }, { 4, 4 }, { 9, 9 }, { 2, 2 } } },
|
||||
{ CYCLES_SAHF, { { 3, 3 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_STC, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_STD, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 4, 4 } } },
|
||||
{ CYCLES_STI, { { 8, 8 }, { 5, 5 }, { 7, 7 }, { 6, 6 } } },
|
||||
{ CYCLES_ALU_REG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_ALU_REG_MEM, { { 7, 7 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_ALU_MEM_REG, { { 6, 6 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_ALU_IMM_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_ALU_IMM_MEM, { { 7, 7 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_ALU_IMM_ACC, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_INC_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_INC_MEM, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_DEC_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_DEC_MEM, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_CMP_REG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_CMP_REG_MEM, { { 5, 5 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_CMP_MEM_REG, { { 6, 6 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_CMP_IMM_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_CMP_IMM_MEM, { { 5, 5 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_CMP_IMM_ACC, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_TEST_REG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_TEST_REG_MEM, { { 5, 5 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_TEST_IMM_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_TEST_IMM_MEM, { { 5, 5 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_TEST_IMM_ACC, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_NEG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_NEG_MEM, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_AAA, { { 4, 4 }, { 3, 3 }, { 3, 3 }, { 3, 3 } } },
|
||||
{ CYCLES_AAS, { { 4, 4 }, { 3, 3 }, { 3, 3 }, { 3, 3 } } },
|
||||
{ CYCLES_DAA, { { 4, 4 }, { 2, 2 }, { 3, 3 }, { 2, 2 } } },
|
||||
{ CYCLES_DAS, { { 4, 4 }, { 2, 2 }, { 3, 3 }, { 2, 2 } } },
|
||||
{ CYCLES_MUL8_ACC_REG, { { 17, 17 }, { 13, 13 }, { 11, 11 }, { 4, 4 } } },
|
||||
{ CYCLES_MUL8_ACC_MEM, { { 20, 20 }, { 13, 13 }, { 11, 11 }, { 4, 4 } } },
|
||||
{ CYCLES_MUL16_ACC_REG, { { 25, 25 }, { 13, 13 }, { 11, 11 }, { 5, 5 } } },
|
||||
{ CYCLES_MUL16_ACC_MEM, { { 28, 28 }, { 13, 13 }, { 11, 11 }, { 5, 5 } } },
|
||||
{ CYCLES_MUL32_ACC_REG, { { 41, 41 }, { 13, 13 }, { 10, 10 }, { 15, 15 } } },
|
||||
{ CYCLES_MUL32_ACC_MEM, { { 44, 44 }, { 13, 13 }, { 10, 10 }, { 15, 15 } } },
|
||||
{ CYCLES_IMUL8_ACC_REG, { { 17, 17 }, { 18, 18 }, { 11, 11 }, { 4, 4 } } },
|
||||
{ CYCLES_IMUL8_ACC_MEM, { { 20, 20 }, { 18, 18 }, { 11, 11 }, { 4, 4 } } },
|
||||
{ CYCLES_IMUL16_ACC_REG, { { 25, 25 }, { 26, 26 }, { 11, 11 }, { 5, 5 } } },
|
||||
{ CYCLES_IMUL16_ACC_MEM, { { 28, 28 }, { 26, 26 }, { 11, 11 }, { 5, 5 } } },
|
||||
{ CYCLES_IMUL32_ACC_REG, { { 41, 41 }, { 42, 42 }, { 10, 10 }, { 15, 15 } } },
|
||||
{ CYCLES_IMUL32_ACC_MEM, { { 44, 44 }, { 42, 42 }, { 10, 10 }, { 15, 15 } } },
|
||||
{ CYCLES_IMUL8_REG_REG, { { 17, 17 }, { 13, 13 }, { 10, 10 }, { 4, 4 } } },
|
||||
{ CYCLES_IMUL8_REG_MEM, { { 20, 20 }, { 13, 13 }, { 10, 10 }, { 4, 4 } } },
|
||||
{ CYCLES_IMUL16_REG_REG, { { 25, 25 }, { 13, 13 }, { 10, 10 }, { 5, 5 } } },
|
||||
{ CYCLES_IMUL16_REG_MEM, { { 28, 28 }, { 13, 13 }, { 10, 10 }, { 5, 5 } } },
|
||||
{ CYCLES_IMUL32_REG_REG, { { 41, 41 }, { 13, 13 }, { 10, 10 }, { 15, 15 } } },
|
||||
{ CYCLES_IMUL32_REG_MEM, { { 44, 44 }, { 13, 13 }, { 10, 10 }, { 15, 15 } } },
|
||||
{ CYCLES_IMUL16_REG_IMM_REG,{ { 26, 26 }, { 26, 26 }, { 10, 10 }, { 6, 6 } } },
|
||||
{ CYCLES_IMUL16_MEM_IMM_REG,{ { 27, 27 }, { 26, 26 }, { 10, 10 }, { 6, 6 } } },
|
||||
{ CYCLES_IMUL32_REG_IMM_REG,{ { 42, 42 }, { 42, 42 }, { 10, 10 }, { 16, 16 } } },
|
||||
{ CYCLES_IMUL32_MEM_IMM_REG,{ { 43, 43 }, { 42, 42 }, { 10, 10 }, { 16, 16 } } },
|
||||
{ CYCLES_DIV8_ACC_REG, { { 14, 14 }, { 16, 16 }, { 17, 17 }, { 20, 20 } } },
|
||||
{ CYCLES_DIV8_ACC_MEM, { { 17, 17 }, { 16, 16 }, { 17, 17 }, { 20, 20 } } },
|
||||
{ CYCLES_DIV16_ACC_REG, { { 22, 22 }, { 24, 24 }, { 25, 25 }, { 29, 29 } } },
|
||||
{ CYCLES_DIV16_ACC_MEM, { { 25, 25 }, { 24, 24 }, { 25, 25 }, { 29, 29 } } },
|
||||
{ CYCLES_DIV32_ACC_REG, { { 38, 38 }, { 40, 40 }, { 41, 41 }, { 45, 45 } } },
|
||||
{ CYCLES_DIV32_ACC_MEM, { { 41, 41 }, { 40, 40 }, { 41, 41 }, { 45, 45 } } },
|
||||
{ CYCLES_IDIV8_ACC_REG, { { 19, 19 }, { 19, 19 }, { 22, 22 }, { 20, 20 } } },
|
||||
{ CYCLES_IDIV8_ACC_MEM, { { 22, 22 }, { 20, 20 }, { 22, 22 }, { 20, 20 } } },
|
||||
{ CYCLES_IDIV16_ACC_REG, { { 27, 27 }, { 27, 27 }, { 30, 30 }, { 29, 29 } } },
|
||||
{ CYCLES_IDIV16_ACC_MEM, { { 30, 30 }, { 28, 28 }, { 30, 30 }, { 29, 29 } } },
|
||||
{ CYCLES_IDIV32_ACC_REG, { { 43, 43 }, { 43, 43 }, { 46, 46 }, { 45, 45 } } },
|
||||
{ CYCLES_IDIV32_ACC_MEM, { { 46, 46 }, { 44, 44 }, { 46, 46 }, { 45, 45 } } },
|
||||
{ CYCLES_AAD, { { 19, 19 }, { 14, 14 }, { 10, 10 }, { 7, 7 } } },
|
||||
{ CYCLES_AAM, { { 17, 17 }, { 15, 15 }, { 18, 18 }, { 19, 19 } } },
|
||||
{ CYCLES_CBW, { { 3, 3 }, { 3, 3 }, { 3, 3 }, { 3, 3 } } },
|
||||
{ CYCLES_CWD, { { 2, 2 }, { 3, 3 }, { 2, 2 }, { 2, 2 } } },
|
||||
{ CYCLES_ROTATE_REG, { { 3, 3 }, { 3, 3 }, { 1, 1 }, { 2, 2 } } },
|
||||
{ CYCLES_ROTATE_MEM, { { 7, 7 }, { 4, 4 }, { 3, 3 }, { 2, 2 } } },
|
||||
{ CYCLES_ROTATE_CARRY_REG, { { 9, 9 }, { 8, 8 }, { 7, 7 }, { 8, 8 } } },
|
||||
{ CYCLES_ROTATE_CARRY_MEM, { { 10, 10 }, { 9, 9 }, { 8, 8 }, { 8, 8 } } },
|
||||
{ CYCLES_SHLD_REG, { { 3, 3 }, { 2, 2 }, { 4, 4 }, { 3, 3 } } },
|
||||
{ CYCLES_SHLD_MEM, { { 7, 7 }, { 3, 3 }, { 4, 4 }, { 6, 6 } } },
|
||||
{ CYCLES_SHRD_REG, { { 3, 3 }, { 2, 2 }, { 4, 4 }, { 3, 3 } } },
|
||||
{ CYCLES_SHRD_MEM, { { 7, 7 }, { 3, 3 }, { 4, 4 }, { 6, 6 } } },
|
||||
{ CYCLES_NOT_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_NOT_MEM, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_CMPS, { { 10, 10 }, { 8, 8 }, { 5, 5 }, { 6, 6 } } },
|
||||
{ CYCLES_INS, { { 15, 29 }, { 17, 30 }, { 9, 22 }, { 11, 11 } } },
|
||||
{ CYCLES_LODS, { { 5, 5 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } },
|
||||
{ CYCLES_MOVS, { { 8, 8 }, { 7, 7 }, { 4, 4 }, { 6, 6 } } },
|
||||
{ CYCLES_OUTS, { { 14, 28 }, { 17, 30 }, { 13, 25 }, { 15, 15 } } },
|
||||
{ CYCLES_SCAS, { { 8, 8 }, { 6, 6 }, { 4, 4 }, { 2, 2 } } },
|
||||
{ CYCLES_STOS, { { 5, 5 }, { 5, 5 }, { 3, 3 }, { 2, 2 } } },
|
||||
{ CYCLES_XLAT, { { 5, 5 }, { 4, 4 }, { 4, 4 }, { 5, 5 } } },
|
||||
{ CYCLES_REP_CMPS_BASE, { { 5, 5 }, { 0, 0 }, { 0, 0 }, { 11, 11 } } },
|
||||
{ CYCLES_REP_INS_BASE, { { 14, 8 }, { 0, 0 }, { 0, 0 }, { 17, 17 } } },
|
||||
{ CYCLES_REP_LODS_BASE, { { 5, 5 }, { 0, 0 }, { 0, 0 }, { 9, 9 } } },
|
||||
{ CYCLES_REP_MOVS_BASE, { { 8, 8 }, { 0, 0 }, { 0, 0 }, { 12, 12 } } },
|
||||
{ CYCLES_REP_OUTS_BASE, { { 12, 6 }, { 0, 0 }, { 0, 0 }, { 24, 24 } } },
|
||||
{ CYCLES_REP_SCAS_BASE, { { 5, 5 }, { 0, 0 }, { 0, 0 }, { 9, 9 } } },
|
||||
{ CYCLES_REP_STOS_BASE, { { 5, 5 }, { 0, 0 }, { 0, 0 }, { 9, 9 } } },
|
||||
{ CYCLES_REP_CMPS, { { 5, 5 }, { 8, 8 }, { 5, 5 }, { 4, 4 } } },
|
||||
{ CYCLES_REP_INS, { { 14, 8 }, { 17, 30 }, { 9, 22 }, { 4, 4 } } },
|
||||
{ CYCLES_REP_LODS, { { 5, 5 }, { 5, 5 }, { 2, 2 }, { 2, 2 } } },
|
||||
{ CYCLES_REP_MOVS, { { 8, 8 }, { 7, 7 }, { 4, 4 }, { 2, 2 } } },
|
||||
{ CYCLES_REP_OUTS, { { 12, 6 }, { 17, 30 }, { 13, 25 }, { 4, 4 } } },
|
||||
{ CYCLES_REP_SCAS, { { 5, 5 }, { 6, 6 }, { 4, 4 }, { 3, 3 } } },
|
||||
{ CYCLES_REP_STOS, { { 5, 5 }, { 5, 5 }, { 3, 3 }, { 2, 2 } } },
|
||||
{ CYCLES_BSF_BASE, { { 11, 11 }, { 6, 6 }, { 6, 6 }, { 4, 4 } } },
|
||||
{ CYCLES_BSF, { { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_BSR_BASE, { { 9, 9 }, { 6, 6 }, { 7, 7 }, { 4, 4 } } },
|
||||
{ CYCLES_BSR, { { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_BT_IMM_REG, { { 3, 3 }, { 3, 3 }, { 4, 4 }, { 1, 1 } } },
|
||||
{ CYCLES_BT_IMM_MEM, { { 6, 6 }, { 6, 6 }, { 4, 4 }, { 1, 1 } } },
|
||||
{ CYCLES_BT_REG_REG, { { 3, 3 }, { 3, 3 }, { 4, 4 }, { 1, 1 } } },
|
||||
{ CYCLES_BT_REG_MEM, { { 12, 12 }, { 12, 12 }, { 9, 9 }, { 7, 7 } } },
|
||||
{ CYCLES_BTC_IMM_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } },
|
||||
{ CYCLES_BTC_IMM_MEM, { { 8, 8 }, { 8, 8 }, { 8, 8 }, { 2, 2 } } },
|
||||
{ CYCLES_BTC_REG_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } },
|
||||
{ CYCLES_BTC_REG_MEM, { { 13, 13 }, { 13, 13 }, { 13, 13 }, { 8, 8 } } },
|
||||
{ CYCLES_BTR_IMM_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } },
|
||||
{ CYCLES_BTR_IMM_MEM, { { 8, 8 }, { 8, 8 }, { 8, 8 }, { 2, 2 } } },
|
||||
{ CYCLES_BTR_REG_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } },
|
||||
{ CYCLES_BTR_REG_MEM, { { 13, 13 }, { 13, 13 }, { 13, 13 }, { 8, 8 } } },
|
||||
{ CYCLES_BTS_IMM_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } },
|
||||
{ CYCLES_BTS_IMM_MEM, { { 8, 8 }, { 8, 8 }, { 8, 8 }, { 2, 2 } } },
|
||||
{ CYCLES_BTS_REG_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } },
|
||||
{ CYCLES_BTS_REG_MEM, { { 13, 13 }, { 13, 13 }, { 13, 13 }, { 8, 8 } } },
|
||||
{ CYCLES_CALL, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 3, 3 } } },
|
||||
{ CYCLES_CALL_REG, { { 7, 7 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } },
|
||||
{ CYCLES_CALL_MEM, { { 10, 10 }, { 5, 5 }, { 2, 2 }, { 4, 4 } } },
|
||||
{ CYCLES_CALL_INTERSEG, { { 17, 34 }, { 18, 20 }, { 4, 13 }, { 9, 14 } } },
|
||||
{ CYCLES_CALL_REG_INTERSEG, { { 22, 38 }, { 17, 20 }, { 4, 14 }, { 11, 15 } } },
|
||||
{ CYCLES_CALL_MEM_INTERSEG, { { 22, 38 }, { 17, 20 }, { 4, 14 }, { 11, 15 } } },
|
||||
{ CYCLES_JMP_SHORT, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_JMP, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_JMP_REG, { { 7, 7 }, { 5, 5 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_JMP_MEM, { { 10, 10 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } },
|
||||
{ CYCLES_JMP_INTERSEG, { { 12, 27 }, { 17, 19 }, { 3, 3 }, { 8, 12 } } },
|
||||
{ CYCLES_JMP_REG_INTERSEG, { { 17, 31 }, { 13, 18 }, { 4, 4 }, { 10, 10 } } },
|
||||
{ CYCLES_JMP_MEM_INTERSEG, { { 17, 31 }, { 13, 18 }, { 4, 4 }, { 10, 13 } } },
|
||||
{ CYCLES_RET, { { 10, 10 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } },
|
||||
{ CYCLES_RET_IMM, { { 10, 10 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } },
|
||||
{ CYCLES_RET_INTERSEG, { { 18, 32 }, { 13, 13 }, { 4, 4 }, { 10, 13 } } },
|
||||
{ CYCLES_RET_IMM_INTERSEG, { { 18, 32 }, { 14, 14 }, { 4, 4 }, { 10, 13 } } },
|
||||
{ CYCLES_JCC_DISP8, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_JCC_FULL_DISP, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_JCC_DISP8_NOBRANCH,{ { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_JCC_FULL_DISP_NOBRANCH,{ { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_JCXZ, { { 9, 9 }, { 1, 1 }, { 1, 1 }, { 2, 2 } } },
|
||||
{ CYCLES_JCXZ_NOBRANCH, { { 5, 5 }, { 1, 1 }, { 1, 1 }, { 2, 2 } } },
|
||||
{ CYCLES_LOOP, { { 11, 11 }, { 6, 6 }, { 5, 5 }, { 2, 2 } } },
|
||||
{ CYCLES_LOOPZ, { { 11, 11 }, { 9, 9 }, { 8, 8 }, { 2, 2 } } },
|
||||
{ CYCLES_LOOPNZ, { { 11, 11 }, { 9, 9 }, { 8, 8 }, { 2, 2 } } },
|
||||
{ CYCLES_SETCC_REG, { { 4, 4 }, { 3, 3 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_SETCC_MEM, { { 5, 5 }, { 4, 4 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_ENTER, { { 10, 10 }, { 14, 14 }, { 11, 11 }, { 13, 13 } } },
|
||||
{ CYCLES_LEAVE, { { 4, 4 }, { 5, 5 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_INT, { { 37, 37 }, { 30, 30 }, { 16, 16 }, { 19, 19 } } },
|
||||
{ CYCLES_INT3, { { 33, 33 }, { 26, 26 }, { 13, 13 }, { 19, 19 } } },
|
||||
{ CYCLES_INTO_OF1, { { 35, 35 }, { 28, 28 }, { 13, 13 }, { 19, 19 } } },
|
||||
{ CYCLES_INTO_OF0, { { 3, 3 }, { 3, 3 }, { 4, 4 }, { 4, 4 } } },
|
||||
{ CYCLES_BOUND_IN_RANGE, { { 10, 10 }, { 7, 7 }, { 8, 8 }, { 7, 7 } } },
|
||||
{ CYCLES_BOUND_OUT_RANGE, { { 44, 44 }, { 7, 7 }, { 8, 8 }, { 8, 8 } } },
|
||||
{ CYCLES_IRET, { { 22, 22 }, { 15, 15 }, { 8, 8 }, { 13, 13 } } },
|
||||
{ CYCLES_HLT, { { 5, 5 }, { 4, 4 }, { 4, 4 }, { 10, 10 } } },
|
||||
{ CYCLES_MOV_REG_CR0, { { 11, 11 }, { 16, 16 }, { 16, 16 }, { 20, 18 } } },
|
||||
{ CYCLES_MOV_REG_CR2, { { 4, 4 }, { 4, 4 }, { 4, 4 }, { 5, 5 } } },
|
||||
{ CYCLES_MOV_REG_CR3, { { 5, 5 }, { 4, 4 }, { 4, 4 }, { 5, 6 } } },
|
||||
{ CYCLES_MOV_CR_REG, { { 6, 6 }, { 4, 4 }, { 4, 4 }, { 6, 6 } } },
|
||||
{ CYCLES_MOV_REG_DR0_3, { { 22, 22 }, { 10, 10 }, { 10, 10 }, { 10, 10 } } },
|
||||
{ CYCLES_MOV_REG_DR6_7, { { 16, 16 }, { 10, 10 }, { 10, 10 }, { 10, 10 } } },
|
||||
{ CYCLES_MOV_DR6_7_REG, { { 14, 14 }, { 11, 11 }, { 11, 11 }, { 9, 9 } } },
|
||||
{ CYCLES_MOV_DR0_3_REG, { { 22, 22 }, { 11, 11 }, { 11, 11 }, { 9, 9 } } },
|
||||
{ CYCLES_MOV_REG_TR6_7, { { 12, 12 }, { 4, 4 }, { 4, 4 }, { 11, 11 } } },
|
||||
{ CYCLES_MOV_TR6_7_REG, { { 12, 12 }, { 3, 3 }, { 3, 3 }, { 3, 3 } } },
|
||||
{ CYCLES_NOP, { { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_WAIT, { { 7, 7 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_ARPL_REG, { { 0, 20 }, { 0, 9 }, { 0, 7 }, { 0, 9 } } },
|
||||
{ CYCLES_ARPL_MEM, { { 0, 21 }, { 0, 9 }, { 0, 7 }, { 0, 9 } } },
|
||||
{ CYCLES_LAR_REG, { { 0, 15 }, { 11, 11 }, { 8, 8 }, { 0, 9 } } },
|
||||
{ CYCLES_LAR_MEM, { { 0, 16 }, { 11, 11 }, { 8, 8 }, { 0, 9 } } },
|
||||
{ CYCLES_LGDT, { { 11, 11 }, { 11, 11 }, { 6, 6 }, { 10, 10 } } },
|
||||
{ CYCLES_LIDT, { { 11, 11 }, { 11, 11 }, { 6, 6 }, { 10, 10 } } },
|
||||
{ CYCLES_LLDT_REG, { { 0, 20 }, { 11, 11 }, { 9, 9 }, { 0, 8 } } },
|
||||
{ CYCLES_LLDT_MEM, { { 0, 24 }, { 11, 11 }, { 9, 9 }, { 0, 8 } } },
|
||||
{ CYCLES_LMSW_REG, { { 11, 11 }, { 13, 13 }, { 8, 8 }, { 11, 11 } } },
|
||||
{ CYCLES_LMSW_MEM, { { 14, 14 }, { 13, 13 }, { 8, 8 }, { 11, 11 } } },
|
||||
{ CYCLES_LSL_REG, { { 0, 21 }, { 10, 10 }, { 8, 8 }, { 0, 9 } } },
|
||||
{ CYCLES_LSL_MEM, { { 0, 22 }, { 10, 10 }, { 8, 8 }, { 0, 9 } } },
|
||||
{ CYCLES_LTR_REG, { { 0, 23 }, { 20, 20 }, { 10, 10 }, { 0, 9 } } },
|
||||
{ CYCLES_LTR_MEM, { { 0, 27 }, { 20, 20 }, { 10, 10 }, { 0, 9 } } },
|
||||
{ CYCLES_SGDT, { { 9, 9 }, { 10, 10 }, { 4, 4 }, { 6, 6 } } },
|
||||
{ CYCLES_SIDT, { { 9, 9 }, { 10, 10 }, { 4, 4 }, { 6, 6 } } },
|
||||
{ CYCLES_SLDT_REG, { { 0, 2 }, { 2, 2 }, { 2, 2 }, { 0, 1 } } },
|
||||
{ CYCLES_SLDT_MEM, { { 0, 2 }, { 3, 3 }, { 2, 2 }, { 0, 1 } } },
|
||||
{ CYCLES_SMSW_REG, { { 2, 2 }, { 2, 2 }, { 4, 4 }, { 4, 4 } } },
|
||||
{ CYCLES_SMSW_MEM, { { 2, 2 }, { 3, 3 }, { 4, 4 }, { 4, 4 } } },
|
||||
{ CYCLES_STR_REG, { { 0, 2 }, { 2, 2 }, { 2, 2 }, { 0, 3 } } },
|
||||
{ CYCLES_STR_MEM, { { 0, 2 }, { 3, 3 }, { 2, 2 }, { 0, 3 } } },
|
||||
{ CYCLES_VERR_REG, { { 0, 10 }, { 11, 11 }, { 7, 7 }, { 0, 8 } } },
|
||||
{ CYCLES_VERR_MEM, { { 0, 11 }, { 11, 11 }, { 7, 7 }, { 0, 8 } } },
|
||||
{ CYCLES_VERW_REG, { { 0, 15 }, { 11, 11 }, { 7, 7 }, { 0, 8 } } },
|
||||
{ CYCLES_VERW_MEM, { { 0, 16 }, { 11, 11 }, { 7, 7 }, { 0, 8 } } },
|
||||
{ CYCLES_LOCK, { { 0, 0 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
|
||||
/* i486+ */
|
||||
{ CYCLES_BSWAP, { { 0, 0 }, { 1, 1 }, { 1, 1 }, { 6, 6 } } },
|
||||
{ CYCLES_CMPXCHG, { { 0, 0 }, { 6, 6 }, { 5, 5 }, { 6, 6 } } },
|
||||
{ CYCLES_INVD, { { 0, 0 }, { 4, 4 }, { 15, 15 }, { 20, 20 } } },
|
||||
{ CYCLES_XADD, { { 0, 0 }, { 4, 4 }, { 4, 4 }, { 2, 2 } } },
|
||||
|
||||
/* Pentium+ */
|
||||
{ CYCLES_CMPXCHG8B, { { 0, 0 }, { 0, 0 }, { 10, 10 }, { 6, 6 } } },
|
||||
{ CYCLES_CPUID, { { 0, 0 }, { 0, 0 }, { 14, 14 }, { 12, 12 } } },
|
||||
{ CYCLES_CPUID_EAX1, { { 0, 0 }, { 0, 0 }, { 14, 14 }, { 12, 12 } } },
|
||||
{ CYCLES_RDTSC, { { 0, 0 }, { 0, 0 }, { 20, 20 }, { 1, 1 } } },
|
||||
{ CYCLES_RSM, { { 0, 0 }, { 0, 0 }, { 82, 82 }, { 57, 57 } } },
|
||||
{ CYCLES_RDMSR, { { 0, 0 }, { 0, 0 }, { 20, 20 }, { 1, 1 } } },
|
||||
|
||||
/* FPU */
|
||||
{ CYCLES_FABS, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FADD, { { 0, 0 }, { 8, 8 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_FBLD, { { 0, 0 }, { 70, 70 }, { 48, 48 }, { 1, 1 } } },
|
||||
{ CYCLES_FBSTP, { { 0, 0 }, {172,172 }, {148,148 }, { 1, 1 } } },
|
||||
{ CYCLES_FCHS, { { 0, 0 }, { 6, 6 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FCLEX, { { 0, 0 }, { 7, 7 }, { 9, 9 }, { 1, 1 } } },
|
||||
{ CYCLES_FCOM, { { 0, 0 }, { 4, 4 }, { 4, 4 }, { 1, 1 } } },
|
||||
{ CYCLES_FCOS, { { 0, 0 }, {255,255 }, {124,124 }, { 1, 1 } } },
|
||||
{ CYCLES_FDECSTP, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FDISI, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FDIV, { { 0, 0 }, { 73, 73 }, { 39, 39 }, { 1, 1 } } },
|
||||
{ CYCLES_FDIVR, { { 0, 0 }, { 73, 73 }, { 39, 39 }, { 1, 1 } } },
|
||||
{ CYCLES_FENI, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FFREE, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FIADD, { { 0, 0 }, { 20, 20 }, { 7, 7 }, { 1, 1 } } },
|
||||
{ CYCLES_FICOM, { { 0, 0 }, { 16, 16 }, { 8, 8 }, { 1, 1 } } },
|
||||
{ CYCLES_FIDIV, { { 0, 0 }, { 85, 85 }, { 42, 42 }, { 1, 1 } } },
|
||||
{ CYCLES_FILD, { { 0, 0 }, { 13, 13 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_FIMUL, { { 0, 0 }, { 23, 23 }, { 7, 7 }, { 1, 1 } } },
|
||||
{ CYCLES_FINCSTP, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FINIT, { { 0, 0 }, { 17, 17 }, { 16, 16 }, { 1, 1 } } },
|
||||
{ CYCLES_FIST, { { 0, 0 }, { 29, 29 }, { 6, 6 }, { 1, 1 } } },
|
||||
{ CYCLES_FISUB, { { 0, 0 }, { 20, 20 }, { 7, 7 }, { 1, 1 } } },
|
||||
{ CYCLES_FLD, { { 0, 0 }, { 4, 4 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FLDZ, { { 0, 0 }, { 4, 4 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_FLD1, { { 0, 0 }, { 4, 4 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_FLDL2E, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } },
|
||||
{ CYCLES_FLDL2T, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } },
|
||||
{ CYCLES_FLDLG2, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } },
|
||||
{ CYCLES_FLDLN2, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } },
|
||||
{ CYCLES_FLDPI, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } },
|
||||
{ CYCLES_FLDCW, { { 0, 0 }, { 4, 4 }, { 7, 7 }, { 1, 1 } } },
|
||||
{ CYCLES_FLDENV, { { 0, 0 }, { 44, 44 }, { 37, 37 }, { 1, 1 } } },
|
||||
{ CYCLES_FMUL, { { 0, 0 }, { 16, 16 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_FNOP, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FPATAN, { { 0, 0 }, {218,218 }, {173,173 }, { 1, 1 } } },
|
||||
{ CYCLES_FPREM, { { 0, 0 }, { 70, 70 }, { 16, 16 }, { 1, 1 } } },
|
||||
{ CYCLES_FPREM1, { { 0, 0 }, { 72, 72 }, { 20, 20 }, { 1, 1 } } },
|
||||
{ CYCLES_FPTAN, { { 0, 0 }, {200,200 }, {173,173 }, { 1, 1 } } },
|
||||
{ CYCLES_FRNDINT, { { 0, 0 }, { 21, 21 }, { 9, 9 }, { 1, 1 } } },
|
||||
{ CYCLES_FRSTOR, { { 0, 0 }, {131,131 }, { 75, 75 }, { 1, 1 } } },
|
||||
{ CYCLES_FSAVE, { { 0, 0 }, {154,154 }, {127,127 }, { 1, 1 } } },
|
||||
{ CYCLES_FSCALE, { { 0, 0 }, { 30, 30 }, { 20, 20 }, { 1, 1 } } },
|
||||
{ CYCLES_FSETPM, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FSIN, { { 0, 0 }, {255,255 }, {126,126 }, { 1, 1 } } },
|
||||
{ CYCLES_FSINCOS, { { 0, 0 }, {255,255 }, {137,137 }, { 1, 1 } } },
|
||||
{ CYCLES_FSQRT, { { 0, 0 }, { 83, 83 }, { 70, 70 }, { 1, 1 } } },
|
||||
{ CYCLES_FST, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FSTCW, { { 0, 0 }, { 3, 3 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_FSTENV, { { 0, 0 }, { 67, 67 }, { 48, 48 }, { 1, 1 } } },
|
||||
{ CYCLES_FSTSW, { { 0, 0 }, { 3, 3 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_FSUB, { { 0, 0 }, { 8, 8 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_FSUBR, { { 0, 0 }, { 8, 8 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_FTST, { { 0, 0 }, { 4, 4 }, { 4, 4 }, { 1, 1 } } },
|
||||
{ CYCLES_FUCOM, { { 0, 0 }, { 4, 4 }, { 4, 4 }, { 1, 1 } } },
|
||||
{ CYCLES_FXAM, { { 0, 0 }, { 8, 8 }, { 21, 21 }, { 1, 1 } } },
|
||||
{ CYCLES_FXCH, { { 0, 0 }, { 4, 4 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FXTRACT, { { 0, 0 }, { 16, 16 }, { 13, 13 }, { 1, 1 } } },
|
||||
{ CYCLES_FYL2X, { { 0, 0 }, {196,196 }, {111,111 }, { 1, 1 } } },
|
||||
{ CYCLES_FYL2XPI, { { 0, 0 }, {171,171 }, {103,103 }, { 1, 1 } } },
|
||||
{ CYCLES_CMPXCHG_REG_REG_T, { { 0, 0 }, { 6, 6 }, { 6, 6 }, { 6, 6 } } },
|
||||
{ CYCLES_CMPXCHG_REG_REG_F, { { 0, 0 }, { 9, 9 }, { 9, 9 }, { 9, 9 } } },
|
||||
{ CYCLES_CMPXCHG_REG_MEM_T, { { 0, 0 }, { 7, 7 }, { 7, 7 }, { 7, 7 } } },
|
||||
{ CYCLES_CMPXCHG_REG_MEM_F, { { 0, 0 }, { 10, 10 }, { 10, 10 }, { 10, 10 } } },
|
||||
};
|
||||
|
||||
#endif /* __CYCLES_H__ */
|
||||
@@ -0,0 +1,868 @@
|
||||
/*
|
||||
Intel 386 emulator
|
||||
|
||||
Written by Ville Linde
|
||||
|
||||
Currently supports:
|
||||
Intel 386
|
||||
Intel 486
|
||||
Intel Pentium
|
||||
Cyrix MediaGX
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "driver.h"
|
||||
#include "state.h"
|
||||
#include "i386priv.h"
|
||||
#include "i386.h"
|
||||
#include "mamedbg.h"
|
||||
|
||||
int i386_ICount;
|
||||
|
||||
/* the 0.139 core stops on what it does not implement; here it is logged once */
|
||||
static void i386_fatal(const char *fmt, ...)
|
||||
{
|
||||
static int reported;
|
||||
if (!reported)
|
||||
{
|
||||
char buf[256];
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
vsprintf(buf, fmt, va);
|
||||
va_end(va);
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%s\n", buf);
|
||||
reported = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* seems to be defined on mingw-gcc */
|
||||
#undef i386
|
||||
|
||||
int i386_parity_table[256];
|
||||
MODRM_TABLE i386_MODRM_table[256];
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#define INT_DEBUG 1
|
||||
|
||||
static void i386_load_protected_mode_segment(i386_state *cpustate, I386_SREG *seg )
|
||||
{
|
||||
UINT32 v1,v2;
|
||||
UINT32 base, limit;
|
||||
int entry;
|
||||
|
||||
if ( seg->selector & 0x4 )
|
||||
{
|
||||
base = cpustate->ldtr.base;
|
||||
limit = cpustate->ldtr.limit;
|
||||
} else {
|
||||
base = cpustate->gdtr.base;
|
||||
limit = cpustate->gdtr.limit;
|
||||
}
|
||||
|
||||
if (limit == 0 || seg->selector + 7 > limit)
|
||||
return;
|
||||
entry = seg->selector & ~0x7;
|
||||
|
||||
v1 = READ32(cpustate, base + entry );
|
||||
v2 = READ32(cpustate, base + entry + 4 );
|
||||
|
||||
seg->flags = (v2 >> 8) & 0xf0ff;
|
||||
seg->base = (v2 & 0xff000000) | ((v2 & 0xff) << 16) | ((v1 >> 16) & 0xffff);
|
||||
seg->limit = (v2 & 0xf0000) | (v1 & 0xffff);
|
||||
if (seg->flags & 0x8000)
|
||||
seg->limit = (seg->limit << 12) | 0xfff;
|
||||
seg->d = (seg->flags & 0x4000) ? 1 : 0;
|
||||
}
|
||||
|
||||
static void i386_load_segment_descriptor(i386_state *cpustate, int segment )
|
||||
{
|
||||
if (PROTECTED_MODE)
|
||||
{
|
||||
if (!V8086_MODE)
|
||||
i386_load_protected_mode_segment(cpustate, &cpustate->sreg[segment] );
|
||||
else
|
||||
{
|
||||
cpustate->sreg[segment].base = cpustate->sreg[segment].selector << 4;
|
||||
cpustate->sreg[segment].limit = 0xffff;
|
||||
cpustate->sreg[segment].flags = (segment == CS) ? 0x009a : 0x0092;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cpustate->sreg[segment].base = cpustate->sreg[segment].selector << 4;
|
||||
|
||||
if( segment == CS && !cpustate->performed_intersegment_jump )
|
||||
cpustate->sreg[segment].base |= 0xfff00000;
|
||||
}
|
||||
}
|
||||
|
||||
static UINT32 get_flags(i386_state *cpustate)
|
||||
{
|
||||
UINT32 f = 0x2;
|
||||
f |= cpustate->CF;
|
||||
f |= cpustate->PF << 2;
|
||||
f |= cpustate->AF << 4;
|
||||
f |= cpustate->ZF << 6;
|
||||
f |= cpustate->SF << 7;
|
||||
f |= cpustate->TF << 8;
|
||||
f |= cpustate->IF << 9;
|
||||
f |= cpustate->DF << 10;
|
||||
f |= cpustate->OF << 11;
|
||||
f |= cpustate->IOP1 << 12;
|
||||
f |= cpustate->IOP2 << 13;
|
||||
f |= cpustate->NT << 14;
|
||||
return (cpustate->eflags & cpustate->eflags_mask) | (f & 0xffff);
|
||||
}
|
||||
|
||||
static void set_flags(i386_state *cpustate, UINT32 f )
|
||||
{
|
||||
cpustate->CF = (f & 0x1) ? 1 : 0;
|
||||
cpustate->PF = (f & 0x4) ? 1 : 0;
|
||||
cpustate->AF = (f & 0x10) ? 1 : 0;
|
||||
cpustate->ZF = (f & 0x40) ? 1 : 0;
|
||||
cpustate->SF = (f & 0x80) ? 1 : 0;
|
||||
cpustate->TF = (f & 0x100) ? 1 : 0;
|
||||
cpustate->IF = (f & 0x200) ? 1 : 0;
|
||||
cpustate->DF = (f & 0x400) ? 1 : 0;
|
||||
cpustate->OF = (f & 0x800) ? 1 : 0;
|
||||
cpustate->IOP1 = (f & 0x1000) ? 1 : 0;
|
||||
cpustate->IOP2 = (f & 0x2000) ? 1 : 0;
|
||||
cpustate->NT = (f & 0x4000) ? 1 : 0;
|
||||
cpustate->eflags = f & cpustate->eflags_mask;
|
||||
}
|
||||
|
||||
static void sib_byte(i386_state *cpustate,UINT8 mod, UINT32* out_ea, UINT8* out_segment)
|
||||
{
|
||||
UINT32 ea = 0;
|
||||
UINT8 segment = 0;
|
||||
UINT8 scale, i, base;
|
||||
UINT8 sib = FETCH(cpustate);
|
||||
scale = (sib >> 6) & 0x3;
|
||||
i = (sib >> 3) & 0x7;
|
||||
base = sib & 0x7;
|
||||
|
||||
switch( base )
|
||||
{
|
||||
case 0: ea = REG32(EAX); segment = DS; break;
|
||||
case 1: ea = REG32(ECX); segment = DS; break;
|
||||
case 2: ea = REG32(EDX); segment = DS; break;
|
||||
case 3: ea = REG32(EBX); segment = DS; break;
|
||||
case 4: ea = REG32(ESP); segment = SS; break;
|
||||
case 5:
|
||||
if( mod == 0 ) {
|
||||
ea = FETCH32(cpustate);
|
||||
segment = DS;
|
||||
} else if( mod == 1 ) {
|
||||
ea = REG32(EBP);
|
||||
segment = SS;
|
||||
} else if( mod == 2 ) {
|
||||
ea = REG32(EBP);
|
||||
segment = SS;
|
||||
}
|
||||
break;
|
||||
case 6: ea = REG32(ESI); segment = DS; break;
|
||||
case 7: ea = REG32(EDI); segment = DS; break;
|
||||
}
|
||||
switch( i )
|
||||
{
|
||||
case 0: ea += REG32(EAX) * (1 << scale); break;
|
||||
case 1: ea += REG32(ECX) * (1 << scale); break;
|
||||
case 2: ea += REG32(EDX) * (1 << scale); break;
|
||||
case 3: ea += REG32(EBX) * (1 << scale); break;
|
||||
case 4: break;
|
||||
case 5: ea += REG32(EBP) * (1 << scale); break;
|
||||
case 6: ea += REG32(ESI) * (1 << scale); break;
|
||||
case 7: ea += REG32(EDI) * (1 << scale); break;
|
||||
}
|
||||
*out_ea = ea;
|
||||
*out_segment = segment;
|
||||
}
|
||||
|
||||
static void modrm_to_EA(i386_state *cpustate,UINT8 mod_rm, UINT32* out_ea, UINT8* out_segment)
|
||||
{
|
||||
INT8 disp8;
|
||||
INT16 disp16;
|
||||
INT32 disp32;
|
||||
UINT8 mod = (mod_rm >> 6) & 0x3;
|
||||
UINT8 rm = mod_rm & 0x7;
|
||||
UINT32 ea;
|
||||
UINT8 segment;
|
||||
|
||||
if( mod_rm >= 0xc0 )
|
||||
i386_fatal("i386: Called modrm_to_EA with modrm value %02X !",mod_rm);
|
||||
|
||||
if( cpustate->address_size ) {
|
||||
switch( rm )
|
||||
{
|
||||
default:
|
||||
case 0: ea = REG32(EAX); segment = DS; break;
|
||||
case 1: ea = REG32(ECX); segment = DS; break;
|
||||
case 2: ea = REG32(EDX); segment = DS; break;
|
||||
case 3: ea = REG32(EBX); segment = DS; break;
|
||||
case 4: sib_byte(cpustate, mod, &ea, &segment ); break;
|
||||
case 5:
|
||||
if( mod == 0 ) {
|
||||
ea = FETCH32(cpustate); segment = DS;
|
||||
} else {
|
||||
ea = REG32(EBP); segment = SS;
|
||||
}
|
||||
break;
|
||||
case 6: ea = REG32(ESI); segment = DS; break;
|
||||
case 7: ea = REG32(EDI); segment = DS; break;
|
||||
}
|
||||
if( mod == 1 ) {
|
||||
disp8 = FETCH(cpustate);
|
||||
ea += (INT32)disp8;
|
||||
} else if( mod == 2 ) {
|
||||
disp32 = FETCH32(cpustate);
|
||||
ea += disp32;
|
||||
}
|
||||
|
||||
if( cpustate->segment_prefix )
|
||||
segment = cpustate->segment_override;
|
||||
|
||||
*out_ea = ea;
|
||||
*out_segment = segment;
|
||||
|
||||
} else {
|
||||
switch( rm )
|
||||
{
|
||||
default:
|
||||
case 0: ea = REG16(BX) + REG16(SI); segment = DS; break;
|
||||
case 1: ea = REG16(BX) + REG16(DI); segment = DS; break;
|
||||
case 2: ea = REG16(BP) + REG16(SI); segment = SS; break;
|
||||
case 3: ea = REG16(BP) + REG16(DI); segment = SS; break;
|
||||
case 4: ea = REG16(SI); segment = DS; break;
|
||||
case 5: ea = REG16(DI); segment = DS; break;
|
||||
case 6:
|
||||
if( mod == 0 ) {
|
||||
ea = FETCH16(cpustate); segment = DS;
|
||||
} else {
|
||||
ea = REG16(BP); segment = SS;
|
||||
}
|
||||
break;
|
||||
case 7: ea = REG16(BX); segment = DS; break;
|
||||
}
|
||||
if( mod == 1 ) {
|
||||
disp8 = FETCH(cpustate);
|
||||
ea += (INT32)disp8;
|
||||
} else if( mod == 2 ) {
|
||||
disp16 = FETCH16(cpustate);
|
||||
ea += (INT32)disp16;
|
||||
}
|
||||
|
||||
if( cpustate->segment_prefix )
|
||||
segment = cpustate->segment_override;
|
||||
|
||||
*out_ea = ea & 0xffff;
|
||||
*out_segment = segment;
|
||||
}
|
||||
}
|
||||
|
||||
static UINT32 GetNonTranslatedEA(i386_state *cpustate,UINT8 modrm)
|
||||
{
|
||||
UINT8 segment;
|
||||
UINT32 ea;
|
||||
modrm_to_EA(cpustate, modrm, &ea, &segment );
|
||||
return ea;
|
||||
}
|
||||
|
||||
static UINT32 GetEA(i386_state *cpustate,UINT8 modrm)
|
||||
{
|
||||
UINT8 segment;
|
||||
UINT32 ea;
|
||||
modrm_to_EA(cpustate, modrm, &ea, &segment );
|
||||
return i386_translate(cpustate, segment, ea );
|
||||
}
|
||||
|
||||
static void i386_trap(i386_state *cpustate,int irq, int irq_gate)
|
||||
{
|
||||
/* I386 Interrupts/Traps/Faults:
|
||||
*
|
||||
* 0x00 Divide by zero
|
||||
* 0x01 Debug exception
|
||||
* 0x02 NMI
|
||||
* 0x03 Int3
|
||||
* 0x04 Overflow
|
||||
* 0x05 Array bounds check
|
||||
* 0x06 Illegal Opcode
|
||||
* 0x07 FPU not available
|
||||
* 0x08 Double fault
|
||||
* 0x09 Coprocessor segment overrun
|
||||
* 0x0a Invalid task state
|
||||
* 0x0b Segment not present
|
||||
* 0x0c Stack exception
|
||||
* 0x0d General Protection Fault
|
||||
* 0x0e Page fault
|
||||
* 0x0f Reserved
|
||||
* 0x10 Coprocessor error
|
||||
*/
|
||||
UINT32 v1, v2;
|
||||
UINT32 offset;
|
||||
UINT16 segment;
|
||||
int entry = irq * (PROTECTED_MODE ? 8 : 4);
|
||||
|
||||
/* Check if IRQ is out of IDTR's bounds */
|
||||
if( entry > cpustate->idtr.limit ) {
|
||||
i386_fatal("I386 Interrupt: IRQ out of IDTR bounds (IRQ: %d, IDTR Limit: %d)", irq, cpustate->idtr.limit);
|
||||
}
|
||||
|
||||
if( !(PROTECTED_MODE) )
|
||||
{
|
||||
/* 16-bit */
|
||||
PUSH16(cpustate, get_flags(cpustate) & 0xffff );
|
||||
PUSH16(cpustate, cpustate->sreg[CS].selector );
|
||||
PUSH16(cpustate, cpustate->eip );
|
||||
|
||||
cpustate->sreg[CS].selector = READ16(cpustate, cpustate->idtr.base + entry + 2 );
|
||||
cpustate->eip = READ16(cpustate, cpustate->idtr.base + entry );
|
||||
|
||||
/* Interrupts that vector through either interrupt gates or trap gates cause TF */
|
||||
/* (the trap flag) to be reset after the current value of TF is saved on the stack as part of EFLAGS. */
|
||||
cpustate->TF = 0;
|
||||
|
||||
if (irq_gate)
|
||||
{
|
||||
cpustate->IF = 0;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
int type;
|
||||
/* 32-bit */
|
||||
|
||||
v1 = READ32(cpustate, cpustate->idtr.base + entry );
|
||||
v2 = READ32(cpustate, cpustate->idtr.base + entry + 4 );
|
||||
offset = (v2 & 0xffff0000) | (v1 & 0xffff);
|
||||
segment = (v1 >> 16) & 0xffff;
|
||||
type = (v2>>8) & 0x1F;
|
||||
|
||||
if(type != 0x0e && type != 0x0f) /* if not 386 interrupt or trap gate */
|
||||
{
|
||||
PUSH16(cpustate, get_flags(cpustate) & 0xffff );
|
||||
PUSH16(cpustate, cpustate->sreg[CS].selector );
|
||||
PUSH16(cpustate, cpustate->eip );
|
||||
}
|
||||
else
|
||||
{
|
||||
PUSH32(cpustate, get_flags(cpustate) & 0x00fcffff );
|
||||
PUSH32(cpustate, cpustate->sreg[CS].selector );
|
||||
PUSH32(cpustate, cpustate->eip );
|
||||
}
|
||||
|
||||
cpustate->sreg[CS].selector = segment;
|
||||
cpustate->eip = offset;
|
||||
|
||||
/* Interrupts that vector through either interrupt gates or trap gates cause TF */
|
||||
/* (the trap flag) to be reset after the current value of TF is saved on the stack as part of EFLAGS. */
|
||||
if ((type == 14) || (type==15))
|
||||
cpustate->TF = 0;
|
||||
|
||||
if (type == 14)
|
||||
{
|
||||
cpustate->IF = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
i386_load_segment_descriptor(cpustate,CS);
|
||||
CHANGE_PC(cpustate,cpustate->eip);
|
||||
|
||||
}
|
||||
|
||||
static void i386_check_irq_line(i386_state *cpustate)
|
||||
{
|
||||
/* Check if the interrupts are enabled */
|
||||
if ( (cpustate->irq_state) && cpustate->IF )
|
||||
{
|
||||
i386_ICount -= 2;
|
||||
i386_trap(cpustate,cpustate->irq_callback(0), 1);
|
||||
}
|
||||
}
|
||||
|
||||
#include "cycles.h"
|
||||
|
||||
static UINT8 *cycle_table_rm[X86_NUM_CPUS];
|
||||
static UINT8 *cycle_table_pm[X86_NUM_CPUS];
|
||||
|
||||
#define CYCLES_NUM(x) (i386_ICount -= (x))
|
||||
|
||||
static INLINE void CYCLES(i386_state *cpustate,int x)
|
||||
{
|
||||
if (PROTECTED_MODE)
|
||||
{
|
||||
i386_ICount -= cpustate->cycle_table_pm[x];
|
||||
}
|
||||
else
|
||||
{
|
||||
i386_ICount -= cpustate->cycle_table_rm[x];
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE void CYCLES_RM(i386_state *cpustate,int modrm, int r, int m)
|
||||
{
|
||||
if (modrm >= 0xc0)
|
||||
{
|
||||
if (PROTECTED_MODE)
|
||||
{
|
||||
i386_ICount -= cpustate->cycle_table_pm[r];
|
||||
}
|
||||
else
|
||||
{
|
||||
i386_ICount -= cpustate->cycle_table_rm[r];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PROTECTED_MODE)
|
||||
{
|
||||
i386_ICount -= cpustate->cycle_table_pm[m];
|
||||
}
|
||||
else
|
||||
{
|
||||
i386_ICount -= cpustate->cycle_table_rm[m];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static UINT8 cycle_tables[X86_NUM_CPUS][2][CYCLES_NUM_OPCODES];
|
||||
|
||||
static void build_cycle_table(void)
|
||||
{
|
||||
int i, j;
|
||||
for (j=0; j < X86_NUM_CPUS; j++)
|
||||
{
|
||||
cycle_table_rm[j] = cycle_tables[j][0];
|
||||
cycle_table_pm[j] = cycle_tables[j][1];
|
||||
|
||||
for (i=0; i < sizeof(x86_cycle_table)/sizeof(X86_CYCLE_TABLE); i++)
|
||||
{
|
||||
int opcode = x86_cycle_table[i].op;
|
||||
cycle_table_rm[j][opcode] = x86_cycle_table[i].cpu_cycles[j][0];
|
||||
cycle_table_pm[j][opcode] = x86_cycle_table[i].cpu_cycles[j][1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Forward declarations */
|
||||
static void I386OP(decode_opcode)(i386_state *cpustate);
|
||||
static void I386OP(decode_two_byte)(i386_state *cpustate);
|
||||
|
||||
|
||||
|
||||
#include "i386ops.c"
|
||||
#include "i386op16.c"
|
||||
#include "i386op32.c"
|
||||
#include "i486ops.c"
|
||||
#include "pentops.c"
|
||||
#include "x87ops.c"
|
||||
#include "i386ops.h"
|
||||
|
||||
static void I386OP(decode_opcode)(i386_state *cpustate)
|
||||
{
|
||||
cpustate->opcode = FETCH(cpustate);
|
||||
if( cpustate->operand_size )
|
||||
cpustate->opcode_table1_32[cpustate->opcode](cpustate);
|
||||
else
|
||||
cpustate->opcode_table1_16[cpustate->opcode](cpustate);
|
||||
}
|
||||
|
||||
/* Two-byte opcode prefix */
|
||||
static void I386OP(decode_two_byte)(i386_state *cpustate)
|
||||
{
|
||||
cpustate->opcode = FETCH(cpustate);
|
||||
if( cpustate->operand_size )
|
||||
cpustate->opcode_table2_32[cpustate->opcode](cpustate);
|
||||
else
|
||||
cpustate->opcode_table2_16[cpustate->opcode](cpustate);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static void build_opcode_table(i386_state *cpustate, UINT32 features)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i < 256; i++)
|
||||
{
|
||||
cpustate->opcode_table1_16[i] = I386OP(invalid);
|
||||
cpustate->opcode_table1_32[i] = I386OP(invalid);
|
||||
cpustate->opcode_table2_16[i] = I386OP(invalid);
|
||||
cpustate->opcode_table2_32[i] = I386OP(invalid);
|
||||
}
|
||||
|
||||
for (i=0; i < sizeof(x86_opcode_table)/sizeof(X86_OPCODE); i++)
|
||||
{
|
||||
const X86_OPCODE *op = &x86_opcode_table[i];
|
||||
|
||||
if ((op->flags & features))
|
||||
{
|
||||
if (op->flags & OP_2BYTE)
|
||||
{
|
||||
cpustate->opcode_table2_32[op->opcode] = op->handler32;
|
||||
cpustate->opcode_table2_16[op->opcode] = op->handler16;
|
||||
}
|
||||
else
|
||||
{
|
||||
cpustate->opcode_table1_32[op->opcode] = op->handler32;
|
||||
cpustate->opcode_table1_16[op->opcode] = op->handler16;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
|
||||
The interface of the CPU core (MAME 0.78 style): one context, copied
|
||||
in and out by the CPU switch
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
static i386_state I;
|
||||
|
||||
static void i386_postload(void)
|
||||
{
|
||||
i386_state *cpustate = &I;
|
||||
int i;
|
||||
for (i = 0; i < 6; i++)
|
||||
i386_load_segment_descriptor(cpustate,i);
|
||||
CHANGE_PC(cpustate,cpustate->eip);
|
||||
}
|
||||
|
||||
/* the fast memory regions of the driver */
|
||||
static struct
|
||||
{
|
||||
UINT32 start, end;
|
||||
UINT8 *base;
|
||||
int flags;
|
||||
} i386_fastmem[I386_FASTMEM_MAX];
|
||||
static int i386_fastmem_count;
|
||||
|
||||
void i386_set_fastmem(UINT32 start, UINT32 end, UINT8 *base, int flags)
|
||||
{
|
||||
if (i386_fastmem_count < I386_FASTMEM_MAX)
|
||||
{
|
||||
i386_fastmem[i386_fastmem_count].start = start;
|
||||
i386_fastmem[i386_fastmem_count].end = end;
|
||||
i386_fastmem[i386_fastmem_count].base = base;
|
||||
i386_fastmem[i386_fastmem_count].flags = flags;
|
||||
i386_fastmem_count++;
|
||||
}
|
||||
/* empty the caches */
|
||||
memset(I.fast_size, 0, sizeof(I.fast_size));
|
||||
}
|
||||
|
||||
/* a miss of the cache: the region of the address, cached; NULL if none */
|
||||
static UINT8 *i386_fast_lookup(i386_state *cpustate, UINT32 address, UINT32 len, int kind)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < i386_fastmem_count; i++)
|
||||
{
|
||||
if ((i386_fastmem[i].flags & (1 << kind)) && address >= i386_fastmem[i].start &&
|
||||
address <= i386_fastmem[i].end && i386_fastmem[i].end - address >= len - 1)
|
||||
{
|
||||
cpustate->fast_start[kind] = i386_fastmem[i].start;
|
||||
cpustate->fast_size[kind] = i386_fastmem[i].end - i386_fastmem[i].start + 1;
|
||||
cpustate->fast_base[kind] = i386_fastmem[i].base;
|
||||
return i386_fastmem[i].base + (address - i386_fastmem[i].start);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void i386_init(void)
|
||||
{
|
||||
int i, j;
|
||||
static const int regs8[8] = {AL,CL,DL,BL,AH,CH,DH,BH};
|
||||
static const int regs16[8] = {AX,CX,DX,BX,SP,BP,SI,DI};
|
||||
static const int regs32[8] = {EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI};
|
||||
int cpu = cpu_getactivecpu();
|
||||
i386_state *cpustate = &I;
|
||||
static const char *const sregname[6] = { "es", "cs", "ss", "ds", "fs", "gs" };
|
||||
|
||||
i386_fastmem_count = 0;
|
||||
memset(I.fast_size, 0, sizeof(I.fast_size));
|
||||
build_cycle_table();
|
||||
|
||||
for( i=0; i < 256; i++ ) {
|
||||
int c=0;
|
||||
for( j=0; j < 8; j++ ) {
|
||||
if( i & (1 << j) )
|
||||
c++;
|
||||
}
|
||||
i386_parity_table[i] = ~(c & 0x1) & 0x1;
|
||||
}
|
||||
|
||||
for( i=0; i < 256; i++ ) {
|
||||
i386_MODRM_table[i].reg.b = regs8[(i >> 3) & 0x7];
|
||||
i386_MODRM_table[i].reg.w = regs16[(i >> 3) & 0x7];
|
||||
i386_MODRM_table[i].reg.d = regs32[(i >> 3) & 0x7];
|
||||
|
||||
i386_MODRM_table[i].rm.b = regs8[i & 0x7];
|
||||
i386_MODRM_table[i].rm.w = regs16[i & 0x7];
|
||||
i386_MODRM_table[i].rm.d = regs32[i & 0x7];
|
||||
}
|
||||
|
||||
state_save_register_UINT32("i386", cpu, "reg", cpustate->reg.d, 8);
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
char name[16];
|
||||
sprintf(name, "%s_sel", sregname[i]);
|
||||
state_save_register_UINT16("i386", cpu, name, &cpustate->sreg[i].selector, 1);
|
||||
sprintf(name, "%s_flags", sregname[i]);
|
||||
state_save_register_UINT16("i386", cpu, name, &cpustate->sreg[i].flags, 1);
|
||||
sprintf(name, "%s_base", sregname[i]);
|
||||
state_save_register_UINT32("i386", cpu, name, &cpustate->sreg[i].base, 1);
|
||||
sprintf(name, "%s_limit", sregname[i]);
|
||||
state_save_register_UINT32("i386", cpu, name, &cpustate->sreg[i].limit, 1);
|
||||
sprintf(name, "%s_d", sregname[i]);
|
||||
state_save_register_int("i386", cpu, name, &cpustate->sreg[i].d);
|
||||
}
|
||||
state_save_register_UINT32("i386", cpu, "eip", &cpustate->eip, 1);
|
||||
state_save_register_UINT32("i386", cpu, "pc", &cpustate->pc, 1);
|
||||
state_save_register_UINT32("i386", cpu, "prev_eip", &cpustate->prev_eip, 1);
|
||||
state_save_register_UINT32("i386", cpu, "eflags", &cpustate->eflags, 1);
|
||||
state_save_register_UINT32("i386", cpu, "eflags_mask", &cpustate->eflags_mask, 1);
|
||||
state_save_register_UINT8("i386", cpu, "CF", &cpustate->CF, 1);
|
||||
state_save_register_UINT8("i386", cpu, "DF", &cpustate->DF, 1);
|
||||
state_save_register_UINT8("i386", cpu, "SF", &cpustate->SF, 1);
|
||||
state_save_register_UINT8("i386", cpu, "OF", &cpustate->OF, 1);
|
||||
state_save_register_UINT8("i386", cpu, "ZF", &cpustate->ZF, 1);
|
||||
state_save_register_UINT8("i386", cpu, "PF", &cpustate->PF, 1);
|
||||
state_save_register_UINT8("i386", cpu, "AF", &cpustate->AF, 1);
|
||||
state_save_register_UINT8("i386", cpu, "IF", &cpustate->IF, 1);
|
||||
state_save_register_UINT8("i386", cpu, "TF", &cpustate->TF, 1);
|
||||
state_save_register_UINT8("i386", cpu, "IOP1", &cpustate->IOP1, 1);
|
||||
state_save_register_UINT8("i386", cpu, "IOP2", &cpustate->IOP2, 1);
|
||||
state_save_register_UINT8("i386", cpu, "NT", &cpustate->NT, 1);
|
||||
state_save_register_UINT32("i386", cpu, "cr", cpustate->cr, 5);
|
||||
state_save_register_UINT32("i386", cpu, "dr", cpustate->dr, 8);
|
||||
state_save_register_UINT32("i386", cpu, "tr", cpustate->tr, 8);
|
||||
state_save_register_UINT32("i386", cpu, "idtr_base", &cpustate->idtr.base, 1);
|
||||
state_save_register_UINT16("i386", cpu, "idtr_limit", &cpustate->idtr.limit, 1);
|
||||
state_save_register_UINT32("i386", cpu, "gdtr_base", &cpustate->gdtr.base, 1);
|
||||
state_save_register_UINT16("i386", cpu, "gdtr_limit", &cpustate->gdtr.limit, 1);
|
||||
state_save_register_UINT32("i386", cpu, "task_base", &cpustate->task.base, 1);
|
||||
state_save_register_UINT16("i386", cpu, "task_segment", &cpustate->task.segment, 1);
|
||||
state_save_register_UINT32("i386", cpu, "task_limit", &cpustate->task.limit, 1);
|
||||
state_save_register_UINT16("i386", cpu, "task_flags", &cpustate->task.flags, 1);
|
||||
state_save_register_UINT32("i386", cpu, "ldtr_base", &cpustate->ldtr.base, 1);
|
||||
state_save_register_UINT16("i386", cpu, "ldtr_segment", &cpustate->ldtr.segment, 1);
|
||||
state_save_register_UINT32("i386", cpu, "ldtr_limit", &cpustate->ldtr.limit, 1);
|
||||
state_save_register_UINT16("i386", cpu, "ldtr_flags", &cpustate->ldtr.flags, 1);
|
||||
state_save_register_int("i386", cpu, "halted", &cpustate->halted);
|
||||
state_save_register_UINT8("i386", cpu, "irq_state", &cpustate->irq_state, 1);
|
||||
state_save_register_UINT8("i386", cpu, "performed_intersegment_jump", &cpustate->performed_intersegment_jump, 1);
|
||||
state_save_register_UINT32("i386", cpu, "a20_mask", &cpustate->a20_mask, 1);
|
||||
state_save_register_func_postload(i386_postload);
|
||||
}
|
||||
|
||||
void i386_reset(void *param)
|
||||
{
|
||||
i386_state *cpustate = &I;
|
||||
int (*save_irqcallback)(int);
|
||||
|
||||
save_irqcallback = cpustate->irq_callback;
|
||||
memset( cpustate, 0, sizeof(*cpustate) );
|
||||
cpustate->irq_callback = save_irqcallback;
|
||||
|
||||
cpustate->sreg[CS].selector = 0xf000;
|
||||
cpustate->sreg[CS].base = 0xffff0000;
|
||||
cpustate->sreg[CS].limit = 0xffff;
|
||||
|
||||
cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000;
|
||||
cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff;
|
||||
cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0092;
|
||||
|
||||
cpustate->idtr.base = 0;
|
||||
cpustate->idtr.limit = 0x3ff;
|
||||
|
||||
cpustate->a20_mask = ~0;
|
||||
|
||||
cpustate->cr[0] = 0x7ffffff0; /* reserved bits set to 1 */
|
||||
cpustate->eflags = 0;
|
||||
cpustate->eflags_mask = 0x00030000;
|
||||
cpustate->eip = 0xfff0;
|
||||
|
||||
/* Family 3 (386), Model 0 (DX), Stepping 8 (D1) */
|
||||
REG32(EAX) = 0;
|
||||
REG32(EDX) = (3 << 8) | (0 << 4) | (8);
|
||||
|
||||
build_opcode_table(cpustate, OP_I386);
|
||||
cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_I386];
|
||||
cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_I386];
|
||||
|
||||
CHANGE_PC(cpustate,cpustate->eip);
|
||||
}
|
||||
|
||||
void i386_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
int i386_execute(int cycles)
|
||||
{
|
||||
i386_state *cpustate = &I;
|
||||
|
||||
i386_ICount = cycles;
|
||||
cpustate->base_cycles = cycles;
|
||||
CHANGE_PC(cpustate,cpustate->eip);
|
||||
|
||||
if (cpustate->halted)
|
||||
{
|
||||
cpustate->tsc += cycles;
|
||||
i386_ICount = 0;
|
||||
return cycles;
|
||||
}
|
||||
|
||||
while( i386_ICount > 0 )
|
||||
{
|
||||
cpustate->operand_size = cpustate->sreg[CS].d;
|
||||
cpustate->address_size = cpustate->sreg[CS].d;
|
||||
|
||||
cpustate->segment_prefix = 0;
|
||||
cpustate->prev_eip = cpustate->eip;
|
||||
|
||||
CALL_MAME_DEBUG;
|
||||
|
||||
i386_check_irq_line(cpustate);
|
||||
I386OP(decode_opcode)(cpustate);
|
||||
}
|
||||
cpustate->tsc += (cycles - i386_ICount);
|
||||
return cycles - i386_ICount;
|
||||
}
|
||||
|
||||
unsigned i386_get_context(void *dst)
|
||||
{
|
||||
if (dst)
|
||||
*(i386_state *)dst = I;
|
||||
return sizeof(i386_state);
|
||||
}
|
||||
|
||||
void i386_set_context(void *src)
|
||||
{
|
||||
if (src)
|
||||
I = *(i386_state *)src;
|
||||
}
|
||||
|
||||
unsigned i386_get_reg(int regnum)
|
||||
{
|
||||
i386_state *cpustate = &I;
|
||||
|
||||
switch (regnum)
|
||||
{
|
||||
case REG_PC: return cpustate->pc;
|
||||
case REG_PREVIOUSPC: return cpustate->sreg[CS].base + cpustate->prev_eip;
|
||||
case REG_SP: return cpustate->sreg[SS].base + REG32(ESP);
|
||||
case I386_EIP: return cpustate->eip;
|
||||
case I386_EAX: return REG32(EAX);
|
||||
case I386_EBX: return REG32(EBX);
|
||||
case I386_ECX: return REG32(ECX);
|
||||
case I386_EDX: return REG32(EDX);
|
||||
case I386_ESI: return REG32(ESI);
|
||||
case I386_EDI: return REG32(EDI);
|
||||
case I386_EBP: return REG32(EBP);
|
||||
case I386_ESP: return REG32(ESP);
|
||||
case I386_EFLAGS: return get_flags(cpustate);
|
||||
case I386_CS: return cpustate->sreg[CS].selector;
|
||||
case I386_SS: return cpustate->sreg[SS].selector;
|
||||
case I386_DS: return cpustate->sreg[DS].selector;
|
||||
case I386_ES: return cpustate->sreg[ES].selector;
|
||||
case I386_FS: return cpustate->sreg[FS].selector;
|
||||
case I386_GS: return cpustate->sreg[GS].selector;
|
||||
case I386_CR0: return cpustate->cr[0];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i386_set_reg(int regnum, unsigned val)
|
||||
{
|
||||
i386_state *cpustate = &I;
|
||||
|
||||
switch (regnum)
|
||||
{
|
||||
case REG_PC:
|
||||
cpustate->eip = val - cpustate->sreg[CS].base;
|
||||
CHANGE_PC(cpustate,cpustate->eip);
|
||||
break;
|
||||
case REG_SP: REG32(ESP) = val - cpustate->sreg[SS].base; break;
|
||||
case I386_EIP: cpustate->eip = val; CHANGE_PC(cpustate,cpustate->eip); break;
|
||||
case I386_EAX: REG32(EAX) = val; break;
|
||||
case I386_EBX: REG32(EBX) = val; break;
|
||||
case I386_ECX: REG32(ECX) = val; break;
|
||||
case I386_EDX: REG32(EDX) = val; break;
|
||||
case I386_ESI: REG32(ESI) = val; break;
|
||||
case I386_EDI: REG32(EDI) = val; break;
|
||||
case I386_EBP: REG32(EBP) = val; break;
|
||||
case I386_ESP: REG32(ESP) = val; break;
|
||||
case I386_EFLAGS: set_flags(cpustate, val); break;
|
||||
}
|
||||
}
|
||||
|
||||
void i386_set_irq_line(int irqline, int state)
|
||||
{
|
||||
i386_state *cpustate = &I;
|
||||
|
||||
if (state != CLEAR_LINE && cpustate->halted)
|
||||
{
|
||||
cpustate->halted = 0;
|
||||
}
|
||||
|
||||
if ( irqline == IRQ_LINE_NMI )
|
||||
{
|
||||
/* NMI (I do not think that this is 100% right) */
|
||||
if ( state )
|
||||
i386_trap(cpustate,2, 1);
|
||||
}
|
||||
else if ( irqline == I386_INPUT_LINE_A20 )
|
||||
{
|
||||
cpustate->a20_mask = state ? ~0 : ~(1 << 20);
|
||||
}
|
||||
else
|
||||
{
|
||||
cpustate->irq_state = state;
|
||||
}
|
||||
}
|
||||
|
||||
void i386_set_irq_callback(int (*callback)(int irqline))
|
||||
{
|
||||
I.irq_callback = callback;
|
||||
}
|
||||
|
||||
const char *i386_info(void *context, int regnum)
|
||||
{
|
||||
static char buffer[16][47+1];
|
||||
static int which = 0;
|
||||
i386_state *r = context ? (i386_state *)context : &I;
|
||||
|
||||
which = (which + 1) % 16;
|
||||
buffer[which][0] = '\0';
|
||||
|
||||
switch( regnum )
|
||||
{
|
||||
case CPU_INFO_REG+I386_EIP: sprintf(buffer[which], "EIP:%08X", r->eip); break;
|
||||
case CPU_INFO_REG+I386_EAX: sprintf(buffer[which], "EAX:%08X", r->reg.d[EAX]); break;
|
||||
case CPU_INFO_REG+I386_EBX: sprintf(buffer[which], "EBX:%08X", r->reg.d[EBX]); break;
|
||||
case CPU_INFO_REG+I386_ECX: sprintf(buffer[which], "ECX:%08X", r->reg.d[ECX]); break;
|
||||
case CPU_INFO_REG+I386_EDX: sprintf(buffer[which], "EDX:%08X", r->reg.d[EDX]); break;
|
||||
case CPU_INFO_REG+I386_ESI: sprintf(buffer[which], "ESI:%08X", r->reg.d[ESI]); break;
|
||||
case CPU_INFO_REG+I386_EDI: sprintf(buffer[which], "EDI:%08X", r->reg.d[EDI]); break;
|
||||
case CPU_INFO_REG+I386_EBP: sprintf(buffer[which], "EBP:%08X", r->reg.d[EBP]); break;
|
||||
case CPU_INFO_REG+I386_ESP: sprintf(buffer[which], "ESP:%08X", r->reg.d[ESP]); break;
|
||||
case CPU_INFO_FLAGS: sprintf(buffer[which], "%08X", r->eflags); break;
|
||||
case CPU_INFO_NAME: return "I386";
|
||||
case CPU_INFO_FAMILY: return "Intel 386";
|
||||
case CPU_INFO_VERSION: return "1.0";
|
||||
case CPU_INFO_FILE: return __FILE__;
|
||||
case CPU_INFO_CREDITS: return "Copyright Ville Linde";
|
||||
}
|
||||
return buffer[which];
|
||||
}
|
||||
|
||||
unsigned i386_dasm(char *buffer, unsigned pc)
|
||||
{
|
||||
sprintf(buffer, "$%02X", cpu_readmem32ledw(pc));
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/***************************************************************************
|
||||
|
||||
Intel 386 emulator (Ville Linde), from MAME 0.139
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef I386INTF_H
|
||||
#define I386INTF_H
|
||||
|
||||
#include "cpuintrf.h"
|
||||
|
||||
/* the A20 gate, as an input line */
|
||||
#define I386_INPUT_LINE_A20 1
|
||||
|
||||
extern int i386_ICount;
|
||||
|
||||
/* the fast memory: a range of plain RAM or ROM at base, which the CPU */
|
||||
/* fetches, reads or writes directly (flags), without the memory handlers; */
|
||||
/* set from DRIVER_INIT, emptied at the CPU init. Little endian hosts only */
|
||||
#define I386_FASTMEM_MAX 8
|
||||
#define I386_FASTMEM_FETCH 1
|
||||
#define I386_FASTMEM_READ 2
|
||||
#define I386_FASTMEM_WRITE 4
|
||||
void i386_set_fastmem(UINT32 start, UINT32 end, UINT8 *base, int flags);
|
||||
|
||||
void i386_init(void);
|
||||
void i386_reset(void *param);
|
||||
void i386_exit(void);
|
||||
int i386_execute(int cycles);
|
||||
unsigned i386_get_context(void *dst);
|
||||
void i386_set_context(void *src);
|
||||
unsigned i386_get_reg(int regnum);
|
||||
void i386_set_reg(int regnum, unsigned val);
|
||||
void i386_set_irq_line(int irqline, int state);
|
||||
void i386_set_irq_callback(int (*callback)(int irqline));
|
||||
const char *i386_info(void *context, int regnum);
|
||||
unsigned i386_dasm(char *buffer, unsigned pc);
|
||||
|
||||
#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,377 @@
|
||||
typedef struct {
|
||||
UINT8 opcode;
|
||||
UINT32 flags;
|
||||
void (*handler16)(i386_state *cpustate);
|
||||
void (*handler32)(i386_state *cpustate);
|
||||
} X86_OPCODE;
|
||||
|
||||
#define OP_I386 0x1
|
||||
#define OP_FPU 0x2
|
||||
#define OP_I486 0x4
|
||||
#define OP_PENTIUM 0x8
|
||||
#define OP_MMX 0x10
|
||||
#define OP_PPRO 0x20
|
||||
#define OP_SSE 0x40
|
||||
#define OP_SSE2 0x80
|
||||
#define OP_SSE3 0x100
|
||||
#define OP_CYRIX 0x8000
|
||||
#define OP_2BYTE 0x80000000
|
||||
|
||||
static const X86_OPCODE x86_opcode_table[] =
|
||||
{
|
||||
/* Opcode Flags 16-bit handler 32-bit handler */
|
||||
{ 0x00, OP_I386, I386OP(add_rm8_r8), I386OP(add_rm8_r8), },
|
||||
{ 0x01, OP_I386, I386OP(add_rm16_r16), I386OP(add_rm32_r32), },
|
||||
{ 0x02, OP_I386, I386OP(add_r8_rm8), I386OP(add_r8_rm8), },
|
||||
{ 0x03, OP_I386, I386OP(add_r16_rm16), I386OP(add_r32_rm32), },
|
||||
{ 0x04, OP_I386, I386OP(add_al_i8), I386OP(add_al_i8), },
|
||||
{ 0x05, OP_I386, I386OP(add_ax_i16), I386OP(add_eax_i32), },
|
||||
{ 0x06, OP_I386, I386OP(push_es16), I386OP(push_es32), },
|
||||
{ 0x07, OP_I386, I386OP(pop_es16), I386OP(pop_es32), },
|
||||
{ 0x08, OP_I386, I386OP(or_rm8_r8), I386OP(or_rm8_r8), },
|
||||
{ 0x09, OP_I386, I386OP(or_rm16_r16), I386OP(or_rm32_r32), },
|
||||
{ 0x0A, OP_I386, I386OP(or_r8_rm8), I386OP(or_r8_rm8), },
|
||||
{ 0x0B, OP_I386, I386OP(or_r16_rm16), I386OP(or_r32_rm32), },
|
||||
{ 0x0C, OP_I386, I386OP(or_al_i8), I386OP(or_al_i8), },
|
||||
{ 0x0D, OP_I386, I386OP(or_ax_i16), I386OP(or_eax_i32), },
|
||||
{ 0x0E, OP_I386, I386OP(push_cs16), I386OP(push_cs32), },
|
||||
{ 0x0F, OP_I386, I386OP(decode_two_byte), I386OP(decode_two_byte), },
|
||||
{ 0x10, OP_I386, I386OP(adc_rm8_r8), I386OP(adc_rm8_r8), },
|
||||
{ 0x11, OP_I386, I386OP(adc_rm16_r16), I386OP(adc_rm32_r32), },
|
||||
{ 0x12, OP_I386, I386OP(adc_r8_rm8), I386OP(adc_r8_rm8), },
|
||||
{ 0x13, OP_I386, I386OP(adc_r16_rm16), I386OP(adc_r32_rm32), },
|
||||
{ 0x14, OP_I386, I386OP(adc_al_i8), I386OP(adc_al_i8), },
|
||||
{ 0x15, OP_I386, I386OP(adc_ax_i16), I386OP(adc_eax_i32), },
|
||||
{ 0x16, OP_I386, I386OP(push_ss16), I386OP(push_ss32), },
|
||||
{ 0x17, OP_I386, I386OP(pop_ss16), I386OP(pop_ss32), },
|
||||
{ 0x18, OP_I386, I386OP(sbb_rm8_r8), I386OP(sbb_rm8_r8), },
|
||||
{ 0x19, OP_I386, I386OP(sbb_rm16_r16), I386OP(sbb_rm32_r32), },
|
||||
{ 0x1A, OP_I386, I386OP(sbb_r8_rm8), I386OP(sbb_r8_rm8), },
|
||||
{ 0x1B, OP_I386, I386OP(sbb_r16_rm16), I386OP(sbb_r32_rm32), },
|
||||
{ 0x1C, OP_I386, I386OP(sbb_al_i8), I386OP(sbb_al_i8), },
|
||||
{ 0x1D, OP_I386, I386OP(sbb_ax_i16), I386OP(sbb_eax_i32), },
|
||||
{ 0x1E, OP_I386, I386OP(push_ds16), I386OP(push_ds32), },
|
||||
{ 0x1F, OP_I386, I386OP(pop_ds16), I386OP(pop_ds32), },
|
||||
{ 0x20, OP_I386, I386OP(and_rm8_r8), I386OP(and_rm8_r8), },
|
||||
{ 0x21, OP_I386, I386OP(and_rm16_r16), I386OP(and_rm32_r32), },
|
||||
{ 0x22, OP_I386, I386OP(and_r8_rm8), I386OP(and_r8_rm8), },
|
||||
{ 0x23, OP_I386, I386OP(and_r16_rm16), I386OP(and_r32_rm32), },
|
||||
{ 0x24, OP_I386, I386OP(and_al_i8), I386OP(and_al_i8), },
|
||||
{ 0x25, OP_I386, I386OP(and_ax_i16), I386OP(and_eax_i32), },
|
||||
{ 0x26, OP_I386, I386OP(segment_ES), I386OP(segment_ES), },
|
||||
{ 0x27, OP_I386, I386OP(daa), I386OP(daa), },
|
||||
{ 0x28, OP_I386, I386OP(sub_rm8_r8), I386OP(sub_rm8_r8), },
|
||||
{ 0x29, OP_I386, I386OP(sub_rm16_r16), I386OP(sub_rm32_r32), },
|
||||
{ 0x2A, OP_I386, I386OP(sub_r8_rm8), I386OP(sub_r8_rm8), },
|
||||
{ 0x2B, OP_I386, I386OP(sub_r16_rm16), I386OP(sub_r32_rm32), },
|
||||
{ 0x2C, OP_I386, I386OP(sub_al_i8), I386OP(sub_al_i8), },
|
||||
{ 0x2D, OP_I386, I386OP(sub_ax_i16), I386OP(sub_eax_i32), },
|
||||
{ 0x2E, OP_I386, I386OP(segment_CS), I386OP(segment_CS), },
|
||||
{ 0x2F, OP_I386, I386OP(das), I386OP(das), },
|
||||
{ 0x30, OP_I386, I386OP(xor_rm8_r8), I386OP(xor_rm8_r8), },
|
||||
{ 0x31, OP_I386, I386OP(xor_rm16_r16), I386OP(xor_rm32_r32), },
|
||||
{ 0x32, OP_I386, I386OP(xor_r8_rm8), I386OP(xor_r8_rm8), },
|
||||
{ 0x33, OP_I386, I386OP(xor_r16_rm16), I386OP(xor_r32_rm32), },
|
||||
{ 0x34, OP_I386, I386OP(xor_al_i8), I386OP(xor_al_i8), },
|
||||
{ 0x35, OP_I386, I386OP(xor_ax_i16), I386OP(xor_eax_i32), },
|
||||
{ 0x36, OP_I386, I386OP(segment_SS), I386OP(segment_SS), },
|
||||
{ 0x37, OP_I386, I386OP(aaa), I386OP(aaa), },
|
||||
{ 0x38, OP_I386, I386OP(cmp_rm8_r8), I386OP(cmp_rm8_r8), },
|
||||
{ 0x39, OP_I386, I386OP(cmp_rm16_r16), I386OP(cmp_rm32_r32), },
|
||||
{ 0x3A, OP_I386, I386OP(cmp_r8_rm8), I386OP(cmp_r8_rm8), },
|
||||
{ 0x3B, OP_I386, I386OP(cmp_r16_rm16), I386OP(cmp_r32_rm32), },
|
||||
{ 0x3C, OP_I386, I386OP(cmp_al_i8), I386OP(cmp_al_i8), },
|
||||
{ 0x3D, OP_I386, I386OP(cmp_ax_i16), I386OP(cmp_eax_i32), },
|
||||
{ 0x3E, OP_I386, I386OP(segment_DS), I386OP(segment_DS), },
|
||||
{ 0x3F, OP_I386, I386OP(aas), I386OP(aas), },
|
||||
{ 0x40, OP_I386, I386OP(inc_ax), I386OP(inc_eax), },
|
||||
{ 0x41, OP_I386, I386OP(inc_cx), I386OP(inc_ecx), },
|
||||
{ 0x42, OP_I386, I386OP(inc_dx), I386OP(inc_edx), },
|
||||
{ 0x43, OP_I386, I386OP(inc_bx), I386OP(inc_ebx), },
|
||||
{ 0x44, OP_I386, I386OP(inc_sp), I386OP(inc_esp), },
|
||||
{ 0x45, OP_I386, I386OP(inc_bp), I386OP(inc_ebp), },
|
||||
{ 0x46, OP_I386, I386OP(inc_si), I386OP(inc_esi), },
|
||||
{ 0x47, OP_I386, I386OP(inc_di), I386OP(inc_edi), },
|
||||
{ 0x48, OP_I386, I386OP(dec_ax), I386OP(dec_eax), },
|
||||
{ 0x49, OP_I386, I386OP(dec_cx), I386OP(dec_ecx), },
|
||||
{ 0x4A, OP_I386, I386OP(dec_dx), I386OP(dec_edx), },
|
||||
{ 0x4B, OP_I386, I386OP(dec_bx), I386OP(dec_ebx), },
|
||||
{ 0x4C, OP_I386, I386OP(dec_sp), I386OP(dec_esp), },
|
||||
{ 0x4D, OP_I386, I386OP(dec_bp), I386OP(dec_ebp), },
|
||||
{ 0x4E, OP_I386, I386OP(dec_si), I386OP(dec_esi), },
|
||||
{ 0x4F, OP_I386, I386OP(dec_di), I386OP(dec_edi), },
|
||||
{ 0x50, OP_I386, I386OP(push_ax), I386OP(push_eax), },
|
||||
{ 0x51, OP_I386, I386OP(push_cx), I386OP(push_ecx), },
|
||||
{ 0x52, OP_I386, I386OP(push_dx), I386OP(push_edx), },
|
||||
{ 0x53, OP_I386, I386OP(push_bx), I386OP(push_ebx), },
|
||||
{ 0x54, OP_I386, I386OP(push_sp), I386OP(push_esp), },
|
||||
{ 0x55, OP_I386, I386OP(push_bp), I386OP(push_ebp), },
|
||||
{ 0x56, OP_I386, I386OP(push_si), I386OP(push_esi), },
|
||||
{ 0x57, OP_I386, I386OP(push_di), I386OP(push_edi), },
|
||||
{ 0x58, OP_I386, I386OP(pop_ax), I386OP(pop_eax), },
|
||||
{ 0x59, OP_I386, I386OP(pop_cx), I386OP(pop_ecx), },
|
||||
{ 0x5A, OP_I386, I386OP(pop_dx), I386OP(pop_edx), },
|
||||
{ 0x5B, OP_I386, I386OP(pop_bx), I386OP(pop_ebx), },
|
||||
{ 0x5C, OP_I386, I386OP(pop_sp), I386OP(pop_esp), },
|
||||
{ 0x5D, OP_I386, I386OP(pop_bp), I386OP(pop_ebp), },
|
||||
{ 0x5E, OP_I386, I386OP(pop_si), I386OP(pop_esi), },
|
||||
{ 0x5F, OP_I386, I386OP(pop_di), I386OP(pop_edi), },
|
||||
{ 0x60, OP_I386, I386OP(pusha), I386OP(pushad), },
|
||||
{ 0x61, OP_I386, I386OP(popa), I386OP(popad), },
|
||||
{ 0x62, OP_I386, I386OP(bound_r16_m16_m16), I386OP(bound_r32_m32_m32), },
|
||||
{ 0x63, OP_I386, I386OP(arpl), I386OP(arpl), },
|
||||
{ 0x64, OP_I386, I386OP(segment_FS), I386OP(segment_FS), },
|
||||
{ 0x65, OP_I386, I386OP(segment_GS), I386OP(segment_GS), },
|
||||
{ 0x66, OP_I386, I386OP(operand_size), I386OP(operand_size), },
|
||||
{ 0x67, OP_I386, I386OP(address_size), I386OP(address_size), },
|
||||
{ 0x68, OP_I386, I386OP(push_i16), I386OP(push_i32), },
|
||||
{ 0x69, OP_I386, I386OP(imul_r16_rm16_i16), I386OP(imul_r32_rm32_i32), },
|
||||
{ 0x6A, OP_I386, I386OP(push_i8), I386OP(push_i8), },
|
||||
{ 0x6B, OP_I386, I386OP(imul_r16_rm16_i8), I386OP(imul_r32_rm32_i8), },
|
||||
{ 0x6C, OP_I386, I386OP(insb), I386OP(insb), },
|
||||
{ 0x6D, OP_I386, I386OP(insw), I386OP(insd), },
|
||||
{ 0x6E, OP_I386, I386OP(outsb), I386OP(outsb), },
|
||||
{ 0x6F, OP_I386, I386OP(outsw), I386OP(outsd), },
|
||||
{ 0x70, OP_I386, I386OP(jo_rel8), I386OP(jo_rel8), },
|
||||
{ 0x71, OP_I386, I386OP(jno_rel8), I386OP(jno_rel8), },
|
||||
{ 0x72, OP_I386, I386OP(jc_rel8), I386OP(jc_rel8), },
|
||||
{ 0x73, OP_I386, I386OP(jnc_rel8), I386OP(jnc_rel8), },
|
||||
{ 0x74, OP_I386, I386OP(jz_rel8), I386OP(jz_rel8), },
|
||||
{ 0x75, OP_I386, I386OP(jnz_rel8), I386OP(jnz_rel8), },
|
||||
{ 0x76, OP_I386, I386OP(jbe_rel8), I386OP(jbe_rel8), },
|
||||
{ 0x77, OP_I386, I386OP(ja_rel8), I386OP(ja_rel8), },
|
||||
{ 0x78, OP_I386, I386OP(js_rel8), I386OP(js_rel8), },
|
||||
{ 0x79, OP_I386, I386OP(jns_rel8), I386OP(jns_rel8), },
|
||||
{ 0x7A, OP_I386, I386OP(jp_rel8), I386OP(jp_rel8), },
|
||||
{ 0x7B, OP_I386, I386OP(jnp_rel8), I386OP(jnp_rel8), },
|
||||
{ 0x7C, OP_I386, I386OP(jl_rel8), I386OP(jl_rel8), },
|
||||
{ 0x7D, OP_I386, I386OP(jge_rel8), I386OP(jge_rel8), },
|
||||
{ 0x7E, OP_I386, I386OP(jle_rel8), I386OP(jle_rel8), },
|
||||
{ 0x7F, OP_I386, I386OP(jg_rel8), I386OP(jg_rel8), },
|
||||
{ 0x80, OP_I386, I386OP(group80_8), I386OP(group80_8), },
|
||||
{ 0x81, OP_I386, I386OP(group81_16), I386OP(group81_32), },
|
||||
{ 0x82, OP_I386, I386OP(group80_8), I386OP(group80_8), },
|
||||
{ 0x83, OP_I386, I386OP(group83_16), I386OP(group83_32), },
|
||||
{ 0x84, OP_I386, I386OP(test_rm8_r8), I386OP(test_rm8_r8), },
|
||||
{ 0x85, OP_I386, I386OP(test_rm16_r16), I386OP(test_rm32_r32), },
|
||||
{ 0x86, OP_I386, I386OP(xchg_r8_rm8), I386OP(xchg_r8_rm8), },
|
||||
{ 0x87, OP_I386, I386OP(xchg_r16_rm16), I386OP(xchg_r32_rm32), },
|
||||
{ 0x88, OP_I386, I386OP(mov_rm8_r8), I386OP(mov_rm8_r8), },
|
||||
{ 0x89, OP_I386, I386OP(mov_rm16_r16), I386OP(mov_rm32_r32), },
|
||||
{ 0x8A, OP_I386, I386OP(mov_r8_rm8), I386OP(mov_r8_rm8), },
|
||||
{ 0x8B, OP_I386, I386OP(mov_r16_rm16), I386OP(mov_r32_rm32), },
|
||||
{ 0x8C, OP_I386, I386OP(mov_rm16_sreg), I386OP(mov_rm16_sreg), },
|
||||
{ 0x8D, OP_I386, I386OP(lea16), I386OP(lea32), },
|
||||
{ 0x8E, OP_I386, I386OP(mov_sreg_rm16), I386OP(mov_sreg_rm16), },
|
||||
{ 0x8F, OP_I386, I386OP(pop_rm16), I386OP(pop_rm32), },
|
||||
{ 0x90, OP_I386, I386OP(nop), I386OP(nop), },
|
||||
{ 0x91, OP_I386, I386OP(xchg_ax_cx), I386OP(xchg_eax_ecx), },
|
||||
{ 0x92, OP_I386, I386OP(xchg_ax_dx), I386OP(xchg_eax_edx), },
|
||||
{ 0x93, OP_I386, I386OP(xchg_ax_bx), I386OP(xchg_eax_ebx), },
|
||||
{ 0x94, OP_I386, I386OP(xchg_ax_sp), I386OP(xchg_eax_esp), },
|
||||
{ 0x95, OP_I386, I386OP(xchg_ax_bp), I386OP(xchg_eax_ebp), },
|
||||
{ 0x96, OP_I386, I386OP(xchg_ax_si), I386OP(xchg_eax_esi), },
|
||||
{ 0x97, OP_I386, I386OP(xchg_ax_di), I386OP(xchg_eax_edi), },
|
||||
{ 0x98, OP_I386, I386OP(cbw), I386OP(cwde), },
|
||||
{ 0x99, OP_I386, I386OP(cwd), I386OP(cdq), },
|
||||
{ 0x9A, OP_I386, I386OP(call_abs16), I386OP(call_abs32), },
|
||||
{ 0x9B, OP_I386, I386OP(wait), I386OP(wait), },
|
||||
{ 0x9C, OP_I386, I386OP(pushf), I386OP(pushfd), },
|
||||
{ 0x9D, OP_I386, I386OP(popf), I386OP(popfd), },
|
||||
{ 0x9E, OP_I386, I386OP(sahf), I386OP(sahf), },
|
||||
{ 0x9F, OP_I386, I386OP(lahf), I386OP(lahf), },
|
||||
{ 0xA0, OP_I386, I386OP(mov_al_m8), I386OP(mov_al_m8), },
|
||||
{ 0xA1, OP_I386, I386OP(mov_ax_m16), I386OP(mov_eax_m32), },
|
||||
{ 0xA2, OP_I386, I386OP(mov_m8_al), I386OP(mov_m8_al), },
|
||||
{ 0xA3, OP_I386, I386OP(mov_m16_ax), I386OP(mov_m32_eax), },
|
||||
{ 0xA4, OP_I386, I386OP(movsb), I386OP(movsb), },
|
||||
{ 0xA5, OP_I386, I386OP(movsw), I386OP(movsd), },
|
||||
{ 0xA6, OP_I386, I386OP(cmpsb), I386OP(cmpsb), },
|
||||
{ 0xA7, OP_I386, I386OP(cmpsw), I386OP(cmpsd), },
|
||||
{ 0xA8, OP_I386, I386OP(test_al_i8), I386OP(test_al_i8), },
|
||||
{ 0xA9, OP_I386, I386OP(test_ax_i16), I386OP(test_eax_i32), },
|
||||
{ 0xAA, OP_I386, I386OP(stosb), I386OP(stosb), },
|
||||
{ 0xAB, OP_I386, I386OP(stosw), I386OP(stosd), },
|
||||
{ 0xAC, OP_I386, I386OP(lodsb), I386OP(lodsb), },
|
||||
{ 0xAD, OP_I386, I386OP(lodsw), I386OP(lodsd), },
|
||||
{ 0xAE, OP_I386, I386OP(scasb), I386OP(scasb), },
|
||||
{ 0xAF, OP_I386, I386OP(scasw), I386OP(scasd), },
|
||||
{ 0xB0, OP_I386, I386OP(mov_al_i8), I386OP(mov_al_i8), },
|
||||
{ 0xB1, OP_I386, I386OP(mov_cl_i8), I386OP(mov_cl_i8), },
|
||||
{ 0xB2, OP_I386, I386OP(mov_dl_i8), I386OP(mov_dl_i8), },
|
||||
{ 0xB3, OP_I386, I386OP(mov_bl_i8), I386OP(mov_bl_i8), },
|
||||
{ 0xB4, OP_I386, I386OP(mov_ah_i8), I386OP(mov_ah_i8), },
|
||||
{ 0xB5, OP_I386, I386OP(mov_ch_i8), I386OP(mov_ch_i8), },
|
||||
{ 0xB6, OP_I386, I386OP(mov_dh_i8), I386OP(mov_dh_i8), },
|
||||
{ 0xB7, OP_I386, I386OP(mov_bh_i8), I386OP(mov_bh_i8), },
|
||||
{ 0xB8, OP_I386, I386OP(mov_ax_i16), I386OP(mov_eax_i32), },
|
||||
{ 0xB9, OP_I386, I386OP(mov_cx_i16), I386OP(mov_ecx_i32), },
|
||||
{ 0xBA, OP_I386, I386OP(mov_dx_i16), I386OP(mov_edx_i32), },
|
||||
{ 0xBB, OP_I386, I386OP(mov_bx_i16), I386OP(mov_ebx_i32), },
|
||||
{ 0xBC, OP_I386, I386OP(mov_sp_i16), I386OP(mov_esp_i32), },
|
||||
{ 0xBD, OP_I386, I386OP(mov_bp_i16), I386OP(mov_ebp_i32), },
|
||||
{ 0xBE, OP_I386, I386OP(mov_si_i16), I386OP(mov_esi_i32), },
|
||||
{ 0xBF, OP_I386, I386OP(mov_di_i16), I386OP(mov_edi_i32), },
|
||||
{ 0xC0, OP_I386, I386OP(groupC0_8), I386OP(groupC0_8), },
|
||||
{ 0xC1, OP_I386, I386OP(groupC1_16), I386OP(groupC1_32), },
|
||||
{ 0xC2, OP_I386, I386OP(ret_near16_i16), I386OP(ret_near32_i16), },
|
||||
{ 0xC3, OP_I386, I386OP(ret_near16), I386OP(ret_near32), },
|
||||
{ 0xC4, OP_I386, I386OP(les16), I386OP(les32), },
|
||||
{ 0xC5, OP_I386, I386OP(lds16), I386OP(lds32), },
|
||||
{ 0xC6, OP_I386, I386OP(mov_rm8_i8), I386OP(mov_rm8_i8), },
|
||||
{ 0xC7, OP_I386, I386OP(mov_rm16_i16), I386OP(mov_rm32_i32), },
|
||||
{ 0xC8, OP_I386, I386OP(enter16), I386OP(enter32), },
|
||||
{ 0xC9, OP_I386, I386OP(leave16), I386OP(leave32), },
|
||||
{ 0xCA, OP_I386, I386OP(retf_i16), I386OP(retf_i32), },
|
||||
{ 0xCB, OP_I386, I386OP(retf16), I386OP(retf32), },
|
||||
{ 0xCC, OP_I386, I386OP(int3), I386OP(int3), },
|
||||
{ 0xCD, OP_I386, I386OP(int), I386OP(int), },
|
||||
{ 0xCE, OP_I386, I386OP(into), I386OP(into), },
|
||||
{ 0xCF, OP_I386, I386OP(iret16), I386OP(iret32), },
|
||||
{ 0xD0, OP_I386, I386OP(groupD0_8), I386OP(groupD0_8), },
|
||||
{ 0xD1, OP_I386, I386OP(groupD1_16), I386OP(groupD1_32), },
|
||||
{ 0xD2, OP_I386, I386OP(groupD2_8), I386OP(groupD2_8), },
|
||||
{ 0xD3, OP_I386, I386OP(groupD3_16), I386OP(groupD3_32), },
|
||||
{ 0xD4, OP_I386, I386OP(aam), I386OP(aam), },
|
||||
{ 0xD5, OP_I386, I386OP(aad), I386OP(aad), },
|
||||
{ 0xD6, OP_I386, I386OP(setalc), I386OP(setalc), },
|
||||
{ 0xD7, OP_I386, I386OP(xlat16), I386OP(xlat32), },
|
||||
{ 0xD8, OP_I386, I386OP(escape), I386OP(escape), },
|
||||
{ 0xD9, OP_I386, I386OP(escape), I386OP(escape), },
|
||||
{ 0xDA, OP_I386, I386OP(escape), I386OP(escape), },
|
||||
{ 0xDB, OP_I386, I386OP(escape), I386OP(escape), },
|
||||
{ 0xDC, OP_I386, I386OP(escape), I386OP(escape), },
|
||||
{ 0xDD, OP_I386, I386OP(escape), I386OP(escape), },
|
||||
{ 0xDE, OP_I386, I386OP(escape), I386OP(escape), },
|
||||
{ 0xDF, OP_I386, I386OP(escape), I386OP(escape), },
|
||||
{ 0xD8, OP_FPU, I386OP(fpu_group_d8), I386OP(fpu_group_d8), },
|
||||
{ 0xD9, OP_FPU, I386OP(fpu_group_d9), I386OP(fpu_group_d9), },
|
||||
{ 0xDA, OP_FPU, I386OP(fpu_group_da), I386OP(fpu_group_da), },
|
||||
{ 0xDB, OP_FPU, I386OP(fpu_group_db), I386OP(fpu_group_db), },
|
||||
{ 0xDC, OP_FPU, I386OP(fpu_group_dc), I386OP(fpu_group_dc), },
|
||||
{ 0xDD, OP_FPU, I386OP(fpu_group_dd), I386OP(fpu_group_dd), },
|
||||
{ 0xDE, OP_FPU, I386OP(fpu_group_de), I386OP(fpu_group_de), },
|
||||
{ 0xDF, OP_FPU, I386OP(fpu_group_df), I386OP(fpu_group_df), },
|
||||
{ 0xE0, OP_I386, I386OP(loopne16), I386OP(loopne32), },
|
||||
{ 0xE1, OP_I386, I386OP(loopz16), I386OP(loopz32), },
|
||||
{ 0xE2, OP_I386, I386OP(loop16), I386OP(loop32), },
|
||||
{ 0xE3, OP_I386, I386OP(jcxz16), I386OP(jcxz32), },
|
||||
{ 0xE4, OP_I386, I386OP(in_al_i8), I386OP(in_al_i8), },
|
||||
{ 0xE5, OP_I386, I386OP(in_ax_i8), I386OP(in_eax_i8), },
|
||||
{ 0xE6, OP_I386, I386OP(out_al_i8), I386OP(out_al_i8), },
|
||||
{ 0xE7, OP_I386, I386OP(out_ax_i8), I386OP(out_eax_i8), },
|
||||
{ 0xE8, OP_I386, I386OP(call_rel16), I386OP(call_rel32), },
|
||||
{ 0xE9, OP_I386, I386OP(jmp_rel16), I386OP(jmp_rel32), },
|
||||
{ 0xEA, OP_I386, I386OP(jmp_abs16), I386OP(jmp_abs32), },
|
||||
{ 0xEB, OP_I386, I386OP(jmp_rel8), I386OP(jmp_rel8), },
|
||||
{ 0xEC, OP_I386, I386OP(in_al_dx), I386OP(in_al_dx), },
|
||||
{ 0xED, OP_I386, I386OP(in_ax_dx), I386OP(in_eax_dx), },
|
||||
{ 0xEE, OP_I386, I386OP(out_al_dx), I386OP(out_al_dx), },
|
||||
{ 0xEF, OP_I386, I386OP(out_ax_dx), I386OP(out_eax_dx), },
|
||||
{ 0xF0, OP_I386, I386OP(lock), I386OP(lock), },
|
||||
{ 0xF1, OP_I386, I386OP(invalid), I386OP(invalid), },
|
||||
{ 0xF2, OP_I386, I386OP(repne), I386OP(repne), },
|
||||
{ 0xF3, OP_I386, I386OP(rep), I386OP(rep), },
|
||||
{ 0xF4, OP_I386, I386OP(hlt), I386OP(hlt), },
|
||||
{ 0xF5, OP_I386, I386OP(cmc), I386OP(cmc), },
|
||||
{ 0xF6, OP_I386, I386OP(groupF6_8), I386OP(groupF6_8), },
|
||||
{ 0xF7, OP_I386, I386OP(groupF7_16), I386OP(groupF7_32), },
|
||||
{ 0xF8, OP_I386, I386OP(clc), I386OP(clc), },
|
||||
{ 0xF9, OP_I386, I386OP(stc), I386OP(stc), },
|
||||
{ 0xFA, OP_I386, I386OP(cli), I386OP(cli), },
|
||||
{ 0xFB, OP_I386, I386OP(sti), I386OP(sti), },
|
||||
{ 0xFC, OP_I386, I386OP(cld), I386OP(cld), },
|
||||
{ 0xFD, OP_I386, I386OP(std), I386OP(std), },
|
||||
{ 0xFE, OP_I386, I386OP(groupFE_8), I386OP(groupFE_8), },
|
||||
{ 0xFF, OP_I386, I386OP(groupFF_16), I386OP(groupFF_32), },
|
||||
{ 0x00, OP_2BYTE|OP_I386, I386OP(group0F00_16), I386OP(group0F00_32), },
|
||||
{ 0x01, OP_2BYTE|OP_I386, I386OP(group0F01_16), I386OP(group0F01_32), },
|
||||
{ 0x01, OP_2BYTE|OP_I486, I486OP(group0F01_16), I486OP(group0F01_32), },
|
||||
{ 0x02, OP_2BYTE|OP_I386, I386OP(unimplemented), I386OP(unimplemented), },
|
||||
{ 0x03, OP_2BYTE|OP_I386, I386OP(lsl_r16_rm16), I386OP(lsl_r32_rm32), },
|
||||
{ 0x06, OP_2BYTE|OP_I386, I386OP(clts), I386OP(clts), },
|
||||
{ 0x08, OP_2BYTE|OP_I486, I486OP(invd), I486OP(invd), },
|
||||
{ 0x09, OP_2BYTE|OP_I486, I486OP(wbinvd), I486OP(wbinvd), },
|
||||
{ 0x0B, OP_2BYTE|OP_I386, I386OP(unimplemented), I386OP(unimplemented), },
|
||||
{ 0x20, OP_2BYTE|OP_I386, I386OP(mov_r32_cr), I386OP(mov_r32_cr), },
|
||||
{ 0x21, OP_2BYTE|OP_I386, I386OP(mov_r32_dr), I386OP(mov_r32_dr), },
|
||||
{ 0x22, OP_2BYTE|OP_I386, I386OP(mov_cr_r32), I386OP(mov_cr_r32), },
|
||||
{ 0x23, OP_2BYTE|OP_I386, I386OP(mov_dr_r32), I386OP(mov_dr_r32), },
|
||||
{ 0x24, OP_2BYTE|OP_I386, I386OP(mov_r32_tr), I386OP(mov_r32_tr), },
|
||||
{ 0x26, OP_2BYTE|OP_I386, I386OP(mov_tr_r32), I386OP(mov_tr_r32), },
|
||||
{ 0x30, OP_2BYTE|OP_PENTIUM, PENTIUMOP(wrmsr), PENTIUMOP(wrmsr), },
|
||||
{ 0x31, OP_2BYTE|OP_PENTIUM, PENTIUMOP(rdtsc), PENTIUMOP(rdtsc), },
|
||||
{ 0x32, OP_2BYTE|OP_PENTIUM, PENTIUMOP(rdmsr), PENTIUMOP(rdmsr), },
|
||||
{ 0x74, OP_2BYTE|OP_CYRIX, I386OP(cyrix_unknown), I386OP(cyrix_unknown), },
|
||||
{ 0x80, OP_2BYTE|OP_I386, I386OP(jo_rel16), I386OP(jo_rel32), },
|
||||
{ 0x81, OP_2BYTE|OP_I386, I386OP(jno_rel16), I386OP(jno_rel32), },
|
||||
{ 0x82, OP_2BYTE|OP_I386, I386OP(jc_rel16), I386OP(jc_rel32), },
|
||||
{ 0x83, OP_2BYTE|OP_I386, I386OP(jnc_rel16), I386OP(jnc_rel32), },
|
||||
{ 0x84, OP_2BYTE|OP_I386, I386OP(jz_rel16), I386OP(jz_rel32), },
|
||||
{ 0x85, OP_2BYTE|OP_I386, I386OP(jnz_rel16), I386OP(jnz_rel32), },
|
||||
{ 0x86, OP_2BYTE|OP_I386, I386OP(jbe_rel16), I386OP(jbe_rel32), },
|
||||
{ 0x87, OP_2BYTE|OP_I386, I386OP(ja_rel16), I386OP(ja_rel32), },
|
||||
{ 0x88, OP_2BYTE|OP_I386, I386OP(js_rel16), I386OP(js_rel32), },
|
||||
{ 0x89, OP_2BYTE|OP_I386, I386OP(jns_rel16), I386OP(jns_rel32), },
|
||||
{ 0x8A, OP_2BYTE|OP_I386, I386OP(jp_rel16), I386OP(jp_rel32), },
|
||||
{ 0x8B, OP_2BYTE|OP_I386, I386OP(jnp_rel16), I386OP(jnp_rel32), },
|
||||
{ 0x8C, OP_2BYTE|OP_I386, I386OP(jl_rel16), I386OP(jl_rel32), },
|
||||
{ 0x8D, OP_2BYTE|OP_I386, I386OP(jge_rel16), I386OP(jge_rel32), },
|
||||
{ 0x8E, OP_2BYTE|OP_I386, I386OP(jle_rel16), I386OP(jle_rel32), },
|
||||
{ 0x8F, OP_2BYTE|OP_I386, I386OP(jg_rel16), I386OP(jg_rel32), },
|
||||
{ 0x90, OP_2BYTE|OP_I386, I386OP(seto_rm8), I386OP(seto_rm8), },
|
||||
{ 0x91, OP_2BYTE|OP_I386, I386OP(setno_rm8), I386OP(setno_rm8), },
|
||||
{ 0x92, OP_2BYTE|OP_I386, I386OP(setc_rm8), I386OP(setc_rm8), },
|
||||
{ 0x93, OP_2BYTE|OP_I386, I386OP(setnc_rm8), I386OP(setnc_rm8), },
|
||||
{ 0x94, OP_2BYTE|OP_I386, I386OP(setz_rm8), I386OP(setz_rm8), },
|
||||
{ 0x95, OP_2BYTE|OP_I386, I386OP(setnz_rm8), I386OP(setnz_rm8), },
|
||||
{ 0x96, OP_2BYTE|OP_I386, I386OP(setbe_rm8), I386OP(setbe_rm8), },
|
||||
{ 0x97, OP_2BYTE|OP_I386, I386OP(seta_rm8), I386OP(seta_rm8), },
|
||||
{ 0x98, OP_2BYTE|OP_I386, I386OP(sets_rm8), I386OP(sets_rm8), },
|
||||
{ 0x99, OP_2BYTE|OP_I386, I386OP(setns_rm8), I386OP(setns_rm8), },
|
||||
{ 0x9A, OP_2BYTE|OP_I386, I386OP(setp_rm8), I386OP(setp_rm8), },
|
||||
{ 0x9B, OP_2BYTE|OP_I386, I386OP(setnp_rm8), I386OP(setnp_rm8), },
|
||||
{ 0x9C, OP_2BYTE|OP_I386, I386OP(setl_rm8), I386OP(setl_rm8), },
|
||||
{ 0x9D, OP_2BYTE|OP_I386, I386OP(setge_rm8), I386OP(setge_rm8), },
|
||||
{ 0x9E, OP_2BYTE|OP_I386, I386OP(setle_rm8), I386OP(setle_rm8), },
|
||||
{ 0x9F, OP_2BYTE|OP_I386, I386OP(setg_rm8), I386OP(setg_rm8), },
|
||||
{ 0xA0, OP_2BYTE|OP_I386, I386OP(push_fs16), I386OP(push_fs32), },
|
||||
{ 0xA1, OP_2BYTE|OP_I386, I386OP(pop_fs16), I386OP(pop_fs32), },
|
||||
{ 0xA2, OP_2BYTE|OP_I486, I486OP(cpuid), I486OP(cpuid), },
|
||||
{ 0xA3, OP_2BYTE|OP_I386, I386OP(bt_rm16_r16), I386OP(bt_rm32_r32), },
|
||||
{ 0xA4, OP_2BYTE|OP_I386, I386OP(shld16_i8), I386OP(shld32_i8), },
|
||||
{ 0xA5, OP_2BYTE|OP_I386, I386OP(shld16_cl), I386OP(shld32_cl), },
|
||||
{ 0xA8, OP_2BYTE|OP_I386, I386OP(push_gs16), I386OP(push_gs32), },
|
||||
{ 0xA9, OP_2BYTE|OP_I386, I386OP(pop_gs16), I386OP(pop_gs32), },
|
||||
{ 0xAA, OP_2BYTE|OP_I386, I386OP(unimplemented), I386OP(unimplemented), },
|
||||
{ 0xAB, OP_2BYTE|OP_I386, I386OP(bts_rm16_r16), I386OP(bts_rm32_r32), },
|
||||
{ 0xAC, OP_2BYTE|OP_I386, I386OP(shrd16_i8), I386OP(shrd32_i8), },
|
||||
{ 0xAD, OP_2BYTE|OP_I386, I386OP(shrd16_cl), I386OP(shrd32_cl), },
|
||||
{ 0xAE, OP_2BYTE|OP_I386, I386OP(invalid), I386OP(invalid), },
|
||||
{ 0xAF, OP_2BYTE|OP_I386, I386OP(imul_r16_rm16), I386OP(imul_r32_rm32), },
|
||||
{ 0xB0, OP_2BYTE|OP_I486, I486OP(cmpxchg_rm8_r8), I486OP(cmpxchg_rm8_r8), },
|
||||
{ 0xB1, OP_2BYTE|OP_I486, I486OP(cmpxchg_rm16_r16), I486OP(cmpxchg_rm32_r32), },
|
||||
{ 0xB2, OP_2BYTE|OP_I386, I386OP(lss16), I386OP(lss32), },
|
||||
{ 0xB3, OP_2BYTE|OP_I386, I386OP(btr_rm16_r16), I386OP(btr_rm32_r32), },
|
||||
{ 0xB4, OP_2BYTE|OP_I386, I386OP(lfs16), I386OP(lfs32), },
|
||||
{ 0xB5, OP_2BYTE|OP_I386, I386OP(lgs16), I386OP(lgs32), },
|
||||
{ 0xB6, OP_2BYTE|OP_I386, I386OP(movzx_r16_rm8), I386OP(movzx_r32_rm8), },
|
||||
{ 0xB7, OP_2BYTE|OP_I386, I386OP(invalid), I386OP(movzx_r32_rm16), },
|
||||
{ 0xBA, OP_2BYTE|OP_I386, I386OP(group0FBA_16), I386OP(group0FBA_32), },
|
||||
{ 0xBB, OP_2BYTE|OP_I386, I386OP(btc_rm16_r16), I386OP(btc_rm32_r32), },
|
||||
{ 0xBC, OP_2BYTE|OP_I386, I386OP(bsf_r16_rm16), I386OP(bsf_r32_rm32), },
|
||||
{ 0xBD, OP_2BYTE|OP_I386, I386OP(bsr_r16_rm16), I386OP(bsr_r32_rm32), },
|
||||
{ 0xBE, OP_2BYTE|OP_I386, I386OP(movsx_r16_rm8), I386OP(movsx_r32_rm8), },
|
||||
{ 0xBF, OP_2BYTE|OP_I386, I386OP(invalid), I386OP(movsx_r32_rm16), },
|
||||
{ 0xC0, OP_2BYTE|OP_I486, I486OP(xadd_rm8_r8), I486OP(xadd_rm8_r8), },
|
||||
{ 0xC1, OP_2BYTE|OP_I486, I486OP(xadd_rm16_r16), I486OP(xadd_rm32_r32), },
|
||||
{ 0xC7, OP_2BYTE|OP_PENTIUM, PENTIUMOP(cmpxchg8b_m64), PENTIUMOP(cmpxchg8b_m64), },
|
||||
{ 0xC8, OP_2BYTE|OP_I486, I486OP(bswap_eax), I486OP(bswap_eax), },
|
||||
{ 0xC9, OP_2BYTE|OP_I486, I486OP(bswap_ecx), I486OP(bswap_ecx), },
|
||||
{ 0xCA, OP_2BYTE|OP_I486, I486OP(bswap_edx), I486OP(bswap_edx), },
|
||||
{ 0xCB, OP_2BYTE|OP_I486, I486OP(bswap_ebx), I486OP(bswap_ebx), },
|
||||
{ 0xCC, OP_2BYTE|OP_I486, I486OP(bswap_esp), I486OP(bswap_esp), },
|
||||
{ 0xCD, OP_2BYTE|OP_I486, I486OP(bswap_ebp), I486OP(bswap_ebp), },
|
||||
{ 0xCE, OP_2BYTE|OP_I486, I486OP(bswap_esi), I486OP(bswap_esi), },
|
||||
{ 0xCF, OP_2BYTE|OP_I486, I486OP(bswap_edi), I486OP(bswap_edi), }
|
||||
};
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,424 @@
|
||||
/* Intel 486+ specific opcodes */
|
||||
|
||||
static void I486OP(cpuid)(i386_state *cpustate) /* Opcode 0x0F A2 */
|
||||
{
|
||||
if (cpustate->cpuid_id0 == 0)
|
||||
{
|
||||
/* this 486 doesn't support the CPUID instruction */
|
||||
logerror("CPUID not supported at %08x!\n", cpustate->eip);
|
||||
i386_trap(cpustate, 6, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (REG32(EAX))
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
REG32(EAX) = cpustate->cpuid_max_input_value_eax;
|
||||
REG32(EBX) = cpustate->cpuid_id0;
|
||||
REG32(ECX) = cpustate->cpuid_id2;
|
||||
REG32(EDX) = cpustate->cpuid_id1;
|
||||
CYCLES(cpustate,CYCLES_CPUID);
|
||||
break;
|
||||
}
|
||||
|
||||
case 1:
|
||||
{
|
||||
REG32(EAX) = cpustate->cpu_version;
|
||||
REG32(EDX) = cpustate->feature_flags;
|
||||
CYCLES(cpustate,CYCLES_CPUID_EAX1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void I486OP(invd)(i386_state *cpustate) /* Opcode 0x0f 08 */
|
||||
{
|
||||
/* Nothing to do ? */
|
||||
CYCLES(cpustate,CYCLES_INVD);
|
||||
}
|
||||
|
||||
static void I486OP(wbinvd)(i386_state *cpustate) /* Opcode 0x0f 09 */
|
||||
{
|
||||
/* Nothing to do ? */
|
||||
}
|
||||
|
||||
static void I486OP(cmpxchg_rm8_r8)(i386_state *cpustate) /* Opcode 0x0f b0 */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
if( modrm >= 0xc0 ) {
|
||||
UINT8 dst = LOAD_RM8(modrm);
|
||||
UINT8 src = LOAD_REG8(modrm);
|
||||
|
||||
if( REG8(AL) == dst ) {
|
||||
STORE_RM8(modrm, src);
|
||||
cpustate->ZF = 1;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_T);
|
||||
} else {
|
||||
REG8(AL) = dst;
|
||||
cpustate->ZF = 0;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_F);
|
||||
}
|
||||
} else {
|
||||
UINT32 ea = GetEA(cpustate,modrm);
|
||||
UINT8 dst = READ8(cpustate,ea);
|
||||
UINT8 src = LOAD_REG8(modrm);
|
||||
|
||||
if( REG8(AL) == dst ) {
|
||||
WRITE8(cpustate,modrm, src);
|
||||
cpustate->ZF = 1;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T);
|
||||
} else {
|
||||
REG8(AL) = dst;
|
||||
cpustate->ZF = 0;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_F);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void I486OP(cmpxchg_rm16_r16)(i386_state *cpustate) /* Opcode 0x0f b1 */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
if( modrm >= 0xc0 ) {
|
||||
UINT16 dst = LOAD_RM16(modrm);
|
||||
UINT16 src = LOAD_REG16(modrm);
|
||||
|
||||
if( REG16(AX) == dst ) {
|
||||
STORE_RM16(modrm, src);
|
||||
cpustate->ZF = 1;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_T);
|
||||
} else {
|
||||
REG16(AX) = dst;
|
||||
cpustate->ZF = 0;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_F);
|
||||
}
|
||||
} else {
|
||||
UINT32 ea = GetEA(cpustate,modrm);
|
||||
UINT16 dst = READ16(cpustate,ea);
|
||||
UINT16 src = LOAD_REG16(modrm);
|
||||
|
||||
if( REG16(AX) == dst ) {
|
||||
WRITE16(cpustate,modrm, src);
|
||||
cpustate->ZF = 1;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T);
|
||||
} else {
|
||||
REG16(AX) = dst;
|
||||
cpustate->ZF = 0;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_F);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void I486OP(cmpxchg_rm32_r32)(i386_state *cpustate) /* Opcode 0x0f b1 */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
if( modrm >= 0xc0 ) {
|
||||
UINT32 dst = LOAD_RM32(modrm);
|
||||
UINT32 src = LOAD_REG32(modrm);
|
||||
|
||||
if( REG32(EAX) == dst ) {
|
||||
STORE_RM32(modrm, src);
|
||||
cpustate->ZF = 1;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_T);
|
||||
} else {
|
||||
REG32(EAX) = dst;
|
||||
cpustate->ZF = 0;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_F);
|
||||
}
|
||||
} else {
|
||||
UINT32 ea = GetEA(cpustate,modrm);
|
||||
UINT32 dst = READ32(cpustate,ea);
|
||||
UINT32 src = LOAD_REG32(modrm);
|
||||
|
||||
if( REG32(EAX) == dst ) {
|
||||
WRITE32(cpustate,ea, src);
|
||||
cpustate->ZF = 1;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T);
|
||||
} else {
|
||||
REG32(EAX) = dst;
|
||||
cpustate->ZF = 0;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_F);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void I486OP(xadd_rm8_r8)(i386_state *cpustate) /* Opcode 0x0f c0 */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
if( modrm >= 0xc0 ) {
|
||||
UINT8 dst = LOAD_RM8(modrm);
|
||||
UINT8 src = LOAD_REG8(modrm);
|
||||
STORE_RM16(modrm, dst + src);
|
||||
STORE_REG16(modrm, dst);
|
||||
CYCLES(cpustate,CYCLES_XADD_REG_REG);
|
||||
} else {
|
||||
UINT32 ea = GetEA(cpustate,modrm);
|
||||
UINT8 dst = READ8(cpustate,ea);
|
||||
UINT8 src = LOAD_REG8(modrm);
|
||||
WRITE8(cpustate,ea, dst + src);
|
||||
STORE_REG8(modrm, dst);
|
||||
CYCLES(cpustate,CYCLES_XADD_REG_MEM);
|
||||
}
|
||||
}
|
||||
|
||||
static void I486OP(xadd_rm16_r16)(i386_state *cpustate) /* Opcode 0x0f c1 */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
if( modrm >= 0xc0 ) {
|
||||
UINT16 dst = LOAD_RM16(modrm);
|
||||
UINT16 src = LOAD_REG16(modrm);
|
||||
STORE_RM16(modrm, dst + src);
|
||||
STORE_REG16(modrm, dst);
|
||||
CYCLES(cpustate,CYCLES_XADD_REG_REG);
|
||||
} else {
|
||||
UINT32 ea = GetEA(cpustate,modrm);
|
||||
UINT16 dst = READ16(cpustate,ea);
|
||||
UINT16 src = LOAD_REG16(modrm);
|
||||
WRITE16(cpustate,ea, dst + src);
|
||||
STORE_REG16(modrm, dst);
|
||||
CYCLES(cpustate,CYCLES_XADD_REG_MEM);
|
||||
}
|
||||
}
|
||||
|
||||
static void I486OP(xadd_rm32_r32)(i386_state *cpustate) /* Opcode 0x0f c1 */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
if( modrm >= 0xc0 ) {
|
||||
UINT32 dst = LOAD_RM32(modrm);
|
||||
UINT32 src = LOAD_REG32(modrm);
|
||||
STORE_RM32(modrm, dst + src);
|
||||
STORE_REG32(modrm, dst);
|
||||
CYCLES(cpustate,CYCLES_XADD_REG_REG);
|
||||
} else {
|
||||
UINT32 ea = GetEA(cpustate,modrm);
|
||||
UINT32 dst = READ32(cpustate,ea);
|
||||
UINT32 src = LOAD_REG32(modrm);
|
||||
WRITE32(cpustate,ea, dst + src);
|
||||
STORE_REG32(modrm, dst);
|
||||
CYCLES(cpustate,CYCLES_XADD_REG_MEM);
|
||||
}
|
||||
}
|
||||
|
||||
static void I486OP(group0F01_16)(i386_state *cpustate) /* Opcode 0x0f 01 */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
UINT16 address;
|
||||
UINT32 ea;
|
||||
|
||||
switch( (modrm >> 3) & 0x7 )
|
||||
{
|
||||
case 0: /* SGDT */
|
||||
{
|
||||
if( modrm >= 0xc0 ) {
|
||||
address = LOAD_RM16(modrm);
|
||||
ea = i386_translate( cpustate, CS, address );
|
||||
} else {
|
||||
ea = GetEA(cpustate,modrm);
|
||||
}
|
||||
WRITE16(cpustate,ea, cpustate->gdtr.limit);
|
||||
WRITE32(cpustate,ea + 2, cpustate->gdtr.base & 0xffffff);
|
||||
CYCLES(cpustate,CYCLES_SGDT);
|
||||
break;
|
||||
}
|
||||
case 1: /* SIDT */
|
||||
{
|
||||
if (modrm >= 0xc0)
|
||||
{
|
||||
address = LOAD_RM16(modrm);
|
||||
ea = i386_translate( cpustate, CS, address );
|
||||
}
|
||||
else
|
||||
{
|
||||
ea = GetEA(cpustate,modrm);
|
||||
}
|
||||
WRITE16(cpustate,ea, cpustate->idtr.limit);
|
||||
WRITE32(cpustate,ea + 2, cpustate->idtr.base & 0xffffff);
|
||||
CYCLES(cpustate,CYCLES_SIDT);
|
||||
break;
|
||||
}
|
||||
case 2: /* LGDT */
|
||||
{
|
||||
if( modrm >= 0xc0 ) {
|
||||
address = LOAD_RM16(modrm);
|
||||
ea = i386_translate( cpustate, CS, address );
|
||||
} else {
|
||||
ea = GetEA(cpustate,modrm);
|
||||
}
|
||||
cpustate->gdtr.limit = READ16(cpustate,ea);
|
||||
cpustate->gdtr.base = READ32(cpustate,ea + 2) & 0xffffff;
|
||||
CYCLES(cpustate,CYCLES_LGDT);
|
||||
break;
|
||||
}
|
||||
case 3: /* LIDT */
|
||||
{
|
||||
if( modrm >= 0xc0 ) {
|
||||
address = LOAD_RM16(modrm);
|
||||
ea = i386_translate( cpustate, CS, address );
|
||||
} else {
|
||||
ea = GetEA(cpustate,modrm);
|
||||
}
|
||||
cpustate->idtr.limit = READ16(cpustate,ea);
|
||||
cpustate->idtr.base = READ32(cpustate,ea + 2) & 0xffffff;
|
||||
CYCLES(cpustate,CYCLES_LIDT);
|
||||
break;
|
||||
}
|
||||
case 4: /* SMSW */
|
||||
{
|
||||
if( modrm >= 0xc0 ) {
|
||||
STORE_RM16(modrm, cpustate->cr[0]);
|
||||
CYCLES(cpustate,CYCLES_SMSW_REG);
|
||||
} else {
|
||||
ea = GetEA(cpustate,modrm);
|
||||
WRITE16(cpustate,ea, cpustate->cr[0]);
|
||||
CYCLES(cpustate,CYCLES_SMSW_MEM);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 6: /* LMSW */
|
||||
{
|
||||
/* TODO: Check for protection fault */
|
||||
UINT8 b;
|
||||
if( modrm >= 0xc0 ) {
|
||||
b = LOAD_RM8(modrm);
|
||||
CYCLES(cpustate,CYCLES_LMSW_REG);
|
||||
} else {
|
||||
ea = GetEA(cpustate,modrm);
|
||||
CYCLES(cpustate,CYCLES_LMSW_MEM);
|
||||
b = READ8(cpustate,ea);
|
||||
}
|
||||
cpustate->cr[0] &= ~0x03;
|
||||
cpustate->cr[0] |= b & 0x03;
|
||||
break;
|
||||
}
|
||||
case 7: /* INVLPG */
|
||||
{
|
||||
/* Nothing to do ? */
|
||||
break;
|
||||
}
|
||||
default:
|
||||
i386_fatal("i486: unimplemented opcode 0x0f 01 /%d at %08X", (modrm >> 3) & 0x7, cpustate->eip - 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void I486OP(group0F01_32)(i386_state *cpustate) /* Opcode 0x0f 01 */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
UINT32 address, ea;
|
||||
|
||||
switch( (modrm >> 3) & 0x7 )
|
||||
{
|
||||
case 0: /* SGDT */
|
||||
{
|
||||
if( modrm >= 0xc0 ) {
|
||||
address = LOAD_RM32(modrm);
|
||||
ea = i386_translate( cpustate, CS, address );
|
||||
} else {
|
||||
ea = GetEA(cpustate,modrm);
|
||||
}
|
||||
WRITE16(cpustate,ea, cpustate->gdtr.limit);
|
||||
WRITE32(cpustate,ea + 2, cpustate->gdtr.base);
|
||||
CYCLES(cpustate,CYCLES_SGDT);
|
||||
break;
|
||||
}
|
||||
case 1: /* SIDT */
|
||||
{
|
||||
if (modrm >= 0xc0)
|
||||
{
|
||||
address = LOAD_RM32(modrm);
|
||||
ea = i386_translate( cpustate, CS, address );
|
||||
}
|
||||
else
|
||||
{
|
||||
ea = GetEA(cpustate,modrm);
|
||||
}
|
||||
WRITE16(cpustate,ea, cpustate->idtr.limit);
|
||||
WRITE32(cpustate,ea + 2, cpustate->idtr.base);
|
||||
CYCLES(cpustate,CYCLES_SIDT);
|
||||
break;
|
||||
}
|
||||
case 2: /* LGDT */
|
||||
{
|
||||
if( modrm >= 0xc0 ) {
|
||||
address = LOAD_RM32(modrm);
|
||||
ea = i386_translate( cpustate, CS, address );
|
||||
} else {
|
||||
ea = GetEA(cpustate,modrm);
|
||||
}
|
||||
cpustate->gdtr.limit = READ16(cpustate,ea);
|
||||
cpustate->gdtr.base = READ32(cpustate,ea + 2);
|
||||
CYCLES(cpustate,CYCLES_LGDT);
|
||||
break;
|
||||
}
|
||||
case 3: /* LIDT */
|
||||
{
|
||||
if( modrm >= 0xc0 ) {
|
||||
address = LOAD_RM32(modrm);
|
||||
ea = i386_translate( cpustate, CS, address );
|
||||
} else {
|
||||
ea = GetEA(cpustate,modrm);
|
||||
}
|
||||
cpustate->idtr.limit = READ16(cpustate,ea);
|
||||
cpustate->idtr.base = READ32(cpustate,ea + 2);
|
||||
CYCLES(cpustate,CYCLES_LIDT);
|
||||
break;
|
||||
}
|
||||
case 7: /* INVLPG */
|
||||
{
|
||||
/* Nothing to do ? */
|
||||
break;
|
||||
}
|
||||
default:
|
||||
i386_fatal("i486: unimplemented opcode 0x0f 01 /%d at %08X", (modrm >> 3) & 0x7, cpustate->eip - 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void I486OP(bswap_eax)(i386_state *cpustate) /* Opcode 0x0f 38 */
|
||||
{
|
||||
REG32(EAX) = SWITCH_ENDIAN_32(REG32(EAX));
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
}
|
||||
|
||||
static void I486OP(bswap_ecx)(i386_state *cpustate) /* Opcode 0x0f 39 */
|
||||
{
|
||||
REG32(ECX) = SWITCH_ENDIAN_32(REG32(ECX));
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
}
|
||||
|
||||
static void I486OP(bswap_edx)(i386_state *cpustate) /* Opcode 0x0f 3A */
|
||||
{
|
||||
REG32(EDX) = SWITCH_ENDIAN_32(REG32(EDX));
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
}
|
||||
|
||||
static void I486OP(bswap_ebx)(i386_state *cpustate) /* Opcode 0x0f 3B */
|
||||
{
|
||||
REG32(EBX) = SWITCH_ENDIAN_32(REG32(EBX));
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
}
|
||||
|
||||
static void I486OP(bswap_esp)(i386_state *cpustate) /* Opcode 0x0f 3C */
|
||||
{
|
||||
REG32(ESP) = SWITCH_ENDIAN_32(REG32(ESP));
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
}
|
||||
|
||||
static void I486OP(bswap_ebp)(i386_state *cpustate) /* Opcode 0x0f 3D */
|
||||
{
|
||||
REG32(EBP) = SWITCH_ENDIAN_32(REG32(EBP));
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
}
|
||||
|
||||
static void I486OP(bswap_esi)(i386_state *cpustate) /* Opcode 0x0f 3E */
|
||||
{
|
||||
REG32(ESI) = SWITCH_ENDIAN_32(REG32(ESI));
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
}
|
||||
|
||||
static void I486OP(bswap_edi)(i386_state *cpustate) /* Opcode 0x0f 3F */
|
||||
{
|
||||
REG32(EDI) = SWITCH_ENDIAN_32(REG32(EDI));
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/* Pentium+ specific opcodes */
|
||||
|
||||
static void PENTIUMOP(rdmsr)(i386_state *cpustate) /* Opcode 0x0f 32 */
|
||||
{
|
||||
/* TODO */
|
||||
CYCLES(cpustate,CYCLES_RDMSR);
|
||||
}
|
||||
|
||||
static void PENTIUMOP(wrmsr)(i386_state *cpustate) /* Opcode 0x0f 30 */
|
||||
{
|
||||
/* TODO */
|
||||
CYCLES(cpustate,1); /* TODO: correct cycle count */
|
||||
}
|
||||
|
||||
static void PENTIUMOP(rdtsc)(i386_state *cpustate) /* Opcode 0x0f 31 */
|
||||
{
|
||||
UINT64 ts = cpustate->tsc + (cpustate->base_cycles - i386_ICount);
|
||||
REG32(EAX) = (UINT32)(ts);
|
||||
REG32(EDX) = (UINT32)(ts >> 32);
|
||||
|
||||
CYCLES(cpustate,CYCLES_RDTSC);
|
||||
}
|
||||
|
||||
static void I386OP(cyrix_unknown)(i386_state *cpustate) /* Opcode 0x0f 74 */
|
||||
{
|
||||
CYCLES(cpustate,1);
|
||||
}
|
||||
|
||||
static void PENTIUMOP(cmpxchg8b_m64)(i386_state *cpustate) /* Opcode 0x0f c7 */
|
||||
{
|
||||
UINT8 modm = FETCH(cpustate);
|
||||
if( modm >= 0xc0 ) {
|
||||
i386_fatal("pentium: cmpxchg8b_m64 - invalid modm");
|
||||
} else {
|
||||
UINT32 ea = GetEA(cpustate,modm);
|
||||
UINT64 value = READ64(cpustate,ea);
|
||||
UINT64 edx_eax = (((UINT64) REG32(EDX)) << 32) | REG32(EAX);
|
||||
UINT64 ecx_ebx = (((UINT64) REG32(ECX)) << 32) | REG32(EBX);
|
||||
|
||||
if( value == edx_eax ) {
|
||||
WRITE64(cpustate,ea, ecx_ebx);
|
||||
cpustate->ZF = 1;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T);
|
||||
} else {
|
||||
REG32(EDX) = (UINT32) (value >> 32);
|
||||
REG32(EAX) = (UINT32) (value >> 0);
|
||||
cpustate->ZF = 0;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_F);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,352 @@
|
||||
/* Intel x87 FPU opcodes */
|
||||
|
||||
#define ST(x) (cpustate->fpu_reg[(cpustate->fpu_top + (x)) & 7])
|
||||
#define FPU_INFINITY_DOUBLE COMBINE_64_32_32(0x7ff00000, 0x00000000)
|
||||
#define FPU_INFINITY_SINGLE (0x7f800000)
|
||||
#define FPU_SIGN_BIT_DOUBLE COMBINE_64_32_32(0x80000000, 0x00000000)
|
||||
#define FPU_SIGN_BIT_SINGLE (0x80000000)
|
||||
|
||||
/* FPU control word flags */
|
||||
#define FPU_MASK_INVALID_OP 0x0001
|
||||
#define FPU_MASK_DENORMAL_OP 0x0002
|
||||
#define FPU_MASK_ZERO_DIVIDE 0x0004
|
||||
#define FPU_MASK_OVERFLOW 0x0008
|
||||
#define FPU_MASK_UNDERFLOW 0x0010
|
||||
#define FPU_MASK_PRECISION 0x0020
|
||||
|
||||
/* FPU status word flags */
|
||||
#define FPU_BUSY 0x8000
|
||||
#define FPU_C3 0x4000
|
||||
#define FPU_STACK_TOP_MASK 0x3800
|
||||
#define FPU_C2 0x0400
|
||||
#define FPU_C1 0x0200
|
||||
#define FPU_C0 0x0100
|
||||
#define FPU_ERROR_SUMMARY 0x0080
|
||||
#define FPU_STACK_FAULT 0x0040
|
||||
#define FPU_EXCEPTION_PRECISION 0x0020
|
||||
#define FPU_EXCEPTION_UNDERFLOW 0x0010
|
||||
#define FPU_EXCEPTION_OVERFLOW 0x0008
|
||||
#define FPU_EXCEPTION_ZERO_DIVIDE 0x0004
|
||||
#define FPU_EXCEPTION_DENORMAL_OP 0x0002
|
||||
#define FPU_EXCEPTION_INVALID_OP 0x0001
|
||||
|
||||
static INLINE void FPU_PUSH(i386_state *cpustate, X87_REG value)
|
||||
{
|
||||
cpustate->fpu_top--;
|
||||
if (cpustate->fpu_top < 0)
|
||||
{
|
||||
cpustate->fpu_top = 7;
|
||||
}
|
||||
|
||||
cpustate->fpu_reg[cpustate->fpu_top] = value;
|
||||
}
|
||||
|
||||
static INLINE X87_REG FPU_POP(i386_state *cpustate)
|
||||
{
|
||||
X87_REG value = cpustate->fpu_reg[cpustate->fpu_top];
|
||||
|
||||
cpustate->fpu_tag_word |= 3 << (cpustate->fpu_top * 2); /* set FPU register tag to 3 (empty) */
|
||||
|
||||
cpustate->fpu_top++;
|
||||
if (cpustate->fpu_top > 7)
|
||||
{
|
||||
cpustate->fpu_top = 0;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static void I386OP(fpu_group_d8)(i386_state *cpustate) /* Opcode 0xd8 */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
i386_fatal("I386: FPU Op D8 %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
|
||||
static void I386OP(fpu_group_d9)(i386_state *cpustate) /* Opcode 0xd9 */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
|
||||
if (modrm < 0xc0)
|
||||
{
|
||||
UINT32 ea = GetEA(cpustate,modrm);
|
||||
|
||||
switch ((modrm >> 3) & 0x7)
|
||||
{
|
||||
case 5: /* FLDCW */
|
||||
{
|
||||
cpustate->fpu_control_word = READ16(cpustate,ea);
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
|
||||
case 7: /* FSTCW */
|
||||
{
|
||||
WRITE16(cpustate,ea, cpustate->fpu_control_word);
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
i386_fatal("I386: FPU Op D9 %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (modrm & 0x3f)
|
||||
{
|
||||
/* FLD */
|
||||
case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
|
||||
{
|
||||
X87_REG t = ST(modrm & 7);
|
||||
FPU_PUSH(cpustate,t);
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x20: /* FCHS */
|
||||
{
|
||||
ST(0).i ^= FPU_SIGN_BIT_DOUBLE;
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x28: /* FLD1 */
|
||||
{
|
||||
X87_REG t;
|
||||
t.f = 1.0;
|
||||
FPU_PUSH(cpustate,t);
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x2e: /* FLDZ */
|
||||
{
|
||||
X87_REG t;
|
||||
t.f = 0.0;
|
||||
FPU_PUSH(cpustate,t);
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
default:
|
||||
i386_fatal("I386: FPU Op D9 %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void I386OP(fpu_group_da)(i386_state *cpustate) /* Opcode 0xda */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
i386_fatal("I386: FPU Op DA %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
|
||||
static void I386OP(fpu_group_db)(i386_state *cpustate) /* Opcode 0xdb */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
|
||||
if (modrm < 0xc0)
|
||||
{
|
||||
i386_fatal("I386: FPU Op DB %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (modrm & 0x3f)
|
||||
{
|
||||
case 0x23: /* FINIT */
|
||||
{
|
||||
cpustate->fpu_control_word = 0x37f;
|
||||
cpustate->fpu_status_word = 0;
|
||||
cpustate->fpu_tag_word = 0xffff;
|
||||
cpustate->fpu_data_ptr = 0;
|
||||
cpustate->fpu_inst_ptr = 0;
|
||||
cpustate->fpu_opcode = 0;
|
||||
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x24: /* FSETPM (treated as nop on 387+) */
|
||||
{
|
||||
CYCLES(cpustate,1);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
i386_fatal("I386: FPU Op DB %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void I386OP(fpu_group_dc)(i386_state *cpustate) /* Opcode 0xdc */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
|
||||
if (modrm < 0xc0)
|
||||
{
|
||||
/*UINT32 ea = GetEA(cpustate,modrm); */
|
||||
|
||||
switch ((modrm >> 3) & 0x7)
|
||||
{
|
||||
default:
|
||||
i386_fatal("I386: FPU Op DC %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (modrm & 0x3f)
|
||||
{
|
||||
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
|
||||
{
|
||||
/* FDIVR */
|
||||
if ((ST(modrm & 7).i & COMBINE_64_32_32(0x7fffffff, 0xffffffff)) == 0)
|
||||
{
|
||||
/* set result as infinity if zero divide is masked */
|
||||
if (cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE)
|
||||
{
|
||||
ST(modrm & 7).i |= FPU_INFINITY_DOUBLE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ST(modrm & 7).f = ST(0).f / ST(modrm & 7).f;
|
||||
}
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
i386_fatal("I386: FPU Op DC %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void I386OP(fpu_group_dd)(i386_state *cpustate) /* Opcode 0xdd */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
|
||||
if (modrm < 0xc0)
|
||||
{
|
||||
UINT32 ea = GetEA(cpustate,modrm);
|
||||
|
||||
switch ((modrm >> 3) & 0x7)
|
||||
{
|
||||
case 7: /* FSTSW */
|
||||
{
|
||||
WRITE16(cpustate,ea, (cpustate->fpu_status_word & ~FPU_STACK_TOP_MASK) | (cpustate->fpu_top << 10));
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
i386_fatal("I386: FPU Op DD %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (modrm & 0x3f)
|
||||
{
|
||||
default:
|
||||
i386_fatal("I386: FPU Op DD %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void I386OP(fpu_group_de)(i386_state *cpustate) /* Opcode 0xde */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
|
||||
if (modrm < 0xc0)
|
||||
{
|
||||
/* UINT32 ea = GetEA(cpustate,modrm); */
|
||||
|
||||
switch ((modrm >> 3) & 0x7)
|
||||
{
|
||||
default:
|
||||
i386_fatal("I386: FPU Op DE %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (modrm & 0x3f)
|
||||
{
|
||||
case 0x19: /* FCOMPP */
|
||||
{
|
||||
cpustate->fpu_status_word &= ~(FPU_C3 | FPU_C2 | FPU_C0);
|
||||
if (ST(0).f > ST(1).f)
|
||||
{
|
||||
/* C3 = 0, C2 = 0, C0 = 0 */
|
||||
}
|
||||
else if (ST(0).f < ST(1).f)
|
||||
{
|
||||
cpustate->fpu_status_word |= FPU_C0;
|
||||
}
|
||||
else if (ST(0).f == ST(1).f)
|
||||
{
|
||||
cpustate->fpu_status_word |= FPU_C3;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* unordered */
|
||||
cpustate->fpu_status_word |= (FPU_C3 | FPU_C2 | FPU_C0);
|
||||
}
|
||||
FPU_POP(cpustate);
|
||||
FPU_POP(cpustate);
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
|
||||
/* FDIVP */
|
||||
case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
|
||||
{
|
||||
if ((ST(0).i & COMBINE_64_32_32(0x7fffffff, 0xffffffff)) == 0)
|
||||
{
|
||||
/* set result as infinity if zero divide is masked */
|
||||
if (cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE)
|
||||
{
|
||||
ST(modrm & 7).i |= FPU_INFINITY_DOUBLE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ST(modrm & 7).f = ST(modrm & 7).f / ST(0).f;
|
||||
}
|
||||
FPU_POP(cpustate);
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
i386_fatal("I386: FPU Op DE %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void I386OP(fpu_group_df)(i386_state *cpustate) /* Opcode 0xdf */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
|
||||
if (modrm < 0xc0)
|
||||
{
|
||||
/* UINT32 ea = GetEA(cpustate,modrm); */
|
||||
|
||||
switch ((modrm >> 3) & 0x7)
|
||||
{
|
||||
default:
|
||||
i386_fatal("I386: FPU Op DF %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (modrm & 0x3f)
|
||||
{
|
||||
case 0x20: /* FSTSW AX */
|
||||
{
|
||||
REG16(AX) = (cpustate->fpu_status_word & ~FPU_STACK_TOP_MASK) | (cpustate->fpu_top << 10);
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
i386_fatal("I386: FPU Op DF %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,104 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* i8051.h
|
||||
* Portable MCS-51 Family Emulator
|
||||
*
|
||||
* Copyright Steve Ellenoff, all rights reserved.
|
||||
*
|
||||
* - This source code is released as freeware for non-commercial purposes.
|
||||
* - You are free to use and redistribute this code in modified or
|
||||
* unmodified form, provided you list me in the credits.
|
||||
* - If you modify this source code, you must add a notice to each modified
|
||||
* source file that it has been changed. If you're a nice person, you
|
||||
* will clearly mark each change too. :)
|
||||
* - If you wish to use this for commercial purposes, please contact me at
|
||||
* sellenoff@hotmail.com
|
||||
* - The author of this copywritten work reserves the right to change the
|
||||
* terms of its usage and license at any time, including retroactively
|
||||
* - This entire notice must remain in the source code.
|
||||
*
|
||||
* October 2008, Couriersud: Major rewrite (MAME 0.128-0.139 mcs51 core)
|
||||
*
|
||||
* MODIFIED for mame2003-plus: backported from MAME 0.139 src/emu/cpu/mcs51
|
||||
* to the MAME 0.78 cpu_interface. DS5002FP and 80C52 variants removed,
|
||||
* internal RAM/SFRs kept inside the CPU context, MOVX routed through
|
||||
* per-CPU driver handlers (the 0.78 core has no DATA address space).
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _I8051_H
|
||||
#define _I8051_H
|
||||
|
||||
#include "cpuintrf.h"
|
||||
#include "osd_cpu.h"
|
||||
#include "memory.h"
|
||||
|
||||
/* The MCS-51 runs one machine cycle every 12 oscillator clocks.
|
||||
Give the CPU clock in the machine driver as XTAL / I8051_CLOCK_DIVIDER. */
|
||||
#define I8051_CLOCK_DIVIDER 12
|
||||
|
||||
/****************************************************************************
|
||||
* Input lines (use with cpu_set_irq_line)
|
||||
* INT0/INT1 follow the TCON IT0/IT1 setting (edge or level);
|
||||
* T0/T1 count 0->1 transitions when the timer is in counter mode,
|
||||
* so drive them with PULSE_LINE.
|
||||
****************************************************************************/
|
||||
enum
|
||||
{
|
||||
I8051_INT0_LINE = 0, /* P3.2: External Interrupt 0 */
|
||||
I8051_INT1_LINE, /* P3.3: External Interrupt 1 */
|
||||
I8051_RX_LINE, /* P3.0: Serial Port Receive Line */
|
||||
I8051_T0_LINE, /* P3.4: Timer 0 External Input */
|
||||
I8051_T1_LINE, /* P3.5: Timer 1 External Input */
|
||||
I8051_INPUT_LINES
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Port space: the four parallel ports. Map them in the MCU's
|
||||
* PORT_READ/PORT_WRITE tables, e.g. { I8051_P1, I8051_P1, mcu_p1_w }
|
||||
****************************************************************************/
|
||||
#define I8051_P0 0x00
|
||||
#define I8051_P1 0x01
|
||||
#define I8051_P2 0x02
|
||||
#define I8051_P3 0x03
|
||||
|
||||
/****************************************************************************
|
||||
* Registers
|
||||
****************************************************************************/
|
||||
enum
|
||||
{
|
||||
I8051_PC=1, I8051_SP, I8051_PSW, I8051_ACC, I8051_B, I8051_DPH, I8051_DPL, I8051_IE,
|
||||
I8051_R0, I8051_R1, I8051_R2, I8051_R3, I8051_R4, I8051_R5, I8051_R6, I8051_R7, I8051_RB
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public functions
|
||||
****************************************************************************/
|
||||
extern int i8051_ICount;
|
||||
|
||||
extern void i8051_init(void);
|
||||
extern void i8051_reset(void *param);
|
||||
extern void i8051_exit(void);
|
||||
extern int i8051_execute(int cycles);
|
||||
extern unsigned i8051_get_context(void *dst);
|
||||
extern void i8051_set_context(void *src);
|
||||
extern unsigned i8051_get_reg(int regnum);
|
||||
extern void i8051_set_reg(int regnum, unsigned val);
|
||||
extern void i8051_set_irq_line(int irqline, int state);
|
||||
extern void i8051_set_irq_callback(int (*callback)(int irqline));
|
||||
extern const char *i8051_info(void *context, int regnum);
|
||||
extern unsigned i8051_dasm(char *buffer, unsigned pc);
|
||||
|
||||
/* External data memory (MOVX). Called from MACHINE_INIT; cpunum is the MCU's
|
||||
CPU index. Unmapped reads return 0xff, unmapped writes are dropped. */
|
||||
extern void i8051_set_movx_handlers(int cpunum, read8_handler rd, write8_handler wr);
|
||||
|
||||
/* Serial port hooks (optional). */
|
||||
extern void i8051_set_serial_tx_callback(int cpunum, void (*callback)(int data));
|
||||
extern void i8051_set_serial_rx_callback(int cpunum, int (*callback)(void));
|
||||
|
||||
/* The 8751 is an 8051 with internal EPROM: the driver loads the dump in the
|
||||
MCU's CPU region exactly as for the 8051. */
|
||||
#define CPU_I8751 CPU_I8051
|
||||
|
||||
#endif /* _I8051_H */
|
||||
@@ -0,0 +1,981 @@
|
||||
/* MODIFIED for mame2003-plus: C89 comments, device reference removed (backport of MAME 0.139 mcs51ops.c) */
|
||||
/*******************************************************************************************
|
||||
NOTE: All registers are accessed directly, instead of using the SFR_R() function for speed
|
||||
Direct register access is availabe from the R_(register name) macros.. ex: ACC for the ACC
|
||||
with the exception of the PC
|
||||
********************************************************************************************/
|
||||
|
||||
/*ACALL code addr 1: aaa1 0001 */
|
||||
OPHANDLER( acall )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab code address byte */
|
||||
PUSH_PC(); /*Save PC to the stack */
|
||||
/*Thanks Gerrit for help with this! :) */
|
||||
PC = (PC & 0xf800) | ((r & 0xe0) << 3) | addr;
|
||||
}
|
||||
|
||||
/*ADD A, #data 1: 0010 0100 */
|
||||
OPHANDLER( add_a_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
UINT8 result = ACC + data; /*Add data to accumulator */
|
||||
DO_ADD_FLAGS(ACC,data,0); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
}
|
||||
|
||||
/*ADD A, data addr 1: 0010 0101 */
|
||||
OPHANDLER( add_a_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr); /*Grab data from data address */
|
||||
UINT8 result = ACC + data; /*Add data to accumulator */
|
||||
DO_ADD_FLAGS(ACC,data,0); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
}
|
||||
|
||||
/*ADD A, @R0/@R1 1: 0010 011i */
|
||||
OPHANDLER( add_a_ir )
|
||||
{
|
||||
UINT8 data = IRAM_IR(R_REG(r)); /*Grab data from memory pointed to by R0 or R1 */
|
||||
UINT8 result = ACC + data; /*Add data to accumulator */
|
||||
DO_ADD_FLAGS(ACC,data,0); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
}
|
||||
|
||||
/*ADD A, R0 to R7 1: 0010 1rrr */
|
||||
OPHANDLER( add_a_r )
|
||||
{
|
||||
UINT8 data = R_REG(r); /*Grab data from R0 - R7 */
|
||||
UINT8 result = ACC + data; /*Add data to accumulator */
|
||||
DO_ADD_FLAGS(ACC,data,0); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
}
|
||||
|
||||
/*ADDC A, #data 1: 0011 0100 */
|
||||
OPHANDLER( addc_a_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
UINT8 result = ACC + data + GET_CY; /*Add data + carry flag to accumulator */
|
||||
DO_ADD_FLAGS(ACC,data,GET_CY); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
}
|
||||
|
||||
/*ADDC A, data addr 1: 0011 0101 */
|
||||
OPHANDLER( addc_a_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr); /*Grab data from data address */
|
||||
UINT8 result = ACC + data + GET_CY; /*Add data + carry flag to accumulator */
|
||||
DO_ADD_FLAGS(ACC,data,GET_CY); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
}
|
||||
|
||||
/*ADDC A, @R0/@R1 1: 0011 011i */
|
||||
OPHANDLER( addc_a_ir )
|
||||
{
|
||||
UINT8 data = IRAM_IR(R_REG(r)); /*Grab data from memory pointed to by R0 or R1 */
|
||||
UINT8 result = ACC + data + GET_CY; /*Add data + carry flag to accumulator */
|
||||
DO_ADD_FLAGS(ACC,data,GET_CY); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
}
|
||||
|
||||
/*ADDC A, R0 to R7 1: 0011 1rrr */
|
||||
OPHANDLER( addc_a_r )
|
||||
{
|
||||
UINT8 data = R_REG(r); /*Grab data from R0 - R7 */
|
||||
UINT8 result = ACC + data + GET_CY; /*Add data + carry flag to accumulator */
|
||||
DO_ADD_FLAGS(ACC,data,GET_CY); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
}
|
||||
|
||||
/*AJMP code addr 1: aaa0 0001 */
|
||||
OPHANDLER( ajmp )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab code address byte */
|
||||
/*Thanks Gerrit for help with this! :) */
|
||||
PC = (PC & 0xf800) | ((r & 0xe0) << 3) | addr;
|
||||
}
|
||||
|
||||
/*ANL data addr, A 1: 0101 0010 */
|
||||
OPHANDLER( anl_mem_a )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr); /*Grab data from data address */
|
||||
IRAM_W(addr,data & ACC); /*Set data address value to it's value Logical AND with ACC */
|
||||
}
|
||||
|
||||
/*ANL data addr, #data 1: 0101 0011 */
|
||||
OPHANDLER( anl_mem_byte )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
UINT8 srcdata = IRAM_R(addr); /*Grab data from data address */
|
||||
IRAM_W(addr,srcdata & data); /*Set data address value to it's value Logical AND with Data */
|
||||
}
|
||||
|
||||
/*ANL A, #data 1: 0101 0100 */
|
||||
OPHANDLER( anl_a_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
SET_ACC(ACC & data); /*Set ACC to value of ACC Logical AND with Data */
|
||||
}
|
||||
|
||||
/*ANL A, data addr 1: 0101 0101 */
|
||||
OPHANDLER( anl_a_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr); /*Grab data from data address */
|
||||
SET_ACC(ACC & data); /*Set ACC to value of ACC Logical AND with Data */
|
||||
}
|
||||
|
||||
/*ANL A, @RO/@R1 1: 0101 011i */
|
||||
OPHANDLER( anl_a_ir )
|
||||
{
|
||||
UINT8 data = IRAM_IR(R_REG(r)); /*Grab data from address R0 or R1 points to */
|
||||
SET_ACC(ACC & data); /*Set ACC to value of ACC Logical AND with Data */
|
||||
}
|
||||
|
||||
/*ANL A, RO to R7 1: 0101 1rrr */
|
||||
OPHANDLER( anl_a_r )
|
||||
{
|
||||
UINT8 data = R_REG(r); /*Grab data from R0 - R7 */
|
||||
SET_ACC(ACC & data); /*Set ACC to value of ACC Logical AND with Data */
|
||||
}
|
||||
|
||||
/*ANL C, bit addr 1: 1000 0010 */
|
||||
OPHANDLER( anl_c_bitaddr )
|
||||
{
|
||||
int cy = GET_CY;
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
UINT8 bit = BIT_R(addr); /*Grab bit data from bit address */
|
||||
SET_CY( (cy & bit) ); /*Set Carry flag to Carry Flag Value Logical AND with Bit */
|
||||
}
|
||||
|
||||
/*ANL C,/bit addr 1: 1011 0000 */
|
||||
OPHANDLER( anl_c_nbitaddr )
|
||||
{
|
||||
int cy = GET_CY;
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
UINT8 bit = BIT_R(addr); /*Grab bit data from bit address */
|
||||
bit = ((~bit)&1); /*Complement bit */
|
||||
SET_CY( (cy & bit) ); /*Set Carry flag to Carry Flag Value Logical AND with Complemented Bit */
|
||||
}
|
||||
|
||||
/*CJNE A, #data, code addr 1: 1011 0100 */
|
||||
OPHANDLER( cjne_a_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
|
||||
if(ACC != data) /*Jump if values are not equal */
|
||||
{
|
||||
PC = PC + rel_addr;
|
||||
}
|
||||
|
||||
/*Set carry flag to 1 if 1st compare value is < 2nd compare value */
|
||||
SET_CY( (ACC < data) );
|
||||
}
|
||||
|
||||
/*CJNE A, data addr, code addr 1: 1011 0101 */
|
||||
OPHANDLER( cjne_a_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
UINT8 data = IRAM_R(addr); /*Pull value from data address */
|
||||
|
||||
if(ACC != data) /*Jump if values are not equal */
|
||||
{
|
||||
PC = PC + rel_addr;
|
||||
}
|
||||
|
||||
/*Set carry flag to 1 if 1st compare value is < 2nd compare value */
|
||||
SET_CY( (ACC < data) );
|
||||
}
|
||||
|
||||
/*CJNE @R0/@R1, #data, code addr 1: 1011 011i */
|
||||
OPHANDLER( cjne_ir_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
UINT8 srcdata = IRAM_IR(R_REG(r)); /*Grab value pointed to by R0 or R1 */
|
||||
|
||||
if(srcdata != data) /*Jump if values are not equal */
|
||||
{
|
||||
PC = PC + rel_addr;
|
||||
}
|
||||
|
||||
/*Set carry flag to 1 if 1st compare value is < 2nd compare value */
|
||||
SET_CY( (srcdata < data) );
|
||||
}
|
||||
|
||||
/*CJNE R0 to R7, #data, code addr 1: 1011 1rrr */
|
||||
OPHANDLER( cjne_r_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
UINT8 srcdata = R_REG(r); /*Grab value of R0 - R7 */
|
||||
|
||||
if(srcdata != data) /*Jump if values are not equal */
|
||||
{
|
||||
PC = PC + rel_addr;
|
||||
}
|
||||
|
||||
/*Set carry flag to 1 if 1st compare value is < 2nd compare value */
|
||||
SET_CY( (srcdata < data) );
|
||||
}
|
||||
|
||||
/*CLR bit addr 1: 1100 0010 */
|
||||
OPHANDLER( clr_bitaddr )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
BIT_W(addr,0); /*Clear bit at specified bit address */
|
||||
}
|
||||
|
||||
/*CLR C 1: 1100 0011 */
|
||||
OPHANDLER( clr_c )
|
||||
{
|
||||
SET_CY(0); /*Clear Carry Flag */
|
||||
}
|
||||
|
||||
/*CLR A 1: 1110 0100 */
|
||||
OPHANDLER( clr_a )
|
||||
{
|
||||
SET_ACC(0); /*Clear Accumulator */
|
||||
}
|
||||
|
||||
/*CPL bit addr 1: 1011 0010 */
|
||||
OPHANDLER( cpl_bitaddr )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
UINT8 data = (~BIT_R(addr))&1;
|
||||
BIT_W(addr,data); /*Complement bit at specified bit address */
|
||||
}
|
||||
|
||||
/*CPL C 1: 1011 0011 */
|
||||
OPHANDLER( cpl_c )
|
||||
{
|
||||
UINT8 bit = (~GET_CY)&1; /*Complement Carry Flag */
|
||||
SET_CY(bit);
|
||||
}
|
||||
|
||||
/*CPL A 1: 1111 0100 */
|
||||
OPHANDLER( cpl_a )
|
||||
{
|
||||
UINT8 data = ((~ACC)&0xff);
|
||||
SET_ACC(data); /*Complement Accumulator */
|
||||
}
|
||||
|
||||
/*DA A 1: 1101 0100 */
|
||||
OPHANDLER( da_a )
|
||||
{
|
||||
/*From several sources, since none said the same thing:
|
||||
The decimal adjust instruction is associated with the use of the ADD and ADDC instructions.
|
||||
The eight-bit value in the accumulator is adjusted to form two BCD digits of four bits each.
|
||||
If the accumulator contents bits 0-3 are greater than 9, OR the AC flag is set, then six is added to
|
||||
produce a proper BCD digit.
|
||||
If the carry is set, OR the four high bits 4-7 exceed nine, six is added to the value of these bits.
|
||||
The carry flag will be set if the result is > 0x99, but not cleared otherwise */
|
||||
|
||||
UINT16 new_acc = ACC & 0xff;
|
||||
if(GET_AC || (new_acc & 0x0f) > 0x09)
|
||||
new_acc += 0x06;
|
||||
if(GET_CY || ((new_acc & 0xf0) > 0x90) || (new_acc & ~0xff))
|
||||
new_acc += 0x60;
|
||||
SET_ACC(new_acc&0xff);
|
||||
if(new_acc & ~0xff)
|
||||
SET_CY(1);
|
||||
}
|
||||
|
||||
/*DEC A 1: 0001 0100 */
|
||||
OPHANDLER( dec_a )
|
||||
{
|
||||
SET_ACC(ACC-1);
|
||||
}
|
||||
|
||||
/*DEC data addr 1: 0001 0101 */
|
||||
OPHANDLER( dec_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr);
|
||||
IRAM_W(addr,data-1);
|
||||
}
|
||||
|
||||
/*DEC @R0/@R1 1: 0001 011i */
|
||||
OPHANDLER( dec_ir )
|
||||
{
|
||||
UINT8 data = IRAM_IR(R_REG(r));
|
||||
IRAM_W(R_REG(r),data-1);
|
||||
}
|
||||
|
||||
/*DEC R0 to R7 1: 0001 1rrr */
|
||||
OPHANDLER( dec_r )
|
||||
{
|
||||
SET_REG(r, R_REG(r) - 1);
|
||||
}
|
||||
|
||||
/*DIV AB 1: 1000 0100 */
|
||||
OPHANDLER( div_ab )
|
||||
{
|
||||
if( B == 0 ) {
|
||||
/*Overflow flag is set! */
|
||||
SET_OV(1);
|
||||
/*Really the values are undefined according to the manual, but we'll just leave them as is.. */
|
||||
/*SET_ACC(0xff); */
|
||||
/*SFR_W(B,0xff); */
|
||||
}
|
||||
else {
|
||||
int a = (int)ACC / B;
|
||||
int b = (int)ACC % B;
|
||||
/*A gets quotient byte, B gets remainder byte */
|
||||
SET_ACC(a);
|
||||
B = b;
|
||||
/*Overflow flag is cleared */
|
||||
SET_OV(0);
|
||||
}
|
||||
/*Carry Flag is always cleared */
|
||||
SET_CY(0);
|
||||
}
|
||||
|
||||
/*DJNZ data addr, code addr 1: 1101 0101 */
|
||||
OPHANDLER( djnz_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
IRAM_W(addr,IRAM_R(addr) - 1); /*Decrement value contained at data address */
|
||||
if(IRAM_R(addr) != 0) /*Branch if contents of data address is not 0 */
|
||||
{
|
||||
PC = PC + rel_addr;
|
||||
}
|
||||
}
|
||||
|
||||
/*DJNZ R0 to R7,code addr 1: 1101 1rrr */
|
||||
OPHANDLER( djnz_r )
|
||||
{
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
SET_REG(r ,R_REG(r) - 1); /*Decrement value */
|
||||
if(R_REG(r) != 0) /*Branch if contents of R0 - R7 is not 0 */
|
||||
{
|
||||
PC = PC + rel_addr;
|
||||
}
|
||||
}
|
||||
|
||||
/*INC A 1: 0000 0100 */
|
||||
OPHANDLER( inc_a )
|
||||
{
|
||||
SET_ACC(ACC+1);
|
||||
}
|
||||
|
||||
/*INC data addr 1: 0000 0101 */
|
||||
OPHANDLER( inc_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr);
|
||||
IRAM_W(addr,data+1);
|
||||
}
|
||||
|
||||
/*INC @R0/@R1 1: 0000 011i */
|
||||
OPHANDLER( inc_ir )
|
||||
{
|
||||
UINT8 data = IRAM_IR(R_REG(r));
|
||||
IRAM_W(R_REG(r),data+1);
|
||||
}
|
||||
|
||||
/*INC R0 to R7 1: 0000 1rrr */
|
||||
OPHANDLER( inc_r )
|
||||
{
|
||||
UINT8 data = R_REG(r);
|
||||
SET_REG(r, data + 1);
|
||||
}
|
||||
|
||||
/*INC DPTR 1: 1010 0011 */
|
||||
OPHANDLER( inc_dptr )
|
||||
{
|
||||
UINT16 dptr = (DPTR)+1;
|
||||
SET_DPTR(dptr);
|
||||
}
|
||||
|
||||
/*JB bit addr, code addr 1: 0010 0000 */
|
||||
OPHANDLER( jb )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
if(BIT_R(addr)) /*If bit set at specified bit address, jump */
|
||||
{
|
||||
PC = PC + rel_addr;
|
||||
}
|
||||
}
|
||||
|
||||
/*JBC bit addr, code addr 1: 0001 0000 */
|
||||
OPHANDLER( jbc )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
if(BIT_R(addr)) { /*If bit set at specified bit address, jump */
|
||||
PC = PC + rel_addr;
|
||||
BIT_W(addr,0); /*Clear Bit also */
|
||||
}
|
||||
}
|
||||
|
||||
/*JC code addr 1: 0100 0000 */
|
||||
OPHANDLER( jc )
|
||||
{
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
if(GET_CY) /*Jump if Carry Flag Set */
|
||||
{
|
||||
PC = PC + rel_addr;
|
||||
}
|
||||
}
|
||||
|
||||
/*JMP @A+DPTR 1: 0111 0011 */
|
||||
OPHANDLER( jmp_iadptr )
|
||||
{
|
||||
PC = ACC + DPTR;
|
||||
}
|
||||
|
||||
/*JNB bit addr, code addr 1: 0011 0000 */
|
||||
OPHANDLER( jnb )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
if(!BIT_R(addr)) /*If bit NOT set at specified bit address, jump */
|
||||
{
|
||||
PC = PC + rel_addr;
|
||||
}
|
||||
}
|
||||
|
||||
/*JNC code addr 1: 0101 0000 */
|
||||
OPHANDLER( jnc )
|
||||
{
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
if(!GET_CY) /*Jump if Carry Flag not set */
|
||||
{
|
||||
PC = PC + rel_addr;
|
||||
}
|
||||
}
|
||||
|
||||
/*JNZ code addr 1: 0111 0000 */
|
||||
OPHANDLER( jnz )
|
||||
{
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
if(ACC != 0) /*Branch if ACC is not 0 */
|
||||
{
|
||||
PC = PC+rel_addr;
|
||||
}
|
||||
}
|
||||
|
||||
/*JZ code addr 1: 0110 0000 */
|
||||
OPHANDLER( jz )
|
||||
{
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
if(ACC == 0) /*Branch if ACC is 0 */
|
||||
{
|
||||
PC = PC+rel_addr;
|
||||
}
|
||||
}
|
||||
|
||||
/*LCALL code addr 1: 0001 0010 */
|
||||
OPHANDLER( lcall )
|
||||
{
|
||||
UINT8 addr_hi, addr_lo;
|
||||
addr_hi = ROP_ARG(PC++);
|
||||
addr_lo = ROP_ARG(PC++);
|
||||
PUSH_PC();
|
||||
PC = (UINT16)((addr_hi<<8) | addr_lo);
|
||||
}
|
||||
|
||||
/*LJMP code addr 1: 0000 0010 */
|
||||
OPHANDLER( ljmp )
|
||||
{
|
||||
UINT8 addr_hi, addr_lo;
|
||||
addr_hi = ROP_ARG(PC++);
|
||||
addr_lo = ROP_ARG(PC++);
|
||||
PC = (UINT16)((addr_hi<<8) | addr_lo);
|
||||
}
|
||||
|
||||
/*MOV A, #data 1: 0111 0100 */
|
||||
OPHANDLER( mov_a_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
SET_ACC(data); /*Store data to ACC */
|
||||
}
|
||||
|
||||
/*MOV A, data addr 1: 1110 0101 */
|
||||
OPHANDLER( mov_a_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
SET_ACC(IRAM_R(addr)); /*Store contents of data address to ACC */
|
||||
}
|
||||
|
||||
/*MOV A,@RO/@R1 1: 1110 011i */
|
||||
OPHANDLER( mov_a_ir )
|
||||
{
|
||||
SET_ACC(IRAM_IR(R_REG(r))); /*Store contents of address pointed by R0 or R1 to ACC */
|
||||
}
|
||||
|
||||
/*MOV A,R0 to R7 1: 1110 1rrr */
|
||||
OPHANDLER( mov_a_r )
|
||||
{
|
||||
SET_ACC(R_REG(r)); /*Store contents of R0 - R7 to ACC */
|
||||
}
|
||||
|
||||
/*MOV data addr, #data 1: 0111 0101 */
|
||||
OPHANDLER( mov_mem_byte )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
IRAM_W(addr,data); /*Store data to data address location */
|
||||
}
|
||||
|
||||
/*MOV data addr, data addr 1: 1000 0101 */
|
||||
OPHANDLER( mov_mem_mem )
|
||||
{
|
||||
/*1st address is src, 2nd is dst, but the mov command works as mov dst,src) */
|
||||
UINT8 src,dst;
|
||||
src = ROP_ARG(PC++); /*Grab source data address */
|
||||
dst = ROP_ARG(PC++); /*Grab destination data address */
|
||||
IRAM_W(dst,IRAM_R(src)); /*Read source address contents and store to destination address */
|
||||
}
|
||||
|
||||
/*MOV @R0/@R1, #data 1: 0111 011i */
|
||||
OPHANDLER( mov_ir_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
IRAM_IW(R_REG(r),data); /*Store data to address pointed by R0 or R1 */
|
||||
}
|
||||
|
||||
/*MOV R0 to R7, #data 1: 0111 1rrr */
|
||||
OPHANDLER( mov_r_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
SET_REG(r, data); /*Store to R0 - R7 */
|
||||
}
|
||||
|
||||
/*MOV data addr, @R0/@R1 1: 1000 011i */
|
||||
OPHANDLER( mov_mem_ir )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
IRAM_W(addr,IRAM_IR(R_REG(r))); /*Store contents pointed to by R0 or R1 to data address */
|
||||
}
|
||||
|
||||
/*MOV data addr,R0 to R7 1: 1000 1rrr */
|
||||
OPHANDLER( mov_mem_r )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
IRAM_W(addr,R_REG(r)); /*Store contents of R0 - R7 to data address */
|
||||
}
|
||||
|
||||
/*MOV DPTR, #data16 1: 1001 0000 */
|
||||
OPHANDLER( mov_dptr_byte )
|
||||
{
|
||||
UINT8 data_hi, data_lo;
|
||||
data_hi = ROP_ARG(PC++); /*Grab hi byte */
|
||||
data_lo = ROP_ARG(PC++); /*Grab lo byte */
|
||||
SET_DPTR((UINT16)((data_hi<<8)|data_lo)); /*Store to DPTR */
|
||||
}
|
||||
|
||||
/*MOV bit addr, C 1: 1001 0010 */
|
||||
OPHANDLER( mov_bitaddr_c )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
BIT_W(addr,GET_CY); /*Store Carry Flag to Bit Address */
|
||||
}
|
||||
|
||||
/*MOV @R0/@R1, data addr 1: 1010 011i */
|
||||
OPHANDLER( mov_ir_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
IRAM_IW(R_REG(r),IRAM_R(addr)); /*Store data from data address to address pointed to by R0 or R1 */
|
||||
}
|
||||
|
||||
/*MOV R0 to R7, data addr 1: 1010 1rrr */
|
||||
OPHANDLER( mov_r_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
SET_REG(r, IRAM_R(addr)); /*Store to R0 - R7 */
|
||||
}
|
||||
|
||||
/*MOV data addr, A 1: 1111 0101 */
|
||||
OPHANDLER( mov_mem_a )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
IRAM_W(addr,ACC); /*Store A to data address */
|
||||
}
|
||||
|
||||
/*MOV @R0/@R1, A 1: 1111 011i */
|
||||
OPHANDLER( mov_ir_a )
|
||||
{
|
||||
IRAM_IW(R_REG(r),ACC); /*Store A to location pointed to by R0 or R1 */
|
||||
}
|
||||
|
||||
/*MOV R0 to R7, A 1: 1111 1rrr */
|
||||
OPHANDLER( mov_r_a )
|
||||
{
|
||||
SET_REG(r, ACC); /*Store A to R0-R7 */
|
||||
}
|
||||
|
||||
/*MOVC A, @A + PC 1: 1000 0011 */
|
||||
OPHANDLER( movc_a_iapc )
|
||||
{
|
||||
UINT8 data;
|
||||
data = CODEMEM_R(ACC+PC); /*Move a byte from CODE(Program) Memory and store to ACC */
|
||||
SET_ACC(data);
|
||||
}
|
||||
|
||||
/*MOV C, bit addr 1: 1010 0010 */
|
||||
OPHANDLER( mov_c_bitaddr )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
SET_CY( (BIT_R(addr)) ); /*Store Bit from Bit Address to Carry Flag */
|
||||
}
|
||||
|
||||
/*MOVC A, @A + DPTR 1: 1001 0011 */
|
||||
OPHANDLER( movc_a_iadptr )
|
||||
{
|
||||
UINT8 data;
|
||||
data = CODEMEM_R(ACC + DPTR); /*Move a byte from CODE(Program) Memory and store to ACC */
|
||||
SET_ACC(data);
|
||||
}
|
||||
|
||||
/*MOVX A,@DPTR 1: 1110 0000 */
|
||||
/*(Move External Ram 16 bit address to A) */
|
||||
OPHANDLER( movx_a_idptr )
|
||||
{
|
||||
/* UINT8 byte = DATAMEM_R(R_DPTR); //Grab 1 byte from External DATA memory pointed to by dptr */
|
||||
UINT32 addr = ERAM_ADDR(DPTR, 0xFFFF);
|
||||
UINT8 byte = DATAMEM_R(addr); /*Grab 1 byte from External DATA memory pointed to by dptr */
|
||||
SET_ACC(byte); /*Store to ACC */
|
||||
}
|
||||
|
||||
/*MOVX A, @R0/@R1 1: 1110 001i */
|
||||
/*(Move External Ram 8 bit address to A) */
|
||||
OPHANDLER( movx_a_ir )
|
||||
{
|
||||
UINT32 addr = ERAM_ADDR(R_REG(r),0xFF); /*Grab address by reading location pointed to by R0 or R1 */
|
||||
UINT8 byte = DATAMEM_R(addr); /*Grab 1 byte from External DATA memory pointed to by address */
|
||||
SET_ACC(byte); /*Store to ACC */
|
||||
}
|
||||
|
||||
/*MOVX @DPTR,A 1: 1111 0000 */
|
||||
/*(Move A to External Ram 16 bit address) */
|
||||
OPHANDLER( movx_idptr_a )
|
||||
{
|
||||
/* DATAMEM_W(R_DPTR, ACC); //Store ACC to External DATA memory address pointed to by DPTR */
|
||||
UINT32 addr = ERAM_ADDR(DPTR, 0xFFFF);
|
||||
DATAMEM_W(addr, ACC); /*Store ACC to External DATA memory address pointed to by DPTR */
|
||||
}
|
||||
|
||||
/*MOVX @R0/@R1,A 1: 1111 001i */
|
||||
/*(Move A to External Ram 8 bit address) */
|
||||
OPHANDLER( movx_ir_a )
|
||||
{
|
||||
UINT32 addr = ERAM_ADDR(R_REG(r),0xFF); /*Grab address by reading location pointed to by R0 or R1 */
|
||||
DATAMEM_W(addr, ACC); /*Store ACC to External DATA memory address */
|
||||
}
|
||||
|
||||
/*MUL AB 1: 1010 0100 */
|
||||
OPHANDLER( mul_ab )
|
||||
{
|
||||
UINT16 result = ACC * B;
|
||||
/*A gets lo bits, B gets hi bits of result */
|
||||
B = (UINT8) ((result & 0xFF00) >> 8);
|
||||
SET_ACC((UINT8)(result & 0x00FF));
|
||||
/*Set flags */
|
||||
SET_OV( ((result & 0x100) >> 8) ); /*Set/Clear Overflow Flag if result > 255 */
|
||||
SET_CY(0); /*Carry Flag always cleared */
|
||||
}
|
||||
|
||||
/*NOP 1: 0000 0000 */
|
||||
OPHANDLER( nop )
|
||||
{
|
||||
}
|
||||
|
||||
/*ORL data addr, A 1: 0100 0010 */
|
||||
OPHANDLER( orl_mem_a )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr); /*Grab data from data address */
|
||||
IRAM_W(addr,data | ACC); /*Set data address value to it's value Logical OR with ACC */
|
||||
}
|
||||
|
||||
/*ORL data addr, #data 1: 0100 0011 */
|
||||
OPHANDLER( orl_mem_byte )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
UINT8 srcdata = IRAM_R(addr); /*Grab data from data address */
|
||||
IRAM_W(addr,srcdata | data); /*Set data address value to it's value Logical OR with Data */
|
||||
}
|
||||
|
||||
/*ORL A, #data 1: 0100 0100 */
|
||||
OPHANDLER( orl_a_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
SET_ACC(ACC | data); /*Set ACC to value of ACC Logical OR with Data */
|
||||
}
|
||||
|
||||
/*ORL A, data addr 1: 0100 0101 */
|
||||
OPHANDLER( orl_a_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr); /*Grab data from data address */
|
||||
SET_ACC(ACC | data); /*Set ACC to value of ACC Logical OR with Data */
|
||||
}
|
||||
|
||||
/*ORL A, @RO/@R1 1: 0100 011i */
|
||||
OPHANDLER( orl_a_ir )
|
||||
{
|
||||
UINT8 data = IRAM_IR(R_REG(r)); /*Grab data from address R0 or R1 points to */
|
||||
SET_ACC(ACC | data); /*Set ACC to value of ACC Logical OR with Data */
|
||||
}
|
||||
|
||||
/*ORL A, RO to R7 1: 0100 1rrr */
|
||||
OPHANDLER( orl_a_r )
|
||||
{
|
||||
UINT8 data = R_REG(r); /*Grab data from R0 - R7 */
|
||||
SET_ACC(ACC | data); /*Set ACC to value of ACC Logical OR with Data */
|
||||
}
|
||||
|
||||
/*ORL C, bit addr 1: 0111 0010 */
|
||||
OPHANDLER( orl_c_bitaddr )
|
||||
{
|
||||
int cy = GET_CY;
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
UINT8 bit = BIT_R(addr); /*Grab bit data from bit address */
|
||||
SET_CY( (cy | bit) ); /*Set Carry flag to Carry Flag Value Logical OR with Bit */
|
||||
}
|
||||
|
||||
/*ORL C, /bit addr 1: 1010 0000 */
|
||||
OPHANDLER( orl_c_nbitaddr )
|
||||
{
|
||||
int cy = GET_CY;
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
UINT8 bit = BIT_R(addr); /*Grab bit data from bit address */
|
||||
bit = ((~bit)&1); /*Complement bit */
|
||||
SET_CY( (cy | bit) ); /*Set Carry flag to Carry Flag Value Logical OR with Complemented Bit */
|
||||
}
|
||||
|
||||
/*POP data addr 1: 1101 0000 */
|
||||
OPHANDLER( pop )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
IRAM_W(addr, IRAM_IR(SP)); /*Store to contents of data addr, data pointed to by Stack - IRAM_IR needed to access upper 128 bytes of stack */
|
||||
/*IRAM_IW(addr, IRAM_IR(R_SP)); //Store to contents of data addr, data pointed to by Stack - doesn't work, sfr's are not restored this way and it's not an indirect access anyway */
|
||||
SP = SP-1; /*Decrement SP */
|
||||
}
|
||||
|
||||
/*PUSH data addr 1: 1100 0000 */
|
||||
OPHANDLER( push )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 tmpSP = SP+1; /*Grab and Increment Stack Pointer */
|
||||
SP = tmpSP; /* "" */
|
||||
IRAM_IW(tmpSP, IRAM_R(addr)); /*Store to stack contents of data address - IRAM_IW needed to store to upper 128 bytes of stack, however, can't use IRAM_IR because that won't store the sfrs and it's not an indirect access anyway */
|
||||
}
|
||||
|
||||
/*RET 1: 0010 0010 */
|
||||
OPHANDLER( ret )
|
||||
{
|
||||
POP_PC();
|
||||
}
|
||||
|
||||
/*RETI 1: 0011 0010 */
|
||||
OPHANDLER( reti )
|
||||
{
|
||||
POP_PC();
|
||||
CLEAR_CURRENT_IRQ();
|
||||
}
|
||||
|
||||
/*RL A 1: 0010 0011 */
|
||||
OPHANDLER( rl_a )
|
||||
{
|
||||
/*Left Shift A, Bit 7 carries to Bit 0 */
|
||||
int carry = ((ACC & 0x80) >> 7);
|
||||
int data = (ACC<<1) & 0xfe;
|
||||
SET_ACC( data | carry);
|
||||
}
|
||||
|
||||
/*RLC A 1: 0011 0011 */
|
||||
OPHANDLER( rlc_a )
|
||||
{
|
||||
/*Left Shift A, Bit 7 goes to Carry Flag, Original Carry Flag goes to Bit 0 of ACC */
|
||||
int carry = ((ACC & 0x80) >> 7);
|
||||
int data = ((ACC<<1) & 0xfe) | GET_CY;
|
||||
SET_ACC( data);
|
||||
SET_CY(carry);
|
||||
}
|
||||
|
||||
/*RR A 1: 0000 0011 */
|
||||
OPHANDLER( rr_a )
|
||||
{
|
||||
/*Right Shift A, Bit 0 carries to Bit 7 */
|
||||
int carry = ((ACC & 1) << 7);
|
||||
int data = (ACC>>1) & 0x7f;
|
||||
SET_ACC( data | carry);
|
||||
}
|
||||
|
||||
/*RRC A 1: 0001 0011 */
|
||||
OPHANDLER( rrc_a )
|
||||
{
|
||||
/*Right Shift A, Bit 0 goes to Carry Flag, Bit 7 of ACC gets set to original Carry Flag */
|
||||
int carry = (ACC & 1);
|
||||
int data = ((ACC>>1) & 0x7f) | (GET_CY<<7);
|
||||
SET_ACC( data);
|
||||
SET_CY(carry);
|
||||
}
|
||||
|
||||
/*SETB C 1: 1101 0011 */
|
||||
OPHANDLER( setb_c )
|
||||
{
|
||||
SET_CY(1); /*Set Carry Flag */
|
||||
}
|
||||
|
||||
/*SETB bit addr 1: 1101 0010 */
|
||||
OPHANDLER( setb_bitaddr )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
BIT_W(addr,1); /*Set Bit at Bit Address */
|
||||
}
|
||||
|
||||
/*SJMP code addr 1: 1000 0000 */
|
||||
OPHANDLER( sjmp )
|
||||
{
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
PC = PC + rel_addr; /*Update PC */
|
||||
}
|
||||
|
||||
/*SUBB A, #data 1: 1001 0100 */
|
||||
OPHANDLER( subb_a_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
UINT8 result = ACC - data - GET_CY; /*Subtract data & carry flag from accumulator */
|
||||
DO_SUB_FLAGS(ACC,data,GET_CY); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
|
||||
}
|
||||
|
||||
/*SUBB A, data addr 1: 1001 0101 */
|
||||
OPHANDLER( subb_a_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr); /*Grab data from data address */
|
||||
UINT8 result = ACC - data - GET_CY; /*Subtract data & carry flag from accumulator */
|
||||
DO_SUB_FLAGS(ACC,data,GET_CY); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
}
|
||||
|
||||
/*SUBB A, @R0/@R1 1: 1001 011i */
|
||||
OPHANDLER( subb_a_ir )
|
||||
{
|
||||
UINT8 data = IRAM_IR(R_REG(r)); /*Grab data from memory pointed to by R0 or R1 */
|
||||
UINT8 result = ACC - data - GET_CY; /*Subtract data & carry flag from accumulator */
|
||||
DO_SUB_FLAGS(ACC,data,GET_CY); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
}
|
||||
|
||||
/*SUBB A, R0 to R7 1: 1001 1rrr */
|
||||
OPHANDLER( subb_a_r )
|
||||
{
|
||||
UINT8 data = R_REG(r); /*Grab data from R0 - R7 */
|
||||
UINT8 result = ACC - data - GET_CY; /*Subtract data & carry flag from accumulator */
|
||||
DO_SUB_FLAGS(ACC,data,GET_CY); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
}
|
||||
|
||||
/*SWAP A 1: 1100 0100 */
|
||||
OPHANDLER( swap_a )
|
||||
{
|
||||
UINT8 a_nib_lo, a_nib_hi;
|
||||
a_nib_hi = (ACC & 0x0f) << 4; /*Grab lo byte of ACC and move to hi */
|
||||
a_nib_lo = (ACC & 0xf0) >> 4; /*Grab hi byte of ACC and move to lo */
|
||||
SET_ACC( a_nib_hi | a_nib_lo);
|
||||
}
|
||||
|
||||
/*XCH A, data addr 1: 1100 0101 */
|
||||
OPHANDLER( xch_a_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr); /*Grab data */
|
||||
UINT8 oldACC = ACC; /*Hold value of ACC */
|
||||
SET_ACC(data); /*Sets ACC to data */
|
||||
IRAM_W(addr,oldACC); /*Sets data address to old value of ACC */
|
||||
}
|
||||
|
||||
/*XCH A, @RO/@R1 1: 1100 011i */
|
||||
OPHANDLER( xch_a_ir )
|
||||
{
|
||||
UINT8 data = IRAM_IR(R_REG(r)); /*Grab data pointed to by R0 or R1 */
|
||||
UINT8 oldACC = ACC; /*Hold value of ACC */
|
||||
SET_ACC(data); /*Sets ACC to data */
|
||||
IRAM_W(R_REG(r),oldACC); /*Sets data address to old value of ACC */
|
||||
}
|
||||
|
||||
/*XCH A, RO to R7 1: 1100 1rrr */
|
||||
OPHANDLER( xch_a_r )
|
||||
{
|
||||
UINT8 data = R_REG(r); /*Grab data from R0-R7 */
|
||||
UINT8 oldACC = ACC; /*Hold value of ACC */
|
||||
SET_ACC(data); /*Sets ACC to data */
|
||||
SET_REG(r, oldACC); /*Sets data address to old value of ACC */
|
||||
}
|
||||
|
||||
/*XCHD A, @R0/@R1 1: 1101 011i */
|
||||
OPHANDLER( xchd_a_ir )
|
||||
{
|
||||
UINT8 acc, ir_data;
|
||||
ir_data = IRAM_IR(R_REG(r)); /*Grab data pointed to by R0 or R1 */
|
||||
acc = ACC; /*Grab ACC value */
|
||||
SET_ACC( (acc & 0xf0) | (ir_data & 0x0f) ); /*Set ACC to lower nibble of data pointed to by R0 or R1 */
|
||||
IRAM_W(R_REG(r), (ir_data & 0xf0) | (acc & 0x0f) ); /*Set data pointed to by R0 or R1 to lower nibble of ACC */
|
||||
}
|
||||
|
||||
/*XRL data addr, A 1: 0110 0010 */
|
||||
OPHANDLER( xrl_mem_a )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr); /*Grab data from data address */
|
||||
IRAM_W(addr,data ^ ACC); /*Set data address value to it's value Logical XOR with ACC */
|
||||
}
|
||||
|
||||
/*XRL data addr, #data 1: 0110 0011 */
|
||||
OPHANDLER( xrl_mem_byte )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
UINT8 srcdata = IRAM_R(addr); /*Grab data from data address */
|
||||
IRAM_W(addr,srcdata ^ data); /*Set data address value to it's value Logical XOR with Data */
|
||||
}
|
||||
|
||||
/*XRL A, #data 1: 0110 0100 */
|
||||
OPHANDLER( xrl_a_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
SET_ACC(ACC ^ data); /*Set ACC to value of ACC Logical XOR with Data */
|
||||
}
|
||||
|
||||
/*XRL A, data addr 1: 0110 0101 */
|
||||
OPHANDLER( xrl_a_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr); /*Grab data from data address */
|
||||
SET_ACC(ACC ^ data); /*Set ACC to value of ACC Logical XOR with Data */
|
||||
}
|
||||
|
||||
/*XRL A, @R0/@R1 1: 0110 011i */
|
||||
OPHANDLER( xrl_a_ir )
|
||||
{
|
||||
UINT8 data = IRAM_IR(R_REG(r)); /*Grab data from address R0 or R1 points to */
|
||||
SET_ACC(ACC ^ data); /*Set ACC to value of ACC Logical XOR with Data */
|
||||
}
|
||||
|
||||
/*XRL A, R0 to R7 1: 0110 1rrr */
|
||||
OPHANDLER( xrl_a_r )
|
||||
{
|
||||
UINT8 data = R_REG(r); /*Grab data from R0 - R7 */
|
||||
SET_ACC(ACC ^ data); /*Set ACC to value of ACC Logical XOR with Data */
|
||||
}
|
||||
|
||||
/*illegal opcodes */
|
||||
OPHANDLER( illegal )
|
||||
{
|
||||
LOG(("i8051 #%d: illegal opcode at 0x%03x: %02x\n", cpu_getactivecpu(), PC-1, r));
|
||||
}
|
||||
@@ -63,6 +63,7 @@ typedef struct
|
||||
INT8 nmi_state;
|
||||
INT8 irq_state;
|
||||
int extra_cycles; /* extra cycles for interrupts */
|
||||
INT8 test_state; /* the TEST input */
|
||||
}
|
||||
i86_Regs;
|
||||
|
||||
@@ -123,12 +124,53 @@ static void i86_state_register(void)
|
||||
state_save_register_INT8( type, cpu, "NMI_STATE", &I.nmi_state, 1);
|
||||
state_save_register_INT8( type, cpu, "IRQ_STATE", &I.irq_state, 1);
|
||||
state_save_register_int( type, cpu, "EXTRA_CYCLES", &I.extra_cycles);
|
||||
state_save_register_INT8( type, cpu, "TEST_STATE", &I.test_state, 1);
|
||||
}
|
||||
|
||||
/* the 16-bit data bus, see i86intf.h */
|
||||
int i86_bus16;
|
||||
int i86_bus16_word;
|
||||
|
||||
unsigned i86_read_word16(unsigned ea)
|
||||
{
|
||||
unsigned lo, hi;
|
||||
|
||||
/* an odd address is two byte cycles on the 8086 too */
|
||||
if (ea & 1)
|
||||
{
|
||||
lo = cpu_readmem20(ea);
|
||||
hi = cpu_readmem20((ea + 1) & AMASK);
|
||||
return lo | (hi << 8);
|
||||
}
|
||||
i86_bus16_word = 1;
|
||||
lo = cpu_readmem20(ea);
|
||||
hi = cpu_readmem20(ea + 1);
|
||||
i86_bus16_word = 0;
|
||||
return lo | (hi << 8);
|
||||
}
|
||||
|
||||
void i86_write_word16(unsigned ea, unsigned val)
|
||||
{
|
||||
if (ea & 1)
|
||||
{
|
||||
cpu_writemem20(ea, val & 0xff);
|
||||
cpu_writemem20((ea + 1) & AMASK, (val >> 8) & 0xff);
|
||||
return;
|
||||
}
|
||||
i86_bus16_word = 1;
|
||||
cpu_writemem20(ea, val & 0xff);
|
||||
cpu_writemem20(ea + 1, (val >> 8) & 0xff);
|
||||
i86_bus16_word = 0;
|
||||
}
|
||||
|
||||
void i86_init(void)
|
||||
{
|
||||
unsigned int i, j, c;
|
||||
BREGS reg_name[8] = {AL, CL, DL, BL, AH, CH, DH, BH};
|
||||
|
||||
/* the 16-bit data bus is off unless the driver turns it on */
|
||||
i86_bus16 = 0;
|
||||
i86_bus16_word = 0;
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
for (j = i, c = 0; j > 0; j >>= 1)
|
||||
@@ -157,6 +199,7 @@ void i86_reset(void *param)
|
||||
{
|
||||
memset(&I, 0, sizeof (I));
|
||||
|
||||
I.test_state = 1;
|
||||
I.sregs[CS] = 0xf000;
|
||||
I.base[CS] = SegBase(CS);
|
||||
I.pc = 0xffff0 & AMASK;
|
||||
@@ -287,6 +330,11 @@ void i86_set_reg(int regnum, unsigned val)
|
||||
|
||||
void i86_set_irq_line(int irqline, int state)
|
||||
{
|
||||
if (irqline == I86_TEST_LINE)
|
||||
{
|
||||
I.test_state = (state != CLEAR_LINE);
|
||||
return;
|
||||
}
|
||||
if (irqline == IRQ_LINE_NMI)
|
||||
{
|
||||
if (I.nmi_state == state)
|
||||
|
||||
+8
-4
@@ -71,20 +71,24 @@ typedef enum { AL,AH,CL,CH,DL,DH,BL,BH,SPL,SPH,BPL,BPH,SIL,SIH,DIL,DIH } BREGS;
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/* the 16-bit data bus of the 8086 (see i86intf.h): off unless a driver turns it on */
|
||||
unsigned i86_read_word16(unsigned ea);
|
||||
void i86_write_word16(unsigned ea, unsigned val);
|
||||
|
||||
#define SegBase(Seg) (I.sregs[Seg] << 4)
|
||||
|
||||
#define DefaultBase(Seg) ((seg_prefix && (Seg == DS || Seg == SS)) ? prefix_base : I.base[Seg])
|
||||
|
||||
#define GetMemB(Seg,Off) (cpu_readmem20((DefaultBase(Seg) + (Off)) & AMASK))
|
||||
#define GetMemW(Seg,Off) ((WORD)GetMemB(Seg, Off) + (WORD)(GetMemB(Seg, (Off) + 1) << 8))
|
||||
#define GetMemW(Seg,Off) (i86_bus16 ? i86_read_word16((DefaultBase(Seg) + (Off)) & AMASK) : ((WORD)GetMemB(Seg, Off) + (WORD)(GetMemB(Seg, (Off) + 1) << 8)))
|
||||
#define PutMemB(Seg,Off,x) cpu_writemem20((DefaultBase(Seg) + (Off)) & AMASK, (x))
|
||||
#define PutMemW(Seg,Off,x) { PutMemB(Seg, Off, (x) & 0xff); PutMemB(Seg, (Off) + 1, ((x) >> 8) & 0xff); }
|
||||
#define PutMemW(Seg,Off,x) { if (i86_bus16) i86_write_word16((DefaultBase(Seg) + (Off)) & AMASK, (x)); else { PutMemB(Seg, Off, (x) & 0xff); PutMemB(Seg, (Off) + 1, ((x) >> 8) & 0xff); } }
|
||||
|
||||
#define PEEKBYTE(ea) (cpu_readmem20((ea) & AMASK))
|
||||
#define ReadByte(ea) (cpu_readmem20((ea) & AMASK))
|
||||
#define ReadWord(ea) (cpu_readmem20((ea) & AMASK) + (cpu_readmem20(((ea) + 1) & AMASK) << 8))
|
||||
#define ReadWord(ea) (i86_bus16 ? i86_read_word16((ea) & AMASK) : (cpu_readmem20((ea) & AMASK) + (cpu_readmem20(((ea) + 1) & AMASK) << 8)))
|
||||
#define WriteByte(ea,val) cpu_writemem20((ea) & AMASK, val);
|
||||
#define WriteWord(ea,val) { cpu_writemem20((ea) & AMASK, (val) & 0xff); cpu_writemem20(((ea) + 1) & AMASK, ((val) >> 8) & 0xff); }
|
||||
#define WriteWord(ea,val) { if (i86_bus16) i86_write_word16((ea) & AMASK, (val)); else { cpu_writemem20((ea) & AMASK, (val) & 0xff); cpu_writemem20(((ea) + 1) & AMASK, ((val) >> 8) & 0xff); } }
|
||||
|
||||
#define read_port(port) cpu_readport16(port)
|
||||
#define write_port(port,val) cpu_writeport16(port,val)
|
||||
|
||||
@@ -11,9 +11,23 @@ enum {
|
||||
I86_VECTOR, I86_PENDING, I86_NMI_STATE, I86_IRQ_STATE
|
||||
};
|
||||
|
||||
/* the TEST input (WAIT instruction): a CPU waits at a WAIT instruction
|
||||
while it is cleared; it is asserted at reset, so WAIT goes on unless a
|
||||
driver clears it */
|
||||
#define I86_TEST_LINE 1
|
||||
|
||||
/* Public variables */
|
||||
extern int i86_ICount;
|
||||
|
||||
/* The 8086 has a 16-bit data bus, but the core accesses memory a byte at a
|
||||
time. A driver whose hardware needs an aligned word access to be one bus
|
||||
cycle sets i86_bus16 (all the i86 CPUs of the machine): the core then
|
||||
accesses an aligned word as its low byte then its high byte, with
|
||||
i86_bus16_word set during the two accesses, so the handlers can make
|
||||
them one 16-bit access. Off by default: nothing changes for the others. */
|
||||
extern int i86_bus16;
|
||||
extern int i86_bus16_word;
|
||||
|
||||
/* Public functions */
|
||||
|
||||
extern void i86_init(void);
|
||||
|
||||
+37
-8
@@ -544,8 +544,13 @@ static void PREFIX(rep)(int flagval)
|
||||
for (; count > 0; count--)
|
||||
{
|
||||
if (ICOUNT <= 0) { I.pc = I.prevpc; break; }
|
||||
PutMemB(ES,I.regs.w[DI],I.regs.b[AL]);
|
||||
PutMemB(ES,I.regs.w[DI]+1,I.regs.b[AH]);
|
||||
if (i86_bus16)
|
||||
PutMemW(ES,I.regs.w[DI],I.regs.w[AX])
|
||||
else
|
||||
{
|
||||
PutMemB(ES,I.regs.w[DI],I.regs.b[AL]);
|
||||
PutMemB(ES,I.regs.w[DI]+1,I.regs.b[AH]);
|
||||
}
|
||||
I.regs.w[DI] += 2 * I.DirVal;
|
||||
ICOUNT -= cycles.rep_stos16_count;
|
||||
}
|
||||
@@ -1994,6 +1999,15 @@ static void PREFIX86(_call_far)(void)
|
||||
|
||||
static void PREFIX86(_wait)(void) /* Opcode 0x9b */
|
||||
{
|
||||
#ifndef I286
|
||||
/* the TEST input cleared: wait on this instruction */
|
||||
if (!I.test_state)
|
||||
{
|
||||
ICOUNT = 0;
|
||||
I.pc--;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
ICOUNT -= cycles.wait;
|
||||
}
|
||||
|
||||
@@ -2060,8 +2074,13 @@ static void PREFIX86(_mov_axdisp)(void) /* Opcode 0xa1 */
|
||||
addr += FETCH << 8;
|
||||
|
||||
ICOUNT -= cycles.mov_am16;
|
||||
I.regs.b[AL] = GetMemB(DS, addr);
|
||||
I.regs.b[AH] = GetMemB(DS, addr+1);
|
||||
if (i86_bus16)
|
||||
I.regs.w[AX] = GetMemW(DS, addr);
|
||||
else
|
||||
{
|
||||
I.regs.b[AL] = GetMemB(DS, addr);
|
||||
I.regs.b[AH] = GetMemB(DS, addr+1);
|
||||
}
|
||||
}
|
||||
|
||||
static void PREFIX86(_mov_dispal)(void) /* Opcode 0xa2 */
|
||||
@@ -2083,8 +2102,13 @@ static void PREFIX86(_mov_dispax)(void) /* Opcode 0xa3 */
|
||||
addr += FETCH << 8;
|
||||
|
||||
ICOUNT -= cycles.mov_ma16;
|
||||
PutMemB(DS, addr, I.regs.b[AL]);
|
||||
PutMemB(DS, addr+1, I.regs.b[AH]);
|
||||
if (i86_bus16)
|
||||
PutMemW(DS, addr, I.regs.w[AX])
|
||||
else
|
||||
{
|
||||
PutMemB(DS, addr, I.regs.b[AL]);
|
||||
PutMemB(DS, addr+1, I.regs.b[AH]);
|
||||
}
|
||||
}
|
||||
|
||||
static void PREFIX86(_movsb)(void) /* Opcode 0xa4 */
|
||||
@@ -2148,8 +2172,13 @@ static void PREFIX86(_stosb)(void) /* Opcode 0xaa */
|
||||
|
||||
static void PREFIX86(_stosw)(void) /* Opcode 0xab */
|
||||
{
|
||||
PutMemB(ES,I.regs.w[DI],I.regs.b[AL]);
|
||||
PutMemB(ES,I.regs.w[DI]+1,I.regs.b[AH]);
|
||||
if (i86_bus16)
|
||||
PutMemW(ES,I.regs.w[DI],I.regs.w[AX])
|
||||
else
|
||||
{
|
||||
PutMemB(ES,I.regs.w[DI],I.regs.b[AL]);
|
||||
PutMemB(ES,I.regs.w[DI]+1,I.regs.b[AH]);
|
||||
}
|
||||
I.regs.w[DI] += 2 * I.DirVal;
|
||||
ICOUNT -= cycles.stos16;
|
||||
}
|
||||
|
||||
+2815
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,67 @@
|
||||
/***************************************************************************
|
||||
|
||||
Intel 80960KA/KB, from current MAME (src/devices/cpu/i960,
|
||||
copyright Farfetch'd, R. Belmont, BSD-3-Clause), in C for MAME 2003.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef I960_H
|
||||
#define I960_H
|
||||
|
||||
#include "osd_cpu.h"
|
||||
|
||||
enum
|
||||
{
|
||||
I960_PFP = 0,
|
||||
I960_SP = 1,
|
||||
I960_RIP = 2,
|
||||
I960_FP = 31
|
||||
};
|
||||
|
||||
/* register numbers for get_reg / set_reg */
|
||||
enum
|
||||
{
|
||||
I960_IPREG = 1, I960_PIPREG, I960_SATREG, I960_PRCBREG, I960_PCREG, I960_ACREG,
|
||||
I960_R0REG
|
||||
/* I960_R0REG + n: r0..r15 g0..g15 */
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
I960_IRQ0 = 0,
|
||||
I960_IRQ1 = 1,
|
||||
I960_IRQ2 = 2,
|
||||
I960_IRQ3 = 3
|
||||
};
|
||||
|
||||
extern int i960_icount;
|
||||
|
||||
extern void i960_init(void);
|
||||
extern void i960_reset(void *param);
|
||||
extern void i960_exit(void);
|
||||
extern int i960_execute(int cycles);
|
||||
extern unsigned i960_get_context(void *dst);
|
||||
extern void i960_set_context(void *src);
|
||||
extern unsigned i960_get_reg(int regnum);
|
||||
extern void i960_set_reg(int regnum, unsigned val);
|
||||
extern void i960_set_irq_line(int irqline, int state);
|
||||
extern void i960_set_irq_callback(int (*callback)(int irqline));
|
||||
extern const char *i960_info(void *context, int regnum);
|
||||
extern unsigned i960_dasm(char *buffer, unsigned pc);
|
||||
|
||||
/* Model 2: a FIFO access that cannot complete now (copro FIFO empty or
|
||||
full) repeats the instruction later; a multi-word access already half
|
||||
done resumes where it stopped (current MAME, i960_stall) */
|
||||
extern void i960_stall(void);
|
||||
/* the regions where ldl/ldt/ldq/stl/stt/stq step through the addresses
|
||||
(current MAME's BURST flag); elsewhere (FIFOs, registers) every word
|
||||
goes to the same address. NULL: everywhere. */
|
||||
extern void i960_set_burst_callback(int (*is_burst)(UINT32 address));
|
||||
|
||||
/* the addresses an idle loop may read: reading them has no side effect
|
||||
and their contents change only between timeslices (RAM, a status
|
||||
register updated by an interrupt). NULL (default): idle loops are not
|
||||
skipped. */
|
||||
extern void i960_set_idle_read_callback(int (*read_ok)(UINT32 address));
|
||||
|
||||
#endif
|
||||
@@ -470,6 +470,20 @@ void konami_set_reg(int regnum, unsigned val)
|
||||
/****************************************************************************/
|
||||
void konami_init(void)
|
||||
{
|
||||
int cpu = cpu_getactivecpu();
|
||||
state_save_register_UINT16("konami", cpu, "PC", &PC, 1);
|
||||
state_save_register_UINT16("konami", cpu, "U", &U, 1);
|
||||
state_save_register_UINT16("konami", cpu, "S", &S, 1);
|
||||
state_save_register_UINT16("konami", cpu, "X", &X, 1);
|
||||
state_save_register_UINT16("konami", cpu, "Y", &Y, 1);
|
||||
state_save_register_UINT16("konami", cpu, "D", &D, 1);
|
||||
state_save_register_UINT8("konami", cpu, "DP", &DP, 1);
|
||||
state_save_register_UINT8("konami", cpu, "CC", &CC, 1);
|
||||
state_save_register_UINT8("konami", cpu, "INT", &konami.int_state, 1);
|
||||
state_save_register_UINT8("konami", cpu, "NMI", &konami.nmi_state, 1);
|
||||
state_save_register_UINT8("konami", cpu, "IRQ", &konami.irq_state[0], 1);
|
||||
state_save_register_UINT8("konami", cpu, "FIRQ", &konami.irq_state[1], 1);
|
||||
state_save_register_int("konami", cpu, "extra_cycles", &konami.extra_cycles); /* the cycles of an interrupt taken outside the execute loop */
|
||||
}
|
||||
|
||||
void konami_reset(void *param)
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,172 @@
|
||||
#ifndef HEADER__M37710
|
||||
#define HEADER__M37710
|
||||
|
||||
/* ======================================================================== */
|
||||
/* =============================== COPYRIGHT ============================== */
|
||||
/* ======================================================================== */
|
||||
/*
|
||||
|
||||
M37710 CPU Emulator v0.1
|
||||
|
||||
mame2003-plus: backported from MAME 0.121 to the 0.78 CPU interface.
|
||||
The on-chip registers (0x00-0x7f), on-chip RAM (0x80-0x27f) and, for the
|
||||
M37702 with internal mask ROM, the internal ROM (0xc000-0xffff) are
|
||||
handled inside the core. The on-chip I/O ports and ADC are routed to the
|
||||
driver through m37710_set_io_handlers(). Single instance only.
|
||||
|
||||
*/
|
||||
|
||||
#include "osd_cpu.h"
|
||||
|
||||
/* ======================================================================== */
|
||||
/* =============================== DEFINES ================================ */
|
||||
/* ======================================================================== */
|
||||
/*
|
||||
Input lines - used with cpu_set_irq_line() and the like.
|
||||
WARNING: these are in the same order as the vector table for simplicity.
|
||||
Do not alter this order!
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
/* these interrupts are maskable */
|
||||
M37710_LINE_ADC = 0,
|
||||
M37710_LINE_UART1XMIT,
|
||||
M37710_LINE_UART1RECV,
|
||||
M37710_LINE_UART0XMIT,
|
||||
M37710_LINE_UART0RECV,
|
||||
M37710_LINE_TIMERB2,
|
||||
M37710_LINE_TIMERB1,
|
||||
M37710_LINE_TIMERB0,
|
||||
M37710_LINE_TIMERA4,
|
||||
M37710_LINE_TIMERA3,
|
||||
M37710_LINE_TIMERA2,
|
||||
M37710_LINE_TIMERA1,
|
||||
M37710_LINE_TIMERA0,
|
||||
M37710_LINE_IRQ2,
|
||||
M37710_LINE_IRQ1,
|
||||
M37710_LINE_IRQ0,
|
||||
/* these interrupts are non-maskable */
|
||||
M37710_LINE_WATCHDOG,
|
||||
M37710_LINE_DEBUG,
|
||||
M37710_LINE_BRK,
|
||||
M37710_LINE_ZERODIV,
|
||||
M37710_LINE_RESET,
|
||||
|
||||
/* these are not interrupts, they're signals external hardware can send */
|
||||
M37710_LINE_TIMERA0TICK,
|
||||
M37710_LINE_TIMERA1TICK,
|
||||
M37710_LINE_TIMERA2TICK,
|
||||
M37710_LINE_TIMERA3TICK,
|
||||
M37710_LINE_TIMERA4TICK,
|
||||
M37710_LINE_TIMERB0TICK,
|
||||
M37710_LINE_TIMERB1TICK,
|
||||
M37710_LINE_TIMERB2TICK,
|
||||
|
||||
/* timer A output pins: the count direction of an event counter in up/down pin mode */
|
||||
M37710_LINE_TIMERA0OUT,
|
||||
M37710_LINE_TIMERA1OUT,
|
||||
M37710_LINE_TIMERA2OUT,
|
||||
M37710_LINE_TIMERA3OUT,
|
||||
M37710_LINE_TIMERA4OUT,
|
||||
|
||||
M37710_LINE_MAX
|
||||
};
|
||||
|
||||
/* Registers - used by m37710_set_reg() and m37710_get_reg() */
|
||||
enum
|
||||
{
|
||||
M37710_PC=1, M37710_S, M37710_P, M37710_A, M37710_B, M37710_X, M37710_Y,
|
||||
M37710_PB, M37710_DB, M37710_D, M37710_E,
|
||||
M37710_NMI_STATE, M37710_IRQ_STATE
|
||||
};
|
||||
|
||||
|
||||
/* I/O ports */
|
||||
enum
|
||||
{
|
||||
M37710_PORT0 = 0,
|
||||
M37710_PORT1, M37710_PORT2, M37710_PORT3, M37710_PORT4,
|
||||
M37710_PORT5, M37710_PORT6, M37710_PORT7, M37710_PORT8,
|
||||
|
||||
M37710_ADC0_L = 0x10, M37710_ADC0_H,
|
||||
M37710_ADC1_L, M37710_ADC1_H, M37710_ADC2_L, M37710_ADC2_H, M37710_ADC3_L, M37710_ADC3_H,
|
||||
M37710_ADC4_L, M37710_ADC4_H, M37710_ADC5_L, M37710_ADC5_H, M37710_ADC6_L, M37710_ADC6_H,
|
||||
M37710_ADC7_L, M37710_ADC7_H,
|
||||
|
||||
M37710_SER0_REC = 0x20,
|
||||
M37710_SER0_XMIT, M37710_SER1_REC, M37710_SER1_XMIT
|
||||
};
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== PROTOTYPES ============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
typedef data8_t (*m37710_io_read_func)(int port);
|
||||
typedef void (*m37710_io_write_func)(int port, data8_t data);
|
||||
|
||||
/* hook the on-chip ports/ADC to the driver */
|
||||
void m37710_set_io_handlers(m37710_io_read_func readfn, m37710_io_write_func writefn);
|
||||
/* M37702 with internal mask ROM: 16KB mapped at 0xc000-0xffff (NULL = external) */
|
||||
void m37710_set_internal_rom(const UINT8 *rom);
|
||||
/*
|
||||
Speedup (0 = off): 'pc' (bank | address) starts a loop of 'count'
|
||||
instructions that only polls memory written by interrupts (such as
|
||||
"lda dp / beq loop"), so every pass leaves the same state. Once one
|
||||
pass has run inside a timeslice, the whole passes that still fit in
|
||||
it are skipped: registers, memory and cycles end up exactly as if
|
||||
they had run.
|
||||
*/
|
||||
void m37710_set_idle_loop(UINT32 pc, int count);
|
||||
|
||||
extern int m37710_ICount; /* cycle count */
|
||||
|
||||
void m37710_init(void);
|
||||
void m37710_reset(void *param);
|
||||
void m37710_exit(void);
|
||||
int m37710_execute(int cycles);
|
||||
unsigned m37710_get_context(void *dst);
|
||||
void m37710_set_context(void *src);
|
||||
unsigned m37710_get_reg(int regnum);
|
||||
void m37710_set_reg(int regnum, unsigned val);
|
||||
void m37710_set_irq_line(int irqline, int state);
|
||||
void m37710_set_irq_callback(int (*callback)(int irqline));
|
||||
const char *m37710_info(void *context, int regnum);
|
||||
unsigned m37710_dasm(char *buffer, unsigned pc);
|
||||
|
||||
#define m37702_ICount m37710_ICount
|
||||
#define m37702_init m37710_init
|
||||
#define m37702_reset m37710_reset
|
||||
#define m37702_exit m37710_exit
|
||||
#define m37702_execute m37710_execute
|
||||
#define m37702_get_context m37710_get_context
|
||||
#define m37702_set_context m37710_set_context
|
||||
#define m37702_get_reg m37710_get_reg
|
||||
#define m37702_set_reg m37710_set_reg
|
||||
#define m37702_set_irq_line m37710_set_irq_line
|
||||
#define m37702_set_irq_callback m37710_set_irq_callback
|
||||
#define m37702_info m37710_info
|
||||
#define m37702_dasm m37710_dasm
|
||||
|
||||
/* memory access, including the on-chip resources */
|
||||
UINT8 m37710_mem_read8(UINT32 address);
|
||||
UINT16 m37710_mem_read16(UINT32 address);
|
||||
void m37710_mem_write8(UINT32 address, UINT8 data);
|
||||
void m37710_mem_write16(UINT32 address, UINT16 data);
|
||||
|
||||
#undef M37710_CALL_DEBUGGER
|
||||
|
||||
#define M37710_CALL_DEBUGGER CALL_MAME_DEBUG
|
||||
#define m37710_read_8(addr) m37710_mem_read8(addr)
|
||||
#define m37710_write_8(addr,data) m37710_mem_write8(addr,data)
|
||||
#define m37710_read_8_immediate(A) m37710_mem_read8(A)
|
||||
#define m37710_read_16(addr) m37710_mem_read16(addr)
|
||||
#define m37710_write_16(addr,data) m37710_mem_write16(addr,data)
|
||||
#define m37710_jumping(A)
|
||||
#define m37710_branching(A)
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== END OF FILE ============================= */
|
||||
/* ======================================================================== */
|
||||
|
||||
#endif /* HEADER__M37710 */
|
||||
@@ -0,0 +1,323 @@
|
||||
/* M37710/M37702 core internals: from MAME 0.121 (MAME license; R. Belmont,
|
||||
based on the G65816 core by Karl Stenerud) */
|
||||
|
||||
#ifndef HEADER__M37710CM
|
||||
#define HEADER__M37710CM
|
||||
|
||||
#define m37710i_branching(A)
|
||||
#define m37710i_jumping(A)
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================ INCLUDES ============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
#include <limits.h>
|
||||
#include "driver.h"
|
||||
#include "cpuintrf.h"
|
||||
#include "mamedbg.h"
|
||||
#include "m37710.h"
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================ GENERAL =============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Fallback on static if we don't have inline */
|
||||
|
||||
|
||||
/* This should be set to the default size of your processor (min 16 bit) */
|
||||
#undef uint
|
||||
#define uint unsigned int
|
||||
|
||||
#undef uint8
|
||||
#define uint8 unsigned char
|
||||
|
||||
#undef int8
|
||||
|
||||
/* Allow for architectures that don't have 8-bit sizes */
|
||||
#if UCHAR_MAX == 0xff
|
||||
#define int8 char
|
||||
#define MAKE_INT_8(A) (int8)((A)&0xff)
|
||||
#else
|
||||
#define int8 int
|
||||
static INLINE int MAKE_INT_8(int A) {return (A & 0x80) ? A | ~0xff : A & 0xff;}
|
||||
#endif /* UCHAR_MAX == 0xff */
|
||||
|
||||
#define MAKE_UINT_8(A) ((A)&0xff)
|
||||
#define MAKE_UINT_16(A) ((A)&0xffff)
|
||||
#define MAKE_UINT_24(A) ((A)&0xffffff)
|
||||
|
||||
/* Bits */
|
||||
#define BIT_0 0x01
|
||||
#define BIT_1 0x02
|
||||
#define BIT_2 0x04
|
||||
#define BIT_3 0x08
|
||||
#define BIT_4 0x10
|
||||
#define BIT_5 0x20
|
||||
#define BIT_6 0x40
|
||||
#define BIT_7 0x80
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================== CPU ================================= */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* CPU Structure */
|
||||
typedef struct
|
||||
{
|
||||
uint a; /* Accumulator */
|
||||
uint b; /* holds high byte of accumulator */
|
||||
uint ba; /* Secondary Accumulator */
|
||||
uint bb; /* holds high byte of secondary accumulator */
|
||||
uint x; /* Index Register X */
|
||||
uint y; /* Index Register Y */
|
||||
uint s; /* Stack Pointer */
|
||||
uint pc; /* Program Counter */
|
||||
uint ppc; /* Previous Program Counter */
|
||||
uint pb; /* Program Bank (shifted left 16) */
|
||||
uint db; /* Data Bank (shifted left 16) */
|
||||
uint d; /* Direct Register */
|
||||
uint flag_e; /* Emulation Mode Flag */
|
||||
uint flag_m; /* Memory/Accumulator Select Flag */
|
||||
uint flag_x; /* Index Select Flag */
|
||||
uint flag_n; /* Negative Flag */
|
||||
uint flag_v; /* Overflow Flag */
|
||||
uint flag_d; /* Decimal Mode Flag */
|
||||
uint flag_i; /* Interrupt Mask Flag */
|
||||
uint flag_z; /* Zero Flag (inverted) */
|
||||
uint flag_c; /* Carry Flag */
|
||||
uint line_irq; /* Bitmask of pending IRQs */
|
||||
uint ipl; /* Interrupt priority level (top of PSW) */
|
||||
uint ir; /* Instruction Register */
|
||||
uint im; /* Immediate load value */
|
||||
uint im2; /* Immediate load target */
|
||||
uint im3; /* Immediate load target */
|
||||
uint im4; /* Immediate load target */
|
||||
uint irq_delay; /* delay 1 instruction before checking irq */
|
||||
uint irq_level; /* irq level */
|
||||
int (*int_ack)(int); /* Interrupt Acknowledge */
|
||||
uint stopped; /* Sets how the CPU is stopped */
|
||||
void (**opcodes)(void); /* opcodes with no prefix */
|
||||
void (**opcodes42)(void); /* opcodes with 0x42 prefix */
|
||||
void (**opcodes89)(void); /* opcodes with 0x89 prefix */
|
||||
uint (*get_reg)(int regnum);
|
||||
void (*set_reg)(int regnum, uint val);
|
||||
void (*set_line)(int line, int state);
|
||||
int (*execute)(int cycles);
|
||||
|
||||
/* on-board peripheral stuff */
|
||||
UINT8 m37710_regs[128];
|
||||
double reload[8];
|
||||
mame_timer *timers[8];
|
||||
double timer_left[8]; /* saved: time left of each timer (< 0: not armed) */
|
||||
} m37710i_cpu_struct;
|
||||
|
||||
extern m37710i_cpu_struct m37710i_cpu;
|
||||
extern UINT32 m37710_idle_pc;
|
||||
extern int m37710_idle_count, m37710_idle_since, m37710_idle_clocks;
|
||||
extern int m37710_ICount;
|
||||
extern uint m37710i_source;
|
||||
extern uint m37710i_destination;
|
||||
extern uint m37710i_adc_tbl[];
|
||||
extern uint m37710i_sbc_tbl[];
|
||||
|
||||
extern void (**m37710i_opcodes[])(void);
|
||||
extern void (**m37710i_opcodes2[])(void);
|
||||
extern void (**m37710i_opcodes3[])(void);
|
||||
extern uint (*m37710i_get_reg[])(int regnum);
|
||||
extern void (*m37710i_set_reg[])(int regnum, uint val);
|
||||
extern void (*m37710i_set_line[])(int line, int state);
|
||||
extern int (*m37710i_execute[])(int cycles);
|
||||
|
||||
#define REG_A m37710i_cpu.a /* Accumulator */
|
||||
#define REG_B m37710i_cpu.b /* Accumulator hi byte */
|
||||
#define REG_BA m37710i_cpu.ba /* Secondary Accumulator */
|
||||
#define REG_BB m37710i_cpu.bb /* Secondary Accumulator hi byte */
|
||||
#define REG_X m37710i_cpu.x /* Index X Register */
|
||||
#define REG_Y m37710i_cpu.y /* Index Y Register */
|
||||
#define REG_S m37710i_cpu.s /* Stack Pointer */
|
||||
#define REG_PC m37710i_cpu.pc /* Program Counter */
|
||||
#define REG_PPC m37710i_cpu.ppc /* Previous Program Counter */
|
||||
#define REG_PB m37710i_cpu.pb /* Program Bank */
|
||||
#define REG_DB m37710i_cpu.db /* Data Bank */
|
||||
#define REG_D m37710i_cpu.d /* Direct Register */
|
||||
#define FLAG_M m37710i_cpu.flag_m /* Memory/Accumulator Select Flag */
|
||||
#define FLAG_X m37710i_cpu.flag_x /* Index Select Flag */
|
||||
#define FLAG_N m37710i_cpu.flag_n /* Negative Flag */
|
||||
#define FLAG_V m37710i_cpu.flag_v /* Overflow Flag */
|
||||
#define FLAG_D m37710i_cpu.flag_d /* Decimal Mode Flag */
|
||||
#define FLAG_I m37710i_cpu.flag_i /* Interrupt Mask Flag */
|
||||
#define FLAG_Z m37710i_cpu.flag_z /* Zero Flag (inverted) */
|
||||
#define FLAG_C m37710i_cpu.flag_c /* Carry Flag */
|
||||
#define LINE_IRQ m37710i_cpu.line_irq /* Status of the IRQ line */
|
||||
#define REG_IR m37710i_cpu.ir /* Instruction Register */
|
||||
#define REG_IM m37710i_cpu.im /* Immediate load value */
|
||||
#define REG_IM2 m37710i_cpu.im2 /* Immediate load target */
|
||||
#define REG_IM3 m37710i_cpu.im3 /* Immediate load target */
|
||||
#define REG_IM4 m37710i_cpu.im4 /* Immediate load target */
|
||||
#define INT_ACK m37710i_cpu.int_ack /* Interrupt Acknowledge function pointer */
|
||||
#define CLOCKS m37710_ICount /* Clock cycles remaining */
|
||||
#define IRQ_DELAY m37710i_cpu.irq_delay /* Delay 1 instruction before checking IRQ */
|
||||
#define CPU_STOPPED m37710i_cpu.stopped /* Stopped status of the CPU */
|
||||
|
||||
#define FTABLE_OPCODES m37710i_cpu.opcodes
|
||||
#define FTABLE_OPCODES2 m37710i_cpu.opcodes42
|
||||
#define FTABLE_OPCODES3 m37710i_cpu.opcodes89
|
||||
#define FTABLE_GET_REG m37710i_cpu.get_reg
|
||||
#define FTABLE_SET_REG m37710i_cpu.set_reg
|
||||
#define FTABLE_SET_LINE m37710i_cpu.set_line
|
||||
#define FTABLE_EXECUTE m37710i_cpu.execute
|
||||
|
||||
#define SRC m37710i_source /* Source Operand */
|
||||
#define DST m37710i_destination /* Destination Operand */
|
||||
|
||||
#define STOP_LEVEL_WAI 1
|
||||
#define STOP_LEVEL_STOP 2
|
||||
|
||||
#define EXECUTION_MODE_M0X0 0
|
||||
#define EXECUTION_MODE_M0X1 1
|
||||
#define EXECUTION_MODE_M1X0 2
|
||||
#define EXECUTION_MODE_M1X1 3
|
||||
|
||||
static INLINE void m37710i_set_execution_mode(uint mode)
|
||||
{
|
||||
FTABLE_OPCODES = m37710i_opcodes[mode];
|
||||
FTABLE_OPCODES2 = m37710i_opcodes2[mode];
|
||||
FTABLE_OPCODES3 = m37710i_opcodes3[mode];
|
||||
FTABLE_GET_REG = m37710i_get_reg[mode];
|
||||
FTABLE_SET_REG = m37710i_set_reg[mode];
|
||||
FTABLE_SET_LINE = m37710i_set_line[mode];
|
||||
FTABLE_EXECUTE = m37710i_execute[mode];
|
||||
}
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================= CLOCK ================================ */
|
||||
/* ======================================================================== */
|
||||
|
||||
#define CLK_OP 1
|
||||
#define CLK_R8 1
|
||||
#define CLK_R16 2
|
||||
#define CLK_R24 3
|
||||
#define CLK_W8 1
|
||||
#define CLK_W16 2
|
||||
#define CLK_W24 3
|
||||
#define CLK_RMW8 3
|
||||
#define CLK_RMW16 5
|
||||
|
||||
#define CLK_IMPLIED 1
|
||||
#define CLK_IMPLIED 1
|
||||
#define CLK_RELATIVE_8 1
|
||||
#define CLK_RELATIVE_16 2
|
||||
#define CLK_IMM 0
|
||||
#define CLK_AI 4
|
||||
#define CLK_AXI 4
|
||||
#define CLK_A 2
|
||||
#define CLK_AL 3
|
||||
#define CLK_ALX 3
|
||||
#define CLK_AX 2
|
||||
#define CLK_AY 2
|
||||
#define CLK_D 1
|
||||
#define CLK_DI 3
|
||||
#define CLK_DIY 3
|
||||
#define CLK_DLI 4
|
||||
#define CLK_DLIY 4
|
||||
#define CLK_DX 2
|
||||
#define CLK_DXI 4
|
||||
#define CLK_DY 2
|
||||
#define CLK_S 2
|
||||
#define CLK_SIY 5
|
||||
|
||||
/* AX and AY addressing modes take 1 extra cycle when writing */
|
||||
#define CLK_W_IMM 0
|
||||
#define CLK_W_AI 4
|
||||
#define CLK_W_AXI 4
|
||||
#define CLK_W_A 2
|
||||
#define CLK_W_AL 3
|
||||
#define CLK_W_ALX 3
|
||||
#define CLK_W_AX 3
|
||||
#define CLK_W_AY 3
|
||||
#define CLK_W_D 1
|
||||
#define CLK_W_DI 3
|
||||
#define CLK_W_DIY 3
|
||||
#define CLK_W_DLI 4
|
||||
#define CLK_W_DLIY 4
|
||||
#define CLK_W_DX 2
|
||||
#define CLK_W_DXI 4
|
||||
#define CLK_W_DY 2
|
||||
#define CLK_W_S 2
|
||||
#define CLK_W_SIY 5
|
||||
|
||||
#define CLK(A) CLOCKS -= (A)
|
||||
#define USE_ALL_CLKS() CLOCKS = 0
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================ STATUS REGISTER =========================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Flag positions in Processor Status Register */
|
||||
/* common */
|
||||
#define FLAGPOS_N BIT_7 /* Negative */
|
||||
#define FLAGPOS_V BIT_6 /* Overflow */
|
||||
#define FLAGPOS_D BIT_3 /* Decimal Mode */
|
||||
#define FLAGPOS_I BIT_2 /* Interrupt Mask */
|
||||
#define FLAGPOS_Z BIT_1 /* Zero */
|
||||
#define FLAGPOS_C BIT_0 /* Carry */
|
||||
/* emulation */
|
||||
#define FLAGPOS_R BIT_5 /* Reserved */
|
||||
#define FLAGPOS_B BIT_4 /* BRK Instruction */
|
||||
/* native */
|
||||
#define FLAGPOS_M BIT_5 /* Mem/Reg Select */
|
||||
#define FLAGPOS_X BIT_4 /* Index Select */
|
||||
|
||||
#define EFLAG_SET 1
|
||||
#define EFLAG_CLEAR 0
|
||||
#define MFLAG_SET FLAGPOS_M
|
||||
#define MFLAG_CLEAR 0
|
||||
#define XFLAG_SET FLAGPOS_X
|
||||
#define XFLAG_CLEAR 0
|
||||
#define NFLAG_SET 0x80
|
||||
#define NFLAG_CLEAR 0
|
||||
#define VFLAG_SET 0x80
|
||||
#define VFLAG_CLEAR 0
|
||||
#define DFLAG_SET FLAGPOS_D
|
||||
#define DFLAG_CLEAR 0
|
||||
#define IFLAG_SET FLAGPOS_I
|
||||
#define IFLAG_CLEAR 0
|
||||
#define BFLAG_SET FLAGPOS_B
|
||||
#define BFLAG_CLEAR 0
|
||||
#define ZFLAG_SET 0
|
||||
#define ZFLAG_CLEAR 1
|
||||
#define CFLAG_SET 0x100
|
||||
#define CFLAG_CLEAR 0
|
||||
|
||||
/* Codition code tests */
|
||||
#define COND_CC() (!(FLAG_C&0x100)) /* Carry Clear */
|
||||
#define COND_CS() (FLAG_C&0x100) /* Carry Set */
|
||||
#define COND_EQ() (!FLAG_Z) /* Equal */
|
||||
#define COND_NE() FLAG_Z /* Not Equal */
|
||||
#define COND_MI() (FLAG_N&0x80) /* Minus */
|
||||
#define COND_PL() (!(FLAG_N&0x80)) /* Plus */
|
||||
#define COND_VC() (!(FLAG_V&0x80)) /* Overflow Clear */
|
||||
#define COND_VS() (FLAG_V&0x80) /* Overflow Set */
|
||||
|
||||
/* Set Overflow flag in math operations */
|
||||
#define VFLAG_ADD_8(S, D, R) ((S^R) & (D^R))
|
||||
#define VFLAG_ADD_16(S, D, R) (((S^R) & (D^R))>>8)
|
||||
#define VFLAG_SUB_8(S, D, R) ((S^D) & (R^D))
|
||||
#define VFLAG_SUB_16(S, D, R) (((S^D) & (R^D))>>8)
|
||||
|
||||
#define CFLAG_8(A) (A)
|
||||
#define CFLAG_16(A) ((A)>>8)
|
||||
#define NFLAG_8(A) (A)
|
||||
#define NFLAG_16(A) ((A)>>8)
|
||||
|
||||
#define CFLAG_AS_1() ((FLAG_C>>8)&1)
|
||||
|
||||
/* update IRQ state (internal use only) */
|
||||
void m37710i_update_irqs(void);
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================== CPU ================================= */
|
||||
/* ======================================================================== */
|
||||
#endif /* HEADER__M37710CM */
|
||||
@@ -0,0 +1,4 @@
|
||||
/* M37710 opcode table instance: from MAME 0.121 (MAME license; R. Belmont) */
|
||||
#include "m37710cm.h"
|
||||
#define EXECUTION_MODE EXECUTION_MODE_M0X0
|
||||
#include "m37710op.h"
|
||||
@@ -0,0 +1,4 @@
|
||||
/* M37710 opcode table instance: from MAME 0.121 (MAME license; R. Belmont) */
|
||||
#include "m37710cm.h"
|
||||
#define EXECUTION_MODE EXECUTION_MODE_M0X1
|
||||
#include "m37710op.h"
|
||||
@@ -0,0 +1,4 @@
|
||||
/* M37710 opcode table instance: from MAME 0.121 (MAME license; R. Belmont) */
|
||||
#include "m37710cm.h"
|
||||
#define EXECUTION_MODE EXECUTION_MODE_M1X0
|
||||
#include "m37710op.h"
|
||||
@@ -0,0 +1,4 @@
|
||||
/* M37710 opcode table instance: from MAME 0.121 (MAME license; R. Belmont) */
|
||||
#include "m37710cm.h"
|
||||
#define EXECUTION_MODE EXECUTION_MODE_M1X1
|
||||
#include "m37710op.h"
|
||||
File diff suppressed because it is too large.
Load diff
@@ -554,6 +554,24 @@ static void state_register(const char *type)
|
||||
state_save_register_UINT8 (type, cpu, "NMI_STATE", &m6800.nmi_state, 1);
|
||||
state_save_register_UINT8 (type, cpu, "IRQ_STATE", &m6800.irq_state[M6800_IRQ_LINE], 1);
|
||||
state_save_register_UINT8 (type, cpu, "TIN_STATE", &m6800.irq_state[M6800_TIN_LINE], 1);
|
||||
state_save_register_UINT16(type, cpu, "PPC", &m6800.ppc.w.l, 1);
|
||||
state_save_register_UINT8 (type, cpu, "WAI_STATE", &m6800.wai_state, 1);
|
||||
state_save_register_UINT8 (type, cpu, "IC_EDDGE", &m6800.ic_eddge, 1);
|
||||
state_save_register_int (type, cpu, "EXTRA_CYCLES", &m6800.extra_cycles);
|
||||
/* the internal registers of the 6801/6803/63701: ports, timer, RAM control */
|
||||
state_save_register_UINT8 (type, cpu, "PORT1_DDR", &m6800.port1_ddr, 1);
|
||||
state_save_register_UINT8 (type, cpu, "PORT2_DDR", &m6800.port2_ddr, 1);
|
||||
state_save_register_UINT8 (type, cpu, "PORT1_DATA", &m6800.port1_data, 1);
|
||||
state_save_register_UINT8 (type, cpu, "PORT2_DATA", &m6800.port2_data, 1);
|
||||
state_save_register_UINT8 (type, cpu, "TCSR", &m6800.tcsr, 1);
|
||||
state_save_register_UINT8 (type, cpu, "PENDING_TCSR", &m6800.pending_tcsr, 1);
|
||||
state_save_register_UINT8 (type, cpu, "IRQ2", &m6800.irq2, 1);
|
||||
state_save_register_UINT8 (type, cpu, "RAM_CTRL", &m6800.ram_ctrl, 1);
|
||||
state_save_register_UINT32(type, cpu, "COUNTER", &m6800.counter.d, 1);
|
||||
state_save_register_UINT32(type, cpu, "OUTPUT_COMPARE", &m6800.output_compare.d, 1);
|
||||
state_save_register_UINT16(type, cpu, "INPUT_CAPTURE", &m6800.input_capture, 1);
|
||||
state_save_register_UINT32(type, cpu, "TIMER_OVER", &m6800.timer_over.d, 1);
|
||||
state_save_register_UINT32(type, cpu, "TIMER_NEXT", &timer_next, 1);
|
||||
}
|
||||
|
||||
void m6800_init(void)
|
||||
|
||||
@@ -260,6 +260,14 @@ void m68k_set_fc_callback(void (*callback)(unsigned int new_fc));
|
||||
*/
|
||||
void m68k_set_instr_hook_callback(void (*callback)(void));
|
||||
|
||||
/* Called after CMPI.L #imm,Dn with the immediate value and the register
|
||||
* number, and when an RTE is executed in supervisor mode. The FD1094 changes
|
||||
* its decryption state on these. Shared by all the 68000 CPUs; m68k_init()
|
||||
* clears them.
|
||||
*/
|
||||
extern void (*m68k_cmpild_callback)(unsigned int val, int reg);
|
||||
extern void (*m68k_rte_callback)(void);
|
||||
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
|
||||
@@ -4178,6 +4178,14 @@ M68KMAKE_OP(cmpi, 32, ., d)
|
||||
FLAG_Z = MASK_OUT_ABOVE_32(res);
|
||||
FLAG_V = VFLAG_SUB_32(src, dst, res);
|
||||
FLAG_C = CFLAG_SUB_32(src, dst, res);
|
||||
|
||||
if (m68k_cmpild_callback)
|
||||
{
|
||||
m68k_cmpild_callback(src, REG_IR & 7);
|
||||
#if M68K_EMULATE_PREFETCH
|
||||
CPU_PREF_ADDR = 1; /* the next words are fetched again (FD1094 state change) */
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8968,6 +8976,14 @@ M68KMAKE_OP(rte, 32, ., .)
|
||||
|
||||
m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
if (m68k_rte_callback)
|
||||
{
|
||||
m68k_rte_callback();
|
||||
#if M68K_EMULATE_PREFETCH
|
||||
CPU_PREF_ADDR = 1; /* fetched again with the new state */
|
||||
#endif
|
||||
}
|
||||
|
||||
if(CPU_TYPE_IS_000(CPU_TYPE))
|
||||
{
|
||||
new_sr = m68ki_pull_16();
|
||||
|
||||
@@ -68,6 +68,10 @@ char* m68ki_cpu_names[9] =
|
||||
/* The CPU core */
|
||||
m68ki_cpu_core m68ki_cpu = {0};
|
||||
|
||||
/* FD1094 hooks, shared by all the 68000 CPUs (see m68k.h) */
|
||||
void (*m68k_cmpild_callback)(unsigned int val, int reg) = NULL;
|
||||
void (*m68k_rte_callback)(void) = NULL;
|
||||
|
||||
#if M68K_EMULATE_ADDRESS_ERROR
|
||||
jmp_buf m68ki_aerr_trap;
|
||||
#endif /* M68K_EMULATE_ADDRESS_ERROR */
|
||||
@@ -755,6 +759,8 @@ void m68k_init(void)
|
||||
m68k_set_pc_changed_callback(NULL);
|
||||
m68k_set_fc_callback(NULL);
|
||||
m68k_set_instr_hook_callback(NULL);
|
||||
m68k_cmpild_callback = NULL;
|
||||
m68k_rte_callback = NULL;
|
||||
}
|
||||
|
||||
/* Pulse the RESET line on the CPU */
|
||||
|
||||
@@ -11782,6 +11782,14 @@ void m68k_op_cmpi_32_d(void)
|
||||
FLAG_Z = MASK_OUT_ABOVE_32(res);
|
||||
FLAG_V = VFLAG_SUB_32(src, dst, res);
|
||||
FLAG_C = CFLAG_SUB_32(src, dst, res);
|
||||
|
||||
if (m68k_cmpild_callback)
|
||||
{
|
||||
m68k_cmpild_callback(src, REG_IR & 7);
|
||||
#if M68K_EMULATE_PREFETCH
|
||||
CPU_PREF_ADDR = 1; /* the next words are fetched again (FD1094 state change) */
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3924,6 +3924,14 @@ void m68k_op_rte_32(void)
|
||||
|
||||
m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
if (m68k_rte_callback)
|
||||
{
|
||||
m68k_rte_callback();
|
||||
#if M68K_EMULATE_PREFETCH
|
||||
CPU_PREF_ADDR = 1; /* fetched again with the new state */
|
||||
#endif
|
||||
}
|
||||
|
||||
if(CPU_TYPE_IS_000(CPU_TYPE))
|
||||
{
|
||||
new_sr = m68ki_pull_16();
|
||||
|
||||
@@ -1,19 +1,10 @@
|
||||
#include "c68000.h"
|
||||
#include "driver.h"
|
||||
#include "cpuintrf.h"
|
||||
#include "cyclone.h"
|
||||
#include "memory.h"
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct Cyclone regs;
|
||||
int pending_interrupts;
|
||||
int (*MAMEIrqCallback)(int int_level);
|
||||
} Cyclone_Regs;
|
||||
|
||||
static Cyclone_Regs cyclone;
|
||||
int cyclone_ICount;
|
||||
Cyclone_Regs cyclone;
|
||||
|
||||
static unsigned int MyCheckPc(unsigned int pc)
|
||||
{
|
||||
@@ -129,9 +120,7 @@ unsigned cyclone_get_context(void *dst)
|
||||
int cyclone_execute(int cycles)
|
||||
{
|
||||
cyclone.regs.cycles = cycles;
|
||||
cyclone_ICount = cyclone.regs.cycles;
|
||||
CycloneRun(&cyclone.regs);
|
||||
cyclone_ICount = cyclone.regs.cycles;
|
||||
return (cycles - cyclone.regs.cycles);
|
||||
}
|
||||
|
||||
@@ -263,7 +252,7 @@ const char *cyclone_info(void *context, int regnum)
|
||||
{
|
||||
case CPU_INFO_NAME: return "Cyclone 68000";
|
||||
case CPU_INFO_FAMILY: return "Motorola 68K";
|
||||
case CPU_INFO_VERSION: return "v0.0088";
|
||||
case CPU_INFO_VERSION: return "v0.0099";
|
||||
case CPU_INFO_FILE: return __FILE__;
|
||||
case CPU_INFO_CREDITS: return "Copyright Copyright 2004-2007 Dave, Reesy and Notaz. All rights reserved";
|
||||
}
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
#ifndef C68000_H
|
||||
#define C68000_H
|
||||
#include "cyclone.h"
|
||||
|
||||
extern int cyclone_ICount;
|
||||
typedef struct
|
||||
{
|
||||
struct Cyclone regs;
|
||||
int pending_interrupts;
|
||||
int (*MAMEIrqCallback)(int int_level);
|
||||
} Cyclone_Regs;
|
||||
|
||||
extern Cyclone_Regs cyclone;
|
||||
|
||||
#define cyclone_ICount cyclone.regs.cycles
|
||||
|
||||
#define cyclone_INT_NONE 0
|
||||
#define cyclone_IRQ_1 1
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -512,12 +512,14 @@ void m6809_init(void)
|
||||
state_save_register_UINT16("m6809", cpu, "S", &S, 1);
|
||||
state_save_register_UINT16("m6809", cpu, "X", &X, 1);
|
||||
state_save_register_UINT16("m6809", cpu, "Y", &Y, 1);
|
||||
state_save_register_UINT16("m6809", cpu, "D", &D, 1); /* the accumulators A and B */
|
||||
state_save_register_UINT8("m6809", cpu, "DP", &DP, 1);
|
||||
state_save_register_UINT8("m6809", cpu, "CC", &CC, 1);
|
||||
state_save_register_UINT8("m6809", cpu, "INT", &m6809.int_state, 1);
|
||||
state_save_register_UINT8("m6809", cpu, "NMI", &m6809.nmi_state, 1);
|
||||
state_save_register_UINT8("m6809", cpu, "IRQ", &m6809.irq_state[0], 1);
|
||||
state_save_register_UINT8("m6809", cpu, "FIRQ", &m6809.irq_state[1], 1);
|
||||
state_save_register_int("m6809", cpu, "extra_cycles", &m6809.extra_cycles); /* the cycles of an interrupt taken outside the execute loop */
|
||||
}
|
||||
|
||||
void m6809_reset(void *param)
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,46 @@
|
||||
/***************************************************************************
|
||||
|
||||
Fujitsu MB86233/MB86234 (TGP), from current MAME
|
||||
(src/devices/cpu/mb86233, copyright Olivier Galibert, BSD-3-Clause),
|
||||
in C for MAME 2003. The four address spaces (program, data, io and
|
||||
register file) are driver callbacks.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MB86233_H
|
||||
#define MB86233_H
|
||||
|
||||
#include "osd_cpu.h"
|
||||
|
||||
struct mb86233_config
|
||||
{
|
||||
UINT32 (*prog_r)( UINT32 offset );
|
||||
UINT32 (*data_r)( UINT32 offset );
|
||||
void (*data_w)( UINT32 offset, UINT32 data );
|
||||
UINT32 (*io_r)( UINT32 offset );
|
||||
void (*io_w)( UINT32 offset, UINT32 data );
|
||||
UINT32 (*rf_r)( UINT32 offset );
|
||||
void (*rf_w)( UINT32 offset, UINT32 data );
|
||||
};
|
||||
|
||||
extern int mb86233_icount;
|
||||
|
||||
extern void mb86233_init(void);
|
||||
extern void mb86233_reset(void *param);
|
||||
extern void mb86233_exit(void);
|
||||
extern int mb86233_execute(int cycles);
|
||||
extern unsigned mb86233_get_context(void *dst);
|
||||
extern void mb86233_set_context(void *src);
|
||||
extern unsigned mb86233_get_reg(int regnum);
|
||||
extern void mb86233_set_reg(int regnum, unsigned val);
|
||||
extern void mb86233_set_irq_line(int irqline, int state);
|
||||
extern void mb86233_set_irq_callback(int (*callback)(int irqline));
|
||||
extern const char *mb86233_info(void *context, int regnum);
|
||||
extern unsigned mb86233_dasm(char *buffer, unsigned pc);
|
||||
|
||||
/* a memory callback that cannot complete now (FIFO empty or full):
|
||||
the instruction is repeated */
|
||||
extern void mb86233_stall(void);
|
||||
extern void mb86233_gpio_w(int pin, int state);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,50 @@
|
||||
/***************************************************************************
|
||||
|
||||
Fujitsu MB86235 "TGPx4", from current MAME
|
||||
(src/devices/cpu/mb86235; copyright Angelo Salese, ElSemi, Ville Linde,
|
||||
Matthew Daniels, BSD-3-Clause), the interpreter in C for MAME 2003.
|
||||
Program memory, the external bus and the FIFOs are driver callbacks;
|
||||
the internal A and B bus RAMs are part of the CPU.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MB86235_H
|
||||
#define MB86235_H
|
||||
|
||||
#include "osd_cpu.h"
|
||||
|
||||
#define MB86235_FIFO_IFF 0 /* input FIFO full */
|
||||
#define MB86235_FIFO_IFE 1 /* input FIFO empty */
|
||||
#define MB86235_FIFO_OFF 2 /* output FIFO full */
|
||||
#define MB86235_FIFO_OFE 3 /* output FIFO empty */
|
||||
|
||||
struct mb86235_config
|
||||
{
|
||||
UINT64 (*prog_r)( UINT32 offset ); /* 64-bit words, 12-bit address */
|
||||
UINT32 (*ext_r)( UINT32 offset ); /* external bus, dword address */
|
||||
void (*ext_w)( UINT32 offset, UINT32 data );
|
||||
UINT32 (*fifoin_r)( void ); /* calls mb86235_stall() when empty */
|
||||
void (*fifoout_w)( UINT32 data );
|
||||
int (*fifo_flag)( int which );
|
||||
void (*fifo_clear)( int which ); /* 0: input, 1: output */
|
||||
};
|
||||
|
||||
extern int mb86235_icount;
|
||||
|
||||
extern void mb86235_init(void);
|
||||
extern void mb86235_reset(void *param);
|
||||
extern void mb86235_exit(void);
|
||||
extern int mb86235_execute(int cycles);
|
||||
extern unsigned mb86235_get_context(void *dst);
|
||||
extern void mb86235_set_context(void *src);
|
||||
extern unsigned mb86235_get_reg(int regnum);
|
||||
extern void mb86235_set_reg(int regnum, unsigned val);
|
||||
extern void mb86235_set_irq_line(int irqline, int state);
|
||||
extern void mb86235_set_irq_callback(int (*callback)(int irqline));
|
||||
extern const char *mb86235_info(void *context, int regnum);
|
||||
extern unsigned mb86235_dasm(char *buffer, unsigned pc);
|
||||
|
||||
/* a FIFO read that cannot complete now: the instruction is repeated */
|
||||
extern void mb86235_stall(void);
|
||||
|
||||
#endif
|
||||
+457
-1
@@ -13,6 +13,7 @@
|
||||
**
|
||||
**#################################################################################################*/
|
||||
|
||||
#include "mips3jit.h"
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
@@ -21,6 +22,7 @@
|
||||
#include "driver.h"
|
||||
#include "mamedbg.h"
|
||||
#include "mips3.h"
|
||||
#include "state.h"
|
||||
|
||||
|
||||
#define ENABLE_OVERFLOWS 0
|
||||
@@ -292,6 +294,193 @@ static const memory_handlers le_memory =
|
||||
|
||||
|
||||
|
||||
/*###################################################################################################
|
||||
** OPTIONAL SPEEDUPS
|
||||
**
|
||||
** Off unless a driver enables them (currently only Killer Instinct):
|
||||
** - fast RAM: plain RAM regions read and written through a direct pointer
|
||||
** instead of the memory system, including instruction fetch;
|
||||
** - idle loop: a loop that polls the COP0 Cause register for an interrupt
|
||||
** gives up the rest of its timeslice instead of spinning.
|
||||
** They live outside the CPU context and are cleared by mips3_init().
|
||||
**#################################################################################################*/
|
||||
|
||||
#define MIPS3_MAX_FASTRAM 8
|
||||
|
||||
struct mips3_fastram
|
||||
{
|
||||
offs_t start;
|
||||
offs_t end;
|
||||
UINT8 * base;
|
||||
UINT8 readonly;
|
||||
int wait; /* cycles each data read costs (wait states), 0 = none */
|
||||
};
|
||||
|
||||
static struct mips3_fastram fastram[MIPS3_MAX_FASTRAM];
|
||||
static int fastram_count;
|
||||
static offs_t fastram_byte_xor, fastram_word_xor;
|
||||
static memory_handlers fastram_slow; /* handlers for everything else */
|
||||
static int fastram_has_wait; /* a region with read wait states exists */
|
||||
|
||||
/* exact skip of the loops that poll Cause for an interrupt (see cause_poll_skip) */
|
||||
#define MIPS3_MAX_POLLREAD 4
|
||||
static int cause_poll_enabled;
|
||||
static struct { offs_t start, end; } pollread[MIPS3_MAX_POLLREAD];
|
||||
static int pollread_count;
|
||||
|
||||
|
||||
void mips3_add_fastram(offs_t start, offs_t end, int readonly, void *base)
|
||||
{
|
||||
mips3_add_fastram_wait(start, end, readonly, base, 0);
|
||||
}
|
||||
|
||||
/* the same, with wait states: each data read (not instruction fetch) costs */
|
||||
/* wait cycles, as a slow ROM does (instruction fetch and translation stay direct) */
|
||||
void mips3_add_fastram_wait(offs_t start, offs_t end, int readonly, void *base, int wait)
|
||||
{
|
||||
if (fastram_count < MIPS3_MAX_FASTRAM)
|
||||
{
|
||||
fastram[fastram_count].start = start;
|
||||
fastram[fastram_count].end = end;
|
||||
fastram[fastram_count].base = (UINT8 *)base;
|
||||
fastram[fastram_count].readonly = readonly;
|
||||
fastram[fastram_count].wait = wait;
|
||||
if (wait)
|
||||
fastram_has_wait = 1;
|
||||
fastram_count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void mips3_set_cause_poll_skip(int enable)
|
||||
{
|
||||
cause_poll_enabled = enable;
|
||||
}
|
||||
|
||||
|
||||
void mips3_add_poll_read(offs_t start, offs_t end)
|
||||
{
|
||||
if (pollread_count < MIPS3_MAX_POLLREAD)
|
||||
{
|
||||
pollread[pollread_count].start = start;
|
||||
pollread[pollread_count].end = end;
|
||||
pollread_count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct mips3_fastram *fastram_last = &fastram[0];
|
||||
|
||||
/* recompiler hook (mips3jit.c): a write may hit translated code */
|
||||
static INLINE void jit_check_write(const void *host);
|
||||
|
||||
static INLINE struct mips3_fastram *find_fastram(offs_t address)
|
||||
{
|
||||
struct mips3_fastram *r = fastram_last;
|
||||
int i;
|
||||
|
||||
/* most accesses hit the same region as the previous one */
|
||||
if (address - r->start <= r->end - r->start)
|
||||
return r;
|
||||
for (i = 0; i < fastram_count; i++)
|
||||
if (address - fastram[i].start <= fastram[i].end - fastram[i].start)
|
||||
return fastram_last = &fastram[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static data8_t fastram_readbyte(offs_t address)
|
||||
{
|
||||
struct mips3_fastram *r = find_fastram(address);
|
||||
if (r) { mips3_icount -= r->wait; return r->base[(address - r->start) ^ fastram_byte_xor]; }
|
||||
return (*fastram_slow.readbyte)(address);
|
||||
}
|
||||
|
||||
static data16_t fastram_readword(offs_t address)
|
||||
{
|
||||
struct mips3_fastram *r = find_fastram(address);
|
||||
if (r) { mips3_icount -= r->wait; return *(data16_t *)&r->base[(address - r->start) ^ fastram_word_xor]; }
|
||||
return (*fastram_slow.readword)(address);
|
||||
}
|
||||
|
||||
static data32_t fastram_readlong(offs_t address)
|
||||
{
|
||||
struct mips3_fastram *r = find_fastram(address);
|
||||
if (r) { mips3_icount -= r->wait; return *(data32_t *)&r->base[address - r->start]; }
|
||||
return (*fastram_slow.readlong)(address);
|
||||
}
|
||||
|
||||
static UINT64 fastram_readdouble(offs_t address)
|
||||
{
|
||||
struct mips3_fastram *r = find_fastram(address);
|
||||
if (r && address + 7 <= r->end)
|
||||
{
|
||||
UINT64 first;
|
||||
UINT64 second;
|
||||
mips3_icount -= r->wait;
|
||||
first = *(data32_t *)&r->base[address - r->start];
|
||||
second = *(data32_t *)&r->base[address + 4 - r->start];
|
||||
return mips3.bigendian ? ((first << 32) | second) : (first | (second << 32));
|
||||
}
|
||||
return (*fastram_slow.readdouble)(address);
|
||||
}
|
||||
|
||||
static void fastram_writebyte(offs_t address, data8_t data)
|
||||
{
|
||||
struct mips3_fastram *r = find_fastram(address);
|
||||
if (r && !r->readonly) { jit_check_write(&r->base[address - r->start]); r->base[(address - r->start) ^ fastram_byte_xor] = data; return; }
|
||||
(*fastram_slow.writebyte)(address, data);
|
||||
}
|
||||
|
||||
static void fastram_writeword(offs_t address, data16_t data)
|
||||
{
|
||||
struct mips3_fastram *r = find_fastram(address);
|
||||
if (r && !r->readonly) { jit_check_write(&r->base[address - r->start]); *(data16_t *)&r->base[(address - r->start) ^ fastram_word_xor] = data; return; }
|
||||
(*fastram_slow.writeword)(address, data);
|
||||
}
|
||||
|
||||
static void fastram_writelong(offs_t address, data32_t data)
|
||||
{
|
||||
struct mips3_fastram *r = find_fastram(address);
|
||||
if (r && !r->readonly) { jit_check_write(&r->base[address - r->start]); *(data32_t *)&r->base[address - r->start] = data; return; }
|
||||
(*fastram_slow.writelong)(address, data);
|
||||
}
|
||||
|
||||
static void fastram_writedouble(offs_t address, UINT64 data)
|
||||
{
|
||||
struct mips3_fastram *r = find_fastram(address);
|
||||
if (r && !r->readonly && address + 7 <= r->end)
|
||||
{
|
||||
jit_check_write(&r->base[address - r->start]);
|
||||
jit_check_write(&r->base[address + 4 - r->start]);
|
||||
*(data32_t *)&r->base[address - r->start] = mips3.bigendian ? (data32_t)(data >> 32) : (data32_t)data;
|
||||
*(data32_t *)&r->base[address + 4 - r->start] = mips3.bigendian ? (data32_t)data : (data32_t)(data >> 32);
|
||||
return;
|
||||
}
|
||||
(*fastram_slow.writedouble)(address, data);
|
||||
}
|
||||
|
||||
static const memory_handlers fastram_memory =
|
||||
{
|
||||
fastram_readbyte, fastram_readword, fastram_readlong, fastram_readdouble,
|
||||
fastram_writebyte, fastram_writeword, fastram_writelong, fastram_writedouble
|
||||
};
|
||||
|
||||
/* switch the memory handlers when fast RAM is in use */
|
||||
static void fastram_attach(void)
|
||||
{
|
||||
if (!fastram_count || mips3.memory.readlong == fastram_readlong)
|
||||
return;
|
||||
fastram_slow = mips3.bigendian ? be_memory : le_memory;
|
||||
fastram_byte_xor = mips3.bigendian ? BYTE4_XOR_BE(0) : BYTE4_XOR_LE(0);
|
||||
fastram_word_xor = mips3.bigendian ? WORD_XOR_BE(0) : WORD_XOR_LE(0);
|
||||
mips3.memory = fastram_memory;
|
||||
}
|
||||
|
||||
|
||||
#include "mips3jit.c"
|
||||
|
||||
|
||||
|
||||
/*###################################################################################################
|
||||
** MEMORY ACCESSORS
|
||||
**#################################################################################################*/
|
||||
@@ -439,9 +628,66 @@ static void compare_int_callback(int cpu)
|
||||
}
|
||||
|
||||
|
||||
/* the Compare interrupt timer is not saved by the core: whether it is set
|
||||
is. After a load it is set again from Count and Compare, in cycles of
|
||||
this CPU, as a write to Compare sets it (both functions run in the
|
||||
context of this CPU) */
|
||||
static UINT8 compare_timer_set;
|
||||
|
||||
static void mips3_presave(void)
|
||||
{
|
||||
compare_timer_set = (timer_timeleft(mips3.compare_int_timer) < TIME_NEVER / 2);
|
||||
}
|
||||
|
||||
static void mips3_postload(void)
|
||||
{
|
||||
int cpunum = cpu_getactivecpu();
|
||||
|
||||
timer_adjust(mips3.compare_int_timer, TIME_NEVER, cpunum, 0);
|
||||
if (compare_timer_set)
|
||||
{
|
||||
UINT32 count = (cpu_gettotalcycles64(cpunum) - mips3.count_zero_time) / 2;
|
||||
UINT32 cyclesleft = (UINT32)mips3.cpr[0][COP0_Compare] - count;
|
||||
timer_adjust(mips3.compare_int_timer, TIME_IN_CYCLES(((UINT64)cyclesleft * 2), cpunum), cpunum, 0);
|
||||
}
|
||||
|
||||
if (mips3.bigendian)
|
||||
change_pc32bedw(mips3.pc);
|
||||
else
|
||||
change_pc32ledw(mips3.pc);
|
||||
}
|
||||
|
||||
void mips3_init(void)
|
||||
{
|
||||
int cpunum = cpu_getactivecpu();
|
||||
|
||||
/* optional speedups are off until a driver asks for them */
|
||||
fastram_count = 0;
|
||||
fastram_has_wait = 0;
|
||||
fastram_last = &fastram[0];
|
||||
mips3_set_jit(0);
|
||||
cause_poll_enabled = 0;
|
||||
pollread_count = 0;
|
||||
|
||||
mips3.compare_int_timer = timer_alloc(compare_int_callback);
|
||||
|
||||
/* save states: the registers of the active context, swapped in per CPU
|
||||
when the state is saved; the 64-bit registers as pairs of 32 bits */
|
||||
state_save_register_UINT32("mips3", cpunum, "pc", &mips3.pc, 1);
|
||||
state_save_register_UINT32("mips3", cpunum, "hi", (UINT32 *)&mips3.hi, 2);
|
||||
state_save_register_UINT32("mips3", cpunum, "lo", (UINT32 *)&mips3.lo, 2);
|
||||
state_save_register_UINT32("mips3", cpunum, "r", (UINT32 *)mips3.r, 32 * 2);
|
||||
state_save_register_UINT32("mips3", cpunum, "cpr", (UINT32 *)mips3.cpr, 4 * 32 * 2);
|
||||
state_save_register_UINT32("mips3", cpunum, "ccr", (UINT32 *)mips3.ccr, 4 * 32 * 2);
|
||||
state_save_register_UINT8 ("mips3", cpunum, "cf", mips3.cf, 4);
|
||||
state_save_register_UINT32("mips3", cpunum, "ppc", &mips3.ppc, 1);
|
||||
state_save_register_UINT32("mips3", cpunum, "nextpc", &mips3.nextpc, 1);
|
||||
state_save_register_int ("mips3", cpunum, "op", &mips3.op);
|
||||
state_save_register_int ("mips3", cpunum, "interrupt_cycles", &mips3.interrupt_cycles);
|
||||
state_save_register_UINT32("mips3", cpunum, "count_zero_time", (UINT32 *)&mips3.count_zero_time, 2);
|
||||
state_save_register_UINT8 ("mips3", cpunum, "compare_timer_set", &compare_timer_set, 1);
|
||||
state_save_register_func_presave(mips3_presave);
|
||||
state_save_register_func_postload(mips3_postload);
|
||||
}
|
||||
|
||||
|
||||
@@ -535,6 +781,8 @@ void r5000le_reset(void *param)
|
||||
|
||||
void mips3_exit(void)
|
||||
{
|
||||
mips3_set_jit(0);
|
||||
|
||||
/* free cache memory */
|
||||
if (mips3.icache)
|
||||
free(mips3.icache);
|
||||
@@ -624,6 +872,9 @@ static INLINE void set_cop0_reg(int idx, UINT64 val)
|
||||
mips3.cpr[0][idx] = val;
|
||||
if (diff & 0x8000)
|
||||
update_cycle_counting();
|
||||
/* the recompiler translates FPU instructions only while COP1 is usable */
|
||||
if (diff & SR_COP1)
|
||||
jit_flush();
|
||||
check_irqs();
|
||||
break;
|
||||
}
|
||||
@@ -682,6 +933,155 @@ static void logtlbentry(void)
|
||||
logonetlbentry(1);
|
||||
}
|
||||
|
||||
/*
|
||||
Exact skip of the loops that wait for an interrupt by polling Cause.
|
||||
|
||||
Within a timeslice nothing changes Cause: interrupt lines and the
|
||||
Count/Compare timer only change between timeslices. So every pass of
|
||||
such a loop leaves the same state, except for counters, and the whole
|
||||
passes that still fit in the timeslice can be skipped: registers and
|
||||
cycles end up exactly as if they had run. The last passes always run
|
||||
normally. Called by the MFC0 of Cause (mips3.ppc), after its read.
|
||||
|
||||
The loop, from the branch target L to the backward branch and its
|
||||
delay slot, may only hold:
|
||||
mfc0 rt, Cause (this instruction, once)
|
||||
andi rt, rt, mask (Cause & mask is 0 now)
|
||||
nop
|
||||
lw/lh/lb $zero, off(rb) (rb + off in a range declared free of
|
||||
side effects, mips3_add_poll_read)
|
||||
beq rc, $zero, outside (a timeout counter)
|
||||
beq rt, $zero, L (the loop branch, last)
|
||||
delay slot: nop, or addi/addiu rc, rc, imm (a counter)
|
||||
A timeout counter must count down by 1 and stays at 1 or more.
|
||||
*/
|
||||
static void cause_poll_skip(UINT32 mfc0_op)
|
||||
{
|
||||
UINT32 pc = mips3.ppc, a, op, branch_pc = 0, rt = (mfc0_op >> 16) & 31, mask = 0;
|
||||
int count, i, n, cost, rc = -1, timeout = 0;
|
||||
INT32 imm = 0;
|
||||
UINT32 body[16];
|
||||
|
||||
if (rt == 0 || mips3.nextpc != ~0)
|
||||
return;
|
||||
|
||||
/* find the backward branch beq rt, $zero, L with L <= pc */
|
||||
for (a = pc + 4; a < pc + 4 * 12; a += 4)
|
||||
{
|
||||
op = ROPCODE(a);
|
||||
if ((op >> 26) == 0x04 && ((op >> 21) & 31) == rt && ((op >> 16) & 31) == 0)
|
||||
{
|
||||
UINT32 target = a + 4 + ((INT32)(INT16)op << 2);
|
||||
if (target <= pc && pc - target < 4 * 8)
|
||||
{
|
||||
branch_pc = a;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!branch_pc)
|
||||
return;
|
||||
{
|
||||
UINT32 target = branch_pc + 4 + ((INT32)(INT16)ROPCODE(branch_pc) << 2);
|
||||
count = (branch_pc + 8 - target) / 4;
|
||||
if (count > 16)
|
||||
return;
|
||||
for (i = 0; i < count; i++)
|
||||
body[i] = ROPCODE(target + i * 4);
|
||||
a = target;
|
||||
}
|
||||
|
||||
/* check every instruction of the loop */
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
UINT32 ia = a + i * 4;
|
||||
op = body[i];
|
||||
if (ia == pc)
|
||||
continue;
|
||||
if (ia == branch_pc)
|
||||
continue;
|
||||
if (op == 0)
|
||||
continue;
|
||||
if (ia == branch_pc + 4)
|
||||
{
|
||||
/* delay slot: a counter */
|
||||
if (((op >> 26) == 0x08 || (op >> 26) == 0x09) && ((op >> 21) & 31) == ((op >> 16) & 31) &&
|
||||
((op >> 16) & 31) != 0 && ((op >> 16) & 31) != rt)
|
||||
{
|
||||
rc = (op >> 16) & 31;
|
||||
imm = (INT16)op;
|
||||
continue;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ((op >> 26) == 0x0c && ((op >> 21) & 31) == rt && ((op >> 16) & 31) == rt)
|
||||
{
|
||||
/* the mask, between the mfc0 and the branch */
|
||||
if (ia < pc || ia > branch_pc)
|
||||
return;
|
||||
mask |= op & 0xffff;
|
||||
continue;
|
||||
}
|
||||
if (((op >> 26) == 0x23 || (op >> 26) == 0x21 || (op >> 26) == 0x20) && ((op >> 16) & 31) == 0)
|
||||
{
|
||||
UINT32 address = (UINT32)mips3.r[(op >> 21) & 31] + (INT16)op;
|
||||
int p, ok = 0;
|
||||
for (p = 0; p < pollread_count; p++)
|
||||
if (address >= pollread[p].start && address <= pollread[p].end)
|
||||
ok = 1;
|
||||
if (ok)
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
if ((op >> 26) == 0x04 && ((op >> 16) & 31) == 0 && ((op >> 21) & 31) != rt)
|
||||
{
|
||||
/* a timeout: beq rc, $zero, out of the loop */
|
||||
UINT32 target = ia + 4 + ((INT32)(INT16)op << 2);
|
||||
if (target >= a && target <= branch_pc + 4)
|
||||
return;
|
||||
if (timeout)
|
||||
return;
|
||||
timeout = (op >> 21) & 31;
|
||||
continue;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!mask || (CAUSE & mask))
|
||||
return;
|
||||
if (timeout && (timeout != rc || imm != -1))
|
||||
return;
|
||||
|
||||
/* whole passes that fit, leaving at least two to run normally */
|
||||
cost = count + 25;
|
||||
n = mips3_icount / cost - 2;
|
||||
if (n <= 0)
|
||||
return;
|
||||
if (rc >= 0)
|
||||
{
|
||||
INT64 value = (INT32)(UINT32)mips3.r[rc];
|
||||
if (timeout)
|
||||
{
|
||||
if (value <= 1)
|
||||
return;
|
||||
if (n > value - 1)
|
||||
n = (int)(value - 1);
|
||||
}
|
||||
else if ((body[(branch_pc + 4 - a) / 4] >> 26) == 0x08)
|
||||
{
|
||||
/* ADDI traps on overflow: stop before it */
|
||||
INT64 limit = imm > 0 ? ((INT64)0x7fffffff - value) / imm : (value + (INT64)0x80000000) / -imm;
|
||||
if (imm == 0)
|
||||
limit = n;
|
||||
if (n > limit)
|
||||
n = (int)limit;
|
||||
}
|
||||
if (n <= 0)
|
||||
return;
|
||||
mips3.r[rc] = (INT64)(INT32)((UINT32)value + (UINT32)(imm * n));
|
||||
}
|
||||
mips3_icount -= n * cost;
|
||||
}
|
||||
|
||||
static INLINE void handle_cop0(UINT32 op)
|
||||
{
|
||||
if ((SR & SR_KSU_MASK) != SR_KSU_KERNEL && !(SR & SR_COP0))
|
||||
@@ -689,7 +1089,11 @@ static INLINE void handle_cop0(UINT32 op)
|
||||
|
||||
switch (RSREG)
|
||||
{
|
||||
case 0x00: /* MFCz */ if (RTREG) RTVAL64 = (INT32)get_cop0_reg(RDREG); break;
|
||||
case 0x00: /* MFCz */ if (RTREG) RTVAL64 = (INT32)get_cop0_reg(RDREG);
|
||||
/* optional: whole passes of a loop waiting for an interrupt in Cause */
|
||||
if (cause_poll_enabled && RDREG == COP0_Cause)
|
||||
cause_poll_skip(op);
|
||||
break;
|
||||
case 0x01: /* DMFCz */ if (RTREG) RTVAL64 = get_cop0_reg(RDREG); break;
|
||||
case 0x02: /* CFCz */ if (RTREG) RTVAL64 = (INT32)get_cop0_creg(RDREG); break;
|
||||
case 0x04: /* MTCz */ set_cop0_reg(RDREG, RTVAL32); break;
|
||||
@@ -1119,6 +1523,14 @@ static INLINE void handle_cop1(UINT32 op)
|
||||
|
||||
|
||||
|
||||
/* a COP1 instruction (not a branch) from translated code: exactly the interpreter's */
|
||||
static void jit_cop1_helper(UINT32 op)
|
||||
{
|
||||
handle_cop1(op);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*###################################################################################################
|
||||
** COP1X (FPU EXTRA) EXECUTION HANDLING
|
||||
**#################################################################################################*/
|
||||
@@ -1283,6 +1695,9 @@ int mips3_execute(int cycles)
|
||||
change_pc32bedw(mips3.pc);
|
||||
|
||||
|
||||
/* optional fast RAM (see mips3_add_fastram) */
|
||||
fastram_attach();
|
||||
|
||||
/* check for IRQs */
|
||||
check_irqs();
|
||||
|
||||
@@ -1297,6 +1712,47 @@ int mips3_execute(int cycles)
|
||||
mips3.ppc = mips3.pc;
|
||||
CALL_MAME_DEBUG;
|
||||
|
||||
#if MIPS3_JIT_SUPPORTED
|
||||
/* recompiled block, when there are enough cycles left for all of it */
|
||||
if (jit_enabled && mips3.nextpc == ~0)
|
||||
{
|
||||
struct jit_block *block = jit_lookup(mips3.pc);
|
||||
if (block && (int)block->len <= mips3_icount)
|
||||
{
|
||||
/* run blocks back to back while they fit in the timeslice; */
|
||||
/* each takes its own cycles, and none taken means a side exit */
|
||||
/* before its first instruction, which the interpreter then runs */
|
||||
int ran = 0, stalled = 0;
|
||||
for (;;)
|
||||
{
|
||||
int before = mips3_icount;
|
||||
mips3.pc = ((jit_func)block->code)();
|
||||
if (mips3_icount == before)
|
||||
{
|
||||
stalled = 1;
|
||||
break;
|
||||
}
|
||||
ran = 1;
|
||||
if (mips3_icount <= 0)
|
||||
break;
|
||||
block = jit_lookup(mips3.pc);
|
||||
if (!block || (int)block->len > mips3_icount)
|
||||
break;
|
||||
}
|
||||
if (ran)
|
||||
{
|
||||
change_pc32bedw(mips3.pc);
|
||||
if (!stalled)
|
||||
{
|
||||
mips3.ppc = mips3.pc - 4;
|
||||
continue;
|
||||
}
|
||||
mips3.ppc = mips3.pc;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* instruction fetch */
|
||||
op = ROPCODE(mips3.pc);
|
||||
|
||||
|
||||
@@ -183,6 +183,20 @@ extern void r5000le_reset(void *param);
|
||||
|
||||
void mips3drc_set_options(UINT8 cpunum, UINT32 opts);
|
||||
|
||||
/* optional speedups for a single MIPS3 CPU, off by default; set them up in DRIVER_INIT */
|
||||
/* plain RAM accessed through a direct pointer (no handlers may sit in the range) */
|
||||
void mips3_add_fastram(offs_t start, offs_t end, int readonly, void *base);
|
||||
void mips3_add_fastram_wait(offs_t start, offs_t end, int readonly, void *base, int wait);
|
||||
/* skip, exactly, the whole passes of loops waiting for an interrupt in Cause (see mips3.c) */
|
||||
void mips3_set_cause_poll_skip(int enable);
|
||||
/* loads from this range, into $zero, have no side effects (they may sit in such a loop) */
|
||||
void mips3_add_poll_read(offs_t start, offs_t end);
|
||||
/* recompile integer code in fast RAM with sljit, where supported (x86 and ARM, 32 and 64-bit) */
|
||||
void mips3_set_jit(int enable);
|
||||
void mips3_ram_written(offs_t address, UINT32 bytes);
|
||||
/* nonzero when this build has the recompiler (x86/ARM hosts that allow run-time code) */
|
||||
int mips3_jit_available(void);
|
||||
|
||||
|
||||
|
||||
#endif /* _MIPS3_H */
|
||||
@@ -5830,3 +5830,49 @@ unsigned mips3_dasm(char *buffer, unsigned pc)
|
||||
return 4;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*###################################################################################################
|
||||
** OPTIONAL SPEEDUPS (see mips3.h)
|
||||
**
|
||||
** This x86 recompiler is built instead of mips3.c when X86_MIPS3_DRC is set (32-bit x86 hosts).
|
||||
** The speedups declared in mips3.h live in mips3.c; here they are accepted and ignored, so
|
||||
** drivers that request them (Killer Instinct) still link and run, just without them.
|
||||
**#################################################################################################*/
|
||||
|
||||
void mips3_add_fastram(offs_t start, offs_t end, int readonly, void *base)
|
||||
{
|
||||
(void)start; (void)end; (void)readonly; (void)base;
|
||||
}
|
||||
|
||||
void mips3_add_fastram_wait(offs_t start, offs_t end, int readonly, void *base, int wait)
|
||||
{
|
||||
(void)start; (void)end; (void)readonly; (void)base; (void)wait;
|
||||
}
|
||||
|
||||
void mips3_set_cause_poll_skip(int enable)
|
||||
{
|
||||
(void)enable;
|
||||
}
|
||||
|
||||
void mips3_add_poll_read(offs_t start, offs_t end)
|
||||
{
|
||||
(void)start; (void)end;
|
||||
}
|
||||
|
||||
void mips3_set_jit(int enable)
|
||||
{
|
||||
(void)enable;
|
||||
}
|
||||
|
||||
int mips3_jit_available(void)
|
||||
{
|
||||
/* no sljit recompiler in this build: the "MIPS Dynarec" core option stays hidden */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mips3_ram_written(offs_t address, UINT32 bytes)
|
||||
{
|
||||
/* no translations to drop in this build */
|
||||
(void)address; (void)bytes;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,18 @@
|
||||
/***************************************************************************
|
||||
|
||||
mips3jit.h
|
||||
|
||||
Host support of the MIPS3 recompiler: the bundled sljit, configured
|
||||
and built once for all the recompilers (src/lib/sljit/sljit_mame.h).
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MIPS3JIT_H
|
||||
#define MIPS3JIT_H
|
||||
|
||||
/* the sljit build shared by the recompilers decides where they run */
|
||||
#include "../../lib/sljit/sljit_mame.h"
|
||||
|
||||
#define MIPS3_JIT_SUPPORTED SLJIT_MAME_SUPPORTED
|
||||
|
||||
#endif /* MIPS3JIT_H */
|
||||
@@ -213,6 +213,20 @@ extern void mips_set_irq_callback(int (*callback)(int irqline));
|
||||
extern const char *mips_info(void *context, int regnum);
|
||||
extern unsigned mips_dasm(char *buffer, UINT32 pc);
|
||||
|
||||
/* optional speedups, off unless a driver enables them */
|
||||
/* loads and stores in a plain RAM region use a direct pointer */
|
||||
extern void psxcpu_add_fastram(offs_t start, offs_t end, int readonly, void *base);
|
||||
/* fast RAM written behind the CPU's back (DMA, driver patches) */
|
||||
extern void psxcpu_ram_written(const void *host, UINT32 bytes);
|
||||
/* recompiler (sljit), where supported. The fast RAM table and the
|
||||
recompiler state are global, not part of the CPU context: one PSXCPU
|
||||
per machine. */
|
||||
extern int psxcpu_jit_available(void);
|
||||
extern void psxcpu_set_jit(int enable);
|
||||
/* fn is called before the instruction at pc runs (NULL: none); set at */
|
||||
/* machine init, cleared at the CPU init */
|
||||
extern void psxcpu_set_pc_hook(UINT32 pc, void (*fn)(void));
|
||||
|
||||
#ifdef MAME_DEBUG
|
||||
extern unsigned DasmMIPS(char *buff, unsigned _pc);
|
||||
#endif
|
||||
|
||||
+1353
-1923
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,941 @@
|
||||
/***************************************************************************
|
||||
|
||||
PlayStation Geometry Transformation Engine, as current MAME
|
||||
(src/devices/cpu/psx/gte.cpp, copyright smf, BSD-3-Clause), in C.
|
||||
|
||||
The hardware divide (reciprocal table, result capped at 0x1ffff and
|
||||
flagged), the 44-bit accumulators with their overflow flags, the
|
||||
register moves (IRGB/ORGB, LZCS/LZCR, the sign extended control
|
||||
registers, FLAG) of current MAME.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#define GTE_SF( op ) ( ( op >> 19 ) & 1 )
|
||||
#define GTE_MX( op ) ( ( op >> 17 ) & 3 )
|
||||
#define GTE_V( op ) ( ( op >> 15 ) & 3 )
|
||||
#define GTE_CV( op ) ( ( op >> 13 ) & 3 )
|
||||
#define GTE_LM( op ) ( ( op >> 10 ) & 1 )
|
||||
#define GTE_FUNCT( op ) ( op & 63 )
|
||||
|
||||
static int m_sf;
|
||||
static INT64 m_mac0;
|
||||
static INT64 m_mac1;
|
||||
static INT64 m_mac2;
|
||||
static INT64 m_mac3;
|
||||
|
||||
static INLINE int count_leading_zeros32( UINT32 v )
|
||||
{
|
||||
int n = 0;
|
||||
if( v == 0 )
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
while( ( v & 0x80000000 ) == 0 )
|
||||
{
|
||||
v <<= 1;
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/* a 44-bit accumulator with sticky overflow flags (MAME's int44) */
|
||||
typedef struct
|
||||
{
|
||||
INT64 value;
|
||||
int pos;
|
||||
int neg;
|
||||
} int44;
|
||||
|
||||
static INLINE int44 i44( INT64 value )
|
||||
{
|
||||
int44 r;
|
||||
r.value = value;
|
||||
r.pos = value > ( ( (INT64)1 << 43 ) - 1 );
|
||||
r.neg = value < -( (INT64)1 << 43 );
|
||||
return r;
|
||||
}
|
||||
|
||||
static INLINE int44 i44_add( int44 a, INT64 add )
|
||||
{
|
||||
int44 r;
|
||||
INT64 value = (INT64)( (UINT64)( a.value + add ) << 20 ) >> 20;
|
||||
r.value = value;
|
||||
r.pos = a.pos || ( value < 0 && a.value >= 0 && add >= 0 );
|
||||
r.neg = a.neg || ( value >= 0 && a.value < 0 && add < 0 );
|
||||
return r;
|
||||
}
|
||||
|
||||
#define VX0 ( (*(INT16 *)&mipscpu.cp2dr[ 0 ].w.l) )
|
||||
#define VY0 ( (*(INT16 *)&mipscpu.cp2dr[ 0 ].w.h) )
|
||||
#define VZ0 ( (*(INT16 *)&mipscpu.cp2dr[ 1 ].w.l) )
|
||||
#define VX1 ( mipscpu.cp2dr[ 2 ].w.l )
|
||||
#define VY1 ( mipscpu.cp2dr[ 2 ].w.h )
|
||||
#define VZ1 ( mipscpu.cp2dr[ 3 ].w.l )
|
||||
#define VX2 ( mipscpu.cp2dr[ 4 ].w.l )
|
||||
#define VY2 ( mipscpu.cp2dr[ 4 ].w.h )
|
||||
#define VZ2 ( mipscpu.cp2dr[ 5 ].w.l )
|
||||
#define R ( mipscpu.cp2dr[ 6 ].b.l )
|
||||
#define G ( mipscpu.cp2dr[ 6 ].b.h )
|
||||
#define B ( mipscpu.cp2dr[ 6 ].b.h2 )
|
||||
#define CODE ( mipscpu.cp2dr[ 6 ].b.h3 )
|
||||
#define OTZ ( mipscpu.cp2dr[ 7 ].w.l )
|
||||
#define IR0 ( (*(INT16 *)&mipscpu.cp2dr[ 8 ].w.l) )
|
||||
#define IR1 ( (*(INT16 *)&mipscpu.cp2dr[ 9 ].w.l) )
|
||||
#define IR2 ( (*(INT16 *)&mipscpu.cp2dr[ 10 ].w.l) )
|
||||
#define IR3 ( (*(INT16 *)&mipscpu.cp2dr[ 11 ].w.l) )
|
||||
#define SXY0 ( mipscpu.cp2dr[ 12 ].d )
|
||||
#define SX0 ( (*(INT16 *)&mipscpu.cp2dr[ 12 ].w.l) )
|
||||
#define SY0 ( (*(INT16 *)&mipscpu.cp2dr[ 12 ].w.h) )
|
||||
#define SXY1 ( mipscpu.cp2dr[ 13 ].d )
|
||||
#define SX1 ( (*(INT16 *)&mipscpu.cp2dr[ 13 ].w.l) )
|
||||
#define SY1 ( (*(INT16 *)&mipscpu.cp2dr[ 13 ].w.h) )
|
||||
#define SXY2 ( mipscpu.cp2dr[ 14 ].d )
|
||||
#define SX2 ( (*(INT16 *)&mipscpu.cp2dr[ 14 ].w.l) )
|
||||
#define SY2 ( (*(INT16 *)&mipscpu.cp2dr[ 14 ].w.h) )
|
||||
#define SXYP ( mipscpu.cp2dr[ 15 ].d )
|
||||
#define SXP ( (*(INT16 *)&mipscpu.cp2dr[ 15 ].w.l) )
|
||||
#define SYP ( (*(INT16 *)&mipscpu.cp2dr[ 15 ].w.h) )
|
||||
#define SZ0 ( mipscpu.cp2dr[ 16 ].w.l )
|
||||
#define SZ1 ( mipscpu.cp2dr[ 17 ].w.l )
|
||||
#define SZ2 ( mipscpu.cp2dr[ 18 ].w.l )
|
||||
#define SZ3 ( mipscpu.cp2dr[ 19 ].w.l )
|
||||
#define RGB0 ( mipscpu.cp2dr[ 20 ].d )
|
||||
#define R0 ( mipscpu.cp2dr[ 20 ].b.l )
|
||||
#define G0 ( mipscpu.cp2dr[ 20 ].b.h )
|
||||
#define B0 ( mipscpu.cp2dr[ 20 ].b.h2 )
|
||||
#define CD0 ( mipscpu.cp2dr[ 20 ].b.h3 )
|
||||
#define RGB1 ( mipscpu.cp2dr[ 21 ].d )
|
||||
#define R1 ( mipscpu.cp2dr[ 21 ].b.l )
|
||||
#define G1 ( mipscpu.cp2dr[ 21 ].b.h )
|
||||
#define B1 ( mipscpu.cp2dr[ 21 ].b.h2 )
|
||||
#define CD1 ( mipscpu.cp2dr[ 21 ].b.h3 )
|
||||
#define RGB2 ( mipscpu.cp2dr[ 22 ].d )
|
||||
#define R2 ( mipscpu.cp2dr[ 22 ].b.l )
|
||||
#define G2 ( mipscpu.cp2dr[ 22 ].b.h )
|
||||
#define B2 ( mipscpu.cp2dr[ 22 ].b.h2 )
|
||||
#define CD2 ( mipscpu.cp2dr[ 22 ].b.h3 )
|
||||
#define RES1 ( mipscpu.cp2dr[ 23 ].d )
|
||||
#define MAC0 ( (*(INT32 *)&mipscpu.cp2dr[ 24 ].d) )
|
||||
#define MAC1 ( (*(INT32 *)&mipscpu.cp2dr[ 25 ].d) )
|
||||
#define MAC2 ( (*(INT32 *)&mipscpu.cp2dr[ 26 ].d) )
|
||||
#define MAC3 ( (*(INT32 *)&mipscpu.cp2dr[ 27 ].d) )
|
||||
#define IRGB ( mipscpu.cp2dr[ 28 ].d )
|
||||
#define ORGB ( mipscpu.cp2dr[ 29 ].d )
|
||||
#define LZCS ( mipscpu.cp2dr[ 30 ].d )
|
||||
#define LZCR ( mipscpu.cp2dr[ 31 ].d )
|
||||
|
||||
#define R11 ( (*(INT16 *)&mipscpu.cp2cr[ 0 ].w.l) )
|
||||
#define R12 ( (*(INT16 *)&mipscpu.cp2cr[ 0 ].w.h) )
|
||||
#define R13 ( (*(INT16 *)&mipscpu.cp2cr[ 1 ].w.l) )
|
||||
#define R21 ( (*(INT16 *)&mipscpu.cp2cr[ 1 ].w.h) )
|
||||
#define R22 ( (*(INT16 *)&mipscpu.cp2cr[ 2 ].w.l) )
|
||||
#define R23 ( (*(INT16 *)&mipscpu.cp2cr[ 2 ].w.h) )
|
||||
#define R31 ( (*(INT16 *)&mipscpu.cp2cr[ 3 ].w.l) )
|
||||
#define R32 ( (*(INT16 *)&mipscpu.cp2cr[ 3 ].w.h) )
|
||||
#define R33 ( (*(INT16 *)&mipscpu.cp2cr[ 4 ].w.l) )
|
||||
#define TRX ( (*(INT32 *)&mipscpu.cp2cr[ 5 ].d) )
|
||||
#define TRY ( (*(INT32 *)&mipscpu.cp2cr[ 6 ].d) )
|
||||
#define TRZ ( (*(INT32 *)&mipscpu.cp2cr[ 7 ].d) )
|
||||
#define L11 ( (*(INT16 *)&mipscpu.cp2cr[ 8 ].w.l) )
|
||||
#define L12 ( (*(INT16 *)&mipscpu.cp2cr[ 8 ].w.h) )
|
||||
#define L13 ( (*(INT16 *)&mipscpu.cp2cr[ 9 ].w.l) )
|
||||
#define L21 ( (*(INT16 *)&mipscpu.cp2cr[ 9 ].w.h) )
|
||||
#define L22 ( (*(INT16 *)&mipscpu.cp2cr[ 10 ].w.l) )
|
||||
#define L23 ( (*(INT16 *)&mipscpu.cp2cr[ 10 ].w.h) )
|
||||
#define L31 ( (*(INT16 *)&mipscpu.cp2cr[ 11 ].w.l) )
|
||||
#define L32 ( (*(INT16 *)&mipscpu.cp2cr[ 11 ].w.h) )
|
||||
#define L33 ( (*(INT16 *)&mipscpu.cp2cr[ 12 ].w.l) )
|
||||
#define RBK ( (*(INT32 *)&mipscpu.cp2cr[ 13 ].d) )
|
||||
#define GBK ( (*(INT32 *)&mipscpu.cp2cr[ 14 ].d) )
|
||||
#define BBK ( (*(INT32 *)&mipscpu.cp2cr[ 15 ].d) )
|
||||
#define LR1 ( (*(INT16 *)&mipscpu.cp2cr[ 16 ].w.l) )
|
||||
#define LR2 ( (*(INT16 *)&mipscpu.cp2cr[ 16 ].w.h) )
|
||||
#define LR3 ( (*(INT16 *)&mipscpu.cp2cr[ 17 ].w.l) )
|
||||
#define LG1 ( (*(INT16 *)&mipscpu.cp2cr[ 17 ].w.h) )
|
||||
#define LG2 ( (*(INT16 *)&mipscpu.cp2cr[ 18 ].w.l) )
|
||||
#define LG3 ( (*(INT16 *)&mipscpu.cp2cr[ 18 ].w.h) )
|
||||
#define LB1 ( (*(INT16 *)&mipscpu.cp2cr[ 19 ].w.l) )
|
||||
#define LB2 ( (*(INT16 *)&mipscpu.cp2cr[ 19 ].w.h) )
|
||||
#define LB3 ( (*(INT16 *)&mipscpu.cp2cr[ 20 ].w.l) )
|
||||
#define RFC ( (*(INT32 *)&mipscpu.cp2cr[ 21 ].d) )
|
||||
#define GFC ( (*(INT32 *)&mipscpu.cp2cr[ 22 ].d) )
|
||||
#define BFC ( (*(INT32 *)&mipscpu.cp2cr[ 23 ].d) )
|
||||
#define OFX ( (*(INT32 *)&mipscpu.cp2cr[ 24 ].d) )
|
||||
#define OFY ( (*(INT32 *)&mipscpu.cp2cr[ 25 ].d) )
|
||||
#define H ( (*(INT16 *)&mipscpu.cp2cr[ 26 ].w.l) )
|
||||
#define DQA ( (*(INT16 *)&mipscpu.cp2cr[ 27 ].w.l) )
|
||||
#define DQB ( (*(INT32 *)&mipscpu.cp2cr[ 28 ].d) )
|
||||
#define ZSF3 ( (*(INT16 *)&mipscpu.cp2cr[ 29 ].w.l) )
|
||||
#define ZSF4 ( (*(INT16 *)&mipscpu.cp2cr[ 30 ].w.l) )
|
||||
#define FLAG ( mipscpu.cp2cr[ 31 ].d )
|
||||
|
||||
#define VX( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2dr[ n << 1 ].w.l) : IR1 )
|
||||
#define VY( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2dr[ n << 1 ].w.h) : IR2 )
|
||||
#define VZ( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2dr[ ( n << 1 ) + 1 ].w.l) : IR3 )
|
||||
#define MX11( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2cr[ ( n << 3 ) ].w.l) : -R << 4 )
|
||||
#define MX12( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2cr[ ( n << 3 ) ].w.h) : R << 4 )
|
||||
#define MX13( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2cr[ ( n << 3 ) + 1 ].w.l) : IR0 )
|
||||
#define MX21( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2cr[ ( n << 3 ) + 1 ].w.h) : R13 )
|
||||
#define MX22( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2cr[ ( n << 3 ) + 2 ].w.l) : R13 )
|
||||
#define MX23( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2cr[ ( n << 3 ) + 2 ].w.h) : R13 )
|
||||
#define MX31( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2cr[ ( n << 3 ) + 3 ].w.l) : R22 )
|
||||
#define MX32( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2cr[ ( n << 3 ) + 3 ].w.h) : R22 )
|
||||
#define MX33( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2cr[ ( n << 3 ) + 4 ].w.l) : R22 )
|
||||
#define CV1( n ) ( n < 3 ? (*(INT32 *)&mipscpu.cp2cr[ ( n << 3 ) + 5 ].d) : 0 )
|
||||
#define CV2( n ) ( n < 3 ? (*(INT32 *)&mipscpu.cp2cr[ ( n << 3 ) + 6 ].d) : 0 )
|
||||
#define CV3( n ) ( n < 3 ? (*(INT32 *)&mipscpu.cp2cr[ ( n << 3 ) + 7 ].d) : 0 )
|
||||
|
||||
static INT32 LIM( INT32 value, INT32 max, INT32 min, UINT32 flag )
|
||||
{
|
||||
if( value > max )
|
||||
{
|
||||
FLAG |= flag;
|
||||
return max;
|
||||
}
|
||||
else if( value < min )
|
||||
{
|
||||
FLAG |= flag;
|
||||
return min;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static UINT32 getcp2dr( int reg )
|
||||
{
|
||||
switch( reg )
|
||||
{
|
||||
case 1:
|
||||
case 3:
|
||||
case 5:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
mipscpu.cp2dr[ reg ].d = (INT32)(*(INT16 *)&mipscpu.cp2dr[ reg ].w.l);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
case 16:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
mipscpu.cp2dr[ reg ].d = (UINT32)mipscpu.cp2dr[ reg ].w.l;
|
||||
break;
|
||||
|
||||
case 15:
|
||||
mipscpu.cp2dr[ reg ].d = SXY2;
|
||||
break;
|
||||
|
||||
case 28:
|
||||
case 29:
|
||||
mipscpu.cp2dr[ reg ].d = LIM( IR1 >> 7, 0x1f, 0, 0 ) | ( LIM( IR2 >> 7, 0x1f, 0, 0 ) << 5 ) | ( LIM( IR3 >> 7, 0x1f, 0, 0 ) << 10 );
|
||||
break;
|
||||
}
|
||||
return mipscpu.cp2dr[ reg ].d;
|
||||
}
|
||||
|
||||
static void setcp2dr( int reg, UINT32 value )
|
||||
{
|
||||
|
||||
switch( reg )
|
||||
{
|
||||
case 15:
|
||||
SXY0 = SXY1;
|
||||
SXY1 = SXY2;
|
||||
SXY2 = value;
|
||||
break;
|
||||
|
||||
case 28:
|
||||
IR1 = ( value & 0x1f ) << 7;
|
||||
IR2 = ( value & 0x3e0 ) << 2;
|
||||
IR3 = ( value & 0x7c00 ) >> 3;
|
||||
break;
|
||||
|
||||
case 30:
|
||||
LZCR = ( value & 0x80000000 ) == 0 ? count_leading_zeros32( value ) : count_leading_zeros32( ~value );
|
||||
break;
|
||||
|
||||
case 31:
|
||||
return;
|
||||
}
|
||||
|
||||
mipscpu.cp2dr[ reg ].d = value;
|
||||
}
|
||||
|
||||
static UINT32 getcp2cr( int reg )
|
||||
{
|
||||
|
||||
return mipscpu.cp2cr[ reg ].d;
|
||||
}
|
||||
|
||||
static void setcp2cr( int reg, UINT32 value )
|
||||
{
|
||||
|
||||
switch( reg )
|
||||
{
|
||||
case 4:
|
||||
case 12:
|
||||
case 20:
|
||||
case 26:
|
||||
case 27:
|
||||
case 29:
|
||||
case 30:
|
||||
value = (INT32)(INT16) value;
|
||||
break;
|
||||
|
||||
case 31:
|
||||
value = value & 0x7ffff000;
|
||||
if( ( value & 0x7f87e000 ) != 0 )
|
||||
{
|
||||
value |= 0x80000000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
mipscpu.cp2cr[ reg ].d = value;
|
||||
}
|
||||
|
||||
static INLINE INT64 gte_shift( INT64 a, int sf )
|
||||
{
|
||||
if( sf > 0 )
|
||||
{
|
||||
return a >> 12;
|
||||
}
|
||||
else if( sf < 0 )
|
||||
{
|
||||
return a << 12;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
static INT32 BOUNDS( int44 value, UINT32 max_flag, UINT32 min_flag )
|
||||
{
|
||||
if( value.pos )
|
||||
{
|
||||
FLAG |= max_flag;
|
||||
}
|
||||
|
||||
if( value.neg )
|
||||
{
|
||||
FLAG |= min_flag;
|
||||
}
|
||||
|
||||
return gte_shift( value.value, m_sf );
|
||||
}
|
||||
|
||||
static INLINE UINT32 gte_divide( UINT16 numerator, UINT16 denominator )
|
||||
{
|
||||
if( numerator < ( denominator * 2 ) )
|
||||
{
|
||||
static const UINT8 table[] =
|
||||
{
|
||||
0xff, 0xfd, 0xfb, 0xf9, 0xf7, 0xf5, 0xf3, 0xf1, 0xef, 0xee, 0xec, 0xea, 0xe8, 0xe6, 0xe4, 0xe3,
|
||||
0xe1, 0xdf, 0xdd, 0xdc, 0xda, 0xd8, 0xd6, 0xd5, 0xd3, 0xd1, 0xd0, 0xce, 0xcd, 0xcb, 0xc9, 0xc8,
|
||||
0xc6, 0xc5, 0xc3, 0xc1, 0xc0, 0xbe, 0xbd, 0xbb, 0xba, 0xb8, 0xb7, 0xb5, 0xb4, 0xb2, 0xb1, 0xb0,
|
||||
0xae, 0xad, 0xab, 0xaa, 0xa9, 0xa7, 0xa6, 0xa4, 0xa3, 0xa2, 0xa0, 0x9f, 0x9e, 0x9c, 0x9b, 0x9a,
|
||||
0x99, 0x97, 0x96, 0x95, 0x94, 0x92, 0x91, 0x90, 0x8f, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x87, 0x86,
|
||||
0x85, 0x84, 0x83, 0x82, 0x81, 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x75, 0x74,
|
||||
0x73, 0x72, 0x71, 0x70, 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64,
|
||||
0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55,
|
||||
0x54, 0x53, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48, 0x48,
|
||||
0x47, 0x46, 0x45, 0x44, 0x43, 0x43, 0x42, 0x41, 0x40, 0x3f, 0x3f, 0x3e, 0x3d, 0x3c, 0x3c, 0x3b,
|
||||
0x3a, 0x39, 0x39, 0x38, 0x37, 0x36, 0x36, 0x35, 0x34, 0x33, 0x33, 0x32, 0x31, 0x31, 0x30, 0x2f,
|
||||
0x2e, 0x2e, 0x2d, 0x2c, 0x2c, 0x2b, 0x2a, 0x2a, 0x29, 0x28, 0x28, 0x27, 0x26, 0x26, 0x25, 0x24,
|
||||
0x24, 0x23, 0x22, 0x22, 0x21, 0x20, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a,
|
||||
0x19, 0x19, 0x18, 0x18, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14, 0x14, 0x13, 0x12, 0x12, 0x11, 0x11,
|
||||
0x10, 0x0f, 0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08,
|
||||
0x07, 0x07, 0x06, 0x06, 0x05, 0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00,
|
||||
0x00
|
||||
};
|
||||
|
||||
int shift = ( count_leading_zeros32( denominator ) - 16 );
|
||||
int r1 = ( denominator << shift ) & 0x7fff;
|
||||
int r2 = table[ ( ( r1 + 0x40 ) >> 7 ) ] + 0x101;
|
||||
int r3 = ( ( 0x80 - ( r2 * ( r1 + 0x8000 ) ) ) >> 8 ) & 0x1ffff;
|
||||
UINT32 reciprocal = ( ( r2 * r3 ) + 0x80 ) >> 8;
|
||||
|
||||
return (UINT32)( ( ( (UINT64)reciprocal * ( (UINT32)numerator << shift ) ) + 0x8000 ) >> 16 );
|
||||
}
|
||||
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
/* Setting bits 12 & 19-22 in FLAG does not set bit 31 */
|
||||
|
||||
static INT32 A1i( int44 a ) { m_mac1 = a.value; return BOUNDS( a, ( 1U << 31 ) | ( 1 << 30 ), ( 1U << 31 ) | ( 1 << 27 ) ); }
|
||||
static INT32 A1( INT64 a ) { return A1i( i44( a ) ); }
|
||||
static INT32 A2i( int44 a ) { m_mac2 = a.value; return BOUNDS( a, ( 1U << 31 ) | ( 1 << 29 ), ( 1U << 31 ) | ( 1 << 26 ) ); }
|
||||
static INT32 A2( INT64 a ) { return A2i( i44( a ) ); }
|
||||
static INT32 A3i( int44 a ) { m_mac3 = a.value; return BOUNDS( a, ( 1U << 31 ) | ( 1 << 28 ), ( 1U << 31 ) | ( 1 << 25 ) ); }
|
||||
static INT32 A3( INT64 a ) { return A3i( i44( a ) ); }
|
||||
static INT32 Lm_B1( INT32 a, int lm ) { return LIM( a, 0x7fff, -0x8000 * !lm, ( 1U << 31 ) | ( 1 << 24 ) ); }
|
||||
static INT32 Lm_B2( INT32 a, int lm ) { return LIM( a, 0x7fff, -0x8000 * !lm, ( 1U << 31 ) | ( 1 << 23 ) ); }
|
||||
static INT32 Lm_B3( INT32 a, int lm ) { return LIM( a, 0x7fff, -0x8000 * !lm, ( 1 << 22 ) ); }
|
||||
|
||||
static INT32 Lm_B3_sf( INT64 value, int sf, int lm )
|
||||
{
|
||||
INT32 value_sf = (INT32)gte_shift( value, sf );
|
||||
INT32 value_12 = (INT32)gte_shift( value, 1 );
|
||||
int max = 0x7fff;
|
||||
int min = 0;
|
||||
if( lm == 0 )
|
||||
{
|
||||
min = -0x8000;
|
||||
}
|
||||
|
||||
if( value_12 < -0x8000 || value_12 > 0x7fff )
|
||||
{
|
||||
FLAG |= ( 1 << 22 );
|
||||
}
|
||||
|
||||
if( value_sf > max )
|
||||
{
|
||||
return max;
|
||||
}
|
||||
else if( value_sf < min )
|
||||
{
|
||||
return min;
|
||||
}
|
||||
|
||||
return value_sf;
|
||||
}
|
||||
|
||||
static INT32 Lm_C1( INT32 a ) { return LIM( a, 0x00ff, 0x0000, ( 1 << 21 ) ); }
|
||||
static INT32 Lm_C2( INT32 a ) { return LIM( a, 0x00ff, 0x0000, ( 1 << 20 ) ); }
|
||||
static INT32 Lm_C3( INT32 a ) { return LIM( a, 0x00ff, 0x0000, ( 1 << 19 ) ); }
|
||||
static INT32 Lm_D( INT64 a, int sf ) { return LIM( gte_shift( a, sf ), 0xffff, 0x0000, ( 1U << 31 ) | ( 1 << 18 ) ); }
|
||||
|
||||
static UINT32 Lm_E( UINT32 result )
|
||||
{
|
||||
if( result == 0xffffffff )
|
||||
{
|
||||
FLAG |= ( 1U << 31 ) | ( 1 << 17 );
|
||||
return 0x1ffff;
|
||||
}
|
||||
|
||||
if( result > 0x1ffff )
|
||||
{
|
||||
return 0x1ffff;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static INT64 F( INT64 a )
|
||||
{
|
||||
m_mac0 = a;
|
||||
|
||||
if( a > 0x7fffffff )
|
||||
{
|
||||
FLAG |= ( 1U << 31 ) | ( 1 << 16 );
|
||||
}
|
||||
|
||||
if( a < -( (INT64)1 << 31 ) )
|
||||
{
|
||||
FLAG |= ( 1U << 31 ) | ( 1 << 15 );
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
static INT32 Lm_G1( INT64 a )
|
||||
{
|
||||
if( a > 0x3ff )
|
||||
{
|
||||
FLAG |= ( 1U << 31 ) | ( 1 << 14 );
|
||||
return 0x3ff;
|
||||
}
|
||||
|
||||
if( a < -0x400 )
|
||||
{
|
||||
FLAG |= ( 1U << 31 ) | ( 1 << 14 );
|
||||
return -0x400;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
static INT32 Lm_G2( INT64 a )
|
||||
{
|
||||
if( a > 0x3ff )
|
||||
{
|
||||
FLAG |= ( 1U << 31 ) | ( 1 << 13 );
|
||||
return 0x3ff;
|
||||
}
|
||||
|
||||
if( a < -0x400 )
|
||||
{
|
||||
FLAG |= ( 1U << 31 ) | ( 1 << 13 );
|
||||
return -0x400;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
static INT32 Lm_H( INT64 value, int sf )
|
||||
{
|
||||
INT64 value_sf = gte_shift( value, sf );
|
||||
INT32 value_12 = (INT32)gte_shift( value, 1 );
|
||||
int max = 0x1000;
|
||||
int min = 0x0000;
|
||||
|
||||
if( value_sf < min || value_sf > max )
|
||||
{
|
||||
FLAG |= ( 1 << 12 );
|
||||
}
|
||||
|
||||
if( value_12 > max )
|
||||
{
|
||||
return max;
|
||||
}
|
||||
|
||||
if( value_12 < min )
|
||||
{
|
||||
return min;
|
||||
}
|
||||
|
||||
return value_12;
|
||||
}
|
||||
|
||||
static int gte_docop2( int gteop )
|
||||
{
|
||||
int v;
|
||||
int lm;
|
||||
int cv;
|
||||
int mx;
|
||||
INT32 h_over_sz3 = 0;
|
||||
|
||||
lm = GTE_LM( gteop );
|
||||
m_sf = GTE_SF( gteop );
|
||||
|
||||
FLAG = 0;
|
||||
|
||||
switch( GTE_FUNCT( gteop ) )
|
||||
{
|
||||
case 0x00: /* drop through to RTPS */
|
||||
case 0x01:
|
||||
|
||||
MAC1 = A1i( i44_add( i44_add( i44_add( i44( (INT64) TRX << 12 ), ( R11 * VX0 ) ), ( R12 * VY0 ) ), ( R13 * VZ0 ) ) );
|
||||
MAC2 = A2i( i44_add( i44_add( i44_add( i44( (INT64) TRY << 12 ), ( R21 * VX0 ) ), ( R22 * VY0 ) ), ( R23 * VZ0 ) ) );
|
||||
MAC3 = A3i( i44_add( i44_add( i44_add( i44( (INT64) TRZ << 12 ), ( R31 * VX0 ) ), ( R32 * VY0 ) ), ( R33 * VZ0 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3_sf( m_mac3, m_sf, lm );
|
||||
SZ0 = SZ1;
|
||||
SZ1 = SZ2;
|
||||
SZ2 = SZ3;
|
||||
SZ3 = Lm_D( m_mac3, 1 );
|
||||
h_over_sz3 = Lm_E( gte_divide( H, SZ3 ) );
|
||||
SXY0 = SXY1;
|
||||
SXY1 = SXY2;
|
||||
SX2 = Lm_G1( F( (INT64) OFX + ( (INT64) IR1 * h_over_sz3 ) ) >> 16 );
|
||||
SY2 = Lm_G2( F( (INT64) OFY + ( (INT64) IR2 * h_over_sz3 ) ) >> 16 );
|
||||
MAC0 = F( (INT64) DQB + ( (INT64) DQA * h_over_sz3 ) );
|
||||
IR0 = Lm_H( m_mac0, 1 );
|
||||
return 1;
|
||||
|
||||
case 0x06:
|
||||
|
||||
MAC0 = F( (INT64) ( SX0 * SY1 ) + ( SX1 * SY2 ) + ( SX2 * SY0 ) - ( SX0 * SY2 ) - ( SX1 * SY0 ) - ( SX2 * SY1 ) );
|
||||
return 1;
|
||||
|
||||
case 0x0c:
|
||||
|
||||
MAC1 = A1( (INT64) ( R22 * IR3 ) - ( R33 * IR2 ) );
|
||||
MAC2 = A2( (INT64) ( R33 * IR1 ) - ( R11 * IR3 ) );
|
||||
MAC3 = A3( (INT64) ( R11 * IR2 ) - ( R22 * IR1 ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
return 1;
|
||||
|
||||
case 0x10:
|
||||
|
||||
MAC1 = A1( ( R << 16 ) + ( IR0 * Lm_B1( A1( ( (INT64) RFC << 12 ) - ( R << 16 ) ), 0 ) ) );
|
||||
MAC2 = A2( ( G << 16 ) + ( IR0 * Lm_B2( A2( ( (INT64) GFC << 12 ) - ( G << 16 ) ), 0 ) ) );
|
||||
MAC3 = A3( ( B << 16 ) + ( IR0 * Lm_B3( A3( ( (INT64) BFC << 12 ) - ( B << 16 ) ), 0 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
return 1;
|
||||
|
||||
case 0x11:
|
||||
|
||||
MAC1 = A1( ( IR1 << 12 ) + ( IR0 * Lm_B1( A1( ( (INT64) RFC << 12 ) - ( IR1 << 12 ) ), 0 ) ) );
|
||||
MAC2 = A2( ( IR2 << 12 ) + ( IR0 * Lm_B2( A2( ( (INT64) GFC << 12 ) - ( IR2 << 12 ) ), 0 ) ) );
|
||||
MAC3 = A3( ( IR3 << 12 ) + ( IR0 * Lm_B3( A3( ( (INT64) BFC << 12 ) - ( IR3 << 12 ) ), 0 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
return 1;
|
||||
|
||||
case 0x12:
|
||||
|
||||
mx = GTE_MX( gteop );
|
||||
v = GTE_V( gteop );
|
||||
cv = GTE_CV( gteop );
|
||||
|
||||
switch( cv )
|
||||
{
|
||||
case 2:
|
||||
MAC1 = A1( (INT64) ( MX12( mx ) * VY( v ) ) + ( MX13( mx ) * VZ( v ) ) );
|
||||
MAC2 = A2( (INT64) ( MX22( mx ) * VY( v ) ) + ( MX23( mx ) * VZ( v ) ) );
|
||||
MAC3 = A3( (INT64) ( MX32( mx ) * VY( v ) ) + ( MX33( mx ) * VZ( v ) ) );
|
||||
Lm_B1( A1( ( (INT64) CV1( cv ) << 12 ) + ( MX11( mx ) * VX( v ) ) ), 0 );
|
||||
Lm_B2( A2( ( (INT64) CV2( cv ) << 12 ) + ( MX21( mx ) * VX( v ) ) ), 0 );
|
||||
Lm_B3( A3( ( (INT64) CV3( cv ) << 12 ) + ( MX31( mx ) * VX( v ) ) ), 0 );
|
||||
break;
|
||||
|
||||
default:
|
||||
MAC1 = A1i( i44_add( i44_add( i44_add( i44( (INT64) CV1( cv ) << 12 ), ( MX11( mx ) * VX( v ) ) ), ( MX12( mx ) * VY( v ) ) ), ( MX13( mx ) * VZ( v ) ) ) );
|
||||
MAC2 = A2i( i44_add( i44_add( i44_add( i44( (INT64) CV2( cv ) << 12 ), ( MX21( mx ) * VX( v ) ) ), ( MX22( mx ) * VY( v ) ) ), ( MX23( mx ) * VZ( v ) ) ) );
|
||||
MAC3 = A3i( i44_add( i44_add( i44_add( i44( (INT64) CV3( cv ) << 12 ), ( MX31( mx ) * VX( v ) ) ), ( MX32( mx ) * VY( v ) ) ), ( MX33( mx ) * VZ( v ) ) ) );
|
||||
break;
|
||||
}
|
||||
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
return 1;
|
||||
|
||||
case 0x13:
|
||||
|
||||
MAC1 = A1( (INT64) ( L11 * VX0 ) + ( L12 * VY0 ) + ( L13 * VZ0 ) );
|
||||
MAC2 = A2( (INT64) ( L21 * VX0 ) + ( L22 * VY0 ) + ( L23 * VZ0 ) );
|
||||
MAC3 = A3( (INT64) ( L31 * VX0 ) + ( L32 * VY0 ) + ( L33 * VZ0 ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1i( i44_add( i44_add( i44_add( i44( (INT64) RBK << 12 ), ( LR1 * IR1 ) ), ( LR2 * IR2 ) ), ( LR3 * IR3 ) ) );
|
||||
MAC2 = A2i( i44_add( i44_add( i44_add( i44( (INT64) GBK << 12 ), ( LG1 * IR1 ) ), ( LG2 * IR2 ) ), ( LG3 * IR3 ) ) );
|
||||
MAC3 = A3i( i44_add( i44_add( i44_add( i44( (INT64) BBK << 12 ), ( LB1 * IR1 ) ), ( LB2 * IR2 ) ), ( LB3 * IR3 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1( ( ( R << 4 ) * IR1 ) + ( IR0 * Lm_B1( A1( ( (INT64) RFC << 12 ) - ( ( R << 4 ) * IR1 ) ), 0 ) ) );
|
||||
MAC2 = A2( ( ( G << 4 ) * IR2 ) + ( IR0 * Lm_B2( A2( ( (INT64) GFC << 12 ) - ( ( G << 4 ) * IR2 ) ), 0 ) ) );
|
||||
MAC3 = A3( ( ( B << 4 ) * IR3 ) + ( IR0 * Lm_B3( A3( ( (INT64) BFC << 12 ) - ( ( B << 4 ) * IR3 ) ), 0 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
return 1;
|
||||
|
||||
case 0x14:
|
||||
|
||||
MAC1 = A1i( i44_add( i44_add( i44_add( i44( (INT64) RBK << 12 ), ( LR1 * IR1 ) ), ( LR2 * IR2 ) ), ( LR3 * IR3 ) ) );
|
||||
MAC2 = A2i( i44_add( i44_add( i44_add( i44( (INT64) GBK << 12 ), ( LG1 * IR1 ) ), ( LG2 * IR2 ) ), ( LG3 * IR3 ) ) );
|
||||
MAC3 = A3i( i44_add( i44_add( i44_add( i44( (INT64) BBK << 12 ), ( LB1 * IR1 ) ), ( LB2 * IR2 ) ), ( LB3 * IR3 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1( ( ( R << 4 ) * IR1 ) + ( IR0 * Lm_B1( A1( ( (INT64) RFC << 12 ) - ( ( R << 4 ) * IR1 ) ), 0 ) ) );
|
||||
MAC2 = A2( ( ( G << 4 ) * IR2 ) + ( IR0 * Lm_B2( A2( ( (INT64) GFC << 12 ) - ( ( G << 4 ) * IR2 ) ), 0 ) ) );
|
||||
MAC3 = A3( ( ( B << 4 ) * IR3 ) + ( IR0 * Lm_B3( A3( ( (INT64) BFC << 12 ) - ( ( B << 4 ) * IR3 ) ), 0 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
return 1;
|
||||
|
||||
case 0x16:
|
||||
|
||||
for( v = 0; v < 3; v++ )
|
||||
{
|
||||
MAC1 = A1( (INT64) ( L11 * VX( v ) ) + ( L12 * VY( v ) ) + ( L13 * VZ( v ) ) );
|
||||
MAC2 = A2( (INT64) ( L21 * VX( v ) ) + ( L22 * VY( v ) ) + ( L23 * VZ( v ) ) );
|
||||
MAC3 = A3( (INT64) ( L31 * VX( v ) ) + ( L32 * VY( v ) ) + ( L33 * VZ( v ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1i( i44_add( i44_add( i44_add( i44( (INT64) RBK << 12 ), ( LR1 * IR1 ) ), ( LR2 * IR2 ) ), ( LR3 * IR3 ) ) );
|
||||
MAC2 = A2i( i44_add( i44_add( i44_add( i44( (INT64) GBK << 12 ), ( LG1 * IR1 ) ), ( LG2 * IR2 ) ), ( LG3 * IR3 ) ) );
|
||||
MAC3 = A3i( i44_add( i44_add( i44_add( i44( (INT64) BBK << 12 ), ( LB1 * IR1 ) ), ( LB2 * IR2 ) ), ( LB3 * IR3 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1( ( ( R << 4 ) * IR1 ) + ( IR0 * Lm_B1( A1( ( (INT64) RFC << 12 ) - ( ( R << 4 ) * IR1 ) ), 0 ) ) );
|
||||
MAC2 = A2( ( ( G << 4 ) * IR2 ) + ( IR0 * Lm_B2( A2( ( (INT64) GFC << 12 ) - ( ( G << 4 ) * IR2 ) ), 0 ) ) );
|
||||
MAC3 = A3( ( ( B << 4 ) * IR3 ) + ( IR0 * Lm_B3( A3( ( (INT64) BFC << 12 ) - ( ( B << 4 ) * IR3 ) ), 0 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
}
|
||||
return 1;
|
||||
|
||||
case 0x1b:
|
||||
|
||||
MAC1 = A1( (INT64) ( L11 * VX0 ) + ( L12 * VY0 ) + ( L13 * VZ0 ) );
|
||||
MAC2 = A2( (INT64) ( L21 * VX0 ) + ( L22 * VY0 ) + ( L23 * VZ0 ) );
|
||||
MAC3 = A3( (INT64) ( L31 * VX0 ) + ( L32 * VY0 ) + ( L33 * VZ0 ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1i( i44_add( i44_add( i44_add( i44( (INT64) RBK << 12 ), ( LR1 * IR1 ) ), ( LR2 * IR2 ) ), ( LR3 * IR3 ) ) );
|
||||
MAC2 = A2i( i44_add( i44_add( i44_add( i44( (INT64) GBK << 12 ), ( LG1 * IR1 ) ), ( LG2 * IR2 ) ), ( LG3 * IR3 ) ) );
|
||||
MAC3 = A3i( i44_add( i44_add( i44_add( i44( (INT64) BBK << 12 ), ( LB1 * IR1 ) ), ( LB2 * IR2 ) ), ( LB3 * IR3 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1( ( R << 4 ) * IR1 );
|
||||
MAC2 = A2( ( G << 4 ) * IR2 );
|
||||
MAC3 = A3( ( B << 4 ) * IR3 );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
return 1;
|
||||
|
||||
case 0x1c:
|
||||
|
||||
MAC1 = A1i( i44_add( i44_add( i44_add( i44( ( (INT64) RBK ) << 12 ), ( LR1 * IR1 ) ), ( LR2 * IR2 ) ), ( LR3 * IR3 ) ) );
|
||||
MAC2 = A2i( i44_add( i44_add( i44_add( i44( ( (INT64) GBK ) << 12 ), ( LG1 * IR1 ) ), ( LG2 * IR2 ) ), ( LG3 * IR3 ) ) );
|
||||
MAC3 = A3i( i44_add( i44_add( i44_add( i44( ( (INT64) BBK ) << 12 ), ( LB1 * IR1 ) ), ( LB2 * IR2 ) ), ( LB3 * IR3 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1( ( R << 4 ) * IR1 );
|
||||
MAC2 = A2( ( G << 4 ) * IR2 );
|
||||
MAC3 = A3( ( B << 4 ) * IR3 );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
return 1;
|
||||
|
||||
case 0x1e:
|
||||
|
||||
MAC1 = A1( (INT64) ( L11 * VX0 ) + ( L12 * VY0 ) + ( L13 * VZ0 ) );
|
||||
MAC2 = A2( (INT64) ( L21 * VX0 ) + ( L22 * VY0 ) + ( L23 * VZ0 ) );
|
||||
MAC3 = A3( (INT64) ( L31 * VX0 ) + ( L32 * VY0 ) + ( L33 * VZ0 ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1i( i44_add( i44_add( i44_add( i44( (INT64) RBK << 12 ), ( LR1 * IR1 ) ), ( LR2 * IR2 ) ), ( LR3 * IR3 ) ) );
|
||||
MAC2 = A2i( i44_add( i44_add( i44_add( i44( (INT64) GBK << 12 ), ( LG1 * IR1 ) ), ( LG2 * IR2 ) ), ( LG3 * IR3 ) ) );
|
||||
MAC3 = A3i( i44_add( i44_add( i44_add( i44( (INT64) BBK << 12 ), ( LB1 * IR1 ) ), ( LB2 * IR2 ) ), ( LB3 * IR3 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
return 1;
|
||||
|
||||
case 0x20:
|
||||
|
||||
for( v = 0; v < 3; v++ )
|
||||
{
|
||||
MAC1 = A1( (INT64) ( L11 * VX( v ) ) + ( L12 * VY( v ) ) + ( L13 * VZ( v ) ) );
|
||||
MAC2 = A2( (INT64) ( L21 * VX( v ) ) + ( L22 * VY( v ) ) + ( L23 * VZ( v ) ) );
|
||||
MAC3 = A3( (INT64) ( L31 * VX( v ) ) + ( L32 * VY( v ) ) + ( L33 * VZ( v ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1i( i44_add( i44_add( i44_add( i44( (INT64) RBK << 12 ), ( LR1 * IR1 ) ), ( LR2 * IR2 ) ), ( LR3 * IR3 ) ) );
|
||||
MAC2 = A2i( i44_add( i44_add( i44_add( i44( (INT64) GBK << 12 ), ( LG1 * IR1 ) ), ( LG2 * IR2 ) ), ( LG3 * IR3 ) ) );
|
||||
MAC3 = A3i( i44_add( i44_add( i44_add( i44( (INT64) BBK << 12 ), ( LB1 * IR1 ) ), ( LB2 * IR2 ) ), ( LB3 * IR3 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
}
|
||||
return 1;
|
||||
|
||||
case 0x28:
|
||||
|
||||
MAC1 = A1( IR1 * IR1 );
|
||||
MAC2 = A2( IR2 * IR2 );
|
||||
MAC3 = A3( IR3 * IR3 );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
return 1;
|
||||
|
||||
case 0x1a: /* end of NCDT */
|
||||
case 0x29:
|
||||
|
||||
MAC1 = A1( ( ( R << 4 ) * IR1 ) + ( IR0 * Lm_B1( A1( ( (INT64) RFC << 12 ) - ( ( R << 4 ) * IR1 ) ), 0 ) ) );
|
||||
MAC2 = A2( ( ( G << 4 ) * IR2 ) + ( IR0 * Lm_B2( A2( ( (INT64) GFC << 12 ) - ( ( G << 4 ) * IR2 ) ), 0 ) ) );
|
||||
MAC3 = A3( ( ( B << 4 ) * IR3 ) + ( IR0 * Lm_B3( A3( ( (INT64) BFC << 12 ) - ( ( B << 4 ) * IR3 ) ), 0 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
return 1;
|
||||
|
||||
case 0x2a:
|
||||
|
||||
for( v = 0; v < 3; v++ )
|
||||
{
|
||||
MAC1 = A1( ( R0 << 16 ) + ( IR0 * Lm_B1( A1( ( (INT64) RFC << 12 ) - ( R0 << 16 ) ), 0 ) ) );
|
||||
MAC2 = A2( ( G0 << 16 ) + ( IR0 * Lm_B2( A2( ( (INT64) GFC << 12 ) - ( G0 << 16 ) ), 0 ) ) );
|
||||
MAC3 = A3( ( B0 << 16 ) + ( IR0 * Lm_B3( A3( ( (INT64) BFC << 12 ) - ( B0 << 16 ) ), 0 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
}
|
||||
return 1;
|
||||
|
||||
case 0x2d:
|
||||
|
||||
MAC0 = F( (INT64) ( ZSF3 * SZ1 ) + ( ZSF3 * SZ2 ) + ( ZSF3 * SZ3 ) );
|
||||
OTZ = Lm_D( m_mac0, 1 );
|
||||
return 1;
|
||||
|
||||
case 0x2e:
|
||||
|
||||
MAC0 = F( (INT64) ( ZSF4 * SZ0 ) + ( ZSF4 * SZ1 ) + ( ZSF4 * SZ2 ) + ( ZSF4 * SZ3 ) );
|
||||
OTZ = Lm_D( m_mac0, 1 );
|
||||
return 1;
|
||||
|
||||
case 0x30:
|
||||
|
||||
for( v = 0; v < 3; v++ )
|
||||
{
|
||||
MAC1 = A1i( i44_add( i44_add( i44_add( i44( (INT64) TRX << 12 ), ( R11 * VX( v ) ) ), ( R12 * VY( v ) ) ), ( R13 * VZ( v ) ) ) );
|
||||
MAC2 = A2i( i44_add( i44_add( i44_add( i44( (INT64) TRY << 12 ), ( R21 * VX( v ) ) ), ( R22 * VY( v ) ) ), ( R23 * VZ( v ) ) ) );
|
||||
MAC3 = A3i( i44_add( i44_add( i44_add( i44( (INT64) TRZ << 12 ), ( R31 * VX( v ) ) ), ( R32 * VY( v ) ) ), ( R33 * VZ( v ) ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3_sf( m_mac3, m_sf, lm );
|
||||
SZ0 = SZ1;
|
||||
SZ1 = SZ2;
|
||||
SZ2 = SZ3;
|
||||
SZ3 = Lm_D( m_mac3, 1 );
|
||||
h_over_sz3 = Lm_E( gte_divide( H, SZ3 ) );
|
||||
SXY0 = SXY1;
|
||||
SXY1 = SXY2;
|
||||
SX2 = Lm_G1( F( (INT64) OFX + ( (INT64) IR1 * h_over_sz3 ) ) >> 16 );
|
||||
SY2 = Lm_G2( F( (INT64) OFY + ( (INT64) IR2 * h_over_sz3 ) ) >> 16 );
|
||||
}
|
||||
|
||||
MAC0 = F( (INT64) DQB + ( (INT64) DQA * h_over_sz3 ) );
|
||||
IR0 = Lm_H( m_mac0, 1 );
|
||||
return 1;
|
||||
|
||||
case 0x3d:
|
||||
|
||||
MAC1 = A1( IR0 * IR1 );
|
||||
MAC2 = A2( IR0 * IR2 );
|
||||
MAC3 = A3( IR0 * IR3 );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
return 1;
|
||||
|
||||
case 0x3e:
|
||||
|
||||
MAC1 = A1( gte_shift( MAC1, -m_sf ) + ( IR0 * IR1 ) );
|
||||
MAC2 = A2( gte_shift( MAC2, -m_sf ) + ( IR0 * IR2 ) );
|
||||
MAC3 = A3( gte_shift( MAC3, -m_sf ) + ( IR0 * IR3 ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
return 1;
|
||||
|
||||
case 0x3f:
|
||||
|
||||
for( v = 0; v < 3; v++ )
|
||||
{
|
||||
MAC1 = A1( (INT64) ( L11 * VX( v ) ) + ( L12 * VY( v ) ) + ( L13 * VZ( v ) ) );
|
||||
MAC2 = A2( (INT64) ( L21 * VX( v ) ) + ( L22 * VY( v ) ) + ( L23 * VZ( v ) ) );
|
||||
MAC3 = A3( (INT64) ( L31 * VX( v ) ) + ( L32 * VY( v ) ) + ( L33 * VZ( v ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1i( i44_add( i44_add( i44_add( i44( (INT64) RBK << 12 ), ( LR1 * IR1 ) ), ( LR2 * IR2 ) ), ( LR3 * IR3 ) ) );
|
||||
MAC2 = A2i( i44_add( i44_add( i44_add( i44( (INT64) GBK << 12 ), ( LG1 * IR1 ) ), ( LG2 * IR2 ) ), ( LG3 * IR3 ) ) );
|
||||
MAC3 = A3i( i44_add( i44_add( i44_add( i44( (INT64) BBK << 12 ), ( LB1 * IR1 ) ), ( LB2 * IR2 ) ), ( LB3 * IR3 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1( ( R << 4 ) * IR1 );
|
||||
MAC2 = A2( ( G << 4 ) * IR2 );
|
||||
MAC3 = A3( ( B << 4 ) * IR3 );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,588 @@
|
||||
/***************************************************************************
|
||||
|
||||
psxloop.c
|
||||
|
||||
Exact skip of the PSX CPU's wait loops (included by psx_cpu.c).
|
||||
|
||||
Within a timeslice nothing but the CPU itself changes main RAM or the
|
||||
CPU state: interrupts, timers, DMA and the other CPUs only act between
|
||||
timeslices. A loop that waits for an interrupt therefore repeats the
|
||||
same work until the timeslice ends, and the whole passes that still fit
|
||||
can be done at once: registers, memory and cycles end up exactly as if
|
||||
they had run (one cycle per instruction, as the interpreter counts),
|
||||
and the last pass runs normally. Three kinds of loops are recognised:
|
||||
|
||||
LOOP_PURE a short loop of loads and register arithmetic, no stores, no
|
||||
other branch, where no register is read before the pass
|
||||
writes it: every pass leaves the same state (for example
|
||||
"lhu v0,x(v1); nop; beqz v0,loop"). The recompiler has its
|
||||
own version of this one (jit_is_idle_loop).
|
||||
LOOP_COUNT "b<cond> r,self" with "addiu r,r,-1" in the delay slot: a
|
||||
plain countdown.
|
||||
LOOP_VSYNC the wait in the PsyQ libraries' VSync(): a timeout counter on
|
||||
the stack, decremented and stored every pass, and a RAM word
|
||||
compared with a target (used by most System 11/12 games).
|
||||
LOOP_RNG the VBLANK wait of Tekken 3 / Tekken Tag Tournament: every pass
|
||||
steps two random number generators in RAM (x = 5x + 1 and
|
||||
x = (x + 1) * 69069) while a flag in RAM stays 0.
|
||||
|
||||
The loop's code is checked word by word every time before a skip, so
|
||||
a changed program is never skipped by mistake. Main RAM and the BIOS
|
||||
must be fast RAM (psxcpu_add_fastram) for any of this to apply; loads
|
||||
from anything else (I/O, shared RAM) are never skipped over.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#define LOOP_PURE 1
|
||||
#define LOOP_COUNT 2
|
||||
#define LOOP_VSYNC 3
|
||||
#define LOOP_RNG 4
|
||||
|
||||
/* build with -DPSX_LOOPSKIP=0 to compare against the plain interpreter */
|
||||
#ifndef PSX_LOOPSKIP
|
||||
#define PSX_LOOPSKIP 1
|
||||
#endif
|
||||
static int loopskip_enabled = PSX_LOOPSKIP;
|
||||
|
||||
/* a word of code or data in fast RAM, or 0 if it is not there */
|
||||
static int loop_word( UINT32 address, UINT32 *word )
|
||||
{
|
||||
struct psx_fastram *r = find_fastram( address, 4 );
|
||||
if( r == NULL || ( address & 3 ) != 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
*word = *(UINT32 *)&r->base[ address - r->start ];
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* host pointer of a writable RAM word away from translated code, or NULL */
|
||||
static UINT32 *loop_data( UINT32 address )
|
||||
{
|
||||
struct psx_fastram *r = find_fastram( address, 4 );
|
||||
UINT8 *host;
|
||||
if( r == NULL || r->readonly || ( address & 3 ) != 0 )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
host = &r->base[ address - r->start ];
|
||||
#if PSXJIT_SUPPORTED
|
||||
if( jit_code_present && jit_codemap[ jit_codemap_index( host ) ] )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
return (UINT32 *)host;
|
||||
}
|
||||
|
||||
static UINT32 loop_branch_target( UINT32 op, UINT32 pc )
|
||||
{
|
||||
return pc + 4 + ( (INT32)(INT16)op << 2 );
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* LOOP_PURE
|
||||
*************************************/
|
||||
|
||||
/* registers read and written by an allowed loop instruction; 0 if not allowed */
|
||||
static int loop_pure_op( UINT32 op, UINT32 *reads, UINT32 *writes, int *load )
|
||||
{
|
||||
UINT32 rs = INS_RS( op ), rt = INS_RT( op ), rd = INS_RD( op );
|
||||
|
||||
*reads = 0; *writes = 0; *load = 0;
|
||||
switch( INS_OP( op ) )
|
||||
{
|
||||
case 0x00: /* SPECIAL */
|
||||
switch( op & 63 )
|
||||
{
|
||||
case 0x00: case 0x02: case 0x03: /* SLL SRL SRA */
|
||||
*reads = 1 << rt; *writes = 1 << rd; return 1;
|
||||
case 0x04: case 0x06: case 0x07: /* SLLV SRLV SRAV */
|
||||
case 0x21: case 0x23: case 0x24: case 0x25: /* ADDU SUBU AND OR */
|
||||
case 0x26: case 0x27: case 0x2a: case 0x2b: /* XOR NOR SLT SLTU */
|
||||
*reads = ( 1 << rs ) | ( 1 << rt ); *writes = 1 << rd; return 1;
|
||||
}
|
||||
return 0;
|
||||
case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: /* ADDIU SLTI SLTIU ANDI ORI XORI */
|
||||
*reads = 1 << rs; *writes = 1 << rt; return 1;
|
||||
case 0x0f: /* LUI */
|
||||
*writes = 1 << rt; return 1;
|
||||
case 0x20: case 0x21: case 0x23: case 0x24: case 0x25: /* LB LH LW LBU LHU */
|
||||
*reads = 1 << rs; *writes = 1 << rt; *load = 1; return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* registers read by the closing branch, or -1 if 'op' is not a usable branch to 'target' */
|
||||
static int loop_pure_branch( UINT32 op, UINT32 pc, UINT32 target, UINT32 *reads )
|
||||
{
|
||||
UINT32 rs = INS_RS( op ), rt = INS_RT( op );
|
||||
switch( INS_OP( op ) )
|
||||
{
|
||||
case 0x01: /* BLTZ BGEZ */
|
||||
if( rt != 0x00 && rt != 0x01 ) return -1;
|
||||
*reads = 1 << rs;
|
||||
break;
|
||||
case 0x04: case 0x05: /* BEQ BNE */
|
||||
*reads = ( 1 << rs ) | ( 1 << rt );
|
||||
break;
|
||||
case 0x06: case 0x07: /* BLEZ BGTZ */
|
||||
if( rt != 0 ) return -1;
|
||||
*reads = 1 << rs;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return loop_branch_target( op, pc ) == target ? 0 : -1;
|
||||
}
|
||||
|
||||
/*
|
||||
The loop at 'l' as LOOP_PURE: the branch closing it in *branch, or 0.
|
||||
Same rules as the recompiler's jit_is_idle_loop, plus no instruction
|
||||
may use a register loaded by the one before it (the load delay would
|
||||
make it see the previous pass's value).
|
||||
*/
|
||||
static int loop_is_pure( UINT32 l, UINT32 *branch )
|
||||
{
|
||||
UINT32 ops[ 18 ], reads[ 18 ], writes[ 18 ], all = 0, written = 0, b;
|
||||
int load[ 18 ], n, i, found = -1;
|
||||
|
||||
for( n = 0; n < 16; n++ )
|
||||
{
|
||||
UINT32 r;
|
||||
if( !loop_word( l + n * 4, &ops[ n ] ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if( loop_pure_branch( ops[ n ], l + n * 4, l, &r ) == 0 )
|
||||
{
|
||||
found = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( found < 0 || !loop_word( l + ( found + 1 ) * 4, &ops[ found + 1 ] ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
b = l + found * 4;
|
||||
for( i = 0; i <= found + 1; i++ )
|
||||
{
|
||||
if( i == found )
|
||||
{
|
||||
loop_pure_branch( ops[ i ], b, l, &reads[ i ] );
|
||||
writes[ i ] = 0;
|
||||
load[ i ] = 0;
|
||||
}
|
||||
else if( !loop_pure_op( ops[ i ], &reads[ i ], &writes[ i ], &load[ i ] ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
all |= writes[ i ];
|
||||
}
|
||||
for( i = 0; i <= found + 1; i++ )
|
||||
{
|
||||
if( reads[ i ] & all & ~written & ~1 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if( i > 0 && load[ i - 1 ] && ( reads[ i ] & writes[ i - 1 ] & ~1 ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
written |= writes[ i ];
|
||||
}
|
||||
/* the slot's load must not reach into the next pass */
|
||||
if( load[ found + 1 ] )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
*branch = b;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* LOOP_COUNT
|
||||
*************************************/
|
||||
|
||||
/* "b<cond> r,self" + "addiu r,r,-1": the register, or -1 */
|
||||
static int loop_is_count( UINT32 l )
|
||||
{
|
||||
UINT32 op, slot, r;
|
||||
if( !loop_word( l, &op ) || !loop_word( l + 4, &slot ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if( loop_branch_target( op, l ) != l )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
r = INS_RS( op );
|
||||
if( r == 0 || slot != ( 0x24000000 | ( r << 21 ) | ( r << 16 ) | 0xffff ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if( ( INS_OP( op ) == 0x01 && INS_RT( op ) == 0x01 ) || /* BGEZ */
|
||||
( INS_OP( op ) == 0x07 && INS_RT( op ) == 0x00 ) || /* BGTZ */
|
||||
( INS_OP( op ) == 0x05 && INS_RT( op ) == 0x00 ) ) /* BNE r,zero */
|
||||
{
|
||||
return (int)r;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* LOOP_VSYNC
|
||||
*************************************/
|
||||
|
||||
/*
|
||||
L+0 lw v0,16(sp) X+0 lui v0,hi
|
||||
L+1 nop X+1 lw v0,lo(v0)
|
||||
L+2 addiu v0,v0,-1 X+2 nop
|
||||
L+3 sw v0,16(sp) X+3 slt v0,v0,a0
|
||||
L+4 lw v0,16(sp) X+4 bnez v0,L
|
||||
L+5 nop X+5 nop
|
||||
L+6 bne v0,v1,X
|
||||
L+7 nop
|
||||
One pass is 14 instructions; the RAM word at hi:lo is in *global.
|
||||
*/
|
||||
static int loop_is_vsync( UINT32 l, UINT32 *global )
|
||||
{
|
||||
static const UINT32 head[ 8 ] = { 0x8fa20010, 0, 0x2442ffff, 0xafa20010, 0x8fa20010, 0, 0, 0 };
|
||||
UINT32 w[ 8 ], x, lui, lw, i;
|
||||
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
if( !loop_word( l + i * 4, &w[ i ] ) || ( i != 6 && w[ i ] != head[ i ] ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if( ( w[ 6 ] & 0xffff0000 ) != 0x14430000 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
x = loop_branch_target( w[ 6 ], l + 24 );
|
||||
if( x <= l + 28 || x - l > 64 * 4 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if( !loop_word( x, &lui ) || ( lui & 0xffff0000 ) != 0x3c020000 ||
|
||||
!loop_word( x + 4, &lw ) || ( lw & 0xffff0000 ) != 0x8c420000 ||
|
||||
!loop_word( x + 8, &w[ 0 ] ) || w[ 0 ] != 0 ||
|
||||
!loop_word( x + 12, &w[ 1 ] ) || w[ 1 ] != 0x0044102a ||
|
||||
!loop_word( x + 16, &w[ 2 ] ) || ( w[ 2 ] & 0xffff0000 ) != 0x14400000 || loop_branch_target( w[ 2 ], x + 16 ) != l ||
|
||||
!loop_word( x + 20, &w[ 3 ] ) || w[ 3 ] != 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
*global = ( ( lui & 0xffff ) << 16 ) + (INT32)(INT16)lw;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* LOOP_RNG
|
||||
*************************************/
|
||||
|
||||
/*
|
||||
L+0 jal F F+0 lw v1,o1(gp)
|
||||
L+1 nop F+1 nop
|
||||
L+2 lui v1,h2 F+2 sll v0,v1,2
|
||||
L+3 lw v1,o2(v1) F+3 addu v0,v0,v1
|
||||
L+4 lw a0,o3(gp) F+4 addiu v0,v0,1
|
||||
L+5 addiu v1,v1,1 F+5 sw v0,o1(gp)
|
||||
L+6.. v0 = v1 * 69069 F+6 jr ra
|
||||
L+16 lui at,h2 F+7 nop
|
||||
L+17 sw v0,o2(at)
|
||||
L+18 beqz a0,L
|
||||
L+19 lui v0,slot
|
||||
One pass is 28 instructions.
|
||||
*/
|
||||
static const UINT32 loop_rng_mul[ 10 ] =
|
||||
{
|
||||
0x00031140, 0x00431021, 0x00021080, 0x00431023, 0x00021080,
|
||||
0x00431023, 0x00021080, 0x00431021, 0x00021940, 0x00431021
|
||||
};
|
||||
|
||||
struct loop_rng
|
||||
{
|
||||
UINT32 x1, x2, flag; /* addresses: generator 1 (5x + 1), generator 2, flag */
|
||||
UINT32 at, v0; /* the values left in at and v0 */
|
||||
};
|
||||
|
||||
static int loop_is_rng( UINT32 l, struct loop_rng *g )
|
||||
{
|
||||
UINT32 w[ 20 ], f[ 8 ], fa, i, gp = mipscpu.r[ 28 ];
|
||||
|
||||
for( i = 0; i < 20; i++ )
|
||||
{
|
||||
if( !loop_word( l + i * 4, &w[ i ] ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if( INS_OP( w[ 0 ] ) != 0x03 || w[ 1 ] != 0 ||
|
||||
( w[ 2 ] & 0xffff0000 ) != 0x3c030000 || ( w[ 3 ] & 0xffff0000 ) != 0x8c630000 ||
|
||||
( w[ 4 ] & 0xffff0000 ) != 0x8f840000 || w[ 5 ] != 0x24630001 ||
|
||||
( w[ 16 ] & 0xffff0000 ) != 0x3c010000 || ( w[ 16 ] & 0xffff ) != ( w[ 2 ] & 0xffff ) ||
|
||||
( w[ 17 ] & 0xffff0000 ) != 0xac220000 || ( w[ 17 ] & 0xffff ) != ( w[ 3 ] & 0xffff ) ||
|
||||
( w[ 18 ] & 0xffff0000 ) != 0x10800000 || loop_branch_target( w[ 18 ], l + 72 ) != l ||
|
||||
( w[ 19 ] & 0xffff0000 ) != 0x3c020000 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
for( i = 0; i < 10; i++ )
|
||||
{
|
||||
if( w[ 6 + i ] != loop_rng_mul[ i ] )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
fa = ( ( l + 4 ) & 0xf0000000 ) | ( ( w[ 0 ] & 0x03ffffff ) << 2 );
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
if( !loop_word( fa + i * 4, &f[ i ] ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if( ( f[ 0 ] & 0xffff0000 ) != 0x8f830000 || f[ 1 ] != 0 || f[ 2 ] != 0x00031080 || f[ 3 ] != 0x00431021 ||
|
||||
f[ 4 ] != 0x24420001 || ( f[ 5 ] & 0xffff0000 ) != 0xaf820000 || ( f[ 5 ] & 0xffff ) != ( f[ 0 ] & 0xffff ) ||
|
||||
f[ 6 ] != 0x03e00008 || f[ 7 ] != 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
g->x1 = gp + (INT32)(INT16)f[ 0 ];
|
||||
g->x2 = ( ( w[ 2 ] & 0xffff ) << 16 ) + (INT32)(INT16)w[ 3 ];
|
||||
g->flag = gp + (INT32)(INT16)w[ 4 ];
|
||||
g->at = ( w[ 16 ] & 0xffff ) << 16;
|
||||
g->v0 = ( w[ 19 ] & 0xffff ) << 16;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* Skipping
|
||||
*************************************/
|
||||
|
||||
/* whole passes of 'pass' cycles that fit, leaving between 1 and 'pass' cycles */
|
||||
static INLINE UINT32 loop_passes( UINT32 pass )
|
||||
{
|
||||
if( mips_ICount <= (int)pass )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return ( (UINT32)mips_ICount - 1 ) / pass;
|
||||
}
|
||||
|
||||
static int loop_state_ok( void )
|
||||
{
|
||||
return loopskip_enabled && mipscpu.delayr == 0 && ( mipscpu.cp0r[ CP0_SR ] & ( SR_ISC | SR_KUC ) ) == 0;
|
||||
}
|
||||
|
||||
/* LOOP_COUNT, LOOP_VSYNC and LOOP_RNG at 'l' (the start of a pass) */
|
||||
static void loop_skip_at( UINT32 l )
|
||||
{
|
||||
UINT32 n, global;
|
||||
int r;
|
||||
struct loop_rng g;
|
||||
|
||||
if( !loop_state_ok() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( ( r = loop_is_count( l ) ) > 0 )
|
||||
{
|
||||
/* passes still taking the branch, counting the one starting now */
|
||||
UINT32 op = 0, v = mipscpu.r[ r ], left;
|
||||
loop_word( l, &op );
|
||||
if( INS_OP( op ) == 0x01 ) /* BGEZ: while v >= 0 */
|
||||
left = (INT32)v >= 0 ? v + 1 : 0;
|
||||
else /* BGTZ, BNE zero: while v > 0 */
|
||||
left = (INT32)v > 0 ? v : 0;
|
||||
n = loop_passes( 2 );
|
||||
if( left < 1 )
|
||||
return;
|
||||
if( n > left - 1 )
|
||||
n = left - 1;
|
||||
if( n == 0 )
|
||||
return;
|
||||
mipscpu.r[ r ] = v - n;
|
||||
mips_ICount -= n * 2;
|
||||
return;
|
||||
}
|
||||
|
||||
if( loop_is_vsync( l, &global ) )
|
||||
{
|
||||
UINT32 *counter = loop_data( mipscpu.r[ 29 ] + 16 ), value, until;
|
||||
if( counter == NULL || !loop_word( global, &value ) || global == mipscpu.r[ 29 ] + 16 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
/* the RAM word must keep the loop going */
|
||||
if( !( (INT32)value < (INT32)mipscpu.r[ 4 ] ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
/* passes before the counter reaches v1 (the timeout), that pass not included */
|
||||
until = *counter - mipscpu.r[ 3 ];
|
||||
n = loop_passes( 14 );
|
||||
if( until != 0 && n > until - 1 )
|
||||
{
|
||||
n = until - 1;
|
||||
}
|
||||
if( n == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
*counter -= n;
|
||||
mipscpu.r[ 2 ] = 1;
|
||||
mips_ICount -= n * 14;
|
||||
return;
|
||||
}
|
||||
|
||||
if( loop_is_rng( l, &g ) )
|
||||
{
|
||||
UINT32 *x1 = loop_data( g.x1 ), *x2 = loop_data( g.x2 ), flag, a, b, k, last = 0;
|
||||
if( x1 == NULL || x2 == NULL || !loop_word( g.flag, &flag ) || flag != 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
/* the three words must be distinct, so the stores leave the flag alone */
|
||||
if( g.x1 == g.x2 || g.flag == g.x1 || g.flag == g.x2 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
n = loop_passes( 28 );
|
||||
if( n == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
a = *x1;
|
||||
b = *x2;
|
||||
for( k = 0; k < n; k++ )
|
||||
{
|
||||
a = a * 5 + 1;
|
||||
last = b;
|
||||
b = ( b + 1 ) * 69069;
|
||||
}
|
||||
*x1 = a;
|
||||
*x2 = b;
|
||||
mipscpu.r[ 1 ] = g.at;
|
||||
mipscpu.r[ 2 ] = g.v0;
|
||||
mipscpu.r[ 3 ] = last + 1;
|
||||
mipscpu.r[ 4 ] = 0;
|
||||
mipscpu.r[ 31 ] = l + 8;
|
||||
mips_ICount -= n * 28;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* the kind of loop starting at 'l', for the recompiler (LOOP_PURE is not reported) */
|
||||
static int loop_kind( UINT32 l )
|
||||
{
|
||||
UINT32 global;
|
||||
struct loop_rng g;
|
||||
if( !loopskip_enabled )
|
||||
{
|
||||
return LOOP_NONE;
|
||||
}
|
||||
if( loop_is_count( l ) > 0 )
|
||||
{
|
||||
return LOOP_COUNT;
|
||||
}
|
||||
if( loop_is_vsync( l, &global ) )
|
||||
{
|
||||
return LOOP_VSYNC;
|
||||
}
|
||||
if( loop_is_rng( l, &g ) )
|
||||
{
|
||||
return LOOP_RNG;
|
||||
}
|
||||
return LOOP_NONE;
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* Interpreter hook
|
||||
*************************************/
|
||||
|
||||
/*
|
||||
Called by the interpreter when the PC moves back to 'l' (a taken
|
||||
backward branch or jump) from the instruction at 'from'. LOOP_PURE
|
||||
needs one whole pass seen first: from the previous arrival at 'l' to
|
||||
the loop's own branch, touching nothing but fast RAM (psx_slow_access).
|
||||
*/
|
||||
#define LOOP_CACHE_SIZE 1024
|
||||
|
||||
static struct
|
||||
{
|
||||
UINT32 pc, op, branch;
|
||||
UINT8 kind;
|
||||
} loop_cache[ LOOP_CACHE_SIZE ];
|
||||
|
||||
static UINT32 loop_pure_pc;
|
||||
|
||||
static void loop_arrive( UINT32 l, UINT32 from )
|
||||
{
|
||||
UINT32 op, idx = ( l >> 2 ) & ( LOOP_CACHE_SIZE - 1 );
|
||||
int armed = loop_pure_armed && loop_pure_pc == l && !psx_slow_access;
|
||||
|
||||
loop_pure_armed = 0;
|
||||
if( !loop_word( l, &op ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
if( loop_cache[ idx ].pc != l || loop_cache[ idx ].op != op )
|
||||
{
|
||||
UINT32 branch;
|
||||
loop_cache[ idx ].pc = l;
|
||||
loop_cache[ idx ].op = op;
|
||||
loop_cache[ idx ].kind = loop_is_pure( l, &branch ) ? LOOP_PURE : LOOP_NONE;
|
||||
loop_cache[ idx ].branch = branch;
|
||||
if( loop_cache[ idx ].kind == LOOP_NONE )
|
||||
{
|
||||
/* the other kinds are told by their first words */
|
||||
UINT32 global;
|
||||
struct loop_rng g;
|
||||
if( loop_is_count( l ) > 0 || loop_is_vsync( l, &global ) || loop_is_rng( l, &g ) )
|
||||
{
|
||||
loop_cache[ idx ].kind = LOOP_COUNT; /* "one of the checked kinds" */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch( loop_cache[ idx ].kind )
|
||||
{
|
||||
case LOOP_PURE:
|
||||
{
|
||||
UINT32 branch;
|
||||
/* a whole pass ran since the last arrival: back here from the slot of the loop's own branch */
|
||||
if( armed && from == loop_cache[ idx ].branch + 4 && loop_state_ok() &&
|
||||
loop_is_pure( l, &branch ) && branch == loop_cache[ idx ].branch )
|
||||
{
|
||||
UINT32 pass = ( branch + 8 - l ) / 4;
|
||||
mips_ICount -= loop_passes( pass ) * pass;
|
||||
}
|
||||
loop_pure_pc = l;
|
||||
loop_pure_armed = 1;
|
||||
psx_slow_access = 0;
|
||||
}
|
||||
break;
|
||||
case LOOP_COUNT:
|
||||
loop_skip_at( l );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* recompiled code: the skip at a loop head inside a block */
|
||||
#if PSXJIT_SUPPORTED
|
||||
static void SLJIT_FUNC loop_skip_helper( sljit_u32 l )
|
||||
{
|
||||
loop_skip_at( l );
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,67 @@
|
||||
/***************************************************************************
|
||||
|
||||
mn10200.h : Panasonic MN10200 (MN1020012A) emulator
|
||||
|
||||
Backported to the MAME 0.78 CPU interface (mame2003-plus) from current
|
||||
MAME (Olivier Galibert, R. Belmont, hap). The on-chip peripherals
|
||||
(interrupt controller, 8-bit timers, ports) are at 0xfc00-0xffff and
|
||||
handled inside the core; the four ports go to the driver through the
|
||||
callbacks below.
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _MN10200_H_
|
||||
#define _MN10200_H_
|
||||
|
||||
#include "osd_cpu.h"
|
||||
|
||||
enum
|
||||
{
|
||||
MN10200_PC = 1,
|
||||
MN10200_PSW,
|
||||
MN10200_MDR,
|
||||
MN10200_D0,
|
||||
MN10200_D1,
|
||||
MN10200_D2,
|
||||
MN10200_D3,
|
||||
MN10200_A0,
|
||||
MN10200_A1,
|
||||
MN10200_A2,
|
||||
MN10200_A3,
|
||||
MN10200_NMICR,
|
||||
MN10200_IAGR
|
||||
};
|
||||
|
||||
/* external interrupt pins */
|
||||
enum
|
||||
{
|
||||
MN10200_IRQ0 = 0,
|
||||
MN10200_IRQ1,
|
||||
MN10200_IRQ2,
|
||||
MN10200_IRQ3,
|
||||
|
||||
MN10200_MAX_EXT_IRQ
|
||||
};
|
||||
|
||||
typedef data8_t (*mn10200_port_read_func)(int port);
|
||||
typedef void (*mn10200_port_write_func)(int port, data8_t data);
|
||||
|
||||
/* hook the ports 0-3 to the driver (call before reset; NULL: open bus) */
|
||||
void mn10200_set_port_handlers(mn10200_port_read_func readfn, mn10200_port_write_func writefn);
|
||||
|
||||
extern int mn10200_ICount;
|
||||
|
||||
void mn10200_init(void);
|
||||
void mn10200_reset(void *param);
|
||||
void mn10200_exit(void);
|
||||
int mn10200_execute(int cycles);
|
||||
unsigned mn10200_get_context(void *dst);
|
||||
void mn10200_set_context(void *src);
|
||||
unsigned mn10200_get_reg(int regnum);
|
||||
void mn10200_set_reg(int regnum, unsigned val);
|
||||
void mn10200_set_irq_line(int irqline, int state);
|
||||
void mn10200_set_irq_callback(int (*callback)(int irqline));
|
||||
const char *mn10200_info(void *context, int regnum);
|
||||
unsigned mn10200_dasm(char *buffer, unsigned pc);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,75 @@
|
||||
/***************************************************************************
|
||||
|
||||
Namco C71 (TMS320C25 with Namco internal ROM) - fast DSP core
|
||||
|
||||
Written for Namco System 22 / Super System 22. The instruction
|
||||
semantics follow the TMS320C2x core of current MAME; the memory
|
||||
system is a page table set up by the driver, so the core does not
|
||||
go through the generic memory handlers.
|
||||
|
||||
Word addresses everywhere: program, data and I/O are 16-bit word
|
||||
spaces.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef C71_H
|
||||
#define C71_H
|
||||
|
||||
#include "osd_cpu.h"
|
||||
#include "cpuintrf.h"
|
||||
#include "memory.h"
|
||||
|
||||
/* interrupt lines (IFR bits) */
|
||||
#define C71_INT0 0
|
||||
#define C71_INT1 1
|
||||
#define C71_INT2 2
|
||||
#define C71_TINT 3
|
||||
#define C71_RINT 4
|
||||
#define C71_XINT 5
|
||||
|
||||
enum
|
||||
{
|
||||
C71_PC=1,
|
||||
C71_PFC, C71_STR0, C71_STR1, C71_IFR,
|
||||
C71_RPTC, C71_ACC, C71_PREG, C71_TREG,
|
||||
C71_AR0, C71_AR1, C71_AR2, C71_AR3,
|
||||
C71_AR4, C71_AR5, C71_AR6, C71_AR7,
|
||||
C71_STK0, C71_STK1, C71_STK2, C71_STK3,
|
||||
C71_STK4, C71_STK5, C71_STK6, C71_STK7,
|
||||
C71_DRR, C71_DXR, C71_TIM, C71_PRD,
|
||||
C71_IMR, C71_GREG
|
||||
};
|
||||
|
||||
/* the generic memory interface is not used: give the CPU empty maps */
|
||||
#define NAMCOC71_PGM_OFFSET 0
|
||||
|
||||
typedef data16_t (*c71_read_fn)(offs_t offset);
|
||||
typedef void (*c71_write_fn)(offs_t offset, data16_t data);
|
||||
|
||||
/* driver configuration, by CPU number; call from DRIVER_INIT or MACHINE_INIT */
|
||||
void c71_set_internal_rom(int cpunum, const data16_t *rom); /* 0x1000 words, native order (a CPU region) */
|
||||
void c71_map_data(int cpunum, offs_t start, offs_t end, data16_t *base, int writable);
|
||||
void c71_map_program(int cpunum, offs_t start, offs_t end, data16_t *base, int writable);
|
||||
void c71_set_data_handlers(int cpunum, c71_read_fn rd, c71_write_fn wr); /* everything not mapped */
|
||||
void c71_set_io(int cpunum, int port, c71_read_fn rd, c71_write_fn wr);
|
||||
void c71_set_bio(int cpunum, int (*bio)(void));
|
||||
void c71_set_serial(int cpunum, data16_t (*dr_in)(void), void (*dx_out)(data16_t));
|
||||
/* the DSP spins in [pc_start, pc_end] waiting for BIO or an interrupt: burn the timeslice there */
|
||||
void c71_set_idle_loop(int cpunum, int slot, UINT16 pc_start, UINT16 pc_end);
|
||||
|
||||
extern int c71_icount;
|
||||
|
||||
void c71_init(void);
|
||||
void c71_reset(void *param);
|
||||
void c71_exit(void);
|
||||
int c71_execute(int cycles);
|
||||
unsigned c71_get_context(void *dst);
|
||||
void c71_set_context(void *src);
|
||||
unsigned c71_get_reg(int regnum);
|
||||
void c71_set_reg(int regnum, unsigned val);
|
||||
void c71_set_irq_line(int irqline, int state);
|
||||
void c71_set_irq_callback(int (*callback)(int irqline));
|
||||
const char *c71_info(void *context, int regnum);
|
||||
unsigned c71_dasm(char *buffer, unsigned pc);
|
||||
|
||||
#endif
|
||||
@@ -122,6 +122,24 @@ static int no_interrupt;
|
||||
|
||||
static UINT8 parity_table[256];
|
||||
|
||||
#include "cpuintrf.h"
|
||||
|
||||
#define FETCHOP fetchop()
|
||||
|
||||
const UINT8* v25v35_decryptiontable = 0;
|
||||
|
||||
INLINE UINT8 fetchop(void)
|
||||
{
|
||||
UINT8 ret = cpu_readop((I.sregs[CS]<<4)+I.ip++);
|
||||
|
||||
if (I.MF == 1)
|
||||
if (v25v35_decryptiontable)
|
||||
{
|
||||
ret = v25v35_decryptiontable[ret];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
void nec_reset (void *param)
|
||||
|
||||
@@ -88,7 +88,6 @@ typedef enum { AL,AH,CL,CH,DL,DH,BL,BH,SPL,SPH,BPL,BPH,IXL,IXH,IYL,IYH } BREGS;
|
||||
#define write_port(port,val) cpu_writeport16(port,val)
|
||||
|
||||
#define FETCH (cpu_readop_arg((I.sregs[CS]<<4)+I.ip++))
|
||||
#define FETCHOP (cpu_readop((I.sregs[CS]<<4)+I.ip++))
|
||||
#define FETCHWORD(var) { var=cpu_readop_arg((((I.sregs[CS]<<4)+I.ip)))+(cpu_readop_arg((((I.sregs[CS]<<4)+I.ip+1)))<<8); I.ip+=2; }
|
||||
#define PUSH(val) { I.regs.w[SP]-=2; WriteWord((((I.sregs[SS]<<4)+I.regs.w[SP])),val); }
|
||||
#define POP(var) { var = ReadWord((((I.sregs[SS]<<4)+I.regs.w[SP]))); I.regs.w[SP]+=2; }
|
||||
|
||||
Loaded 100 of 1061 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user