diff segacd.c @ 2116:cd057d6fe030

Initial stab at subcode emulation
author Michael Pavone <pavone@retrodev.com>
date Sun, 06 Mar 2022 22:03:52 -0800
parents 4be496489eda
children 5ec2f97365a2
line wrap: on
line diff
--- a/segacd.c	Sat Mar 05 14:17:59 2022 -0800
+++ b/segacd.c	Sun Mar 06 22:03:52 2022 -0800
@@ -55,6 +55,8 @@
 	GA_FONT_DATA1,
 	GA_FONT_DATA2,
 	GA_FONT_DATA3,
+	GA_SUBCODE_START = 0x80,
+	GA_SUBCODE_MIRROR = 0xC0,
 
 	GA_HINT_VECTOR = GA_CDC_REG_DATA
 };
@@ -387,48 +389,57 @@
 	context->int_cycle = CYCLE_NEVER;
 	uint8_t mask = context->status & 0x7;
 	uint32_t cdc_cycle = CYCLE_NEVER;
-	if (mask < 5) {
-		if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN5) {
-			cdc_cycle = lc8951_next_interrupt(&cd->cdc);
-			//CDC interrupts only generated on falling edge of !INT signal
-			if (cd->cdc_int_ack) {
-				if (cdc_cycle > cd->cdc.cycle) {
-					cd->cdc_int_ack = 0;
-				} else {
-					cdc_cycle = CYCLE_NEVER;
-				}
-			}
-			if (cdc_cycle < context->int_cycle) {
-				context->int_cycle = cdc_cycle;
-				context->int_num = 5;
+	if (mask < 6) {
+		if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN6) {
+			uint32_t subcode_cycle = cd->cdd.subcode_int_pending ? context->current_cycle : cd->cdd.next_subcode_int_cycle;
+			if (subcode_cycle != CYCLE_NEVER) {
+				context->int_cycle = subcode_cycle;
+				context->int_num = 6;
 			}
 		}
-		if (mask < 4) {
-			if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN4) {
-				uint32_t cdd_cycle = cd->cdd.int_pending ? context->current_cycle : cd->cdd.next_int_cycle;
-				if (cdd_cycle < context->int_cycle) {
-					context->int_cycle = cdd_cycle;
-					context->int_num = 4;
+		if (mask < 5) {
+			if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN5) {
+				cdc_cycle = lc8951_next_interrupt(&cd->cdc);
+				//CDC interrupts only generated on falling edge of !INT signal
+				if (cd->cdc_int_ack) {
+					if (cdc_cycle > cd->cdc.cycle) {
+						cd->cdc_int_ack = 0;
+					} else {
+						cdc_cycle = CYCLE_NEVER;
+					}
+				}
+				if (cdc_cycle < context->int_cycle) {
+					context->int_cycle = cdc_cycle;
+					context->int_num = 5;
 				}
 			}
-			if (mask < 3) {
-				uint32_t next_timer;
-				if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN3) {
-					uint32_t next_timer_cycle = next_timer_int(cd);
-					if (next_timer_cycle < context->int_cycle) {
-						context->int_cycle = next_timer_cycle;
-						context->int_num = 3;
+			if (mask < 4) {
+				if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN4) {
+					uint32_t cdd_cycle = cd->cdd.int_pending ? context->current_cycle : cd->cdd.next_int_cycle;
+					if (cdd_cycle < context->int_cycle) {
+						context->int_cycle = cdd_cycle;
+						context->int_num = 4;
 					}
 				}
-				if (mask < 2) {
-					if (cd->int2_cycle < context->int_cycle && (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN2)) {
-						context->int_cycle = cd->int2_cycle;
-						context->int_num = 2;
+				if (mask < 3) {
+					uint32_t next_timer;
+					if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN3) {
+						uint32_t next_timer_cycle = next_timer_int(cd);
+						if (next_timer_cycle < context->int_cycle) {
+							context->int_cycle = next_timer_cycle;
+							context->int_num = 3;
+						}
 					}
-					if (mask < 1) {
-						if (cd->graphics_int_cycle < context->int_cycle && (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN1)) {
-							context->int_cycle = cd->graphics_int_cycle;
-							context->int_num = 1;
+					if (mask < 2) {
+						if (cd->int2_cycle < context->int_cycle && (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN2)) {
+							context->int_cycle = cd->int2_cycle;
+							context->int_num = 2;
+						}
+						if (mask < 1) {
+							if (cd->graphics_int_cycle < context->int_cycle && (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN1)) {
+								context->int_cycle = cd->graphics_int_cycle;
+								context->int_num = 1;
+							}
 						}
 					}
 				}
@@ -521,6 +532,7 @@
 			value |= pixel << (i * 4);
 		}
 		return value;
+	}
 	case GA_STAMP_SIZE:
 	case GA_IMAGE_BUFFER_LINES:
 		//these two have bits that change based on graphics operations
@@ -529,8 +541,10 @@
 	case GA_TRACE_VECTOR_BASE:
 		//write only
 		return 0xFFFF;
-	}
 	default:
+		if (reg >= GA_SUBCODE_MIRROR) {
+			return cd->gate_array[GA_SUBCODE_START + (reg & 0x3F)];
+		}
 		return cd->gate_array[reg];
 	}
 }
@@ -655,6 +669,10 @@
 		calculate_target_cycle(m68k);
 		break;
 	case GA_INT_MASK:
+		if (!(cd->gate_array[reg] & BIT_MASK_IEN6)) {
+			//subcode interrupts can't be made pending when they are disabled in this reg
+			cd->cdd.subcode_int_pending = 0;
+		}
 		cd->gate_array[reg] = value & (BIT_MASK_IEN6|BIT_MASK_IEN5|BIT_MASK_IEN4|BIT_MASK_IEN3|BIT_MASK_IEN2|BIT_MASK_IEN1);
 		calculate_target_cycle(m68k);
 		break;
@@ -903,6 +921,9 @@
 	case 5:
 		cd->cdc_int_ack = 1;
 		break;
+	case 6:
+		cd->cdd.subcode_int_pending = 0;
+		break;
 	}
 	context->int_ack = 0;
 	calculate_target_cycle(context);