diff lc8951.c @ 2066:a61a8a87410c segacd

Fix a bunch of CDC/CDD related mcd-verificator failures
author Michael Pavone <pavone@retrodev.com>
date Sun, 30 Jan 2022 00:21:58 -0800
parents 02a9846668d1
children f22e04b69272
line wrap: on
line diff
--- a/lc8951.c	Sat Jan 29 17:43:37 2022 -0800
+++ b/lc8951.c	Sun Jan 30 00:21:58 2022 -0800
@@ -60,6 +60,8 @@
 //STAT3
 #define BIT_VALST 0x80
 
+#define DECI_AUTO_CLEAR 575
+
 //datasheet timing info
 //3 cycles for memory operation
 //6 cycles min for DMA-mode host transfer
@@ -75,11 +77,11 @@
 	context->handler_data = handler_data;
 	context->decode_end = CYCLE_NEVER;
 	context->transfer_end = CYCLE_NEVER;
+	context->deci_clear = CYCLE_NEVER;
 }
 
 void lc8951_reg_write(lc8951 *context, uint8_t value)
 {
-	printf("CDC write %X: %X\n", context->ar, value);
 	switch (context->ar)
 	{
 	case SBOUT:
@@ -94,7 +96,7 @@
 			context->regs[IFSTAT] |= BIT_STBSY;
 		}
 		if (!(value & BIT_DOUTEN)) {
-			context->regs[IFSTAT] |= BIT_DTBSY;
+			context->regs[IFSTAT] |= BIT_DTBSY|BIT_DTEI;
 			context->transfer_end = CYCLE_NEVER;
 		}
 		break;
@@ -173,6 +175,7 @@
 	}
 	if (context->ar == STAT3) {
 		context->regs[IFSTAT] |= BIT_DECI;
+		context->deci_clear = CYCLE_NEVER;
 	}
 	if (context->ar >= sizeof(context->regs)) {
 		value = 0xFF;
@@ -203,6 +206,7 @@
 		if (context->cycle >= context->decode_end) {
 			context->decode_end = CYCLE_NEVER;
 			context->regs[IFSTAT] &= ~BIT_DECI;
+			context->deci_clear = context->cycle + DECI_AUTO_CLEAR;
 			context->regs[STAT3] &= ~BIT_VALST;
 			uint16_t block_start = (context->regs[PTL] | (context->regs[PTH] << 8)) & (sizeof(context->buffer)-1);
 			for (int reg = HEAD0; reg < PTL; reg++)
@@ -233,16 +237,28 @@
 				context->transfer_end = CYCLE_NEVER;
 			}
 		}
+		if (context->cycle >= context->deci_clear) {
+			context->regs[IFSTAT] |= BIT_DECI;
+			context->deci_clear = CYCLE_NEVER;
+		}
 	}
 }
 
-void lc8951_resume_transfer(lc8951 *context)
+void lc8951_resume_transfer(lc8951 *context, uint32_t cycle)
 {
 	if (context->transfer_end == CYCLE_NEVER && (context->ifctrl & BIT_DOUTEN)) {
 		uint16_t transfer_size = context->regs[DBCL] | (context->regs[DBCH] << 8);
-		if (transfer_size) {
+		if (transfer_size != 0xFFFF) {
+			//HACK!!! Work around Sub CPU running longer than we would like and dragging other components with it
+			uint32_t step_diff = (context->cycle - cycle) / context->clock_step;
+			if (step_diff) {
+				context->cycle -= step_diff * context->clock_step;
+			}
 			context->transfer_end = context->cycle + transfer_size * context->clock_step;
 			printf("RESUME: size %u, cycle %u, end %u\n", transfer_size, context->cycle, context->transfer_end);
+			if (step_diff) {
+				lc8951_run(context, cycle);
+			}
 		}
 	}
 }
@@ -297,3 +313,16 @@
 	}
 	return deci_cycle < dtei_cycle ? deci_cycle : dtei_cycle;
 }
+
+void lc8951_adjust_cycles(lc8951 *context, uint32_t deduction)
+{
+	if (context->decode_end != CYCLE_NEVER) {
+		context->decode_end -= deduction;
+	}
+	if (context->transfer_end != CYCLE_NEVER) {
+		context->transfer_end -= deduction;
+	}
+	if (context->deci_clear != CYCLE_NEVER) {
+		context->transfer_end -= deduction;
+	}
+}