trunk/src/mame/machine/kaneko_calc3.c
| r31856 | r31857 | |
| 28 | 28 | const device_type KANEKO_CALC3 = &device_creator<kaneko_calc3_device>; |
| 29 | 29 | |
| 30 | 30 | kaneko_calc3_device::kaneko_calc3_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 31 | | : device_t(mconfig, KANEKO_CALC3, "Kaneko CALC3 MCU", tag, owner, clock, "kaneko_calc3", __FILE__) |
| 31 | : device_t(mconfig, KANEKO_CALC3, "Kaneko CALC3 MCU", tag, owner, clock, "kaneko_calc3", __FILE__), |
| 32 | m_mcu_status(0), |
| 33 | m_mcu_command_offset(0), |
| 34 | m_mcu_crc(0), |
| 35 | m_decryption_key_byte(0), |
| 36 | m_alternateswaps(0), |
| 37 | m_shift(0), |
| 38 | m_subtracttype(0), |
| 39 | m_mode(0), |
| 40 | m_blocksize_offset(0), |
| 41 | m_dataend(0), |
| 42 | m_database(0), |
| 43 | m_writeaddress(0), |
| 44 | m_writeaddress_current(0), |
| 45 | m_dsw_addr(0), |
| 46 | m_eeprom_addr(0), |
| 47 | m_poll_addr(0), |
| 48 | m_checksumaddress(0), |
| 49 | m_mcuram(NULL) |
| 32 | 50 | { |
| 33 | | memset(&m_calc3, 0, sizeof m_calc3); |
| 51 | m_data_header[0] = m_data_header[1] = 0; |
| 34 | 52 | } |
| 35 | 53 | |
| 36 | 54 | |
| 37 | | TIMER_CALLBACK_MEMBER( kaneko_calc3_device::run_callback ) |
| 38 | | { |
| 39 | | calc3_mcu_run(machine()); |
| 40 | | reset_run_timer(); |
| 41 | | } |
| 42 | | |
| 43 | 55 | void kaneko_calc3_device::device_start() |
| 44 | 56 | { |
| 45 | | m_calc3_mcuram = (UINT16*)auto_alloc_array_clear(this->machine(), UINT16, 0x10000/2); |
| 46 | | initial_scan_tables(this->machine()); |
| 47 | | m_runtimer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(kaneko_calc3_device::run_callback), this)); |
| 57 | m_mcuram = (UINT16*)auto_alloc_array_clear(machine(), UINT16, 0x10000/2); |
| 58 | initial_scan_tables(); |
| 59 | m_runtimer = timer_alloc(MCU_RUN_TIMER); |
| 48 | 60 | |
| 49 | 61 | |
| 50 | | save_item(NAME(m_calc3.mcu_status)); |
| 51 | | save_item(NAME(m_calc3.mcu_command_offset)); |
| 52 | | save_item(NAME(m_calc3.mcu_crc)); |
| 53 | | save_item(NAME(m_calc3.decryption_key_byte)); |
| 54 | | save_item(NAME(m_calc3.alternateswaps)); |
| 55 | | save_item(NAME(m_calc3.shift)); |
| 56 | | save_item(NAME(m_calc3.subtracttype)); |
| 57 | | save_item(NAME(m_calc3.mode)); |
| 58 | | save_item(NAME(m_calc3.blocksize_offset)); |
| 59 | | save_item(NAME(m_calc3.dataend)); |
| 60 | | save_item(NAME(m_calc3.database)); |
| 61 | | save_item(NAME(m_calc3.data_header)); |
| 62 | | save_item(NAME(m_calc3.writeaddress)); |
| 63 | | save_item(NAME(m_calc3.writeaddress_current)); |
| 64 | | save_item(NAME(m_calc3.dsw_addr)); |
| 65 | | save_item(NAME(m_calc3.eeprom_addr)); |
| 66 | | save_item(NAME(m_calc3.poll_addr)); |
| 67 | | save_item(NAME(m_calc3.checksumaddress)); |
| 68 | | save_pointer(NAME(m_calc3_mcuram), 0x10000/2); |
| 62 | save_item(NAME(m_mcu_status)); |
| 63 | save_item(NAME(m_mcu_command_offset)); |
| 64 | save_item(NAME(m_mcu_crc)); |
| 65 | save_item(NAME(m_decryption_key_byte)); |
| 66 | save_item(NAME(m_alternateswaps)); |
| 67 | save_item(NAME(m_shift)); |
| 68 | save_item(NAME(m_subtracttype)); |
| 69 | save_item(NAME(m_mode)); |
| 70 | save_item(NAME(m_blocksize_offset)); |
| 71 | save_item(NAME(m_dataend)); |
| 72 | save_item(NAME(m_database)); |
| 73 | save_item(NAME(m_data_header)); |
| 74 | save_item(NAME(m_writeaddress)); |
| 75 | save_item(NAME(m_writeaddress_current)); |
| 76 | save_item(NAME(m_dsw_addr)); |
| 77 | save_item(NAME(m_eeprom_addr)); |
| 78 | save_item(NAME(m_poll_addr)); |
| 79 | save_item(NAME(m_checksumaddress)); |
| 80 | save_pointer(NAME(m_mcuram), 0x10000/2); |
| 69 | 81 | } |
| 70 | 82 | |
| 71 | 83 | void kaneko_calc3_device::device_reset() |
| 72 | 84 | { |
| 73 | | calc3_mcu_init(this->machine()); |
| 85 | mcu_init(); |
| 74 | 86 | reset_run_timer(); |
| 75 | 87 | } |
| 76 | 88 | |
| r31856 | r31857 | |
| 79 | 91 | m_runtimer->adjust(attotime::from_hz(59.1854)); |
| 80 | 92 | } |
| 81 | 93 | |
| 94 | void kaneko_calc3_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) |
| 95 | { |
| 96 | switch(id) |
| 97 | { |
| 98 | case MCU_RUN_TIMER: |
| 99 | mcu_run(); |
| 100 | reset_run_timer(); |
| 101 | break; |
| 102 | default: |
| 103 | assert_always(FALSE, "Unknown id in kaneko_calc3_device::device_timer"); |
| 104 | } |
| 105 | } |
| 82 | 106 | |
| 83 | | |
| 84 | 107 | /* |
| 85 | 108 | |
| 86 | 109 | MCU Initialization command: |
| r31856 | r31857 | |
| 101 | 124 | */ |
| 102 | 125 | |
| 103 | 126 | |
| 104 | | void kaneko_calc3_device::calc3_mcu_init(running_machine &machine) |
| 127 | void kaneko_calc3_device::mcu_init() |
| 105 | 128 | { |
| 106 | | calc3_t &calc3 = m_calc3; |
| 107 | | calc3.mcu_status = 0; |
| 108 | | calc3.mcu_command_offset = 0; |
| 129 | m_mcu_status = 0; |
| 130 | m_mcu_command_offset = 0; |
| 109 | 131 | } |
| 110 | 132 | |
| 111 | | READ16_MEMBER(kaneko_calc3_device::calc3_mcu_ram_r) |
| 133 | READ16_MEMBER(kaneko_calc3_device::mcu_ram_r) |
| 112 | 134 | { |
| 113 | | return m_calc3_mcuram[offset]; |
| 135 | return m_mcuram[offset]; |
| 114 | 136 | } |
| 115 | 137 | |
| 116 | | |
| 117 | | WRITE16_MEMBER(kaneko_calc3_device::calc3_mcu_ram_w) |
| 138 | WRITE16_MEMBER(kaneko_calc3_device::mcu_ram_w) |
| 118 | 139 | { |
| 119 | | COMBINE_DATA(&m_calc3_mcuram[offset]); |
| 140 | COMBINE_DATA(&m_mcuram[offset]); |
| 120 | 141 | } |
| 121 | 142 | |
| 122 | | void kaneko_calc3_device::calc3_mcu_com_w(offs_t offset, UINT16 data, UINT16 mem_mask, int _n_) |
| 143 | void kaneko_calc3_device::mcu_com_w(offs_t offset, UINT16 data, UINT16 mem_mask, int _n_) |
| 123 | 144 | { |
| 124 | | calc3_t &calc3 = m_calc3; |
| 125 | 145 | logerror("calc3w %d %04x %04x\n", _n_, data, mem_mask); |
| 126 | | calc3.mcu_status |= (1 << _n_); |
| 146 | m_mcu_status |= (1 << _n_); |
| 127 | 147 | } |
| 128 | 148 | |
| 129 | | WRITE16_MEMBER(kaneko_calc3_device::calc3_mcu_com0_w){ calc3_mcu_com_w(offset, data, mem_mask, 0); } |
| 130 | | WRITE16_MEMBER(kaneko_calc3_device::calc3_mcu_com1_w){ calc3_mcu_com_w(offset, data, mem_mask, 1); } |
| 131 | | WRITE16_MEMBER(kaneko_calc3_device::calc3_mcu_com2_w){ calc3_mcu_com_w(offset, data, mem_mask, 2); } |
| 132 | | WRITE16_MEMBER(kaneko_calc3_device::calc3_mcu_com3_w){ calc3_mcu_com_w(offset, data, mem_mask, 3); } |
| 149 | WRITE16_MEMBER(kaneko_calc3_device::mcu_com0_w){ mcu_com_w(offset, data, mem_mask, 0); } |
| 150 | WRITE16_MEMBER(kaneko_calc3_device::mcu_com1_w){ mcu_com_w(offset, data, mem_mask, 1); } |
| 151 | WRITE16_MEMBER(kaneko_calc3_device::mcu_com2_w){ mcu_com_w(offset, data, mem_mask, 2); } |
| 152 | WRITE16_MEMBER(kaneko_calc3_device::mcu_com3_w){ mcu_com_w(offset, data, mem_mask, 3); } |
| 133 | 153 | |
| 134 | 154 | |
| 135 | 155 | |
| 136 | 156 | /* |
| 137 | 157 | |
| 138 | | esentially the data rom is a linked list of encrypted blocks |
| 158 | essentially the data rom is a linked list of encrypted blocks |
| 139 | 159 | |
| 140 | 160 | contains the following |
| 141 | 161 | ROM ADDRESS 0x0000 = the number of tables in this rom |
| r31856 | r31857 | |
| 146 | 166 | - this is usually '3', but if it's larger than 3 it enables an 'inline encryption' mode, whereby the decryption table is stored in the |
| 147 | 167 | - right before the length register |
| 148 | 168 | |
| 149 | | OFFSET 1 - a 'mode' register of some sort, usually 0,1,2 or 3 for used data, shogun also called a 'blank' command (length 0) with mode 8 and mode 6 |
| 169 | OFFSET 1 - a 'mode' register of some sort, usually 0,1,2 or 3 for used data, shogwarr also called a 'blank' command (length 0) with mode 8 and mode 6 |
| 150 | 170 | - seems to cause eeprom access and reset write addresses |
| 151 | 171 | |
| 152 | 172 | OFFSET 2 - unknown, might be some kind of 'step' register |
| r31856 | r31857 | |
| 159 | 179 | |
| 160 | 180 | OFFSET 4-5 (or after the inline decryption table) - the length of the current block (so that the start of the next block can be found) |
| 161 | 181 | |
| 162 | | OFFSET 6-size - data for thie block |
| 182 | OFFSET 6-size - data for this block |
| 163 | 183 | |
| 164 | 184 | this continues for the number of blocks specified |
| 165 | 185 | after all the blocks there is a 0x1000 block of data which is the same between games |
| r31856 | r31857 | |
| 181 | 201 | part of the table to be 0 |
| 182 | 202 | */ |
| 183 | 203 | |
| 184 | | static const INT16 calc3_keydata[0x40*0x100] = { |
| 204 | static const INT16 keydata[0x40*0x100] = { |
| 185 | 205 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, |
| 186 | 206 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, |
| 187 | 207 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, |
| r31856 | r31857 | |
| 1224 | 1244 | return dat; |
| 1225 | 1245 | } |
| 1226 | 1246 | |
| 1227 | | |
| 1228 | | int kaneko_calc3_device::calc3_decompress_table(running_machine& machine, int tabnum, UINT8* dstram, int dstoffset) |
| 1247 | int kaneko_calc3_device::decompress_table(int tabnum, UINT8* dstram, int dstoffset) |
| 1229 | 1248 | { |
| 1230 | | calc3_t &calc3 = m_calc3; |
| 1231 | | address_space &space = machine.device(":maincpu")->memory().space(AS_PROGRAM); |
| 1249 | address_space &space = machine().device(":maincpu")->memory().space(AS_PROGRAM); |
| 1232 | 1250 | UINT8* datarom = memregion(":calc3_rom")->base(); |
| 1233 | 1251 | |
| 1234 | 1252 | UINT8 numregions; |
| r31856 | r31857 | |
| 1260 | 1278 | { |
| 1261 | 1279 | UINT16 inline_table_base = 0; |
| 1262 | 1280 | UINT16 inline_table_size = 0; |
| 1263 | | calc3.database = offset; |
| 1264 | | calc3.blocksize_offset = datarom[offset+0]; // location of the 'block length' |
| 1265 | | calc3.mode = datarom[offset+1]; |
| 1266 | | calc3.alternateswaps = datarom[offset+2]; |
| 1267 | | calc3.shift = (calc3.alternateswaps &0xf0)>>4; |
| 1268 | | calc3.subtracttype = (calc3.alternateswaps &0x03); |
| 1269 | | calc3.alternateswaps &= 0x0c; |
| 1270 | | calc3.alternateswaps >>=2; |
| 1281 | m_database = offset; |
| 1282 | m_blocksize_offset = datarom[offset+0]; // location of the 'block length' |
| 1283 | m_mode = datarom[offset+1]; |
| 1284 | m_alternateswaps = datarom[offset+2]; |
| 1285 | m_shift = (m_alternateswaps &0xf0)>>4; |
| 1286 | m_subtracttype = (m_alternateswaps &0x03); |
| 1287 | m_alternateswaps &= 0x0c; |
| 1288 | m_alternateswaps >>=2; |
| 1271 | 1289 | |
| 1272 | | calc3.decryption_key_byte = datarom[offset+3]; |
| 1290 | m_decryption_key_byte = datarom[offset+3]; |
| 1273 | 1291 | |
| 1274 | 1292 | |
| 1275 | 1293 | // if blocksize_offset > 3, it appears to specify the encryption table as 'inline' which can be of any size (odd or even) and loops over the bytes to decrypt |
| 1276 | 1294 | // the decryption key specified seems to be ignored? |
| 1277 | | if (calc3.blocksize_offset>3) |
| 1295 | if (m_blocksize_offset>3) |
| 1278 | 1296 | { |
| 1279 | 1297 | inline_table_base = offset+4; |
| 1280 | | inline_table_size = calc3.blocksize_offset-3; |
| 1298 | inline_table_size = m_blocksize_offset-3; |
| 1281 | 1299 | } |
| 1282 | 1300 | |
| 1283 | | offset+= calc3.blocksize_offset+1; |
| 1301 | offset+= m_blocksize_offset+1; |
| 1284 | 1302 | length = datarom[offset+0] | (datarom[offset+1]<<8); |
| 1285 | 1303 | offset+=2; |
| 1286 | 1304 | |
| 1287 | | #if CALC3_VERBOSE_OUTPUT |
| 1305 | #if VERBOSE_OUTPUT |
| 1288 | 1306 | if (inline_table_size) |
| 1289 | 1307 | { |
| 1290 | | printf("Block %02x Found Base %04x - Inline Encryption (size %02x) - Mode? %02x Shift %01x Subtract Type %01x AltSwaps %01x Key (unused?) %02x Length %04x\n", tabnum, calc3.database, inline_table_size, calc3.shift, calc3.mode, calc3.subtracttype, calc3.alternateswaps, calc3.decryption_key_byte, length); |
| 1308 | printf("Block %02x Found Base %04x - Inline Encryption (size %02x) - Mode? %02x Shift %01x Subtract Type %01x AltSwaps %01x Key (unused?) %02x Length %04x\n", tabnum, m_database, inline_table_size, m_shift, m_mode, m_subtracttype, m_alternateswaps, m_decryption_key_byte, length); |
| 1291 | 1309 | } |
| 1292 | 1310 | else |
| 1293 | 1311 | { |
| 1294 | | printf("Block %02x Found Base %04x - Mode? %02x Shift %01x Subtract Type %01x AltSwaps %01x Key %02x Length %04x\n", tabnum, calc3.database, calc3.mode, calc3.shift, calc3.subtracttype, calc3.alternateswaps, calc3.decryption_key_byte, length); |
| 1312 | printf("Block %02x Found Base %04x - Mode? %02x Shift %01x Subtract Type %01x AltSwaps %01x Key %02x Length %04x\n", tabnum, m_database, m_mode, m_shift, m_subtracttype, m_alternateswaps, m_decryption_key_byte, length); |
| 1295 | 1313 | } |
| 1296 | 1314 | #endif |
| 1297 | 1315 | // copy + decrypt the table to the specified memory area |
| r31856 | r31857 | |
| 1305 | 1323 | //printf("CALC3: requested 0 length table!\n"); |
| 1306 | 1324 | // -- seems to be 'reset stack' to default for the protection table writes |
| 1307 | 1325 | |
| 1308 | | // except this will break shogun going into game, must be specific conditions for |
| 1326 | // except this will break shogwarr going into game, must be specific conditions for |
| 1309 | 1327 | // this, or it can remember addresses and restore those |
| 1310 | 1328 | |
| 1311 | 1329 | // hack, set it to a known address instead of trying to restore to anywhere specific.. |
| r31856 | r31857 | |
| 1314 | 1332 | |
| 1315 | 1333 | // !dstram is used because we don't want to process these during our initial table scan, only when the game asks! |
| 1316 | 1334 | |
| 1317 | | if (calc3.mode==0x06) |
| 1335 | if (m_mode==0x06) |
| 1318 | 1336 | { |
| 1319 | | calc3.writeaddress_current = 0x202000; // this is reasoanble for brapboys, not sure about shogun, needs emulating properly! |
| 1320 | | //calc3.writeaddress_current = 0x20c000; |
| 1337 | m_writeaddress_current = 0x202000; // this is reasonable for brapboys, not sure about shogwarr, needs emulating properly! |
| 1338 | //m_writeaddress_current = 0x20c000; |
| 1321 | 1339 | } |
| 1322 | | else if (calc3.mode==0x07) |
| 1340 | else if (m_mode==0x07) |
| 1323 | 1341 | { |
| 1324 | 1342 | // also calls empty table with Mode? 07 |
| 1325 | 1343 | // maybe they reset to different points? |
| 1326 | 1344 | } |
| 1327 | | else if (calc3.mode==0x08 && !dstram) |
| 1345 | else if (m_mode==0x08 && !dstram) |
| 1328 | 1346 | { |
| 1329 | 1347 | //printf("save to eeprom\n"); |
| 1330 | 1348 | |
| r31856 | r31857 | |
| 1333 | 1351 | |
| 1334 | 1352 | for (i=0;i<0x80;i++) |
| 1335 | 1353 | { |
| 1336 | | eeprom_space.write_byte(i, space.read_byte(calc3.eeprom_addr+0x200000+i)); |
| 1354 | eeprom_space.write_byte(i, space.read_byte(m_eeprom_addr+0x200000+i)); |
| 1337 | 1355 | } |
| 1338 | 1356 | |
| 1339 | 1357 | } |
| r31856 | r31857 | |
| 1360 | 1378 | |
| 1361 | 1379 | |
| 1362 | 1380 | /* special case for Shogun Warriors table 0x40 */ |
| 1363 | | if (calc3.subtracttype==3 && calc3.alternateswaps ==0) |
| 1381 | if (m_subtracttype==3 && m_alternateswaps ==0) |
| 1364 | 1382 | { |
| 1365 | 1383 | UINT8 inlinet = datarom[inline_table_base + (i%inline_table_size)]; |
| 1366 | 1384 | dat = datarom[offset+i]; |
| r31856 | r31857 | |
| 1381 | 1399 | UINT8 inlinet = datarom[inline_table_base + (i%inline_table_size)]; |
| 1382 | 1400 | dat = datarom[offset+i]; |
| 1383 | 1401 | dat -= inlinet; |
| 1384 | | dat = shift_bits(dat, calc3.shift); |
| 1402 | dat = shift_bits(dat, m_shift); |
| 1385 | 1403 | } |
| 1386 | 1404 | else |
| 1387 | 1405 | { |
| 1388 | 1406 | UINT8 inlinet = datarom[inline_table_base + (i%inline_table_size)]; |
| 1389 | 1407 | dat = datarom[offset+i]; |
| 1390 | 1408 | |
| 1391 | | if (calc3.subtracttype!=0x02) |
| 1409 | if (m_subtracttype!=0x02) |
| 1392 | 1410 | { |
| 1393 | 1411 | dat -= inlinet; |
| 1394 | 1412 | dat -= extra[(i%inline_table_size)>>1]; |
| r31856 | r31857 | |
| 1399 | 1417 | dat += extra[(i%inline_table_size)>>1]; |
| 1400 | 1418 | } |
| 1401 | 1419 | |
| 1402 | | dat = shift_bits(dat, 8-calc3.shift); |
| 1420 | dat = shift_bits(dat, 8-m_shift); |
| 1403 | 1421 | } |
| 1404 | 1422 | } |
| 1405 | 1423 | else |
| r31856 | r31857 | |
| 1409 | 1427 | UINT8 inlinet = datarom[inline_table_base + (i%inline_table_size)]; |
| 1410 | 1428 | dat = datarom[offset+i]; |
| 1411 | 1429 | dat -= inlinet; |
| 1412 | | dat = shift_bits(dat, calc3.shift); |
| 1430 | dat = shift_bits(dat, m_shift); |
| 1413 | 1431 | } |
| 1414 | 1432 | else |
| 1415 | 1433 | { |
| 1416 | 1434 | dat = datarom[offset+i]; |
| 1417 | 1435 | |
| 1418 | | if (calc3.subtracttype!=0x02) |
| 1436 | if (m_subtracttype!=0x02) |
| 1419 | 1437 | { |
| 1420 | 1438 | dat -= extra2[(i%inline_table_size)>>1]; |
| 1421 | 1439 | } |
| r31856 | r31857 | |
| 1423 | 1441 | { |
| 1424 | 1442 | dat += extra2[(i%inline_table_size)>>1]; |
| 1425 | 1443 | } |
| 1426 | | dat = shift_bits(dat, 8-calc3.shift); |
| 1444 | dat = shift_bits(dat, 8-m_shift); |
| 1427 | 1445 | } |
| 1428 | 1446 | } |
| 1429 | 1447 | } |
| r31856 | r31857 | |
| 1439 | 1457 | } |
| 1440 | 1458 | } |
| 1441 | 1459 | else |
| 1442 | | calc3.data_header[local_counter]=dat; |
| 1460 | m_data_header[local_counter]=dat; |
| 1443 | 1461 | |
| 1444 | 1462 | ++local_counter; |
| 1445 | 1463 | } |
| 1446 | 1464 | } |
| 1447 | 1465 | else |
| 1448 | 1466 | { |
| 1449 | | const INT16* key = calc3_keydata+(calc3.decryption_key_byte*0x40); |
| 1467 | const INT16* key = keydata+(m_decryption_key_byte*0x40); |
| 1450 | 1468 | |
| 1451 | 1469 | if (key[0] == -1) |
| 1452 | 1470 | { |
| r31856 | r31857 | |
| 1459 | 1477 | UINT8 keydat = (UINT8)key[i&0x3f]; |
| 1460 | 1478 | |
| 1461 | 1479 | { |
| 1462 | | if (calc3.subtracttype==0) |
| 1480 | if (m_subtracttype==0) |
| 1463 | 1481 | { |
| 1464 | 1482 | //dat = dat; |
| 1465 | 1483 | } |
| 1466 | | else if (calc3.subtracttype==1) |
| 1484 | else if (m_subtracttype==1) |
| 1467 | 1485 | { |
| 1468 | 1486 | if ((i&1)==1) dat += keydat; |
| 1469 | 1487 | else dat -= keydat; |
| 1470 | 1488 | } |
| 1471 | | else if (calc3.subtracttype==2) |
| 1489 | else if (m_subtracttype==2) |
| 1472 | 1490 | { |
| 1473 | 1491 | if ((i&1)==0) dat += keydat; |
| 1474 | 1492 | else dat -= keydat; |
| 1475 | 1493 | } |
| 1476 | | else if (calc3.subtracttype==3) |
| 1494 | else if (m_subtracttype==3) |
| 1477 | 1495 | { |
| 1478 | 1496 | dat -= keydat; |
| 1479 | 1497 | } |
| 1480 | 1498 | |
| 1481 | | if (calc3.alternateswaps == 0) |
| 1499 | if (m_alternateswaps == 0) |
| 1482 | 1500 | { |
| 1483 | | if ((i&1)==0) dat = shift_bits(dat, 8-calc3.shift); |
| 1484 | | else dat = shift_bits(dat, calc3.shift); |
| 1501 | if ((i&1)==0) dat = shift_bits(dat, 8-m_shift); |
| 1502 | else dat = shift_bits(dat, m_shift); |
| 1485 | 1503 | } |
| 1486 | | else if (calc3.alternateswaps==1) |
| 1504 | else if (m_alternateswaps==1) |
| 1487 | 1505 | { |
| 1488 | | dat = shift_bits(dat, 8-calc3.shift); |
| 1506 | dat = shift_bits(dat, 8-m_shift); |
| 1489 | 1507 | } |
| 1490 | | else if (calc3.alternateswaps==2) |
| 1508 | else if (m_alternateswaps==2) |
| 1491 | 1509 | { |
| 1492 | | dat = shift_bits(dat, calc3.shift); |
| 1510 | dat = shift_bits(dat, m_shift); |
| 1493 | 1511 | } |
| 1494 | | else if (calc3.alternateswaps==3) |
| 1512 | else if (m_alternateswaps==3) |
| 1495 | 1513 | { |
| 1496 | 1514 | // same as 0 |
| 1497 | | if ((i&1)==0) dat = shift_bits(dat, 8-calc3.shift); |
| 1498 | | else dat = shift_bits(dat, calc3.shift); |
| 1515 | if ((i&1)==0) dat = shift_bits(dat, 8-m_shift); |
| 1516 | else dat = shift_bits(dat, m_shift); |
| 1499 | 1517 | } |
| 1500 | 1518 | } |
| 1501 | 1519 | |
| r31856 | r31857 | |
| 1510 | 1528 | } |
| 1511 | 1529 | } |
| 1512 | 1530 | else |
| 1513 | | calc3.data_header[local_counter]=dat; |
| 1531 | m_data_header[local_counter]=dat; |
| 1514 | 1532 | |
| 1515 | 1533 | ++local_counter; |
| 1516 | 1534 | |
| r31856 | r31857 | |
| 1519 | 1537 | } |
| 1520 | 1538 | } |
| 1521 | 1539 | |
| 1522 | | calc3.dataend = offset+length+1; |
| 1540 | m_dataend = offset+length+1; |
| 1523 | 1541 | } |
| 1524 | 1542 | |
| 1525 | | //printf("data base %04x data end %04x\n", calc3.database, calc3.dataend); |
| 1543 | //printf("data base %04x data end %04x\n", m_database, m_dataend); |
| 1526 | 1544 | |
| 1527 | 1545 | return length; |
| 1528 | 1546 | |
| 1529 | 1547 | } |
| 1530 | 1548 | |
| 1531 | | |
| 1532 | | |
| 1533 | | void kaneko_calc3_device::initial_scan_tables(running_machine& machine) |
| 1549 | void kaneko_calc3_device::initial_scan_tables() |
| 1534 | 1550 | { |
| 1535 | | calc3_t &calc3 = m_calc3; |
| 1536 | 1551 | UINT8 numregions; |
| 1537 | 1552 | UINT8* datarom = memregion(":calc3_rom")->base(); |
| 1538 | 1553 | |
| 1539 | 1554 | int x; |
| 1540 | 1555 | |
| 1541 | | calc3.mcu_crc = 0; |
| 1556 | m_mcu_crc = 0; |
| 1542 | 1557 | for (x=0;x<0x20000;x++) |
| 1543 | 1558 | { |
| 1544 | | calc3.mcu_crc+=datarom[x]; |
| 1559 | m_mcu_crc+=datarom[x]; |
| 1545 | 1560 | } |
| 1546 | | //printf("crc %04x\n",calc3.mcu_crc); |
| 1561 | //printf("crc %04x\n",m_mcu_crc); |
| 1547 | 1562 | numregions = datarom[0]; |
| 1548 | 1563 | |
| 1549 | 1564 | for (x=0;x<numregions;x++) |
| 1550 | 1565 | { |
| 1551 | 1566 | dynamic_buffer tmpdstram(0x2000); |
| 1552 | | #if CALC3_VERBOSE_OUTPUT |
| 1567 | #if VERBOSE_OUTPUT |
| 1553 | 1568 | int length; |
| 1554 | 1569 | #endif |
| 1555 | 1570 | |
| 1556 | 1571 | memset(tmpdstram, 0x00,0x2000); |
| 1557 | 1572 | |
| 1558 | | #if CALC3_VERBOSE_OUTPUT |
| 1559 | | length = calc3_decompress_table(machine, x, tmpdstram, 0); |
| 1573 | #if VERBOSE_OUTPUT |
| 1574 | length = decompress_table(x, tmpdstram, 0); |
| 1560 | 1575 | // dump to file |
| 1561 | 1576 | if (length) |
| 1562 | 1577 | { |
| 1563 | 1578 | FILE *fp; |
| 1564 | 1579 | char filename[256]; |
| 1565 | 1580 | |
| 1566 | | if (calc3.blocksize_offset==3) |
| 1581 | if (m_blocksize_offset==3) |
| 1567 | 1582 | { |
| 1568 | 1583 | sprintf(filename,"data_%s_table_%04x k%02x m%02x u%02x length %04x", |
| 1569 | 1584 | machine().system().name, |
| 1570 | | x, calc3.decryption_key_byte, calc3.mode, calc3.alternateswaps, length); |
| 1585 | x, m_decryption_key_byte, m_mode, m_alternateswaps, length); |
| 1571 | 1586 | } |
| 1572 | 1587 | else |
| 1573 | 1588 | { |
| 1574 | 1589 | sprintf(filename,"data_%s_table_%04x k%02x (use indirect size %02x) m%02x u%02x length %04x", |
| 1575 | 1590 | machine().system().name, |
| 1576 | | x, calc3.decryption_key_byte, calc3.blocksize_offset-3, calc3.mode, calc3.alternateswaps, length); |
| 1591 | x, m_decryption_key_byte, m_blocksize_offset-3, m_mode, m_alternateswaps, length); |
| 1577 | 1592 | } |
| 1578 | 1593 | |
| 1579 | 1594 | fp=fopen(filename, "w+b"); |
| r31856 | r31857 | |
| 1591 | 1606 | // to that extra block of data |
| 1592 | 1607 | |
| 1593 | 1608 | // dump out the 0x1000 sized block at the end |
| 1594 | | #if CALC3_VERBOSE_OUTPUT |
| 1609 | #if VERBOSE_OUTPUT |
| 1595 | 1610 | { |
| 1596 | 1611 | FILE *fp; |
| 1597 | 1612 | char filename[256]; |
| 1598 | 1613 | |
| 1599 | 1614 | sprintf(filename,"data_%s_finalblock", |
| 1600 | | machine.system().name); |
| 1615 | machine().system().name); |
| 1601 | 1616 | |
| 1602 | 1617 | fp=fopen(filename, "w+b"); |
| 1603 | 1618 | if (fp) |
| 1604 | 1619 | { |
| 1605 | | fwrite(&datarom[calc3.dataend], 0x1000, 1, fp); |
| 1620 | fwrite(&datarom[m_dataend], 0x1000, 1, fp); |
| 1606 | 1621 | fclose(fp); |
| 1607 | 1622 | } |
| 1608 | 1623 | } |
| 1609 | 1624 | #endif |
| 1610 | 1625 | } |
| 1611 | 1626 | |
| 1612 | | |
| 1613 | | |
| 1614 | | void kaneko_calc3_device::calc3_mcu_run(running_machine &machine) |
| 1627 | void kaneko_calc3_device::mcu_run() |
| 1615 | 1628 | { |
| 1616 | | calc3_t &calc3 = m_calc3; |
| 1617 | 1629 | UINT16 mcu_command; |
| 1618 | 1630 | int i; |
| 1619 | | address_space &space = machine.device(":maincpu")->memory().space(AS_PROGRAM); |
| 1631 | address_space &space = machine().device(":maincpu")->memory().space(AS_PROGRAM); |
| 1620 | 1632 | |
| 1621 | | if ( calc3.mcu_status != (1|2|4|8) ) return; |
| 1633 | if ( m_mcu_status != (1|2|4|8) ) return; |
| 1622 | 1634 | |
| 1623 | | if (calc3.dsw_addr) space.write_byte(calc3.dsw_addr+0x200000, ( ~ioport(":DSW1")->read())&0xff); // // DSW // dsw actually updates in realtime - mcu reads+writes it every frame |
| 1635 | if (m_dsw_addr) space.write_byte(m_dsw_addr+0x200000, ( ~ioport(":DSW1")->read())&0xff); // // DSW // dsw actually updates in realtime - mcu reads+writes it every frame |
| 1624 | 1636 | |
| 1625 | 1637 | |
| 1626 | | //calc3.mcu_status = 0; |
| 1638 | //m_mcu_status = 0; |
| 1627 | 1639 | |
| 1628 | | mcu_command = m_calc3_mcuram[calc3.mcu_command_offset/2 + 0]; |
| 1640 | mcu_command = m_mcuram[m_mcu_command_offset/2 + 0]; |
| 1629 | 1641 | |
| 1630 | 1642 | if (mcu_command == 0) return; |
| 1631 | 1643 | |
| 1632 | 1644 | logerror("%s : MCU executed command at %04X: %04X\n", |
| 1633 | | machine.describe_context(),calc3.mcu_command_offset,mcu_command); |
| 1645 | machine().describe_context(),m_mcu_command_offset,mcu_command); |
| 1634 | 1646 | |
| 1635 | 1647 | |
| 1636 | 1648 | if (mcu_command>0) |
| r31856 | r31857 | |
| 1639 | 1651 | if (mcu_command == 0xff) |
| 1640 | 1652 | { |
| 1641 | 1653 | // clear old command (handshake to main cpu) |
| 1642 | | m_calc3_mcuram[(calc3.mcu_command_offset>>1)+0] = 0x0000; |
| 1654 | m_mcuram[(m_mcu_command_offset>>1)+0] = 0x0000; |
| 1643 | 1655 | |
| 1644 | 1656 | |
| 1645 | | calc3.dsw_addr = m_calc3_mcuram[(0>>1) + 1]; |
| 1646 | | calc3.eeprom_addr = m_calc3_mcuram[(0>>1) + 2]; |
| 1647 | | calc3.mcu_command_offset = m_calc3_mcuram[(0>>1) + 3]; |
| 1648 | | calc3.poll_addr = m_calc3_mcuram[(0>>1) + 4]; |
| 1649 | | calc3.checksumaddress = m_calc3_mcuram[(0>>1) + 5]; |
| 1650 | | calc3.writeaddress = (m_calc3_mcuram[(0>>1) + 6] << 16) | |
| 1651 | | (m_calc3_mcuram[(0>>1) + 7]); |
| 1657 | m_dsw_addr = m_mcuram[(0>>1) + 1]; |
| 1658 | m_eeprom_addr = m_mcuram[(0>>1) + 2]; |
| 1659 | m_mcu_command_offset = m_mcuram[(0>>1) + 3]; |
| 1660 | m_poll_addr = m_mcuram[(0>>1) + 4]; |
| 1661 | m_checksumaddress = m_mcuram[(0>>1) + 5]; |
| 1662 | m_writeaddress = (m_mcuram[(0>>1) + 6] << 16) | |
| 1663 | (m_mcuram[(0>>1) + 7]); |
| 1652 | 1664 | |
| 1653 | 1665 | // set our current write / stack pointer to the address specified |
| 1654 | | calc3.writeaddress_current = calc3.writeaddress; |
| 1655 | | #if CALC3_VERBOSE_OUTPUT |
| 1656 | | printf("Calc 3 Init Command - %04x DSW addr\n", calc3.dsw_addr); |
| 1657 | | printf("Calc 3 Init Command - %04x Eeprom Address\n", calc3.eeprom_addr); |
| 1658 | | printf("Calc 3 Init Command - %04x Future Commands Base\n", calc3.mcu_command_offset); |
| 1659 | | printf("Calc 3 Init Command - %04x Poll / Busy Address\n", calc3.poll_addr); |
| 1660 | | printf("Calc 3 Init Command - %04x ROM Checksum Address\n", calc3.checksumaddress); |
| 1661 | | printf("Calc 3 Init Command - %08x Data Write Address\n", calc3.writeaddress); |
| 1666 | m_writeaddress_current = m_writeaddress; |
| 1667 | #if VERBOSE_OUTPUT |
| 1668 | printf("Calc 3 Init Command - %04x DSW addr\n", m_dsw_addr); |
| 1669 | printf("Calc 3 Init Command - %04x Eeprom Address\n", m_eeprom_addr); |
| 1670 | printf("Calc 3 Init Command - %04x Future Commands Base\n", m_mcu_command_offset); |
| 1671 | printf("Calc 3 Init Command - %04x Poll / Busy Address\n", m_poll_addr); |
| 1672 | printf("Calc 3 Init Command - %04x ROM Checksum Address\n", m_checksumaddress); |
| 1673 | printf("Calc 3 Init Command - %08x Data Write Address\n", m_writeaddress); |
| 1662 | 1674 | #endif |
| 1663 | | // space.write_byte(calc3.dsw_addr+0x200000, ( ~ioport("DSW1")->read())&0xff); // // DSW // dsw actually updates in realtime - mcu reads+writes it every frame |
| 1675 | // space.write_byte(m_dsw_addr+0x200000, ( ~ioport("DSW1")->read())&0xff); // // DSW // dsw actually updates in realtime - mcu reads+writes it every frame |
| 1664 | 1676 | |
| 1665 | | m_calc3_mcuram[calc3.checksumaddress / 2] = calc3.mcu_crc; // MCU Rom Checksum! |
| 1677 | m_mcuram[m_checksumaddress / 2] = m_mcu_crc; // MCU Rom Checksum! |
| 1666 | 1678 | |
| 1667 | 1679 | #if 0 |
| 1668 | 1680 | for (i=0;i<0x40;i++) |
| 1669 | 1681 | { |
| 1670 | | m_calc3_mcuram[(calc3.eeprom_addr / 2)+i] = kaneko16_eeprom_data[i];//((eepromData[i]&0xff00)>>8) | ((eepromData[i]&0x00ff)<<8); |
| 1682 | m_mcuram[(m_eeprom_addr / 2)+i] = kaneko16_eeprom_data[i];//((eepromData[i]&0xff00)>>8) | ((eepromData[i]&0x00ff)<<8); |
| 1671 | 1683 | } |
| 1672 | 1684 | #endif |
| 1673 | 1685 | { |
| r31856 | r31857 | |
| 1675 | 1687 | |
| 1676 | 1688 | for (i=0;i<0x80;i++) |
| 1677 | 1689 | { |
| 1678 | | space.write_byte(calc3.eeprom_addr+0x200000+i, eeprom_space.read_byte(i)); |
| 1690 | space.write_byte(m_eeprom_addr+0x200000+i, eeprom_space.read_byte(i)); |
| 1679 | 1691 | } |
| 1680 | 1692 | |
| 1681 | 1693 | } |
| r31856 | r31857 | |
| 1688 | 1700 | int i; |
| 1689 | 1701 | |
| 1690 | 1702 | // clear old command (handshake to main cpu) |
| 1691 | | m_calc3_mcuram[calc3.mcu_command_offset>>1] = 0x0000;; |
| 1703 | m_mcuram[m_mcu_command_offset>>1] = 0x0000;; |
| 1692 | 1704 | |
| 1693 | 1705 | logerror("Calc3 transfer request, %d transfers\n", num_transfers); |
| 1694 | 1706 | |
| 1695 | 1707 | for (i=0;i<num_transfers;i++) |
| 1696 | 1708 | { |
| 1697 | | int param1 = m_calc3_mcuram[(calc3.mcu_command_offset>>1) + 1 + (2*i)]; |
| 1698 | | int param2 = m_calc3_mcuram[(calc3.mcu_command_offset>>1) + 2 + (2*i)]; |
| 1709 | int param1 = m_mcuram[(m_mcu_command_offset>>1) + 1 + (2*i)]; |
| 1710 | int param2 = m_mcuram[(m_mcu_command_offset>>1) + 2 + (2*i)]; |
| 1699 | 1711 | UINT8 commandtabl = (param1&0xff00) >> 8; |
| 1700 | 1712 | UINT16 commandaddr =param2;// (param1&0x00ff) | (param2&0xff00); |
| 1701 | 1713 | UINT8 commandunk = (param1&0x00ff); // brap boys sets.. seems to cause further writebasck address displacement?? (when tested on hw it looked like a simple +, but that doesn't work for brapboys...) |
| 1702 | | #if CALC3_VERBOSE_OUTPUT |
| 1714 | #if VERBOSE_OUTPUT |
| 1703 | 1715 | printf("transfer %d table %02x writeback address %04x unknown %02x\n", i, commandtabl, commandaddr, commandunk); |
| 1704 | 1716 | #endif |
| 1705 | 1717 | { |
| 1706 | 1718 | int length; |
| 1707 | 1719 | |
| 1708 | | length = calc3_decompress_table(machine, commandtabl, 0, calc3.writeaddress_current-2); |
| 1720 | length = decompress_table(commandtabl, 0, m_writeaddress_current-2); |
| 1709 | 1721 | |
| 1710 | 1722 | if (length) |
| 1711 | 1723 | { |
| 1712 | 1724 | int write=commandaddr; |
| 1713 | | #if CALC3_VERBOSE_OUTPUT |
| 1714 | | printf("writing back address %08x to %08x %08x\n", calc3.writeaddress_current, commandaddr,write); |
| 1725 | #if VERBOSE_OUTPUT |
| 1726 | printf("writing back address %08x to %08x %08x\n", m_writeaddress_current, commandaddr,write); |
| 1715 | 1727 | #endif |
| 1716 | 1728 | |
| 1717 | | space.write_byte(write+0x200000, calc3.data_header[0]); |
| 1718 | | space.write_byte(write+0x200001, calc3.data_header[1]); |
| 1729 | space.write_byte(write+0x200000, m_data_header[0]); |
| 1730 | space.write_byte(write+0x200001, m_data_header[1]); |
| 1719 | 1731 | |
| 1720 | 1732 | write=commandaddr+(char)commandunk; |
| 1721 | | space.write_word(write+0x200000, (calc3.writeaddress_current>>16)&0xffff); |
| 1722 | | space.write_word(write+0x200002, (calc3.writeaddress_current&0xffff)); |
| 1733 | space.write_word(write+0x200000, (m_writeaddress_current>>16)&0xffff); |
| 1734 | space.write_word(write+0x200002, (m_writeaddress_current&0xffff)); |
| 1723 | 1735 | |
| 1724 | | calc3.writeaddress_current += ((length+3)&(~1)); |
| 1736 | m_writeaddress_current += ((length+3)&(~1)); |
| 1725 | 1737 | } |
| 1726 | 1738 | |
| 1727 | 1739 | } |