comparison sms.c @ 2053:3414a4423de1 segacd

Merge from default
author Michael Pavone <pavone@retrodev.com>
date Sat, 15 Jan 2022 13:15:21 -0800
parents 81df9aa2de9b
children a7b753e260a2 9caebcfeac72
comparison
equal deleted inserted replaced
1692:5dacaef602a7 2053:3414a4423de1
7 #include "util.h" 7 #include "util.h"
8 #include "debug.h" 8 #include "debug.h"
9 #include "saves.h" 9 #include "saves.h"
10 #include "bindings.h" 10 #include "bindings.h"
11 11
12 #ifdef NEW_CORE
13 #define Z80_CYCLE cycles
14 #define Z80_OPTS opts
15 #define z80_handle_code_write(...)
16 #else
17 #define Z80_CYCLE current_cycle
18 #define Z80_OPTS options
19 #endif
20
12 static void *memory_io_write(uint32_t location, void *vcontext, uint8_t value) 21 static void *memory_io_write(uint32_t location, void *vcontext, uint8_t value)
13 { 22 {
14 z80_context *z80 = vcontext; 23 z80_context *z80 = vcontext;
15 sms_context *sms = z80->system; 24 sms_context *sms = z80->system;
16 if (location & 1) { 25 if (location & 1) {
17 uint8_t fuzzy_ctrl_0 = sms->io.ports[0].control, fuzzy_ctrl_1 = sms->io.ports[1].control; 26 uint8_t fuzzy_ctrl_0 = sms->io.ports[0].control, fuzzy_ctrl_1 = sms->io.ports[1].control;
18 io_control_write(sms->io.ports, (~value) << 5 & 0x60, z80->current_cycle); 27 io_control_write(sms->io.ports, (~value) << 5 & 0x60, z80->Z80_CYCLE);
19 fuzzy_ctrl_0 |= sms->io.ports[0].control; 28 fuzzy_ctrl_0 |= sms->io.ports[0].control;
20 io_control_write(sms->io.ports+1, (~value) << 3 & 0x60, z80->current_cycle); 29 io_control_write(sms->io.ports+1, (~value) << 3 & 0x60, z80->Z80_CYCLE);
21 fuzzy_ctrl_1 |= sms->io.ports[1].control; 30 fuzzy_ctrl_1 |= sms->io.ports[1].control;
22 if ( 31 if (
23 (fuzzy_ctrl_0 & 0x40 & (sms->io.ports[0].output ^ (value << 1)) & (value << 1)) 32 (fuzzy_ctrl_0 & 0x40 & (sms->io.ports[0].output ^ (value << 1)) & (value << 1))
24 || (fuzzy_ctrl_0 & 0x40 & (sms->io.ports[1].output ^ (value >> 1)) & (value >> 1)) 33 || (fuzzy_ctrl_0 & 0x40 & (sms->io.ports[1].output ^ (value >> 1)) & (value >> 1))
25 ) { 34 ) {
26 //TH is an output and it went from 0 -> 1 35 //TH is an output and it went from 0 -> 1
27 vdp_run_context(sms->vdp, z80->current_cycle); 36 vdp_run_context(sms->vdp, z80->Z80_CYCLE);
28 vdp_latch_hv(sms->vdp); 37 vdp_latch_hv(sms->vdp);
29 } 38 }
30 io_data_write(sms->io.ports, value << 1, z80->current_cycle); 39 io_data_write(sms->io.ports, value << 1, z80->Z80_CYCLE);
31 io_data_write(sms->io.ports + 1, value >> 1, z80->current_cycle); 40 io_data_write(sms->io.ports + 1, value >> 1, z80->Z80_CYCLE);
32 } else { 41 } else {
33 //TODO: memory control write 42 //TODO: memory control write
34 } 43 }
35 return vcontext; 44 return vcontext;
36 } 45 }
37 46
38 static uint8_t hv_read(uint32_t location, void *vcontext) 47 static uint8_t hv_read(uint32_t location, void *vcontext)
39 { 48 {
40 z80_context *z80 = vcontext; 49 z80_context *z80 = vcontext;
41 sms_context *sms = z80->system; 50 sms_context *sms = z80->system;
42 vdp_run_context(sms->vdp, z80->current_cycle); 51 vdp_run_context(sms->vdp, z80->Z80_CYCLE);
43 uint16_t hv = vdp_hv_counter_read(sms->vdp); 52 uint16_t hv = vdp_hv_counter_read(sms->vdp);
44 if (location & 1) { 53 if (location & 1) {
45 return hv; 54 return hv;
46 } else { 55 } else {
47 return hv >> 8; 56 return hv >> 8;
50 59
51 static void *sms_psg_write(uint32_t location, void *vcontext, uint8_t value) 60 static void *sms_psg_write(uint32_t location, void *vcontext, uint8_t value)
52 { 61 {
53 z80_context *z80 = vcontext; 62 z80_context *z80 = vcontext;
54 sms_context *sms = z80->system; 63 sms_context *sms = z80->system;
55 psg_run(sms->psg, z80->current_cycle); 64 psg_run(sms->psg, z80->Z80_CYCLE);
56 psg_write(sms->psg, value); 65 psg_write(sms->psg, value);
57 return vcontext; 66 return vcontext;
58 } 67 }
59 68
60 static void update_interrupts(sms_context *sms) 69 static void update_interrupts(sms_context *sms)
61 { 70 {
62 uint32_t vint = vdp_next_vint(sms->vdp); 71 uint32_t vint = vdp_next_vint(sms->vdp);
63 uint32_t hint = vdp_next_hint(sms->vdp); 72 uint32_t hint = vdp_next_hint(sms->vdp);
73 #ifdef NEW_CORE
74 sms->z80->int_cycle = vint < hint ? vint : hint;
75 z80_sync_cycle(sms->z80, sms->z80->sync_cycle);
76 #else
64 sms->z80->int_pulse_start = vint < hint ? vint : hint; 77 sms->z80->int_pulse_start = vint < hint ? vint : hint;
78 #endif
65 } 79 }
66 80
67 static uint8_t vdp_read(uint32_t location, void *vcontext) 81 static uint8_t vdp_read(uint32_t location, void *vcontext)
68 { 82 {
69 z80_context *z80 = vcontext; 83 z80_context *z80 = vcontext;
70 sms_context *sms = z80->system; 84 sms_context *sms = z80->system;
71 vdp_run_context(sms->vdp, z80->current_cycle); 85 vdp_run_context(sms->vdp, z80->Z80_CYCLE);
72 if (location & 1) { 86 if (location & 1) {
73 uint8_t ret = vdp_control_port_read(sms->vdp); 87 uint8_t ret = vdp_control_port_read(sms->vdp);
74 sms->vdp->flags2 &= ~(FLAG2_VINT_PENDING|FLAG2_HINT_PENDING); 88 sms->vdp->flags2 &= ~(FLAG2_VINT_PENDING|FLAG2_HINT_PENDING);
75 update_interrupts(sms); 89 update_interrupts(sms);
76 return ret; 90 return ret;
82 static void *vdp_write(uint32_t location, void *vcontext, uint8_t value) 96 static void *vdp_write(uint32_t location, void *vcontext, uint8_t value)
83 { 97 {
84 z80_context *z80 = vcontext; 98 z80_context *z80 = vcontext;
85 sms_context *sms = z80->system; 99 sms_context *sms = z80->system;
86 if (location & 1) { 100 if (location & 1) {
87 vdp_run_context_full(sms->vdp, z80->current_cycle); 101 vdp_run_context_full(sms->vdp, z80->Z80_CYCLE);
88 vdp_control_port_write_pbc(sms->vdp, value); 102 vdp_control_port_write_pbc(sms->vdp, value);
89 update_interrupts(sms); 103 update_interrupts(sms);
90 } else { 104 } else {
91 vdp_run_context(sms->vdp, z80->current_cycle); 105 vdp_run_context(sms->vdp, z80->Z80_CYCLE);
92 vdp_data_port_write_pbc(sms->vdp, value); 106 vdp_data_port_write_pbc(sms->vdp, value);
93 } 107 }
94 return vcontext; 108 return vcontext;
95 } 109 }
96 110
97 static uint8_t io_read(uint32_t location, void *vcontext) 111 static uint8_t io_read(uint32_t location, void *vcontext)
98 { 112 {
99 z80_context *z80 = vcontext; 113 z80_context *z80 = vcontext;
100 sms_context *sms = z80->system; 114 sms_context *sms = z80->system;
101 if (location == 0xC0 || location == 0xDC) { 115 if (location == 0xC0 || location == 0xDC) {
102 uint8_t port_a = io_data_read(sms->io.ports, z80->current_cycle); 116 uint8_t port_a = io_data_read(sms->io.ports, z80->Z80_CYCLE);
103 uint8_t port_b = io_data_read(sms->io.ports+1, z80->current_cycle); 117 uint8_t port_b = io_data_read(sms->io.ports+1, z80->Z80_CYCLE);
104 return (port_a & 0x3F) | (port_b << 6); 118 return (port_a & 0x3F) | (port_b << 6);
105 } 119 }
106 if (location == 0xC1 || location == 0xDD) { 120 if (location == 0xC1 || location == 0xDD) {
107 uint8_t port_a = io_data_read(sms->io.ports, z80->current_cycle); 121 uint8_t port_a = io_data_read(sms->io.ports, z80->Z80_CYCLE);
108 uint8_t port_b = io_data_read(sms->io.ports+1, z80->current_cycle); 122 uint8_t port_b = io_data_read(sms->io.ports+1, z80->Z80_CYCLE);
109 return (port_a & 0x40) | (port_b >> 2 & 0xF) | (port_b << 1 & 0x80) | 0x10; 123 return (port_a & 0x40) | (port_b >> 2 & 0xF) | (port_b << 1 & 0x80) | 0x10;
110 } 124 }
111 return 0xFF; 125 return 0xFF;
112 } 126 }
113 127
231 245
232 start_section(buf, SECTION_CART_RAM); 246 start_section(buf, SECTION_CART_RAM);
233 save_int8(buf, SMS_CART_RAM_SIZE / 1024); 247 save_int8(buf, SMS_CART_RAM_SIZE / 1024);
234 save_buffer8(buf, sms->cart_ram, SMS_CART_RAM_SIZE); 248 save_buffer8(buf, sms->cart_ram, SMS_CART_RAM_SIZE);
235 end_section(buf); 249 end_section(buf);
250 }
251
252 static uint8_t *serialize(system_header *sys, size_t *size_out)
253 {
254 sms_context *sms = (sms_context *)sys;
255 serialize_buffer state;
256 init_serialize(&state);
257 sms_serialize(sms, &state);
258 if (size_out) {
259 *size_out = state.size;
260 }
261 return state.data;
236 } 262 }
237 263
238 static void ram_deserialize(deserialize_buffer *buf, void *vsms) 264 static void ram_deserialize(deserialize_buffer *buf, void *vsms)
239 { 265 {
240 sms_context *sms = vsms; 266 sms_context *sms = vsms;
288 z80_invalidate_code_range(sms->z80, 0xC000, 0x10000); 314 z80_invalidate_code_range(sms->z80, 0xC000, 0x10000);
289 if (sms->bank_regs[0] & 8) { 315 if (sms->bank_regs[0] & 8) {
290 //cart RAM is enabled, invalidate the region in case there is any code there 316 //cart RAM is enabled, invalidate the region in case there is any code there
291 z80_invalidate_code_range(sms->z80, 0x8000, 0xC000); 317 z80_invalidate_code_range(sms->z80, 0x8000, 0xC000);
292 } 318 }
319 free(buf->handlers);
320 buf->handlers = NULL;
321 }
322
323 static void deserialize(system_header *sys, uint8_t *data, size_t size)
324 {
325 sms_context *sms = (sms_context *)sys;
326 deserialize_buffer buffer;
327 init_deserialize(&buffer, data, size);
328 sms_deserialize(&buffer, sms);
293 } 329 }
294 330
295 static void save_state(sms_context *sms, uint8_t slot) 331 static void save_state(sms_context *sms, uint8_t slot)
296 { 332 {
297 char *save_path = get_slot_name(&sms->header, slot, "state"); 333 char *save_path = get_slot_name(&sms->header, slot, "state");
319 static uint8_t load_state(system_header *system, uint8_t slot) 355 static uint8_t load_state(system_header *system, uint8_t slot)
320 { 356 {
321 sms_context *sms = (sms_context *)system; 357 sms_context *sms = (sms_context *)system;
322 char *statepath = get_slot_name(system, slot, "state"); 358 char *statepath = get_slot_name(system, slot, "state");
323 uint8_t ret; 359 uint8_t ret;
360 #ifndef NEW_CORE
324 if (!sms->z80->native_pc) { 361 if (!sms->z80->native_pc) {
325 ret = get_modification_time(statepath) != 0; 362 ret = get_modification_time(statepath) != 0;
326 if (ret) { 363 if (ret) {
327 system->delayed_load_slot = slot + 1; 364 system->delayed_load_slot = slot + 1;
328 } 365 }
329 goto done; 366 goto done;
330 367
331 } 368 }
369 #endif
332 ret = load_state_path(sms, statepath); 370 ret = load_state_path(sms, statepath);
333 done: 371 done:
334 free(statepath); 372 free(statepath);
335 return ret; 373 return ret;
336 } 374 }
337 375
338 static void run_sms(system_header *system) 376 static void run_sms(system_header *system)
339 { 377 {
340 sms_context *sms = (sms_context *)system; 378 sms_context *sms = (sms_context *)system;
341 uint32_t target_cycle = sms->z80->current_cycle + 3420*16; 379 uint32_t target_cycle = sms->z80->Z80_CYCLE + 3420*16;
342 //TODO: PAL support 380 //TODO: PAL support
343 render_set_video_standard(VID_NTSC); 381 render_set_video_standard(VID_NTSC);
344 while (!sms->should_return) 382 while (!sms->should_return)
345 { 383 {
346 if (system->delayed_load_slot) { 384 if (system->delayed_load_slot) {
350 } 388 }
351 if (system->enter_debugger && sms->z80->pc) { 389 if (system->enter_debugger && sms->z80->pc) {
352 system->enter_debugger = 0; 390 system->enter_debugger = 0;
353 zdebugger(sms->z80, sms->z80->pc); 391 zdebugger(sms->z80, sms->z80->pc);
354 } 392 }
393 #ifdef NEW_CORE
394 if (sms->z80->nmi_cycle == CYCLE_NEVER) {
395 #else
355 if (sms->z80->nmi_start == CYCLE_NEVER) { 396 if (sms->z80->nmi_start == CYCLE_NEVER) {
397 #endif
356 uint32_t nmi = vdp_next_nmi(sms->vdp); 398 uint32_t nmi = vdp_next_nmi(sms->vdp);
357 if (nmi != CYCLE_NEVER) { 399 if (nmi != CYCLE_NEVER) {
358 z80_assert_nmi(sms->z80, nmi); 400 z80_assert_nmi(sms->z80, nmi);
359 } 401 }
360 } 402 }
361 z80_run(sms->z80, target_cycle); 403 z80_run(sms->z80, target_cycle);
362 if (sms->z80->reset) { 404 if (sms->z80->reset) {
363 z80_clear_reset(sms->z80, sms->z80->current_cycle + 128*15); 405 z80_clear_reset(sms->z80, sms->z80->Z80_CYCLE + 128*15);
364 } 406 }
365 target_cycle = sms->z80->current_cycle; 407 target_cycle = sms->z80->Z80_CYCLE;
366 vdp_run_context(sms->vdp, target_cycle); 408 vdp_run_context(sms->vdp, target_cycle);
367 psg_run(sms->psg, target_cycle); 409 psg_run(sms->psg, target_cycle);
368 410
369 if (system->save_state) { 411 if (system->save_state) {
370 while (!sms->z80->pc) { 412 while (!sms->z80->pc) {
371 //advance Z80 to an instruction boundary 413 //advance Z80 to an instruction boundary
372 z80_run(sms->z80, sms->z80->current_cycle + 1); 414 z80_run(sms->z80, sms->z80->Z80_CYCLE + 1);
373 } 415 }
374 save_state(sms, system->save_state - 1); 416 save_state(sms, system->save_state - 1);
375 system->save_state = 0; 417 system->save_state = 0;
376 } 418 }
377 419
378 target_cycle += 3420*16; 420 target_cycle += 3420*16;
379 if (target_cycle > 0x10000000) { 421 if (target_cycle > 0x10000000) {
380 uint32_t adjust = sms->z80->current_cycle - 3420*262*2; 422 uint32_t adjust = sms->z80->Z80_CYCLE - 3420*262*2;
381 io_adjust_cycles(sms->io.ports, sms->z80->current_cycle, adjust); 423 io_adjust_cycles(sms->io.ports, sms->z80->Z80_CYCLE, adjust);
382 io_adjust_cycles(sms->io.ports+1, sms->z80->current_cycle, adjust); 424 io_adjust_cycles(sms->io.ports+1, sms->z80->Z80_CYCLE, adjust);
383 z80_adjust_cycles(sms->z80, adjust); 425 z80_adjust_cycles(sms->z80, adjust);
384 vdp_adjust_cycles(sms->vdp, adjust); 426 vdp_adjust_cycles(sms->vdp, adjust);
385 sms->psg->cycles -= adjust; 427 sms->psg->cycles -= adjust;
386 target_cycle -= adjust; 428 target_cycle -= adjust;
387 } 429 }
388 } 430 }
389 bindings_release_capture(); 431 if (sms->header.force_release || render_should_release_on_exit()) {
390 vdp_release_framebuffer(sms->vdp); 432 bindings_release_capture();
391 render_pause_source(sms->psg->audio); 433 vdp_release_framebuffer(sms->vdp);
434 render_pause_source(sms->psg->audio);
435 }
392 sms->should_return = 0; 436 sms->should_return = 0;
393 } 437 }
394 438
395 static void resume_sms(system_header *system) 439 static void resume_sms(system_header *system)
396 { 440 {
397 sms_context *sms = (sms_context *)system; 441 sms_context *sms = (sms_context *)system;
398 bindings_reacquire_capture(); 442 if (sms->header.force_release || render_should_release_on_exit()) {
399 vdp_reacquire_framebuffer(sms->vdp); 443 sms->header.force_release = 0;
400 render_resume_source(sms->psg->audio); 444 bindings_reacquire_capture();
445 vdp_reacquire_framebuffer(sms->vdp);
446 render_resume_source(sms->psg->audio);
447 }
401 run_sms(system); 448 run_sms(system);
402 } 449 }
403 450
404 static void start_sms(system_header *system, char *statefile) 451 static void start_sms(system_header *system, char *statefile)
405 { 452 {
421 } 468 }
422 469
423 static void soft_reset(system_header *system) 470 static void soft_reset(system_header *system)
424 { 471 {
425 sms_context *sms = (sms_context *)system; 472 sms_context *sms = (sms_context *)system;
426 z80_assert_reset(sms->z80, sms->z80->current_cycle); 473 z80_assert_reset(sms->z80, sms->z80->Z80_CYCLE);
427 sms->z80->target_cycle = sms->z80->sync_cycle = sms->z80->current_cycle; 474 #ifndef NEW_CORE
475 sms->z80->target_cycle = sms->z80->sync_cycle = sms->z80->Z80_CYCLE;
476 #endif
428 } 477 }
429 478
430 static void free_sms(system_header *system) 479 static void free_sms(system_header *system)
431 { 480 {
432 sms_context *sms = (sms_context *)system; 481 sms_context *sms = (sms_context *)system;
433 vdp_free(sms->vdp); 482 vdp_free(sms->vdp);
434 z80_options_free(sms->z80->options); 483 z80_options_free(sms->z80->Z80_OPTS);
435 free(sms->z80); 484 free(sms->z80);
436 psg_free(sms->psg); 485 psg_free(sms->psg);
437 free(sms); 486 free(sms);
438 } 487 }
439 488
444 493
445 static void request_exit(system_header *system) 494 static void request_exit(system_header *system)
446 { 495 {
447 sms_context *sms = (sms_context *)system; 496 sms_context *sms = (sms_context *)system;
448 sms->should_return = 1; 497 sms->should_return = 1;
498 #ifndef NEW_CORE
499 sms->z80->target_cycle = sms->z80->sync_cycle = sms->z80->Z80_CYCLE;
500 #endif
449 } 501 }
450 502
451 static void inc_debug_mode(system_header *system) 503 static void inc_debug_mode(system_header *system)
452 { 504 {
453 sms_context *sms = (sms_context *)system; 505 sms_context *sms = (sms_context *)system;
514 566
515 static void keyboard_up(system_header *system, uint8_t scancode) 567 static void keyboard_up(system_header *system, uint8_t scancode)
516 { 568 {
517 sms_context *sms = (sms_context *)system; 569 sms_context *sms = (sms_context *)system;
518 io_keyboard_up(&sms->io, scancode); 570 io_keyboard_up(&sms->io, scancode);
571 }
572
573 static void set_gain_config(sms_context *sms)
574 {
575 char *config_gain;
576 config_gain = tern_find_path(config, "audio\0psg_gain\0", TVAL_PTR).ptrval;
577 render_audio_source_gaindb(sms->psg->audio, config_gain ? atof(config_gain) : 0.0f);
519 } 578 }
520 579
521 static void config_updated(system_header *system) 580 static void config_updated(system_header *system)
522 { 581 {
523 sms_context *sms = (sms_context *)system; 582 sms_context *sms = (sms_context *)system;
548 memcpy(sms->header.info.map, memory_map, sizeof(memmap_chunk) * sms->header.info.map_chunks); 607 memcpy(sms->header.info.map, memory_map, sizeof(memmap_chunk) * sms->header.info.map_chunks);
549 z80_options *zopts = malloc(sizeof(z80_options)); 608 z80_options *zopts = malloc(sizeof(z80_options));
550 init_z80_opts(zopts, sms->header.info.map, sms->header.info.map_chunks, io_map, 4, 15, 0xFF); 609 init_z80_opts(zopts, sms->header.info.map, sms->header.info.map_chunks, io_map, 4, 15, 0xFF);
551 sms->z80 = init_z80_context(zopts); 610 sms->z80 = init_z80_context(zopts);
552 sms->z80->system = sms; 611 sms->z80->system = sms;
553 sms->z80->options->gen.debug_cmd_handler = debug_commands; 612 sms->z80->Z80_OPTS->gen.debug_cmd_handler = debug_commands;
554 613
555 sms->rom = media->buffer; 614 sms->rom = media->buffer;
556 sms->rom_size = rom_size; 615 sms->rom_size = rom_size;
557 if (sms->header.info.map_chunks > 2) { 616 if (sms->header.info.map_chunks > 2) {
558 sms->z80->mem_pointers[0] = sms->rom; 617 sms->z80->mem_pointers[0] = sms->rom;
567 sms->normal_clock = sms->master_clock = 53693175; 626 sms->normal_clock = sms->master_clock = 53693175;
568 627
569 sms->psg = malloc(sizeof(psg_context)); 628 sms->psg = malloc(sizeof(psg_context));
570 psg_init(sms->psg, sms->master_clock, 15*16); 629 psg_init(sms->psg, sms->master_clock, 15*16);
571 630
572 sms->vdp = init_vdp_context(0); 631 set_gain_config(sms);
632
633 sms->vdp = init_vdp_context(0, 0);
573 sms->vdp->system = &sms->header; 634 sms->vdp->system = &sms->header;
574 635
575 sms->header.info.save_type = SAVE_NONE; 636 sms->header.info.save_type = SAVE_NONE;
576 sms->header.info.name = strdup(media->name); 637 sms->header.info.name = strdup(media->name);
577 638
596 sms->header.mouse_motion_absolute = mouse_motion_absolute; 657 sms->header.mouse_motion_absolute = mouse_motion_absolute;
597 sms->header.mouse_motion_relative = mouse_motion_relative; 658 sms->header.mouse_motion_relative = mouse_motion_relative;
598 sms->header.keyboard_down = keyboard_down; 659 sms->header.keyboard_down = keyboard_down;
599 sms->header.keyboard_up = keyboard_up; 660 sms->header.keyboard_up = keyboard_up;
600 sms->header.config_updated = config_updated; 661 sms->header.config_updated = config_updated;
662 sms->header.serialize = serialize;
663 sms->header.deserialize = deserialize;
601 sms->header.type = SYSTEM_SMS; 664 sms->header.type = SYSTEM_SMS;
602 665
603 return sms; 666 return sms;
604 } 667 }