Mercurial > repos > blastem
comparison genesis.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 | 33ec5df77fac |
comparison
equal
deleted
inserted
replaced
1751:c5d4e1d14dac | 1752:d6d4c006a7b3 |
---|---|
37 #define MAX_SOUND_CYCLES 1000 | 37 #define MAX_SOUND_CYCLES 1000 |
38 #else | 38 #else |
39 #define MAX_SOUND_CYCLES 100000 | 39 #define MAX_SOUND_CYCLES 100000 |
40 #endif | 40 #endif |
41 | 41 |
42 #ifdef NEW_CORE | |
43 #define Z80_CYCLE cycles | |
44 #define Z80_OPTS opts | |
45 #define z80_handle_code_write(...) | |
46 #else | |
47 #define Z80_CYCLE current_cycle | |
48 #define Z80_OPTS options | |
49 #endif | |
50 | |
42 void genesis_serialize(genesis_context *gen, serialize_buffer *buf, uint32_t m68k_pc) | 51 void genesis_serialize(genesis_context *gen, serialize_buffer *buf, uint32_t m68k_pc) |
43 { | 52 { |
44 start_section(buf, SECTION_68000); | 53 start_section(buf, SECTION_68000); |
45 m68k_serialize(gen->m68k, m68k_pc, buf); | 54 m68k_serialize(gen->m68k, m68k_pc, buf); |
46 end_section(buf); | 55 end_section(buf); |
62 end_section(buf); | 71 end_section(buf); |
63 | 72 |
64 start_section(buf, SECTION_GEN_BUS_ARBITER); | 73 start_section(buf, SECTION_GEN_BUS_ARBITER); |
65 save_int8(buf, gen->z80->reset); | 74 save_int8(buf, gen->z80->reset); |
66 save_int8(buf, gen->z80->busreq); | 75 save_int8(buf, gen->z80->busreq); |
67 save_int16(buf, gen->z80->bank_reg); | 76 save_int16(buf, gen->z80_bank_reg); |
68 end_section(buf); | 77 end_section(buf); |
69 | 78 |
70 start_section(buf, SECTION_SEGA_IO_1); | 79 start_section(buf, SECTION_SEGA_IO_1); |
71 io_serialize(gen->io.ports, buf); | 80 io_serialize(gen->io.ports, buf); |
72 end_section(buf); | 81 end_section(buf); |
139 z80_invalidate_code_range(gen->z80, 0, 0x4000); | 148 z80_invalidate_code_range(gen->z80, 0, 0x4000); |
140 } | 149 } |
141 | 150 |
142 static void update_z80_bank_pointer(genesis_context *gen) | 151 static void update_z80_bank_pointer(genesis_context *gen) |
143 { | 152 { |
144 if (gen->z80->bank_reg < 0x140) { | 153 if (gen->z80_bank_reg < 0x140) { |
145 gen->z80->mem_pointers[1] = get_native_pointer(gen->z80->bank_reg << 15, (void **)gen->m68k->mem_pointers, &gen->m68k->options->gen); | 154 gen->z80->mem_pointers[1] = get_native_pointer(gen->z80_bank_reg << 15, (void **)gen->m68k->mem_pointers, &gen->m68k->options->gen); |
146 } else { | 155 } else { |
147 gen->z80->mem_pointers[1] = NULL; | 156 gen->z80->mem_pointers[1] = NULL; |
148 } | 157 } |
149 } | 158 } |
150 | 159 |
151 static void bus_arbiter_deserialize(deserialize_buffer *buf, void *vgen) | 160 static void bus_arbiter_deserialize(deserialize_buffer *buf, void *vgen) |
152 { | 161 { |
153 genesis_context *gen = vgen; | 162 genesis_context *gen = vgen; |
154 gen->z80->reset = load_int8(buf); | 163 gen->z80->reset = load_int8(buf); |
155 gen->z80->busreq = load_int8(buf); | 164 gen->z80->busreq = load_int8(buf); |
156 gen->z80->bank_reg = load_int16(buf) & 0x1FF; | 165 gen->z80_bank_reg = load_int16(buf) & 0x1FF; |
157 } | 166 } |
158 | 167 |
159 static void adjust_int_cycle(m68k_context * context, vdp_context * v_context); | 168 static void adjust_int_cycle(m68k_context * context, vdp_context * v_context); |
160 void genesis_deserialize(deserialize_buffer *buf, genesis_context *gen) | 169 void genesis_deserialize(deserialize_buffer *buf, genesis_context *gen) |
161 { | 170 { |
282 #else | 291 #else |
283 #define dprintf | 292 #define dprintf |
284 #define dputs | 293 #define dputs |
285 #endif | 294 #endif |
286 | 295 |
296 #ifndef NEW_CORE | |
287 static void z80_next_int_pulse(z80_context * z_context) | 297 static void z80_next_int_pulse(z80_context * z_context) |
288 { | 298 { |
289 genesis_context * gen = z_context->system; | 299 genesis_context * gen = z_context->system; |
290 z_context->int_pulse_start = vdp_next_vint_z80(gen->vdp); | 300 z_context->int_pulse_start = vdp_next_vint_z80(gen->vdp); |
291 z_context->int_pulse_end = z_context->int_pulse_start + Z80_INT_PULSE_MCLKS; | 301 z_context->int_pulse_end = z_context->int_pulse_start + Z80_INT_PULSE_MCLKS; |
292 z_context->im2_vector = 0xFF; | 302 z_context->im2_vector = 0xFF; |
293 } | 303 } |
304 #endif | |
294 | 305 |
295 static void sync_z80(z80_context * z_context, uint32_t mclks) | 306 static void sync_z80(z80_context * z_context, uint32_t mclks) |
296 { | 307 { |
297 #ifndef NO_Z80 | 308 #ifndef NO_Z80 |
298 if (z80_enabled) { | 309 if (z80_enabled) { |
299 z80_run(z_context, mclks); | 310 z80_run(z_context, mclks); |
300 } else | 311 } else |
301 #endif | 312 #endif |
302 { | 313 { |
303 z_context->current_cycle = mclks; | 314 z_context->Z80_CYCLE = mclks; |
304 } | 315 } |
305 } | 316 } |
306 | 317 |
307 static void sync_sound(genesis_context * gen, uint32_t target) | 318 static void sync_sound(genesis_context * gen, uint32_t target) |
308 { | 319 { |
408 if (address) { | 419 if (address) { |
409 if (gen->header.enter_debugger) { | 420 if (gen->header.enter_debugger) { |
410 gen->header.enter_debugger = 0; | 421 gen->header.enter_debugger = 0; |
411 debugger(context, address); | 422 debugger(context, address); |
412 } | 423 } |
424 #ifdef NEW_CORE | |
425 if (gen->header.save_state) { | |
426 #else | |
413 if (gen->header.save_state && (z_context->pc || !z_context->native_pc || z_context->reset || !z_context->busreq)) { | 427 if (gen->header.save_state && (z_context->pc || !z_context->native_pc || z_context->reset || !z_context->busreq)) { |
428 #endif | |
414 uint8_t slot = gen->header.save_state - 1; | 429 uint8_t slot = gen->header.save_state - 1; |
415 gen->header.save_state = 0; | 430 gen->header.save_state = 0; |
431 #ifndef NEW_CORE | |
416 if (z_context->native_pc && !z_context->reset) { | 432 if (z_context->native_pc && !z_context->reset) { |
417 //advance Z80 core to the start of an instruction | 433 //advance Z80 core to the start of an instruction |
418 while (!z_context->pc) | 434 while (!z_context->pc) |
419 { | 435 { |
420 sync_z80(z_context, z_context->current_cycle + MCLKS_PER_Z80); | 436 sync_z80(z_context, z_context->current_cycle + MCLKS_PER_Z80); |
421 } | 437 } |
422 } | 438 } |
439 #endif | |
423 char *save_path = slot == SERIALIZE_SLOT ? NULL : get_slot_name(&gen->header, slot, use_native_states ? "state" : "gst"); | 440 char *save_path = slot == SERIALIZE_SLOT ? NULL : get_slot_name(&gen->header, slot, use_native_states ? "state" : "gst"); |
424 if (use_native_states || slot == SERIALIZE_SLOT) { | 441 if (use_native_states || slot == SERIALIZE_SLOT) { |
425 serialize_buffer state; | 442 serialize_buffer state; |
426 init_serialize(&state); | 443 init_serialize(&state); |
427 genesis_serialize(gen, &state, address); | 444 genesis_serialize(gen, &state, address); |
569 fatal_error("machine freeze due to write to Z80 address %X\n", 0x7F00 | vdp_port); | 586 fatal_error("machine freeze due to write to Z80 address %X\n", 0x7F00 | vdp_port); |
570 } | 587 } |
571 if (vdp_port < 0x10) { | 588 if (vdp_port < 0x10) { |
572 //These probably won't currently interact well with the 68K accessing the VDP | 589 //These probably won't currently interact well with the 68K accessing the VDP |
573 if (vdp_port < 4) { | 590 if (vdp_port < 4) { |
574 vdp_run_context(gen->vdp, context->current_cycle); | 591 vdp_run_context(gen->vdp, context->Z80_CYCLE); |
575 vdp_data_port_write(gen->vdp, value << 8 | value); | 592 vdp_data_port_write(gen->vdp, value << 8 | value); |
576 } else if (vdp_port < 8) { | 593 } else if (vdp_port < 8) { |
577 vdp_run_context_full(gen->vdp, context->current_cycle); | 594 vdp_run_context_full(gen->vdp, context->Z80_CYCLE); |
578 vdp_control_port_write(gen->vdp, value << 8 | value); | 595 vdp_control_port_write(gen->vdp, value << 8 | value); |
579 } else { | 596 } else { |
580 fatal_error("Illegal write to HV Counter port %X\n", vdp_port); | 597 fatal_error("Illegal write to HV Counter port %X\n", vdp_port); |
581 } | 598 } |
582 } else if (vdp_port < 0x18) { | 599 } else if (vdp_port < 0x18) { |
583 sync_sound(gen, context->current_cycle); | 600 sync_sound(gen, context->Z80_CYCLE); |
584 psg_write(gen->psg, value); | 601 psg_write(gen->psg, value); |
585 } else { | 602 } else { |
586 vdp_test_port_write(gen->vdp, value); | 603 vdp_test_port_write(gen->vdp, value); |
587 } | 604 } |
588 return context; | 605 return context; |
657 fatal_error("machine freeze due to read from Z80 address %X\n", 0x7F00 | vdp_port); | 674 fatal_error("machine freeze due to read from Z80 address %X\n", 0x7F00 | vdp_port); |
658 } | 675 } |
659 genesis_context * gen = context->system; | 676 genesis_context * gen = context->system; |
660 //VDP access goes over the 68K bus like a bank area access | 677 //VDP access goes over the 68K bus like a bank area access |
661 //typical delay from bus arbitration | 678 //typical delay from bus arbitration |
662 context->current_cycle += 3 * MCLKS_PER_Z80; | 679 context->Z80_CYCLE += 3 * MCLKS_PER_Z80; |
663 //TODO: add cycle for an access right after a previous one | 680 //TODO: add cycle for an access right after a previous one |
664 //TODO: Below cycle time is an estimate based on the time between 68K !BG goes low and Z80 !MREQ goes high | 681 //TODO: Below cycle time is an estimate based on the time between 68K !BG goes low and Z80 !MREQ goes high |
665 // Needs a new logic analyzer capture to get the actual delay on the 68K side | 682 // Needs a new logic analyzer capture to get the actual delay on the 68K side |
666 gen->m68k->current_cycle += 8 * MCLKS_PER_68K; | 683 gen->m68k->current_cycle += 8 * MCLKS_PER_68K; |
667 | 684 |
668 | 685 |
669 vdp_port &= 0x1F; | 686 vdp_port &= 0x1F; |
670 uint16_t ret; | 687 uint16_t ret; |
671 if (vdp_port < 0x10) { | 688 if (vdp_port < 0x10) { |
672 //These probably won't currently interact well with the 68K accessing the VDP | 689 //These probably won't currently interact well with the 68K accessing the VDP |
673 vdp_run_context(gen->vdp, context->current_cycle); | 690 vdp_run_context(gen->vdp, context->Z80_CYCLE); |
674 if (vdp_port < 4) { | 691 if (vdp_port < 4) { |
675 ret = vdp_data_port_read(gen->vdp); | 692 ret = vdp_data_port_read(gen->vdp); |
676 } else if (vdp_port < 8) { | 693 } else if (vdp_port < 8) { |
677 ret = vdp_control_port_read(gen->vdp); | 694 ret = vdp_control_port_read(gen->vdp); |
678 } else { | 695 } else { |
709 ym_address_write_part2(gen->ym, value); | 726 ym_address_write_part2(gen->ym, value); |
710 } else { | 727 } else { |
711 ym_address_write_part1(gen->ym, value); | 728 ym_address_write_part1(gen->ym, value); |
712 } | 729 } |
713 } else if (location == 0x6000) { | 730 } else if (location == 0x6000) { |
714 gen->z80->bank_reg = (gen->z80->bank_reg >> 1 | value << 8) & 0x1FF; | 731 gen->z80_bank_reg = (gen->z80_bank_reg >> 1 | value << 8) & 0x1FF; |
715 if (gen->z80->bank_reg < 0x80) { | 732 if (gen->z80_bank_reg < 0x80) { |
716 gen->z80->mem_pointers[1] = (gen->z80->bank_reg << 15) + ((char *)gen->z80->mem_pointers[2]); | 733 gen->z80->mem_pointers[1] = (gen->z80_bank_reg << 15) + ((char *)gen->z80->mem_pointers[2]); |
717 } else { | 734 } else { |
718 gen->z80->mem_pointers[1] = NULL; | 735 gen->z80->mem_pointers[1] = NULL; |
719 } | 736 } |
720 } else { | 737 } else { |
721 fatal_error("68K write to unhandled Z80 address %X\n", location); | 738 fatal_error("68K write to unhandled Z80 address %X\n", location); |
940 | 957 |
941 static void * z80_write_ym(uint32_t location, void * vcontext, uint8_t value) | 958 static void * z80_write_ym(uint32_t location, void * vcontext, uint8_t value) |
942 { | 959 { |
943 z80_context * context = vcontext; | 960 z80_context * context = vcontext; |
944 genesis_context * gen = context->system; | 961 genesis_context * gen = context->system; |
945 sync_sound(gen, context->current_cycle); | 962 sync_sound(gen, context->Z80_CYCLE); |
946 if (location & 1) { | 963 if (location & 1) { |
947 ym_data_write(gen->ym, value); | 964 ym_data_write(gen->ym, value); |
948 } else if (location & 2) { | 965 } else if (location & 2) { |
949 ym_address_write_part2(gen->ym, value); | 966 ym_address_write_part2(gen->ym, value); |
950 } else { | 967 } else { |
955 | 972 |
956 static uint8_t z80_read_ym(uint32_t location, void * vcontext) | 973 static uint8_t z80_read_ym(uint32_t location, void * vcontext) |
957 { | 974 { |
958 z80_context * context = vcontext; | 975 z80_context * context = vcontext; |
959 genesis_context * gen = context->system; | 976 genesis_context * gen = context->system; |
960 sync_sound(gen, context->current_cycle); | 977 sync_sound(gen, context->Z80_CYCLE); |
961 return ym_read_status(gen->ym); | 978 return ym_read_status(gen->ym); |
962 } | 979 } |
963 | 980 |
964 static uint8_t z80_read_bank(uint32_t location, void * vcontext) | 981 static uint8_t z80_read_bank(uint32_t location, void * vcontext) |
965 { | 982 { |
966 z80_context * context = vcontext; | 983 z80_context * context = vcontext; |
967 genesis_context *gen = context->system; | 984 genesis_context *gen = context->system; |
968 if (gen->bus_busy) { | 985 if (gen->bus_busy) { |
969 context->current_cycle = context->sync_cycle; | 986 context->Z80_CYCLE = gen->m68k->current_cycle; |
970 } | 987 } |
971 //typical delay from bus arbitration | 988 //typical delay from bus arbitration |
972 context->current_cycle += 3 * MCLKS_PER_Z80; | 989 context->Z80_CYCLE += 3 * MCLKS_PER_Z80; |
973 //TODO: add cycle for an access right after a previous one | 990 //TODO: add cycle for an access right after a previous one |
974 //TODO: Below cycle time is an estimate based on the time between 68K !BG goes low and Z80 !MREQ goes high | 991 //TODO: Below cycle time is an estimate based on the time between 68K !BG goes low and Z80 !MREQ goes high |
975 // Needs a new logic analyzer capture to get the actual delay on the 68K side | 992 // Needs a new logic analyzer capture to get the actual delay on the 68K side |
976 gen->m68k->current_cycle += 8 * MCLKS_PER_68K; | 993 gen->m68k->current_cycle += 8 * MCLKS_PER_68K; |
977 | 994 |
978 location &= 0x7FFF; | 995 location &= 0x7FFF; |
979 if (context->mem_pointers[1]) { | 996 if (context->mem_pointers[1]) { |
980 return context->mem_pointers[1][location ^ 1]; | 997 return context->mem_pointers[1][location ^ 1]; |
981 } | 998 } |
982 uint32_t address = context->bank_reg << 15 | location; | 999 uint32_t address = gen->z80_bank_reg << 15 | location; |
983 if (address >= 0xC00000 && address < 0xE00000) { | 1000 if (address >= 0xC00000 && address < 0xE00000) { |
984 return z80_vdp_port_read(location & 0xFF, context); | 1001 return z80_vdp_port_read(location & 0xFF, context); |
985 } else { | 1002 } else { |
986 fprintf(stderr, "Unhandled read by Z80 from address %X through banked memory area (%X)\n", address, context->bank_reg << 15); | 1003 fprintf(stderr, "Unhandled read by Z80 from address %X through banked memory area (%X)\n", address, gen->z80_bank_reg << 15); |
987 } | 1004 } |
988 return 0; | 1005 return 0; |
989 } | 1006 } |
990 | 1007 |
991 static void *z80_write_bank(uint32_t location, void * vcontext, uint8_t value) | 1008 static void *z80_write_bank(uint32_t location, void * vcontext, uint8_t value) |
992 { | 1009 { |
993 z80_context * context = vcontext; | 1010 z80_context * context = vcontext; |
994 genesis_context *gen = context->system; | 1011 genesis_context *gen = context->system; |
995 if (gen->bus_busy) { | 1012 if (gen->bus_busy) { |
996 context->current_cycle = context->sync_cycle; | 1013 context->Z80_CYCLE = gen->m68k->current_cycle; |
997 } | 1014 } |
998 //typical delay from bus arbitration | 1015 //typical delay from bus arbitration |
999 context->current_cycle += 3 * MCLKS_PER_Z80; | 1016 context->Z80_CYCLE += 3 * MCLKS_PER_Z80; |
1000 //TODO: add cycle for an access right after a previous one | 1017 //TODO: add cycle for an access right after a previous one |
1001 //TODO: Below cycle time is an estimate based on the time between 68K !BG goes low and Z80 !MREQ goes high | 1018 //TODO: Below cycle time is an estimate based on the time between 68K !BG goes low and Z80 !MREQ goes high |
1002 // Needs a new logic analyzer capture to get the actual delay on the 68K side | 1019 // Needs a new logic analyzer capture to get the actual delay on the 68K side |
1003 gen->m68k->current_cycle += 8 * MCLKS_PER_68K; | 1020 gen->m68k->current_cycle += 8 * MCLKS_PER_68K; |
1004 | 1021 |
1005 location &= 0x7FFF; | 1022 location &= 0x7FFF; |
1006 uint32_t address = context->bank_reg << 15 | location; | 1023 uint32_t address = gen->z80_bank_reg << 15 | location; |
1007 if (address >= 0xE00000) { | 1024 if (address >= 0xE00000) { |
1008 address &= 0xFFFF; | 1025 address &= 0xFFFF; |
1009 ((uint8_t *)gen->work_ram)[address ^ 1] = value; | 1026 ((uint8_t *)gen->work_ram)[address ^ 1] = value; |
1010 } else if (address >= 0xC00000) { | 1027 } else if (address >= 0xC00000) { |
1011 z80_vdp_port_write(location & 0xFF, context, value); | 1028 z80_vdp_port_write(location & 0xFF, context, value); |
1016 } | 1033 } |
1017 | 1034 |
1018 static void *z80_write_bank_reg(uint32_t location, void * vcontext, uint8_t value) | 1035 static void *z80_write_bank_reg(uint32_t location, void * vcontext, uint8_t value) |
1019 { | 1036 { |
1020 z80_context * context = vcontext; | 1037 z80_context * context = vcontext; |
1021 | 1038 genesis_context *gen = context->system; |
1022 context->bank_reg = (context->bank_reg >> 1 | value << 8) & 0x1FF; | 1039 |
1040 gen->z80_bank_reg = (gen->z80_bank_reg >> 1 | value << 8) & 0x1FF; | |
1023 update_z80_bank_pointer(context->system); | 1041 update_z80_bank_pointer(context->system); |
1024 | 1042 |
1025 return context; | 1043 return context; |
1026 } | 1044 } |
1027 | 1045 |
1238 memmap_chunk *map = (memmap_chunk *)gen->m68k->options->gen.memmap; | 1256 memmap_chunk *map = (memmap_chunk *)gen->m68k->options->gen.memmap; |
1239 m68k_options_free(gen->m68k->options); | 1257 m68k_options_free(gen->m68k->options); |
1240 free(gen->cart); | 1258 free(gen->cart); |
1241 free(gen->m68k); | 1259 free(gen->m68k); |
1242 free(gen->work_ram); | 1260 free(gen->work_ram); |
1243 z80_options_free(gen->z80->options); | 1261 z80_options_free(gen->z80->Z80_OPTS); |
1244 free(gen->z80); | 1262 free(gen->z80); |
1245 free(gen->zram); | 1263 free(gen->zram); |
1246 ym_free(gen->ym); | 1264 ym_free(gen->ym); |
1247 psg_free(gen->psg); | 1265 psg_free(gen->psg); |
1248 free(gen->header.save_dir); | 1266 free(gen->header.save_dir); |
1366 z80_map[0].buffer = gen->zram = calloc(1, Z80_RAM_BYTES); | 1384 z80_map[0].buffer = gen->zram = calloc(1, Z80_RAM_BYTES); |
1367 #ifndef NO_Z80 | 1385 #ifndef NO_Z80 |
1368 z80_options *z_opts = malloc(sizeof(z80_options)); | 1386 z80_options *z_opts = malloc(sizeof(z80_options)); |
1369 init_z80_opts(z_opts, z80_map, 5, NULL, 0, MCLKS_PER_Z80, 0xFFFF); | 1387 init_z80_opts(z_opts, z80_map, 5, NULL, 0, MCLKS_PER_Z80, 0xFFFF); |
1370 gen->z80 = init_z80_context(z_opts); | 1388 gen->z80 = init_z80_context(z_opts); |
1389 #ifndef NEW_CORE | |
1371 gen->z80->next_int_pulse = z80_next_int_pulse; | 1390 gen->z80->next_int_pulse = z80_next_int_pulse; |
1391 #endif | |
1372 z80_assert_reset(gen->z80, 0); | 1392 z80_assert_reset(gen->z80, 0); |
1373 #else | 1393 #else |
1374 gen->z80 = calloc(1, sizeof(z80_context)); | 1394 gen->z80 = calloc(1, sizeof(z80_context)); |
1375 #endif | 1395 #endif |
1376 | 1396 |