Mercurial > repos > blastem
comparison blastem.c @ 668:5439ae7946ca
Made the Z80 core more contained by refactoring some code in blastem.c into z80_to_x86.c
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 03 Jan 2015 18:23:04 -0800 |
parents | 30ccf56842d6 |
children | 7a9a7c96cb22 |
comparison
equal
deleted
inserted
replaced
667:30ccf56842d6 | 668:5439ae7946ca |
---|---|
153 } | 153 } |
154 | 154 |
155 int break_on_sync = 0; | 155 int break_on_sync = 0; |
156 int save_state = 0; | 156 int save_state = 0; |
157 | 157 |
158 uint8_t reset = 1; | |
159 uint8_t need_reset = 0; | |
160 uint8_t busreq = 0; | |
161 uint8_t busack = 0; | |
162 uint32_t busack_cycle = CYCLE_NEVER; | |
163 uint8_t new_busack = 0; | |
164 //#define DO_DEBUG_PRINT | 158 //#define DO_DEBUG_PRINT |
165 #ifdef DO_DEBUG_PRINT | 159 #ifdef DO_DEBUG_PRINT |
166 #define dprintf printf | 160 #define dprintf printf |
167 #define dputs puts | 161 #define dputs puts |
168 #else | 162 #else |
170 #define dputs | 164 #define dputs |
171 #endif | 165 #endif |
172 | 166 |
173 #define Z80_VINT_DURATION 128 | 167 #define Z80_VINT_DURATION 128 |
174 | 168 |
169 void z80_next_int_pulse(z80_context * z_context) | |
170 { | |
171 genesis_context * gen = z_context->system; | |
172 z_context->int_pulse_start = vdp_next_vint_z80(gen->vdp); | |
173 z_context->int_pulse_end = z_context->int_pulse_start + Z80_VINT_DURATION; | |
174 } | |
175 | |
175 void sync_z80(z80_context * z_context, uint32_t mclks) | 176 void sync_z80(z80_context * z_context, uint32_t mclks) |
176 { | 177 { |
177 #ifndef NO_Z80 | 178 #ifndef NO_Z80 |
178 if (z80_enabled && !reset && !busreq) { | 179 if (z80_enabled) { |
179 genesis_context * gen = z_context->system; | 180 z80_run(z_context, mclks); |
180 z_context->sync_cycle = mclks; | |
181 if (z_context->current_cycle < z_context->sync_cycle) { | |
182 if (need_reset) { | |
183 z80_reset(z_context); | |
184 need_reset = 0; | |
185 } | |
186 | |
187 while (z_context->current_cycle < z_context->sync_cycle) { | |
188 if (z_context->int_pulse_end < z_context->current_cycle || z_context->int_pulse_end == CYCLE_NEVER) { | |
189 z_context->int_pulse_start = vdp_next_vint_z80(gen->vdp); | |
190 z_context->int_pulse_end = z_context->int_pulse_start + Z80_VINT_DURATION; | |
191 } | |
192 if (z_context->iff1) { | |
193 z_context->int_cycle = z_context->int_pulse_start < z_context->int_enable_cycle ? z_context->int_enable_cycle : z_context->int_pulse_start; | |
194 } else { | |
195 z_context->int_cycle = CYCLE_NEVER; | |
196 } | |
197 z_context->target_cycle = z_context->sync_cycle < z_context->int_cycle ? z_context->sync_cycle : z_context->int_cycle; | |
198 dprintf("Running Z80 from cycle %d to cycle %d. Int cycle: %d\n", z_context->current_cycle, z_context->sync_cycle, z_context->int_cycle); | |
199 z_context->run(z_context); | |
200 dprintf("Z80 ran to cycle %d\n", z_context->current_cycle); | |
201 } | |
202 } | |
203 } else | 181 } else |
204 #endif | 182 #endif |
205 { | 183 { |
206 z_context->current_cycle = mclks; | 184 z_context->current_cycle = mclks; |
207 } | 185 } |
254 mclks -= mclk_target; | 232 mclks -= mclk_target; |
255 vdp_adjust_cycles(v_context, mclk_target); | 233 vdp_adjust_cycles(v_context, mclk_target); |
256 io_adjust_cycles(gen->ports, context->current_cycle, mclk_target); | 234 io_adjust_cycles(gen->ports, context->current_cycle, mclk_target); |
257 io_adjust_cycles(gen->ports+1, context->current_cycle, mclk_target); | 235 io_adjust_cycles(gen->ports+1, context->current_cycle, mclk_target); |
258 io_adjust_cycles(gen->ports+2, context->current_cycle, mclk_target); | 236 io_adjust_cycles(gen->ports+2, context->current_cycle, mclk_target); |
259 if (busack_cycle != CYCLE_NEVER) { | |
260 if (busack_cycle > mclk_target) { | |
261 busack_cycle -= mclk_target; | |
262 } else { | |
263 busack_cycle = CYCLE_NEVER; | |
264 busack = new_busack; | |
265 } | |
266 } | |
267 context->current_cycle -= mclk_target; | 237 context->current_cycle -= mclk_target; |
268 if (z_context->current_cycle >= mclk_target) { | 238 z80_adjust_cycles(z_context, mclk_target); |
269 z_context->current_cycle -= mclk_target; | |
270 } else { | |
271 z_context->current_cycle = 0; | |
272 } | |
273 if (z_context->int_cycle != CYCLE_NEVER) { | |
274 if (z_context->int_cycle >= mclk_target) { | |
275 z_context->int_cycle -= mclk_target; | |
276 } else { | |
277 z_context->int_cycle = 0; | |
278 } | |
279 } | |
280 if (z_context->int_pulse_start != CYCLE_NEVER) { | |
281 if (z_context->int_pulse_end >= mclk_target) { | |
282 z_context->int_pulse_end -= mclk_target; | |
283 if (z_context->int_pulse_start >= mclk_target) { | |
284 z_context->int_pulse_start -= mclk_target; | |
285 } else { | |
286 z_context->int_pulse_start = 0; | |
287 } | |
288 } | |
289 } else { | |
290 z_context->int_pulse_start = CYCLE_NEVER; | |
291 z_context->int_pulse_end = CYCLE_NEVER; | |
292 } | |
293 if (z_context->int_enable_cycle >= mclk_target) { | |
294 z_context->int_enable_cycle -= mclk_target; | |
295 } else { | |
296 z_context->int_enable_cycle = 0; | |
297 } | |
298 if (mclks) { | 239 if (mclks) { |
299 vdp_run_context(v_context, mclks); | 240 vdp_run_context(v_context, mclks); |
300 } | 241 } |
301 mclk_target = vdp_cycles_to_frame_end(v_context); | 242 mclk_target = vdp_cycles_to_frame_end(v_context); |
302 context->sync_cycle = mclk_target; | 243 context->sync_cycle = mclk_target; |
456 value = vdp_control_port_read(v_context); | 397 value = vdp_control_port_read(v_context); |
457 } else { | 398 } else { |
458 value = vdp_hv_counter_read(v_context); | 399 value = vdp_hv_counter_read(v_context); |
459 //printf("HV Counter: %X at cycle %d\n", value, v_context->cycles); | 400 //printf("HV Counter: %X at cycle %d\n", value, v_context->cycles); |
460 } | 401 } |
461 } else if (vdp_port < 0x18){ | 402 } else if (vdp_port < 0x18) { |
462 printf("Illegal read from PSG port %X\n", vdp_port); | 403 printf("Illegal read from PSG port %X\n", vdp_port); |
463 exit(1); | 404 exit(1); |
464 } else { | 405 } else { |
465 value = vdp_test_port_read(v_context); | 406 value = vdp_test_port_read(v_context); |
466 } | 407 } |
518 | 459 |
519 m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value) | 460 m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value) |
520 { | 461 { |
521 genesis_context * gen = context->system; | 462 genesis_context * gen = context->system; |
522 if (location < 0x10000) { | 463 if (location < 0x10000) { |
523 if (busack_cycle <= context->current_cycle) { | 464 if (!z80_enabled || z80_get_busack(gen->z80, context->current_cycle)) { |
524 busack = new_busack; | |
525 busack_cycle = CYCLE_NEVER; | |
526 } | |
527 if (!(busack || reset)) { | |
528 location &= 0x7FFF; | 465 location &= 0x7FFF; |
529 if (location < 0x4000) { | 466 if (location < 0x4000) { |
530 z80_ram[location & 0x1FFF] = value; | 467 z80_ram[location & 0x1FFF] = value; |
531 #ifndef NO_Z80 | 468 #ifndef NO_Z80 |
532 z80_handle_code_write(location & 0x1FFF, gen->z80); | 469 z80_handle_code_write(location & 0x1FFF, gen->z80); |
576 gen->ports[2].control = value; | 513 gen->ports[2].control = value; |
577 break; | 514 break; |
578 } | 515 } |
579 } else { | 516 } else { |
580 if (location == 0x1100) { | 517 if (location == 0x1100) { |
581 if (busack_cycle <= context->current_cycle) { | |
582 busack = new_busack; | |
583 busack_cycle = CYCLE_NEVER; | |
584 } | |
585 if (value & 1) { | 518 if (value & 1) { |
586 dputs("bus requesting Z80"); | 519 dputs("bus requesting Z80"); |
587 | 520 if (z80_enabled) { |
588 if(!reset && !busreq) { | 521 z80_assert_busreq(gen->z80, context->current_cycle); |
589 sync_z80(gen->z80, context->current_cycle + Z80_ACK_DELAY*MCLKS_PER_Z80); | |
590 busack_cycle = gen->z80->current_cycle;//context->current_cycle + Z80_ACK_DELAY; | |
591 new_busack = Z80_REQ_ACK; | |
592 } | 522 } |
593 busreq = 1; | |
594 } else { | 523 } else { |
595 sync_z80(gen->z80, context->current_cycle); | 524 if (gen->z80->busreq) { |
596 if (busreq) { | |
597 dputs("releasing z80 bus"); | 525 dputs("releasing z80 bus"); |
598 #ifdef DO_DEBUG_PRINT | 526 #ifdef DO_DEBUG_PRINT |
599 char fname[20]; | 527 char fname[20]; |
600 sprintf(fname, "zram-%d", zram_counter++); | 528 sprintf(fname, "zram-%d", zram_counter++); |
601 FILE * f = fopen(fname, "wb"); | 529 FILE * f = fopen(fname, "wb"); |
602 fwrite(z80_ram, 1, sizeof(z80_ram), f); | 530 fwrite(z80_ram, 1, sizeof(z80_ram), f); |
603 fclose(f); | 531 fclose(f); |
604 #endif | 532 #endif |
605 busack_cycle = gen->z80->current_cycle + Z80_BUSY_DELAY; | |
606 new_busack = Z80_REQ_BUSY; | |
607 busreq = 0; | |
608 } | 533 } |
609 //busack_cycle = CYCLE_NEVER; | 534 if (z80_enabled) { |
610 //busack = Z80_REQ_BUSY; | 535 z80_clear_busreq(gen->z80, context->current_cycle); |
611 | 536 } |
612 } | 537 } |
613 } else if (location == 0x1200) { | 538 } else if (location == 0x1200) { |
614 sync_z80(gen->z80, context->current_cycle); | 539 sync_z80(gen->z80, context->current_cycle); |
615 if (value & 1) { | 540 if (value & 1) { |
616 if (reset && busreq) { | 541 if (z80_enabled) { |
617 new_busack = 0; | 542 z80_clear_reset(gen->z80, context->current_cycle); |
618 busack_cycle = gen->z80->current_cycle + Z80_ACK_DELAY;//context->current_cycle + Z80_ACK_DELAY; | 543 } else { |
544 gen->z80->reset = 0; | |
619 } | 545 } |
620 //TODO: Deal with the scenario in which reset is not asserted long enough | 546 } else { |
621 if (reset) { | 547 if (z80_enabled) { |
622 need_reset = 1; | 548 z80_assert_reset(gen->z80, context->current_cycle); |
623 //TODO: Add necessary delay between release of reset and start of execution | 549 } else { |
624 gen->z80->current_cycle = context->current_cycle + 16 * MCLKS_PER_Z80; | 550 gen->z80->reset = 1; |
625 } | 551 } |
626 reset = 0; | |
627 } else { | |
628 reset = 1; | |
629 } | 552 } |
630 } | 553 } |
631 } | 554 } |
632 } | 555 } |
633 return context; | 556 return context; |
651 uint8_t io_read(uint32_t location, m68k_context * context) | 574 uint8_t io_read(uint32_t location, m68k_context * context) |
652 { | 575 { |
653 uint8_t value; | 576 uint8_t value; |
654 genesis_context *gen = context->system; | 577 genesis_context *gen = context->system; |
655 if (location < 0x10000) { | 578 if (location < 0x10000) { |
656 if (busack_cycle <= context->current_cycle) { | 579 if (!z80_enabled || z80_get_busack(gen->z80, context->current_cycle)) { |
657 busack = new_busack; | |
658 busack_cycle = CYCLE_NEVER; | |
659 } | |
660 if (!(busack==Z80_REQ_BUSY || reset)) { | |
661 location &= 0x7FFF; | 580 location &= 0x7FFF; |
662 if (location < 0x4000) { | 581 if (location < 0x4000) { |
663 value = z80_ram[location & 0x1FFF]; | 582 value = z80_ram[location & 0x1FFF]; |
664 } else if (location < 0x6000) { | 583 } else if (location < 0x6000) { |
665 sync_sound(gen, context->current_cycle); | 584 sync_sound(gen, context->current_cycle); |
700 default: | 619 default: |
701 value = 0xFF; | 620 value = 0xFF; |
702 } | 621 } |
703 } else { | 622 } else { |
704 if (location == 0x1100) { | 623 if (location == 0x1100) { |
705 if (busack_cycle <= context->current_cycle) { | 624 value = z80_enabled ? !z80_get_busack(gen->z80, context->current_cycle) : 0; |
706 busack = new_busack; | 625 dprintf("Byte read of BUSREQ returned %d @ %d (reset: %d)\n", value, context->current_cycle, gen->z80->reset); |
707 busack_cycle = CYCLE_NEVER; | |
708 } | |
709 value = Z80_RES_BUSACK || busack; | |
710 dprintf("Byte read of BUSREQ returned %d @ %d (reset: %d, busack: %d, busack_cycle %d)\n", value, context->current_cycle, reset, busack, busack_cycle); | |
711 } else if (location == 0x1200) { | 626 } else if (location == 0x1200) { |
712 value = !reset; | 627 value = !gen->z80->reset; |
713 } else { | 628 } else { |
714 value = 0xFF; | 629 value = 0xFF; |
715 printf("Byte read of unknown IO location: %X\n", location); | 630 printf("Byte read of unknown IO location: %X\n", location); |
716 } | 631 } |
717 } | 632 } |
1103 printf("Loaded %s\n", statefile); | 1018 printf("Loaded %s\n", statefile); |
1104 if (debugger) { | 1019 if (debugger) { |
1105 insert_breakpoint(&context, pc, debugger); | 1020 insert_breakpoint(&context, pc, debugger); |
1106 } | 1021 } |
1107 adjust_int_cycle(gen->m68k, gen->vdp); | 1022 adjust_int_cycle(gen->m68k, gen->vdp); |
1108 #ifndef NO_Z80 | |
1109 gen->z80->native_pc = z80_get_native_address_trans(gen->z80, gen->z80->pc); | |
1110 #endif | |
1111 start_68k_context(&context, pc); | 1023 start_68k_context(&context, pc); |
1112 } else { | 1024 } else { |
1113 if (debugger) { | 1025 if (debugger) { |
1114 insert_breakpoint(&context, address, debugger); | 1026 insert_breakpoint(&context, address, debugger); |
1115 } | 1027 } |
1362 z80_context z_context; | 1274 z80_context z_context; |
1363 #ifndef NO_Z80 | 1275 #ifndef NO_Z80 |
1364 z80_options z_opts; | 1276 z80_options z_opts; |
1365 init_z80_opts(&z_opts, z80_map, 5, MCLKS_PER_Z80); | 1277 init_z80_opts(&z_opts, z80_map, 5, MCLKS_PER_Z80); |
1366 init_z80_context(&z_context, &z_opts); | 1278 init_z80_context(&z_context, &z_opts); |
1279 z80_assert_reset(&z_context, 0); | |
1367 #endif | 1280 #endif |
1368 | 1281 |
1369 z_context.system = &gen; | 1282 z_context.system = &gen; |
1370 z_context.mem_pointers[0] = z80_ram; | 1283 z_context.mem_pointers[0] = z80_ram; |
1371 z_context.sync_cycle = z_context.target_cycle = mclk_target; | 1284 z_context.sync_cycle = z_context.target_cycle = mclk_target; |