changeset 470:541c1ae8abf3

Properly delay 68K on VDP reads. Dummy VDP test port implementation. Initial stab at handling undefined bits of VSRAM and CRAM.
author Mike Pavone <pavone@retrodev.com>
date Fri, 13 Sep 2013 19:22:46 -0700
parents 5f3344d0d42f
children f065769836e8
files blastem.c vdp.c vdp.h
diffstat 3 files changed, 49 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/blastem.c	Wed Sep 11 19:26:35 2013 -0700
+++ b/blastem.c	Fri Sep 13 19:22:46 2013 -0700
@@ -362,7 +362,7 @@
 			exit(1);
 		}
 		if (v_context->cycles != before_cycle) {
-			//printf("68K paused for %d (%d) cycles at cycle %d (%d)\n", v_context->cycles / MCLKS_PER_68K - context->current_cycle, v_context->cycles - before_cycle, context->current_cycle, before_cycle);
+			printf("68K paused for %d (%d) cycles at cycle %d (%d) for write\n", v_context->cycles / MCLKS_PER_68K - context->current_cycle, v_context->cycles - before_cycle, context->current_cycle, before_cycle);
 			context->current_cycle = v_context->cycles / MCLKS_PER_68K;
 		}
 	} else if (vdp_port < 0x18) {
@@ -402,7 +402,7 @@
 		sync_sound(gen, context->current_cycle * MCLKS_PER_Z80);
 		psg_write(gen->psg, value);
 	} else {
-		//TODO: Implement undocumented test register(s)
+		vdp_test_port_write(gen->vdp, value);
 	}
 	return context;
 }
@@ -417,6 +417,7 @@
 	uint16_t value;
 	sync_components(context, 0);
 	vdp_context * v_context = context->video_context;
+	uint32_t before_cycle = v_context->cycles;
 	if (vdp_port < 0x10) {
 		if (vdp_port < 4) {
 			value = vdp_data_port_read(v_context);
@@ -426,9 +427,15 @@
 			value = vdp_hv_counter_read(v_context);
 			//printf("HV Counter: %X at cycle %d\n", value, v_context->cycles);
 		}
+	} else if (vdp_port < 0x18){
+		printf("Illegal read from PSG  port %X\n", vdp_port);
+		exit(1);
 	} else {
-		printf("Illegal read from PSG or test register port %X\n", vdp_port);
-		exit(1);
+		value = vdp_test_port_read(v_context);
+	}
+	if (v_context->cycles != before_cycle) {
+		printf("68K paused for %d (%d) cycles at cycle %d (%d) for read\n", v_context->cycles / MCLKS_PER_68K - context->current_cycle, v_context->cycles - before_cycle, context->current_cycle, before_cycle);
+		context->current_cycle = v_context->cycles / MCLKS_PER_68K;
 	}
 	return value;
 }
--- a/vdp.c	Wed Sep 11 19:26:35 2013 -0700
+++ b/vdp.c	Fri Sep 13 19:22:46 2013 -0700
@@ -1,6 +1,6 @@
 /*
  Copyright 2013 Michael Pavone
- This file is part of BlastEm. 
+ This file is part of BlastEm.
  BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
 */
 #include "vdp.h"
