# HG changeset patch # User Michael Pavone # Date 1484811816 28800 # Node ID b1147418254a123a245f3c6945fcebf86260722c # Parent 8d8c71ebbbce8316de2be62510d1b1998b214468 Overscan is now configurable diff -r 8d8c71ebbbce -r b1147418254a default.cfg --- 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 { diff -r 8d8c71ebbbce -r b1147418254a genesis.c --- 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); } diff -r 8d8c71ebbbce -r b1147418254a render.h --- 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); diff -r 8d8c71ebbbce -r b1147418254a render_sdl.c --- 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 }; diff -r 8d8c71ebbbce -r b1147418254a shaders/default.f.glsl --- 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 ); } diff -r 8d8c71ebbbce -r b1147418254a shaders/default.v.glsl --- 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); } diff -r 8d8c71ebbbce -r b1147418254a sms.c --- 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) {