changeset 1337:d092c15246a3

Initial stab at horizontal border when VDP test register layer selection is in effect for H40. Extended horizontal borders in Titancade scene and ninja escape scene mostly correct now
author Michael Pavone <pavone@retrodev.com>
date Sat, 29 Apr 2017 16:51:57 -0700
parents baaf05fd64c4
children 3706b683cd48
files vdp.c
diffstat 1 files changed, 185 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/vdp.c	Sat Apr 29 12:32:50 2017 -0700
+++ b/vdp.c	Sat Apr 29 16:51:57 2017 -0700
@@ -316,6 +316,8 @@
 			}
 			x += dir;
 		}
+	} else {
+		context->cur_slot--;
 	}
 }
 
@@ -717,6 +719,7 @@
 				for (i=0; i < width && context->sprite_draws; i++) {
 					--context->sprite_draws;
 					context->sprite_draw_list[context->sprite_draws].x_pos = -128;
+					context->sprite_draw_list[context->sprite_draws].address = address + i * height * 4;
 				}
 			} else {
 				x -= 128;
@@ -1265,12 +1268,11 @@
 static void render_map_output(uint32_t line, int32_t col, vdp_context * context)
 {
 	uint32_t *dst;
+	uint8_t output_disabled = (context->test_port & TEST_BIT_DISABLE) != 0;
+	uint8_t test_layer = context->test_port >> 7 & 3;
 	if (context->state == PREPARING) {
-		if (!col) {
-			return;
-		}
-		col -= 2;
 		if (col) {
+			col -= 2;
 			dst = context->output + BORDER_LEFT + col * 8;
 		} else {
 			dst = context->output;
@@ -1279,6 +1281,7 @@
 			{
 				*dst = bg_color;
 			}
+			return;
 		}
 		uint32_t color = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
 		for (int i = 0; i < 16; i++)
@@ -1294,16 +1297,7 @@
 	if (col)
 	{
 		col-=2;
-		if (col) {
-			dst = context->output + BORDER_LEFT + col * 8;
-		} else {
-			dst = context->output;
-			uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
-			for (int i = 0; i < BORDER_LEFT; i++, dst++)
-			{
-				*dst = bg_color;
-			}
-		}
+		dst = context->output + BORDER_LEFT + col * 8;
 		if (context->debug < 2) {
 			sprite_buf = context->linebuf + col * 8;
 			uint8_t a_src, src;
@@ -1316,8 +1310,6 @@
 			}
 			plane_b_off = context->buf_b_off - (context->hscroll_b & 0xF);
 			//printf("A | tmp_buf offset: %d\n", 8 - (context->hscroll_a & 0x7));
-			uint8_t output_disabled = (context->test_port & TEST_BIT_DISABLE) != 0;
-			uint8_t test_layer = context->test_port >> 7 & 3;
 
 			if (context->regs[REG_MODE_4] & BIT_HILIGHT) {
 				for (int i = 0; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i) {
@@ -1490,6 +1482,63 @@
 				address++;
 			}
 		}
+	} else {
+		dst = context->output;
+		uint8_t pixel = context->regs[REG_BG_COLOR] & 0x3F;
+		if (output_disabled) {
+			pixel = 0x3F;
+		}
+		uint32_t bg_color = context->colors[pixel];
+		if (test_layer) {
+			switch(test_layer)
+			{
+			case 1:
+				//TODO: Display garbage from bus?
+				for (int i = 0; i < BORDER_LEFT; i++, dst++)
+				{
+					*dst = bg_color;
+				}
+				break;
+			case 2: {
+				//plane A
+				//TODO: Deal with Window layer
+				int i;
+				/*for (i = 0; i < (context->hscroll_a & 0xF) - (16 - BORDER_LEFT); i++, dst++)
+				{
+					*dst = bg_color;
+				}*/
+				i = 0;
+				uint8_t buf_off = context->buf_a_off - (context->hscroll_a & 0xF) + (16 - BORDER_LEFT);
+				//uint8_t *src = context->tmp_buf_a + ((context->buf_a_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_a & 0xF))) & SCROLL_BUFFER_MASK); 
+				for (; i < BORDER_LEFT; buf_off++, i++, dst++)
+				{
+					*dst = context->colors[context->tmp_buf_a[buf_off & SCROLL_BUFFER_MASK]];
+				}
+				break;
+			}
+			case 3: {
+				//plane B
+				int i;
+				/*for (i = 0; i < (context->hscroll_b & 0xF) - (16 - BORDER_LEFT); i++, dst++)
+				{
+					*dst = bg_color;
+				}*/
+				i = 0;
+				uint8_t buf_off = context->buf_b_off - (context->hscroll_b & 0xF) + (16 - BORDER_LEFT);
+				//uint8_t *src = context->tmp_buf_b + ((context->buf_b_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_b & 0xF))) & SCROLL_BUFFER_MASK); 
+				for (; i < BORDER_LEFT; buf_off++, i++, dst++)
+				{
+					*dst = context->colors[context->tmp_buf_b[buf_off & SCROLL_BUFFER_MASK]];
+				}
+				break;
+			}
+			}
+		} else {
+			for (int i = 0; i < BORDER_LEFT; i++, dst++)
+			{
+				*dst = bg_color;
+			}
+		}
 	}
 	context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;
 	context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;
@@ -1697,6 +1746,80 @@
 	}
 }
 
+static void render_border_garbage(vdp_context *context, uint32_t address, uint8_t *buf, uint8_t buf_off, uint16_t col)
+{
+	uint8_t base = col >> 9 & 0x30;
+	for (int i = 0; i < 4; i++, address++)
+	{
+		uint8_t byte = context->vdpmem[address & 0xFFFF];
+		buf[(buf_off++) & SCROLL_BUFFER_MASK] = base | byte >> 4;
+		buf[(buf_off++) & SCROLL_BUFFER_MASK] = base | byte & 0xF;
+	}
+}
+
+static void draw_right_border(vdp_context *context)
+{
+	uint32_t *dst = context->output + BORDER_LEFT + ((context->regs[REG_MODE_4] & BIT_H40) ? 320 : 256);
+	uint8_t pixel = context->regs[REG_BG_COLOR] & 0x3F;
+	if ((context->test_port & TEST_BIT_DISABLE) != 0) {
+		pixel = 0x3F;
+	}
+	uint32_t bg_color = context->colors[pixel];
+	uint8_t test_layer = context->test_port >> 7 & 3;
+	if (test_layer) {
+		switch(test_layer)
+			{
+			case 1:
+				//TODO: Display garbage from bus?
+				for (int i = 0; i < BORDER_RIGHT; i++, dst++)
+				{
+					*dst = bg_color;
+				}
+				break;
+			case 2: {
+				//plane A
+				//TODO: Deal with Window layer
+				int i;
+				/*for (i = 0; i < (context->hscroll_a & 0xF) - (16 - BORDER_LEFT); i++, dst++)
+				{
+					*dst = bg_color;
+				}*/
+				i = 0;
+				uint8_t buf_off = context->buf_a_off - (context->hscroll_a & 0xF);
+				//uint8_t *src = context->tmp_buf_a + ((context->buf_a_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_a & 0xF))) & SCROLL_BUFFER_MASK); 
+				for (; i < BORDER_RIGHT; buf_off++, i++, dst++)
+				{
+					*dst = context->colors[context->tmp_buf_a[buf_off & SCROLL_BUFFER_MASK] & 0x3F];
+				}
+				break;
+			}
+			case 3: {
+				//plane B
+				int i;
+				/*for (i = 0; i < (context->hscroll_b & 0xF) - (16 - BORDER_LEFT); i++, dst++)
+				{
+					*dst = bg_color;
+				}*/
+				i = 0;
+				uint8_t buf_off = context->buf_b_off - (context->hscroll_b & 0xF);
+				//uint8_t *src = context->tmp_buf_b + ((context->buf_b_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_b & 0xF))) & SCROLL_BUFFER_MASK); 
+				for (; i < BORDER_RIGHT; buf_off++, i++, dst++)
+				{
+					*dst = context->colors[context->tmp_buf_b[buf_off & SCROLL_BUFFER_MASK] & 0x3F];
+				}
+				break;
+			}
+			}
+	} else {
+		for (int i = 0; i < BORDER_RIGHT; i++, dst++)
+		{
+			*dst = bg_color;
+		}
+	}
+	context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;
+	context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;
+}
+
 #define CHECK_ONLY if (context->cycles >= target_cycles) { return; }
 #define CHECK_LIMIT if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } context->hslot++; context->cycles += slot_cycles; CHECK_ONLY
 
@@ -1791,6 +1914,29 @@
 		if ((slot) == BG_START_SLOT + LINEBUF_SIZE/2) {\
 			advance_output_line(context);\
 		}\
+		if (slot == 168 || slot == 247 || slot == 248) {\
+			render_border_garbage(\
+				context,\
+				context->sprite_draw_list[context->cur_slot].address,\
+				context->tmp_buf_b,\
+				context->buf_b_off + (slot == 247 ? 0 : 8),\
+				slot == 247 ? context->col_1 : context->col_2\
+			);\
+			if (slot == 248) {\
+				context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;\
+				context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;\
+			}\
+		} else if (slot == 243) {\
+			render_border_garbage(\
+				context,\
+				context->sprite_draw_list[context->cur_slot].address,\
+				context->tmp_buf_a,\
+				context->buf_a_off,\
+				context->col_1\
+			);\
+		} else if (slot == 169) {\
+			draw_right_border(context);\
+		}\
 		render_sprite_cells( context);\
 		scan_sprite_table(context->vcounter, context);\
 		CHECK_LIMIT_HSYNC(slot)
@@ -1912,6 +2058,12 @@
 		}
 		context->sprite_index = 0x80;
 		context->slot_counter = 0;
