mirror of
https://github.com/libretro/mame2003-plus-libretro.git
synced 2026-11-07 12:28:04 -10:00
Compare commits
1493
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86676fd030 | ||
|
|
101a3c4615 | ||
|
|
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
|
||||
+374
-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,46 +10,64 @@ 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
|
||||
* 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)
|
||||
* Deluxe 5
|
||||
* Denjin Makai
|
||||
* Deer Hunting
|
||||
* Deroon DeroDero
|
||||
* Dice - The Dice Game
|
||||
* Diet Go Go
|
||||
* Digger (CVS)
|
||||
* Dolmen
|
||||
@@ -59,17 +77,22 @@ 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
|
||||
* 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 +104,102 @@ 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)
|
||||
* 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
|
||||
* Multi Champ Deluxe * Mature *
|
||||
* 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
|
||||
* 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
|
||||
* 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 +209,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 +247,22 @@ 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)
|
||||
* Tylz
|
||||
* Ufo Senshi Yohko Chan
|
||||
* Varia Metal
|
||||
@@ -200,8 +274,10 @@ 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
|
||||
|
||||
@@ -216,10 +292,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 +357,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
|
||||
@@ -290,8 +375,9 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Midnight Resistance (joystick hack bootleg)
|
||||
* Mortal Kombat 2 Plus Beta 2
|
||||
* 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 +403,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 +418,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 +458,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 +484,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 +499,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 +514,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 +529,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 +537,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 +566,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 +584,16 @@ 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
|
||||
* Athena
|
||||
* Bandito
|
||||
* Big Event Golf
|
||||
* Bosconian
|
||||
* Burgler X
|
||||
* Congo Bongo
|
||||
* Cookie & Bibi 2
|
||||
* Crazy Balloon
|
||||
* Destination Earth - (Added lrescue.zip sample support)
|
||||
@@ -492,9 +608,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 +630,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 +655,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 +667,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 +676,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 +684,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 +703,81 @@ 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
|
||||
|
||||
* 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 +855,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 +878,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 +902,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 +1026,161 @@ 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]
|
||||
|
||||
@@ -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,11 @@ 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
|
||||
|
||||
# Required for RZIP support in cheat.c
|
||||
CFLAGS += -DHAVE_ZLIB
|
||||
|
||||
@@ -834,8 +860,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 +878,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
|
||||
|
||||
+159
-24
@@ -68,6 +68,7 @@ SOURCES_C += \
|
||||
$(CORE_DIR)/x86drc.c
|
||||
|
||||
SOURCES_C += \
|
||||
$(CORE_DIR)/machine/fd1089.c \
|
||||
$(CORE_DIR)/machine/6522via.c \
|
||||
$(CORE_DIR)/machine/6532riot.c \
|
||||
$(CORE_DIR)/machine/6821pia.c \
|
||||
@@ -94,7 +95,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)
|
||||
@@ -132,6 +134,7 @@ CPUS+=I8039@
|
||||
CPUS+=I8048@
|
||||
CPUS+=N7751@
|
||||
CPUS+=I8X41@
|
||||
CPUS+=I8051@
|
||||
CPUS+=M6800@
|
||||
CPUS+=M6801@
|
||||
CPUS+=M6802@
|
||||
@@ -165,17 +168,26 @@ 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+=MN10200@
|
||||
CPUS+=M37702@
|
||||
CPUS+=ASAP@
|
||||
CPUS+=UPD7810@
|
||||
CPUS+=UPD7807@
|
||||
CPUS+=ARM@
|
||||
CPUS+=ARM7@
|
||||
CPUS+=JAGUAR@
|
||||
CPUS+=R3000@
|
||||
CPUS+=R4600@
|
||||
@@ -241,6 +253,7 @@ SOUNDS+=SEGAPCM@
|
||||
SOUNDS+=RF5C68@
|
||||
SOUNDS+=CEM3394@
|
||||
SOUNDS+=C140@
|
||||
SOUNDS+=C352@
|
||||
SOUNDS+=QSOUND@
|
||||
SOUNDS+=SAA1099@
|
||||
SOUNDS+=IREMGA20@
|
||||
@@ -365,7 +378,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 +435,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 +491,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 +515,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 \
|
||||
@@ -1040,9 +1054,13 @@ 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)/machine/sega315_5881.c $(CORE_DIR)/machine/sega315_5838.c \
|
||||
$(CORE_DIR)/drivers/calorie.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
|
||||
|
||||
|
||||
|
||||
@@ -1089,6 +1107,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
|
||||
@@ -1429,6 +1455,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 +1857,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 +1930,33 @@ 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 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 +2006,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
|
||||
@@ -2504,6 +2611,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 +2772,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 +2798,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 +2838,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
|
||||
|
||||
|
||||
+2787
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,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.
+5393
-5045
File diff suppressed because it is too large.
Load diff
+827
-333
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
|
||||
|
||||
@@ -3270,7 +3272,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 +5934,7 @@ offtwallc:
|
||||
0:3fee2e:37:00:49
|
||||
|
||||
bublbobl:
|
||||
bublbobr:
|
||||
bub68705:
|
||||
bublboblr:
|
||||
bublboblr1:
|
||||
|
||||
+24
-24
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
|
||||
+46361
-7798
File diff suppressed because it is too large.
Load diff
+5
-5
@@ -2295,10 +2295,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 +2312,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))
|
||||
@@ -3367,7 +3367,7 @@ 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 */
|
||||
|
||||
/* switch off the type */
|
||||
switch (list->type & ~OVERLAY_FLAG_MASK)
|
||||
|
||||
+1
-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;
|
||||
|
||||
+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;
|
||||
|
||||
|
||||
+163
-158
@@ -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
|
||||
@@ -1051,7 +1026,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 +1111,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 +1128,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;
|
||||
@@ -1473,10 +1428,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 +1514,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 +1599,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 +1613,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 +1659,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 +1670,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 +1706,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 +1735,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 +1799,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 +1816,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 +1985,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))
|
||||
|
||||
+29
-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)
|
||||
@@ -441,7 +457,7 @@ 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 +568,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
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));
|
||||
}
|
||||
+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
@@ -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,17 @@ 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);
|
||||
|
||||
#ifdef MAME_DEBUG
|
||||
extern unsigned DasmMIPS(char *buff, unsigned _pc);
|
||||
#endif
|
||||
|
||||
+1331
-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; }
|
||||
|
||||
+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);
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,98 @@
|
||||
/***************************************************************************
|
||||
|
||||
Analog Devices ADSP-21062 "SHARC", from current MAME
|
||||
(src/devices/cpu/sharc, copyright Ville Linde, BSD-3-Clause),
|
||||
translated to C for MAME 2003. Interpreter only (no recompiler).
|
||||
|
||||
The internal memory (two 32K x 32-bit blocks, with the 48-bit program
|
||||
and 16-bit short-word views) and the IOP registers live inside the
|
||||
core. External data memory (and external program memory, if any)
|
||||
is reached through driver callbacks in the config passed to the CPU
|
||||
with MDRV_CPU_CONFIG; the mame2003 memory system is not used.
|
||||
|
||||
Only one SHARC per machine is supported (the state is static).
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef SHARC_H
|
||||
#define SHARC_H
|
||||
|
||||
#include "osd_cpu.h"
|
||||
|
||||
enum
|
||||
{
|
||||
SHARC_BOOT_MODE_EPROM = 0,
|
||||
SHARC_BOOT_MODE_HOST,
|
||||
SHARC_BOOT_MODE_LINK,
|
||||
SHARC_BOOT_MODE_NOBOOT
|
||||
};
|
||||
|
||||
/* interrupt lines for set_irq_line (IRQ0-2 pins) */
|
||||
enum
|
||||
{
|
||||
SHARC_IRQ0 = 0,
|
||||
SHARC_IRQ1 = 1,
|
||||
SHARC_IRQ2 = 2
|
||||
};
|
||||
|
||||
/* register numbers for get_reg / set_reg (also CPU_INFO_REG + n) */
|
||||
enum
|
||||
{
|
||||
SHARC_PC = 1, SHARC_PCSTK, SHARC_PCSTKP, SHARC_LSTKP, SHARC_FADDR, SHARC_DADDR,
|
||||
SHARC_MODE1, SHARC_MODE2, SHARC_ASTAT, SHARC_STKY, SHARC_IRPTL, SHARC_IMASK,
|
||||
SHARC_USTAT1, SHARC_USTAT2, SHARC_LCNTR, SHARC_CURLCNTR, SHARC_STSTKP,
|
||||
SHARC_R0,
|
||||
SHARC_R15 = SHARC_R0 + 15,
|
||||
SHARC_I0,
|
||||
SHARC_I15 = SHARC_I0 + 15
|
||||
};
|
||||
|
||||
struct sharc_config
|
||||
{
|
||||
int boot_mode; /* SHARC_BOOT_MODE_xxx (MAME default: HOST) */
|
||||
UINT32 (*data_r)(UINT32 address); /* external DM, 32-bit words, word address */
|
||||
void (*data_w)(UINT32 address, UINT32 data);
|
||||
void (*flag_out)(int flag, int state); /* FLAG0-3 outputs, may be NULL */
|
||||
/* optional, may be NULL (unmapped: reads 0): external program memory,
|
||||
48-bit words in the low bits, word address */
|
||||
UINT64 (*pgm_r)(UINT32 address);
|
||||
void (*pgm_w)(UINT32 address, UINT64 data);
|
||||
};
|
||||
|
||||
extern int sharc_icount;
|
||||
|
||||
/* CPU interface */
|
||||
extern void sharc_init(void);
|
||||
extern void sharc_reset(void *param);
|
||||
extern void sharc_exit(void);
|
||||
extern int sharc_execute(int cycles);
|
||||
extern unsigned sharc_get_context(void *dst);
|
||||
extern void sharc_set_context(void *src);
|
||||
extern unsigned sharc_get_reg(int regnum);
|
||||
extern void sharc_set_reg(int regnum, unsigned val);
|
||||
extern void sharc_set_irq_line(int irqline, int state);
|
||||
extern void sharc_set_irq_callback(int (*callback)(int irqline));
|
||||
extern const char *sharc_info(void *context, int regnum);
|
||||
extern unsigned sharc_dasm(char *buffer, unsigned pc);
|
||||
|
||||
/* helpers acting on the (single) SHARC; safe to call while another CPU
|
||||
is executing, e.g. from the host CPU's memory handlers */
|
||||
|
||||
/* MAME external_iop_write: host write to an IOP register */
|
||||
extern void sharc_external_iop_write(UINT32 address, UINT32 data);
|
||||
/* MAME external_dma_write: host write to the external port DMA buffer
|
||||
(host boot); with 16/48 packing, address % 3 selects the 16-bit piece */
|
||||
extern void sharc_external_dma_write(UINT32 address, UINT64 data);
|
||||
/* MAME set_flag_input: FLAG0-3 pins configured as inputs */
|
||||
extern void sharc_set_flag_input(int flag_num, int state);
|
||||
/* MAME write_stall: while asserted, the core does not execute */
|
||||
extern void sharc_write_stall(int state);
|
||||
|
||||
/* to be called from a data_r/data_w callback that cannot complete now
|
||||
(FIFO empty/full): the access must not be committed by the driver
|
||||
(the value returned by data_r is ignored); the core ends the
|
||||
timeslice and executes the same instruction again next time, with no
|
||||
side effects committed. A stalled DMA transfer cycle is retried. */
|
||||
extern void sharc_stall(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,335 @@
|
||||
/***************************************************************************
|
||||
|
||||
ADSP-21062 SHARC DMA operations, from current MAME
|
||||
(src/devices/cpu/sharc/sharcdma.hxx, copyright Ville Linde,
|
||||
BSD-3-Clause), translated to C for MAME 2003.
|
||||
Included from sharc.c, not compiled on its own.
|
||||
|
||||
Only the interpreter paths are translated: MAME uses the DMA timer
|
||||
(sharc_dma_callback) with the recompiler only; the interpreter
|
||||
transfers one DMA word per instruction (dma_run_cycle).
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#define DMA_PMODE_NO_PACKING 0
|
||||
#define DMA_PMODE_16_32 1
|
||||
#define DMA_PMODE_16_48 2
|
||||
#define DMA_PMODE_32_48 3
|
||||
#define DMA_PMODE_8_48 4
|
||||
|
||||
static void schedule_chained_dma_op(int channel, UINT32 dma_chain_ptr, int chained_direction)
|
||||
{
|
||||
UINT32 op_ptr = 0x20000 + (dma_chain_ptr & 0x1ffff);
|
||||
|
||||
UINT32 int_index = dm_read32(op_ptr - 0);
|
||||
UINT32 int_modifier = dm_read32(op_ptr - 1);
|
||||
UINT32 int_count = dm_read32(op_ptr - 2);
|
||||
UINT32 chain_ptr = dm_read32(op_ptr - 3);
|
||||
/*UINT32 gen_purpose = dm_read32(op_ptr - 4);*/
|
||||
UINT32 ext_index = dm_read32(op_ptr - 5);
|
||||
UINT32 ext_modifier = dm_read32(op_ptr - 6);
|
||||
UINT32 ext_count = dm_read32(op_ptr - 7);
|
||||
|
||||
if (m_core->dma_op[channel].active)
|
||||
{
|
||||
/* MAME: fatal error */
|
||||
sharc_error("SHARC: schedule_chained_dma_op: DMA operation already scheduled at %08X!\n", m_core->pc);
|
||||
}
|
||||
|
||||
if (chained_direction) /* Transmit to external */
|
||||
{
|
||||
m_core->dma_op[channel].dst = ext_index;
|
||||
m_core->dma_op[channel].dst_modifier = (INT32)ext_modifier;
|
||||
m_core->dma_op[channel].dst_count = (INT32)ext_count;
|
||||
m_core->dma_op[channel].src = int_index;
|
||||
m_core->dma_op[channel].src_modifier = (INT32)int_modifier;
|
||||
m_core->dma_op[channel].src_count = (INT32)int_count;
|
||||
}
|
||||
else /* Receive from external */
|
||||
{
|
||||
m_core->dma_op[channel].src = ext_index;
|
||||
m_core->dma_op[channel].src_modifier = (INT32)ext_modifier;
|
||||
m_core->dma_op[channel].src_count = (INT32)ext_count;
|
||||
m_core->dma_op[channel].dst = int_index;
|
||||
m_core->dma_op[channel].dst_modifier = (INT32)int_modifier;
|
||||
m_core->dma_op[channel].dst_count = (INT32)int_count;
|
||||
}
|
||||
|
||||
m_core->dma_op[channel].pmode = 0;
|
||||
m_core->dma_op[channel].chain_ptr = chain_ptr;
|
||||
m_core->dma_op[channel].chained_direction = chained_direction;
|
||||
|
||||
m_core->dma_op[channel].chained = 1;
|
||||
m_core->dma_op[channel].active = 1;
|
||||
|
||||
/* enable busy flag */
|
||||
m_core->dma_status |= (1 << channel);
|
||||
}
|
||||
|
||||
static void schedule_dma_op(int channel, UINT32 src, UINT32 dst, int src_modifier, int dst_modifier, int src_count, int dst_count, int pmode)
|
||||
{
|
||||
if (m_core->dma_op[channel].active)
|
||||
{
|
||||
/* MAME: fatal error */
|
||||
sharc_error("SHARC: schedule_dma_op: DMA operation already scheduled at %08X!\n", m_core->pc);
|
||||
}
|
||||
|
||||
m_core->dma_op[channel].src = src;
|
||||
m_core->dma_op[channel].dst = dst;
|
||||
m_core->dma_op[channel].src_modifier = src_modifier;
|
||||
m_core->dma_op[channel].dst_modifier = dst_modifier;
|
||||
m_core->dma_op[channel].src_count = src_count;
|
||||
m_core->dma_op[channel].dst_count = dst_count;
|
||||
m_core->dma_op[channel].pmode = pmode;
|
||||
m_core->dma_op[channel].chain_ptr = 0;
|
||||
|
||||
m_core->dma_op[channel].chained = 0;
|
||||
m_core->dma_op[channel].active = 1;
|
||||
|
||||
/* enable busy flag */
|
||||
m_core->dma_status |= (1 << channel);
|
||||
}
|
||||
|
||||
/* one DMA transfer; returns 1 if a driver callback stalled it (port:
|
||||
nothing is committed then, and the same transfer is retried later) */
|
||||
static int dma_run_cycle(int channel)
|
||||
{
|
||||
if (m_core->dma_status & (1 << channel))
|
||||
{
|
||||
UINT32 src = m_core->dma_op[channel].src;
|
||||
UINT32 dst = m_core->dma_op[channel].dst;
|
||||
int src_modifier = m_core->dma_op[channel].src_modifier;
|
||||
int dst_modifier = m_core->dma_op[channel].dst_modifier;
|
||||
int src_count = m_core->dma_op[channel].src_count;
|
||||
int pmode = m_core->dma_op[channel].pmode;
|
||||
|
||||
m_core->stalled = 0;
|
||||
|
||||
switch (pmode)
|
||||
{
|
||||
case DMA_PMODE_NO_PACKING:
|
||||
{
|
||||
UINT32 data = dm_read32(src);
|
||||
if (m_core->stalled) break;
|
||||
dm_write32(dst, data);
|
||||
src += src_modifier;
|
||||
dst += dst_modifier;
|
||||
src_count--;
|
||||
break;
|
||||
}
|
||||
case DMA_PMODE_16_32:
|
||||
{
|
||||
UINT32 data = (dm_read32(src + 0) & 0xffff) << 16;
|
||||
data |= dm_read32(src + 1) & 0xffff;
|
||||
if (m_core->stalled) break;
|
||||
|
||||
dm_write32(dst, data);
|
||||
src += src_modifier * 2;
|
||||
dst += dst_modifier;
|
||||
src_count -= 2;
|
||||
break;
|
||||
}
|
||||
case DMA_PMODE_8_48:
|
||||
{
|
||||
UINT64 data = ((UINT64)(dm_read32(src + 0) & 0xff) << 0);
|
||||
data |= ((UINT64)(dm_read32(src + 1) & 0xff) << 8);
|
||||
data |= ((UINT64)(dm_read32(src + 2) & 0xff) << 16);
|
||||
data |= ((UINT64)(dm_read32(src + 3) & 0xff) << 24);
|
||||
data |= ((UINT64)(dm_read32(src + 4) & 0xff) << 32);
|
||||
data |= ((UINT64)(dm_read32(src + 5) & 0xff) << 40);
|
||||
if (m_core->stalled) break;
|
||||
|
||||
pm_write48(dst, data);
|
||||
src += src_modifier * 6;
|
||||
dst += dst_modifier;
|
||||
src_count -= 6;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* MAME: fatal error */
|
||||
sharc_error("SHARC: dma_op: unimplemented packing mode %d\n", pmode);
|
||||
/* drop the transfer instead of looping on it forever */
|
||||
src_count = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_core->stalled)
|
||||
{
|
||||
m_core->stalled = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
m_core->dma_op[channel].src_count = src_count;
|
||||
m_core->dma_op[channel].src = src;
|
||||
m_core->dma_op[channel].dst = dst;
|
||||
|
||||
if (src_count <= 0)
|
||||
{
|
||||
/* clear busy flag */
|
||||
m_core->dma_status &= ~(1 << channel);
|
||||
|
||||
m_core->dma_op[channel].active = 0;
|
||||
|
||||
/* raise interrupt if
|
||||
* non-chained DMA
|
||||
* chained-DMA with PCI set in the next chain pointer */
|
||||
if (!m_core->dma_op[channel].chained || (m_core->dma_op[channel].chained && (m_core->dma_op[channel].chain_ptr & 0x20000)))
|
||||
{
|
||||
m_core->irptl |= (1 << (channel + 10));
|
||||
|
||||
/* DMA interrupt */
|
||||
if (m_core->imask & (1 << (channel + 10)))
|
||||
{
|
||||
m_core->irq_pending |= 1 << (channel + 10);
|
||||
}
|
||||
}
|
||||
|
||||
/* schedule chained op if chaining */
|
||||
if ((m_core->dma_op[channel].chain_ptr & 0x1ffff) != 0)
|
||||
{
|
||||
schedule_chained_dma_op(channel, m_core->dma_op[channel].chain_ptr, m_core->dma_op[channel].chained_direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* whole transfer at once (used by the EPROM boot) */
|
||||
static void dma_op(int channel)
|
||||
{
|
||||
int i;
|
||||
UINT32 src = m_core->dma_op[channel].src;
|
||||
UINT32 dst = m_core->dma_op[channel].dst;
|
||||
int src_modifier = m_core->dma_op[channel].src_modifier;
|
||||
int dst_modifier = m_core->dma_op[channel].dst_modifier;
|
||||
int src_count = m_core->dma_op[channel].src_count;
|
||||
int pmode = m_core->dma_op[channel].pmode;
|
||||
|
||||
switch (pmode)
|
||||
{
|
||||
case DMA_PMODE_NO_PACKING:
|
||||
{
|
||||
for (i=0; i < src_count; i++)
|
||||
{
|
||||
UINT32 data = dm_read32(src);
|
||||
dm_write32(dst, data);
|
||||
src += src_modifier;
|
||||
dst += dst_modifier;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DMA_PMODE_16_32:
|
||||
{
|
||||
int length = src_count/2;
|
||||
for (i=0; i < length; i++)
|
||||
{
|
||||
UINT32 data = (dm_read32(src+0) & 0xffff) << 16;
|
||||
data |= dm_read32(src+1) & 0xffff;
|
||||
|
||||
dm_write32(dst, data);
|
||||
src += src_modifier * 2;
|
||||
dst += dst_modifier;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DMA_PMODE_8_48:
|
||||
{
|
||||
int length = src_count/6;
|
||||
for (i=0; i < length; i++)
|
||||
{
|
||||
UINT64 data = ((UINT64)(dm_read32(src+0) & 0xff) << 0);
|
||||
data |= ((UINT64)(dm_read32(src+1) & 0xff) << 8);
|
||||
data |= ((UINT64)(dm_read32(src+2) & 0xff) << 16);
|
||||
data |= ((UINT64)(dm_read32(src+3) & 0xff) << 24);
|
||||
data |= ((UINT64)(dm_read32(src+4) & 0xff) << 32);
|
||||
data |= ((UINT64)(dm_read32(src+5) & 0xff) << 40);
|
||||
|
||||
pm_write48(dst, data);
|
||||
src += src_modifier * 6;
|
||||
dst += dst_modifier;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* MAME: fatal error */
|
||||
sharc_error("SHARC: dma_op: unimplemented packing mode %d\n", pmode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (channel == 6)
|
||||
{
|
||||
m_core->irptl |= (1 << (channel+10));
|
||||
|
||||
/* DMA interrupt */
|
||||
if (m_core->imask & (1 << (channel+10)))
|
||||
{
|
||||
m_core->irq_pending |= 1 << (channel+10);
|
||||
}
|
||||
}
|
||||
|
||||
/* clear busy flag */
|
||||
m_core->dma_status &= ~(1 << channel);
|
||||
|
||||
m_core->dma_op[channel].active = 0;
|
||||
}
|
||||
|
||||
static void sharc_dma_exec(int channel)
|
||||
{
|
||||
UINT32 src, dst;
|
||||
UINT32 src_count, dst_count;
|
||||
UINT32 src_modifier, dst_modifier;
|
||||
int chen, tran, dtype, pmode, ishake, intio;
|
||||
|
||||
chen = (m_core->dma[channel].control >> 1) & 0x1;
|
||||
tran = (m_core->dma[channel].control >> 2) & 0x1;
|
||||
dtype = (m_core->dma[channel].control >> 5) & 0x1;
|
||||
pmode = (m_core->dma[channel].control >> 6) & 0x3;
|
||||
ishake = (m_core->dma[channel].control >> 10) & 0x1;
|
||||
intio = (m_core->dma[channel].control >> 11) & 0x1;
|
||||
|
||||
/* MAME: fatal errors */
|
||||
if (ishake)
|
||||
sharc_error("SHARC: dma_exec: handshake not supported\n");
|
||||
if (intio)
|
||||
sharc_error("SHARC: dma_exec: single-word interrupt enable not supported\n");
|
||||
|
||||
|
||||
if (chen) /* Chained DMA */
|
||||
{
|
||||
UINT32 dma_chain_ptr = m_core->dma[channel].chain_ptr & 0x1ffff;
|
||||
|
||||
schedule_chained_dma_op(channel, dma_chain_ptr, tran);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tran) /* Transmit to external */
|
||||
{
|
||||
dst = m_core->dma[channel].ext_index;
|
||||
dst_modifier = m_core->dma[channel].ext_modifier;
|
||||
dst_count = m_core->dma[channel].ext_count;
|
||||
src = (m_core->dma[channel].int_index & 0x1ffff) | 0x20000;
|
||||
src_modifier = m_core->dma[channel].int_modifier;
|
||||
src_count = m_core->dma[channel].int_count;
|
||||
}
|
||||
else /* Receive from external */
|
||||
{
|
||||
src = m_core->dma[channel].ext_index;
|
||||
src_modifier = m_core->dma[channel].ext_modifier;
|
||||
src_count = m_core->dma[channel].ext_count;
|
||||
dst = (m_core->dma[channel].int_index & 0x1ffff) | 0x20000;
|
||||
dst_modifier = m_core->dma[channel].int_modifier;
|
||||
dst_count = m_core->dma[channel].int_count;
|
||||
}
|
||||
|
||||
if (dtype)
|
||||
{
|
||||
pmode = DMA_PMODE_8_48;
|
||||
}
|
||||
|
||||
schedule_dma_op(channel, src, dst, (INT32)src_modifier, (INT32)dst_modifier, (INT32)src_count, (INT32)dst_count, pmode);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -617,7 +617,9 @@ static void mmfm_b(void) { MMFM(B,0x10); }
|
||||
COUNT_CYCLES(2); \
|
||||
{ \
|
||||
INT32 rd = R##DSTREG; \
|
||||
SET_N(R##REG(rd)^0x80000000); \
|
||||
/* only the 34020 sets N; on the 34010 MMTM leaves it */ \
|
||||
if (state.is_34020) \
|
||||
SET_N(R##REG(rd)^0x80000000); \
|
||||
for (i = 0; i < 16; i++) \
|
||||
{ \
|
||||
if (l & 0x8000) \
|
||||
|
||||
+52
-10
@@ -153,6 +153,13 @@ static UINT8 external_host_access;
|
||||
static void * dpyint_timer[MAX_CPU]; /* Display interrupt timer */
|
||||
static void * vsblnk_timer[MAX_CPU]; /* VBLANK start timer */
|
||||
|
||||
/* internal interrupts are delivered through TIME_NOW timers, which the */
|
||||
/* core does not save; remember the queued ones so a save state taken */
|
||||
/* while one is pending does not lose it */
|
||||
static UINT32 pending_internal[MAX_CPU];
|
||||
static int pending_generation[MAX_CPU];
|
||||
|
||||
|
||||
/* default configuration */
|
||||
static struct tms34010_config default_config =
|
||||
{
|
||||
@@ -843,6 +850,12 @@ void tms34010_init(void)
|
||||
vsblnk_timer[i] = timer_alloc(vsblnk_callback);
|
||||
}
|
||||
|
||||
/* allocate the shiftreg here rather than in reset, so the pointer */
|
||||
/* registered below is valid (a NULL entry zeroes the state size) */
|
||||
state.shiftreg = malloc(SHIFTREG_SIZE);
|
||||
if (state.shiftreg)
|
||||
memset(state.shiftreg, 0, SHIFTREG_SIZE);
|
||||
|
||||
cpunum = cpu_getactivecpu();
|
||||
state_save_register_UINT32("tms34010", cpunum, "OP", &state.op, 1);
|
||||
state_save_register_UINT32("tms34010", cpunum, "PC", &state.pc, 1);
|
||||
@@ -871,6 +884,9 @@ void tms34010_init(void)
|
||||
state_save_register_int("tms34010", cpunum, "gfxcycles", &state.gfxcycles);
|
||||
state_save_register_int("tms34010", cpunum, "luvcount", &state.last_update_vcount);
|
||||
state_save_register_int("tms34010", cpunum, "ICount", &tms34010_ICount);
|
||||
pending_internal[cpunum] = 0;
|
||||
pending_generation[cpunum] = 0;
|
||||
state_save_register_UINT32("tms34010", cpunum, "PENDINT", &pending_internal[cpunum], 1);
|
||||
state_save_register_func_presave(tms34010_state_presave);
|
||||
state_save_register_func_postload(tms34010_state_postload);
|
||||
}
|
||||
@@ -878,13 +894,13 @@ void tms34010_init(void)
|
||||
void tms34010_reset(void *param)
|
||||
{
|
||||
struct tms34010_config *config = param ? param : &default_config;
|
||||
UINT16 *shiftreg = state.shiftreg;
|
||||
|
||||
/* zap the state and copy in the config pointer */
|
||||
/* zap the state and copy in the config pointer; keep the shiftreg */
|
||||
/* allocated in init, it is registered for save states */
|
||||
memset(&state, 0, sizeof(state));
|
||||
state.config = config;
|
||||
|
||||
/* allocate the shiftreg */
|
||||
state.shiftreg = malloc(SHIFTREG_SIZE);
|
||||
state.shiftreg = shiftreg;
|
||||
|
||||
/* fetch the initial PC and reset the state */
|
||||
PC = RLONG(0xffffffe0) & 0xfffffff0;
|
||||
@@ -1198,10 +1214,23 @@ void tms34020_set_irq_callback(int (*callback)(int irqline))
|
||||
** Generate internal interrupt
|
||||
*#################################################################################################*/
|
||||
|
||||
static void internal_interrupt_callback(int param);
|
||||
|
||||
static void queue_internal_interrupt(int cpunum, int type)
|
||||
{
|
||||
pending_internal[cpunum] |= type;
|
||||
timer_set(TIME_NOW, cpunum | (type << 8) | ((pending_generation[cpunum] & 0x7f) << 24), internal_interrupt_callback);
|
||||
}
|
||||
|
||||
static void internal_interrupt_callback(int param)
|
||||
{
|
||||
int cpunum = param & 0xff;
|
||||
int type = param >> 8;
|
||||
int type = (param >> 8) & 0xffff;
|
||||
|
||||
/* ignore interrupts queued before a state load, they were re-queued */
|
||||
if (((param >> 24) & 0x7f) != (pending_generation[cpunum] & 0x7f))
|
||||
return;
|
||||
pending_internal[cpunum] &= ~type;
|
||||
|
||||
/* call through to the CPU to generate the int */
|
||||
cpuintrf_push_context(cpunum);
|
||||
@@ -1553,7 +1582,7 @@ static void dpyint_callback(int cpunum)
|
||||
|
||||
/* set the CPU's context and queue an interrupt */
|
||||
cpuintrf_push_context(cpunum);
|
||||
timer_set(TIME_NOW, cpunum | (TMS34010_DI << 8), internal_interrupt_callback);
|
||||
queue_internal_interrupt(cpunum, TMS34010_DI);
|
||||
|
||||
/* allow a callback so we can update before they are likely to do nasty things */
|
||||
if (state.config->display_int_callback)
|
||||
@@ -1678,7 +1707,7 @@ WRITE16_HANDLER( tms34010_io_register_w )
|
||||
|
||||
/* NMI issued? */
|
||||
if (data & 0x0100)
|
||||
timer_set(TIME_NOW, cpunum | (TMS34010_NMI << 8), internal_interrupt_callback);
|
||||
queue_internal_interrupt(cpunum, TMS34010_NMI);
|
||||
break;
|
||||
|
||||
case REG_HSTCTLL:
|
||||
@@ -1715,7 +1744,7 @@ WRITE16_HANDLER( tms34010_io_register_w )
|
||||
|
||||
/* input interrupt? (should really be state-based, but the functions don't exist!) */
|
||||
if (!(oldreg & 0x0008) && (newreg & 0x0008))
|
||||
timer_set(TIME_NOW, cpunum | (TMS34010_HI << 8), internal_interrupt_callback);
|
||||
queue_internal_interrupt(cpunum, TMS34010_HI);
|
||||
else if ((oldreg & 0x0008) && !(newreg & 0x0008))
|
||||
IOREG(REG_INTPEND) &= ~TMS34010_HI;
|
||||
break;
|
||||
@@ -1845,7 +1874,7 @@ WRITE16_HANDLER( tms34020_io_register_w )
|
||||
|
||||
/* NMI issued? */
|
||||
if (data & 0x0100)
|
||||
timer_set(TIME_NOW, cpunum | (TMS34010_NMI << 8), internal_interrupt_callback);
|
||||
queue_internal_interrupt(cpunum, TMS34010_NMI);
|
||||
break;
|
||||
|
||||
case REG020_HSTCTLL:
|
||||
@@ -1880,7 +1909,7 @@ WRITE16_HANDLER( tms34020_io_register_w )
|
||||
|
||||
/* input interrupt? (should really be state-based, but the functions don't exist!) */
|
||||
if (!(oldreg & 0x0008) && (newreg & 0x0008))
|
||||
timer_set(TIME_NOW, cpunum | (TMS34010_HI << 8), internal_interrupt_callback);
|
||||
queue_internal_interrupt(cpunum, TMS34010_HI);
|
||||
else if ((oldreg & 0x0008) && !(newreg & 0x0008))
|
||||
IOREG(REG020_INTPEND) &= ~TMS34010_HI;
|
||||
break;
|
||||
@@ -2150,6 +2179,19 @@ static void tms34010_state_postload(void)
|
||||
tms34010_io_register_w(REG_DPYINT,IOREG(REG_DPYINT),0);
|
||||
set_raster_op();
|
||||
set_pixel_function();
|
||||
|
||||
/* re-queue the internal interrupts that were pending at save time */
|
||||
{
|
||||
int cpunum = cpu_getactivecpu();
|
||||
UINT32 pending = pending_internal[cpunum];
|
||||
int bit;
|
||||
|
||||
pending_generation[cpunum]++;
|
||||
pending_internal[cpunum] = 0;
|
||||
for (bit = 0; bit < 16; bit++)
|
||||
if (pending & (1 << bit))
|
||||
queue_internal_interrupt(cpunum, 1 << bit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,38 @@
|
||||
/***************************************************************************
|
||||
|
||||
TMS57002 "DASP" emulator
|
||||
|
||||
Backported to mame2003-plus from current MAME src/devices/cpu/tms57002
|
||||
(Olivier Galibert). Not a scheduled CPU here: it runs one sample period
|
||||
at a time from the sound stream of the board that has it, as in MAME
|
||||
where each stream sample syncs it.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TMS57002_H
|
||||
#define TMS57002_H
|
||||
|
||||
#include "osd_cpu.h"
|
||||
|
||||
void tms57002dsp_init( void );
|
||||
void tms57002dsp_reset( void );
|
||||
void tms57002dsp_state_register( void );
|
||||
|
||||
/* host port */
|
||||
UINT8 tms57002dsp_data_r( void );
|
||||
void tms57002dsp_data_w( UINT8 data );
|
||||
void tms57002dsp_pload_w( int state );
|
||||
void tms57002dsp_cload_w( int state );
|
||||
int tms57002dsp_empty_r( void );
|
||||
int tms57002dsp_fifo_count( void ); /* coefficient updates waiting */
|
||||
/* called with the "update FIFO empty" line when it changes */
|
||||
void tms57002dsp_set_empty_callback( void (*callback)( int state ) );
|
||||
|
||||
/*
|
||||
One sample period: the four inputs (16-bit samples), the four outputs
|
||||
of the previous period (16-bit), then the DSP runs its program for the
|
||||
next one (cycles: instruction clock / sample rate).
|
||||
*/
|
||||
void tms57002dsp_sample( const INT32 *in, INT32 *out, int cycles );
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
+11
-11
@@ -1,21 +1,21 @@
|
||||
|
||||
// NOTE for bit string/field addressing
|
||||
// ************************************
|
||||
// modDim must be passed as 10 for bit string instructions,
|
||||
// and as 11 for bit field instructions
|
||||
/* NOTE for bit string/field addressing */
|
||||
/* ************************************ */
|
||||
/* modDim must be passed as 10 for bit string instructions, */
|
||||
/* and as 11 for bit field instructions */
|
||||
|
||||
|
||||
|
||||
// Output variables for ReadAMAddress()
|
||||
/* Output variables for ReadAMAddress() */
|
||||
static UINT8 amFlag;
|
||||
static UINT32 amOut;
|
||||
static UINT32 bamOffset;
|
||||
|
||||
// Appo temp var
|
||||
/* Appo temp var */
|
||||
static UINT32 amLength1,amLength2;
|
||||
|
||||
|
||||
// Global vars used by AM functions
|
||||
/* Global vars used by AM functions */
|
||||
static UINT32 modAdd;
|
||||
static UINT8 modM;
|
||||
static UINT8 modVal;
|
||||
@@ -25,10 +25,10 @@ static UINT16 modWriteValH;
|
||||
static UINT32 modWriteValW;
|
||||
static UINT8 modDim;
|
||||
|
||||
// Addressing mode functions and tables
|
||||
#include "am1.c" // ReadAM
|
||||
#include "am2.c" // ReadAMAddress
|
||||
#include "am3.c" // WriteAM
|
||||
/* Addressing mode functions and tables */
|
||||
#include "am1.c" /* ReadAM */
|
||||
#include "am2.c" /* ReadAMAddress */
|
||||
#include "am3.c" /* WriteAM */
|
||||
|
||||
/*
|
||||
Input:
|
||||
|
||||
+5
-5
@@ -1,6 +1,6 @@
|
||||
|
||||
// AM1 Functions (for ReadAM)
|
||||
// **************************
|
||||
/* AM1 Functions (for ReadAM) */
|
||||
/* ************************** */
|
||||
|
||||
static UINT32 am1Register(void)
|
||||
{
|
||||
@@ -1071,7 +1071,7 @@ static UINT32 am1Immediate(void)
|
||||
break;
|
||||
}
|
||||
|
||||
// It should not be here! Written to avoid warning
|
||||
/* It should not be here! Written to avoid warning */
|
||||
assert(0);
|
||||
return 1;
|
||||
}
|
||||
@@ -1085,8 +1085,8 @@ static UINT32 am1ImmediateQuick(void)
|
||||
|
||||
|
||||
|
||||
// AM1 Tables (for ReadAM)
|
||||
// ***********************
|
||||
/* AM1 Tables (for ReadAM) */
|
||||
/* *********************** */
|
||||
|
||||
static UINT32 am1Error1(void)
|
||||
{
|
||||
|
||||
+6
-6
@@ -1,6 +1,6 @@
|
||||
|
||||
// AM2 Functions (for ReadAMAddress)
|
||||
// *********************************
|
||||
/* AM2 Functions (for ReadAMAddress) */
|
||||
/* ********************************* */
|
||||
|
||||
static UINT32 am2Register(void)
|
||||
{
|
||||
@@ -940,19 +940,19 @@ static UINT32 bam2DirectAddressDeferredIndexed(void)
|
||||
|
||||
static UINT32 am2Immediate(void)
|
||||
{
|
||||
// Fuck off LDPR
|
||||
/* Fuck off LDPR */
|
||||
return am1Immediate();
|
||||
}
|
||||
|
||||
static UINT32 am2ImmediateQuick(void)
|
||||
{
|
||||
// fuck off LDPR
|
||||
/* fuck off LDPR */
|
||||
return am1ImmediateQuick();
|
||||
}
|
||||
|
||||
|
||||
// AM2 Tables (for ReadAMAddress)
|
||||
// ******************************
|
||||
/* AM2 Tables (for ReadAMAddress) */
|
||||
/* ****************************** */
|
||||
|
||||
static UINT32 am2Error1(void)
|
||||
{
|
||||
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
|
||||
// AM3 Functions (for ReadAM)
|
||||
// **************************
|
||||
/* AM3 Functions (for ReadAM) */
|
||||
/* ************************** */
|
||||
|
||||
static UINT32 am3Register(void)
|
||||
{
|
||||
@@ -730,8 +730,8 @@ static UINT32 am3ImmediateQuick(void)
|
||||
|
||||
|
||||
|
||||
// AM3 Tables (for ReadAMAddress)
|
||||
// ******************************
|
||||
/* AM3 Tables (for ReadAMAddress) */
|
||||
/* ****************************** */
|
||||
|
||||
static UINT32 am3Error1(void)
|
||||
{
|
||||
|
||||
+78
-78
@@ -78,13 +78,13 @@ static UINT8 f12Flag1, f12Flag2;
|
||||
|
||||
static UINT8 if12;
|
||||
|
||||
// Decode the first operand of the instruction and prepare
|
||||
// writing to the second operand.
|
||||
/* Decode the first operand of the instruction and prepare */
|
||||
/* writing to the second operand. */
|
||||
static void F12DecodeFirstOperand(UINT32 (*DecodeOp1)(void), UINT8 dim1)
|
||||
{
|
||||
if12 = OpRead8(PC + 1);
|
||||
|
||||
// Check if F1 or F2
|
||||
/* Check if F1 or F2 */
|
||||
if (if12 & 0x80)
|
||||
{
|
||||
modDim = dim1;
|
||||
@@ -96,7 +96,7 @@ static void F12DecodeFirstOperand(UINT32 (*DecodeOp1)(void), UINT8 dim1)
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check D flag
|
||||
/* Check D flag */
|
||||
if (if12 & 0x20)
|
||||
{
|
||||
modDim = dim1;
|
||||
@@ -140,7 +140,7 @@ static void F12WriteSecondOperand(UINT8 dim2)
|
||||
{
|
||||
modDim = dim2;
|
||||
|
||||
// Check if F1 or F2
|
||||
/* Check if F1 or F2 */
|
||||
if (if12 & 0x80)
|
||||
{
|
||||
modM = if12 & 0x20;
|
||||
@@ -150,7 +150,7 @@ static void F12WriteSecondOperand(UINT8 dim2)
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check D flag
|
||||
/* Check D flag */
|
||||
if (if12 & 0x20)
|
||||
{
|
||||
switch (dim2)
|
||||
@@ -180,12 +180,12 @@ static void F12WriteSecondOperand(UINT8 dim2)
|
||||
|
||||
|
||||
|
||||
// Decode both format 1/2 operands
|
||||
/* Decode both format 1/2 operands */
|
||||
static void F12DecodeOperands(UINT32 (*DecodeOp1)(void), UINT8 dim1, UINT32 (*DecodeOp2)(void), UINT8 dim2)
|
||||
{
|
||||
UINT8 _if12 = OpRead8(PC + 1);
|
||||
|
||||
// Check if F1 or F2
|
||||
/* Check if F1 or F2 */
|
||||
if (_if12 & 0x80)
|
||||
{
|
||||
modDim = dim1;
|
||||
@@ -204,7 +204,7 @@ static void F12DecodeOperands(UINT32 (*DecodeOp1)(void), UINT8 dim1, UINT32 (*De
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check D flag
|
||||
/* Check D flag */
|
||||
if (_if12 & 0x20)
|
||||
{
|
||||
if (DecodeOp2==ReadAMAddress)
|
||||
@@ -423,7 +423,7 @@ static UINT32 opCHKAR(void)
|
||||
{
|
||||
F12DecodeOperands(ReadAM,0,ReadAM,0);
|
||||
|
||||
// No MMU and memory permissions yet @@@
|
||||
/* No MMU and memory permissions yet @@@ */
|
||||
_Z = 1;
|
||||
_CY = 0;
|
||||
_S = 0;
|
||||
@@ -435,7 +435,7 @@ static UINT32 opCHKAW(void)
|
||||
{
|
||||
F12DecodeOperands(ReadAM,0,ReadAM,0);
|
||||
|
||||
// No MMU and memory permissions yet @@@
|
||||
/* No MMU and memory permissions yet @@@ */
|
||||
_Z = 1;
|
||||
_CY = 0;
|
||||
_S = 0;
|
||||
@@ -447,7 +447,7 @@ static UINT32 opCHKAE(void)
|
||||
{
|
||||
F12DecodeOperands(ReadAM,0,ReadAM,0);
|
||||
|
||||
// No MMU and memory permissions yet @@@
|
||||
/* No MMU and memory permissions yet @@@ */
|
||||
_Z = 1;
|
||||
_CY = 0;
|
||||
_S = 0;
|
||||
@@ -805,14 +805,14 @@ static UINT32 opLDTASK(void)
|
||||
|
||||
v60ReloadStack();
|
||||
|
||||
// 31 registers supported, _not_ 32
|
||||
/* 31 registers supported, _not_ 32 */
|
||||
for(i=0; i<31; i++)
|
||||
if(f12Op1 & (1<<i)) {
|
||||
v60.reg[i] = MemRead32(f12Op2);
|
||||
f12Op2 += 4;
|
||||
}
|
||||
|
||||
// #### Ignore the virtual addressing crap.
|
||||
/* #### Ignore the virtual addressing crap. */
|
||||
|
||||
F12END();
|
||||
}
|
||||
@@ -925,8 +925,8 @@ static UINT32 opMOVTHB(void)
|
||||
F12DecodeFirstOperand(ReadAM,1);
|
||||
modWriteValB = (UINT8)(f12Op1&0xFF);
|
||||
|
||||
// Check for overflow: the truncated bits must match the sign
|
||||
// of the result, otherwise overflow
|
||||
/* Check for overflow: the truncated bits must match the sign */
|
||||
/* of the result, otherwise overflow */
|
||||
if (((modWriteValB&0x80)==0x80 && ((f12Op1&0xFF00)==0xFF00)) ||
|
||||
((modWriteValB&0x80)==0 && ((f12Op1&0xFF00)==0x0000)))
|
||||
_OV = 0;
|
||||
@@ -942,8 +942,8 @@ static UINT32 opMOVTWB(void)
|
||||
F12DecodeFirstOperand(ReadAM,2);
|
||||
modWriteValB = (UINT8)(f12Op1&0xFF);
|
||||
|
||||
// Check for overflow: the truncated bits must match the sign
|
||||
// of the result, otherwise overflow
|
||||
/* Check for overflow: the truncated bits must match the sign */
|
||||
/* of the result, otherwise overflow */
|
||||
if (((modWriteValB&0x80)==0x80 && ((f12Op1&0xFFFFFF00)==0xFFFFFF00)) ||
|
||||
((modWriteValB&0x80)==0 && ((f12Op1&0xFFFFFF00)==0x00000000)))
|
||||
_OV = 0;
|
||||
@@ -959,8 +959,8 @@ static UINT32 opMOVTWH(void)
|
||||
F12DecodeFirstOperand(ReadAM,2);
|
||||
modWriteValH = (UINT16)(f12Op1&0xFFFF);
|
||||
|
||||
// Check for overflow: the truncated bits must match the sign
|
||||
// of the result, otherwise overflow
|
||||
/* Check for overflow: the truncated bits must match the sign */
|
||||
/* of the result, otherwise overflow */
|
||||
if (((modWriteValH&0x8000)==0x8000 && ((f12Op1&0xFFFF0000)==0xFFFF0000)) ||
|
||||
((modWriteValH&0x8000)==0 && ((f12Op1&0xFFFF0000)==0x00000000)))
|
||||
_OV = 0;
|
||||
@@ -1640,7 +1640,7 @@ static UINT32 opSETF(void)
|
||||
{
|
||||
F12DecodeFirstOperand(ReadAM,0);
|
||||
|
||||
// Normalize the flags
|
||||
/* Normalize the flags */
|
||||
NORMALIZEFLAGS();
|
||||
|
||||
switch (f12Op1 & 0xF)
|
||||
@@ -1726,7 +1726,7 @@ static UINT32 opSETF(void)
|
||||
}
|
||||
*/
|
||||
|
||||
// During the shift, the overflow is set if the sign bit changes at any point during the shift
|
||||
/* During the shift, the overflow is set if the sign bit changes at any point during the shift */
|
||||
#define SHIFTLEFT_OV(val, count, bitsize) \
|
||||
{\
|
||||
UINT32 tmp; \
|
||||
@@ -1765,7 +1765,7 @@ static UINT32 opSHAB(void)
|
||||
|
||||
count=(INT8)(f12Op1&0xFF);
|
||||
|
||||
// Special case: destination unchanged, flags set
|
||||
/* Special case: destination unchanged, flags set */
|
||||
if (count == 0)
|
||||
{
|
||||
_CY = _OV = 0;
|
||||
@@ -1775,16 +1775,16 @@ static UINT32 opSHAB(void)
|
||||
{
|
||||
SHIFTLEFT_OV(appb, count, 8);
|
||||
|
||||
// @@@ Undefined what happens to CY when count >= bitsize
|
||||
/* @@@ Undefined what happens to CY when count >= bitsize */
|
||||
SHIFTLEFT_CY(appb, count, 8);
|
||||
|
||||
// do the actual shift...
|
||||
/* do the actual shift... */
|
||||
if (count >= 8)
|
||||
appb = 0;
|
||||
else
|
||||
appb <<= count;
|
||||
|
||||
// and set zero and sign
|
||||
/* and set zero and sign */
|
||||
SetSZPF_Byte(appb);
|
||||
}
|
||||
else
|
||||
@@ -1802,7 +1802,7 @@ static UINT32 opSHAB(void)
|
||||
SetSZPF_Byte(appb);
|
||||
}
|
||||
|
||||
// mame_printf_debug("SHAB: %x _CY: %d _Z: %d _OV: %d _S: %d\n", appb, _CY, _Z, _OV, _S);
|
||||
/* mame_printf_debug("SHAB: %x _CY: %d _Z: %d _OV: %d _S: %d\n", appb, _CY, _Z, _OV, _S); */
|
||||
|
||||
F12STOREOP2BYTE();
|
||||
F12END();
|
||||
@@ -1819,7 +1819,7 @@ static UINT32 opSHAH(void)
|
||||
|
||||
count=(INT8)(f12Op1&0xFF);
|
||||
|
||||
// Special case: destination unchanged, flags set
|
||||
/* Special case: destination unchanged, flags set */
|
||||
if (count == 0)
|
||||
{
|
||||
_CY = _OV = 0;
|
||||
@@ -1829,16 +1829,16 @@ static UINT32 opSHAH(void)
|
||||
{
|
||||
SHIFTLEFT_OV(apph, count, 16);
|
||||
|
||||
// @@@ Undefined what happens to CY when count >= bitsize
|
||||
/* @@@ Undefined what happens to CY when count >= bitsize */
|
||||
SHIFTLEFT_CY(apph, count, 16);
|
||||
|
||||
// do the actual shift...
|
||||
/* do the actual shift... */
|
||||
if (count >= 16)
|
||||
apph = 0;
|
||||
else
|
||||
apph <<= count;
|
||||
|
||||
// and set zero and sign
|
||||
/* and set zero and sign */
|
||||
SetSZPF_Word(apph);
|
||||
}
|
||||
else
|
||||
@@ -1856,7 +1856,7 @@ static UINT32 opSHAH(void)
|
||||
SetSZPF_Word(apph);
|
||||
}
|
||||
|
||||
// mame_printf_debug("SHAH: %x >> %d = %x _CY: %d _Z: %d _OV: %d _S: %d\n", oldval, count, apph, _CY, _Z, _OV, _S);
|
||||
/* mame_printf_debug("SHAH: %x >> %d = %x _CY: %d _Z: %d _OV: %d _S: %d\n", oldval, count, apph, _CY, _Z, _OV, _S); */
|
||||
|
||||
F12STOREOP2HALF();
|
||||
F12END();
|
||||
@@ -1873,7 +1873,7 @@ static UINT32 opSHAW(void)
|
||||
|
||||
count=(INT8)(f12Op1&0xFF);
|
||||
|
||||
// Special case: destination unchanged, flags set
|
||||
/* Special case: destination unchanged, flags set */
|
||||
if (count == 0)
|
||||
{
|
||||
_CY = _OV = 0;
|
||||
@@ -1883,16 +1883,16 @@ static UINT32 opSHAW(void)
|
||||
{
|
||||
SHIFTLEFT_OV(appw, count, 32);
|
||||
|
||||
// @@@ Undefined what happens to CY when count >= bitsize
|
||||
/* @@@ Undefined what happens to CY when count >= bitsize */
|
||||
SHIFTLEFT_CY(appw, count, 32);
|
||||
|
||||
// do the actual shift...
|
||||
/* do the actual shift... */
|
||||
if (count >= 32)
|
||||
appw = 0;
|
||||
else
|
||||
appw <<= count;
|
||||
|
||||
// and set zero and sign
|
||||
/* and set zero and sign */
|
||||
SetSZPF_Long(appw);
|
||||
}
|
||||
else
|
||||
@@ -1910,7 +1910,7 @@ static UINT32 opSHAW(void)
|
||||
SetSZPF_Long(appw);
|
||||
}
|
||||
|
||||
// mame_printf_debug("SHAW: %x >> %d = %x _CY: %d _Z: %d _OV: %d _S: %d\n", oldval, count, appw, _CY, _Z, _OV, _S);
|
||||
/* mame_printf_debug("SHAW: %x >> %d = %x _CY: %d _Z: %d _OV: %d _S: %d\n", oldval, count, appw, _CY, _Z, _OV, _S); */
|
||||
|
||||
F12STOREOP2WORD();
|
||||
F12END();
|
||||
@@ -1930,36 +1930,36 @@ static UINT32 opSHLB(void) /* TRUSTED */
|
||||
count=(INT8)(f12Op1&0xFF);
|
||||
if (count>0)
|
||||
{
|
||||
// left shift flags:
|
||||
// carry gets the last bit shifted out,
|
||||
// overflow is always CLEARed
|
||||
/* left shift flags: */
|
||||
/* carry gets the last bit shifted out, */
|
||||
/* overflow is always CLEARed */
|
||||
|
||||
_OV = 0; // default to no overflow
|
||||
_OV = 0; /* default to no overflow */
|
||||
|
||||
// now handle carry
|
||||
/* now handle carry */
|
||||
tmp = appb & 0xff;
|
||||
tmp <<= count;
|
||||
SetCFB(tmp); // set carry properly
|
||||
SetCFB(tmp); /* set carry properly */
|
||||
|
||||
// do the actual shift...
|
||||
/* do the actual shift... */
|
||||
appb <<= count;
|
||||
|
||||
// and set zero and sign
|
||||
/* and set zero and sign */
|
||||
SetSZPF_Byte(appb);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
// special case: clear carry and overflow, do nothing else
|
||||
/* special case: clear carry and overflow, do nothing else */
|
||||
_CY = _OV = 0;
|
||||
SetSZPF_Byte(appb); // doc. is unclear if this is true...
|
||||
SetSZPF_Byte(appb); /* doc. is unclear if this is true... */
|
||||
}
|
||||
else
|
||||
{
|
||||
// right shift flags:
|
||||
// carry = last bit shifted out
|
||||
// overflow always cleared
|
||||
/* right shift flags: */
|
||||
/* carry = last bit shifted out */
|
||||
/* overflow always cleared */
|
||||
tmp = appb & 0xff;
|
||||
tmp >>= ((-count)-1);
|
||||
_CY = (UINT8)(tmp & 0x1);
|
||||
@@ -1970,7 +1970,7 @@ static UINT32 opSHLB(void) /* TRUSTED */
|
||||
}
|
||||
}
|
||||
|
||||
// mame_printf_debug("SHLB: %x _CY: %d _Z: %d _OV: %d _S: %d\n", appb, _CY, _Z, _OV, _S);
|
||||
/* mame_printf_debug("SHLB: %x _CY: %d _Z: %d _OV: %d _S: %d\n", appb, _CY, _Z, _OV, _S); */
|
||||
|
||||
F12STOREOP2BYTE();
|
||||
F12END();
|
||||
@@ -1987,39 +1987,39 @@ static UINT32 opSHLH(void) /* TRUSTED */
|
||||
F12LOADOP2HALF();
|
||||
|
||||
count=(INT8)(f12Op1&0xFF);
|
||||
// mame_printf_debug("apph: %x count: %d ", apph, count);
|
||||
/* mame_printf_debug("apph: %x count: %d ", apph, count); */
|
||||
if (count>0)
|
||||
{
|
||||
// left shift flags:
|
||||
// carry gets the last bit shifted out,
|
||||
// overflow is always CLEARed
|
||||
/* left shift flags: */
|
||||
/* carry gets the last bit shifted out, */
|
||||
/* overflow is always CLEARed */
|
||||
|
||||
_OV = 0;
|
||||
|
||||
// now handle carry
|
||||
/* now handle carry */
|
||||
tmp = apph & 0xffff;
|
||||
tmp <<= count;
|
||||
SetCFW(tmp); // set carry properly
|
||||
SetCFW(tmp); /* set carry properly */
|
||||
|
||||
// do the actual shift...
|
||||
/* do the actual shift... */
|
||||
apph <<= count;
|
||||
|
||||
// and set zero and sign
|
||||
/* and set zero and sign */
|
||||
SetSZPF_Word(apph);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
// special case: clear carry and overflow, do nothing else
|
||||
/* special case: clear carry and overflow, do nothing else */
|
||||
_CY = _OV = 0;
|
||||
SetSZPF_Word(apph); // doc. is unclear if this is true...
|
||||
SetSZPF_Word(apph); /* doc. is unclear if this is true... */
|
||||
}
|
||||
else
|
||||
{
|
||||
// right shift flags:
|
||||
// carry = last bit shifted out
|
||||
// overflow always cleared
|
||||
/* right shift flags: */
|
||||
/* carry = last bit shifted out */
|
||||
/* overflow always cleared */
|
||||
tmp = apph & 0xffff;
|
||||
tmp >>= ((-count)-1);
|
||||
_CY = (UINT8)(tmp & 0x1);
|
||||
@@ -2030,7 +2030,7 @@ static UINT32 opSHLH(void) /* TRUSTED */
|
||||
}
|
||||
}
|
||||
|
||||
// mame_printf_debug("SHLH: %x _CY: %d _Z: %d _OV: %d _S: %d\n", apph, _CY, _Z, _OV, _S);
|
||||
/* mame_printf_debug("SHLH: %x _CY: %d _Z: %d _OV: %d _S: %d\n", apph, _CY, _Z, _OV, _S); */
|
||||
|
||||
F12STOREOP2HALF();
|
||||
F12END();
|
||||
@@ -2049,36 +2049,36 @@ static UINT32 opSHLW(void) /* TRUSTED */
|
||||
count=(INT8)(f12Op1&0xFF);
|
||||
if (count>0)
|
||||
{
|
||||
// left shift flags:
|
||||
// carry gets the last bit shifted out,
|
||||
// overflow is always CLEARed
|
||||
/* left shift flags: */
|
||||
/* carry gets the last bit shifted out, */
|
||||
/* overflow is always CLEARed */
|
||||
|
||||
_OV = 0;
|
||||
|
||||
// now handle carry
|
||||
/* now handle carry */
|
||||
tmp = appw & 0xffffffff;
|
||||
tmp <<= count;
|
||||
SetCFL(tmp); // set carry properly
|
||||
SetCFL(tmp); /* set carry properly */
|
||||
|
||||
// do the actual shift...
|
||||
/* do the actual shift... */
|
||||
appw <<= count;
|
||||
|
||||
// and set zero and sign
|
||||
/* and set zero and sign */
|
||||
SetSZPF_Long(appw);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
// special case: clear carry and overflow, do nothing else
|
||||
/* special case: clear carry and overflow, do nothing else */
|
||||
_CY = _OV = 0;
|
||||
SetSZPF_Long(appw); // doc. is unclear if this is true...
|
||||
SetSZPF_Long(appw); /* doc. is unclear if this is true... */
|
||||
}
|
||||
else
|
||||
{
|
||||
// right shift flags:
|
||||
// carry = last bit shifted out
|
||||
// overflow always cleared
|
||||
/* right shift flags: */
|
||||
/* carry = last bit shifted out */
|
||||
/* overflow always cleared */
|
||||
tmp = (UINT64)(appw & 0xffffffff);
|
||||
tmp >>= ((-count)-1);
|
||||
_CY = (UINT8)(tmp & 0x1);
|
||||
@@ -2089,7 +2089,7 @@ static UINT32 opSHLW(void) /* TRUSTED */
|
||||
}
|
||||
}
|
||||
|
||||
// mame_printf_debug("SHLW: %x _CY: %d _Z: %d _OV: %d _S: %d\n", appw, _CY, _Z, _OV, _S);
|
||||
/* mame_printf_debug("SHLW: %x _CY: %d _Z: %d _OV: %d _S: %d\n", appw, _CY, _Z, _OV, _S); */
|
||||
|
||||
F12STOREOP2WORD();
|
||||
F12END();
|
||||
|
||||
+27
-7
@@ -55,7 +55,7 @@ static UINT32 opCVTWS(void)
|
||||
|
||||
F2DecodeFirstOperand(ReadAM,2);
|
||||
|
||||
// Convert to float
|
||||
/* Convert to float */
|
||||
val = (float)(INT32)f2Op1;
|
||||
modWriteValW = f2u(val);
|
||||
|
||||
@@ -68,21 +68,41 @@ static UINT32 opCVTWS(void)
|
||||
F2END();
|
||||
}
|
||||
|
||||
static float truncf_c89(float x)
|
||||
{
|
||||
if (x >= 0.0f) {
|
||||
return floorf(x);
|
||||
} else {
|
||||
return ceilf(x);
|
||||
}
|
||||
}
|
||||
|
||||
static UINT32 opCVTSW(void)
|
||||
{
|
||||
float val;
|
||||
|
||||
F2DecodeFirstOperand(ReadAM,2);
|
||||
|
||||
// Convert to UINT32
|
||||
// Apply RDI rounding control
|
||||
val = u2f(f2Op1);
|
||||
modWriteValW = (INT32)val;
|
||||
switch (TKCW & 7)
|
||||
{
|
||||
case 0: val = roundf(val); break;
|
||||
case 1: val = floorf(val); break;
|
||||
case 2: val = ceilf(val); break;
|
||||
#if defined _MSC_VER
|
||||
default: val = truncf_c89(val); break;
|
||||
#else
|
||||
default: val = truncf(val); break;
|
||||
#endif
|
||||
}
|
||||
|
||||
_OV=0;
|
||||
_CY=(val < 0.0f);
|
||||
_S=((modWriteValW & 0x80000000)!=0);
|
||||
_Z=(val == 0.0f);
|
||||
// Convert to uint32_t
|
||||
modWriteValW = (uint32_t)(int64_t)val;
|
||||
|
||||
_S = ((modWriteValW & 0x80000000) != 0);
|
||||
_OV = (_S && val >= 0.0f) || (!_S && val <= -1.0f);
|
||||
_Z = (modWriteValW == 0);
|
||||
F2WriteSecondOperand(2);
|
||||
F2END();
|
||||
}
|
||||
|
||||
+38
-38
@@ -141,13 +141,13 @@ static UINT32 opJMP(void) /* TRUSTED */
|
||||
modAdd=PC+1;
|
||||
modDim=0;
|
||||
|
||||
// Read the address of the operand
|
||||
/* Read the address of the operand */
|
||||
ReadAMAddress();
|
||||
|
||||
// It cannot be a register!!
|
||||
/* It cannot be a register!! */
|
||||
assert(amFlag==0);
|
||||
|
||||
// Jump there
|
||||
/* Jump there */
|
||||
PC=amOut;
|
||||
ChangePC(PC);
|
||||
|
||||
@@ -159,17 +159,17 @@ static UINT32 opJSR(void) /* TRUSTED */
|
||||
modAdd=PC + 1;
|
||||
modDim=0;
|
||||
|
||||
// Read the address of the operand
|
||||
/* Read the address of the operand */
|
||||
amLength1=ReadAMAddress();
|
||||
|
||||
// It cannot be a register!!
|
||||
/* It cannot be a register!! */
|
||||
assert(amFlag==0);
|
||||
|
||||
// Save NextPC into the stack
|
||||
/* Save NextPC into the stack */
|
||||
SP -= 4;
|
||||
MemWrite32(SP, PC + amLength1 + 1);
|
||||
|
||||
// Jump there
|
||||
/* Jump there */
|
||||
PC=amOut;
|
||||
ChangePC(PC);
|
||||
|
||||
@@ -181,17 +181,17 @@ static UINT32 opPREPARE(void) /* somewhat TRUSTED */
|
||||
modAdd=PC+1;
|
||||
modDim=2;
|
||||
|
||||
// Read the operand
|
||||
/* Read the operand */
|
||||
amLength1=ReadAM();
|
||||
|
||||
// step 1: save frame pointer on the stack
|
||||
/* step 1: save frame pointer on the stack */
|
||||
SP -= 4;
|
||||
MemWrite32(SP, FP);
|
||||
|
||||
// step 2: FP = new SP
|
||||
/* step 2: FP = new SP */
|
||||
FP = SP;
|
||||
|
||||
// step 3: SP -= operand
|
||||
/* step 3: SP -= operand */
|
||||
SP -= amOut;
|
||||
|
||||
return amLength1 + 1;
|
||||
@@ -202,19 +202,19 @@ static UINT32 opRET(void) /* TRUSTED */
|
||||
modAdd=PC + 1;
|
||||
modDim=2;
|
||||
|
||||
// Read the operand
|
||||
/* Read the operand */
|
||||
ReadAM();
|
||||
|
||||
// Read return address from stack
|
||||
/* Read return address from stack */
|
||||
PC=MemRead32(SP);
|
||||
SP+=4;
|
||||
ChangePC(PC);
|
||||
|
||||
// Restore AP from stack
|
||||
/* Restore AP from stack */
|
||||
AP=MemRead32(SP);
|
||||
SP+=4;
|
||||
|
||||
// Skip stack frame
|
||||
/* Skip stack frame */
|
||||
SP += amOut;
|
||||
|
||||
return 0;
|
||||
@@ -227,10 +227,10 @@ static UINT32 opTRAP(void)
|
||||
modAdd=PC + 1;
|
||||
modDim=0;
|
||||
|
||||
// Read the operand
|
||||
/* Read the operand */
|
||||
amLength1=ReadAM();
|
||||
|
||||
// Normalize the flags
|
||||
/* Normalize the flags */
|
||||
NORMALIZEFLAGS();
|
||||
|
||||
switch ((amOut >> 4) & 0xF)
|
||||
@@ -285,7 +285,7 @@ static UINT32 opTRAP(void)
|
||||
|
||||
oldPSW = v60_update_psw_for_exception(0, 0);
|
||||
|
||||
// Issue the software trap with interrupts
|
||||
/* Issue the software trap with interrupts */
|
||||
SP -= 4;
|
||||
MemWrite32(SP, EXCEPTION_CODE_AND_SIZE(0x3000 + 0x100 * (amOut&0xF), 4));
|
||||
|
||||
@@ -307,10 +307,10 @@ static UINT32 opRETIU(void) /* TRUSTED */
|
||||
modAdd=PC + 1;
|
||||
modDim=1;
|
||||
|
||||
// Read the operand
|
||||
/* Read the operand */
|
||||
ReadAM();
|
||||
|
||||
// Restore PC and PSW from stack
|
||||
/* Restore PC and PSW from stack */
|
||||
PC = MemRead32(SP);
|
||||
SP += 4;
|
||||
ChangePC(PC);
|
||||
@@ -318,7 +318,7 @@ static UINT32 opRETIU(void) /* TRUSTED */
|
||||
newPSW = MemRead32(SP);
|
||||
SP += 4;
|
||||
|
||||
// Destroy stack frame
|
||||
/* Destroy stack frame */
|
||||
SP += amOut;
|
||||
|
||||
v60WritePSW(newPSW);
|
||||
@@ -333,10 +333,10 @@ static UINT32 opRETIS(void)
|
||||
modAdd=PC + 1;
|
||||
modDim=1;
|
||||
|
||||
// Read the operand
|
||||
/* Read the operand */
|
||||
ReadAM();
|
||||
|
||||
// Restore PC and PSW from stack
|
||||
/* Restore PC and PSW from stack */
|
||||
PC = MemRead32(SP);
|
||||
SP += 4;
|
||||
ChangePC(PC);
|
||||
@@ -344,7 +344,7 @@ static UINT32 opRETIS(void)
|
||||
newPSW = MemRead32(SP);
|
||||
SP += 4;
|
||||
|
||||
// Destroy stack frame
|
||||
/* Destroy stack frame */
|
||||
SP += amOut;
|
||||
|
||||
v60WritePSW(newPSW);
|
||||
@@ -386,14 +386,14 @@ static UINT32 opSTTASK(void)
|
||||
adr += 4;
|
||||
}
|
||||
|
||||
// 31 registers supported, _not_ 32
|
||||
/* 31 registers supported, _not_ 32 */
|
||||
for(i=0; i<31; i++)
|
||||
if(amOut & (1<<i)) {
|
||||
MemWrite32(adr, v60.reg[i]);
|
||||
adr += 4;
|
||||
}
|
||||
|
||||
// #### Ignore the virtual addressing crap.
|
||||
/* #### Ignore the virtual addressing crap. */
|
||||
|
||||
return amLength1 + 1;
|
||||
}
|
||||
@@ -404,7 +404,7 @@ static UINT32 opGETPSW(void)
|
||||
modDim=2;
|
||||
modWriteValW=v60ReadPSW();
|
||||
|
||||
// Write PSW to the operand
|
||||
/* Write PSW to the operand */
|
||||
amLength1=WriteAM();
|
||||
|
||||
return amLength1 + 1;
|
||||
@@ -416,19 +416,19 @@ static UINT32 opTASI(void)
|
||||
modAdd=PC + 1;
|
||||
modDim=0;
|
||||
|
||||
// Load the address of the operand
|
||||
/* Load the address of the operand */
|
||||
amLength1=ReadAMAddress();
|
||||
|
||||
// Load UINT8 from the address
|
||||
/* Load UINT8 from the address */
|
||||
if (amFlag)
|
||||
appb=(UINT8)v60.reg[amOut&0x1F];
|
||||
else
|
||||
appb=MemRead8(amOut);
|
||||
|
||||
// Set the flags for SUB appb,FF
|
||||
/* Set the flags for SUB appb,FF */
|
||||
SUBB(appb, 0xff);
|
||||
|
||||
// Write FF in the operand
|
||||
/* Write FF in the operand */
|
||||
if (amFlag)
|
||||
SETREG8(v60.reg[amOut&0x1F], 0xFF);
|
||||
else
|
||||
@@ -442,10 +442,10 @@ static UINT32 opCLRTLB(void)
|
||||
modAdd=PC+1;
|
||||
modDim=2;
|
||||
|
||||
// Read the operand
|
||||
/* Read the operand */
|
||||
amLength1=ReadAM();
|
||||
|
||||
// @@@ TLB not yet emulated
|
||||
/* @@@ TLB not yet emulated */
|
||||
|
||||
return amLength1 + 1;
|
||||
}
|
||||
@@ -457,7 +457,7 @@ static UINT32 opPOPM(void)
|
||||
modAdd=PC+1;
|
||||
modDim=2;
|
||||
|
||||
// Read the bit register list
|
||||
/* Read the bit register list */
|
||||
amLength1=ReadAM();
|
||||
|
||||
for (i=0;i<31;i++)
|
||||
@@ -483,7 +483,7 @@ static UINT32 opPUSHM(void)
|
||||
modAdd=PC+1;
|
||||
modDim=2;
|
||||
|
||||
// Read the bit register list
|
||||
/* Read the bit register list */
|
||||
amLength1=ReadAM();
|
||||
|
||||
if (amOut & (1<<31))
|
||||
@@ -508,7 +508,7 @@ static UINT32 opTESTB(void) /* TRUSTED */
|
||||
modAdd=PC+1;
|
||||
modDim=0;
|
||||
|
||||
// Read the operand
|
||||
/* Read the operand */
|
||||
amLength1=ReadAM();
|
||||
|
||||
_Z = (amOut == 0);
|
||||
@@ -524,7 +524,7 @@ static UINT32 opTESTH(void) /* TRUSTED */
|
||||
modAdd=PC+1;
|
||||
modDim=1;
|
||||
|
||||
// Read the operand
|
||||
/* Read the operand */
|
||||
amLength1=ReadAM();
|
||||
|
||||
_Z = (amOut == 0);
|
||||
@@ -540,7 +540,7 @@ static UINT32 opTESTW(void) /* TRUSTED */
|
||||
modAdd=PC+1;
|
||||
modDim=2;
|
||||
|
||||
// Read the operand
|
||||
/* Read the operand */
|
||||
amLength1=ReadAM();
|
||||
|
||||
_Z = (amOut == 0);
|
||||
|
||||
+2
-2
@@ -343,11 +343,11 @@ static UINT32 opBR16(void) /* TRUSTED */
|
||||
|
||||
static UINT32 opBSR(void) /* TRUSTED */
|
||||
{
|
||||
// Save Next PC onto the stack
|
||||
/* Save Next PC onto the stack */
|
||||
SP -= 4;
|
||||
MemWrite32(SP, PC+3);
|
||||
|
||||
// Jump to subroutine
|
||||
/* Jump to subroutine */
|
||||
PC += (INT16)OpRead16(PC + 1);
|
||||
return 0;
|
||||
}
|
||||
+4
-4
@@ -42,7 +42,7 @@ static UINT32 opBRKV(void)
|
||||
|
||||
static UINT32 opCLRTLBA(void)
|
||||
{
|
||||
// @@@ TLB not yet supported
|
||||
/* @@@ TLB not yet supported */
|
||||
logerror("Skipping CLRTLBA opcode! PC=%x\n", PC);
|
||||
return 1;
|
||||
}
|
||||
@@ -58,8 +58,8 @@ static UINT32 opDISPOSE(void)
|
||||
|
||||
static UINT32 opHALT(void)
|
||||
{
|
||||
// @@@ It should wait for an interrupt to occur
|
||||
//logerror("HALT found: skipping");
|
||||
/* @@@ It should wait for an interrupt to occur */
|
||||
/*logerror("HALT found: skipping"); */
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ static UINT32 opTRAPFL(void)
|
||||
{
|
||||
if ((TKCW & 0x1F0) & ((v60ReadPSW() & 0x1F00) >> 4))
|
||||
{
|
||||
// @@@ FPU exception
|
||||
/* @@@ FPU exception */
|
||||
log_cb(RETRO_LOG_DEBUG, "Hit TRAPFL! PC=%x", PC);
|
||||
}
|
||||
|
||||
|
||||
+54
-54
@@ -49,7 +49,7 @@ static UINT32 f7bBamOffset1, f7bBamOffset2;
|
||||
static void F7aDecodeOperands(UINT32 (*DecodeOp1)(void), UINT8 dim1, UINT32 (*DecodeOp2)(void), UINT8 dim2)
|
||||
{
|
||||
UINT8 appb;
|
||||
// Decode first operand
|
||||
/* Decode first operand */
|
||||
modDim=dim1;
|
||||
modM=subOp&0x40;
|
||||
modAdd=PC+2;
|
||||
@@ -57,14 +57,14 @@ static void F7aDecodeOperands(UINT32 (*DecodeOp1)(void), UINT8 dim1, UINT32 (*De
|
||||
f7aFlag1=amFlag;
|
||||
f7aOp1=amOut;
|
||||
|
||||
// Decode length
|
||||
/* Decode length */
|
||||
appb=OpRead8(PC+2+amLength1);
|
||||
if (appb&0x80)
|
||||
f7aLenOp1=v60.reg[appb&0x1F];
|
||||
else
|
||||
f7aLenOp1=appb;
|
||||
|
||||
// Decode second operand
|
||||
/* Decode second operand */
|
||||
modDim=dim2;
|
||||
modM=subOp&0x20;
|
||||
modAdd=PC+3+amLength1;
|
||||
@@ -72,7 +72,7 @@ static void F7aDecodeOperands(UINT32 (*DecodeOp1)(void), UINT8 dim1, UINT32 (*De
|
||||
f7aFlag2=amFlag;
|
||||
f7aOp2=amOut;
|
||||
|
||||
// Decode length
|
||||
/* Decode length */
|
||||
appb=OpRead8(PC+3+amLength1+amLength2);
|
||||
if (appb&0x80)
|
||||
f7aLenOp2=v60.reg[appb&0x1F];
|
||||
@@ -83,7 +83,7 @@ static void F7aDecodeOperands(UINT32 (*DecodeOp1)(void), UINT8 dim1, UINT32 (*De
|
||||
static void F7bDecodeFirstOperand(UINT32 (*DecodeOp1)(void), UINT8 dim1)
|
||||
{
|
||||
UINT8 appb;
|
||||
// Decode first operand
|
||||
/* Decode first operand */
|
||||
modDim=dim1;
|
||||
modM=subOp&0x40;
|
||||
modAdd=PC+2;
|
||||
@@ -91,7 +91,7 @@ static void F7bDecodeFirstOperand(UINT32 (*DecodeOp1)(void), UINT8 dim1)
|
||||
f7bFlag1=amFlag;
|
||||
f7bOp1=amOut;
|
||||
|
||||
// Decode ext
|
||||
/* Decode ext */
|
||||
appb=OpRead8(PC+2+amLength1);
|
||||
if (appb&0x80)
|
||||
f7bLen=v60.reg[appb&0x1F];
|
||||
@@ -111,11 +111,11 @@ static void F7bWriteSecondOperand(UINT8 dim2)
|
||||
|
||||
static void F7bDecodeOperands(UINT32 (*DecodeOp1)(void), UINT8 dim1, UINT32 (*DecodeOp2)(void), UINT8 dim2)
|
||||
{
|
||||
// Decode first operand
|
||||
/* Decode first operand */
|
||||
F7bDecodeFirstOperand(DecodeOp1,dim1);
|
||||
f7bBamOffset1 = bamOffset;
|
||||
|
||||
// Decode second operand
|
||||
/* Decode second operand */
|
||||
modDim=dim2;
|
||||
modM=subOp&0x20;
|
||||
modAdd=PC+3+amLength1;
|
||||
@@ -128,7 +128,7 @@ static void F7bDecodeOperands(UINT32 (*DecodeOp1)(void), UINT8 dim1, UINT32 (*De
|
||||
static void F7cDecodeOperands(UINT32 (*DecodeOp1)(void), UINT8 dim1, UINT32 (*DecodeOp2)(void), UINT8 dim2)
|
||||
{
|
||||
UINT8 appb;
|
||||
// Decode first operand
|
||||
/* Decode first operand */
|
||||
modDim=dim1;
|
||||
modM=subOp&0x40;
|
||||
modAdd=PC+2;
|
||||
@@ -136,7 +136,7 @@ static void F7cDecodeOperands(UINT32 (*DecodeOp1)(void), UINT8 dim1, UINT32 (*De
|
||||
f7cFlag1=amFlag;
|
||||
f7cOp1=amOut;
|
||||
|
||||
// Decode second operand
|
||||
/* Decode second operand */
|
||||
modDim=dim2;
|
||||
modM=subOp&0x20;
|
||||
modAdd=PC+2+amLength1;
|
||||
@@ -144,7 +144,7 @@ static void F7cDecodeOperands(UINT32 (*DecodeOp1)(void), UINT8 dim1, UINT32 (*De
|
||||
f7cFlag2=amFlag;
|
||||
f7cOp2=amOut;
|
||||
|
||||
// Decode ext
|
||||
/* Decode ext */
|
||||
appb=OpRead8(PC+2+amLength1+amLength2);
|
||||
if (appb&0x80)
|
||||
f7cLen=v60.reg[appb&0x1F];
|
||||
@@ -184,7 +184,7 @@ static UINT32 opCMPSTRB(UINT8 bFill, UINT8 bStop)
|
||||
|
||||
F7aDecodeOperands(ReadAMAddress,0,ReadAMAddress,0);
|
||||
|
||||
// Filling
|
||||
/* Filling */
|
||||
if (bFill)
|
||||
{
|
||||
if (f7aLenOp1 < f7aLenOp2)
|
||||
@@ -250,7 +250,7 @@ static UINT32 opCMPSTRH(UINT8 bFill, UINT8 bStop)
|
||||
|
||||
F7aDecodeOperands(ReadAMAddress,0,ReadAMAddress,0);
|
||||
|
||||
// Filling
|
||||
/* Filling */
|
||||
if (bFill)
|
||||
{
|
||||
if (f7aLenOp1 < f7aLenOp2)
|
||||
@@ -316,10 +316,10 @@ static UINT32 opMOVSTRUB(UINT8 bFill, UINT8 bStop) /* TRUSTED (0,0) (1,0) */
|
||||
UINT32 i,dest;
|
||||
UINT8 c1;
|
||||
|
||||
// if (bStop)
|
||||
// {
|
||||
// int a=1;
|
||||
// }
|
||||
/* if (bStop) */
|
||||
/* { */
|
||||
/* int a=1; */
|
||||
/* } */
|
||||
|
||||
F7aDecodeOperands(ReadAMAddress,0,ReadAMAddress,0);
|
||||
|
||||
@@ -386,8 +386,8 @@ static UINT32 opMOVSTRUH(UINT8 bFill, UINT8 bStop) /* TRUSTED (0,0) (1,0) */
|
||||
UINT32 i,dest;
|
||||
UINT16 c1;
|
||||
|
||||
// if (bStop)
|
||||
// { int a=1; }
|
||||
/* if (bStop) */
|
||||
/* { int a=1; } */
|
||||
|
||||
F7aDecodeOperands(ReadAMAddress,1,ReadAMAddress,1);
|
||||
|
||||
@@ -420,13 +420,13 @@ static UINT32 opMOVSTRDH(UINT8 bFill, UINT8 bStop)
|
||||
UINT32 i,dest;
|
||||
UINT16 c1;
|
||||
|
||||
// if (bFill | bStop)
|
||||
// { int a=1; }
|
||||
/* if (bFill | bStop) */
|
||||
/* { int a=1; } */
|
||||
|
||||
F7aDecodeOperands(ReadAMAddress,1,ReadAMAddress,1);
|
||||
|
||||
// if (f7aLenOp1 != f7aLenOp2)
|
||||
// { int a=1; }
|
||||
/* if (f7aLenOp1 != f7aLenOp2) */
|
||||
/* { int a=1; } */
|
||||
|
||||
dest=(f7aLenOp1 < f7aLenOp2 ? f7aLenOp1 : f7aLenOp2);
|
||||
|
||||
@@ -469,7 +469,7 @@ static UINT32 opSEARCHUB(UINT8 bSearch)
|
||||
R28=f7bOp1+i;
|
||||
R27=i;
|
||||
|
||||
// This is the opposite as stated in V60 manual...
|
||||
/* This is the opposite as stated in V60 manual... */
|
||||
if (i!=f7bLen)
|
||||
_Z=0;
|
||||
else
|
||||
@@ -520,7 +520,7 @@ static UINT32 opSEARCHDB(UINT8 bSearch)
|
||||
R28=f7bOp1+i;
|
||||
R27=i;
|
||||
|
||||
// This is the opposite as stated in V60 manual...
|
||||
/* This is the opposite as stated in V60 manual... */
|
||||
if ((UINT32)i!=f7bLen)
|
||||
_Z=0;
|
||||
else
|
||||
@@ -635,37 +635,37 @@ static UINT32 opSCHBS(UINT32 bSearch1)
|
||||
|
||||
F7bDecodeFirstOperand(BitReadAMAddress,10);
|
||||
|
||||
// Read first UINT8
|
||||
/* Read first UINT8 */
|
||||
f7bOp1 += bamOffset/8;
|
||||
data = MemRead8(f7bOp1);
|
||||
offset = bamOffset&7;
|
||||
|
||||
// Scan bitstring
|
||||
/* Scan bitstring */
|
||||
for (i=0;i<f7bLen;i++)
|
||||
{
|
||||
// Update the work register
|
||||
/* Update the work register */
|
||||
R28 = f7bOp1;
|
||||
|
||||
// There is a 0/1 at current offset?
|
||||
/* There is a 0/1 at current offset? */
|
||||
if ((bSearch1 && (data&(1<<offset))) ||
|
||||
(!bSearch1 && !(data&(1<<offset))))
|
||||
break;
|
||||
|
||||
// Next bit please
|
||||
/* Next bit please */
|
||||
offset++;
|
||||
if (offset==8)
|
||||
{
|
||||
// Next UINT8 please
|
||||
/* Next UINT8 please */
|
||||
offset=0;
|
||||
f7bOp1++;
|
||||
data = MemRead8(f7bOp1);
|
||||
}
|
||||
}
|
||||
|
||||
// Set zero if bit not found
|
||||
/* Set zero if bit not found */
|
||||
_Z = (i == f7bLen);
|
||||
|
||||
// Write to destination the final offset
|
||||
/* Write to destination the final offset */
|
||||
modWriteValW = i;
|
||||
F7bWriteSecondOperand(2);
|
||||
|
||||
@@ -722,8 +722,8 @@ static UINT32 opMOVBSD(void)
|
||||
|
||||
F7bDecodeOperands(BitReadAMAddress,10,BitReadAMAddress,10);
|
||||
|
||||
// if (f7bLen!=1)
|
||||
// { int a=1; }
|
||||
/* if (f7bLen!=1) */
|
||||
/* { int a=1; } */
|
||||
|
||||
f7bBamOffset1 += f7bLen-1;
|
||||
f7bBamOffset2 += f7bLen-1;
|
||||
@@ -739,7 +739,7 @@ static UINT32 opMOVBSD(void)
|
||||
|
||||
for (i=0;i<f7bLen;i++)
|
||||
{
|
||||
// Update work registers
|
||||
/* Update work registers */
|
||||
R28 = f7bOp1;
|
||||
R27 = f7bOp2;
|
||||
|
||||
@@ -764,7 +764,7 @@ static UINT32 opMOVBSD(void)
|
||||
f7bBamOffset2--;
|
||||
}
|
||||
|
||||
// Flush of the final data
|
||||
/* Flush of the final data */
|
||||
if (f7bBamOffset2 != 7)
|
||||
MemWrite8(f7bOp2, dstdata);
|
||||
|
||||
@@ -789,7 +789,7 @@ static UINT32 opMOVBSU(void)
|
||||
|
||||
for (i=0;i<f7bLen;i++)
|
||||
{
|
||||
// Update work registers
|
||||
/* Update work registers */
|
||||
R28 = f7bOp1;
|
||||
R27 = f7bOp2;
|
||||
|
||||
@@ -813,14 +813,14 @@ static UINT32 opMOVBSU(void)
|
||||
}
|
||||
}
|
||||
|
||||
// Flush of the final data
|
||||
/* Flush of the final data */
|
||||
if (f7bBamOffset2 != 0)
|
||||
MemWrite8(f7bOp2, dstdata);
|
||||
|
||||
F7BEND();
|
||||
}
|
||||
|
||||
// RADM 0x20f4b8 holds the time left
|
||||
/* RADM 0x20f4b8 holds the time left */
|
||||
|
||||
static UINT32 opADDDC(void)
|
||||
{
|
||||
@@ -849,9 +849,9 @@ static UINT32 opADDDC(void)
|
||||
else
|
||||
_CY = 0;
|
||||
|
||||
// compute z flag:
|
||||
// cleared if result non-zero or carry generated
|
||||
// unchanged otherwise
|
||||
/* compute z flag: */
|
||||
/* cleared if result non-zero or carry generated */
|
||||
/* unchanged otherwise */
|
||||
if (appb != 0 || _CY)
|
||||
_Z = 0;
|
||||
|
||||
@@ -878,7 +878,7 @@ static UINT32 opSUBDC(void)
|
||||
src = (UINT32)(f7cOp1 >> 4) * 10 + (UINT32)(f7cOp1 & 0xF);
|
||||
dst = ((appb & 0xF0) >> 4) * 10 + (appb & 0xF);
|
||||
|
||||
// Note that this APPB must be SIGNED!
|
||||
/* Note that this APPB must be SIGNED! */
|
||||
appb = (INT32)dst - (INT32)src - (_CY?1:0);
|
||||
|
||||
if (appb < 0)
|
||||
@@ -889,9 +889,9 @@ static UINT32 opSUBDC(void)
|
||||
else
|
||||
_CY = 0;
|
||||
|
||||
// compute z flag:
|
||||
// cleared if result non-zero or carry generated
|
||||
// unchanged otherwise
|
||||
/* compute z flag: */
|
||||
/* cleared if result non-zero or carry generated */
|
||||
/* unchanged otherwise */
|
||||
if (appb != 0 || _CY)
|
||||
_Z = 0;
|
||||
|
||||
@@ -918,7 +918,7 @@ static UINT32 opSUBRDC(void)
|
||||
src = (UINT32)(f7cOp1 >> 4) * 10 + (UINT32)(f7cOp1 & 0xF);
|
||||
dst = ((appb & 0xF0) >> 4) * 10 + (appb & 0xF);
|
||||
|
||||
// Note that this APPB must be SIGNED!
|
||||
/* Note that this APPB must be SIGNED! */
|
||||
appb = (INT32)src - (INT32)dst - (_CY?1:0);
|
||||
|
||||
if (appb < 0)
|
||||
@@ -929,9 +929,9 @@ static UINT32 opSUBRDC(void)
|
||||
else
|
||||
_CY = 0;
|
||||
|
||||
// compute z flag:
|
||||
// cleared if result non-zero or carry generated
|
||||
// unchanged otherwise
|
||||
/* compute z flag: */
|
||||
/* cleared if result non-zero or carry generated */
|
||||
/* unchanged otherwise */
|
||||
if (appb != 0 || _CY)
|
||||
_Z = 0;
|
||||
|
||||
@@ -951,7 +951,7 @@ static UINT32 opCVTDPZ(void)
|
||||
apph |= (f7cLen);
|
||||
apph |= (f7cLen<<8);
|
||||
|
||||
// Z flag is unchanged if src is zero, cleared otherwise
|
||||
/* Z flag is unchanged if src is zero, cleared otherwise */
|
||||
if (f7cOp1 != 0) _Z = 0;
|
||||
|
||||
F7CSTOREOP2HALF();
|
||||
@@ -965,13 +965,13 @@ static UINT32 opCVTDZP(void)
|
||||
|
||||
if ((f7cOp1 & 0xF0) != (f7cLen & 0xF0) || ((f7cOp1 >> 8) & 0xF0) != (f7cLen & 0xF0))
|
||||
{
|
||||
// Decimal exception
|
||||
/* Decimal exception */
|
||||
logerror("CVTD.ZP Decimal exception #1!\n");
|
||||
}
|
||||
|
||||
if ((f7cOp1 & 0xF) > 9 || ((f7cOp1 >> 8) & 0xF) > 9)
|
||||
{
|
||||
// Decimal exception
|
||||
/* Decimal exception */
|
||||
logerror("CVTD.ZP Decimal exception #2!\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
static UINT32 (*OpCodeTable[256])(void) =
|
||||
//static UINT32 (*const OpCodeTable[256])(void) =
|
||||
/*static UINT32 (*const OpCodeTable[256])(void) = */
|
||||
{
|
||||
/* 0x00 */ opHALT,
|
||||
/* 0x01 */ opLDTASK,
|
||||
|
||||
+79
-10
@@ -7,6 +7,7 @@
|
||||
#include "osd_cpu.h"
|
||||
#include "mamedbg.h"
|
||||
#include "state.h"
|
||||
#include <math.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
@@ -278,17 +279,17 @@ UINT32 v60_update_psw_for_exception(int is_interrupt, int target_level)
|
||||
UINT32 oldPSW = v60ReadPSW();
|
||||
UINT32 newPSW = oldPSW;
|
||||
|
||||
// Change to interrupt context
|
||||
newPSW &= ~(3 << 24); // PSW.EL = 0
|
||||
newPSW |= target_level << 24; // set target level
|
||||
newPSW &= ~(1 << 18); // PSW.IE = 0
|
||||
newPSW &= ~(1 << 16); // PSW.TE = 0
|
||||
newPSW &= ~(1 << 27); // PSW.TP = 0
|
||||
newPSW &= ~(1 << 17); // PSW.AE = 0
|
||||
newPSW &= ~(1 << 29); // PSW.EM = 0
|
||||
/* Change to interrupt context */
|
||||
newPSW &= ~(3 << 24); /* PSW.EL = 0 */
|
||||
newPSW |= target_level << 24; /* set target level */
|
||||
newPSW &= ~(1 << 18); /* PSW.IE = 0 */
|
||||
newPSW &= ~(1 << 16); /* PSW.TE = 0 */
|
||||
newPSW &= ~(1 << 27); /* PSW.TP = 0 */
|
||||
newPSW &= ~(1 << 17); /* PSW.AE = 0 */
|
||||
newPSW &= ~(1 << 29); /* PSW.EM = 0 */
|
||||
if (is_interrupt)
|
||||
newPSW |= (1 << 28);// PSW.IS = 1
|
||||
newPSW |= (1 << 31); // PSW.ASA = 1
|
||||
newPSW |= (1 << 28);/* PSW.IS = 1 */
|
||||
newPSW |= (1 << 31); /* PSW.ASA = 1 */
|
||||
v60WritePSW(newPSW);
|
||||
|
||||
return oldPSW;
|
||||
@@ -359,6 +360,7 @@ static void base_init(const char *type)
|
||||
|
||||
v60.irq_cb = v60_default_irq_cb;
|
||||
v60.irq_line = CLEAR_LINE;
|
||||
v60_set_idle_loops(NULL, 0);
|
||||
v60.nmi_line = CLEAR_LINE;
|
||||
|
||||
state_save_register_UINT32(type, cpu, "reg", v60.reg, 68);
|
||||
@@ -409,6 +411,7 @@ void v60_reset(void *param)
|
||||
|
||||
void v60_exit(void)
|
||||
{
|
||||
v60_set_idle_loops(NULL, 0);
|
||||
}
|
||||
|
||||
static void v60_do_irq(int vector)
|
||||
@@ -484,9 +487,73 @@ void v60_set_irq_callback(int (*irq_cb)(int irqline))
|
||||
|
||||
/* Actual cycles/instruction is unknown*/
|
||||
|
||||
/*
|
||||
Idle loop fast-forward (opt-in, set by the driver with v60_set_idle_loops)
|
||||
|
||||
A game that waits for an interrupt by polling RAM spends most of its time
|
||||
in a loop like "[inc counter] / test mem / branch back". Only the CPU
|
||||
itself can change that RAM, and the interrupt line does not change while
|
||||
the CPU runs its slice. So once a whole iteration has run without an
|
||||
interrupt (the branch back came exactly one iteration of cycles after the
|
||||
previous one), every further iteration of the slice is the same: the
|
||||
counter goes up by one and 8 cycles are spent per instruction. This runs
|
||||
those iterations at once, leaving the last one and the end of the slice
|
||||
to the interpreter, so the CPU state, the counter and the cycle count are
|
||||
exactly what the instruction-by-instruction run gives.
|
||||
|
||||
The whole uninterrupted iteration is needed: an interrupt taken between
|
||||
the test and the branch returns to the branch with the flags of the old
|
||||
test, so a branch back alone does not prove that the loop goes on.
|
||||
*/
|
||||
|
||||
static const struct v60_idle_loop *v60_idle;
|
||||
static int v60_idle_count;
|
||||
static int v60_idle_armed; /* index + 1 of the loop seen at the last branch back in this slice */
|
||||
static int v60_idle_icount; /* v60_ICount at that branch back */
|
||||
|
||||
void v60_set_idle_loops(const struct v60_idle_loop *loops, int count)
|
||||
{
|
||||
v60_idle = loops;
|
||||
v60_idle_count = loops ? count : 0;
|
||||
v60_idle_armed = 0;
|
||||
}
|
||||
|
||||
static void v60_idle_fast_forward(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < v60_idle_count; i++)
|
||||
{
|
||||
const struct v60_idle_loop *l = &v60_idle[i];
|
||||
if (PC == l->start && PPC == l->branch)
|
||||
{
|
||||
int iteration = 8 * l->instructions;
|
||||
if (v60_idle_armed == i + 1 && v60_idle_icount - v60_ICount == iteration)
|
||||
{
|
||||
int k = v60_ICount / iteration - 1;
|
||||
if (k > 0)
|
||||
{
|
||||
v60_ICount -= k * iteration;
|
||||
switch (l->counter)
|
||||
{
|
||||
case V60_IDLE_COUNTER_REG: v60.reg[l->counter_addr] += k; break;
|
||||
case V60_IDLE_COUNTER_MEM8: MemWrite8(l->counter_addr, (UINT8)(MemRead8(l->counter_addr) + k)); break;
|
||||
case V60_IDLE_COUNTER_MEM16: MemWrite16(l->counter_addr, (UINT16)(MemRead16(l->counter_addr) + k)); break;
|
||||
case V60_IDLE_COUNTER_MEM32: MemWrite32(l->counter_addr, MemRead32(l->counter_addr) + k); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
v60_idle_armed = i + 1;
|
||||
v60_idle_icount = v60_ICount;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int v60_execute(int cycles)
|
||||
{
|
||||
v60_ICount = cycles;
|
||||
v60_idle_armed = 0;
|
||||
if(v60.irq_line != CLEAR_LINE)
|
||||
v60_try_irq();
|
||||
while(v60_ICount >= 0) {
|
||||
@@ -496,6 +563,8 @@ int v60_execute(int cycles)
|
||||
PC += OpCodeTable[OpRead8(PC)]();
|
||||
if(v60.irq_line != CLEAR_LINE)
|
||||
v60_try_irq();
|
||||
if(v60_idle_count)
|
||||
v60_idle_fast_forward();
|
||||
}
|
||||
|
||||
return cycles - v60_ICount;
|
||||
|
||||
@@ -112,4 +112,27 @@ const char *v70_info(void *context, int regnum);
|
||||
#define v70_set_reg v60_set_reg
|
||||
#define v70_set_irq_line v60_set_irq_line
|
||||
#define v70_set_irq_callback v60_set_irq_callback
|
||||
/* idle loop fast-forward: a loop of "instructions" instructions from "start"
|
||||
to the branch back at "branch", that only polls RAM and optionally counts
|
||||
its iterations in a register or in memory (see v60.c) */
|
||||
enum
|
||||
{
|
||||
V60_IDLE_COUNTER_NONE = 0,
|
||||
V60_IDLE_COUNTER_REG,
|
||||
V60_IDLE_COUNTER_MEM8,
|
||||
V60_IDLE_COUNTER_MEM16,
|
||||
V60_IDLE_COUNTER_MEM32
|
||||
};
|
||||
|
||||
struct v60_idle_loop
|
||||
{
|
||||
UINT32 start;
|
||||
UINT32 branch;
|
||||
int instructions;
|
||||
int counter;
|
||||
UINT32 counter_addr; /* register number or address */
|
||||
};
|
||||
|
||||
void v60_set_idle_loops(const struct v60_idle_loop *loops, int count);
|
||||
|
||||
#endif
|
||||
@@ -375,7 +375,7 @@ static struct cpu_info v70_i =
|
||||
#define PortRead32 v60.info.pr32
|
||||
#define PortWrite32 v60.info.pw32
|
||||
|
||||
#if !defined(MSB_FIRST) && !defined(ALIGN_INTS)
|
||||
#if defined(LSB_FIRST) && !defined(ALIGN_INTS)
|
||||
#define OpRead8(a) (OP_ROM[a])
|
||||
#define OpRead16(a) (*(UINT16 *)&OP_ROM[a])
|
||||
#define OpRead32(a) (*(UINT32 *)&OP_ROM[a])
|
||||
|
||||
+32
-28
@@ -85,6 +85,14 @@
|
||||
#include "z80.h"
|
||||
#include "log.h"
|
||||
|
||||
#define VERBOSE 0
|
||||
|
||||
#if VERBOSE
|
||||
#define LOG(x) logerror x
|
||||
#else
|
||||
#define LOG(x)
|
||||
#endif
|
||||
|
||||
/* execute main opcodes inside a big switch statement */
|
||||
#ifndef BIG_SWITCH
|
||||
#define BIG_SWITCH 1
|
||||
@@ -811,7 +819,7 @@ static INLINE UINT32 ARG16(void)
|
||||
* RETN
|
||||
***************************************************************/
|
||||
#define RETN { \
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Z80 #%d RETN IFF1:%d IFF2:%d\n", cpu_getactivecpu(), _IFF1, _IFF2); \
|
||||
LOG(("Z80 #%d RETN IFF1:%d IFF2:%d\n", cpu_getactivecpu(), _IFF1, _IFF2)); \
|
||||
POP(PC); \
|
||||
change_pc16(_PCD); \
|
||||
if( _IFF1 == 0 && _IFF2 == 1 ) \
|
||||
@@ -820,8 +828,8 @@ static INLINE UINT32 ARG16(void)
|
||||
if( Z80.irq_state != CLEAR_LINE || \
|
||||
Z80.request_irq >= 0 ) \
|
||||
{ \
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Z80 #%d RETN takes IRQ\n", \
|
||||
cpu_getactivecpu()); \
|
||||
LOG(("Z80 #%d RETN takes IRQ\n", \
|
||||
cpu_getactivecpu())); \
|
||||
take_interrupt(); \
|
||||
} \
|
||||
} \
|
||||
@@ -839,8 +847,8 @@ static INLINE UINT32 ARG16(void)
|
||||
/* _IFF1 = _IFF2; */ \
|
||||
if( device >= 0 ) \
|
||||
{ \
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Z80 #%d RETI device %d: $%02x\n", \
|
||||
cpu_getactivecpu(), device, Z80.irq[device].irq_param); \
|
||||
LOG(("Z80 #%d RETI device %d: $%02x\n", \
|
||||
cpu_getactivecpu(), device, Z80.irq[device].irq_param)); \
|
||||
Z80.irq[device].interrupt_reti(Z80.irq[device].irq_param); \
|
||||
} \
|
||||
}
|
||||
@@ -1977,8 +1985,8 @@ static INLINE UINT8 SET(UINT8 bit, UINT8 value)
|
||||
_R++; \
|
||||
while( cpu_readop(_PCD) == 0xfb ) /* more EIs? */ \
|
||||
{ \
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Z80 #%d multiple EI opcodes at %04X\n", \
|
||||
cpu_getactivecpu(), _PC); \
|
||||
LOG(("Z80 #%d multiple EI opcodes at %04X\n", \
|
||||
cpu_getactivecpu(), _PC)); \
|
||||
CC(op,0xfb); \
|
||||
_PPC =_PCD; \
|
||||
CALL_MAME_DEBUG; \
|
||||
@@ -1991,7 +1999,7 @@ static INLINE UINT8 SET(UINT8 bit, UINT8 value)
|
||||
after_EI = 1; /* avoid cycle skip hacks */ \
|
||||
EXEC(op,ROP()); \
|
||||
after_EI = 0; \
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Z80 #%d EI takes irq\n", cpu_getactivecpu()); \
|
||||
LOG(("Z80 #%d EI takes irq\n", cpu_getactivecpu())); \
|
||||
take_interrupt(); \
|
||||
} else EXEC(op,ROP()); \
|
||||
} else _IFF2 = 1; \
|
||||
@@ -2583,7 +2591,7 @@ OP(xycb,fe) { WM( EA, SET(7,RM(EA)) ); } /* SET 7,(XY+o) */
|
||||
OP(xycb,ff) { _A = SET(7, RM(EA) ); WM( EA,_A ); } /* SET 7,A=(XY+o) */
|
||||
|
||||
OP(illegal,1) {
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Z80 #%d ill. opcode $%02x $%02x\n",
|
||||
logerror("Z80 #%d ill. opcode $%02x $%02x\n",
|
||||
cpu_getactivecpu(), cpu_readop((_PCD-1)&0xffff), cpu_readop(_PCD));
|
||||
}
|
||||
|
||||
@@ -3171,7 +3179,7 @@ OP(fd,ff) { illegal_1(); op_ff(); } /* DB FD */
|
||||
|
||||
OP(illegal,2)
|
||||
{
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Z80 #%d ill. opcode $ed $%02x\n",
|
||||
logerror("Z80 #%d ill. opcode $ed $%02x\n",
|
||||
cpu_getactivecpu(), cpu_readop((_PCD-1)&0xffff));
|
||||
}
|
||||
|
||||
@@ -3917,7 +3925,7 @@ static void take_interrupt(void)
|
||||
/* Clear both interrupt flip flops */
|
||||
_IFF1 = _IFF2 = 0;
|
||||
irq_vector = Z80.irq[Z80.request_irq].interrupt_entry(Z80.irq[Z80.request_irq].irq_param);
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Z80 #%d daisy chain irq_vector $%02x\n", cpu_getactivecpu(), irq_vector);
|
||||
LOG(("Z80 #%d daisy chain irq_vector $%02x\n", cpu_getactivecpu(), irq_vector));
|
||||
Z80.request_irq = -1;
|
||||
} else return;
|
||||
}
|
||||
@@ -3927,7 +3935,7 @@ static void take_interrupt(void)
|
||||
_IFF1 = _IFF2 = 0;
|
||||
/* call back the cpu interface to retrieve the vector */
|
||||
irq_vector = (*Z80.irq_callback)(0);
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Z80 #%d single int. irq_vector $%02x\n", cpu_getactivecpu(), irq_vector);
|
||||
LOG(("Z80 #%d single int. irq_vector $%02x\n", cpu_getactivecpu(), irq_vector));
|
||||
}
|
||||
|
||||
/* Interrupt mode 2. Call [Z80.I:databyte] */
|
||||
@@ -3936,7 +3944,7 @@ static void take_interrupt(void)
|
||||
irq_vector = (irq_vector & 0xff) | (_I << 8);
|
||||
PUSH( PC );
|
||||
RM16( irq_vector, &Z80.PC );
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Z80 #%d IM2 [$%04x] = $%04x\n",cpu_getactivecpu() , irq_vector, _PCD);
|
||||
LOG(("Z80 #%d IM2 [$%04x] = $%04x\n",cpu_getactivecpu() , irq_vector, _PCD));
|
||||
/* CALL opcode timing */
|
||||
Z80.extra_cycles += cc[Z80_TABLE_op][0xcd];
|
||||
}
|
||||
@@ -3944,7 +3952,7 @@ static void take_interrupt(void)
|
||||
/* Interrupt mode 1. RST 38h */
|
||||
if( _IM == 1 )
|
||||
{
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Z80 #%d IM1 $0038\n",cpu_getactivecpu());
|
||||
LOG(("Z80 #%d IM1 $0038\n",cpu_getactivecpu() ));
|
||||
PUSH( PC );
|
||||
_PCD = 0x0038;
|
||||
/* RST $38 + 'interrupt latency' cycles */
|
||||
@@ -3955,7 +3963,7 @@ static void take_interrupt(void)
|
||||
/* Interrupt mode 0. We check for CALL and JP instructions, */
|
||||
/* if neither of these were found we assume a 1 byte opcode */
|
||||
/* was placed on the databus */
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Z80 #%d IM0 $%04x\n",cpu_getactivecpu() , irq_vector);
|
||||
LOG(("Z80 #%d IM0 $%04x\n",cpu_getactivecpu() , irq_vector));
|
||||
switch (irq_vector & 0xff0000)
|
||||
{
|
||||
case 0xcd0000: /* call */
|
||||
@@ -3999,11 +4007,7 @@ void z80_init(void)
|
||||
SZHVC_sub = (UINT8 *)malloc(2*256*256);
|
||||
if( !SZHVC_add || !SZHVC_sub )
|
||||
{
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Z80: failed to allocate 2 * 128K flags arrays!!!\n");
|
||||
|
||||
/* TODO: Don't abort, switch back to main thread and exit cleanly:
|
||||
* This is only used if a malloc fails in src/cpu/z80/z80.c so not too high a priority */
|
||||
abort();
|
||||
osd_die("Z80: failed to allocate 2 * 128K flags arrays!!!\n");
|
||||
}
|
||||
padd = &SZHVC_add[ 0*256];
|
||||
padc = &SZHVC_add[256*256];
|
||||
@@ -4332,11 +4336,11 @@ void z80_set_irq_line(int irqline, int state)
|
||||
{
|
||||
if( Z80.nmi_state == state ) return;
|
||||
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Z80 #%d set_irq_line (NMI) %d\n", cpu_getactivecpu(), state);
|
||||
LOG(("Z80 #%d set_irq_line (NMI) %d\n", cpu_getactivecpu(), state));
|
||||
Z80.nmi_state = state;
|
||||
if( state == CLEAR_LINE ) return;
|
||||
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Z80 #%d take NMI\n", cpu_getactivecpu());
|
||||
LOG(("Z80 #%d take NMI\n", cpu_getactivecpu()));
|
||||
_PPC = -1; /* there isn't a valid previous program counter */
|
||||
LEAVE_HALT; /* Check if processor was halted */
|
||||
|
||||
@@ -4347,7 +4351,7 @@ void z80_set_irq_line(int irqline, int state)
|
||||
}
|
||||
else
|
||||
{
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Z80 #%d set_irq_line %d\n",cpu_getactivecpu() , state);
|
||||
LOG(("Z80 #%d set_irq_line %d\n",cpu_getactivecpu() , state));
|
||||
Z80.irq_state = state;
|
||||
if( state == CLEAR_LINE ) return;
|
||||
|
||||
@@ -4357,11 +4361,11 @@ void z80_set_irq_line(int irqline, int state)
|
||||
daisychain = (*Z80.irq_callback)(irqline);
|
||||
device = daisychain >> 8;
|
||||
int_state = daisychain & 0xff;
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Z80 #%d daisy chain $%04x -> device %d, state $%02x",cpu_getactivecpu(), daisychain, device, int_state);
|
||||
LOG(("Z80 #%d daisy chain $%04x -> device %d, state $%02x",cpu_getactivecpu(), daisychain, device, int_state));
|
||||
|
||||
if( Z80.int_state[device] != int_state )
|
||||
{
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE " change\n");
|
||||
LOG((" change\n"));
|
||||
/* set new interrupt status */
|
||||
Z80.int_state[device] = int_state;
|
||||
/* check interrupt status */
|
||||
@@ -4380,12 +4384,12 @@ void z80_set_irq_line(int irqline, int state)
|
||||
if( Z80.int_state[device] & Z80_INT_REQ )
|
||||
Z80.request_irq = device;
|
||||
}
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Z80 #%d daisy chain service_irq $%02x, request_irq $%02x\n", cpu_getactivecpu(), Z80.service_irq, Z80.request_irq);
|
||||
LOG(("Z80 #%d daisy chain service_irq $%02x, request_irq $%02x\n", cpu_getactivecpu(), Z80.service_irq, Z80.request_irq));
|
||||
if( Z80.request_irq < 0 ) return;
|
||||
}
|
||||
else
|
||||
{
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE " no change\n");
|
||||
LOG((" no change\n"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -4398,7 +4402,7 @@ void z80_set_irq_line(int irqline, int state)
|
||||
****************************************************************************/
|
||||
void z80_set_irq_callback(int (*callback)(int))
|
||||
{
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Z80 #%d set_irq_callback $%08x\n",cpu_getactivecpu() , (int)callback);
|
||||
LOG(("Z80 #%d set_irq_callback $%08x\n",cpu_getactivecpu() , (int)callback));
|
||||
Z80.irq_callback = callback;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,16 +4,7 @@
|
||||
#include "drz80_z80.h"
|
||||
#include "drz80.h"
|
||||
|
||||
typedef struct {
|
||||
struct DrZ80 regs;
|
||||
unsigned int nmi_state;
|
||||
unsigned int irq_state;
|
||||
int previouspc;
|
||||
int (*MAMEIrqCallback)(int int_level);
|
||||
} drz80_regs;
|
||||
|
||||
static drz80_regs DRZ80;
|
||||
int drz80_ICount;
|
||||
drz80_regs DRZ80;
|
||||
|
||||
#define INT_IRQ 0x01
|
||||
#define NMI_IRQ 0x02
|
||||
@@ -129,10 +120,8 @@ void drz80_exit(void)
|
||||
int drz80_execute(int cycles)
|
||||
{
|
||||
DRZ80.regs.cycles = cycles;
|
||||
drz80_ICount = DRZ80.regs.cycles;
|
||||
DrZ80Run(&DRZ80.regs, cycles);
|
||||
change_pc16(DRZ80.regs.Z80PC - DRZ80.regs.Z80PC_BASE);
|
||||
drz80_ICount = DRZ80.regs.cycles;
|
||||
return (cycles-DRZ80.regs.cycles);
|
||||
}
|
||||
|
||||
@@ -144,7 +133,6 @@ void drz80_burn(int cycles)
|
||||
int n = (cycles + 3) / 4;
|
||||
//DRZ80.regs.Z80R += n;
|
||||
DRZ80.regs.cycles -= 4 * n;
|
||||
drz80_ICount = DRZ80.regs.cycles;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loaded 100 of 897 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user