changeset 149:139e5dcd6aa3

Make writes to control and data port block when DMA is in progress
author Mike Pavone <pavone@retrodev.com>
date Tue, 01 Jan 2013 07:06:57 -0800
parents 4a400aec81bb
children 3e68e517cc01
files blastem.c runtime.S vdp.c vdp.h
diffstat 4 files changed, 41 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/blastem.c	Tue Jan 01 07:04:48 2013 -0800
+++ b/blastem.c	Tue Jan 01 07:06:57 2013 -0800
@@ -115,11 +115,9 @@
 	sync_components(context);
 	vdp_context * v_context = context->next_context;
 	if (vdp_port < 0x10) {
+		int blocked;
 		if (vdp_port < 4) {
-			vdp_data_port_write(v_context, value);
-		} else if(vdp_port < 8) {
-			int blocked = vdp_control_port_write(v_context, value);
-			if (blocked) {
+			while (vdp_data_port_write(v_context, value) < 0) {
 				while(v_context->flags & FLAG_DMA_RUN) {
 					vdp_run_dma_done(v_context, MCLKS_PER_FRAME);
 					if (v_context->cycles >= MCLKS_PER_FRAME) {
@@ -130,6 +128,27 @@
 					}
 				}
 				context->current_cycle = v_context->cycles / MCLKS_PER_68K;
+			}
+		} else if(vdp_port < 8) {
+			blocked = vdp_control_port_write(v_context, value);
+			if (blocked) {
+				while (blocked) {
+					while(v_context->flags & FLAG_DMA_RUN) {
+						vdp_run_dma_done(v_context, MCLKS_PER_FRAME);
+						if (v_context->cycles >= MCLKS_PER_FRAME) {
+							wait_render_frame(v_context);
+							vdp_adjust_cycles(v_context, MCLKS_PER_FRAME);
+							io_adjust_cycles(&gamepad_1, v_context->cycles/MCLKS_PER_68K, MCLKS_PER_FRAME/MCLKS_PER_68K);
+							io_adjust_cycles(&gamepad_2, v_context->cycles/MCLKS_PER_68K, MCLKS_PER_FRAME/MCLKS_PER_68K);
+						}
+					}
+					if (blocked < 0) {
+						blocked = vdp_control_port_write(v_context, value);
+					} else {
+						blocked = 0;
+					}
+				}
+				context->current_cycle = v_context->cycles / MCLKS_PER_68K;
 			} else {
 				if (v_context->regs[REG_MODE_2] & 0x20 && ((context->status & 0x7) < 6)) {
 					if (context->int_cycle > VINT_CYCLE) {
--- a/runtime.S	Tue Jan 01 07:04:48 2013 -0800
+++ b/runtime.S	Tue Jan 01 07:06:57 2013 -0800
@@ -209,6 +209,9 @@
 	push %rbx
 	/* fetch VDP context pointer from 68K context */
 	mov 128(%rsi), %rdx
+	/* check DMA flag */
+	bt $6, 19(%rdx)
+	jc fifo_fallback
 	/* get fifo_cur and compare it to fifo_end */
 	mov (%rdx), %rbx
 	cmp %rbx, 8(%rdx)
--- a/vdp.c	Tue Jan 01 07:04:48 2013 -0800
+++ b/vdp.c	Tue Jan 01 07:06:57 2013 -0800
@@ -184,7 +184,7 @@
 	//TODO: Figure out what happens if CD bit 4 is not set in DMA copy mode
 	//TODO: Figure out what happens when CD:0-3 is not set to a write mode in DMA operations
 	//TODO: Figure out what happens if DMA gets disabled part way through a DMA fill or DMA copy
-	if((context->regs[REG_MODE_2] & BIT_DMA_ENABLE) && (context->flags & FLAG_DMA_RUN)) {
+	if(context->flags & FLAG_DMA_RUN) {
 		uint16_t dma_len;
 		switch(context->regs[REG_DMASRC_H] & 0xC0)
 		{
@@ -1022,6 +1022,9 @@
 int vdp_control_port_write(vdp_context * context, uint16_t value)
 {
 	//printf("control port write: %X\n", value);
+	if (context->flags & FLAG_DMA_RUN) {
+		return -1;
+	}
 	if (context->flags & FLAG_PENDING) {
 		context->address = (context->address & 0x3FFF) | (value << 14);
 		context->cd = (context->cd & 0x3) | ((value >> 2) & 0x3C);
@@ -1057,9 +1060,16 @@
 	return 0;
 }
 
-void vdp_data_port_write(vdp_context * context, uint16_t value)
+int vdp_data_port_write(vdp_context * context, uint16_t value)
 {
 	//printf("data port write: %X\n", value);
+	if (context->flags & FLAG_DMA_RUN) {
+		return -1;
+	}
+	if (!(context->cd & 1)) {
+		//ignore writes when cd is configured for read
+		return 0;
+	}
 	context->flags &= ~FLAG_PENDING;
 	/*if (context->fifo_cur == context->fifo_end) {
 		printf("FIFO full, waiting for space before next write at cycle %X\n", context->cycles);
@@ -1074,6 +1084,7 @@
 	context->fifo_cur->partial = 0;
 	context->fifo_cur++;
 	context->address += context->regs[REG_AUTOINC];
+	return 0;
 }
 
 uint16_t vdp_control_port_read(vdp_context * context)
@@ -1086,7 +1097,7 @@
 	if (context->fifo_cur == context->fifo_end) {
 		value |= 0x100;
 	}
-	if ((context->regs[REG_MODE_2] & BIT_DMA_ENABLE) && (context->flags & FLAG_DMA_RUN)) {
+	if (context->flags & FLAG_DMA_RUN) {
 		value |= 0x2;
 	}
 	uint32_t line= context->cycles / MCLKS_LINE;
--- a/vdp.h	Tue Jan 01 07:04:48 2013 -0800
+++ b/vdp.h	Tue Jan 01 07:06:57 2013 -0800
@@ -126,7 +126,7 @@
 void vdp_load_savestate(vdp_context * context, FILE * state_file);
 void vdp_save_state(vdp_context * context, FILE * outfile);
 int vdp_control_port_write(vdp_context * context, uint16_t value);
-void vdp_data_port_write(vdp_context * context, uint16_t value);
+int vdp_data_port_write(vdp_context * context, uint16_t value);
 uint16_t vdp_control_port_read(vdp_context * context);
 uint16_t vdp_data_port_read(vdp_context * context);
 uint16_t vdp_hv_counter_read(vdp_context * context);