changeset 1184:b1147418254a

Overscan is now configurable
author Michael Pavone <pavone@retrodev.com>
date Wed, 18 Jan 2017 23:43:36 -0800
parents 8d8c71ebbbce
children 9de9d2c6ebe5
files default.cfg genesis.c render.h render_sdl.c shaders/default.f.glsl shaders/default.v.glsl sms.c
diffstat 7 files changed, 84 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/default.cfg	Wed Jan 18 21:30:20 2017 -0800
+++ b/default.cfg	Wed Jan 18 23:43:36 2017 -0800
@@ -111,6 +111,31 @@
 	scanlines off
 	vsync off
 	fullscreen off
+	ntsc {
+		overscan {
+			#these values will result in square pixels in H40 mode
+			top 2
+			bottom 1
+			#if you want to completely hide the border instead
+			#comment out those two lines and uncomment these
+			#top 11
+			#bottom 8
+		}
+	}
+	pal {
+		overscan {
+			#these values will produce the same size border in V30 mode
+			#as the default NTSC settings will produce in V24 mode
+			#this results in a slightly vertically squished picture
+			#which is probably approximately correct on a properly calibrated TV
+			top 21
+			bottom 17
+			#for square pixels and zero border in V30 mode
+			#coment out those two lines and uncomment these
+			#top 30
+			#bottom 24
+		}
+	}
 }
 
 audio {
--- a/genesis.c	Wed Jan 18 21:30:20 2017 -0800
+++ b/genesis.c	Wed Jan 18 23:43:36 2017 -0800
@@ -792,6 +792,7 @@
 {
 	genesis_context *gen = (genesis_context *)system;
 	set_keybindings(&gen->io);
+	render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC);
 	if (statefile) {
 		uint32_t pc = load_gst(gen, statefile);
 		if (!pc) {
@@ -818,6 +819,7 @@
 {
 	genesis_context *gen = (genesis_context *)system;
 	map_all_bindings(&gen->io);
+	render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC);
 	resume_68k(gen->m68k);
 }
 
--- a/render.h	Wed Jan 18 21:30:20 2017 -0800
+++ b/render.h	Wed Jan 18 23:43:36 2017 -0800
@@ -57,10 +57,17 @@
 #include "psg.h"
 #include "ym2612.h"
 
+typedef enum {
+	VID_NTSC,
+	VID_PAL,
+	NUM_VID_STD
+} vid_std;
+
 uint32_t render_map_color(uint8_t r, uint8_t g, uint8_t b);
 uint32_t *render_get_framebuffer(uint8_t which, int *pitch);
 void render_framebuffer_updated(uint8_t which, int width);
 void render_init(int width, int height, char * title, uint8_t fullscreen);
+void render_set_video_standard(vid_std std);
 void render_update_caption(char *title);
 void render_wait_quit(vdp_context * context);
 void render_wait_psg(psg_context * context);
--- a/render_sdl.c	Wed Jan 18 21:30:20 2017 -0800
+++ b/render_sdl.c	Wed Jan 18 23:43:36 2017 -0800
@@ -133,7 +133,7 @@
 }
 
 #ifndef DISABLE_OPENGL
-static GLuint textures[3], buffers[2], vshader, fshader, program, un_textures[2], un_width, at_pos;
+static GLuint textures[3], buffers[2], vshader, fshader, program, un_textures[2], un_width, un_height, at_pos;
 
 static GLfloat vertex_data[] = {
 	-1.0f, -1.0f,
@@ -211,7 +211,7 @@
 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 			if (i < 2) {
 				//TODO: Fixme for PAL + invalid display mode
-				glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 512, 256, 0, GL_BGRA, GL_UNSIGNED_BYTE, texture_buf);
+				glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 512, 512, 0, GL_BGRA, GL_UNSIGNED_BYTE, texture_buf);
 			} else {
 				uint32_t blank = 255 << 24;
 				glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_BGRA, GL_UNSIGNED_BYTE, &blank);
@@ -239,12 +239,13 @@
 		un_textures[0] = glGetUniformLocation(program, "textures[0]");
 		un_textures[1] = glGetUniformLocation(program, "textures[1]");
 		un_width = glGetUniformLocation(program, "width");
+		un_height = glGetUniformLocation(program, "height");
 		at_pos = glGetAttribLocation(program, "pos");
 	} else {
 #endif
 		
-		//TODO: Fixme for PAL + invalid display mode
-		sdl_textures[0] = sdl_textures[1] = SDL_CreateTexture(main_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 320, 480);
+		//TODO: Fixme for invalid display mode
+		sdl_textures[0] = sdl_textures[1] = SDL_CreateTexture(main_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 320, 588);
 #ifndef DISABLE_OPENGL
 	}
 #endif
@@ -264,6 +265,10 @@
 	}
 }
 
