Mercurial > repos > blastem
comparison romdb.c @ 1409:b0e0bb20fc41
Fix and enhance Sega/SSF2 mapper support to handle homebrew and hacks that use it in combination with SRAM
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Mon, 19 Jun 2017 23:27:11 -0700 |
parents | 71b6e2298e4a |
children | 4cd4aa6be5f6 |
comparison
equal
deleted
inserted
replaced
1408:71b6e2298e4a | 1409:b0e0bb20fc41 |
---|---|
491 address &= 0xE; | 491 address &= 0xE; |
492 address >>= 1; | 492 address >>= 1; |
493 gen->bank_regs[address] = value; | 493 gen->bank_regs[address] = value; |
494 if (!address) { | 494 if (!address) { |
495 if (value & 1) { | 495 if (value & 1) { |
496 for (int i = 0; i < 8; i++) | 496 //Used for games that only use the mapper for SRAM |
497 context->mem_pointers[gen->mapper_start_index] = NULL; | |
498 //For games that need more than 4MB | |
499 for (int i = 4; i < 8; i++) | |
497 { | 500 { |
498 context->mem_pointers[gen->mapper_start_index + i] = NULL; | 501 context->mem_pointers[gen->mapper_start_index + i] = NULL; |
499 } | 502 } |
500 } else { | 503 } else { |
501 //Used for games that only use the mapper for SRAM | 504 //Used for games that only use the mapper for SRAM |
502 context->mem_pointers[gen->mapper_start_index] = gen->cart + 0x200000/2; | 505 context->mem_pointers[gen->mapper_start_index] = gen->cart + 0x200000/2; |
503 //For games that need more than 4MB | 506 //For games that need more than 4MB |
504 for (int i = 1; i < 8; i++) | 507 for (int i = 4; i < 8; i++) |
505 { | 508 { |
506 context->mem_pointers[gen->mapper_start_index + i] = gen->cart + 0x40000*gen->bank_regs[i]; | 509 context->mem_pointers[gen->mapper_start_index + i] = gen->cart + 0x40000*gen->bank_regs[i]; |
507 } | 510 } |
508 } | 511 } |
509 } else { | 512 } else { |
714 } else { | 717 } else { |
715 return nearest_pow2(map_size)-1; | 718 return nearest_pow2(map_size)-1; |
716 } | 719 } |
717 } | 720 } |
718 | 721 |
722 uint8_t has_ram_header(uint8_t *rom, uint32_t rom_size) | |
723 { | |
724 return rom_size >= (RAM_END + 4) && rom[RAM_ID] == 'R' && rom[RAM_ID + 1] == 'A'; | |
725 } | |
726 | |
727 uint32_t read_ram_header(rom_info *info, uint8_t *rom) | |
728 { | |
729 uint32_t ram_start = get_u32be(rom + RAM_START); | |
730 uint32_t ram_end = get_u32be(rom + RAM_END); | |
731 uint32_t ram_flags = info->save_type = rom[RAM_FLAGS] & RAM_FLAG_MASK; | |
732 ram_start &= 0xFFFFFE; | |
733 ram_end |= 1; | |
734 info->save_mask = ram_end - ram_start; | |
735 uint32_t save_size = info->save_mask + 1; | |
736 if (ram_flags != RAM_FLAG_BOTH) { | |
737 save_size /= 2; | |
738 } | |
739 info->save_size = save_size; | |
740 info->save_buffer = malloc(save_size); | |
741 return ram_start; | |
742 } | |
743 | |
719 void add_memmap_header(rom_info *info, uint8_t *rom, uint32_t size, memmap_chunk const *base_map, int base_chunks) | 744 void add_memmap_header(rom_info *info, uint8_t *rom, uint32_t size, memmap_chunk const *base_map, int base_chunks) |
720 { | 745 { |
721 uint32_t rom_end = get_u32be(rom + ROM_END) + 1; | 746 uint32_t rom_end = get_u32be(rom + ROM_END) + 1; |
722 if (size > rom_end) { | 747 if (size > rom_end) { |
723 rom_end = size; | 748 rom_end = size; |
735 info->map[0].end = 0x80000; | 760 info->map[0].end = 0x80000; |
736 info->map[0].mask = 0xFFFFFF; | 761 info->map[0].mask = 0xFFFFFF; |
737 info->map[0].flags = MMAP_READ; | 762 info->map[0].flags = MMAP_READ; |
738 info->map[0].buffer = rom; | 763 info->map[0].buffer = rom; |
739 | 764 |
765 if (has_ram_header(rom, size)){ | |
766 read_ram_header(info, rom); | |
767 } | |
768 | |
740 for (int i = 1; i < 8; i++) | 769 for (int i = 1; i < 8; i++) |
741 { | 770 { |
742 info->map[i].start = i * 0x80000; | 771 info->map[i].start = i * 0x80000; |
743 info->map[i].end = (i + 1) * 0x80000; | 772 info->map[i].end = (i + 1) * 0x80000; |
744 info->map[i].mask = 0x7FFFF; | 773 info->map[i].mask = 0x7FFFF; |
745 info->map[i].buffer = (i + 1) * 0x80000 <= size ? rom + i * 0x80000 : rom; | 774 info->map[i].buffer = (i + 1) * 0x80000 <= size ? rom + i * 0x80000 : rom; |
746 info->map[i].ptr_index = i; | 775 info->map[i].ptr_index = i; |
747 info->map[i].flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE; | 776 info->map[i].flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE | MMAP_FUNC_NULL; |
777 | |
778 info->map[i].read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[i] == NULL | |
779 info->map[i].read_8 = (read_8_fun)read_sram_b; | |
780 info->map[i].write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area | |
781 info->map[i].write_8 = (write_8_fun)write_sram_area_b; | |
748 | 782 |
749 } | 783 } |
750 info->map[8].start = 0xA13000; | 784 info->map[8].start = 0xA13000; |
751 info->map[8].end = 0xA13100; | 785 info->map[8].end = 0xA13100; |
752 info->map[8].mask = 0xFF; | 786 info->map[8].mask = 0xFF; |
753 info->map[8].write_16 = (write_16_fun)write_bank_reg_w; | 787 info->map[8].write_16 = (write_16_fun)write_bank_reg_w; |
754 info->map[8].write_8 = (write_8_fun)write_bank_reg_b; | 788 info->map[8].write_8 = (write_8_fun)write_bank_reg_b; |
755 } else if (rom[RAM_ID] == 'R' && rom[RAM_ID+1] == 'A') { | 789 } else if (has_ram_header(rom, size)) { |
756 uint32_t ram_start = get_u32be(rom + RAM_START); | 790 uint32_t ram_start = read_ram_header(info, rom); |
757 uint32_t ram_end = get_u32be(rom + RAM_END); | |
758 uint32_t ram_flags = info->save_type = rom[RAM_FLAGS] & RAM_FLAG_MASK; | |
759 ram_start &= 0xFFFFFE; | |
760 ram_end |= 1; | |
761 info->save_mask = ram_end - ram_start; | |
762 uint32_t save_size = info->save_mask + 1; | |
763 if (ram_flags != RAM_FLAG_BOTH) { | |
764 save_size /= 2; | |
765 } | |
766 info->save_size = save_size; | |
767 info->save_buffer = malloc(save_size); | |
768 | 791 |
769 info->map_chunks = base_chunks + (ram_start >= rom_end ? 2 : 3); | 792 info->map_chunks = base_chunks + (ram_start >= rom_end ? 2 : 3); |
770 info->map = malloc(sizeof(memmap_chunk) * info->map_chunks); | 793 info->map = malloc(sizeof(memmap_chunk) * info->map_chunks); |
771 memset(info->map, 0, sizeof(memmap_chunk)*2); | 794 memset(info->map, 0, sizeof(memmap_chunk)*2); |
772 memcpy(info->map+2, base_map, sizeof(memmap_chunk) * base_chunks); | 795 memcpy(info->map+2, base_map, sizeof(memmap_chunk) * base_chunks); |
781 info->map[0].flags = MMAP_READ; | 804 info->map[0].flags = MMAP_READ; |
782 info->map[0].buffer = rom; | 805 info->map[0].buffer = rom; |
783 | 806 |
784 info->map[1].start = ram_start; | 807 info->map[1].start = ram_start; |
785 info->map[1].mask = info->save_mask; | 808 info->map[1].mask = info->save_mask; |
786 info->map[1].end = ram_end + 1; | 809 info->map[1].end = ram_start + info->save_size; |
787 info->map[1].flags = MMAP_READ | MMAP_WRITE; | 810 info->map[1].flags = MMAP_READ | MMAP_WRITE; |
788 | 811 |
789 if (ram_flags == RAM_FLAG_ODD) { | 812 if (info->save_type == RAM_FLAG_ODD) { |
790 info->map[1].flags |= MMAP_ONLY_ODD; | 813 info->map[1].flags |= MMAP_ONLY_ODD; |
791 } else if (ram_flags == RAM_FLAG_EVEN) { | 814 } else if (info->save_type == RAM_FLAG_EVEN) { |
792 info->map[1].flags |= MMAP_ONLY_EVEN; | 815 info->map[1].flags |= MMAP_ONLY_EVEN; |
793 } | 816 } |
794 info->map[1].buffer = info->save_buffer; | 817 info->map[1].buffer = info->save_buffer; |
795 } else { | 818 } else { |
796 //Assume the standard Sega mapper | 819 //Assume the standard Sega mapper |
1095 map = state->info->map + state->index; | 1118 map = state->info->map + state->index; |
1096 char *save_device = tern_find_path(node, "save\0device\0", TVAL_PTR).ptrval; | 1119 char *save_device = tern_find_path(node, "save\0device\0", TVAL_PTR).ptrval; |
1097 if (save_device && !strcmp(save_device, "EEPROM")) { | 1120 if (save_device && !strcmp(save_device, "EEPROM")) { |
1098 process_eeprom_def(key, state); | 1121 process_eeprom_def(key, state); |
1099 add_eeprom_map(node, start & map->mask, end & map->mask, state); | 1122 add_eeprom_map(node, start & map->mask, end & map->mask, state); |
1123 } else if (save_device && !strcmp(save_device, "SRAM")) { | |
1124 process_sram_def(key, state); | |
1125 } else if(has_ram_header(state->rom, state->rom_size)) { | |
1126 //no save definition in ROM DB entry, but there is an SRAM header | |
1127 //this support is mostly to handle homebrew that uses the SSF2 product ID | |
1128 //in an attempt to signal desire for the full Sega/SSF2 mapper, but also uses SRAM unlike SSF2 | |
1129 read_ram_header(state->info, state->rom); | |
1100 } | 1130 } |
1101 for (int i = 0; i < 7; i++, state->index++, map++) | 1131 for (int i = 0; i < 7; i++, state->index++, map++) |
1102 { | 1132 { |
1103 map->start = start + i * 0x80000; | 1133 map->start = start + i * 0x80000; |
1104 map->end = start + (i + 1) * 0x80000; | 1134 map->end = start + (i + 1) * 0x80000; |
1105 map->mask = 0x7FFFF; | 1135 map->mask = 0x7FFFF; |
1106 map->buffer = state->rom + offset + i * 0x80000; | 1136 map->buffer = state->rom + offset + i * 0x80000; |
1107 map->ptr_index = state->ptr_index++; | 1137 map->ptr_index = state->ptr_index++; |
1108 if (i < 3 || !save_device) { | 1138 if (i < 3) { |
1109 map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE; | 1139 map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE; |
1110 } else { | 1140 } else { |
1111 map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE | MMAP_FUNC_NULL; | 1141 map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE | MMAP_FUNC_NULL; |
1112 if (!strcmp(save_device, "SRAM")) { | 1142 if (save_device && !strcmp(save_device, "EEPROM")) { |
1113 process_sram_def(key, state); | 1143 map->write_16 = write_eeprom_i2c_w; |
1144 map->write_8 = write_eeprom_i2c_b; | |
1145 map->read_16 = read_eeprom_i2c_w; | |
1146 map->read_8 = read_eeprom_i2c_b; | |
1147 } else { | |
1114 map->read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[2] == NULL | 1148 map->read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[2] == NULL |
1115 map->read_8 = (read_8_fun)read_sram_b; | 1149 map->read_8 = (read_8_fun)read_sram_b; |
1116 map->write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area | 1150 map->write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area |
1117 map->write_8 = (write_8_fun)write_sram_area_b; | 1151 map->write_8 = (write_8_fun)write_sram_area_b; |
1118 } else if (!strcmp(save_device, "EEPROM")) { | |
1119 map->write_16 = write_eeprom_i2c_w; | |
1120 map->write_8 = write_eeprom_i2c_b; | |
1121 map->read_16 = read_eeprom_i2c_w; | |
1122 map->read_8 = read_eeprom_i2c_b; | |
1123 } | 1152 } |
1124 } | 1153 } |
1125 } | 1154 } |
1126 map->start = 0xA13000; | 1155 map->start = 0xA13000; |
1127 map->end = 0xA13100; | 1156 map->end = 0xA13100; |