Mercurial > repos > blastem
comparison genesis.c @ 1983:a7b753e260a2 mame_interp
Merge from default
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 09 May 2020 23:39:44 -0700 |
parents | 2c1c88cd1a3f 81df9aa2de9b |
children | 0d5f88e53dca |
comparison
equal
deleted
inserted
replaced
1937:cafde1255ad3 | 1983:a7b753e260a2 |
---|---|
17 #include "gdb_remote.h" | 17 #include "gdb_remote.h" |
18 #include "saves.h" | 18 #include "saves.h" |
19 #include "bindings.h" | 19 #include "bindings.h" |
20 #include "jcart.h" | 20 #include "jcart.h" |
21 #include "config.h" | 21 #include "config.h" |
22 #include "event_log.h" | |
22 #define MCLKS_NTSC 53693175 | 23 #define MCLKS_NTSC 53693175 |
23 #define MCLKS_PAL 53203395 | 24 #define MCLKS_PAL 53203395 |
24 | 25 |
25 uint32_t MCLKS_PER_68K; | 26 uint32_t MCLKS_PER_68K; |
26 #define MCLKS_PER_YM 7 | 27 #define MCLKS_PER_YM 7 |
48 #else | 49 #else |
49 #define Z80_CYCLE current_cycle | 50 #define Z80_CYCLE current_cycle |
50 #define Z80_OPTS options | 51 #define Z80_OPTS options |
51 #endif | 52 #endif |
52 | 53 |
53 void genesis_serialize(genesis_context *gen, serialize_buffer *buf, uint32_t m68k_pc) | 54 void genesis_serialize(genesis_context *gen, serialize_buffer *buf, uint32_t m68k_pc, uint8_t all) |
54 { | 55 { |
55 start_section(buf, SECTION_68000); | 56 if (all) { |
56 m68k_serialize(gen->m68k, m68k_pc, buf); | 57 start_section(buf, SECTION_68000); |
57 end_section(buf); | 58 m68k_serialize(gen->m68k, m68k_pc, buf); |
58 | 59 end_section(buf); |
59 start_section(buf, SECTION_Z80); | 60 |
60 z80_serialize(gen->z80, buf); | 61 start_section(buf, SECTION_Z80); |
61 end_section(buf); | 62 z80_serialize(gen->z80, buf); |
63 end_section(buf); | |
64 } | |
62 | 65 |
63 start_section(buf, SECTION_VDP); | 66 start_section(buf, SECTION_VDP); |
64 vdp_serialize(gen->vdp, buf); | 67 vdp_serialize(gen->vdp, buf); |
65 end_section(buf); | 68 end_section(buf); |
66 | 69 |
70 | 73 |
71 start_section(buf, SECTION_PSG); | 74 start_section(buf, SECTION_PSG); |
72 psg_serialize(gen->psg, buf); | 75 psg_serialize(gen->psg, buf); |
73 end_section(buf); | 76 end_section(buf); |
74 | 77 |
75 start_section(buf, SECTION_GEN_BUS_ARBITER); | 78 if (all) { |
76 save_int8(buf, gen->z80->reset); | 79 start_section(buf, SECTION_GEN_BUS_ARBITER); |
77 save_int8(buf, gen->z80->busreq); | 80 save_int8(buf, gen->z80->reset); |
78 save_int16(buf, gen->z80_bank_reg); | 81 save_int8(buf, gen->z80->busreq); |
79 end_section(buf); | 82 save_int16(buf, gen->z80_bank_reg); |
80 | 83 end_section(buf); |
81 start_section(buf, SECTION_SEGA_IO_1); | 84 |
82 io_serialize(gen->io.ports, buf); | 85 start_section(buf, SECTION_SEGA_IO_1); |
83 end_section(buf); | 86 io_serialize(gen->io.ports, buf); |
84 | 87 end_section(buf); |
85 start_section(buf, SECTION_SEGA_IO_2); | 88 |
86 io_serialize(gen->io.ports + 1, buf); | 89 start_section(buf, SECTION_SEGA_IO_2); |
87 end_section(buf); | 90 io_serialize(gen->io.ports + 1, buf); |
88 | 91 end_section(buf); |
89 start_section(buf, SECTION_SEGA_IO_EXT); | 92 |
90 io_serialize(gen->io.ports + 2, buf); | 93 start_section(buf, SECTION_SEGA_IO_EXT); |
91 end_section(buf); | 94 io_serialize(gen->io.ports + 2, buf); |
92 | 95 end_section(buf); |
93 start_section(buf, SECTION_MAIN_RAM); | 96 |
94 save_int8(buf, RAM_WORDS * 2 / 1024); | 97 start_section(buf, SECTION_MAIN_RAM); |
95 save_buffer16(buf, gen->work_ram, RAM_WORDS); | 98 save_int8(buf, RAM_WORDS * 2 / 1024); |
96 end_section(buf); | 99 save_buffer16(buf, gen->work_ram, RAM_WORDS); |
97 | 100 end_section(buf); |
98 start_section(buf, SECTION_SOUND_RAM); | 101 |
99 save_int8(buf, Z80_RAM_BYTES / 1024); | 102 start_section(buf, SECTION_SOUND_RAM); |
100 save_buffer8(buf, gen->zram, Z80_RAM_BYTES); | 103 save_int8(buf, Z80_RAM_BYTES / 1024); |
101 end_section(buf); | 104 save_buffer8(buf, gen->zram, Z80_RAM_BYTES); |
102 | 105 end_section(buf); |
103 cart_serialize(&gen->header, buf); | 106 |
107 cart_serialize(&gen->header, buf); | |
108 } | |
104 } | 109 } |
105 | 110 |
106 static uint8_t *serialize(system_header *sys, size_t *size_out) | 111 static uint8_t *serialize(system_header *sys, size_t *size_out) |
107 { | 112 { |
108 genesis_context *gen = (genesis_context *)sys; | 113 genesis_context *gen = (genesis_context *)sys; |
118 } else { | 123 } else { |
119 serialize_buffer state; | 124 serialize_buffer state; |
120 init_serialize(&state); | 125 init_serialize(&state); |
121 uint32_t address = read_word(4, (void **)gen->m68k->mem_pointers, &gen->m68k->options->gen, gen->m68k) << 16; | 126 uint32_t address = read_word(4, (void **)gen->m68k->mem_pointers, &gen->m68k->options->gen, gen->m68k) << 16; |
122 address |= read_word(6, (void **)gen->m68k->mem_pointers, &gen->m68k->options->gen, gen->m68k); | 127 address |= read_word(6, (void **)gen->m68k->mem_pointers, &gen->m68k->options->gen, gen->m68k); |
123 genesis_serialize(gen, &state, address); | 128 genesis_serialize(gen, &state, address, 1); |
124 if (size_out) { | 129 if (size_out) { |
125 *size_out = state.size; | 130 *size_out = state.size; |
126 } | 131 } |
127 return state.data; | 132 return state.data; |
128 } | 133 } |
349 ym_run(gen->ym, target); | 354 ym_run(gen->ym, target); |
350 | 355 |
351 //printf("Target: %d, YM bufferpos: %d, PSG bufferpos: %d\n", target, gen->ym->buffer_pos, gen->psg->buffer_pos * 2); | 356 //printf("Target: %d, YM bufferpos: %d, PSG bufferpos: %d\n", target, gen->ym->buffer_pos, gen->psg->buffer_pos * 2); |
352 } | 357 } |
353 | 358 |
354 //TODO: move this inside the system context | |
355 static uint32_t last_frame_num; | |
356 | |
357 //My refresh emulation isn't currently good enough and causes more problems than it solves | 359 //My refresh emulation isn't currently good enough and causes more problems than it solves |
358 #define REFRESH_EMULATION | 360 #define REFRESH_EMULATION |
359 #ifdef REFRESH_EMULATION | 361 #ifdef REFRESH_EMULATION |
360 #define REFRESH_INTERVAL 128 | 362 #define REFRESH_INTERVAL 128 |
361 #define REFRESH_DELAY 2 | 363 #define REFRESH_DELAY 2 |
390 if (mclks >= gen->reset_cycle) { | 392 if (mclks >= gen->reset_cycle) { |
391 gen->reset_requested = 1; | 393 gen->reset_requested = 1; |
392 context->should_return = 1; | 394 context->should_return = 1; |
393 gen->reset_cycle = CYCLE_NEVER; | 395 gen->reset_cycle = CYCLE_NEVER; |
394 } | 396 } |
395 if (v_context->frame != last_frame_num) { | 397 if (v_context->frame != gen->last_frame) { |
396 //printf("reached frame end %d | MCLK Cycles: %d, Target: %d, VDP cycles: %d, vcounter: %d, hslot: %d\n", last_frame_num, mclks, gen->frame_end, v_context->cycles, v_context->vcounter, v_context->hslot); | 398 //printf("reached frame end %d | MCLK Cycles: %d, Target: %d, VDP cycles: %d, vcounter: %d, hslot: %d\n", gen->last_frame, mclks, gen->frame_end, v_context->cycles, v_context->vcounter, v_context->hslot); |
397 last_frame_num = v_context->frame; | 399 gen->last_frame = v_context->frame; |
400 event_flush(mclks); | |
401 gen->last_flush_cycle = mclks; | |
398 | 402 |
399 if(exit_after){ | 403 if(exit_after){ |
400 --exit_after; | 404 --exit_after; |
401 if (!exit_after) { | 405 if (!exit_after) { |
402 exit(0); | 406 exit(0); |
419 } | 423 } |
420 gen->psg->cycles -= deduction; | 424 gen->psg->cycles -= deduction; |
421 if (gen->reset_cycle != CYCLE_NEVER) { | 425 if (gen->reset_cycle != CYCLE_NEVER) { |
422 gen->reset_cycle -= deduction; | 426 gen->reset_cycle -= deduction; |
423 } | 427 } |
424 } | 428 event_cycle_adjust(mclks, deduction); |
429 gen->last_flush_cycle -= deduction; | |
430 } | |
431 } else if (mclks - gen->last_flush_cycle > gen->soft_flush_cycles) { | |
432 event_soft_flush(mclks); | |
433 gen->last_flush_cycle = mclks; | |
425 } | 434 } |
426 gen->frame_end = vdp_cycles_to_frame_end(v_context); | 435 gen->frame_end = vdp_cycles_to_frame_end(v_context); |
427 context->sync_cycle = gen->frame_end; | 436 context->sync_cycle = gen->frame_end; |
428 //printf("Set sync cycle to: %d @ %d, vcounter: %d, hslot: %d\n", context->sync_cycle, context->current_cycle, v_context->vcounter, v_context->hslot); | 437 //printf("Set sync cycle to: %d @ %d, vcounter: %d, hslot: %d\n", context->sync_cycle, context->current_cycle, v_context->vcounter, v_context->hslot); |
429 if (context->int_ack) { | 438 if (context->int_ack) { |
459 { | 468 { |
460 sync_z80(z_context, z_context->current_cycle + MCLKS_PER_Z80); | 469 sync_z80(z_context, z_context->current_cycle + MCLKS_PER_Z80); |
461 } | 470 } |
462 } | 471 } |
463 #endif | 472 #endif |
464 char *save_path = slot == SERIALIZE_SLOT ? NULL : get_slot_name(&gen->header, slot, use_native_states ? "state" : "gst"); | 473 char *save_path = slot >= SERIALIZE_SLOT ? NULL : get_slot_name(&gen->header, slot, use_native_states ? "state" : "gst"); |
465 #ifndef NEW_CORE | 474 #ifndef NEW_CORE |
466 if (use_native_states || slot == SERIALIZE_SLOT) { | 475 if (use_native_states || slot >= SERIALIZE_SLOT) { |
467 #endif | 476 #endif |
468 serialize_buffer state; | 477 serialize_buffer state; |
469 init_serialize(&state); | 478 init_serialize(&state); |
470 genesis_serialize(gen, &state, address); | 479 genesis_serialize(gen, &state, address); |
471 if (slot == SERIALIZE_SLOT) { | 480 if (slot == SERIALIZE_SLOT) { |
472 gen->serialize_tmp = state.data; | 481 gen->serialize_tmp = state.data; |
473 gen->serialize_size = state.size; | 482 gen->serialize_size = state.size; |
474 context->sync_cycle = context->current_cycle; | 483 context->sync_cycle = context->current_cycle; |
475 context->should_return = 1; | 484 context->should_return = 1; |
485 } else if (slot == EVENTLOG_SLOT) { | |
486 event_state(context->current_cycle, &state); | |
476 } else { | 487 } else { |
477 save_to_file(&state, save_path); | 488 save_to_file(&state, save_path); |
478 free(state.data); | 489 free(state.data); |
479 } | 490 } |
480 #ifndef NEW_CORE | 491 #ifndef NEW_CORE |
481 } else { | 492 } else { |
482 save_gst(gen, save_path, address); | 493 save_gst(gen, save_path, address); |
483 } | 494 } |
484 #endif | 495 #endif |
485 printf("Saved state to %s\n", save_path); | 496 if (slot != SERIALIZE_SLOT) { |
497 debug_message("Saved state to %s\n", save_path); | |
498 } | |
486 free(save_path); | 499 free(save_path); |
487 } else if(gen->header.save_state) { | 500 } else if(gen->header.save_state) { |
488 context->sync_cycle = context->current_cycle + 1; | 501 context->sync_cycle = context->current_cycle + 1; |
489 } | 502 } |
490 } | 503 } |
642 } | 655 } |
643 vdp_port &= 0x1F; | 656 vdp_port &= 0x1F; |
644 uint16_t value; | 657 uint16_t value; |
645 #ifdef REFRESH_EMULATION | 658 #ifdef REFRESH_EMULATION |
646 if (context->current_cycle - 4*MCLKS_PER_68K > last_sync_cycle) { | 659 if (context->current_cycle - 4*MCLKS_PER_68K > last_sync_cycle) { |
647 //do refresh check here so we can avoid adding a penalty for a refresh that happens during a VDP access | 660 //do refresh check here so we can avoid adding a penalty for a refresh that happens during a VDP access |
648 refresh_counter += context->current_cycle - 4*MCLKS_PER_68K - last_sync_cycle; | 661 refresh_counter += context->current_cycle - 4*MCLKS_PER_68K - last_sync_cycle; |
649 context->current_cycle += REFRESH_DELAY * MCLKS_PER_68K * (refresh_counter / (MCLKS_PER_68K * REFRESH_INTERVAL)); | 662 context->current_cycle += REFRESH_DELAY * MCLKS_PER_68K * (refresh_counter / (MCLKS_PER_68K * REFRESH_INTERVAL)); |
650 refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL); | 663 refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL); |
651 last_sync_cycle = context->current_cycle; | 664 last_sync_cycle = context->current_cycle; |
652 } | 665 } |
653 #endif | 666 #endif |
654 genesis_context *gen = context->system; | 667 genesis_context *gen = context->system; |
655 vdp_context * v_context = gen->vdp; | 668 vdp_context * v_context = gen->vdp; |
656 if (vdp_port < 0x10) { | 669 if (vdp_port < 0x10) { |
1196 gen->version_reg = NO_DISK | USA; | 1209 gen->version_reg = NO_DISK | USA; |
1197 } | 1210 } |
1198 | 1211 |
1199 if (region & HZ50) { | 1212 if (region & HZ50) { |
1200 gen->normal_clock = MCLKS_PAL; | 1213 gen->normal_clock = MCLKS_PAL; |
1214 gen->soft_flush_cycles = MCLKS_LINE * 262 / 3 + 2; | |
1201 } else { | 1215 } else { |
1202 gen->normal_clock = MCLKS_NTSC; | 1216 gen->normal_clock = MCLKS_NTSC; |
1217 gen->soft_flush_cycles = MCLKS_LINE * 313 / 3 + 2; | |
1203 } | 1218 } |
1204 gen->master_clock = gen->normal_clock; | 1219 gen->master_clock = gen->normal_clock; |
1205 } | 1220 } |
1206 | 1221 |
1207 static uint8_t load_state(system_header *system, uint8_t slot) | 1222 static uint8_t load_state(system_header *system, uint8_t slot) |
1263 load_state(&gen->header, gen->header.delayed_load_slot - 1); | 1278 load_state(&gen->header, gen->header.delayed_load_slot - 1); |
1264 gen->header.delayed_load_slot = 0; | 1279 gen->header.delayed_load_slot = 0; |
1265 resume_68k(gen->m68k); | 1280 resume_68k(gen->m68k); |
1266 } | 1281 } |
1267 } | 1282 } |
1268 if (render_should_release_on_exit()) { | 1283 if (gen->header.force_release || render_should_release_on_exit()) { |
1269 bindings_release_capture(); | 1284 bindings_release_capture(); |
1270 vdp_release_framebuffer(gen->vdp); | 1285 vdp_release_framebuffer(gen->vdp); |
1271 render_pause_source(gen->ym->audio); | 1286 render_pause_source(gen->ym->audio); |
1272 render_pause_source(gen->psg->audio); | 1287 render_pause_source(gen->psg->audio); |
1273 } | 1288 } |
1319 } | 1334 } |
1320 | 1335 |
1321 static void resume_genesis(system_header *system) | 1336 static void resume_genesis(system_header *system) |
1322 { | 1337 { |
1323 genesis_context *gen = (genesis_context *)system; | 1338 genesis_context *gen = (genesis_context *)system; |
1324 if (render_should_release_on_exit()) { | 1339 if (gen->header.force_release || render_should_release_on_exit()) { |
1340 gen->header.force_release = 0; | |
1325 render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC); | 1341 render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC); |
1326 bindings_reacquire_capture(); | 1342 bindings_reacquire_capture(); |
1327 vdp_reacquire_framebuffer(gen->vdp); | 1343 vdp_reacquire_framebuffer(gen->vdp); |
1328 render_resume_source(gen->ym->audio); | 1344 render_resume_source(gen->ym->audio); |
1329 render_resume_source(gen->psg->audio); | 1345 render_resume_source(gen->psg->audio); |
1563 gen->max_cycles = config_cycles ? atoi(config_cycles) : DEFAULT_SYNC_INTERVAL; | 1579 gen->max_cycles = config_cycles ? atoi(config_cycles) : DEFAULT_SYNC_INTERVAL; |
1564 gen->int_latency_prev1 = MCLKS_PER_68K * 32; | 1580 gen->int_latency_prev1 = MCLKS_PER_68K * 32; |
1565 gen->int_latency_prev2 = MCLKS_PER_68K * 16; | 1581 gen->int_latency_prev2 = MCLKS_PER_68K * 16; |
1566 | 1582 |
1567 render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC); | 1583 render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC); |
1584 event_system_start(SYSTEM_GENESIS, (gen->version_reg & HZ50) ? VID_PAL : VID_NTSC, rom->name); | |
1568 | 1585 |
1569 gen->ym = malloc(sizeof(ym2612_context)); | 1586 gen->ym = malloc(sizeof(ym2612_context)); |
1587 char *fm = tern_find_ptr_default(model, "fm", "discrete 2612"); | |
1588 if (!strcmp(fm + strlen(fm) -4, "3834")) { | |
1589 system_opts |= YM_OPT_3834; | |
1590 } | |
1570 ym_init(gen->ym, gen->master_clock, MCLKS_PER_YM, system_opts); | 1591 ym_init(gen->ym, gen->master_clock, MCLKS_PER_YM, system_opts); |
1571 | 1592 |
1572 gen->psg = malloc(sizeof(psg_context)); | 1593 gen->psg = malloc(sizeof(psg_context)); |
1573 psg_init(gen->psg, gen->master_clock, MCLKS_PER_PSG); | 1594 psg_init(gen->psg, gen->master_clock, MCLKS_PER_PSG); |
1574 | 1595 |
1674 for (int i = 1; i < sizeof(gen->bank_regs); i++) | 1695 for (int i = 1; i < sizeof(gen->bank_regs); i++) |
1675 { | 1696 { |
1676 gen->bank_regs[i] = i; | 1697 gen->bank_regs[i] = i; |
1677 } | 1698 } |
1678 } | 1699 } |
1700 gen->reset_cycle = CYCLE_NEVER; | |
1679 | 1701 |
1680 return gen; | 1702 return gen; |
1681 } | 1703 } |
1682 | 1704 |
1683 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) | 1705 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) |