changeset 2419:0871f555eff6

Fix some CD-ROM emulation issues and make timing better match my MCD2. Seems to fix or at least improve video playback in Iron Helix and Power Rangers
author Michael Pavone <pavone@retrodev.com>
date Thu, 18 Jan 2024 23:03:58 -0800
parents cc07f544c620
children 1fba97414ba6
files cdd_mcu.c lc8951.c
diffstat 2 files changed, 39 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/cdd_mcu.c	Wed Jan 17 23:51:37 2024 -0800
+++ b/cdd_mcu.c	Thu Jan 18 23:03:58 2024 -0800
@@ -11,7 +11,7 @@
 #define NIBBLE_CLOCKS (CDD_MCU_DIVIDER * 77)
 #define BYTE_CLOCKS (SECTOR_CLOCKS/2352) // 96
 #define SUBCODE_CLOCKS (SECTOR_CLOCKS/98)
-#define PROCESSING_DELAY 54000 //approximate, based on Wondermega M1 measurements
+#define PROCESSING_DELAY 121600 //approximate, based on relative level 4 and level 5 interrupt timing on MCD2 in pause_test
 
 //lead in start max diameter 46 mm
 //program area start max diameter 50 mm
@@ -179,7 +179,6 @@
 static void update_status(cdd_mcu *context, uint16_t *gate_array)
 {
 	gate_array[GAO_CDD_CTRL] |= BIT_MUTE;
-	uint32_t prev_pba = context->head_pba;
 	switch (context->status)
 	{
 	case DS_STOP:
@@ -255,16 +254,16 @@
 		switch (force_not_ready ? SF_NOTREADY : context->requested_format)
 		{
 		case SF_ABSOLUTE:
-			if (context->toc_valid && prev_pba >= LEADIN_SECTORS) {
-				lba_to_status(context, prev_pba - LEADIN_SECTORS);
+			if (context->toc_valid && context->head_pba >= LEADIN_SECTORS) {
+				lba_to_status(context, context->head_pba - LEADIN_SECTORS);
 				context->status_buffer.format = SF_ABSOLUTE;
 			} else {
 				context->status_buffer.format = SF_NOTREADY;
 			}
 			break;
 		case SF_RELATIVE:
-			if (context->toc_valid && prev_pba >= LEADIN_SECTORS) {
-				uint32_t lba =prev_pba - LEADIN_SECTORS;
+			if (context->toc_valid && context->head_pba >= LEADIN_SECTORS) {
+				uint32_t lba =context->head_pba - LEADIN_SECTORS;
 				for (uint32_t i = 0; i < context->media->num_tracks; i++)
 				{
 					if (lba < context->media->tracks[i].end_lba) {
@@ -295,8 +294,8 @@
 			}
 			break;
 		case SF_TRACK:
-			if (context->toc_valid && prev_pba >= LEADIN_SECTORS) {
-				uint32_t lba =prev_pba - LEADIN_SECTORS;
+			if (context->toc_valid && context->head_pba >= LEADIN_SECTORS) {
+				uint32_t lba =context->head_pba - LEADIN_SECTORS;
 				uint32_t i;
 				for (i = 0; i < context->media->num_tracks; i++)
 				{
@@ -373,7 +372,7 @@
 				}
 				lba_to_status(context, lba);
 				if (context->media->tracks[context->requested_track - 1].type == TRACK_DATA) {
-					context->status_buffer.b.tocn.frame_low |= 0x80;
+					context->status_buffer.b.tocn.frame_high |= 0x8;
 				}
 				context->status_buffer.b.tocn.track_low = context->requested_track % 10;
 				context->status_buffer.format = SF_TOCN;
@@ -663,10 +662,7 @@
 				context->next_subcode_int_cycle = CYCLE_NEVER;
 			}
 			if (old_coarse != context->coarse_seek) {
-				context->next_int_cycle = cd_block_to_mclks(context->cycle + PROCESSING_DELAY + 7 * NIBBLE_CLOCKS);
-				if (context->coarse_seek % 3) {
-					context->next_int_cycle += cd_block_to_mclks(SECTOR_CLOCKS * (3 - (context->coarse_seek % 3)));
-				}
+				context->next_int_cycle = cd_block_to_mclks(next_nibble + 7 * NIBBLE_CLOCKS);
 			}
 		}
 		if (context->cycle >= next_nibble) {
@@ -721,7 +717,16 @@
 			}
 		}
 		if (context->cycle >= context->next_byte_cycle) {
-			if (context->current_sector_byte >= 0 && (!fader->byte_counter || context->current_sector_byte)) {
+			if (context->current_sector_byte >= 0/* && (!fader->byte_counter || context->current_sector_byte)*/) {
+				if (!context->current_sector_byte) {
+					//HACK: things can get a little out of sync currently which causes a mess in the fader code
+					// since it expects even multiples of 4 bytes (1 stereo sample)
+					while (fader->byte_counter)
+					{
+						lc8951_write_byte(cdc, cd_block_to_mclks(context->cycle), 0, 0);
+						cdd_fader_data(fader, 0);
+					}
+				}
 				uint8_t byte = context->media->read(context->media, context->current_sector_byte);
 				if (context->status != DS_PLAY) {
 					byte = 0;
@@ -731,10 +736,6 @@
 			} else {
 				lc8951_write_byte(cdc, cd_block_to_mclks(context->cycle), 0, 0);
 				cdd_fader_data(fader, 0);
-				if (context->current_sector_byte >= 0) {
-					next_subcode += BYTE_CLOCKS;
-					context->last_sector_cycle += BYTE_CLOCKS;
-				}
 			}
 			if (context->current_sector_byte == 2352) {
 				context->current_sector_byte = -1;
--- a/lc8951.c	Wed Jan 17 23:51:37 2024 -0800
+++ b/lc8951.c	Thu Jan 18 23:03:58 2024 -0800
@@ -56,6 +56,7 @@
 
 //CTRL0
 #define BIT_DECEN  0x80
+#define BIT_EDCRQ  0x40
 #define BIT_WRRQ   0x04
 #define BIT_ORQ    0x02
 #define BIT_PRQ    0x01
@@ -240,11 +241,12 @@
 				uint16_t block_start = (context->regs[PTL] | (context->regs[PTH] << 8)) & (sizeof(context->buffer)-1);
 				for (int reg = HEAD0; reg < PTL; reg++)
 				{
+					printf("Setting header reg %X to %X: %X\n", reg, block_start, context->buffer[block_start]);
 					context->regs[reg] =context->buffer[block_start++];
 					block_start &= (sizeof(context->buffer)-1);
 				}
 			}
-			printf("Decode done %X:%X:%X mode %X\n", context->regs[HEAD0], context->regs[HEAD1], context->regs[HEAD2], context->regs[HEAD3]);
+			printf("Decode done %X:%X:%X mode %X @ %u\n", context->regs[HEAD0], context->regs[HEAD1], context->regs[HEAD2], context->regs[HEAD3], context->cycle);
 			// This check is a hack until I properly implement error detection
 			if (context->regs[HEAD0] < 0x74 && (context->regs[HEAD0] & 0xF) < 0xA
 				&& context->regs[HEAD1] < 0x60 && (context->regs[HEAD1] & 0xF) < 0xA
@@ -258,7 +260,7 @@
 				context->regs[STAT1] = 0;
 				context->regs[STAT2] = 0x10;
 			} else {
-				if (context->ctrl0 & (BIT_WRRQ|BIT_ORQ|BIT_PRQ)) {
+				if (context->ctrl0 & (BIT_EDCRQ|BIT_ORQ|BIT_PRQ)) {
 					context->regs[STAT0] |= BIT_UCEBLK;
 				}
 				context->regs[STAT1] = 0xFF;
@@ -341,7 +343,19 @@
 		if ((context->ctrl0 & (BIT_DECEN|BIT_WRRQ)) == (BIT_DECEN)) {
 			//monitor only mode
 			context->regs[HEAD0 + context->sector_counter] = byte;
+			if (context->sector_counter == 3) {
+				printf("Monitoring sector %02d:%02d:%02d\n", context->regs[HEAD0], context->regs[HEAD1], context->regs[HEAD2]);
+			}
+		} else {
+			if (context->sector_counter == 3) {
+				printf("Writing sector %02d:%02d:%02d @ %u\n",
+					context->buffer[(current_write_addr - 3) & (sizeof(context->buffer)-1)],
+					context->buffer[(current_write_addr - 2) & (sizeof(context->buffer)-1)],
+					context->buffer[(current_write_addr - 1) & (sizeof(context->buffer)-1)],
+					context->cycle);
+			}
 		}
+
 	}
 
 	if (sync_detected || sync_inserted) {
@@ -369,9 +383,10 @@
 				context->regs[PTL] = block_start;
 				context->regs[PTH] = block_start >> 8;
 			}
-			printf("Decoding block starting at %X (WRRQ: %d, sector_offset: %X)\n", context->regs[PTL] | (context->regs[PTH] << 8), !!(context->ctrl0 & BIT_WRRQ), sector_offset);
-			//Based on measurements of a Wondermega M1 (LC8951) with SYDEN, SYIEN and DECEN only
-			context->decode_end = context->cycle + 22030 * context->clock_step;
+			printf("Decoding block starting at %X (WRRQ: %d, sector_offset: %X), current write address: %X @ %u\n", context->regs[PTL] | (context->regs[PTH] << 8), !!(context->ctrl0 & BIT_WRRQ), sector_offset, current_write_addr, context->cycle);
+			//Based on mcd-verificator results on an MCD2 with LC89515
+			//value seems to be between ~132500 and ~133500
+			context->decode_end = context->cycle + 133000 * context->clock_step;
 		}
 	} else {
 		context->sector_counter++;