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;