comparison sms.c @ 1752:d6d4c006a7b3

Initial attempt at interrupts in new Z80 core and integrating it into main executable
author Michael Pavone <pavone@retrodev.com>
date Sun, 10 Feb 2019 11:58:23 -0800
parents 319d90025d50
children 6e4faa10f9ee
comparison
equal deleted inserted replaced
1751:c5d4e1d14dac 1752:d6d4c006a7b3
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 #else
64 sms->z80->int_pulse_start = vint < hint ? vint : hint; 76 sms->z80->int_pulse_start = vint < hint ? vint : hint;
77 #endif
65 } 78 }
66 79
67 static uint8_t vdp_read(uint32_t location, void *vcontext) 80 static uint8_t vdp_read(uint32_t location, void *vcontext)
68 { 81 {
69 z80_context *z80 = vcontext; 82 z80_context *z80 = vcontext;
70 sms_context *sms = z80->system; 83 sms_context *sms = z80->system;
71 vdp_run_context(sms->vdp, z80->current_cycle); 84 vdp_run_context(sms->vdp, z80->Z80_CYCLE);
72 if (location & 1) { 85 if (location & 1) {
73 uint8_t ret = vdp_control_port_read(sms->vdp); 86 uint8_t ret = vdp_control_port_read(sms->vdp);
74 sms->vdp->flags2 &= ~(FLAG2_VINT_PENDING|FLAG2_HINT_PENDING); 87 sms->vdp->flags2 &= ~(FLAG2_VINT_PENDING|FLAG2_HINT_PENDING);
75 update_interrupts(sms); 88 update_interrupts(sms);
76 return ret; 89 return ret;
82 static void *vdp_write(uint32_t location, void *vcontext, uint8_t value) 95 static void *vdp_write(uint32_t location, void *vcontext, uint8_t value)
83 { 96 {
84 z80_context *z80 = vcontext; 97 z80_context *z80 = vcontext;
85 sms_context *sms = z80->system; 98 sms_context *sms = z80->system;
86 if (location & 1) { 99 if (location & 1) {
87 vdp_run_context_full(sms->vdp, z80->current_cycle); 100 vdp_run_context_full(sms->vdp, z80->Z80_CYCLE);
88 vdp_control_port_write_pbc(sms->vdp, value); 101 vdp_control_port_write_pbc(sms->vdp, value);
89 update_interrupts(sms); 102 update_interrupts(sms);
90 } else { 103 } else {
91 vdp_run_context(sms->vdp, z80->current_cycle); 104 vdp_run_context(sms->vdp, z80->Z80_CYCLE);
92 vdp_data_port_write_pbc(sms->vdp, value); 105 vdp_data_port_write_pbc(sms->vdp, value);
93 } 106 }
94 return vcontext; 107 return vcontext;
95 } 108 }
96 109
97 static uint8_t io_read(uint32_t location, void *vcontext) 110 static uint8_t io_read(uint32_t location, void *vcontext)
98 { 111 {
99 z80_context *z80 = vcontext; 112 z80_context *z80 = vcontext;
100 sms_context *sms = z80->system; 113 sms_context *sms = z80->system;
101 if (location == 0xC0 || location == 0xDC) { 114 if (location == 0xC0 || location == 0xDC) {
102 uint8_t port_a = io_data_read(sms->io.ports, z80->current_cycle); 115 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); 116 uint8_t port_b = io_data_read(sms->io.ports+1, z80->Z80_CYCLE);
104 return (port_a & 0x3F) | (port_b << 6); 117 return (port_a & 0x3F) | (port_b << 6);
105 } 118 }
106 if (location == 0xC1 || location == 0xDD) { 119 if (location == 0xC1 || location == 0xDD) {
107 uint8_t port_a = io_data_read(sms->io.ports, z80->current_cycle); 120 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); 121 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; 122 return (port_a & 0x40) | (port_b >> 2 & 0xF) | (port_b << 1 & 0x80) | 0x10;
110 } 123 }
111 return 0xFF; 124 return 0xFF;
112 } 125 }
113 126
341 static uint8_t load_state(system_header *system, uint8_t slot) 354 static uint8_t load_state(system_header *system, uint8_t slot)
342 { 355 {
343 sms_context *sms = (sms_context *)system; 356 sms_context *sms = (sms_context *)system;
344 char *statepath = get_slot_name(system, slot, "state"); 357 char *statepath = get_slot_name(system, slot, "state");
345 uint8_t ret; 358 uint8_t ret;
359 #ifndef NEW_CORE
346 if (!sms->z80->native_pc) { 360 if (!sms->z80->native_pc) {
347 ret = get_modification_time(statepath) != 0; 361 ret = get_modification_time(statepath) != 0;
348 if (ret) { 362 if (ret) {
349 system->delayed_load_slot = slot + 1; 363 system->delayed_load_slot = slot + 1;
350 } 364 }
351 goto done; 365 goto done;
352 366
353 } 367 }
368 #endif
354 ret = load_state_path(sms, statepath); 369 ret = load_state_path(sms, statepath);
355 done: 370 done:
356 free(statepath); 371 free(statepath);
357 return ret; 372 return ret;
358 } 373 }
359 374
360 static void run_sms(system_header *system) 375 static void run_sms(system_header *system)
361 { 376 {
362 sms_context *sms = (sms_context *)system; 377 sms_context *sms = (sms_context *)system;
363 uint32_t target_cycle = sms->z80->current_cycle + 3420*16; 378 uint32_t target_cycle = sms->z80->Z80_CYCLE + 3420*16;
364 //TODO: PAL support 379 //TODO: PAL support
365 render_set_video_standard(VID_NTSC); 380 render_set_video_standard(VID_NTSC);
366 while (!sms->should_return) 381 while (!sms->should_return)
367 { 382 {
368 if (system->delayed_load_slot) { 383 if (system->delayed_load_slot) {
372 } 387 }
373 if (system->enter_debugger && sms->z80->pc) { 388 if (system->enter_debugger && sms->z80->pc) {
374 system->enter_debugger = 0; 389 system->enter_debugger = 0;
375 zdebugger(sms->z80, sms->z80->pc); 390 zdebugger(sms->z80, sms->z80->pc);
376 } 391 }
392 #ifdef NEW_CORE
393 if (sms->z80->nmi_cycle == CYCLE_NEVER) {
394 #else
377 if (sms->z80->nmi_start == CYCLE_NEVER) { 395 if (sms->z80->nmi_start == CYCLE_NEVER) {
396 #endif
378 uint32_t nmi = vdp_next_nmi(sms->vdp); 397 uint32_t nmi = vdp_next_nmi(sms->vdp);
379 if (nmi != CYCLE_NEVER) { 398 if (nmi != CYCLE_NEVER) {
380 z80_assert_nmi(sms->z80, nmi); 399 z80_assert_nmi(sms->z80, nmi);
381 } 400 }
382 } 401 }
383 z80_run(sms->z80, target_cycle); 402 z80_run(sms->z80, target_cycle);
384 if (sms->z80->reset) { 403 if (sms->z80->reset) {
385 z80_clear_reset(sms->z80, sms->z80->current_cycle + 128*15); 404 z80_clear_reset(sms->z80, sms->z80->Z80_CYCLE + 128*15);
386 } 405 }
387 target_cycle = sms->z80->current_cycle; 406 target_cycle = sms->z80->Z80_CYCLE;
388 vdp_run_context(sms->vdp, target_cycle); 407 vdp_run_context(sms->vdp, target_cycle);
389 psg_run(sms->psg, target_cycle); 408 psg_run(sms->psg, target_cycle);
390 409
391 if (system->save_state) { 410 if (system->save_state) {
392 while (!sms->z80->pc) { 411 while (!sms->z80->pc) {
393 //advance Z80 to an instruction boundary 412 //advance Z80 to an instruction boundary
394 z80_run(sms->z80, sms->z80->current_cycle + 1); 413 z80_run(sms->z80, sms->z80->Z80_CYCLE + 1);
395 } 414 }
396 save_state(sms, system->save_state - 1); 415 save_state(sms, system->save_state - 1);
397 system->save_state = 0; 416 system->save_state = 0;
398 } 417 }
399 418
400 target_cycle += 3420*16; 419 target_cycle += 3420*16;
401 if (target_cycle > 0x10000000) { 420 if (target_cycle > 0x10000000) {
402 uint32_t adjust = sms->z80->current_cycle - 3420*262*2; 421 uint32_t adjust = sms->z80->Z80_CYCLE - 3420*262*2;
403 io_adjust_cycles(sms->io.ports, sms->z80->current_cycle, adjust); 422 io_adjust_cycles(sms->io.ports, sms->z80->Z80_CYCLE, adjust);
404 io_adjust_cycles(sms->io.ports+1, sms->z80->current_cycle, adjust); 423 io_adjust_cycles(sms->io.ports+1, sms->z80->Z80_CYCLE, adjust);
405 z80_adjust_cycles(sms->z80, adjust); 424 z80_adjust_cycles(sms->z80, adjust);
406 vdp_adjust_cycles(sms->vdp, adjust); 425 vdp_adjust_cycles(sms->vdp, adjust);
407 sms->psg->cycles -= adjust; 426 sms->psg->cycles -= adjust;
408 target_cycle -= adjust; 427 target_cycle -= adjust;
409 } 428 }
447 } 466 }
448 467
449 static void soft_reset(system_header *system) 468 static void soft_reset(system_header *system)
450 { 469 {
451 sms_context *sms = (sms_context *)system; 470 sms_context *sms = (sms_context *)system;
452 z80_assert_reset(sms->z80, sms->z80->current_cycle); 471 z80_assert_reset(sms->z80, sms->z80->Z80_CYCLE);
453 sms->z80->target_cycle = sms->z80->sync_cycle = sms->z80->current_cycle; 472 #ifndef NEW_CORE
473 sms->z80->target_cycle = sms->z80->sync_cycle = sms->z80->Z80_CYCLE;
474 #endif
454 } 475 }
455 476
456 static void free_sms(system_header *system) 477 static void free_sms(system_header *system)
457 { 478 {
458 sms_context *sms = (sms_context *)system; 479 sms_context *sms = (sms_context *)system;
459 vdp_free(sms->vdp); 480 vdp_free(sms->vdp);
460 z80_options_free(sms->z80->options); 481 z80_options_free(sms->z80->Z80_OPTS);
461 free(sms->z80); 482 free(sms->z80);
462 psg_free(sms->psg); 483 psg_free(sms->psg);
463 free(sms); 484 free(sms);
464 } 485 }
465 486
470 491
471 static void request_exit(system_header *system) 492 static void request_exit(system_header *system)
472 { 493 {
473 sms_context *sms = (sms_context *)system; 494 sms_context *sms = (sms_context *)system;
474 sms->should_return = 1; 495 sms->should_return = 1;
475 sms->z80->target_cycle = sms->z80->sync_cycle = sms->z80->current_cycle; 496 #ifndef NEW_CORE
497 sms->z80->target_cycle = sms->z80->sync_cycle = sms->z80->Z80_CYCLE;
498 #endif
476 } 499 }
477 500
478 static void inc_debug_mode(system_header *system) 501 static void inc_debug_mode(system_header *system)
479 { 502 {
480 sms_context *sms = (sms_context *)system; 503 sms_context *sms = (sms_context *)system;
575 memcpy(sms->header.info.map, memory_map, sizeof(memmap_chunk) * sms->header.info.map_chunks); 598 memcpy(sms->header.info.map, memory_map, sizeof(memmap_chunk) * sms->header.info.map_chunks);
576 z80_options *zopts = malloc(sizeof(z80_options)); 599 z80_options *zopts = malloc(sizeof(z80_options));
577 init_z80_opts(zopts, sms->header.info.map, sms->header.info.map_chunks, io_map, 4, 15, 0xFF); 600 init_z80_opts(zopts, sms->header.info.map, sms->header.info.map_chunks, io_map, 4, 15, 0xFF);
578 sms->z80 = init_z80_context(zopts); 601 sms->z80 = init_z80_context(zopts);
579 sms->z80->system = sms; 602 sms->z80->system = sms;
580 sms->z80->options->gen.debug_cmd_handler = debug_commands; 603 sms->z80->Z80_OPTS->gen.debug_cmd_handler = debug_commands;
581 604
582 sms->rom = media->buffer; 605 sms->rom = media->buffer;
583 sms->rom_size = rom_size; 606 sms->rom_size = rom_size;
584 if (sms->header.info.map_chunks > 2) { 607 if (sms->header.info.map_chunks > 2) {
585 sms->z80->mem_pointers[0] = sms->rom; 608 sms->z80->mem_pointers[0] = sms->rom;