changeset 628:041578693329

Fix Z80 interrupts
author Michael Pavone <pavone@retrodev.com>
date Sat, 21 Jun 2014 09:36:15 -0700
parents c5820734a5b6
children 9089951a1994
files blastem.c z80_to_x86.c z80_to_x86.h
diffstat 3 files changed, 36 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/blastem.c	Fri Jun 20 07:57:32 2014 -0700
+++ b/blastem.c	Sat Jun 21 09:36:15 2014 -0700
@@ -190,10 +190,14 @@
 				z80_reset(z_context);
 				need_reset = 0;
 			}
-			uint32_t vint_cycle = vdp_next_vint_z80(gen->vdp) / MCLKS_PER_Z80;
+
 			while (z_context->current_cycle < z_context->sync_cycle) {
-				if (z_context->iff1 && z_context->int_cycle == CYCLE_NEVER && z_context->current_cycle < (vint_cycle + Z80_VINT_DURATION)) {
-					z_context->int_cycle = vint_cycle < z_context->int_enable_cycle ? z_context->int_enable_cycle : vint_cycle;
+				if (z_context->int_pulse_end < z_context->current_cycle || z_context->int_pulse_end == CYCLE_NEVER) {
+					z_context->int_pulse_start = vdp_next_vint_z80(gen->vdp) / MCLKS_PER_Z80;
+					z_context->int_pulse_end = z_context->int_pulse_start + Z80_VINT_DURATION;
+				}
+				if (z_context->iff1) {
+					z_context->int_cycle = z_context->int_pulse_start < z_context->int_enable_cycle ? z_context->int_enable_cycle : z_context->int_pulse_start;
 				}
 				z_context->target_cycle = z_context->sync_cycle < z_context->int_cycle ? z_context->sync_cycle : z_context->int_cycle;
 				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);
@@ -269,6 +273,31 @@
 		} else {
 			z_context->current_cycle = 0;
 		}
+		if (z_context->int_cycle != CYCLE_NEVER) {
+			if (z_context->int_cycle >= mclk_target/MCLKS_PER_Z80) {
+				z_context->int_cycle -= mclk_target/MCLKS_PER_Z80;
+			} else {
+				z_context->int_cycle = 0;
+			}
+		}
+		if (z_context->int_pulse_start != CYCLE_NEVER) {
+			if (z_context->int_pulse_end >= mclk_target/MCLKS_PER_Z80) {
+				z_context->int_pulse_end -= mclk_target/MCLKS_PER_Z80;
+				if (z_context->int_pulse_start >= mclk_target/MCLKS_PER_Z80) {
+					z_context->int_pulse_start -= mclk_target/MCLKS_PER_Z80;
+				} else {
+					z_context->int_pulse_start = 0;
+				}
+			}
+		} else {
+			z_context->int_pulse_start = CYCLE_NEVER;
+			z_context->int_pulse_end = CYCLE_NEVER;
+		}
+		if (z_context->int_enable_cycle >= mclk_target/MCLKS_PER_Z80) {
+			z_context->int_enable_cycle -= mclk_target/MCLKS_PER_Z80;
+		} else {
+			z_context->int_enable_cycle = 0;
+		}
 		if (mclks) {
 			vdp_run_context(v_context, mclks);
 		}
--- a/z80_to_x86.c	Fri Jun 20 07:57:32 2014 -0700
+++ b/z80_to_x86.c	Sat Jun 21 09:36:15 2014 -0700
@@ -2022,6 +2022,8 @@
 	memset(context->banked_code_map, 0, sizeof(native_map_slot));
 	context->options = options;
 	context->int_cycle = 0xFFFFFFFF;
+	context->int_pulse_start = 0xFFFFFFFF;
+	context->int_pulse_end = 0xFFFFFFFF;
 }
 
 void z80_reset(z80_context * context)
--- a/z80_to_x86.h	Fri Jun 20 07:57:32 2014 -0700
+++ b/z80_to_x86.h	Sat Jun 21 09:36:15 2014 -0700
@@ -56,6 +56,8 @@
 	uint8_t           ram_code_flags[(8 * 1024)/128/8];
 	uint32_t          int_enable_cycle;
 	uint16_t          pc;
+	uint32_t          int_pulse_start;
+	uint32_t          int_pulse_end;
 	uint8_t           breakpoint_flags[(16 * 1024)/sizeof(uint8_t)];
 	uint8_t *         bp_handler;
 	uint8_t *         bp_stub;