diff --git a/config.def.h b/config.def.h index 1e10214dd1..2f4cae1deb 100644 --- a/config.def.h +++ b/config.def.h @@ -216,6 +216,11 @@ static const unsigned int def_user_language = 0; #ifdef GEKKO /* Removes 480i flicker, smooths picture a little. */ #define DEFAULT_VIDEO_VFILTER true + +/* Allow overscan to be corrected on displays that + * do not have proper 'pixel perfect' scaling */ +#define DEFAULT_VIDEO_OVERSCAN_CORRECTION_TOP 0 +#define DEFAULT_VIDEO_OVERSCAN_CORRECTION_BOTTOM 0 #endif /* Smooths picture. */ diff --git a/configuration.c b/configuration.c index 7c3fbae2ac..c5c8ff3256 100644 --- a/configuration.c +++ b/configuration.c @@ -1734,7 +1734,9 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings, SETTING_UINT("network_remote_base_port", &settings->uints.network_remote_base_port, true, network_remote_base_port, false); #endif #ifdef GEKKO - SETTING_UINT("video_viwidth", &settings->uints.video_viwidth, true, DEFAULT_VIDEO_VI_WIDTH, false); + SETTING_UINT("video_viwidth", &settings->uints.video_viwidth, true, DEFAULT_VIDEO_VI_WIDTH, false); + SETTING_UINT("video_overscan_correction_top", &settings->uints.video_overscan_correction_top, true, DEFAULT_VIDEO_OVERSCAN_CORRECTION_TOP, false); + SETTING_UINT("video_overscan_correction_bottom", &settings->uints.video_overscan_correction_bottom, true, DEFAULT_VIDEO_OVERSCAN_CORRECTION_BOTTOM, false); #endif #ifdef HAVE_MENU SETTING_UINT("dpi_override_value", &settings->uints.menu_dpi_override_value, true, menu_dpi_override_value, false); diff --git a/configuration.h b/configuration.h index b4744e8fe1..3285a71f0e 100644 --- a/configuration.h +++ b/configuration.h @@ -450,6 +450,10 @@ typedef struct settings #ifdef HAVE_VIDEO_LAYOUT unsigned video_layout_selected_view; #endif +#ifdef GEKKO + unsigned video_overscan_correction_top; + unsigned video_overscan_correction_bottom; +#endif unsigned menu_timedate_style; unsigned menu_thumbnails; diff --git a/gfx/drivers/gx_gfx.c b/gfx/drivers/gx_gfx.c index a5c0ab0a76..ee88e7221f 100644 --- a/gfx/drivers/gx_gfx.c +++ b/gfx/drivers/gx_gfx.c @@ -95,6 +95,8 @@ typedef struct gx_video bool menu_texture_enable; video_viewport_t vp; unsigned scale; + unsigned overscan_correction_top; + unsigned overscan_correction_bottom; #ifdef HAVE_OVERLAY struct gx_overlay_data *overlay; unsigned overlays; @@ -909,7 +911,7 @@ static void convert_texture32(const uint32_t *_src, uint32_t *_dst, } } -static void gx_resize(void *data) +static void gx_resize(void *data, settings_t *settings) { int gamma; unsigned degrees; @@ -918,10 +920,9 @@ static void gx_resize(void *data) float top = 1, bottom = -1, left = -1, right = 1; int x = 0, y = 0; gx_video_t *gx = (gx_video_t*)data; - settings_t *settings = config_get_ptr(); const global_t *global = global_get_ptr(); - if (!gx) + if (!gx || !settings) return; width = gx->vp.full_width; @@ -994,6 +995,24 @@ static void gx_resize(void *data) } } + /* Overscan correction */ + if ((settings->uints.video_overscan_correction_top > 0) || + (settings->uints.video_overscan_correction_bottom > 0)) + { + float current_aspect = (float)width / (float)height; + int new_height = height - (settings->uints.video_overscan_correction_top + + settings->uints.video_overscan_correction_bottom); + int new_width = (int)((new_height * current_aspect) + 0.5f); + + if ((new_height > 0) && (new_width > 0)) + { + x += (int)((float)(width - new_width) * 0.5f); + y += (int)settings->uints.video_overscan_correction_top; + width = (unsigned)new_width; + height = (unsigned)new_height; + } + } + if(gx_isValidXOrigin(gx_xOrigin + x)) { gx_mode.viXOrigin = gx_xOrigin + x; @@ -1506,21 +1525,30 @@ static bool gx_frame(void *data, const void *frame, video_frame_info_t *video_info) { char fps_text_buf[128]; + settings_t *settings = config_get_ptr(); gx_video_t *gx = (gx_video_t*)data; u8 clear_efb = GX_FALSE; uint32_t level = 0; fps_text_buf[0] = '\0'; - if(!gx || (!frame && !gx->menu_texture_enable)) + if(!gx || (!frame && !gx->menu_texture_enable) || !settings) return true; if (!frame) width = height = 4; /* draw a black square in the background */ + if ((gx->overscan_correction_top != settings->uints.video_overscan_correction_top) || + (gx->overscan_correction_bottom != settings->uints.video_overscan_correction_bottom)) + { + gx->overscan_correction_top = settings->uints.video_overscan_correction_top; + gx->overscan_correction_bottom = settings->uints.video_overscan_correction_bottom; + gx->should_resize = true; + } + if(gx->should_resize) { - gx_resize(gx); + gx_resize(gx, settings); clear_efb = GX_TRUE; } diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index cb0a32da8e..1a84196f2b 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -1345,6 +1345,10 @@ MSG_HASH(MENU_ENUM_LABEL_VIDEO_VIEWPORT_CUSTOM_Y, "video_viewport_custom_y") MSG_HASH(MENU_ENUM_LABEL_VIDEO_VI_WIDTH, "video_vi_width") +MSG_HASH(MENU_ENUM_LABEL_VIDEO_OVERSCAN_CORRECTION_TOP, + "video_overscan_correction_top") +MSG_HASH(MENU_ENUM_LABEL_VIDEO_OVERSCAN_CORRECTION_BOTTOM, + "video_overscan_correction_bottom") MSG_HASH(MENU_ENUM_LABEL_VIDEO_VSYNC, "video_vsync") MSG_HASH(MENU_ENUM_LABEL_VIDEO_ADAPTIVE_VSYNC, diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 1070fe2c2f..2071bda87a 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -3776,6 +3776,22 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_VI_WIDTH, "Set VI Screen Width" ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_OVERSCAN_CORRECTION_TOP, + "Overscan Correction (Top)" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_OVERSCAN_CORRECTION_TOP, + "Adjust display overscan cropping by reducing image size by specified number of scanlines (taken from top of screen). Note: May introduce scaling artefacts." + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_OVERSCAN_CORRECTION_BOTTOM, + "Overscan Correction (Bottom)" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_OVERSCAN_CORRECTION_BOTTOM, + "Adjust display overscan cropping by reducing image size by specified number of scanlines (taken from bottom of screen). Note: May introduce scaling artefacts." + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_VSYNC, "Vertical Sync (Vsync)" diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index 9bdcb00a1b..0df61f1b55 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -581,6 +581,11 @@ default_sublabel_macro(action_bind_sublabel_video_3ds_lcd_bottom, MENU default_sublabel_macro(action_bind_sublabel_video_3ds_display_mode, MENU_ENUM_SUBLABEL_VIDEO_3DS_DISPLAY_MODE) #endif +#if defined(GEKKO) +default_sublabel_macro(action_bind_sublabel_video_overscan_correction_top, MENU_ENUM_SUBLABEL_VIDEO_OVERSCAN_CORRECTION_TOP) +default_sublabel_macro(action_bind_sublabel_video_overscan_correction_bottom, MENU_ENUM_SUBLABEL_VIDEO_OVERSCAN_CORRECTION_BOTTOM) +#endif + default_sublabel_macro(action_bind_sublabel_playlist_show_sublabels, MENU_ENUM_SUBLABEL_PLAYLIST_SHOW_SUBLABELS) default_sublabel_macro(action_bind_sublabel_menu_rgui_border_filler_enable, MENU_ENUM_SUBLABEL_MENU_RGUI_BORDER_FILLER_ENABLE) default_sublabel_macro(action_bind_sublabel_menu_rgui_border_filler_thickness_enable, MENU_ENUM_SUBLABEL_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE) @@ -2506,6 +2511,14 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_VIDEO_3DS_DISPLAY_MODE: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_3ds_display_mode); break; +#endif +#if defined(GEKKO) + case MENU_ENUM_LABEL_VIDEO_OVERSCAN_CORRECTION_TOP: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_overscan_correction_top); + break; + case MENU_ENUM_LABEL_VIDEO_OVERSCAN_CORRECTION_BOTTOM: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_overscan_correction_bottom); + break; #endif case MENU_ENUM_LABEL_CHEAT_APPLY_AFTER_LOAD: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_cheat_apply_after_load); diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index df572b48fc..e632326155 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -5915,6 +5915,12 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist_parse_settings_enum(info->list, MENU_ENUM_LABEL_VIDEO_VFILTER, PARSE_ONLY_BOOL, false); + menu_displaylist_parse_settings_enum(info->list, + MENU_ENUM_LABEL_VIDEO_OVERSCAN_CORRECTION_TOP, + PARSE_ONLY_UINT, false); + menu_displaylist_parse_settings_enum(info->list, + MENU_ENUM_LABEL_VIDEO_OVERSCAN_CORRECTION_BOTTOM, + PARSE_ONLY_UINT, false); menu_displaylist_parse_settings_enum(info->list, MENU_ENUM_LABEL_VIDEO_ROTATION, PARSE_ONLY_UINT, false); diff --git a/menu/menu_setting.c b/menu/menu_setting.c index 5f7dd9e89c..51dd43dac3 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -8726,7 +8726,7 @@ static bool setting_append_list( &settings->bools.video_vfilter, MENU_ENUM_LABEL_VIDEO_VFILTER, MENU_ENUM_LABEL_VALUE_VIDEO_VFILTER, - video_vfilter, + DEFAULT_VIDEO_VFILTER, MENU_ENUM_LABEL_VALUE_OFF, MENU_ENUM_LABEL_VALUE_ON, &group_info, @@ -8735,6 +8735,32 @@ static bool setting_append_list( general_write_handler, general_read_handler, SD_FLAG_NONE); + + CONFIG_UINT( + list, list_info, + &settings->uints.video_overscan_correction_top, + MENU_ENUM_LABEL_VIDEO_OVERSCAN_CORRECTION_TOP, + MENU_ENUM_LABEL_VALUE_VIDEO_OVERSCAN_CORRECTION_TOP, + DEFAULT_VIDEO_OVERSCAN_CORRECTION_TOP, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler); + menu_settings_list_current_add_range(list, list_info, 0, 24, 1, true, true); + + CONFIG_UINT( + list, list_info, + &settings->uints.video_overscan_correction_bottom, + MENU_ENUM_LABEL_VIDEO_OVERSCAN_CORRECTION_BOTTOM, + MENU_ENUM_LABEL_VALUE_VIDEO_OVERSCAN_CORRECTION_BOTTOM, + DEFAULT_VIDEO_OVERSCAN_CORRECTION_BOTTOM, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler); + menu_settings_list_current_add_range(list, list_info, 0, 24, 1, true, true); #endif CONFIG_BOOL( diff --git a/msg_hash.h b/msg_hash.h index e901ee58fd..04cb15284b 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -1849,6 +1849,8 @@ enum msg_hash_enums MENU_LABEL(USER_LANGUAGE), MENU_LABEL(NETPLAY_NICKNAME), MENU_LABEL(VIDEO_VI_WIDTH), + MENU_LABEL(VIDEO_OVERSCAN_CORRECTION_TOP), + MENU_LABEL(VIDEO_OVERSCAN_CORRECTION_BOTTOM), MENU_LABEL(VIDEO_ASPECT_RATIO), MENU_LABEL(VIDEO_FORCE_ASPECT), MENU_LABEL(VIDEO_ASPECT_RATIO_AUTO),