trunk/src/mame/machine/snes.c
r17409 | r17410 | |
13 | 13 | Thanks to Anomie for invaluable technical information. |
14 | 14 | Thanks to byuu for invaluable technical information. |
15 | 15 | |
| 16 | TODO: |
| 17 | - DMA takes some Master CPU clock cycles that aren't taken into account |
| 18 | for now. |
| 19 | |
16 | 20 | ***************************************************************************/ |
17 | 21 | #define __MACHINE_SNES_C |
18 | 22 | |
r17409 | r17410 | |
55 | 59 | #include "machine/snes7110.c" |
56 | 60 | #include "machine/snesbsx.c" |
57 | 61 | |
58 | | #define USE_CYCLE_STEAL 1 |
59 | | |
60 | 62 | // ST-010 and ST-011 RAM interface |
61 | 63 | UINT8 st010_read_ram(snes_state *state, UINT16 addr) |
62 | 64 | { |
r17409 | r17410 | |
892 | 894 | |
893 | 895 | */ |
894 | 896 | |
895 | | #if USE_CYCLE_STEAL |
896 | | /*FIXME: missing work RAM access steal / we need to do this less "aggressive" otherwise we lose too much CPU horsepower, why? */ |
897 | | static int snes_bank_0x00_0x3f_cycles(running_machine &machine,UINT32 offset) |
898 | | { |
899 | | /* |
900 | | $00-$3F | $0000-$1FFF | Slow | Address Bus A + /WRAM (mirror $7E:0000-$1FFF) |
901 | | | $2000-$20FF | Fast | Address Bus A |
902 | | | $2100-$21FF | Fast | Address Bus B |
903 | | | $2200-$3FFF | Fast | Address Bus A |
904 | | | $4000-$41FF | XSlow | Internal CPU registers (see Note 1 below) |
905 | | | $4200-$43FF | Fast | Internal CPU registers (see Note 1 below) |
906 | | | $4400-$5FFF | Fast | Address Bus A |
907 | | | $6000-$7FFF | Slow | Address Bus A |
908 | | | $8000-$FFFF | Slow | Address Bus A + /CART |
909 | | */ |
910 | | |
911 | | if(((offset & 0xff00) == 0x4000) || ((offset & 0xff00) == 0x4100)) |
912 | | return 0; //TODO: 12 |
913 | | if(((offset & 0xff00) == 0x4200) || ((offset & 0xff00) == 0x4300)) |
914 | | return 0; //TODO: 6 |
915 | | |
916 | | if((offset & 0xff00) <= 0x1f00) |
917 | | return 0; //TODO: 8 |
918 | | |
919 | | if((offset & 0xff00) >= 0x6000) |
920 | | return 8; |
921 | | |
922 | | return 0; //TODO: 6 |
923 | | } |
924 | | |
925 | | static int snes_bank_0x80_0xbf_cycles(running_machine &machine,UINT32 offset) |
926 | | { |
927 | | /* |
928 | | $80-$BF | $0000-$1FFF | Slow | Address Bus A + /WRAM (mirror $7E:0000-$1FFF) |
929 | | | $2000-$20FF | Fast | Address Bus A |
930 | | | $2100-$21FF | Fast | Address Bus B |
931 | | | $2200-$3FFF | Fast | Address Bus A |
932 | | | $4000-$41FF | XSlow | Internal CPU registers (see Note 1 below) |
933 | | | $4200-$43FF | Fast | Internal CPU registers (see Note 1 below) |
934 | | | $4400-$5FFF | Fast | Address Bus A |
935 | | | $6000-$7FFF | Slow | Address Bus A |
936 | | | $8000-$FFFF | Note2 | Address Bus A + /CART |
937 | | */ |
938 | | |
939 | | |
940 | | if(((offset & 0xff00) == 0x4000) || ((offset & 0xff00) == 0x4100)) |
941 | | return 0; //TODO: 12 |
942 | | |
943 | | if(((offset & 0xff00) == 0x4200) || ((offset & 0xff00) == 0x4300)) |
944 | | return 0; //TODO: 6 |
945 | | |
946 | | if((offset & 0xff00) <= 0x1f00) |
947 | | return 0; //TODO: 8 |
948 | | |
949 | | if(((offset & 0xff00) >= 0x6000) && ((offset & 0xff00) <= 0x7f00)) |
950 | | return 0; //TODO: 8 |
951 | | |
952 | | if(((offset & 0xff00) >= 0x8000) && ((offset & 0xff00) <= 0xff00)) |
953 | | return (snes_ram[MEMSEL] & 1) ? 6 : 8; |
954 | | |
955 | | return 0; //TODO: 6 |
956 | | } |
957 | | #endif |
958 | | |
959 | 897 | /* 0x000000 - 0x2fffff */ |
960 | 898 | READ8_HANDLER( snes_r_bank1 ) |
961 | 899 | { |
r17409 | r17410 | |
1007 | 945 | else |
1008 | 946 | value = snes_ram[offset]; |
1009 | 947 | |
1010 | | #if USE_CYCLE_STEAL |
1011 | | if(!space->debugger_access()) |
1012 | | device_adjust_icount(&space->device(), -snes_bank_0x00_0x3f_cycles(space->machine(), offset)); |
1013 | | #endif |
1014 | | |
1015 | 948 | return value; |
1016 | 949 | } |
1017 | 950 | |
r17409 | r17410 | |
1074 | 1007 | else |
1075 | 1008 | value = snes_ram[0x300000 + offset]; |
1076 | 1009 | |
1077 | | #if USE_CYCLE_STEAL |
1078 | | if(!space->debugger_access()) |
1079 | | device_adjust_icount(&space->device(), -snes_bank_0x00_0x3f_cycles(space->machine(), offset)); |
1080 | | #endif |
1081 | | |
1082 | 1010 | return value; |
1083 | 1011 | } |
1084 | 1012 | |
r17409 | r17410 | |
1117 | 1045 | else /* Mode 21 & 25 + SuperFX games */ |
1118 | 1046 | value = snes_ram[0x400000 + offset]; |
1119 | 1047 | |
1120 | | #if USE_CYCLE_STEAL |
1121 | | if(!space->debugger_access()) |
1122 | | device_adjust_icount(&space->device(), -8); |
1123 | | #endif |
1124 | | |
1125 | 1048 | return value; |
1126 | 1049 | } |
1127 | 1050 | |
r17409 | r17410 | |
1166 | 1089 | else if (state->m_cart[0].mode & 0x0a) /* Mode 21 & 25 */ |
1167 | 1090 | value = snes_ram[0x600000 + offset]; |
1168 | 1091 | |
1169 | | #if USE_CYCLE_STEAL |
1170 | | if(!space->debugger_access()) |
1171 | | device_adjust_icount(&space->device(), -8); |
1172 | | #endif |
1173 | | |
1174 | 1092 | return value; |
1175 | 1093 | } |
1176 | 1094 | |
r17409 | r17410 | |
1204 | 1122 | else |
1205 | 1123 | value = snes_ram[0x700000 + offset]; |
1206 | 1124 | |
1207 | | #if USE_CYCLE_STEAL |
1208 | | if(!space->debugger_access()) |
1209 | | device_adjust_icount(&space->device(), -8); |
1210 | | #endif |
1211 | | |
1212 | 1125 | return value; |
1213 | 1126 | } |
1214 | 1127 | |
r17409 | r17410 | |
1254 | 1167 | else |
1255 | 1168 | value = snes_ram[0x800000 + offset]; |
1256 | 1169 | |
1257 | | #if USE_CYCLE_STEAL |
1258 | | if(!space->debugger_access()) |
1259 | | device_adjust_icount(&space->device(), -snes_bank_0x80_0xbf_cycles(space->machine(), offset)); |
1260 | | #endif |
1261 | | |
1262 | 1170 | return value; |
1263 | 1171 | } |
1264 | 1172 | |
r17409 | r17410 | |
1318 | 1226 | else /* Mode 21 & 25 + SuperFX Games */ |
1319 | 1227 | value = snes_ram[0xc00000 + offset]; |
1320 | 1228 | |
1321 | | #if USE_CYCLE_STEAL |
1322 | | if(!space->debugger_access()) |
1323 | | device_adjust_icount(&space->device(), -((snes_ram[MEMSEL] & 1) ? 6 : 8)); |
1324 | | #endif |
1325 | | |
1326 | 1229 | return value; |
1327 | 1230 | } |
1328 | 1231 | |
r17409 | r17410 | |
1376 | 1279 | dsp_set_sr(data); |
1377 | 1280 | else |
1378 | 1281 | logerror( "(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(&space->device()),offset ); |
1379 | | |
1380 | | #if USE_CYCLE_STEAL |
1381 | | if(!space->debugger_access()) |
1382 | | device_adjust_icount(&space->device(), -snes_bank_0x00_0x3f_cycles(space->machine(), offset)); |
1383 | | #endif |
1384 | 1282 | } |
1385 | 1283 | |
1386 | 1284 | /* 0x300000 - 0x3fffff */ |
r17409 | r17410 | |
1438 | 1336 | dsp_set_sr(data); |
1439 | 1337 | else |
1440 | 1338 | logerror("(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(&space->device()),offset + 0x300000); |
1441 | | |
1442 | | #if USE_CYCLE_STEAL |
1443 | | if(!space->debugger_access()) |
1444 | | device_adjust_icount(&space->device(), -snes_bank_0x00_0x3f_cycles(space->machine(), offset)); |
1445 | | #endif |
1446 | 1339 | } |
1447 | 1340 | |
1448 | 1341 | /* 0x600000 - 0x6fffff */ |
r17409 | r17410 | |
1479 | 1372 | } |
1480 | 1373 | else if (state->m_cart[0].mode & 0x0a) |
1481 | 1374 | logerror("(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(&space->device()),offset + 0x600000); |
1482 | | |
1483 | | #if USE_CYCLE_STEAL |
1484 | | if(!space->debugger_access()) |
1485 | | device_adjust_icount(&space->device(), -8); |
1486 | | #endif |
1487 | 1375 | } |
1488 | 1376 | |
1489 | 1377 | /* 0x700000 - 0x7dffff */ |
r17409 | r17410 | |
1506 | 1394 | } |
1507 | 1395 | else if (state->m_cart[0].mode & 0x0a) |
1508 | 1396 | logerror("(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(&space->device()),offset + 0x700000); |
1509 | | |
1510 | | #if USE_CYCLE_STEAL |
1511 | | if(!space->debugger_access()) |
1512 | | device_adjust_icount(&space->device(), -8); |
1513 | | #endif |
1514 | 1397 | } |
1515 | 1398 | |
1516 | 1399 | |
r17409 | r17410 | |
1562 | 1445 | dsp_set_sr(data); |
1563 | 1446 | else |
1564 | 1447 | logerror("(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(&space->device()),offset + 0x800000); |
1565 | | |
1566 | | #if USE_CYCLE_STEAL |
1567 | | if(!space->debugger_access()) |
1568 | | device_adjust_icount(&space->device(), -snes_bank_0x80_0xbf_cycles(space->machine(), offset)); |
1569 | | #endif |
1570 | 1448 | } |
1571 | 1449 | |
1572 | 1450 | |
r17409 | r17410 | |
1617 | 1495 | } |
1618 | 1496 | else if (state->m_cart[0].mode & 0x0a) |
1619 | 1497 | logerror("(PC=%06x) Attempt to write to ROM address: %X\n",cpu_get_pc(&space->device()),offset + 0xc00000); |
1620 | | |
1621 | | #if USE_CYCLE_STEAL |
1622 | | if(!space->debugger_access()) |
1623 | | device_adjust_icount(&space->device(), -((snes_ram[MEMSEL] & 1) ? 6 : 8)); |
1624 | | #endif |
1625 | 1498 | } |
1626 | 1499 | |
1627 | 1500 | |
r17409 | r17410 | |
2143 | 2016 | { |
2144 | 2017 | snes_state *state = space->machine().driver_data<snes_state>(); |
2145 | 2018 | |
2146 | | #if USE_CYCLE_STEAL |
2147 | | /* every byte transfer takes 8 master cycles */ |
2148 | | // FIXME: this cycle steal makes Final Fantasy VI (III in US) very glitchy! |
2149 | | // device_adjust_icount(&space->device(),-8); |
2150 | | #endif |
2151 | | |
2152 | 2019 | if (state->m_dma_channel[dma].dmap & 0x80) /* PPU->CPU */ |
2153 | 2020 | { |
2154 | 2021 | if (bbus == 0x2180 && ((abus & 0xfe0000) == 0x7e0000 || (abus & 0x40e000) == 0x0000)) |
r17409 | r17410 | |
2355 | 2222 | |
2356 | 2223 | /* FIXME: we also need to round to the nearest 8 master cycles */ |
2357 | 2224 | |
2358 | | #if USE_CYCLE_STEAL |
2359 | | /* overhead steals 8 master cycles, correct? */ |
2360 | | device_adjust_icount(&space->device(),-8); |
2361 | | #endif |
2362 | | |
2363 | 2225 | /* Assume priority of the 8 DMA channels is 0-7 */ |
2364 | 2226 | for (i = 0; i < 8; i++) |
2365 | 2227 | { |
r17409 | r17410 | |
2468 | 2330 | /* We're done, so write the new abus back to the registers */ |
2469 | 2331 | state->m_dma_channel[i].src_addr = abus; |
2470 | 2332 | state->m_dma_channel[i].trans_size = 0; |
2471 | | |
2472 | | #if USE_CYCLE_STEAL |
2473 | | /* active channel takes 8 master cycles */ |
2474 | | device_adjust_icount(&space->device(),-8); |
2475 | | #endif |
2476 | 2333 | } |
2477 | 2334 | } |
2478 | 2335 | |
2479 | | /* finally, take yet another 8 master cycles for the aforementioned overhead */ |
2480 | | #if USE_CYCLE_STEAL |
2481 | | device_adjust_icount(&space->device(),-8); |
2482 | | #endif |
2483 | 2336 | } |
2484 | 2337 | |
2485 | 2338 | READ8_HANDLER( superfx_r_bank1 ) |