+static uint32_t overscan_top[NUM_VID_STD] = {2, 21};
+static uint32_t overscan_bot[NUM_VID_STD] = {1, 17};
+static vid_std video_standard = VID_NTSC;
+static char *vid_std_names[NUM_VID_STD] = {"ntsc", "pal"};
 void render_init(int width, int height, char * title, uint8_t fullscreen)
 {
 	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) {
@@ -291,6 +296,29 @@
 	render_gl = 0;
 	tern_val def = {.ptrval = "off"};
 	char *vsync = tern_find_path_default(config, "video\0vsync\0", def).ptrval;
+	
+	tern_val video_node = {.ptrval = NULL};
+	tern_find(config, "video", &video_node);
+	tern_node *video = tern_get_node(video_node);
+	if (video)
+	{
+		for (int i = 0; i < NUM_VID_STD; i++)
+		{
+			video_node.ptrval = NULL;
+			tern_find(video, vid_std_names[i], &video_node);
+			tern_node *std_settings = tern_get_node(video_node);
+			if (std_settings) {
+				char *val = tern_find_path_default(std_settings, "overscan\0top\0", (tern_val){.ptrval = NULL}).ptrval;
+				if (val) {
+					overscan_top[i] = atoi(val);
+				}
+				val = tern_find_path_default(std_settings, "overscan\0bottom\0", (tern_val){.ptrval = NULL}).ptrval;
+				if (val) {
+					overscan_bot[i] = atoi(val);
+				}
+			}
+		}
+	}
 
 #ifndef DISABLE_OPENGL
 	flags |= SDL_WINDOW_OPENGL;
@@ -418,6 +446,11 @@
 	atexit(render_quit);
 }
 
+void render_set_video_standard(vid_std std)
+{
+	video_standard = std;
+}
+
 void render_update_caption(char *title)
 {
 	caption = title;
@@ -472,10 +505,13 @@
 void render_framebuffer_updated(uint8_t which, int width)
 {
 	static uint8_t last;
+	uint32_t height = which <= FRAMEBUFFER_EVEN 
+		? (video_standard == VID_NTSC ? 243 : 294) - (overscan_top[video_standard] + overscan_bot[video_standard])
+		: 240;
 #ifndef DISABLE_OPENGL
 	if (render_gl && which <= FRAMEBUFFER_EVEN) {
 		glBindTexture(GL_TEXTURE_2D, textures[which]);
-		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 320, 240, GL_BGRA, GL_UNSIGNED_BYTE, texture_buf);
+		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 320, height, GL_BGRA, GL_UNSIGNED_BYTE, texture_buf + 320 * overscan_top[video_standard]);
 
 		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
 		glClear(GL_COLOR_BUFFER_BIT);
@@ -490,6 +526,7 @@
 		glUniform1i(un_textures[1], 1);
 
 		glUniform1f(un_width, width);
+		glUniform1f(un_height, height);
 
 		glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
 		glVertexAttribPointer(at_pos, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat[2]), (void *)0);
@@ -503,13 +540,12 @@
 		SDL_GL_SwapWindow(main_window);
 	} else {
 #endif
-		uint32_t height = 240;
 		if (which <= FRAMEBUFFER_EVEN && last != which) {
 			uint8_t *cur_dst = (uint8_t *)locked_pixels;
 			uint8_t *cur_saved = (uint8_t *)texture_buf;
 			uint32_t dst_off = which == FRAMEBUFFER_EVEN ? 0 : locked_pitch;
 			uint32_t src_off = which == FRAMEBUFFER_EVEN ? locked_pitch : 0;
-			for (int i = 0; i < 240; ++i)
+			for (int i = 0; i < height; ++i)
 			{
 				//copy saved line from other field
 				memcpy(cur_dst + dst_off, cur_saved, locked_pitch);
@@ -523,7 +559,7 @@
 		SDL_UnlockTexture(sdl_textures[which]);
 		SDL_Rect src_clip = {
 			.x = 0,
-			.y = 0,
+			.y = overscan_top[video_standard],
 			.w = width,
 			.h = height
 		};
--- a/shaders/default.f.glsl	Wed Jan 18 21:30:20 2017 -0800
+++ b/shaders/default.f.glsl	Wed Jan 18 23:43:36 2017 -0800
@@ -8,7 +8,7 @@
 {
 	gl_FragColor = mix(
 		texture2D(textures[0], texcoord),
-		texture2D(textures[1], vec2(texcoord.x, texcoord.y - 1.0/512.0)),
-		sin((texcoord.y * 512.0 - 0.75) * 3.14159265359) / 2.0 + 0.5
+		texture2D(textures[1], vec2(texcoord.x, texcoord.y - 1.0/1024.0)),
+		sin((texcoord.y * 1024.0 - 0.75) * 3.14159265359) / 2.0 + 0.5
 	);
 }
--- a/shaders/default.v.glsl	Wed Jan 18 21:30:20 2017 -0800
+++ b/shaders/default.v.glsl	Wed Jan 18 23:43:36 2017 -0800
@@ -2,10 +2,10 @@
 
 attribute vec2 pos;
 varying vec2 texcoord;
-uniform float width;
+uniform float width, height;
 
 void main()
 {
 	gl_Position = vec4(pos, 0.0, 1.0);
-	texcoord = sign(pos) * vec2(width/1024.0, 240.0/-512.0) + vec2(width/1024.0, 240.0/512.0);
+	texcoord = sign(pos) * vec2(width/1024.0, height/-1024.0) + vec2(width/1024.0, height/1024.0);
 }
--- a/sms.c	Wed Jan 18 21:30:20 2017 -0800
+++ b/sms.c	Wed Jan 18 23:43:36 2017 -0800
@@ -193,6 +193,8 @@
 	render_disable_ym();
 	sms_context *sms = (sms_context *)system;
 	uint32_t target_cycle = sms->z80->current_cycle + 3420*262;
+	//TODO: PAL support
+	render_set_video_standard(VID_NTSC);
 	while (!sms->should_return)
 	{
 		if (system->enter_debugger && sms->z80->pc) {