comparison romdb.c @ 2321:2eda5f81f91e

More fully baked ROM db support for SMS
author Michael Pavone <pavone@retrodev.com>
date Thu, 15 Jun 2023 09:36:11 -0700
parents 8016dbb0fcde
children 26597f9805b4
comparison
equal deleted inserted replaced
2320:8016dbb0fcde 2321:2eda5f81f91e
701 } 701 }
702 debug_message("EEPROM address %X: sda read: %X, sda write: %X, scl: %X\n", start, eep_map->sda_read_bit, eep_map->sda_write_mask, eep_map->scl_mask); 702 debug_message("EEPROM address %X: sda read: %X, sda write: %X, scl: %X\n", start, eep_map->sda_read_bit, eep_map->sda_write_mask, eep_map->scl_mask);
703 state->info->num_eeprom++; 703 state->info->num_eeprom++;
704 } 704 }
705 705
706 void map_iter_fun(char *key, tern_val val, uint8_t valtype, void *data) 706 char *map_node_common(char *key, tern_val val, uint8_t valtype, map_iter_state *state)
707 { 707 {
708 map_iter_state *state = data;
709 if (valtype != TVAL_NODE) { 708 if (valtype != TVAL_NODE) {
710 fatal_error("ROM DB map entry %d with address %s is not a node\n", state->index, key); 709 fatal_error("ROM DB map entry %d with address %s is not a node\n", state->index, key);
711 } 710 }
712 tern_node *node = val.ptrval; 711 tern_node *node = val.ptrval;
713 uint32_t start = strtol(key, NULL, 16); 712 uint32_t start = strtol(key, NULL, 16);
718 char * dtype = tern_find_ptr_default(node, "device", "ROM"); 717 char * dtype = tern_find_ptr_default(node, "device", "ROM");
719 uint32_t offset = strtol(tern_find_ptr_default(node, "offset", "0"), NULL, 16); 718 uint32_t offset = strtol(tern_find_ptr_default(node, "offset", "0"), NULL, 16);
720 memmap_chunk *map = state->info->map + state->index; 719 memmap_chunk *map = state->info->map + state->index;
721 map->start = start; 720 map->start = start;
722 map->end = end + 1; 721 map->end = end + 1;
722
723 if (!strcmp(dtype, "ROM")) { 723 if (!strcmp(dtype, "ROM")) {
724 uint32_t expanded_size = nearest_pow2(state->rom_size); 724 uint32_t expanded_size = nearest_pow2(state->rom_size);
725 if (offset >= expanded_size) { 725 if (offset >= expanded_size) {
726 fatal_error("offset of %X is invalid for ROM size of %X in map entry %d with addess %s\n", offset, state->rom_size, state->index, key); 726 fatal_error("offset of %X is invalid for ROM size of %X in map entry %d with addess %s\n", offset, state->rom_size, state->index, key);
727 } 727 }
730 if (strcmp(tern_find_ptr_default(node, "writeable", "no"), "yes")) { 730 if (strcmp(tern_find_ptr_default(node, "writeable", "no"), "yes")) {
731 map->flags = MMAP_READ; 731 map->flags = MMAP_READ;
732 } else { 732 } else {
733 map->flags = MMAP_READ | MMAP_WRITE | MMAP_CODE; 733 map->flags = MMAP_READ | MMAP_WRITE | MMAP_CODE;
734 } 734 }
735 } else if (!strcmp(dtype, "LOCK-ON")) { 735 return NULL;
736 }
737 if (!strcmp(dtype, "EEPROM")) {
738 process_eeprom_def(key, state);
739 add_eeprom_map(node, start, end, state);
740
741 map->write_16 = write_eeprom_i2c_w;
742 map->write_8 = write_eeprom_i2c_b;
743 map->read_16 = read_eeprom_i2c_w;
744 map->read_8 = read_eeprom_i2c_b;
745 map->mask = 0xFFFFFF;
746 return NULL;
747 }
748 if (!strcmp(dtype, "SRAM")) {
749 process_sram_def(key, state);
750 map->buffer = state->info->save_buffer + offset;
751 map->flags = MMAP_READ | MMAP_WRITE;
752 uint32_t save_size_mask = state->info->save_size;
753 if (state->info->save_type == RAM_FLAG_ODD) {
754 map->flags |= MMAP_ONLY_ODD;
755 save_size_mask *= 2;
756 } else if(state->info->save_type == RAM_FLAG_EVEN) {
757 map->flags |= MMAP_ONLY_EVEN;
758 save_size_mask *= 2;
759 } else {
760 map->flags |= MMAP_CODE;
761 }
762 map->mask = calc_mask(save_size_mask, start, end);
763 return NULL;
764 }
765 if (!strcmp(dtype, "RAM")) {
766 uint32_t size = strtol(tern_find_ptr_default(node, "size", "0"), NULL, 16);
767 if (!size || size > map->end - map->start) {
768 size = map->end - map->start;
769 }
770 map->buffer = calloc(size, 1);
771 map->flags = MMAP_READ | MMAP_WRITE;
772 char *bus = tern_find_ptr_default(node, "bus", "both");
773 if (!strcmp(bus, "odd")) {
774 map->flags |= MMAP_ONLY_ODD;
775 size *= 2;
776 } else if (!strcmp(bus, "even")) {
777 map->flags |= MMAP_ONLY_EVEN;
778 size *= 2;
779 } else {
780 map->flags |= MMAP_CODE;
781 }
782 map->mask = calc_mask(size, start, end);
783 return NULL;
784 }
785 if (!strcmp(dtype, "NOR")) {
786 process_nor_def(key, state);
787
788 map->write_16 = nor_flash_write_w;
789 map->write_8 = nor_flash_write_b;
790 map->read_16 = nor_flash_read_w;
791 map->read_8 = nor_flash_read_b;
792 if (state->info->save_bus == RAM_FLAG_BOTH) {
793 map->flags |= MMAP_READ_CODE | MMAP_CODE;
794 map->buffer = state->info->save_buffer;
795 }
796 map->mask = 0xFFFFFF;
797 return NULL;
798 }
799 if (!strcmp(dtype, "fixed")) {
800 uint16_t *value = malloc(2);
801 map->buffer = value;
802 map->mask = 0;
803 map->flags = MMAP_READ;
804 *value = strtol(tern_find_ptr_default(node, "value", "0"), NULL, 16);
805 return NULL;
806 }
807 return dtype;
808 }
809
810 void map_iter_fun(char *key, tern_val val, uint8_t valtype, void *data)
811 {
812 map_iter_state *state = data;
813 char *dtype = map_node_common(key, val, valtype, state);
814 if (!dtype) {
815 //entry was handled by common function
816 state->index++;
817 return;
818 }
819 tern_node *node = val.ptrval;
820 memmap_chunk *map = state->info->map + state->index;
821 uint32_t offset = strtol(tern_find_ptr_default(node, "offset", "0"), NULL, 16);
822 if (!strcmp(dtype, "LOCK-ON")) {
736 rom_info lock_info; 823 rom_info lock_info;
737 if (state->lock_on) { 824 if (state->lock_on) {
738 lock_info = configure_rom(state->rom_db, state->lock_on, state->lock_on_size, NULL, 0, NULL, 0); 825 lock_info = configure_rom(state->rom_db, state->lock_on, state->lock_on_size, NULL, 0, NULL, 0);
739 } else if (state->rom_size > start) { 826 } else if (state->rom_size > map->start) {
740 //This is a bit of a hack to deal with pre-combined S3&K/S2&K ROMs and S&K ROM hacks 827 //This is a bit of a hack to deal with pre-combined S3&K/S2&K ROMs and S&K ROM hacks
741 lock_info = configure_rom(state->rom_db, state->rom + start, state->rom_size - start, NULL, 0, NULL, 0); 828 lock_info = configure_rom(state->rom_db, state->rom + map->start, state->rom_size - map->start, NULL, 0, NULL, 0);
742 } else { 829 } else {
743 //skip this entry if there is no lock on cartridge attached 830 //skip this entry if there is no lock on cartridge attached
744 return; 831 return;
745 } 832 }
746 uint32_t matching_chunks = 0; 833 uint32_t matching_chunks = 0;
791 lock_info.save_buffer = NULL; 878 lock_info.save_buffer = NULL;
792 lock_info.save_type = SAVE_NONE; 879 lock_info.save_type = SAVE_NONE;
793 } 880 }
794 free_rom_info(&lock_info); 881 free_rom_info(&lock_info);
795 return; 882 return;
796 } else if (!strcmp(dtype, "EEPROM")) {
797 process_eeprom_def(key, state);
798 add_eeprom_map(node, start, end, state);
799
800 map->write_16 = write_eeprom_i2c_w;
801 map->write_8 = write_eeprom_i2c_b;
802 map->read_16 = read_eeprom_i2c_w;
803 map->read_8 = read_eeprom_i2c_b;
804 map->mask = 0xFFFFFF;
805 } else if (!strcmp(dtype, "SRAM")) {
806 process_sram_def(key, state);
807 map->buffer = state->info->save_buffer + offset;
808 map->flags = MMAP_READ | MMAP_WRITE;
809 uint32_t save_size_mask = state->info->save_size;
810 if (state->info->save_type == RAM_FLAG_ODD) {
811 map->flags |= MMAP_ONLY_ODD;
812 save_size_mask *= 2;
813 } else if(state->info->save_type == RAM_FLAG_EVEN) {
814 map->flags |= MMAP_ONLY_EVEN;
815 save_size_mask *= 2;
816 } else {
817 map->flags |= MMAP_CODE;
818 }
819 map->mask = calc_mask(save_size_mask, start, end);
820 } else if (!strcmp(dtype, "RAM")) {
821 uint32_t size = strtol(tern_find_ptr_default(node, "size", "0"), NULL, 16);
822 if (!size || size > map->end - map->start) {
823 size = map->end - map->start;
824 }
825 map->buffer = calloc(size, 1);
826 map->flags = MMAP_READ | MMAP_WRITE;
827 char *bus = tern_find_ptr_default(node, "bus", "both");
828 if (!strcmp(bus, "odd")) {
829 map->flags |= MMAP_ONLY_ODD;
830 size *= 2;
831 } else if (!strcmp(bus, "even")) {
832 map->flags |= MMAP_ONLY_EVEN;
833 size *= 2;
834 } else {
835 map->flags |= MMAP_CODE;
836 }
837 map->mask = calc_mask(size, start, end);
838 } else if (!strcmp(dtype, "NOR")) {
839 process_nor_def(key, state);
840
841 map->write_16 = nor_flash_write_w;
842 map->write_8 = nor_flash_write_b;
843 map->read_16 = nor_flash_read_w;
844 map->read_8 = nor_flash_read_b;
845 if (state->info->save_bus == RAM_FLAG_BOTH) {
846 map->flags |= MMAP_READ_CODE | MMAP_CODE;
847 map->buffer = state->info->save_buffer;
848 }
849 map->mask = 0xFFFFFF;
850 } else if (!strcmp(dtype, "Sega mapper")) { 883 } else if (!strcmp(dtype, "Sega mapper")) {
851 state->info->mapper_type = MAPPER_SEGA; 884 state->info->mapper_type = MAPPER_SEGA;
852 state->info->mapper_start_index = state->ptr_index++; 885 state->info->mapper_start_index = state->ptr_index++;
853 char *variant = tern_find_ptr_default(node, "variant", "full"); 886 char *variant = tern_find_ptr_default(node, "variant", "full");
854 char *save_device = tern_find_path(node, "save\0device\0", TVAL_PTR).ptrval; 887 char *save_device = tern_find_path(node, "save\0device\0", TVAL_PTR).ptrval;
855 if (save_device && !strcmp(save_device, "EEPROM")) { 888 if (save_device && !strcmp(save_device, "EEPROM")) {
856 process_eeprom_def(key, state); 889 process_eeprom_def(key, state);
857 add_eeprom_map(node, start & map->mask, end & map->mask, state); 890 add_eeprom_map(node, map->start & map->mask, (map->end - 1) & map->mask, state);
858 } else if (save_device && !strcmp(save_device, "SRAM")) { 891 } else if (save_device && !strcmp(save_device, "SRAM")) {
859 process_sram_def(key, state); 892 process_sram_def(key, state);
860 } else if(has_ram_header(state->rom, state->rom_size)) { 893 } else if(has_ram_header(state->rom, state->rom_size)) {
861 //no save definition in ROM DB entry, but there is an SRAM header 894 //no save definition in ROM DB entry, but there is an SRAM header
862 //this support is mostly to handle homebrew that uses the SSF2 product ID 895 //this support is mostly to handle homebrew that uses the SSF2 product ID
866 if (!strcmp(variant, "save-only")) { 899 if (!strcmp(variant, "save-only")) {
867 state->info->map_chunks+=1; 900 state->info->map_chunks+=1;
868 state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks); 901 state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks);
869 memset(state->info->map + state->info->map_chunks - 1, 0, sizeof(memmap_chunk) * 1); 902 memset(state->info->map + state->info->map_chunks - 1, 0, sizeof(memmap_chunk) * 1);
870 map = state->info->map + state->index; 903 map = state->info->map + state->index;
871 map->start = start;
872 map->end = end;
873 offset &= nearest_pow2(state->rom_size) - 1; 904 offset &= nearest_pow2(state->rom_size) - 1;
874 map->buffer = state->rom + offset; 905 map->buffer = state->rom + offset;
875 map->mask = calc_mask(state->rom_size - offset, start, end); 906 map->mask = calc_mask(state->rom_size - offset, map->start, map->end - 1);
876 map->ptr_index = state->info->mapper_start_index; 907 map->ptr_index = state->info->mapper_start_index;
877 map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE | MMAP_FUNC_NULL; 908 map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE | MMAP_FUNC_NULL;
878 if (save_device && !strcmp(save_device, "EEPROM")) { 909 if (save_device && !strcmp(save_device, "EEPROM")) {
879 map->write_16 = write_eeprom_i2c_w; 910 map->write_16 = write_eeprom_i2c_w;
880 map->write_8 = write_eeprom_i2c_b; 911 map->write_8 = write_eeprom_i2c_b;
891 } else { 922 } else {
892 state->info->map_chunks+=7; 923 state->info->map_chunks+=7;
893 state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks); 924 state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks);
894 memset(state->info->map + state->info->map_chunks - 7, 0, sizeof(memmap_chunk) * 7); 925 memset(state->info->map + state->info->map_chunks - 7, 0, sizeof(memmap_chunk) * 7);
895 map = state->info->map + state->index; 926 map = state->info->map + state->index;
927 uint32_t start = map->start;
896 for (int i = 0; i < 7; i++, state->index++, map++) 928 for (int i = 0; i < 7; i++, state->index++, map++)
897 { 929 {
898 map->start = start + i * 0x80000; 930 map->start = start + i * 0x80000;
899 map->end = start + (i + 1) * 0x80000; 931 map->end = start + (i + 1) * 0x80000;
900 map->mask = 0x7FFFF; 932 map->mask = 0x7FFFF;
929 map->buffer = NULL; 961 map->buffer = NULL;
930 map->mask = 0xFF; 962 map->mask = 0xFF;
931 map->write_16 = menu_write_w; 963 map->write_16 = menu_write_w;
932 map->read_16 = menu_read_w; 964 map->read_16 = menu_read_w;
933 #endif 965 #endif
934 } else if (!strcmp(dtype, "fixed")) {
935 uint16_t *value = malloc(2);
936 map->buffer = value;
937 map->mask = 0;
938 map->flags = MMAP_READ;
939 *value = strtol(tern_find_ptr_default(node, "value", "0"), NULL, 16);
940 } else if (!strcmp(dtype, "multi-game")) { 966 } else if (!strcmp(dtype, "multi-game")) {
941 state->info->mapper_type = MAPPER_MULTI_GAME; 967 state->info->mapper_type = MAPPER_MULTI_GAME;
942 state->info->mapper_start_index = state->ptr_index++; 968 state->info->mapper_start_index = state->ptr_index++;
943 //make a mirror copy of the ROM so we can efficiently support arbitrary start offsets 969 //make a mirror copy of the ROM so we can efficiently support arbitrary start offsets
944 state->rom = realloc(state->rom, state->rom_size * 2); 970 state->rom = realloc(state->rom, state->rom_size * 2);
948 state->info->map_chunks+=1; 974 state->info->map_chunks+=1;
949 state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks); 975 state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks);
950 memset(state->info->map + state->info->map_chunks - 1, 0, sizeof(memmap_chunk) * 1); 976 memset(state->info->map + state->info->map_chunks - 1, 0, sizeof(memmap_chunk) * 1);
951 map = state->info->map + state->index; 977 map = state->info->map + state->index;
952 map->buffer = state->rom; 978 map->buffer = state->rom;
953 map->mask = calc_mask(state->rom_size, start, end); 979 map->mask = calc_mask(state->rom_size, map->start, map->end - 1);
954 map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE; 980 map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE;
955 map->ptr_index = state->info->mapper_start_index; 981 map->ptr_index = state->info->mapper_start_index;
956 map++; 982 map++;
957 state->index++; 983 state->index++;
958 map->start = 0xA13000; 984 map->start = 0xA13000;
986 uint32_t expanded_size = nearest_pow2(state->rom_size); 1012 uint32_t expanded_size = nearest_pow2(state->rom_size);
987 if (offset >= expanded_size) { 1013 if (offset >= expanded_size) {
988 fatal_error("offset of %X is invalid for ROM size of %X in map entry %d with addess %s\n", offset, state->rom_size, state->index, key); 1014 fatal_error("offset of %X is invalid for ROM size of %X in map entry %d with addess %s\n", offset, state->rom_size, state->index, key);
989 } 1015 }
990 map->buffer = state->rom + offset; 1016 map->buffer = state->rom + offset;
991 map->mask = calc_mask(nearest_pow2(state->rom_size) - offset, start, end); 1017 map->mask = calc_mask(nearest_pow2(state->rom_size) - offset, map->start, map->end - 1);
992 map->write_8 = sft_wukong_write_b; 1018 map->write_8 = sft_wukong_write_b;
993 map->write_16 = sft_wukong_write_w; 1019 map->write_16 = sft_wukong_write_w;
994 if (!strcmp(dtype, "sft-wukong-remap")) { 1020 if (!strcmp(dtype, "sft-wukong-remap")) {
995 map->flags = MMAP_READ | MMAP_CODE | MMAP_PTR_IDX; 1021 map->flags = MMAP_READ | MMAP_CODE | MMAP_PTR_IDX;
996 state->info->mapper_start_index = state->ptr_index++; 1022 state->info->mapper_start_index = state->ptr_index++;
999 } 1025 }
1000 } else { 1026 } else {
1001 fatal_error("Invalid device type %s for ROM DB map entry %d with address %s\n", dtype, state->index, key); 1027 fatal_error("Invalid device type %s for ROM DB map entry %d with address %s\n", dtype, state->index, key);
1002 } 1028 }
1003 state->index++; 1029 state->index++;
1030 }
1031
1032 void handle_io_overrides(tern_node *entry, rom_info *info)
1033 {
1034 tern_node *device_overrides = tern_find_node(entry, "device_overrides");
1035 if (device_overrides) {
1036 info->port1_override = tern_find_ptr(device_overrides, "1");
1037 info->port2_override = tern_find_ptr(device_overrides, "2");
1038 info->ext_override = tern_find_ptr(device_overrides, "ext");
1039 if (
1040 info->save_type == SAVE_NONE
1041 && (
1042 (info->port1_override && startswith(info->port1_override, "heartbeat_trainer."))
1043 || (info->port2_override && startswith(info->port2_override, "heartbeat_trainer."))
1044 || (info->ext_override && startswith(info->ext_override, "heartbeat_trainer."))
1045 )
1046 ) {
1047 info->save_type = SAVE_HBPT;
1048 info->save_size = atoi(tern_find_path_default(entry, "HeartbeatTrainer\0size\0", (tern_val){.ptrval="512"}, TVAL_PTR).ptrval);
1049 info->save_buffer = calloc(info->save_size + 5 + 8, 1);
1050 memset(info->save_buffer, 0xFF, info->save_size);
1051 }
1052 } else {
1053 info->port1_override = info->port2_override = info->ext_override = NULL;
1054 }
1004 } 1055 }
1005 1056
1006 rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, void *lock_on, uint32_t lock_on_size, memmap_chunk const *base_map, uint32_t base_chunks) 1057 rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, void *lock_on, uint32_t lock_on_size, memmap_chunk const *base_map, uint32_t base_chunks)
1007 { 1058 {
1008 uint8_t product_id[GAME_ID_LEN+1]; 1059 uint8_t product_id[GAME_ID_LEN+1];
1108 } 1159 }
1109 } else { 1160 } else {
1110 add_memmap_header(&info, rom, rom_size, base_map, base_chunks); 1161 add_memmap_header(&info, rom, rom_size, base_map, base_chunks);
1111 } 1162 }
1112 1163
1113 tern_node *device_overrides = tern_find_node(entry, "device_overrides"); 1164 handle_io_overrides(entry, &info);
1114 if (device_overrides) {
1115 info.port1_override = tern_find_ptr(device_overrides, "1");
1116 info.port2_override = tern_find_ptr(device_overrides, "2");
1117 info.ext_override = tern_find_ptr(device_overrides, "ext");
1118 if (
1119 info.save_type == SAVE_NONE
1120 && (
1121 (info.port1_override && startswith(info.port1_override, "heartbeat_trainer."))
1122 || (info.port2_override && startswith(info.port2_override, "heartbeat_trainer."))
1123 || (info.ext_override && startswith(info.ext_override, "heartbeat_trainer."))
1124 )
1125 ) {
1126 info.save_type = SAVE_HBPT;
1127 info.save_size = atoi(tern_find_path_default(entry, "HeartbeatTrainer\0size\0", (tern_val){.ptrval="512"}, TVAL_PTR).ptrval);
1128 info.save_buffer = calloc(info.save_size + 5 + 8, 1);
1129 memset(info.save_buffer, 0xFF, info.save_size);
1130 }
1131 } else {
1132 info.port1_override = info.port2_override = info.ext_override = NULL;
1133 }
1134 info.mouse_mode = tern_find_ptr(entry, "mouse_mode"); 1165 info.mouse_mode = tern_find_ptr(entry, "mouse_mode");
1135 info.wants_cd = !strcmp(tern_find_ptr_default(entry, "wants_cd", "no"), "yes"); 1166 info.wants_cd = !strcmp(tern_find_ptr_default(entry, "wants_cd", "no"), "yes");
1136 1167
1137 return info; 1168 return info;
1138 } 1169 }
1139 1170
1140 void *sms_sega_mapper_write(uint32_t location, void *vcontext, uint8_t value); 1171 void *sms_sega_mapper_write(uint32_t location, void *vcontext, uint8_t value);
1172 void *sms_cart_ram_write(uint32_t location, void *vcontext, uint8_t value);
1173 void map_iter_fun_sms(char *key, tern_val val, uint8_t valtype, void *data)
1174 {
1175 map_iter_state *state = data;
1176 char *dtype = map_node_common(key, val, valtype, state);
1177 if (!dtype) {
1178 //entry was handled by common function
1179 state->index++;
1180 return;
1181 }
1182 tern_node *node = val.ptrval;
1183 memmap_chunk *map = state->info->map + state->index;
1184 uint32_t offset = strtol(tern_find_ptr_default(node, "offset", "0"), NULL, 16);
1185 if (!strcmp(dtype, "Sega mapper")) {
1186 state->info->mapper_type = MAPPER_SMS_SEGA;
1187 state->info->mapper_start_index = state->ptr_index++;
1188 char *save_device = tern_find_path(node, "save\0device\0", TVAL_PTR).ptrval;
1189 if (save_device && !strcmp(save_device, "EEPROM")) {
1190 process_eeprom_def(key, state);
1191 add_eeprom_map(node, map->start & map->mask, (map->end - 1) & map->mask, state);
1192 } else if (save_device && !strcmp(save_device, "SRAM")) {
1193 process_sram_def(key, state);
1194 }
1195 state->info->map_chunks += 4;
1196 state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks);
1197 map = state->info->map + state->index;
1198 map[0].start = 0;
1199 map[0].end = 0x400;
1200 map[0].mask = 0xFFFF;
1201 map[0].flags = MMAP_READ;
1202 map[0].buffer = state->info->rom;
1203 map[1].start = 0x400;
1204 map[1].end = 0x4000;
1205 map[1].mask = 0x3FFF;
1206 map[1].ptr_index = 0;
1207 map[1].flags = MMAP_READ|MMAP_PTR_IDX|MMAP_CODE;
1208 map[2].start = 0x4000;
1209 map[2].end = 0x8000;
1210 map[2].mask = 0x3FFF;
1211 map[2].ptr_index = 1;
1212 map[2].flags = MMAP_READ|MMAP_PTR_IDX|MMAP_CODE;
1213 map[3].start = 0x8000;
1214 map[3].end = 0xC000;
1215 map[3].mask = 0x3FFF;
1216 map[3].ptr_index = 2;
1217 if (state->info->save_type == RAM_FLAG_ODD || state->info->save_type == RAM_FLAG_EVEN) {
1218 map[3].write_8 = sms_cart_ram_write;
1219 }
1220 map[3].flags = MMAP_READ|MMAP_PTR_IDX|MMAP_CODE;
1221 map[4].start = 0xFFFC;
1222 map[4].end = 0x10000;
1223 map[4].mask = 3;
1224 map[4].flags = MMAP_READ;
1225 map[4].write_8 = sms_sega_mapper_write;
1226 } else {
1227 fatal_error("Invalid device type %s for ROM DB map entry %d with address %s\n", dtype, state->index, key);
1228 }
1229 }
1230
1141 void sms_memmap_heuristics(rom_info *info, memmap_chunk const *base_map, uint32_t num_base_chunks) 1231 void sms_memmap_heuristics(rom_info *info, memmap_chunk const *base_map, uint32_t num_base_chunks)
1142 { 1232 {
1143 uint32_t num_chunks = num_base_chunks + (info->rom_size > 0xC000 ? 5 : 1); 1233 uint32_t num_chunks = num_base_chunks + (info->rom_size > 0xC000 ? 5 : 1);
1144 memmap_chunk *chunks = calloc(num_chunks, sizeof(memmap_chunk)); 1234 memmap_chunk *chunks = calloc(num_chunks, sizeof(memmap_chunk));
1145 info->map = chunks; 1235 info->map = chunks;
1153 chunks[0].mask = 0xFFFF; 1243 chunks[0].mask = 0xFFFF;
1154 chunks[0].flags = MMAP_READ; 1244 chunks[0].flags = MMAP_READ;
1155 chunks[0].buffer = info->rom; 1245 chunks[0].buffer = info->rom;
1156 chunks[1].start = 0x400; 1246 chunks[1].start = 0x400;
1157 chunks[1].end = 0x4000; 1247 chunks[1].end = 0x4000;
1158 chunks[1].mask = 0xFFFF; 1248 chunks[1].mask = 0x3FFF;
1159 chunks[1].ptr_index = 0; 1249 chunks[1].ptr_index = 0;
1160 chunks[1].flags = MMAP_READ|MMAP_PTR_IDX|MMAP_CODE; 1250 chunks[1].flags = MMAP_READ|MMAP_PTR_IDX|MMAP_CODE;
1161 chunks[2].start = 0x4000; 1251 chunks[2].start = 0x4000;
1162 chunks[2].end = 0x8000; 1252 chunks[2].end = 0x8000;
1163 chunks[2].mask = 0x3FFF; 1253 chunks[2].mask = 0x3FFF;
1166 chunks[3].start = 0x8000; 1256 chunks[3].start = 0x8000;
1167 chunks[3].end = 0xC000; 1257 chunks[3].end = 0xC000;
1168 chunks[3].mask = 0x3FFF; 1258 chunks[3].mask = 0x3FFF;
1169 chunks[3].ptr_index = 2; 1259 chunks[3].ptr_index = 2;
1170 chunks[3].flags = MMAP_READ|MMAP_PTR_IDX|MMAP_CODE; 1260 chunks[3].flags = MMAP_READ|MMAP_PTR_IDX|MMAP_CODE;
1171 chunks[5].start = 0xFFFC; 1261 chunks[3].write_8 = sms_cart_ram_write;
1172 chunks[5].end = 0x10000; 1262 chunks[num_chunks - 1].start = 0xFFFC;
1173 chunks[5].mask = 3; 1263 chunks[num_chunks - 1].end = 0x10000;
1174 chunks[5].flags = MMAP_READ; 1264 chunks[num_chunks - 1].mask = 3;
1175 chunks[5].write_8 = sms_sega_mapper_write; 1265 chunks[num_chunks - 1].flags = MMAP_READ;
1176 if (chunks[4].end > 0xFFFC) { 1266 chunks[num_chunks - 1].write_8 = sms_sega_mapper_write;
1177 //mapper regs overlap RAM from base map 1267 for (uint32_t i = 4; i < num_chunks - 1; i++)
1178 chunks[4].end = 0xFFFC; 1268 {
1269 if (chunks[i].end > 0xFFFC) {
1270 //mapper regs overlap RAM from base map
1271 chunks[i].end = 0xFFFC;
1272 }
1179 } 1273 }
1180 } else { 1274 } else {
1181 info->mapper_type = MAPPER_NONE; 1275 info->mapper_type = MAPPER_NONE;
1182 memcpy(chunks + 1, base_map, sizeof(memmap_chunk) * num_base_chunks); 1276 memcpy(chunks + 1, base_map, sizeof(memmap_chunk) * num_base_chunks);
1183 chunks[0].start = 0; 1277 chunks[0].start = 0;
1267 while (*dbreg != 0) 1361 while (*dbreg != 0)
1268 { 1362 {
1269 info.regions |= translate_region_char(*(dbreg++)); 1363 info.regions |= translate_region_char(*(dbreg++));
1270 } 1364 }
1271 } 1365 }
1272 //TODO: check for and handle map from db 1366 tern_node *map = tern_find_node(entry, "map");
1273 sms_memmap_heuristics(&info, base_chunks, num_base_chunks); 1367 if (map) {
1368 info.save_type = SAVE_NONE;
1369 info.map_chunks = tern_count(map);
1370 if (info.map_chunks) {
1371 info.map_chunks += num_base_chunks;
1372 info.save_buffer = NULL;
1373 info.save_size = 0;
1374 info.map = malloc(sizeof(memmap_chunk) * info.map_chunks);
1375 info.eeprom_map = NULL;
1376 info.num_eeprom = 0;
1377 memset(info.map, 0, sizeof(memmap_chunk) * info.map_chunks);
1378 map_iter_state state = {
1379 .info = &info,
1380 .rom = rom,
1381 .root = entry,
1382 .rom_db = rom_db,
1383 .rom_size = rom_size,
1384 .index = 0,
1385 .num_els = info.map_chunks - num_base_chunks,
1386 .ptr_index = 0
1387 };
1388 tern_foreach(map, map_iter_fun_sms, &state);
1389 memcpy(info.map + state.index, base_chunks, sizeof(memmap_chunk) * num_base_chunks);
1390 info.rom = state.rom;
1391 info.rom_size = state.rom_size;
1392 } else {
1393 sms_memmap_heuristics(&info, base_chunks, num_base_chunks);
1394 }
1395 } else {
1396 sms_memmap_heuristics(&info, base_chunks, num_base_chunks);
1397 }
1398 handle_io_overrides(entry, &info);
1274 return info; 1399 return info;
1275 } 1400 }