changeset 2223:1cccc57c069a

Admit defeat on VDP address latching theory and implement it the way GPGX does. Fixes regression in VDP FIFO Testing and SMS VDPTEST
author Michael Pavone <pavone@retrodev.com>
date Sun, 04 Sep 2022 23:29:37 -0700
parents bb1bcdb027e0
children d8b0244101c4
files vdp.c vdp.h
diffstat 2 files changed, 22 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/vdp.c	Sun Sep 04 14:26:12 2022 -0700
+++ b/vdp.c	Sun Sep 04 23:29:37 2022 -0700
@@ -1040,7 +1040,7 @@
 
 			context->flags |= FLAG_READ_FETCHED;
 		}
-	} else if (!(context->cd & 1) && !(context->flags & FLAG_READ_FETCHED)) {
+	} else if (!(context->cd & 1) && !(context->flags & (FLAG_READ_FETCHED|FLAG_PENDING))) {
 		switch(context->cd & 0xF)
 		{
 		case VRAM_READ:
@@ -3785,19 +3785,6 @@
 	return hv;
 }
 
-static void clear_pending(vdp_context *context)
-{
-	context->flags &= ~FLAG_PENDING;
-	context->address = context->address_latch;
-	//It seems like the DMA enable bit doesn't so much enable DMA so much
-	//as it enables changing CD5 from control port writes
-	if (context->regs[REG_MODE_2] & BIT_DMA_ENABLE) {
-		context->cd = context->cd_latch;
-	} else {
-		context->cd = (context->cd & 0x20) | (context->cd_latch & 0x1F);
-	}
-}
-
 int vdp_control_port_write(vdp_context * context, uint16_t value)
 {
 	//printf("control port write: %X at %d\n", value, context->cycles);
@@ -3805,9 +3792,16 @@
 		return -1;
 	}
 	if (context->flags & FLAG_PENDING) {
-		context->address_latch = (context->address_latch & 0x3FFF) | (value << 14 & 0x1C000);
-		context->cd_latch = (context->cd_latch & 0x3) | ((value >> 2) & ~0x3 & 0xFF);
-		clear_pending(context);
+		context->address_latch = value << 14 & 0x1C000;
+		context->address = (context->address & 0x3FFF) | context->address_latch;
+		//It seems like the DMA enable bit doesn't so much enable DMA so much
+		//as it enables changing CD5 from control port writes
+		if (context->regs[REG_MODE_2] & BIT_DMA_ENABLE) {
+			context->cd = (context->cd & 0x3) | ((value >> 2) & ~0x3 & 0xFF);
+		} else {
+			context->cd = (context->cd & 0x23) | ((value >> 2) & ~0x23 & 0xFF);
+		}
+		context->flags &= ~FLAG_PENDING;
 		//Should these be taken care of here or after the first write?
 		context->flags &= ~FLAG_READ_FETCHED;
 		context->flags2 &= ~FLAG2_READ_PENDING;
@@ -3836,15 +3830,11 @@
 		}
 	} else {
 		uint8_t mode_5 = context->regs[REG_MODE_2] & BIT_MODE_5;
-		context->address_latch = (context->address_latch & 0x1C000) | (value & 0x3FFF);
-		context->cd_latch = (context->cd_latch & 0x3C) | (value >> 14);
+		context->address = context->address_latch | (value & 0x3FFF);
+		context->cd = (context->cd & 0x3C) | (value >> 14);
 		if ((value & 0xC000) == 0x8000) {
 			//Register write
 			uint8_t reg = (value >> 8) & 0x1F;
-			// The fact that this is needed seems to pour some cold water on my theory
-			// about how the address latch actually works. Needs more search to definitively confirm
-			context->address = (context->address & 0x1C000) | (value & 0x3FFF);
-			context->cd = (context->cd & 0x3C) | (value >> 14);
 			if (reg < (mode_5 ? VDP_REGS : 0xB)) {
 				//printf("register %d set to %X\n", reg, value & 0xFF);
 				if (reg == REG_MODE_1 && (value & BIT_HVC_LATCH) && !(context->regs[reg] & BIT_HVC_LATCH)) {
@@ -3915,7 +3905,6 @@
 			//context->flags &= ~FLAG_READ_FETCHED;
 			//context->flags2 &= ~FLAG2_READ_PENDING;
 		} else {
-			clear_pending(context);
 			context->flags &= ~FLAG_READ_FETCHED;
 			context->flags2 &= ~FLAG2_READ_PENDING;
 		}
@@ -3946,7 +3935,7 @@
 		return -1;
 	}
 	if (context->flags & FLAG_PENDING) {
-		clear_pending(context);
+		context->flags &= ~FLAG_PENDING;
 		//Should these be cleared here?
 		context->flags &= ~FLAG_READ_FETCHED;
 		context->flags2 &= ~FLAG2_READ_PENDING;
@@ -3981,7 +3970,7 @@
 void vdp_data_port_write_pbc(vdp_context * context, uint8_t value)
 {
 	if (context->flags & FLAG_PENDING) {
-		clear_pending(context);
+		context->flags &= ~FLAG_PENDING;
 		//Should these be cleared here?
 		context->flags &= ~FLAG_READ_FETCHED;
 		context->flags2 &= ~FLAG2_READ_PENDING;
@@ -4020,9 +4009,7 @@
 
 uint16_t vdp_control_port_read(vdp_context * context)
 {
-	if (context->flags & FLAG_PENDING) {
-		clear_pending(context);
-	}
+	context->flags &= ~FLAG_PENDING;
 	context->flags2 &= ~FLAG2_BYTE_PENDING;
 	//Bits 15-10 are not fixed like Charles MacDonald's doc suggests, but instead open bus values that reflect 68K prefetch
 	uint16_t value = context->system->get_open_bus_value(context->system) & 0xFC00;
@@ -4072,7 +4059,7 @@
 uint16_t vdp_data_port_read(vdp_context * context)
 {
 	if (context->flags & FLAG_PENDING) {
-		clear_pending(context);
+		context->flags &= ~FLAG_PENDING;
 		//Should these be cleared here?
 		context->flags &= ~FLAG_READ_FETCHED;
 		context->flags2 &= ~FLAG2_READ_PENDING;
@@ -4103,10 +4090,7 @@
 
 uint8_t vdp_data_port_read_pbc(vdp_context * context)
 {
-	if (context->flags & FLAG_PENDING) {
-		clear_pending(context);
-	}
-	context->flags &= ~FLAG_READ_FETCHED;
+	context->flags &= ~(FLAG_PENDING | FLAG_READ_FETCHED);
 	context->flags2 &= ~FLAG2_BYTE_PENDING;
 
 	context->cd = VRAM_READ8;
@@ -4486,7 +4470,8 @@
 	save_int32(buf, context->pending_vint_start);
 	save_int32(buf, context->pending_hint_start);
 	save_int32(buf, context->address_latch);
-	save_int8(buf, context->cd_latch);
+	//was cd_latch, for compatibility with older builds that expect it
+	save_int8(buf, context->cd);
 }
 
 void vdp_deserialize(deserialize_buffer *buf, void *vcontext)
@@ -4623,10 +4608,10 @@
 	context->pending_hint_start = load_int32(buf);
 	if (version > 2) {
 		context->address_latch = load_int32(buf);
-		context->cd_latch = load_int8(buf);
+		//was cd_latch, no longer used
+		load_int8(buf);
 	} else {
 		context->address_latch = context->address;
-		context->cd_latch = context->cd;
 	}
 	update_video_params(context);
 }
--- a/vdp.h	Sun Sep 04 14:26:12 2022 -0700
+++ b/vdp.h	Sun Sep 04 23:29:37 2022 -0700
@@ -198,7 +198,6 @@
 	uint32_t       frame;
 	uint32_t       vsram_size;
 	uint8_t        cd;
-	uint8_t        cd_latch;
 	uint8_t	       flags;
 	uint8_t        regs[VDP_REGS];
 	//cycle count in MCLKs