Mercurial > repos > blastem
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[] = { |