trunk/src/mess/machine/snescart.c
| r21634 | r21635 | |
| 413 | 413 | return retvalue; |
| 414 | 414 | } |
| 415 | 415 | |
| 416 | | static int snes_find_addon_chip( running_machine &machine ) |
| 416 | static int snes_find_addon_chip( running_machine &machine, UINT8 *buffer, UINT32 start_offs ) |
| 417 | 417 | { |
| 418 | 418 | snes_state *state = machine.driver_data<snes_state>(); |
| 419 | | address_space &space = machine.device("maincpu")->memory().space(AS_PROGRAM); |
| 420 | 419 | int supported_type = 1; |
| 421 | 420 | int dsp_prg_offset = 0; |
| 422 | 421 | |
| 423 | 422 | /* Info mostly taken from http://snesemu.black-ship.net/misc/-from%20nsrt.edgeemu.com-chipinfo.htm */ |
| 424 | | switch (snes_r_bank1(space, 0x00ffd6)) |
| 423 | switch (buffer[start_offs + 0x16]) |
| 425 | 424 | { |
| 426 | 425 | case 0x00: |
| 427 | 426 | case 0x01: |
| r21634 | r21635 | |
| 430 | 429 | break; |
| 431 | 430 | |
| 432 | 431 | case 0x03: |
| 433 | | if (snes_r_bank1(space, 0x00ffd5) == 0x30) |
| 432 | if (buffer[start_offs + 0x15] == 0x30) |
| 434 | 433 | { |
| 435 | 434 | state->m_has_addon_chip = HAS_DSP4; |
| 436 | 435 | dsp_prg_offset = SNES_DSP4_OFFSET; |
| r21634 | r21635 | |
| 448 | 447 | break; |
| 449 | 448 | |
| 450 | 449 | case 0x05: |
| 451 | | if (snes_r_bank1(space, 0x00ffd5) == 0x20) |
| 450 | if (buffer[start_offs + 0x15] == 0x20) |
| 452 | 451 | { |
| 453 | 452 | state->m_has_addon_chip = HAS_DSP2; |
| 454 | 453 | dsp_prg_offset = SNES_DSP2_OFFSET; |
| 455 | 454 | } |
| 456 | 455 | /* DSP-3 is hard to detect. We exploit the fact that the only game has been manufactured by Bandai */ |
| 457 | | else if ((snes_r_bank1(space, 0x00ffd5) == 0x30) && (snes_r_bank1(space, 0x00ffda) == 0xb2)) |
| 456 | else if ((buffer[start_offs + 0x15] == 0x30) && (buffer[start_offs + 0x1a] == 0xb2)) |
| 458 | 457 | { |
| 459 | 458 | state->m_has_addon_chip = HAS_DSP3; |
| 460 | 459 | dsp_prg_offset = SNES_DSP3_OFFSET; |
| r21634 | r21635 | |
| 470 | 469 | case 0x14: // GSU-x |
| 471 | 470 | case 0x15: // GSU-x |
| 472 | 471 | case 0x1a: // GSU-1 (21 MHz at start) |
| 473 | | if (snes_r_bank1(space, 0x00ffd5) == 0x20) |
| 472 | if (buffer[start_offs + 0x15] == 0x20) |
| 474 | 473 | state->m_has_addon_chip = HAS_SUPERFX; |
| 475 | 474 | break; |
| 476 | 475 | |
| r21634 | r21635 | |
| 481 | 480 | case 0x32: // needed by a Sample game (according to ZSNES) |
| 482 | 481 | case 0x34: |
| 483 | 482 | case 0x35: |
| 484 | | if (snes_r_bank1(space, 0x00ffd5) == 0x23) |
| 483 | if (buffer[start_offs + 0x15] == 0x23) |
| 485 | 484 | { |
| 486 | 485 | state->m_has_addon_chip = HAS_SA1; |
| 487 | 486 | supported_type = 0; |
| r21634 | r21635 | |
| 491 | 490 | |
| 492 | 491 | case 0x43: |
| 493 | 492 | case 0x45: |
| 494 | | if (snes_r_bank1(space, 0x00ffd5) == 0x32) |
| 493 | if (buffer[start_offs + 0x15] == 0x32) |
| 495 | 494 | { |
| 496 | 495 | state->m_has_addon_chip = HAS_SDD1; |
| 497 | 496 | } |
| 498 | 497 | break; |
| 499 | 498 | |
| 500 | 499 | case 0x55: |
| 501 | | if (snes_r_bank1(space, 0x00ffd5) == 0x35) |
| 500 | if (buffer[start_offs + 0x15] == 0x35) |
| 502 | 501 | { |
| 503 | 502 | state->m_has_addon_chip = HAS_RTC; |
| 504 | 503 | } |
| r21634 | r21635 | |
| 514 | 513 | break; |
| 515 | 514 | |
| 516 | 515 | case 0xf5: |
| 517 | | if (snes_r_bank1(space, 0x00ffd5) == 0x30) |
| 516 | if (buffer[start_offs + 0x15] == 0x30) |
| 518 | 517 | { |
| 519 | 518 | state->m_has_addon_chip = HAS_ST018; |
| 520 | 519 | supported_type = 0; |
| 521 | 520 | } |
| 522 | | else if (snes_r_bank1(space, 0x00ffd5) == 0x3a) |
| 521 | else if (buffer[start_offs + 0x15] == 0x3a) |
| 523 | 522 | { |
| 524 | 523 | state->m_has_addon_chip = HAS_SPC7110; |
| 525 | 524 | } |
| r21634 | r21635 | |
| 528 | 527 | case 0xf6: |
| 529 | 528 | /* These Seta ST-01X chips have both 0x30 at 0x00ffd5, |
| 530 | 529 | they only differ for the 'size' at 0x00ffd7 */ |
| 531 | | if (snes_r_bank1(space, 0x00ffd7) < 0x0a) |
| 530 | if (buffer[start_offs + 0x17] < 0x0a) |
| 532 | 531 | state->m_has_addon_chip = HAS_ST011; |
| 533 | 532 | else |
| 534 | 533 | state->m_has_addon_chip = HAS_ST010; |
| r21634 | r21635 | |
| 539 | 538 | break; |
| 540 | 539 | |
| 541 | 540 | case 0xf9: |
| 542 | | if (snes_r_bank1(space, 0x00ffd5) == 0x3a) |
| 541 | if (buffer[start_offs + 0x15] == 0x3a) |
| 543 | 542 | { |
| 544 | 543 | state->m_has_addon_chip = HAS_SPC7110_RTC; |
| 545 | 544 | supported_type = 0; |
| r21634 | r21635 | |
| 595 | 594 | return supported_type; |
| 596 | 595 | } |
| 597 | 596 | |
| 598 | | static void snes_cart_log_info( running_machine &machine, int total_blocks, int supported ) |
| 597 | static void snes_cart_log_info( running_machine &machine, UINT8* ROM, int total_blocks, int supported ) |
| 599 | 598 | { |
| 600 | 599 | snes_state *state = machine.driver_data<snes_state>(); |
| 601 | | address_space &space = machine.device("maincpu")->memory().space(AS_PROGRAM); |
| 600 | device_image_interface *image = dynamic_cast<device_image_interface *>(machine.device("cart")); |
| 602 | 601 | char title[21], rom_id[4], company_id[2]; |
| 603 | 602 | int i, company, has_ram = 0, has_sram = 0; |
| 604 | | |
| 603 | UINT32 offset = snes_skip_header(*image, state->m_cart_size); |
| 604 | UINT32 hilo_mode = snes_find_hilo_mode(*image, ROM, offset, 0); |
| 605 | |
| 605 | 606 | /* Company */ |
| 606 | 607 | for (i = 0; i < 2; i++) |
| 607 | | company_id[i] = snes_r_bank1(space, 0x00ffb0 + i); |
| 608 | company_id[i] = ROM[hilo_mode - 0x10 + i]; |
| 608 | 609 | company = (char_to_int_conv(company_id[0]) << 4) + char_to_int_conv(company_id[1]); |
| 609 | 610 | if (company == 0) |
| 610 | | company = snes_r_bank1(space, 0x00ffda); |
| 611 | company = ROM[hilo_mode + 0x1a]; |
| 611 | 612 | |
| 612 | 613 | /* ROM ID */ |
| 613 | | for( i = 0; i < 4; i++ ) |
| 614 | | rom_id[i] = snes_r_bank1(space, 0x00ffb2 + i); |
| 614 | for (i = 0; i < 4; i++) |
| 615 | rom_id[i] = ROM[hilo_mode - 0x0e + i]; |
| 615 | 616 | |
| 616 | 617 | /* Title */ |
| 617 | | for( i = 0; i < 21; i++ ) |
| 618 | | title[i] = snes_r_bank1(space, 0x00ffc0 + i); |
| 618 | for (i = 0; i < 21; i++) |
| 619 | title[i] = ROM[hilo_mode + i]; |
| 619 | 620 | |
| 620 | 621 | /* RAM */ |
| 621 | | if (((snes_r_bank1(space, 0x00ffd6) & 0xf) == 1) || |
| 622 | | ((snes_r_bank1(space, 0x00ffd6) & 0xf) == 2) || |
| 623 | | ((snes_r_bank1(space, 0x00ffd6) & 0xf) == 4) || |
| 624 | | ((snes_r_bank1(space, 0x00ffd6) & 0xf) == 5)) |
| 622 | if (((ROM[hilo_mode + 0x16] & 0xf) == 1) || |
| 623 | ((ROM[hilo_mode + 0x16] & 0xf) == 2) || |
| 624 | ((ROM[hilo_mode + 0x16] & 0xf) == 4) || |
| 625 | ((ROM[hilo_mode + 0x16] & 0xf) == 5)) |
| 625 | 626 | has_ram = 1; |
| 626 | 627 | |
| 627 | 628 | /* SRAM */ |
| 628 | | if (((snes_r_bank1(space, 0x00ffd6) & 0xf) == 2) || |
| 629 | | ((snes_r_bank1(space, 0x00ffd6) & 0xf) == 5) || |
| 630 | | ((snes_r_bank1(space, 0x00ffd6) & 0xf) == 6)) |
| 629 | if (((ROM[hilo_mode + 0x16] & 0xf) == 2) || |
| 630 | ((ROM[hilo_mode + 0x16] & 0xf) == 5) || |
| 631 | ((ROM[hilo_mode + 0x16] & 0xf) == 6)) |
| 631 | 632 | has_sram = 1; |
| 632 | 633 | |
| 633 | 634 | logerror( "ROM DETAILS\n" ); |
| r21634 | r21635 | |
| 644 | 645 | logerror( "HEADER DETAILS\n" ); |
| 645 | 646 | logerror( "==============\n\n" ); |
| 646 | 647 | logerror( "\tName: %.21s\n", title ); |
| 647 | | logerror( "\tSpeed: %s [%d]\n", ((snes_r_bank1(space, 0x00ffd5) & 0xf0)) ? "FastROM" : "SlowROM", (snes_r_bank1(space, 0x00ffd5) & 0xf0) >> 4 ); |
| 648 | | logerror( "\tBank size: %s [%d]\n", (snes_r_bank1(space, 0x00ffd5) & 0xf) ? "HiROM" : "LoROM", snes_r_bank1(space, 0x00ffd5) & 0xf ); |
| 648 | logerror( "\tSpeed: %s [%d]\n", ((ROM[hilo_mode + 0x15] & 0xf0)) ? "FastROM" : "SlowROM", (ROM[hilo_mode + 0x15] & 0xf0) >> 4 ); |
| 649 | logerror( "\tBank size: %s [%d]\n", (ROM[hilo_mode + 0x15] & 0xf) ? "HiROM" : "LoROM", ROM[hilo_mode + 0x15] & 0xf ); |
| 649 | 650 | |
| 650 | 651 | logerror( "\tType: %s", types[state->m_has_addon_chip]); |
| 651 | 652 | if (has_ram) |
| 652 | 653 | logerror( ", RAM"); |
| 653 | 654 | if (has_sram) |
| 654 | 655 | logerror( ", SRAM"); |
| 655 | | logerror( " [%d]\n", snes_r_bank1(space, 0x00ffd6) ); |
| 656 | logerror( " [%d]\n", ROM[hilo_mode + 0x16] ); |
| 656 | 657 | |
| 657 | | logerror( "\tSize: %d megabits [%d]\n", 1 << (snes_r_bank1(space, 0x00ffd7) - 7), snes_r_bank1(space, 0x00ffd7) ); |
| 658 | | logerror( "\tSRAM: %d kilobits [%d]\n", state->m_cart[0].m_nvram_size * 8, snes_ram[0xffd8] ); |
| 659 | | logerror( "\tCountry: %s [%d]\n", countries[snes_r_bank1(space, 0x00ffd9)], snes_r_bank1(space, 0x00ffd9) ); |
| 660 | | logerror( "\tLicense: %s [%X]\n", companies[snes_r_bank1(space, 0x00ffda)], snes_r_bank1(space, 0x00ffda) ); |
| 661 | | logerror( "\tVersion: 1.%d\n", snes_r_bank1(space, 0x00ffdb) ); |
| 662 | | logerror( "\tInv Checksum: %X %X\n", snes_r_bank1(space, 0x00ffdd), snes_r_bank1(space, 0x00ffdc) ); |
| 663 | | logerror( "\tChecksum: %X %X\n", snes_r_bank1(space, 0x00ffdf), snes_r_bank1(space, 0x00ffde) ); |
| 664 | | logerror( "\tNMI Address: %2X%2Xh\n", snes_r_bank1(space, 0x00fffb), snes_r_bank1(space, 0x00fffa) ); |
| 665 | | logerror( "\tStart Address: %2X%2Xh\n\n", snes_r_bank1(space, 0x00fffd), snes_r_bank1(space, 0x00fffc) ); |
| 658 | logerror( "\tSize: %d megabits [%d]\n", 1 << (ROM[hilo_mode + 0x17] - 7), ROM[hilo_mode + 0x17] ); |
| 659 | logerror( "\tSRAM: %d kilobits [%d]\n", state->m_cart[0].m_nvram_size * 8, ROM[hilo_mode + 0x18] ); |
| 660 | logerror( "\tCountry: %s [%d]\n", countries[ROM[hilo_mode + 0x19]], ROM[hilo_mode + 0x19] ); |
| 661 | logerror( "\tLicense: %s [%X]\n", companies[ROM[hilo_mode + 0x1a]], ROM[hilo_mode + 0x1a] ); |
| 662 | logerror( "\tVersion: 1.%d\n", ROM[hilo_mode + 0x1b] ); |
| 663 | logerror( "\tInv Checksum: %X %X\n", ROM[hilo_mode + 0x1d], ROM[hilo_mode + 0x1c] ); |
| 664 | logerror( "\tChecksum: %X %X\n", ROM[hilo_mode + 0x1f], ROM[hilo_mode + 0x1e] ); |
| 665 | logerror( "\tNMI Address: %2X%2Xh\n", ROM[hilo_mode + 0x2b], ROM[hilo_mode + 0x2a] ); |
| 666 | logerror( "\tStart Address: %2X%2Xh\n\n", ROM[hilo_mode + 0x2d], ROM[hilo_mode + 0x2c] ); |
| 666 | 667 | |
| 667 | 668 | logerror( "\tMode: %d\n", state->m_cart[0].mode); |
| 668 | 669 | |
| r21634 | r21635 | |
| 674 | 675 | { |
| 675 | 676 | int supported_type = 1; |
| 676 | 677 | running_machine &machine = image.device().machine(); |
| 677 | | address_space &space = machine.device( "maincpu")->memory().space( AS_PROGRAM ); |
| 678 | 678 | int total_blocks, read_blocks, has_bsx_slot = 0, st_bios = 0; |
| 679 | 679 | UINT32 offset, int_header_offs; |
| 680 | 680 | UINT8 *ROM = memregion("cart")->base(); |
| r21634 | r21635 | |
| 1003 | 1003 | } |
| 1004 | 1004 | |
| 1005 | 1005 | /* Detect special chips */ |
| 1006 | | supported_type = snes_find_addon_chip(machine); |
| 1006 | supported_type = snes_find_addon_chip(machine, ROM, int_header_offs); |
| 1007 | 1007 | |
| 1008 | 1008 | /* Find the amount of cart ram */ |
| 1009 | 1009 | m_cart[0].m_nvram_size = 0; |
| r21634 | r21635 | |
| 1011 | 1011 | { |
| 1012 | 1012 | UINT32 nvram_size; |
| 1013 | 1013 | if ((m_has_addon_chip != HAS_SUPERFX)) |
| 1014 | | nvram_size = snes_r_bank1(space, 0x00ffd8); |
| 1014 | nvram_size = ROM[int_header_offs + 0x18]; |
| 1015 | 1015 | else |
| 1016 | | nvram_size = (snes_r_bank1(space, 0x00ffbd) & 0x07); |
| 1016 | nvram_size = (ROM[0x00ffbd] & 0x07); |
| 1017 | 1017 | |
| 1018 | 1018 | if (nvram_size > 0) |
| 1019 | 1019 | { |
| r21634 | r21635 | |
| 1044 | 1044 | m_cart[0].m_nvram = auto_alloc_array_clear(machine, UINT8, m_cart[0].m_nvram_size); |
| 1045 | 1045 | |
| 1046 | 1046 | /* Log snes_cart information */ |
| 1047 | | snes_cart_log_info(machine, total_blocks, supported_type); |
| 1047 | snes_cart_log_info(machine, ROM, total_blocks, supported_type); |
| 1048 | 1048 | |
| 1049 | 1049 | /* Load SRAM */ |
| 1050 | 1050 | snes_load_sram(machine); |