trunk/src/mess/machine/snescart.c
| r21631 | r21632 | |
| 750 | 750 | { |
| 751 | 751 | int supported_type = 1; |
| 752 | 752 | running_machine &machine = image.device().machine(); |
| 753 | | snes_state *state = machine.driver_data<snes_state>(); |
| 754 | 753 | address_space &space = machine.device( "maincpu")->memory().space( AS_PROGRAM ); |
| 755 | 754 | int total_blocks, read_blocks, has_bsx_slot = 0, st_bios = 0; |
| 756 | 755 | UINT32 offset, int_header_offs; |
| 757 | | UINT8 *ROM = state->memregion("cart")->base(); |
| 756 | UINT8 *ROM = memregion("cart")->base(); |
| 758 | 757 | |
| 759 | 758 | if (image.software_entry() == NULL) |
| 760 | | state->m_cart_size = image.length(); |
| 759 | m_cart_size = image.length(); |
| 761 | 760 | else |
| 762 | | state->m_cart_size = image.get_software_region_length("rom"); |
| 761 | m_cart_size = image.get_software_region_length("rom"); |
| 763 | 762 | |
| 764 | 763 | /* Check for a header (512 bytes), and skip it if found */ |
| 765 | | offset = snes_skip_header(image, state->m_cart_size); |
| 764 | offset = snes_skip_header(image, m_cart_size); |
| 766 | 765 | |
| 767 | 766 | if (image.software_entry() == NULL) |
| 768 | 767 | { |
| 769 | 768 | image.fseek(offset, SEEK_SET); |
| 770 | | image.fread( ROM, state->m_cart_size - offset); |
| 769 | image.fread(ROM, m_cart_size - offset); |
| 771 | 770 | } |
| 772 | 771 | else |
| 773 | | memcpy(ROM, image.get_software_region("rom") + offset, state->m_cart_size - offset); |
| 772 | memcpy(ROM, image.get_software_region("rom") + offset, m_cart_size - offset); |
| 774 | 773 | |
| 775 | | if (SNES_CART_DEBUG) mame_printf_error("size %08X\n", state->m_cart_size - offset); |
| 774 | if (SNES_CART_DEBUG) mame_printf_error("size %08X\n", m_cart_size - offset); |
| 776 | 775 | |
| 777 | 776 | /* First, look if the cart is HiROM or LoROM (and set snes_cart accordingly) */ |
| 778 | 777 | int_header_offs = snes_find_hilo_mode(image, ROM, offset, 0); |
| r21631 | r21632 | |
| 788 | 787 | if (ROM[int_header_offs + 0x1a] == 0x33 || ROM[int_header_offs + 0x1a] == 0xff) |
| 789 | 788 | { |
| 790 | 789 | // BS-X Flash Cart |
| 791 | | state->m_cart[0].mode = SNES_MODE_BSX; |
| 790 | m_cart[0].mode = SNES_MODE_BSX; |
| 792 | 791 | } |
| 793 | 792 | } |
| 794 | 793 | } |
| r21631 | r21632 | |
| 813 | 812 | if (!memcmp(ROM + int_header_offs, "Satellaview BS-X ", 21)) |
| 814 | 813 | { |
| 815 | 814 | //BS-X Base Cart |
| 816 | | state->m_cart[0].mode = SNES_MODE_BSX; |
| 815 | m_cart[0].mode = SNES_MODE_BSX; |
| 817 | 816 | // handle RAM |
| 818 | 817 | } |
| 819 | 818 | else |
| 820 | 819 | { |
| 821 | | state->m_cart[0].mode = (int_header_offs ==0x007fc0) ? SNES_MODE_BSLO : SNES_MODE_BSHI; |
| 820 | m_cart[0].mode = (int_header_offs ==0x007fc0) ? SNES_MODE_BSLO : SNES_MODE_BSHI; |
| 822 | 821 | // handle RAM? |
| 823 | 822 | } |
| 824 | 823 | } |
| r21631 | r21632 | |
| 826 | 825 | /* Then, detect Sufami Turbo carts */ |
| 827 | 826 | if (!memcmp(ROM, "BANDAI SFC-ADX", 14)) |
| 828 | 827 | { |
| 829 | | state->m_cart[0].mode = SNES_MODE_ST; |
| 828 | m_cart[0].mode = SNES_MODE_ST; |
| 830 | 829 | if (!memcmp(ROM + 16, "SFC-ADX BACKUP", 14)) |
| 831 | 830 | st_bios = 1; |
| 832 | 831 | } |
| 833 | 832 | |
| 834 | | if (SNES_CART_DEBUG) mame_printf_error("mode %d\n", state->m_cart[0].mode); |
| 833 | if (SNES_CART_DEBUG) mame_printf_error("mode %d\n", m_cart[0].mode); |
| 835 | 834 | |
| 836 | 835 | /* FIXME: Insert crc check here? */ |
| 837 | 836 | |
| 838 | 837 | /* How many blocks of data are available to be loaded? */ |
| 839 | | total_blocks = ((state->m_cart_size - offset) / (state->m_cart[0].mode & 0xa5 ? 0x8000 : 0x10000)); |
| 838 | total_blocks = ((m_cart_size - offset) / (m_cart[0].mode & 0xa5 ? 0x8000 : 0x10000)); |
| 840 | 839 | read_blocks = 0; |
| 841 | 840 | |
| 842 | 841 | if (SNES_CART_DEBUG) mame_printf_error("blocks %d\n", total_blocks); |
| r21631 | r21632 | |
| 852 | 851 | * This is likely what happens in the real SNES as well, because the unit cannot be aware of the exact |
| 853 | 852 | * size of data in the cart (procedure confirmed by byuu) |
| 854 | 853 | */ |
| 855 | | switch (state->m_cart[0].mode) |
| 854 | switch (m_cart[0].mode) |
| 856 | 855 | { |
| 857 | 856 | case SNES_MODE_21: |
| 858 | 857 | /* HiROM carts load data in banks 0xc0 to 0xff. Each bank is fully mirrored in banks 0x40 to 0x7f |
| r21631 | r21632 | |
| 1018 | 1017 | /* not handled yet */ |
| 1019 | 1018 | mame_printf_error("This is a BS-X Satellaview image: MESS does not support these yet, sorry.\n"); |
| 1020 | 1019 | /* so treat it like MODE_20 */ |
| 1021 | | state->m_cart[0].mode = SNES_MODE_20; |
| 1020 | m_cart[0].mode = SNES_MODE_20; |
| 1022 | 1021 | /* and load it as such... */ |
| 1023 | 1022 | |
| 1024 | 1023 | default: |
| r21631 | r21632 | |
| 1081 | 1080 | /* Find the amount of cart ram (even if we call it sram...) */ |
| 1082 | 1081 | if (image.software_entry() == NULL) |
| 1083 | 1082 | { |
| 1084 | | if ((state->m_has_addon_chip != HAS_SUPERFX)) |
| 1085 | | state->m_cart[0].sram = snes_r_bank1(space, 0x00ffd8); |
| 1083 | if ((m_has_addon_chip != HAS_SUPERFX)) |
| 1084 | m_cart[0].sram = snes_r_bank1(space, 0x00ffd8); |
| 1086 | 1085 | else |
| 1087 | | state->m_cart[0].sram = (snes_r_bank1(space, 0x00ffbd) & 0x07); |
| 1086 | m_cart[0].sram = (snes_r_bank1(space, 0x00ffbd) & 0x07); |
| 1088 | 1087 | |
| 1089 | | if (state->m_cart[0].sram > 0) |
| 1088 | if (m_cart[0].sram > 0) |
| 1090 | 1089 | { |
| 1091 | | state->m_cart[0].sram = (1024 << state->m_cart[0].sram); |
| 1092 | | if (state->m_cart[0].sram > state->m_cart[0].sram_max) |
| 1093 | | state->m_cart[0].sram = state->m_cart[0].sram_max; |
| 1090 | m_cart[0].sram = (1024 << m_cart[0].sram); |
| 1091 | if (m_cart[0].sram > m_cart[0].sram_max) |
| 1092 | m_cart[0].sram = m_cart[0].sram_max; |
| 1094 | 1093 | } |
| 1095 | | // printf("size %x\n", state->m_cart[0].sram); |
| 1094 | // printf("size %x\n", m_cart[0].sram); |
| 1096 | 1095 | } |
| 1097 | 1096 | else |
| 1098 | 1097 | { |
| 1099 | 1098 | // if we are loading from softlist, take memory length from the xml |
| 1100 | | state->m_cart[0].sram = image.get_software_region("nvram") ? image.get_software_region_length("nvram") : 0; |
| 1099 | m_cart[0].sram = image.get_software_region("nvram") ? image.get_software_region_length("nvram") : 0; |
| 1101 | 1100 | |
| 1102 | | if (state->m_cart[0].sram > 0) |
| 1101 | if (m_cart[0].sram > 0) |
| 1103 | 1102 | { |
| 1104 | | if (state->m_cart[0].sram > state->m_cart[0].sram_max) |
| 1105 | | fatalerror("Found more memory than max allowed (found: %x, max: %x), check xml file!\n", state->m_cart[0].sram, state->m_cart[0].sram_max); |
| 1103 | if (m_cart[0].sram > m_cart[0].sram_max) |
| 1104 | fatalerror("Found more memory than max allowed (found: %x, max: %x), check xml file!\n", m_cart[0].sram, m_cart[0].sram_max); |
| 1106 | 1105 | } |
| 1107 | 1106 | // TODO: Eventually sram handlers should point to the allocated cart:sram region! |
| 1108 | 1107 | // For now, we only use the region as a placeholder to carry size info... |
| 1109 | | // printf("size %x\n", state->m_cart[0].sram); |
| 1108 | // printf("size %x\n", m_cart[0].sram); |
| 1110 | 1109 | } |
| 1111 | 1110 | |
| 1112 | 1111 | /* adjust size for very large carts */ |
| 1113 | | if (state->m_cart[0].mode == SNES_MODE_20 && ((state->m_cart_size - offset) > 0x200000 || state->m_cart[0].sram > (32 * 1024))) |
| 1114 | | state->m_cart[0].small_sram = 1; |
| 1112 | if (m_cart[0].mode == SNES_MODE_20 && ((m_cart_size - offset) > 0x200000 || m_cart[0].sram > (32 * 1024))) |
| 1113 | m_cart[0].small_sram = 1; |
| 1115 | 1114 | else |
| 1116 | | state->m_cart[0].small_sram = 0; |
| 1115 | m_cart[0].small_sram = 0; |
| 1117 | 1116 | |
| 1118 | 1117 | /* Log snes_cart information */ |
| 1119 | 1118 | snes_cart_log_info(machine, total_blocks, supported_type); |
| r21631 | r21632 | |
| 1128 | 1127 | DEVICE_IMAGE_LOAD_MEMBER( snes_state,sufami_cart ) |
| 1129 | 1128 | { |
| 1130 | 1129 | running_machine &machine = image.device().machine(); |
| 1131 | | snes_state *state = machine.driver_data<snes_state>(); |
| 1132 | 1130 | int total_blocks, read_blocks; |
| 1133 | 1131 | int st_bios = 0, slot_id = 0; |
| 1134 | 1132 | UINT32 offset, st_data_offset = 0; |
| 1135 | 1133 | UINT8 *ROM = image.device().machine().root_device().memregion(image.device().tag())->base(); |
| 1136 | 1134 | |
| 1137 | | snes_ram = state->memregion("maincpu")->base(); |
| 1135 | snes_ram = memregion("maincpu")->base(); |
| 1138 | 1136 | |
| 1139 | 1137 | if (strcmp(image.device().tag(), ":slot_a") == 0) |
| 1140 | 1138 | { |
| r21631 | r21632 | |
| 1149 | 1147 | } |
| 1150 | 1148 | |
| 1151 | 1149 | if (image.software_entry() == NULL) |
| 1152 | | state->m_cart_size = image.length(); |
| 1150 | m_cart_size = image.length(); |
| 1153 | 1151 | else |
| 1154 | | state->m_cart_size = image.get_software_region_length("rom"); |
| 1152 | m_cart_size = image.get_software_region_length("rom"); |
| 1155 | 1153 | |
| 1156 | 1154 | /* Check for a header (512 bytes), and skip it if found */ |
| 1157 | | offset = snes_skip_header(image, state->m_cart_size); |
| 1155 | offset = snes_skip_header(image, m_cart_size); |
| 1158 | 1156 | |
| 1159 | 1157 | if (image.software_entry() == NULL) |
| 1160 | 1158 | { |
| 1161 | 1159 | image.fseek(offset, SEEK_SET); |
| 1162 | | image.fread( ROM, state->m_cart_size - offset); |
| 1160 | image.fread(ROM, m_cart_size - offset); |
| 1163 | 1161 | } |
| 1164 | 1162 | else |
| 1165 | | memcpy(ROM, image.get_software_region("rom") + offset, state->m_cart_size - offset); |
| 1163 | memcpy(ROM, image.get_software_region("rom") + offset, m_cart_size - offset); |
| 1166 | 1164 | |
| 1167 | | if (SNES_CART_DEBUG) mame_printf_error("size %08X\n", state->m_cart_size - offset); |
| 1165 | if (SNES_CART_DEBUG) mame_printf_error("size %08X\n", m_cart_size - offset); |
| 1168 | 1166 | |
| 1169 | 1167 | /* Detect Sufami Turbo carts */ |
| 1170 | 1168 | if (!memcmp(ROM, "BANDAI SFC-ADX", 14)) |
| 1171 | 1169 | { |
| 1172 | | state->m_cart[slot_id].mode = SNES_MODE_ST; |
| 1170 | m_cart[slot_id].mode = SNES_MODE_ST; |
| 1173 | 1171 | if (!memcmp(ROM + 16, "SFC-ADX BACKUP", 14)) |
| 1174 | 1172 | st_bios = 1; |
| 1175 | 1173 | } |
| r21631 | r21632 | |
| 1190 | 1188 | /* FIXME: Insert crc check here? */ |
| 1191 | 1189 | |
| 1192 | 1190 | /* How many blocks of data are available to be loaded? */ |
| 1193 | | total_blocks = (state->m_cart_size - offset) / 0x8000; |
| 1191 | total_blocks = (m_cart_size - offset) / 0x8000; |
| 1194 | 1192 | read_blocks = 0; |
| 1195 | 1193 | |
| 1196 | 1194 | if (SNES_CART_DEBUG) |
| r21631 | r21632 | |
| 1223 | 1221 | |
| 1224 | 1222 | sufami_load_sram(machine, image.device().tag()); |
| 1225 | 1223 | |
| 1226 | | state->m_cart[slot_id].slot_in_use = 1; // aknowledge the cart in this slot, for saving sram at exit |
| 1224 | m_cart[slot_id].slot_in_use = 1; // aknowledge the cart in this slot, for saving sram at exit |
| 1227 | 1225 | |
| 1228 | 1226 | auto_free(image.device().machine(), ROM); |
| 1229 | 1227 | |