diff vdp.c @ 317:e5e8b48ad157

Initial stab at horizontal interrupts and improving accuracy of vertical interrupts. Also added the VINT pending flag to status port.
author Mike Pavone <pavone@retrodev.com>
date Fri, 10 May 2013 22:57:56 -0700
parents eea3b118940d
children 789f2f5f2277
line wrap: on
line diff
--- a/vdp.c	Thu May 09 20:59:49 2013 -0700
+++ b/vdp.c	Fri May 10 22:57:56 2013 -0700
@@ -1028,18 +1028,34 @@
 		if (!line) {
 			latch_mode(context);
 		}
+		uint32_t linecyc = context->cycles % MCLKS_LINE;
+		if (linecyc == 0) {
+			if (line <= 1 || line >= active_lines) {
+				context->hint_counter = context->regs[REG_HINT];
+			} else if (context->hint_counter) {
+				context->hint_counter--;
+			} else {
+				context->flags2 |= FLAG2_HINT_PENDING;
+				context->hint_counter = context->regs[REG_HINT];
+			}
+		} else if(line == active_lines) {
+			uint32_t intcyc = context->latched_mode & BIT_H40 ? (148 + 40) * 4 :  (132 + 28) * 5;;
+			if (linecyc == intcyc) {
+				context->flags2 |= FLAG2_VINT_PENDING;
+			}
+		}
 		if (line < active_lines && context->regs[REG_MODE_2] & DISPLAY_ENABLE) {
 			//first sort-of active line is treated as 255 internally
 			//it's used for gathering sprite info for line 
 			line = (line - 1) & 0xFF;
-			uint32_t linecyc = context->cycles % MCLKS_LINE;
 			
 			//Convert to slot number
 			if (context->latched_mode & BIT_H40){
 				//TODO: Deal with nasty clock switching during HBLANK
+				uint32_t clock_inc = MCLKS_LINE-linecyc < 16 ? MCLKS_LINE-linecyc : 16;
 				linecyc = linecyc/16;
 				vdp_h40(line, linecyc, context);
-				context->cycles += 16;
+				context->cycles += clock_inc;
 			} else {
 				linecyc = linecyc/20;
 				vdp_h32(line, linecyc, context);
@@ -1053,8 +1069,9 @@
 				check_render_bg(context, line);
 			}
 			if (context->latched_mode & BIT_H40){
+				uint32_t clock_inc = MCLKS_LINE-linecyc < 16 ? MCLKS_LINE-linecyc : 16;
 				//TODO: Deal with nasty clock switching during HBLANK
-				context->cycles += 16;
+				context->cycles += clock_inc;
 			} else {
 				context->cycles += 20;
 			}
@@ -1173,6 +1190,9 @@
 	if (context->fifo_cur == context->fifo_end) {
 		value |= 0x100;
 	}
+	if (context->flags2 & FLAG2_VINT_PENDING) {
+		value |- 0x80;
+	}
 	if (context->flags & FLAG_DMA_RUN) {
 		value |= 0x2;
 	}
@@ -1180,6 +1200,9 @@
 	if (line >= (context->latched_mode & BIT_PAL ? PAL_ACTIVE : NTSC_ACTIVE)) {
 		value |= 0x8;
 	}
+	if (context->latched_mode & BIT_PAL) {//Not sure about this, need to verify
+		value |= 0x1;
+	}
 	//TODO: Lots of other bits in status port
 	return value;
 }
@@ -1268,6 +1291,57 @@
 	}
 }
 
+uint32_t vdp_next_hint(vdp_context * context)
+{
+	if (!(context->regs[REG_MODE_1] & 0x10)) {
+		return 0xFFFFFFFF;
+	}
+	if (context->flags2 & FLAG2_HINT_PENDING) {
+		return context->cycles;
+	}
+	uint32_t active_lines = context->latched_mode & BIT_PAL ? PAL_ACTIVE : NTSC_ACTIVE;
+	uint32_t line = context->cycles / MCLKS_LINE;
+	if (line >= active_lines) {
+		return 0xFFFFFFFF;
+	}
+	uint32_t linecyc = context->cycles % MCLKS_LINE;
+	uint32_t hcycle = context->cycles + context->hint_counter * MCLKS_LINE + MCLKS_LINE - linecyc;
+	if (!line) {
+		hcycle += MCLKS_LINE;
+	}
+	return hcycle;
+}
+
+uint32_t vdp_next_vint(vdp_context * context)
+{
+	if (!(context->regs[REG_MODE_2] & 0x20)) {
+		return 0xFFFFFFFF;
+	}
+	if (context->flags2 & FLAG2_VINT_PENDING) {
+		return context->cycles;
+	}
+	uint32_t active_lines = context->latched_mode & BIT_PAL ? PAL_ACTIVE : NTSC_ACTIVE;
+	uint32_t vcycle =  MCLKS_LINE * active_lines;
+	if (context->latched_mode & BIT_H40) {
+		vcycle += (148 + 40) * 4;
+	} else {
+		vcycle += (132 + 28) * 5;
+	}
+	if (vcycle < context->cycles) {
+		return 0xFFFFFFFF;
+	}
+	return vcycle;
+}
+
+void vdp_int_ack(vdp_context * context, uint16_t int_num)
+{
+	if (int_num == 6) {
+		context->flags2 &= ~FLAG2_VINT_PENDING;
+	} else if(int_num ==4) {
+		context->flags2 &= ~FLAG2_HINT_PENDING;
+	}
+}
+
 #define GST_VDP_REGS 0xFA
 #define GST_VDP_MEM 0x12478