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