Mercurial > repos > blastem
comparison genesis.c @ 1503:a763523dadf4 segacd
Added code for initializing a combined Genesis + Sega CD system when a Sega CD ISO is loaded
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 13 Dec 2017 09:44:41 -0800 |
parents | f284ad74afe1 |
children | 5dacaef602a7 |
comparison
equal
deleted
inserted
replaced
1502:2564b6ba2e12 | 1503:a763523dadf4 |
---|---|
2 Copyright 2013-2016 Michael Pavone | 2 Copyright 2013-2016 Michael Pavone |
3 This file is part of BlastEm. | 3 This file is part of BlastEm. |
4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. | 4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. |
5 */ | 5 */ |
6 #include "genesis.h" | 6 #include "genesis.h" |
7 #include "segacd.h" | |
7 #include "blastem.h" | 8 #include "blastem.h" |
8 #include "nor.h" | 9 #include "nor.h" |
9 #include <stdlib.h> | 10 #include <stdlib.h> |
10 #include <ctype.h> | 11 #include <ctype.h> |
11 #include <time.h> | 12 #include <time.h> |
1084 adjust_int_cycle(gen->m68k, gen->vdp); | 1085 adjust_int_cycle(gen->m68k, gen->vdp); |
1085 start_68k_context(gen->m68k, pc); | 1086 start_68k_context(gen->m68k, pc); |
1086 } else { | 1087 } else { |
1087 if (gen->header.enter_debugger) { | 1088 if (gen->header.enter_debugger) { |
1088 gen->header.enter_debugger = 0; | 1089 gen->header.enter_debugger = 0; |
1089 uint32_t address = gen->cart[2] << 16 | gen->cart[3]; | 1090 uint32_t address = read_word(4, (void **)gen->m68k->mem_pointers, &gen->m68k->options->gen, gen->m68k) << 16 |
1091 | read_word(6, (void **)gen->m68k->mem_pointers, &gen->m68k->options->gen, gen->m68k); | |
1090 insert_breakpoint(gen->m68k, address, gen->header.debugger_type == DEBUGGER_NATIVE ? debugger : gdb_debug_enter); | 1092 insert_breakpoint(gen->m68k, address, gen->header.debugger_type == DEBUGGER_NATIVE ? debugger : gdb_debug_enter); |
1091 } | 1093 } |
1092 m68k_reset(gen->m68k); | 1094 m68k_reset(gen->m68k); |
1093 } | 1095 } |
1094 handle_reset_requests(gen); | 1096 handle_reset_requests(gen); |
1182 free(gen->header.save_dir); | 1184 free(gen->header.save_dir); |
1183 free(gen->lock_on); | 1185 free(gen->lock_on); |
1184 free(gen); | 1186 free(gen); |
1185 } | 1187 } |
1186 | 1188 |
1187 genesis_context *alloc_init_genesis(rom_info *rom, void *main_rom, void *lock_on, uint32_t system_opts, uint8_t force_region) | 1189 static genesis_context *shared_init(uint32_t system_opts, rom_info *rom, uint8_t force_region) |
1188 { | 1190 { |
1189 static memmap_chunk z80_map[] = { | 1191 static memmap_chunk z80_map[] = { |
1190 { 0x0000, 0x4000, 0x1FFF, 0, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, NULL, NULL, NULL, NULL, NULL }, | 1192 { 0x0000, 0x4000, 0x1FFF, 0, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, NULL, NULL, NULL, NULL, NULL }, |
1191 { 0x8000, 0x10000, 0x7FFF, 0, 0, 0, NULL, NULL, NULL, z80_read_bank, z80_write_bank}, | 1193 { 0x8000, 0x10000, 0x7FFF, 0, 0, 0, NULL, NULL, NULL, z80_read_bank, z80_write_bank}, |
1192 { 0x4000, 0x6000, 0x0003, 0, 0, 0, NULL, NULL, NULL, z80_read_ym, z80_write_ym}, | 1194 { 0x4000, 0x6000, 0x0003, 0, 0, 0, NULL, NULL, NULL, z80_read_ym, z80_write_ym}, |
1193 { 0x6000, 0x6100, 0xFFFF, 0, 0, 0, NULL, NULL, NULL, NULL, z80_write_bank_reg}, | 1195 { 0x6000, 0x6100, 0xFFFF, 0, 0, 0, NULL, NULL, NULL, NULL, z80_write_bank_reg}, |
1194 { 0x7F00, 0x8000, 0x00FF, 0, 0, 0, NULL, NULL, NULL, z80_vdp_port_read, z80_vdp_port_write} | 1196 { 0x7F00, 0x8000, 0x00FF, 0, 0, 0, NULL, NULL, NULL, z80_vdp_port_read, z80_vdp_port_write} |
1195 }; | 1197 }; |
1198 | |
1199 char *m68k_divider = tern_find_path(config, "clocks\0m68k_divider\0", TVAL_PTR).ptrval; | |
1200 if (!m68k_divider) { | |
1201 m68k_divider = "7"; | |
1202 } | |
1203 MCLKS_PER_68K = atoi(m68k_divider); | |
1204 if (!MCLKS_PER_68K) { | |
1205 MCLKS_PER_68K = 7; | |
1206 } | |
1207 | |
1196 genesis_context *gen = calloc(1, sizeof(genesis_context)); | 1208 genesis_context *gen = calloc(1, sizeof(genesis_context)); |
1197 gen->header.set_speed_percent = set_speed_percent; | 1209 gen->header.set_speed_percent = set_speed_percent; |
1198 gen->header.start_context = start_genesis; | 1210 gen->header.start_context = start_genesis; |
1199 gen->header.resume_context = resume_genesis; | 1211 gen->header.resume_context = resume_genesis; |
1200 gen->header.load_save = load_save; | 1212 gen->header.load_save = load_save; |
1205 gen->header.get_open_bus_value = get_open_bus_value; | 1217 gen->header.get_open_bus_value = get_open_bus_value; |
1206 gen->header.request_exit = request_exit; | 1218 gen->header.request_exit = request_exit; |
1207 gen->header.inc_debug_mode = inc_debug_mode; | 1219 gen->header.inc_debug_mode = inc_debug_mode; |
1208 gen->header.inc_debug_pal = inc_debug_pal; | 1220 gen->header.inc_debug_pal = inc_debug_pal; |
1209 gen->header.type = SYSTEM_GENESIS; | 1221 gen->header.type = SYSTEM_GENESIS; |
1222 | |
1210 set_region(gen, rom, force_region); | 1223 set_region(gen, rom, force_region); |
1211 | 1224 |
1212 gen->vdp = malloc(sizeof(vdp_context)); | 1225 gen->vdp = malloc(sizeof(vdp_context)); |
1213 init_vdp_context(gen->vdp, gen->version_reg & 0x40); | 1226 init_vdp_context(gen->vdp, gen->version_reg & 0x40); |
1214 gen->vdp->system = &gen->header; | 1227 gen->vdp->system = &gen->header; |
1215 gen->frame_end = vdp_cycles_to_frame_end(gen->vdp); | 1228 gen->frame_end = vdp_cycles_to_frame_end(gen->vdp); |
1216 char * config_cycles = tern_find_path(config, "clocks\0max_cycles\0", TVAL_PTR).ptrval; | 1229 char * config_cycles = tern_find_path(config, "clocks\0max_cycles\0", TVAL_PTR).ptrval; |
1217 gen->max_cycles = config_cycles ? atoi(config_cycles) : DEFAULT_SYNC_INTERVAL; | 1230 gen->max_cycles = config_cycles ? atoi(config_cycles) : DEFAULT_SYNC_INTERVAL; |
1218 gen->int_latency_prev1 = MCLKS_PER_68K * 32; | 1231 gen->int_latency_prev1 = MCLKS_PER_68K * 32; |
1219 gen->int_latency_prev2 = MCLKS_PER_68K * 16; | 1232 gen->int_latency_prev2 = MCLKS_PER_68K * 16; |
1220 | 1233 |
1221 char * lowpass_cutoff_str = tern_find_path(config, "audio\0lowpass_cutoff\0", TVAL_PTR).ptrval; | 1234 char * lowpass_cutoff_str = tern_find_path(config, "audio\0lowpass_cutoff\0", TVAL_PTR).ptrval; |
1222 uint32_t lowpass_cutoff = lowpass_cutoff_str ? atoi(lowpass_cutoff_str) : DEFAULT_LOWPASS_CUTOFF; | 1235 uint32_t lowpass_cutoff = lowpass_cutoff_str ? atoi(lowpass_cutoff_str) : DEFAULT_LOWPASS_CUTOFF; |
1223 | 1236 |
1224 gen->ym = malloc(sizeof(ym2612_context)); | 1237 gen->ym = malloc(sizeof(ym2612_context)); |
1225 ym_init(gen->ym, render_sample_rate(), gen->master_clock, MCLKS_PER_YM, render_audio_buffer(), system_opts, lowpass_cutoff); | 1238 ym_init(gen->ym, render_sample_rate(), gen->master_clock, MCLKS_PER_YM, render_audio_buffer(), system_opts, lowpass_cutoff); |
1239 gen->z80 = calloc(1, sizeof(z80_context)); | 1252 gen->z80 = calloc(1, sizeof(z80_context)); |
1240 #endif | 1253 #endif |
1241 | 1254 |
1242 gen->z80->system = gen; | 1255 gen->z80->system = gen; |
1243 gen->z80->mem_pointers[0] = gen->zram; | 1256 gen->z80->mem_pointers[0] = gen->zram; |
1244 gen->z80->mem_pointers[1] = gen->z80->mem_pointers[2] = (uint8_t *)main_rom; | 1257 gen->z80->mem_pointers[1] = gen->z80->mem_pointers[2] = NULL; |
1245 | 1258 |
1246 gen->cart = main_rom; | |
1247 gen->lock_on = lock_on; | |
1248 gen->work_ram = calloc(2, RAM_WORDS); | 1259 gen->work_ram = calloc(2, RAM_WORDS); |
1249 if (!strcmp("random", tern_find_path_default(config, "system\0ram_init\0", (tern_val){.ptrval = "zero"}, TVAL_PTR).ptrval)) | 1260 if (!strcmp("random", tern_find_path_default(config, "system\0ram_init\0", (tern_val){.ptrval = "zero"}, TVAL_PTR).ptrval)) |
1250 { | 1261 { |
1251 srand(time(NULL)); | 1262 srand(time(NULL)); |
1252 for (int i = 0; i < RAM_WORDS; i++) | 1263 for (int i = 0; i < RAM_WORDS; i++) |
1272 for (int i = 0; i < VSRAM_SIZE; i++) | 1283 for (int i = 0; i < VSRAM_SIZE; i++) |
1273 { | 1284 { |
1274 gen->vdp->vsram[i] = rand(); | 1285 gen->vdp->vsram[i] = rand(); |
1275 } | 1286 } |
1276 } | 1287 } |
1288 | |
1289 return gen; | |
1290 } | |
1291 | |
1292 genesis_context *alloc_init_genesis(rom_info *rom, void *main_rom, void *lock_on, uint32_t system_opts, uint8_t force_region) | |
1293 { | |
1294 genesis_context *gen = shared_init(system_opts, rom, force_region); | |
1295 gen->z80->mem_pointers[1] = gen->z80->mem_pointers[2] = (uint8_t *)main_rom; | |
1296 | |
1297 gen->cart = main_rom; | |
1298 gen->lock_on = lock_on; | |
1299 | |
1277 setup_io_devices(config, rom, &gen->io); | 1300 setup_io_devices(config, rom, &gen->io); |
1278 | |
1279 gen->mapper_type = rom->mapper_type; | 1301 gen->mapper_type = rom->mapper_type; |
1280 gen->save_type = rom->save_type; | 1302 gen->save_type = rom->save_type; |
1281 if (gen->save_type != SAVE_NONE) { | 1303 if (gen->save_type != SAVE_NONE) { |
1282 gen->save_ram_mask = rom->save_mask; | 1304 gen->save_ram_mask = rom->save_mask; |
1283 gen->save_size = rom->save_size; | 1305 gen->save_size = rom->save_size; |
1327 } | 1349 } |
1328 | 1350 |
1329 return gen; | 1351 return gen; |
1330 } | 1352 } |
1331 | 1353 |
1354 static memmap_chunk base_map[] = { | |
1355 {0xE00000, 0x1000000, 0xFFFF, 0, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, NULL, | |
1356 NULL, NULL, NULL, NULL}, | |
1357 {0xC00000, 0xE00000, 0x1FFFFF, 0, 0, 0, NULL, | |
1358 (read_16_fun)vdp_port_read, (write_16_fun)vdp_port_write, | |
1359 (read_8_fun)vdp_port_read_b, (write_8_fun)vdp_port_write_b}, | |
1360 {0xA00000, 0xA12000, 0x1FFFF, 0, 0, 0, NULL, | |
1361 (read_16_fun)io_read_w, (write_16_fun)io_write_w, | |
1362 (read_8_fun)io_read, (write_8_fun)io_write} | |
1363 }; | |
1364 const size_t base_chunks = sizeof(base_map)/sizeof(*base_map); | |
1365 | |
1332 genesis_context *alloc_config_genesis(void *rom, uint32_t rom_size, void *lock_on, uint32_t lock_on_size, uint32_t ym_opts, uint8_t force_region, rom_info *info_out) | 1366 genesis_context *alloc_config_genesis(void *rom, uint32_t rom_size, void *lock_on, uint32_t lock_on_size, uint32_t ym_opts, uint8_t force_region, rom_info *info_out) |
1333 { | 1367 { |
1334 static memmap_chunk base_map[] = { | 1368 tern_node *rom_db = get_rom_db(); |
1335 {0xE00000, 0x1000000, 0xFFFF, 0, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, NULL, | 1369 *info_out = configure_rom(rom_db, rom, rom_size, lock_on, lock_on_size, base_map, base_chunks); |
1336 NULL, NULL, NULL, NULL}, | |
1337 {0xC00000, 0xE00000, 0x1FFFFF, 0, 0, 0, NULL, | |
1338 (read_16_fun)vdp_port_read, (write_16_fun)vdp_port_write, | |
1339 (read_8_fun)vdp_port_read_b, (write_8_fun)vdp_port_write_b}, | |
1340 {0xA00000, 0xA12000, 0x1FFFF, 0, 0, 0, NULL, | |
1341 (read_16_fun)io_read_w, (write_16_fun)io_write_w, | |
1342 (read_8_fun)io_read, (write_8_fun)io_write} | |
1343 }; | |
1344 static tern_node *rom_db; | |
1345 if (!rom_db) { | |
1346 rom_db = load_rom_db(); | |
1347 } | |
1348 *info_out = configure_rom(rom_db, rom, rom_size, lock_on, lock_on_size, base_map, sizeof(base_map)/sizeof(base_map[0])); | |
1349 rom = info_out->rom; | 1370 rom = info_out->rom; |
1350 rom_size = info_out->rom_size; | 1371 rom_size = info_out->rom_size; |
1351 #ifndef BLASTEM_BIG_ENDIAN | 1372 #ifndef BLASTEM_BIG_ENDIAN |
1352 byteswap_rom(rom_size, rom); | 1373 byteswap_rom(rom_size, rom); |
1353 if (lock_on) { | 1374 if (lock_on) { |
1354 byteswap_rom(lock_on_size, lock_on); | 1375 byteswap_rom(lock_on_size, lock_on); |
1355 } | 1376 } |
1356 #endif | 1377 #endif |
1357 char *m68k_divider = tern_find_path(config, "clocks\0m68k_divider\0", TVAL_PTR).ptrval; | |
1358 if (!m68k_divider) { | |
1359 m68k_divider = "7"; | |
1360 } | |
1361 MCLKS_PER_68K = atoi(m68k_divider); | |
1362 if (!MCLKS_PER_68K) { | |
1363 MCLKS_PER_68K = 7; | |
1364 } | |
1365 return alloc_init_genesis(info_out, rom, lock_on, ym_opts, force_region); | 1378 return alloc_init_genesis(info_out, rom, lock_on, ym_opts, force_region); |
1366 } | 1379 } |
1380 | |
1381 genesis_context *alloc_config_genesis_cdboot(system_media *media, uint32_t system_opts, uint8_t force_region, rom_info *info_out) | |
1382 { | |
1383 segacd_context *cd = alloc_configure_segacd(media, system_opts, force_region, info_out); | |
1384 genesis_context *gen = shared_init(system_opts, info_out, force_region); | |
1385 gen->cart = gen->lock_on = NULL; | |
1386 gen->save_storage = NULL; | |
1387 gen->save_type = SAVE_NONE; | |
1388 gen->version_reg &= ~NO_DISK; | |
1389 | |
1390 gen->expansion = cd; | |
1391 setup_io_devices(config, info_out, &gen->io); | |
1392 | |
1393 uint32_t cd_chunks; | |
1394 memmap_chunk *cd_map = segacd_main_cpu_map(gen->expansion, &cd_chunks); | |
1395 memmap_chunk *map = malloc(sizeof(memmap_chunk) * (cd_chunks + base_chunks)); | |
1396 memcpy(map, cd_map, sizeof(memmap_chunk) * cd_chunks); | |
1397 memcpy(map + cd_chunks, base_map, sizeof(memmap_chunk) * base_chunks); | |
1398 map[cd_chunks].buffer = gen->work_ram; | |
1399 uint32_t num_chunks = cd_chunks + base_chunks; | |
1400 | |
1401 m68k_options *opts = malloc(sizeof(m68k_options)); | |
1402 init_m68k_opts(opts, map, num_chunks, MCLKS_PER_68K); | |
1403 //TODO: make this configurable | |
1404 opts->gen.flags |= M68K_OPT_BROKEN_READ_MODIFY; | |
1405 gen->m68k = init_68k_context(opts, NULL); | |
1406 gen->m68k->system = gen; | |
1407 opts->address_log = (system_opts & OPT_ADDRESS_LOG) ? fopen("address.log", "w") : NULL; | |
1408 | |
1409 //This must happen after the 68K context has been allocated | |
1410 for (int i = 0; i < num_chunks; i++) | |
1411 { | |
1412 if (map[i].flags & MMAP_PTR_IDX) { | |
1413 gen->m68k->mem_pointers[map[i].ptr_index] = map[i].buffer; | |
1414 } | |
1415 } | |
1416 return gen; | |
1417 } |