@@ -391,15 +391,21 @@
 void external_slot(vdp_context * context)
 {
 	fifo_entry * start = (context->fifo_end - FIFO_SIZE);
+	if (context->flags2 & FLAG2_READ_PENDING) {
+		context->flags2 &= ~FLAG2_READ_PENDING;
+		context->flags |= FLAG_UNUSED_SLOT;
+		return;
+	}
 	if (context->fifo_cur != start && start->cycle <= context->cycles) {
 		switch (start->cd & 0xF)
 		{
 		case VRAM_WRITE:
 			if (start->partial) {
-				//printf("VRAM Write: %X to %X\n", start->value, context->address ^ 1);
+				printf("VRAM Write: %X to %X at %d (line %d, slot %d)\n", start->value, start->address ^ 1, context->cycles, context->cycles/MCLKS_LINE, (context->cycles%MCLKS_LINE)/16);
+				context->last_fifo_val = start->value;
 				context->vdpmem[start->address ^ 1] = start->value;
 			} else {
-				//printf("VRAM Write High: %X to %X\n", start->value >> 8, context->address);
+				printf("VRAM Write High: %X to %X at %d (line %d, slot %d)\n", start->value >> 8, start->address, context->cycles, context->cycles/MCLKS_LINE, (context->cycles%MCLKS_LINE)/16);
 				context->vdpmem[start->address] = start->value >> 8;
 				start->partial = 1;
 				//skip auto-increment and removal of entry from fifo
@@ -409,12 +415,14 @@
 		case CRAM_WRITE: {
 			//printf("CRAM Write | %X to %X\n", start->value, (start->address/2) & (CRAM_SIZE-1));
 			write_cram(context, start->address, start->value);
+			context->last_fifo_val = start->value;
 			break;
 		}
 		case VSRAM_WRITE:
 			if (((start->address/2) & 63) < VSRAM_SIZE) {
 				//printf("VSRAM Write: %X to %X\n", start->value, context->address);
 				context->vsram[(start->address/2) & 63] = start->value;
+				context->last_fifo_val = start->value;
 			}
 
 			break;
@@ -1428,7 +1436,7 @@
 
 int vdp_control_port_write(vdp_context * context, uint16_t value)
 {
-	//printf("control port write: %X at %d\n", value, context->cycles);
+	printf("control port write: %X at %d\n", value, context->cycles);
 	if (context->flags & FLAG_DMA_RUN) {
 		return -1;
 	}
@@ -1482,7 +1490,7 @@
 
 int vdp_data_port_write(vdp_context * context, uint16_t value)
 {
-	//printf("data port write: %X at %d\n", value, context->cycles);
+	printf("data port write: %X at %d\n", value, context->cycles);
 	if (context->flags & FLAG_DMA_RUN && (context->regs[REG_DMASRC_H] & 0xC0) != 0x80) {
 		return -1;
 	}
@@ -1514,6 +1522,11 @@
 	return 0;
 }
 
+void vdp_test_port_write(vdp_context * context, uint16_t value)
+{
+	//TODO: implement test register
+}
+
 uint16_t vdp_control_port_read(vdp_context * context)
 {
 	context->flags &= ~FLAG_PENDING;
@@ -1549,6 +1562,9 @@
 	return value;
 }
 
+#define CRAM_BITS 0xEEE
+#define VSRAM_BITS 0x3FF
+
 uint16_t vdp_data_port_read(vdp_context * context)
 {
 	context->flags &= ~FLAG_PENDING;
@@ -1557,6 +1573,7 @@
 	}
 	//Not sure if the FIFO should be drained before processing a read or not, but it would make sense
 	context->flags &= ~FLAG_UNUSED_SLOT;
+	context->flags2 |= FLAG2_READ_PENDING;
 	while (!(context->flags & FLAG_UNUSED_SLOT)) {
 		vdp_run_context(context, context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20));
 	}
@@ -1566,17 +1583,20 @@
 	case VRAM_READ:
 		value = context->vdpmem[context->address] << 8;
 		context->flags &= ~FLAG_UNUSED_SLOT;
+		context->flags2 |= FLAG2_READ_PENDING;
 		while (!(context->flags & FLAG_UNUSED_SLOT)) {
 			vdp_run_context(context, context->cycles + ((context->latched_mode & BIT_H40) ? 16 : 20));
 		}
 		value |= context->vdpmem[context->address ^ 1];
 		break;
 	case CRAM_READ:
-		value = context->cram[(context->address/2) & (CRAM_SIZE-1)];
+		value = context->cram[(context->address/2) & (CRAM_SIZE-1)] & CRAM_BITS;
+		value |= context->last_fifo_val & ~CRAM_BITS;
 		break;
 	case VSRAM_READ:
 		if (((context->address / 2) & 63) < VSRAM_SIZE) {
-			value = context->vsram[context->address & 63];
+			value = context->vsram[context->address & 63] & VSRAM_BITS;
+			value |= context->last_fifo_val & ~VSRAM_BITS;
 		}
 		break;
 	}
@@ -1693,6 +1713,12 @@
 	return (line << 8) | linecyc;
 }
 
+uint16_t vdp_test_port_read(vdp_context * context)
+{
+	//TODO: Find out what actually gets returned here
+	return 0xFFFF;
+}
+
 void vdp_adjust_cycles(vdp_context * context, uint32_t deduction)
 {
 	context->cycles -= deduction;
--- a/vdp.h	Wed Sep 11 19:26:35 2013 -0700
+++ b/vdp.h	Fri Sep 13 19:22:46 2013 -0700
@@ -1,6 +1,6 @@
 /*
  Copyright 2013 Michael Pavone
- This file is part of BlastEm. 
+ This file is part of BlastEm.
  BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
 */
 #ifndef VDP_H_
@@ -47,6 +47,7 @@
 
 #define FLAG2_VINT_PENDING 0x01
 #define FLAG2_HINT_PENDING 0x02
+#define FLAG2_READ_PENDING 0x04
 
 #define DISPLAY_ENABLE 0x40
 
@@ -149,6 +150,7 @@
 	uint16_t    col_1;
 	uint16_t    col_2;
 	uint16_t    last_write_val;
+	uint16_t    last_fifo_val;
 	uint8_t     v_offset;
 	uint8_t     dma_cd;
 	uint8_t     hint_counter;
@@ -172,9 +174,11 @@
 uint8_t vdp_save_gst(vdp_context * context, FILE * outfile);
 int vdp_control_port_write(vdp_context * context, uint16_t value);
 int vdp_data_port_write(vdp_context * context, uint16_t value);
+void vdp_test_port_write(vdp_context * context, uint16_t value);
 uint16_t vdp_control_port_read(vdp_context * context);
 uint16_t vdp_data_port_read(vdp_context * context);
 uint16_t vdp_hv_counter_read(vdp_context * context);
+uint16_t vdp_test_port_read(vdp_context * context);
 void vdp_adjust_cycles(vdp_context * context, uint32_t deduction);
 uint32_t vdp_next_hint(vdp_context * context);
 uint32_t vdp_next_vint(vdp_context * context);