diff vdp.c @ 1117:928a65750345

Initial support for Genesis/Megadrive PBC mode. VDP still needs Mode 4 to be useful.
author Michael Pavone <pavone@retrodev.com>
date Thu, 22 Dec 2016 19:51:25 -0800
parents cacbd3f18f03
children e9369d6f0101
line wrap: on
line diff
--- a/vdp.c	Thu Dec 22 10:51:33 2016 -0800
+++ b/vdp.c	Thu Dec 22 19:51:25 2016 -0800
@@ -554,13 +554,33 @@
 			break;
 		case CRAM_WRITE: {
 			//printf("CRAM Write | %X to %X\n", start->value, (start->address/2) & (CRAM_SIZE-1));
-			write_cram(context, start->address, start->partial == 2 ? context->fifo[context->fifo_write].value : start->value);
+			if (start->partial == 1) {
+				uint16_t val;
+				if (start->address & 1) {
+					val = (context->cram[start->address >> 1 & (CRAM_SIZE-1)] & 0xFF) | start->value << 8;
+				} else {
+					val = (context->cram[start->address >> 1 & (CRAM_SIZE-1)] & 0xFF00) | start->value;
+				}
+				write_cram(context, start->address, val);
+			} else {
+				write_cram(context, start->address, start->partial == 2 ? context->fifo[context->fifo_write].value : start->value);
+			}
 			break;
 		}
 		case VSRAM_WRITE:
 			if (((start->address/2) & 63) < VSRAM_SIZE) {
 				//printf("VSRAM Write: %X to %X @ vcounter: %d, hslot: %d, cycle: %d\n", start->value, context->address, context->vcounter, context->hslot, context->cycles);
-				context->vsram[(start->address/2) & 63] = start->partial == 2 ? context->fifo[context->fifo_write].value : start->value;
+				if (start->partial == 1) {
+					if (start->address & 1) {
+						context->vsram[(start->address/2) & 63] &= 0xFF;
+						context->vsram[(start->address/2) & 63] |= start->value << 8;
+					} else {
+						context->vsram[(start->address/2) & 63] &= 0xFF00;
+						context->vsram[(start->address/2) & 63] |= start->value;
+					}
+				} else {
+					context->vsram[(start->address/2) & 63] = start->partial == 2 ? context->fifo[context->fifo_write].value : start->value;
+				}
 			}
 
 			break;
@@ -1673,6 +1693,19 @@
 	return 0;
 }
 
+void vdp_control_port_write_pbc(vdp_context *context, uint8_t value)
+{
+	if (context->flags2 & FLAG2_BYTE_PENDING) {
+		uint16_t full_val = value << 8 | context->pending_byte;
+		context->flags2 &= ~FLAG2_BYTE_PENDING;
+		//TODO: Deal with fact that Vbus->VDP DMA doesn't do anything in PBC mode
+		vdp_control_port_write(context, full_val);
+	} else {
+		context->pending_byte = value;
+		context->flags2 |= FLAG2_BYTE_PENDING;
+	}
+}
+
 int vdp_data_port_write(vdp_context * context, uint16_t value)
 {
 	//printf("data port write: %X at %d\n", value, context->cycles);
@@ -1708,6 +1741,36 @@
 	return 0;
 }
 
+void vdp_data_port_write_pbc(vdp_context * context, uint8_t value)
+{
+	if (context->flags & FLAG_PENDING) {
+		context->flags &= ~FLAG_PENDING;
+		//Should these be cleared here?
+		context->flags &= ~FLAG_READ_FETCHED;
+		context->flags2 &= ~FLAG2_READ_PENDING;
+	}
+	/*if (context->fifo_cur == context->fifo_end) {
+		printf("FIFO full, waiting for space before next write at cycle %X\n", context->cycles);
+	}*/
+	if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & 0xC0) == 0x80) {
+		context->flags &= ~FLAG_DMA_RUN;
+	}
+	while (context->fifo_write == context->fifo_read) {
+		vdp_run_context(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20));
+	}
+	fifo_entry * cur = context->fifo + context->fifo_write;
+	cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY;
+	cur->address = context->address;
+	cur->value = value;
+	cur->cd = context->cd;
+	cur->partial = 1;
+	if (context->fifo_read < 0) {
+		context->fifo_read = context->fifo_write;
+	}
+	context->fifo_write = (context->fifo_write + 1) & (FIFO_SIZE-1);
+	context->address += context->regs[REG_AUTOINC];
+}
+
 void vdp_test_port_write(vdp_context * context, uint16_t value)
 {
 	//TODO: implement test register
@@ -1717,7 +1780,7 @@
 {
 	context->flags &= ~FLAG_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 = get_open_bus_value() & 0xFC00;
+	uint16_t value = context->system->get_open_bus_value(context->system) & 0xFC00;
 	if (context->fifo_read < 0) {
 		value |= 0x200;
 	}