diff vdp.c @ 413:36fbbced25c2

Initial work on interlace
author Mike Pavone <pavone@retrodev.com>
date Sat, 22 Jun 2013 21:19:43 -0700
parents f8c6f8684cd6
children 51ee0f117365
line wrap: on
line diff
--- a/vdp.c	Wed Jun 19 00:40:13 2013 -0700
+++ b/vdp.c	Sat Jun 22 21:19:43 2013 -0700
@@ -10,27 +10,6 @@
 #define MAP_BIT_H_FLIP 0x800
 #define MAP_BIT_V_FLIP 0x1000
 
-//Mode reg 1
-#define BIT_HINT_EN    0x10
-#define BIT_PAL_SEL    0x04
-#define BIT_HVC_LATCH  0x02
-#define BIT_DISP_DIS   0x01
-
-//Mode reg 2
-#define BIT_DISP_EN    0x40
-#define BIT_VINT_EN    0x20
-#define BIT_DMA_ENABLE 0x10
-#define BIT_PAL        0x08
-#define BIT_MODE_5     0x04
-
-//Mode reg 3
-#define BIT_EINT_EN    0x10
-#define BIT_VSCROLL    0x04
-
-//Mode reg 4
-#define BIT_H40        0x01
-#define BIT_HILIGHT    0x8
-
 #define SCROLL_BUFFER_SIZE 32
 #define SCROLL_BUFFER_DRAW 16
 
@@ -52,8 +31,10 @@
 	memset(context, 0, sizeof(*context));
 	context->vdpmem = malloc(VRAM_SIZE);
 	memset(context->vdpmem, 0, VRAM_SIZE);
-	context->framebuf = malloc(FRAMEBUF_SIZE);
+	context->oddbuf = context->framebuf = malloc(FRAMEBUF_SIZE);
 	memset(context->framebuf, 0, FRAMEBUF_SIZE);
+	context->evenbuf = malloc(FRAMEBUF_SIZE);
+	memset(context->evenbuf, 0, FRAMEBUF_SIZE);
 	context->linebuf = malloc(LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2);
 	memset(context->linebuf, 0, LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2);
 	context->tmp_buf_a = context->linebuf + LINEBUF_SIZE;
