diff segacd.c @ 2061:7c1760b5b3e5 segacd

Implemented basic TOC functionality of CDD MCU
author Michael Pavone <pavone@retrodev.com>
date Thu, 27 Jan 2022 00:33:41 -0800
parents 70260f6051dd
children 07ed42bd7b4c
line wrap: on
line diff
--- a/segacd.c	Sun Jan 23 11:11:07 2022 -0800
+++ b/segacd.c	Thu Jan 27 00:33:41 2022 -0800
@@ -81,6 +81,9 @@
 #define BIT_MASK_IEN5  0x0020
 #define BIT_MASK_IEN6  0x0040
 
+//GA_CDD_CTRL
+#define BIT_HOCK       0x0004
+
 static void *prog_ram_wp_write16(uint32_t address, void *vcontext, uint16_t value)
 {
 	m68k_context *m68k = vcontext;
@@ -308,19 +311,28 @@
 	segacd_context *cd = context->system;
 	context->int_cycle = CYCLE_NEVER;
 	uint8_t mask = context->status & 0x7;
-	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 < 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;
+				}
 			}
 		}
 	}
@@ -363,6 +375,14 @@
 	case GA_TIMER:
 		timers_run(cd, m68k->current_cycle);
 		return cd->gate_array[reg];
+	case GA_CDD_STATUS0:
+	case GA_CDD_STATUS1:
+	case GA_CDD_STATUS2:
+	case GA_CDD_STATUS3:
+	case GA_CDD_STATUS4:
+		cdd_mcu_run(&cd->cdd, m68k->current_cycle, cd->gate_array + GA_CDD_CTRL);
+		return cd->gate_array[reg];
+		break;
 	case GA_FONT_DATA0:
 	case GA_FONT_DATA1:
 	case GA_FONT_DATA2:
@@ -499,6 +519,33 @@
 		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;
+	case GA_CDD_CTRL: {
+		cdd_mcu_run(&cd->cdd, m68k->current_cycle, cd->gate_array + GA_CDD_CTRL);
+		uint16_t changed = cd->gate_array[reg] ^ value;
+		cd->gate_array[reg] &= ~BIT_HOCK;
+		cd->gate_array[reg] |= value & BIT_HOCK;
+		if (changed & BIT_HOCK) {
+			if (value & BIT_HOCK) {
+				cdd_hock_enabled(&cd->cdd);
+			} else {
+				cdd_hock_disabled(&cd->cdd);
+			}
+			calculate_target_cycle(m68k);
+		}
+		break;
+	}
+	case GA_CDD_CMD0:
+	case GA_CDD_CMD1:
+	case GA_CDD_CMD2:
+	case GA_CDD_CMD3:
+		cdd_mcu_run(&cd->cdd, m68k->current_cycle, cd->gate_array + GA_CDD_CTRL);
+		cd->gate_array[reg] = value & 0x0F0F;
+		break;
+	case GA_CDD_CMD4:
+		cdd_mcu_run(&cd->cdd, m68k->current_cycle, cd->gate_array + GA_CDD_CTRL);
+		cd->gate_array[reg] = value & 0x0F0F;
+		cdd_mcu_start_cmd_recv(&cd->cdd, cd->gate_array + GA_CDD_CTRL);
+		break;
 	case GA_FONT_COLOR:
 		cd->gate_array[reg] = value & 0xFF;
 		break;
@@ -536,6 +583,15 @@
 			cd->gate_array[reg] = value << 8;
 		}
 		return vcontext;
+	case GA_CDD_CMD4:
+		if (!address) {
+			//byte write to $FF804A should not trigger transfer
+			cdd_mcu_run(&cd->cdd, m68k->current_cycle, cd->gate_array + GA_CDD_CTRL);
+			cd->gate_array[reg] &= 0x0F;
+			cd->gate_array[reg] |= (value << 8 & 0x0F00);
+			return vcontext;
+		}
+		//intentional fallthrough for $FF804B
 	default:
 		if (address & 1) {
 			value16 = cd->gate_array[reg] & 0xFF00 | value;
@@ -555,6 +611,7 @@
 static void scd_peripherals_run(segacd_context *cd, uint32_t cycle)
 {
 	timers_run(cd, cycle);
+	cdd_mcu_run(&cd->cdd, cycle, cd->gate_array + GA_CDD_CTRL);
 }
 
 static m68k_context *sync_components(m68k_context * context, uint32_t address)
@@ -569,6 +626,8 @@
 	case 3:
 		cd->timer_pending = 0;
 		break;
+	case 4:
+		cd->cdd.int_pending = 0;
 	}
 	context->int_ack = 0;
 	calculate_target_cycle(context);
@@ -613,6 +672,7 @@
 	} else if (cd->periph_reset_cycle != CYCLE_NEVER) {
 		cd->periph_reset_cycle -= deduction;
 	}
+	cdd_mcu_adjust_cycle(&cd->cdd, deduction);
 }
 
 static uint16_t main_gate_read16(uint32_t address, void *vcontext)
@@ -849,6 +909,10 @@
 	cd->gate_array[1] = 1;
 	cd->gate_array[0x1B] = 0x100;
 	lc8951_init(&cd->cdc);
+	if (media->chain && media->type != MEDIA_CDROM) {
+		media = media->chain;
+	}
+	cdd_mcu_init(&cd->cdd, media);
 
 	return cd;
 }