trunk/src/mess/machine/snescart.c
| r21737 | r21738 | |
| 297 | 297 | |
| 298 | 298 | /* Check for a header (512 bytes) */ |
| 299 | 299 | if (image.software_entry() == NULL) |
| 300 | | image.fread( header, 512); |
| 300 | image.fread(header, 512); |
| 301 | 301 | else |
| 302 | 302 | memcpy(header, image.get_software_region("rom"), 512); |
| 303 | 303 | |
| r21737 | r21738 | |
| 330 | 330 | /* This determines if a cart is in Mode 20, 21, 22 or 25; sets state->m_cart[0].mode and |
| 331 | 331 | state->m_cart[0].sram_max accordingly; and returns the offset of the internal header |
| 332 | 332 | (needed to detect BSX and ST carts) */ |
| 333 | | static UINT32 snes_find_hilo_mode( device_image_interface &image, UINT8 *buffer, UINT32 offset, int cartid ) |
| 333 | static UINT32 snes_find_hilo_mode( device_image_interface &image, UINT8 *buffer, UINT32 len, UINT32 offset, int cartid ) |
| 334 | 334 | { |
| 335 | 335 | snes_state *state = image.device().machine().driver_data<snes_state>(); |
| 336 | 336 | UINT8 valid_mode20, valid_mode21, valid_mode25; |
| r21737 | r21738 | |
| 339 | 339 | /* Now to determine if this is a lo-ROM, a hi-ROM or an extended lo/hi-ROM */ |
| 340 | 340 | valid_mode20 = snes_validate_infoblock(buffer, 0x007fc0); |
| 341 | 341 | valid_mode21 = snes_validate_infoblock(buffer, 0x00ffc0); |
| 342 | | valid_mode25 = snes_validate_infoblock(buffer, 0x40ffc0); |
| 342 | valid_mode25 = (len > 0x40ffc0) ? snes_validate_infoblock(buffer, 0x40ffc0) : 0; |
| 343 | 343 | |
| 344 | 344 | /* Images larger than 32mbits are likely ExHiRom */ |
| 345 | 345 | if (valid_mode25) |
| r21737 | r21738 | |
| 561 | 561 | return supported_type; |
| 562 | 562 | } |
| 563 | 563 | |
| 564 | | static void snes_cart_log_info( running_machine &machine, UINT8* ROM, int supported ) |
| 564 | static void snes_cart_log_info( running_machine &machine, UINT8* ROM, UINT32 len, int supported ) |
| 565 | 565 | { |
| 566 | 566 | snes_state *state = machine.driver_data<snes_state>(); |
| 567 | 567 | device_image_interface *image = dynamic_cast<device_image_interface *>(machine.device("cart")); |
| 568 | 568 | char title[21], rom_id[4], company_id[2]; |
| 569 | 569 | int i, company, has_ram = 0, has_sram = 0; |
| 570 | 570 | UINT32 offset = snes_skip_header(*image, state->m_cart_size); |
| 571 | | UINT32 hilo_mode = snes_find_hilo_mode(*image, ROM, offset, 0); |
| 571 | UINT32 hilo_mode = snes_find_hilo_mode(*image, ROM, len, offset, 0); |
| 572 | 572 | |
| 573 | 573 | /* Company */ |
| 574 | 574 | for (i = 0; i < 2; i++) |
| r21737 | r21738 | |
| 645 | 645 | int supported_type = 1; |
| 646 | 646 | int has_bsx_slot = 0, st_bios = 0; |
| 647 | 647 | UINT32 offset, int_header_offs; |
| 648 | | UINT8 *ROM = memregion("cart")->base(); |
| 649 | 648 | |
| 650 | 649 | if (image.software_entry() == NULL) |
| 651 | 650 | m_cart_size = image.length(); |
| 652 | 651 | else |
| 653 | 652 | m_cart_size = image.get_software_region_length("rom"); |
| 654 | 653 | |
| 655 | | /* Check for a header (512 bytes), and skip it if found */ |
| 654 | // Check for a header (512 bytes), and skip it if found |
| 656 | 655 | offset = snes_skip_header(image, m_cart_size); |
| 657 | 656 | |
| 657 | // Allocate rom pointer |
| 658 | m_cart[0].m_rom_size = m_cart_size - offset; |
| 659 | m_cart[0].m_rom = auto_alloc_array_clear(machine(), UINT8, m_cart[0].m_rom_size); |
| 660 | |
| 658 | 661 | if (image.software_entry() == NULL) |
| 659 | 662 | { |
| 660 | 663 | image.fseek(offset, SEEK_SET); |
| 661 | | image.fread(ROM, m_cart_size - offset); |
| 664 | image.fread(m_cart[0].m_rom, m_cart_size - offset); |
| 662 | 665 | } |
| 663 | 666 | else |
| 664 | | memcpy(ROM, image.get_software_region("rom") + offset, m_cart_size - offset); |
| 667 | memcpy(m_cart[0].m_rom, image.get_software_region("rom") + offset, m_cart_size - offset); |
| 665 | 668 | |
| 666 | 669 | if (SNES_CART_DEBUG) mame_printf_error("size %08X\n", m_cart_size - offset); |
| 667 | 670 | |
| 668 | | m_cart[0].m_rom_size = m_cart_size; |
| 669 | | m_cart[0].m_rom = auto_alloc_array_clear(machine(), UINT8, m_cart[0].m_rom_size); |
| 670 | | memcpy(m_cart[0].m_rom, ROM, m_cart[0].m_rom_size - offset); |
| 671 | // Setup the bank map to handle mirroring of ROM up to 8MB of accessible memory |
| 671 | 672 | rom_map_setup(m_cart[0].m_rom_size); |
| 672 | 673 | |
| 673 | | /* First, look if the cart is HiROM or LoROM (and set snes_cart accordingly) */ |
| 674 | | int_header_offs = snes_find_hilo_mode(image, ROM, offset, 0); |
| 674 | // Check if the cart is HiROM or LoROM (and set variables accordingly) |
| 675 | int_header_offs = snes_find_hilo_mode(image, m_cart[0].m_rom, m_cart[0].m_rom_size, offset, 0); |
| 675 | 676 | |
| 676 | | /* Then, detect BS-X carts */ |
| 677 | | // Detect presence of BS-X Flash Cart |
| 678 | | if ((ROM[int_header_offs + 0x13] == 0x00 || ROM[int_header_offs + 0x13] == 0xff) && |
| 679 | | ROM[int_header_offs + 0x14] == 0x00) |
| 677 | // Detect BS-X carts: |
| 678 | // 1. Detect BS-X Flash Cart |
| 679 | if ((m_cart[0].m_rom[int_header_offs + 0x13] == 0x00 || m_cart[0].m_rom[int_header_offs + 0x13] == 0xff) && |
| 680 | m_cart[0].m_rom[int_header_offs + 0x14] == 0x00) |
| 680 | 681 | { |
| 681 | | UINT8 n15 = ROM[int_header_offs + 0x15]; |
| 682 | UINT8 n15 = m_cart[0].m_rom[int_header_offs + 0x15]; |
| 682 | 683 | if (n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c || n15 == 0xbc || n15 == 0xfc) |
| 683 | 684 | { |
| 684 | | if (ROM[int_header_offs + 0x1a] == 0x33 || ROM[int_header_offs + 0x1a] == 0xff) |
| 685 | if (m_cart[0].m_rom[int_header_offs + 0x1a] == 0x33 || m_cart[0].m_rom[int_header_offs + 0x1a] == 0xff) |
| 685 | 686 | { |
| 686 | 687 | // BS-X Flash Cart |
| 687 | 688 | mame_printf_error("This is a game with BS-X slot: MESS does not support these yet, sorry.\n"); |
| r21737 | r21738 | |
| 690 | 691 | } |
| 691 | 692 | } |
| 692 | 693 | |
| 693 | | // Detect presence of BS-X flash cartridge connector |
| 694 | | if ((ROM[int_header_offs - 14] == 'Z') && (ROM[int_header_offs - 11] == 'J')) |
| 694 | // 2. Detect presence of BS-X flash cartridge connector |
| 695 | if ((m_cart[0].m_rom[int_header_offs - 14] == 'Z') && (m_cart[0].m_rom[int_header_offs - 11] == 'J')) |
| 695 | 696 | { |
| 696 | | UINT8 n13 = ROM[int_header_offs - 13]; |
| 697 | UINT8 n13 = m_cart[0].m_rom[int_header_offs - 13]; |
| 697 | 698 | if ((n13 >= 'A' && n13 <= 'Z') || (n13 >= '0' && n13 <= '9')) |
| 698 | 699 | { |
| 699 | | if (ROM[int_header_offs + 0x1a] == 0x33 || |
| 700 | | (ROM[int_header_offs - 10] == 0x00 && ROM[int_header_offs - 4] == 0x00)) |
| 700 | if (m_cart[0].m_rom[int_header_offs + 0x1a] == 0x33 || |
| 701 | (m_cart[0].m_rom[int_header_offs - 10] == 0x00 && m_cart[0].m_rom[int_header_offs - 4] == 0x00)) |
| 701 | 702 | { |
| 702 | 703 | has_bsx_slot = 1; |
| 703 | 704 | } |
| r21737 | r21738 | |
| 708 | 709 | if (has_bsx_slot) |
| 709 | 710 | { |
| 710 | 711 | mame_printf_error("This is a game with BS-X slot: MESS does not support these yet, sorry.\n"); |
| 711 | | if (!memcmp(ROM + int_header_offs, "Satellaview BS-X ", 21)) |
| 712 | if (!memcmp(m_cart[0].m_rom + int_header_offs, "Satellaview BS-X ", 21)) |
| 712 | 713 | { |
| 713 | 714 | //BS-X Base Cart |
| 714 | 715 | m_cart[0].mode = SNES_MODE_20; //SNES_MODE_BSX; |
| 715 | | // handle RAM |
| 716 | 716 | } |
| 717 | 717 | else |
| 718 | 718 | { |
| 719 | 719 | m_cart[0].mode = (int_header_offs == 0x007fc0) ? SNES_MODE_20 : SNES_MODE_21; //SNES_MODE_BSLO : SNES_MODE_BSHI; |
| 720 | | // handle RAM? |
| 721 | 720 | } |
| 722 | 721 | } |
| 723 | 722 | |
| 724 | 723 | /* Then, detect Sufami Turbo carts */ |
| 725 | | if (!memcmp(ROM, "BANDAI SFC-ADX", 14)) |
| 724 | if (!memcmp(m_cart[0].m_rom, "BANDAI SFC-ADX", 14)) |
| 726 | 725 | { |
| 727 | 726 | m_cart[0].mode = SNES_MODE_ST; |
| 728 | | if (!memcmp(ROM + 16, "SFC-ADX BACKUP", 14)) |
| 727 | if (!memcmp(m_cart[0].m_rom + 16, "SFC-ADX BACKUP", 14)) |
| 729 | 728 | st_bios = 1; |
| 730 | 729 | } |
| 731 | 730 | if (st_bios) |
| r21737 | r21738 | |
| 741 | 740 | if (SNES_CART_DEBUG) mame_printf_error("mode %d\n", m_cart[0].mode); |
| 742 | 741 | |
| 743 | 742 | /* Detect special chips */ |
| 744 | | supported_type = snes_find_addon_chip(machine(), ROM, int_header_offs); |
| 743 | supported_type = snes_find_addon_chip(machine(), m_cart[0].m_rom, int_header_offs); |
| 745 | 744 | |
| 746 | 745 | /* Find the amount of cart ram */ |
| 747 | 746 | m_cart[0].m_nvram_size = 0; |
| r21737 | r21738 | |
| 749 | 748 | { |
| 750 | 749 | UINT32 nvram_size; |
| 751 | 750 | if ((m_has_addon_chip != HAS_SUPERFX)) |
| 752 | | nvram_size = ROM[int_header_offs + 0x18]; |
| 751 | nvram_size = m_cart[0].m_rom[int_header_offs + 0x18]; |
| 753 | 752 | else |
| 754 | | nvram_size = (ROM[0x007fbd] & 0x07); |
| 753 | nvram_size = (m_cart[0].m_rom[0x007fbd] & 0x07); |
| 755 | 754 | |
| 756 | 755 | if (nvram_size > 0) |
| 757 | 756 | { |
| r21737 | r21738 | |
| 782 | 781 | m_cart[0].m_nvram = auto_alloc_array_clear(machine(), UINT8, m_cart[0].m_nvram_size); |
| 783 | 782 | |
| 784 | 783 | /* Log snes_cart information */ |
| 785 | | snes_cart_log_info(machine(), ROM, supported_type); |
| 784 | snes_cart_log_info(machine(), m_cart[0].m_rom, m_cart[0].m_rom_size, supported_type); |
| 786 | 785 | |
| 787 | 786 | /* Load SRAM */ |
| 788 | 787 | if (m_cart[0].m_nvram_size > 0) |