@@ -158,6 +139,21 @@
 	if (context->sprite_index && context->slot_counter) {
 		line += 1;
 		line &= 0xFF;
+		uint16_t ymask, ymin;
+		uint8_t height_mult;
+		if (context->double_res) {
+			line *= 2;
+			if (context->framebuf != context->oddbuf) {
+				line++;
+			}
+			ymask = 0x3FF;
+			ymin = 256;
+			height_mult = 16;
+		} else {
+			ymask = 0x1FF;
+			ymin = 128;
+			height_mult = 8;
+		}
 		context->sprite_index &= 0x7F;
 		if (context->latched_mode & BIT_H40) {
 			if (context->sprite_index >= MAX_SPRITES_FRAME) {
@@ -171,28 +167,28 @@
 		//TODO: Read from SAT cache rather than from VRAM
 		uint16_t sat_address = (context->regs[REG_SAT] & 0x7F) << 9;
 		uint16_t address = context->sprite_index * 8 + sat_address;
-		line += 128;
+		line += ymin;
 		uint16_t y = ((context->vdpmem[address] & 0x3) << 8 | context->vdpmem[address+1]) & 0x1FF;
-		uint8_t height = ((context->vdpmem[address+2] & 0x3) + 1) * 8;
+		uint8_t height = ((context->vdpmem[address+2] & 0x3) + 1) * height_mult;
 		//printf("Sprite %d | y: %d, height: %d\n", context->sprite_index, y, height);
 		if (y <= line && line < (y + height)) {
 			//printf("Sprite %d at y: %d with height %d is on line %d\n", context->sprite_index, y, height, line);
 			context->sprite_info_list[--(context->slot_counter)].size = context->vdpmem[address+2];
 			context->sprite_info_list[context->slot_counter].index = context->sprite_index;
-			context->sprite_info_list[context->slot_counter].y = y-128;
+			context->sprite_info_list[context->slot_counter].y = y-ymin;
 		}
 		context->sprite_index = context->vdpmem[address+3] & 0x7F;
 		if (context->sprite_index && context->slot_counter)
 		{
 			address = context->sprite_index * 8 + sat_address;
 			y = ((context->vdpmem[address] & 0x3) << 8 | context->vdpmem[address+1]) & 0x1FF;
-			height = ((context->vdpmem[address+2] & 0x3) + 1) * 8;
+			height = ((context->vdpmem[address+2] & 0x3) + 1) * height_mult;
 			//printf("Sprite %d | y: %d, height: %d\n", context->sprite_index, y, height);
 			if (y <= line && line < (y + height)) {
 				//printf("Sprite %d at y: %d with height %d is on line %d\n", context->sprite_index, y, height, line);
 				context->sprite_info_list[--(context->slot_counter)].size = context->vdpmem[address+2];
 				context->sprite_info_list[context->slot_counter].index = context->sprite_index;
-				context->sprite_info_list[context->slot_counter].y = y-128;
+				context->sprite_info_list[context->slot_counter].y = y-ymin;
 			}
 			context->sprite_index = context->vdpmem[address+3] & 0x7F;
 		}
@@ -209,6 +205,13 @@
 			uint8_t width = ((context->sprite_info_list[context->cur_slot].size >> 2) & 0x3) + 1;
 			//in pixels
 			uint8_t height = ((context->sprite_info_list[context->cur_slot].size & 0x3) + 1) * 8;
+			if (context->double_res) {
+				line *= 2;
+				if (context->framebuf != context->oddbuf) {
+					line++;
+				}
+				height *= 2;
+			}
 			uint16_t att_addr = ((context->regs[REG_SAT] & 0x7F) << 9) + context->sprite_info_list[context->cur_slot].index * 8 + 4;
 			uint16_t tileinfo = (context->vdpmem[att_addr] << 8) | context->vdpmem[att_addr+1];		
 			uint8_t pal_priority = (tileinfo >> 9) & 0x70;
@@ -218,7 +221,12 @@
 			} else {
 				row = line-context->sprite_info_list[context->cur_slot].y;
 			}
-			uint16_t address = ((tileinfo & 0x7FF) << 5) + row * 4;
+			uint16_t address;
+			if (context->double_res) {
+				address = ((tileinfo & 0x3FF) << 6) + row * 4;
+			} else {
+				address = ((tileinfo & 0x7FF) << 5) + row * 4;
+			}
 			int16_t x = ((context->vdpmem[att_addr+ 2] & 0x3) << 8 | context->vdpmem[att_addr + 3]) & 0x1FF;
 			if (x) {
 				context->flags |= FLAG_CAN_MASK;
@@ -432,6 +440,12 @@
 
 void read_map_scroll(uint16_t column, uint16_t vsram_off, uint32_t line, uint16_t address, uint16_t hscroll_val, vdp_context * context)
 {
+	/*if (context->double_res) {
+		line *= 2;
+		if (context->framebuf != context->oddbuf) {
+			line++;
+		}
+	}*/
 	if (!vsram_off) {
 		uint16_t left_col, right_col;
 		if (context->regs[REG_WINDOW_H] & WINDOW_RIGHT) {
@@ -493,6 +507,10 @@
 		vscroll = 0x3FF;
 		break;
 	}
+	/*if (context->double_res) {
+		vscroll <<= 1;
+		vscroll |= 1;
+	}*/
 	vscroll &= (context->vsram[(context->regs[REG_MODE_3] & BIT_VSCROLL ? column : 0) + vsram_off] + line);
 	context->v_offset = vscroll & 0x7;
 	//printf("%s | line %d, vsram: %d, vscroll: %d, v_offset: %d\n",(vsram_off ? "B" : "A"), line, context->vsram[context->regs[REG_MODE_3] & 0x4 ? column : 0], vscroll, context->v_offset);
@@ -545,11 +563,21 @@
 
 void render_map(uint16_t col, uint8_t * tmp_buf, vdp_context * context)
 {
-	uint16_t address = ((col & 0x7FF) << 5);
+	uint16_t address;
+	uint8_t shift, add;
+	if (context->double_res) {
+		address = ((col & 0x3FF) << 6);
+		shift = 1;
+		add = context->framebuf != context->oddbuf ? 1 : 0;
+	} else {
+		address = ((col & 0x7FF) << 5);
+		shift = 0;
+		add = 0;
+	}
 	if (col & MAP_BIT_V_FLIP) {
-		address +=  28 - 4 * context->v_offset;
+		address +=  28 - 4 * ((context->v_offset << shift) + add);
 	} else {
-		address += 4 * context->v_offset;
+		address += 4 * ((context->v_offset << shift) + add);
 	}
 	uint16_t pal_priority = (col >> 9) & 0x70;
 	int32_t dir;
@@ -1314,6 +1342,9 @@
 				if (reg == REG_MODE_2) {
 					//printf("Display is now %s\n", (context->regs[REG_MODE_2] & DISPLAY_ENABLE) ? "enabled" : "disabled");
 				}
+				if (reg == REG_MODE_4) {
+					context->double_res = (value & (BIT_INTERLACE | BIT_DOUBLE_RES)) == (BIT_INTERLACE | BIT_DOUBLE_RES);
+				}
 			}
 		} else {
 			context->flags |= FLAG_PENDING;
@@ -1362,7 +1393,10 @@
 		value |= 0x100;
 	}
 	if (context->flags2 & FLAG2_VINT_PENDING) {
-		value |- 0x80;
+		value |= 0x80;
+	}
+	if ((context->regs[REG_MODE_4] & BIT_INTERLACE) && context->framebuf == context->oddbuf) {
+		value |= 0x10;
 	}
 	uint32_t line= context->cycles / MCLKS_LINE;
 	uint32_t linecyc = context->cycles % MCLKS_LINE;
@@ -1517,6 +1551,12 @@
 		}
 	}
 	linecyc &= 0xFF;
+	if (context->double_res) {
+		line <<= 1;
+		if (line & 0x100) {
+			line |= 1;
+		}
+	}
 	return (line << 8) | linecyc;
 }