Mercurial > repos > blastem
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; |