changeset 413:36fbbced25c2

Initial work on interlace
author Mike Pavone <pavone@retrodev.com>
date Sat, 22 Jun 2013 21:19:43 -0700
parents 00d5a2b532f4
children 51ee0f117365
files render_sdl.c vdp.c vdp.h
diffstat 3 files changed, 110 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/render_sdl.c	Wed Jun 19 00:40:13 2013 -0700
+++ b/render_sdl.c	Sat Jun 22 21:19:43 2013 -0700
@@ -147,6 +147,8 @@
     SDL_PauseAudio(0);
 }
 
+uint16_t blankbuf[320*240];
+
 void render_context(vdp_context * context)
 {
 	uint8_t *buf_8;
@@ -166,13 +168,15 @@
     } else {
     	repeat_y = repeat_x;
     }
+    int othermask = repeat_y >> 1;
+    uint16_t *otherbuf = (context->regs[REG_MODE_4] & BIT_INTERLACE) ? context->evenbuf : blankbuf;
     switch (screen->format->BytesPerPixel) {
     case 2:
         buf_16 = (uint16_t *)screen->pixels;
         for (int y = 0; y < 240; y++) {
         	for (int i = 0; i < repeat_y; i++,buf_16 += screen->pitch/2) {
         		uint16_t *line = buf_16;
-        		uint16_t *src_line = context->framebuf + y * 320;
+        		uint16_t *src_line = (i & othermask ? otherbuf : context->oddbuf) + y * 320;
 		    	for (int x = 0; x < 320; x++) {
 		    		uint16_t color = color_map[*(src_line++) & 0xFFF];
 		    		for (int j = 0; j < repeat_x; j++) {
@@ -188,7 +192,7 @@
         	for (int i = 0; i < repeat_y; i++,buf_8 += screen->pitch) {
         		uint8_t *line = buf_8;
 		    	for (int x = 0; x < 320; x++) {
-		    		uint16_t gen_color = context->framebuf[y * 320 + x];
+		    		uint16_t gen_color = context->oddbuf[y * 320 + x];
 		    		b = ((gen_color >> 8) & 0xE) * 18;
 		    		g = ((gen_color >> 4) & 0xE) * 18;
 		    		r = (gen_color& 0xE) * 18;
@@ -208,7 +212,7 @@
 	    for (int y = 0; y < 240; y++) {
 	    	for (int i = 0; i < repeat_y; i++,buf_32 += screen->pitch/4) {
 	    		uint32_t *line = buf_32;
-	    		uint16_t *src_line = context->framebuf + y * 320;
+	    		uint16_t *src_line = (i & othermask ? otherbuf : context->oddbuf) + y * 320;
 		    	for (int x = 0; x < 320; x++) {
 		    		uint32_t color;
 		    		if (!render_dbg) {
@@ -222,7 +226,7 @@
 							color = color_map[context->cram[ (debug_pal << 4) | (context->vdpmem[(x/8)*32 + (y/8)*32*40 + (x%8)/2 + (y%8)*4] >> 4) ]];
 						}
 					}else {
-						uint16_t gen_color = context->framebuf[y * 320 + x];
+						uint16_t gen_color = context->oddbuf[y * 320 + x];
 						r = g = b = 0;
 						switch(gen_color & FBUF_SRC_MASK)
 						{
@@ -271,6 +275,10 @@
         SDL_UnlockSurface(screen);
     }
     SDL_UpdateRect(screen, 0, 0, screen->clip_rect.w, screen->clip_rect.h);
+    if (context->regs[REG_MODE_4] & BIT_INTERLACE)
+    {
+    	context->framebuf = context->framebuf == context->oddbuf ? context->evenbuf : context->oddbuf;
+    }
 }
 
 void render_wait_quit(vdp_context * context)
--- 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;
 }
 
--- a/vdp.h	Wed Jun 19 00:40:13 2013 -0700
+++ b/vdp.h	Sat Jun 22 21:19:43 2013 -0700
@@ -67,6 +67,29 @@
 	REG_DMASRC_H
 } vdp_regs;
 
+//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 BIT_DOUBLE_RES 0x4
+#define BIT_INTERLACE  0x2
+
 typedef struct {
 	uint16_t address;
 	int16_t x_pos;
@@ -102,6 +125,8 @@
 	uint8_t     *linebuf;
 	//stores 12-bit color + shadow/highlight bits
 	uint16_t    *framebuf;
+	uint16_t    *oddbuf;
+	uint16_t    *evenbuf;
 	uint16_t    cram[CRAM_SIZE];
 	uint16_t    vsram[VSRAM_SIZE];
 	uint8_t     latched_mode;
@@ -120,6 +145,7 @@
 	uint8_t     dma_cd;
 	uint8_t     hint_counter;
 	uint8_t     flags2;
+	uint8_t     double_res;
 	uint8_t     *tmp_buf_a;
 	uint8_t     *tmp_buf_b;
 } vdp_context;