mirror of
https://github.com/libretro/mame2003-plus-libretro.git
synced 2026-11-07 18:36:31 -10:00
Compare commits
1535
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71bf4f7fcc | ||
|
|
0742497860 | ||
|
|
02cbb28183 | ||
|
|
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
+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
|
||||
+395
-14
@@ -2,7 +2,7 @@
|
||||
|
||||
* 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
|
||||
|
||||
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 +10,71 @@ 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
|
||||
* Aladdin (bootleg of Megadrive version)
|
||||
* Angler Dangler (Deco Cassette)
|
||||
* Argus (Gottlieb, prototype)
|
||||
* Astropal
|
||||
* Asura Buster
|
||||
* Backfire!
|
||||
* Back Fire (Tecmo)
|
||||
* Bang Bang Busters
|
||||
* 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
|
||||
* 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
|
||||
* 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 +82,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 +110,110 @@ 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
|
||||
* 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)
|
||||
* 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 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
|
||||
* 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
|
||||
@@ -152,20 +223,31 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Sega Megaplay : Tecmo World Cup
|
||||
* Sega Sonic Bros (Japan, Prototype)
|
||||
* Sengoku 3
|
||||
* Shuihu Feng Yun Zhuan
|
||||
* Skater (Deco Cassette)
|
||||
* Skull Fang
|
||||
* 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)
|
||||
* Space Fever High Splitter
|
||||
* Space Launcher
|
||||
* Space Raider
|
||||
* Spectrum 2000 (Euro)
|
||||
* Squash
|
||||
* 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)
|
||||
* Super Monaco GP
|
||||
* Super Rider
|
||||
* Super Trio
|
||||
* SWAT Police
|
||||
@@ -179,16 +261,23 @@ 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
|
||||
* 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
|
||||
* Twinkle
|
||||
* Twinkle Tale (Bootleg Of Megadrive Version)
|
||||
* TX-1 (World, Japan rev. B and C)
|
||||
* Tylz
|
||||
* Ufo Senshi Yohko Chan
|
||||
* Varia Metal
|
||||
@@ -200,13 +289,16 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* 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
|
||||
|
||||
* 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
|
||||
* Battle Shark (Japan, Joystick)
|
||||
* Botanic (French version)
|
||||
* Bubble Bobble (prototype on tokio hardware)
|
||||
@@ -216,10 +308,14 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Crouching Tiger Hidden Dragon 2003
|
||||
* Crouching Tiger Hidden Dragon 2003 Super Plus
|
||||
* Crystal Castles (Joystick Version)
|
||||
* 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 *
|
||||
@@ -277,10 +373,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,9 +390,11 @@ 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
|
||||
@@ -317,10 +420,13 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Competition Golf Final Round (revision 3) - `compgolf`
|
||||
* Crater Raider - Romset `crater`
|
||||
* Crazy Climber 2 - Romset `cclimbr2`
|
||||
* Dark Edge - Romset `darkedge`
|
||||
* DD Crew - Romset `ddcrew`
|
||||
* 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 +435,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`
|
||||
@@ -363,14 +475,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`
|
||||
@@ -384,9 +501,11 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* 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`
|
||||
* 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 +516,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 +531,14 @@ 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`
|
||||
* 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 +546,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 +554,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 +583,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 +601,17 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
|
||||
## Games now with improved sound
|
||||
|
||||
* 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 +626,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 +648,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 +673,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 +685,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 +694,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 +702,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 +721,83 @@ 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
|
||||
* 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 +875,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 +898,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 +922,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 +1046,162 @@ 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]
|
||||
|
||||
@@ -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 ?=
|
||||
@@ -179,6 +181,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 +194,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 +207,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 +220,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 +244,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 +277,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 +308,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 +330,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 +388,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 +405,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 +462,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 +480,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 +533,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 +769,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 +823,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 +868,16 @@ else
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_ARMv6),1)
|
||||
CFLAGS += -DHAVE_ARMv6
|
||||
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 +886,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
|
||||
|
||||
+197
-24
@@ -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@
|
||||
@@ -165,22 +173,33 @@ CPUS+=Z8000@
|
||||
CPUS+=TMS32010@
|
||||
CPUS+=TMS32025@
|
||||
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 +260,7 @@ SOUNDS+=SEGAPCM@
|
||||
SOUNDS+=RF5C68@
|
||||
SOUNDS+=CEM3394@
|
||||
SOUNDS+=C140@
|
||||
SOUNDS+=C352@
|
||||
SOUNDS+=QSOUND@
|
||||
SOUNDS+=SAA1099@
|
||||
SOUNDS+=IREMGA20@
|
||||
@@ -365,7 +385,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 +442,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 +498,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/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,12 +522,13 @@ 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/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/segac2_vidhrdw.c $(CORE_DIR)/drivers/segac2.c \
|
||||
$(CORE_DIR)/drivers/stv.c $(CORE_DIR)/drivers/stvhacks.c $(CORE_DIR)/machine/stvcd.c \
|
||||
$(CORE_DIR)/machine/scudsp.c \
|
||||
@@ -803,6 +824,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 +1062,16 @@ 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)/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 +1118,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 +1382,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 +1475,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
|
||||
@@ -1822,6 +1877,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 +1950,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 +2035,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 +2108,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 +2649,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 +2810,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 +2836,22 @@ 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
|
||||
|
||||
ifeq ($(STATIC_LINKING),1)
|
||||
else
|
||||
SOURCES_C += \
|
||||
@@ -2697,23 +2876,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
|
||||
|
||||
|
||||
+2797
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,501 @@
|
||||
# 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.
|
||||
|
||||
## 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.
|
||||
+3
-2
@@ -5,7 +5,7 @@ CORE_DIR := $(ROOT_DIR)/src
|
||||
|
||||
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 +16,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.
+5451
-5045
File diff suppressed because it is too large.
Load diff
+1023
-421
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:
|
||||
|
||||
+29
-29
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
|
||||
+48402
-8125
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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
+2783
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,19 @@ 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);
|
||||
}
|
||||
|
||||
void konami_reset(void *param)
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,165 @@
|
||||
#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,
|
||||
|
||||
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
@@ -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
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
|
||||
@@ -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; }
|
||||
|
||||
+1306
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,53 @@
|
||||
/*****************************************************************************
|
||||
|
||||
NEC V25 (and V25+) CPU, see v25.c
|
||||
|
||||
license:BSD-3-Clause
|
||||
copyright-holders:Bryan McPhail, Alex W. Jackson
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef V25_H
|
||||
#define V25_H
|
||||
|
||||
#include "memory.h"
|
||||
#include "osd_cpu.h"
|
||||
|
||||
/* input lines, besides 0 (INT) and IRQ_LINE_NMI */
|
||||
#define V25_INPUT_LINE_INTP0 10
|
||||
#define V25_INPUT_LINE_INTP1 11
|
||||
#define V25_INPUT_LINE_INTP2 12
|
||||
#define V25_INPUT_LINE_POLL 20
|
||||
|
||||
enum
|
||||
{
|
||||
V25_PC=1, V25_IP, V25_AW, V25_CW, V25_DW, V25_BW, V25_SP, V25_BP, V25_IX, V25_IY,
|
||||
V25_DS1, V25_PS, V25_SS, V25_DS0, V25_PSW, V25_IDB, V25_PENDING
|
||||
};
|
||||
|
||||
extern int v25_ICount;
|
||||
|
||||
extern void v25_init(void);
|
||||
extern void v25_reset(void *param);
|
||||
extern void v25_exit(void);
|
||||
extern int v25_execute(int cycles);
|
||||
extern unsigned v25_get_context(void *dst);
|
||||
extern void v25_set_context(void *src);
|
||||
extern unsigned v25_get_reg(int regnum);
|
||||
extern void v25_set_reg(int regnum, unsigned val);
|
||||
extern void v25_set_irq_line(int irqline, int state);
|
||||
extern void v25_set_irq_callback(int (*callback)(int irqline));
|
||||
extern const char *v25_info(void *context, int regnum);
|
||||
extern unsigned v25_dasm(char *buffer, unsigned pc);
|
||||
|
||||
/* Configuration, from DRIVER_INIT (before the CPU is reset).
|
||||
The opcodes are decrypted with the table when the CPU is in secure
|
||||
mode (the default when there is a table). */
|
||||
extern void v25_set_decryption_table(int cpunum, const UINT8 *table);
|
||||
|
||||
/* the port pins: PT (input only), P0, P1 (upper 4 bits), P2 */
|
||||
extern void v25_set_port_handlers(int cpunum,
|
||||
read8_handler pt_in, read8_handler p0_in, read8_handler p1_in, read8_handler p2_in,
|
||||
write8_handler p0_out, write8_handler p1_out, write8_handler p2_out);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
+54
-33
@@ -145,6 +145,8 @@ typedef struct
|
||||
int dma_timer_active[2];
|
||||
|
||||
int is_slave, cpu_number;
|
||||
data16_t (*opcode_read)(offs_t pc);
|
||||
data32_t (*dma_read_hook)(UINT32 src, UINT32 dst, data32_t data, int size);
|
||||
} SH2;
|
||||
|
||||
int sh2_icount;
|
||||
@@ -152,8 +154,8 @@ static SH2 sh2;
|
||||
|
||||
/* Atrocious hack that makes the soldivid music correct*/
|
||||
|
||||
/*static const int div_tab[4] = { 3, 5, 7, 0 };*/
|
||||
static const int div_tab[4] = { 3, 5, 3, 0 };
|
||||
/* FRT clock: internal clock / 8, / 32, / 128, external */
|
||||
static const int div_tab[4] = { 3, 5, 7, 0 };
|
||||
|
||||
enum {
|
||||
ICF = 0x00800000,
|
||||
@@ -1143,22 +1145,20 @@ static INLINE void MAC_L(UINT32 m, UINT32 n)
|
||||
}
|
||||
if (sh2.sr & S)
|
||||
{
|
||||
Res0 = sh2.macl + Res0;
|
||||
if (sh2.macl > Res0)
|
||||
Res2++;
|
||||
Res2 += (sh2.mach & 0x0000ffff);
|
||||
if (((INT32) Res2 < 0) && (Res2 < 0xffff8000))
|
||||
/* full 64-bit accumulate, saturated to the 48-bit range with the sign of the product (as MAME) */
|
||||
UINT64 sum = ((((UINT64)sh2.mach) << 32) | sh2.macl) + ((((UINT64)Res2) << 32) | Res0);
|
||||
UINT32 sum_hi = (UINT32)(sum >> 32);
|
||||
|
||||
/* outside 0xffff800000000000 .. 0x00007fffffffffff */
|
||||
if (sum_hi > 0x00007fff && sum_hi < 0xffff8000)
|
||||
{
|
||||
Res2 = 0x00008000;
|
||||
Res0 = 0x00000000;
|
||||
if (fnLmL < 0)
|
||||
sum = ((UINT64)0xffff8000) << 32;
|
||||
else
|
||||
sum = (((UINT64)0x00007fff) << 32) | 0xffffffff;
|
||||
}
|
||||
else if (((INT32) Res2 > 0) && (Res2 > 0x00007fff))
|
||||
{
|
||||
Res2 = 0x00007fff;
|
||||
Res0 = 0xffffffff;
|
||||
}
|
||||
sh2.mach = Res2;
|
||||
sh2.macl = Res0;
|
||||
sh2.mach = (UINT32)(sum >> 32);
|
||||
sh2.macl = (UINT32)sum;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1208,12 +1208,19 @@ static INLINE void MAC_W(UINT32 m, UINT32 n)
|
||||
if (sh2.sr & S)
|
||||
{
|
||||
if (ans == 1)
|
||||
{
|
||||
/* both addends with the same sign: the sign change is an overflow */
|
||||
if (src == 0)
|
||||
{
|
||||
if (src == 0)
|
||||
sh2.macl = 0x7fffffff;
|
||||
if (src == 2)
|
||||
sh2.macl = 0x80000000;
|
||||
sh2.macl = 0x7fffffff;
|
||||
sh2.mach |= 1;
|
||||
}
|
||||
else if (src == 2)
|
||||
{
|
||||
sh2.macl = 0x80000000;
|
||||
sh2.mach |= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2307,7 +2314,11 @@ void sh2_reset(void *param)
|
||||
memset(sh2.m, 0, 0x200);
|
||||
|
||||
if(conf)
|
||||
{
|
||||
sh2.is_slave = conf->is_slave;
|
||||
sh2.opcode_read = conf->opcode_read;
|
||||
sh2.dma_read_hook = conf->dma_read_hook;
|
||||
}
|
||||
else
|
||||
sh2.is_slave = 0;
|
||||
|
||||
@@ -2343,12 +2354,12 @@ int sh2_execute(int cycles)
|
||||
|
||||
if (sh2.delay)
|
||||
{
|
||||
opcode = RW(sh2.delay & AM);
|
||||
opcode = sh2.opcode_read ? sh2.opcode_read(sh2.delay) : RW(sh2.delay & AM);
|
||||
change_pc32bedw(sh2.pc & AM);
|
||||
sh2.pc -= 2;
|
||||
}
|
||||
else
|
||||
opcode = RW(sh2.pc & AM);
|
||||
opcode = sh2.opcode_read ? sh2.opcode_read(sh2.pc) : RW(sh2.pc & AM);
|
||||
|
||||
CALL_MAME_DEBUG;
|
||||
|
||||
@@ -2407,9 +2418,15 @@ static void sh2_timer_resync(void)
|
||||
int divider = div_tab[(sh2.m[5] >> 8) & 3];
|
||||
UINT32 cur_time = cpunum_gettotalcycles(sh2.cpu_number);
|
||||
|
||||
if(divider)
|
||||
sh2.frc += (cur_time - sh2.frc_base) >> divider;
|
||||
sh2.frc_base = cur_time;
|
||||
UINT32 add = (cur_time - sh2.frc_base) >> divider;
|
||||
|
||||
/* keep the cycles that don't make a whole count yet (as MAME) */
|
||||
if (add > 0)
|
||||
{
|
||||
if (divider)
|
||||
sh2.frc += add;
|
||||
sh2.frc_base = cur_time;
|
||||
}
|
||||
}
|
||||
|
||||
static void sh2_timer_activate(void)
|
||||
@@ -2536,6 +2553,10 @@ static void sh2_dmac_callback(int dma)
|
||||
cpuintrf_pop_context();
|
||||
}
|
||||
|
||||
/* a unit read by the internal DMA, through the optional hook */
|
||||
#define DMA_READ(src, dst, data, size) \
|
||||
(sh2.dma_read_hook ? sh2.dma_read_hook((src), (dst), (data), (size)) : (data))
|
||||
|
||||
static void sh2_dmac_check(int dma)
|
||||
{
|
||||
if(sh2.m[0x63+4*dma] & sh2.m[0x6c] & 1)
|
||||
@@ -2575,7 +2596,7 @@ static void sh2_dmac_check(int dma)
|
||||
src --;
|
||||
if(incd == 2)
|
||||
dst --;
|
||||
cpu_writemem32bedw(dst, cpu_readmem32bedw(src));
|
||||
cpu_writemem32bedw(dst, DMA_READ(src, dst, cpu_readmem32bedw(src), 0));
|
||||
if(incs == 1)
|
||||
src ++;
|
||||
if(incd == 1)
|
||||
@@ -2591,7 +2612,7 @@ static void sh2_dmac_check(int dma)
|
||||
src -= 2;
|
||||
if(incd == 2)
|
||||
dst -= 2;
|
||||
cpu_writemem32bedw_word(dst, cpu_readmem32bedw_word(src));
|
||||
cpu_writemem32bedw_word(dst, DMA_READ(src, dst, cpu_readmem32bedw_word(src), 1));
|
||||
if(incs == 1)
|
||||
src += 2;
|
||||
if(incd == 1)
|
||||
@@ -2607,7 +2628,7 @@ static void sh2_dmac_check(int dma)
|
||||
src -= 4;
|
||||
if(incd == 2)
|
||||
dst -= 4;
|
||||
cpu_writemem32bedw_dword(dst, cpu_readmem32bedw_dword(src));
|
||||
cpu_writemem32bedw_dword(dst, DMA_READ(src, dst, cpu_readmem32bedw_dword(src), 2));
|
||||
if(incs == 1)
|
||||
src += 4;
|
||||
if(incd == 1)
|
||||
@@ -2622,10 +2643,10 @@ static void sh2_dmac_check(int dma)
|
||||
{
|
||||
if(incd == 2)
|
||||
dst -= 16;
|
||||
cpu_writemem32bedw_dword(dst, cpu_readmem32bedw_dword(src));
|
||||
cpu_writemem32bedw_dword(dst+4, cpu_readmem32bedw_dword(src+4));
|
||||
cpu_writemem32bedw_dword(dst+8, cpu_readmem32bedw_dword(src+8));
|
||||
cpu_writemem32bedw_dword(dst+12, cpu_readmem32bedw_dword(src+12));
|
||||
cpu_writemem32bedw_dword(dst, DMA_READ(src, dst, cpu_readmem32bedw_dword(src), 2));
|
||||
cpu_writemem32bedw_dword(dst+4, DMA_READ(src+4, dst+4, cpu_readmem32bedw_dword(src+4), 2));
|
||||
cpu_writemem32bedw_dword(dst+8, DMA_READ(src+8, dst+8, cpu_readmem32bedw_dword(src+8), 2));
|
||||
cpu_writemem32bedw_dword(dst+12, DMA_READ(src+12, dst+12, cpu_readmem32bedw_dword(src+12), 2));
|
||||
src += 16;
|
||||
if(incd == 1)
|
||||
dst += 16;
|
||||
@@ -2739,7 +2760,7 @@ WRITE32_HANDLER( sh2_internal_w )
|
||||
{
|
||||
INT64 a = sh2.m[0x45] | ((UINT64)(sh2.m[0x44]) << 32);
|
||||
INT64 b = sh2.m[0x40];
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "SH2 #%d div+mod %lld/%lld\n", cpu_getactivecpu(), a, b);
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "SH2 #%d div+mod %08x%08x/%08x\n", cpu_getactivecpu(), sh2.m[0x44], sh2.m[0x45], sh2.m[0x40]);
|
||||
if (b)
|
||||
{
|
||||
INT64 q = a / b;
|
||||
|
||||
@@ -60,6 +60,13 @@ extern int sh2_icount; /* cycle count */
|
||||
struct sh2_config
|
||||
{
|
||||
int is_slave;
|
||||
/* optional: opcode fetch, for CPUs that decrypt opcodes (CPS-3);
|
||||
NULL fetches opcodes as data */
|
||||
data16_t (*opcode_read)(offs_t pc);
|
||||
/* optional: called for each unit an internal DMA transfer reads, can
|
||||
change the data (CPS-3: the DMA bypasses the decryption);
|
||||
size 0 byte, 1 word, 2 long */
|
||||
data32_t (*dma_read_hook)(UINT32 src, UINT32 dst, data32_t data, int size);
|
||||
};
|
||||
|
||||
extern void sh2_init(void);
|
||||
|
||||
+3127
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,87 @@
|
||||
/*****************************************************************************
|
||||
|
||||
sh3.h
|
||||
|
||||
Hitachi SH-3 (SH7709S) CPU core, from current MAME (sh.cpp, sh4.cpp,
|
||||
sh3comn.cpp, sh4comn.cpp, sh4tmu.cpp, sh7709s.cpp: R. Belmont,
|
||||
David Haywood, Jesus Ramos and the other authors of those files).
|
||||
|
||||
Big endian, 32-bit data bus (32bedw). No FPU and no MMU (current MAME
|
||||
doesn't emulate the SH-3 MMU either). The internal registers of the
|
||||
SH7709S are emulated in the core; the I/O ports call the driver.
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _SH3_H
|
||||
#define _SH3_H
|
||||
|
||||
#include "cpuintrf.h"
|
||||
#include "osd_cpu.h"
|
||||
|
||||
/* the external interrupt lines IRL0-IRL3 (current MAME: SH4_IRL0-SH4_IRL3) */
|
||||
#define SH3_IRL0 0
|
||||
#define SH3_IRL1 1
|
||||
#define SH3_IRL2 2
|
||||
#define SH3_IRL3 3
|
||||
|
||||
/* the I/O ports, for the port callbacks */
|
||||
enum
|
||||
{
|
||||
SH3_PORT_A = 0, SH3_PORT_B, SH3_PORT_C, SH3_PORT_D, SH3_PORT_E, SH3_PORT_F,
|
||||
SH3_PORT_G, SH3_PORT_H, SH3_PORT_J, SH3_PORT_K, SH3_PORT_L, SH3_PORT_COUNT
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SH3_PC=1, SH3_SR, SH3_PR, SH3_GBR, SH3_VBR, SH3_MACH, SH3_MACL,
|
||||
SH3_R0, SH3_R1, SH3_R2, SH3_R3, SH3_R4, SH3_R5, SH3_R6, SH3_R7,
|
||||
SH3_R8, SH3_R9, SH3_R10, SH3_R11, SH3_R12, SH3_R13, SH3_R14, SH3_R15,
|
||||
SH3_SSR, SH3_SPC, SH3_EA
|
||||
};
|
||||
|
||||
struct sh3_config
|
||||
{
|
||||
/* the SH7709S cache and bus timing of current MAME (sh7709s.cpp, made
|
||||
for the CV1000): data accesses and cache misses cost cycles */
|
||||
int cache_timing;
|
||||
/* the clock of the peripheral modules (TMU), Hz */
|
||||
int pm_clock;
|
||||
/* the I/O ports (SH3_PORT_x); NULL reads 0 */
|
||||
data8_t (*port_r)(int port);
|
||||
void (*port_w)(int port, data8_t data);
|
||||
};
|
||||
|
||||
extern int sh3_ICount;
|
||||
|
||||
/* the fast memory: plain RAM or ROM at base (an array of data32_t, as the
|
||||
memory system keeps a 32-bit big-endian space), read, written and fetched
|
||||
without the memory handlers; physical addresses (29 bits). Set from
|
||||
DRIVER_INIT, emptied at the CPU init */
|
||||
#define SH3_FASTRAM_MAX 4
|
||||
void sh3_set_fastram(UINT32 start, UINT32 end, int readonly, data32_t *base);
|
||||
|
||||
/* the cache and bus timing of an access done by a memory handler (current
|
||||
MAME: sh7709s_device::update_access_cycles) */
|
||||
void sh3_update_access_cycles(UINT32 address, int write);
|
||||
|
||||
/* the recompiler (sh3jit.c): available on this host, and on/off (off by default) */
|
||||
int sh3_jit_available(void);
|
||||
void sh3_set_jit(int enable);
|
||||
|
||||
/* the total number of cycles run */
|
||||
UINT32 sh3_total_cycles_lo(void);
|
||||
|
||||
void sh3_init(void);
|
||||
void sh3_reset(void *param);
|
||||
void sh3_exit(void);
|
||||
int sh3_execute(int cycles);
|
||||
unsigned sh3_get_context(void *dst);
|
||||
void sh3_set_context(void *src);
|
||||
unsigned sh3_get_reg(int regnum);
|
||||
void sh3_set_reg(int regnum, unsigned val);
|
||||
void sh3_set_irq_line(int irqline, int state);
|
||||
void sh3_set_irq_callback(int (*callback)(int irqline));
|
||||
const char *sh3_info(void *context, int regnum);
|
||||
unsigned sh3_dasm(char *buffer, unsigned pc);
|
||||
|
||||
#endif
|
||||
Loaded 100 of 1002 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user