diff --git a/gfx/video_driver.c b/gfx/video_driver.c index 541ad4c0d5..0fb87601f2 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -2019,20 +2019,30 @@ bool video_driver_supports_read_frame_raw(void) return false; } -void video_driver_set_viewport_core(void) +/* Get aspect ratio (DAR) requested by the core */ +float video_driver_get_core_aspect(void) { video_driver_state_t *video_st = &video_driver_st; struct retro_game_geometry *geom = &video_st->av_info.geometry; + float out_aspect = 0; if (!geom || geom->base_width <= 0.0f || geom->base_height <= 0.0f) - return; + return out_aspect; /* Fallback to 1:1 pixel ratio if none provided */ if (geom->aspect_ratio > 0.0f) - aspectratio_lut[ASPECT_RATIO_CORE].value = geom->aspect_ratio; + out_aspect = geom->aspect_ratio; else - aspectratio_lut[ASPECT_RATIO_CORE].value = - (float)geom->base_width / geom->base_height; + out_aspect = (float)geom->base_width / geom->base_height; + + return out_aspect; +} + +void video_driver_set_viewport_core(void) +{ + float core_aspect = video_driver_get_core_aspect(); + if (core_aspect != 0) + aspectratio_lut[ASPECT_RATIO_CORE].value = core_aspect; } void video_driver_set_rgba(void) diff --git a/gfx/video_driver.h b/gfx/video_driver.h index 9a0a880cd8..9f810c0ecc 100644 --- a/gfx/video_driver.h +++ b/gfx/video_driver.h @@ -911,6 +911,8 @@ bool video_driver_prefer_viewport_read(void); bool video_driver_supports_read_frame_raw(void); +float video_driver_get_core_aspect(void); + void video_driver_set_viewport_core(void); void video_driver_reset_custom_viewport(settings_t *settings); diff --git a/gfx/video_shader_parse.c b/gfx/video_shader_parse.c index 0ca0bc96e0..2b8eeea094 100644 --- a/gfx/video_shader_parse.c +++ b/gfx/video_shader_parse.c @@ -59,6 +59,25 @@ /* Maximum depth of chain of referenced shader presets. * 16 seems to be a very large number of references at the moment. */ #define SHADER_MAX_REFERENCE_DEPTH 16 +#define SHADER_NUM_WILDCARDS 15 + +struct wildcard_token wildcard_tokens[SHADER_NUM_WILDCARDS] = { + {RARCH_WILDCARD_CONTENT_DIR, "$CONTENT-DIR$"}, + {RARCH_WILDCARD_CORE, "$CORE$"}, + {RARCH_WILDCARD_GAME, "$GAME$"}, + {RARCH_WILDCARD_VIDEO_DRIVER, "$VID-DRV$"}, + {RARCH_WILDCARD_VIDEO_DRIVER_PRESET_EXT, "$VID-DRV-PRESET-EXT$"}, + {RARCH_WILDCARD_VIDEO_DRIVER_SHADER_EXT, "$VID-DRV-SHADER-EXT$"}, + {RARCH_WILDCARD_CORE_REQUESTED_ROTATION, "$CORE-REQ-ROT$"}, + {RARCH_WILDCARD_VIDEO_ALLOW_CORE_ROTATION, "$VID-ALLOW-CORE-ROT$"}, + {RARCH_WILDCARD_VIDEO_USER_ROTATION, "$VID-USER-ROT$"}, + {RARCH_WILDCARD_VIDEO_FINAL_ROTATION, "$VID-FINAL-ROT$"}, + {RARCH_WILDCARD_SCREEN_ORIENTATION, "$SCREEN-ORIENT$"}, + {RARCH_WILDCARD_VIEWPORT_ASPECT_ORIENTATION, "$VIEW-ASPECT-ORIENT$"}, + {RARCH_WILDCARD_CORE_ASPECT_ORIENTATION, "$CORE-ASPECT-ORIENT$"}, + {RARCH_WILDCARD_PRESET_DIR, "$PRESET-DIR$"}, + {RARCH_WILDCARD_PRESET, "$PRESET$"}, +}; /* TODO/FIXME - global state - perhaps move outside this file */ static path_change_data_t *file_change_data = NULL; @@ -81,7 +100,8 @@ static path_change_data_t *file_change_data = NULL; * out_path is filled with the absolute path **/ static void fill_pathname_expanded_and_absolute(char *out_path, - const char *in_refpath, const char *in_path) + const char *in_refpath, + const char *in_path) { char expanded_path[PATH_MAX_LENGTH]; @@ -101,6 +121,313 @@ static void fill_pathname_expanded_and_absolute(char *out_path, pathname_conform_slashes_to_os(out_path); } +/** + * replace_wildcards: + * + * @param inout_absolute_path + * Absolute path to replace wildcards in + * + * @param in_preset_path + * Path of the preset that this path is being used in + * + * All the wildcards are replaced by the live values which come from retroarch + * or the preset context + * + * Possible wildcards/tokens to be replaced: + * + * $CONTENT-DIR$ -> Content Directory of the game rom + * + * $CORE$ -> Core name + * + * $GAME$ -> Game ROM's name + * + * $VID-DRV$ -> Video Driver: Currently active driver, possible replacement values: + * glcore + * gl + * vulkan + * d3d11 + * d3d9_hlsl + * "N/A" + * + * $VID-DRV-SHADER-EXT$ -> Video Driver Shader File Extension: The extension of shaders type supported by the current video driver: + * cg + * glsl + * slang + * + * $VID-DRV-PRESET-EXT$ -> Video Driver Preset File Extension: The extension of shaders type supported by the current video driver: + * cgp + * glslp + * slangp + * + * $CORE-REQ-ROT$ -> Core Requested Rotation: Rotation the core is requesting, possible replacement values: + * CORE-REQ-ROT-0 + * CORE-REQ-ROT-90 + * CORE-REQ-ROT-180 + * CORE-REQ-ROT-270 + * + * $VID-ALLOW-CORE-ROT$ -> Video Allow Core Rotation: Reflect's Retroarch's setting allowing the core requested rotation to affect the final rotation: + * VID-ALLOW-CORE-ROT-OFF + * VID-ALLOW-CORE-ROT-ON + * + * $VID-USER-ROT$ -> Video User Rotation: Rotation the core is requesting, possible replacement values, does not affect the UI: + * VID-USER-ROT-0 + * VID-USER-ROT-90 + * VID-USER-ROT-180 + * VID-USER-ROT-270 + * + * $VID-FINAL-ROT$ -> Video Final Rotation: Rotation which is the sum of the user rotation and the core rotation if it has been allowed, does not affect the UI: + * VID-FINAL-ROT-0 + * VID-FINAL-ROT-90 + * VID-FINAL-ROT-180 + * VID-FINAL-ROT-270 + * + * $SCREEN-ORIENT$ -> Screen Orientation: User adjusted screen orientation, will change windows from landscape to portrait, including the Retroarch UI: + * SCREEN-ORIENT-0 + * SCREEN-ORIENT-90 + * SCREEN-ORIENT-180 + * SCREEN-ORIENT-270 + * + * $VIEW-ASPECT-ORIENT$ -> Viewport Aspect Orientation: Orientation of the aspect ratio of the retroarch viewport + * VIEW-ASPECT-ORIENT-HORZ + * VIEW-ASPECT-ORIENT-VERT + * + * $CORE-ASPECT-ORIENT$ -> Core Aspect Orientation: Orientation of the aspect ratio requested by the core + * CORE-ASPECT-ORIENT-HORZ + * CORE-ASPECT-ORIENT-VERT + * + * $PRESET_DIR$ -> Preset directory's name + * + * $PRESET$ -> Preset's name + * + * If no wildcards are found within the path, or the path + * after replacing the wildcards does not exist on disk, + * the path returned will be uneffected. + **/ +static void replace_wildcards(char *inout_absolute_path, const unsigned in_absolute_path_length, char *in_preset_path) +{ + int i = 0; + char replaced_path[PATH_MAX_LENGTH] = ""; + + if (!strstr(inout_absolute_path, RARCH_WILDCARD_DELIMITER)) + return; + + strlcpy(replaced_path, inout_absolute_path, sizeof(replaced_path)); + + /* Step through the wildcards while we can still find the + * delimiter in the replaced path + */ + for (i = 0; (i < SHADER_NUM_WILDCARDS) && (strstr(replaced_path, RARCH_WILDCARD_DELIMITER)); i++) + { + /* If the wildcard text is in the path then process it */ + if (strstr(replaced_path, wildcard_tokens[i].token_name)) + { + char replace_text[PATH_MAX_LENGTH] = ""; + + switch (wildcard_tokens[i].token_id) + { + case RARCH_WILDCARD_CONTENT_DIR: + { + char content_dir_name[PATH_MAX_LENGTH] = ""; + const char* rarch_path_basename = path_get(RARCH_PATH_BASENAME); + if (rarch_path_basename) + { + fill_pathname_parent_dir_name(content_dir_name, + rarch_path_basename, + sizeof(content_dir_name)); + } + if (string_is_not_equal_fast(content_dir_name, "", sizeof(""))) + { + strlcpy(content_dir_name, + path_basename_nocompression(content_dir_name), + sizeof(content_dir_name)); + } + if (string_is_not_equal_fast(content_dir_name, "", sizeof(""))) + path_remove_extension(content_dir_name); + + if (string_is_not_equal_fast(content_dir_name, "", sizeof(""))) + strlcpy(replace_text, content_dir_name, sizeof(replace_text)); + + break; + } + case RARCH_WILDCARD_CORE: + { + runloop_state_t* runloop_st = runloop_state_get_ptr(); + strlcpy(replace_text, runloop_st->system.info.library_name, sizeof(replace_text)); + break; + } + case RARCH_WILDCARD_GAME: + { + const char* path_basename = path_get(RARCH_PATH_BASENAME); + if (path_basename) + path_basename = path_basename_nocompression(path_basename); + if (path_basename) + strlcpy(replace_text, path_basename, sizeof(replace_text)); + break; + } + case RARCH_WILDCARD_VIDEO_DRIVER: + { + strlcpy(replace_text, config_get_ptr()->arrays.video_driver, sizeof(replace_text)); + break; + } + case RARCH_WILDCARD_CORE_REQUESTED_ROTATION: + { + char rotation_replace_strings[4][PATH_MAX_LENGTH] = { + "CORE-REQ-ROT-0", + "CORE-REQ-ROT-90", + "CORE-REQ-ROT-180", + "CORE-REQ-ROT-270" + }; + strlcpy(replace_text, rotation_replace_strings[retroarch_get_core_requested_rotation()], sizeof(replace_text)); + break; + } + case RARCH_WILDCARD_VIDEO_ALLOW_CORE_ROTATION: + { + if (config_get_ptr()->bools.video_allow_rotate) + strlcpy(replace_text, "VID-ALLOW-CORE-ROT-ON", sizeof(replace_text)); + else + strlcpy(replace_text, "VID-ALLOW-CORE-ROT-OFF", sizeof(replace_text)); + break; + } + case RARCH_WILDCARD_VIDEO_USER_ROTATION: + { + char rotation_replace_strings[4][PATH_MAX_LENGTH] = { + "VID-USER-ROT-0", + "VID-USER-ROT-90", + "VID-USER-ROT-180", + "VID-USER-ROT-270" + }; + strlcpy(replace_text, rotation_replace_strings[retroarch_get_video_rotation()], sizeof(replace_text)); + break; + } + case RARCH_WILDCARD_VIDEO_FINAL_ROTATION: + { + char rotation_replace_strings[4][PATH_MAX_LENGTH] = { + "VID-FINAL-ROT-0", + "VID-FINAL-ROT-90", + "VID-FINAL-ROT-180", + "VID-FINAL-ROT-270" + }; + strlcpy(replace_text, rotation_replace_strings[retroarch_get_rotation()], sizeof(replace_text)); + break; + } + case RARCH_WILDCARD_SCREEN_ORIENTATION: + { + char rotation_replace_strings[4][PATH_MAX_LENGTH] = { + "SCREEN-ORIENT-0", + "SCREEN-ORIENT-90", + "SCREEN-ORIENT-180", + "SCREEN-ORIENT-270" + }; + + strlcpy(replace_text, rotation_replace_strings[config_get_ptr()->uints.screen_orientation], sizeof(replace_text)); + break; + } + case RARCH_WILDCARD_CORE_ASPECT_ORIENTATION: + { + const int requested_rotation = retroarch_get_core_requested_rotation(); + strlcpy(replace_text, (video_driver_get_core_aspect() < 1 || requested_rotation == 1 || requested_rotation == 3) ? + "CORE-ASPECT-ORIENT-VERT" : + "CORE-ASPECT-ORIENT-HORZ", + sizeof(replace_text)); + break; + } + case RARCH_WILDCARD_VIEWPORT_ASPECT_ORIENTATION: + { + unsigned viewport_width = 0; + unsigned viewport_height = 0; + + video_driver_get_size(&viewport_width, &viewport_height); + strlcpy(replace_text, ((float)viewport_width / viewport_height < 1) ? + "VIEW-ASPECT-ORIENT-VERT" : + "VIEW-ASPECT-ORIENT-HORZ", + sizeof(replace_text)); + break; + } + case RARCH_WILDCARD_PRESET_DIR: + { + char preset_dir_name[PATH_MAX_LENGTH] = ""; + fill_pathname_parent_dir_name(preset_dir_name, in_preset_path, sizeof(preset_dir_name)); + if (string_is_not_equal_fast(preset_dir_name, "", sizeof(""))) + strlcpy(preset_dir_name, path_basename_nocompression(preset_dir_name), sizeof(preset_dir_name)); + if (string_is_not_equal_fast(preset_dir_name, "", sizeof(""))) + path_remove_extension(preset_dir_name); + if (string_is_not_equal_fast(preset_dir_name, "", sizeof(""))) + strlcpy(replace_text, preset_dir_name, sizeof(replace_text)); + break; + } + case RARCH_WILDCARD_PRESET: + { + char preset_name[PATH_MAX_LENGTH] = ""; + strlcpy(preset_name, path_basename_nocompression(in_preset_path), sizeof(preset_name)); + if (string_is_not_equal_fast(preset_name, "", sizeof(""))) + path_remove_extension(preset_name); + if (string_is_not_equal_fast(preset_name, "", sizeof(""))) + strlcpy(replace_text, preset_name, sizeof(replace_text)); + break; + } + case RARCH_WILDCARD_VIDEO_DRIVER_SHADER_EXT: + { + if (video_shader_is_supported(RARCH_SHADER_CG)) + strlcpy(replace_text, "cg", sizeof(replace_text)); + else if (video_shader_is_supported(RARCH_SHADER_GLSL)) + strlcpy(replace_text, "glsl", sizeof(replace_text)); + else if (video_shader_is_supported(RARCH_SHADER_SLANG)) + strlcpy(replace_text, "slang", sizeof(replace_text)); + break; + } + case RARCH_WILDCARD_VIDEO_DRIVER_PRESET_EXT: + { + if (video_shader_is_supported(RARCH_SHADER_CG)) + strlcpy(replace_text, "cgp", sizeof(replace_text)); + else if (video_shader_is_supported(RARCH_SHADER_GLSL)) + strlcpy(replace_text, "glslp", sizeof(replace_text)); + else if (video_shader_is_supported(RARCH_SHADER_SLANG)) + strlcpy(replace_text, "slangp", sizeof(replace_text)); + break; + } + } + { + char *replace_output = NULL; + replace_output = string_replace_substring(replaced_path, + wildcard_tokens[i].token_name, strlen(wildcard_tokens[i].token_name), + replace_text, strlen(replace_text)); + + strlcpy(replaced_path, replace_output, PATH_MAX_LENGTH); + + free(replace_output); + } + } + } + + /* If a file does not exist at the location of the replaced path + * then output the original path instead */ + if (!path_is_valid(replaced_path)) + { + RARCH_DBG("\n[Shaders]: Filepath after wildcard replacement can't be found:\n"); + RARCH_DBG(" \"%s\" \n", replaced_path); + RARCH_DBG(" Falling back to original Filepath\n"); + RARCH_DBG(" \"%s\" \n\n", inout_absolute_path); + } + else + { + strlcpy(inout_absolute_path, replaced_path, in_absolute_path_length); + } + + return; +} + +/** + * gather_reference_path_list: + * + * @param path_linked_list + * List of paths which accrues as we move down the chain of references + * @param path + * Current path of preset to process + * @param reference_depth + * This is used to check against the SHADER_MAX_REFERENCE_DEPTH + * + * @return void + **/ static void gather_reference_path_list( struct path_linked_list *in_path_linked_list, char *path, @@ -118,7 +445,10 @@ static void gather_reference_path_list( { char* reference_preset_path = (char*)malloc(PATH_MAX_LENGTH); + /* Get the absolute path and replace wildcards in the path */ fill_pathname_expanded_and_absolute(reference_preset_path, conf->path, ref_tmp->path); + replace_wildcards(reference_preset_path, PATH_MAX_LENGTH, conf->path); + gather_reference_path_list(in_path_linked_list, reference_preset_path, reference_depth + 1); free(reference_preset_path); @@ -128,7 +458,7 @@ static void gather_reference_path_list( } else { - RARCH_WARN("\n [Shaders]: No Preset located at \"%s\".\n", path); + RARCH_WARN("\n[Shaders]: No Preset located at \"%s\".\n", path); } config_file_free(conf); } @@ -240,9 +570,9 @@ static bool video_shader_parse_pass(config_file_t *conf, return false; } - /* Get the absolute path */ - fill_pathname_expanded_and_absolute(pass->source.path, - conf->path, tmp_path); + /* Get the absolute path and replace wildcards in the path */ + fill_pathname_expanded_and_absolute(pass->source.path, conf->path, tmp_path); + replace_wildcards(pass->source.path, PATH_MAX_LENGTH, conf->path); /* Smooth */ strlcpy(filter_name_buf, "filter_linear", sizeof(filter_name_buf)); @@ -481,9 +811,9 @@ static bool video_shader_parse_textures(config_file_t *conf, config_get_path(conf, id, texture_path, sizeof(texture_path)); - /* Get the absolute path */ - fill_pathname_expanded_and_absolute( - shader->lut[shader->luts].path, conf->path, texture_path); + /* Get the absolute path and replace wildcards in the path */ + fill_pathname_expanded_and_absolute(shader->lut[shader->luts].path, conf->path, texture_path); + replace_wildcards(shader->lut[shader->luts].path, PATH_MAX_LENGTH, conf->path); entry = NULL; @@ -537,7 +867,7 @@ static struct video_shader_parameter *video_shader_parse_find_parameter( { size_t i; - for (i = 0; i < num_params; i++) + for (i = 0; (unsigned)i < num_params; i++) { if (string_is_equal(params[i].id, id)) return ¶ms[i]; @@ -964,8 +1294,9 @@ static config_file_t *video_shader_get_root_preset_config(const char *path) return NULL; } - /* Get the absolute path for the reference */ - fill_pathname_expanded_and_absolute(nested_reference_path, conf->path, conf->references->path); + /* Get the absolute path and replace wildcards in the path */ + fill_pathname_expanded_and_absolute(nested_reference_path, conf->path, conf->references->path); + replace_wildcards(nested_reference_path, PATH_MAX_LENGTH, conf->path); /* Create a new config from the referenced path */ config_file_free(conf); @@ -1049,8 +1380,9 @@ static bool video_shader_check_reference_chain_for_save( break; } - /* Get the absolute path for the reference */ + /* Get the absolute path and replace wildcards in the path */ fill_pathname_expanded_and_absolute(nested_ref_path, conf->path, conf->references->path); + replace_wildcards(nested_ref_path, PATH_MAX_LENGTH, conf->path); /* If one of the reference paths is the same as the file we want to save then this reference chain would be * self-referential / cyclical and we can't save this as a simple preset*/ @@ -1194,9 +1526,9 @@ static bool video_shader_write_referenced_preset( * trying to save */ if (ref_conf->references) { - /* Get the absolute path for the reference */ - fill_pathname_expanded_and_absolute(abs_tmp_ref_path, - ref_conf->path, ref_conf->references->path); + /* Get the absolute path and replace wildcards in the path */ + fill_pathname_expanded_and_absolute(abs_tmp_ref_path, ref_conf->path, ref_conf->references->path); + replace_wildcards(abs_tmp_ref_path, PATH_MAX_LENGTH, ref_conf->path); pathname_conform_slashes_to_os(abs_tmp_ref_path); @@ -1234,9 +1566,9 @@ static bool video_shader_write_referenced_preset( * we will use this same nested reference for the new preset */ if (ref_conf->references) { - /* Get the absolute path for the reference */ - fill_pathname_expanded_and_absolute(path_to_ref, - ref_conf->path, ref_conf->references->path); + /* Get the absolute path and replace wildcards in the path */ + fill_pathname_expanded_and_absolute(path_to_ref, ref_conf->path, ref_conf->references->path); + replace_wildcards(path_to_ref, PATH_MAX_LENGTH, ref_conf->path); /* If the reference path is also the same as what * we are trying to save @@ -1254,8 +1586,11 @@ static bool video_shader_write_referenced_preset( /* If the reference also has a reference inside it */ /* Get the absolute path for the reference */ if (ref_conf->references) - fill_pathname_expanded_and_absolute(path_to_ref, - ref_conf->path, ref_conf->references->path); + { + /* Get the absolute path and replace wildcards in the path */ + fill_pathname_expanded_and_absolute(path_to_ref, ref_conf->path, ref_conf->references->path); + replace_wildcards(path_to_ref, PATH_MAX_LENGTH, ref_conf->path); + } else { /* If the config referenced is a full preset */ @@ -1721,8 +2056,6 @@ static bool override_shader_values(config_file_t *override_conf, { char *override_tex_path = (char*)malloc(PATH_MAX_LENGTH); - override_tex_path[0] = '\0'; - /* Step through the textures in the shader and see if there is an entry * for each in the override config */ for (i = 0; i < shader->luts; i++) @@ -1730,13 +2063,16 @@ static bool override_shader_values(config_file_t *override_conf, /* If the texture is defined in the reference config */ if (config_get_entry(override_conf, shader->lut[i].id)) { - /* Texture path from shader the config */ - config_get_path(override_conf, shader->lut[i].id, - override_tex_path, PATH_MAX_LENGTH); + char *tex_path = (char*)malloc(PATH_MAX_LENGTH); - /* Get the absolute path */ - fill_pathname_expanded_and_absolute(shader->lut[i].path, - override_conf->path, override_tex_path); + /* Texture path from the config */ + config_get_path(override_conf, shader->lut[i].id, tex_path, PATH_MAX_LENGTH); + + /* Get the absolute path and replace wildcards in the path */ + fill_pathname_expanded_and_absolute(override_tex_path, override_conf->path, tex_path); + replace_wildcards(override_tex_path, PATH_MAX_LENGTH, override_conf->path); + + strlcpy(shader->lut[i].path, override_tex_path, PATH_MAX_LENGTH); #ifdef DEBUG RARCH_DBG("[Shaders]: Texture: \"%s\" = %s.\n", @@ -1744,6 +2080,7 @@ static bool override_shader_values(config_file_t *override_conf, shader->lut[i].path); #endif + free(tex_path); return_val = true; } } @@ -1953,8 +2290,8 @@ bool video_shader_load_preset_into_shader(const char *path, goto end; } - /* Check if the root preset is a valid shader chain */ - /* If the config has a shaders entry then it is considered + /* Check if the root preset is a valid shader chain + If the config has a shaders entry then it is considered a shader chain config, vs a config which may only have parameter values and texture overrides */ @@ -1994,12 +2331,14 @@ bool video_shader_load_preset_into_shader(const char *path, config_file_t *tmp_conf = NULL; char *path_to_ref = (char*)malloc(PATH_MAX_LENGTH); + /* Get the absolute path and replace wildcards in the path */ fill_pathname_expanded_and_absolute(path_to_ref, conf->path, path_list_tmp->path); + replace_wildcards(path_to_ref, PATH_MAX_LENGTH, conf->path); if ((tmp_conf = video_shader_get_root_preset_config(path_to_ref))) { - /* Check if the config is a valid shader chain config */ - /* If the config has a shaders entry then it is considered + /* Check if the config is a valid shader chain config + If the config has a shaders entry then it is considered a shader chain config, vs a config which may only have parameter values and texture overrides */ diff --git a/gfx/video_shader_parse.h b/gfx/video_shader_parse.h index 7f24d5e93f..dc80de6844 100644 --- a/gfx/video_shader_parse.h +++ b/gfx/video_shader_parse.h @@ -188,6 +188,33 @@ struct video_shader }; +#define RARCH_WILDCARD_DELIMITER "$" + +enum wildcard_type +{ + RARCH_WILDCARD_CONTENT_DIR = 0, + RARCH_WILDCARD_CORE, + RARCH_WILDCARD_GAME, + RARCH_WILDCARD_VIDEO_DRIVER, + RARCH_WILDCARD_VIDEO_USER_ROTATION, + RARCH_WILDCARD_VIDEO_ALLOW_CORE_ROTATION, + RARCH_WILDCARD_CORE_REQUESTED_ROTATION, + RARCH_WILDCARD_VIDEO_FINAL_ROTATION, + RARCH_WILDCARD_SCREEN_ORIENTATION, + RARCH_WILDCARD_VIEWPORT_ASPECT_ORIENTATION, + RARCH_WILDCARD_CORE_ASPECT_ORIENTATION, + RARCH_WILDCARD_PRESET_DIR, + RARCH_WILDCARD_PRESET, + RARCH_WILDCARD_VIDEO_DRIVER_SHADER_EXT, + RARCH_WILDCARD_VIDEO_DRIVER_PRESET_EXT +}; + +struct wildcard_token +{ + enum wildcard_type token_id; + char token_name[64]; +}; + /** * video_shader_resolve_parameters: diff --git a/retroarch.h b/retroarch.h index 7d44f525f9..a34a5e9609 100644 --- a/retroarch.h +++ b/retroarch.h @@ -143,6 +143,21 @@ const char* config_get_audio_driver_options(void); /* Camera */ +/* + Returns the user defined video rotation set in the video_rotation user setting +*/ +unsigned int retroarch_get_video_rotation(void); + +/* + Returns rotation requested by the core regardless of if it has been + applied with the final video rotation +*/ +unsigned int retroarch_get_core_requested_rotation(void); + +/* + Returns final rotation including both user chosen video rotation + and core requested rotation if allowed by video_allow_rotate +*/ unsigned int retroarch_get_rotation(void); void retroarch_init_task_queue(void); diff --git a/retroarch_types.h b/retroarch_types.h index c39c65b949..54c806cd07 100644 --- a/retroarch_types.h +++ b/retroarch_types.h @@ -180,6 +180,7 @@ typedef struct rarch_system_info unsigned size; } ports; unsigned rotation; + unsigned core_requested_rotation; unsigned performance_level; char valid_extensions[255]; bool load_no_content; diff --git a/runloop.c b/runloop.c index 76f28efa94..5378c29812 100644 --- a/runloop.c +++ b/runloop.c @@ -1897,6 +1897,8 @@ bool runloop_environment_cb(unsigned cmd, void *data) bool video_allow_rotate = settings->bools.video_allow_rotate; RARCH_LOG("[Environ]: SET_ROTATION: %u\n", rotation); + if (system) + system->core_requested_rotation = rotation; if (!video_allow_rotate) return false; @@ -4253,11 +4255,32 @@ unsigned runloop_get_video_swap_interval( swap_interval_config; } -unsigned int retroarch_get_rotation(void) +/* + Returns the user defined video rotation set in the video_rotation user setting +*/ +unsigned int retroarch_get_video_rotation(void) { settings_t *settings = config_get_ptr(); unsigned video_rotation = settings->uints.video_rotation; - return video_rotation + runloop_state.system.rotation; + return settings->uints.video_rotation; +} + +/* + Returns rotation requested by the core regardless of if it has been + applied with the final video rotation +*/ +unsigned int retroarch_get_core_requested_rotation(void) +{ + return runloop_state.system.core_requested_rotation; +} + +/* + Returns final rotation including both user chosen video rotation + and core requested rotation if allowed by video_allow_rotate +*/ +unsigned int retroarch_get_rotation(void) +{ + return retroarch_get_video_rotation() + runloop_state.system.rotation; } static void retro_run_null(void) { } /* Stub function callback impl. */