comparison blastem.c @ 351:2f264d2a60c2

Support for SRAM with SEGA mapper. Half-finished support for SRAM without SEGA mapper.
author Mike Pavone <pavone@retrodev.com>
date Tue, 21 May 2013 22:08:59 -0700
parents aff29d50afd5
children 15dd6418fe67
comparison
equal deleted inserted replaced
350:91aa2aa05e68 351:2f264d2a60c2
810 genesis_context * gen = context->system; 810 genesis_context * gen = context->system;
811 ym_run(gen->ym, (context->current_cycle * MCLKS_PER_Z80) / MCLKS_PER_68K); 811 ym_run(gen->ym, (context->current_cycle * MCLKS_PER_Z80) / MCLKS_PER_68K);
812 return ym_read_status(gen->ym); 812 return ym_read_status(gen->ym);
813 } 813 }
814 814
815 uint16_t read_sram_w(uint32_t address, m68k_context * context)
816 {
817 genesis_context * gen = context->system;
818 address &= gen->save_ram_mask;
819 switch(gen->save_flags)
820 {
821 case RAM_FLAG_BOTH:
822 return gen->save_ram[address] << 8 | gen->save_ram[address+1];
823 case RAM_FLAG_EVEN:
824 return gen->save_ram[address >> 1] << 8 | 0xFF;
825 case RAM_FLAG_ODD:
826 return gen->save_ram[address >> 1] | 0xFF00;
827 }
828 return 0xFFFF;//We should never get here
829 }
830
831 uint8_t read_sram_b(uint32_t address, m68k_context * context)
832 {
833 genesis_context * gen = context->system;
834 address &= gen->save_ram_mask;
835 switch(gen->save_flags)
836 {
837 case RAM_FLAG_BOTH:
838 return gen->save_ram[address];
839 case RAM_FLAG_EVEN:
840 if (address & 1) {
841 return 0xFF;
842 } else {
843 return gen->save_ram[address >> 1];
844 }
845 case RAM_FLAG_ODD:
846 if (address & 1) {
847 return gen->save_ram[address >> 1];
848 } else {
849 return 0xFF;
850 }
851 }
852 return 0xFF;//We should never get here
853 }
854
855 m68k_context * write_sram_area_w(uint32_t address, m68k_context * context, uint16_t value)
856 {
857 genesis_context * gen = context->system;
858 if ((gen->bank_regs[0] & 0x3) == 1) {
859 address &= gen->save_ram_mask;
860 switch(gen->save_flags)
861 {
862 case RAM_FLAG_BOTH:
863 gen->save_ram[address] = value >> 8;
864 gen->save_ram[address+1] = value;
865 break;
866 case RAM_FLAG_EVEN:
867 gen->save_ram[address >> 1] = value >> 8;
868 break;
869 case RAM_FLAG_ODD:
870 gen->save_ram[address >> 1] = value;
871 break;
872 }
873 }
874 return context;
875 }
876
877 m68k_context * write_sram_area_b(uint32_t address, m68k_context * context, uint8_t value)
878 {
879 genesis_context * gen = context->system;
880 if ((gen->bank_regs[0] & 0x3) == 1) {
881 address &= gen->save_ram_mask;
882 switch(gen->save_flags)
883 {
884 case RAM_FLAG_BOTH:
885 gen->save_ram[address] = value;
886 break;
887 case RAM_FLAG_EVEN:
888 if (!(address & 1)) {
889 gen->save_ram[address >> 1] = value;
890 }
891 break;
892 case RAM_FLAG_ODD:
893 if (address & 1) {
894 gen->save_ram[address >> 1] = value;
895 }
896 break;
897 }
898 }
899 return context;
900 }
901
902 m68k_context * write_bank_reg_w(uint32_t address, m68k_context * context, uint16_t value)
903 {
904 genesis_context * gen = context->system;
905 address &= 0xE;
906 address >>= 1;
907 gen->bank_regs[address] = value;
908 if (!address) {
909 if (value & 1) {
910 context->mem_pointers[2] = NULL;
911 } else {
912 context->mem_pointers[2] = cart + 0x200000/2;
913 }
914 }
915 return context;
916 }
917
918 m68k_context * write_bank_reg_b(uint32_t address, m68k_context * context, uint8_t value)
919 {
920 if (address & 1) {
921 genesis_context * gen = context->system;
922 address &= 0xE;
923 address >>= 1;
924 gen->bank_regs[address] = value;
925 if (!address) {
926 if (value & 1) {
927 context->mem_pointers[2] = NULL;
928 } else {
929 context->mem_pointers[2] = cart + 0x200000/2;
930 }
931 }
932 }
933 return context;
934 }
935
815 typedef struct bp_def { 936 typedef struct bp_def {
816 struct bp_def * next; 937 struct bp_def * next;
817 uint32_t address; 938 uint32_t address;
818 uint32_t index; 939 uint32_t index;
819 } bp_def; 940 } bp_def;
1052 } 1173 }
1053 } 1174 }
1054 return context; 1175 return context;
1055 } 1176 }
1056 1177
1057 void init_run_cpu(genesis_context * gen, int debug, FILE * address_log) 1178 #define ROM_END 0x1A4
1058 { 1179 #define RAM_ID 0x1B0
1059 m68k_context context; 1180 #define RAM_FLAGS 0x1B2
1060 x86_68k_options opts; 1181 #define RAM_START 0x1B4
1061 gen->m68k = &context; 1182 #define RAM_END 0x1B8
1062 memmap_chunk memmap[] = { 1183 #define MAX_MAP_CHUNKS (4+7+1)
1063 {0, 0x400000, 0xFFFFFF, 0, MMAP_READ | MMAP_WRITE, cart, 1184 #define RAM_FLAG_MASK 0x1800
1185
1186 const memmap_chunk static_map[] = {
1187 {0, 0x400000, 0xFFFFFF, 0, MMAP_READ, cart,
1064 NULL, NULL, NULL, NULL}, 1188 NULL, NULL, NULL, NULL},
1065 {0xE00000, 0x1000000, 0xFFFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, ram, 1189 {0xE00000, 0x1000000, 0xFFFF, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, ram,
1066 NULL, NULL, NULL, NULL}, 1190 NULL, NULL, NULL, NULL},
1067 {0xC00000, 0xE00000, 0x1FFFFF, 0, 0, NULL, 1191 {0xC00000, 0xE00000, 0x1FFFFF, 0, 0, NULL,
1068 (read_16_fun)vdp_port_read, (write_16_fun)vdp_port_write, 1192 (read_16_fun)vdp_port_read, (write_16_fun)vdp_port_write,
1069 (read_8_fun)vdp_port_read_b, (write_8_fun)vdp_port_write_b}, 1193 (read_8_fun)vdp_port_read_b, (write_8_fun)vdp_port_write_b},
1070 {0xA00000, 0xA12000, 0x1FFFF, 0, 0, NULL, 1194 {0xA00000, 0xA12000, 0x1FFFF, 0, 0, NULL,
1071 (read_16_fun)io_read_w, (write_16_fun)io_write_w, 1195 (read_16_fun)io_read_w, (write_16_fun)io_write_w,
1072 (read_8_fun)io_read, (write_8_fun)io_write} 1196 (read_8_fun)io_read, (write_8_fun)io_write}
1073 }; 1197 };
1074 init_x86_68k_opts(&opts, memmap, sizeof(memmap)/sizeof(memmap_chunk)); 1198
1199 char * sram_filename;
1200 genesis_context * genesis;
1201 void save_sram()
1202 {
1203 FILE * f = fopen(sram_filename, "wb");
1204 if (!f) {
1205 fprintf(stderr, "Failed to open SRAM file %s for writing\n", sram_filename);
1206 return;
1207 }
1208 uint32_t size = genesis->save_ram_mask+1;
1209 if (genesis->save_flags != RAM_FLAG_BOTH) {
1210 size/= 2;
1211 }
1212 fwrite(genesis->save_ram, 1, size, f);
1213 fclose(f);
1214 printf("Saved SRAM to %s\n", sram_filename);
1215 }
1216
1217 void init_run_cpu(genesis_context * gen, int debug, FILE * address_log)
1218 {
1219 m68k_context context;
1220 x86_68k_options opts;
1221 gen->m68k = &context;
1222 memmap_chunk memmap[MAX_MAP_CHUNKS];
1223 uint32_t num_chunks;
1224 void * initial_mapped = NULL;
1225 gen->save_ram = NULL;
1226 //TODO: Handle carts larger than 4MB
1227 //TODO: Handle non-standard mappers
1228 uint32_t size;
1229 if ((cart[RAM_ID/2] & 0xFF) == 'A' && (cart[RAM_ID/2] >> 8) == 'R') {
1230 //Cart has save RAM
1231 uint32_t rom_end = ((cart[ROM_END/2] << 16) | cart[ROM_END/2+1]) + 1;
1232 uint32_t ram_start = (cart[RAM_START/2] << 16) | cart[RAM_START/2+1];
1233 uint32_t ram_end = (cart[RAM_END/2] << 16) | cart[RAM_END/2+1];
1234 uint16_t ram_flags = cart[RAM_FLAGS/2];
1235 gen->save_flags = ram_flags & RAM_FLAG_MASK;
1236 memset(memmap, 0, sizeof(memmap_chunk)*2);
1237 if (ram_start >= rom_end) {
1238 memmap[0].end = rom_end;
1239 memmap[0].mask = 0xFFFFFF;
1240 memmap[0].flags = MMAP_READ;
1241 memmap[0].buffer = cart;
1242
1243 ram_start &= 0xFFFFFE;
1244 ram_end |= 1;
1245 memmap[1].start = ram_start;
1246 gen->save_ram_mask = memmap[1].mask = ram_end-ram_start;
1247 ram_end += 1;
1248 memmap[1].end = ram_end;
1249 memmap[1].flags = MMAP_READ | MMAP_WRITE;
1250 size = ram_end-ram_start;
1251 if ((ram_flags & RAM_FLAG_MASK) == RAM_FLAG_ODD) {
1252 memmap[1].flags |= MMAP_ONLY_ODD;
1253 size /= 2;
1254 } else if((ram_flags & RAM_FLAG_MASK) == RAM_FLAG_EVEN) {
1255 memmap[1].flags |= MMAP_ONLY_EVEN;
1256 size /= 2;
1257 }
1258 memmap[1].buffer = gen->save_ram = malloc(size);
1259
1260 memcpy(memmap+2, static_map+1, sizeof(static_map)-sizeof(static_map[0]));
1261 num_chunks = sizeof(static_map)/sizeof(memmap_chunk)+1;
1262 } else {
1263 //Assume the standard Sega mapper for now
1264 memmap[0].end = 0x200000;
1265 memmap[0].mask = 0xFFFFFF;
1266 memmap[0].flags = MMAP_READ;
1267 memmap[0].buffer = cart;
1268
1269 memmap[1].start = 0x200000;
1270 memmap[1].end = 0x400000;
1271 memmap[1].mask = 0x1FFFFF;
1272 ram_start &= 0xFFFFFE;
1273 ram_end |= 1;
1274 gen->save_ram_mask = ram_end-ram_start;
1275 memmap[1].flags = MMAP_READ | MMAP_PTR_IDX | MMAP_FUNC_NULL;
1276 memmap[1].ptr_index = 2;
1277 memmap[1].read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[2] == NULL
1278 memmap[1].read_8 = (read_8_fun)read_sram_b;
1279 memmap[1].write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area
1280 memmap[1].write_8 = (write_8_fun)write_sram_area_b;
1281 memcpy(memmap+2, static_map+1, sizeof(static_map)-sizeof(static_map[0]));
1282 num_chunks = sizeof(static_map)/sizeof(memmap_chunk)+1;
1283 memset(memmap+num_chunks, 0, sizeof(memmap[num_chunks]));
1284 memmap[num_chunks].start = 0xA13000;
1285 memmap[num_chunks].end = 0xA13100;
1286 memmap[num_chunks].mask = 0xFF;
1287 memmap[num_chunks].write_16 = (write_16_fun)write_bank_reg_w;
1288 memmap[num_chunks].write_8 = (write_8_fun)write_bank_reg_b;
1289 num_chunks++;
1290 ram_end++;
1291 size = ram_end-ram_start;
1292 if ((ram_flags & RAM_FLAG_MASK) != RAM_FLAG_BOTH) {
1293 size /= 2;
1294 }
1295 gen->save_ram = malloc(size);
1296 memmap[1].buffer = initial_mapped = cart + 0x200000/2;
1297 }
1298 } else {
1299 memcpy(memmap, static_map, sizeof(static_map));
1300 num_chunks = sizeof(static_map)/sizeof(memmap_chunk);
1301 }
1302 if (gen->save_ram) {
1303 memset(gen->save_ram, 0, size);
1304 FILE * f = fopen(sram_filename, "rb");
1305 if (f) {
1306 uint32_t read = fread(gen->save_ram, 1, size, f);
1307 fclose(f);
1308 if (read > 0) {
1309 printf("Loaded SRAM from %s\n", sram_filename);
1310 }
1311 }
1312 atexit(save_sram);
1313 }
1314 init_x86_68k_opts(&opts, memmap, num_chunks);
1075 opts.address_log = address_log; 1315 opts.address_log = address_log;
1076 init_68k_context(&context, opts.native_code_map, &opts); 1316 init_68k_context(&context, opts.native_code_map, &opts);
1077 1317
1078 context.video_context = gen->vdp; 1318 context.video_context = gen->vdp;
1079 context.system = gen; 1319 context.system = gen;
1080 //cartridge ROM 1320 //cartridge ROM
1081 context.mem_pointers[0] = cart; 1321 context.mem_pointers[0] = cart;
1082 context.target_cycle = context.sync_cycle = mclks_per_frame/MCLKS_PER_68K; 1322 context.target_cycle = context.sync_cycle = mclks_per_frame/MCLKS_PER_68K;
1083 //work RAM 1323 //work RAM
1084 context.mem_pointers[1] = ram; 1324 context.mem_pointers[1] = ram;
1325 //save RAM/map
1326 context.mem_pointers[2] = initial_mapped;
1327 context.mem_pointers[3] = (uint16_t *)gen->save_ram;
1085 uint32_t address; 1328 uint32_t address;
1086 /*address = cart[0x68/2] << 16 | cart[0x6A/2];
1087 translate_m68k_stream(address, &context);
1088 address = cart[0x70/2] << 16 | cart[0x72/2];
1089 translate_m68k_stream(address, &context);
1090 address = cart[0x78/2] << 16 | cart[0x7A/2];
1091 translate_m68k_stream(address, &context);*/
1092 address = cart[2] << 16 | cart[3]; 1329 address = cart[2] << 16 | cart[3];
1093 translate_m68k_stream(address, &context); 1330 translate_m68k_stream(address, &context);
1094 if (debug) { 1331 if (debug) {
1095 insert_breakpoint(&context, address, (uint8_t *)debugger); 1332 insert_breakpoint(&context, address, (uint8_t *)debugger);
1096 } 1333 }
1247 z_context.mem_pointers[1] = z_context.mem_pointers[2] = (uint8_t *)cart; 1484 z_context.mem_pointers[1] = z_context.mem_pointers[2] = (uint8_t *)cart;
1248 1485
1249 gen.z80 = &z_context; 1486 gen.z80 = &z_context;
1250 gen.vdp = &v_context; 1487 gen.vdp = &v_context;
1251 gen.ym = &y_context; 1488 gen.ym = &y_context;
1489 genesis = &gen;
1490
1491 int fname_size = strlen(argv[1]);
1492 sram_filename = malloc(fname_size+6);
1493 memcpy(sram_filename, argv[1], fname_size);
1494 int i;
1495 for (i = fname_size-1; fname_size >= 0; --i) {
1496 if (sram_filename[i] == '.') {
1497 strcpy(sram_filename + i + 1, "sram");
1498 break;
1499 }
1500 }
1501 if (i < 0) {
1502 strcpy(sram_filename + fname_size, ".sram");
1503 }
1252 1504
1253 init_run_cpu(&gen, debug, address_log); 1505 init_run_cpu(&gen, debug, address_log);
1254 return 0; 1506 return 0;
1255 } 1507 }