Mercurial > repos > blastem
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 } |