+		render_border_garbage(
+			context,
+			context->sprite_draw_list[context->cur_slot].address,
+			context->tmp_buf_b, context->buf_b_off,
+			context->col_1
+		);
 		render_sprite_cells( context);
 		scan_sprite_table(context->vcounter, context);
 		CHECK_LIMIT
@@ -1947,7 +2099,7 @@
 	SPRITE_RENDER_H40(240)
 	SPRITE_RENDER_H40(241)
 	SPRITE_RENDER_H40(242)
-	SPRITE_RENDER_H40(243)
+	SPRITE_RENDER_H40(243) //provides "garbage" for border when plane A selected
 	case 244:
 		address = (context->regs[REG_HSCROLL] & 0x3F) << 10;
 		mask = 0;
@@ -1957,6 +2109,7 @@
 		if (context->regs[REG_MODE_3] & 0x1) {
 			mask |= 0x7;
 		}
+		render_border_garbage(context, address, context->tmp_buf_a, context->buf_a_off+8, context->col_2);
 		address += (context->vcounter & mask) * 4;
 		context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1];
 		context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3];
@@ -1964,12 +2117,12 @@
 		if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); }
 		context->hslot++;
 		context->cycles += h40_hsync_cycles[14];
-		CHECK_ONLY
+		CHECK_ONLY //provides "garbage" for border when plane A selected
 	//!HSYNC high
 	SPRITE_RENDER_H40(245)
 	SPRITE_RENDER_H40(246)
-	SPRITE_RENDER_H40(247)
-	SPRITE_RENDER_H40(248)
+	SPRITE_RENDER_H40(247) //provides "garbage" for border when plane B selected
+	SPRITE_RENDER_H40(248) //provides "garbage" for border when plane B selected
 	case 249:
 		read_map_scroll_a(0, context->vcounter, context);
 		CHECK_LIMIT
@@ -2037,9 +2190,21 @@
 	case 163:
 		context->cur_slot = MAX_DRAWS-1;
 		memset(context->linebuf, 0, LINEBUF_SIZE);
+		render_border_garbage(
+			context,
+			context->sprite_draw_list[context->cur_slot].address,
+			context->tmp_buf_a, context->buf_a_off,
+			context->col_1
+		);
 		render_sprite_cells(context);
 		CHECK_LIMIT
 	case 164:
+		render_border_garbage(
+			context,
+			context->sprite_draw_list[context->cur_slot].address,
+			context->tmp_buf_a, context->buf_a_off + 8,
+			context->col_2
+		);
 		render_sprite_cells(context);
 		if (context->flags & FLAG_DMA_RUN) {
 			run_dma_src(context, -1);