comparison segacd.c @ 2280:9ead0fe69d9b

Implement savestate support for Sega CD
author Michael Pavone <pavone@retrodev.com>
date Sun, 08 Jan 2023 14:42:24 -0800
parents 5a21bc0ec583
children b9fed07f19e4
comparison
equal deleted inserted replaced
2279:3b5fef896475 2280:9ead0fe69d9b
5 #include "genesis.h" 5 #include "genesis.h"
6 #include "util.h" 6 #include "util.h"
7 #include "debug.h" 7 #include "debug.h"
8 #include "gdb_remote.h" 8 #include "gdb_remote.h"
9 #include "blastem.h" 9 #include "blastem.h"
10 #include "cdimage.h"
10 11
11 #define SCD_MCLKS 50000000 12 #define SCD_MCLKS 50000000
12 #define SCD_PERIPH_RESET_CLKS (SCD_MCLKS / 10) 13 #define SCD_PERIPH_RESET_CLKS (SCD_MCLKS / 10)
13 #define TIMER_TICK_CLKS 1536 14 #define TIMER_TICK_CLKS 1536
14 15
1055 uint32_t num_refresh = (context->current_cycle - cd->last_refresh_cycle) / REFRESH_INTERVAL; 1056 uint32_t num_refresh = (context->current_cycle - cd->last_refresh_cycle) / REFRESH_INTERVAL;
1056 cd->last_refresh_cycle = cd->last_refresh_cycle + num_refresh * REFRESH_INTERVAL; 1057 cd->last_refresh_cycle = cd->last_refresh_cycle + num_refresh * REFRESH_INTERVAL;
1057 context->current_cycle += num_refresh * REFRESH_DELAY; 1058 context->current_cycle += num_refresh * REFRESH_DELAY;
1058 1059
1059 scd_peripherals_run(cd, context->current_cycle); 1060 scd_peripherals_run(cd, context->current_cycle);
1060 if (address && cd->enter_debugger) { 1061 if (address) {
1061 genesis_context *gen = cd->genesis; 1062 if (cd->enter_debugger) {
1062 cd->enter_debugger = 0; 1063 genesis_context *gen = cd->genesis;
1063 if (gen->header.debugger_type == DEBUGGER_NATIVE) { 1064 cd->enter_debugger = 0;
1064 debugger(context, address); 1065 if (gen->header.debugger_type == DEBUGGER_NATIVE) {
1065 } else { 1066 debugger(context, address);
1066 gdb_debug_enter(context, address); 1067 } else {
1067 } 1068 gdb_debug_enter(context, address);
1069 }
1070 }
1071 cd->m68k_pc = address;
1068 } 1072 }
1069 switch (context->int_ack) 1073 switch (context->int_ack)
1070 { 1074 {
1071 case 1: 1075 case 1:
1072 cd->graphics_int_cycle = CYCLE_NEVER; 1076 cd->graphics_int_cycle = CYCLE_NEVER;
1451 cd->rom_mut = malloc(adjusted_size); 1455 cd->rom_mut = malloc(adjusted_size);
1452 byteswap_rom(adjusted_size, cd->rom); 1456 byteswap_rom(adjusted_size, cd->rom);
1453 memcpy(cd->rom_mut, cd->rom, adjusted_size); 1457 memcpy(cd->rom_mut, cd->rom, adjusted_size);
1454 cd->rom_mut[0x72/2] = 0xFFFF; 1458 cd->rom_mut[0x72/2] = 0xFFFF;
1455 1459
1456 //memset(info, 0, sizeof(*info));
1457 //tern_node *db = get_rom_db();
1458 //*info = configure_rom(db, media->buffer, media->size, media->chain ? media->chain->buffer : NULL, media->chain ? media->chain->size : 0, NULL, 0);
1459
1460 cd->prog_ram = calloc(512*1024, 1); 1460 cd->prog_ram = calloc(512*1024, 1);
1461 cd->word_ram = calloc(256*1024, 1); 1461 cd->word_ram = calloc(256*1024, 1);
1462 cd->pcm_ram = calloc(64*1024, 1);
1463 //TODO: Load state from file
1464 cd->bram = calloc(8*1024, 1); 1462 cd->bram = calloc(8*1024, 1);
1465 1463
1466 1464
1467 sub_cpu_map[0].buffer = sub_cpu_map[1].buffer = cd->prog_ram; 1465 sub_cpu_map[0].buffer = sub_cpu_map[1].buffer = cd->prog_ram;
1468 sub_cpu_map[4].buffer = cd->bram; 1466 sub_cpu_map[4].buffer = cd->bram;
1495 cdd_fader_deinit(&cd->fader); 1493 cdd_fader_deinit(&cd->fader);
1496 rf5c164_deinit(&cd->pcm); 1494 rf5c164_deinit(&cd->pcm);
1497 m68k_options_free(cd->m68k->options); 1495 m68k_options_free(cd->m68k->options);
1498 free(cd->m68k); 1496 free(cd->m68k);
1499 free(cd->bram); 1497 free(cd->bram);
1500 free(cd->pcm_ram);
1501 free(cd->word_ram); 1498 free(cd->word_ram);
1502 free(cd->prog_ram); 1499 free(cd->prog_ram);
1503 free(cd->rom_mut); 1500 free(cd->rom_mut);
1501 }
1502
1503 void segacd_serialize(segacd_context *cd, serialize_buffer *buf, uint8_t all)
1504 {
1505 if (all) {
1506 start_section(buf, SECTION_SUB_68000);
1507 m68k_serialize(cd->m68k, cd->m68k_pc, buf);
1508 end_section(buf);
1509
1510 start_section(buf, SECTION_GATE_ARRAY);
1511 save_buffer16(buf, cd->gate_array, sizeof(cd->gate_array)/sizeof(*cd->gate_array));
1512 save_buffer16(buf, cd->prog_ram, 256*1024);
1513 save_buffer16(buf, cd->word_ram, 128*1024);
1514 save_int16(buf, cd->rom_mut[0x72/2]);
1515 save_int32(buf, cd->stopwatch_cycle);
1516 save_int32(buf, cd->int2_cycle);
1517 save_int32(buf, cd->graphics_int_cycle);
1518 save_int32(buf, cd->periph_reset_cycle);
1519 save_int32(buf, cd->last_refresh_cycle);
1520 save_int32(buf, cd->graphics_cycle);
1521 save_int32(buf, cd->base);
1522 save_int32(buf, cd->graphics_x);
1523 save_int32(buf, cd->graphics_y);
1524 save_int32(buf, cd->graphics_dx);
1525 save_int32(buf, cd->graphics_dy);
1526 save_int32(buf, cd->graphics_dst_x);
1527 save_buffer8(buf, cd->graphics_pixels, sizeof(cd->graphics_pixels));
1528 save_int8(buf, cd->timer_pending);
1529 save_int8(buf, cd->timer_value);
1530 save_int8(buf, cd->busreq);
1531 save_int8(buf, cd->reset);
1532 save_int8(buf, cd->need_reset);
1533 save_int8(buf, cd->cdc_dst_low);
1534 save_int8(buf, cd->cdc_int_ack);
1535 save_int8(buf, cd->graphics_step);
1536 save_int8(buf, cd->graphics_dst_y);
1537 save_int8(buf, cd->main_has_word2m);
1538 save_int8(buf, cd->main_swap_request);
1539 save_int8(buf, cd->bank_toggle);
1540 save_int8(buf, cd->sub_paused_wordram);
1541 end_section(buf);
1542
1543 start_section(buf, SECTION_CDD_MCU);
1544 cdd_mcu_serialize(&cd->cdd, buf);
1545 end_section(buf);
1546
1547 start_section(buf, SECTION_LC8951);
1548 lc8951_serialize(&cd->cdc, buf);
1549 end_section(buf);
1550
1551 start_section(buf, SECTION_CDROM);
1552 cdimage_serialize(cd->cdd.media, buf);
1553 end_section(buf);
1554 }
1555 start_section(buf, SECTION_RF5C164);
1556 rf5c164_serialize(&cd->pcm, buf);
1557 end_section(buf);
1558
1559 start_section(buf, SECTION_CDD_FADER);
1560 cdd_fader_serialize(&cd->fader, buf);
1561 end_section(buf);
1562 }
1563
1564 static void gate_array_deserialize(deserialize_buffer *buf, void *vcd)
1565 {
1566 segacd_context *cd = vcd;
1567 load_buffer16(buf, cd->gate_array, sizeof(cd->gate_array)/sizeof(*cd->gate_array));
1568 load_buffer16(buf, cd->prog_ram, 256*1024);
1569 load_buffer16(buf, cd->word_ram, 128*1024);
1570 cd->rom_mut[0x72/2] = load_int16(buf);
1571 cd->stopwatch_cycle = load_int32(buf);
1572 cd->int2_cycle = load_int32(buf);
1573 cd->graphics_int_cycle = load_int32(buf);
1574 cd->periph_reset_cycle = load_int32(buf);
1575 cd->last_refresh_cycle = load_int32(buf);
1576 cd->graphics_cycle = load_int32(buf);
1577 cd->base = load_int32(buf);
1578 cd->graphics_x = load_int32(buf);
1579 cd->graphics_y = load_int32(buf);
1580 cd->graphics_dx = load_int32(buf);
1581 cd->graphics_dy = load_int32(buf);
1582 cd->graphics_dst_x = load_int32(buf);
1583 load_buffer8(buf, cd->graphics_pixels, sizeof(cd->graphics_pixels));
1584 cd->timer_pending = load_int8(buf);
1585 cd->timer_value = load_int8(buf);
1586 cd->busreq = load_int8(buf);
1587 cd->reset = load_int8(buf);
1588 cd->need_reset = load_int8(buf);
1589 cd->cdc_dst_low = load_int8(buf);
1590 cd->cdc_int_ack = load_int8(buf);
1591 cd->graphics_step = load_int8(buf);
1592 cd->graphics_dst_y = load_int8(buf);
1593 cd->main_has_word2m = load_int8(buf);
1594 cd->main_swap_request = load_int8(buf);
1595 cd->bank_toggle = load_int8(buf);
1596 cd->sub_paused_wordram = load_int8(buf);
1597
1598 if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) {
1599 //1M mode
1600 cd->genesis->m68k->mem_pointers[cd->memptr_start_index + 1] = NULL;
1601 cd->genesis->m68k->mem_pointers[cd->memptr_start_index + 2] = NULL;
1602 cd->m68k->mem_pointers[0] = NULL;
1603 cd->m68k->mem_pointers[1] = cd->bank_toggle ? cd->word_ram : cd->word_ram + 1;
1604 } else {
1605 //2M mode
1606 if (cd->main_has_word2m) {
1607 //main CPU has word ram
1608 cd->genesis->m68k->mem_pointers[cd->memptr_start_index + 1] = cd->word_ram;
1609 cd->genesis->m68k->mem_pointers[cd->memptr_start_index + 2] = cd->word_ram + 0x10000;
1610 cd->m68k->mem_pointers[0] = NULL;
1611 cd->m68k->mem_pointers[1] = NULL;
1612 } else {
1613 //sub cpu has word ram
1614 cd->genesis->m68k->mem_pointers[cd->memptr_start_index + 1] = NULL;
1615 cd->genesis->m68k->mem_pointers[cd->memptr_start_index + 2] = NULL;
1616 cd->m68k->mem_pointers[0] = cd->word_ram;
1617 cd->m68k->mem_pointers[1] = NULL;
1618 }
1619 }
1620
1621 m68k_invalidate_code_range(cd->m68k, 0, 0x0E0000);
1622 m68k_invalidate_code_range(cd->genesis->m68k, cd->base + 0x200000, cd->base + 0x240000);
1623 }
1624
1625 void segacd_register_section_handlers(segacd_context *cd, deserialize_buffer *buf)
1626 {
1627 register_section_handler(buf, (section_handler){.fun = m68k_deserialize, .data = cd->m68k}, SECTION_SUB_68000);
1628 register_section_handler(buf, (section_handler){.fun = gate_array_deserialize, .data = cd}, SECTION_GATE_ARRAY);
1629 register_section_handler(buf, (section_handler){.fun = cdd_mcu_deserialize, .data = &cd->cdd}, SECTION_CDD_MCU);
1630 register_section_handler(buf, (section_handler){.fun = lc8951_deserialize, .data = &cd->cdc}, SECTION_LC8951);
1631 register_section_handler(buf, (section_handler){.fun = rf5c164_deserialize, .data = &cd->pcm}, SECTION_RF5C164);
1632 register_section_handler(buf, (section_handler){.fun = cdd_fader_deserialize, .data = &cd->fader}, SECTION_CDD_FADER);
1633 register_section_handler(buf, (section_handler){.fun = cdimage_deserialize, .data = cd->cdd.media}, SECTION_CDROM);
1504 } 1634 }
1505 1635
1506 memmap_chunk *segacd_main_cpu_map(segacd_context *cd, uint8_t cart_boot, uint32_t *num_chunks) 1636 memmap_chunk *segacd_main_cpu_map(segacd_context *cd, uint8_t cart_boot, uint32_t *num_chunks)
1507 { 1637 {
1508 static memmap_chunk main_cpu_map[] = { 1638 static memmap_chunk main_cpu_map[] = {